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>
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
#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];
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;
}
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);