Subject: rpc.yppasswd and NIS-specific passwd database
To: None <tech-userlevel@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-userlevel
Date: 06/10/2002 22:37:32
--R3G7APHDIzY6R/pk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,
the NIS server has all necessary hooks to use a different passwd
database from the system one (e.g serve passwd from /etc/nis/master.passwd
instead of /etc/master.passwd). This is especially usefull in evironnements
where you don't want to have user accounts on servers (or different user
accounts than the ones provided though NIS). The only problem is
rpc.yppasswdd, which uses getpwnam() to get the user's passwd entry.

The attached patche fixes it by remplacing getpwnam() with a function
getting the line from the NIS passwd file. This could also be a funtion
pw_getpwnam() in libutil, honoring pw_setprefix(). But going this way
would also require implementing pw_getpwuid() and pw_getpwent() to be
consistent. This would be a lot of code for only one customer, which would
only use one function.

Comments ? If I get no objections I'll commit this in the near future.

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
--

--R3G7APHDIzY6R/pk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="yppasswdd.diff"

Index: yppasswdd_mkpw.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/rpc.yppasswdd/yppasswdd_mkpw.c,v
retrieving revision 1.9
diff -u -r1.9 yppasswdd_mkpw.c
--- yppasswdd_mkpw.c	2001/08/18 19:35:32	1.9
+++ yppasswdd_mkpw.c	2002/06/10 20:24:30
@@ -68,9 +68,11 @@
 void
 make_passwd(yppasswd *argp, struct svc_req *rqstp, SVCXPRT *transp)
 {
-	struct passwd *pw;
+	struct passwd pw;
 	int pfd, tfd;
 	char mpwd[MAXPATHLEN];
+	char buf[8192]; /* from libutil */
+	FILE *fpw;
 
 #define REPLY(val)	do { \
 		int res = (val); \
@@ -91,12 +93,30 @@
 	}
 	handling_request = 1;
 
-	pw = getpwnam(argp->newpw.pw_name);
-	if (!pw)
+	(void)strlcpy(mpwd, pw_getprefix(), sizeof(mpwd));
+	(void)strlcat(mpwd, _PATH_MASTERPASSWD, sizeof(mpwd));
+	fpw = fopen(mpwd, "r");
+	if (fpw == NULL) {
+		warnx("%s", mpwd);
 		RETURN(1);
-
-	if (*pw->pw_passwd &&
-	    strcmp(crypt(argp->oldpass, pw->pw_passwd), pw->pw_passwd) != 0)
+	}
+	for(;;) {
+		if (fgets(buf, sizeof(buf), fpw) == NULL) {
+			if (feof(fpw))
+				warnx("%s: %s not found", mpwd,
+				    argp->newpw.pw_name);
+			else
+				warnx("%s: %s", mpwd, strerror(errno));
+			RETURN(1);
+		}
+		if (pw_scan(buf, &pw, NULL) == 0)
+			continue;
+		if (strncmp(argp->newpw.pw_name, pw.pw_name, MAXLOGNAME) == 0)
+			break;
+	}
+	fclose(fpw);
+	if (*pw.pw_passwd &&
+	    strcmp(crypt(argp->oldpass, pw.pw_passwd), pw.pw_passwd) != 0)
 		RETURN(1);
 
 	pw_init();
@@ -105,8 +125,6 @@
 		warnx("the passwd file is busy.");
 		RETURN(1);
 	}
-	(void)strlcpy(mpwd, pw_getprefix(), sizeof(mpwd));
-	(void)strlcat(mpwd, _PATH_MASTERPASSWD, sizeof(mpwd));
 	pfd = open(mpwd, O_RDONLY, 0);
 	if (pfd < 0) {
 		pw_abort();
@@ -120,17 +138,17 @@
 	 * class and reset the timer.
 	 */
 	if (!nopw) {
-		pw->pw_passwd = argp->newpw.pw_passwd;
-		pw->pw_change = 0;
+		pw.pw_passwd = argp->newpw.pw_passwd;
+		pw.pw_change = 0;
 	}
 	if (!nogecos)
-		pw->pw_gecos = argp->newpw.pw_gecos;
+		pw.pw_gecos = argp->newpw.pw_gecos;
 	if (!noshell)
-		pw->pw_shell = argp->newpw.pw_shell;
+		pw.pw_shell = argp->newpw.pw_shell;
 
-	pw_copy(pfd, tfd, pw, NULL);
+	pw_copy(pfd, tfd, &pw, NULL);
 
-	if (pw_mkdb(pw->pw_name, 0) < 0) {
+	if (pw_mkdb(pw.pw_name, 0) < 0) {
 		warnx("pw_mkdb failed");
 		pw_abort();
 		RETURN(1);

--R3G7APHDIzY6R/pk--