[Bps-public-commit] rt-authen-externalauth branch, master, updated. 0.09-9-g35ed38a
Thomas Sibley
trs at bestpractical.com
Fri Jan 13 16:09:04 EST 2012
The branch, master has been updated
via 35ed38a0acdfbcde5be195ee79521e0ae0855e6c (commit)
from 32d24eabd8641a1bfb2b7f27352428a2ed9a87b3 (commit)
Summary of changes:
lib/RT/Authen/ExternalAuth.pm.orig | 672 ------------------------------------
1 files changed, 0 insertions(+), 672 deletions(-)
delete mode 100644 lib/RT/Authen/ExternalAuth.pm.orig
- Log -----------------------------------------------------------------
commit 35ed38a0acdfbcde5be195ee79521e0ae0855e6c
Author: Thomas Sibley <trs at bestpractical.com>
Date: Fri Jan 13 16:08:59 2012 -0500
Delete cruft leftover from running patch
diff --git a/lib/RT/Authen/ExternalAuth.pm.orig b/lib/RT/Authen/ExternalAuth.pm.orig
deleted file mode 100644
index 7b7acc2..0000000
--- a/lib/RT/Authen/ExternalAuth.pm.orig
+++ /dev/null
@@ -1,672 +0,0 @@
-package RT::Authen::ExternalAuth;
-
-our $VERSION = '0.09';
-
-=head1 NAME
-
- RT::Authen::ExternalAuth - RT Authentication using External Sources
-
-=head1 DESCRIPTION
-
- A complete package for adding external authentication mechanisms
- to RT. It currently supports LDAP via Net::LDAP and External Database
- authentication for any database with an installed DBI driver.
-
- It also allows for authenticating cookie information against an
- external database through the use of the RT-Authen-CookieAuth extension.
-
-=head1 UPGRADING
-
-If you are upgrading from an earlier version of this extension, you must
-remove the following files manually:
-
- $RTHOME/local/plugins/RT-Authen-ExternalAuth/lib/RT/User_Vendor.pm
- $RTHOME/local/lib/RT/User_Vendor.pm
- $RTHOME/local/lib/RT/Authen/External_Auth.pm
-
-Otherwise you will most likely encounter an error about modifying a read
-only value and be unable to start RT.
-
-You may not have all of these files. It depends what versions you are
-upgrading between.
-
-If you are using a vendor packaged RT, your local directories are likely
-to be somewhere under /usr/local instead of in $RTHOME so you will need
-to visit Configuration -> Tools -> System Configuration to find your
-plugin root.
-
-=head2 VERSION NOTES
-
-If you are using RT 3.6, you want to use the 0.05 version.
-
-If you are using RT 3.8.0 or 3.8.1, you may have trouble using this
-due to RT bugs related to plugins, but you may be able to use 0.08.
-
-0.08_02 or later will not work on 3.8.0 or 3.8.1
-
-If you are using RT 4.0.0 or greater, you must use at least 0.09
-
-=head1 MORE ABOUT THIS MODULE
-
-This module provides the ability to authenticate RT users
-against one or more external data sources at once. It will
-also allow information about that user to be loaded from
-the same, or any other available, source as well as allowing
-multple redundant servers for each method.
-
-The extension currently supports authentication and
-information from LDAP via the Net::LDAP module, and from
-any data source that an installed DBI driver is available
-for.
-
-It is also possible to use cookies set by an alternate
-application for Single Sign-On (SSO) with that application.
-For example, you may integrate RT with your own website login
-system so that once users log in to your website, they will be
-automagically logged in to RT when they access it.
-
-It was originally designed and tested against:
-
-MySQL v4.1.21-standard
-MySQL v5.0.22
-Windows Active Directory v2003
-
-But it has been designed so that it should work with ANY
-LDAP service and ANY DBI-drivable database, based upon the
-configuration given in your $RTHOME/etc/RT_SiteConfig.pm
-
-As of v0.08 ExternalAuth also allows you to pull a browser
-cookie value and test it against a DBI data source allowing
-the use of cookies for Single Sign-On (SSO) authentication
-with another application or website login system. This is
-due to the merging of RT::Authen::ExternalAuth and
-RT::Authen::CookieAuth. For example, you may integrate RT
-with your own website login system so that once users log in
-to your website, they will be automagically logged in to RT
-when they access it.
-
-
-=head1 INSTALLATION
-
-To install this module, run the following commands:
-
- perl Makefile.PL
- make
- make install
-
-If you are using RT 3.8.x, you need to enable this
-module by adding RT::Authen::ExternalAuth to your
- at Plugins configuration:
-
-Set( @Plugins, qw(RT::Authen::ExternalAuth) );
-
-If you already have a @Plugins line, add RT::Authen::ExternalAuth to the
-existing list. Adding a second @Plugins line will cause interesting
-bugs.
-
-Once installed, you should view the file:
-
-3.4/3.6 $RTHOME/local/etc/ExternalAuth/RT_SiteConfig.pm
-3.8 $RTHOME/local/plugins/RT-Authen-ExternalAuth/etc/RT_SiteConfig.pm
-
-Then use the examples provided to prepare your own custom
-configuration which should be added to your site configuration in
-$RTHOME/etc/RT_SiteConfig.pm
-
-=head1 AUTHOR
- Mike Peachey
- Jennic Ltd.
- zordrak at cpan.org
-
- Various Best Practical Developers
-
-=head1 COPYRIGHT AND LICENCE
-
-Copyright (C) 2008, Jennic Ltd.
-
-This software is released under version 2 of the GNU
-General Public License. The license is distributed with
-this package in the LICENSE file found in the directory
-root.
-
-=cut
-
-use RT::Authen::ExternalAuth::LDAP;
-use RT::Authen::ExternalAuth::DBI;
-
-use strict;
-
-sub DoAuth {
- my ($session,$given_user,$given_pass) = @_;
-
- unless(defined($RT::ExternalAuthPriority)) {
- return (0, "ExternalAuthPriority not defined, please check your configuration file.");
- }
-
- my $no_info_check = 0;
- unless(defined($RT::ExternalInfoPriority)) {
- $RT::Logger->debug("ExternalInfoPriority not defined. User information (including user enabled/disabled cannot be externally-sourced");
- $no_info_check = 1;
- }
-
- # This may be used by single sign-on (SSO) authentication mechanisms for bypassing a password check.
- my $pass_bypass = 0;
- my $success = 0;
-
- # Should have checked if user is already logged in before calling this function,
- # but just in case, we'll check too.
- return (0, "User already logged in!") if ($session->{'CurrentUser'} && $session->{'CurrentUser'}->Id);
- # We don't have a logged in user. Let's try all our available methods in order.
- # last if success, next if not.
-
- # Get the prioritised list of external authentication services
- my @auth_services = @$RT::ExternalAuthPriority;
-
- # For each of those services..
- foreach my $service (@auth_services) {
-
- $pass_bypass = 0;
-
- # Get the full configuration for that service as a hashref
- my $config = $RT::ExternalSettings->{$service};
- $RT::Logger->debug( "Attempting to use external auth service:",
- $service);
-
- # $username will be the final username we decide to check
- # This will not necessarily be $given_user
- my $username = undef;
-
- #############################################################
- ####################### SSO Check ###########################
- #############################################################
- if ($config->{'type'} eq 'cookie') {
- # Currently, Cookie authentication is our only SSO method
- $username = RT::Authen::ExternalAuth::DBI::GetCookieAuth($config);
- }
- #############################################################
-
- # If $username is defined, we have a good SSO $username and can
- # safely bypass the password checking later on; primarily because
- # it's VERY unlikely we even have a password to check if an SSO succeeded.
- $pass_bypass = 0;
- if(defined($username)) {
- $RT::Logger->debug("Pass not going to be checked, attempting SSO");
- $pass_bypass = 1;
- } else {
-
- # SSO failed and no $user was passed for a login attempt
- # We only don't return here because the next iteration could be an SSO attempt
- unless(defined($given_user)) {
- $RT::Logger->debug("SSO Failed and no user to test with. Nexting");
- next;
- }
-
- # We don't have an SSO login, so we will be using the credentials given
- # on RT's login page to do our authentication.
- $username = $given_user;
-
- # Don't continue unless the service works.
- # next unless RT::Authen::ExternalAuth::TestConnection($config);
-
- # Don't continue unless the $username exists in the external service
-
- $RT::Logger->debug("Calling UserExists with \$username ($username) and \$service ($service)");
- next unless RT::Authen::ExternalAuth::UserExists($username, $service);
- }
-
- ####################################################################
- ########## Load / Auto-Create ######################################
- ####################################################################
- # We are now sure that we're talking about a valid RT user.
- # If the user already exists, load up their info. If they don't
- # then we need to create the user in RT.
-
- # Does user already exist internally to RT?
- $session->{'CurrentUser'} = RT::CurrentUser->new();
- $session->{'CurrentUser'}->Load($username);
-
- # Unless we have loaded a valid user with a UserID create one.
- unless ($session->{'CurrentUser'}->Id) {
- my $UserObj = RT::User->new($RT::SystemUser);
- my ($val, $msg) =
- $UserObj->Create(%{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
- Name => $username,
- Gecos => $username,
- );
- unless ($val) {
- $RT::Logger->error( "Couldn't create user $username: $msg" );
- next;
- }
- $RT::Logger->info( "Autocreated external user",
- $UserObj->Name,
- "(",
- $UserObj->Id,
- ")");
-
- $RT::Logger->debug("Loading new user (",
- $username,
- ") into current session");
- $session->{'CurrentUser'}->Load($username);
- }
-
- ####################################################################
- ########## Authentication ##########################################
- ####################################################################
- # If we successfully used an SSO service, then authentication
- # succeeded. If we didn't then, success is determined by a password
- # test.
- $success = 0;
- if($pass_bypass) {
- $RT::Logger->debug("Password check bypassed due to SSO method being in use");
- $success = 1;
- } else {
- $RT::Logger->debug("Password validation required for service - Executing...");
- $success = RT::Authen::ExternalAuth::GetAuth($service,$username,$given_pass);
- }
-
- $RT::Logger->debug("Password Validation Check Result: ",$success);
-
- # If the password check succeeded then this is our authoritative service
- # and we proceed to user information update and login.
- last if $success;
- }
-
- # If we got here and don't have a user loaded we must have failed to
- # get a full, valid user from an authoritative external source.
- unless ($session->{'CurrentUser'} && $session->{'CurrentUser'}->Id) {
- delete $session->{'CurrentUser'};
- return (0, "No User");
- }
-
- unless($success) {
- delete $session->{'CurrentUser'};
- return (0, "Password Invalid");
- }
-
- # Otherwise we succeeded.
- $RT::Logger->debug("Authentication successful. Now updating user information and attempting login.");
-
- ####################################################################################################
- ############################### The following is auth-method agnostic ##############################
- ####################################################################################################
-
- # If we STILL have a completely valid RT user to play with...
- # and therefore password has been validated...
- if ($session->{'CurrentUser'} && $session->{'CurrentUser'}->Id) {
-
- # Even if we have JUST created the user in RT, we are going to
- # reload their information from an external source. This allows us
- # to be sure that the user the cookie gave us really does exist in
- # the database, but more importantly, UpdateFromExternal will check
- # whether the user is disabled or not which we have not been able to
- # do during auto-create
-
- # These are not currently used, but may be used in the future.
- my $info_updated = 0;
- my $info_updated_msg = "User info not updated";
-
- unless($no_info_check) {
- # Note that UpdateUserInfo does not care how we authenticated the user
- # It will look up user info from whatever is specified in $RT::ExternalInfoPriority
- ($info_updated,$info_updated_msg) = RT::Authen::ExternalAuth::UpdateUserInfo($session->{'CurrentUser'}->Name);
- }
-
- # Now that we definitely have up-to-date user information,
- # if the user is disabled, kick them out. Now!
- if ($session->{'CurrentUser'}->UserObj->Disabled) {
- delete $session->{'CurrentUser'};
- return (0, "User account disabled, login denied");
- }
- }
-
- # If we **STILL** have a full user and the session hasn't already been deleted
- # This If/Else is logically unnecessary, but it doesn't hurt to leave it here
- # just in case. Especially to be a double-check to future modifications.
- if ($session->{'CurrentUser'} && $session->{'CurrentUser'}->Id) {
-
- $RT::Logger->info( "Successful login for",
- $session->{'CurrentUser'}->Name,
- "from",
- $ENV{'REMOTE_ADDR'});
- # Do not delete the session. User stays logged in and
- # autohandler will not check the password again
- } else {
- # Make SURE the session is deleted.
- delete $session->{'CurrentUser'};
- return (0, "Failed to authenticate externally");
- # This will cause autohandler to request IsPassword
- # which will in turn call IsExternalPassword
- }
-
- return (1, "Successful login");
-}
-
-sub UpdateUserInfo {
- my $username = shift;
-
- # Prepare for the worst...
- my $found = 0;
- my $updated = 0;
- my $msg = "User NOT updated";
-
- my $user_disabled = RT::Authen::ExternalAuth::UserDisabled($username);
-
- my $UserObj = RT::User->new($RT::SystemUser);
- $UserObj->Load($username);
-
- # If user is disabled, set the RT::Principal to disabled and return out of the function.
- # I think it's a waste of time and energy to update a user's information if they are disabled
- # and it could be a security risk if they've updated their external information with some
- # carefully concocted code to try to break RT - worst case scenario, but they have been
- # denied access after all, don't take any chances.
-
- # If someone gives me a good enough reason to do it,
- # then I'll update all the info for disabled users
-
- if ($user_disabled) {
- unless ( $UserObj->Disabled ) {
- # Make sure principal is disabled in RT
- my ($val, $message) = $UserObj->SetDisabled(1);
- # Log what has happened
- $RT::Logger->info("User marked as DISABLED (",
- $username,
- ") per External Service",
- "($val, $message)\n");
- $msg = "User Disabled";
- }
-
- return ($updated, $msg);
- }
-
- # Make sure principal is not disabled in RT
- if ( $UserObj->Disabled ) {
- my ($val, $message) = $UserObj->SetDisabled(0);
- unless ( $val ) {
- $RT::Logger->error("Failed to enable user ($username) per External Service: ".($message||''));
- return ($updated, "Failed to enable");
- }
-
- $RT::Logger->info("User ($username) was disabled, marked as ENABLED ",
- "per External Service",
- "($val, $message)\n");
- }
-
- # Update their info from external service using the username as the lookup key
- # CanonicalizeUserInfo will work out for itself which service to use
- # Passing it a service instead could break other RT code
- my %args = (Name => $username);
- $UserObj->CanonicalizeUserInfo(\%args);
-
- # For each piece of information returned by CanonicalizeUserInfo,
- # run the Set method for that piece of info to change it for the user
- foreach my $key (sort(keys(%args))) {
- next unless $args{$key};
- my $method = "Set$key";
- # We do this on the UserObj from above, not self so that there
- # are no permission restrictions on setting information
- my ($method_success,$method_msg) = $UserObj->$method($args{$key});
-
- # If your user information is not getting updated,
- # uncomment the following logging statements
- if ($method_success) {
- # At DEBUG level, log that method succeeded
- # $RT::Logger->debug((caller(0))[3],"$method Succeeded. $method_msg");
- } else {
- # At DEBUG level, log that method failed
- # $RT::Logger->debug((caller(0))[3],"$method Failed. $method_msg");
- }
- }
-
- # Confirm update success
- $updated = 1;
- $RT::Logger->debug( "UPDATED user (",
- $username,
- ") from External Service\n");
- $msg = 'User updated';
-
- return ($updated, $msg);
-}
-
-sub GetAuth {
-
- # Request a username/password check from the specified service
- # This is only valid for non-SSO services.
-
- my ($service,$username,$password) = @_;
-
- my $success = 0;
-
- # Get the full configuration for that service as a hashref
- my $config = $RT::ExternalSettings->{$service};
-
- # And then act accordingly depending on what type of service it is.
- # Right now, there is only code for DBI and LDAP non-SSO services
- if ($config->{'type'} eq 'db') {
- $success = RT::Authen::ExternalAuth::DBI::GetAuth($service,$username,$password);
- $RT::Logger->debug("DBI password validation result:",$success);
- } elsif ($config->{'type'} eq 'ldap') {
- $success = RT::Authen::ExternalAuth::LDAP::GetAuth($service,$username,$password);
- $RT::Logger->debug("LDAP password validation result:",$success);
- } else {
- $RT::Logger->error("Invalid service type for GetAuth:",$service);
- }
-
- return $success;
-}
-
-sub UserExists {
-
- # Request a username/password check from the specified service
- # This is only valid for non-SSO services.
-
- my ($username,$service) = @_;
-
- my $success = 0;
-
- # Get the full configuration for that service as a hashref
- my $config = $RT::ExternalSettings->{$service};
-
- # And then act accordingly depending on what type of service it is.
- # Right now, there is only code for DBI and LDAP non-SSO services
- if ($config->{'type'} eq 'db') {
- $success = RT::Authen::ExternalAuth::DBI::UserExists($username,$service);
- } elsif ($config->{'type'} eq 'ldap') {
- $success = RT::Authen::ExternalAuth::LDAP::UserExists($username,$service);
- } else {
- $RT::Logger->debug("Invalid service type for UserExists:",$service);
- }
-
- return $success;
-}
-
-sub UserDisabled {
-
- my $username = shift;
- my $user_disabled = 0;
-
- my @info_services = $RT::ExternalInfoPriority ? @{$RT::ExternalInfoPriority} : undef;
-
- # For each named service in the list
- # Check to see if the user is found in the external service
- # If not found, jump to next service
- # If found, check to see if user is considered disabled by the service
- # Then update the user's info in RT and return
- foreach my $service (@info_services) {
-
- # Get the external config for this service as a hashref
- my $config = $RT::ExternalSettings->{$service};
-
- # If the config doesn't exist, don't bother doing anything, skip to next in list.
- unless(defined($config)) {
- $RT::Logger->debug("You haven't defined a configuration for the service named \"",
- $service,
- "\" so I'm not going to try to get user information from it. Skipping...");
- next;
- }
-
- # If it's a DBI config:
- if ($config->{'type'} eq 'db') {
-
- unless(RT::Authen::ExternalAuth::DBI::UserExists($username,$service)) {
- $RT::Logger->debug("User (",
- $username,
- ") doesn't exist in service (",
- $service,
- ") - Cannot update information - Skipping...");
- next;
- }
- $user_disabled = RT::Authen::ExternalAuth::DBI::UserDisabled($username,$service);
-
- } elsif ($config->{'type'} eq 'ldap') {
-
- unless(RT::Authen::ExternalAuth::LDAP::UserExists($username,$service)) {
- $RT::Logger->debug("User (",
- $username,
- ") doesn't exist in service (",
- $service,
- ") - Cannot update information - Skipping...");
- next;
- }
- $user_disabled = RT::Authen::ExternalAuth::LDAP::UserDisabled($username,$service);
-
- } elsif ($config->{'type'} eq 'cookie') {
- RT::Logger->error("You cannot use SSO Cookies as an information service.");
- next;
- } else {
- # The type of external service doesn't currently have any methods associated with it. Or it's a typo.
- RT::Logger->error("Invalid type specification for config %config->{'name'}");
- # Drop out to next service in list
- next;
- }
-
- }
- return $user_disabled;
-}
-
-sub CanonicalizeUserInfo {
-
- # Careful, this $args hashref was given to RT::User::CanonicalizeUserInfo and
- # then transparently passed on to this function. The whole purpose is to update
- # the original hash as whatever passed it to RT::User is expecting to continue its
- # code with an update args hash.
-
- my $UserObj = shift;
- my $args = shift;
-
- my $found = 0;
- my %params = (Name => undef,
- EmailAddress => undef,
- RealName => undef);
-
- $RT::Logger->debug( (caller(0))[3],
- "called by",
- caller,
- "with:",
- join(", ", map {sprintf("%s: %s", $_, $args->{$_})}
- sort(keys(%$args))));
-
- # Get the list of defined external services
- my @info_services = $RT::ExternalInfoPriority ? @{$RT::ExternalInfoPriority} : undef;
- # For each external service...
- foreach my $service (@info_services) {
-
- $RT::Logger->debug( "Attempting to get user info using this external service:",
- $service);
-
- # Get the config for the service so that we know what attrs we can canonicalize
- my $config = $RT::ExternalSettings->{$service};
-
- if($config->{'type'} eq 'cookie'){
- $RT::Logger->debug("You cannot use SSO cookies as an information service!");
- next;
- }
-
- # For each attr we've been told to canonicalize in the match list
- foreach my $rt_attr (@{$config->{'attr_match_list'}}) {
- # Jump to the next attr in $args if this one isn't in the attr_match_list
- $RT::Logger->debug( "Attempting to use this canonicalization key:",$rt_attr);
- unless(defined($args->{$rt_attr})) {
- $RT::Logger->debug("This attribute (",
- $rt_attr,
- ") is null or incorrectly defined in the attr_map for this service (",
- $service,
- ")");
- next;
- }
-
- # Else, use it as a canonicalization key and lookup the user info
- my $key = $config->{'attr_map'}->{$rt_attr};
- my $value = $args->{$rt_attr};
-
- # Check to see that the key being asked for is defined in the config's attr_map
- my $valid = 0;
- my ($attr_key, $attr_value);
- my $attr_map = $config->{'attr_map'};
- while (($attr_key, $attr_value) = each %$attr_map) {
- $valid = 1 if ($key eq $attr_value);
- }
- unless ($valid){
- $RT::Logger->debug( "This key (",
- $key,
- "is not a valid attribute key (",
- $service,
- ")");
- next;
- }
-
- # Use an if/elsif structure to do a lookup with any custom code needed
- # for any given type of external service, or die if no code exists for
- # the service requested.
-
- if($config->{'type'} eq 'ldap'){
- ($found, %params) = RT::Authen::ExternalAuth::LDAP::CanonicalizeUserInfo($service,$key,$value);
- } elsif ($config->{'type'} eq 'db') {
- ($found, %params) = RT::Authen::ExternalAuth::DBI::CanonicalizeUserInfo($service,$key,$value);
- } else {
- $RT::Logger->debug( (caller(0))[3],
- "does not consider",
- $service,
- "a valid information service");
- }
-
- # Don't Check any more attributes
- last if $found;
- }
- # Don't Check any more services
- last if $found;
- }
-
- # If found, Canonicalize Email Address and
- # update the args hash that we were given the hashref for
- if ($found) {
- # It's important that we always have a canonical email address
- if ($params{'EmailAddress'}) {
- $params{'EmailAddress'} = $UserObj->CanonicalizeEmailAddress($params{'EmailAddress'});
- }
- %$args = (%$args, %params);
- }
-
- $RT::Logger->info( (caller(0))[3],
- "returning",
- join(", ", map {sprintf("%s: %s", $_, $args->{$_})}
- sort(keys(%$args))));
-
- ### HACK: The config var below is to overcome the (IMO) bug in
- ### RT::User::Create() which expects this function to always
- ### return true or rejects the user for creation. This should be
- ### a different config var (CreateUncanonicalizedUsers) and
- ### should be honored in RT::User::Create()
- return($found || $RT::AutoCreateNonExternalUsers);
-
-}
-
-{
- no warnings 'redefine';
- *RT::User::CanonicalizeUserInfo = sub {
- my $self = shift;
- my $args = shift;
- return ( CanonicalizeUserInfo( $self, $args ) );
- };
-}
-
-1;
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list