diff --git a/lib/Simba/CA.pm b/lib/Simba/CA.pm index 635fee8..4c2682b 100644 --- a/lib/Simba/CA.pm +++ b/lib/Simba/CA.pm @@ -17,7 +17,7 @@ use Scalar::Util qw(tainted); Readonly my $BUFSIZE => 128 * 1024; sub new { - my ($class) = @_; + my ($class, $opt) = @_; my $self = {}; bless $self, $class; @@ -26,6 +26,10 @@ sub new { $self->{targets} = [ { host => 'localhost', dir => '/var/tmp', }, ]; + $self->{unknown_uid} = 65533; + $self->{unknown_gid} = 65533; + $self->{fh_log} = exists($opt->{fh_log}) ? $opt->{fh_log} : \*STDERR; + $self->{log_level} = 99; return $self; } @@ -158,8 +162,8 @@ sub present { return unless $st; if ($st->mtime == $f->{m} && $st->size == $f->{s} && - $st->uid == name2uid($f->{o}) && - $st->gid == name2gid($f->{g}) && + $st->uid == $self->name2uid($f->{o}) && + $st->gid == $self->name2gid($f->{g}) && ($st->mode & 07777) == $self->acl2mode($f) ) { return 1; @@ -226,7 +230,7 @@ sub setmeta { my $mode = $self->acl2mode($f); print STDERR "$mode is tainted!" if tainted($mode); chmod($mode, $fn); - chown(name2uid($f->{o}), name2gid($f->{g}), $fn); + chown($self->name2uid($f->{o}), $self->name2gid($f->{g}), $fn); utime(time, $f->{m}, $fn); } @@ -260,7 +264,7 @@ sub acl2mode { my %ucache; sub name2uid { - my ($uname) = @_; + my ($self, $uname) = @_; $uname = $1 if $uname =~ /(.*)/; # detaint return $ucache{$uname} if (defined $ucache{$uname}); if ($uname =~ /^\d+$/) { @@ -270,14 +274,14 @@ sub name2uid { if (defined($uid)) { return $ucache{$uname} = $uid; } else { - return $ucache{$uname} = -2; + return $ucache{$uname} = $self->{unknown_uid}; } } } my %gcache; sub name2gid { - my ($gname) = @_; + my ($self, $gname) = @_; $gname = $1 if $gname =~ /(.*)/; # detaint return $gcache{$gname} if (defined $gcache{$gname}); if ($gname =~ /^\d+$/) { @@ -287,10 +291,23 @@ sub name2gid { if (defined($gid)) { return $gcache{$gname} = $gid; } else { - return $gcache{$gname} = -2; + return $gcache{$gname} = $self->{unknown_gid}; } } } +sub log { + my ($self, $level, $msg) = @_; + if ($level <= $self->{log_level}) { + $self->{fh_log}->print(strftime("%Y-%m-%dT%H:%M:%S%z", localtime), " $$ [$level]: $msg\n"); + } +} + +sub log_level { + my ($self, $log_level) = @_; + $self->{log_level} = $log_level if defined($log_level); + return $self->{log_level}; +} + # vim: tw=0 expandtab 1; diff --git a/t/01_ca.t b/t/01_ca.t index 1203672..ae993c5 100644 --- a/t/01_ca.t +++ b/t/01_ca.t @@ -2,7 +2,7 @@ use warnings; use strict; -use Test::More 'no_plan'; +use Test::More tests => 15; BEGIN { use_ok( 'Simba::CA' ); } @@ -10,11 +10,11 @@ my $ca = Simba::CA->new(); ok($ca, 'new CA'); my $uid; -$uid = Simba::CA::name2uid('root'); +$uid = $ca->name2uid('root'); ok(defined($uid), 'root has uid'); cmp_ok($uid, '==', 0, 'root has correct uid'); -$uid = Simba::CA::name2uid('bin'); +$uid = $ca->name2uid('bin'); ok(defined($uid), 'bin has uid'); my $bin_uid; { @@ -27,7 +27,7 @@ my $bin_uid; } cmp_ok($uid, '==', $bin_uid, 'bin has correct uid'); -$uid = Simba::CA::name2uid('daemon'); +$uid = $ca->name2uid('daemon'); ok(defined($uid), 'daemon has uid'); my $daemon_uid; { @@ -40,15 +40,15 @@ my $daemon_uid; } cmp_ok($uid, '==', $daemon_uid, 'daemon has correct uid'); -$uid = Simba::CA::name2uid('4711'); +$uid = $ca->name2uid('4711'); ok(defined($uid), 'numerical "user name" has uid'); cmp_ok($uid, '==', 4711, 'numerical "user name" has correct uid'); -$uid = Simba::CA::name2uid('i.am.quite.sure.that.this.is.not.a.real.username'); +$uid = $ca->name2uid('i.am.quite.sure.that.this.is.not.a.real.username'); ok(defined($uid), 'unknown user has uid'); -cmp_ok($uid, '==', -2, 'unknown user has correct uid'); +cmp_ok($uid, '==', $ca->{unknown_uid}, 'unknown user has correct uid'); -my $gid = Simba::CA::name2gid('adm'); +my $gid = $ca->name2gid('adm'); ok(defined($gid), 'adm has gid'); my $adm_gid; { @@ -61,3 +61,23 @@ my $adm_gid; } cmp_ok($gid, '==', $adm_gid, 'adm has correct gid'); +SKIP: { + skip "not running as root", 1 unless $> == 0; + mkdir "t/backup"; + mkdir "t/backup/1"; + open my $fh, '>:raw', 't/backup/1/t1'; + print $fh "test\n"; + close($fh); + chown($ca->{unknown_uid}, $ca->{unknown_gid}, 't/backup/1/t1'); + chmod(0644, 't/backup/1/t1'); + my $f = { + name => 't1', + m => time(), + s => 5, + o => $ca->{unknown_uid}, + g => $ca->{unknown_gid}, + acl => 'u::rw-,g::r--,o:r--', + }; + $ca->{last_backup} = 't/backup/1'; + ok($ca->present($f), "file with unknown owner is present"); +}