[PATCH 09/24] auth: Split auth form prompt logic from parsing logic

Kevin Cernekee cernekee at gmail.com
Sat Nov 3 13:22:51 EDT 2012


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 at gmail.com>
---
 auth.c                 |   75 +++++++++++++++++++++++++++++-------------------
 http.c                 |   11 +++++--
 openconnect-internal.h |    8 ++++--
 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 */
-- 
1.7.10.4




More information about the openconnect-devel mailing list