Don't unregister p11-kit PIN callback until vpninfo is finished with
authorDavid Woodhouse <David.Woodhouse@intel.com>
Sat, 9 Jun 2012 16:06:09 +0000 (17:06 +0100)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Sat, 9 Jun 2012 20:05:05 +0000 (21:05 +0100)
Unregistering in openconnect_close_https() meant that when we reconnect to
the server, we lose the PIN callback. And then when we connect again, if
GnuTLS is asking us for the PIN on every attempt to touch the key, we fail
because there's no PIN handler.

So add a 'final' flag to openconnect_close_https(). Use this to clean up
library.c::openconnect_close_https() a little, too.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
cstp.c
gnutls.c
http.c
library.c
openconnect-internal.h
openssl.c

diff --git a/cstp.c b/cstp.c
index d799f15..792c17e 100644 (file)
--- a/cstp.c
+++ b/cstp.c
@@ -230,7 +230,7 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
                             _("Error fetching HTTPS response\n"));
                if (!retried) {
                        retried = 1;
-                       openconnect_close_https(vpninfo);
+                       openconnect_close_https(vpninfo, 0);
 
                        if (openconnect_open_https(vpninfo)) {
                                vpn_progress(vpninfo, PRG_ERR,
@@ -526,7 +526,7 @@ int cstp_reconnect(struct openconnect_info *vpninfo)
        int timeout;
        int interval;
 
-       openconnect_close_https(vpninfo);
+       openconnect_close_https(vpninfo, 0);
 
        /* Requeue the original packet that was deflated */
        if (vpninfo->current_ssl_pkt == vpninfo->deflate_pkt) {
index eaa4275..7476564 100644 (file)
--- a/gnutls.c
+++ b/gnutls.c
@@ -1056,17 +1056,8 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
        return 0;
 }
 
-void openconnect_close_https(struct openconnect_info *vpninfo)
+void openconnect_close_https(struct openconnect_info *vpninfo, int final)
 {
-#ifdef HAVE_P11KIT
-       if (!strncmp(vpninfo->cert, "pkcs11:", 7)) {
-               char pin_source[40];
-
-               sprintf(pin_source, "openconnect:%p", vpninfo);
-               p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
-       }
-#endif
-
        if (vpninfo->peer_cert) {
                gnutls_x509_crt_deinit(vpninfo->peer_cert);
                vpninfo->peer_cert = NULL;
@@ -1082,6 +1073,18 @@ void openconnect_close_https(struct openconnect_info *vpninfo)
                FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
                vpninfo->ssl_fd = -1;
        }
+       if (final && vpninfo->https_cred) {
+               gnutls_certificate_free_credentials(vpninfo->https_cred);
+               vpninfo->https_cred = NULL;
+#ifdef HAVE_P11KIT
+               if (!strncmp(vpninfo->cert, "pkcs11:", 7)) {
+                       char pin_source[40];
+
+                       sprintf(pin_source, "openconnect:%p", vpninfo);
+                       p11_kit_pin_unregister_callback(pin_source, pin_callback, vpninfo);
+               }
+#endif
+       }
 }
 
 void openconnect_init_ssl(void)
diff --git a/http.c b/http.c
index 68a15a3..e8ef020 100644 (file)
--- a/http.c
+++ b/http.c
@@ -335,7 +335,7 @@ static int process_http_response(struct openconnect_info *vpninfo, int *result,
        }
 
        if (closeconn || vpninfo->no_http_keepalive)
-               openconnect_close_https(vpninfo);
+               openconnect_close_https(vpninfo, 0);
 
        if (body)
                body[done] = 0;
@@ -728,7 +728,7 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
                                /* Kill the existing connection, and a new one will happen */
                                free(vpninfo->peer_addr);
                                vpninfo->peer_addr = NULL;
-                               openconnect_close_https(vpninfo);
+                               openconnect_close_https(vpninfo, 0);
 
                                for (opt = vpninfo->cookies; opt; opt = next) {
                                        next = opt->next;
index 0b4eae8..92b7c25 100644 (file)
--- a/library.c
+++ b/library.c
@@ -171,23 +171,11 @@ void openconnect_clear_cookie (struct openconnect_info *vpninfo)
 
 void openconnect_reset_ssl (struct openconnect_info *vpninfo)
 {
-       openconnect_close_https(vpninfo);
+       openconnect_close_https(vpninfo, 1);
        if (vpninfo->peer_addr) {
                free(vpninfo->peer_addr);
                vpninfo->peer_addr = NULL;
        }
-#if defined (OPENCONNECT_OPENSSL)
-       if (vpninfo->https_ctx) {
-               SSL_CTX_free(vpninfo->https_ctx);
-               vpninfo->https_ctx = NULL;
-       }
-#elif defined (OPENCONNECT_GNUTLS)
-       if (vpninfo->https_cred) {
-               gnutls_certificate_free_credentials(vpninfo->https_cred);
-               vpninfo->https_cred = NULL;
-       }
-#endif
-
 }
 
 int openconnect_parse_url (struct openconnect_info *vpninfo, char *url)
index fafd8f3..ac6ffe4 100644 (file)
@@ -321,7 +321,7 @@ int openconnect_SSL_gets(struct openconnect_info *vpninfo, char *buf, size_t len
 int openconnect_SSL_write(struct openconnect_info *vpninfo, char *buf, size_t len);
 int openconnect_SSL_read(struct openconnect_info *vpninfo, char *buf, size_t len);
 int openconnect_open_https(struct openconnect_info *vpninfo);
-void openconnect_close_https(struct openconnect_info *vpninfo);
+void openconnect_close_https(struct openconnect_info *vpninfo, int final);
 int get_cert_md5_fingerprint(struct openconnect_info *vpninfo, OPENCONNECT_X509 *cert,
                             char *buf);
 /* This one is actually OpenSSL-specific */
index 5765358..ab18cf9 100644 (file)
--- a/openssl.c
+++ b/openssl.c
@@ -1283,7 +1283,7 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
        return 0;
 }
 
-void openconnect_close_https(struct openconnect_info *vpninfo)
+void openconnect_close_https(struct openconnect_info *vpninfo, int final)
 {
        if (vpninfo->peer_cert) {
                X509_free(vpninfo->peer_cert);
@@ -1300,6 +1300,10 @@ void openconnect_close_https(struct openconnect_info *vpninfo)
                FD_CLR(vpninfo->ssl_fd, &vpninfo->select_efds);
                vpninfo->ssl_fd = -1;
        }
+       if (final && vpninfo->https_ctx) {
+               SSL_CTX_free(vpninfo->https_ctx);
+               vpninfo->https_ctx = NULL;
+       }
 }
 
 void openconnect_init_ssl(void)