view release on metacpan or search on metacpan
THEN AS ROOT,
cd db; cp dbilogin.txt /usr/local/apache/conf/private
NOTE: This path is hard-coded in startup.pl, so if you change it, you must
change it consistently everywhere.
5. Set up IP Aliasing.
The demo shows the transfer of credentials between different hosts. You
don't actually need separate physical hosts, if your machine supports IP
aliasing.
On Linux, if you have an old kernel (<2.4?) read the HOWTO on IP Aliasing.
Otherwise (new linux kernels), ip aliasing is automatic. Here is the
relevant fragment from my /etc/hosts:
## prototype web devel virtual hosts (some Libertarians)
192.168.1.11 adam.acme.com adam smith
192.168.1.12 lysander.acme.com lysander spooner
7. Try the demos.
All relevant user login info is:
user: bob
password: sekret
pin code: 0918
As you go from top to bottom in the menu, there are increasing
authentication requirements, and increasingly strong credentials are
issued. When you get to milt.sec.acme.com, watch carefully, as you will
be redirected to stu.transacme.com for login. And, when stu issues
URL credentials you will be transparently redirected across domains to get
cookies for milt.sec.acme.com and noam.acme.org, before being redirected
back to the original milt request. Then you may hop to noam and stu
without further interruption.
./rfc/*.txt Related IETF RFC's describing cookies.
./COPYING,./LICENSE Copyright and license info.
1. What Problems are We Trying to Solve?
-----------------------------------------
Problem 1: No Secure Single Sign-On.
There is not as far as we know, an Apache module which will securely transfer
credentials from a login on one trusted host to multiple cooperating hosts,
across multiple DNS domains and across a range of SSL capabilities.
Problem 2: HTTP Cookie Weaknesses.
Not implicit from problem (1), is the subtle fact that considerable
care must be taken to securely share credentials within a single DNS
domain using HTTP state management (aka Netscape Cookies) as described
in [RFC2109] and [RFC2965]. In fact, the traps and pitfalls are so numerous
that [RFC2964] generally forbids the use of cookies for any kind of security
authentication.
One way to look at this package is as a very simple cryptographic
protocol designed to defend against attacks which exploit known cookie
vulnerabilities.
2. Summary of Features
-----------------------
* Secure sharing of multi-level credentials within and across DNS domains.
* Support for different representations of credentials with the ability to
chain and interoperate between them.
* Built-in defense against on-line guessing attacks.
* Built-in session timeout, both idle and hard-limit.
* Built-in SU-type function for admins to switch user ID's.
* Encapsulated database interface.
3. Known Security Issues with HTTP Cookies
-------------------------------------------
cookie to a user who can then request resources from wendel. Even
if you don't admit either passive or active adversaries on the network, the
user's identity might still be compromised. If hopkins.acme.com is
compromised and the user visits *any* other compromised site, say
www.fantasyland.org, a trojan .html document with a malicious image
tag <img src="http://hopkins.acme.com">, will send the identity cookies
directly to hopkins who is waiting for them. (This is the old 3rd-party
cookie bugaboo exploited by *click.com.)
Solution: Regardless of the mechanism used for representing user
credentials (cookies, URL's, etc), there will be some set of hosts
included in the system (whether spanned by wildcard matches or server
side redirects). No untrusted host should be in that set. This is
just classic host security.
Issue 3: Secure Wildcard Cookies Don't Always Have Intended Protection
The underlying weakness in issue (2) is perhaps more relevant for so-called
secure cookies (with secure flag is set). Even where host security can be
assumed across a large heterogeneous environment, there might be one
host which only supports 40-bit SSL, say hopkins.acme.org again. Supposed
bruce and wendel were properly configured for only 128-bit cipher suites
and issued only secure cookies for the .acme.com domain. Then a malicious
image tag <img src="https://hopkins.acme.com"> will force a connection
to hopkins. If 40-bit encryption is negotiated (see next issue), the user's
credentials are reduced from 128-bits to 40-bits.
Unlike issue (2), we cannot pass this off as a matter of host security,
because hopkins is not compromised. A passive adversary who obtains
a 40-bit encrypted copy of the credentials. He can then do an offline crack
in order to assume the users identity. Naively, bruce and wendel might
think an implausible work factor of 2^128 would be necessary.
Solution: A cookie-based authentication module must be configurable
to treat a wildcard .acme.com domain as essentially weak. Cookies
used for strong authentication must be either confined to a single
host, or to a more restrictive wildcard like '.secure.acme.com'. The
demo software shows examples of both.
-------------------------
5.1 The Authentication Processes
---------------------------------
There are three notions of 'authentication' in Apache::SecSess.
User Authentication: This serves to identify the user and to provide
a suitable proof of that identity. This is typically a login form,
which interrupts the user, but it might transparently use other
credentials which are already available electronically like an X.509
client certificate or a persistent cookie.
Session Authentication: This is Apache's notion of authentication as
carried out by PerlAuthenHandler. Here, an actual resource, like an
HTML doc, will be delivered if all is successful.
Chaining Authentication: In this type of authentication, credentials
suitable for session authentication are interpreted instead as user
authentication in order to issue another type of credential. In the
demo for example, single sign-on across DNS domains is accomplished
by double chaining. Local cookies are used to the identify user and
issue URL credentials during a redirect across the domain, where
the URL credentials are used to identify/authenticate the user again
in order to issue cookies within the *new* domain.
5.2 The Security Mechanism
---------------------------
The fundamental security mechanism of Apache::SecSess is the issuance
of simple cryptographic proofs of identity explicitly constructed to
return to the system's various servers via HTTP(S) sessions which are
protected with sufficient strength, despite the malicious behavior by an
adversary. This is achieved in a rather mundane way, namely by avoiding
all the pitfalls of the enumerated issues in Sect. 3.
In the case of URL credentials, the current implementation requires all
URL's to be explicitly configured. All redirects are automatic, occurring
under SSL of a specified strength. There should be no surprises here; if
URL credentials were stolen, the adversary would have had to crack one of
a small number of SSL connections under the complete control of the security
administrator.
In the case of Cookie credentials, *multiple* cookies are issued, one for
each anticipated security level. For example, a user who logs in with an
X.509 client certificate might be issued 3 cookies: one cleartext cookie
intended for non-sensitive data, one SSL (secure flag) cookie broadly
distributed to .acme.com with 40-bit crypto possible, and finally one SSL
cookie intended only for the 128-bit originating host. An adversary who
manages to steal either the cleartext or the 40-bit cookie cannot use it to
acquire 128-bit level resources, because the cookies themselves have
unforgeable assertions of security level which are checked during session
authentication as described in the next section.
Credentials in Apache::SecSess have a similar format:
URL Credentials:
realm=E_k(md5(hash),hash)
Cookie Credentials:
realm:qop,authqop=E_k(md5(hash),hash)
(The only difference is that the quality of protection parameters
discussed below, qop and authqop, are repeated in the clear for cookie
credentials in order to ease processing.)
The string 'realm' is any symbol (without obvious special characters
':', '=', etc) which is used to identify cooperating security services,
thus providing a way to put credentials into their own namespace.
The 'hash' is a string representation of a Perl hash of the form:
hash = {
uid => string: user ID
timestamp => integer: time stamp from time(),
qop => integer: session quality of protection,
authqop => integer: user authentication quality of protection
}
See the source code of Wrapper.pm for details of how the hash is converted
into a string.
The encryption function E_k is currently not very configurable. It is
Rijndael (AES) in CBC mode with IV=0. It is well known that CBC mode is
vulnerable to forgeries, so a cryptographic checksum is prepended to the
plaintext, as indicated.
The secret key k must be shared by all host or web servers which use the same
realm. Without the secret key, it should be cryptographically infeasible to
produce credentials in which the hash and checksum match. It should
therefore be cryptographically infeasible for anyone to forge credentials or
alter them in any way.
References
----------
[RFC2109] D. Kristol, L. Montulli, HTTP State Management Mechanism,
RFC 2109, 1997.
[RFC2964] K. Moore and N. Freed, Use of HTTP State Management
if (ref($resp)) {
if ($msg = $resp->{message}) { $log->info($msg); }
if ($resp->{forbidden}) { return FORBIDDEN; }
unless ($resp->{uri}) { return SERVER_ERROR; }
$r->header_out(Location => $resp->{uri});
return REDIRECT;
}
return DECLINED;
}
## authenticate user & issue credentials
sub issue ($$) {
my($self, $r) = @_;
my $log = $r->log;
my($resp, $msg);
## don't perform in subrequests
unless ($r->is_initial_req) { return OK; }
$log->debug(ref($self), "->issue():");
return REDIRECT;
}
$resp = $self->issueCredentials($r);
unless (ref($resp)) { $log->error($resp); return SERVER_ERROR; }
if ($msg = $resp->{message}) { $log->info($msg); }
unless ($resp->{uri}) { return SERVER_ERROR; }
$r->header_out(Location => $resp->{uri});
return REDIRECT;
}
## renew credentials
sub renew ($$) {
my($self, $r) = @_;
my $log = $r->log;
my($cred, $resp, $msg);
## don't perform in subrequests
unless ($r->is_initial_req) { return OK; }
$log->debug(ref($self), "->renew():");
$cred = $self->getCredentials($r);
$resp = $self->validateCredentials($r, $cred);
unless (ref($resp)) { $log->error($resp); return SERVER_ERROR; }
unless ($resp->{renew}) { # make sure credentials are sufficiently fresh
$log->warn("Timeout before renewal."); # or replay attempt?
if ($msg = $resp->{message}) { $log->info($msg); }
unless ($resp->{uri}) { return SERVER_ERROR; }
$r->header_out(Location => $resp->{uri});
return REDIRECT;
}
$resp = $self->issueCredentials($r);
unless (ref($resp)) { $log->error($resp); return SERVER_ERROR; }
if ($msg = $resp->{message}) { $log->info($msg); }
unless ($resp->{uri}) { return SERVER_ERROR; }
$r->header_out(Location => $resp->{uri});
return REDIRECT;
}
## delete credentials
sub delete ($$) {
my($self, $r) = @_;
my $log = $r->log;
my($resp, $msg);
## don't perform in subrequests
unless ($r->is_initial_req) { return OK; }
$log->debug(ref($self), "->delete():");
unless ($r->is_initial_req) { return OK; }
$log->debug(ref($self), "->changeid():");
## admin functions must be explicitly allowed in httpd.conf
unless ($r->dir_config('SecSess::AllowRemoteAdmin') eq 'true') {
$log->error('Remote administration not permitted.');
return FORBIDDEN;
}
## get credentials and validate them in usual way
$cred = $self->getCredentials($r);
$resp = $self->validateCredentials($r, $cred);
if (ref($resp)) {
if ($msg = $resp->{message}) { $log->info($msg); }
unless ($resp->{uri}) { return SERVER_ERROR; }
$r->header_out(Location => $resp->{uri});
return REDIRECT;
}
## make sure request is consistent and comes from an administrator
unless (ref($resp)) { $log->error($resp); return SERVER_ERROR; }
if ($msg = $resp->{message}) { $log->info($msg); }
if ($resp->{forbidden}) { return FORBIDDEN; } # non-admin
if ($resp->{fill_form}) { return OK; }
unless ($uid = $resp->{newuid}) {
unless ($uri = $resp->{uri}) { return SERVER_ERROR; }
$r->header_out(Location => $uri);
return REDIRECT;
}
## every looks good, set uid and issue new credentials
$r->user($uid);
$resp = $self->issueCredentials($r);
unless (ref($resp)) { $log->error($resp); return SERVER_ERROR; }
if ($msg = $resp->{message}) { $log->info($msg); }
unless ($resp->{uri}) { return SERVER_ERROR; }
$r->header_out(Location => $resp->{uri});
return REDIRECT;
}
#
sub issueURL { my $self = shift; return $self->{issueURL}; }
sub chainURLS { my $self = shift; return $self->{chainURLS}; }
## admin form
sub adminURL { my $self = shift; return $self->{adminURL}; }
#
# routines
#
## validate common hash credentials from
sub validateCredentials {
my $self = shift;
my($r, $cred) = @_;
my $log = $r->log;
my($uri, $requri, $resp, $uid);
$log->debug(ref($self), "->validateCredentials():");
## were illegitimate credentials found?
unless (defined($cred)) { # probably a key-change, treat as timeout
# but possibly tampering, so log as warning
$log->warn("Decryption Error");
$uri = $self->timeoutURL;
return {
message => "Decryption failure, redirecting to '$uri'.",
uri => "$uri?type=notvalid"
};
}
## were any credentials found at all?
unless (ref($cred)) {
$uri = sprintf('%s?url=%s',
$self->authenURL,
$self->requested_uri($r)
);
return {
message => "$cred Redirecting to '$uri'",
uri => $uri
};
}
$uri = $self->timeoutURL;
return {
message => "Cookie idle too long '$uid'.",
uri => "$uri?type=idle"
};
}
if ($t > $ts + 60*$renew) { # renew
$uri = $self->renewURL;
$requri = $self->requested_uri($r);
return {
message => "Renewing credentials for user '$uid'.",
renew => 'true',
uri => "$uri?url=$requri"
};
}
return undef;
}
## get requirements
sub getRequirements {
`+-Cookie
| `+--BasicAuth (for debugging)
| +--LoginForm
| +--X509
| +--X509PIN
| `--URL
`-URL
`---Cookie
SecSess contains (in addition to common code) all Apache phase handlers
(Currently only PerlAuthenHandler are needed). At this level credentials
and status are considered opaque objects. The important methods are:
->authen() Used to protect underlying resources. Checks credentials for freshness and validity.
->issue() Used as the "initial" identity authentication before issuing credentials (cookies or mangled URLs) used by ->authen().
->renew() Will re-issue credentials if proper conditions are satisfied
->delete() Will delete credentials where relevant (i.e. deletes cookies).
At one level beneath SecSess (SecSess::Cookie.pm and SecSess::URL.pm),
are the methods for interpreting and manipulating credentials.
At the lowest level, are subclasses which "know" how to interpret the
*initial* identifying information during the issuance of credentials.
So, *::Cookie::LoginForm presents the client with a user/password
login form for identification. And thus the difference between
*::Cookie::URL and *::URL::Cookie is that the former will issue cookies
after validating an URL credential, and the latter will "issue" an URL
credential (typically it will redirect to a resource with realm=cred in
the URL) after validating a cookie.
=head1 CREDENTIAL FORMAT
Credentials in Apache::SecSess have a similar format:
URL Credentials (defined in Apache::SecSess::URL):
realm=E_k(md5(hash),hash)
Cookie Credentials: (defined in Apache::SecSess::Cookie):
realm:qop,authqop=E_k(md5(hash),hash)
The string 'realm' is any symbol (without obvious special characters
':', '=', etc) which is used to identify cooperating security services,
thus providing a way to put credentials into their own namespace.
The 'hash' is a string representation of a Perl hash of the form:
hash = {uid => str, timestamp => int, qop => int, authqop => int}
See README and Wrapper.pm for further details.
=head1 ARGUMENTS
=head2 Credential Arguments
authRealm => <realm>
Defines string 'realm' as identifying tag for credentials as described
above in CREDENTIAL FORMAT.
secretFile => <filename>
The first line of this file is used to create the secret encryption
key for credentials as described above in CREDENTIAL FORMAT. This
secret key is never given to users and should never leave the system
servers.
=head2 Timing Arguments
lifeTime => <minutes>
Session will expire after the specified number of minutes.
idleTime => <minutes>
renewRate => <minutes>
A session which is constantly active will have a transparent
renewal (resetting an implicit 'idle timer') every period of the
specified number of minutes.
=head2 Quality of Protection Arguments
minSessQOP => 128, minAuthQOP => 128, authQOP => 128, sessQOP => 128
When credentials are validated during a request, two checks of the
qualities of protection (QOP's) are made, namely that
qop >= minSessQOP
and
authqop >= minAuthQOP
where qop and authqop indicate the session and user authentication
protection or strength roughly measured in bits. They are the signed
values appearing *inside* the credential hash described above. In the
case of cookies, where multiple credentials with different security
levels are may be present at request time, only the strongest credentials
are used to make this determination. (The cleartext pairs (qop,authqop)
are sorted lexicographically to determine which cookies to use. The
cleartext values are not trusted.)
The QOP parameters are separated to allow flexibility in the threat model.
In the simplest paradigm (and first demo examples), qop=0 and authqop=40,
which merely indicates that the user ID's and passwords are protected with
SSL but the web docs acquired with them are not. This is somewhat common
over intranets. Under the stronger threat model of an active adversary
who controls the untrusted network, true end-to-end security is
required, but we may still wish to separate session and authentication
qualities of protection. For example, if all SSL sessions never drop
below 128-bits, we may still choose to allow weaker strength during user
authentication, say with a 20-bit PIN or one-time password. Scientific
cryptography cannot always afford to distinguish between an attack which
costs 2^20 computations and one which succeeds with probability 1/2^20,
because with 1 million users, the two situations are identical. But, for
practical risk assessment, it may be perfectly acceptable to trade strong
session credentials for weak login credentials.
The values of qop and authqop issued are determined by the
Apache::SecSess object in all cases. For URL credentials they come
directly from arguments sessQOP and authQOP, respectively. For cookie
credentials, they come from the hash keys of the argument cookieDomain
described below.
Note that no attempt is made to check the correctness of the QOP
settings against the values of the httpd.conf directive SSLCipherSuite.
This would be mistake in fact because the session strength is dependent
on global factors as described in README. Nevertheless, you should
check your assumptions about your local site's openssl with the script
utils/minstren which prints the weakest cipher strength for common
SSLCipherSuite arguments. At my site, I was surprised to find
ALL:!ADH:!EXP:!EXP56 => 56 bits.
wildcard domains, *.acme.com supporting any export crippled, SSLv2
host, and *.sec.acme.com which intended to have a minimum of 64 bits
throughout.
=head2 Session State URL Arguments
These have the obvious meaning and must agree in host, scheme, and
path with the corresponding Apache directives, as shown in the EXAMPLE
section. Generally for example,
authenURL => Where to go to get the appropriate credentials for a requested
resource.
defaultURL => Where to go after logging in (if no initial request was made).
timeoutURL => Where to go to delete credentials. Timeouts and signouts
are both sent here.
=head2 URL Chaining Arguments
chainURLS => <arrayref>, issueURL => <string>
Apache::SecSess is designed to use cookies for most local authentication. By
their definition, cookies are restricted to a host, a DNS domain or subdomain.
The subclass Apache::SecSess::URL, which allows you to span authentication
across DNS domains, requires additional arguments to accomplish this. The
argument chainURLS expects an array reference which defines a list of places
to go for more (typically cookie) credentials. For example,
chainURLS => [
'https://milt.sec.acme.com/authen',
'https://noam.acme.org/authen'
]
says that when URL credentials are issued, the client will be redirected
to each of the specified sites, in turn. Each of these is expected to
be protected by a PerlAuthenHandler of type Apache::SecSess::Cookie::URL,
which will issue local cookies.
The argument issueURL is used to tell the remote sites (listed in chainURLS
arg) where to redirect the client back to, in order to continue chaining.
See the URL-Chaining example and the demo for more details.
=head2 Database Object Argument
128 => 'tom.acme.com'
},
minSessQOP => 128, minAuthQOP => 128,
authenURL => 'https://tom.acme.com/authen',
defaultURL => 'https://tom.acme.com/protected',
renewURL => 'https://tom.acme.com/renew',
timeoutURL => 'https://tom.acme.com/signout/timeout.html',
errorURL => 'http://tom.acme.com/error.html'
);
Now, on the host which issues credentials, (tom.acme.com in this example),
add the following additional Apache directives to http.conf:
## issues cookies
<Location /authen>
SetHandler perl-script
AuthName "Adam Realm"
AuthType Basic
PerlAuthenHandler $Acme::obj->issue
require valid-user
</Location>
SecSess/Cookie.pm view on Meta::CPAN
my($bs, $ba) = split(',', $b);
return ($bs <=> $as) ? ($bs <=> $as) : ($ba <=> $aa);
} (keys %ckys);
$max = $tags[0];
unless (defined($max)) { return 'No cookie found.'; }
$log->debug(sprintf("Found Cookie: %s:%s=%s", $realm, $max, $ckys{$max}));
return $self->{wrapper}->unwraphash($ckys{$max});
}
## validate (usually non-cookie) credentials used to authenicate user
sub verifyIdentity { my $self = shift; return undef }
## issue cookies
sub issueCredentials {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my(@cky, %args, $url);
$log->debug(ref($self), "->issueCredentials():");
## put credentials into headers
for (@cky = $self->setCookies($r)) {
$r->err_headers_out->add('Set-Cookie' => $_);
}
## form target URL and response
%args = $r->args;
$url = $self->unwrap_uri($args{url}) || $self->defaultURL;
$log->debug("redirect url (after cookies) = ", $url, " args{url}: ",
$args{url});
unless ($url) { return 'No place to go (no defaultURL set).'; }
SecSess/Cookie/BasicAuth.pm view on Meta::CPAN
use Apache::Constants qw(:common :response);
use Apache::SecSess::Cookie;
use vars qw(@ISA $VERSION);
$VERSION = sprintf("%d.%02d", (q$Name: SecSess_Release_0_09 $ =~ /\d+/g));
@ISA = qw(Apache::SecSess::Cookie);
## validate (usually non-cookie) credentials used to authenicate user
sub verifyIdentity {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my($uid, $res, $pw, $msg);
$log->debug(ref($self), "->verifyIdentity():");
## read password and user id if present, bail otherwise
($res, $pw) = $r->get_basic_auth_pw;
SecSess/Cookie/LoginForm.pm view on Meta::CPAN
use strict;
use Apache::SecSess::Cookie;
use vars qw(@ISA $VERSION);
$VERSION = sprintf("%d.%02d", (q$Name: SecSess_Release_0_09 $ =~ /\d+/g));
@ISA = qw(Apache::SecSess::Cookie);
## validate (usually non-cookie) credentials used to authenicate user
sub verifyIdentity {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my(%params, $uid, $pw, %args, $url, $form, $msg);
$log->debug(ref($self), "->verifyIdentity():");
## is this the initial visit to the form?
unless ($r->method eq 'POST') { # allow no GET for now ...
SecSess/Cookie/URL.pm view on Meta::CPAN
use Apache::SecSess::Cookie;
use Apache::SecSess::Wrapper;
use vars qw(@ISA $VERSION);
$VERSION = sprintf("%d.%02d", (q$Name: SecSess_Release_0_09 $ =~ /\d+/g));
@ISA = qw(Apache::SecSess::Cookie);
## validate (usually non-cookie) credentials used to authenicate user
sub verifyIdentity {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my(%args, $ctxt, $urlcred);
$log->debug(ref($self), "->verifyIdentity():");
## extract ciphertext from URL
%args = $r->args;
$ctxt = $args{$self->authRealm};
$urlcred = $self->{wrapper}->unwraphash($ctxt);
## validate URL credentials as we would at higher level
return $self->validateCredentials($r, $urlcred);
}
1;
__END__
What are you looking at?
SecSess/Cookie/X509.pm view on Meta::CPAN
use strict;
use Apache::SecSess::Cookie;
use vars qw(@ISA $VERSION);
$VERSION = sprintf("%d.%02d", (q$Name: SecSess_Release_0_09 $ =~ /\d+/g));
@ISA = qw(Apache::SecSess::Cookie);
## validate (usually non-cookie) credentials used to authenicate user
sub verifyIdentity {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my($subr, $email, $uid);
$log->debug(ref($self), "->verifyIdentity():");
## resolve user ID from certificate DN email
$subr = $r->lookup_uri($r->uri);
SecSess/Cookie/X509PIN.pm view on Meta::CPAN
use strict;
use Apache::SecSess::Cookie;
use vars qw(@ISA $VERSION);
$VERSION = sprintf("%d.%02d", (q$Name: SecSess_Release_0_09 $ =~ /\d+/g));
@ISA = qw(Apache::SecSess::Cookie);
## validate (usually non-cookie) credentials used to authenicate user
sub verifyIdentity {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my($subr, $email, $uid, %params, $pin, %args, $url, $form, $msg);
$log->debug(ref($self), "->verifyIdentity():");
## resolve user ID from certificate DN email
$subr = $r->lookup_uri($r->uri);
SecSess/URL.pm view on Meta::CPAN
use Apache::Constants qw(:common :response);
use Apache::SecSess;
use Apache::SecSess::Wrapper;
use vars qw(@ISA $VERSION);
$VERSION = sprintf("%d.%02d", (q$Name: SecSess_Release_0_09 $ =~ /\d+/g));
@ISA = qw(Apache::SecSess);
## extract appropriate credentials from headers and decrypt contents
sub getCredentials {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my(%args, $ctxt);
$log->debug(ref($self), "->verifyIdentity():");
## extract ciphertext from URL
%args = $r->args;
$ctxt = $args{$self->authRealm};
unless ($ctxt) { return 'No URL credentials found.'; }
return $self->{wrapper}->unwraphash($ctxt);
}
## validate (usually non-url) credentials used to authenicate user
sub verifyIdentity { my $self = shift; return undef }
## issue credentials
sub issueCredentials {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my($uid, $realm, $ctxt, %args, $requrl, $idx, @chains, $chain, $url, $sep);
my($backurl);
$log->debug(ref($self), "->issueCredentials():");
## form credentials as URL query string fragments
$uid = $r->user;
$realm = $self->authRealm;
$ctxt = $self->{wrapper}->wraphash({
uid => $uid,
timestamp => time,
qop => $self->sessQOP,
authqop => $self->authQOP
});
## determine whether in (multi-host) chaining mode
SecSess/URL.pm view on Meta::CPAN
};
}
else { # done chaining
return {
message => "Redirecting '$uid' to original '$requrl'.",
uri => $requrl
};
}
}
## non-chaining mode, tack credentials onto original url and redirect
$sep = ($requrl =~ /\?/) ? '&' : '?';
$requrl .= sprintf('%s%s=%s', $sep, $realm, $ctxt);
return {
message => "Redirecting '$uid' to '$requrl'.",
uri => $requrl
};
}
## delete - nothing to delete
sub deleteCredentials { }
SecSess/URL/Cookie.pm view on Meta::CPAN
use Apache::SecSess;
use Apache::SecSess::URL;
use Apache::SecSess::Wrapper;
use vars qw(@ISA $VERSION);
$VERSION = sprintf("%d.%02d", (q$Name: SecSess_Release_0_09 $ =~ /\d+/g));
@ISA = qw(Apache::SecSess::URL);
## validate credentials used to first authenicate user
sub verifyIdentity {
my $self = shift;
my($r) = @_;
my $log = $r->log;
my($realm, $ckyhead, %ckys, @tags, $max, $url, $ckycred);
$log->debug(ref($self), "->verifyIdentity():");
## extract strongest cookie with appropriate name/tag pair
$realm = $self->authRealm;
demo/ht/adam.acme.com/signout/timeout.html view on Meta::CPAN
<& /index.comp, title => 'Session Timeout', content => $content &>
<%init>
my %messages = (
idle =>
'<b>Idle Timeout:</b> your session remained inactive for too long.',
expire =>
'<b>Expiration:</b> your session has expired.',
notvalid =>
'<b>No Longer Valid:</b> your session credentials are no longer valid.',
unknown =>
'<b>Unknown Reason.</b>'
);
my $content = <<"ENDCONTENT";
<font color="#f42424" size=5>Session Timeout.</font><p>
Your login session has timed out due to the following reason:
<ul>
<li> $messages{$type}
</ul>
demo/ht/john.sec.acme.com/signout/timeout.html view on Meta::CPAN
<& /index.comp, title => 'Session Timeout', content => $content &>
<%init>
my %messages = (
idle =>
'<b>Idle Timeout:</b> your session remained inactive for too long.',
expire =>
'<b>Expiration:</b> your session has expired.',
notvalid =>
'<b>No Longer Valid:</b> your session credentials are no longer valid.',
unknown =>
'<b>Unknown Reason.</b>'
);
my $content = <<"ENDCONTENT";
<font color="#f42424" size=5>Session Timeout.</font><p>
Your login session has timed out due to the following reason:
<ul>
<li> $messages{$type}
</ul>
demo/ht/lysander.acme.com/signout/timeout.html view on Meta::CPAN
<& /index.comp, title => 'Session Timeout', content => $content &>
<%init>
my %messages = (
idle =>
'<b>Idle Timeout:</b> your session remained inactive for too long.',
expire =>
'<b>Expiration:</b> your session has expired.',
notvalid =>
'<b>No Longer Valid:</b> your session credentials are no longer valid.',
unknown =>
'<b>Unknown Reason.</b>'
);
my $content = <<"ENDCONTENT";
<font color="#f42424" size=5>Session Timeout.</font><p>
Your login session has timed out due to the following reason:
<ul>
<li> $messages{$type}
</ul>
demo/ht/milt.sec.acme.com/signout/timeout.html view on Meta::CPAN
<& /index.comp, title => 'Session Timeout', content => $content &>
<%init>
my %messages = (
idle =>
'<b>Idle Timeout:</b> your session remained inactive for too long.',
expire =>
'<b>Expiration:</b> your session has expired.',
notvalid =>
'<b>No Longer Valid:</b> your session credentials are no longer valid.',
unknown =>
'<b>Unknown Reason.</b>'
);
my $content = <<"ENDCONTENT";
<font color="#f42424" size=5>Session Timeout.</font><p>
Your login session has timed out due to the following reason:
<ul>
<li> $messages{$type}
</ul>
demo/ht/noam.acme.org/signout/timeout.html view on Meta::CPAN
<& /index.comp, title => 'Session Timeout', content => $content &>
<%init>
my %messages = (
idle =>
'<b>Idle Timeout:</b> your session remained inactive for too long.',
expire =>
'<b>Expiration:</b> your session has expired.',
notvalid =>
'<b>No Longer Valid:</b> your session credentials are no longer valid.',
unknown =>
'<b>Unknown Reason.</b>'
);
my $content = <<"ENDCONTENT";
<font color="#f42424" size=5>Session Timeout.</font><p>
Your login session has timed out due to the following reason:
<ul>
<li> $messages{$type}
</ul>
demo/ht/stu.transacme.com/signout/timeout.html view on Meta::CPAN
<& /index.comp, title => 'Session Timeout', content => $content &>
<%init>
my %messages = (
idle =>
'<b>Idle Timeout:</b> your session remained inactive for too long.',
expire =>
'<b>Expiration:</b> your session has expired.',
notvalid =>
'<b>No Longer Valid:</b> your session credentials are no longer valid.',
unknown =>
'<b>Unknown Reason.</b>'
);
my $content = <<"ENDCONTENT";
<font color="#f42424" size=5>Session Timeout.</font><p>
Your login session has timed out due to the following reason:
<ul>
<li> $messages{$type}
</ul>
demo/ht/tom.acme.com/signout/timeout.html view on Meta::CPAN
<& /index.comp, title => 'Session Timeout', content => $content &>
<%init>
my %messages = (
idle =>
'<b>Idle Timeout:</b> your session remained inactive for too long.',
expire =>
'<b>Expiration:</b> your session has expired.',
notvalid =>
'<b>No Longer Valid:</b> your session credentials are no longer valid.',
unknown =>
'<b>Unknown Reason.</b>'
);
my $content = <<"ENDCONTENT";
<font color="#f42424" size=5>Session Timeout.</font><p>
Your login session has timed out due to the following reason:
<ul>
<li> $messages{$type}
</ul>
demo/httpdconf/startup.pl view on Meta::CPAN
authRealm => 'Acme',
cookieDomain => { 128 => 'stu.transacme.com' },
authenURL => 'https://stu.transacme.com/authen',
defaultURL => 'https://stu.transacme.com/chain',
renewURL => 'https://stu.transacme.com/renew',
timeoutURL => 'https://stu.transacme.com/signout/timeout.html',
adminURL => 'https://stu.transacme.com/changeid',
errorURL => 'http://stu.transacme.com/error.html'
);
## stu.transacme.com issue mangled-URL credentials based on stu cookies
$Acme::chain = Apache::SecSess::URL::Cookie->new(
dbo => Apache::SecSess::DBI->new(
dbifile => '/usr/local/apache/conf/private/dbilogin.txt'
),
secretFile => '/usr/local/apache/conf/private/ckysec.txt',
lifeTime => 1440, idleTime => 60, renewRate => 5,
sessQOP => 128, authQOP => 128,
minSessQOP => 128, minAuthQOP => 128,
authRealm => 'Acme',
authenURL => 'https://stu.transacme.com/authen',
rfc/rfc2964.txt view on Meta::CPAN
Because such practices encourage users to defeat HTTP State
Management mechanisms, they tend to reduce the effectiveness of HTTP
State Management, and are therefore considered detrimental to the
operation of the web.
2.2.2. Use as an Authentication Mechanism
It is generally inappropriate to use the HTTP State Management
protocol as an authentication mechanism. HTTP State Management is
not designed with such use in mind, and safeguards for protection of
authentication credentials are lacking in both the protocol
specification and in widely deployed HTTP clients and servers. Most
HTTP sessions are not encrypted and "cookies" may therefore be
exposed to passive eavesdroppers. Furthermore, HTTP clients and
servers typically store "cookies" in cleartext with little or no
protection against exposure. HTTP State Management therefore SHOULD
Moore & Freed Best Current Practice [Page 4]