Subject: chpass
To: None <freebsd-bugs@freefall.cdrom.com>
From: Heikki Suonsivu <hsu@clinet.fi>
List: netbsd-bugs
Date: 12/11/1994 06:49:07
[This is for FB1.1.5.1 but by a quick glance, 4.4 code seems to be similar
in this respect.  I didn't verify this]

chfn allows changing user name by default; if user name is changed to
"restricted", chfn gets does a null pointer dereference when strlening the
length of new gcos field when malloc'ing space for it (as save field is
never initialized).  I don't know if changing the user name should be
allowed by default or not; we wish to restrict it.

diff -c /scratch/hsu/usr/src/usr.bin/chpass/edit.c usr.bin/chpass/edit.c
*** /scratch/hsu/usr/src/usr.bin/chpass/edit.c	Sat Jun 12 17:54:00 1993
--- usr.bin/chpass/edit.c	Sun Dec 11 05:36:59 1994
***************
*** 112,125 ****
  	else
  		list[E_SHELL].restricted = 1;
  	bp = pw->pw_gecos;
  	p = strsep(&bp, ",");
! 	(void)fprintf(fp, "Full Name: %s\n", p ? p : "");
  	p = strsep(&bp, ",");
! 	(void)fprintf(fp, "Location: %s\n", p ? p : "");
  	p = strsep(&bp, ",");
! 	(void)fprintf(fp, "Office Phone: %s\n", p ? p : "");
  	p = strsep(&bp, ",");
! 	(void)fprintf(fp, "Home Phone: %s\n", p ? p : "");
  
  	(void)fchown(fd, getuid(), getgid());
  	(void)fclose(fp);
--- 112,144 ----
  	else
  		list[E_SHELL].restricted = 1;
  	bp = pw->pw_gecos;
+ 
+ 	/* XXX save strings are dupped, and not freed.  This is not a problem
+ 	   with chpass, but don't copy this code your applications as it is if
+ 	   you don't take this into account. */ 
  	p = strsep(&bp, ",");
! 	if (p)
! 	  list[E_NAME].save = strdup(p);
! 	if (!list[E_NAME].restricted)
! 	  (void)fprintf(fp, "Full Name: %s\n", p ? p : "");
! 	
  	p = strsep(&bp, ",");
! 	if (p)
! 	  list[E_LOCATE].save = strdup(p);
! 	if (!list[E_LOCATE].restricted)
! 	  (void)fprintf(fp, "Location: %s\n", p ? p : "");
! 	
  	p = strsep(&bp, ",");
! 	if (p)
! 	  list[E_BPHONE].save = strdup(p);
! 	if (!list[E_BPHONE].restricted)
! 	  (void)fprintf(fp, "Office Phone: %s\n", p ? p : "");
! 	
  	p = strsep(&bp, ",");
! 	if (p)
! 	  list[E_HPHONE].save = strdup(p);
! 	if (!list[E_HPHONE].restricted)
! 	  (void)fprintf(fp, "Home Phone: %s\n", p ? p : "");
  
  	(void)fchown(fd, getuid(), getgid());
  	(void)fclose(fp);
diff -c /scratch/hsu/usr/src/usr.bin/chpass/table.c usr.bin/chpass/table.c
*** /scratch/hsu/usr/src/usr.bin/chpass/table.c	Sat Jun 12 17:54:00 1993
--- usr.bin/chpass/table.c	Sun Dec 11 05:25:12 1994
***************
*** 53,59 ****
  	{ "class",		p_class,  1,   5, e1,   },
  	{ "change",		p_change, 1,   6, NULL, },
  	{ "expire",		p_expire, 1,   6, NULL, },
! 	{ "full name",		p_gecos,  0,   9, e2,   },
  	{ "office phone",	p_gecos,  0,  12, e2,   },
  	{ "home phone",		p_gecos,  0,  10, e2,   },
  	{ "location",		p_gecos,  0,   8, e2,   },
--- 53,59 ----
  	{ "class",		p_class,  1,   5, e1,   },
  	{ "change",		p_change, 1,   6, NULL, },
  	{ "expire",		p_expire, 1,   6, NULL, },
! 	{ "full name",		p_gecos,  1,   9, e2,   },
  	{ "office phone",	p_gecos,  0,  12, e2,   },
  	{ "home phone",		p_gecos,  0,  10, e2,   },
  	{ "location",		p_gecos,  0,   8, e2,   },