123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- #!/usr/bin/perl
- # A Perl wrapper for setquota utility which updates LDAP accordingly.
- # /etc/fstab: usrquota,grpquota
- # mount -o remount /f/s
- # touch /f/s/aquota.{user,group}
- # chmod 600 /f/s/aquota.{user,group}
- # quotacheck -cguvamf
- use strict;
- use warnings;
- use Net::LDAP;
- use Net::LDAP::Entry;
- use Getopt::Long;
- Getopt::Long::Configure ("bundling");
- my $help = $#ARGV >= 0 ? 0 : 1;
- my $ldaphost = 'localhost';
- my $passwordfile = '';
- my $password = '';
- my $binddn = $ENV{BINDDN};
- my $basedn = $ENV{BASEDN};
- my $oc = 'systemQuotas';
- my $attr = 'quota';
- my %Q = ();
- my $F = 'cn=*';
- GetOptions(
- 'help|?' => \$help,
- 'oc|o=s' => \$oc,
- 'attr|a=s' => \$attr,
- 'quota|Q=s' => \%Q,
- 'filter|F=s' => \$F,
- 'ldaphost|h=s' => \$ldaphost,
- 'basedn|b=s' => \$basedn,
- 'binddn|D=s' => \$binddn,
- 'password|w=s' => \$password,
- 'passwordfile|W=s' => \$passwordfile,
- );
- die "Usage: $0 -b basedn [-o objectClass] [-a attr] [-F '(extrafilter)'] [-Q
- /f/s=sb:hb:gb:sf:hf:gf ...]\n" if $help;
- %Q = checkQ(%Q);
- my ($ldap, $bind);
- if ( $ldap = Net::LDAP->new($ldaphost, version => 3, timeout => 3) ) {
- if ( $binddn && $password ) {
- $bind = $ldap->bind($binddn, password=>$password);
- } elsif ( $binddn && $passwordfile ){
- $bind = $ldap->bind($binddn, password=>bindpw($passwordfile));
- } else {
- $bind = $ldap->bind();
- }
- die "Unable to connect to LDAP\n" if $bind->code;
- undef $passwordfile;
- } else {
- die "Unable to connect to LDAP\n";
- }
- my $search = $ARGV[0] ? $ldap->search(base=>$basedn, filter=>"uid=$ARGV[0]") : $ldap->search(base=>$basedn, filter=>$F);
- if ( $search->code ) {
- die "LDAP Error: ", error($search), "\n";
- } elsif ( $search->count <= 0 ) {
- die "0 results found in LDAP\n";
- } else {
- my $i = 0;
- for ( $i=0; $i<$search->count; $i++ ) {
- my $entry = $search->entry($i);
- my @oc = $entry->get_value('objectClass');
- # objectClass: $oc
- unless ( grep { /^$oc$/ } @oc ) {
- my $modify = $ldap->modify($entry->dn, add => {objectClass => $oc});
- if ( $modify->code ) {
- print STDERR "Failed to add objectClass $oc:", error($modify), "\n";
- }
- }
- # $attr: /f/s=sb:hb:sf:hf
- if ( $entry->exists($attr) ) {
- my @attr = $entry->get_value($attr);
- if ( keys %Q ) {
- foreach my $fs ( keys %Q ) {
- foreach ( @attr ) {
- next unless /^$fs=/;
- my $modify = $ldap->modify($entry->dn, delete => {$attr => "$_"});
- if ( $modify->code ) {
- print STDERR "Failed to delete $attr: $_: ", error($modify), "\n";
- }
- }
- my $modify = $ldap->modify($entry->dn, add => {$attr => "$fs=$Q{$fs}"});
- if ( $modify->code ) {
- print STDERR "Failed to add $attr: $fs=$Q{$fs}: ", error($modify), "\n";
- } else {
- print STDERR "Failed to setquota: $fs=$Q{$fs}\n" if setquota($entry->get_value('uid'), $fs, $Q{$fs});
- }
- }
- } else {
- my $modify = $ldap->modify($entry->dn, delete => [($attr)]);
- if ( $modify->code ) {
- print STDERR "Failed to delete $attr: ", error($modify), "\n";
- } else {
- foreach ( @attr ) {
- my ($fs) = m!^(/[^=]*)!;
- $Q{$fs} = '0:0:0:0:0:0';
- print STDERR "Failed to setquota: $fs=$Q{$fs}\n" if setquota($entry->get_value('uid'), $fs, $Q{$fs});
- }
- }
- }
- } else {
- if ( keys %Q ) {
- foreach my $fs ( keys %Q ) {
- my $modify = $ldap->modify($entry->dn, add => {$attr => "$fs=$Q{$fs}"});
- if ( $modify->code ) {
- print STDERR "Failed to add $attr: $fs=$Q{$fs}: ", error($modify), "\n";
- } else {
- print STDERR "Failed to setquota: $fs=$Q{$fs}\n" if setquota($entry->get_value('uid'), $fs, $Q{$fs});
- }
- }
- }
- }
- }
- }
- sub setquota {
- $_[2] = '0:0:0:0:0:0' unless $_[2];
- $_[2] =~ /^(\d+):(\d+):(\d+):(\d+):(\d+):(\d+)$/;
- qx{/usr/sbin/setquota -u $_[0] $1 $2 $4 $5 $_[1]};
- qx{/usr/sbin/setquota -T -u $_[0] $3 $6 $_[1]};
- return 0;
- }
- sub checkQ {
- my (%Q) = @_;
- foreach ( keys %Q ) {
- die "$_: invalid format\n" unless m!^(/[^=]*)! && $Q{$_} =~ /^(\d+):(\d+):(\d+):(\d+):(\d+):(\d+)$/;
- }
- return %Q;
- }
- sub bindpw {
- my ($passwordfile) = @_;
- open P, $passwordfile or die "Can't open passwordfile: $!";
- chomp(my $password = <P>);
- close P;
- return $password;
- }
- sub error {
- return $_[0]->error, "(", $_[0]->code, ")";
- }
|