Subject: Re: user/3698: chsh incorrectly changes login name
To: Todd C. Miller <Todd.Miller@courtesan.com>
From: gabriel ware <ware_g@epita.fr>
List: netbsd-help
Date: 03/08/2004 05:17:30
On Wed, Mar 03, 2004 at 12:15:01PM -0700, Todd C. Miller wrote:
> The following reply was made to PR user/3698; it has been noted by GNATS.
> 
> From: "Todd C. Miller" <Todd.Miller@courtesan.com>
> 
>  There are two problems:
>   1) pw_copy(3) matches existing entries based on the passed in passwd struct
>      This can be fixed by adding an additional username param.

Since its behavior is the same as the man page describes I don't think
pw_copy needs a fix. And as you said it'll end up breaking all the
packages using pw_copy.

>  
>   2) chpass is calling pw_mkdb with a username even if the username changed.
>      This can be fixed in chpass itself.
>

I don't really understand why is it a bug, could you explain ?

>  Both of these are fixable but #1 will affect other consumers of pw_copy()
>  

Maybe we should use another function to copy to /etc/ptmp instead of
pw_copy. If the old pw_name differs from the new one we should use a
function like the one used in userdel. Otherwise we can use pw_copy.

Below is a patch I made to the netbsd's chpass. It seems to work.
I hope I didn't break anything.

If you want me to make the same patch to OpenBSD you just have to ask ;)

Best regards,
  Gabriel

patch : apply to chpass.c
-------------------------------------------------
64a65,66
> #define MAXENTRYLEN 2048
> 
91a94,99
> 	char buf[MAXENTRYLEN];
> 	char *colon;
> 	int  namlen, collen, len, cc, error;
> 	FILE *master;
> 
> 	master = NULL;
274a283,331
> 	if (strcmp(pw->pw_name, old_pw.pw_name)) {
> 	  if ((master = fdopen(pfd, "r")) == NULL) {
> 	    pw_abort();
> 	    err(-1, "can't open fd for %s", _PATH_MASTERPASSWD);
> 	  }
> 	  namlen = strlen(old_pw.pw_name);
> 	  while (fgets(buf, sizeof(buf), master)) {
> 	    if ((colon = strchr(buf, ':')) == NULL) {
> 	      warnx("Malformed entry %s. Skipping", buf);
> 	      continue ;
> 	    }
> 	    collen = (size_t) (colon - buf);
> 	    if (namlen == collen && 
> 		strncmp(old_pw.pw_name, buf, namlen) == 0) {
> 	      /* modifying login entry */
> 	      len = snprintf(buf, sizeof(buf), "%s:%s:%d:%d:"
> #ifdef EXTENSIONS
> 		  				"%s"
> #endif
> 						":%ld:%ld:%s:%s:%s\n",
> 				pw->pw_name,
> 				pw->pw_passwd,
> 				pw->pw_uid,
> 				pw->pw_gid,
> #ifdef EXTENSIONS
> 				pw->pw_class,
> #endif 
> 				(long)pw->pw_change,
> 				(long)pw->pw_expire,
> 				pw->pw_gecos,
> 				pw->pw_dir,
> 				pw->pw_shell);
> 	      if (write(tfd, buf, len) != len) {
> 		pw_abort();
> 		err(-1, "can't add '%s'", buf);
> 	      }
> 	    } else {
> 	      /* copying */
> 	      len = strlen(buf);
> 	      if ((cc = write(tfd, buf, len)) != len) {
> 		pw_abort();
> 		err(-1, "short write to /etc/ptmp (%lld not %lld chars)",
> 		    (long long)cc,
> 		    (long long)len);
> 	      }
> 	    }
> 	
> 	  }
> 	} else {
275a333
> 	}
278,279c336,342
< 	if (pw_mkdb(username, 0) < 0)
< 		pw_error(NULL, 0, 1);
---
> 	if (strcmp(pw->pw_name, old_pw.pw_name) == 0)
> 	  error = pw_mkdb(username, 0);
> 	else
> 	  error = pw_mkdb(NULL, 0);
> 
> 	if (error < 0)
> 	  pw_error(NULL, 0, 1);

-- 
Gabriel WARE
tel  :  06 64 35 91 19
mail :  ware_g@epita.fr
http://www.epita.fr/~ware_g