1 |
diff -up e-smith-ldap-5.2.0/createlinks.simple-ldap-update e-smith-ldap-5.2.0/createlinks |
2 |
--- e-smith-ldap-5.2.0/createlinks.simple-ldap-update 2010-11-08 11:48:06.000000000 -0700 |
3 |
+++ e-smith-ldap-5.2.0/createlinks 2010-11-08 11:48:42.000000000 -0700 |
4 |
@@ -14,26 +14,27 @@ templates2events("/etc/openldap/$_", |
5 |
)); |
6 |
} |
7 |
|
8 |
-event_link("ldap-update", "group-create", "95"); |
9 |
+event_link("ldap-update-simple", "group-create", "95"); |
10 |
+event_link("ldap-update-simple", "group-modify", "95"); |
11 |
event_link("ldap-delete", "group-delete", "55"); |
12 |
-event_link("ldap-update", "user-create", "95"); |
13 |
+ |
14 |
+event_link("ldap-update-simple", "user-create", "95"); |
15 |
+event_link("ldap-update-simple", "user-modify", "95"); |
16 |
+event_link("ldap-update-simple", "user-modify-admin", "95"); |
17 |
event_link("ldap-delete", "user-delete", "55"); |
18 |
-event_link("ldap-update", "user-lock", "55"); |
19 |
|
20 |
-event_link("ldap-update", "user-modify", "95"); |
21 |
-event_link("ldap-update", "user-modify-admin", "95"); |
22 |
-event_link("ldap-update", "group-modify", "95"); |
23 |
-event_link("ldap-update", "password-modify", "95"); |
24 |
+event_link("ldap-update-simple", "password-modify", "95"); |
25 |
+event_link("ldap-update-simple", "user-lock", "55"); |
26 |
|
27 |
-event_link("ldap-update", "ibay-create", "95"); |
28 |
-event_link("ldap-update", "ibay-modify", "95"); |
29 |
+event_link("ldap-update-simple", "ibay-create", "95"); |
30 |
+event_link("ldap-update-simple", "ibay-modify", "95"); |
31 |
event_link("ldap-delete", "ibay-delete", "55"); |
32 |
|
33 |
+event_link("ldap-update-simple", "machine-account-create", "95"); |
34 |
+ |
35 |
event_link("ldap-update", "bootstrap-ldap-save", "25"); |
36 |
event_link("cleanup-unix-user-group", "bootstrap-ldap-save", "98"); |
37 |
|
38 |
-event_link("ldap-update", "machine-account-create", "95"); |
39 |
- |
40 |
event_link("ldap-dump", "pre-backup", "30"); |
41 |
|
42 |
event_link("ldap-update", "ldap-update", "80"); |
43 |
diff -up e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update.simple-ldap-update e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update |
44 |
--- e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update.simple-ldap-update 2010-11-08 11:48:06.000000000 -0700 |
45 |
+++ e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update 2010-11-08 11:48:42.000000000 -0700 |
46 |
@@ -120,7 +120,7 @@ my ($dc,undef) = split (/\./, $domain); |
47 |
my $o = $l->prop('defaultCompany') || $domain; |
48 |
|
49 |
# Try and find base record |
50 |
-my %seen; |
51 |
+my $seen; |
52 |
my @objects = qw(top organization dcObject); |
53 |
my $result = $ldap->search( base => $base, filter => '(objectClass=*)', scope => 'base' ); |
54 |
if ($result->code == 32) |
55 |
@@ -134,8 +134,8 @@ elsif ($result->code) |
56 |
else |
57 |
{ |
58 |
# Don't overwrite objectClass (just update if necessary) |
59 |
- %seen = (); |
60 |
- @objects = grep { ! $seen{$_} ++ } (@objects, $result->entry(0)->get_value('objectClass') ); |
61 |
+ $seen = (); |
62 |
+ @objects = grep { ! $seen->{$_} ++ } (@objects, $result->entry(0)->get_value('objectClass') ); |
63 |
$ldap->modify( $base, replace => { dc => $dc, o => $o, objectClass => \@objects } ); |
64 |
} |
65 |
warn "failed to add/update entry $base: ", $result->error if $result->code; |
66 |
@@ -156,8 +156,8 @@ foreach my $obj ( qw(Users Groups Comput |
67 |
else |
68 |
{ |
69 |
# Don't overwrite objectClass (just update if necessary) |
70 |
- %seen = (); |
71 |
- @objects = grep { ! $seen{$_} ++ } (@objects, $result->entry(0)->get_value('objectClass') ); |
72 |
+ $seen = (); |
73 |
+ @objects = grep { ! $seen->{$_} ++ } (@objects, $result->entry(0)->get_value('objectClass') ); |
74 |
$result = $ldap->modify( "ou=$obj,$base", replace => { ou => $obj, objectClass => \@objects } ); |
75 |
} |
76 |
warn "failed to add/update entry ou=$obj,$base: ", $result->error if $result->code; |
77 |
@@ -175,6 +175,7 @@ foreach my $user (qw/www/){ |
78 |
|
79 |
# Read information from getent passwd |
80 |
@{$updates->{$dn}}{'uid','userPassword','uidNumber','gidNumber','junk','junk','gecos','homeDirectory','loginShell'} = getpwnam($user); |
81 |
+ $updates->{$dn}->{userPassword} = "!*" if $updates->{$dn}->{userPassword} eq '!!'; |
82 |
$updates->{$dn}->{userPassword} =~ s/^/{CRYPT}/ unless $updates->{$dn}->{userPassword} =~ m/^{/; |
83 |
$updates->{$dn}->{cn} = $updates->{$dn}->{gecos}; |
84 |
|
85 |
@@ -197,6 +198,16 @@ foreach my $user (qw/www/){ |
86 |
} |
87 |
push @{$updates->{$dn}->{objectClass}}, 'sambaSamAccount'; |
88 |
} |
89 |
+ else |
90 |
+ { |
91 |
+ $updates->{$dn}->{sambaLMPassword} = []; |
92 |
+ $updates->{$dn}->{sambaNTPassword} = []; |
93 |
+ $updates->{$dn}->{sambaSID} = []; |
94 |
+ $updates->{$dn}->{displayName} = []; |
95 |
+ $updates->{$dn}->{sambaPrimaryGroupSID} = []; |
96 |
+ $updates->{$dn}->{sambaAcctFlags} = []; |
97 |
+ $updates->{$dn}->{sambaPwdLastSet} = []; |
98 |
+ } |
99 |
} |
100 |
} |
101 |
endpwent(); |
102 |
@@ -217,12 +228,21 @@ foreach my $group (qw/nobody shared www/ |
103 |
} |
104 |
|
105 |
# Samba parameters if we find the samba.schema |
106 |
- if ( -f "$schema" and exists $groupmap->{$group} ) |
107 |
- { |
108 |
- push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping'; |
109 |
- $updates->{$dn}->{displayName} = $groupmap->{$group}->{name}; |
110 |
- $updates->{$dn}->{sambaSID} = $groupmap->{$group}->{sid}; |
111 |
- $updates->{$dn}->{sambaGroupType} = '2'; |
112 |
+ if ( -f "$schema" ) |
113 |
+ { |
114 |
+ if ( exists $groupmap->{$group} ) |
115 |
+ { |
116 |
+ push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping'; |
117 |
+ $updates->{$dn}->{displayName} = $groupmap->{$group}->{name}; |
118 |
+ $updates->{$dn}->{sambaSID} = $groupmap->{$group}->{sid}; |
119 |
+ $updates->{$dn}->{sambaGroupType} = '2'; |
120 |
+ } |
121 |
+ else |
122 |
+ { |
123 |
+ $updates->{$dn}->{displayName} = []; |
124 |
+ $updates->{$dn}->{sambaSID} = []; |
125 |
+ $updates->{$dn}->{sambaGroupType} = []; |
126 |
+ } |
127 |
} |
128 |
} |
129 |
endgrent(); |
130 |
@@ -260,6 +280,7 @@ foreach my $acct (@accounts) |
131 |
delete $updates->{$dn}; |
132 |
next; |
133 |
} |
134 |
+ $updates->{$dn}->{userPassword} = "!*" if $updates->{$dn}->{userPassword} eq '!!'; |
135 |
$updates->{$dn}->{userPassword} =~ s/^/{CRYPT}/ unless $updates->{$dn}->{userPassword} =~ m/^{/; |
136 |
$desc = $updates->{$dn}->{cn} = $updates->{$dn}->{gecos}; |
137 |
|
138 |
@@ -300,6 +321,16 @@ foreach my $acct (@accounts) |
139 |
} |
140 |
push @{$updates->{$dn}->{objectClass}}, 'sambaSamAccount'; |
141 |
} |
142 |
+ else |
143 |
+ { |
144 |
+ $updates->{$dn}->{sambaLMPassword} = []; |
145 |
+ $updates->{$dn}->{sambaNTPassword} = []; |
146 |
+ $updates->{$dn}->{sambaSID} = []; |
147 |
+ $updates->{$dn}->{displayName} = []; |
148 |
+ $updates->{$dn}->{sambaPrimaryGroupSID} = []; |
149 |
+ $updates->{$dn}->{sambaAcctFlags} = []; |
150 |
+ $updates->{$dn}->{sambaPwdLastSet} = []; |
151 |
+ } |
152 |
} |
153 |
|
154 |
#------------------------------------------------------------ |
155 |
@@ -322,20 +353,27 @@ foreach my $acct (@accounts) |
156 |
} |
157 |
|
158 |
# Samba parameters if we find the samba.schema |
159 |
- if ( -f "$schema" and exists $groupmap->{$key} ) |
160 |
+ if ( -f "$schema" ) |
161 |
{ |
162 |
- push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping'; |
163 |
- $updates->{$dn}->{displayName} = $groupmap->{$key}->{name}; |
164 |
- $updates->{$dn}->{sambaSID} = $groupmap->{$key}->{sid}; |
165 |
- $updates->{$dn}->{sambaGroupType} = '2'; |
166 |
+ if ( exists $groupmap->{$key} ) |
167 |
+ { |
168 |
+ push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping'; |
169 |
+ $updates->{$dn}->{displayName} = $groupmap->{$key}->{name}; |
170 |
+ $updates->{$dn}->{sambaSID} = $groupmap->{$key}->{sid}; |
171 |
+ $updates->{$dn}->{sambaGroupType} = '2'; |
172 |
+ } |
173 |
+ else |
174 |
+ { |
175 |
+ $updates->{$dn}->{displayName} = []; |
176 |
+ $updates->{$dn}->{sambaSID} = []; |
177 |
+ $updates->{$dn}->{sambaGroupType} = []; |
178 |
+ } |
179 |
} |
180 |
- |
181 |
} |
182 |
} |
183 |
endpwent(); |
184 |
endgrent(); |
185 |
|
186 |
- |
187 |
#------------------------------------------------------------ |
188 |
# Update LDAP database entry. |
189 |
#------------------------------------------------------------ |
190 |
@@ -423,8 +461,12 @@ foreach my $dn (keys %$updates) |
191 |
else |
192 |
{ |
193 |
# Don't overwrite objectClass (just remove person if existing) |
194 |
- %seen = ( person => 1 ); |
195 |
- @{$updates->{$dn}->{objectClass}} = grep { ! $seen{$_}++ } (@{$updates->{$dn}->{objectClass}}, @objectClass ); |
196 |
+ $seen = { person => 1 }; |
197 |
+ |
198 |
+ # Remove samba objectClasses if removing samba attributes |
199 |
+ @{$seen}{'sambaSamAccount','sambaGroupMapping'} = (1,1) if ref($updates->{$dn}->{sambaSID}) eq 'ARRAY'; |
200 |
+ |
201 |
+ @{$updates->{$dn}->{objectClass}} = grep { ! $seen->{$_}++ } (@{$updates->{$dn}->{objectClass}}, @objectClass ); |
202 |
|
203 |
$result = $ldap->modify( $dn, replace => $updates->{$dn}); |
204 |
$result->code && warn "failed to modify entry $dn: ", $result->error; |
205 |
diff -up e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update-simple.simple-ldap-update e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update-simple |
206 |
--- e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update-simple.simple-ldap-update 2010-11-08 11:48:53.000000000 -0700 |
207 |
+++ e-smith-ldap-5.2.0/root/etc/e-smith/events/actions/ldap-update-simple 2010-11-08 11:48:42.000000000 -0700 |
208 |
@@ -0,0 +1,245 @@ |
209 |
+#!/usr/bin/perl -w |
210 |
+ |
211 |
+package esmith; |
212 |
+ |
213 |
+use strict; |
214 |
+use Errno; |
215 |
+use esmith::ConfigDB; |
216 |
+use esmith::AccountsDB; |
217 |
+use esmith::util; |
218 |
+use Net::LDAP; |
219 |
+use Date::Parse; |
220 |
+ |
221 |
+my $c = esmith::ConfigDB->open_ro; |
222 |
+my $a = esmith::AccountsDB->open_ro; |
223 |
+ |
224 |
+my $l = $c->get('ldap'); |
225 |
+my $status = $l->prop('status') || "disabled"; |
226 |
+unless ($status eq "enabled" ) |
227 |
+{ |
228 |
+ warn "Not running action script $0, LDAP service not enabled!\n"; |
229 |
+ exit(0); |
230 |
+} |
231 |
+ |
232 |
+exit(0) if ($c->get('ldap')->prop('Authentication') || 'disabled') eq 'enabled'; |
233 |
+ |
234 |
+my $domain = $c->get('DomainName') |
235 |
+ || die("Couldn't determine domain name"); |
236 |
+$domain = $domain->value; |
237 |
+ |
238 |
+my $schema = '/etc/openldap/schema/samba.schema'; |
239 |
+ |
240 |
+my $event = shift || die "Event name must be specified"; |
241 |
+ |
242 |
+my @name = @ARGV; |
243 |
+die "Account name argument missing." unless scalar (@name) >= 1; |
244 |
+ |
245 |
+#------------------------------------------------------------ |
246 |
+# Update LDAP database entry. |
247 |
+#------------------------------------------------------------ |
248 |
+my $base = esmith::util::ldapBase ($domain); |
249 |
+my $pw = esmith::util::LdapPassword(); |
250 |
+ |
251 |
+my $ldap = Net::LDAP->new('localhost') |
252 |
+ or die "$@"; |
253 |
+ |
254 |
+$ldap->bind( |
255 |
+ dn => "cn=root,$base", |
256 |
+ password => $pw |
257 |
+); |
258 |
+ |
259 |
+my @accounts; |
260 |
+my $account; |
261 |
+foreach my $name (@name) |
262 |
+{ |
263 |
+ $account = $a->get($name); |
264 |
+ die "Account $name not found.\n" unless defined $account; |
265 |
+ my $type = $account->prop('type') || "unknown"; |
266 |
+ |
267 |
+ die "Account $name is not a user, group, ibay, machine account; update LDAP entry failed.\n" |
268 |
+ unless ($type =~ m{^(?:user|group|ibay|machine)$} or $name eq 'admin'); |
269 |
+ |
270 |
+ push @accounts, $account; |
271 |
+} |
272 |
+ |
273 |
+#------------------------------------------------------------ |
274 |
+# Read all samba groups (can't do individual lookups) |
275 |
+#------------------------------------------------------------ |
276 |
+ |
277 |
+my $groupmap = (); |
278 |
+ |
279 |
+# Only do if schema is found |
280 |
+if ( -f "$schema" and -x '/usr/bin/net' ) |
281 |
+{ |
282 |
+ foreach (`/usr/bin/net groupmap list 2> /dev/null`){ |
283 |
+ chomp; |
284 |
+ next if m{\(S-1-5-32-\d+\)}; |
285 |
+ $groupmap->{$3} = { name => "$1", sid => "$2" } if (/^(.*) \((S-.*-\d+)\) -> (.*)$/); |
286 |
+ } |
287 |
+} |
288 |
+ |
289 |
+#------------------------------------------------------------ |
290 |
+# Create a list of updates that need to happen |
291 |
+#------------------------------------------------------------ |
292 |
+ |
293 |
+my $updates; |
294 |
+foreach my $acct (@accounts) |
295 |
+{ |
296 |
+ my $key = $acct->key; |
297 |
+ my $type = $acct->prop('type'); |
298 |
+ my $desc = undef; |
299 |
+ my $dn; |
300 |
+ |
301 |
+ if ($type =~ m{^(?:user|group|ibay|machine)$} or $key eq 'admin') |
302 |
+ { |
303 |
+ #------------------------------------------------------------ |
304 |
+ # Do the user portion |
305 |
+ #------------------------------------------------------------ |
306 |
+ if ($type eq 'machine') |
307 |
+ { |
308 |
+ $dn = "uid=$key,ou=Computers,$base"; |
309 |
+ } |
310 |
+ else |
311 |
+ { |
312 |
+ $dn = "uid=$key,ou=Users,$base"; |
313 |
+ } |
314 |
+ utf8::upgrade($dn); |
315 |
+ |
316 |
+ # Read information from getent passwd |
317 |
+ @{$updates->{$dn}}{'uid','userPassword'} = getpwnam($key); |
318 |
+ unless ($updates->{$dn}->{uid}) |
319 |
+ { |
320 |
+ delete $updates->{$dn}; |
321 |
+ next; |
322 |
+ } |
323 |
+ $updates->{$dn}->{userPassword} = "!*" if $updates->{$dn}->{userPassword} eq '!!'; |
324 |
+ $updates->{$dn}->{userPassword} =~ s/^/{CRYPT}/ unless $updates->{$dn}->{userPassword} =~ m/^{/; |
325 |
+ |
326 |
+ # Samba parameters if we find the samba.schema |
327 |
+ if ( -f "$schema" and -x '/usr/bin/pdbedit' ) |
328 |
+ { |
329 |
+ my $line = `/usr/bin/pdbedit -wu '$key' 2> /dev/null`; |
330 |
+ chomp($line); |
331 |
+ if ($line) |
332 |
+ { |
333 |
+ @{$updates->{$dn}}{'junk','junk','sambaLMPassword','sambaNTPassword'} = split(/:/,$line); |
334 |
+ foreach $line (`/usr/bin/pdbedit -vu '$key' 2> /dev/null`) |
335 |
+ { |
336 |
+ chomp($line); |
337 |
+ $updates->{$dn}->{sambaSID} = $1 if $line =~ m{User SID:\s+(S-.*)$}; |
338 |
+ $updates->{$dn}->{displayName} = $1 if $line =~ m{Full Name:\s+(.*)$}; |
339 |
+ $updates->{$dn}->{sambaPrimaryGroupSID} = $1 if $line =~ m{Primary Group SID:\s+(S-.*)$}; |
340 |
+ $updates->{$dn}->{sambaAcctFlags} = $1 if $line =~ m{Account Flags:\s+(.*)$}; |
341 |
+ $updates->{$dn}->{sambaPwdLastSet} = str2time($1) if $line =~ m{Password last set:\s+(.*)$}; |
342 |
+ } |
343 |
+ push @{$updates->{$dn}->{objectClass}}, 'sambaSamAccount'; |
344 |
+ } |
345 |
+ else |
346 |
+ { |
347 |
+ $updates->{$dn}->{sambaLMPassword} = []; |
348 |
+ $updates->{$dn}->{sambaNTPassword} = []; |
349 |
+ $updates->{$dn}->{sambaSID} = []; |
350 |
+ $updates->{$dn}->{displayName} = []; |
351 |
+ $updates->{$dn}->{sambaPrimaryGroupSID} = []; |
352 |
+ $updates->{$dn}->{sambaAcctFlags} = []; |
353 |
+ $updates->{$dn}->{sambaPwdLastSet} = []; |
354 |
+ } |
355 |
+ } |
356 |
+ } |
357 |
+} |
358 |
+endpwent(); |
359 |
+ |
360 |
+#------------------------------------------------------------ |
361 |
+# Do the group portion (only if we have samba) |
362 |
+#------------------------------------------------------------ |
363 |
+if ( -f "$schema" ) |
364 |
+{ |
365 |
+ foreach my $group ( (map { $_->key } $a->users), (map { $_->key } $a->groups), qw/admin nobody shared/ ){ |
366 |
+ my $dn = "cn=$group,ou=Groups,$base"; |
367 |
+ utf8::upgrade($dn); |
368 |
+ |
369 |
+ if ( exists $groupmap->{$group} ) |
370 |
+ { |
371 |
+ push @{$updates->{$dn}->{objectClass}}, 'sambaGroupMapping'; |
372 |
+ $updates->{$dn}->{displayName} = $groupmap->{$group}->{name}; |
373 |
+ $updates->{$dn}->{sambaSID} = $groupmap->{$group}->{sid}; |
374 |
+ $updates->{$dn}->{sambaGroupType} = '2'; |
375 |
+ } |
376 |
+ else |
377 |
+ { |
378 |
+ $updates->{$dn}->{displayName} = []; |
379 |
+ $updates->{$dn}->{sambaSID} = []; |
380 |
+ $updates->{$dn}->{sambaGroupType} = []; |
381 |
+ } |
382 |
+ } |
383 |
+} |
384 |
+ |
385 |
+#------------------------------------------------------------ |
386 |
+# Update LDAP database entry. |
387 |
+#------------------------------------------------------------ |
388 |
+foreach my $dn (keys %$updates) |
389 |
+{ |
390 |
+ # Try and find record |
391 |
+ my $result = $ldap->search( base => $dn, filter => '(objectClass=*)', scope => 'base' ); |
392 |
+ warn "failed looking up entry $dn: ", $result->error if $result->code && $result->code != 32; |
393 |
+ my $code = $result->code; |
394 |
+ my @objectClass = $code == 32 ? () : $result->entry(0)->get_value('objectClass'); |
395 |
+ |
396 |
+ # Clean up attributes and convert to utf8 |
397 |
+ delete $updates->{$dn}->{'junk'}; |
398 |
+ foreach my $attr ( keys %{$updates->{$dn}} ) |
399 |
+ { |
400 |
+ if ( ref($updates->{$dn}->{$attr}) eq 'ARRAY' ) |
401 |
+ { |
402 |
+ if ( $code == 32 and scalar(@{$updates->{$dn}->{$attr}}) == 0 ) |
403 |
+ { |
404 |
+ delete $updates->{$dn}->{$attr}; |
405 |
+ } |
406 |
+ else |
407 |
+ { |
408 |
+ for (my $c = 0; $c < scalar(@{$updates->{$dn}->{$attr}}); $c++) |
409 |
+ { |
410 |
+ utf8::upgrade($updates->{$dn}->{$attr}[$c]); |
411 |
+ } |
412 |
+ } |
413 |
+ } |
414 |
+ else |
415 |
+ { |
416 |
+ if ($updates->{$dn}->{$attr} !~ /^\s*$/) |
417 |
+ { |
418 |
+ utf8::upgrade($updates->{$dn}->{$attr}); |
419 |
+ } |
420 |
+ elsif ( $code == 32 ) |
421 |
+ { |
422 |
+ delete $updates->{$dn}->{$attr}; |
423 |
+ } |
424 |
+ else |
425 |
+ { |
426 |
+ $updates->{$dn}->{$attr} = []; |
427 |
+ } |
428 |
+ } |
429 |
+ } |
430 |
+ |
431 |
+ # Perform insert or update |
432 |
+ if ( $code == 32 ) |
433 |
+ { |
434 |
+ $result = $ldap->add( $dn, attrs => [ %{$updates->{$dn}} ] ); |
435 |
+ $result->code && warn "failed to add entry $dn: ", $result->error; |
436 |
+ } |
437 |
+ else |
438 |
+ { |
439 |
+ # Don't overwrite objectClass (just update if necessary) |
440 |
+ my $seen = (); |
441 |
+ |
442 |
+ # Remove samba objectClasses if removing samba attributes |
443 |
+ @{$seen}{'sambaSamAccount','sambaGroupMapping'} = (1,1) if ref($updates->{$dn}->{sambaSID}) eq 'ARRAY'; |
444 |
+ |
445 |
+ @{$updates->{$dn}->{objectClass}} = grep { ! $seen->{$_}++ } (@{$updates->{$dn}->{objectClass}}, @objectClass ); |
446 |
+ |
447 |
+ $result = $ldap->modify( $dn, replace => $updates->{$dn}); |
448 |
+ $result->code && warn "failed to modify entry $dn: ", $result->error; |
449 |
+ } |
450 |
+} |
451 |
+$ldap->unbind; |
452 |
+ |
453 |
+exit (0); |