From 8f113f32adcfeb03c919dbb8c96d1ccb041880fd Mon Sep 17 00:00:00 2001 From: Daniel Lenski Date: Mon, 8 Feb 2021 11:38:19 -0800 Subject: [PATCH] factor out internal_split_cookies from auth-juniper.c MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is useful for other protocols that use HTTP cookies for authentication, and may need a way to handoff >1 cookie from the authentication phase to the connection phase. Improve it slightly by allowing it to set a "default" HTTP cookie if the authcookie string doesn't contain '=', since most protocols really only NEED one cookie for the connection phase to work. This allows shortcuts (like `openconnect --protocol=nc -C 'foobar'` → 'Cookie: DSID=foobar' or `openconnect --protocol=fortinet -C 'ABCD123456=='` → 'Cookie: SVPNCOOKIE=ABCD123456==') without limiting the ability to store multiple cookies if/when useful. Signed-off-by: Daniel Lenski --- http.c | 41 +++++++++++++++++++++++++++++++++++++++++ oncp.c | 39 ++------------------------------------- openconnect-internal.h | 1 + 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/http.c b/http.c index 7598862e..333d4028 100644 --- a/http.c +++ b/http.c @@ -395,6 +395,47 @@ int http_add_cookie(struct openconnect_info *vpninfo, const char *option, return 0; } +/* Some protocols use an "authentication cookie" which needs + * to be split into multiple HTTP cookies. (For example, oNCP + * 'DSSignInUrl=/; DSID=xxx; DSFirstAccess=xxx; DSLastAccess=xxx') + * Process those into vpninfo->cookies. + */ +int internal_split_cookies(struct openconnect_info *vpninfo, int replace, const char *def_cookie) +{ + char *p = vpninfo->cookie; + + while (p && *p) { + char *semicolon = strchr(p, ';'); + char *equals; + + if (semicolon) + *semicolon = 0; + + equals = strchr(p, '='); + if (equals) { + *equals = 0; + http_add_cookie(vpninfo, p, equals+1, replace); + *equals = '='; + } else if (def_cookie) { + /* XX: assume this represents a single cookie's value */ + http_add_cookie(vpninfo, def_cookie, p, replace); + } else { + vpn_progress(vpninfo, PRG_ERR, _("Invalid cookie '%s'\n"), p); + return -EINVAL; + } + + p = semicolon; + if (p) { + *p = ';'; + p++; + while (*p && isspace((int)(unsigned char)*p)) + p++; + } + } + + return 0; +} + /* Read one HTTP header line into hdrbuf, potentially allowing for * continuation lines. Will never leave a character in 'nextchar' when * an empty line (signifying end of headers) is received. Will only diff --git a/oncp.c b/oncp.c index 7e8feac3..1c5b8995 100644 --- a/oncp.c +++ b/oncp.c @@ -36,42 +36,6 @@ #include "openconnect-internal.h" -static int parse_cookie(struct openconnect_info *vpninfo) -{ - char *p = vpninfo->cookie; - - /* We currenly expect the "cookie" to be contain multiple cookies: - * DSSignInUrl=/; DSID=xxx; DSFirstAccess=xxx; DSLastAccess=xxx - * Process those into vpninfo->cookies unless we already had them - * (in which case they'll may be newer. */ - while (p && *p) { - char *semicolon = strchr(p, ';'); - char *equals; - - if (semicolon) - *semicolon = 0; - - equals = strchr(p, '='); - if (!equals) { - vpn_progress(vpninfo, PRG_ERR, _("Invalid cookie '%s'\n"), p); - return -EINVAL; - } - *equals = 0; - http_add_cookie(vpninfo, p, equals+1, 0); - *equals = '='; - - p = semicolon; - if (p) { - *p = ';'; - p++; - while (*p && isspace((int)(unsigned char)*p)) - p++; - } - } - - return 0; -} - static void buf_append_tlv(struct oc_text_buf *buf, uint16_t val, uint32_t len, void *data) { unsigned char b[6]; @@ -529,7 +493,8 @@ int oncp_connect(struct openconnect_info *vpninfo) const char *old_addr = vpninfo->ip_info.addr, *old_netmask = vpninfo->ip_info.netmask; if (!vpninfo->cookies) { - ret = parse_cookie(vpninfo); + /* XX: This will happen if authentication was separate/external */ + ret = internal_split_cookies(vpninfo, 0, "DSID"); if (ret) return ret; } diff --git a/openconnect-internal.h b/openconnect-internal.h index 5d19e263..b9a00456 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -1164,6 +1164,7 @@ int do_https_request(struct openconnect_info *vpninfo, const char *method, char **form_buf, int fetch_redirect); int http_add_cookie(struct openconnect_info *vpninfo, const char *option, const char *value, int replace); +int internal_split_cookies(struct openconnect_info *vpninfo, int replace, const char *def_cookie); int process_http_response(struct openconnect_info *vpninfo, int connect, int (*header_cb)(struct openconnect_info *, char *, char *), struct oc_text_buf *body); -- 2.49.0