Can't connect to Juniper VPN because: "Unknown form ID 'frmSelectRoles'"
David Woodhouse
dwmw2 at infradead.org
Tue Jul 19 14:24:26 PDT 2016
On Tue, 2016-07-19 at 14:08 -0600, Benjamin Cardon wrote:
> Attached is a scrubbed for session values version of the select roles
> page.
Try this please. Should work both on the command line and from
NetworkManager. I'll clean it up a little if it's working. Mostly based
on Hillel's original HTML parsing code.
diff --git a/auth-juniper.c b/auth-juniper.c
index a037ffa..6729807 100644
--- a/auth-juniper.c
+++ b/auth-juniper.c
@@ -456,6 +456,106 @@ static int tncc_preauth(struct openconnect_info *vpninfo)
}
#endif
+static struct oc_auth_form *parse_roles_table_node(xmlNodePtr node)
+{
+ struct oc_auth_form *form;
+ xmlNodePtr table_itr;
+ xmlNodePtr row_itr;
+ xmlNodePtr data_itr;
+ struct oc_form_opt_select *opt;
+ struct oc_choice *choice;
+
+
+ form = calloc(1, sizeof(*form));
+ if (!form)
+ return NULL;
+
+ opt = calloc(1, sizeof(*opt));
+ if (!opt) {
+ free(form);
+ return NULL;
+ }
+
+ form->opts = &opt->form;
+ opt->form.label = strdup("frmSelectRoles");
+ opt->form.name = strdup("frmSelectRoles");
+ opt->form.type = OC_FORM_OPT_SELECT;
+
+ for (table_itr = node->children; table_itr; table_itr = table_itr->next) {
+ if (!table_itr->name || strcasecmp((const char *)table_itr->name, "tr"))
+ continue;
+ for (row_itr = table_itr->children; row_itr; row_itr = row_itr->next) {
+ if (!row_itr->name || strcasecmp((const char *)row_itr->name, "td"))
+ continue;
+ for (data_itr = row_itr->children; data_itr; data_itr = data_itr->next) {
+ struct oc_choice **new_choices;
+ char *role_link = NULL;
+ char *role_name = NULL;
+
+ if (!data_itr->name || strcasecmp((const char *)data_itr->name, "a"))
+ continue;
+
+ // Discovered <a> tag with role selection.
+ role_link = (char *)xmlGetProp(data_itr, (unsigned char *)"href");
+ if (!role_link) continue;
+
+ role_name = (char *)xmlNodeGetContent(data_itr);
+ if (!role_name) {
+ // some weird case?
+ free(role_link);
+ continue;
+ }
+
+ choice = calloc(1, sizeof(*choice));
+ if (!choice) {
+ free_auth_form(form);
+ return NULL;
+ }
+
+ choice->label = role_name;
+ choice->name = role_link;
+ new_choices = realloc(opt->choices, sizeof(opt->choices[0]) * (opt->nr_choices+1));
+ if (!new_choices) {
+ free(choice);
+ free_auth_form(form);
+ return NULL;
+ }
+ opt->choices = new_choices;
+ opt->choices[opt->nr_choices++] = choice;
+ }
+ }
+ }
+
+ return form;
+}
+
+static struct oc_auth_form *parse_roles_form_node(xmlNodePtr node)
+{
+ struct oc_auth_form *form;
+ xmlNodePtr child;
+
+ // Set form->action here as a redirect url with keys and ids.
+ for (child = htmlnode_next(node, node); child && child != node; child = htmlnode_next(node, child)) {
+ if (!child->name)
+ continue;
+
+ if (!strcasecmp((char *)child->name, "table")) {
+ char *table_id = (char *)xmlGetProp(child, (unsigned char *)"id");
+
+ if (table_id) {
+ if (!strcmp(table_id, "TABLE_SelectRole_1"))
+ form = parse_roles_table_node(child);
+
+ free(table_id);
+
+ if (form) break; // Redirect URL was constructed
+ }
+ }
+ }
+
+ return form;
+}
+
int oncp_obtain_cookie(struct openconnect_info *vpninfo)
{
int ret;
@@ -472,6 +572,7 @@ int oncp_obtain_cookie(struct openconnect_info *vpninfo)
while (1) {
char *form_buf = NULL;
+ int role_select = 0;
struct oc_text_buf *url;
if (resp_buf && resp_buf->pos)
@@ -560,6 +661,13 @@ int oncp_obtain_cookie(struct openconnect_info *vpninfo)
}
/* XXX: Actually ask the user? */
goto form_done;
+ } else if (!strcmp(form_id, "frmSelectRoles")) {
+ form = parse_roles_form_node(node);
+ if (!form) {
+ ret = -EINVAL;
+ break;
+ }
+ role_select = 1;
} else {
vpn_progress(vpninfo, PRG_ERR,
_("Unknown form ID '%s'\n"),
@@ -584,6 +692,10 @@ int oncp_obtain_cookie(struct openconnect_info *vpninfo)
goto out;
}
+ if (role_select) {
+ vpninfo->redirect_url = strdup(form->opts[0]._value);
+ goto do_redirect;
+ }
form_done:
append_form_opts(vpninfo, form, resp_buf);
ret = buf_error(resp_buf);
@@ -592,6 +704,7 @@ int oncp_obtain_cookie(struct openconnect_info *vpninfo)
vpninfo->redirect_url = form->action;
form->action = NULL;
+ do_redirect:
free_auth_form(form);
form = NULL;
handle_redirect(vpninfo);
--
David Woodhouse Open Source Technology Centre
David.Woodhouse at intel.com Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5760 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/openconnect-devel/attachments/20160719/e3a0bb09/attachment.bin>
More information about the openconnect-devel
mailing list