Commit b0b4b34f authored by David Woodhouse's avatar David Woodhouse

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: default avatarDavid Woodhouse <>
parent c86d7e0d
......@@ -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,27 @@ 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) + 9);
if (p) {
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++ = ']';
if (vpninfo->port != 443)
snprintf(p, 7, ":%d", vpninfo->port);
*p = 0;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment