package LATMOS::Accounts::Acls; use strict; use warnings; use LATMOS::Accounts::Log; use LATMOS::Accounts::Acls::Acl; our $VERSION = (q$Rev: 330 $ =~ /^Rev: (\d+) /)[0]; =head1 NAME LATMOS::Accounts::Acls - Acl support in L =head1 FUNCTIONS =cut =head2 new ($file) Instanciate Acls from C<$file> =cut sub new { my ($class, $file) = @_; my $acls = bless( { _acls => [] }, $class ); if ($file) { $acls->read_acl_file($file) or return; } $acls } =head1 ACL FILE FORMAT OBJ_TYPE.ATTRIBUTE USER: read,write USER2: read =over 4 =item OBJ_TYPE is the type the object, '*' match all =item ATTRIBUTE is either an attribute, either an comma separate attribute enclose into bracket, either a '*' to match any attribute. Special keyword C<@CREATE> and C<@DELETE> can be used to allow or deny object creation and deletion. In this case read permission and USER in form C<$...> for C<@CREATE> have no effect (see below). C<*> do not include C<@CREATE> and C<@DELETE> action. =item USER can be =over 4 =item a username =item group, prefixed by a '%' =item an attribute of the accessed object which should contains the username, prefixed by '$' =item C<*> to math any user =item @authenticated or @anonymous for any authenticated user and non authenticated user ('*' include both) =back =item Permission are read and or write, or deny. =back ACL are applied in the order they appear in the file. =cut =head2 read_acl_file ($file) Load acls from file C<$file>. =cut sub read_acl_file { my ($self, $file) = @_; my $acl; my $line_nb = 0; my $prevline = ""; if (open(my $handle, '<', $file)) { while(my $realline = <$handle>) { $line_nb++; chomp($realline); if ($realline =~ /\\$/) { # continuation line $prevline .= $realline; $prevline =~ s/\s*\\$//; next; } my $line = $prevline . $realline; # keep track to report malformed file $prevline = ""; $line =~ s/\s*#.*//; if ($line =~ /^(\S.*)/) { if ($acl) { push(@{$self->{_acls}}, $acl); } $acl = LATMOS::Accounts::Acls::Acl->new($1) or do { la_log(LA_ERR, "Error in %s at line %d", $file, $line_nb); return; }; } elsif ($line =~ /^\s+(\S.*)/) { if ($acl) { $acl->add_perm($line) or do { la_log(LA_ERR, "Error in %s at line %d", $file, $line_nb); return; }; } else { # err no acl return; } } elsif ($line =~ /^\s*$/) { # just empty line } else { } } if ($acl) { push(@{$self->{_acls}}, $acl); } } else { la_log(LA_ERR, "Cannot open acl file %s", $file); return; } 1; } =head2 add ($obj_dot_attr, $list) A new acl for C<$obj_dot_attr> (in form C) with C<$list> permissions. =cut sub add { my ($self, $obj, $list) = @_; my $acl = LATMOS::Accounts::Acls::Acl->new( $obj, $list) or return; push(@{$self->{_acls}}, $acl); return 1; } =head2 check ($obj, $attr, $perm, $who, $groups) Return true is this acl apply to C<$obj>/C<$attr> for C<$perm> by user C<$who> in groups C<$groups>. =cut sub check { my ($self, $obj, $attr, $perm, $who, $groups) = @_; # Asking 'r' perm over create or delete has no sense: $attr =~ /^@(CREATE|DELETE)$/ && $perm eq 'r' and return; foreach my $acl (@{$self->{_acls}}) { my $res = $acl->match($obj, $attr, $perm, $who, $groups); defined($res) and return $res; } return 0; } =head2 dump Return currently load acl as text =cut sub dump { my ($self) = @_; foreach my $acl (@{$self->{_acls}}) { print $acl->dump, "\n"; } } 1; __END__ =head1 SEE ALSO L =head1 AUTHOR Thauvin Olivier, Eolivier.thauvin@latmos.ipsl.frE =head1 COPYRIGHT AND LICENSE Copyright (C) 2009, 2010, 2011, 2012 by Thauvin Olivier This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available. =cut