From 7d4e9164d1d2269b0fe51e54db4544585a7ab4b6 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sun, 18 Feb 2018 18:16:59 -0800 Subject: [PATCH] Port to Windows. This also cleans up file descriptors to use an assuan_fd_t rather than an int and also uses the existing libassuan file descriptor closing function __assuan_close() for portability. --- configure.ac | 8 +++ src/Makefile.am | 6 +- src/libpwmd.c | 206 ++++++++++++++++++++++++++++++++++++++++++-------------- src/misc.c | 25 +++++++ src/misc.h | 7 +- src/pinentry.c | 2 +- src/pwmc.c | 18 +++-- src/ssh.c | 72 +++++++++++++++++--- src/ssh.h | 1 - src/tls.c | 38 ++++++----- src/tls.h | 1 - src/types.h | 18 ++++- src/zxcvbn.c | 2 + 13 files changed, 317 insertions(+), 87 deletions(-) diff --git a/configure.ac b/configure.ac index 99f90f9f..595660ce 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,8 @@ AC_SUBST(LIBTOOL_CUR) AC_SUBST(LIBTOOL_REV) AC_SUBST(LIBTOOL_AGE) +is_mingw32=0 + case "$target_os" in darwin*) LDFLAGS="$LDFLAGS -flat_namespace -L/sw/lib" @@ -49,10 +51,16 @@ case "$target_os" in ;; esac ;; + mingw32*) + LT_INIT([win32-dll]) + is_mingw32=1 + ;; *) ;; esac +AM_CONDITIONAL([WITH_MINGW32], [test x"$is_mingw32" = "x1"]) + dnl Checks for programs. AC_PROG_CC_C99 diff --git a/src/Makefile.am b/src/Makefile.am index 52419cbe..e5916f52 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,8 +8,12 @@ libpwmd_la_HEADERS = libpwmd.h libpwmd_la_LDFLAGS = -version-info @LIBTOOL_CUR@:@LIBTOOL_REV@:@LIBTOOL_AGE@ \ @PTHREAD_LIBS@ @GPG_ERROR_LIBS@ @LTLIBINTL@ \ @LIBASSUAN_LIBS@ +if WITH_MINGW32 +libpwmd_la_LDFLAGS += -no-undefined +endif libpwmd_la_CFLAGS = -DLOCALEDIR=\"${prefix}/share/locale\" @GPG_ERROR_CFLAGS@ \ @PTHREAD_CFLAGS@ @LIBASSUAN_CFLAGS@ +libpwmd_la_DEPENDENCIES = @LTLIBOBJS@ if WITH_SSH libpwmd_la_SOURCES += ssh.c ssh.h @@ -40,7 +44,7 @@ endif pwmc_CFLAGS = -DLOCALEDIR=\"${prefix}/share/locale\" @GPG_ERROR_CFLAGS@ \ @GNUTLS_CFLAGS@ @libssh2_CFLAGS@ @LIBASSUAN_CFLAGS@ pwmc_LDFLAGS = @GPG_ERROR_LIBS@ @LIBASSUAN_LIBS@ @GNUTLS_LIBS@ @libssh2_LIBS@ -pwmc_LDADD = libpwmd.la +pwmc_LDADD = libpwmd.la @LTLIBOBJS@ if WITH_READLINE pwmc_LDFLAGS += @READLINE_LIBS@ diff --git a/src/libpwmd.c b/src/libpwmd.c index 0dee149d..809c60ab 100644 --- a/src/libpwmd.c +++ b/src/libpwmd.c @@ -25,23 +25,27 @@ #include #include #include -#include #include #include #include #include -#include -#include #include #include #include -#include #include -#include #include #include + +#ifndef __MINGW32__ +#include +#include +#include +#include +#include #include #include +#endif + #include #ifdef HAVE_STRINGS_H @@ -66,10 +70,12 @@ #if defined(WITH_SSH) || defined(WITH_GNUTLS) #include +#ifndef __MINGW32__ #include #include #include #endif +#endif enum { @@ -95,12 +101,25 @@ hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len) pwm_t *pwm = assuan_get_pointer (ctx); if (pwm->read_cb) - return pwm->read_cb (pwm->read_cb_data, fd, data, len); + return pwm->read_cb (pwm->read_cb_data, HANDLE2SOCKET (fd), data, len); #if defined(WITH_SSH) || defined(WITH_GNUTLS) #ifdef WITH_SSH if (pwm && pwm->tcp && pwm->tcp->ssh) - return read_hook_ssh (pwm->tcp->ssh, fd, data, len); + { + ssize_t ret = read_hook_ssh (pwm->tcp->ssh, fd, data, len); + + if (ret == -1) + { + int e = errno; + + __assuan_close (ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; + errno = e; + } + + return ret; + } #endif #ifdef WITH_GNUTLS if (pwm && pwm->tcp && pwm->tcp->tls) @@ -108,7 +127,7 @@ hook_read (assuan_context_t ctx, assuan_fd_t fd, void *data, size_t len) #endif #endif - return read ((int) fd, data, len); + return read (HANDLE2SOCKET (fd), data, len); } ssize_t @@ -119,12 +138,25 @@ hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data, ssize_t wrote; if (pwm->write_cb) - return pwm->write_cb (pwm->write_cb_data, fd, data, len); + return pwm->write_cb (pwm->write_cb_data, HANDLE2SOCKET (fd), data, len); #if defined(WITH_SSH) || defined(WITH_GNUTLS) #ifdef WITH_SSH if (pwm && pwm->tcp && pwm->tcp->ssh) - return write_hook_ssh (pwm->tcp->ssh, fd, data, len); + { + ssize_t ret = write_hook_ssh (pwm->tcp->ssh, fd, data, len); + + if (ret == -1) + { + int e = errno; + + __assuan_close (ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; + errno = e; + } + + return ret; + } #endif #ifdef WITH_GNUTLS if (pwm && pwm->tcp && pwm->tcp->tls) @@ -135,15 +167,16 @@ hook_write (assuan_context_t ctx, assuan_fd_t fd, const void *data, /* libassuan cannot handle EAGAIN when doing writes. */ do { - wrote = write ((int) fd, data, len); + wrote = write (HANDLE2SOCKET (fd), data, len); if (wrote == -1 && errno == EAGAIN) - usleep (50000); + __assuan_usleep (pwm->ctx, 50000); } while (wrote == -1 && errno == EAGAIN); return wrote; } +#ifndef __MINGW32__ pid_t hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status, int options) @@ -152,6 +185,7 @@ hook_waitpid (assuan_context_t ctx, pid_t pid, int action, int *status, (void)action; return waitpid (pid, status, options); } +#endif gpg_error_t pwmd_init () @@ -199,7 +233,7 @@ _connect_finalize (pwm_t * pwm) { gpg_error_t rc = 0; char *result = NULL; - int active[2]; + assuan_fd_t active[2]; int n = assuan_get_active_fds (pwm->ctx, 0, active, N_ARRAY (active)); if (n <= 0) @@ -227,14 +261,17 @@ _connect_finalize (pwm_t * pwm) static gpg_error_t connect_uds (pwm_t * pwm, const char *path) { +#ifdef __MINGW32__ + return GPG_ERR_UNSUPPORTED_PROTOCOL; +#else + if (!pwm) + return GPG_ERR_INV_ARG; + char *socketpath = NULL; struct passwd pw; char *pwbuf; gpg_error_t rc; - if (!pwm) - return GPG_ERR_INV_ARG; - pwbuf = _getpwuid (&pw); if (!pwbuf) return gpg_error_from_syserror (); @@ -251,6 +288,7 @@ connect_uds (pwm_t * pwm, const char *path) rc = assuan_socket_connect (pwm->ctx, socketpath, ASSUAN_INVALID_FD, 0); pwmd_free (socketpath); return rc ? rc : _connect_finalize (pwm); +#endif } static gpg_error_t @@ -271,7 +309,11 @@ init_handle (pwm_t * pwm) NULL, //recvmsg NULL, //sendmsg both are used for FD passing __assuan_spawn, +#ifdef __MINGW32__ + __assuan_waitpid, +#else hook_waitpid, +#endif __assuan_socketpair, __assuan_socket, __assuan_connect @@ -432,8 +474,13 @@ tcp_connect_common (pwm_t * pwm) for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr; pwm->tcp->addr = pwm->tcp->addrs->ai_next) { +#ifdef __MINGW32__ + pwm->fh = _open_osfhandle (socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0), 0); + pwm->fd = SOCKET2HANDLE (_get_osfhandle (pwm->fh)); +#else pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0); - if (pwm->fd == -1) +#endif + if (pwm->fd == ASSUAN_INVALID_FD) { rc = gpg_error_from_syserror (); if (pwm->tcp->addr == pwm->tcp->addrs->ai_next) @@ -441,13 +488,15 @@ tcp_connect_common (pwm_t * pwm) continue; } - if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1) + rc = set_non_blocking (pwm->fd, 1); + if (rc) { - rc = gpg_error_from_syserror (); - break; + __assuan_close (pwm->ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; + break; } - if (connect (pwm->fd, pwm->tcp->addr->ai_addr, + if (connect (HANDLE2SOCKET (pwm->fd), pwm->tcp->addr->ai_addr, pwm->tcp->addr->ai_family == AF_INET6 ? sizeof (struct sockaddr_in6) : sizeof (struct sockaddr)) == -1) @@ -457,10 +506,23 @@ tcp_connect_common (pwm_t * pwm) unsigned elapsed = 0; rc = gpg_error_from_syserror (); +#ifdef __MINGW32__ + int w = WSAGetLastError (); + switch (w) + { + case WSAEINPROGRESS: + case WSAEWOULDBLOCK: + rc = GPG_ERR_EINPROGRESS; + break; + default: + break; + } +#endif + if (gpg_err_code (rc) != GPG_ERR_EINPROGRESS) { - close (pwm->fd); - pwm->fd = -1; + __assuan_close (pwm->ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; if (pwm->tcp->addr == pwm->tcp->addrs->ai_next) return rc; continue; @@ -470,8 +532,8 @@ again: tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO (&wfds); - FD_SET (pwm->fd, &wfds); - n = select (pwm->fd+1, NULL, &wfds, NULL, &tv); + FD_SET (HANDLE2SOCKET (pwm->fd), &wfds); + n = select (HANDLE2SOCKET (pwm->fd)+1, NULL, &wfds, NULL, &tv); rc = 0; if (!n || pwm->cancel) { @@ -484,19 +546,27 @@ again: } else if (n != -1) { - socklen_t len = sizeof(int); - + socklen_t len = sizeof (int); +#ifdef __MINGW32__ + char ret; + + len = sizeof (char); + getsockopt (HANDLE2SOCKET (pwm->fd), SOL_SOCKET, SO_ERROR, &ret, &len); + if (ret) + rc = gpg_error_from_errno (ret); +#else getsockopt (pwm->fd, SOL_SOCKET, SO_ERROR, &n, &len); if (n) rc = gpg_error_from_errno (n); +#endif } else if (n == -1) rc = gpg_error_from_syserror (); if (rc) { - close (pwm->fd); - pwm->fd = -1; + __assuan_close (pwm->ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; if (pwm->tcp->addr == pwm->tcp->addrs->ai_next || gpg_err_code (rc) == GPG_ERR_ETIMEDOUT || pwm->cancel) @@ -510,8 +580,14 @@ again: } if (!rc) - if (fcntl (pwm->fd, F_SETFL, 0) == -1) - rc = gpg_error_from_syserror (); + { + rc = set_non_blocking (pwm->fd, 0); + if (rc) + { + __assuan_close (pwm->ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; + } + } return rc; } @@ -536,18 +612,20 @@ pwmd_connect_fd (pwm_t * pwm, int fd) if (rc) return FINISH (rc); } - else if (pwm->fd != -1) + else if (pwm->fd != ASSUAN_INVALID_FD) return FINISH (GPG_ERR_INV_STATE); command_start (pwm); +#ifndef __MINGW32__ if (!(pwm->opts & OPT_SIGPIPE)) signal (SIGPIPE, SIG_IGN); +#endif rc = assuan_socket_connect_fd (pwm->ctx, fd, 0); if (!rc) { - pwm->fd = fd; + pwm->fd = SOCKET2HANDLE (fd); pwm->connected = pwm->user_fd = 1; rc = _connect_finalize (pwm); } @@ -572,13 +650,15 @@ pwmd_connect (pwm_t * pwm, const char *url, ...) if (rc) return FINISH (GPG_ERR_INV_ARG); } - else if (pwm->fd != -1) + else if (pwm->fd != ASSUAN_INVALID_FD) return FINISH (GPG_ERR_INV_STATE); command_start (pwm); +#ifndef __MINGW32__ if (!(pwm->opts & OPT_SIGPIPE)) signal (SIGPIPE, SIG_IGN); +#endif #ifdef WITH_GNUTLS pwm->tls_error = 0; @@ -749,7 +829,7 @@ disconnect (pwm_t * pwm) free_tcp (pwm); #endif pwm->ctx = NULL; - pwm->fd = -1; + pwm->fd = ASSUAN_INVALID_FD; pwm->connected = 0; pwm->user_fd = -1; } @@ -807,7 +887,9 @@ get_password (pwm_t * pwm, char **result, size_t * len, pwmd_pinentry_t w, int echo) { char buf[ASSUAN_LINELENGTH+1] = { 0 }, *p; +#ifndef __MINGW32__ struct termios told, tnew; +#endif char *key = NULL; if (result) @@ -822,6 +904,7 @@ get_password (pwm_t * pwm, char **result, size_t * len, return GPG_ERR_ENOTTY; } +#ifndef __MINGW32__ if (!echo) { if (tcgetattr (STDIN_FILENO, &told) == -1) @@ -839,6 +922,7 @@ get_password (pwm_t * pwm, char **result, size_t * len, return gpg_error_from_errno (n); } } +#endif if (pwm->passphrase_hint) fprintf(stderr, N_("Key info: %s\n"), pwm->passphrase_hint); @@ -872,8 +956,10 @@ get_password (pwm_t * pwm, char **result, size_t * len, p = fgets (buf, sizeof (buf), stdin); +#ifndef __MINGW32__ if (!echo) tcsetattr (STDIN_FILENO, TCSANOW, &told); +#endif if (!p || feof (stdin)) { @@ -1173,7 +1259,7 @@ parse_assuan_line (pwm_t * pwm) static void reset_handle (pwm_t *pwm) { - pwm->fd = -1; + pwm->fd = ASSUAN_INVALID_FD; pwm->user_fd = -1; pwm->cancel = 0; pwm->pinentry_disabled = 0; @@ -1187,7 +1273,9 @@ reset_handle (pwm_t *pwm) #endif if (pwm->tcp) - pwm->tcp->rc = 0; + { + pwm->tcp->rc = 0; + } #endif } @@ -1199,7 +1287,7 @@ pwmd_disconnect (pwm_t * pwm) command_start (pwm); - if (pwm->fd == -1) + if (pwm->fd == ASSUAN_INVALID_FD) return FINISH (GPG_ERR_INV_STATE); disconnect (pwm); @@ -1216,21 +1304,21 @@ pwmd_process (pwm_t * pwm) struct timeval tv = { 0, 0 }; int n; - if (!pwm || pwm->fd == -1) + if (!pwm || pwm->fd == ASSUAN_INVALID_FD) return FINISH (GPG_ERR_INV_ARG); else if (!pwm->ctx) return FINISH (GPG_ERR_INV_STATE); FD_ZERO (&fds); - FD_SET (pwm->fd, &fds); - n = select (pwm->fd + 1, &fds, NULL, NULL, &tv); + FD_SET (HANDLE2SOCKET (pwm->fd), &fds); + n = select (HANDLE2SOCKET (pwm->fd) + 1, &fds, NULL, NULL, &tv); if (n == -1) return FINISH (gpg_error_from_syserror ()); if (n > 0) { - if (FD_ISSET (pwm->fd, &fds)) + if (FD_ISSET (HANDLE2SOCKET (pwm->fd), &fds)) rc = parse_assuan_line (pwm); } @@ -1240,8 +1328,8 @@ pwmd_process (pwm_t * pwm) #if defined (WITH_SSH) || defined (WITH_GNUTLS) if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp) { - close (pwm->fd); - pwm->fd = -1; + __assuan_close (pwm->ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; } #endif @@ -1484,7 +1572,7 @@ pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result) *result = PWMD_SOCKET_LOCAL; - if (pwm->fd == -1) + if (pwm->fd == ASSUAN_INVALID_FD) return FINISH (GPG_ERR_INV_STATE); if (pwm->user_fd != -1) @@ -1800,7 +1888,11 @@ pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap) arg1 = va_arg (ap, char *); pwmd_free (pwm->pinentry_path); +#ifdef __MINGW32__ + pwm->pinentry_path = arg1 ? pwmd_strdup (arg1) : NULL; +#else pwm->pinentry_path = arg1 ? _expand_homedir (arg1, NULL) : NULL; +#endif break; case PWMD_OPTION_PINENTRY_TTY: if (get) @@ -1825,8 +1917,10 @@ pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap) arg1 = va_arg (ap, char *); pwmd_free (pwm->pinentry_display); pwm->pinentry_display = arg1 && *arg1 ? pwmd_strdup (arg1) : NULL; +#ifndef __MINGW32__ if (!pwm->pinentry_display) unsetenv ("DISPLAY"); +#endif break; case PWMD_OPTION_PINENTRY_TERM: if (get) @@ -1839,8 +1933,10 @@ pwmd_get_set_opt (pwm_t *pwm, pwmd_option_t opt, int get, va_list ap) arg1 = va_arg (ap, char *); pwmd_free (pwm->pinentry_term); pwm->pinentry_term = arg1 && *arg1 ? pwmd_strdup (arg1) : NULL; +#ifndef __MINGW32__ if (pwm->pinentry_term) unsetenv ("TERM"); +#endif break; case PWMD_OPTION_PINENTRY_ERROR: if (get) @@ -2134,6 +2230,7 @@ set_rcdefaults (pwm_t *pwm, char *filename) unsigned line_n = 0; gpg_error_t rc = 0; +#ifndef __MINGW32__ if (!filename && isatty (STDIN_FILENO)) { char buf[256]; @@ -2160,9 +2257,14 @@ set_rcdefaults (pwm_t *pwm, char *filename) if (rc) return rc; } +#endif +#ifdef __MINGW32__ + f = pwmd_strdup ("libpwmd.conf"); +#else f = _expand_homedir (filename ? filename : (char *)"~/.config/libpwmd.conf", NULL); +#endif if (f) { line = pwmd_malloc (LINE_MAX); @@ -2306,6 +2408,12 @@ pwmd_new (const char *name, pwm_t ** pwm) h->prot = PWMD_IP_ANY; h->socket_timeout = 120; h->tls_verify = 1; +#ifdef __MINGW32__ + WSADATA wsdata; + + WSAStartup (0x202, &wsdata); +#endif + #endif h->opts |= OPT_LOCK_ON_OPEN; @@ -2439,10 +2547,10 @@ pwmd_fd (pwm_t * pwm, int *fd) if (!pwm || !fd) return FINISH (GPG_ERR_INV_ARG); - if (pwm->fd == -1) + if (pwm->fd == ASSUAN_INVALID_FD) return FINISH (GPG_ERR_INV_STATE); - *fd = pwm->fd; + *fd = HANDLE2SOCKET (pwm->fd); return 0; } @@ -2480,9 +2588,9 @@ pwmd_cancel (pwm_t *pwm) return FINISH (GPG_ERR_INV_ARG); #if defined(WITH_SSH) || defined(WITH_GNUTLS) - if (pwm->fd == -1 && !pwm->tcp) + if (pwm->fd == ASSUAN_INVALID_FD && !pwm->tcp) #else - if (pwm->fd == -1) + if (pwm->fd == ASSUAN_INVALID_FD) #endif return FINISH (GPG_ERR_INV_STATE); diff --git a/src/misc.c b/src/misc.c index 8d5e78b8..88b9f301 100644 --- a/src/misc.c +++ b/src/misc.c @@ -43,6 +43,7 @@ #include #include "misc.h" +#ifndef __MINGW32__ #ifdef HAVE_GETPWUID_R char * _expand_homedir (char *str, struct passwd *pw) @@ -140,6 +141,7 @@ _getpwuid (struct passwd *pwd) return pwmd_strdup (""); } #endif +#endif /* * Borrowed from libassuan. @@ -260,3 +262,26 @@ bin2hex (const unsigned char *data, size_t len) return pwmd_strdup (buf); } + +gpg_error_t +set_non_blocking (assuan_fd_t fd, int n) +{ +#ifdef __MINGW32__ + unsigned long opt = !!n; + + if (ioctlsocket (HANDLE2SOCKET (fd), FIONBIO, &opt) != NO_ERROR) + return gpg_error_from_syserror (); +#else + int flags = fcntl (fd, F_GETFL); + + if (!n) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + + if (fcntl (fd, F_SETFL, flags) == -1) + return gpg_error_from_syserror (); +#endif + + return 0; +} diff --git a/src/misc.h b/src/misc.h index 9963a80e..06e73194 100644 --- a/src/misc.h +++ b/src/misc.h @@ -21,13 +21,18 @@ #ifndef MISC_H #define MISC_H -#include #include "types.h" +#ifndef __MINGW32__ +#include + char *_expand_homedir (char *str, struct passwd *pw); char *_getpwuid (struct passwd *pwd); +#endif + char *_percent_escape (const char *atext); gpg_error_t parse_hostname_common (const char *str, char **host, int *port); char *bin2hex (const unsigned char *data, size_t len); +gpg_error_t set_non_blocking (assuan_fd_t fd, int n); #endif diff --git a/src/pinentry.c b/src/pinentry.c index 70575f9e..bd0ae8a6 100644 --- a/src/pinentry.c +++ b/src/pinentry.c @@ -45,7 +45,7 @@ launch_pinentry (pwm_t * pwm) { gpg_error_t rc; assuan_context_t ctx; - int child_list[] = { -1 }; + assuan_fd_t child_list[] = { ASSUAN_INVALID_FD }; const char *argv[12]; const char **p = argv; static struct assuan_malloc_hooks mhooks = { diff --git a/src/pwmc.c b/src/pwmc.c index e8e453eb..8d3fbf77 100644 --- a/src/pwmc.c +++ b/src/pwmc.c @@ -26,21 +26,25 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include #include -#include #include #include #include +#ifndef __MINGW32__ +#include +#include +#include +#include +#endif + #include "util-string.h" #include "util-slist.h" @@ -2557,11 +2561,13 @@ main (int argc, char *argv[]) goto done; } - if (fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK) == -1) +#ifndef __MINGW32__ + if (fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK, 1) == -1) { rc = gpg_error_from_errno (errno); goto done; } +#endif ssize_t n; @@ -2577,7 +2583,11 @@ main (int argc, char *argv[]) { if (errno == EAGAIN) { +#ifdef __MINGW32__ + Sleep (100000); +#else usleep (100000); +#endif continue; } diff --git a/src/ssh.c b/src/ssh.c index 834a6e07..8591ac2a 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -26,15 +26,19 @@ #include #include #include +#include +#include +#include + +#ifndef __MINGW32__ #include #include #include #include #include #include -#include -#include -#include +#endif + #include #ifndef LINE_MAX @@ -46,6 +50,28 @@ #include "ssh.h" #define INTERVAL 50000 +#ifdef __MINGW32__ +#define TEST_TIMEOUT(pwm, ssh, n) do { \ + if (pwm->cancel) \ + n = LIBSSH2_ERROR_TIMEOUT; \ + else if (n == LIBSSH2_ERROR_EAGAIN) \ + { \ + if (ssh->elapsed.tv_usec + INTERVAL >= 1000000L) \ + { \ + ssh->elapsed.tv_sec++; \ + ssh->elapsed.tv_usec = 0; \ + } \ + if (ssh->elapsed.tv_sec >= pwm->socket_timeout) \ + n = LIBSSH2_ERROR_TIMEOUT; \ + else \ + { \ + struct timeval tv = { 0, INTERVAL }; \ + __assuan_usleep (pwm->ctx, INTERVAL); \ + ssh->elapsed.tv_usec += INTERVAL; \ + } \ + } \ +} while (0); +#else #define TEST_TIMEOUT(pwm, ssh, n) do { \ if (pwm->cancel) \ n = LIBSSH2_ERROR_TIMEOUT; \ @@ -66,6 +92,7 @@ } \ } \ } while (0); +#endif static gpg_error_t ssh_connect_finalize (pwm_t * pwm); static gpg_error_t _setup_ssh_init (pwm_t * pwm); @@ -125,13 +152,12 @@ ssh_deinit (struct ssh_s *ssh) ssize_t read_hook_ssh (struct ssh_s *ssh, assuan_fd_t fd, void *data, size_t len) { + ssize_t ret = libssh2_channel_read (ssh->channel, data, len); (void)fd; if (ret == LIBSSH2_ERROR_TIMEOUT) { - close (*ssh->fd); - *ssh->fd = -1; errno = ETIMEDOUT; return -1; } @@ -159,8 +185,6 @@ write_hook_ssh (struct ssh_s * ssh, assuan_fd_t fd, const void *data, if (ret == LIBSSH2_ERROR_TIMEOUT) { - close (*ssh->fd); - *ssh->fd = -1; errno = ETIMEDOUT; return -1; } @@ -174,7 +198,6 @@ _free_ssh_conn (struct ssh_s *ssh) if (!ssh) return; - ssh->fd = NULL; pwmd_free (ssh->username); ssh->username = NULL; pwmd_free (ssh->known_hosts); @@ -198,8 +221,14 @@ init_ssh (pwm_t *pwm, const char *host, int port, const char *identity, { struct tcp_s *conn; gpg_error_t rc = 0; +#ifndef __MINGW32__ char *pwbuf = NULL; struct passwd pw; +#else + + if (!user) + return GPG_ERR_INV_ARG; +#endif if (!host || !*host || (!use_agent && (!identity || !*identity)) || (known_hosts && !*known_hosts)) @@ -218,6 +247,7 @@ init_ssh (pwm_t *pwm, const char *host, int port, const char *identity, goto fail; } +#ifndef __MINGW32__ pwbuf = _getpwuid (&pw); if (!pwbuf) { @@ -227,6 +257,9 @@ init_ssh (pwm_t *pwm, const char *host, int port, const char *identity, pwmd_free (conn->ssh->username); conn->ssh->username = pwmd_strdup (user ? user : pw.pw_name); +#else + conn->ssh->username = pwmd_strdup (user); +#endif if (!conn->ssh->username) { rc = gpg_error_from_errno (ENOMEM); @@ -239,7 +272,11 @@ init_ssh (pwm_t *pwm, const char *host, int port, const char *identity, conn->ssh->identity_pub = NULL; if (identity) { +#ifdef __MINGW32__ + conn->ssh->identity = pwmd_strdup (identity); +#else conn->ssh->identity = _expand_homedir ((char *) identity, &pw); +#endif if (!conn->ssh->identity) { @@ -257,17 +294,26 @@ init_ssh (pwm_t *pwm, const char *host, int port, const char *identity, } pwmd_free (conn->ssh->known_hosts); +#ifdef __MINGW32__ + if (known_hosts) + conn->ssh->known_hosts = pwmd_strdup (known_hosts); + else + conn->ssh->known_hosts = pwmd_strdup ("known_hosts"); +#else if (!known_hosts) known_hosts = "~/.ssh/known_hosts"; conn->ssh->known_hosts = _expand_homedir ((char *) known_hosts, &pw); +#endif if (!conn->ssh->known_hosts) { rc = gpg_error_from_errno (ENOMEM); goto fail; } +#ifndef __MINGW32__ pwmd_free (pwbuf); +#endif conn->port = port; conn->host = pwmd_strdup (host); if (!conn->host) @@ -280,8 +326,10 @@ init_ssh (pwm_t *pwm, const char *host, int port, const char *identity, return 0; fail: +#ifndef __MINGW32__ if (pwbuf) pwmd_free (pwbuf); +#endif pwm->tcp = conn; free_tcp (pwm); @@ -746,7 +794,11 @@ static gpg_error_t ssh_connect_finalize (pwm_t * pwm) { libssh2_session_set_blocking (pwm->tcp->ssh->session, 1); +#ifdef __MINGW32__ + return assuan_socket_connect_fd (pwm->ctx, pwm->fh, 0); +#else return assuan_socket_connect_fd (pwm->ctx, pwm->fd, 0); +#endif } static gpg_error_t @@ -756,7 +808,8 @@ _setup_ssh_init (pwm_t * pwm) do { - n = libssh2_session_handshake (pwm->tcp->ssh->session, pwm->fd); + n = libssh2_session_handshake (pwm->tcp->ssh->session, + HANDLE2SOCKET (pwm->fd)); TEST_TIMEOUT (pwm, pwm->tcp->ssh, n); } while (n == LIBSSH2_ERROR_EAGAIN); @@ -822,7 +875,6 @@ _do_ssh_connect (pwm_t * pwm, const char *host, int port, if (rc) goto fail; - pwm->tcp->fd = pwm->tcp->ssh->fd = &pwm->fd; pwm->tcp->ssh->timeout = pwm->socket_timeout; rc = _setup_ssh_session (pwm); diff --git a/src/ssh.h b/src/ssh.h index 65001827..2ea0bb95 100644 --- a/src/ssh.h +++ b/src/ssh.h @@ -38,7 +38,6 @@ struct ssh_s struct libssh2_knownhost *hostent; char *hostkey; int timeout; - int *fd; struct timeval elapsed; }; diff --git a/src/tls.c b/src/tls.c index da677c12..a1895ec1 100644 --- a/src/tls.c +++ b/src/tls.c @@ -28,13 +28,16 @@ #include #include #include -#include -#include #ifdef HAVE_STRINGS_H #include #endif +#ifndef __MINGW32__ +#include +#include +#endif + #include "types.h" #include "misc.h" @@ -96,10 +99,10 @@ tls_free (pwm_t *pwm) gnutls_deinit (tls->session); } - else if (pwm->fd != -1) + else if (pwm->fd != ASSUAN_INVALID_FD) { - close (pwm->fd); - pwm->fd = -1; + __assuan_close (pwm->ctx, pwm->fd); + pwm->fd = ASSUAN_INVALID_FD; } if (tls->x509) @@ -118,7 +121,7 @@ tls_read_hook (pwm_t *pwm, assuan_fd_t fd, void *data, size_t len) ssize_t ret; time_t start = time (NULL); - if (*tls->fd == -1) + if (pwm->fd == ASSUAN_INVALID_FD) return -1; (void)fd; @@ -130,8 +133,8 @@ tls_read_hook (pwm_t *pwm, assuan_fd_t fd, void *data, size_t len) int n; FD_ZERO (&fds); - FD_SET (*tls->fd, &fds); - n = select (*tls->fd+1, &fds, NULL, NULL, &tv); + FD_SET (HANDLE2SOCKET (pwm->fd), &fds); + n = select (HANDLE2SOCKET (pwm->fd)+1, &fds, NULL, NULL, &tv); if (n == 0 && tls->nl) { char c[] = "#\n"; @@ -194,7 +197,7 @@ tls_write_hook (pwm_t *pwm, assuan_fd_t fd, const void *data, size_t len) /* This is probably the BYE command after a previous call timed * out. If not done, the time(2) call seems to hang.*/ - if (*tls->fd == -1) + if (pwm->fd == ASSUAN_INVALID_FD) return -1; ssize_t ret; @@ -465,12 +468,10 @@ tls_init (pwm_t * pwm) } gnutls_transport_set_ptr (pwm->tcp->tls->session, - (gnutls_transport_ptr_t) pwm->fd); - if (fcntl (pwm->fd, F_SETFL, O_NONBLOCK) == -1) - { - rc = gpg_error_from_errno (errno); - goto fail; - } + (gnutls_transport_ptr_t) HANDLE2SOCKET (pwm->fd)); + rc = set_non_blocking (pwm->fd, 1); + if (rc) + goto fail; time_t start = time (NULL); do @@ -589,9 +590,12 @@ tls_connect (pwm_t * pwm, const char *host, int port, const char *cert, { rc = tls_init (pwm); if (!rc) - { - pwm->tcp->fd = pwm->tcp->tls->fd = &pwm->fd; + { +#ifdef __MINGW32__ + rc = assuan_socket_connect_fd (pwm->ctx, pwm->fh, 0); +#else rc = assuan_socket_connect_fd (pwm->ctx, pwm->fd, 0); +#endif } } diff --git a/src/tls.h b/src/tls.h index f597ff17..6c68b968 100644 --- a/src/tls.h +++ b/src/tls.h @@ -37,7 +37,6 @@ struct tls_s gnutls_session_t session; gnutls_certificate_credentials_t x509; int timeout; - int *fd; int nl; }; diff --git a/src/types.h b/src/types.h index e7864351..2ace3aef 100644 --- a/src/types.h +++ b/src/types.h @@ -59,7 +59,6 @@ struct tcp_s { char *host; unsigned port; - int *fd; gpg_error_t rc; struct addrinfo *addrs; struct addrinfo *addr; @@ -74,6 +73,18 @@ struct tcp_s }; #endif +/* Borrowed from g10code. */ +#if __WIN64__ +# define SOCKET2HANDLE(s) ((void *)(s)) +# define HANDLE2SOCKET(h) ((uintptr_t)(h)) +#elif __MINGW32__ +# define SOCKET2HANDLE(s) ((void *)(s)) +# define HANDLE2SOCKET(h) ((unsigned int)(h)) +#else +# define SOCKET2HANDLE(s) (s) +# define HANDLE2SOCKET(h) (h) +#endif + #define OPT_LOCK_ON_OPEN 0x0001 #define OPT_SIGPIPE 0x0002 @@ -86,6 +97,9 @@ struct pwm_s int tls_error; #endif #endif +#ifdef __MINGW32__ + SOCKET fh; +#endif /* Options set with pwmd_setopt(). */ pwmd_read_cb_t read_cb; void *read_cb_data; @@ -101,7 +115,7 @@ struct pwm_s int tls_verify; char *tls_priority; int socket_timeout; - int fd; + assuan_fd_t fd; int cancel; int connected; #ifdef WITH_PINENTRY diff --git a/src/zxcvbn.c b/src/zxcvbn.c index 74685868..e477fb2a 100644 --- a/src/zxcvbn.c +++ b/src/zxcvbn.c @@ -47,8 +47,10 @@ /* For pre-compiled headers under windows */ #ifdef _WIN32 +#ifndef __MINGW32__ #include "stdafx.h" #endif +#endif /* Minimum number of characters in a incrementing/decrementing sequence match */ #define MIN_SEQUENCE_LEN 3 -- 2.11.4.GIT