]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
Support js redirects from Fortinet 7.4.x
authorJan-Michael Brummer <jan-michael.brummer1@volkswagen.de>
Wed, 6 Aug 2025 05:26:46 +0000 (07:26 +0200)
committerJan-Michael Brummer <jan-michael.brummer1@volkswagen.de>
Mon, 1 Sep 2025 12:27:06 +0000 (14:27 +0200)
Signed-off-by: Jan-Michael Brummer <jan-michael.brummer1@volkswagen.de>
fortinet.c

index 20fc68ee869757100c837a9f1984c6174cb41d80..22b5982aa5d0c581a96265e7c8501cbbf4227a27 100644 (file)
@@ -102,6 +102,7 @@ int fortinet_obtain_cookie(struct openconnect_info *vpninfo)
        struct oc_auth_form *form = NULL;
        struct oc_form_opt *opt, *opt2;
        char *resp_buf = NULL, *realm = NULL, *tokeninfo_fields = NULL, *ti;
+       char *js_top_location = NULL;
 
        req_buf = buf_alloc();
        if (buf_error(req_buf)) {
@@ -109,10 +110,35 @@ int fortinet_obtain_cookie(struct openconnect_info *vpninfo)
                goto out;
        }
 
+again:
        ret = do_https_request(vpninfo, "GET", NULL, NULL, &resp_buf, NULL, HTTP_REDIRECT);
        if (ret < 0)
                goto out;
 
+       /* Starting with FortiOS 7.4 server returns a javascript redirect request, so let's
+        * check it here and set it manually:
+        *
+        * <html><script type="text/javascript">
+        * if (window!=top) top.location=window.location;top.location="/remote/login";
+        * </script></html>
+        */
+       js_top_location = strstr(resp_buf, "top.location=\"");
+       if (js_top_location) {
+               int top_location_str_len = strlen("top.location=\"");
+               char *js_top_location_end = strchrnul(js_top_location + top_location_str_len, '"');
+               char *location = strndup(js_top_location + top_location_str_len, js_top_location_end - js_top_location - top_location_str_len);
+
+               /* Skip leading / if necessary */
+               if (location && location[0] == '/') {
+                       vpninfo->urlpath = strdup(location + 1);
+                       free(location);
+               } else {
+                       vpninfo->urlpath = location;
+               }
+
+               goto again;
+       }
+
        /* XX: Fortinet's initial 'GET /' normally redirects to /remote/login.
         * If a valid, non-default "realm" is specified (~= usergroup or authgroup),
         * it will appear as a query parameter of the resulting URL, and we need to