From 288a7f427fa56c88f5dff8eedc86bf4837cc8205 Mon Sep 17 00:00:00 2001
From: Rex Feany <rfeany@rf.cx>
Date: Fri, 18 Mar 2005 09:59:44 +0000
Subject: [PATCH 1/1] new stuff added, this is a patch and a script to allow my
 netbsd client talk to my linux nis server

---
 Makefile.patch   |  34 +++++++++++++++
 README           |  24 +++++++++++
 master-passwd.pl | 109 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 167 insertions(+)
 create mode 100644 Makefile.patch
 create mode 100644 README
 create mode 100755 master-passwd.pl

diff --git a/Makefile.patch b/Makefile.patch
new file mode 100644
index 0000000..6582e97
--- /dev/null
+++ b/Makefile.patch
@@ -0,0 +1,34 @@
+--- Makefile.old	2005-03-17 18:40:44.570660984 -0800
++++ Makefile	2005-03-17 18:41:04.779588760 -0800
+@@ -111,6 +111,7 @@
+ #ALL +=	amd.home auto.master auto.home auto.local
+ #ALL +=	timezone locale networks netmasks
+ ALL += auto.master auto.home amd.home
++ALL += master.passwd
+ 
+ # Autodetect /etc/shadow if it's there
+ ifneq ($(wildcard $(SHADOW)),)
+@@ -158,6 +159,7 @@
+ timezone:      timezone.byname
+ locale:                locale.byname
+ netmasks:      netmasks.byaddr
++master.passwd: master.passwd.byname
+ 
+ ypservers: $(YPSERVERS) $(YPDIR)/Makefile
+ 	@echo "Updating $@..."
+@@ -351,6 +353,15 @@
+ 	-@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
+ endif
+ 
++master.passwd.byname: $(PASSWD) $(SHADOW) $(YPDIR)/Makefile
++	@echo "Updating $@..."
++	@$(UMASK); \
++	../master-passwd.pl /etc/passwd /etc/shadow | \
++	$(AWK) -F: '!/^[-+#]/ { if ($$1 != "" && $$3 >= $(MINUID) && $$3 != $(NFSNOBODYUID) ) \
++	   print $$1"\t"$$0 }' | \
++	   $(DBLOAD) -i /etc/master.passwd -o $(YPMAPDIR)/$@ - $@
++	-@$(NOPUSH) || $(YPPUSH) -d $(DOMAIN) $@
++
+ passwd.adjunct.byname: $(ADJUNCT) $(YPDIR)/Makefile
+ 	@echo "Updating $@..."
+ 	@$(UMASK); \
diff --git a/README b/README
new file mode 100644
index 0000000..99c22ea
--- /dev/null
+++ b/README
@@ -0,0 +1,24 @@
+Patch and bits for linux yp/nis server to handle
+netbsd clients (maybe *bsd?)
+
+The problem is linux uses shadow, netbsd uses master.passwd
+and they are different formats. This generates a master.passwd
+file from the linux info. It requires perl and Class::Date to
+be installed.
+
+It tries to handle expiration/password change but it probably
+doesn't work (I havent tested it).
+
+Install -
+
+stick master-passwd.pl in /var/yp
+make sure its output looks right:
+
+./master-passwd.pl /etc/passwd /etc/shadow
+
+patch /var/yp/Makefile and then you should
+be good to go!
+
+take care
+/rex.
+laeos@laeos.net
diff --git a/master-passwd.pl b/master-passwd.pl
new file mode 100755
index 0000000..2446029
--- /dev/null
+++ b/master-passwd.pl
@@ -0,0 +1,109 @@
+#!/usr/bin/perl -w
+#
+# convert from linux passwd/shadow to master.passwd
+#
+use strict;
+use Class::Date qw(:errors date now);
+use Data::Dumper;
+
+
+sub read_file {
+    my ($f, $data, $fields) = @_;
+
+    open(FH, '<', $f) || die "can't open $f";
+    while (<FH>) {
+	chomp;
+	my @list = split(':');
+
+	for (my $i = 0; $i < scalar(@$fields); $i++) {
+	    $data->{$list[0]}->{$fields->[$i]} = $list[$i];
+	}
+    }
+    close(FH);
+}
+
+sub write_file {
+    my ($fh, $data, $fields) = @_;
+
+    foreach my $key (keys(%$data)) {
+	print $fh join(':', map { my $x = $data->{$key}->{$_}; die $_ unless(defined($x)); $x } @$fields), "\n";
+    }
+}
+
+sub read_passwd {
+    my ($f, $users) = @_;
+    &read_file($f, $users, 
+	    ['login', 'pw', 'uid', 'gid', 'gecos', 'home', 'shell']);
+}
+
+sub read_shadow {
+    my ($f, $users) = @_;
+    &read_file($f, $users, 
+	    ['login', 'pw', 'last_changed', 'may_change', 'must_change', 'expire_warn', 'disable', 'disabled_since', 'reserved']);
+}
+
+sub write_bsd {
+    my ($users) = @_;
+    &write_file(\*STDOUT, $users, 
+    	[ 'login', 'pw', 'uid', 'gid', 'class', 'change', 'expire', 'gecos', 'home', 'shell' ]);
+}
+
+sub days_to_epoch_seconds {
+    my ($days) = @_;
+    my $from = now;
+    my $rel = new Class::Date::Rel { day => $days };
+    my $r = $from+$rel;
+    return $r->epoch;
+}
+
+sub conv_class {
+    my ($u, $d) = @_;
+    $d->{'class'} = '';
+}
+
+sub conv_change {
+    my ($u, $d) = @_;
+    my $f = $d->{'must_change'};
+
+    if (defined($f) && $f > 0) {
+    	$d->{'change'} = &days_to_epoch_seconds($f);
+    } elsif ($f == '-1') {
+    	$d->{'change'} = -1;
+    } else {
+    	$d->{'change'} = '';
+    }
+}
+
+sub conv_expire {
+    my ($u, $d) = @_;
+    $d->{'expire'} = '';
+}
+
+sub conv_fields {
+    my ($data) = @_;
+
+    while (my ($user, $data) = each(%$data)) {
+	&conv_class($user, $data);
+	&conv_change($user, $data);
+	&conv_expire($user, $data);
+    }
+}
+
+sub usage {
+	print STDERR "Usage: $0 <passwd> <shadow>\n";
+	exit 1;
+}
+
+sub main {
+    &usage() if (scalar(@ARGV) != 2);
+    my %users;
+
+    &read_passwd($ARGV[0], \%users);
+    &read_shadow($ARGV[1], \%users);
+    &conv_fields(\%users);
+    &write_bsd(\%users);
+}
+
+&main;
+
+# all done!
-- 
2.39.5