diff --git a/digest.c b/digest.c index 27f28269..b2eab04e 100644 --- a/digest.c +++ b/digest.c @@ -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: diff --git a/gssapi.c b/gssapi.c index a713f568..68db5d76 100644 --- a/gssapi.c +++ b/gssapi.c @@ -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); diff --git a/http.c b/http.c index 594d027e..a8570afe 100644 --- a/http.c +++ b/http.c @@ -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; } diff --git a/ntlm.c b/ntlm.c index a25c60f3..b0dccd05 100644 --- a/ntlm.c +++ b/ntlm.c @@ -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;} } diff --git a/openconnect-internal.h b/openconnect-internal.h index f4bc672d..e9ada0d8 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -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;