WHATSNEW: Start release notes for Samba 3.4.9.
[Samba.git] / lib / nss_wrapper / nss_wrapper.pl
blob1f1aef111887e0086e8b86d703a17a8fbc12ec6a
1 #!/usr/bin/perl
4 use strict;
6 use Getopt::Long;
7 use Cwd qw(abs_path);
9 my $opt_help = 0;
10 my $opt_passwd_path = undef;
11 my $opt_group_path = undef;
12 my $opt_action = undef;
13 my $opt_type = undef;
14 my $opt_name = undef;
15 my $opt_member = undef;
17 my $passwdfn = undef;
18 my $groupfn = undef;
19 my $memberfn = undef;
20 my $actionfn = undef;
22 sub passwd_add($$$$);
23 sub passwd_delete($$$$);
24 sub group_add($$$$);
25 sub group_delete($$$$);
26 sub member_add($$$$);
27 sub member_delete($$$$);
29 sub check_path($$);
31 my $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
41 sub usage($;$)
43 my ($ret, $msg) = @_;
45 print $msg."\n\n" if defined($msg);
47 print "usage:
49 --help|-h|-? Show this help.
51 --passwd_path <path> Path of the 'passwd' file.
52 --group_path <path> Path of the 'group' file.
54 --type <type> 'passwd', 'group' and 'member' are supported.
56 --action <action> 'add' or 'delete'.
58 --name <name> The name of the object.
60 --member <member> The name of the member.
62 exit($ret);
65 usage(1) if (not $result);
67 usage(0) if ($opt_help);
69 if (not defined($opt_action)) {
70 usage(1, "missing: --action [add|delete]");
72 if ($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'");
84 if (not defined($opt_type)) {
85 usage(1, "missing: --type [passwd|group|member]");
87 if ($opt_type eq "member" and not defined($opt_member)) {
88 usage(1, "missing: --member <member>");
90 my $opt_fullpath_passwd;
91 my $opt_fullpath_group;
92 if ($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'")
106 if (not defined($opt_name)) {
107 usage(1, "missing: --name <name>");
109 if ($opt_name eq "") {
110 usage(1, "invalid: --name <name>");
113 exit $actionfn->($opt_fullpath_passwd, $opt_member, $opt_fullpath_group, $opt_name);
115 sub check_path($$)
117 my ($path,$type) = @_;
119 if (not defined($path)) {
120 usage(1, "missing: --$type\_path <path>");
122 if ($path eq "" or $path eq "/") {
123 usage(1, "invalid: --$type\_path <path>: '$path'");
125 my $fullpath = abs_path($path);
126 if (not defined($fullpath)) {
127 usage(1, "invalid: --$type\_path <path>: '$path'");
129 return $fullpath;
132 sub passwd_add_entry($$);
134 sub passwd_load($)
136 my ($path) = @_;
137 my @lines;
138 my $passwd = undef;
140 open(PWD, "<$path") or die("Unable to open '$path' for read");
141 @lines = <PWD>;
142 close(PWD);
144 $passwd->{array} = ();
145 $passwd->{name} = {};
146 $passwd->{uid} = {};
147 $passwd->{path} = $path;
149 foreach my $line (@lines) {
150 passwd_add_entry($passwd, $line);
153 return $passwd;
156 sub group_add_entry($$);
158 sub group_load($)
160 my ($path) = @_;
161 my @lines;
162 my $group = undef;
164 open(GROUP, "<$path") or die("Unable to open '$path' for read");
165 @lines = <GROUP>;
166 close(GROUP);
168 $group->{array} = ();
169 $group->{name} = {};
170 $group->{gid} = {};
171 $group->{path} = $path;
173 foreach my $line (@lines) {
174 group_add_entry($group, $line);
177 return $group;
180 sub passwd_lookup_name($$)
182 my ($passwd, $name) = @_;
184 return undef unless defined($passwd->{name}{$name});
186 return $passwd->{name}{$name};
189 sub group_lookup_name($$)
191 my ($group, $name) = @_;
193 return undef unless defined($group->{name}{$name});
195 return $group->{name}{$name};
198 sub passwd_lookup_uid($$)
200 my ($passwd, $uid) = @_;
202 return undef unless defined($passwd->{uid}{$uid});
204 return $passwd->{uid}{$uid};
207 sub group_lookup_gid($$)
209 my ($group, $gid) = @_;
211 return undef unless defined($group->{gid}{$gid});
213 return $group->{gid}{$gid};
216 sub passwd_get_free_uid($)
218 my ($passwd) = @_;
219 my $uid = 1000;
221 while (passwd_lookup_uid($passwd, $uid)) {
222 $uid++;
225 return $uid;
228 sub group_get_free_gid($)
230 my ($group) = @_;
231 my $gid = 1000;
233 while (group_lookup_gid($group, $gid)) {
234 $gid++;
237 return $gid;
240 sub passwd_add_entry($$)
242 my ($passwd, $str) = @_;
244 chomp $str;
245 my @e = split(':', $str);
247 push(@{$passwd->{array}}, \@e);
248 $passwd->{name}{$e[0]} = \@e;
249 $passwd->{uid}{$e[2]} = \@e;
252 sub group_add_entry($$)
254 my ($group, $str) = @_;
256 chomp $str;
257 my @e = split(':', $str);
259 push(@{$group->{array}}, \@e);
260 $group->{name}{$e[0]} = \@e;
261 $group->{gid}{$e[2]} = \@e;
264 sub passwd_remove_entry($$)
266 my ($passwd, $eref) = @_;
268 for (my $i = 0; defined($passwd->{array}[$i]); $i++) {
269 if ($eref == $passwd->{array}[$i]) {
270 $passwd->{array}[$i] = undef;
274 delete $passwd->{name}{${$eref}[0]};
275 delete $passwd->{uid}{${$eref}[2]};
278 sub group_remove_entry($$)
280 my ($group, $eref) = @_;
282 for (my $i = 0; defined($group->{array}[$i]); $i++) {
283 if ($eref == $group->{array}[$i]) {
284 $group->{array}[$i] = undef;
288 delete $group->{name}{${$eref}[0]};
289 delete $group->{gid}{${$eref}[2]};
292 sub group_add_member($$$)
294 my ($group, $eref, $username) = @_;
296 my @members;
297 my $str = @$eref[3] || undef;
298 if ($str) {
299 @members = split(",", $str);
302 foreach my $member (@members) {
303 if ($member and $member eq $username) {
304 die("account[$username] is already member of '@$eref[0]'");
308 push(@members, $username);
310 my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @members);
312 group_remove_entry($group, $eref);
314 group_add_entry($group, $gwent);
317 sub group_delete_member($$$)
319 my ($group, $eref, $username) = @_;
321 my @members = undef;
322 my $str = @$eref[3] || undef;
323 if ($str) {
324 @members = split(",", $str);
326 my @new_members;
327 my $removed = 0;
329 foreach my $member (@members) {
330 if ($member and $member ne $username) {
331 push(@new_members, $member);
332 } else {
333 $removed = 1;
337 if ($removed != 1) {
338 die("account[$username] is not member of '@$eref[0]'");
341 my $gwent = @$eref[0].":x:".@$eref[2].":".join(",", @new_members);
343 group_remove_entry($group, $eref);
345 group_add_entry($group, $gwent);
348 sub passwd_save($)
350 my ($passwd) = @_;
351 my @lines = ();
352 my $path = $passwd->{path};
353 my $tmppath = $path.$$;
355 foreach my $eref (@{$passwd->{array}}) {
356 next unless defined($eref);
358 my $line = join(':', @{$eref});
359 push(@lines, $line);
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");
368 sub group_save($)
370 my ($group) = @_;
371 my @lines = ();
372 my $path = $group->{path};
373 my $tmppath = $path.$$;
375 foreach my $eref (@{$group->{array}}) {
376 next unless defined($eref);
378 my $line = join(':', @{$eref});
379 if (scalar(@{$eref}) == 3) {
380 $line .= ":";
382 push(@lines, $line);
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");
391 sub passwd_add($$$$)
393 my ($path, $dummy, $dummy2, $name) = @_;
395 #print "passwd_add: '$name' in '$path'\n";
397 my $passwd = passwd_load($path);
399 my $e = passwd_lookup_name($passwd, $name);
400 die("account[$name] already exists in '$path'") if defined($e);
402 my $uid = passwd_get_free_uid($passwd);
403 my $gid = 65534;# nogroup gid
405 my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
407 passwd_add_entry($passwd, $pwent);
409 passwd_save($passwd);
411 return 0;
414 sub passwd_delete($$$$)
416 my ($path, $dummy, $dummy2, $name) = @_;
418 #print "passwd_delete: '$name' in '$path'\n";
420 my $passwd = passwd_load($path);
422 my $e = passwd_lookup_name($passwd, $name);
423 die("account[$name] does not exists in '$path'") unless defined($e);
425 passwd_remove_entry($passwd, $e);
427 passwd_save($passwd);
429 return 0;
432 sub group_add($$$$)
434 my ($dummy, $dummy2, $path, $name) = @_;
436 #print "group_add: '$name' in '$path'\n";
438 my $group = group_load($path);
440 my $e = group_lookup_name($group, $name);
441 die("group[$name] already exists in '$path'") if defined($e);
443 my $gid = group_get_free_gid($group);
445 my $gwent = $name.":x:".$gid.":"."";
447 group_add_entry($group, $gwent);
449 group_save($group);
451 #printf("%d\n", $gid);
453 return 0;
456 sub group_delete($$$$)
458 my ($dummy, $dummy2, $path, $name) = @_;
460 #print "group_delete: '$name' in '$path'\n";
462 my $group = group_load($path);
464 my $e = group_lookup_name($group, $name);
465 die("group[$name] does not exists in '$path'") unless defined($e);
467 group_remove_entry($group, $e);
469 group_save($group);
471 return 0;
474 sub member_add($$$$)
476 my ($passwd_path, $username, $group_path, $groupname) = @_;
478 #print "member_add: adding '$username' in '$passwd_path' to '$groupname' in '$group_path'\n";
480 my $group = group_load($group_path);
482 my $g = group_lookup_name($group, $groupname);
483 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
485 my $passwd = passwd_load($passwd_path);
487 my $u = passwd_lookup_name($passwd, $username);
488 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
490 group_add_member($group, $g, $username);
492 group_save($group);
494 return 0;
497 sub member_delete($$$$)
499 my ($passwd_path, $username, $group_path, $groupname) = @_;
501 #print "member_delete: removing '$username' in '$passwd_path' from '$groupname' in '$group_path'\n";
503 my $group = group_load($group_path);
505 my $g = group_lookup_name($group, $groupname);
506 die("group[$groupname] does not exists in '$group_path'") unless defined($g);
508 my $passwd = passwd_load($passwd_path);
510 my $u = passwd_lookup_name($passwd, $username);
511 die("account[$username] does not exists in '$passwd_path'") unless defined($u);
513 group_delete_member($group, $g, $username);
515 group_save($group);
517 return 0;