diff options
-rw-r--r-- | CGI.pl | 42 | ||||
-rw-r--r-- | defparams.pl | 26 | ||||
-rw-r--r-- | template/en/default/account/login.html.tmpl | 23 |
3 files changed, 82 insertions, 9 deletions
@@ -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" |