]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Canonicalise hostname during authentication if necessary
authorDavid Woodhouse <David.Woodhouse@intel.com>
Mon, 4 Feb 2013 15:57:35 +0000 (15:57 +0000)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Wed, 13 Feb 2013 21:02:54 +0000 (21:02 +0000)
Some people have round-robin servers, all addressed by the same hostname
but with different SSL certificates. Where we do the authentication (and
user-interactive approval of certificates) from a GUI via libopenconnect,
or with 'openconnect --authenticate', we end up being given the SHA1 on
the server's certificate and the non-interactive connection is going to
expect to see exactly that certificate. So if there is more than one
result in the original DNS lookup, *change* vpninfo->hostname to hold
the IP address that we actually connected to.

This means that the Host: header in what we send will be the numeric IP
address instead of the hostname, but that doesn't seem to hurt. It could
potentially, theoretically, break virtual hosts but I don't think that
kind of setup could ever existing in practice.

This also works only in the case where we're *not* connecting via a proxy.
We currently let the proxy do the DNS lookups *for* us, and we'd have to
do them locally and then ask the proxy for a connection by IP address
even for the *first* connection.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
(cherry picked from commit b0b4b34f5b3b397db1558c7c2c0b358db07c9964
 and subsequent fix commit 3e6ecfa511ab29ed83aac6fc3a96080fffdf1635)

ssl.c

diff --git a/ssl.c b/ssl.c
index e9916fbe0f15d9cc13f097bc9f09ec245c7efc73..fb48d969d36ff9111c4cc368090a093f55902b0b 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -220,6 +220,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
                for (rp = result; rp ; rp = rp->ai_next) {
                        char host[80];
 
+                       host[0] = 0;
                        if (!getnameinfo(rp->ai_addr, rp->ai_addrlen, host,
                                         sizeof(host), NULL, 0, NI_NUMERICHOST))
                                vpn_progress(vpninfo, PRG_INFO, vpninfo->proxy_type?
@@ -246,6 +247,23 @@ int connect_https_socket(struct openconnect_info *vpninfo)
                                }
                                vpninfo->peer_addrlen = rp->ai_addrlen;
                                memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
+                               /* If no proxy, and if more than one address for the hostname,
+                                  ensure that we output the same IP address in authentication
+                                  results (from libopenconnect or --authenticate). */
+                               if (!vpninfo->proxy && (rp != result || rp->ai_next) && host[0]) {
+                                       char *p = malloc(strlen(host) + 3);
+                                       if (p) {
+                                               free(vpninfo->hostname);
+                                               vpninfo->hostname = p;
+                                               if (rp->ai_family == AF_INET6)
+                                                       *p++ = '[';
+                                               memcpy(p, host, strlen(host));
+                                               p += strlen(host);
+                                               if (rp->ai_family == AF_INET6)
+                                                       *p++ = ']';
+                                               *p = 0;
+                                       }
+                               }
                                break;
                        }
                        close(ssl_sock);