Skip to content

Commit

Permalink
Drop proxy connection and reconnect when auth fails
Browse files Browse the repository at this point in the history
My squid proxy is fairly picky; when one type of authentication fails and
we need to fall back to the next, it doesn't work. Unless we drop the
connection completely and retry.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Jun 20, 2014
1 parent eb41c18 commit 9e50ba4
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 19 deletions.
2 changes: 1 addition & 1 deletion digest.c
Expand Up @@ -96,7 +96,7 @@ int digest_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *h

if (vpninfo->digest_auth.state == AUTH_IN_PROGRESS) {
vpninfo->digest_auth.state = AUTH_FAILED;
return -EINVAL;
return -EAGAIN;
}

chall = vpninfo->digest_auth.challenge;
Expand Down
2 changes: 1 addition & 1 deletion gssapi.c
Expand Up @@ -102,7 +102,7 @@ int gssapi_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *h
vpninfo->gssapi_auth.state = AUTH_FAILED;
gss_release_name(&minor, &vpninfo->gss_target_name);
gss_delete_sec_context(&minor, &vpninfo->gss_context, GSS_C_NO_BUFFER);
return -EIO;
return -EAGAIN;
}
buf_append(hdrbuf, "Proxy-Authorization: Negotiate ");
buf_append_base64(hdrbuf, out.value, out.length);
Expand Down
25 changes: 16 additions & 9 deletions http.c
Expand Up @@ -1658,19 +1658,26 @@ void buf_append_base64(struct oc_text_buf *buf, const void *bytes, int len)
/* Generate Proxy-Authorization: header for request if appropriate */
static int proxy_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *buf)
{
int ret;
#ifdef HAVE_GSSAPI
if (vpninfo->gssapi_auth.state > AUTH_UNSEEN &&
!gssapi_authorization(vpninfo, buf))
return 0;
if (vpninfo->gssapi_auth.state > AUTH_UNSEEN) {
ret = gssapi_authorization(vpninfo, buf);
if (ret == -EAGAIN || !ret)
return ret;
}
#endif

if (vpninfo->ntlm_auth.state > AUTH_UNSEEN &&
!ntlm_authorization(vpninfo, buf))
return 0;
if (vpninfo->ntlm_auth.state > AUTH_UNSEEN) {
ret = ntlm_authorization(vpninfo, buf);
if (ret == -EAGAIN || !ret)
return ret;
}

if (vpninfo->digest_auth.state > AUTH_UNSEEN &&
!digest_authorization(vpninfo, buf))
return 0;
if (vpninfo->digest_auth.state > AUTH_UNSEEN) {
ret = digest_authorization(vpninfo, buf);
if (ret == -EAGAIN || !ret)
return ret;
}

if (vpninfo->basic_auth.state == AUTH_AVAILABLE &&
vpninfo->proxy_user && vpninfo->proxy_pass) {
Expand Down
20 changes: 12 additions & 8 deletions ntlm.c
Expand Up @@ -142,7 +142,7 @@ static int ntlm_helper_challenge(struct openconnect_info *vpninfo, struct oc_tex
err:
close(vpninfo->ntlm_helper_fd);
vpninfo->ntlm_helper_fd = -1;
return -EIO;
return -EAGAIN;
}
len = read(vpninfo->ntlm_helper_fd, helperbuf, sizeof(helperbuf));
if (len < 4 || helperbuf[0] != 'K' || helperbuf[1] != 'K' ||
Expand Down Expand Up @@ -939,9 +939,11 @@ int ntlm_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *buf
}
}
if (vpninfo->ntlm_auth.state == NTLM_SSO_REQ) {
int ret;
vpninfo->ntlm_auth.state = NTLM_MANUAL;
if (!ntlm_helper_challenge(vpninfo, buf))
return 0;
ret = ntlm_helper_challenge(vpninfo, buf);
if (!ret || ret == -EAGAIN)
return ret;
#endif
}
if (vpninfo->ntlm_auth.state == NTLM_MANUAL && vpninfo->proxy_user &&
Expand All @@ -951,10 +953,12 @@ int ntlm_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *buf
vpninfo->ntlm_auth.state = NTLM_MANUAL_REQ;
return 0;
}
if (vpninfo->ntlm_auth.state == NTLM_MANUAL_REQ) {
vpninfo->ntlm_auth.state = AUTH_FAILED;
return ntlm_manual_challenge(vpninfo, buf);

if (vpninfo->ntlm_auth.state == NTLM_MANUAL_REQ &&
!ntlm_manual_challenge(vpninfo, buf)) {
/* Leave the state as it is. If we come back there'll be no
challenge string and we'll fail then. */
return 0;
}
return -EINVAL;
vpninfo->ntlm_auth.state = AUTH_FAILED;
return -EAGAIN;
}
7 changes: 7 additions & 0 deletions ssl.c
Expand Up @@ -113,6 +113,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
vpninfo->port = 443;

if (vpninfo->peer_addr) {
reconnect:
#ifdef SOCK_CLOEXEC
ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP);
if (ssl_sock < 0)
Expand Down Expand Up @@ -299,6 +300,12 @@ int connect_https_socket(struct openconnect_info *vpninfo)
err = process_proxy(vpninfo, ssl_sock);
if (err) {
closesocket(ssl_sock);
if (err == -EAGAIN) {
/* Proxy authentication failed and we need to retry */
vpn_progress(vpninfo, PRG_DEBUG,
_("Reconnecting to proxy %s\n"), vpninfo->proxy);
goto reconnect;
}
return err;
}
}
Expand Down

0 comments on commit 9e50ba4

Please sign in to comment.