From d306c2edbbc171d5345b3378bd76ed5b69984316 Mon Sep 17 00:00:00 2001 From: "bugreport%peshkin.net" <> Date: Wed, 11 Aug 2004 20:53:43 +0000 Subject: Bug 241903: Add Environment Variable Authentication for apache auth and SSO patch by erik r=joel a=justdave --- Bugzilla/Auth/Login/WWW.pm | 10 ++- Bugzilla/Auth/Login/WWW/CGI.pm | 3 + Bugzilla/Auth/Login/WWW/Env.pm | 182 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 Bugzilla/Auth/Login/WWW/Env.pm (limited to 'Bugzilla/Auth') 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 + +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 + -- cgit v1.2.3-24-g4f1b