diff -ur Apache-AxKit-Plugin-Session-0.92/lib/Apache/AxKit/Plugin/Session.pm axkit-plugin-session/lib/Apache/AxKit/Plugin/Session.pm --- Apache-AxKit-Plugin-Session-0.92/lib/Apache/AxKit/Plugin/Session.pm 2002-07-08 05:06:44.000000000 -0500 +++ axkit-plugin-session/lib/Apache/AxKit/Plugin/Session.pm 2002-10-18 01:45:34.000000000 -0500 @@ -4,11 +4,9 @@ use vars qw($redirect_location); BEGIN { - #use Apache::AuthCookieURL; use Apache::Table; use Apache::Session::File; use Apache::Constants qw(:common :response); - #@Apache::AxKit::Plugin::Session::ISA = ('Apache::AuthCookieURL'); $Apache::AxKit::Plugin::Session::VERSION = 0.92; } @@ -20,7 +18,7 @@ use Apache::Constants qw(:common M_GET REDIRECT MOVED); use Apache::URI (); use Apache::Cookie; -use Apache::RequestNotes; +use Apache::Request; use URI::Escape; # store reason of failed authentication, authorization or login for later retrieval @@ -104,10 +102,10 @@ return SERVER_ERROR; } - my $uri = uri_escape($r->uri); - $authen_script =~ s/((?:[?&])destination=)/$1$uri/; + $authen_script .= "?".join("&",map{"$_=".$r->pnotes("INPUT")->get($_)} Apache::Request->instance($r)->param); + $self->debug(3,"Internally redirecting to $authen_script"); - $r->custom_response(FORBIDDEN, $authen_script); + $r->internal_redirect_handler($authen_script); return FORBIDDEN; } # ____ End of login_form ____ @@ -130,9 +128,8 @@ #================ sub parse_input { #---------------- - my $r = Apache->request(); - return if ($r->pnotes('INPUT')); - Apache::RequestNotes::handler($r); + my $r = Apache->request; +# We don't read the data here -- the init handler does it now. $r->pnotes('INPUT',{}) unless $r->pnotes('INPUT'); $r->pnotes('UPLOADS',[]) unless $r->pnotes('UPLOADS'); $r->pnotes('COOKIES',{}) unless $r->pnotes('COOKIES'); @@ -289,7 +286,7 @@ # retrieve session id from URL or HTTP 'Referer:' header - my (undef, $session, $rest) = split /\/+/, $r->uri, 3; + my (undef, $session, $rest) = split /\/+/, $r->uri.$r->args, 3; $rest ||= ''; return DECLINED unless $session && $session =~ /^$prefix(.+)$/; @@ -452,7 +449,7 @@ my $mr = $r; $mr = $mr->prev while ($mr->prev); $mr = $mr->main while ($mr->main); - $destination = $mr->uri; + $destination = $mr->uri.($mr->args?"?".$mr->args:""); } $self->debug(1,"destination = '$destination'"); @@ -627,7 +624,7 @@ $self->debug(1,'Bad session key sent.'); # Do this even if no cookie was sent - $auth_type->send_cookie(value=>'none', expires=>'-1d'); + $self->send_cookie(value=>'none', expires=>'-1d'); $error_message ||= 'bad_session_provided'; } @@ -697,10 +694,5 @@ } # ____ End of import ____ -$redirect_location ||= '/redirect'; -if (!defined $AxKit::Cfg) { - my $self = __PACKAGE__; - $self->initialize_url_sessions($redirect_location); -} # @@ -833,6 +841,7 @@ $r->dir_config->get($auth_name.'ManagerArgs'), }; }; + die "_get_session_from_store: $@" if $@; return $session; } @@ -842,7 +851,7 @@ $self->debug(3,"--------- _get_session(".join(',',@_).")"); my $dir = $r->dir_config($auth_name.'Dir') || '/tmp/sessions'; my $expire = ($r->dir_config($auth_name.'Expire') || 30) / 5 + 1; #/ - my $check = $r->dir_config($auth_name.'IPCheck'); + my $check = $r->dir_config($auth_name.'IPCheck') || 0; my $remote = ($check == 1?($r->header_in('X-Forwarded-For') || $r->connection->remote_ip): $check == 2?($r->connection->remote_ip =~ m/(.*)\./): $check == 3?($r->connection->remote_ip): @@ -873,7 +882,7 @@ #// retrieve session from a previous internal request $session = $mr->pnotes('SESSION') if $mr->pnotes('SESSION'); - $self->debug(3,"checkpoint beta, session={".join(',',keys %$session)."}"); + $self->debug(3,"checkpoint beta, session={".join(',',keys %$session)."}"); #// create/retrieve session, providing parameters for several common session managers if (!keys %$session) { $session = $self->_get_session_from_store($r,$session_id); @@ -913,7 +922,7 @@ if (!$globals) { $globals = {}; eval { - tie %$globals, $r->dir_config($auth_name.'Manager')||'Apache::Session::File', $r->dir_config('SessionGlobal')||"00000000000000000000000000000000", { + tie %$globals, $r->dir_config($auth_name.'Manager')||'Apache::Session::File', $r->dir_config($auth_name.'Global')||"00000000000000000000000000000000", { Directory => $dir, DataSource => $dir, FileName => $dir.'/sessions.db', @@ -931,7 +940,7 @@ DirLevels => 3, $r->dir_config->get($auth_name.'ManagerArgs'), }; - $$globals{'_session_id'} = $r->dir_config('SessionGlobal')||"00000000000000000000000000000000"; + $$globals{'_session_id'} = $r->dir_config($auth_name.'Global')||"00000000000000000000000000000000"; my $sessobj = tied(%$globals); $sessobj->release_write_lock; $sessobj->{status} = Apache::Session::NEW; @@ -947,9 +956,8 @@ return $session; } -# this is a NO-OP! Don't use this one (or ->login) directly, -# unless you have verified the credentials yourself or don't -# want user logins +# Don't use this one (or ->login) directly, unless you have +# verified the credentials yourself or don't want user logins sub authen_cred($$\@) { my ($self, $r, @credentials) = @_; $self->debug(3,"--------- authen_cred(".join(',',@_).")"); @@ -1265,19 +1273,23 @@ =head1 SYNOPSIS -Session management only: (minimal configuration, uses cookies, won't work without cookies, in httpd.conf or .htaccess) +Session management only: (minimal configuration, uses cookies, +won't work without cookies, in httpd.conf or .htaccess) AxAddPlugin Apache::AxKit::Plugin::Session -Session Management only: (uses cookies, falls back to URL session ID tracking, must be in httpd.conf) +Session Management only: (uses cookies, falls back to URL session +ID tracking, must be in httpd.conf) PerlModule Apache::AxKit::Plugin::Session; - Full-featured configuration: #### this must be in httpd.conf + + PerlInitHandler Apache::RequestNotes + # want a different redirector location? (default is '/redirect') #$Apache::AxKit::Plugin::Session::redirect_location = "/redir"; @@ -1285,8 +1297,12 @@ PerlModule Apache::AxKit::Plugin::Session; #### the rest may go into .htaccess + # don't use URL sessions - #AxAddPlugin Apache::AxKit::Plugin::Session; + AxAddPlugin Apache::AxKit::Plugin::Session; + + $Apache::AxKit::Plugin::Session::UseURLSessions = "NO"; + # Your session manager, if not using the default "Apache::Session::File' #PerlModule Apache::Session::Counted @@ -1295,6 +1311,7 @@ # Prefix "AxKitSession" is set by AuthName # unless otherwise noted, all settings may appear # in main config and in directory config/.htaccess + # how long a session is valid when idle (minutes, multiple of 5, default 30) #PerlSetVar AxKitSessionExpires 30 @@ -1302,11 +1319,15 @@ #PerlSetVar AxKitSessionDomain some.domain #PerlSetVar AxKitSessionSecure 1 - # Disable cookies: (useful for Apache::Session::Counted, it won't currently work with cookies) - #PerlSetVar AxKitSessionNoCookie 1 + # Disable cookies: (useful for Apache::Session::Counted, it + # won't currently work with cookies) + + # PerlSetVar AxKitSessionNoCookie 1 - # Location of login page: (it must call A:A:P:S->login($r) on successful login) + # Location of login page: (See LOGIN SCRIPT below) #PerlSetVar AxKitSessionLoginScript /login.xsp + # Location of logout script. This will be executed after the user's credentials are revoked. + #PerlSetVar AxKitSessionLoginScript /logout.xsp # do not enforce logins (default, makes all users appear as 'guest' initially) #PerlSetVar AxKitSessionLoginScript NONE @@ -1319,10 +1340,12 @@ # Prefix to session ID in URLs: (can only be set in main config) #PerlSetVar SessionPrefix Session- - # Which session module to use: (supported are File, DB_File, Flex and (without cookies) Counted, File is default) + # Which session module to use: (supported are File, DB_File, + # Flex and (without cookies) Counted, File is default) #PerlSetVar AxKitSessionManager Apache::Session::File # Where to put session files (data and locks): + # NOTE: Dir/lock will be used for session locks. #PerlSetVar AxKitSessionDir /tmp/sessions # What name the guest account shall have: (set to some false value to disable) @@ -1388,18 +1411,31 @@ PerlSetVar DisableAuthCookieURL 1 + # This is the action of the login.pl script above. + + AuthType Apache::AxKit::Plugin::Session + AuthName AxKitSession + SetHandler perl-script + PerlHandler Sample::AuthCookieHandler->login + + # ### End of directory settings =head1 DESCRIPTION -This module is an authentication and authorization handler for Apache, designed specifically -to work with Apache::AxKit. That said, it should be generic enough to work without it as well, only -much of its comfort lies in a separate XSP taglib which is distributed alongside this module. - -It combines authentication and authorization in Apache::AuthCookieURL style with session management -via one of the Apache::Session modules. It even works fine with Apache::Session::Counted. See those -manpages for more information, but be sure to note the differences in configuration! +This module is an authentication and authorization handler for +Apache, designed specifically to work with Apache::AxKit. That +said, it should be generic enough to work without it as well, +only much of its comfort lies in a separate XSP taglib which is +distributed alongside this module. + +It combines authentication and authorization in +Apache::AuthCookieURL (which functionality is included herein) +style with session management via one of the Apache::Session +modules. It even works fine with Apache::Session::Counted. See +those manpages for more information, but be sure to note the +differences in configuration! In addition to Apache::AuthCookieURL, you get: @@ -1425,15 +1461,21 @@ =back -To use authentication, you have to provide a login script which displays a login form, -verifies those values and calls Apache::AxKit::Plugin::Session->login($r,$user_name) on success. -This can easily be done with the PerForm XSP taglib combined with the Auth taglib. If you want logouts, you have to -write a custom logout script. Both functions are provided in the Auth XSP taglib -for ease of use. +To use authentication, you have to provide a login script which +displays a login form and accepts the username as C +(other authentication credentials can be taken as well as +C where x is an increasing number.), verifies those +values and calls Apache::AxKit::Plugin::Session->login($r, +$destination) on success. This can easily be done with the +PerForm XSP taglib combined with the Auth taglib. If you want +logouts, you have to write a custom logout script. Both functions +are provided in the Auth XSP taglib for ease of use. -Authorization via user name works by comparing the user name given at login time. +Authorization via user name works by comparing the user name +given at login time. -Authorization via groups and levels works by using 2 additional session variables: +Authorization via groups and levels works by using 2 additional +session variables: =over 4 @@ -1449,7 +1491,7 @@ =back -Multiple require lines are handled unlike in Apache::AuthCookieURL as a logical OR. +Multiple require lines are handled as a logical OR. =head1 CONFIGURATION SETTINGS @@ -1463,7 +1505,7 @@ =over 4 =item * AuthCookieURLDebug, DisableAuthCookieURL, SessionPrefix, Cache, -LoginScript, NoCookie, Domain, Secure +LoginScript, NoCookie, Domain, Secure, LogoutURI These settings are the same like in Apache::AuthCookieURL. Do not use any of the other settings provided by that module! They will not work as expected! @@ -1480,6 +1522,8 @@ DB_File, Counted, and all DB server modules if connecting anonymously. For all other configurations (including Flex), you need ManagerArgs, too. +Default: Apache::Session::File + Example: PerlSetVar AxKitSessionManager Apache::Session::Counted =item * ManagerArgs @@ -1487,6 +1531,8 @@ List of additional session manager parameters in the form: Name Value. Use with PerlAddVar. +Default: none + Example: PerlAddVar AxKitSessionManagerArgs User foo =item * Dir @@ -1494,6 +1540,14 @@ The location where all session files go, including lockfiles. If you are using a database server as session backend, this is the server specific db/table string. +NOTE: Dir/locks will be used for session locks. + +NOTE: Dir/counters should exist is you are using +Apache::Session::Counter as it will be used for session +information + +Default: /tmp/session + Example: PerlSetVar AxKitSessionDir /home/sites/site42/data/session =item * Guest @@ -1512,6 +1566,8 @@ application data does not belong here. But this is the right place to put "how many people are online?" counters and similar things. +Default: 00000000000000000000000000000000 + Example: PerlSetVar AxKitSessionGlobal 0 =item * IPCheck @@ -1522,15 +1578,74 @@ HTTP X-Forwarded-For header, if present, 2 = numeric IP address with last part stripped off, 3 = whole numeric IP address. +Default: 0 + Example: PerlSetVar AxKitSessionIPCheck 3 =back +=head1 LOGIN SCRIPT + +You will need to create a login script (called login.xsp above) +that generates an HTML form for the user to fill out. + +The following fields must be present in the form: + +1. The ACTION of the form must be /LOGIN (or whatever you defined + in your server configuration as handled by the ->login() + method - see example in the SYNOPSIS section). + +2. The various user input fields (username, passwords, etc.) must + be named 'credential_0', 'credential_1', etc. on the + form. These will get passed to your authen_cred() method. + +3. You must define a form field called 'destination' that tells + AuthCookie where to redirect the request after successfully + logging in. Typically this value is obtained from + $r->prev->uri. See the login.pl script in t/eg/. + +In addition, you might want your login page to be able to tell +why the user is being asked to log in. In other words, if the +user sent bad credentials, then it might be useful to display an +error message saying that the given username or password are +invalid. Also, it might be useful to determine the difference +between a user that sent an invalid auth cookie, and a user that +sent no auth cookie at all. To cope with these situations, +AuthCookie will set $r->subprocess_env('AuthCookieReason') to one +of the following values. + +=over 4 + +=item bad_session_provided + +Either a session was not provided, or the one provided was not found. + +=item ip_mismatchh + +The IP didn't match the IPCheck requirements + +=item session_expired + +The user tried to log in, but the credentials that were passed +have expired. + +=back + +You can examine this value in your login form by examining +$r->prev->subprocess_env('AuthCookieReason') (because it's a +sub-request). + +Of course, if you want to give more specific information about +why access failed when a cookie is present, your authen_ses_key() +method can set arbitrary entries in $r->subprocess_env. + =head1 WARNING -URL munging has security issues. Session keys can get written to access logs, cached by -browsers, leak outside your site, and can be broken if your pages use absolute links to other -pages on-site (but there is HTTP Referer: header tracking for this case). Keep this in mind. +URL munging has security issues. Session keys can get written to +access logs, cached by browsers, leak outside your site, and can +be broken if your pages use absolute links to other pages on-site +(but there is HTTP Referer: header tracking for this case). Keep +this in mind. The redirect handler tries to catch the case of external redirects by changing them into self-refreshing pages, thus removing a possibly sensitive http referrer header. This diff -ur Apache-AxKit-Plugin-Session-0.92/lib/AxKit/XSP/Auth.pm axkit-plugin-session/lib/AxKit/XSP/Auth.pm --- Apache-AxKit-Plugin-Session-0.92/lib/AxKit/XSP/Auth.pm 2002-06-10 07:33:12.000000000 -0500 +++ axkit-plugin-session/lib/AxKit/XSP/Auth.pm 2002-10-29 22:58:57.000000000 -0600 @@ -140,7 +140,7 @@ return set_access(@_).<< 'EOC'; my $auth_type = $r->auth_type; no strict 'refs'; -$r->pnotes('INPUT')->{'credential_0'} = $$session{'auth_access_user'}; +$$session{'auth_access_user'} = $r->pnotes('INPUT')->{'credential_0'}; my $rc; if (defined $attr_destination) { $rc = $auth_type->login($r,$attr_destination); @@ -195,7 +195,7 @@ sub is_logged_in : expr { - return '$$session{"auth_access_user"} ne "guest"?1:0'; + return '(defined $$session{"auth_access_user"} && $$session{"auth_access_user"} ne "guest" && $$session{"auth_access_user"} ne "")?1:0'; } sub get_permission : attribOrChild(target) struct