diff options
author | bugreport%peshkin.net <> | 2004-08-11 22:53:43 +0200 |
---|---|---|
committer | bugreport%peshkin.net <> | 2004-08-11 22:53:43 +0200 |
commit | d306c2edbbc171d5345b3378bd76ed5b69984316 (patch) | |
tree | 9810bba5d11c730fd4412a962dfd263655793470 /Bugzilla | |
parent | def7903801fcdbab2f227688375f38c5cb490f27 (diff) | |
download | bugzilla-d306c2edbbc171d5345b3378bd76ed5b69984316.tar.gz bugzilla-d306c2edbbc171d5345b3378bd76ed5b69984316.tar.xz |
Bug 241903: Add Environment Variable Authentication for apache auth and SSO
patch by erik
r=joel
a=justdave
Diffstat (limited to 'Bugzilla')
-rw-r--r-- | Bugzilla/Auth/Login/WWW.pm | 10 | ||||
-rw-r--r-- | Bugzilla/Auth/Login/WWW/CGI.pm | 3 | ||||
-rw-r--r-- | Bugzilla/Auth/Login/WWW/Env.pm | 182 | ||||
-rw-r--r-- | Bugzilla/User.pm | 29 |
4 files changed, 223 insertions, 1 deletions
diff --git a/Bugzilla/Auth/Login/WWW.pm b/Bugzilla/Auth/Login/WWW.pm index def68df63..8b7724bef 100644 --- a/Bugzilla/Auth/Login/WWW.pm +++ b/Bugzilla/Auth/Login/WWW.pm @@ -36,6 +36,12 @@ sub login_class { return $current_login_class; } +# can_logout determines if a user may log out +sub can_logout { + return 1 if (login_class && login_class->can_logout); + return 0; +} + sub login { my ($class, $type) = @_; @@ -64,6 +70,8 @@ sub login { if ($userid) { $user = new Bugzilla::User($userid); + $user->set_flags('can_logout' => $class->can_logout); + # Compat stuff $::userid = $userid; } else { @@ -74,7 +82,7 @@ sub login { sub logout { my ($class, $user, $option) = @_; - if ($class->login_class) { + if (can_logout) { $class->login_class->logout($user, $option); } } diff --git a/Bugzilla/Auth/Login/WWW/CGI.pm b/Bugzilla/Auth/Login/WWW/CGI.pm index fb00cd018..3b90ec6ad 100644 --- a/Bugzilla/Auth/Login/WWW/CGI.pm +++ b/Bugzilla/Auth/Login/WWW/CGI.pm @@ -186,6 +186,9 @@ sub login { type => $type, }); } +# This auth style allows the user to log out. +sub can_logout { return 1; } + # Logs user out, according to the option provided; this consists of # removing entries from logincookies for the specified $user. sub logout { diff --git a/Bugzilla/Auth/Login/WWW/Env.pm b/Bugzilla/Auth/Login/WWW/Env.pm new file mode 100644 index 000000000..abd176315 --- /dev/null +++ b/Bugzilla/Auth/Login/WWW/Env.pm @@ -0,0 +1,182 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Bug Tracking System. +# +# The Initial Developer of the Original Code is Netscape Communications +# Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): Erik Stambaugh <erik@dasbistro.com> + +package Bugzilla::Auth::Login::WWW::Env; + +use strict; + +use Bugzilla::Config; +use Bugzilla::Error; +use Bugzilla::Util; + +sub login { + my ($class, $type) = @_; + + # XXX This does not currently work correctly with Param('requirelogin'). + # Bug 253636 will hopefully see that param's needs taken care of in a + # parent module, but for the time being, this module does not honor + # the param in the way that CGI.pm does. + + my $matched_userid = ''; + my $matched_extern_id = ''; + my $disabledtext = ''; + + my $dbh = Bugzilla->dbh; + my $sth; + + # Gather the environment variables + my $env_id = $ENV{Param("auth_env_id")}; + my $env_email = $ENV{Param("auth_env_email")}; + my $env_realname = $ENV{Param("auth_env_realname")}; + + # allow undefined values to work with trick_taint + for ($env_id, $env_email, $env_realname) { $_ ||= '' }; + # make sure the email field contains only a valid email address + my $emailregexp = Param("emailregexp"); + $env_email =~ /($emailregexp)/; + $env_email = $1; + # untaint the remaining values + trick_taint($env_id); + trick_taint($env_realname); + + if ($env_id | $env_email) { + # Look in the DB for the extern_id + if ($env_id) { + + # Not having the email address defined but having an ID isn't + # allowed. + return undef unless $env_email; + + $sth = $dbh->prepare("SELECT userid, disabledtext " . + "FROM profiles WHERE extern_id=?"); + $sth->execute($env_id); + my $fetched = $sth->fetch; + if ($fetched) { + $matched_userid = $fetched->[0]; + $disabledtext = $fetched->[1]; + } + } + + unless ($matched_userid) { + # There was either no match for the external ID given, or one was + # not present. + # + # Check to see if the email address is in there and has no + # external id assigned. We test for both the login name (which we + # also sent), and the id, so that we have a way of telling that we + # got something instead of a bunch of NULLs + $sth = $dbh->prepare("SELECT extern_id, userid, disabledtext " . + "FROM profiles WHERE login_name=?"); + $sth->execute($env_email); + + $sth->execute(); + my $fetched = $sth->fetch(); + if ($fetched) { + ($matched_extern_id, $matched_userid, $disabledtext) = @{$fetched}; + } + if ($matched_userid) { + if ($matched_extern_id) { + # someone with a different external ID has that address! + ThrowUserError("extern_id_conflict"); + } + else + { + # someone with no external ID used that address, time to + # add the ID! + $sth = $dbh->prepare("UPDATE profiles " . + "SET extern_id=? WHERE userid=?"); + $sth->execute($env_id, $matched_userid); + } + } + else + { + # Need to create a new user with that email address. Note + # that cryptpassword has been filled in with '*', since the + # user has no DB password. + $sth = $dbh->prepare("INSERT INTO profiles ( " . + "login_name, cryptpassword, " . + "realname, disabledtext " . + ") VALUES ( ?, ?, ?, '' )"); + $sth->execute($env_email, '*', $env_realname); + $sth = $dbh->prepare("SELECT last_insert_id()"); + $sth->execute(); + $matched_userid = $sth->fetch->[0]; + } + } + } + + # now that we hopefully have a username, we need to see if the data + # has to be updated + if ($matched_userid) { + $sth = $dbh->prepare("SELECT login_name, realname " . + "FROM profiles " . + "WHERE userid=?"); + $sth->execute($matched_userid); + my $fetched = $sth->fetch; + my $username = $fetched->[0]; + my $this_realname = $fetched->[1]; + if ( ($username ne $env_email) || + ($this_realname ne $env_realname) ) { + + $sth = $dbh->prepare("UPDATE profiles " . + "SET login_name=?, " . + "realname=? " . + "WHERE userid=?"); + $sth->execute($env_email, + ($env_realname || $this_realname), + $matched_userid); + $sth->execute; + } + } + + # Now we throw an error if the user has been disabled + if ($disabledtext) { + ThrowUserError("account_disabled", + {'disabled_reason' => $disabledtext}); + } + + return $matched_userid; + +} + +# This auth style does not allow the user to log out. +sub can_logout { return 0; } + +1; + +__END__ + +=head1 NAME + +Bugzilla::Auth::Env - Environment Variable Authentication + +=head1 DESCRIPTION + +Many external user authentication systems supply login information to CGI +programs via environment variables. This module checks to see if those +variables are populated and, if so, assumes authentication was successful and +returns the user's ID, having automatically created a new profile if +necessary. + +=head1 SEE ALSO + +L<Bugzilla::Auth> + diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm index a40450076..38453841b 100644 --- a/Bugzilla/User.pm +++ b/Bugzilla/User.pm @@ -79,6 +79,7 @@ sub _create { 'name' => '', 'login' => '', 'showmybugslink' => 0, + 'flags' => {}, }; bless ($self, $class); return $self unless $cond && $val; @@ -139,6 +140,19 @@ sub email { $_[0]->{login}; } sub name { $_[0]->{name}; } sub showmybugslink { $_[0]->{showmybugslink}; } +sub set_flags { + my $self = shift; + while (my $key = shift) { + $self->{'flags'}->{$key} = shift; + } +} + +sub get_flag { + my $self = shift; + my $key = shift; + return $self->{'flags'}->{$key}; +} + # Generate a string to identify the user by name + email if the user # has a name or by email only if she doesn't. sub identity { @@ -1109,6 +1123,21 @@ all MySQL supported, this will go away. Returns C<1> if the user can bless at least one group. Otherwise returns C<0>. +=item C<set_flags> +=item C<get_flag> + +User flags are template-accessible user status information, stored in the form +of a hash. For an example of use, when the current user is authenticated in +such a way that they are allowed to log out, the 'can_logout' flag is set to +true (1). The template then checks this flag before displaying the "Log Out" +link. + +C<set_flags> is called with any number of key,value pairs. Flags for each key +will be set to the specified value. + +C<get_flag> is called with a single key name, which returns the associated +value. + =back =head1 SEE ALSO |