Commit 3e91f7bf authored by Daniel Lenski's avatar Daniel Lenski

GlobalProtect: query and parse prelogin.esp and use it to build auth forms,...

GlobalProtect: query and parse prelogin.esp and use it to build auth forms, including preliminary SAML support

Until recently, I've believed the prelogin.esp to be useless, because the
initial GlobalProtect login form always contains the same two fields:
username and password.

However, the prelogin response is also important for signalling when SAML
login is required.  When the VPN uses SAML login, the official GP clients
redirect the user to a web-based authentication flow (e.g.  Okta,

That auth flow eventually sends the official client back to the GP VPN,
armed with a special cookie field, `portal-userauthcookie` or
`prelogin-cookie`, that needs to be submitted in place of the password
(already supported by openconnect as of 8b2bc5f2).

This preliminary SAML support simply includes the SAML method and URL in the
form banner, and fails with an error message if the cookie field name was
not specified (since it cannot be autodetected).
Signed-off-by: default avatarDaniel Lenski <>
parent 227526e3
This diff is collapsed.
......@@ -248,6 +248,24 @@ int gpst_xml_or_error(struct openconnect_info *vpninfo, char *response,
goto bad_xml;
/* Is it <prelogin-response><status>Error</status><msg>..</msg></prelogin-response> ? */
if (xmlnode_is_named(xml_node, "prelogin-response")) {
char *s = NULL;
int has_err = 0;
xmlNode *x;
for (x=xml_node->children; x; x=x->next) {
if (!xmlnode_get_val(x, "status", &s))
has_err = strcmp(s, "Success");
xmlnode_get_val(x, "msg", &err);
if (has_err)
goto out;
err = NULL;
/* is it <challenge><user></user><inputstr>...</inputstr><respmsg>...</respmsg></challenge> */
if (xmlnode_is_named(xml_node, "challenge")) {
for (xml_node=xml_node->children; xml_node; xml_node=xml_node->next) {
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment