diff --git a/http.c b/http.c index 2ae4b01a..8e13235f 100644 --- a/http.c +++ b/http.c @@ -693,6 +693,12 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo) if (result < 0) return result; + /* Remember the peer's SSL certificate; it may disconnect during + the response and then we wouldn't be able to find it */ + if (vpninfo->peer_cert) + X509_free(vpninfo->peer_cert); + vpninfo->peer_cert = SSL_get_peer_certificate(vpninfo->https_ssl); + buflen = process_http_response(vpninfo, &result, NULL, &form_buf); if (buflen < 0) { /* We'll already have complained about whatever offended us */ diff --git a/library.c b/library.c index 4a90a6c8..3e79b7f2 100644 --- a/library.c +++ b/library.c @@ -99,6 +99,8 @@ void openconnect_vpninfo_free (struct openconnect_info *vpninfo) if (vpninfo->cert != vpninfo->sslkey) free((void *)vpninfo->sslkey); free((void *)vpninfo->cert); + if (vpninfo->peer_cert) + X509_free(vpninfo->peer_cert); /* No need to free deflate streams; they weren't initialised */ free(vpninfo); } @@ -154,7 +156,7 @@ void openconnect_set_client_cert (struct openconnect_info *vpninfo, char *cert, struct x509_st *openconnect_get_peer_cert (struct openconnect_info *vpninfo) { - return SSL_get_peer_certificate(vpninfo->https_ssl); + return vpninfo->peer_cert; } int openconnect_get_port (struct openconnect_info *vpninfo) diff --git a/openconnect-internal.h b/openconnect-internal.h index fd1bb1a7..5f532eb7 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -135,6 +135,8 @@ struct openconnect_info { int uid_csd_given; int no_http_keepalive; + X509 *peer_cert; + char *cookie; /* Pointer to within cookies list */ struct vpn_option *cookies; struct vpn_option *cstp_options; diff --git a/openconnect.h b/openconnect.h index defefe3e..13f0757d 100644 --- a/openconnect.h +++ b/openconnect.h @@ -146,7 +146,13 @@ void openconnect_set_xmlsha1 (struct openconnect_info *, char *, int size); void openconnect_set_cafile (struct openconnect_info *, char *); void openconnect_setup_csd (struct openconnect_info *, uid_t, int silent, char *wrapper); void openconnect_set_client_cert (struct openconnect_info *, char *cert, char *sslkey); + +/* This is *not* yours and must not be destroyed with X509_free(). It + * will be valid when a cookie has been obtained successfully, and will + * be valid until the connection is destroyed or another attempt it made + * to use it. */ struct x509_st *openconnect_get_peer_cert (struct openconnect_info *); + int openconnect_get_port (struct openconnect_info *); char *openconnect_get_cookie (struct openconnect_info *); void openconnect_clear_cookie (struct openconnect_info *); diff --git a/ssl.c b/ssl.c index b322baf5..22e968bc 100644 --- a/ssl.c +++ b/ssl.c @@ -1293,6 +1293,10 @@ int openconnect_open_https(struct openconnect_info *vpninfo) void openconnect_close_https(struct openconnect_info *vpninfo) { + if (vpninfo->peer_cert) { + X509_free(vpninfo->peer_cert); + vpninfo->peer_cert = NULL; + } SSL_free(vpninfo->https_ssl); vpninfo->https_ssl = NULL; close(vpninfo->ssl_fd); diff --git a/www/changelog.xml b/www/changelog.xml index 6f2f26fb..c9abf6af 100644 --- a/www/changelog.xml +++ b/www/changelog.xml @@ -17,7 +17,7 @@