Date: Fri, 22 Sep 1995 13:27:47 PDT From: Bill Fenner <fenner@parc.xerox.com> To: FreeBSD-gnats-submit@freebsd.org Subject: bin/732: getpwent() dumps core if NIS password file is malformed Message-ID: <199509222027.NAA14886@baobab.parc.xerox.com> Resent-Message-ID: <199509222030.NAA17658@freefall.freebsd.org>
index | next in thread | raw e-mail
>Number: 732
>Category: bin
>Synopsis: getpwent() dumps core if NIS password file is malformed
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Sep 22 13:30:01 PDT 1995
>Last-Modified:
>Originator: Bill Fenner
>Organization:
Xerox PARC
>Release: FreeBSD 2.0-BUILT-19950628 i386
>Environment:
FreeBSD 2.1.0-950726-SNAP
>Description:
"finger" dumps core after enabling NIS passwords with +:::::::::
in /etc/master.passwd
It turns out that there is an entry in our NIS map with a 13-character
username, which overflows a static buffer. It also turns out that
this static buffer is one character too small anyway, as 8-character
usernames can overflow it with the trailing NUL. (but probably won't
cause a core dump...)
>How-To-Repeat:
Create an entry with a 13-character username, and then try "finger <someuser>".
finger will core dump because of a buffer overrun in _getyppass()
>Fix:
I rewrote the code to not require the static buffer, and instead to
use the malloc()'d buffer that yp_first(), yp_next(), or yp_match()
allocated for us.
I was sure that I sent these diffs in previously, but I can't find the
email message so I am sending them as a PR now that gnats is fixed.
I should note that it seems like a real shame to have two functions
whose bodies are so similar, but I wasn't prepared to address the
higher level problem, I just wanted it to stop dumping core.
--- getpwent.c.orig Tue Sep 5 17:04:47 1995
+++ getpwent.c Tue Sep 5 18:30:56 1995
@@ -586,13 +586,11 @@
_getyppass(struct passwd *pw, const char *name, const char *map)
{
char *result, *s;
- static char resultbuf[1024];
int resultlen;
char mastermap[1024];
int gotmaster = 0;
struct _pw_cache *m, *p;
struct _namelist *n;
- char user[UT_NAMESIZE];
if(!_pw_yp_domain) {
if(yp_get_default_domain(&_pw_yp_domain))
@@ -613,18 +611,23 @@
return 0;
s = strchr(result, '\n');
- if(s) *s = '\0';
+ if (s) *s = '\0';
- if(resultlen >= sizeof resultbuf) return 0;
- strcpy(resultbuf, result);
- sprintf (user, "%.*s", (strchr(result, ':') - result), result);
+ s = strchr(result, ':');
+ if (s) {
+ *s = '\0';
+ } else {
+ /* malformed, no colon */
+ free(result);
+ return 0;
+ }
_pw_passwd.pw_fields = -1; /* Impossible value */
if (_minuscnt && _minushead) {
m = _minushead;
while (m) {
n = m->namelist;
while (n) {
- if (!strcmp(n->name,user) || *n->name == '\0') {
+ if (!strcmp(n->name,result) || *n->name == '\0') {
free(result);
return (0);
}
@@ -638,7 +641,7 @@
while (p) {
n = p->namelist;
while (n) {
- if (!strcmp(n->name, user) || *n->name == '\0')
+ if (!strcmp(n->name, result) || *n->name == '\0')
bcopy((char *)&p->pw_entry,
(char *)&_pw_passwd, sizeof(p->pw_entry));
n = n->next;
@@ -646,12 +649,14 @@
p = p->next;
}
}
- free(result);
/* No hits in the plus or minus lists: Bzzt! reject. */
- if (_pw_passwd.pw_fields == -1)
+ if (_pw_passwd.pw_fields == -1) {
+ free(result);
return(0);
- result = resultbuf;
- _pw_breakout_yp(pw, resultbuf, gotmaster);
+ }
+ *s = ':'; /* Put colon back */
+ _pw_breakout_yp(pw, result, gotmaster);
+ free(result);
return 1;
}
@@ -662,14 +667,13 @@
static char *key;
static int keylen;
char *lastkey, *result;
- static char resultbuf[1024];
int resultlen;
int rv;
char *map = "passwd.byname";
int gotmaster = 0;
struct _pw_cache *m, *p;
struct _namelist *n;
- char user[UT_NAMESIZE];
+ char *s;
if(!_pw_yp_domain) {
if(yp_get_default_domain(&_pw_yp_domain))
@@ -704,20 +708,21 @@
return 0;
}
- if(resultlen > sizeof(resultbuf)) {
+ s = strchr(result, ':');
+ if (s) {
+ *s = '\0';
+ } else {
+ /* malformed, no colon */
free(result);
goto tryagain;
}
-
- strcpy(resultbuf, result);
- sprintf(user, "%.*s", (strchr(result, ':') - result), result);
_pw_passwd.pw_fields = -1; /* Impossible value */
if (_minuscnt && _minushead) {
m = _minushead;
while (m) {
n = m->namelist;
while (n) {
- if (!strcmp(n->name, user) || *n->name == '\0') {
+ if (!strcmp(n->name, result) || *n->name == '\0') {
free(result);
goto tryagain;
}
@@ -731,7 +736,7 @@
while (p) {
n = p->namelist;
while (n) {
- if (!strcmp(n->name, user) || *n->name == '\0')
+ if (!strcmp(n->name, result) || *n->name == '\0')
bcopy((char *)&p->pw_entry,
(char*)&_pw_passwd, sizeof(p->pw_entry));
n = n->next;
@@ -739,12 +744,15 @@
p = p->next;
}
}
- free(result);
/* No plus or minus hits: Bzzzt! reject. */
- if (_pw_passwd.pw_fields == -1)
+ if (_pw_passwd.pw_fields == -1) {
+ free(result);
goto tryagain;
- if(result = strchr(resultbuf, '\n')) *result = '\0';
- _pw_breakout_yp(pw, resultbuf, gotmaster);
+ }
+ *s = ':'; /* Put colon back */
+ if(s = strchr(result, '\n')) *s = '\0';
+ _pw_breakout_yp(pw, result, gotmaster);
+ free(result);
}
return 1;
}
>Audit-Trail:
>Unformatted:
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199509222027.NAA14886>
