nss_wrapper: add nss_wrapper.pl
authormetze <metze@0c0555d6-39d7-0310-84fc-f1cc0bd64818>
Mon, 5 Nov 2007 15:42:38 +0000 (15:42 +0000)
committerStefan Metzmacher <metze@samba.org>
Fri, 9 Nov 2007 08:52:58 +0000 (09:52 +0100)
This script will be used to add|delete passwd|group entries

metze

git-svn-id: svn+ssh://svn.samba.org/data/svn/samba/branches/SAMBA_4_0@25837 0c0555d6-39d7-0310-84fc-f1cc0bd64818

source/lib/nss_wrapper/nss_wrapper.pl [new file with mode: 0644]

diff --git a/source/lib/nss_wrapper/nss_wrapper.pl b/source/lib/nss_wrapper/nss_wrapper.pl
new file mode 100644 (file)
index 0000000..b1c9be5
--- /dev/null
@@ -0,0 +1,265 @@
+#!/usr/bin/perl
+#
+
+use strict;
+
+use Getopt::Long;
+use Cwd qw(abs_path);
+
+my $opt_help = 0;
+my $opt_path = undef;
+my $opt_action = undef;
+my $opt_type = undef;
+my $opt_name = undef;
+
+my $passwdfn = undef;
+my $groupfn = undef;
+my $actionfn = undef;
+
+sub passwd_add($$);
+sub passwd_delete($$);
+sub group_add($$);
+sub group_delete($$);
+
+my $result = GetOptions(
+       'help|h|?'      => \$opt_help,
+       'path=s'        => \$opt_path,
+       'action=s'      => \$opt_action,
+       'type=s'        => \$opt_type,
+       'name=s'        => \$opt_name
+);
+
+sub usage($;$)
+{
+       my ($ret, $msg) = @_;
+
+       print $msg."\n\n" if defined($msg);
+
+       print "usage:
+
+       --help|-h|-?            Show this help.
+
+       --path <path>           Path of the 'passwd' or 'group' file.
+
+       --type <type>           Only 'passwd' is supported yet,
+                               but 'group' and maybe 'member' will be added
+                               in future.
+
+       --action <action>       'add' or 'delete'.
+
+       --name <name>           The name of the object.
+";
+       exit($ret);
+}
+
+usage(1) if (not $result);
+
+usage(0) if ($opt_help);
+
+if (not defined($opt_path)) {
+       usage(1, "missing: --path <path>");
+}
+if ($opt_path eq "" or $opt_path eq "/") {
+       usage(1, "invalid: --path <path>: '$opt_path'");
+}
+my $opt_fullpath = abs_path($opt_path);
+if (not defined($opt_fullpath)) {
+       usage(1, "invalid: --path <path>: '$opt_path'");
+}
+
+
+if (not defined($opt_action)) {
+       usage(1, "missing: --action [add|delete]");
+}
+if ($opt_action eq "add") {
+       $passwdfn = \&passwd_add;
+       $groupfn = \&group_add;
+} elsif ($opt_action eq "delete") {
+       $passwdfn = \&passwd_delete;
+       $groupfn = \&group_delete;
+} else {
+       usage(1, "invalid: --action [add|delete]: '$opt_action'");
+}
+
+if (not defined($opt_type)) {
+       usage(1, "missing: --type [passwd|group]");
+}
+if ($opt_type eq "passwd") {
+       $actionfn = $passwdfn;
+} elsif ($opt_type eq "group") {
+       $actionfn = $groupfn;
+} else {
+       usage(1, "invalid: --type [passwd|group]: '$opt_type'")
+}
+
+if (not defined($opt_name)) {
+       usage(1, "missing: --name <name>");
+}
+if ($opt_name eq "") {
+       usage(1, "invalid: --name <name>");
+}
+
+exit $actionfn->($opt_fullpath, $opt_name);
+
+sub passwd_add_entry($$);
+
+sub passwd_load($)
+{
+       my ($path) = @_;
+       my @lines;
+       my $passwd = undef;
+
+       open(PWD, "<$path") or die("Unable to open '$path' for read");
+       @lines = <PWD>;
+       close(PWD);
+
+       $passwd->{array} = ();
+       $passwd->{name} = {};
+       $passwd->{uid} = {};
+       $passwd->{path} = $path;
+
+       foreach my $line (@lines) {
+               passwd_add_entry($passwd, $line);
+       }
+
+       return $passwd;
+}
+
+sub passwd_lookup_name($$)
+{
+       my ($passwd, $name) = @_;
+
+       return undef unless defined($passwd->{name}{$name});
+
+       return $passwd->{name}{$name};
+}
+
+sub passwd_lookup_uid($$)
+{
+       my ($passwd, $uid) = @_;
+
+       return undef unless defined($passwd->{uid}{$uid});
+
+       return $passwd->{uid}{$uid};
+}
+
+sub passwd_get_free_uid($)
+{
+       my ($passwd) = @_;
+       my $uid = 1000;
+
+       while (passwd_lookup_uid($passwd, $uid)) {
+               $uid++;
+       }
+
+       return $uid;
+}
+
+sub passwd_add_entry($$)
+{
+       my ($passwd, $str) = @_;
+
+       chomp $str;
+       my @e = split(':', $str);
+
+       push(@{$passwd->{array}}, \@e);
+       $passwd->{name}{$e[0]} = \@e;
+       $passwd->{uid}{$e[2]} = \@e;
+}
+
+sub passwd_remove_entry($$)
+{
+       my ($passwd, $eref) = @_;
+
+       for(my $i; defined($passwd->{array}[$i]); $i++) {
+               if ($eref == $passwd->{array}[$i]) {
+                       $passwd->{array}[$i] = undef;
+               }
+       }
+
+       delete $passwd->{name}{${$eref}[0]};
+       delete $passwd->{uid}{${$eref}[2]};
+}
+
+sub passwd_save($)
+{
+       my ($passwd) = @_;
+       my @lines = ();
+       my $path = $passwd->{path};
+       my $tmppath = $path.$$;
+
+       foreach my $eref (@{$passwd->{array}}) {
+               next unless defined($eref);
+
+               my $line = join(':', @{$eref});
+               push(@lines, $line);
+       }
+
+       open(PWD, ">$tmppath") or die("Unable to open '$tmppath' for write");
+       print PWD join("\n", @lines)."\n";
+       close(PWD);
+       rename($tmppath, $path) or die("Unable to rename $tmppath => $path");
+}
+
+sub passwd_add($$)
+{
+       my ($path, $name) = @_;
+
+       #print "passwd_add: '$name' in '$path'\n";
+
+       my $passwd = passwd_load($path);
+
+       my $e = passwd_lookup_name($passwd, $name);
+       die("account[$name] already exists in '$path'") if defined($e);
+
+       my $uid = passwd_get_free_uid($passwd);
+       my $gid = 65534;# nogroup gid
+
+       my $pwent = $name.":x:".$uid.":".$gid.":".$name." gecos:/nodir:/bin/false";
+
+       passwd_add_entry($passwd, $pwent);
+
+       passwd_save($passwd);
+
+       return 0;
+}
+
+sub passwd_delete($$)
+{
+       my ($path, $name) = @_;
+
+       #print "passwd_delete: '$name' in '$path'\n";
+
+       my $passwd = passwd_load($path);
+
+       my $e = passwd_lookup_name($passwd, $name);
+       die("account[$name] does not exists in '$path'") unless defined($e);
+
+       passwd_remove_entry($passwd, $e);
+
+       passwd_save($passwd);
+
+       return 0;
+}
+
+sub group_add($$)
+{
+       my ($path, $name) = @_;
+
+       #print "group_add: '$name' in '$path'\n";
+
+       die("group_add: not implemented yet!");
+
+       return 0;
+}
+
+sub group_delete($$)
+{
+       my ($path, $name) = @_;
+
+       #print "group_delete: '$name' in '$path'\n";
+
+       die("group_delete: not implemented yet!");
+
+       return 0;
+}