[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