view release on metacpan or search on metacpan
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), "->authen():");
$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;
}
return OK;
}
## authorize request
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; }
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
$resp = $self->verifyAdminRequest($r);
unless (ref($resp)) { $log->error($resp); return SERVER_ERROR; }
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"
};
uri => $uri
};
}
## set user id for Apache
$uid = $cred->{uid};
$log->debug("Setting user ID: '$uid'.");
$r->user($uid);
## checksum is good, examine the protection qualities and freshness
if ($resp = $self->validateQOP($r, $cred)) { return $resp; }
if ($resp = $self->validateAge($r, $cred)) { return $resp; }
## user authenticated
$log->info("User '$uid' authenticated.");
return undef;
}
## validate quality of protection
sub validateQOP {
my $self = shift;
my($r, $cred) = @_;
my($uri, $requri);
unless ($cred->{qop} >= $self->minSessQOP) {
$uri = $self->authenURL;
$requri = $self->requested_uri($r);
return {
message => "Insufficient session protection.",
uri => "$uri?url=$requri"
$requri = $self->requested_uri($r);
return {
message => "Insufficient authentication protection.",
uri => "$uri?url=$requri"
}
}
return undef;
}
## validated time stamp
sub validateAge {
my $self = shift;
my($r, $cred) = @_;
my($life, $idle, $renew, $uid, $ts, $t, $uri, $requri);
## get object timing constants
$life = $self->lifeTime;
$idle = $self->idleTime;
$renew = $self->renewRate;
## check times
$uid = $cred->{uid};
$ts = $cred->{timestamp};
$t = time;
$r->log->debug(sprintf(
"validateAge(): uid = '%s', time - ts = %.02f (min):"
. " vs renew = %d, idle = %d, life = %d",
$uid, ($t-$ts)/60.0, $renew, $idle, $life
));
if ($t > $ts + 60*$life) { # hard timeout
$uri = $self->timeoutURL;
return {
message => "Expired, redirecting '$uid' to '$uri?type=expire'.",
uri => "$uri?type=expire"
};
}
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
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():");
SecSess/Cookie.pm view on Meta::CPAN
## check if *new* user is valid
$status = $self->{dbo}->get_user_status($newuid);
unless ($status eq 'enabled') {
return {
message => "User '$newuid' unavailable: '$status'.",
uri => "$form?msg=$status"
};
}
## validate super user's password
$msg = $self->{dbo}->validate_user_pass($uid, $pw);
unless ($msg eq 'OK') {
return {
message => "Incorrect superuser password for '$uid'.",
uri => "$form?msg=$msg"
};
}
## everything looks good, allow the change of identity
return {
message => "Superuser '$uid' changing to user '$newuid'",
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/BasicAuth.pm view on Meta::CPAN
}
$uid = $r->user;
unless ($uid && $pw) {
$r->note_basic_auth_failure;
return {
message => "Basic auth failed, uid: '$uid', pw: '$pw'.",
auth_required => 'true'
};
}
## validate user and password
$msg = $self->{dbo}->validate_user_pass($uid, $pw);
unless ($msg eq 'OK') {
return {
message => $msg,
auth_required => 'true',
};
}
return undef;
}
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/LoginForm.pm view on Meta::CPAN
}
}
## extract user ID, password and other data
%params = $r->content;
$uid = $params{uid};
$pw = $params{pw};
%args = $r->args;
$url = $args{url};
## validate user and password
$msg = $self->{dbo}->validate_user_pass($uid, $pw);
unless ($msg eq 'OK') {
$form = $self->authenURL;
$form .= "?msg=$msg";
$form .= "&url=$url" if $url;
return {
message => "Auth error code: '$msg'",
uri => $form
};
}
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/Cookie/X509PIN.pm view on Meta::CPAN
fill_form => 'true'
}
}
## extract user ID, password and other data from POST
%params = $r->content;
$pin = $params{pin};
%args = $r->args;
$url = $args{url};
## validate PIN code
$msg = $self->{dbo}->validate_stored_token($uid, $pin, 'pin');
unless ($msg eq 'OK') {
$form = $self->authenURL;
$form .= "?msg=$msg";
$form .= "&url=$url" if $url;
return {
message => "Auth error code: '$msg'",
uri => $form
};
}
SecSess/DBI.pm view on Meta::CPAN
$uasth->execute($uid, $authid);
# process query output
($token) = $uasth->fetchrow_array;
$uasth->finish;
return $self->dbunquote($token);
}
## valid a user/password against database
sub validate_user_pass {
my $self = shift;
my($uid, $pw) = @_;
## this little extra step is necessary for crypt() to work
unless ($uid && $pw) { return 'empty'; }
my $pwhash = $self->get_pwhash($uid);
return $self->validate_stored_token($uid, crypt($pw, $pwhash), 'unixpw');
}
## validate a general stored token (eg, password, PIN, etc)
sub validate_stored_token {
my $self = shift;
my($uid, $token, $authid) = @_;
my($status);
unless ($uid) { return 'empty'; } # empty uid argument
$status = $self->get_user_status($uid);
unless ($status eq 'enabled') { return $status; } # disabled or unknown
unless ($token) { return 'empty'; } # empty token argument
unless ($token eq $self->get_stored_token($uid, $authid)) {
$self->note_auth_failure($uid, $authid);
SecSess/URL.pm view on Meta::CPAN
$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);
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;
SecSess/URL/Cookie.pm view on Meta::CPAN
);
return {
message => "No cookie found, redirecting to '$url'",
uri => $url
};
}
## cookie found, but must be verified
$log->debug(sprintf("Found Cookie: %s:%s=%s", $realm, $max, $ckys{$max}));
$ckycred = $self->{wrapper}->unwraphash($ckys{$max});
return $self->validateCredentials($r, $ckycred);
}
1;
__END__
What are you looking at?
@uids = ('bob', 'guest');
for $uid (@uids) {
printf("groups(%s): ('%s')\n", $uid,
join("','", $dbo->get_groups($uid))
);
printf("%s is valid: %d\n", $uid, $dbo->is_valid_user($uid));
printf("%s is super: %d\n", $uid, $dbo->is_super_user($uid));
printf("%s is admin: %d\n", $uid, $dbo->is_administrator($uid));
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'sekret'));
}
## invalidate guest
$uid = 'guest';
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'sekret'));
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'sekret'));
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'sekret'));
printf("status(%s) = %s\n", $uid, $dbo->get_user_status($uid));
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'johnanon'));
printf("re-enabling user '%s'\n", $uid);
$dbo->enable_user($uid);
printf("status(%s) = %s\n", $uid, $dbo->get_user_status($uid));
## see if it works for multivalued auths
$uid = 'bob';
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'secret'));
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'secret'));
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'secret'));
printf("verified = '%s'\n", $dbo->validate_user_pass($uid, 'secret'));
printf("status(%s) = %s\n", $uid, $dbo->get_user_status($uid));
printf("re-enabling user '%s'\n", $uid);
$dbo->enable_user($uid);
printf("status(%s) = %s\n", $uid, $dbo->get_user_status($uid));
## resolve X509 emails to uids
for $uid (@uids) {
$email = $dbo->get_stored_token($uid, 'x509email');
next unless $email;
printf("uid('%s') = '%s'\n", $email, $dbo->x509email_to_uid($email));
rfc/rfc2109.txt view on Meta::CPAN
response headers, depending on circumstances:
* To suppress caching of the Set-Cookie header: Cache-control: no-
cache="set-cookie".
and one of the following:
* To suppress caching of a private document in shared caches: Cache-
control: private.
* To allow caching of a document and require that it be validated
before returning it to the client: Cache-control: must-revalidate.
* To allow caching of a document, but to require that proxy caches
(not user agent caches) validate it before returning it to the
client: Cache-control: proxy-revalidate.
* To allow caching of a document and request that it be validated
before returning it to the client (by "pre-expiring" it):
Cache-control: max-age=0. Not all caches will revalidate the
document in every case.
HTTP/1.1 servers must send Expires: old-date (where old-date is a
date long in the past) on responses containing Set-Cookie response
headers unless they know for certain (by out of band means) that
there are no downsteam HTTP/1.0 proxies. HTTP/1.1 servers may send
other Cache-Control directives that permit caching by HTTP/1.1
proxies in addition to the Expires: old-date directive; the Cache-
Control directive will override the Expires: old-date for HTTP/1.1
proxies.
rfc/rfc2965.txt view on Meta::CPAN
Cache-control: private
Kristol & Montulli Standards Track [Page 7]
RFC 2965 HTTP State Management Mechanism October 2000
* To allow caching of a document and require that it be validated
before returning it to the client:
Cache-Control: must-revalidate, max-age=0
* To allow caching of a document, but to require that proxy
caches (not user agent caches) validate it before returning it
to the client:
Cache-Control: proxy-revalidate, max-age=0
* To allow caching of a document and request that it be validated
before returning it to the client (by "pre-expiring" it):
Cache-control: max-age=0
Not all caches will revalidate the document in every case.
HTTP/1.1 servers MUST send Expires: old-date (where old-date is a
date long in the past) on responses containing Set-Cookie2 response
headers unless they know for certain (by out of band means) that
there are no HTTP/1.0 proxies in the response chain. HTTP/1.1
servers MAY send other Cache-Control directives that permit caching
by HTTP/1.1 proxies in addition to the Expires: old-date directive;
the Cache-Control directive will override the Expires: old-date for
HTTP/1.1 proxies.