getpwent.c revision 5714
11573Srgrimes/* 21573Srgrimes * Copyright (c) 1988, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer. 101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111573Srgrimes * notice, this list of conditions and the following disclaimer in the 121573Srgrimes * documentation and/or other materials provided with the distribution. 131573Srgrimes * 3. All advertising materials mentioning features or use of this software 141573Srgrimes * must display the following acknowledgement: 151573Srgrimes * This product includes software developed by the University of 161573Srgrimes * California, Berkeley and its contributors. 171573Srgrimes * 4. Neither the name of the University nor the names of its contributors 181573Srgrimes * may be used to endorse or promote products derived from this software 191573Srgrimes * without specific prior written permission. 201573Srgrimes * 211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311573Srgrimes * SUCH DAMAGE. 321573Srgrimes */ 331573Srgrimes 341573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 351573Srgrimesstatic char sccsid[] = "@(#)getpwent.c 8.1 (Berkeley) 6/4/93"; 361573Srgrimes#endif /* LIBC_SCCS and not lint */ 371573Srgrimes 381573Srgrimes#include <sys/param.h> 391573Srgrimes#include <fcntl.h> 401573Srgrimes#include <db.h> 411573Srgrimes#include <syslog.h> 421573Srgrimes#include <pwd.h> 431573Srgrimes#include <utmp.h> 441573Srgrimes#include <errno.h> 451573Srgrimes#include <unistd.h> 461573Srgrimes#include <stdlib.h> 471573Srgrimes#include <string.h> 481573Srgrimes#include <limits.h> 491573Srgrimes 501573Srgrimesstatic struct passwd _pw_passwd; /* password structure */ 511573Srgrimesstatic DB *_pw_db; /* password database */ 521573Srgrimesstatic int _pw_keynum; /* key counter */ 531573Srgrimesstatic int _pw_stayopen; /* keep fd's open */ 542917Swollman#ifdef YP 552917Swollmanstatic struct passwd _pw_copy; 562917Swollmanstatic int _yp_enabled; /* set true when yp enabled */ 572917Swollmanstatic int _pw_stepping_yp; /* set true when stepping thru map */ 582917Swollman#endif 591573Srgrimesstatic int __hashpw(), __initdb(); 601573Srgrimes 612917Swollmanstatic int _getyppass(struct passwd *, const char *, const char *); 622917Swollmanstatic int _nextyppass(struct passwd *); 632917Swollman 641573Srgrimesstruct passwd * 651573Srgrimesgetpwent() 661573Srgrimes{ 671573Srgrimes DBT key; 681573Srgrimes char bf[sizeof(_pw_keynum) + 1]; 692917Swollman int rv; 701573Srgrimes 711573Srgrimes if (!_pw_db && !__initdb()) 721573Srgrimes return((struct passwd *)NULL); 731573Srgrimes 742917Swollman#ifdef YP 752917Swollman if(_pw_stepping_yp) { 762917Swollman _pw_passwd = _pw_copy; 772917Swollman return (_nextyppass(&_pw_passwd) ? &_pw_passwd : 0); 782917Swollman } 792917Swollman#endif 802917Swollman 812917Swollmantryagain: 821573Srgrimes ++_pw_keynum; 831573Srgrimes bf[0] = _PW_KEYBYNUM; 841573Srgrimes bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum)); 851573Srgrimes key.data = (u_char *)bf; 861573Srgrimes key.size = sizeof(_pw_keynum) + 1; 872917Swollman rv = __hashpw(&key); 882917Swollman if(!rv) return (struct passwd *)NULL; 892917Swollman#ifdef YP 902917Swollman if(_pw_passwd.pw_name[0] == '+' && _pw_passwd.pw_name[1]) { 912917Swollman _getyppass(&_pw_passwd, &_pw_passwd.pw_name[1], 922917Swollman "passwd.byname"); 932917Swollman } else if(_pw_passwd.pw_name[0] == '+') { 942917Swollman _pw_copy = _pw_passwd; 952917Swollman return (_nextyppass(&_pw_passwd) ? &_pw_passwd : 0); 962917Swollman } 972917Swollman#else 982917Swollman /* Ignore YP password file entries when YP is disabled. */ 992917Swollman if(_pw_passwd.pw_name[0] == '+') { 1002917Swollman goto tryagain; 1012917Swollman } 1022917Swollman#endif 1032917Swollman return(&_pw_passwd); 1041573Srgrimes} 1051573Srgrimes 1061573Srgrimesstruct passwd * 1071573Srgrimesgetpwnam(name) 1081573Srgrimes const char *name; 1091573Srgrimes{ 1101573Srgrimes DBT key; 1111573Srgrimes int len, rval; 1122917Swollman char bf[UT_NAMESIZE + 2]; 1131573Srgrimes 1141573Srgrimes if (!_pw_db && !__initdb()) 1151573Srgrimes return((struct passwd *)NULL); 1161573Srgrimes 1171573Srgrimes bf[0] = _PW_KEYBYNAME; 1181573Srgrimes len = strlen(name); 1191573Srgrimes bcopy(name, bf + 1, MIN(len, UT_NAMESIZE)); 1201573Srgrimes key.data = (u_char *)bf; 1211573Srgrimes key.size = len + 1; 1221573Srgrimes rval = __hashpw(&key); 1231573Srgrimes 1242917Swollman#ifdef YP 1252917Swollman if (!rval && _yp_enabled) { 1262917Swollman bf[1] = '+'; 1272935Swollman bcopy(name, bf + 2, MIN(len, UT_NAMESIZE - 1)); 1282917Swollman key.data = (u_char *)bf; 1292917Swollman key.size = len + 2; 1302917Swollman rval = __hashpw(&key); 1312935Swollman if (!rval && _yp_enabled < 0) { 1322917Swollman key.size = 2; 1332917Swollman rval = __hashpw(&key); 1342917Swollman } 1352935Swollman if(rval) 1362935Swollman rval = _getyppass(&_pw_passwd, name, "passwd.byname"); 1372917Swollman } 1385703Swollman#endif 1392917Swollman /* 1402917Swollman * Prevent login attempts when YP is not enabled but YP entries 1412917Swollman * are in /etc/master.passwd. 1422917Swollman */ 1432917Swollman if (rval && _pw_passwd.pw_name[0] == '+') rval = 0; 1445714Swollman 1451573Srgrimes if (!_pw_stayopen) { 1461573Srgrimes (void)(_pw_db->close)(_pw_db); 1471573Srgrimes _pw_db = (DB *)NULL; 1481573Srgrimes } 1491573Srgrimes return(rval ? &_pw_passwd : (struct passwd *)NULL); 1501573Srgrimes} 1511573Srgrimes 1521573Srgrimesstruct passwd * 1531573Srgrimes#ifdef __STDC__ 1541573Srgrimesgetpwuid(uid_t uid) 1551573Srgrimes#else 1561573Srgrimesgetpwuid(uid) 1571573Srgrimes int uid; 1581573Srgrimes#endif 1591573Srgrimes{ 1601573Srgrimes DBT key; 1611573Srgrimes int keyuid, rval; 1621573Srgrimes char bf[sizeof(keyuid) + 1]; 1631573Srgrimes 1641573Srgrimes if (!_pw_db && !__initdb()) 1651573Srgrimes return((struct passwd *)NULL); 1661573Srgrimes 1671573Srgrimes bf[0] = _PW_KEYBYUID; 1681573Srgrimes keyuid = uid; 1691573Srgrimes bcopy(&keyuid, bf + 1, sizeof(keyuid)); 1701573Srgrimes key.data = (u_char *)bf; 1711573Srgrimes key.size = sizeof(keyuid) + 1; 1721573Srgrimes rval = __hashpw(&key); 1731573Srgrimes 1742917Swollman#ifdef YP 1752917Swollman if (!rval && _yp_enabled) { 1762917Swollman char ypbuf[16]; /* big enough for 32-bit uids and then some */ 1772917Swollman snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid); 1782917Swollman rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid"); 1792917Swollman } 1802917Swollman#endif 1811573Srgrimes if (!_pw_stayopen) { 1821573Srgrimes (void)(_pw_db->close)(_pw_db); 1831573Srgrimes _pw_db = (DB *)NULL; 1841573Srgrimes } 1851573Srgrimes return(rval ? &_pw_passwd : (struct passwd *)NULL); 1861573Srgrimes} 1871573Srgrimes 1881573Srgrimesint 1891573Srgrimessetpassent(stayopen) 1901573Srgrimes int stayopen; 1911573Srgrimes{ 1921573Srgrimes _pw_keynum = 0; 1932917Swollman#ifdef YP 1942917Swollman _pw_stepping_yp = 0; 1952917Swollman#endif 1961573Srgrimes _pw_stayopen = stayopen; 1971573Srgrimes return(1); 1981573Srgrimes} 1991573Srgrimes 2001573Srgrimesint 2011573Srgrimessetpwent() 2021573Srgrimes{ 2031573Srgrimes _pw_keynum = 0; 2042917Swollman#ifdef YP 2052917Swollman _pw_stepping_yp = 0; 2062917Swollman#endif 2071573Srgrimes _pw_stayopen = 0; 2081573Srgrimes return(1); 2091573Srgrimes} 2101573Srgrimes 2111573Srgrimesvoid 2121573Srgrimesendpwent() 2131573Srgrimes{ 2141573Srgrimes _pw_keynum = 0; 2152917Swollman#ifdef YP 2162917Swollman _pw_stepping_yp = 0; 2172917Swollman#endif 2181573Srgrimes if (_pw_db) { 2191573Srgrimes (void)(_pw_db->close)(_pw_db); 2201573Srgrimes _pw_db = (DB *)NULL; 2211573Srgrimes } 2221573Srgrimes} 2231573Srgrimes 2241573Srgrimesstatic 2251573Srgrimes__initdb() 2261573Srgrimes{ 2271573Srgrimes static int warned; 2281573Srgrimes char *p; 2291573Srgrimes 2301573Srgrimes p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB; 2311573Srgrimes _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL); 2322917Swollman if (_pw_db) { 2332917Swollman#ifdef YP 2342917Swollman DBT key, data; 2352917Swollman char buf[] = { _PW_KEYYPENABLED }; 2362917Swollman key.data = buf; 2372917Swollman key.size = 1; 2382917Swollman if ((_pw_db->get)(_pw_db, &key, &data, 0)) { 2392917Swollman _yp_enabled = 0; 2402917Swollman } else { 2412935Swollman /* Distinguish between old and new versions of 2422935Swollman pwd_mkdb. */ 2432935Swollman if(data.size != 1) { 2442935Swollman _yp_enabled = -1; 2452935Swollman } else { 2462935Swollman _yp_enabled = (int)*((char *)data.data) - 2; 2472935Swollman } 2482917Swollman } 2492917Swollman#endif 2501573Srgrimes return(1); 2512917Swollman } 2521573Srgrimes if (!warned) 2531573Srgrimes syslog(LOG_ERR, "%s: %m", p); 2541573Srgrimes return(0); 2551573Srgrimes} 2561573Srgrimes 2571573Srgrimesstatic 2581573Srgrimes__hashpw(key) 2591573Srgrimes DBT *key; 2601573Srgrimes{ 2611573Srgrimes register char *p, *t; 2621573Srgrimes static u_int max; 2631573Srgrimes static char *line; 2641573Srgrimes DBT data; 2651573Srgrimes 2661573Srgrimes if ((_pw_db->get)(_pw_db, key, &data, 0)) 2671573Srgrimes return(0); 2681573Srgrimes p = (char *)data.data; 2691573Srgrimes if (data.size > max && !(line = realloc(line, max += 1024))) 2701573Srgrimes return(0); 2711573Srgrimes 2721573Srgrimes t = line; 2731573Srgrimes#define EXPAND(e) e = t; while (*t++ = *p++); 2741573Srgrimes EXPAND(_pw_passwd.pw_name); 2751573Srgrimes EXPAND(_pw_passwd.pw_passwd); 2761573Srgrimes bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int)); 2771573Srgrimes p += sizeof(int); 2781573Srgrimes bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int)); 2791573Srgrimes p += sizeof(int); 2801573Srgrimes bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t)); 2811573Srgrimes p += sizeof(time_t); 2821573Srgrimes EXPAND(_pw_passwd.pw_class); 2831573Srgrimes EXPAND(_pw_passwd.pw_gecos); 2841573Srgrimes EXPAND(_pw_passwd.pw_dir); 2851573Srgrimes EXPAND(_pw_passwd.pw_shell); 2861573Srgrimes bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t)); 2871573Srgrimes p += sizeof(time_t); 2882917Swollman bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields); 2892917Swollman p += sizeof _pw_passwd.pw_fields; 2901573Srgrimes return(1); 2911573Srgrimes} 2922917Swollman 2932917Swollman#ifdef YP 2942917Swollmanstatic void 2952917Swollman_pw_breakout_yp(struct passwd *pw, char *result) 2962917Swollman{ 2972917Swollman char *s; 2982917Swollman 2992917Swollman s = strsep(&result, ":"); /* name */ 3002917Swollman if(!(pw->pw_fields & _PWF_NAME) || (pw->pw_name[0] == '+')) { 3012917Swollman pw->pw_name = s; 3022917Swollman pw->pw_fields |= _PWF_NAME; 3032917Swollman } 3042917Swollman 3052917Swollman s = strsep(&result, ":"); /* password */ 3062917Swollman if(!(pw->pw_fields & _PWF_PASSWD)) { 3072917Swollman pw->pw_passwd = s; 3082917Swollman pw->pw_fields |= _PWF_PASSWD; 3092917Swollman } 3102917Swollman 3112917Swollman s = strsep(&result, ":"); /* uid */ 3122917Swollman if(!(pw->pw_fields & _PWF_UID)) { 3132917Swollman pw->pw_uid = atoi(s); 3142917Swollman pw->pw_fields |= _PWF_UID; 3152917Swollman } 3162917Swollman 3172917Swollman s = strsep(&result, ":"); /* gid */ 3182917Swollman if(!(pw->pw_fields & _PWF_GID)) { 3192917Swollman pw->pw_gid = atoi(s); 3202917Swollman pw->pw_fields |= _PWF_GID; 3212917Swollman } 3222917Swollman 3232917Swollman s = strsep(&result, ":"); /* gecos */ 3242917Swollman if(!(pw->pw_fields & _PWF_GECOS)) { 3252917Swollman pw->pw_gecos = s; 3262917Swollman pw->pw_fields |= _PWF_GECOS; 3272917Swollman } 3282917Swollman 3292917Swollman s = strsep(&result, ":"); /* dir */ 3302917Swollman if(!(pw->pw_fields & _PWF_DIR)) { 3312917Swollman pw->pw_dir = s; 3322917Swollman pw->pw_fields |= _PWF_DIR; 3332917Swollman } 3342917Swollman 3352917Swollman s = strsep(&result, ":"); /* shell */ 3362917Swollman if(!(pw->pw_fields & _PWF_SHELL)) { 3372917Swollman pw->pw_shell = s; 3382917Swollman pw->pw_fields |= _PWF_SHELL; 3392917Swollman } 3402917Swollman} 3412917Swollman 3422917Swollmanstatic char *_pw_yp_domain; 3432917Swollman 3442917Swollmanstatic int 3452917Swollman_getyppass(struct passwd *pw, const char *name, const char *map) 3462917Swollman{ 3472917Swollman char *result, *s; 3482917Swollman static char resultbuf[1024]; 3492917Swollman int resultlen; 3502917Swollman 3512917Swollman if(!_pw_yp_domain) { 3522917Swollman if(yp_get_default_domain(&_pw_yp_domain)) 3532917Swollman return 0; 3542917Swollman } 3552917Swollman 3562917Swollman if(yp_match(_pw_yp_domain, map, name, strlen(name), 3572917Swollman &result, &resultlen)) 3582917Swollman return 0; 3592917Swollman 3602917Swollman s = strchr(result, '\n'); 3612917Swollman if(s) *s = '\0'; 3622917Swollman 3632935Swollman if(resultlen >= sizeof resultbuf) return 0; 3642917Swollman strcpy(resultbuf, result); 3652917Swollman result = resultbuf; 3662917Swollman _pw_breakout_yp(pw, resultbuf); 3672917Swollman 3682917Swollman return 1; 3692917Swollman} 3702917Swollman 3712917Swollmanstatic int 3722917Swollman_nextyppass(struct passwd *pw) 3732917Swollman{ 3742917Swollman static char *key; 3752917Swollman static int keylen; 3762917Swollman char *lastkey, *result; 3772917Swollman static char resultbuf[1024]; 3782917Swollman int resultlen; 3792917Swollman int rv; 3802917Swollman 3812917Swollman if(!_pw_yp_domain) { 3822917Swollman if(yp_get_default_domain(&_pw_yp_domain)) 3832917Swollman return 0; 3842917Swollman } 3852917Swollman 3862917Swollman if(!_pw_stepping_yp) { 3872917Swollman if(key) free(key); 3882917Swollman rv = yp_first(_pw_yp_domain, "passwd.byname", 3892917Swollman &key, &keylen, &result, &resultlen); 3902917Swollman if(rv) { 3912917Swollman return 0; 3922917Swollman } 3932917Swollman _pw_stepping_yp = 1; 3942917Swollman goto unpack; 3952917Swollman } else { 3962917Swollmantryagain: 3972917Swollman lastkey = key; 3982917Swollman rv = yp_next(_pw_yp_domain, "passwd.byname", key, keylen, 3992917Swollman &key, &keylen, &result, &resultlen); 4002917Swollman free(lastkey); 4012917Swollmanunpack: 4022917Swollman if(rv) { 4032917Swollman _pw_stepping_yp = 0; 4042917Swollman return 0; 4052917Swollman } 4062917Swollman 4072917Swollman if(resultlen > sizeof(resultbuf)) { 4082917Swollman free(result); 4092917Swollman goto tryagain; 4102917Swollman } 4112917Swollman 4122917Swollman strcpy(resultbuf, result); 4132917Swollman free(result); 4142917Swollman if(result = strchr(resultbuf, '\n')) *result = '\0'; 4152917Swollman _pw_breakout_yp(pw, resultbuf); 4162917Swollman } 4172917Swollman return 1; 4182917Swollman} 4192917Swollman 4202917Swollman#endif /* YP */ 421