From debaa24e41b5388cb8371b84606d71daa8510d00 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 1 Oct 2008 11:39:26 +0100 Subject: [PATCH] Tidy up cookie handling, check XML config file sha1 against server --- anyconnect.h | 5 +++-- http.c | 39 ++++++++++++++++++++++++++++++++------- ssl.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/anyconnect.h b/anyconnect.h index 6e1805b..f5961fc 100644 --- a/anyconnect.h +++ b/anyconnect.h @@ -32,8 +32,8 @@ struct pkt { }; struct vpn_option { - const char *option; - const char *value; + char *option; + char *value; struct vpn_option *next; }; @@ -52,6 +52,7 @@ struct anyconnect_info { char xmlsha1[(SHA_DIGEST_LENGTH * 2) + 1]; const char *cookie; + struct vpn_option *cookies; struct vpn_option *cstp_options; struct vpn_option *dtls_options; diff --git a/http.c b/http.c index aae899e..160bbdb 100644 --- a/http.c +++ b/http.c @@ -103,15 +103,40 @@ int process_http_response(struct anyconnect_info *vpninfo, int *result, } } if (!strcmp(buf, "Set-Cookie")) { + struct vpn_option *new, **this; char *semicolon = strchr(colon, ';'); - if (semicolon) - *semicolon = 0; - if (!strncmp(colon, "webvpn=", 7)) { - vpninfo->cookie = strdup(colon + 7); + char *equals = strchr(colon, '='); + + if (!semicolon || !equals) { + fprintf(stderr, "Invalid cookie offered: %s\n", buf); + return -EINVAL; + } + *semicolon = *(equals++) = 0; + + new = malloc(sizeof(*new)); + if (!new) { + fprintf(stderr, "No memory for allocating cookies\n"); + return -ENOMEM; + } + new->next = NULL; + new->option = strdup(colon); + new->value = strdup(equals); + + for (this = &vpninfo->cookies; *this; this = &(*this)->next) { + if (!strcmp(new->option, (*this)->option)) { + /* Replace existing cookie */ + new->next = (*this)->next; + free((*this)->option); + free((*this)->value); + free(*this); + *this = new; + break; + } + } + if (!*this) { + *this = new; + new->next = NULL; } - /* FIXME: Handle other cookies, including the webvpnc one - which tells us whether to update the XML config file */ - } if (!strcmp(buf, "Transfer-Encoding")) { if (!strcmp(colon, "chunked")) diff --git a/ssl.c b/ssl.c index e2ffbb0..fd58abb 100644 --- a/ssl.c +++ b/ssl.c @@ -286,6 +286,7 @@ static int open_https(struct anyconnect_info *vpninfo) int obtain_cookie_cert(struct anyconnect_info *vpninfo) { + struct vpn_option *opt, *next; char buf[65536]; int result; @@ -335,6 +336,14 @@ int obtain_cookie_cert(struct anyconnect_info *vpninfo) SSL_free(vpninfo->https_ssl); vpninfo->https_ssl = NULL; + for (opt = vpninfo->cookies; opt; opt = next) { + next = opt->next; + printf("Discard cookie %s\n", opt->option); + free(opt->option); + free(opt->value); + free(opt); + } + vpninfo->cookies = NULL; goto retry; } else if (vpninfo->redirect_url[0] == '/') { /* Absolute redirect within same host */ @@ -348,9 +357,31 @@ int obtain_cookie_cert(struct anyconnect_info *vpninfo) return -EINVAL; } } - if (vpninfo->cookie) { - return 0; + + for (opt = vpninfo->cookies; opt; opt = opt->next) { + + if (!strcmp(opt->option, "webvpn")) + vpninfo->cookie = opt->value; + else if (!strcmp(opt->option, "webvpnc")) { + char *amp = opt->value; + + while ((amp = strchr(amp, '&'))) { + amp++; + if (!strncmp(amp, "fh:", 3)) { + if (strncasecmp(amp+3, vpninfo->xmlsha1, + SHA_DIGEST_LENGTH * 2)) { + /* FIXME. Obviously */ + printf("SHA1 changed; need new config\n"); + /* URL is $bu: + $fu: */ + } else if (verbose) + printf("XML config SHA1 match\n"); + } + } + } } + if (vpninfo->cookie) + return 0; + return -1; } -- 2.7.4