From: Kevin Cernekee Date: Fri, 26 Oct 2012 04:53:10 +0000 (-0700) Subject: auth: Parse the new server response format X-Git-Tag: v4.99~26^2~14 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=c407e79e9825503cd8ea73cd6cc5193785598b1e;p=users%2Fdwmw2%2Fopenconnect.git auth: Parse the new server response format Newer AnyConnect installations use a different XML document tree to pass information to the client. This patch allows OpenConnect to parse the new format, and attempts to document both the old format and the new format in the comments. Signed-off-by: Kevin Cernekee --- diff --git a/auth.c b/auth.c index 4cfc1e1d..79c9bc1b 100644 --- a/auth.c +++ b/auth.c @@ -348,6 +348,63 @@ static int xmlnode_get_text(xmlNode *xml_node, const char *name, char **var) return 0; } +/* + * Legacy server response looks like: + * + * "> + * <!-- title to display to user --> + * + * + * + * + * Please enter your username and password. + *
+ * + * + * + * + * + *
+ *
+ * + * New server response looks like: + * + * + * + * + * + * + * foobar + * 1234567 + * + * method = strdup("POST"); + form->action = strdup("/"); + xmlnode_get_prop(xml_node, "method", &form->method); xmlnode_get_prop(xml_node, "action", &form->action); @@ -394,6 +455,24 @@ out: return ret; } +static int parse_host_scan_node(struct openconnect_info *vpninfo, xmlNode *xml_node) +{ + /* ignore this whole section if the CSD trojan has already run */ + if (vpninfo->csd_scriptname) + return 0; + + for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) { + if (xml_node->type != XML_ELEMENT_NODE) + continue; + + xmlnode_get_text(xml_node, "host-scan-ticket", &vpninfo->csd_ticket); + xmlnode_get_text(xml_node, "host-scan-token", &vpninfo->csd_token); + xmlnode_get_text(xml_node, "host-scan-base-uri", &vpninfo->csd_starturl); + xmlnode_get_text(xml_node, "host-scan-wait-uri", &vpninfo->csd_waiturl); + } + return 0; +} + /* Return value: * < 0, on error * = 0, on success; *form is populated @@ -403,6 +482,7 @@ int parse_xml_response(struct openconnect_info *vpninfo, char *response, struct struct oc_auth_form *form; xmlDocPtr xml_doc; xmlNode *xml_node; + int ret = -EINVAL; if (*formp) { free_auth_form(*formp); @@ -424,23 +504,52 @@ int parse_xml_response(struct openconnect_info *vpninfo, char *response, struct } xml_node = xmlDocGetRootElement(xml_doc); - if (xml_node->type != XML_ELEMENT_NODE || strcmp((char *)xml_node->name, "auth")) { + while (xml_node) { + int ret = 0; + + if (xml_node->type != XML_ELEMENT_NODE) { + xml_node = xml_node->next; + continue; + } + if (xmlnode_is_named(xml_node, "config-auth")) { + /* if we do have a config-auth node, it is the root element */ + xml_node = xml_node->children; + continue; + } else if (xmlnode_is_named(xml_node, "auth")) { + xmlnode_get_prop(xml_node, "id", &form->auth_id); + ret = parse_auth_node(vpninfo, xml_node, form); + } else if (xmlnode_is_named(xml_node, "opaque")) { + if (vpninfo->opaque_srvdata) + xmlFreeNode(vpninfo->opaque_srvdata); + vpninfo->opaque_srvdata = xmlCopyNode(xml_node, 1); + if (!vpninfo->opaque_srvdata) + ret = -ENOMEM; + } else if (xmlnode_is_named(xml_node, "host-scan")) { + ret = parse_host_scan_node(vpninfo, xml_node); + } else { + xmlnode_get_text(xml_node, "session-token", &vpninfo->cookie); + xmlnode_get_text(xml_node, "error", &form->error); + } + + if (ret) + goto out; + xml_node = xml_node->next; + } + + if (!form->auth_id) { vpn_progress(vpninfo, PRG_ERR, - _("XML response has no \"auth\" root node\n")); + _("XML response has no \"auth\" node\n")); goto out; } - form->auth_id = (char *)xmlGetProp(xml_node, (unsigned char *)"id"); - if (parse_auth_node(vpninfo, xml_node, form) == 0) { - xmlFreeDoc(xml_doc); - *formp = form; - return 0; - } + *formp = form; + xmlFreeDoc(xml_doc); + return 0; out: xmlFreeDoc(xml_doc); free_auth_form(form); - return -EINVAL; + return ret; } /* Return value: diff --git a/openconnect-internal.h b/openconnect-internal.h index 1349e9e9..cd0e7e74 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -74,6 +74,8 @@ #endif #define N_(s) s +#include + #define SHA1_SIZE 20 #define MD5_SIZE 16 @@ -139,6 +141,7 @@ struct openconnect_info { char *csd_preurl; char *csd_scriptname; + xmlNode *opaque_srvdata; #ifdef LIBPROXY_HDR pxProxyFactory *proxy_factory;