LP#1908576: Restrict login redirection
authorMike Rylander <mrylander@gmail.com>
Thu, 1 Dec 2022 19:13:35 +0000 (14:13 -0500)
committerJason Boyer <JBoyer@equinoxOLI.org>
Wed, 17 May 2023 14:25:31 +0000 (10:25 -0400)
This commit implements a new global flag: opac.login_redirect_domains
When this flag is enabled, redirection from login via redirect_to will
be restricted to local URLs.  For local URLs, they must either start
with a / (provide an absolute path) or the hostname in the URL must
match the current hostname and have a scheme of http, https, ftp, or
ftps.

The value for the global flag can be set to a list of comma-separated
domain names.  Redirection to these domains, and subdomains/hosts
thereof, will also be allowed.  For all non-local URLs allowed by the
global flag value, the scheme must be one of http, https, ftp, or ftps.

Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Jason Stephenson <jason@sigio.com>
Signed-off-by: Jason Boyer <JBoyer@equinoxOLI.org>

Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.data.login_redirect_regexp.sql [new file with mode: 0644]

index f5c59a9..3df5c1d 100644 (file)
@@ -716,7 +716,30 @@ sub load_login {
         );
     }
 
+    # TODO: maybe move this logic to generic_redirect()?
     my $redirect_to = $cgi->param('redirect_to') || $acct;
+    if (my $login_redirect_gf = $self->editor->retrieve_config_global_flag('opac.login_redirect_domains')) {
+        if ($login_redirect_gf->enabled eq 't') {
+
+            my @redir_hosts = ();
+            if ($login_redirect_gf->value) {
+                @redir_hosts = map { '(?:[^/.]+\.)*' . quotemeta($_) } grep { $_ } split(/,\s*/, $login_redirect_gf->value);
+            }
+            unshift @redir_hosts, quotemeta($ctx->{hostname});
+
+            my $hn = join('|', @redir_hosts);
+            my $relative_redir = qr#^(?:(?:(?:(?:f|ht)tps?:)?(?://(?:$hn))(?:/|$))|/$|/[^/]+)#;
+
+            if ($redirect_to !~ $relative_redir) {
+                $logger->warn(
+                    "Login redirection of [$redirect_to] ".
+                    "disallowed based on Global Flag opac.".
+                    "login_redirect_domains RE [$relative_redir]"
+                );
+                $redirect_to = $acct; # fall back to myopac/main
+            }
+        }
+    }
 
     return
         $self->_perform_any_sso_required($response, $redirect_to, $cookie_list)
index ec54030..9de9799 100644 (file)
@@ -23281,10 +23281,7 @@ VALUES (
         'Limit the number of global concurrent matching search queries',
         'cgf', 'label'
     )
-);
-
-INSERT INTO config.global_flag (name, value, enabled, label)
-VALUES (
+), (
     'opac.max_concurrent_search.ip',
     '0',
     TRUE,
@@ -23293,6 +23290,15 @@ VALUES (
         'Limit the number of global concurrent searches per client IP address',
         'cgf', 'label'
     )
+), (
+    'opac.login_redirect_domains',
+    '',
+    TRUE,
+    oils_i18n_gettext(
+        'opac.login_redirect_domains',
+        'Restrict post-login redirection to local URLs, or those that match the supplied comma-separated list of foreign domains or host names.',
+        'cgf', 'label'
+    )
 );
 
 INSERT INTO config.global_flag (name, enabled, label) VALUES (
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.login_redirect_regexp.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.login_redirect_regexp.sql
new file mode 100644 (file)
index 0000000..c8a5f98
--- /dev/null
@@ -0,0 +1,21 @@
+BEGIN;
+
+-- check whether patch can be applied
+SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+-- 950.data.seed-values.sql
+
+INSERT INTO config.global_flag (name, value, enabled, label)
+VALUES (
+    'opac.login_redirect_domains',
+    '',
+    TRUE,
+    oils_i18n_gettext(
+        'opac.login_redirect_domains',
+        'Restrict post-login redirection to local URLs, or those that match the supplied comma-separated list of foreign domains or host names.',
+        'cgf', 'label'
+    )
+);
+
+COMMIT;
+