Skip to content

Commit

Permalink
move more form handling out into separate function
Browse files Browse the repository at this point in the history
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Oct 1, 2008
1 parent adbf93b commit 3ab49d7
Showing 1 changed file with 81 additions and 52 deletions.
133 changes: 81 additions & 52 deletions http.c
Expand Up @@ -247,7 +247,7 @@ int process_http_response(struct anyconnect_info *vpninfo, int *result,
}

int parse_form(struct anyconnect_info *vpninfo, char *form_message, char *form_error,
xmlNode *xml_node, char *body)
xmlNode *xml_node, char *body, int bodylen)
{
UI *ui = UI_new();
char msg_buf[1024], err_buf[1024];
Expand All @@ -270,6 +270,7 @@ int parse_form(struct anyconnect_info *vpninfo, char *form_message, char *form_e
snprintf(msg_buf, 1023, "%s\n", form_message);
UI_add_info_string(ui, msg_buf);
}

if (!vpninfo->username)
UI_add_input_string(ui, "Enter username: ", UI_INPUT_FLAG_ECHO, username, 1, 80);
UI_add_input_string(ui, "Enter SecurID token: ", UI_INPUT_FLAG_ECHO, token, 1, 80);
Expand All @@ -285,19 +286,88 @@ int parse_form(struct anyconnect_info *vpninfo, char *form_message, char *form_e
return 0;
}

int obtain_cookie(struct anyconnect_info *vpninfo)
int parse_xml_response(struct anyconnect_info *vpninfo, char *response,
char *request_body, int req_len)
{
struct vpn_option *opt, *next;
char *form_message, *form_error;
xmlDocPtr xml_doc;
xmlNode *xml_node;
int success = 0;

xml_doc = xmlReadMemory(response, strlen(response), "noname.xml", NULL, 0);
if (!xml_doc) {
fprintf(stderr, "Failed to parse server response\n");
if (verbose)
printf("Response was:%s\n", response);
return -EINVAL;
}

xml_node = xmlDocGetRootElement(xml_doc);
if (xml_node->type != XML_ELEMENT_NODE ||
strcmp((char *)xml_node->name, "auth")) {
fprintf(stderr, "XML response has no \"auth\" root node\n");
xmlFreeDoc(xml_doc);
return -EINVAL;
}

form_message = form_error = NULL;
for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
if (xml_node->type != XML_ELEMENT_NODE)
continue;

if (!strcmp((char *)xml_node->name, "message"))
form_message = (char *)xmlNodeGetContent(xml_node);
else if (!strcmp((char *)xml_node->name, "error")) {
form_error = (char *)xmlNodeGetContent(xml_node);
/* Login failure. Forget the username */
if (vpninfo->username) {
free(vpninfo->username);
vpninfo->username = NULL;
}
} else if (!strcmp((char *)xml_node->name, "form")) {
char *form_method, *form_action;
form_method = (char *)xmlGetProp(xml_node, (unsigned char *)"method");
form_action = (char *)xmlGetProp(xml_node, (unsigned char *)"action");
if (strcasecmp(form_method, "POST")) {
fprintf(stderr, "Cannot handle form method '%s'\n",
form_method);
xmlFreeDoc(xml_doc);
return -EINVAL;
}
free(vpninfo->urlpath);
vpninfo->urlpath = strdup(form_action);

if (parse_form(vpninfo, form_message, form_error, xml_node, request_body, req_len)) {
xmlFreeDoc(xml_doc);
return -EINVAL;
}

/* Let the caller know there's a form to be submitted */
return 1;

} else if (!strcmp((char *)xml_node->name, "success")) {
success = 1;
}
}

xmlFreeDoc(xml_doc);
if (success)
return 0;

fprintf(stderr, "Response neither indicated success nor requested input\n");
printf("Response was:\n%s\n", response);
return -EINVAL;
}

int obtain_cookie(struct anyconnect_info *vpninfo)
{
struct vpn_option *opt, *next;
char buf[65536];
int result, buflen;
char request_body[2048];
char *request_body_type = NULL;
char *method = "GET";
char *form_message, *form_error;

request_body[0] = 0;
retry:
if (!vpninfo->https_ssl && open_https(vpninfo)) {
fprintf(stderr, "Failed to open HTTPS connection to %s\n",
Expand Down Expand Up @@ -381,58 +451,17 @@ int obtain_cookie(struct anyconnect_info *vpninfo)
}
}

xml_doc = xmlReadMemory(buf, strlen(buf), "noname.xml", NULL, 0);
if (!xml_doc) {
fprintf(stderr, "Failed to parse server response\n");
if (verbose)
printf("Response was:%s\n", buf);
return -EINVAL;
}

xml_node = xmlDocGetRootElement(xml_doc);
if (xml_node->type != XML_ELEMENT_NODE ||
strcmp((char *)xml_node->name, "auth")) {
fprintf(stderr, "XML response has no \"auth\" root node\n");
xmlFreeDoc(xml_doc);
return -EINVAL;
}

form_message = form_error = NULL;
for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
if (xml_node->type != XML_ELEMENT_NODE)
continue;

if (!strcmp((char *)xml_node->name, "message"))
form_message = (char *)xmlNodeGetContent(xml_node);
else if (!strcmp((char *)xml_node->name, "error")) {
form_error = (char *)xmlNodeGetContent(xml_node);
/* Login failure. Forget the username */
if (vpninfo->username) {
free(vpninfo->username);
vpninfo->username = NULL;
}
} else if (!strcmp((char *)xml_node->name, "form")) {
char *form_method, *form_action;
form_method = (char *)xmlGetProp(xml_node, (unsigned char *)"method");
form_action = (char *)xmlGetProp(xml_node, (unsigned char *)"action");
if (strcasecmp(form_method, "POST")) {
fprintf(stderr, "Cannot handle form method '%s'\n",
form_method);
return -EINVAL;
}
request_body[0] = 0;
if (parse_xml_response(vpninfo, buf, request_body, sizeof(request_body))) {
/* Failure, or a form response to submit. If the latter, we'll
have a form to submit. */
if (request_body[0]) {
method = "POST";
free(vpninfo->urlpath);
vpninfo->urlpath = strdup(form_action);
if (verbose)
printf("WILL POST: %s %s\n", form_method, form_action);
request_body_type = "application/x-www-form-urlencoded";

if (parse_form(vpninfo, form_message, form_error, xml_node, request_body))
return -EINVAL;
goto retry;
}
return -EINVAL;
}
xmlFreeDoc(xml_doc);

for (opt = vpninfo->cookies; opt; opt = opt->next) {

Expand Down

0 comments on commit 3ab49d7

Please sign in to comment.