diff --git a/webtools/bugzilla/Bugzilla/Auth/Login/WWW.pm b/webtools/bugzilla/Bugzilla/Auth/Login/WWW.pm index 8b7724befc2..cc3ae25e291 100644 --- a/webtools/bugzilla/Bugzilla/Auth/Login/WWW.pm +++ b/webtools/bugzilla/Bugzilla/Auth/Login/WWW.pm @@ -70,6 +70,11 @@ sub login { if ($userid) { $user = new Bugzilla::User($userid); + # Redirect to SSL if required + if (Param('sslbase') ne '' and Param('ssl') ne 'never') { + Bugzilla->cgi->require_https(Param('sslbase')); + } + $user->set_flags('can_logout' => $class->can_logout); # Compat stuff diff --git a/webtools/bugzilla/Bugzilla/Auth/Login/WWW/CGI.pm b/webtools/bugzilla/Bugzilla/Auth/Login/WWW/CGI.pm index a66ce7425b5..10eb85f60ec 100644 --- a/webtools/bugzilla/Bugzilla/Auth/Login/WWW/CGI.pm +++ b/webtools/bugzilla/Bugzilla/Auth/Login/WWW/CGI.pm @@ -135,6 +135,12 @@ sub login { # No login details were given, but we require a login if the # page does if ($authres == AUTH_NODATA && $type == LOGIN_REQUIRED) { + + # Redirect to SSL if required + if (Param('sslbase') ne '' and Param('ssl') ne 'never') { + $cgi->require_https(Param('sslbase')); + } + # Throw up the login page print Bugzilla->cgi->header(); diff --git a/webtools/bugzilla/Bugzilla/CGI.pm b/webtools/bugzilla/Bugzilla/CGI.pm index e81cf5da8ce..ce0a8ab6c94 100644 --- a/webtools/bugzilla/Bugzilla/CGI.pm +++ b/webtools/bugzilla/Bugzilla/CGI.pm @@ -52,6 +52,11 @@ sub new { # Make sure that we don't send any charset headers $self->charset(''); + # Redirect to SSL if required + if (Param('sslbase') ne '' and Param('ssl') eq 'always') { + $self->require_https(Param('sslbase')); + } + # Check for errors # All of the Bugzilla code wants to do this, so do it here instead of # in each script @@ -185,6 +190,21 @@ sub send_cookie { return; } +# 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; + } +} 1; @@ -238,6 +258,14 @@ Bugzilla code (instead of C or the C<-cookie> argument to C
), so that under mod_perl the headers can be sent correctly, using C or the mod_perl APIs as appropriate. +=item C + +This routine checks if the current page is being served over https, and +redirects to the https protocol if required, retaining QUERY_STRING. + +It takes an option argument which will be used as the base URL. If $baseurl +is not provided, the current URL is used. + =back =head1 SEE ALSO diff --git a/webtools/bugzilla/defparams.pl b/webtools/bugzilla/defparams.pl index 4fdf52a608e..d97a0908559 100644 --- a/webtools/bugzilla/defparams.pl +++ b/webtools/bugzilla/defparams.pl @@ -50,12 +50,36 @@ use strict; use vars qw(@param_list); use File::Spec; # for find_languages +use Socket; use Bugzilla::Config qw(:DEFAULT $templatedir $webdotdir); +use Bugzilla::Util; # Checking functions for the various values # Some generic checking functions are included in Bugzilla::Config +sub check_sslbase { + my $url = shift; + if ($url ne '') { + if ($url !~ m#^https://([^/]+).*/$#) { + return "must be a legal URL, that starts with https and ends with a slash."; + } + my $host = $1; + if ($host =~ /:\d+$/) { + return "must not contain a port."; + } + local *SOCK; + my $proto = getprotobyname('tcp'); + socket(SOCK, PF_INET, SOCK_STREAM, $proto); + my $sin = sockaddr_in(443, inet_aton($host)); + if (!connect(SOCK, $sin)) { + return "Failed to connect to " . html_quote($host) . + ":443, unable to enable SSL."; + } + } + return ""; +} + sub check_priority { my ($value) = (@_); &::GetVersionTable(); @@ -292,6 +316,24 @@ sub find_languages { checker => \&check_urlbase }, + { + name => 'sslbase', + desc => 'The URL that is the common initial leading part of all HTTPS ' . + '(SSL) Bugzilla URLs.', + type => 't', + default => '', + checker => \&check_sslbase + }, + + { + name => 'ssl', + desc => 'Controls when Bugzilla should enforce sessions to use HTTPS by ' . + 'using sslbase.', + type => 's', + choices => ['never', 'authenticated sessions', 'always'], + default => 'never' + }, + { name => 'languages' , desc => 'A comma-separated list of RFC 1766 language tags. These ' .