Subject: Re: rpc.yppasswdd problems
To: Martti Kuparinen <martti.kuparinen@iki.fi>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: netbsd-help
Date: 06/10/2002 22:26:13
--82I3+IH0IqGh5yIs
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Mon, Jun 10, 2002 at 12:31:17PM +0300, Martti Kuparinen wrote:
> Hi!
> 
> I'm having problems with my NIS server. Users can authenticate just fine
> against this server (1.6_BETA1) but nobody can change the passwords, not
> even root. And to make things more difficult to debug, there's nothing
> in the logs to help. The only thing in the logs is this line in
> /var/log/authlog:
> 
> Jun 10 11:20:16 server rpcbind: connect from x.x.x.x to getport/addr(yppasswdd)
> 
> server:~> passwd
> Changing YP password for martti.
> Old password:
> New password:
> Retype new password:
> Couldn't change YP password.
> 
> server:~> ypcat passwd
> martti:*:1000:1000:Martti Kuparinen:/home/martti:/bin/bash
> [...]
> 
> server:~> ls -l /var/yp/etc
> total 4
> -rw-r--r--  1 root  wheel  153 May 17 11:22 group
> -rw-r--r--  1 root  wheel  108 May 17 11:22 hosts
> -rw-------  1 root  wheel  601 May 17 09:37 master.passwd
> -rw-r--r--  1 root  wheel  435 May 17 09:37 passwd
> 
> server:~> cat /etc/rc.conf
> sshd=YES
> wscons=YES
> rpcbind=YES
> ypbind=YES
> ypserv=YES
> yppasswdd=YES           yppasswdd_flags="-d /var/yp"

Yes, I ran into this too. rpc.yppasswdd uses getpwnam() to get the
user's passwd entry. This is wrong if the server isn't running NIS and
the NIS passwd file isn't /etc/master.passwd.

I fixed this problem in the attached patch. This is for 1.6.
Should be commited soon unless I get objections (I'm going to post this
to tech-userlevel)

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

--82I3+IH0IqGh5yIs
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);

--82I3+IH0IqGh5yIs--