source: branches/samba-3.5.x/lib/nss_wrapper/nss_wrapper.pl

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 9.9 KB
Line 
1#!/usr/bin/perl
2#
3
4use strict;
5
6use Getopt::Long;
7use Cwd qw(abs_path);
8
9my $opt_help = 0;
10my $opt_passwd_path = undef;
11my $opt_group_path = undef;
12my $opt_action = undef;
13my $opt_type = undef;
14my $opt_name = undef;
15my $opt_member = undef;
16
17my $passwdfn = undef;
18my $groupfn = undef;
19my $memberfn = undef;
20my $actionfn = undef;
21
22sub passwd_add($$$$);
23sub passwd_delete($$$$);
24sub group_add($$$$);
25sub group_delete($$$$);
26sub member_add($$$$);
27sub member_delete($$$$);
28
29sub check_path($$);
30
31my $result = GetOptions(
32 'help|h|?' => \$opt_help,
33 'passwd_path=s' => \$opt_passwd_path,
34 'group_path=s' => \$opt_group_path,
35 'action=s' => \$opt_action,
36 'type=s' => \$opt_type,
37 'name=s' => \$opt_name,
38 'member=s' => \$opt_member
39);
40
41sub usage($;$)
42{
43 my ($ret, $msg) = @_;
44
45 print $msg."\n\n" if defined($msg);
46
47 print "usage:
48
49 --help|-h|-? Show this help.
50
51 --passwd_path <path> Path of the 'passwd' file.
52 --group_path <path> Path of the 'group' file.
53
54 --type <type> 'passwd', 'group' and 'member' are supported.
55
56 --action <action> 'add' or 'delete'.
57
58 --name <name> The name of the object.
59
60 --member <member> The name of the member.
61";
62 exit($ret);
63}
64
65usage(1) if (not $result);
66
67usage(0) if ($opt_help);
68
69if (not defined($opt_action)) {
70 usage(1, "missing: --action [add|delete]");
71}
72if ($opt_action eq "add") {
73 $passwdfn = \&passwd_add;
74 $groupfn = \&group_add;
75 $memberfn = \&member_add;
76} elsif ($opt_action eq "delete") {
77 $passwdfn = \&passwd_delete;
78 $groupfn = \&group_delete;
79 $memberfn = \&member_delete;
80} else {
81 usage(1, "invalid: --action [add|delete]: '$opt_action'");
82}
83
84if (not defined($opt_type)) {
85 usage(1, "missing: --type [passwd|group|member]");
86}
87if ($opt_type eq "member" and not defined($opt_member)) {
88 usage(1, "missing: --member <member>");
89}
90my $opt_fullpath_passwd;
91my $opt_fullpath_group;
92if ($opt_type eq "passwd") {
93 $actionfn = $passwdfn;
94 $opt_fullpath_passwd = check_path($opt_passwd_path, $opt_type);
95} elsif ($opt_type eq "group") {
96 $actionfn = $groupfn;
97 $opt_fullpath_group = check_path($opt_group_path, $opt_type);
98} elsif ($opt_type eq "member") {
99 $actionfn = $memberfn;
100 $opt_fullpath_passwd = check_path($opt_passwd_path, "passwd");
101 $opt_fullpath_group = check_path($opt_group_path, "group");
102} else {
103 usage(1, "invalid: --type [passwd|group]: '$opt_type'")
104}
105
106if (not defined($opt_name)) {
107 usage(1, "missing: --name <name>");
108}
109if ($opt_name eq "") {
110 usage(1, "invalid: --name <name>");
111}
112
113exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name);
114
115sub check_path($$)
116{
117 my ($path,$type) = @_;
118
119 if (not defined($path)) {
120 usage(1, "missing: --$type\_path <path>");
121 }
122 if ($path eq "" or $path eq "/") {
123 usage(1, "invalid: --$type\_path <path>: '$path'");
124 }
125 my $fullpath = abs_path($path);
126 if (not defined($fullpath)) {
127 usage(1, "invalid: --$type\_path <path>: '$path'");
128 }
129 return $fullpath;
130}
131
132sub passwd_add_entry($$);
133
134sub passwd_load($)
135{
136 my ($path) = @_;
137 my @lines;
138 my $passwd = undef;
139
140 open(PWD, "<$path") or die("Unable to open '$path' for read");
141 @lines = <PWD>;
142 close(PWD);
143
144 $passwd->{array} = ();
145 $passwd->{name} = {};
146 $passwd->{uid} = {};
147 $passwd->{path} = $path;
148
149 foreach my $line (@lines) {
150 passwd_add_entry($passwd, $line);
151 }
152
153 return $passwd;
154}
155
156sub group_add_entry($$);
157
158sub group_load($)
159{
160 my ($path) = @_;
161 my @lines;
162 my $group = undef;
163
164 open(GROUP, "<$path") or die("Unable to open '$path' for read");
165 @lines = <GROUP>;
166 close(GROUP);
167
168 $group->{array} = ();
169 $group->{name} = {};
170 $group->{gid} = {};
171 $group->{path} = $path;
172
173 foreach my $line (@lines) {
174 group_add_entry($group, $line);
175 }
176
177 return $group;
178}
179
180sub passwd_lookup_name($$)
181{
182 my ($passwd, $name) = @_;
183
184 return undef unless defined($passwd->{name}{$name});
185
186 return $passwd->{name}{$name};
187}
188
189sub group_lookup_name($$)
190{
191 my ($group, $name) = @_;
192
193 return undef unless defined($group->{name}{$name});
194
195 return $group->{name}{$name};
196}
197
198sub passwd_lookup_uid($$)
199{
200 my ($passwd, $uid) = @_;
201
202 return undef unless defined($passwd->{uid}{$uid});
203
204 return $passwd->{uid}{$uid};
205}
206
207sub group_lookup_gid($$)
208{
209 my ($group, $gid) = @_;
210
211 return undef unless defined($group->{gid}{$gid});
212
213 return $group->{gid}{$gid};
214}
215
216sub passwd_get_free_uid($)
217{
218 my ($passwd) = @_;
219 my $uid = 1000;
220
221 while (passwd_lookup_uid($passwd, $uid)) {
222 $uid++;
223 }
224
225 return $uid;
226}
227
228sub group_get_free_gid($)
229{
230 my ($group) = @_;
231 my $gid = 1000;
232
233 while (group_lookup_gid($group, $gid)) {
234 $gid++;
235 }
236
237 return $gid;
238}
239
240sub passwd_add_entry($$)
241{
242 my ($passwd, $str) = @_;
243
244 chomp $str;
245 my @e = split(':', $str);
246
247 push(@{$passwd->{array}}, \@e);
248 $passwd->{name}{$e[0]} = \@e;
249 $passwd->{uid}{$e[2]} = \@e;
250}
251
252sub group_add_entry($$)
253{
254 my ($group, $str) = @_;
255
256 chomp $str;
257 my @e = split(':', $str);
258
259 push(@{$group->{array}}, \@e);
260 $group->{name}{$e[0]} = \@e;
261 $group->{gid}{$e[2]} = \@e;
262}
263
264sub passwd_remove_entry($$)
265{
266 my ($passwd, $eref) = @_;
267
268 for (my $i = 0; defined($passwd->{array}[$i]); $i++) {
269 if ($eref == $passwd->{array}[$i]) {
270 $passwd->{array}[$i] = undef;
271 }
272 }
273
274 delete $passwd->{name}{${$eref}[0]};
275 delete $passwd->{uid}{${$eref}[2]};
276}
277
278sub group_remove_entry($$)
279{
280 my ($group, $eref) = @_;
281
282 for (my $i = 0; defined($group->{array}[$i]); $i++) {
283 if ($eref == $group->{array}[$i]) {
284 $group->{array}[$i] = undef;
285 }
286 }
287
288 delete $group->{name}{${$eref}[0]};
289 delete $group->{gid}{${$eref}[2]};
290}
291
292sub group_add_member($$$)
293{
294 my ($group, $eref, $username) = @_;
295
296 my @members;
297 my $str = @$eref[3] || undef;
298 if ($str) {
299 @members = split(",", $str);
300 }
301
302 foreach my $member (@members) {
303 if ($member and $member eq $username) {
304 die("account[$username] is already member of '@$eref[0]'");
305 }
306 }
307
308 push(@members, $username);
309
310 my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @members);
311
312 group_remove_entry($group, $eref);
313
314 group_add_entry($group, $gwent);
315}
316
317sub group_delete_member($$$)
318{
319 my ($group, $eref, $username) = @_;
320
321 my @members = undef;
322 my $str = @$eref[3] || undef;
323 if ($str) {
324 @members = split(",", $str);
325 }
326 my @new_members;
327 my $removed = 0;
328
329 foreach my $member (@members) {
330 if ($member and $member ne $username) {
331 push(@new_members, $member);
332 } else {
333 $removed = 1;
334 }
335 }
336
337 if ($removed != 1) {
338 die("account[$username] is not member of '@$eref[0]'");
339 }
340
341 my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @new_members);
342
343 group_remove_entry($group, $eref);
344
345 group_add_entry($group, $gwent);
346}
347
348sub passwd_save($)
349{
350 my ($passwd) = @_;
351 my @lines = ();
352 my $path = $passwd->{path};
353 my $tmppath = $path.$$;
354
355 foreach my $eref (@{$passwd->{array}}) {
356 next unless defined($eref);
357
358 my $line = join(':', @{$eref});
359 push(@lines, $line);
360 }
361
362 open(PWD, ">$tmppath") or die("Unable to open '$tmppath' for write");
363 print PWD join("\n", @lines)."\n";
364 close(PWD);
365 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
366}
367
368sub group_save($)
369{
370 my ($group) = @_;
371 my @lines = ();
372 my $path = $group->{path};
373 my $tmppath = $path.$$;
374
375 foreach my $eref (@{$group->{array}}) {
376 next unless defined($eref);
377
378 my $line = join(':', @{$eref});
379 if (scalar(@{$eref}) == 3) {
380 $line .= ":";
381 }
382 push(@lines, $line);
383 }
384
385 open(GROUP, ">$tmppath") or die("Unable to open '$tmppath' for write");
386 print GROUP join("\n", @lines)."\n";
387 close(GROUP);
388 rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
389}
390
391sub passwd_add($$$$)
392{
393 my ($path, $dummy, $dummy2, $name) = @_;
394
395 #print "passwd_add: '$name' in '$path'\n";
396
397 my $passwd = passwd_load($path);
398
399 my $e = passwd_lookup_name($passwd, $name);
400 die("account[$name] already exists in '$path'") if defined($e);
401
402 my $uid = passwd_get_free_uid($passwd);
403 my $gid = 65534;# nogroup gid
404
405 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
406
407 passwd_add_entry($passwd, $pwent);
408
409 passwd_save($passwd);
410
411 return 0;
412}
413
414sub passwd_delete($$$$)
415{
416 my ($path, $dummy, $dummy2, $name) = @_;
417
418 #print "passwd_delete: '$name' in '$path'\n";
419
420 my $passwd = passwd_load($path);
421
422 my $e = passwd_lookup_name($passwd, $name);
423 die("account[$name] does not exists in '$path'") unless defined($e);
424
425 passwd_remove_entry($passwd, $e);
426
427 passwd_save($passwd);
428
429 return 0;
430}
431
432sub group_add($$$$)
433{
434 my ($dummy, $dummy2, $path, $name) = @_;
435
436 #print "group_add: '$name' in '$path'\n";
437
438 my $group = group_load($path);
439
440 my $e = group_lookup_name($group, $name);
441 die("group[$name] already exists in '$path'") if defined($e);
442
443 my $gid = group_get_free_gid($group);
444
445 my $gwent = $name.":x:".$gid.":"."";
446
447 group_add_entry($group, $gwent);
448
449 group_save($group);
450
451 #printf("%d\n", $gid);
452
453 return 0;
454}
455
456sub group_delete($$$$)
457{
458 my ($dummy, $dummy2, $path, $name) = @_;
459
460 #print "group_delete: '$name' in '$path'\n";
461
462 my $group = group_load($path);
463
464 my $e = group_lookup_name($group, $name);
465 die("group[$name] does not exists in '$path'") unless defined($e);
466
467 group_remove_entry($group, $e);
468
469 group_save($group);
470
471 return 0;
472}
473
474sub member_add($$$$)
475{
476 my ($passwd_path, $username, $group_path, $groupname) = @_;
477
478 #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n";
479
480 my $group = group_load($group_path);
481
482 my $g = group_lookup_name($group, $groupname);
483 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
484
485 my $passwd = passwd_load($passwd_path);
486
487 my $u = passwd_lookup_name($passwd, $username);
488 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
489
490 group_add_member($group, $g, $username);
491
492 group_save($group);
493
494 return 0;
495}
496
497sub member_delete($$$$)
498{
499 my ($passwd_path, $username, $group_path, $groupname) = @_;
500
501 #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n";
502
503 my $group = group_load($group_path);
504
505 my $g = group_lookup_name($group, $groupname);
506 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
507
508 my $passwd = passwd_load($passwd_path);
509
510 my $u = passwd_lookup_name($passwd, $username);
511 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
512
513 group_delete_member($group, $g, $username);
514
515 group_save($group);
516
517 return 0;
518}
Note: See TracBrowser for help on using the repository browser.