source: trunk/server/lib/nss_wrapper/nss_wrapper.pl

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

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