From 173c3143d6bb3856e7e68f50f06b6aca43551f93 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 4 Feb 2013 15:57:35 +0000 Subject: [PATCH] Canonicalise hostname during authentication if necessary 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 (cherry picked from commit b0b4b34f5b3b397db1558c7c2c0b358db07c9964 and subsequent fix commit 3e6ecfa511ab29ed83aac6fc3a96080fffdf1635) --- ssl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ssl.c b/ssl.c index e9916fbe..fb48d969 100644 --- 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);