Tidy up cookie handling, check XML config file sha1 against server
authorDavid Woodhouse <David.Woodhouse@intel.com>
Wed, 1 Oct 2008 10:39:26 +0000 (11:39 +0100)
committerDavid Woodhouse <David.Woodhouse@intel.com>
Wed, 1 Oct 2008 10:39:26 +0000 (11:39 +0100)
anyconnect.h
http.c
ssl.c

index 6e1805b..f5961fc 100644 (file)
@@ -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 (file)
--- 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 (file)
--- 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;
 }