• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/lib/nss_wrapper/
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}
519