X-Git-Url: https://git.sesse.net/?p=itkacl;a=blobdiff_plain;f=itkacl-2.1%2Fsync-itkacl.pl;h=d8e49c9318359c474d15b0431354b53479f3f9e3;hp=868ee0f5b051ae9fb2c20dee6ea293138647bc1e;hb=refs%2Fheads%2Fmaster;hpb=abd4d9e935d576dc3cd8b2a1d18bcf0451f03c2c diff --git a/itkacl-2.1/sync-itkacl.pl b/itkacl-2.1/sync-itkacl.pl deleted file mode 100755 index 868ee0f..0000000 --- a/itkacl-2.1/sync-itkacl.pl +++ /dev/null @@ -1,179 +0,0 @@ -#! /usr/bin/perl -use strict; -use warnings; -no warnings qw(once); -use DBI; -use AppConfig; -use lib qw(. /etc/itkacl); -require 'config.pm'; - -my $conf = AppConfig->new(); -$conf->define('force!'); -$conf->getopt(\@ARGV); - -exit 0 if (!should_run()); - -my $dbh = DBI->connect("dbi:Pg:" . - "dbname=" . $itkaclsyncconfig::db_name . ";" . - "host= " . $itkaclsyncconfig::db_host, - $itkaclsyncconfig::db_user, - $itkaclsyncconfig::db_pass) -or die "Couldn't connect to database: " . DBI::errstr(); -$dbh->{RaiseError} = 1; - -# Fetch members of all groups. -my %members = (); -while (my ($name,$passwd,$gid,$members) = getgrent()) { - push @{$members{$name}}, ( split /\s+/, $members ); -} - -my %access = (); -while (my ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell,$expire) = getpwent()) { - # No system users, except those that are explicitly included - next if ($uid < $itkaclsyncconfig::minimum_uid && (grep { $name eq $_ } (@itkaclsyncconfig::force_include_users)) == 0); - - # No Samba machine accounts - next if $name =~ /\$$/; - - # Initially, nobody has access. - $access{$name} = 0; - - # The user is implicitly a member in his/her primary group. - my ($grnam) = getgrgid($gid); - if (defined($grnam)) { - push @{$members{$grnam}}, $name; - } else { - warn "User $name has unknown gid $gid"; - } - - # Everybody is a member of the "" group. - push @{$members{''}}, $name; -} - -my %entries = (); -dump_recursively($itkaclsyncconfig::dns_zone . ".", undef, \%access, \%entries); - -do { } while (update_zone() == 0); - -# Don't run again before we've got updates -utime(time(), time(), $itkaclsyncconfig::last_sync_file); - -sub update_zone { - # Dump the zone in its current form. - my %current_entries = (); - open ZONE, "dig +nocmd +nostats +nocomments -t axfr $itkaclsyncconfig::dns_zone. \@$itkaclsyncconfig::dns_server |" - or die "dig failed: $!"; - while () { - chomp; - /( .*? \Q$itkaclsyncconfig::dns_zone\E \. ) \s+ 10 \s+ IN \s+ A \s+ 127\.0\.0\.1 \s* $/x or next; - $current_entries{$1} = 1; - - } - close ZONE; - - if ($? != 0) { - die "dig failed with \$\? = $?"; - } - if (scalar keys %current_entries < 1) { - die "No entries in zone, transfer probably failed."; - } - - # Call nsupdate to update DNS. - # Note: We limit ourselves to 1000 records at a time due to nsupdate limitations. - # If we hit the limit, we'll return 0 to signal that we should try again. - my $num_lines = 0; - - open NSUPDATE, "| nsupdate -y $itkaclsyncconfig::dns_key" - or die "nsupdate failed: $!"; - print NSUPDATE "zone $itkaclsyncconfig::dns_zone.\n"; - print NSUPDATE "server $itkaclsyncconfig::dns_server\n"; - - for my $entry (keys %entries) { - next if (exists($current_entries{$entry})); - last if (++$num_lines == $itkaclsyncconfig::max_updates_per_transaction); - print NSUPDATE "update add $entry 10 A 127.0.0.1\n"; - } - for my $entry (keys %current_entries) { - next if (exists($entries{$entry})); - last if (++$num_lines == $itkaclsyncconfig::max_updates_per_transaction); - print NSUPDATE "update delete $entry\n"; - } - print NSUPDATE "send\n"; - close NSUPDATE; - - print "Made $num_lines updates.\n"; - if ($num_lines >= $itkaclsyncconfig::max_updates_per_transaction) { - print "Note: Hit limit of $itkaclsyncconfig::max_updates_per_transaction updates, will continue in a separate transaction.\n"; - return 0; - } - return 1; -} - -sub dump_recursively { - my ($path, $id, $allowed, $entries) = @_; - - if (defined($id)) { - # Find all changes to the access tree at this level in the tree. - my $q = $dbh->prepare('SELECT entity_type,entity,allow FROM aclentries WHERE object=? ORDER BY entity_type ASC, allow DESC'); - $q->execute($id); - - while (my $ref = $q->fetchrow_hashref) { - my $entity_type = $ref->{'entity_type'}; - my $entity = $ref->{'entity'}; - my $allow = ($ref->{'allow'} eq 'grant'); - - if ($entity_type eq 'user') { - if (!exists($allowed->{$entity})) { - warn "$path has an ACL entry for non-existant user $entity"; - } else { - $allowed->{$entity} = $allow; - } - } elsif ($entity_type eq 'group') { - if (!exists($members{$entity})) { - warn "$path has an ACL entry for non-existant group $entity"; - } else { - for my $member (@{$members{$entity}}) { - $allowed->{$member} = $allow; - } - } - } - } - } - - # Output everyone who has access to this path. - for my $user (keys %$allowed) { - next if (!$allowed->{$user}); - $entries->{"$user.$path"} = 1; - } - - # Now, find all children. - my $q; - if (defined($id)) { - $q = $dbh->prepare('SELECT id,name FROM objects WHERE parent=?'); - $q->execute($id); - } else { - $q = $dbh->prepare('SELECT id,name FROM objects WHERE parent IS NULL'); - $q->execute; - } - - while (my $ref = $q->fetchrow_hashref) { - my %allowed_copy = %$allowed; - dump_recursively($ref->{'name'} . "." . $path, $ref->{'id'}, \%allowed_copy, $entries); - } -} - -# Check if we have updates since last run (or if we're forced) -sub should_run { - return 1 if ($conf->force); - my $last_update = (stat($itkaclsyncconfig::updated_file))[10] or die "Can't get mtime for $itkaclsyncconfig::updated_file"; - my $last_sync = (stat($itkaclsyncconfig::last_sync_file))[10] or die "Can't get mtime for $itkaclsyncconfig::last_sync_file"; - my $last_group = (stat('/etc/group'))[10] or die "Can't get mtime for /etc/group"; - my $last_group_db = (stat('/var/lib/misc/group.db'))[10] or die "Can't get mtime for /etc/group"; - my $last_passwd = (stat('/etc/passwd'))[10] or die "Can't get mtime for /etc/passwd"; - return 1 if ($last_sync - 10 < $last_update); - return 1 if ($last_sync - 10 < $last_group); - return 1 if ($last_sync - 10 < $last_group_db); - return 1 if ($last_sync - 10 < $last_passwd); - - return 0; -}