-%# BEGIN LICENSE BLOCK
+%# BEGIN BPS TAGGED BLOCK {{{
%#
-%# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
+%# <jesse@bestpractical.com>
%#
-%# (Except where explictly superceded by other copyright notices)
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
%#
%# This work is made available to you under the terms of Version 2 of
%# the GNU General Public License. A copy of that license should have
%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%# General Public License for more details.
%#
-%# Unless otherwise specified, all modifications, corrections or
-%# extensions to this work which alter its source code become the
-%# property of Best Practical Solutions, LLC when submitted for
-%# inclusion in the work.
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
%#
-%# END LICENSE BLOCK
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
<%INIT>
# Roll back any dangling transactions from a previous failed connection
$RT::Handle->ForceRollback() if $RT::Handle->TransactionDepth;
-local *session;
+local *session unless $m->is_subrequest; # avoid reentrancy, as suggested by masonbook
+
+# Disable AutoFlush using an attribute
+if ($m->request_comp->attr_exists('AutoFlush')) {
+ $m->autoflush($m->request_comp->attr('AutoFlush'));
+}
+
%ARGS = map {
- # if they've passed multiple values, they'll be an array. if they've passed just one, a scalar
- # whatever they are, mark them as utf8
+ # if they've passed multiple values, they'll be an array. if they've
+ # passed just one, a scalar whatever they are, mark them as utf8
my $type = ref($_);
(!$type)
- ? Encode::decode(utf8 => $_, Encode::FB_PERLQQ) :
- ($type eq 'ARRAY')
- ? [ map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } @$_ ] :
- ($type eq 'HASH')
- ? { map { ref($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } %$_ } : $_
-} %ARGS;
-
-if ($ARGS{'Debug'}) {
- require Time::HiRes;
- $m->{'rt_base_time'} = [Time::HiRes::gettimeofday()];
+ ? Encode::is_utf8($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) :
+ ($type eq 'ARRAY')
+ ? [ map { (ref($_) or Encode::is_utf8($_)) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } @$_ ] :
+ ($type eq 'HASH')
+ ? { map { (ref($_) or Encode::is_utf8($_)) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } %$_ } : $_
+ } %ARGS;
+
+$m->{'rt_base_time'} = [Time::HiRes::gettimeofday()];
-}
-else {
- $m->{'rt_base_time'} = time;
-}
$m->comp('/Elements/SetupSessionCookie', %ARGS);
unless ($session{'CurrentUser'} && $session{'CurrentUser'}->Id) {
$r->content_type("text/html; charset=utf-8");
# If it's a noauth file, don't ask for auth.
-if ($m->base_comp->path =~ '^/+NoAuth/' ||
- $m->base_comp->path =~ '^/+REST/\d+\.\d+/NoAuth/')
+if ($m->base_comp->path =~ $RT::WebNoAuthRegex )
{
$m->call_next(%ARGS);
$m->abort();
}
-# If RT is configured for external auth, let's get REMOTE_USER
-elsif ($RT::WebExternalAuth and length($ENV{'REMOTE_USER'})) {
- my $orig_user = $user;
-
- $user = $ENV{'REMOTE_USER'};
- $session{'CurrentUser'} = RT::CurrentUser->new();
- my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
-
- if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
- my $NodeName = Win32::NodeName();
- $user =~ s/^\Q$NodeName\E\\//i;
- }
-
- $session{'CurrentUser'}->$load_method($user);
-
- if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
- # Create users on-the-fly with default attributes
-
- my $UserObj = RT::User->new(RT::CurrentUser->new('root'));
-
- my ($val, $msg) = $UserObj->Create(
- %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
- Name => $user,
- Gecos => $user,
- );
-
- if ($val) {
- $UserObj->SetPrivileged(1);
-
- if ($^O !~ /^(?:riscos|MacOS|MSWin32|dos|os2)$/) {
- # Populate fields with information from Unix /etc/passwd
-
- my ($comments, $realname) = (getpwnam($user))[5, 6];
- $UserObj->SetComments($comments) if defined $comments;
- $UserObj->SetRealName($realname) if defined $realname;
+# If RT is configured for external auth, let's go through and get REMOTE_USER
+elsif ( $RT::WebExternalAuth ) {
+
+ # do we actually have a REMOTE_USER equivlent?
+ if ( RT::Interface::Web::WebCanonicalizeInfo() ) {
+
+ my $orig_user = $user;
+
+ $user = RT::Interface::Web::WebCanonicalizeInfo();
+ $session{'CurrentUser'} = RT::CurrentUser->new();
+ my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
+
+ if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
+ my $NodeName = Win32::NodeName();
+ $user =~ s/^\Q$NodeName\E\\//i;
+ }
+
+ $session{'CurrentUser'}->$load_method($user);
+
+ if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
+ # Create users on-the-fly
+
+ my $UserObj = RT::User->new(RT::CurrentUser->new('RT_System'));
+
+ my ($val, $msg) = $UserObj->Create(
+ %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
+ Name => $user,
+ Gecos => $user,
+ );
+
+ if ($val) {
+
+ # now get user specific information, to better create our user.
+ my $new_user_info = RT::Interface::Web::WebExternalAutoInfo($user);
+
+ # set the attributes that have been defined.
+ # FIXME: this is a horrible kludge. I'm sure there's something cleaner
+ foreach my $attribute ('Name', 'Comments', 'Signature', 'EmailAddress',
+ 'PagerEmailAddress', 'FreeformContactInfo',
+ 'Organization', 'Disabled', 'Privileged',
+ 'RealName', 'NickName', 'Lang', 'EmailEncoding',
+ 'WebEncoding', 'ExternalContactInfoId',
+ 'ContactInfoSystem', 'ExternalAuthId', 'Gecos',
+ 'HomePhone', 'WorkPhone', 'MobilePhone',
+ 'PagerPhone', 'Address1', 'Address2', 'City',
+ 'State', 'Zip', 'Country') {
+ $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'NewUser');
+
+ my $method = "Set$attribute";
+ $UserObj->$method($new_user_info->{$attribute})
+ if( defined $new_user_info->{$attribute} );
+ }
+ $session{'CurrentUser'}->Load($user);
}
- elsif ($^O eq 'MSWin32' and eval 'use Net::AdminMisc; 1') {
- # Populate fields with information from NT domain controller
+ else {
+ # we failed to successfully create the user. abort abort abort.
+ delete $session{'CurrentUser'};
+ $m->abort() unless $RT::WebFallbackToInternalAuth;
+ $m->comp('/Elements/Login', %ARGS,
+ Error=> loc('Cannot create user: [_1]', $msg));
}
-
- $session{'CurrentUser'}->Load($user);
}
- else {
+
+ unless ( $session{'CurrentUser'}->Id() ) {
delete $session{'CurrentUser'};
- $m->abort() unless $RT::WebFallbackToInternalAuth;
- $m->comp('/Elements/Login', %ARGS, Error=> loc('Cannot create user: [_1]', $msg));
+ $user = $orig_user;
+
+ if ( $RT::WebExternalOnly ) {
+ $m->comp('/Elements/Login', %ARGS,
+ Error=> loc('You are not an authorized user'));
+ $m->abort();
+ }
}
}
-
- unless ( $session{'CurrentUser'}->Id() ) {
- delete $session{'CurrentUser'};
- $user = $orig_user;
-
- if ( $RT::WebExternalOnly ) {
- $m->comp('/Elements/Login', %ARGS, Error=> loc('You are not an authorized user'));
- $m->abort();
+ elsif ($RT::WebFallbackToInternalAuth) {
+ unless (defined($session{'CurrentUser'})) {
+ $m->comp('/Elements/Login', %ARGS,
+ Error=> loc('You are not an authorized user'));
+ $m->abort();
}
+ } else {
+ # WebExternalAuth is set, but we don't have a REMOTE_USER. abort
+ delete $session{'CurrentUser'} if defined $session{'CurrentUser'};
}
}
delete $session{'CurrentUser'}
unless $session{'CurrentUser'} and defined $session{'CurrentUser'}->Id;
+
# Process per-page authentication callbacks
$m->comp('/Elements/Callback', %ARGS, _CallbackName => 'Auth');
!$session{'CurrentUser'}->IsPassword($pass))
{
delete $session{'CurrentUser'};
+ $RT::Logger->error("FAILED LOGIN for $user from $ENV{'REMOTE_ADDR'}");
$m->comp('/Elements/Login', %ARGS,
Error => loc('Your username or password is incorrect'));
$m->abort();
}
+ else {
+ $RT::Logger->info("Successful login for $user from $ENV{'REMOTE_ADDR'}");
+ }
}
# If we've got credentials, let's serve the file up.