]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
F5, Fortinet: ignore errors in landing page once we've got a cookie
authorDaniel Lenski <dlenski@gmail.com>
Fri, 23 Apr 2021 23:39:04 +0000 (16:39 -0700)
committerDaniel Lenski <dlenski@gmail.com>
Fri, 23 Apr 2021 23:44:39 +0000 (16:44 -0700)
Like Juniper, F5 and Fortinet redirect the user to a landing page (“webtop”)
after a successful authentication.  We should ignore HTTP errors in fetching
the landing page if/when we've received a valid cookie, as done for Juniper
in 3e77943692b511719d9217d2ecc43588b7c6c08b.

Tests for {f5,fortinet}-auth-and-config are still passing with these
changes.

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
f5.c
fortinet.c

diff --git a/f5.c b/f5.c
index 4035f4baf1810315ef115800900aeebbecd97968..e1c69ecfcf7e82d13c065d1a67c906b861b53723 100644 (file)
--- a/f5.c
+++ b/f5.c
@@ -68,8 +68,13 @@ static int check_cookie_success(struct openconnect_info *vpninfo)
        struct oc_vpn_option *cookie;
        const char *session = NULL, *f5_st = NULL;
 
-       /* XX: if login succeeded worked, we should have a response size of zero, and F5_ST
-        * and MRHSession cookies in the response.
+       /* XX: The MRHSession cookie is often set repeatedly to new values prior
+        * to the completion of authentication, so it is not a sufficient
+        * indicator of successfully completed authentication by itself.
+        *
+        * The combination of the MRHSession and F5_ST cookies appears to be
+        * reliable indicator. F5_ST is a "session timeout" cookie (see
+        * https://support.f5.com/csp/article/K15387).
         */
        for (cookie = vpninfo->cookies; cookie; cookie = cookie->next) {
                if (!strcmp(cookie->option, "MRHSession"))
@@ -111,15 +116,15 @@ int f5_obtain_cookie(struct openconnect_info *vpninfo)
                        ret = do_https_request(vpninfo, "GET", NULL, NULL,
                                               &resp_buf, 2);
 
-               if (ret < 0)
-                       break;
-
                if (!check_cookie_success(vpninfo)) {
                        free(resp_buf);
                        ret = 0;
                        break;
                }
 
+               if (ret < 0)
+                       break;
+
                url = internal_get_url(vpninfo);
                if (!url) {
                        free(resp_buf);
index e51994decd0718af484a4c6f75f2f0b974d1bf6c..0373e2d1406c4437aede0bf7a6680afd12357fc2 100644 (file)
@@ -194,55 +194,53 @@ int fortinet_obtain_cookie(struct openconnect_info *vpninfo)
                ret = do_https_request(vpninfo, "POST", "application/x-www-form-urlencoded",
                                       req_buf, &resp_buf, 0);
 
-               /* XX: if this worked, we should have 200 status */
-               if (ret >= 0) {
-                       /* If we got SVPNCOOKIE, then we're done. */
-                       struct oc_vpn_option *cookie;
-                       for (cookie = vpninfo->cookies; cookie; cookie = cookie->next) {
-                               if (!strcmp(cookie->option, "SVPNCOOKIE")) {
-                                       free(vpninfo->cookie);
-                                       vpninfo->cookie = strdup(cookie->value);
-                                       if (!vpninfo->cookie)
-                                               goto nomem;
-                                       ret = 0;
-                                       goto out;
-                               }
+               /* If we got SVPNCOOKIE, then we're done. */
+               struct oc_vpn_option *cookie;
+               for (cookie = vpninfo->cookies; cookie; cookie = cookie->next) {
+                       if (!strcmp(cookie->option, "SVPNCOOKIE")) {
+                               free(vpninfo->cookie);
+                               vpninfo->cookie = strdup(cookie->value);
+                               if (!vpninfo->cookie)
+                                       goto nomem;
+                               ret = 0;
+                               goto out;
                        }
+               }
 
-                       /* XX: We didn't get SVPNCOOKIE. 2FA? */
-                       if (!strncmp(resp_buf, "ret=", 4) && strstr(resp_buf, ",tokeninfo=")) {
-                               const char *prompt;
-                               struct oc_text_buf *action_buf = buf_alloc();
-
-                               /* Hide 'username' field */
-                               opt->type = OC_FORM_OPT_HIDDEN;
-                               free(opt2->label);
-                               free(opt2->_value);
-
-                               /* Change 'credential' field to 'code'. */
-                               opt2->_value = NULL;
-                               opt2->name = strdup("code");
-                               opt2->label = strdup("Code: ");
-                               if (!can_gen_tokencode(vpninfo, form, opt2))
-                                       opt2->type = OC_FORM_OPT_TOKEN;
-                               else
-                                       opt2->type = OC_FORM_OPT_PASSWORD;
-
-                               /* Save a bunch of values to parrot back */
-                               filter_opts(action_buf, resp_buf, "reqid,polid,grp,portal,peer,magic", 1);
-                               if ((ret = buf_error(action_buf)))
-                                       goto out;
-                               free(form->action);
-                               form->action = action_buf->data;
-                               action_buf->data = NULL;
-                               buf_free(action_buf);
-
-                               if ((prompt = strstr(resp_buf, ",chal_msg="))) {
-                                       const char *end = strchrnul(prompt, ',');
-                                       prompt += 10;
-                                       free(form->message);
-                                       form->message = strndup(prompt, end-prompt);
-                               }
+               /* XX: We got 200 status, but no SVPNCOOKIE. 2FA? */
+               if (ret >= 0 &&
+                   !strncmp(resp_buf, "ret=", 4) && strstr(resp_buf, ",tokeninfo=")) {
+                       const char *prompt;
+                       struct oc_text_buf *action_buf = buf_alloc();
+
+                       /* Hide 'username' field */
+                       opt->type = OC_FORM_OPT_HIDDEN;
+                       free(opt2->label);
+                       free(opt2->_value);
+
+                       /* Change 'credential' field to 'code'. */
+                       opt2->_value = NULL;
+                       opt2->name = strdup("code");
+                       opt2->label = strdup("Code: ");
+                       if (!can_gen_tokencode(vpninfo, form, opt2))
+                               opt2->type = OC_FORM_OPT_TOKEN;
+                       else
+                               opt2->type = OC_FORM_OPT_PASSWORD;
+
+                       /* Save a bunch of values to parrot back */
+                       filter_opts(action_buf, resp_buf, "reqid,polid,grp,portal,peer,magic", 1);
+                       if ((ret = buf_error(action_buf)))
+                               goto out;
+                       free(form->action);
+                       form->action = action_buf->data;
+                       action_buf->data = NULL;
+                       buf_free(action_buf);
+
+                       if ((prompt = strstr(resp_buf, ",chal_msg="))) {
+                               const char *end = strchrnul(prompt, ',');
+                               prompt += 10;
+                               free(form->message);
+                               form->message = strndup(prompt, end-prompt);
                        }
                }
        }