Can't connect to Juniper VPN because: "Unknown form ID 'frmSelectRoles'"
Benjamin Cardon
bj.cardon at gmail.com
Tue Jul 19 15:16:54 PDT 2016
David,
This worked PERFECTLY! Wow, thanks, this is so much easier to set up
and use than my previous solution. :)
Also, I'm on KDE 5.5... I'm guessing I can't test the NetworkManager
integration from here?
BJ
On Tue, Jul 19, 2016 at 3:24 PM, David Woodhouse <dwmw2 at infradead.org> wrote:
> 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
>
More information about the openconnect-devel
mailing list