initial commit of file from CVS for e-smith-ldap on Wed 12 Jul 08:58:23 BST 2023
This commit is contained in:
248
root/etc/e-smith/events/actions/ldap-update-simple
Normal file
248
root/etc/e-smith/events/actions/ldap-update-simple
Normal file
@@ -0,0 +1,248 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
package esmith;
|
||||
|
||||
use strict;
|
||||
use Errno;
|
||||
use esmith::ConfigDB;
|
||||
use esmith::AccountsDB;
|
||||
use esmith::util;
|
||||
use Net::LDAP;
|
||||
use Date::Parse;
|
||||
|
||||
$ENV{'LANG'} = 'C';
|
||||
$ENV{'TZ'} = '';
|
||||
|
||||
my $c = esmith::ConfigDB->open_ro;
|
||||
my $a = esmith::AccountsDB->open_ro;
|
||||
|
||||
my $l = $c->get('ldap');
|
||||
my $status = $l->prop('status') || "disabled";
|
||||
unless ($status eq "enabled" )
|
||||
{
|
||||
warn "Not running action script $0, LDAP service not enabled!\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
exit(0) if ($c->get('ldap')->prop('Authentication') || 'disabled') eq 'enabled';
|
||||
|
||||
my $domain = $c->get('DomainName')
|
||||
|| die("Couldn't determine domain name");
|
||||
$domain = $domain->value;
|
||||
|
||||
my $schema = '/etc/openldap/schema/samba.schema';
|
||||
|
||||
my $event = shift || die "Event name must be specified";
|
||||
|
||||
my @name = @ARGV;
|
||||
die "Account name argument missing." unless scalar (@name) >= 1;
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Update LDAP database entry.
|
||||
#------------------------------------------------------------
|
||||
my $base = esmith::util::ldapBase ($domain);
|
||||
my $pw = esmith::util::LdapPassword();
|
||||
|
||||
my $ldap = Net::LDAP->new('localhost')
|
||||
or die "$@";
|
||||
|
||||
$ldap->bind(
|
||||
dn => "cn=root,$base",
|
||||
password => $pw
|
||||
);
|
||||
|
||||
my @accounts;
|
||||
my $account;
|
||||
foreach my $name (@name)
|
||||
{
|
||||
$account = $a->get($name);
|
||||
die "Account $name not found.\n" unless defined $account;
|
||||
my $type = $account->prop('type') || "unknown";
|
||||
|
||||
die "Account $name is not a user, group, ibay, machine account; update LDAP entry failed.\n"
|
||||
unless ($type =~ m{^(?:user|group|ibay|machine)$} or $name eq 'admin');
|
||||
|
||||
push @accounts, $account;
|
||||
}
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Read all samba groups (can't do individual lookups)
|
||||
#------------------------------------------------------------
|
||||
|
||||
my $groupmap = ();
|
||||
|
||||
# Only do if schema is found
|
||||
if ( -f "$schema" and -x '/usr/bin/net' )
|
||||
{
|
||||
foreach (`/usr/bin/net groupmap list 2> /dev/null`){
|
||||
chomp;
|
||||
next if m{\(S-1-5-32-\d+\)};
|
||||
$groupmap->{$3} = { name => "$1", sid => "$2" } if (/^(.*) \((S-.*-\d+)\) -> (.*)$/);
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Create a list of updates that need to happen
|
||||
#------------------------------------------------------------
|
||||
|
||||
my $updates;
|
||||
foreach my $acct (@accounts)
|
||||
{
|
||||
my $key = $acct->key;
|
||||
my $type = $acct->prop('type');
|
||||
my $desc = undef;
|
||||
my $dn;
|
||||
|
||||
if ($type =~ m{^(?:user|group|ibay|machine)$} or $key eq 'admin')
|
||||
{
|
||||
#------------------------------------------------------------
|
||||
# Do the user portion
|
||||
#------------------------------------------------------------
|
||||
if ($type eq 'machine')
|
||||
{
|
||||
$dn = "uid=$key,ou=Computers,$base";
|
||||
}
|
||||
else
|
||||
{
|
||||
$dn = "uid=$key,ou=Users,$base";
|
||||
}
|
||||
utf8::upgrade($dn);
|
||||
|
||||
# Read information from getent passwd
|
||||
@{$updates->{$dn}}{'uid','userPassword'} = getpwnam($key);
|
||||
unless ($updates->{$dn}->{uid})
|
||||
{
|
||||
delete $updates->{$dn};
|
||||
next;
|
||||
}
|
||||
$updates->{$dn}->{userPassword} = "!*" if $updates->{$dn}->{userPassword} eq '!!';
|
||||
$updates->{$dn}->{userPassword} =~ s/^/{CRYPT}/ unless $updates->{$dn}->{userPassword} =~ m/^{/;
|
||||
|
||||
# Samba parameters if we find the samba.schema
|
||||
if ( -f "$schema" and -x '/usr/bin/pdbedit' )
|
||||
{
|
||||
my $line = `/usr/bin/pdbedit -wu '$key' 2> /dev/null`;
|
||||
chomp($line);
|
||||
if ($line)
|
||||
{
|
||||
@{$updates->{$dn}}{'junk','junk','sambaLMPassword','sambaNTPassword'} = split(/:/,$line);
|
||||
foreach $line (`/usr/bin/pdbedit -vu '$key' 2> /dev/null`)
|
||||
{
|
||||
chomp($line);
|
||||
$updates->{$dn}->{sambaSID} = $1 if $line =~ m{User SID:\s+(S-.*)$};
|
||||
$updates->{$dn}->{displayName} = $1 if $line =~ m{Full Name:\s+(.*)$};
|
||||
$updates->{$dn}->{sambaPrimaryGroupSID} = $1 if $line =~ m{Primary Group SID:\s+(S-.*)$};
|
||||
$updates->{$dn}->{sambaAcctFlags} = $1 if $line =~ m{Account Flags:\s+(.*)$};
|
||||
$updates->{$dn}->{sambaPwdLastSet} = str2time($1) if $line =~ m{Password last set:\s+(.*)$};
|
||||
}
|
||||
push @{$updates->{$dn}->{objectClass}}, 'sambaSamAccount';
|
||||
}
|
||||
else
|
||||
{
|
||||
$updates->{$dn}->{sambaLMPassword} = [];
|
||||
$updates->{$dn}->{sambaNTPassword} = [];
|
||||
$updates->{$dn}->{sambaSID} = [];
|
||||
$updates->{$dn}->{displayName} = [];
|
||||
$updates->{$dn}->{sambaPrimaryGroupSID} = [];
|
||||
$updates->{$dn}->{sambaAcctFlags} = [];
|
||||
$updates->{$dn}->{sambaPwdLastSet} = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
endpwent();
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Do the group portion (only if we have samba)
|
||||
#------------------------------------------------------------
|
||||
if ( -f "$schema" )
|
||||
{
|
||||
foreach my $group ( (map { $_->key } $a->users), (map { $_->key } $a->groups), qw/admin nobody shared/ ){
|
||||
my $dn = "cn=$group,ou=Groups,$base";
|
||||
utf8::upgrade($dn);
|
||||
|
||||
if ( exists $groupmap->{$group} )
|
||||
{
|
||||
push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping';
|
||||
$updates->{$dn}->{displayName} = $groupmap->{$group}->{name};
|
||||
$updates->{$dn}->{sambaSID} = $groupmap->{$group}->{sid};
|
||||
$updates->{$dn}->{sambaGroupType} = '2';
|
||||
}
|
||||
else
|
||||
{
|
||||
$updates->{$dn}->{displayName} = [];
|
||||
$updates->{$dn}->{sambaSID} = [];
|
||||
$updates->{$dn}->{sambaGroupType} = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Update LDAP database entry.
|
||||
#------------------------------------------------------------
|
||||
foreach my $dn (keys %$updates)
|
||||
{
|
||||
# Try and find record
|
||||
my $result = $ldap->search( base => $dn, filter => '(objectClass=*)', scope => 'base' );
|
||||
warn "failed looking up entry $dn: ", $result->error if $result->code && $result->code != 32;
|
||||
my $code = $result->code;
|
||||
my @objectClass = $code == 32 ? () : $result->entry(0)->get_value('objectClass');
|
||||
|
||||
# Clean up attributes and convert to utf8
|
||||
delete $updates->{$dn}->{'junk'};
|
||||
foreach my $attr ( keys %{$updates->{$dn}} )
|
||||
{
|
||||
if ( ref($updates->{$dn}->{$attr}) eq 'ARRAY' )
|
||||
{
|
||||
if ( $code == 32 and scalar(@{$updates->{$dn}->{$attr}}) == 0 )
|
||||
{
|
||||
delete $updates->{$dn}->{$attr};
|
||||
}
|
||||
else
|
||||
{
|
||||
for (my $c = 0; $c < scalar(@{$updates->{$dn}->{$attr}}); $c++)
|
||||
{
|
||||
utf8::upgrade($updates->{$dn}->{$attr}[$c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($updates->{$dn}->{$attr} !~ /^\s*$/)
|
||||
{
|
||||
utf8::upgrade($updates->{$dn}->{$attr});
|
||||
}
|
||||
elsif ( $code == 32 )
|
||||
{
|
||||
delete $updates->{$dn}->{$attr};
|
||||
}
|
||||
else
|
||||
{
|
||||
$updates->{$dn}->{$attr} = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Perform insert or update
|
||||
if ( $code == 32 )
|
||||
{
|
||||
$result = $ldap->add( $dn, attrs => [ %{$updates->{$dn}} ] );
|
||||
$result->code && warn "failed to add entry $dn: ", $result->error;
|
||||
}
|
||||
else
|
||||
{
|
||||
# Don't overwrite objectClass (just update if necessary)
|
||||
my $seen = ();
|
||||
|
||||
# Remove samba objectClasses if removing samba attributes
|
||||
@{$seen}{'sambaSamAccount','sambaGroupMapping'} = (1,1) if ref($updates->{$dn}->{sambaSID}) eq 'ARRAY';
|
||||
|
||||
@{$updates->{$dn}->{objectClass}} = grep { ! $seen->{$_}++ } (@{$updates->{$dn}->{objectClass}}, @objectClass );
|
||||
|
||||
$result = $ldap->modify( $dn, replace => $updates->{$dn});
|
||||
$result->code && warn "failed to modify entry $dn: ", $result->error;
|
||||
}
|
||||
}
|
||||
$ldap->unbind;
|
||||
|
||||
exit (0);
|
Reference in New Issue
Block a user