diff -Nur -x '*.orig' -x '*.rej' e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update mezzanine_patched_e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update --- e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update 2010-12-01 17:14:14.000000000 +0100 +++ mezzanine_patched_e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update 2010-12-01 17:13:56.000000000 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/bin/bash #---------------------------------------------------------------------- # copyright (C) 1999, 2000 e-smith, inc. @@ -22,456 +22,5 @@ # call us on 1 888 ESMITH 1 (US/Canada toll free) or +1 613 564 8000 #---------------------------------------------------------------------- -package esmith; +/usr/bin/perl /var/service/ldap/convert_ldif --update -use strict; -use Errno; -use esmith::ConfigDB; -use esmith::AccountsDB; -use esmith::util; -use Net::LDAP; -use Date::Parse; - -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); -} - -my $hostname = $c->get('SystemName') - || die("Couldn't determine system name"); -$hostname = $hostname->value; - -my $domain = $c->get('DomainName') - || die("Couldn't determine domain name"); -$domain = $domain->value; - -my $schema = '/etc/openldap/schema/samba.schema'; -my $map = { 'FirstName' => 'givenName', - 'LastName' => 'sn', - 'Phone' => 'telephoneNumber', - 'Company' => 'o', - 'Dept' => 'ou', - 'City' => 'l', - 'Street' => 'street', - }; - -my @accounts; -my $account; -my $event = shift || die "Event name must be specified"; -if ($event eq 'ldap-update' or $event eq 'bootstrap-ldap-save') -{ - @accounts = ($a->users, $a->groups, $a->ibays, $a->get_all_by_prop(type => 'machine')); - push(@accounts, $a->get('admin')); -} -else -{ - my @name = @ARGV; - die "Account name argument missing." unless scalar (@name) >= 1; - - 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+)\) -> (.*)$/); - } -} - -#------------------------------------------------------------ -# 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 ($dc,undef) = split (/\./, $domain); -my $o = $l->prop('defaultCompany') || $domain; - -# Try and find base record -my $seen; -my @objects = qw(top organization dcObject); -my $result = $ldap->search( base => $base, filter => '(objectClass=*)', scope => 'base' ); -if ($result->code == 32) -{ - $result = $ldap->add( $base, attr => [ dc => $dc, o => $o, objectClass => \@objects ] ); -} -elsif ($result->code) -{ - warn "failed checking base entry $base: ", $result->error; -} -else -{ - # Don't overwrite objectClass (just update if necessary) - $seen = (); - @objects = grep { ! $seen->{$_} ++ } (@objects, $result->entry(0)->get_value('objectClass') ); - $ldap->modify( $base, replace => { dc => $dc, o => $o, objectClass => \@objects } ); -} -warn "failed to add/update entry $base: ", $result->error if $result->code; - -# Try and find container records -foreach my $obj ( qw(Users Groups Computers) ) -{ - @objects = qw(top organizationalUnit); - $result = $ldap->search( base => "ou=$obj,$base", filter => '(objectClass=*)', scope => 'base' ); - if ($result->code == 32) - { - $result = $ldap->add( "ou=$obj,$base", attr => [ ou => $obj, objectClass => \@objects ] ); - } - elsif ($result->code) - { - warn "failed checking base entry ou=$obj,$base: ", $result->error; - } - else - { - # Don't overwrite objectClass (just update if necessary) - $seen = (); - @objects = grep { ! $seen->{$_} ++ } (@objects, $result->entry(0)->get_value('objectClass') ); - $result = $ldap->modify( "ou=$obj,$base", replace => { ou => $obj, objectClass => \@objects } ); - } - warn "failed to add/update entry ou=$obj,$base: ", $result->error if $result->code; -} - -my $updates; - -#------------------------------------------------------------ -# Ensure nobody, shared, www objects are there -#------------------------------------------------------------ -foreach my $user (qw/www/){ - my $dn = "uid=$user,ou=Users,$base"; - utf8::upgrade($dn); - $updates->{$dn}->{objectClass} = ['account', 'posixAccount', 'shadowAccount']; - - # Read information from getent passwd - @{$updates->{$dn}}{'uid','userPassword','uidNumber','gidNumber','junk','junk','gecos','homeDirectory','loginShell'} = getpwnam($user); - $updates->{$dn}->{userPassword} = "!*" if $updates->{$dn}->{userPassword} eq '!!'; - $updates->{$dn}->{userPassword} =~ s/^/{CRYPT}/ unless $updates->{$dn}->{userPassword} =~ m/^{/; - $updates->{$dn}->{cn} = $updates->{$dn}->{gecos}; - - # Samba parameters if we find the samba.schema - if ( -f "$schema" and -x '/usr/bin/pdbedit' ) - { - my $line = `/usr/bin/pdbedit -wu '$user' 2> /dev/null`; - chomp($line); - if ($line) - { - @{$updates->{$dn}}{'junk','junk','sambaLMPassword','sambaNTPassword'} = split(/:/,$line); - foreach $line (`/usr/bin/pdbedit -vu '$user' 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(); - -foreach my $group (qw/nobody shared www/){ - my $dn = "cn=$group,ou=Groups,$base"; - utf8::upgrade($dn); - $updates->{$dn}->{objectClass} = ['posixGroup']; - - # Read information from getent group - @{$updates->{$dn}}{'cn','junk','gidNumber','memberUid'} = getgrnam($group); - $updates->{$dn}->{memberUid} = [ split /\s+/, $updates->{$dn}->{memberUid} ]; - - # Ensure groups have the needed properties - if ($group eq 'shared'){ - push @{$updates->{$dn}->{objectClass}}, 'mailboxRelatedObject'; - $updates->{$dn}->{mail} = "everyone\@$domain"; - } - - # Samba parameters if we find the samba.schema - if ( -f "$schema" ) - { - 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} = []; - } - } -} -endgrent(); - -#------------------------------------------------------------ -# Create a list of updates that need to happen -#------------------------------------------------------------ -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); - $updates->{$dn}->{objectClass} = ['posixAccount', 'shadowAccount']; - - # Read information from getent passwd - @{$updates->{$dn}}{'uid','userPassword','uidNumber','gidNumber','junk','junk','gecos','homeDirectory','loginShell'} = 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/^{/; - $desc = $updates->{$dn}->{cn} = $updates->{$dn}->{gecos}; - - # Load values from db record - foreach my $attr ( keys %$map ) - { - my $val = $acct->prop($attr); - $updates->{$dn}->{$map->{$attr}} = $val if defined $val; - } - - # Ensure users have the needed properties - if ($type eq 'user' or $key eq 'admin') - { - push @{$updates->{$dn}->{objectClass}}, 'inetOrgPerson'; - $updates->{$dn}->{mail} = "$key\@$domain"; - } - else - { - push @{$updates->{$dn}->{objectClass}}, 'account'; - } - - # 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} = []; - } - } - - #------------------------------------------------------------ - # Do the group portion - #------------------------------------------------------------ - $dn = "cn=$key,ou=Groups,$base"; - utf8::upgrade($dn); - $updates->{$dn}->{objectClass} = ['posixGroup']; - - # Read information from getent group - @{$updates->{$dn}}{'cn','junk','gidNumber','memberUid'} = getgrnam($key); - $updates->{$dn}->{memberUid} = [ split /\s+/, $updates->{$dn}->{memberUid} ]; - - # Ensure groups have the needed properties - if ($type eq 'group') - { - push @{$updates->{$dn}->{objectClass}}, 'mailboxRelatedObject'; - $updates->{$dn}->{mail} = "$key\@$domain"; - $updates->{$dn}->{description} = $desc if $desc; - } - - # Samba parameters if we find the samba.schema - if ( -f "$schema" ) - { - if ( exists $groupmap->{$key} ) - { - push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping'; - $updates->{$dn}->{displayName} = $groupmap->{$key}->{name}; - $updates->{$dn}->{sambaSID} = $groupmap->{$key}->{sid}; - $updates->{$dn}->{sambaGroupType} = '2'; - } - else - { - $updates->{$dn}->{displayName} = []; - $updates->{$dn}->{sambaSID} = []; - $updates->{$dn}->{sambaGroupType} = []; - } - } - } -} -endpwent(); -endgrent(); - -#------------------------------------------------------------ -# Update LDAP database entry. -#------------------------------------------------------------ -foreach my $dn (keys %$updates) -{ - # Try and find record - $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} = []; - } - } - } - - # Try and find old record (sme7) - my ($oldfilter, undef, $oldsearchbase) = split /,/, $dn, 3; - my $oldresult = $ldap->search( base => "$oldfilter,$oldsearchbase", filter => '(objectClass=*)', scope => 'base' ); - if ($oldresult->code) - { - warn "failed looking up old entry $oldfilter,$oldsearchbase: ", $result->error if $oldresult->code != 32; - } - else - { - if ($code == 32) - { - my ($newdn, $newbase) = split /,/, $dn, 2; - - # Ensure key entry exist in old record before renaming - $result = $ldap->modify( "$oldfilter,$oldsearchbase", replace => { split('=', $newdn) } ); - warn "failed to add attributes to old entry $oldfilter,$oldsearchbase: ", $result->error if $result->code; - - # Move old record to new location - $result = $ldap->moddn( "$oldfilter,$oldsearchbase", newrdn => $newdn, newsuperior => $newbase, deleteoldrdn => 1 ); - warn "failed to rename old entry $oldfilter,$oldsearchbase: ", $result->error if $result->code; - - # Set things up as if we had found the new entry - $code = $oldresult->code; - @objectClass = $oldresult->entry(0)->get_value('objectClass'); - } - else - { - $result = $ldap->delete( "$oldfilter,$oldsearchbase" ); - warn "failed to remove old entry $oldfilter,$oldsearchbase: ", $result->error if $result->code; - } - } - - # 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 remove person if existing) - $seen = { person => 1 }; - - # 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);