Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Allow specification of an "alternative secret" field for GP login for…
…m(s), instead of 'passwd'.

The alternative field is specified by appending :FIELDNAME to the URL path, or --usergroup.

Known use cases:

	openconnect --protocol=gp vpn.bigcorp.com --usergroup=gateway:prelogin-cookie
	openconnect --protocol=gp vpn.bigcorp.com --usergroup=portal:portal-userauthcookie

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
  • Loading branch information
dlenski authored and dwmw2 committed May 31, 2018
1 parent 78091bb commit 8b2bc5f
Showing 1 changed file with 24 additions and 11 deletions.
35 changes: 24 additions & 11 deletions auth-globalprotect.c
Expand Up @@ -40,12 +40,13 @@ void gpst_common_headers(struct openconnect_info *vpninfo,
* 2) one secret value:
* - normal account password
* - "challenge" (2FA) password, along with form name in auth_id
* - cookie from external authentication flow (INSTEAD OF password)
*
* This function steals the value of auth_id and prompt and username for
* use in the auth form.
* use in the auth form; pw_or_cookie_field is NOT stolen.
*/
static struct oc_auth_form *auth_form(struct openconnect_info *vpninfo,
char *prompt, char *auth_id, char *username)
char *prompt, char *auth_id, char *username, char *pw_or_cookie_field)
{
struct oc_auth_form *form;
struct oc_form_opt *opt, *opt2;
Expand All @@ -70,8 +71,9 @@ static struct oc_auth_form *auth_form(struct openconnect_info *vpninfo,
opt2 = opt->next = calloc(1, sizeof(*opt));
if (!opt2)
goto nomem;
opt2->name = strdup("passwd");
opt2->label = auth_id ? strdup(_("Challenge: ")) : strdup(_("Password: "));
opt2->name = strdup(pw_or_cookie_field ? : "passwd");
if (asprintf(&opt2->label, "%s: ", auth_id ? _("Challenge") : (pw_or_cookie_field ? : _("Password"))) == 0)
return NULL;

/* XX: Some VPNs use a password in the first form, followed by a
* a token in the second ("challenge") form. Others use only a
Expand Down Expand Up @@ -316,7 +318,7 @@ static int parse_portal_xml(struct openconnect_info *vpninfo, xmlNode *xml_node)
return result;
}

static int gpst_login(struct openconnect_info *vpninfo, int portal)
static int gpst_login(struct openconnect_info *vpninfo, int portal, char *pw_or_cookie_field)
{
int result;

Expand All @@ -335,7 +337,7 @@ static int gpst_login(struct openconnect_info *vpninfo, int portal)
}
#endif

form = auth_form(vpninfo, prompt, NULL, NULL);
form = auth_form(vpninfo, prompt, NULL, NULL, pw_or_cookie_field);
if (!form)
return -ENOMEM;

Expand Down Expand Up @@ -389,7 +391,7 @@ static int gpst_login(struct openconnect_info *vpninfo, int portal)
char *username = form->opts ? form->opts->_value : NULL;
form->opts->_value = NULL;
free_auth_form(form);
form = auth_form(vpninfo, prompt, auth_id, username);
form = auth_form(vpninfo, prompt, auth_id, username, pw_or_cookie_field);
if (!form)
return -ENOMEM;
} else if (portal && result == 0) {
Expand All @@ -412,21 +414,32 @@ static int gpst_login(struct openconnect_info *vpninfo, int portal)

int gpst_obtain_cookie(struct openconnect_info *vpninfo)
{
char *pw_or_cookie_field = NULL;
int result;

/* An alternate password/secret field may be specified in the "URL path". Known possibilities:
* /portal:portal-userauthcookie
* /gateway:prelogin-cookie
*/
if (vpninfo->urlpath
&& (pw_or_cookie_field = strrchr(vpninfo->urlpath, ':'))!=NULL) {
*pw_or_cookie_field = '\0';
pw_or_cookie_field++;
}

if (vpninfo->urlpath && (!strcmp(vpninfo->urlpath, "portal") || !strncmp(vpninfo->urlpath, "global-protect", 14))) {
/* assume the server is a portal */
return gpst_login(vpninfo, 1);
return gpst_login(vpninfo, 1, pw_or_cookie_field);
} else if (vpninfo->urlpath && (!strcmp(vpninfo->urlpath, "gateway") || !strncmp(vpninfo->urlpath, "ssl-vpn", 7))) {
/* assume the server is a gateway */
return gpst_login(vpninfo, 0);
return gpst_login(vpninfo, 0, pw_or_cookie_field);
} else {
/* first try handling it as a gateway, then a portal */
result = gpst_login(vpninfo, 0);
result = gpst_login(vpninfo, 0, pw_or_cookie_field);
if (result == -EEXIST) {
/* XX: Don't we want to start by trying the same username/password the user just
entered for the 'gateway' attempt? */
result = gpst_login(vpninfo, 1);
result = gpst_login(vpninfo, 1, pw_or_cookie_field);
if (result == -EEXIST)
vpn_progress(vpninfo, PRG_ERR, _("Server is neither a GlobalProtect portal nor a gateway.\n"));
}
Expand Down

0 comments on commit 8b2bc5f

Please sign in to comment.