Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 292459 Details for
Bug 406231
3.13: Login system enhancements
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Patch to add series key based login to 3.x Bugzilla code
series_login.patch (text/plain), 16.41 KB, created by
David Lawrence
on 2008-01-22 05:00:29 UTC
(
hide
)
Description:
Patch to add series key based login to 3.x Bugzilla code
Filename:
MIME Type:
Creator:
David Lawrence
Created:
2008-01-22 05:00:29 UTC
Size:
16.41 KB
patch
obsolete
>? patches >? lib/.htaccess >Index: Bugzilla/Auth.pm >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Auth.pm,v >retrieving revision 1.20 >diff -u -r1.20 Auth.pm >--- Bugzilla/Auth.pm 12 Jul 2006 11:51:43 -0000 1.20 >+++ Bugzilla/Auth.pm 22 Jan 2008 04:46:36 -0000 >@@ -150,6 +150,12 @@ > elsif ($fail_code == AUTH_ERROR) { > ThrowCodeError($result->{error}, $result->{details}); > } >+ elsif ($fail_code == AUTH_BADSESSION) { >+ $self->{_persister}->logout(); >+ # XXX This is NOT a good way to do this, architecturally. >+ $self->{_persister}->clear_browser_cookies(); >+ ThrowUserError('stolen_session_cookie'); >+ } > elsif ($fail_code == AUTH_NODATA) { > if ($login_type == LOGIN_REQUIRED) { > # This seems like as good as time as any to get rid of >Index: Bugzilla/Constants.pm >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Constants.pm,v >retrieving revision 1.87 >diff -u -r1.87 Constants.pm >--- Bugzilla/Constants.pm 12 Jan 2008 17:20:50 -0000 1.87 >+++ Bugzilla/Constants.pm 22 Jan 2008 04:46:36 -0000 >@@ -55,6 +55,7 @@ > AUTH_LOGINFAILED > AUTH_DISABLED > AUTH_NO_SUCH_USER >+ AUTH_BADSESSION > > USER_PASSWORD_MIN_LENGTH > USER_PASSWORD_MAX_LENGTH >@@ -210,6 +211,7 @@ > use constant AUTH_LOGINFAILED => 3; > use constant AUTH_DISABLED => 4; > use constant AUTH_NO_SUCH_USER => 5; >+use constant AUTH_BADSESSION => 6; > > # The minimum and maximum lengths a password must have. > use constant USER_PASSWORD_MIN_LENGTH => 3; >Index: Bugzilla/Auth/Login/Cookie.pm >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Auth/Login/Cookie.pm,v >retrieving revision 1.5 >diff -u -r1.5 Cookie.pm >--- Bugzilla/Auth/Login/Cookie.pm 5 Jul 2006 23:42:47 -0000 1.5 >+++ Bugzilla/Auth/Login/Cookie.pm 22 Jan 2008 04:46:36 -0000 >@@ -35,32 +35,26 @@ > my $cgi = Bugzilla->cgi; > my $dbh = Bugzilla->dbh; > >- my $ip_addr = $cgi->remote_addr(); >- my $net_addr = get_netaddr($ip_addr); >- my $login_cookie = $cgi->cookie("Bugzilla_logincookie"); >- my $user_id = $cgi->cookie("Bugzilla_login"); >- >- # If cookies cannot be found, this could mean that they haven't >- # been made available yet. In this case, look at Bugzilla_cookie_list. >- unless ($login_cookie) { >- my $cookie = first {$_->name eq 'Bugzilla_logincookie'} >- @{$cgi->{'Bugzilla_cookie_list'}}; >- $login_cookie = $cookie->value if $cookie; >- } >- unless ($user_id) { >- my $cookie = first {$_->name eq 'Bugzilla_login'} >- @{$cgi->{'Bugzilla_cookie_list'}}; >- $user_id = $cookie->value if $cookie; >- } >+ my $cookie_info = $self->get_cookie_info($cgi); >+ return { failure => AUTH_NODATA } if !$cookie_info->{userid}; >+ >+ my $ip_addr = $cgi->remote_addr(); >+ my $net_addr = get_netaddr($ip_addr); >+ my $token = $cookie_info->{token}; >+ my $session = $cookie_info->{session}; >+ my $user_id = $cookie_info->{userid}; > >- if ($login_cookie && $user_id) { >+ if ($token && $user_id) { > # Anything goes for these params - they're just strings which > # we're going to verify against the db > trick_taint($ip_addr); >- trick_taint($login_cookie); >+ trick_taint($token); >+ trick_taint($session); > detaint_natural($user_id); >- >- my $query = "SELECT userid >+ >+ my $query = "SELECT logincookies.userid, >+ logincookies.cookie, >+ logincookies.session > FROM logincookies > WHERE logincookies.cookie = ? > AND logincookies.userid = ? >@@ -68,7 +62,7 @@ > > # If we have a network block that's allowed to use this cookie, > # as opposed to just a single IP. >- my @params = ($login_cookie, $user_id, $ip_addr); >+ my @params = ($token, $user_id, $ip_addr); > if (defined $net_addr) { > trick_taint($net_addr); > $query .= " OR logincookies.ipaddr = ?"; >@@ -76,14 +70,27 @@ > } > $query .= ")"; > >- # If the cookie is valid, return a valid username. >- if ($dbh->selectrow_array($query, undef, @params)) { >- # If we logged in successfully, then update the lastused >- # time on the login cookie >- $dbh->do("UPDATE logincookies SET lastused = NOW() >- WHERE cookie = ?", undef, $login_cookie); >- return { user_id => $user_id }; >+ my ( $db_userid, $db_token, $db_session ) >+ = $dbh->selectrow_array( $query, undef, @params ); >+ >+ # This could happen because their login info has been deleted from >+ # the logincookies table since they last logged in >+ if ( not( $db_userid and $db_token ) ) { >+ return { failure => AUTH_NODATA }; > } >+ >+ # A row was returned that matched on the cookie and userid. >+ # Check if we recieved a session ID then make sure it matches >+ if ( $session and ( $session ne $db_session ) ) { >+ return { failure => AUTH_BADSESSION }; >+ } >+ >+ # If the cookie is valid, return a valid username. >+ # If we logged in successfully, then update the lastused >+ # time on the login cookie >+ $dbh->do("UPDATE logincookies SET lastused = NOW() >+ WHERE cookie = ?", undef, $token); >+ return { user_id => $user_id }; > } > > # Either the he cookie is invalid, or we got no cookie. We don't want >@@ -93,4 +100,68 @@ > return { failure => AUTH_NODATA }; > } > >+sub get_cookie_info { >+ my $self = shift; >+ my $cgi = shift || Bugzilla->cgi; >+ my $MAC_SECRET = Bugzilla->params->{mac_secret}; >+ >+ ########## >+ # Token # >+ ########## >+ >+ my @info = $cgi->cookie('Bugzilla_logincookie'); >+ if ( not( @info == 6 ) ) { >+ # expect 3 key/val pairs (userid/token/MAC) >+ return { userid => 0 }; >+ } >+ >+ my %info = @info; >+ >+ # Find attributes >+ for my $attr qw(userid token MAC) { >+ if ( not $info{$attr} ) { >+ return { userid => 0 }; >+ } >+ } >+ >+ # This method of using a MAC to make sure a cookie is valid >+ # is discussed in the Eagle Book. >+ my $MAC = Digest::SHA1::sha1_hex( $info{userid} . $info{token} . $MAC_SECRET ); >+ >+ # If the cookie's MAC matches the one we generate, we know >+ # that the cookie has not been tampered with. >+ if ( $info{MAC} ne $MAC ) { >+ return { userid => 0 }; >+ } >+ >+ ############ >+ # Session # >+ ############ >+ >+ my @session_info = $cgi->cookie('Bugzilla_session'); >+ if ( @session_info == 4 ) { >+ >+ # expect 2 key/val pairs (session/MAC) >+ my %sinfo = @session_info; >+ >+ my $sMAC = Digest::SHA1::sha1_hex( $sinfo{session}, $MAC_SECRET ); >+ if ( $sinfo{MAC} ne $sMAC ) { >+ return { userid => 0 }; >+ } >+ >+ $info{session} = $sinfo{session}; >+ } >+ >+ ######################################## >+ # untaint data and return as hash ref # >+ ######################################## >+ >+ delete $info{MAC}; # discard >+ trick_taint( $info{userid} ); >+ trick_taint( $info{token} ); >+ trick_taint( $info{session} ) if $info{session}; >+ >+ return \%info; >+} >+ > 1; >Index: Bugzilla/Auth/Persist/Cookie.pm >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Auth/Persist/Cookie.pm,v >retrieving revision 1.5 >diff -u -r1.5 Cookie.pm >--- Bugzilla/Auth/Persist/Cookie.pm 3 Jul 2006 21:42:46 -0000 1.5 >+++ Bugzilla/Auth/Persist/Cookie.pm 22 Jan 2008 04:46:37 -0000 >@@ -35,7 +35,7 @@ > use Bugzilla::Constants; > use Bugzilla::Util; > use Bugzilla::Token; >- >+use Digest::SHA1; > use List::Util qw(first); > > sub new { >@@ -45,7 +45,7 @@ > } > > sub persist_login { >- my ($self, $user) = @_; >+ my ($self, $user, $token, $session) = @_; > my $dbh = Bugzilla->dbh; > my $cgi = Bugzilla->cgi; > >@@ -60,12 +60,18 @@ > # subsequent login > trick_taint($ip_addr); > >- my $login_cookie = >- Bugzilla::Token::GenerateUniqueToken('logincookies', 'cookie'); >+ my $ref; >+ if ( $token and $session ) { >+ $ref = _update_lastused( $user->id, $token, $session ); >+ } >+ elsif ($token) { >+ $ref = _update_lastused_new_session( $user->id, $token ); >+ } >+ else { >+ $ref = _insert_new_session( $user->id, $ip_addr ); >+ } > >- $dbh->do("INSERT INTO logincookies (cookie, userid, ipaddr, lastused) >- VALUES (?, ?, ?, NOW())", >- undef, $login_cookie, $user->id, $ip_addr); >+ my $MAC_SECRET = Bugzilla->params->{mac_secret}; > > # Remember cookie only if admin has told so > # or admin didn't forbid it and user told to remember. >@@ -74,22 +80,100 @@ > $cgi->param('Bugzilla_remember') && > $cgi->param('Bugzilla_remember') eq 'on') ) > { >- $cgi->send_cookie(-name => 'Bugzilla_login', >- -value => $user->id, >- -expires => 'Fri, 01-Jan-2038 00:00:00 GMT'); > $cgi->send_cookie(-name => 'Bugzilla_logincookie', >- -value => $login_cookie, >+ -value => { >+ userid => $user->id, >+ token => $ref->{token}, >+ MAC => Digest::SHA1::sha1_hex( $user->id . $ref->{token} . $MAC_SECRET ) >+ }, >+ -expires => 'Fri, 01-Jan-2038 00:00:00 GMT'); >+ $cgi->send_cookie(-name => 'Bugzilla_session', >+ -value => { >+ session => $ref->{session}, >+ MAC => Digest::SHA1::sha1_hex( $ref->{session}, $MAC_SECRET ), >+ }, > -expires => 'Fri, 01-Jan-2038 00:00:00 GMT'); > > } > else { >- $cgi->send_cookie(-name => 'Bugzilla_login', >- -value => $user->id); > $cgi->send_cookie(-name => 'Bugzilla_logincookie', >- -value => $login_cookie); >+ -value => { >+ userid => $user->id, >+ token => $ref->{token}, >+ MAC => Digest::SHA1::sha1_hex( $user->id . $ref->{token} . $MAC_SECRET ) >+ }); >+ $cgi->send_cookie(-name => 'Bugzilla_session', >+ -value => { >+ session => $ref->{session}, >+ MAC => Digest::SHA1::sha1_hex( $ref->{session}, $MAC_SECRET ), >+ }); > } > } > >+# record in db the last time this user connected >+sub _update_lastused { >+ my ( $userid, $token, $session ) = @_; >+ >+ # same session, same token >+ my $query = "UPDATE logincookies >+ SET lastused = NOW() >+ WHERE cookie = ? >+ AND userid = ? >+ AND session = ?"; >+ my @bindv = ( $token, $userid, $session ); >+ >+ my $dbh = Bugzilla->dbh; >+ $dbh->do( $query, undef, @bindv ); >+ >+ return { token => $token, session => $session }; >+} >+ >+# user has come back with a good token but no session >+# allow them in, update lastused and create them a new session >+sub _update_lastused_new_session { >+ my ( $userid, $token ) = @_; >+ >+ # new session, same token >+ my $session = generate_unique_id(); >+ >+ my $query = "UPDATE logincookies >+ SET lastused = NOW(), >+ session = ? >+ WHERE cookie = ? >+ AND userid = ?"; >+ my @bindv = ( $session, $token, $userid ); >+ >+ my $dbh = Bugzilla->dbh; >+ $dbh->do( $query, undef, @bindv ); >+ >+ return { token => $token, session => $session }; >+} >+ >+# totally new login. create new session and new login token >+sub _insert_new_session { >+ my $userid = shift; >+ my $ipaddr = shift; >+ >+ my $session = generate_unique_id(); >+ my $token = generate_unique_id(); >+ >+ my $dbh = Bugzilla->dbh; >+ $dbh->do( >+ "INSERT INTO logincookies >+ (cookie, session, userid, lastused, ipaddr) >+ VALUES ( ?, ?, ?, NOW(), ?)", >+ undef, $token, $session, $userid, $ipaddr >+ ); >+ >+ return { token => $token, session => $session }; >+} >+ >+# generate unique id >+sub generate_unique_id { >+ Digest::SHA1::sha1_hex( >+ Digest::SHA1::sha1_hex( time() . {} . rand() . $$ ) ); >+} >+ > sub logout { > my ($self, $param) = @_; > >@@ -144,8 +228,8 @@ > > sub clear_browser_cookies { > my $cgi = Bugzilla->cgi; >- $cgi->remove_cookie('Bugzilla_login'); > $cgi->remove_cookie('Bugzilla_logincookie'); >+ $cgi->remove_cookie('Bugzilla_session'); > } > > 1; >Index: Bugzilla/Config/Auth.pm >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Config/Auth.pm,v >retrieving revision 1.3 >diff -u -r1.3 Auth.pm >--- Bugzilla/Config/Auth.pm 2 Aug 2007 22:38:39 -0000 1.3 >+++ Bugzilla/Config/Auth.pm 22 Jan 2008 04:46:37 -0000 >@@ -104,6 +104,12 @@ > }, > > { >+ name => 'mac_secret', >+ type => 't', >+ default => '', >+ }, >+ >+ { > name => 'emailregexp', > type => 't', > default => q:^[\\w\\.\\+\\-=]+@[\\w\\.\\-]+\\.[\\w\\-]+$:, >Index: Bugzilla/DB/Schema.pm >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/DB/Schema.pm,v >retrieving revision 1.97 >diff -u -r1.97 Schema.pm >--- Bugzilla/DB/Schema.pm 9 Jan 2008 15:14:02 -0000 1.97 >+++ Bugzilla/DB/Schema.pm 22 Jan 2008 04:46:39 -0000 >@@ -829,7 +829,7 @@ > > logincookies => { > FIELDS => [ >- cookie => {TYPE => 'varchar(16)', NOTNULL => 1, >+ cookie => {TYPE => 'varchar(40)', NOTNULL => 1, > PRIMARYKEY => 1}, > userid => {TYPE => 'INT3', NOTNULL => 1, > REFERENCES => {TABLE => 'profiles', >@@ -837,6 +837,7 @@ > DELETE => 'CASCADE'}}, > ipaddr => {TYPE => 'varchar(40)', NOTNULL => 1}, > lastused => {TYPE => 'DATETIME', NOTNULL => 1}, >+ session => {TYPE => 'varchar(40)', NOTNULL => 1}, > ], > INDEXES => [ > logincookies_lastused_idx => ['lastused'], >Index: template/en/default/admin/params/auth.html.tmpl >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/template/en/default/admin/params/auth.html.tmpl,v >retrieving revision 1.4 >diff -u -r1.4 auth.html.tmpl >--- template/en/default/admin/params/auth.html.tmpl 5 Dec 2007 00:48:30 -0000 1.4 >+++ template/en/default/admin/params/auth.html.tmpl 22 Jan 2008 04:46:39 -0000 >@@ -111,6 +111,9 @@ > requirelogin => "If this option is set, all access to the system beyond the " _ > "front page will require a login. No anonymous users will " _ > "be permitted.", >+ >+ mac_secret => "If the cookie\'s MAC matches the one we generate, " _ >+ "we know that a cookie has not been tampered with.", > > emailregexp => "This defines the regexp to use for legal email addresses. The " _ > "default tries to match fully qualified email addresses. Another " _ >Index: template/en/default/global/user-error.html.tmpl >=================================================================== >RCS file: /cvsroot/mozilla/webtools/bugzilla/template/en/default/global/user-error.html.tmpl,v >retrieving revision 1.243 >diff -u -r1.243 user-error.html.tmpl >--- template/en/default/global/user-error.html.tmpl 20 Jan 2008 02:35:25 -0000 1.243 >+++ template/en/default/global/user-error.html.tmpl 22 Jan 2008 04:46:41 -0000 >@@ -885,6 +885,13 @@ > [% title = "Invalid Username Or Password" %] > The username or password you entered is not valid. > >+ [% ELSIF error == "stolen_session_cookie" %] >+ [% title = "Invalid Cookie Token. All Sessions Logged Out" %] >+ The session token on your cookie in invalid. It's possible someone >+ has stolen your cookie. >+ As a precaution all of your sessions have been invalidated. You >+ will need to <a href="query.cgi?GoAheadAndLogIn=1">relogin</a>. >+ > [% ELSIF error == "keyword_already_exists" %] > [% title = "Keyword Already Exists" %] > A keyword with the name [% name FILTER html %] already exists.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 406231
:
292459
|
292694