Home | History | Annotate | Line # | Download | only in gen
getpwent.c revision 1.11
      1 /*
      2  * Copyright (c) 1988 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #if defined(LIBC_SCCS) && !defined(lint)
     35 /*static char *sccsid = "from: @(#)getpwent.c	5.21 (Berkeley) 3/14/91";*/
     36 static char *rcsid = "$Id: getpwent.c,v 1.11 1994/03/09 10:10:29 deraadt Exp $";
     37 #endif /* LIBC_SCCS and not lint */
     38 
     39 #include <sys/param.h>
     40 #include <fcntl.h>
     41 #include <db.h>
     42 #include <syslog.h>
     43 #include <pwd.h>
     44 #include <utmp.h>
     45 #include <errno.h>
     46 #include <unistd.h>
     47 #include <stdlib.h>
     48 #include <string.h>
     49 #include <limits.h>
     50 #ifdef YP
     51 #include <stdio.h>
     52 #include <rpc/rpc.h>
     53 #include <rpcsvc/yp_prot.h>
     54 #include <rpcsvc/ypclnt.h>
     55 #endif
     56 
     57 static struct passwd _pw_passwd;	/* password structure */
     58 static DB *_pw_db;			/* password database */
     59 static int _pw_keynum;			/* key counter */
     60 static int _pw_stayopen;		/* keep fd's open */
     61 static int __hashpw(), __initdb();
     62 
     63 #ifdef YP
     64 static char     *__ypcurrent, *__ypdomain;
     65 static int      __ypcurrentlen, __ypmode=0;
     66 static char	line[1024];
     67 
     68 static int
     69 __ypparse(pw, s)
     70 struct passwd *pw;
     71 char *s;
     72 {
     73 	char *bp, *cp;
     74 
     75 	bp = s;
     76 	pw->pw_name = strsep(&bp, ":\n");
     77 	pw->pw_passwd = strsep(&bp, ":\n");
     78 	if (!(cp = strsep(&bp, ":\n")))
     79 		return 1;
     80 	pw->pw_uid = atoi(cp);
     81 	if (!(cp = strsep(&bp, ":\n")))
     82 		return 0;
     83 	pw->pw_gid = atoi(cp);
     84 	pw->pw_change = 0;
     85 	pw->pw_class = "";
     86 	pw->pw_gecos = strsep(&bp, ":\n");
     87 	pw->pw_dir = strsep(&bp, ":\n");
     88 	pw->pw_shell = strsep(&bp, ":\n");
     89 	pw->pw_expire = 0;
     90 	return 0;
     91 }
     92 #endif
     93 
     94 struct passwd *
     95 getpwent()
     96 {
     97 	DBT key;
     98 	char bf[sizeof(_pw_keynum) + 1];
     99 #ifdef YP
    100 	char *bp, *cp;
    101 #endif
    102 
    103 	if (!_pw_db && !__initdb())
    104 		return((struct passwd *)NULL);
    105 
    106 #ifdef YP
    107 again:
    108 	if(__ypmode) {
    109 		char *key, *data;
    110 		int keylen, datalen;
    111 		int r;
    112 
    113 		if(!__ypdomain) {
    114 			if( _yp_check(&__ypdomain) == 0) {
    115 				__ypmode = 0;
    116 				goto again;
    117 			}
    118 		}
    119 		if(__ypcurrent) {
    120 			r = yp_next(__ypdomain, "passwd.byname",
    121 				__ypcurrent, __ypcurrentlen,
    122 				&key, &keylen, &data, &datalen);
    123 			free(__ypcurrent);
    124 			__ypcurrent = NULL;
    125 			/*printf("yp_next %d\n", r);*/
    126 			switch(r) {
    127 			case 0:
    128 				break;
    129 			default:
    130 				__ypcurrent = NULL;
    131 				__ypmode = 0;
    132 				free(data);
    133 				data = NULL;
    134 				goto again;
    135 			}
    136 			__ypcurrent = key;
    137 			__ypcurrentlen = keylen;
    138 			bcopy(data, line, datalen);
    139 			free(data);
    140 			data = NULL;
    141 		} else {
    142 			r = yp_first(__ypdomain, "passwd.byname",
    143 				&__ypcurrent, &__ypcurrentlen,
    144 				&data, &datalen);
    145 			/*printf("yp_first %d\n", r);*/
    146 			switch(r) {
    147 			case 0:
    148 				break;
    149 			default:
    150 				__ypmode = 0;
    151 				free(data);
    152 				goto again;
    153 			}
    154 			bcopy(data, line, datalen);
    155 			free(data);
    156 			data = NULL;
    157 		}
    158 		line[datalen] = '\0';
    159 		/*printf("line = %s\n", line);*/
    160 		bp = line;
    161 		goto parse;
    162 	}
    163 #endif
    164 
    165 	++_pw_keynum;
    166 	bf[0] = _PW_KEYBYNUM;
    167 	bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
    168 	key.data = (u_char *)bf;
    169 	key.size = sizeof(_pw_keynum) + 1;
    170 	if(__hashpw(&key)) {
    171 #ifdef YP
    172 		if(strcmp(_pw_passwd.pw_name, "+") == 0) {
    173 			__ypmode = 1;
    174 			goto again;
    175 		}
    176 #endif
    177 		return &_pw_passwd;
    178 	}
    179 	return (struct passwd *)NULL;
    180 
    181 #ifdef YP
    182 parse:
    183 	_pw_passwd.pw_name = strsep(&bp, ":\n");
    184 	_pw_passwd.pw_passwd = strsep(&bp, ":\n");
    185 	if (!(cp = strsep(&bp, ":\n")))
    186 		goto again;
    187 	_pw_passwd.pw_uid = atoi(cp);
    188 	if (!(cp = strsep(&bp, ":\n")))
    189 		goto again;
    190 	_pw_passwd.pw_gid = atoi(cp);
    191 	_pw_passwd.pw_change = 0;
    192 	_pw_passwd.pw_class = "";
    193 	_pw_passwd.pw_gecos = strsep(&bp, ":\n");
    194 	_pw_passwd.pw_dir = strsep(&bp, ":\n");
    195 	_pw_passwd.pw_shell = strsep(&bp, ":\n");
    196 	_pw_passwd.pw_expire = 0;
    197 	return &_pw_passwd;
    198 #endif
    199 }
    200 
    201 struct passwd *
    202 getpwnam(name)
    203 	const char *name;
    204 {
    205 	DBT key;
    206 	int len, rval;
    207 	char bf[UT_NAMESIZE + 1];
    208 
    209 	if (!_pw_db && !__initdb())
    210 		return((struct passwd *)NULL);
    211 
    212 #ifdef YP
    213 	bf[0] = _PW_KEYBYNAME;
    214 	len = strlen("+");
    215 	bcopy("+", bf + 1, MIN(len, UT_NAMESIZE));
    216 	key.data = (u_char *)bf;
    217 	key.size = len + 1;
    218 
    219 	/*
    220 	 * If there is a user called "+", then YP is active. In that
    221 	 * case we must sequence through the passwd file in sequence.
    222 	 */
    223 	if ( __hashpw(&key)) {
    224 		int r;
    225 
    226 		for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
    227 			bf[0] = _PW_KEYBYNUM;
    228 			bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
    229 			key.data = (u_char *)bf;
    230 			key.size = sizeof(_pw_keynum) + 1;
    231 			if(__hashpw(&key) == 0)
    232 				break;
    233 			if(strcmp(_pw_passwd.pw_name, "+") == 0) {
    234 				if(!__ypdomain) {
    235 					if(_yp_check(&__ypdomain) == 0) {
    236 						continue;
    237 					}
    238 				}
    239 				if(__ypcurrent) {
    240 					free(__ypcurrent);
    241 					__ypcurrent = NULL;
    242 				}
    243 				r = yp_match(__ypdomain, "passwd.byname",
    244 					name, strlen(name),
    245 					&__ypcurrent, &__ypcurrentlen);
    246 				switch(r) {
    247 				case 0:
    248 					break;
    249 				default:
    250 					free(__ypcurrent);
    251 					__ypcurrent = NULL;
    252 					continue;
    253 				}
    254 				bcopy(__ypcurrent, line, __ypcurrentlen);
    255 				line[__ypcurrentlen] = '\0';
    256 				if(__ypparse(&_pw_passwd, line))
    257 					continue;
    258 			}
    259 			if( strcmp(_pw_passwd.pw_name, name) == 0) {
    260 				if (!_pw_stayopen) {
    261 					(void)(_pw_db->close)(_pw_db);
    262 					_pw_db = (DB *)NULL;
    263 				}
    264 				return &_pw_passwd;
    265 			}
    266 			continue;
    267 		}
    268 		if (!_pw_stayopen) {
    269 			(void)(_pw_db->close)(_pw_db);
    270 			_pw_db = (DB *)NULL;
    271 		}
    272 		return (struct passwd *)NULL;
    273 	}
    274 #endif /* YP */
    275 
    276 	bf[0] = _PW_KEYBYNAME;
    277 	len = strlen(name);
    278 	bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));
    279 	key.data = (u_char *)bf;
    280 	key.size = len + 1;
    281 	rval = __hashpw(&key);
    282 
    283 	if (!_pw_stayopen) {
    284 		(void)(_pw_db->close)(_pw_db);
    285 		_pw_db = (DB *)NULL;
    286 	}
    287 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
    288 }
    289 
    290 struct passwd *
    291 #ifdef __STDC__
    292 getpwuid(uid_t uid)
    293 #else
    294 getpwuid(uid)
    295 	int uid;
    296 #endif
    297 {
    298 	DBT key;
    299 	char bf[sizeof(_pw_keynum) + 1];
    300 	int keyuid, rval, len;
    301 
    302 	if (!_pw_db && !__initdb())
    303 		return((struct passwd *)NULL);
    304 
    305 #ifdef YP
    306 	bf[0] = _PW_KEYBYNAME;
    307 	len = strlen("+");
    308 	bcopy("+", bf + 1, MIN(len, UT_NAMESIZE));
    309 	key.data = (u_char *)bf;
    310 	key.size = len + 1;
    311 
    312 	/*
    313 	 * If there is a user called "+", then YP is active. In that
    314 	 * case we must sequence through the passwd file in sequence.
    315 	 */
    316 	if ( __hashpw(&key)) {
    317 		char uidbuf[20];
    318 		int r;
    319 
    320 		for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
    321 			bf[0] = _PW_KEYBYNUM;
    322 			bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
    323 			key.data = (u_char *)bf;
    324 			key.size = sizeof(_pw_keynum) + 1;
    325 			if(__hashpw(&key) == 0)
    326 				break;
    327 			if(strcmp(_pw_passwd.pw_name, "+") == 0) {
    328 				if(!__ypdomain) {
    329 					if(_yp_check(&__ypdomain) == 0) {
    330 						continue;
    331 					}
    332 				}
    333 				if(__ypcurrent) {
    334 					free(__ypcurrent);
    335 					__ypcurrent = NULL;
    336 				}
    337 				sprintf(uidbuf, "%d", uid);
    338 				r = yp_match(__ypdomain, "passwd.byuid",
    339 					uidbuf, strlen(uidbuf),
    340 					&__ypcurrent, &__ypcurrentlen);
    341 				switch(r) {
    342 				case 0:
    343 					break;
    344 				default:
    345 					free(__ypcurrent);
    346 					__ypcurrent = NULL;
    347 					continue;
    348 				}
    349 				bcopy(__ypcurrent, line, __ypcurrentlen);
    350 				line[__ypcurrentlen] = '\0';
    351 				if(__ypparse(&_pw_passwd, line))
    352 					continue;
    353 			}
    354 			if( _pw_passwd.pw_uid == uid) {
    355 				if (!_pw_stayopen) {
    356 					(void)(_pw_db->close)(_pw_db);
    357 					_pw_db = (DB *)NULL;
    358 				}
    359 				return &_pw_passwd;
    360 			}
    361 			continue;
    362 		}
    363 		if (!_pw_stayopen) {
    364 			(void)(_pw_db->close)(_pw_db);
    365 			_pw_db = (DB *)NULL;
    366 		}
    367 		return (struct passwd *)NULL;
    368 	}
    369 #endif /* YP */
    370 
    371 	bf[0] = _PW_KEYBYUID;
    372 	keyuid = uid;
    373 	bcopy(&keyuid, bf + 1, sizeof(keyuid));
    374 	key.data = (u_char *)bf;
    375 	key.size = sizeof(keyuid) + 1;
    376 	rval = __hashpw(&key);
    377 
    378 	if (!_pw_stayopen) {
    379 		(void)(_pw_db->close)(_pw_db);
    380 		_pw_db = (DB *)NULL;
    381 	}
    382 	return(rval ? &_pw_passwd : (struct passwd *)NULL);
    383 }
    384 
    385 int
    386 setpassent(stayopen)
    387 	int stayopen;
    388 {
    389 	_pw_keynum = 0;
    390 	_pw_stayopen = stayopen;
    391 #ifdef YP
    392 	__ypmode = 0;
    393 	if(__ypcurrent)
    394 		free(__ypcurrent);
    395 	__ypcurrent = NULL;
    396 #endif
    397 	return(1);
    398 }
    399 
    400 void
    401 setpwent()
    402 {
    403 	(void) setpassent(0);
    404 }
    405 
    406 void
    407 endpwent()
    408 {
    409 	_pw_keynum = 0;
    410 	if (_pw_db) {
    411 		(void)(_pw_db->close)(_pw_db);
    412 		_pw_db = (DB *)NULL;
    413 	}
    414 #ifdef YP
    415 	__ypmode = 0;
    416 	if(__ypcurrent)
    417 		free(__ypcurrent);
    418 	__ypcurrent = NULL;
    419 #endif
    420 }
    421 
    422 static int
    423 __initdb()
    424 {
    425 	static int warned;
    426 	char *p;
    427 
    428 	p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
    429 	_pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
    430 	if (_pw_db)
    431 		return(1);
    432 	if (!warned)
    433 		syslog(LOG_ERR, "%s: %m", p);
    434 	warned = 1;
    435 	return(0);
    436 }
    437 
    438 static int
    439 __hashpw(key)
    440 	DBT *key;
    441 {
    442 	register char *p, *t;
    443 	static u_int max;
    444 	static char *line;
    445 	DBT data;
    446 
    447 	if ((_pw_db->get)(_pw_db, key, &data, 0))
    448 		return(0);
    449 	p = (char *)data.data;
    450 	if (data.size > max && !(line = realloc(line, max += 1024)))
    451 		return(0);
    452 
    453 	t = line;
    454 #define	EXPAND(e)	e = t; while (*t++ = *p++);
    455 	EXPAND(_pw_passwd.pw_name);
    456 	EXPAND(_pw_passwd.pw_passwd);
    457 	bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
    458 	p += sizeof(int);
    459 	bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
    460 	p += sizeof(int);
    461 	bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
    462 	p += sizeof(time_t);
    463 	EXPAND(_pw_passwd.pw_class);
    464 	EXPAND(_pw_passwd.pw_gecos);
    465 	EXPAND(_pw_passwd.pw_dir);
    466 	EXPAND(_pw_passwd.pw_shell);
    467 	bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
    468 	p += sizeof(time_t);
    469 	return(1);
    470 }
    471