]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
factor out internal_split_cookies from auth-juniper.c
authorDaniel Lenski <dlenski@gmail.com>
Mon, 8 Feb 2021 19:38:19 +0000 (11:38 -0800)
committerDaniel Lenski <dlenski@gmail.com>
Mon, 29 Mar 2021 02:27:01 +0000 (19:27 -0700)
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 <dlenski@gmail.com>
http.c
oncp.c
openconnect-internal.h

diff --git a/http.c b/http.c
index 7598862e2fcc72a5dabfa35441b3b9c2040e08ad..333d4028e8d5e95f9a6f4cf736ad01e830fae3fe 100644 (file)
--- 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 7e8feac3dd76b18f00d5b94d8e9098930647bc1c..1c5b8995171721c0df87a9b166e3dd308c789185 100644 (file)
--- a/oncp.c
+++ b/oncp.c
 
 #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;
        }
index 5d19e26380e30340d85674642757f7d3d6f4cb87..b9a00456c1731dc7206bde5fa0ba5c9b70ff9e7e 100644 (file)
@@ -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);