]> git.sesse.net Git - itkacl/blobdiff - itkacl-web-1.0/include/itkaclcommon.pm
Release a new version of the Apache module, with the context support.
[itkacl] / itkacl-web-1.0 / include / itkaclcommon.pm
index 36eb89014701935a70293ef93f40e4192906d2f3..cd86a3b5ddb6bee1eca2a819cb6b9a9f8411095f 100644 (file)
@@ -6,6 +6,7 @@ use DBI;
 use Apache::Session::Postgres;
 use Encode;
 use HTML::Entities;
+use Digest::HMAC_SHA1;
 use locale;
 use utf8;
 
@@ -17,6 +18,8 @@ our $cgi;
 our $dbh;
 our $last_modified = '$Date: 2011-11-19 11:08:01 $';
 our %session;
+our $csrf_token;
+our $masked_csrf_token;
 
 sub init {
        $cgi = new CGI;
@@ -26,6 +29,46 @@ sub init {
        $dbh->{pg_enable_utf8} = 1;
        $last_modified = '$Date: 2011-11-19 11:08:01 $';
        %session = ();
+
+       if (defined($ENV{'REMOTE_USER'})) {
+               $csrf_token = Digest::HMAC_SHA1::hmac_sha1($ENV{'REMOTE_USER'}, $itkaclcommon::hmac_key);
+
+               # Mask the CSRF token to avoid the BREACH attack.
+               my @hmac_bytes = map { ord($_) } (split //, $csrf_token);
+               my @random_bytes = map { int(rand(256)) } (0..$#hmac_bytes);
+               my @masked_bytes = map { $hmac_bytes[$_] ^ $random_bytes[$_] } (0..$#hmac_bytes);
+               
+               my $random_bytes_string = join('', map { chr($_) } (@random_bytes));
+               my $masked_bytes_string = join('', map { chr($_) } (@masked_bytes));
+               $masked_csrf_token = unpack('H*', $random_bytes_string) . '_' . unpack("H*", $masked_bytes_string);
+       } else {
+               $csrf_token = '';
+               $masked_csrf_token = '';
+       }
+}
+
+sub check_csrf_token {
+       if ($csrf_token eq '') {
+               # Not logged in, so always fine.
+               return 1;
+       }
+       
+       my $candidate_csrf_token = $cgi->param('csrftoken');
+       if ($candidate_csrf_token !~ /^([0-9a-f]+)_([0-9a-f]+)$/) {
+               die "Invalid CSRF token!";
+       }
+
+       my ($random_bytes_string, $masked_bytes_string) = ($1, $2);
+       if (length($random_bytes_string) != length($masked_bytes_string)) {
+               die "Length mismatch in CSRF token!";
+       }
+
+       my @random_bytes = map { ord($_) } (split //, pack('H*', $random_bytes_string));
+       my @masked_bytes = map { ord($_) } (split //, pack('H*', $masked_bytes_string));
+       my @hmac_bytes = map { $masked_bytes[$_] ^ $random_bytes[$_] } (0..$#masked_bytes);
+       my $hmac_string = join('', map { chr($_) } (@hmac_bytes));
+
+       die "CSRF token mismatch!" if ($hmac_string ne $csrf_token);
 }
 
 sub print_header {
@@ -150,9 +193,9 @@ sub print_tree_element {
                # Stuff to the left of folder
                for my $i (1..$level) {
                        if ($vbars->[$i - 1]) {
-                               print '<img src="/img/verticalbar.png" alt="|" width="18" height="18" />';
+                               print '<img src="/img/verticalbar.png" alt="|" width="16" height="18" />';
                        } else {
-                               print '<img src="/img/whitespace.png" alt="&nbsp;" width="18" height="18" />';
+                               print '<img src="/img/whitespace.png" alt="&nbsp;" width="16" height="18" />';
                        }
                }
 
@@ -160,9 +203,9 @@ sub print_tree_element {
                my $countref = $dbh->selectrow_hashref('SELECT COUNT(*) AS num FROM objects WHERE parent=?', undef, $ref->[0]);
                if ($countref->{'num'} == 0) {
                        if ($i == $count) {
-                               print "<img src=\"/img/folder-nochildren.png\" alt=\"\" width=\"39\" height=\"18\" />";
+                               print "<img src=\"/img/folder-nochildren.png\" alt=\"\" width=\"37\" height=\"18\" />";
                        } else {
-                               print "<img src=\"/img/folder-nochildren-moresiblings.png\" alt=\"|\" width=\"39\" height=\"18\" />";
+                               print "<img src=\"/img/folder-nochildren-moresiblings.png\" alt=\"|\" width=\"37\" height=\"18\" />";
                        }
                } else {
                        my $url = $cgi->url(-absolute=>1) . "?";
@@ -177,9 +220,9 @@ sub print_tree_element {
                        }
                                                         
                        if (defined($session{$ref->[0]})) {
-                               print "<a href=\"${url}close=$ref->[0]\"><img src=\"/img/folder-open$msb.png\" alt=\"-\" width=\"39\" height=\"18\" /></a>";
+                               print "<a href=\"${url}close=$ref->[0]\"><img src=\"/img/folder-open$msb.png\" alt=\"-\" width=\"37\" height=\"18\" /></a>";
                        } else {
-                               print "<a href=\"${url}open=$ref->[0]\"><img src=\"/img/folder-closed$msb.png\" alt=\"+\" width=\"39\" height=\"18\" /></a>";
+                               print "<a href=\"${url}open=$ref->[0]\"><img src=\"/img/folder-closed$msb.png\" alt=\"+\" width=\"37\" height=\"18\" /></a>";
                        }
                }