auth: Split auth form prompt logic from parsing logic
authorKevin Cernekee <cernekee@gmail.com>
Sat, 27 Oct 2012 22:44:23 +0000 (15:44 -0700)
committerKevin Cernekee <cernekee@gmail.com>
Sun, 28 Oct 2012 05:10:03 +0000 (22:10 -0700)
Provide separate calls for parse_xml_response() and handle_auth_form(),
so that the ordering of events in openconnect_obtain_cookie() can be
modified.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
auth.c
http.c
openconnect-internal.h

diff --git a/auth.c b/auth.c
index d51da87..4cfc1e1 100644 (file)
--- a/auth.c
+++ b/auth.c
@@ -396,19 +396,18 @@ out:
 
 /* Return value:
  *  < 0, on error
- *  = 0, when form parsed and POST required
- *  = 1, when response was cancelled by user
- *  = 2, when form indicates that login was already successful
+ *  = 0, on success; *form is populated
  */
-int parse_xml_response(struct openconnect_info *vpninfo, char *response,
-                      char *request_body, int req_len, const char **method,
-                      const char **request_body_type)
+int parse_xml_response(struct openconnect_info *vpninfo, char *response, struct oc_auth_form **formp)
 {
        struct oc_auth_form *form;
        xmlDocPtr xml_doc;
        xmlNode *xml_node;
-       int ret;
-       struct vpn_option *opt, *next;
+
+       if (*formp) {
+               free_auth_form(*formp);
+               *formp = NULL;
+       }
 
        form = calloc(1, sizeof(*form));
        if (!form)
@@ -428,27 +427,44 @@ int parse_xml_response(struct openconnect_info *vpninfo, char *response,
        if (xml_node->type != XML_ELEMENT_NODE || strcmp((char *)xml_node->name, "auth")) {
                vpn_progress(vpninfo, PRG_ERR,
                             _("XML response has no \"auth\" root node\n"));
-               ret = -EINVAL;
                goto out;
        }
-
        form->auth_id = (char *)xmlGetProp(xml_node, (unsigned char *)"id");
-       if (!strcmp(form->auth_id, "success")) {
-               ret = 2;
-               goto out;
+
+       if (parse_auth_node(vpninfo, xml_node, form) == 0) {
+               xmlFreeDoc(xml_doc);
+               *formp = form;
+               return 0;
        }
 
+ out:
+       xmlFreeDoc(xml_doc);
+       free_auth_form(form);
+       return -EINVAL;
+}
+
+/* Return value:
+ *  < 0, on error
+ *  = 0, when form parsed and POST required
+ *  = 1, when response was cancelled by user
+ *  = 2, when form indicates that login was already successful
+ */
+int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_form *form,
+                    char *request_body, int req_len, const char **method,
+                    const char **request_body_type)
+{
+       int ret;
+       struct vpn_option *opt, *next;
+
+       if (!strcmp(form->auth_id, "success"))
+               return 2;
+
        if (vpninfo->nopasswd) {
                vpn_progress(vpninfo, PRG_ERR,
                             _("Asked for password but '--no-passwd' set\n"));
-               ret = -EPERM;
-               goto out;
+               return -EPERM;
        }
 
-       ret = parse_auth_node(vpninfo, xml_node, form);
-       if (ret)
-               goto out;
-
        if (vpninfo->csd_token && vpninfo->csd_ticket && vpninfo->csd_starturl && vpninfo->csd_waiturl) {
                /* First, redirect to the stuburl -- we'll need to fetch and run that */
                vpninfo->redirect_url = strdup(vpninfo->csd_stuburl);
@@ -462,17 +478,14 @@ int parse_xml_response(struct openconnect_info *vpninfo, char *response,
                        free(opt);
                }
                vpninfo->cookies = NULL;
-
-               ret = 0;
-               goto out;
+               return 0;
        }
        if (!form->opts) {
                if (form->message)
                        vpn_progress(vpninfo, PRG_INFO, "%s\n", form->message);
                if (form->error)
                        vpn_progress(vpninfo, PRG_ERR, "%s\n", form->error);
-               ret = -EPERM;
-               goto out;
+               return -EPERM;
        }
 
        if (vpninfo->process_auth_form)
@@ -482,20 +495,25 @@ int parse_xml_response(struct openconnect_info *vpninfo, char *response,
                ret = 1;
        }
        if (ret)
-               goto out;
+               return ret;
 
        /* tokencode generation is deferred until after username prompts and CSD */
        ret = do_gen_tokencode(vpninfo, form);
        if (ret)
-               goto out;
+               return ret;
 
        ret = append_form_opts(vpninfo, form, request_body, req_len);
        if (!ret) {
                *method = "POST";
                *request_body_type = "application/x-www-form-urlencoded";
        }
- out:
-       xmlFreeDoc(xml_doc);
+       return ret;
+}
+
+void free_auth_form(struct oc_auth_form *form)
+{
+       if (!form)
+               return;
        while (form->opts) {
                struct oc_form_opt *tmp = form->opts->next;
                if (form->opts->type == OC_FORM_OPT_TEXT ||
@@ -527,7 +545,6 @@ int parse_xml_response(struct openconnect_info *vpninfo, char *response,
        free(form->method);
        free(form->action);
        free(form);
-       return ret;
 }
 
 #ifdef LIBSTOKEN_HDR
diff --git a/http.c b/http.c
index 43d4c61..f0c0a5b 100644 (file)
--- a/http.c
+++ b/http.c
@@ -792,6 +792,7 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
        struct vpn_option *opt;
        struct oc_text_buf *buf;
        char *form_buf = NULL;
+       struct oc_auth_form *form = NULL;
        int result, buflen;
        char request_body[2048];
        const char *request_body_type = NULL;
@@ -900,9 +901,15 @@ int openconnect_obtain_cookie(struct openconnect_info *vpninfo)
                free(form_buf);
                return -EINVAL;
        }
+       result = parse_xml_response(vpninfo, form_buf, &form);
+       if (result) {
+               free(form_buf);
+               return -ENOMEM;
+       }
        request_body[0] = 0;
-       result = parse_xml_response(vpninfo, form_buf, request_body, sizeof(request_body),
-                                   &method, &request_body_type);
+       result = handle_auth_form(vpninfo, form, request_body, sizeof(request_body),
+                                 &method, &request_body_type);
+       free_auth_form(form);
 
        if (!result)
                goto redirect;
index 413bf3a..1349e9e 100644 (file)
@@ -402,9 +402,11 @@ extern int killed;
 int config_lookup_host(struct openconnect_info *vpninfo, const char *host);
 
 /* auth.c */
-int parse_xml_response(struct openconnect_info *vpninfo, char *response,
-                      char *request_body, int req_len, const char **method,
-                      const char **request_body_type);
+int parse_xml_response(struct openconnect_info *vpninfo, char *response, struct oc_auth_form **form);
+int handle_auth_form(struct openconnect_info *vpninfo, struct oc_auth_form *form,
+                    char *request_body, int req_len, const char **method,
+                    const char **request_body_type);
+void free_auth_form(struct oc_auth_form *form);
 int prepare_stoken(struct openconnect_info *vpninfo);
 
 /* http.c */