Deleted Added
full compact
getpwent.c (23608) getpwent.c (23668)
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. 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)
1/*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. 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)
35static char sccsid[] = "@(#)getpwent.c 8.1 (Berkeley) 6/4/93";
35static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95";
36#endif /* LIBC_SCCS and not lint */
37
38#include <stdio.h>
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#include <grp.h>
51
52extern void setnetgrent __P(( char * ));
53extern int getnetgrent __P(( char **, char **, char ** ));
54extern int innetgr __P(( const char *, const char *, const char *, const char * ));
55
36#endif /* LIBC_SCCS and not lint */
37
38#include <stdio.h>
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#include <grp.h>
51
52extern void setnetgrent __P(( char * ));
53extern int getnetgrent __P(( char **, char **, char ** ));
54extern int innetgr __P(( const char *, const char *, const char *, const char * ));
55
56/*
57 * The lookup techniques and data extraction code here must be kept
58 * in sync with that in `pwd_mkdb'.
59 */
60
56static struct passwd _pw_passwd; /* password structure */
57static DB *_pw_db; /* password database */
58static int _pw_keynum; /* key counter */
59static int _pw_stayopen; /* keep fd's open */
60#ifdef YP
61#include <rpc/rpc.h>
62#include <rpcsvc/yp_prot.h>
63#include <rpcsvc/ypclnt.h>
64
65static struct passwd _pw_copy;
66static DBT empty = { NULL, 0 };
67static DB *_ypcache = (DB *)NULL;
68static int _yp_exclusions = 0;
69static int _yp_enabled; /* set true when yp enabled */
70static int _pw_stepping_yp; /* set true when stepping thru map */
71static char _ypnam[YPMAXRECORD];
72#define YP_HAVE_MASTER 2
73#define YP_HAVE_ADJUNCT 1
74#define YP_HAVE_NONE 0
75static int _gotmaster;
76static char *_pw_yp_domain;
77static inline int unwind __P(( char * ));
78static inline void _ypinitdb __P(( void ));
79static int _havemaster __P((char *));
80static int _getyppass __P((struct passwd *, const char *, const char * ));
81static int _nextyppass __P((struct passwd *));
82#endif
83static int __hashpw(), __initdb();
84
85struct passwd *
86getpwent()
87{
88 DBT key;
89 char bf[sizeof(_pw_keynum) + 1];
90 int rv;
91
92 if (!_pw_db && !__initdb())
93 return((struct passwd *)NULL);
94
95#ifdef YP
96 if(_pw_stepping_yp) {
97 _pw_passwd = _pw_copy;
98 if (unwind((char *)&_ypnam))
99 return(&_pw_passwd);
100 }
101#endif
102tryagain:
103
104 ++_pw_keynum;
105 bf[0] = _PW_KEYBYNUM;
106 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
107 key.data = (u_char *)bf;
108 key.size = sizeof(_pw_keynum) + 1;
109 rv = __hashpw(&key);
110 if(!rv) return (struct passwd *)NULL;
111#ifdef YP
112 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
113 bzero((char *)&_ypnam, sizeof(_ypnam));
114 bcopy(_pw_passwd.pw_name, _ypnam,
115 strlen(_pw_passwd.pw_name));
116 _pw_copy = _pw_passwd;
117 if (unwind((char *)&_ypnam) == 0)
118 goto tryagain;
119 else
120 return(&_pw_passwd);
121 }
122#else
123 /* Ignore YP password file entries when YP is disabled. */
124 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
125 goto tryagain;
126 }
127#endif
128 return(&_pw_passwd);
129}
130
131struct passwd *
132getpwnam(name)
133 const char *name;
134{
135 DBT key;
136 int len, rval;
137 char bf[UT_NAMESIZE + 2];
138
139 if (!_pw_db && !__initdb())
140 return((struct passwd *)NULL);
141
142 bf[0] = _PW_KEYBYNAME;
143 len = strlen(name);
144 bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));
145 key.data = (u_char *)bf;
146 key.size = len + 1;
147 rval = __hashpw(&key);
148
149#ifdef YP
150 if (!rval && _yp_enabled)
151 rval = _getyppass(&_pw_passwd, name, "passwd.byname");
152#endif
153 /*
154 * Prevent login attempts when YP is not enabled but YP entries
155 * are in /etc/master.passwd.
156 */
157 if (rval && (_pw_passwd.pw_name[0] == '+'||
158 _pw_passwd.pw_name[0] == '-')) rval = 0;
159
160 endpwent();
161 return(rval ? &_pw_passwd : (struct passwd *)NULL);
162}
163
164struct passwd *
61static struct passwd _pw_passwd; /* password structure */
62static DB *_pw_db; /* password database */
63static int _pw_keynum; /* key counter */
64static int _pw_stayopen; /* keep fd's open */
65#ifdef YP
66#include <rpc/rpc.h>
67#include <rpcsvc/yp_prot.h>
68#include <rpcsvc/ypclnt.h>
69
70static struct passwd _pw_copy;
71static DBT empty = { NULL, 0 };
72static DB *_ypcache = (DB *)NULL;
73static int _yp_exclusions = 0;
74static int _yp_enabled; /* set true when yp enabled */
75static int _pw_stepping_yp; /* set true when stepping thru map */
76static char _ypnam[YPMAXRECORD];
77#define YP_HAVE_MASTER 2
78#define YP_HAVE_ADJUNCT 1
79#define YP_HAVE_NONE 0
80static int _gotmaster;
81static char *_pw_yp_domain;
82static inline int unwind __P(( char * ));
83static inline void _ypinitdb __P(( void ));
84static int _havemaster __P((char *));
85static int _getyppass __P((struct passwd *, const char *, const char * ));
86static int _nextyppass __P((struct passwd *));
87#endif
88static int __hashpw(), __initdb();
89
90struct passwd *
91getpwent()
92{
93 DBT key;
94 char bf[sizeof(_pw_keynum) + 1];
95 int rv;
96
97 if (!_pw_db && !__initdb())
98 return((struct passwd *)NULL);
99
100#ifdef YP
101 if(_pw_stepping_yp) {
102 _pw_passwd = _pw_copy;
103 if (unwind((char *)&_ypnam))
104 return(&_pw_passwd);
105 }
106#endif
107tryagain:
108
109 ++_pw_keynum;
110 bf[0] = _PW_KEYBYNUM;
111 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
112 key.data = (u_char *)bf;
113 key.size = sizeof(_pw_keynum) + 1;
114 rv = __hashpw(&key);
115 if(!rv) return (struct passwd *)NULL;
116#ifdef YP
117 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
118 bzero((char *)&_ypnam, sizeof(_ypnam));
119 bcopy(_pw_passwd.pw_name, _ypnam,
120 strlen(_pw_passwd.pw_name));
121 _pw_copy = _pw_passwd;
122 if (unwind((char *)&_ypnam) == 0)
123 goto tryagain;
124 else
125 return(&_pw_passwd);
126 }
127#else
128 /* Ignore YP password file entries when YP is disabled. */
129 if(_pw_passwd.pw_name[0] == '+' || _pw_passwd.pw_name[0] == '-') {
130 goto tryagain;
131 }
132#endif
133 return(&_pw_passwd);
134}
135
136struct passwd *
137getpwnam(name)
138 const char *name;
139{
140 DBT key;
141 int len, rval;
142 char bf[UT_NAMESIZE + 2];
143
144 if (!_pw_db && !__initdb())
145 return((struct passwd *)NULL);
146
147 bf[0] = _PW_KEYBYNAME;
148 len = strlen(name);
149 bcopy(name, bf + 1, MIN(len, UT_NAMESIZE));
150 key.data = (u_char *)bf;
151 key.size = len + 1;
152 rval = __hashpw(&key);
153
154#ifdef YP
155 if (!rval && _yp_enabled)
156 rval = _getyppass(&_pw_passwd, name, "passwd.byname");
157#endif
158 /*
159 * Prevent login attempts when YP is not enabled but YP entries
160 * are in /etc/master.passwd.
161 */
162 if (rval && (_pw_passwd.pw_name[0] == '+'||
163 _pw_passwd.pw_name[0] == '-')) rval = 0;
164
165 endpwent();
166 return(rval ? &_pw_passwd : (struct passwd *)NULL);
167}
168
169struct passwd *
165#ifdef __STDC__
166getpwuid(uid_t uid)
167#else
168getpwuid(uid)
170getpwuid(uid)
169 int uid;
170#endif
171 uid_t uid;
171{
172 DBT key;
173 int keyuid, rval;
174 char bf[sizeof(keyuid) + 1];
175
176 if (!_pw_db && !__initdb())
177 return((struct passwd *)NULL);
178
179 bf[0] = _PW_KEYBYUID;
180 keyuid = uid;
181 bcopy(&keyuid, bf + 1, sizeof(keyuid));
182 key.data = (u_char *)bf;
183 key.size = sizeof(keyuid) + 1;
184 rval = __hashpw(&key);
185
186#ifdef YP
187 if (!rval && _yp_enabled) {
188 char ypbuf[16]; /* big enough for 32-bit uids and then some */
189 snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid);
190 rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid");
191 }
192#endif
193 /*
194 * Prevent login attempts when YP is not enabled but YP entries
195 * are in /etc/master.passwd.
196 */
197 if (rval && (_pw_passwd.pw_name[0] == '+'||
198 _pw_passwd.pw_name[0] == '-')) rval = 0;
199
200 endpwent();
201 return(rval ? &_pw_passwd : (struct passwd *)NULL);
202}
203
204int
205setpassent(stayopen)
206 int stayopen;
207{
208 _pw_keynum = 0;
209#ifdef YP
210 _pw_stepping_yp = 0;
211#endif
212 _pw_stayopen = stayopen;
213 return(1);
214}
215
216int
217setpwent()
218{
219 _pw_keynum = 0;
220#ifdef YP
221 _pw_stepping_yp = 0;
222#endif
223 _pw_stayopen = 0;
224 return(1);
225}
226
227void
228endpwent()
229{
230 _pw_keynum = 0;
231#ifdef YP
232 _pw_stepping_yp = 0;
233#endif
234 if (_pw_db) {
235 (void)(_pw_db->close)(_pw_db);
236 _pw_db = (DB *)NULL;
237 }
238#ifdef YP
239 if (_ypcache) {
240 (void)(_ypcache->close)(_ypcache);
241 _ypcache = (DB *)NULL;
242 _yp_exclusions = 0;
243 }
244#endif
245}
246
247static int
248__initdb()
249{
250 static int warned;
251 char *p;
252
253 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
254 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
255 if (_pw_db) {
256#ifdef YP
257 DBT key, data;
258 char buf[] = { _PW_KEYYPENABLED };
259 key.data = buf;
260 key.size = 1;
261 if ((_pw_db->get)(_pw_db, &key, &data, 0)) {
262 _yp_enabled = 0;
263 } else {
264 _yp_enabled = (int)*((char *)data.data) - 2;
265 /* Don't even bother with this if we aren't root. */
266 if (!geteuid()) {
267 if (!_pw_yp_domain)
268 if (yp_get_default_domain(&_pw_yp_domain))
269 return(1);
270 _gotmaster = _havemaster(_pw_yp_domain);
271 } else _gotmaster = YP_HAVE_NONE;
272 if (!_ypcache)
273 _ypinitdb();
274 }
275#endif
276 return(1);
277 }
278 if (!warned++)
279 syslog(LOG_ERR, "%s: %m", p);
280 return(0);
281}
282
283static int
284__hashpw(key)
285 DBT *key;
286{
287 register char *p, *t;
288 static u_int max;
289 static char *line;
290 DBT data;
291
292 if ((_pw_db->get)(_pw_db, key, &data, 0))
293 return(0);
294 p = (char *)data.data;
295 if (data.size > max && !(line = realloc(line, max += 1024)))
296 return(0);
297
172{
173 DBT key;
174 int keyuid, rval;
175 char bf[sizeof(keyuid) + 1];
176
177 if (!_pw_db && !__initdb())
178 return((struct passwd *)NULL);
179
180 bf[0] = _PW_KEYBYUID;
181 keyuid = uid;
182 bcopy(&keyuid, bf + 1, sizeof(keyuid));
183 key.data = (u_char *)bf;
184 key.size = sizeof(keyuid) + 1;
185 rval = __hashpw(&key);
186
187#ifdef YP
188 if (!rval && _yp_enabled) {
189 char ypbuf[16]; /* big enough for 32-bit uids and then some */
190 snprintf(ypbuf, sizeof ypbuf, "%u", (unsigned)uid);
191 rval = _getyppass(&_pw_passwd, ypbuf, "passwd.byuid");
192 }
193#endif
194 /*
195 * Prevent login attempts when YP is not enabled but YP entries
196 * are in /etc/master.passwd.
197 */
198 if (rval && (_pw_passwd.pw_name[0] == '+'||
199 _pw_passwd.pw_name[0] == '-')) rval = 0;
200
201 endpwent();
202 return(rval ? &_pw_passwd : (struct passwd *)NULL);
203}
204
205int
206setpassent(stayopen)
207 int stayopen;
208{
209 _pw_keynum = 0;
210#ifdef YP
211 _pw_stepping_yp = 0;
212#endif
213 _pw_stayopen = stayopen;
214 return(1);
215}
216
217int
218setpwent()
219{
220 _pw_keynum = 0;
221#ifdef YP
222 _pw_stepping_yp = 0;
223#endif
224 _pw_stayopen = 0;
225 return(1);
226}
227
228void
229endpwent()
230{
231 _pw_keynum = 0;
232#ifdef YP
233 _pw_stepping_yp = 0;
234#endif
235 if (_pw_db) {
236 (void)(_pw_db->close)(_pw_db);
237 _pw_db = (DB *)NULL;
238 }
239#ifdef YP
240 if (_ypcache) {
241 (void)(_ypcache->close)(_ypcache);
242 _ypcache = (DB *)NULL;
243 _yp_exclusions = 0;
244 }
245#endif
246}
247
248static int
249__initdb()
250{
251 static int warned;
252 char *p;
253
254 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
255 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
256 if (_pw_db) {
257#ifdef YP
258 DBT key, data;
259 char buf[] = { _PW_KEYYPENABLED };
260 key.data = buf;
261 key.size = 1;
262 if ((_pw_db->get)(_pw_db, &key, &data, 0)) {
263 _yp_enabled = 0;
264 } else {
265 _yp_enabled = (int)*((char *)data.data) - 2;
266 /* Don't even bother with this if we aren't root. */
267 if (!geteuid()) {
268 if (!_pw_yp_domain)
269 if (yp_get_default_domain(&_pw_yp_domain))
270 return(1);
271 _gotmaster = _havemaster(_pw_yp_domain);
272 } else _gotmaster = YP_HAVE_NONE;
273 if (!_ypcache)
274 _ypinitdb();
275 }
276#endif
277 return(1);
278 }
279 if (!warned++)
280 syslog(LOG_ERR, "%s: %m", p);
281 return(0);
282}
283
284static int
285__hashpw(key)
286 DBT *key;
287{
288 register char *p, *t;
289 static u_int max;
290 static char *line;
291 DBT data;
292
293 if ((_pw_db->get)(_pw_db, key, &data, 0))
294 return(0);
295 p = (char *)data.data;
296 if (data.size > max && !(line = realloc(line, max += 1024)))
297 return(0);
298
299 /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
298 t = line;
299#define EXPAND(e) e = t; while ( (*t++ = *p++) );
300 t = line;
301#define EXPAND(e) e = t; while ( (*t++ = *p++) );
302#define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v
300 EXPAND(_pw_passwd.pw_name);
301 EXPAND(_pw_passwd.pw_passwd);
303 EXPAND(_pw_passwd.pw_name);
304 EXPAND(_pw_passwd.pw_passwd);
302 bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
303 p += sizeof(int);
304 bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
305 p += sizeof(int);
306 bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
307 p += sizeof(time_t);
305 SCALAR(_pw_passwd.pw_uid);
306 SCALAR(_pw_passwd.pw_gid);
307 SCALAR(_pw_passwd.pw_change);
308 EXPAND(_pw_passwd.pw_class);
309 EXPAND(_pw_passwd.pw_gecos);
310 EXPAND(_pw_passwd.pw_dir);
311 EXPAND(_pw_passwd.pw_shell);
308 EXPAND(_pw_passwd.pw_class);
309 EXPAND(_pw_passwd.pw_gecos);
310 EXPAND(_pw_passwd.pw_dir);
311 EXPAND(_pw_passwd.pw_shell);
312 bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
313 p += sizeof(time_t);
312 SCALAR(_pw_passwd.pw_expire);
314 bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);
315 p += sizeof _pw_passwd.pw_fields;
316 return(1);
317}
318
319#ifdef YP
320
321/*
322 * Create a DB hash database in memory. Bet you didn't know you
323 * could do a dbopen() will a NULL filename, did you.
324 */
325static inline void _ypinitdb()
326{
327 if (_ypcache == (DB *)NULL)
328 _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
329 return;
330}
331
332/*
333 * See if a user is in the blackballed list.
334 */
335static inline int lookup(name)
336 char *name;
337{
338 DBT key;
339
340 if (!_yp_exclusions)
341 return(0);
342
343 key.data = name;
344 key.size = strlen(name);
345
346 if ((_ypcache->get)(_ypcache, &key, &empty, 0)) {
347 return(0);
348 }
349
350 return(1);
351}
352
353/*
354 * Store a blackballed user in an in-core hash database.
355 */
356static inline void store(key)
357 char *key;
358{
359 DBT lkey;
360/*
361 if (lookup(key))
362 return;
363*/
364
365 _yp_exclusions = 1;
366
367 lkey.data = key;
368 lkey.size = strlen(key);
369
370 (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE);
371}
372
373/*
374 * Parse the + entries in the password database and do appropriate
375 * NIS lookups. While ugly to look at, this is optimized to do only
376 * as many lookups as are absolutely necessary in any given case.
377 * Basically, the getpwent() function will feed us + and - lines
378 * as they appear in the database. For + lines, we do netgroup/group
379 * and user lookups to find all usernames that match the rule and
380 * extract them from the NIS passwd maps. For - lines, we save the
381 * matching names in a database and a) exlude them, and b) make sure
382 * we don't consider them when processing other + lines that appear
383 * later.
384 */
385static inline int unwind(grp)
386 char *grp;
387{
388 char *user, *host, *domain;
389 static int latch = 0;
390 static struct group *gr = NULL;
391 int rv = 0;
392
393 if (grp[0] == '+') {
394 if (strlen(grp) == 1) {
395 return(_nextyppass(&_pw_passwd));
396 }
397 if (grp[1] == '@') {
398 _pw_stepping_yp = 1;
399grpagain:
400 if (gr != NULL) {
401 if (*gr->gr_mem != NULL) {
402 if (lookup(*gr->gr_mem)) {
403 gr->gr_mem++;
404 goto grpagain;
405 }
406 rv = _getyppass(&_pw_passwd,
407 *gr->gr_mem,
408 "passwd.byname");
409 gr->gr_mem++;
410 return(rv);
411 } else {
412 endgrent();
413 latch = 0;
414 gr = NULL;
415 return(0);
416 }
417 }
418 if (!latch) {
419 setnetgrent(grp+2);
420 latch++;
421 }
422again:
423 if (getnetgrent(&host, &user, &domain) == NULL) {
424 if ((gr = getgrnam(grp+2)) != NULL)
425 goto grpagain;
426 latch = 0;
427 _pw_stepping_yp = 0;
428 return(0);
429 } else {
430 if (lookup(user))
431 goto again;
432 if (_getyppass(&_pw_passwd, user,
433 "passwd.byname"))
434 return(1);
435 else
436 goto again;
437 }
438 } else {
439 if (lookup(grp+1))
440 return(0);
441 return(_getyppass(&_pw_passwd, grp+1, "passwd.byname"));
442 }
443 } else {
444 if (grp[1] == '@') {
445 setnetgrent(grp+2);
446 rv = 0;
447 while(getnetgrent(&host, &user, &domain) != NULL) {
448 store(user);
449 rv++;
450 }
451 if (!rv && (gr = getgrnam(grp+2)) != NULL) {
452 while(gr->gr_mem) {
453 store(gr->gr_mem);
454 gr->gr_mem++;
455 }
456 }
457 } else {
458 store(grp+1);
459 }
460 }
461 return(0);
462}
463
464/*
465 * See if a user is a member of a particular group.
466 */
467static inline int ingr(grp, name)
468 char *grp;
469 char *name;
470{
471 register struct group *gr;
472
473 if ((gr = getgrnam(grp)) == NULL)
474 return(0);
475
476 while(*gr->gr_mem) {
477 if (!strcmp(*gr->gr_mem, name)) {
478 endgrent();
479 return(1);
480 }
481 gr->gr_mem++;
482 }
483
484 endgrent();
485 return(0);
486}
487
488/*
489 * Check a user against the +@netgroup/-@netgroup lines listed in
490 * the local password database. Also checks +user/-user lines.
491 * If no netgroup exists that matches +@netgroup/-@netgroup,
492 * try searching regular groups with the same name.
493 */
494static inline int verf(name)
495 char *name;
496{
497 DBT key;
498 char bf[sizeof(_pw_keynum) + 1];
499 int keynum = 0;
500
501again:
502 ++keynum;
503 bf[0] = _PW_KEYYPBYNUM;
504 bcopy((char *)&keynum, bf + 1, sizeof(keynum));
505 key.data = (u_char *)bf;
506 key.size = sizeof(keynum) + 1;
507 if (!__hashpw(&key)) {
508 /* Try again using old format */
509 bf[0] = _PW_KEYBYNUM;
510 bcopy((char *)&keynum, bf + 1, sizeof(keynum));
511 key.data = (u_char *)bf;
512 if (!__hashpw(&key))
513 return(0);
514 }
515 if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-'))
516 goto again;
517 if (_pw_passwd.pw_name[0] == '+') {
518 if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */
519 return(1);
520 if (_pw_passwd.pw_name[1] == '@') {
521 if ((innetgr(_pw_passwd.pw_name+2, NULL, name,
522 _pw_yp_domain) ||
523 ingr(_pw_passwd.pw_name+2, name)) && !lookup(name))
524 return(1);
525 else
526 goto again;
527 } else {
528 if (!strcmp(name, _pw_passwd.pw_name+1) &&
529 !lookup(name))
530 return(1);
531 else
532 goto again;
533 }
534 }
535 if (_pw_passwd.pw_name[0] == '-') {
536 /* Note that a minus wildcard is a no-op. */
537 if (_pw_passwd.pw_name[1] == '@') {
538 if (innetgr(_pw_passwd.pw_name+2, NULL, name,
539 _pw_yp_domain) ||
540 ingr(_pw_passwd.pw_name+2, name)) {
541 store(name);
542 return(0);
543 } else
544 goto again;
545 } else {
546 if (!strcmp(name, _pw_passwd.pw_name+1)) {
547 store(name);
548 return(0);
549 } else
550 goto again;
551 }
552
553 }
554 return(0);
555}
556
557static char * _get_adjunct_pw(name)
558 char *name;
559{
560 static char adjunctbuf[YPMAXRECORD+2];
561 int rval;
562 char *result;
563 int resultlen;
564 char *map = "passwd.adjunct.byname";
565 char *s;
566
567 if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name),
568 &result, &resultlen)))
569 return(NULL);
570
571 strncpy(adjunctbuf, result, resultlen);
572 adjunctbuf[resultlen] = '\0';
573 free(result);
574 result = (char *)&adjunctbuf;
575
576 /* Don't care about the name. */
577 if ((s = strsep(&result, ":")) == NULL)
578 return (NULL); /* name */
579 if ((s = strsep(&result, ":")) == NULL)
580 return (NULL); /* password */
581
582 return(s);
583}
584
585static int
586_pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master)
587{
588 char *s, *result;
589 static char resbuf[YPMAXRECORD+2];
590
591 /*
592 * Be triple, ultra super-duper paranoid: reject entries
593 * that start with a + or -. yp_mkdb and /var/yp/Makefile
594 * are _both_ supposed to strip these out, but you never
595 * know.
596 */
597 if (*res == '+' || *res == '-')
598 return 0;
599
600 /*
601 * The NIS protocol definition limits the size of an NIS
602 * record to YPMAXRECORD bytes. We need to do a copy to
603 * a static buffer here since the memory pointed to by
604 * res will be free()ed when this function returns.
605 */
606 strncpy((char *)&resbuf, res, resultlen);
607 resbuf[resultlen] = '\0';
608 result = (char *)&resbuf;
609
610 /*
611 * XXX Sanity check: make sure all fields are valid (no NULLs).
612 * If we find a badly formatted entry, we punt.
613 */
614 if ((s = strsep(&result, ":")) == NULL) return 0; /* name */
615 /*
616 * We don't care what pw_fields says: we _always_ want the
617 * username returned to us by NIS.
618 */
619 pw->pw_name = s;
620 pw->pw_fields |= _PWF_NAME;
621
622 if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
623 if(!(pw->pw_fields & _PWF_PASSWD)) {
624 /* SunOS passwd.adjunct hack */
625 if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) {
626 char *realpw;
627 realpw = _get_adjunct_pw(pw->pw_name);
628 if (realpw == NULL)
629 pw->pw_passwd = s;
630 else
631 pw->pw_passwd = realpw;
632 } else {
633 pw->pw_passwd = s;
634 }
635 pw->pw_fields |= _PWF_PASSWD;
636 }
637
638 if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */
639 if(!(pw->pw_fields & _PWF_UID)) {
640 pw->pw_uid = atoi(s);
641 pw->pw_fields |= _PWF_UID;
642 }
643
644 if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */
645 if(!(pw->pw_fields & _PWF_GID)) {
646 pw->pw_gid = atoi(s);
647 pw->pw_fields |= _PWF_GID;
648 }
649
650 if (master == YP_HAVE_MASTER) {
651 if ((s = strsep(&result, ":")) == NULL) return 0; /* class */
652 if(!(pw->pw_fields & _PWF_CLASS)) {
653 pw->pw_class = s;
654 pw->pw_fields |= _PWF_CLASS;
655 }
656
657 if ((s = strsep(&result, ":")) == NULL) return 0; /* change */
658 if(!(pw->pw_fields & _PWF_CHANGE)) {
659 pw->pw_change = atol(s);
660 pw->pw_fields |= _PWF_CHANGE;
661 }
662
663 if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */
664 if(!(pw->pw_fields & _PWF_EXPIRE)) {
665 pw->pw_expire = atol(s);
666 pw->pw_fields |= _PWF_EXPIRE;
667 }
668 }
669
670 if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */
671 if(!(pw->pw_fields & _PWF_GECOS)) {
672 pw->pw_gecos = s;
673 pw->pw_fields |= _PWF_GECOS;
674 }
675
676 if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */
677 if(!(pw->pw_fields & _PWF_DIR)) {
678 pw->pw_dir = s;
679 pw->pw_fields |= _PWF_DIR;
680 }
681
682 if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */
683 if(!(pw->pw_fields & _PWF_SHELL)) {
684 pw->pw_shell = s;
685 pw->pw_fields |= _PWF_SHELL;
686 }
687
688 /* Be consistent. */
689 if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0';
690
691 return 1;
692}
693
694static int
695_havemaster(char *_pw_yp_domain)
696{
697 int order;
698 int rval;
699
700 if (!(rval = yp_order(_pw_yp_domain, "master.passwd.byname", &order)))
701 return(YP_HAVE_MASTER);
702
703 /*
704 * NIS+ in YP compat mode doesn't support
705 * YPPROC_ORDER -- no point in continuing.
706 */
707 if (rval == YPERR_YPERR)
708 return(YP_HAVE_NONE);
709
710 /* master.passwd doesn't exist -- try passwd.adjunct */
711 if (rval == YPERR_MAP) {
712 rval = yp_order(_pw_yp_domain, "passwd.adjunct.byname", &order);
713 if (!rval)
714 return(YP_HAVE_ADJUNCT);
715 }
716
717 return (YP_HAVE_NONE);
718}
719
720static int
721_getyppass(struct passwd *pw, const char *name, const char *map)
722{
723 char *result, *s;
724 int resultlen;
725 int rv;
726 char mastermap[YPMAXRECORD];
727
728 if(!_pw_yp_domain) {
729 if(yp_get_default_domain(&_pw_yp_domain))
730 return 0;
731 }
732
733 sprintf(mastermap,"%s",map);
734
735 if (_gotmaster == YP_HAVE_MASTER)
736 sprintf(mastermap,"master.%s", map);
737
738 if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name),
739 &result, &resultlen))
740 return 0;
741
742 if (!_pw_stepping_yp) {
743 s = strchr(result, ':');
744 if (s) {
745 *s = '\0';
746 } else {
747 /* Must be a malformed entry if no colons. */
748 free(result);
749 return(0);
750 }
751
752 if (!verf(result)) {
753 *s = ':';
754 free(result);
755 return(0);
756 }
757
758 *s = ':'; /* Put back the colon we previously replaced with a NUL. */
759 }
760
761 rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster);
762 free(result);
763 return(rv);
764}
765
766static int
767_nextyppass(struct passwd *pw)
768{
769 static char *key;
770 static int keylen;
771 char *lastkey, *result, *s;
772 int resultlen;
773 int rv;
774 char *map = "passwd.byname";
775
776 if(!_pw_yp_domain) {
777 if(yp_get_default_domain(&_pw_yp_domain))
778 return 0;
779 }
780
781 if (_gotmaster == YP_HAVE_MASTER)
782 map = "master.passwd.byname";
783
784 if(!_pw_stepping_yp) {
785 if(key) free(key);
786 rv = yp_first(_pw_yp_domain, map,
787 &key, &keylen, &result, &resultlen);
788 if(rv) {
789 return 0;
790 }
791 _pw_stepping_yp = 1;
792 goto unpack;
793 } else {
794tryagain:
795 lastkey = key;
796 rv = yp_next(_pw_yp_domain, map, key, keylen,
797 &key, &keylen, &result, &resultlen);
798 free(lastkey);
799unpack:
800 if(rv) {
801 _pw_stepping_yp = 0;
802 return 0;
803 }
804
805 s = strchr(result, ':');
806 if (s) {
807 *s = '\0';
808 } else {
809 /* Must be a malformed entry if no colons. */
810 free(result);
811 goto tryagain;
812 }
813
814 if (lookup(result)) {
815 *s = ':';
816 free(result);
817 goto tryagain;
818 }
819
820 *s = ':'; /* Put back the colon we previously replaced with a NUL. */
821 if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) {
822 free(result);
823 return(1);
824 } else {
825 free(result);
826 goto tryagain;
827 }
828 }
829}
830
831#endif /* YP */
313 bcopy(p, (char *)&_pw_passwd.pw_fields, sizeof _pw_passwd.pw_fields);
314 p += sizeof _pw_passwd.pw_fields;
315 return(1);
316}
317
318#ifdef YP
319
320/*
321 * Create a DB hash database in memory. Bet you didn't know you
322 * could do a dbopen() will a NULL filename, did you.
323 */
324static inline void _ypinitdb()
325{
326 if (_ypcache == (DB *)NULL)
327 _ypcache = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
328 return;
329}
330
331/*
332 * See if a user is in the blackballed list.
333 */
334static inline int lookup(name)
335 char *name;
336{
337 DBT key;
338
339 if (!_yp_exclusions)
340 return(0);
341
342 key.data = name;
343 key.size = strlen(name);
344
345 if ((_ypcache->get)(_ypcache, &key, &empty, 0)) {
346 return(0);
347 }
348
349 return(1);
350}
351
352/*
353 * Store a blackballed user in an in-core hash database.
354 */
355static inline void store(key)
356 char *key;
357{
358 DBT lkey;
359/*
360 if (lookup(key))
361 return;
362*/
363
364 _yp_exclusions = 1;
365
366 lkey.data = key;
367 lkey.size = strlen(key);
368
369 (void)(_ypcache->put)(_ypcache, &lkey, &empty, R_NOOVERWRITE);
370}
371
372/*
373 * Parse the + entries in the password database and do appropriate
374 * NIS lookups. While ugly to look at, this is optimized to do only
375 * as many lookups as are absolutely necessary in any given case.
376 * Basically, the getpwent() function will feed us + and - lines
377 * as they appear in the database. For + lines, we do netgroup/group
378 * and user lookups to find all usernames that match the rule and
379 * extract them from the NIS passwd maps. For - lines, we save the
380 * matching names in a database and a) exlude them, and b) make sure
381 * we don't consider them when processing other + lines that appear
382 * later.
383 */
384static inline int unwind(grp)
385 char *grp;
386{
387 char *user, *host, *domain;
388 static int latch = 0;
389 static struct group *gr = NULL;
390 int rv = 0;
391
392 if (grp[0] == '+') {
393 if (strlen(grp) == 1) {
394 return(_nextyppass(&_pw_passwd));
395 }
396 if (grp[1] == '@') {
397 _pw_stepping_yp = 1;
398grpagain:
399 if (gr != NULL) {
400 if (*gr->gr_mem != NULL) {
401 if (lookup(*gr->gr_mem)) {
402 gr->gr_mem++;
403 goto grpagain;
404 }
405 rv = _getyppass(&_pw_passwd,
406 *gr->gr_mem,
407 "passwd.byname");
408 gr->gr_mem++;
409 return(rv);
410 } else {
411 endgrent();
412 latch = 0;
413 gr = NULL;
414 return(0);
415 }
416 }
417 if (!latch) {
418 setnetgrent(grp+2);
419 latch++;
420 }
421again:
422 if (getnetgrent(&host, &user, &domain) == NULL) {
423 if ((gr = getgrnam(grp+2)) != NULL)
424 goto grpagain;
425 latch = 0;
426 _pw_stepping_yp = 0;
427 return(0);
428 } else {
429 if (lookup(user))
430 goto again;
431 if (_getyppass(&_pw_passwd, user,
432 "passwd.byname"))
433 return(1);
434 else
435 goto again;
436 }
437 } else {
438 if (lookup(grp+1))
439 return(0);
440 return(_getyppass(&_pw_passwd, grp+1, "passwd.byname"));
441 }
442 } else {
443 if (grp[1] == '@') {
444 setnetgrent(grp+2);
445 rv = 0;
446 while(getnetgrent(&host, &user, &domain) != NULL) {
447 store(user);
448 rv++;
449 }
450 if (!rv && (gr = getgrnam(grp+2)) != NULL) {
451 while(gr->gr_mem) {
452 store(gr->gr_mem);
453 gr->gr_mem++;
454 }
455 }
456 } else {
457 store(grp+1);
458 }
459 }
460 return(0);
461}
462
463/*
464 * See if a user is a member of a particular group.
465 */
466static inline int ingr(grp, name)
467 char *grp;
468 char *name;
469{
470 register struct group *gr;
471
472 if ((gr = getgrnam(grp)) == NULL)
473 return(0);
474
475 while(*gr->gr_mem) {
476 if (!strcmp(*gr->gr_mem, name)) {
477 endgrent();
478 return(1);
479 }
480 gr->gr_mem++;
481 }
482
483 endgrent();
484 return(0);
485}
486
487/*
488 * Check a user against the +@netgroup/-@netgroup lines listed in
489 * the local password database. Also checks +user/-user lines.
490 * If no netgroup exists that matches +@netgroup/-@netgroup,
491 * try searching regular groups with the same name.
492 */
493static inline int verf(name)
494 char *name;
495{
496 DBT key;
497 char bf[sizeof(_pw_keynum) + 1];
498 int keynum = 0;
499
500again:
501 ++keynum;
502 bf[0] = _PW_KEYYPBYNUM;
503 bcopy((char *)&keynum, bf + 1, sizeof(keynum));
504 key.data = (u_char *)bf;
505 key.size = sizeof(keynum) + 1;
506 if (!__hashpw(&key)) {
507 /* Try again using old format */
508 bf[0] = _PW_KEYBYNUM;
509 bcopy((char *)&keynum, bf + 1, sizeof(keynum));
510 key.data = (u_char *)bf;
511 if (!__hashpw(&key))
512 return(0);
513 }
514 if (_pw_passwd.pw_name[0] != '+' && (_pw_passwd.pw_name[0] != '-'))
515 goto again;
516 if (_pw_passwd.pw_name[0] == '+') {
517 if (strlen(_pw_passwd.pw_name) == 1) /* Wildcard */
518 return(1);
519 if (_pw_passwd.pw_name[1] == '@') {
520 if ((innetgr(_pw_passwd.pw_name+2, NULL, name,
521 _pw_yp_domain) ||
522 ingr(_pw_passwd.pw_name+2, name)) && !lookup(name))
523 return(1);
524 else
525 goto again;
526 } else {
527 if (!strcmp(name, _pw_passwd.pw_name+1) &&
528 !lookup(name))
529 return(1);
530 else
531 goto again;
532 }
533 }
534 if (_pw_passwd.pw_name[0] == '-') {
535 /* Note that a minus wildcard is a no-op. */
536 if (_pw_passwd.pw_name[1] == '@') {
537 if (innetgr(_pw_passwd.pw_name+2, NULL, name,
538 _pw_yp_domain) ||
539 ingr(_pw_passwd.pw_name+2, name)) {
540 store(name);
541 return(0);
542 } else
543 goto again;
544 } else {
545 if (!strcmp(name, _pw_passwd.pw_name+1)) {
546 store(name);
547 return(0);
548 } else
549 goto again;
550 }
551
552 }
553 return(0);
554}
555
556static char * _get_adjunct_pw(name)
557 char *name;
558{
559 static char adjunctbuf[YPMAXRECORD+2];
560 int rval;
561 char *result;
562 int resultlen;
563 char *map = "passwd.adjunct.byname";
564 char *s;
565
566 if ((rval = yp_match(_pw_yp_domain, map, name, strlen(name),
567 &result, &resultlen)))
568 return(NULL);
569
570 strncpy(adjunctbuf, result, resultlen);
571 adjunctbuf[resultlen] = '\0';
572 free(result);
573 result = (char *)&adjunctbuf;
574
575 /* Don't care about the name. */
576 if ((s = strsep(&result, ":")) == NULL)
577 return (NULL); /* name */
578 if ((s = strsep(&result, ":")) == NULL)
579 return (NULL); /* password */
580
581 return(s);
582}
583
584static int
585_pw_breakout_yp(struct passwd *pw, char *res, int resultlen, int master)
586{
587 char *s, *result;
588 static char resbuf[YPMAXRECORD+2];
589
590 /*
591 * Be triple, ultra super-duper paranoid: reject entries
592 * that start with a + or -. yp_mkdb and /var/yp/Makefile
593 * are _both_ supposed to strip these out, but you never
594 * know.
595 */
596 if (*res == '+' || *res == '-')
597 return 0;
598
599 /*
600 * The NIS protocol definition limits the size of an NIS
601 * record to YPMAXRECORD bytes. We need to do a copy to
602 * a static buffer here since the memory pointed to by
603 * res will be free()ed when this function returns.
604 */
605 strncpy((char *)&resbuf, res, resultlen);
606 resbuf[resultlen] = '\0';
607 result = (char *)&resbuf;
608
609 /*
610 * XXX Sanity check: make sure all fields are valid (no NULLs).
611 * If we find a badly formatted entry, we punt.
612 */
613 if ((s = strsep(&result, ":")) == NULL) return 0; /* name */
614 /*
615 * We don't care what pw_fields says: we _always_ want the
616 * username returned to us by NIS.
617 */
618 pw->pw_name = s;
619 pw->pw_fields |= _PWF_NAME;
620
621 if ((s = strsep(&result, ":")) == NULL) return 0; /* password */
622 if(!(pw->pw_fields & _PWF_PASSWD)) {
623 /* SunOS passwd.adjunct hack */
624 if (master == YP_HAVE_ADJUNCT && strstr(s, "##") != NULL) {
625 char *realpw;
626 realpw = _get_adjunct_pw(pw->pw_name);
627 if (realpw == NULL)
628 pw->pw_passwd = s;
629 else
630 pw->pw_passwd = realpw;
631 } else {
632 pw->pw_passwd = s;
633 }
634 pw->pw_fields |= _PWF_PASSWD;
635 }
636
637 if ((s = strsep(&result, ":")) == NULL) return 0; /* uid */
638 if(!(pw->pw_fields & _PWF_UID)) {
639 pw->pw_uid = atoi(s);
640 pw->pw_fields |= _PWF_UID;
641 }
642
643 if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */
644 if(!(pw->pw_fields & _PWF_GID)) {
645 pw->pw_gid = atoi(s);
646 pw->pw_fields |= _PWF_GID;
647 }
648
649 if (master == YP_HAVE_MASTER) {
650 if ((s = strsep(&result, ":")) == NULL) return 0; /* class */
651 if(!(pw->pw_fields & _PWF_CLASS)) {
652 pw->pw_class = s;
653 pw->pw_fields |= _PWF_CLASS;
654 }
655
656 if ((s = strsep(&result, ":")) == NULL) return 0; /* change */
657 if(!(pw->pw_fields & _PWF_CHANGE)) {
658 pw->pw_change = atol(s);
659 pw->pw_fields |= _PWF_CHANGE;
660 }
661
662 if ((s = strsep(&result, ":")) == NULL) return 0; /* expire */
663 if(!(pw->pw_fields & _PWF_EXPIRE)) {
664 pw->pw_expire = atol(s);
665 pw->pw_fields |= _PWF_EXPIRE;
666 }
667 }
668
669 if ((s = strsep(&result, ":")) == NULL) return 0; /* gecos */
670 if(!(pw->pw_fields & _PWF_GECOS)) {
671 pw->pw_gecos = s;
672 pw->pw_fields |= _PWF_GECOS;
673 }
674
675 if ((s = strsep(&result, ":")) == NULL) return 0; /* dir */
676 if(!(pw->pw_fields & _PWF_DIR)) {
677 pw->pw_dir = s;
678 pw->pw_fields |= _PWF_DIR;
679 }
680
681 if ((s = strsep(&result, ":")) == NULL) return 0; /* shell */
682 if(!(pw->pw_fields & _PWF_SHELL)) {
683 pw->pw_shell = s;
684 pw->pw_fields |= _PWF_SHELL;
685 }
686
687 /* Be consistent. */
688 if ((s = strchr(pw->pw_shell, '\n'))) *s = '\0';
689
690 return 1;
691}
692
693static int
694_havemaster(char *_pw_yp_domain)
695{
696 int order;
697 int rval;
698
699 if (!(rval = yp_order(_pw_yp_domain, "master.passwd.byname", &order)))
700 return(YP_HAVE_MASTER);
701
702 /*
703 * NIS+ in YP compat mode doesn't support
704 * YPPROC_ORDER -- no point in continuing.
705 */
706 if (rval == YPERR_YPERR)
707 return(YP_HAVE_NONE);
708
709 /* master.passwd doesn't exist -- try passwd.adjunct */
710 if (rval == YPERR_MAP) {
711 rval = yp_order(_pw_yp_domain, "passwd.adjunct.byname", &order);
712 if (!rval)
713 return(YP_HAVE_ADJUNCT);
714 }
715
716 return (YP_HAVE_NONE);
717}
718
719static int
720_getyppass(struct passwd *pw, const char *name, const char *map)
721{
722 char *result, *s;
723 int resultlen;
724 int rv;
725 char mastermap[YPMAXRECORD];
726
727 if(!_pw_yp_domain) {
728 if(yp_get_default_domain(&_pw_yp_domain))
729 return 0;
730 }
731
732 sprintf(mastermap,"%s",map);
733
734 if (_gotmaster == YP_HAVE_MASTER)
735 sprintf(mastermap,"master.%s", map);
736
737 if(yp_match(_pw_yp_domain, (char *)&mastermap, name, strlen(name),
738 &result, &resultlen))
739 return 0;
740
741 if (!_pw_stepping_yp) {
742 s = strchr(result, ':');
743 if (s) {
744 *s = '\0';
745 } else {
746 /* Must be a malformed entry if no colons. */
747 free(result);
748 return(0);
749 }
750
751 if (!verf(result)) {
752 *s = ':';
753 free(result);
754 return(0);
755 }
756
757 *s = ':'; /* Put back the colon we previously replaced with a NUL. */
758 }
759
760 rv = _pw_breakout_yp(pw, result, resultlen, _gotmaster);
761 free(result);
762 return(rv);
763}
764
765static int
766_nextyppass(struct passwd *pw)
767{
768 static char *key;
769 static int keylen;
770 char *lastkey, *result, *s;
771 int resultlen;
772 int rv;
773 char *map = "passwd.byname";
774
775 if(!_pw_yp_domain) {
776 if(yp_get_default_domain(&_pw_yp_domain))
777 return 0;
778 }
779
780 if (_gotmaster == YP_HAVE_MASTER)
781 map = "master.passwd.byname";
782
783 if(!_pw_stepping_yp) {
784 if(key) free(key);
785 rv = yp_first(_pw_yp_domain, map,
786 &key, &keylen, &result, &resultlen);
787 if(rv) {
788 return 0;
789 }
790 _pw_stepping_yp = 1;
791 goto unpack;
792 } else {
793tryagain:
794 lastkey = key;
795 rv = yp_next(_pw_yp_domain, map, key, keylen,
796 &key, &keylen, &result, &resultlen);
797 free(lastkey);
798unpack:
799 if(rv) {
800 _pw_stepping_yp = 0;
801 return 0;
802 }
803
804 s = strchr(result, ':');
805 if (s) {
806 *s = '\0';
807 } else {
808 /* Must be a malformed entry if no colons. */
809 free(result);
810 goto tryagain;
811 }
812
813 if (lookup(result)) {
814 *s = ':';
815 free(result);
816 goto tryagain;
817 }
818
819 *s = ':'; /* Put back the colon we previously replaced with a NUL. */
820 if (_pw_breakout_yp(pw, result, resultlen, _gotmaster)) {
821 free(result);
822 return(1);
823 } else {
824 free(result);
825 goto tryagain;
826 }
827 }
828}
829
830#endif /* YP */