summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Cernekee <cernekee@gmail.com>2012-10-27 15:44:23 -0700
committerKevin Cernekee <cernekee@gmail.com>2012-10-27 22:10:03 -0700
commitb4e67f481966f7c831414783b98b173e2999e95c (patch)
tree1e1c4bb05df1a2e92e2996a274675badf96f5168
parentdbc605c968bfdd9b882f97562e389489b5ce06f8 (diff)
downloadopenconnect-b4e67f481966f7c831414783b98b173e2999e95c.tar.gz
openconnect-b4e67f481966f7c831414783b98b173e2999e95c.tar.bz2
openconnect-b4e67f481966f7c831414783b98b173e2999e95c.zip
auth: Split auth form prompt logic from parsing logic
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>
-rw-r--r--auth.c75
-rw-r--r--http.c11
-rw-r--r--openconnect-internal.h8
3 files changed, 60 insertions, 34 deletions
diff --git a/auth.c b/auth.c
index d51da87..4cfc1e1 100644
--- 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
--- 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;
diff --git a/openconnect-internal.h b/openconnect-internal.h
index 413bf3a..1349e9e 100644
--- a/openconnect-internal.h
+++ b/openconnect-internal.h
@@ -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 */