wsr@lmi-angel.UUCP (Wolfgang Rupprecht) (05/22/86)
[] Has anyone else noticed how /etc/passwd often gets lines of the form: -- joe::100:100:joe shmoe:/usr/joe:/bin/csh foo:xyz:101:100:bar foo:/usr/foo:/bin/ksh <----- blank line ::0:0::: <----- empty templates ::0:0::: ::0:0::: -- Well, I finally got motivated to look into what causes this. It turns out that both "passwd (1)" and "chsh (1)" behave badly if ANY invalid lines are found in /etc/passwd. Infact, a *blank line* will produce a 'struct passwd' that has all pointers to null length strings for the char pointer fields, and 0's for the integer fields. These struct passwds are then written to the new passwd file via a printf(). This causes the NULL and zero fields. This happens, for example, whenever you have a *blank line* as the last line of /etc/passwd. The problem is that "getpwent (2)" is less than generous with blank lines. Below is a set of diffs for bullet-proofing getpwent(). Oh yes, these blank entries *are* security loopholes, *big ones*. If you don't believe me, put a blank line in /etc/passwd, then generate a blank entry or two via a 'chsh' or two. Then try a: su '' *poof* you are root (the nameless one). I am very surprised that ATT and Berkley haven't fixed this yet. (If you don't have lib sources; you can't fix getpwent. Complain to Ma Belle and/or Bezerkly. :-) In the mean time just KEEP the BLANK lines out of /etc/passwd. You'll be perfectly safe then.) -- Wolfgang Rupprecht {harvard|decvax!cca|mit-eddie}!lmi-angel!wsr *** getpwent.c~ Mon Jun 27 18:07:08 1983 --- getpwent.c Wed May 21 18:10:24 1986 *************** *** 34,41 return(p); } ! struct passwd * ! getpwent() { register char *p; --- 34,42 ----- return(p); } ! static char * ! npwskip(p) ! register char *p; { while( *p && *p != ':' ) ++p; *************** *** 37,43 struct passwd * getpwent() { ! register char *p; if (pwf == NULL) { if( (pwf = fopen( PASSWD, "r" )) == NULL ) --- 38,49 ----- npwskip(p) register char *p; { ! while( *p && *p != ':' ) ! ++p; ! if (*p != ':') ! return 0; ! if( *p ) *p++ = 0; ! return (p); } *************** *** 39,51 { register char *p; ! if (pwf == NULL) { ! if( (pwf = fopen( PASSWD, "r" )) == NULL ) ! return(0); ! } ! p = fgets(line, BUFSIZ, pwf); ! if (p==NULL) ! return(0); passwd.pw_name = p; p = pwskip(p); passwd.pw_passwd = p; --- 45,67 ----- if( *p ) *p++ = 0; return (p); ! ! } ! ! struct passwd * ! getpwent () ! { ! register char *p; ! ! if (pwf == NULL) ! { ! if ((pwf = fopen (PASSWD, "r")) == NULL) ! return (0); ! } ! while (p = fgets (line, BUFSIZ, pwf)) ! { ! if ((*p == NULL) || (*p == ':')) /* get rid of old trash */ ! continue; passwd.pw_name = p; p = npwskip (p); if (p == NULL) *************** *** 47,53 if (p==NULL) return(0); passwd.pw_name = p; ! p = pwskip(p); passwd.pw_passwd = p; p = pwskip(p); passwd.pw_uid = atoi(p); --- 63,71 ----- if ((*p == NULL) || (*p == ':')) /* get rid of old trash */ continue; passwd.pw_name = p; ! p = npwskip (p); ! if (p == NULL) ! continue; passwd.pw_passwd = p; p = npwskip (p); if (p == NULL) *************** *** 49,58 passwd.pw_name = p; p = pwskip(p); passwd.pw_passwd = p; ! p = pwskip(p); ! passwd.pw_uid = atoi(p); ! p = pwskip(p); ! passwd.pw_gid = atoi(p); passwd.pw_quota = 0; passwd.pw_comment = EMPTY; p = pwskip(p); --- 67,80 ----- if (p == NULL) continue; passwd.pw_passwd = p; ! p = npwskip (p); ! if (p == NULL) ! continue; ! passwd.pw_uid = atoi (p); ! p = npwskip (p); ! if (p == NULL) ! continue; ! passwd.pw_gid = atoi (p); passwd.pw_quota = 0; passwd.pw_comment = EMPTY; p = npwskip (p); *************** *** 55,61 passwd.pw_gid = atoi(p); passwd.pw_quota = 0; passwd.pw_comment = EMPTY; ! p = pwskip(p); passwd.pw_gecos = p; p = pwskip(p); passwd.pw_dir = p; --- 77,85 ----- passwd.pw_gid = atoi (p); passwd.pw_quota = 0; passwd.pw_comment = EMPTY; ! p = npwskip (p); ! if (p == NULL) ! continue; passwd.pw_gecos = p; p = npwskip (p); if (p == NULL) *************** *** 57,63 passwd.pw_comment = EMPTY; p = pwskip(p); passwd.pw_gecos = p; ! p = pwskip(p); passwd.pw_dir = p; p = pwskip(p); passwd.pw_shell = p; --- 81,89 ----- if (p == NULL) continue; passwd.pw_gecos = p; ! p = npwskip (p); ! if (p == NULL) ! continue; passwd.pw_dir = p; p = pwskip (p); passwd.pw_shell = p; *************** *** 59,65 passwd.pw_gecos = p; p = pwskip(p); passwd.pw_dir = p; ! p = pwskip(p); passwd.pw_shell = p; while(*p && *p != '\n') p++; *p = '\0'; --- 85,91 ----- if (p == NULL) continue; passwd.pw_dir = p; ! p = pwskip (p); passwd.pw_shell = p; while (*p && *p != '\n') p++; *************** *** 61,67 passwd.pw_dir = p; p = pwskip(p); passwd.pw_shell = p; ! while(*p && *p != '\n') p++; *p = '\0'; return(&passwd); } --- 87,94 ----- passwd.pw_dir = p; p = pwskip (p); passwd.pw_shell = p; ! while (*p && *p != '\n') ! p++; *p = '\0'; return (&passwd); } *************** *** 63,67 passwd.pw_shell = p; while(*p && *p != '\n') p++; *p = '\0'; ! return(&passwd); } --- 90,96 ----- while (*p && *p != '\n') p++; *p = '\0'; ! return (&passwd); ! } ! return (0); } -- Wolfgang Rupprecht {harvard|decvax!cca|mit-eddie}!lmi-angel!wsr