summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CGI.pl42
-rw-r--r--defparams.pl26
-rw-r--r--template/en/default/account/login.html.tmpl23
3 files changed, 82 insertions, 9 deletions
diff --git a/CGI.pl b/CGI.pl
index f4a9813f0..1e534b384 100644
--- a/CGI.pl
+++ b/CGI.pl
@@ -412,12 +412,31 @@ sub PasswordForLogin {
return $result;
}
+sub get_netaddr {
+ my ($ipaddr) = @_;
+
+ # Check for a valid IPv4 addr which we know how to parse
+ if ($ipaddr !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
+ return undef;
+ }
+
+ my $addr = unpack("N", pack("CCCC", split(/\./, $ipaddr)));
+
+ my $maskbits = Param('loginnetmask');
+
+ $addr >>= (32-$maskbits);
+ $addr <<= (32-$maskbits);
+ return join(".", unpack("CCCC", pack("N", $addr)));
+}
+
sub quietly_check_login() {
$::disabledreason = '';
my $userid = 0;
+ my $ipaddr = $ENV{'REMOTE_ADDR'};
+ my $netaddr = get_netaddr($ipaddr);
if (defined $::COOKIE{"Bugzilla_login"} &&
defined $::COOKIE{"Bugzilla_logincookie"}) {
- SendSQL("SELECT profiles.userid," .
+ my $query = "SELECT profiles.userid," .
" profiles.login_name, " .
" profiles.disabledtext " .
" FROM profiles, logincookies WHERE logincookies.cookie = " .
@@ -425,8 +444,14 @@ sub quietly_check_login() {
" AND profiles.userid = logincookies.userid AND" .
" profiles.login_name = " .
SqlQuote($::COOKIE{"Bugzilla_login"}) .
- " AND logincookies.ipaddr = " .
- SqlQuote($ENV{"REMOTE_ADDR"}));
+ " AND (logincookies.ipaddr = " .
+ SqlQuote($ipaddr);
+ if (defined $netaddr) {
+ $query .= " OR logincookies.ipaddr = " . SqlQuote($netaddr);
+ }
+ $query .= ")";
+ SendSQL($query);
+
my @row;
if (MoreSQLData()) {
($userid, my $loginname, my $disabledtext) = FetchSQLData();
@@ -728,7 +753,16 @@ sub confirm_login {
# the cookies.
if($enteredlogin ne "") {
$::COOKIE{"Bugzilla_login"} = $enteredlogin;
- SendSQL("insert into logincookies (userid,ipaddr) values (@{[DBNameToIdAndCheck($enteredlogin)]}, @{[SqlQuote($ENV{'REMOTE_ADDR'})]})");
+ my $ipaddr = $ENV{'REMOTE_ADDR'};
+
+ # Unless we're restricting the login, or restricting would have no
+ # effect, loosen the IP which we record in the table
+ unless ($::FORM{'Bugzilla_restrictlogin'} ||
+ Param('loginnetmask') == 32) {
+ $ipaddr = get_netaddr($ipaddr);
+ $ipaddr = $ENV{'REMOTE_ADDR'} unless defined $ipaddr;
+ }
+ SendSQL("insert into logincookies (userid,ipaddr) values (@{[DBNameToIdAndCheck($enteredlogin)]}, @{[SqlQuote($ipaddr)]})");
SendSQL("select LAST_INSERT_ID()");
my $logincookie = FetchOneColumn();
diff --git a/defparams.pl b/defparams.pl
index 8e931006f..232b6c346 100644
--- a/defparams.pl
+++ b/defparams.pl
@@ -111,6 +111,21 @@ sub check_webdotbase {
return "";
}
+sub check_netmask {
+ my ($mask) = @_;
+ my $res = check_numeric($mask);
+ return $res if $res;
+ if ($mask < 0 || $mask > 32) {
+ return "an IPv4 netmask must be between 0 and 32 bits";
+ }
+ # Note that if we changed the netmask from anything apart from 32, then
+ # existing logincookies which aren't for a single IP won't work
+ # any more. We can't know which ones they are, though, so they'll just
+ # take space until they're preiodically cleared, later.
+
+ return "";
+}
+
# OK, here are the parameter definitions themselves.
#
# Each definition is a hash with keys:
@@ -845,6 +860,17 @@ Reason: %reason%
type => 't',
default => ''
},
+
+ {
+ name => 'loginnetmask',
+ desc => 'The number of bits for the netmask used if a user chooses to ' .
+ 'allow a login to be valid for more than a single IP. Setting ' .
+ 'this to 32 disables this feature.<br>' .
+ 'Note that enabling this may decrease the security of your system.',
+ type => 't',
+ default => '32',
+ checker => \&check_netmask
+ },
);
1;
diff --git a/template/en/default/account/login.html.tmpl b/template/en/default/account/login.html.tmpl
index 29b5b1aee..16a49580f 100644
--- a/template/en/default/account/login.html.tmpl
+++ b/template/en/default/account/login.html.tmpl
@@ -38,8 +38,8 @@
<form action="[% target %]" method="POST">
<table>
- [% IF Param("useLDAP") %]
- <tr>
+ <tr>
+ [% IF Param("useLDAP") %]
<td align="right">
<b>Username:</b>
</td>
@@ -54,9 +54,7 @@
<td>
<input type="password" size="10" name="LDAP_password">
</td>
- </tr>
- [% ELSE %]
- <tr>
+ [% ELSE %]
<td align="right">
<b>E-mail address:</b>
</td>
@@ -71,8 +69,23 @@
<td>
<input type="password" size="35" name="Bugzilla_password">
</td>
+ [% END %]
+ [% IF Param('loginnetmask') < 32 %]
+ <tr>
+ <td align="right">
+ <b>
+ Restrict this session<br>
+ to this IP address:
+ </b>
+ </td>
+ <td>
+ <input type="checkbox" name="Bugzilla_restrictlogin"
+ checked="checked">
+ (Using this option increases security)
+ </td>
</tr>
[% END %]
+ </tr>
</table>
[% PROCESS "global/hidden-fields.html.tmpl"