Commit 74f9d130 authored by David Woodhouse's avatar David Woodhouse

Use an array of auth states

Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 32570e6d
......@@ -91,15 +91,15 @@ int digest_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *h
if (!vpninfo->proxy_user || !vpninfo->proxy_pass)
return -EINVAL;
if (vpninfo->digest_auth.state < AUTH_AVAILABLE)
if (vpninfo->auth[AUTH_TYPE_DIGEST].state < AUTH_AVAILABLE)
return -EINVAL;
if (vpninfo->digest_auth.state == AUTH_IN_PROGRESS) {
vpninfo->digest_auth.state = AUTH_FAILED;
if (vpninfo->auth[AUTH_TYPE_DIGEST].state == AUTH_IN_PROGRESS) {
vpninfo->auth[AUTH_TYPE_DIGEST].state = AUTH_FAILED;
return -EAGAIN;
}
chall = vpninfo->digest_auth.challenge;
chall = vpninfo->auth[AUTH_TYPE_DIGEST].challenge;
if (!chall)
return -EINVAL;
......@@ -226,7 +226,7 @@ int digest_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *h
ret = 0;
vpninfo->digest_auth.state = AUTH_IN_PROGRESS;
vpninfo->auth[AUTH_TYPE_DIGEST].state = AUTH_IN_PROGRESS;
vpn_progress(vpninfo, PRG_INFO,
_("Attempting Digest authentication to proxy\n"));
err:
......
......@@ -71,17 +71,17 @@ int gssapi_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *h
gss_buffer_desc in = GSS_C_EMPTY_BUFFER;
gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
if (vpninfo->gssapi_auth.state == AUTH_AVAILABLE && gssapi_setup(vpninfo)) {
vpninfo->gssapi_auth.state = AUTH_FAILED;
if (vpninfo->auth[AUTH_TYPE_GSSAPI].state == AUTH_AVAILABLE && gssapi_setup(vpninfo)) {
vpninfo->auth[AUTH_TYPE_GSSAPI].state = AUTH_FAILED;
return -EIO;
}
if (vpninfo->gssapi_auth.challenge && *vpninfo->gssapi_auth.challenge) {
int len = openconnect_base64_decode(in.value, vpninfo->gssapi_auth.challenge);
if (vpninfo->auth[AUTH_TYPE_GSSAPI].challenge && *vpninfo->auth[AUTH_TYPE_GSSAPI].challenge) {
int len = openconnect_base64_decode(in.value, vpninfo->auth[AUTH_TYPE_GSSAPI].challenge);
if (len < 0)
return -EINVAL;
in.length = len;
} else if (vpninfo->gssapi_auth.state > AUTH_AVAILABLE) {
} else if (vpninfo->auth[AUTH_TYPE_GSSAPI].state > AUTH_AVAILABLE) {
/* This indicates failure. We were trying, but got an empty
'Proxy-Authorization: Negotiate' header back from the server
implying that we should start again... */
......@@ -93,13 +93,13 @@ int gssapi_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *h
GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, &in, NULL,
&out, NULL, NULL);
if (major == GSS_S_COMPLETE)
vpninfo->gssapi_auth.state = GSSAPI_COMPLETE;
vpninfo->auth[AUTH_TYPE_GSSAPI].state = GSSAPI_COMPLETE;
else if (major == GSS_S_CONTINUE_NEEDED)
vpninfo->gssapi_auth.state = GSSAPI_CONTINUE;
vpninfo->auth[AUTH_TYPE_GSSAPI].state = GSSAPI_CONTINUE;
else {
print_gss_err(vpninfo, major, minor);
fail_gssapi:
vpninfo->gssapi_auth.state = AUTH_FAILED;
vpninfo->auth[AUTH_TYPE_GSSAPI].state = AUTH_FAILED;
gss_release_name(&minor, &vpninfo->gss_target_name);
gss_delete_sec_context(&minor, &vpninfo->gss_context, GSS_C_NO_BUFFER);
return -EAGAIN;
......@@ -110,7 +110,7 @@ int gssapi_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *h
if (in.value)
free(in.value);
gss_release_buffer(&minor, &out);
if (!vpninfo->gssapi_auth.challenge)
if (!vpninfo->auth[AUTH_TYPE_GSSAPI].challenge)
vpn_progress(vpninfo, PRG_INFO,
_("Attempting GSSAPI authentication to proxy\n"));
return 0;
......@@ -120,7 +120,7 @@ void cleanup_gssapi_auth(struct openconnect_info *vpninfo)
{
OM_uint32 minor;
if (vpninfo->gssapi_auth.state <= AUTH_AVAILABLE)
if (vpninfo->auth[AUTH_TYPE_GSSAPI].state <= AUTH_AVAILABLE)
return;
gss_release_name(&minor, &vpninfo->gss_target_name);
......
......@@ -1664,8 +1664,8 @@ static int basic_authorization(struct openconnect_info *vpninfo, struct oc_text_
if (!vpninfo->proxy_user || !vpninfo->proxy_pass)
return -EINVAL;
if (vpninfo->basic_auth.state == AUTH_IN_PROGRESS) {
vpninfo->basic_auth.state = AUTH_FAILED;
if (vpninfo->auth[AUTH_TYPE_BASIC].state == AUTH_IN_PROGRESS) {
vpninfo->auth[AUTH_TYPE_BASIC].state = AUTH_FAILED;
return -EAGAIN;
}
......@@ -1701,7 +1701,7 @@ static int basic_authorization(struct openconnect_info *vpninfo, struct oc_text_
buf_append(buf, "\r\n");
vpn_progress(vpninfo, PRG_INFO, _("Attempting HTTP Basic authentication to proxy\n"));
vpninfo->basic_auth.state = AUTH_IN_PROGRESS;
vpninfo->auth[AUTH_TYPE_BASIC].state = AUTH_IN_PROGRESS;
return 0;
}
......@@ -1710,26 +1710,26 @@ static int proxy_authorization(struct openconnect_info *vpninfo, struct oc_text_
{
int ret;
#ifdef HAVE_GSSAPI
if (vpninfo->gssapi_auth.state > AUTH_UNSEEN) {
if (vpninfo->auth[AUTH_TYPE_GSSAPI].state > AUTH_UNSEEN) {
ret = gssapi_authorization(vpninfo, buf);
if (ret == -EAGAIN || !ret)
return ret;
}
#endif
if (vpninfo->ntlm_auth.state > AUTH_UNSEEN) {
if (vpninfo->auth[AUTH_TYPE_NTLM].state > AUTH_UNSEEN) {
ret = ntlm_authorization(vpninfo, buf);
if (ret == -EAGAIN || !ret)
return ret;
}
if (vpninfo->digest_auth.state > AUTH_UNSEEN) {
if (vpninfo->auth[AUTH_TYPE_DIGEST].state > AUTH_UNSEEN) {
ret = digest_authorization(vpninfo, buf);
if (ret == -EAGAIN || !ret)
return ret;
}
if (vpninfo->basic_auth.state > AUTH_UNSEEN) {
if (vpninfo->auth[AUTH_TYPE_BASIC].state > AUTH_UNSEEN) {
ret = basic_authorization(vpninfo, buf);
if (ret == -EAGAIN || !ret)
return ret;
......@@ -1767,10 +1767,10 @@ static int proxy_hdrs(struct openconnect_info *vpninfo, char *hdr, char *val)
if (strcasecmp(hdr, "Proxy-Authenticate"))
return 0;
handle_auth_proto(vpninfo, &vpninfo->basic_auth, "Basic", val);
handle_auth_proto(vpninfo, &vpninfo->ntlm_auth, "NTLM", val);
handle_auth_proto(vpninfo, &vpninfo->gssapi_auth, "Negotiate", val);
handle_auth_proto(vpninfo, &vpninfo->digest_auth, "Digest", val);
handle_auth_proto(vpninfo, &vpninfo->auth[AUTH_TYPE_BASIC], "Basic", val);
handle_auth_proto(vpninfo, &vpninfo->auth[AUTH_TYPE_NTLM], "NTLM", val);
handle_auth_proto(vpninfo, &vpninfo->auth[AUTH_TYPE_GSSAPI], "Negotiate", val);
handle_auth_proto(vpninfo, &vpninfo->auth[AUTH_TYPE_DIGEST], "Digest", val);
return 0;
}
......@@ -1819,10 +1819,10 @@ static int process_http_proxy(struct openconnect_info *vpninfo)
return result;
}
/* Forget existing challenges */
clear_auth_state(&vpninfo->basic_auth, 0);
clear_auth_state(&vpninfo->ntlm_auth, 0);
clear_auth_state(&vpninfo->gssapi_auth, 0);
clear_auth_state(&vpninfo->digest_auth, 0);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_BASIC], 0);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_NTLM], 0);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_GSSAPI], 0);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_DIGEST], 0);
}
buf_append(reqbuf, "\r\n");
......@@ -1885,14 +1885,14 @@ int process_proxy(struct openconnect_info *vpninfo, int ssl_sock)
}
vpninfo->proxy_fd = -1;
clear_auth_state(&vpninfo->basic_auth, 1);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_BASIC], 1);
cleanup_ntlm_auth(vpninfo);
clear_auth_state(&vpninfo->ntlm_auth, 1);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_NTLM], 1);
#ifdef HAVE_GSSAPI
cleanup_gssapi_auth(vpninfo);
#endif
clear_auth_state(&vpninfo->gssapi_auth, 1);
clear_auth_state(&vpninfo->digest_auth, 1);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_GSSAPI], 1);
clear_auth_state(&vpninfo->auth[AUTH_TYPE_DIGEST], 1);
return ret;
}
......
......@@ -134,10 +134,10 @@ static int ntlm_helper_challenge(struct openconnect_info *vpninfo, struct oc_tex
char helperbuf[4096];
int len;
if (!vpninfo->ntlm_auth.challenge ||
if (!vpninfo->auth[AUTH_TYPE_NTLM].challenge ||
write(vpninfo->ntlm_helper_fd, "TT ", 3) != 3 ||
write(vpninfo->ntlm_helper_fd, vpninfo->ntlm_auth.challenge,
strlen(vpninfo->ntlm_auth.challenge)) != strlen(vpninfo->ntlm_auth.challenge) ||
write(vpninfo->ntlm_helper_fd, vpninfo->auth[AUTH_TYPE_NTLM].challenge,
strlen(vpninfo->auth[AUTH_TYPE_NTLM].challenge)) != strlen(vpninfo->auth[AUTH_TYPE_NTLM].challenge) ||
write(vpninfo->ntlm_helper_fd, "\n", 1) != 1) {
err:
close(vpninfo->ntlm_helper_fd);
......@@ -812,11 +812,11 @@ static int ntlm_manual_challenge(struct openconnect_info *vpninfo, struct oc_tex
int token_len;
int ntlmver;
if (!vpninfo->ntlm_auth.challenge)
if (!vpninfo->auth[AUTH_TYPE_NTLM].challenge)
return -EINVAL;
token_len = openconnect_base64_decode(&token,
vpninfo->ntlm_auth.challenge);
vpninfo->auth[AUTH_TYPE_NTLM].challenge);
if (token_len < 0)
return token_len;
......@@ -929,43 +929,43 @@ static int ntlm_manual_challenge(struct openconnect_info *vpninfo, struct oc_tex
int ntlm_authorization(struct openconnect_info *vpninfo, struct oc_text_buf *buf)
{
if (vpninfo->ntlm_auth.state == AUTH_AVAILABLE) {
vpninfo->ntlm_auth.state = NTLM_MANUAL;
if (vpninfo->auth[AUTH_TYPE_NTLM].state == AUTH_AVAILABLE) {
vpninfo->auth[AUTH_TYPE_NTLM].state = NTLM_MANUAL;
#ifndef _WIN32
/* Don't attempt automatic NTLM auth if we were given a password */
if (!vpninfo->proxy_pass && !ntlm_helper_spawn(vpninfo, buf)) {
vpninfo->ntlm_auth.state = NTLM_SSO_REQ;
vpninfo->auth[AUTH_TYPE_NTLM].state = NTLM_SSO_REQ;
return 0;
}
}
if (vpninfo->ntlm_auth.state == NTLM_SSO_REQ) {
if (vpninfo->auth[AUTH_TYPE_NTLM].state == NTLM_SSO_REQ) {
int ret;
vpninfo->ntlm_auth.state = NTLM_MANUAL;
vpninfo->auth[AUTH_TYPE_NTLM].state = NTLM_MANUAL;
ret = ntlm_helper_challenge(vpninfo, buf);
if (!ret || ret == -EAGAIN)
return ret;
#endif
}
if (vpninfo->ntlm_auth.state == NTLM_MANUAL && vpninfo->proxy_user &&
if (vpninfo->auth[AUTH_TYPE_NTLM].state == NTLM_MANUAL && vpninfo->proxy_user &&
vpninfo->proxy_pass) {
buf_append(buf, "Proxy-Authorization: NTLM %s\r\n",
"TlRMTVNTUAABAAAABYIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAwAAAA");
vpninfo->ntlm_auth.state = NTLM_MANUAL_REQ;
vpninfo->auth[AUTH_TYPE_NTLM].state = NTLM_MANUAL_REQ;
return 0;
}
if (vpninfo->ntlm_auth.state == NTLM_MANUAL_REQ &&
if (vpninfo->auth[AUTH_TYPE_NTLM].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;
}
vpninfo->ntlm_auth.state = AUTH_FAILED;
vpninfo->auth[AUTH_TYPE_NTLM].state = AUTH_FAILED;
return -EAGAIN;
}
void cleanup_ntlm_auth(struct openconnect_info *vpninfo)
{
if (vpninfo->ntlm_auth.state == NTLM_SSO_REQ) {
if (vpninfo->auth[AUTH_TYPE_NTLM].state == NTLM_SSO_REQ) {
close(vpninfo->ntlm_helper_fd);
vpninfo->ntlm_helper_fd = -1;}
}
......@@ -149,6 +149,13 @@ struct oc_text_buf {
#define REDIR_TYPE_NEWHOST 1
#define REDIR_TYPE_LOCAL 2
#define AUTH_TYPE_GSSAPI 0
#define AUTH_TYPE_NTLM 1
#define AUTH_TYPE_DIGEST 2
#define AUTH_TYPE_BASIC 3
#define MAX_AUTH_TYPES 4
#define AUTH_FAILED -1 /* Failed */
#define AUTH_UNSEEN 0 /* Server has not offered it */
#define AUTH_AVAILABLE 1 /* Server has offered it, we have not tried it */
......@@ -192,10 +199,7 @@ struct openconnect_info {
int proxy_fd;
char *proxy_user;
char *proxy_pass;
struct proxy_auth_state basic_auth;
struct proxy_auth_state ntlm_auth;
struct proxy_auth_state gssapi_auth;
struct proxy_auth_state digest_auth;
struct proxy_auth_state auth[MAX_AUTH_TYPES];
#ifdef HAVE_GSSAPI
gss_name_t gss_target_name;
gss_ctx_id_t gss_context;
......
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