]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 514913: Eliminate ssl="authenticated sessions"
authormkanat%bugzilla.org <>
Fri, 9 Oct 2009 04:31:08 +0000 (04:31 +0000)
committermkanat%bugzilla.org <>
Fri, 9 Oct 2009 04:31:08 +0000 (04:31 +0000)
Patch by Max Kanat-Alexander <mkanat@bugzilla.org> r=dkl, a=mkanat

15 files changed:
Bugzilla.pm
Bugzilla/Auth/Login/CGI.pm
Bugzilla/Auth/Persist/Cookie.pm
Bugzilla/CGI.pm
Bugzilla/Config.pm
Bugzilla/Config/Core.pm
Bugzilla/Mailer.pm
Bugzilla/Util.pm
Bugzilla/WebService/Server.pm
docs/en/xml/administration.xml
index.cgi
template/en/default/account/auth/login-small.html.tmpl
template/en/default/admin/params/core.html.tmpl
template/en/default/bug/edit.html.tmpl
token.cgi

index 43a9b39ae9492600225e21ad9312ff3100ac0043..62b1af659a0853f4785e61e44bbacbefb1261282 100644 (file)
@@ -85,7 +85,6 @@ use constant SHUTDOWNHTML_EXIT_SILENTLY => [
 sub init_page {
     (binmode STDOUT, ':utf8') if Bugzilla->params->{'utf8'};
 
-
     if (${^TAINT}) {
         # Some environment variables are not taint safe
         delete @::ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
@@ -94,6 +93,12 @@ sub init_page {
         $ENV{'PATH'} = '';
     }
 
+    # Because this function is run live from perl "use" commands of
+    # other scripts, we're skipping the rest of this function if we get here
+    # during a perl syntax check (perl -c, like we do during the
+    # 001compile.t test).
+    return if $^C;
+
     # IIS prints out warnings to the webpage, so ignore them, or log them
     # to a file if the file exists.
     if ($ENV{SERVER_SOFTWARE} && $ENV{SERVER_SOFTWARE} =~ /microsoft-iis/i) {
@@ -108,18 +113,15 @@ sub init_page {
         };
     }
 
+    do_ssl_redirect_if_required();
+
     # If Bugzilla is shut down, do not allow anything to run, just display a
     # message to the user about the downtime and log out.  Scripts listed in 
     # SHUTDOWNHTML_EXEMPT are exempt from this message.
     #
-    # Because this is code which is run live from perl "use" commands of other
-    # scripts, we're skipping this part if we get here during a perl syntax 
-    # check -- runtests.pl compiles scripts without running them, so we 
-    # need to make sure that this check doesn't apply to 'perl -c' calls.
-    #
     # This code must go here. It cannot go anywhere in Bugzilla::CGI, because
     # it uses Template, and that causes various dependency loops.
-    if (!$^C && Bugzilla->params->{"shutdownhtml"} 
+    if (Bugzilla->params->{"shutdownhtml"} 
         && lsearch(SHUTDOWNHTML_EXEMPT, basename($0)) == -1)
     {
         # Allow non-cgi scripts to exit silently (without displaying any
@@ -318,14 +320,6 @@ sub login {
         $class->set_user($authenticated_user);
     }
 
-    # We run after the login has completed since
-    # some of the checks in ssl_require_redirect
-    # look for Bugzilla->user->id to determine 
-    # if redirection is required.
-    if (i_am_cgi() && ssl_require_redirect()) {
-        $class->cgi->require_https($class->params->{'sslbase'});
-    }
-    
     return $class->user;
 }
 
index 5be98aa7ac8c82505a13105db2052485de6943f9..a93bc3d3a33b3f8d44b0f37b84c65b14a96a98ee 100644 (file)
@@ -65,17 +65,6 @@ sub fail_nodata {
             ->faultstring('Login Required');
     }
 
-    # If system is not configured to never require SSL connections
-    # we want to always redirect to SSL since passing usernames and
-    # passwords over an unprotected connection is a bad idea. If we 
-    # get here then a login form will be provided to the user so we
-    # want this to be protected if possible.
-    if ($cgi->protocol ne 'https' && Bugzilla->params->{'sslbase'} ne ''
-        && Bugzilla->params->{'ssl'} ne 'never')
-    {
-        $cgi->require_https(Bugzilla->params->{'sslbase'});
-    }
-
     print $cgi->header();
     $template->process("account/auth/login.html.tmpl",
                        { 'target' => $cgi->url(-relative=>1) }) 
index c533252d33f1344e85a08b8181719a620f69a98e..60f90925ee67c9c4287031e1588643068a38c2a6 100644 (file)
@@ -89,11 +89,9 @@ sub persist_login {
         # Not a session cookie, so set an infinite expiry
         $cookieargs{'-expires'} = 'Fri, 01-Jan-2038 00:00:00 GMT';
     }
-    if (Bugzilla->params->{'ssl'} ne 'never'
-        && Bugzilla->params->{'sslbase'} ne '')
-    {
-        # Bugzilla->login will automatically redirect to https://,
-        # so it's safe to turn on the 'secure' bit.
+    if (Bugzilla->params->{'ssl_redirect'}) {
+        # Make these cookies only be sent to us by the browser during 
+        # HTTPS sessions, if we're using SSL.
         $cookieargs{'-secure'} = 1;
     }
 
index a00d632c34a7660b1b962e634eaa2ce1b5bc2fe2..c30e13618e031850e66d6fdc535d09ee5660efbe 100644 (file)
@@ -368,22 +368,23 @@ sub remove_cookie {
                        '-value'   => 'X');
 }
 
-# Redirect to https if required
-sub require_https {
-    my ($self, $url) = @_;
-    # Do not create query string if data submitted via XMLRPC
-    # since we want the data to be resubmitted over POST method.
-    my $query = Bugzilla->usage_mode == USAGE_MODE_XMLRPC ? 0 : 1;
-    # XMLRPC clients (SOAP::Lite at least) requires 301 to redirect properly
-    # and do not work with 302.
-    my $status = Bugzilla->usage_mode == USAGE_MODE_XMLRPC ? 301 : 302;
-    if (defined $url) {
-        $url .= $self->url('-path_info' => 1, '-query' => $query, '-relative' => 1);
-    } else {
-        $url = $self->self_url;
-        $url =~ s/^http:/https:/i;
-    }
-    print $self->redirect(-location => $url, -status => $status);
+sub redirect_to_https {
+    my $self = shift;
+    my $sslbase = Bugzilla->params->{'sslbase'};
+    # If this is a POST, we don't want ?POSTDATA in the query string.
+    # We expect the client to re-POST, which may be a violation of
+    # the HTTP spec, but the only time we're expecting it often is
+    # in the WebService, and WebService clients usually handle this
+    # correctly.
+    $self->delete('POSTDATA');
+    my $url = $sslbase . $self->url('-path_info' => 1, '-query' => 1, 
+                                    '-relative' => 1);
+
+    # XML-RPC clients (SOAP::Lite at least) require a 301 to redirect properly
+    # and do not work with 302. Our redirect really is permanent anyhow, so
+    # it doesn't hurt to make it a 301.
+    print $self->redirect(-location => $url, -status => 301);
+
     # When using XML-RPC with mod_perl, we need the headers sent immediately.
     $self->r->rflush if $ENV{MOD_PERL};
     exit;
@@ -459,13 +460,13 @@ effectively removing the cookie.
 
 As its only argument, it takes the name of the cookie to expire.
 
-=item C<require_https($baseurl)>
+=item C<redirect_to_https>
 
-This routine redirects the client to a different location using the https protocol. 
-If the client is using XMLRPC, it will not retain the QUERY_STRING since XMLRPC uses POST.
+This routine redirects the client to the https version of the page that
+they're looking at, using the C<sslbase> parameter for the redirection.
 
-It takes an optional argument which will be used as the base URL.  If $baseurl
-is not provided, the current URL is used.
+Generally you should use L<Bugzilla::Util/do_ssl_redirect_if_required>
+instead of calling this directly.
 
 =item C<redirect_to_urlbase>
 
index a20751737196e9f22ea37cb88db86d2cd923abdd..f56ffd78aaa0125270bc4d41544ed9e6c4cb77e3 100644 (file)
@@ -192,6 +192,11 @@ sub update_params {
         $param->{'mail_delivery_method'} = $translation{$method};
     }
 
+    # Convert the old "ssl" parameter to the new "ssl_redirect" parameter.
+    # Both "authenticated sessions" and "always" turn on "ssl_redirect"
+    # when upgrading.
+    $param->{'ssl_redirect'} = 1 if $param->{'ssl'} ne 'never';
+
     # --- DEFAULTS FOR NEW PARAMS ---
 
     _load_params unless %params;
index 6d413b965770a56846dd49d6ae0102b24463b8ba..91426b30acee55caa96eef9b9599eb49419ef96d 100644 (file)
@@ -68,10 +68,9 @@ sub get_param_list {
   },
 
   {
-   name => 'ssl',
-   type => 's',
-   choices => ['never', 'authenticated sessions', 'always'],
-   default => 'never'
+   name => 'ssl_redirect',
+   type => 'b',
+   default => 0
   },
 
 
index 610523b8a7e9b2dadf043a6c9161a02798b98a8b..83ae5a60046a0c9b8b5c9d740ab08bd62d4716c6 100644 (file)
@@ -82,10 +82,7 @@ sub MessageToMTA {
     #
     # We don't use correct_urlbase, because we want this URL to
     # *always* be the same for this Bugzilla, in every email,
-    # and some emails we send when we're logged out (in which case
-    # some emails might get urlbase while the logged-in emails might 
-    # get sslbase). Also, we want this to stay the same even if
-    # the admin changes the "ssl" parameter.
+    # even if the admin changes the "ssl_redirect" parameter some day.
     $email->header_set('X-Bugzilla-URL', Bugzilla->params->{'urlbase'});
     
     # We add this header to mark the mail as "auto-generated" and
index 55ec6dcf8ce796d6648b9ac672cdef8006d3b495..90525b9d42f4341e384a98910dc399fca76e042c 100644 (file)
@@ -36,7 +36,7 @@ use base qw(Exporter);
                              html_quote url_quote xml_quote
                              css_class_quote html_light_quote url_decode
                              i_am_cgi get_netaddr correct_urlbase
-                             lsearch ssl_require_redirect use_attachbase
+                             lsearch do_ssl_redirect_if_required use_attachbase
                              diff_arrays
                              trim wrap_hard wrap_comment find_wrap_point
                              format_time format_time_decimal validate_date
@@ -264,60 +264,28 @@ sub i_am_cgi {
     return exists $ENV{'SERVER_SOFTWARE'} ? 1 : 0;
 }
 
-sub ssl_require_redirect {
-    my $method = shift;
-
-    # If currently not in a protected SSL 
-    # connection, determine if a redirection is 
-    # needed based on value in Bugzilla->params->{ssl}.
-    # If we are already in a protected connection or
-    # sslbase is not set then no action is required.
-    if (uc($ENV{'HTTPS'}) ne 'ON' 
-        && $ENV{'SERVER_PORT'} != 443 
-        && Bugzilla->params->{'sslbase'} ne '')
-    {
-        # System is configured to never require SSL 
-        # so no redirection is needed.
-        return 0 
-            if Bugzilla->params->{'ssl'} eq 'never';
-            
-        # System is configured to always require a SSL
-        # connection so we need to redirect.
-        return 1
-            if Bugzilla->params->{'ssl'} eq 'always';
-
-        # System is configured such that if we are inside
-        # of an authenticated session, then we need to make
-        # sure that all of the connections are over SSL. Non
-        # authenticated sessions SSL is not mandatory.
-        # For XMLRPC requests, if the method is User.login
-        # then we always want the connection to be over SSL
-        # if the system is configured for authenticated
-        # sessions since the user's username and password
-        # will be passed before the user is logged in.
-        return 1 
-            if Bugzilla->params->{'ssl'} eq 'authenticated sessions'
-                && (Bugzilla->user->id 
-                    || (defined $method && $method eq 'User.login'));
-    }
+# This exists as a separate function from Bugzilla::CGI::redirect_to_https
+# because we don't want to create a CGI object during XML-RPC calls
+# (doing so can mess up XML-RPC).
+sub do_ssl_redirect_if_required {
+    return if !i_am_cgi();
+    return if !Bugzilla->params->{'ssl_redirect'};
 
-    return 0;
+    my $sslbase = Bugzilla->params->{'sslbase'};
+    
+    # If we're already running under SSL, never redirect.
+    return if uc($ENV{HTTPS} || '') eq 'ON';
+    # Never redirect if there isn't an sslbase.
+    return if !$sslbase;
+    Bugzilla->cgi->redirect_to_https();
 }
 
 sub correct_urlbase {
-    my $ssl = Bugzilla->params->{'ssl'};
-    return Bugzilla->params->{'urlbase'} if $ssl eq 'never';
-
+    my $ssl = Bugzilla->params->{'ssl_redirect'};
+    my $urlbase = Bugzilla->params->{'urlbase'};
     my $sslbase = Bugzilla->params->{'sslbase'};
-    if ($sslbase) {
-        return $sslbase if $ssl eq 'always';
-        # Authenticated Sessions
-        return $sslbase if Bugzilla->user->id;
-    }
 
-    # Set to "authenticated sessions" but nobody's logged in, or
-    # sslbase isn't set.
-    return Bugzilla->params->{'urlbase'};
+    return ($ssl && $sslbase) ? $sslbase : $urlbase;
 }
 
 sub use_attachbase {
@@ -830,7 +798,7 @@ cookies) to only some addresses.
 =item C<correct_urlbase()>
 
 Returns either the C<sslbase> or C<urlbase> parameter, depending on the
-current setting for the C<ssl> parameter.
+current setting for the C<ssl_redirect> parameter.
 
 =item C<use_attachbase()>
 
index dfb9f559a104a803368a54b781bcecf86ab8033f..2db182fd44f196234ccedb61a8d063f126c106c5 100644 (file)
 
 package Bugzilla::WebService::Server;
 use strict;
-use Bugzilla::Util qw(ssl_require_redirect);
 
 sub handle_login {
     my ($self, $class, $method, $full_method) = @_;
     eval "require $class";
     return if $class->login_exempt($method);
     Bugzilla->login();
-
-    # Even though we check for the need to redirect in
-    # Bugzilla->login() we check here again since Bugzilla->login()
-    # does not know what the current XMLRPC method is. Therefore
-    # ssl_require_redirect in Bugzilla->login() will have returned 
-    # false if system was configured to redirect for authenticated 
-    # sessions and the user was not yet logged in.
-    # So here we pass in the method name to ssl_require_redirect so
-    # it can then check for the extra case where the method equals
-    # User.login, which we would then need to redirect if not
-    # over a secure connection. 
-    Bugzilla->cgi->require_https(Bugzilla->params->{'sslbase'})
-        if ssl_require_redirect($full_method);
 }
 
 1;
index 6b6ff5fdaa5a1ced9bcb80d02612e6bd89bc6c73..0c9a60ce20ad3bb63ff59b4d094110b61cb0846c 100644 (file)
 
           <varlistentry>
             <term>
-              ssl
+              ssl_redirect
             </term>
             <listitem>
               <para>
-                Determines when Bugzilla will force HTTPS (SSL) connections, using
-                the URL defined in <command>sslbase</command>. 
-                Options include "always", "never", and "authenticated sessions". 
+                If enabled, Bugzilla will force HTTPS (SSL) connections, by
+                automatically redirecting any users who try to use a non-SSL
+                connection.
               </para>
             </listitem>
           </varlistentry>
index 660909452e4e19c8c83f8bd16dd0af01ab06f504..fac26434aa9d8663b2b1e7e2024361785e6859da 100755 (executable)
--- a/index.cgi
+++ b/index.cgi
@@ -56,14 +56,6 @@ if ($cgi->param('logout')) {
 # Main Body Execution
 ###############################################################################
 
-# Force to use HTTPS unless Bugzilla->params->{'ssl'} equals 'never'.
-# This is required because the user may want to log in from here.
-if ($cgi->protocol ne 'https' && Bugzilla->params->{'sslbase'} ne ''
-    && Bugzilla->params->{'ssl'} ne 'never')
-{
-    $cgi->require_https(Bugzilla->params->{'sslbase'});
-}
-
 # Return the appropriate HTTP response headers.
 print $cgi->header();
 
index 752aa64df034f1e63eb1bc1e93893397b6f78caa..710d7d0a53e0757c5527b6f4e383bdb868c397a7 100644 (file)
  [% login_target = "index.cgi" %]
 [% END %]
 
-[%# If SSL is in use, use 'sslbase', else use 'urlbase'. %]
-[% IF Param("sslbase") != "" && Param("ssl") != "never" %]
-  [% login_target = Param("sslbase") _ login_target %]
-[% ELSE %]
-  [% login_target = Param("urlbase") _ login_target %]
-[% END %]
+[% login_target = urlbase _ login_target %]
 
 <li id="mini_login_container[% qs_suffix %]">
   <span class="separator">| </span>
index d66c4a51bd6d4443ff187a0bcbe21c71fbcc6960..b65dde233e0d0e295ce7f257ac2ac9dc0a1d6903 100644 (file)
   sslbase => "The URL that is the common initial leading part of all HTTPS " _
              "(SSL) $terms.Bugzilla URLs.",
 
-  ssl => "Controls when $terms.Bugzilla should enforce sessions to use HTTPS by " _
-         "using <tt>sslbase</tt>.",
+  ssl_redirect => 
+    "When this is enabled, $terms.Bugzilla will ensure that every page is"
+    _ " accessed over SSL, by redirecting any plain HTTP requests to HTTPS"
+    _ " using the <tt>sslbase</tt> parameter. Also, when this is enabled,"
+    _ " $terms.Bugzilla will send out links using <tt>sslbase</tt> in emails"
+    _ " instead of <tt>urlbase</tt>.",
 
   cookiedomain => "The domain for $terms.Bugzilla cookies. Normally blank. " _
                   "If your website is at 'www.foo.com', setting this to " _
index 76ca259e5941e8c1e15724bf8648ff0f6c3f27dc..d5a34518271575a715f462f994537d59b958ecf0 100644 (file)
             <legend>Note</legend>
             <p>
               You need to
-              <a href="[% IF Param('ssl') != 'never' %][% Param('sslbase') %][% END %]show_bug.cgi?id=[% bug.bug_id %]&amp;GoAheadAndLogIn=1">log in</a>
+              <a href="show_bug.cgi?id=
+                       [%- bug.bug_id %]&amp;GoAheadAndLogIn=1">log in</a>
               before you can comment on or make changes to this [% terms.bug %].
             </p>
           </fieldset>
index 614feefa9d1e474253aab17c41b9702fb79babf8..d4298cde78882d729bf6ab675ba254f3345c7958 100755 (executable)
--- a/token.cgi
+++ b/token.cgi
@@ -360,15 +360,7 @@ sub request_create_account {
     $vars->{'email'} = $login_name . Bugzilla->params->{'emailsuffix'};
     $vars->{'expiration_ts'} = ctime(str2time($date) + MAX_TOKEN_AGE * 86400);
 
-    # When 'ssl' equals 'always' or 'authenticated sessions', 
-    # we want this form to always be over SSL.
-    if ($cgi->protocol ne 'https' && Bugzilla->params->{'sslbase'} ne ''
-        && Bugzilla->params->{'ssl'} ne 'never')
-    {
-        $cgi->require_https(Bugzilla->params->{'sslbase'});
-    }
     print $cgi->header();
-
     $template->process('account/email/confirm-new.html.tmpl', $vars)
       || ThrowTemplateError($template->error());
 }