Commit 091cd79d authored by David Woodhouse's avatar David Woodhouse

Honour Proxy-Connection: close during authentication

Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 4af79106
......@@ -1879,6 +1879,12 @@ static int proxy_hdrs(struct openconnect_info *vpninfo, char *hdr, char *val)
{
int i;
if (!strcasecmp(hdr, "Proxy-Connection")) {
if (!strcasecmp(val, "close"))
vpninfo->proxy_close_during_auth = 1;
return 0;
}
if (strcasecmp(hdr, "Proxy-Authenticate"))
return 0;
......@@ -1919,7 +1925,9 @@ static int process_http_proxy(struct openconnect_info *vpninfo)
int resplen;
struct oc_text_buf *reqbuf;
int result;
int auth = 0;
int auth = vpninfo->proxy_close_during_auth;
vpninfo->proxy_close_during_auth = 0;
vpn_progress(vpninfo, PRG_INFO,
_("Requesting HTTP proxy connection to %s:%d\n"),
......@@ -1973,6 +1981,10 @@ static int process_http_proxy(struct openconnect_info *vpninfo)
}
if (result == 407) {
/* If the proxy asked us to close the connection, do so */
if (vpninfo->proxy_close_during_auth)
return -EAGAIN;
auth = 1;
goto retry;
}
......@@ -1985,9 +1997,17 @@ static int process_http_proxy(struct openconnect_info *vpninfo)
return -EIO;
}
void cleanup_proxy_auth(struct openconnect_info *vpninfo)
{
int i;
for (i = 0; i < sizeof(auth_methods) / sizeof(auth_methods[0]); i++)
clear_auth_state(vpninfo, &auth_methods[i], 1);
}
int process_proxy(struct openconnect_info *vpninfo, int ssl_sock)
{
int ret, i;
int ret;
vpninfo->proxy_fd = ssl_sock;
vpninfo->ssl_read = proxy_read;
......@@ -2006,8 +2026,9 @@ int process_proxy(struct openconnect_info *vpninfo, int ssl_sock)
}
vpninfo->proxy_fd = -1;
for (i = 0; i < sizeof(auth_methods) / sizeof(auth_methods[0]); i++)
clear_auth_state(vpninfo, &auth_methods[i], 1);
if (!vpninfo->proxy_close_during_auth)
cleanup_proxy_auth(vpninfo);
return ret;
}
......
......@@ -206,6 +206,7 @@ struct openconnect_info {
int proxy_fd;
char *proxy_user;
char *proxy_pass;
int proxy_close_during_auth;
struct proxy_auth_state auth[MAX_AUTH_TYPES];
#ifdef HAVE_GSSAPI
gss_name_t gss_target_name;
......@@ -610,6 +611,7 @@ void *openconnect_base64_decode(int *len, const char *in);
int buf_error(struct oc_text_buf *buf);
int buf_free(struct oc_text_buf *buf);
char *openconnect_create_useragent(const char *base);
void cleanup_proxy_auth(struct openconnect_info *vpninfo);
int process_proxy(struct openconnect_info *vpninfo, int ssl_sock);
int internal_parse_url(char *url, char **res_proto, char **res_host,
int *res_port, char **res_path, int default_port);
......
......@@ -139,7 +139,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
}
if (ssl_sock >= 0)
closesocket(ssl_sock);
return -EINVAL;
ssl_sock = -EINVAL;
goto out;
}
} else {
struct addrinfo hints, *result, *rp;
......@@ -176,8 +177,10 @@ int connect_https_socket(struct openconnect_info *vpninfo)
else
i = asprintf(&url, "https://%s:%d/%s", vpninfo->hostname,
vpninfo->port, vpninfo->urlpath?:"");
if (i == -1)
return -ENOMEM;
if (i == -1) {
ssl_sock = -ENOMEM;
goto out;
}
proxies = px_proxy_factory_get_proxies(vpninfo->proxy_factory,
url);
......@@ -211,8 +214,10 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (hostname[0] == '[' && hostname[strlen(hostname)-1] == ']') {
hostname = strndup(hostname + 1, strlen(hostname) - 2);
if (!hostname)
return -ENOMEM;
if (!hostname) {
ssl_sock = -ENOMEM;
goto out;
}
hints.ai_flags |= AI_NUMERICHOST;
}
......@@ -224,7 +229,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
hostname, gai_strerror(err));
if (hints.ai_flags & AI_NUMERICHOST)
free(hostname);
return -EINVAL;
ssl_sock = -EINVAL;
goto out;
}
if (hints.ai_flags & AI_NUMERICHOST)
free(hostname);
......@@ -256,7 +262,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
vpn_progress(vpninfo, PRG_ERR,
_("Failed to allocate sockaddr storage\n"));
closesocket(ssl_sock);
return -ENOMEM;
ssl_sock = -ENOMEM;
goto out;
}
vpninfo->peer_addrlen = rp->ai_addrlen;
memcpy(vpninfo->peer_addr, rp->ai_addr, rp->ai_addrlen);
......@@ -288,7 +295,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
vpn_progress(vpninfo, PRG_ERR,
_("Failed to connect to host %s\n"),
vpninfo->proxy?:vpninfo->hostname);
return -EINVAL;
ssl_sock = -EINVAL;
goto out;
}
}
......@@ -302,10 +310,13 @@ int connect_https_socket(struct openconnect_info *vpninfo)
_("Reconnecting to proxy %s\n"), vpninfo->proxy);
goto reconnect;
}
return err;
ssl_sock = err;
}
}
out:
/* If proxy processing returned -EAGAIN to reconnect before attempting
further auth, and we failed to reconnect, we have to clean up here. */
cleanup_proxy_auth(vpninfo);
return ssl_sock;
}
......
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