From ae26daebb9fa7fe69406c5b25ee14330fc8d5206 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Mon, 7 Jan 2013 22:52:24 -0500 Subject: [PATCH] Fix pwmd_process() to handle GPG_ERR_EOF. May occur when the remote closes the connection. Doing pwmd_close() may hang (BYE command from libassuan) so close the FD when this error is encountered. Cleanups of how tcp FD's are done. Sheesh. --- src/libpwmd.c | 49 ++++++++++++++----------------------------------- src/ssh.c | 9 +++------ src/tls.c | 11 ++++------- src/types.h | 2 +- 4 files changed, 22 insertions(+), 49 deletions(-) diff --git a/src/libpwmd.c b/src/libpwmd.c index a44bde31..621e3030 100644 --- a/src/libpwmd.c +++ b/src/libpwmd.c @@ -272,9 +272,6 @@ free_tcp (struct tcp_s *tcp) tcp->addrs = NULL; } - if (tcp->fd != -1) - close (tcp->fd); - pwmd_free (tcp); } #endif @@ -313,8 +310,8 @@ tcp_connect_common (pwm_t * pwm) for (pwm->tcp->addr = pwm->tcp->addrs; pwm->tcp->addr; pwm->tcp->addr = pwm->tcp->addrs->ai_next) { - pwm->tcp->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0); - if (pwm->tcp->fd == -1) + pwm->fd = socket (pwm->tcp->addr->ai_family, SOCK_STREAM, 0); + if (pwm->fd == -1) { rc = gpg_error_from_syserror (); if (pwm->tcp->addr == pwm->tcp->addrs->ai_next) @@ -322,14 +319,14 @@ tcp_connect_common (pwm_t * pwm) continue; } - if (connect (pwm->tcp->fd, pwm->tcp->addr->ai_addr, + if (connect (pwm->fd, pwm->tcp->addr->ai_addr, pwm->tcp->addr->ai_family == AF_INET6 ? sizeof (struct sockaddr_in6) : sizeof (struct sockaddr)) == -1) { rc = gpg_error_from_syserror (); - close (pwm->tcp->fd); - pwm->tcp->fd = -1; + close (pwm->fd); + pwm->fd = -1; if (pwm->tcp->addr == pwm->tcp->addrs->ai_next) break; continue; @@ -937,16 +934,10 @@ pwmd_disconnect (pwm_t * pwm) if (!pwm) return FINISH (GPG_ERR_INV_ARG); -#if defined(WITH_SSH) || defined(WITH_GNUTLS) - if (pwm->fd == -1 && pwm->tcp && pwm->tcp->fd == -1) -#else if (pwm->fd == -1) -#endif return FINISH (GPG_ERR_INV_STATE); - if (pwm->fd != 1) - disconnect (pwm); - + disconnect (pwm); reset_handle (pwm); return 0; } @@ -981,6 +972,14 @@ pwmd_process (pwm_t * pwm) while (!rc && assuan_pending_line (pwm->ctx)) rc = parse_assuan_line (pwm); +#if defined (WITH_SSH) || defined (WITH_GNUTLS) + if (gpg_err_code (rc) == GPG_ERR_EOF && pwm->tcp) + { + close (pwm->fd); + pwm->fd = -1; + } +#endif + return FINISH (rc); } @@ -1184,20 +1183,8 @@ pwmd_socket_type (pwm_t * pwm, pwmd_socket_t * result) *result = PWMD_SOCKET_LOCAL; -#if defined(WITH_SSH) || defined(WITH_GNUTLS) - if ((pwm->fd == -1 && (!pwm->tcp -#ifdef WITH_SSH - || !pwm->tcp->ssh -#endif -#ifdef WITH_GNUTLS - || !pwm->tcp->tls -#endif - )) || (pwm->fd == -1 && pwm->tcp && pwm->tcp->fd == -1)) - return FINISH (GPG_ERR_INV_STATE); -#else if (pwm->fd == -1) return FINISH (GPG_ERR_INV_STATE); -#endif #if defined(WITH_SSH) || defined(WITH_GNUTLS) #ifdef WITH_SSH @@ -1627,17 +1614,9 @@ pwmd_fd (pwm_t * pwm, int *fd) if (!pwm || !fd) return FINISH (GPG_ERR_INV_ARG); -#if defined(WITH_SSH) || defined(WITH_GNUTLS) - if (pwm->tcp && pwm->tcp->fd == -1 && pwm->fd == -1) - return GPG_ERR_INV_STATE; - - *fd = pwm->tcp && pwm->tcp->fd != -1 ? pwm->tcp->fd : pwm->fd; -#else if (pwm->fd == -1) return FINISH (GPG_ERR_INV_STATE); *fd = pwm->fd; -#endif - return 0; } diff --git a/src/ssh.c b/src/ssh.c index e3887e3f..51402b44 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -149,7 +149,6 @@ _free_ssh_conn (struct ssh_s *ssh) if (!ssh) return; - pwmd_free (ssh->fd); ssh->fd = NULL; pwmd_free (ssh->username); ssh->username = NULL; @@ -648,7 +647,7 @@ _setup_ssh_shell (pwm_t * pwm) static gpg_error_t ssh_connect_finalize (pwm_t * pwm) { - return assuan_socket_connect_fd (pwm->ctx, pwm->tcp->fd, 0); + return assuan_socket_connect_fd (pwm->ctx, pwm->fd, 0); } static gpg_error_t @@ -658,7 +657,7 @@ _setup_ssh_init (pwm_t * pwm) do { - n = libssh2_session_handshake (pwm->tcp->ssh->session, pwm->tcp->fd); + n = libssh2_session_handshake (pwm->tcp->ssh->session, pwm->fd); if (n == LIBSSH2_ERROR_EAGAIN) usleep (50000); } @@ -723,10 +722,8 @@ _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; - pwmd_free (pwm->tcp->ssh->fd); - pwm->tcp->ssh->fd = pwmd_malloc (sizeof(int)); - *pwm->tcp->ssh->fd = pwm->tcp->fd; rc = _setup_ssh_session (pwm); fail: diff --git a/src/tls.c b/src/tls.c index aca3659c..1a25e63b 100644 --- a/src/tls.c +++ b/src/tls.c @@ -62,7 +62,6 @@ tls_free (struct tls_s *tls) if (!tls) return; - pwmd_free (tls->fd); pwmd_free (tls->ca); pwmd_free (tls->cert); pwmd_free (tls->key); @@ -371,8 +370,8 @@ tls_init (pwm_t * pwm) } gnutls_transport_set_ptr (pwm->tcp->tls->session, - (gnutls_transport_ptr_t) pwm->tcp->fd); - fcntl (pwm->tcp->fd, F_SETFL, O_NONBLOCK); + (gnutls_transport_ptr_t) pwm->fd); + fcntl (pwm->fd, F_SETFL, O_NONBLOCK); time_t start = time (NULL); do { @@ -485,10 +484,8 @@ _do_tls_connect (pwm_t * pwm, const char *host, int port, rc = tls_init (pwm); if (!rc) { - pwmd_free (pwm->tcp->tls->fd); - pwm->tcp->tls->fd = pwmd_malloc (sizeof(int)); - *pwm->tcp->tls->fd = pwm->tcp->fd; - rc = assuan_socket_connect_fd (pwm->ctx, pwm->tcp->fd, 0); + pwm->tcp->fd = pwm->tcp->tls->fd = &pwm->fd; + rc = assuan_socket_connect_fd (pwm->ctx, pwm->fd, 0); } } diff --git a/src/types.h b/src/types.h index ace2a219..fc3150f1 100644 --- a/src/types.h +++ b/src/types.h @@ -57,7 +57,7 @@ struct tcp_s { char *host; unsigned port; - int fd; + int *fd; gpg_error_t rc; struct addrinfo *addrs; struct addrinfo *addr; -- 2.11.4.GIT