]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 428659 รข\80\93 Setting SSL param to 'authenticated sessions' only protects logins...
authordkl%redhat.com <>
Mon, 18 Aug 2008 08:57:38 +0000 (08:57 +0000)
committerdkl%redhat.com <>
Mon, 18 Aug 2008 08:57:38 +0000 (08:57 +0000)
doesn't protect WebService calls at all
Patch by David Lawrence <dkl@redhat.com> - r/a=LpSolit/mkanat

Bugzilla.pm
Bugzilla/Auth/Login/CGI.pm
Bugzilla/CGI.pm
Bugzilla/Util.pm
Bugzilla/WebService.pm
index.cgi
token.cgi

index a20aa0f6b1a911d7214391ba8147ef3c7c5432e8..abba18924ada792d9538351d237f11f34ad353ac 100644 (file)
@@ -270,6 +270,14 @@ sub login {
     else {
         $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 980e2712390062461e5cc97c7598cd79414f7129..9e008be82cba920c80f7389c5afb19e40f288a19 100644 (file)
@@ -65,12 +65,17 @@ sub fail_nodata {
             ->faultstring('Login Required');
     }
 
-    # Redirect to SSL if required
-    if (Bugzilla->params->{'sslbase'} ne '' 
-        and Bugzilla->params->{'ssl'} ne 'never') 
+    # 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 8c8b590cc822652386b8f51b3cc722201c17d70f..d5d361cbcae381a301223051b328432ac6c137e9 100644 (file)
@@ -71,14 +71,6 @@ sub new {
     # Send appropriate charset
     $self->charset(Bugzilla->params->{'utf8'} ? 'UTF-8' : '');
 
-    # Redirect to SSL if required
-    if (Bugzilla->params->{'sslbase'} ne ''
-        && Bugzilla->params->{'ssl'} eq 'always'
-        && i_am_cgi())
-    {
-        $self->require_https(Bugzilla->params->{'sslbase'});
-    }
-
     # Check for errors
     # All of the Bugzilla code wants to do this, so do it here instead of
     # in each script
@@ -297,18 +289,23 @@ sub remove_cookie {
 
 # Redirect to https if required
 sub require_https {
-     my $self = shift;
-     if ($self->protocol ne 'https') {
-         my $url = shift;
-         if (defined $url) {
-             $url .= $self->url('-path_info' => 1, '-query' => 1, '-relative' => 1);
-         } else {
-             $url = $self->self_url;
-             $url =~ s/^http:/https:/i;
-         }
-         print $self->redirect(-location => $url);
-         exit;
-    }
+     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_WEBSERVICE ? 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_WEBSERVICE ? 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);
+     # When using XML-RPC with mod_perl, we need the headers sent immediately.
+     $self->r->rflush if $ENV{MOD_PERL};
+     exit;
 }
 
 1;
@@ -375,10 +372,10 @@ As its only argument, it takes the name of the cookie to expire.
 
 =item C<require_https($baseurl)>
 
-This routine checks if the current page is being served over https, and
-redirects to the https protocol if required, retaining QUERY_STRING.
+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.
 
-It takes an option argument which will be used as the base URL.  If $baseurl
+It takes an optional argument which will be used as the base URL.  If $baseurl
 is not provided, the current URL is used.
 
 =back
index e7a76e21d1c8a2b5d10e9e1510233c6dd10c0c5b..1e7dbf8d1bf9e2c1edc6f7b986fdcfdedacc8901 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
+                             lsearch ssl_require_redirect
                              diff_arrays diff_strings
                              trim wrap_hard wrap_comment find_wrap_point
                              format_time format_time_decimal validate_date
@@ -218,6 +218,46 @@ 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'));
+    }
+
+    return 0;
+}
+
 sub correct_urlbase {
     my $ssl = Bugzilla->params->{'ssl'};
     return Bugzilla->params->{'urlbase'} if $ssl eq 'never';
index 94dbb621778ab2695a2ed3a65f8c0c8830c6c00c..5eb86a8d041ceaaebea99dba015c88a13413128a 100755 (executable)
@@ -19,6 +19,7 @@ package Bugzilla::WebService;
 
 use strict;
 use Bugzilla::WebService::Constants;
+use Bugzilla::Util;
 use Date::Parse;
 
 sub fail_unimplemented {
@@ -48,7 +49,21 @@ sub handle_login {
     eval "require $class";
 
     return if $class->login_exempt($method);
-    Bugzilla->login;
+    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. 
+    my $full_method = $uri . "." . $method;
+    Bugzilla->cgi->require_https(Bugzilla->params->{'sslbase'})
+        if ssl_require_redirect($full_method);
 
     return;
 }
index 100941765d9c03e82659ab593e3186d8b4d8ac8e..89880d1632d60ce012d9af957e898b0de51bfde7 100755 (executable)
--- a/index.cgi
+++ b/index.cgi
@@ -46,7 +46,9 @@ my $user = Bugzilla->login(LOGIN_OPTIONAL);
 my $cgi = Bugzilla->cgi;
 # Force to use HTTPS unless Bugzilla->params->{'ssl'} equals 'never'.
 # This is required because the user may want to log in from here.
-if (Bugzilla->params->{'sslbase'} ne '' and Bugzilla->params->{'ssl'} ne 'never') {
+if ($cgi->protocol ne 'https' && Bugzilla->params->{'sslbase'} ne ''
+    && Bugzilla->params->{'ssl'} ne 'never')
+{
     $cgi->require_https(Bugzilla->params->{'sslbase'});
 }
 
index c91c2f94ffbbbd8b82c2bd54eba8888cc3750899..d7f9f3c98a52b1682ba651afc83fe7343fae8c30 100755 (executable)
--- a/token.cgi
+++ b/token.cgi
@@ -346,8 +346,9 @@ sub request_create_account {
     $vars->{'email'} = $login_name . Bugzilla->params->{'emailsuffix'};
     $vars->{'date'} = str2time($date);
 
-    # We require a HTTPS connection if possible.
-    if (Bugzilla->params->{'sslbase'} ne ''
+    # 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'});