aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <[email protected]>2015-11-18 14:06:48 +0000
committerJustus Winter <[email protected]>2015-11-18 14:06:48 +0000
commiteb54fca4bf3ef8e0cd50b01df5b40e0d6d318d7e (patch)
tree18917c92bd1bdb4f8c8180bca75f4eaee2605fae
parenttools: Fix option parsing for gpg-zip. (diff)
downloadgnupg-fix-1950.tar.gz
gnupg-fix-1950.zip
dirmngr: Gracefully handle premature termination of TLS streams.fix-1950
* dirmngr/http.c (close_tls_session): New function. (session_unref): Use the new function to close the TLS stream. (cookie_read): If the stream terminated prematurely, close it and return a short read. -- With this patch, I was able to update all the keys in the Debian keyring over hkps. Signed-off-by: Justus Winter <[email protected]> GnuPG-bug-id: 1950
-rw-r--r--dirmngr/http.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/dirmngr/http.c b/dirmngr/http.c
index e33a59436..60dc45f4d 100644
--- a/dirmngr/http.c
+++ b/dirmngr/http.c
@@ -511,6 +511,27 @@ http_register_tls_ca (const char *fname)
}
+#ifdef USE_TLS
+/* Free the TLS session associated with SESS, if any. */
+static void
+close_tls_session (http_session_t sess)
+{
+ if (sess->tls_session)
+ {
+# ifdef HTTP_USE_GNUTLS
+ my_socket_t sock = gnutls_transport_get_ptr (sess->tls_session);
+ my_socket_unref (sock, NULL, NULL);
+ gnutls_deinit (sess->tls_session);
+ if (sess->certcred)
+ gnutls_certificate_free_credentials (sess->certcred);
+# endif /*HTTP_USE_GNUTLS*/
+ xfree (sess->servername);
+ sess->tls_session = NULL;
+ }
+}
+#endif /*USE_TLS*/
+
+
/* Release a session. Take care not to release it while it is being
used by a http context object. */
static void
@@ -527,17 +548,7 @@ session_unref (int lnr, http_session_t sess)
return;
#ifdef USE_TLS
-# ifdef HTTP_USE_GNUTLS
- if (sess->tls_session)
- {
- my_socket_t sock = gnutls_transport_get_ptr (sess->tls_session);
- my_socket_unref (sock, NULL, NULL);
- gnutls_deinit (sess->tls_session);
- }
- if (sess->certcred)
- gnutls_certificate_free_credentials (sess->certcred);
-# endif /*HTTP_USE_GNUTLS*/
- xfree (sess->servername);
+ close_tls_session (sess);
#endif /*USE_TLS*/
xfree (sess);
@@ -2447,6 +2458,13 @@ cookie_read (void *cookie, void *buffer, size_t size)
}
if (nread == GNUTLS_E_REHANDSHAKE)
goto again; /* A client is allowed to just ignore this request. */
+ if (nread == GNUTLS_E_PREMATURE_TERMINATION)
+ {
+ /* The server terminated the connection. Close the TLS
+ session, and indicate EOF using a short read. */
+ close_tls_session (c->session);
+ return 0;
+ }
log_info ("TLS network read failed: %s\n", gnutls_strerror (nread));
gpg_err_set_errno (EIO);
return -1;