check
changeset 0 b30cade45ad7
child 1 1ea5da2535d7
equal deleted inserted replaced
-1:000000000000 0:b30cade45ad7
       
     1 #! /usr/bin/perl
       
     2 
       
     3 use 5.010;
       
     4 use strict;
       
     5 use warnings;
       
     6 use POSIX;
       
     7 use File::Spec::Functions;
       
     8 use Data::Dumper;
       
     9 use File::Find;
       
    10 use Carp;
       
    11 
       
    12 sub su;
       
    13 sub find_tool;
       
    14 sub check_perms;
       
    15 sub config_names;
       
    16 sub get_devices;
       
    17 sub amcheck;
       
    18 sub amlist;
       
    19 
       
    20 # test needs to be run as root:* or as backup:backup
       
    21 my $USER = 'backup';
       
    22 my $CFDIR = '/etc/amanda';
       
    23 
       
    24 # change to backup if still root
       
    25 su $USER if $> == 0;
       
    26 
       
    27 # amservice needs to be suid root, but executable
       
    28 # by the backup user/group
       
    29 check_perms find_tool('amservice'), 04750, 'root', $);
       
    30 
       
    31 # find the backup sets we know about
       
    32 # here we suppose that it's possible to find strings like
       
    33 # 'conf "foo"' in files named 'amanda-client.conf' below /etc/amanda
       
    34 
       
    35 my @confs = config_names $CFDIR
       
    36 	or die "no amanda backup sets found (did: find $CFDIR -name amanda-client.conf)\n";
       
    37 
       
    38 #eval { amcheck $_ } or die $@
       
    39 #		foreach @confs;
       
    40 
       
    41 my @devs = get_devices;
       
    42 foreach (@confs) {
       
    43 	my @dles = amlist $_;
       
    44 	warn Dumper \@dles;
       
    45 	warn Dumper \@devs;
       
    46 }
       
    47 
       
    48 exit;
       
    49 #---
       
    50 
       
    51 # compare the file systems
       
    52 # get a list of file system
       
    53 sub get_devices {
       
    54 	open(my $fh, '/proc/filesystems');
       
    55 	my @types = map { /^\s+(\S+)/ ? $1 : () } <$fh>;
       
    56 	my @df = (df => '-P', map { -t => $_ } @types);
       
    57 	map { [$_, (stat)[0]] } map { (split ' ', $_)[5] } grep { /^\// } `@df`;
       
    58 }
       
    59 
       
    60 sub su {
       
    61 	my $user = shift;
       
    62 	my $group = (getgrnam $user)[0];
       
    63 	my $uid = getpwnam $user;
       
    64 	my $gid = getgrnam $group;
       
    65 
       
    66 	my @groups;
       
    67 	
       
    68 	setgrent;
       
    69 	my @rc;
       
    70 	while (my @g = getgrent) {
       
    71 		 push @groups, $g[2] if $USER ~~ [split ' ', $g[3]];
       
    72 	}
       
    73 	endgrent;
       
    74 	$) = "@groups";
       
    75 	setgid $gid;
       
    76 	setuid $uid;
       
    77 }
       
    78 
       
    79 sub find_tool {
       
    80 	my $name = shift;
       
    81 	my @rc = grep { -f -x } map { catfile $_, $name } split /:/, $ENV{PATH}
       
    82 		or croak "Can't find `$name' in $ENV{PATH}\n";
       
    83 	$rc[0];
       
    84 };
       
    85 
       
    86 sub check_perms {
       
    87 	my ($file, $mode, $owner, $group) = @_;
       
    88 
       
    89 	$owner = getpwuid $owner if $owner ~~ /^\d+$/;
       
    90 	
       
    91 	$group = getgrgid +(split ' ', $group)[0]
       
    92 		if $group ~~ /^[\d\s]+$/;
       
    93 
       
    94 	stat $file or croak "Can't stat `$file': $!\n";
       
    95 
       
    96 	eval {
       
    97 		my $f_owner = getpwuid +(stat _)[4] or die $!;
       
    98 		my $f_group = getgrgid +(stat _)[5] or die $!;
       
    99 		my $f_mode = (stat _)[2] & 07777 or die $!;
       
   100 
       
   101 		my $msg = sprintf "need: 0%04o root:$group, got: 0%04o $f_owner:$f_group\n", 
       
   102 			$mode, $f_mode;
       
   103 
       
   104 		die $msg unless $f_owner eq $owner;
       
   105 		die $msg unless $f_group eq $group;
       
   106 		die $msg unless $f_mode == $mode;
       
   107 	};
       
   108 	croak "wrong permissions for `$file', $@" if $@;
       
   109 }
       
   110 
       
   111 
       
   112 sub config_names {
       
   113 	my $dir = shift;
       
   114 	my @configs = ();
       
   115 	find(sub {
       
   116 		-f and /^amanda-client\.conf$/ or return;
       
   117 		open(my $fh, '<', $_) or die "Can't open  $File::Find::name: $!\n";
       
   118 		push @configs, map { /^conf\s+"(.+?)"/ ? $1 : () } <$fh>;
       
   119 	}, $dir);
       
   120 	return @configs;
       
   121 };
       
   122 
       
   123 sub amcheck {
       
   124 	my $conf = shift;
       
   125 	my @errors = map { "$conf: $_" } grep { /^error/i } qx(amdump_client --config '$conf' check 2>&1);
       
   126 	die @errors if @errors;
       
   127 	return 1;
       
   128 }
       
   129 
       
   130 sub amlist {
       
   131 	my $conf = shift;
       
   132 	chomp((undef, my @dles) = qx(amdump_client --config '$conf' list));
       
   133 	return map { [$_, (stat $_)[0] ] } @dles;
       
   134 }
       
   135 
       
   136 __END__
       
   137 system amdump_client => '--config', 'daily', 'list';