]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Fix hostname canonicalisation to stop breaking certifcate checks
authorDavid Woodhouse <David.Woodhouse@intel.com>
Fri, 22 Feb 2013 12:42:07 +0000 (12:42 +0000)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Fri, 22 Feb 2013 12:55:24 +0000 (12:55 +0000)
Commit b0b4b34f ('Canonicalise hostname during authentication if necessary')
replaces the hostname with a bare IP address if necessary, so that
reconnecting is guaranteed to get the *same* host from a round-robin and
comparing the SSL cert with its previous SHA1 fingerprint (which is how we
do it for two-stage connection for example from NetworkManager) is
guaranteed to work.

However, this breaks certificate auth when invoked in one-stage mode from
the command line to authenticate *and* actually make the connection. When
vpninfo->hostname is replaced with a bare IP address, that might not
actually be what's listed in the certificate's Subject or Altname fields.
So users have reported a certificate validation failure on *reconnecting*
to the server which was acceptable the first time round when we looked it
up by name.

So, don't actually replace vpninfo->hostname at all. Introduce a new field
vpninfo->unique_hostname which is returned by openconnect_get_hostname(),
and leave vpninfo->hostname as it was.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
http.c
library.c
main.c
openconnect-internal.h
ssl.c
www/changelog.xml

diff --git a/http.c b/http.c
index 9b77be58b330d8986e9d597ae1c949d280b7f227..9bdc9d9dcce8798b4c50c3ee8bb9284bf8e89f0e 100644 (file)
--- a/http.c
+++ b/http.c
@@ -738,6 +738,8 @@ static int handle_redirect(struct openconnect_info *vpninfo)
                }
 
                if (strcasecmp(vpninfo->hostname, host) || port != vpninfo->port) {
+                       free(vpninfo->unique_hostname);
+                       vpninfo->unique_hostname = NULL;
                        free(vpninfo->hostname);
                        vpninfo->hostname = host;
                        vpninfo->port = port;
index 73e7c5416ec2523ab96c205391c076630e098aa8..be4b119dd1595680188b3171f716eb6966b7e88d 100644 (file)
--- a/library.c
+++ b/library.c
@@ -151,12 +151,15 @@ void openconnect_vpninfo_free (struct openconnect_info *vpninfo)
 
 char *openconnect_get_hostname (struct openconnect_info *vpninfo)
 {
-       return vpninfo->hostname;
+       return vpninfo->unique_hostname?:vpninfo->hostname;
 }
 
 void openconnect_set_hostname (struct openconnect_info *vpninfo, char *hostname)
 {
+       free(vpninfo->hostname);
        vpninfo->hostname = hostname;
+       free(vpninfo->unique_hostname);
+       vpninfo->unique_hostname = NULL;
 }
 
 char *openconnect_get_urlpath (struct openconnect_info *vpninfo)
@@ -240,6 +243,8 @@ int openconnect_parse_url (struct openconnect_info *vpninfo, char *url)
 
        free(vpninfo->hostname);
        vpninfo->hostname = NULL;
+       free(vpninfo->unique_hostname);
+       vpninfo->unique_hostname = NULL;
        free(vpninfo->urlpath);
        vpninfo->urlpath = NULL;
 
diff --git a/main.c b/main.c
index 258932fbc494c23795912a763e57b1a6b4308e78..d40207bb1dd855780fb68152e1505353c9bedeaf 100644 (file)
--- a/main.c
+++ b/main.c
@@ -809,7 +809,7 @@ int main(int argc, char **argv)
        if (cookieonly == 3) {
                /* --authenticate */
                printf("COOKIE='%s'\n", vpninfo->cookie);
-               printf("HOST='%s'\n", vpninfo->hostname);
+               printf("HOST='%s'\n", openconnect_get_hostname(vpninfo));
                if (vpninfo->peer_cert) {
                        char buf[41] = {0, };
                        openconnect_get_cert_sha1(vpninfo, vpninfo->peer_cert, buf);
index ff1b80bfedbcea99ca6b3d638274c1bc5f2e0509..a35e798bf65767a9253bcec62b53c0aabdb83e4a 100644 (file)
@@ -158,6 +158,7 @@ struct openconnect_info {
 
        const char *localname;
        char *hostname;
+       char *unique_hostname;
        int port;
        char *urlpath;
        int cert_expire_warning;
diff --git a/ssl.c b/ssl.c
index d6a551a444107e34a2cdc15dfda3dc8d0bf6a0d5..4d00d19f70cbff02c3c0fdc9425fcb324d130246 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -253,8 +253,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
                                if (!vpninfo->proxy && (rp != result || rp->ai_next) && host[0]) {
                                        char *p = malloc(strlen(host) + 3);
                                        if (p) {
-                                               free(vpninfo->hostname);
-                                               vpninfo->hostname = p;
+                                               free(vpninfo->unique_hostname);
+                                               vpninfo->unique_hostname = p;
                                                if (rp->ai_family == AF_INET6)
                                                        *p++ = '[';
                                                memcpy(p, host, strlen(host));
index e8f9901976988458877eda3f86e8e155d8d2e72e..be07c95c02273a4251bde45f68f418ad6b3be75e 100644 (file)
@@ -21,6 +21,7 @@
        <li>Avoid using deprecated <tt>gnutls_pubkey_verify_data()</tt> function.</li>
        <li>Fix compatibility issues with XML POST authentication.</li>
        <li>Fix memory leaks on <tt>realloc()</tt> failure.</li>
+       <li>Fix certificate validation problem caused by hostname canonicalisation.</li>
      </ul><br/>
   </li>
   <li><b><a href="ftp://ftp.infradead.org/pub/openconnect/openconnect-4.99.tar.gz">OpenConnect v4.99</a></b>