[Rt-commit] [svn] r781 - in rt: . branches/rt-3.3/html/REST/2.0
branches/rt-3.3/lib/RT
autrijus at pallas.eruditorum.org
autrijus at pallas.eruditorum.org
Fri Apr 30 23:24:13 EDT 2004
Author: autrijus
Date: Fri Apr 30 23:24:12 2004
New Revision: 781
Added:
rt/branches/rt-3.3/html/REST/2.0/
rt/branches/rt-3.3/html/REST/2.0/autohandler
rt/branches/rt-3.3/html/REST/2.0/dhandler
Modified:
rt/ (props changed)
rt/branches/rt-3.3/lib/RT/CurrentUser.pm
Log:
----------------------------------------------------------------------
r4309 at not: autrijus | 2004-05-01T03:22:53.730384Z
* initial commit of RT/REST 2.0 API and WSSE authentication.
----------------------------------------------------------------------
Added: rt/branches/rt-3.3/html/REST/2.0/autohandler
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/autohandler Fri Apr 30 23:24:12 2004
@@ -0,0 +1,6 @@
+%# Forbid direct access in this directory -- everything goes thru dhandler
+% $r->content_type('text/html; charset=utf-8');
+% $m->abort(403);
+<%flags>
+inherit => undef
+</%flags>
Added: rt/branches/rt-3.3/html/REST/2.0/dhandler
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/dhandler Fri Apr 30 23:24:12 2004
@@ -0,0 +1,84 @@
+%# The main dispatcher for RT/REST 2.0
+<%INIT>
+my $realm = $RT::rtname;
+$realm =~ s/[^\w.]//g;
+
+# XXX - do Digest auth here too?
+$r->header_out(
+ 'WWW-Authenticate' => qq(WSSE realm="$realm", profile="UsernameToken")
+);
+
+my $CurrentUser;
+
+AUTH: {
+ my $auth = $r->header_in('Authorization');
+ $auth =~ /^WSSE (?=.*\bprofile="UsernameToken")/ or last;
+
+ my $wsse = $r->header_in('X-WSSE');
+ $wsse =~ s/^(?:WSSE|UsernameToken) // or last;
+
+ my %param;
+ foreach my $i (split /,\s*/, $wsse) {
+ my ($k, $v) = split /=/, $i, 2;
+ $v =~ s/^"//; $v =~ s/"$//;
+ $param{lc($k)} = $v;
+ }
+
+ my ($username, $auth_digest, $auth_nonce, $auth_created)
+ = map { defined($_) ? $_ : last AUTH }
+ @param{qw(username passworddigest nonce created)};
+
+ require RT::CurrentUser;
+ $CurrentUser = RT::CurrentUser->new;
+ $CurrentUser->Load($username) or last;
+
+ # check against reused nonces
+ my $nonce_cache;
+ if ($auth_nonce) {
+ require Cache::FileCache;
+ $nonce_cache = Cache::FileCache->new({
+ namespace => 'RT-Nonces',
+ default_expires_in => 1728000,
+ auto_purge_interval => 3600,
+ });
+ $auth_nonce = substr($auth_nonce, 0, 32);
+ last if $nonce_cache->get( $auth_nonce );
+ }
+
+ # if ($auth_created and abs($auth_created - time) >= 864000) {
+ # last; # system clock differ by more than one day, oops!
+ # }
+
+ delete $INC{'RT/CurrentUser.pm'};
+ require RT::CurrentUser;
+
+ require MIME::Base64;
+ $auth_nonce = MIME::Base64::decode_base64($auth_nonce);
+
+ $CurrentUser->Authenticate(
+ $auth_digest, $auth_created, $auth_nonce, $realm
+ ) or (undef($CurrentUser), last);
+
+ # remember issued nonces
+ $nonce_cache->set( $auth_nonce, 1 );
+}
+
+if ($CurrentUser and $CurrentUser->Id) {
+ # $m->comp( $m->dhandler_arg ); # XXX - proper delegation goes here
+ print << ".";
+<?xml version="1.0" encoding="utf-8"?>
+<feed version="0.3" xmlns="http://purl.org/atom/ns#">
+ <title>Ticket search results</title>
+ <modified>2000-01-01T01:01:01Z</modified>
+ <author><name>$RT::rtname</name></author>
+</feed>
+.
+}
+else {
+ $r->status(401);
+}
+
+</%INIT>
+<%FLAGS>
+inherit => undef
+</%FLAGS>
Modified: rt/branches/rt-3.3/lib/RT/CurrentUser.pm
==============================================================================
--- rt/branches/rt-3.3/lib/RT/CurrentUser.pm (original)
+++ rt/branches/rt-3.3/lib/RT/CurrentUser.pm Fri Apr 30 23:24:12 2004
@@ -403,6 +403,47 @@
}
+=head2 Authenticate
+
+Takes $password, $created and $nonce, and returns a boolean value
+representing whether the authentication succeeded.
+
+If both $nonce and $created are specified, validate $password against:
+
+ encode_base64(sha1(
+ $nonce .
+ $created .
+ sha1_hex( "$username:$realm:$server_pass" )
+ ))
+
+where $server_pass is the md5_hex(password) digest stored in the
+database, $created is in ISO time format, and $nonce is a random
+string no longer than 32 bytes.
+
+=cut
+
+sub Authenticate {
+ my ($self, $password, $created, $nonce, $realm) = @_;
+
+ require Digest::SHA1;
+ require MIME::Base64;
+
+ my $username = $self->UserObj->Name or return;
+ my $server_pass = $self->UserObj->__Value('Password') or return;
+ my $auth_digest = MIME::Base64::encode_base64(Digest::SHA1::sha1(
+ $nonce .
+ $created .
+ Digest::SHA1::sha1_hex("$username:$realm:$server_pass")
+ ));
+
+ chomp($password);
+ chomp($auth_digest);
+
+ return ($password eq $auth_digest);
+}
+
+# }}}
+
eval "require RT::CurrentUser_Vendor";
die $@ if ($@ && $@ !~ qr{^Can't locate RT/CurrentUser_Vendor.pm});
More information about the Rt-commit
mailing list