Apache-AppSamurai

 view release on metacpan or  search on metacpan

lib/Apache/AppSamurai.pm  view on Meta::CPAN

    # Use HMAC_SHA and CryptBase64 for session creation and serialization
    # by default.
    (exists($sessconfig->{Generate})) || ($sessconfig->{Generate} = "AppSamurai/HMAC_SHA");
    (exists($sessconfig->{Serialize})) || ($sessconfig->{Serialize} = "AppSamurai/CryptBase64");
   
    # Check/clean ServerPass if present (else assume ServerKey set)
    if (exists($sessconfig->{ServerPass})) {
	# Set the key (note - GetServerKey logs the error, if any)
	($sessconfig->{ServerKey} = $self->GetServerKey($r)) || (return undef);
    }

    # We have to have a ServerKey at this point, in hex form.
    if (($sessconfig->{Generate} =~ /HMAC/i) || ($sessconfig->{Serialize} =~ /Crypt/i)) {
	unless (CheckSidFormat($sessconfig->{ServerKey})) {
	    # Bad server key format
	    $self->Log($r, ('error', "GetSessionConfig(): You must a valid ${auth_name}ServerPass or ${auth_name}ServerKey!"));
	    return undef;
	}
	
	# For speed, SerializeCipher should be set in the config
	if (!$sessconfig->{SerializeCipher}) {
	    # Attempt to load CryptBase64 module
	    unless (eval "require Apache::AppSamurai::Session::Serialize::CryptBase64") {
		$self->Log($r, ('error', "GetSessionConfig(): Could not load CryptBase64 while attempting to auto-select ${auth_name}SerializeCipher value: $!"));
		return undef;
	    }
	    # Use CryptBase64 cipher detection utility (Slower)
	    unless ($sessconfig->{SerializeCipher} = &Apache::AppSamurai::Session::Serialize::CryptBase64::find_cipher()) {
		# None found.  (Note - Check @allowedciphers in CryptBase64.pm
		# for supported ciphers)
		$self->Log($r, ('error', "GetSessionConfig(): Could not auto-detect a suitable ${auth_name}SerializeCipher value (Please configure manualy): $!"));
		return undef;
	    }
	}
    }
    
    # Set a 1hr Timeout if neither Timeout or Expire are set
    unless ($sessconfig->{Timeout} || $sessconfig->{Expire}) {
	$sessconfig->{Timeout} = 3600;
    }
    
    return $sessconfig;
}


# Compute/check server key from server pass, returning key.
sub GetServerKey {
    my ($self, $r) = @_;
    my $auth_name = ($r->auth_name()) || (die("GetServerKey(): No auth name defined!\n"));
    my $dirconfig = $r->dir_config;
    my $serverkey = '';
    
    if (exists($dirconfig->{$auth_name . "SessionServerPass"})) {
	my $serverpass = $dirconfig->{$auth_name . "SessionServerPass"};
	
	unless ($serverpass =~ s/^\s*([[:print:]]{8,}?)\s*$/$1/s) {
	    $self->Log($r, ('error', "GetServerKey(): Invalid ${auth_name}SessionServerPass (must be use at least 8 printable characters"));
	    return undef;
	}
	
	if ($serverpass =~ /^(password|serverkey|serverpass|12345678)$/i) {
	    $self->Log($r, ('error', "GetServerKey(): ${auth_name}SessionServerPass is $1...  That is too lousy"));
	    return undef;
	}
	
	unless ($serverkey = HashPass($serverpass)) {
	    $self->Log($r, ('error', "GetServerKey(): Problem computing server key hash for ${auth_name}SessionServerPass"));
	    return undef;
	}

    } elsif (exists($dirconfig->{$auth_name . "SessionServerKey"})) {
	$serverkey = $dirconfig->{$auth_name . "SessionServerKey"};

    } else {
	$self->Log($r, ('error', "GetServerKey(): You must define either ${auth_name}SessionServerPass or ${auth_name}SessionServerKey in your Apache configuration"));
	return undef;
    }
    
    # Check for valid key format
    unless (CheckSidFormat($serverkey)) {
	# Not good, dude.  This should not happen
	$self->Log($r, ('error', "GetServerKey(): Invalid server session key (CheckSidFormat() failure) for $auth_name"));
	return undef;
    }

    return $serverkey;
}


# Apply the configured BasicAuthMap to the passed in credentials
# BasicAuthMap allows for flexibly parsing a single line of authentication
# data into multiple credentials in any order.  (Keep those users happy...)
# Returns an array with the parsed credentials in order, or an empty set on
# failure.
sub ApplyAuthMap {
    my ($self, $r, $pass, $amc) = @_;
    my $auth_name = ($r->auth_name) || ('');
    my ($o, $m, $i, @ct);
    my @creds = ();

    # Check basic map format
    ($r->dir_config("${auth_name}BasicAuthMap") =~ /^\s*([\d\,]+)\s*\=\s*(.+?)\s*$/) || (die("ApplyAuthMap(): Bad format in ${auth_name}BasicAuthMap\n"));
    $o = $1;
    $m = $2;
    
    # Try to map values from pass string
    (@ct) = $pass =~ /^$m$/;
    unless (scalar(@ct) eq $amc) {
	$self->Log($r, ('warn', "ApplyAuthMap: Unable to match credentials with ${auth_name}BasicAuthMap"));
	return ();
    }
    
    # Check credential numbers for sanity and assign values
    foreach $i (split(',', $o)) {
	($i =~ s/^\s*(\d+)\s*$/$1/) || (die("ApplyAuthMap(): Bad mapping format in ${auth_name}BasicAuthMap\n"));
	push(@creds, $ct[$i - 1]);
    }
	    
    return @creds;
}

lib/Apache/AppSamurai.pm  view on Meta::CPAN

"Protect your master, even if he is without honour...."

=head1 SYNOPSIS

All configuration is done within Apache.  Requires Apache 1.3.x/mod_perl1 or 
Apache 2.0.x/mod_perl2.  See L</EXAMPLES> for sample configuration segments.

=head1 DESCRIPTION

B<Apache::AppSamurai> protects web applications from direct attack by
unauthenticated users, and adds a flexible authentication front end
to local or proxied applications with limited authentication options.

Unauthenticated users are presented with either a login form, or a basic
authentication popup (depending on configuration.)  User supplied credentials
are checked against one or more authentication systems before the user's
session is created and a session authentication cookie is passed back to the
browser.  Only authenticated and authorized requests are proxied through
to the backend server.

Apache::AppSamurai is based on, and includes some code from,
L<Apache::AuthCookie|Apache::AuthCookie>.
Upon that core is added a full authentication and session handling framework.
(No coding required.)  Features include:

=over 4

=item *

B<Modular authentication> - Uses authentication sub-modules for the easy
addition custom authentication methods

=item *

B<Form based or Basic Auth login> - On the front end, supports standard
form based logins, or optionally Basic Auth login.  (For use with automated
systems that can not process a form.)

=item *

B<Apache::Session> - Used for session data handling

=item *

B<Session data encrypted on server> - By default, all session
data encrypted before storing to proxy's filesystem  (Uses custom
B<Apache::Session> compatible session generator and session serialization
modules)

=item *

B<Unified mod_perl 1 and 2 support> - One module set supports both
Apache 1.x/mod_perl 1.x and Apache 2.x/mod_perl 2.x

=back

=head1 SESSION STORAGE SECURITY

Server side session data may include sensitive information, including the basic
authentication C<Authorization> header to be sent to the backend server.
(This is just a Base64 encoded value, revealing the username and password
if stolen.)

To protect the data on-disk, Apache::AppSamurai includes
its own HMAC based session ID generator and encrypting session serializer.
(L<Apache::AppSamurai::Session::Generate::HMAC_SHA|Apache::AppSamurai::Session::Generate::HMAC_SHA>
and
L<Apache::AppSamurai::Session::Serialize::CryptBase64|Apache::AppSamurai::Session::Serialize::CryptBase64>
, respectively.)
These modules are configured by default and may be used directly with
Apache::Session, or outside of Apache::AppSamurai if desired.

=head1 USAGE

Almost all options are set using C<PerlSetVar> statements, and can be used
inside most configuration sections.

Each configuration option must be prefixed by the I<AuthName> for the
Apache::AppSamurai instance you wish to apply the option to.  This
I<AuthName> is then referenced within the protected area(s).   Most of setups
only require one I<AuthName>.  You can call it "BOB" or "MegaAuthProtection".
You can even call it "authname". 

B<IMPORTANT NOTE> - The I<AuthName> is omitted in the configuration
descriptions below for brevity.  "Example" is used as the I<AuthName> in the
L</EXAMPLES> section.

Most setups will include a set of global configuration values to setup the
Apache::AppSamurai instance.  Each protected area then points to a specific
AuthName and Apache::AppSamurai methods for authentication and
authorization.

=head2 GENERAL CONFIGURATION

=head3 I<Debug> C<0|1>

(Default: 0)
Set to 1 to send debugging output to the Apache logs.  (Note - you must have
a log configured to catch errors, including debug level errors, to see the
output.)

=head3 I<CookieName> C<NAME>

(Default:AUTHTYPE_AUTHNAME)
The name of the session cookie to send to the browser.

=head3 I<LoginScript> C<PATH>

(Default: undef)
The URL path (location) of the proxy's login page for form based login.
(Sample script provided with the Apache::AppSamurai distribution.)

=head3 I<Path> C<PATH>

(Default: /)
The URL path to protect.

=head3 I<Domain> C<DOMAIN>

(Default: not set)
The optional domain to set for all session cookies.  Do not configure this
unless you are sure you need it: A misconfigured domain can result in session
stealing.

=head3 I<Satisfy> C<All|Any>

(Default: All)
Set C<require> behaviour within protected areas.  Either C<All> to require all
authentication checks to succeed, or C<Any> to require only one to.

=head3 I<Secure> C<0|1>

(Default: 1)
Set to 1 to require the C<secure> flag to be set on the session cookie, forcing
the use of SSL/TLS.

=head3 I<HttpOnly> C<0|1>

(Default: 0)
Set to 1 to require the Microsoft proprietary C<http-only> flag to be set on
session cookies.

=head3 I<LoginDestination> C<PATH>

(Default: undef)
Set an optional hard coded destination URI path all users will be directed to
after login.  (While full URLs are allowed, a path starting in / is
recommended.)  This setting only applies so form based login.  Basic Auth
logins always follow the requested URL.

=head3 I<LogoutDestination> C<PATH>

(Default: undef)
Set an optional hard coded destination URI path all users will be directed to
after logging out. (While full URLs are allowed, a path starting in / is
recommended.)   This setting only applies so form based login.  Basic Auth
logins always follow the requested URL.

If I<LogoutDestination> is unset and I<LoginDestination> is set,
users will be directed to I<LoginDestination> after logout.  (This is
to prevent a user from logging back into the logout URI, which would log them
back out again.  Oh the humanity!) 

=head2 AUTHENTICATION CONFIGURATION

Most authentication is specific to the authentication module(s) being used.
Review their specific documentation while configuring.

=head3 I<AuthMethods> C<METHOD1,METHOD2...>

(Default: undef)
A comma separated list of the authentication sub-modules to use.  The order of
the list must match the order of the C<credentials_X> parameters in the login
form. (Note - C<credential_0> is always the username, and is passed as such to
all the authentication modules.)

=head3 I<BasicAuthMap> C<N1,N2,.. = REGEX>

(Default: undef)

Custom mapping of Basic authentication password input to specific and separate
individual credentials. This allows for AppSamurai to request basic
authentication for an area, then split the input into credentials that can be
checked against multiple targets, just like a form based login.  This is very
useful for clients, like Windows Mobile ActiveSync, that only support basic
auth logins.  Using this feature you can add SecurID or other additional
authentication factors without having to pick only one.

The syntax is a bit odd.  First, specify a list of the credential numbers
you want mapped, in order they will be found within the input. Then
create a regular expression that will match the input, and group each item
you want mapped.

Example:

 PerlSetVar BobAuthBasicAuthMap "2,1=(.+);([^;]+)"

If the user logs into the basic auth popup with the password:
C<myRockinPassword;1234123456> ,the map above will set credential_1 as
C<1234123456> and credential_2 as C<myRockinPassword>, then proceed as if 
the same were entered into a form login.

=head3 ADDITIONAL AUTHENTICATION OPTIONS

Authentication submodules usually have one or more required settings.  All
settings are passed using PerlSetVar directives with variable names prefixed
with the AuthName and the module's name.

Example:

 PerlSetVar BobAuthBasicLoginUrl C<https://bob.org/login>

For AuthName C<Bob>, set the C<LoginUrl> for the C<AuthBasic> authentication
module to C<https://bob.org/login>

See L<Apache::AppSamurai::AuthBase> for general authentication module
information.  If you need an authentication type that is not supported
by the authentication modules shipped with AppSamurai, and is not
available as an add on module, please review L<Apache::AppSamurai::AuthBase>
and use the skeletal code from AuthTest.pm, which is included under
/examples/auth/ in the AppSamurai distribution.

=head2 SESSION CONFIGURATION

Each Apache::AppSamurai instance must have its local (proxy server side)
session handling defined.
L<Apache::Session|Apache::Session> provides the majority of the session
framework.  Around Apache::Session is wrapped
L<Apache::AppSamurai::Session|Apache::AppSamurai::Session>, which
adds features to allow for more flexible selection of sub-modules.

Most Apache::Session style configuration options can be passed directly to the
session system by prefixing them with C<authnameSession>.

Module selection is slightly different than the default supplied with
Apache::Session.  Plain names, without any path or ::, are handled
exactly the same: Modules are loaded from within the Apache::Session
tree.  Two additional alternatives are provided:

=over 4

=item *

I<AppSamurai/MODULE> - Load I<MODULE> from under the
B<Apache::AppSamurai::Session> tree instead of the B<Apache::Session> tree.

=item *

I<PATH::MODULE> - Load I<PATH::MODULE> literally.  Note - Since :: is required
to be present, a root module name will not work.

=back

The most common configuration options follow.  See
L<Apache::AppSamurai::Session|Apache::AppSamurai::Session> and
L<Apache::Session|Apache::Session> for
more advanced options, like using a database for storage.

lib/Apache/AppSamurai.pm  view on Meta::CPAN

Should be called directly by your logout page or logout pseudo file.
This expects an Apache request handle.  It can also take a second
option, which should be a scalar URI path to redirect users to after
logout.  C<logout()> attempts to look up and destroy the session tied to the
passed in session authentication key.

Like C<login()>, you may create a special pseudo file named LOGOUT and
use PerlHandler, (or "PerlResponseHandler" for mod_perl 2.x), to map it
to the C<logout()> method.  This is particularly handy when paired with
mod_rewrite to map a specific application URI to a pseudo file mapped to
C<logout()>  (See L</EXAMPLES> for a sample config that uses this method.)


=head1 EXAMPLES

 ## This is a partial configuration example showing most supported
 ## configuration options and a reverse proxy setup.  See examples/conf/
 ## in the Apache::AppSamurai distribution for real-world example configs.

 ## Apache 1.x/mod_perl 1.x settings are enabled with Apache 2.x/mod_perl 2.x
 ## config alternatives commented out. ("*FOR MODPERL2 USE:" precedes
 ## the Apache 2.x/mod_perl 2.x version of any alternative config items.)
 ## Note that example configs in examples/conf/ use IfDefine to support
 ## both version sets without having to comment out items. Also note that it
 ## is far too ugly looking to include in this example.

 ## General mod_perl setup
 
 # Apache::AppSamurai is always strict, warn, and taint clean. (Unless
 # I mucked something up ;)
 PerlWarn On
 PerlTaintCheck On
 PerlModule Apache::Registry
 #*FOR MODPERL2 USE:
 # PerlSwitches -wT
 # PerlModule ModPerl::Registry

 # Load the main module and define configuration options for the 
 # "Example" auth_name
 PerlModule Apache::AppSamurai
 PerlSetVar ExampleDebug 0
 PerlSetVar ExampleCookieName MmmmCookies
 PerlSetVar ExamplePath /
 PerlSetVar ExampleLoginScript /login.pl

 # Defaults to All by may also be Any
 #PerlSetVar ExampleSatisty All
 
 # Optional session cookie domain (Avoid unless absolutely needed.)
 #PerlSetVar ExampleDomain ".thing.er"

 # Require secure sessions (default: 1)
 #PerlSetVar ExampleSecure 1

 # Set proprietary MS flag
 PerlSetVar ExampleHttpOnly 1

 # Define authentication sources, in order
 PerlSetVar ExampleAuthMethods "AuthRadius,AuthBasic"

 # Custom mapping of xxxxxx;yyyyyy Basic authentication password input
 # to specific and separate individual credentials. (default: undef)
 PerlSetVar ExampleBasicAuthMap "2,1=(.+);([^;]+)"

 
 ## Apache::AppSamurai::AuthRadius options ##
 # (Note - See L<Apache::AppSamurai::AuthRadius> for more info)
 PerlSetVar ExampleAuthRadiusConnect "192.168.168.168:1645"
 PerlSetVar ExampleAuthRadiusSecret "radiuspassword"

 
 ## Apache::AppSamurai::AuthBasic options.##
 # (Note - See L<Apache::AppSamurai::AuthBasic> for more info)
 
 # Set the URL to send Basic auth checks to
 PerlSetVar ExampleAuthBasicLoginUrl "https://ex.amp.le/thing/login"
 
 # Always send Basic authentication header to backend server
 PerlSetVar ExampleAuthBasicKeepAuth 1
 
 # Capture cookies from AuthBasic login and set in client browser
 PerlSetVar ExampleAuthBasicPassBackCookies 1
 
 # Abort the check unless the "realm" returned by the server matches
 PerlSetVar ExampleAuthBasicRequireRealm "blah.bleh.blech"
 
 # Pass the named header directly through to the AuthBasic server 
 PerlSetVar ExampleAuthBasicUserAgent "header:User-Agent"

 
 ## Session storage options ##
 # (Note - See L<Apache::AppSamurai::Session> and L<Apache::Session> for
 # more information.)
 
 # Inactivity timeout (in seconds)
 PerlSetVar ExampleSessionTimeout 1800

 # Use the File storage and lock types from Apache::Session
 PerlSetVar ExampleSessionStore "File"
 PerlSetVar ExampleSessionLock "File"

 # File storage options (Relevant only to File storage and lock types)
 PerlSetVar ExampleSessionDirectory "/var/www/session/sessions"
 PerlSetVar ExampleSessionLockDirectory "/var/www/session/slock"

 # Use the Apache::AppSamurai::Session::Generate::HMAC_SHA generator
 PerlSetVar ExampleSessionGenerate "AppSamurai/HMAC_SHA"

 # Use the Apache::AppSamurai::Session::Serialize::CryptBase64
 # data serializer module with Crypt::Rijndael (AES) as the block
 # cipher provider
 PerlSetVar ExampleSessionSerialize "AppSamurai/CryptBase64"
 PerlSetVar ExampleSessionSerializeCipher "Crypt::Rijndael"

 # Set the server's encryption passphrase (for use with HMAC session
 # generation and/or encrypted session storage)
 PerlSetVar ExampleSessionServerPass "This is an example passphrase"

 
 ## Tracker storage options ##
 
 # Cleanup tracker entries that have not changed in 1 day 
 PerlSetVar ExampleTrackerCleanup 86400

 # Block further login attempts from IPs that send 10 failures with
 # no more than 60 seconds between each subsequent failure
 PerlSetVar ExampleIPFailures "10:60"

 # Force at least one credential to be unique per-login.  (Requires



( run in 1.028 second using v1.01-cache-2.11-cpan-39bf76dae61 )