1 |
slords |
1.1 |
diff -up e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update.code_cleanup e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update |
2 |
|
|
--- e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update.code_cleanup 2010-09-24 10:58:52.000000000 -0600 |
3 |
|
|
+++ e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update 2010-09-25 02:13:08.000000000 -0600 |
4 |
|
|
@@ -30,6 +30,7 @@ use esmith::ConfigDB; |
5 |
|
|
use esmith::AccountsDB; |
6 |
|
|
use esmith::util; |
7 |
|
|
use Net::LDAP; |
8 |
|
|
+use Date::Parse; |
9 |
|
|
|
10 |
|
|
my $c = esmith::ConfigDB->open_ro; |
11 |
|
|
my $a = esmith::AccountsDB->open_ro; |
12 |
|
|
@@ -44,11 +45,21 @@ unless ($status eq "enabled" ) |
13 |
|
|
|
14 |
|
|
my $hostname = $c->get('SystemName') |
15 |
|
|
|| die("Couldn't determine system name"); |
16 |
|
|
- $hostname = $hostname->value; |
17 |
|
|
+$hostname = $hostname->value; |
18 |
|
|
|
19 |
|
|
my $domain = $c->get('DomainName') |
20 |
|
|
|| die("Couldn't determine domain name"); |
21 |
|
|
- $domain = $domain->value; |
22 |
|
|
+$domain = $domain->value; |
23 |
|
|
+ |
24 |
|
|
+my $schema = '/etc/openldap/schema/samba.schema'; |
25 |
|
|
+my $map = { 'FirstName' => 'givenName', |
26 |
|
|
+ 'LastName' => 'sn', |
27 |
|
|
+ 'Phone' => 'telephoneNumber', |
28 |
|
|
+ 'Company' => 'o', |
29 |
|
|
+ 'Department' => 'ou', |
30 |
|
|
+ 'City' => 'l', |
31 |
|
|
+ 'Street' => 'street', |
32 |
|
|
+ }; |
33 |
|
|
|
34 |
|
|
my @accounts; |
35 |
|
|
my $account; |
36 |
|
|
@@ -69,73 +80,32 @@ else |
37 |
|
|
|
38 |
|
|
exit (0) if ($type eq 'ibay'); |
39 |
|
|
|
40 |
|
|
- die "Account $userName is not a user or group account; " . |
41 |
|
|
- "update LDAP entry failed.\n" |
42 |
|
|
+ die "Account $userName is not a user or group account; update LDAP entry failed.\n" |
43 |
|
|
unless (($type eq 'user') || ($type eq 'group') || ($userName eq 'admin')); |
44 |
|
|
@accounts = ($account); |
45 |
|
|
} |
46 |
|
|
|
47 |
|
|
#------------------------------------------------------------ |
48 |
|
|
-# Update LDAP directory entry. First read LDAP password |
49 |
|
|
+# Read all samba groups (can't do individual lookups) |
50 |
|
|
#------------------------------------------------------------ |
51 |
|
|
-my $pw = esmith::util::LdapPassword(); |
52 |
|
|
-my %passwd; |
53 |
|
|
-my %uid; |
54 |
|
|
-my %gid; |
55 |
|
|
-my %home; |
56 |
|
|
-my %shell; |
57 |
|
|
- |
58 |
|
|
-while(my ($key,$pwd,$uid,$gid, |
59 |
|
|
- undef,undef,undef, |
60 |
|
|
- $home,$shell) = getpwent()) { |
61 |
|
|
- |
62 |
|
|
- $passwd{$key} = "{CRYPT}$pwd"; |
63 |
|
|
- $uid{$key} = $uid; |
64 |
|
|
- $gid{$key} = $gid; |
65 |
|
|
- $home{$key} = $home; |
66 |
|
|
- $shell{$key} = $shell; |
67 |
|
|
-} |
68 |
|
|
-endpwent(); |
69 |
|
|
|
70 |
|
|
-# Now parse samba info |
71 |
|
|
-# We want to copy all this into LDAP |
72 |
|
|
-# so it'll be easier to switch to real LDAP auth later |
73 |
|
|
-my %lmpass; |
74 |
|
|
-my %ntpass; |
75 |
|
|
-my %smbflag; |
76 |
|
|
-my %smblct; |
77 |
|
|
-my %smbsid; |
78 |
|
|
-my %smbpgsid; |
79 |
|
|
- |
80 |
|
|
-# First, parse users data |
81 |
|
|
-foreach my $line (`/usr/bin/pdbedit -Lw`){ |
82 |
|
|
- my ($key,undef,$lmpass,$ntpass,$smbflag,$smblct) = split(/:/,$line); |
83 |
|
|
- $lmpass{$key} = $lmpass; |
84 |
|
|
- $ntpass{$key} = $ntpass; |
85 |
|
|
- $smbflag{$key} = $smbflag; |
86 |
|
|
- $smblct =~ s/LCT\-//; |
87 |
|
|
- $smblct{$key} = hex($smblct); |
88 |
|
|
- foreach my $info (`/usr/bin/pdbedit -v $key`){ |
89 |
|
|
- $smbsid{$key} = $1 if ($info =~ m/User SID:\s+(S-.*)/); |
90 |
|
|
- $smbpgsid{$key} = $1 if ($info =~ m/Primary Group SID:\s+(S-.*)/); |
91 |
|
|
- } |
92 |
|
|
-} |
93 |
|
|
+my $groupmap = (); |
94 |
|
|
|
95 |
|
|
-# Now, parse groupmaps data |
96 |
|
|
-foreach (`/usr/bin/net groupmap list`){ |
97 |
|
|
- chomp; |
98 |
|
|
- next unless (/^(.*?) \((S-.*-\d+)\) -> (.*)$/); |
99 |
|
|
- my ($desc, $smbsid, $key) = ($1, $2, $3); |
100 |
|
|
- # We only want group sid |
101 |
|
|
- my $account = $a->get($key) || next; |
102 |
|
|
- next unless ($account->prop('type') eq 'group'); |
103 |
|
|
- $smbsid{$key} = $smbsid; |
104 |
|
|
+# Only do if schema is found |
105 |
|
|
+if ( -f "$schema" and -x '/usr/bin/net' ) |
106 |
|
|
+{ |
107 |
|
|
+ foreach (`/usr/bin/net groupmap list 2> /dev/null`){ |
108 |
|
|
+ chomp; |
109 |
|
|
+ next if m{\(S-1-5-32-\d+\)}; |
110 |
|
|
+ $groupmap->{$3} = { name => "$1", sid => "$2" } if (/^(.*) \((S-.*-\d+)\) -> (.*)$/); |
111 |
|
|
+ } |
112 |
|
|
} |
113 |
|
|
|
114 |
|
|
#------------------------------------------------------------ |
115 |
|
|
# Update LDAP database entry. |
116 |
|
|
#------------------------------------------------------------ |
117 |
|
|
my $base = esmith::util::ldapBase ($domain); |
118 |
|
|
+my $pw = esmith::util::LdapPassword(); |
119 |
|
|
|
120 |
|
|
my $ldap = Net::LDAP->new('localhost') |
121 |
|
|
or die "$@"; |
122 |
|
|
@@ -145,109 +115,155 @@ $ldap->bind( |
123 |
|
|
password => $pw |
124 |
|
|
); |
125 |
|
|
|
126 |
|
|
-my $phone = $l->prop('defaultTelephoneNumber') || ''; |
127 |
|
|
-my $company = $l->prop('defaultCompany') || ''; |
128 |
|
|
-my $dept = $l->prop('defaultDepartment') || ''; |
129 |
|
|
-my $city = $l->prop('defaultCity') || ''; |
130 |
|
|
-my $street = $l->prop('defaultStreet') || ''; |
131 |
|
|
+my $updates; |
132 |
|
|
foreach my $acct (@accounts) |
133 |
|
|
{ |
134 |
|
|
my $key = $acct->key; |
135 |
|
|
my $type = $acct->prop('type'); |
136 |
|
|
- next unless ($type eq 'user' || $key eq 'admin' || $type eq 'group'); |
137 |
|
|
- my @attrs = (); |
138 |
|
|
- my $dn = $base; |
139 |
|
|
- if (($type eq 'user') || ($key eq 'admin')) |
140 |
|
|
- { |
141 |
|
|
- $dn = "uid=$key,ou=Users,$base"; |
142 |
|
|
- my $name = $acct->prop('FirstName') . " " . $acct->prop('LastName'); |
143 |
|
|
- utf8::upgrade($name); |
144 |
|
|
- my $first = $acct->prop('FirstName') || ''; |
145 |
|
|
- utf8::upgrade($first); |
146 |
|
|
- my $last = $acct->prop('LastName') || ''; |
147 |
|
|
- utf8::upgrade($last); |
148 |
|
|
- my $phone = $acct->prop('Phone') || ''; |
149 |
|
|
- my $company = $acct->prop('Company') || ''; |
150 |
|
|
- utf8::upgrade($company); |
151 |
|
|
- my $dept = $acct->prop('Dept') || ''; |
152 |
|
|
- utf8::upgrade($dept); |
153 |
|
|
- my $city = $acct->prop('City') || ''; |
154 |
|
|
- utf8::upgrade($city); |
155 |
|
|
- my $street = $acct->prop('Street') || ''; |
156 |
|
|
- utf8::upgrade($street); |
157 |
|
|
- my $password = $passwd{$key} || ''; |
158 |
|
|
- utf8::upgrade($password); |
159 |
|
|
- my $uid = $uid{$key} || ''; |
160 |
|
|
- my $gid = $gid{$key} || ''; |
161 |
|
|
- my $home = $home{$key} || ''; |
162 |
|
|
- my $shell = $shell{$key} || ''; |
163 |
|
|
- my $lmpass = $lmpass{$key} || ''; |
164 |
|
|
- my $ntpass = $ntpass{$key} || ''; |
165 |
|
|
- my $smbflag = $smbflag{$key} || ''; |
166 |
|
|
- my $smblct = $smblct{$key} || ''; |
167 |
|
|
- my $smbsid = $smbsid{$key} || ''; |
168 |
|
|
- my $smbpgsid = $smbpgsid{$key} || ''; |
169 |
|
|
- |
170 |
|
|
- push @attrs, (objectClass => ['inetOrgPerson', 'posixAccount', 'sambaSamAccount']); |
171 |
|
|
- push @attrs, (uid => $key); |
172 |
|
|
- |
173 |
|
|
- push @attrs, (cn => $name) unless ($name =~ /^\s*$/); |
174 |
|
|
- push @attrs, (givenName => $first) unless $first =~ /^\s*$/; |
175 |
|
|
- push @attrs, (sn => $last) unless $last =~ /^\s*$/; |
176 |
|
|
- push @attrs, (mail => "$key\@$domain"); |
177 |
|
|
- push @attrs, (telephoneNumber => $phone) unless $phone =~ /^\s*$/; |
178 |
|
|
- push @attrs, (o => $company) unless $company =~ /^\s*$/; |
179 |
|
|
- push @attrs, (ou => $dept) unless $dept =~ /^\s*$/; |
180 |
|
|
- push @attrs, (l => $city) unless $city =~ /^\s*$/; |
181 |
|
|
- push @attrs, (street => $street) unless $street =~ /^\s*$/; |
182 |
|
|
- push @attrs, (userPassword => $password) unless $password =~ /^\s*$/; |
183 |
|
|
- push @attrs, (uidNumber => $uid) unless $uid =~ /^\s*$/; |
184 |
|
|
- push @attrs, (gidNumber => $gid) unless $gid =~ /^\s*$/; |
185 |
|
|
- push @attrs, (homeDirectory => $home) unless $home =~ /^\s*$/; |
186 |
|
|
- push @attrs, (loginShell => $shell) unless $shell =~ /^\s*$/; |
187 |
|
|
- push @attrs, (sambaLMPassword => $lmpass) unless $lmpass =~ /^\s*$/; |
188 |
|
|
- push @attrs, (sambaNTPassword => $ntpass) unless $ntpass =~ /^\s*$/; |
189 |
|
|
- push @attrs, (sambaAcctFlags => $smbflag) unless $smbflag =~ /^\s*$/; |
190 |
|
|
- push @attrs, (sambaPwdLastSet => $smblct) unless $smblct =~ /^\s*$/; |
191 |
|
|
- push @attrs, (sambaSID => $smbsid) unless $smbsid =~ /^\s*$/; |
192 |
|
|
- push @attrs, (sambaPrimaryGroupSID => $smbpgsid) unless $smbpgsid =~ /^\s*$/; |
193 |
|
|
- } |
194 |
|
|
- elsif ($type eq 'group') |
195 |
|
|
+ my $desc = undef; |
196 |
|
|
+ |
197 |
|
|
+ if ($type =~ m{^(?:user|group)$} or $key eq 'admin') |
198 |
|
|
{ |
199 |
|
|
+ #------------------------------------------------------------ |
200 |
|
|
+ # Do the user portion |
201 |
|
|
+ #------------------------------------------------------------ |
202 |
|
|
+ my $dn = "uid=$key,ou=Users,$base"; |
203 |
|
|
+ $updates->{$dn}->{objectClass} = ['posixAccount', 'shadowAccount', 'account']; |
204 |
|
|
+ |
205 |
|
|
+ # Read information from getent passwd |
206 |
|
|
+ @{$updates->{$dn}}{'uid','userPassword','uidNumber','gidNumber','junk','junk','gecos','homeDirectory','loginShell'} = getpwnam($key); |
207 |
|
|
+ $updates->{$dn}->{userPassword} =~ s/^/{CRYPT}/ unless $updates->{$dn}->{userPassword} =~ m/^{/; |
208 |
|
|
+ $desc = $updates->{$dn}->{cn} = $updates->{$dn}->{gecos}; |
209 |
|
|
+ |
210 |
|
|
+ # Load values from db record |
211 |
|
|
+ foreach my $attr ( keys %$map ) |
212 |
|
|
+ { |
213 |
|
|
+ my $val = $acct->prop($attr); |
214 |
|
|
+ $updates->{$dn}->{$map->{$attr}} = $val if defined $val; |
215 |
|
|
+ } |
216 |
|
|
+ |
217 |
|
|
+ # Ensure users have the needed properties |
218 |
|
|
+ if ($type eq 'user') |
219 |
|
|
+ { |
220 |
|
|
+ push @{$updates->{$dn}->{objectClass}}, 'inetOrgPerson'; |
221 |
|
|
+ $updates->{$dn}->{mail} = "$key\@$domain"; |
222 |
|
|
+ |
223 |
|
|
+ # Samba parameters if we find the samba.schema |
224 |
|
|
+ if ( -f "$schema" and -x '/usr/bin/pdbedit' ) |
225 |
|
|
+ { |
226 |
|
|
+ my $line = `/usr/bin/pdbedit -wu '$key' 2> /dev/null`; |
227 |
|
|
+ chomp($line); |
228 |
|
|
+ if ($line) |
229 |
|
|
+ { |
230 |
|
|
+ @{$updates->{$dn}}{'junk','junk','sambaLMPassword','sambaNTPassword'} = split(/:/,$line); |
231 |
|
|
+ foreach $line (`/usr/bin/pdbedit -vu '$key' 2> /dev/null`) |
232 |
|
|
+ { |
233 |
|
|
+ chomp($line); |
234 |
|
|
+ $updates->{$dn}->{sambaSID} = $1 if $line =~ m{User SID:\s+(S-.*)$}; |
235 |
|
|
+ $updates->{$dn}->{displayName} = $1 if $line =~ m{Full Name:\s+(.*)$}; |
236 |
|
|
+ $updates->{$dn}->{sambaPrimaryGroupSID} = $1 if $line =~ m{Primary Group SID:\s+(S-.*)$}; |
237 |
|
|
+ $updates->{$dn}->{sambaAcctFlags} = $1 if $line =~ m{Account Flags:\s+(.*)$}; |
238 |
|
|
+ $updates->{$dn}->{sambaPwdLastSet} = str2time($1) if $line =~ m{Password last set:\s+(.*)$}; |
239 |
|
|
+ } |
240 |
|
|
+ push @{$updates->{$dn}->{objectClass}}, 'sambaSamAccount'; |
241 |
|
|
+ } |
242 |
|
|
+ } |
243 |
|
|
+ } |
244 |
|
|
+ |
245 |
|
|
+ #------------------------------------------------------------ |
246 |
|
|
+ # Do the group portion |
247 |
|
|
+ #------------------------------------------------------------ |
248 |
|
|
$dn = "cn=$key,ou=Groups,$base"; |
249 |
|
|
- my $key = $acct->key; |
250 |
|
|
- my $desc = $acct->prop('Description') || ''; |
251 |
|
|
- utf8::upgrade($desc); |
252 |
|
|
- my @members = split(/,/,($acct->prop('Members') || '')); |
253 |
|
|
- my $gid = $acct->prop('Gid'); |
254 |
|
|
- my $smbsid = $smbsid{$key}; |
255 |
|
|
- |
256 |
|
|
- push @attrs, (objectClass => ['posixGroup','mailboxRelatedObject','sambaGroupMapping']); |
257 |
|
|
- push @attrs, (cn => $key); |
258 |
|
|
- push @attrs, (mail => "$key\@$domain"); |
259 |
|
|
- push @attrs, (gidNumber => $gid); |
260 |
|
|
- push @attrs, (description => $desc) unless $desc =~ /^\s*$/; |
261 |
|
|
- push @attrs, (memberUid => \@members) |
262 |
|
|
- unless ((scalar @members == 0) && ($event eq 'group-create')); |
263 |
|
|
- # Samba requires the displayName attribute |
264 |
|
|
- push @attrs, (displayName => $desc) unless $desc =~ /^\s*$/; |
265 |
|
|
- push @attrs, (sambaGroupType => '2'); |
266 |
|
|
- push @attrs, (sambaSID => $smbsid); |
267 |
|
|
+ $updates->{$dn}->{objectClass} = ['posixGroup']; |
268 |
|
|
+ |
269 |
|
|
+ # Read information from getent group |
270 |
|
|
+ @{$updates->{$dn}}{'cn','userPassword','gidNumber','memberUid'} = getgrnam($key); |
271 |
|
|
+ $updates->{$dn}->{userPassword} =~ s/^/{CRYPT}/ unless $updates->{$dn}->{userPassword} =~ m/^{/; |
272 |
|
|
+ $updates->{$dn}->{description} = $desc if $desc; |
273 |
|
|
+ $updates->{$dn}->{memberUid} = [ split /\s+/, $updates->{$dn}->{memberUid} ]; |
274 |
|
|
+ |
275 |
|
|
+ # Ensure groups have the needed properties |
276 |
|
|
+ if ($type eq 'group') |
277 |
|
|
+ { |
278 |
|
|
+ push @{$updates->{$dn}->{objectClass}}, 'mailboxRelatedObject'; |
279 |
|
|
+ $updates->{$dn}->{mail} = "$key\@$domain"; |
280 |
|
|
+ } |
281 |
|
|
+ |
282 |
|
|
+ # Samba parameters if we find the samba.schema |
283 |
|
|
+ if ( -f "$schema" and exists $groupmap->{$key} ) |
284 |
|
|
+ { |
285 |
|
|
+ push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping'; |
286 |
|
|
+ $updates->{$dn}->{displayName} = $groupmap->{$key}->{name}; |
287 |
|
|
+ $updates->{$dn}->{sambaSID} = $groupmap->{$key}->{sid}; |
288 |
|
|
+ $updates->{$dn}->{sambaGroupType} = '2'; |
289 |
|
|
+ } |
290 |
|
|
+ |
291 |
|
|
+ } |
292 |
|
|
+} |
293 |
|
|
+endpwent(); |
294 |
|
|
+ |
295 |
|
|
+# Fix attributes and update ldap |
296 |
|
|
+foreach my $dn (keys %$updates) |
297 |
|
|
+{ |
298 |
|
|
+ # Try and find record |
299 |
|
|
+ my ($filter, $searchbase) = split /,/, $dn, 2; |
300 |
|
|
+ my $result = $ldap->search( base => $searchbase, filter => "($filter)" ); |
301 |
|
|
+ if ( $result->code ) |
302 |
|
|
+ { |
303 |
|
|
+ warn "failed looking up entry for $dn: ", $result->error; |
304 |
|
|
+ next; |
305 |
|
|
} |
306 |
|
|
- if (($event eq 'user-create') || ($event eq 'group-create')) |
307 |
|
|
+ my $cnt = scalar $result->entries(); |
308 |
|
|
+ |
309 |
|
|
+ # Clean up attributes and convert to utf8 |
310 |
|
|
+ delete $updates->{$dn}->{'junk'}; |
311 |
|
|
+ foreach my $attr ( keys %{$updates->{$dn}} ) |
312 |
|
|
{ |
313 |
|
|
- my $result = $ldap->add ($dn, attr => \@attrs); |
314 |
|
|
+ if ( ref($updates->{$dn}->{$attr}) eq 'ARRAY' ) |
315 |
|
|
+ { |
316 |
|
|
+ if ( $cnt == 0 and scalar(@{$updates->{$dn}->{$attr}}) == 0 ) |
317 |
|
|
+ { |
318 |
|
|
+ delete $updates->{$dn}->{$attr}; |
319 |
|
|
+ } |
320 |
|
|
+ else |
321 |
|
|
+ { |
322 |
|
|
+ for (my $c = 0; $c < scalar(@{$updates->{$dn}->{$attr}}); $c++) |
323 |
|
|
+ { |
324 |
|
|
+ utf8::upgrade($updates->{$dn}->{$attr}[$c]); |
325 |
|
|
+ } |
326 |
|
|
+ } |
327 |
|
|
+ } |
328 |
|
|
+ else |
329 |
|
|
+ { |
330 |
|
|
+ if ($updates->{$dn}->{$attr} !~ /^\s*$/) |
331 |
|
|
+ { |
332 |
|
|
+ utf8::upgrade($updates->{$dn}->{$attr}); |
333 |
|
|
+ } |
334 |
|
|
+ elsif ( $cnt == 0 ) |
335 |
|
|
+ { |
336 |
|
|
+ delete $updates->{$dn}->{$attr}; |
337 |
|
|
+ } |
338 |
|
|
+ else |
339 |
|
|
+ { |
340 |
|
|
+ $updates->{$dn}->{$attr} = []; |
341 |
|
|
+ } |
342 |
|
|
+ } |
343 |
|
|
+ } |
344 |
|
|
|
345 |
|
|
- $result->code && |
346 |
|
|
- warn "failed to add entry for $dn: ", $result->error ; |
347 |
|
|
+ # Perform insert or update |
348 |
|
|
+ if ( $cnt == 0 ) |
349 |
|
|
+ { |
350 |
|
|
+ $result = $ldap->add ($dn, attrs => [ %{$updates->{$dn}} ] ); |
351 |
|
|
+ $result->code && warn "failed to add entry for $dn: ", $result->error; |
352 |
|
|
+ } |
353 |
|
|
+ elsif ( $cnt == 1 ) |
354 |
|
|
+ { |
355 |
|
|
+ $result = $ldap->modify ($dn, replace => $updates->{$dn}); |
356 |
|
|
+ $result->code && warn "failed to modify entry for $dn: ", $result->error; |
357 |
|
|
} |
358 |
|
|
else |
359 |
|
|
{ |
360 |
|
|
- my %attrs = @attrs; |
361 |
|
|
- my $result = $ldap->modify ($dn, replace => \%attrs); |
362 |
|
|
- |
363 |
|
|
- $result->code && |
364 |
|
|
- warn "failed to modify entry for $dn: ", $result->error ; |
365 |
|
|
+ warn "failed looking up entry for $dn: found $cnt results"; |
366 |
|
|
} |
367 |
|
|
} |
368 |
|
|
$ldap->unbind; |