#! /usr/bin/perl package My::simple; # Version 1.0 MCLA CSS use Apache2::Access (); use Apache2::RequestUtil (); # load modules that are going to be used use Data::Dumper; use CGI qw(:standard); use CGI::Cookie; use Cache::Memcached; use PHP::Serialization qw(serialize unserialize); # compile (or import) constants use Apache2::Const -compile => qw(OK FORBIDDEN); $debug=0; $debug_file="/tmp/xxx"; dmp('prerun',('test')); sub handler { my $r = shift; my $user = $r->user; dmp('0 user',$user); # ------------------------ get valid group(s) for this session my $valid_group_expr=$r->dir_config("VALID_GROUP_EXPR"); dmp('1 valid group list',$valid_group_expr); # -- get the session cooke to retrieve the session $query = new CGI; # fetch existing cookies my %cookies = CGI::Cookie->fetch; # dmp('Cookies',%cookies); my $ID = $cookies{'SimpleSAMLSessionID'}->value; dmp('2 SimpleSAMLSessionID value',$ID); my $SessionID='simpleSAMLphp.session.' . $ID; # -- use the session ID to look up the value of memcached key simpleSAMLphp.session. my $cache = new Cache::Memcached { 'servers' => ['127.0.0.1:11211'], 'compress_threshold' => 10_000, }; # Get the value from cache: my $value = $cache->get($SessionID); # dmp('mamcache value',($value)); # -- use the value data to find the groups my $hashref = unserialize($value); # dmp('mamcache unserialized',($hashref)); my %hash = %{ $hashref }; %hash = % { $hash {'data'}{chr(0) . 'SimpleSAML_Session' . chr(0) . 'authData'}{'default-sp'}{'Attributes'} }; my @groups = @ { $hash{'groups'} }; dmp("3 Comparing $valid_group_expr to", \@groups); my $result=evaluate($valid_group_expr,@groups); if ($result) { dmp("this guy oK",$result); return Apache2::Const::HTTP_OK; } dmp("blowing this guy off",$result); $r->log_reason("Not a member of group " . $valid_group_expr); return Apache2::Const::FORBIDDEN; # return Apache2::Const::HTTP_FORBIDDEN; # return Apache2::Const::HTTP_OK; # return Apache2::Const::DECLINED; } # ======================= utility functions # evaluate returns the boolean value of the expression $expr # after substituting membership information in @groups # # valid operators are # # &&, and, AND logical AND # ||, or, OR logical OR # !, NOT, not logical NOT # # expression must be infix and precidence can be indicated by () sub evaluate { my ($expr,@groups)=@_; # print "$expr\n"; # print Dumper(\%group_hash); # operator tokens my %token_hash = ( '(' => '(', ')' => ')', 'AND' => '&&', 'and' => '&&', 'or' => '||', 'OR' => '||', '!' => '!', 'not' => '!', 'NOT' => '!', ) ; # add the group array into the token hash as TRUEs foreach $v (@groups) { $v=~s/ /_/g; $token_hash{$v} = 1; } dmp('merged hash',\%token_hash); # merge the two hashes into %token_hash # foreach my $tkey ( keys %group_hash) { $token_hash{$tkey} = $group_hash{$tkey}; } # print Dumper(\%token_hash); $expr=~s/\(/ ( /g; $expr=~s/\)/ ) /g; $expr=~s/\!/ ! /g; # print "$expr\n"; my @expr_hash=split (/ /,$expr); $expr=''; foreach my $t (@expr_hash) { if ($t ne '') { if (exists ($token_hash{$t})) { $t = $token_hash{$t} } else {$t = 0;} $expr = $expr . "$t "; } } dmp("expression",$expr); my $result=0; my $assignment="\$result = $expr;"; dmp("assignment",$assignment); eval($assignment); dmp("result",$result); return $result; } # debug dump structure funcion sub dmp { if ($debug == 1) { my ($label,@value) = @_; my $temp = Dumper(@value); open (T, ">>$debug_file"); # || die "Can't open $debug_file: $!\n"; print T "$label: $temp\n"; close (T); } } 1;