Bug Summary

File:src/lib/libc/gen/getpwent.c
Warning:line 1014, column 3
Value stored to 'p' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name getpwent.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libc/obj -resource-dir /usr/local/llvm16/lib/clang/16 -include namespace.h -I /usr/src/lib/libc/include -I /usr/src/lib/libc/hidden -D __LIBC__ -D APIWARN -D YP -I /usr/src/lib/libc/yp -I /usr/src/lib/libc -I /usr/src/lib/libc/gdtoa -I /usr/src/lib/libc/arch/amd64/gdtoa -D INFNAN_CHECK -D MULTIPLE_THREADS -D NO_FENV_H -D USE_LOCALE -I /usr/src/lib/libc -I /usr/src/lib/libc/citrus -D RESOLVSORT -D FLOATING_POINT -D PRINTF_WIDE_CHAR -D SCANF_WIDE_CHAR -D FUTEX -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libc/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libc/gen/getpwent.c
1/* $OpenBSD: getpwent.c,v 1.66 2022/08/02 17:00:15 deraadt Exp $ */
2/*
3 * Copyright (c) 2008 Theo de Raadt
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 * Portions Copyright (c) 1994, 1995, 1996, Jason Downs. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/types.h>
34#include <sys/mman.h>
35#include <fcntl.h>
36#include <db.h>
37#include <syslog.h>
38#include <pwd.h>
39#include <errno(*__errno()).h>
40#include <unistd.h>
41#include <stdbool.h>
42#include <stdlib.h>
43#include <string.h>
44#include <limits.h>
45#include <netgroup.h>
46#ifdef YP1
47#include <stdio.h>
48#include <rpc/rpc.h>
49#include <rpcsvc/yp.h>
50#include <rpcsvc/ypclnt.h>
51#include "ypinternal.h"
52#include "ypexclude.h"
53#endif
54#include "thread_private.h"
55
56#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
57
58struct pw_storage {
59 struct passwd pw;
60 uid_t uid;
61 char name[_PW_NAME_LEN31 + 1];
62 char pwbuf[_PW_BUF_LEN1024];
63};
64
65_THREAD_PRIVATE_KEY(pw)static void *_thread_tagname_pw;
66
67static DB *_pw_db; /* password database */
68
69/* mmap'd password storage */
70static struct pw_storage *_pw_storage = MAP_FAILED((void *)-1);
71
72/* Following are used only by setpwent(), getpwent(), and endpwent() */
73static int _pw_keynum; /* key counter */
74static int _pw_stayopen; /* keep fd's open */
75static int _pw_flags; /* password flags */
76
77static int __hashpw(DBT *, char *buf, size_t buflen, struct passwd *, int *);
78static int __initdb(int);
79static struct passwd *_pwhashbyname(const char *name, char *buf,
80 size_t buflen, struct passwd *pw, int *);
81static struct passwd *_pwhashbyuid(uid_t uid, char *buf,
82 size_t buflen, struct passwd *pw, int *);
83
84#ifdef YP1
85static char *__ypdomain;
86
87/* Following are used only by setpwent(), getpwent(), and endpwent() */
88enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_USER, YPMODE_NETGRP };
89static enum _ypmode __ypmode;
90static char *__ypcurrent;
91static int __ypcurrentlen;
92static int __yp_pw_flags;
93static int __getpwent_has_yppw = -1;
94static struct _ypexclude *__ypexhead;
95
96static int __has_yppw(void);
97static int __has_ypmaster(void);
98static int __ypparse(struct passwd *pw, char *s, int);
99
100#define LOOKUP_BYNAME0 0
101#define LOOKUP_BYUID1 1
102static struct passwd *__yppwlookup(int, char *, uid_t, struct passwd *,
103 char *, size_t, int *);
104
105/* macro for deciding which YP maps to use. */
106#define PASSWD_BYNAME(__has_ypmaster() ? "master.passwd.byname" : "passwd.byname") \
107 (__has_ypmaster() ? "master.passwd.byname" : "passwd.byname")
108#define PASSWD_BYUID(__has_ypmaster() ? "master.passwd.byuid" : "passwd.byuid") \
109 (__has_ypmaster() ? "master.passwd.byuid" : "passwd.byuid")
110
111static struct passwd *__ypproto;
112
113static void __ypproto_set(struct passwd *, struct pw_storage *, int, int *);
114
115static void
116__ypproto_set(struct passwd *pw, struct pw_storage *buf, int flags,
117 int *yp_pw_flagsp)
118{
119 char *ptr = buf->pwbuf;
120 __ypproto = &buf->pw;
121
122 /* name */
123 if (pw->pw_name && (pw->pw_name)[0]) {
124 bcopy(pw->pw_name, ptr, strlen(pw->pw_name) + 1);
125 __ypproto->pw_name = ptr;
126 ptr += (strlen(pw->pw_name) + 1);
127 } else
128 __ypproto->pw_name = NULL((void *)0);
129
130 /* password */
131 if (pw->pw_passwd && (pw->pw_passwd)[0]) {
132 bcopy(pw->pw_passwd, ptr, strlen(pw->pw_passwd) + 1);
133 __ypproto->pw_passwd = ptr;
134 ptr += (strlen(pw->pw_passwd) + 1);
135 } else
136 __ypproto->pw_passwd = NULL((void *)0);
137
138 /* uid */
139 __ypproto->pw_uid = pw->pw_uid;
140
141 /* gid */
142 __ypproto->pw_gid = pw->pw_gid;
143
144 /* change (ignored anyway) */
145 __ypproto->pw_change = pw->pw_change;
146
147 /* class (ignored anyway) */
148 __ypproto->pw_class = "";
149
150 /* gecos */
151 if (pw->pw_gecos && (pw->pw_gecos)[0]) {
152 bcopy(pw->pw_gecos, ptr, strlen(pw->pw_gecos) + 1);
153 __ypproto->pw_gecos = ptr;
154 ptr += (strlen(pw->pw_gecos) + 1);
155 } else
156 __ypproto->pw_gecos = NULL((void *)0);
157
158 /* dir */
159 if (pw->pw_dir && (pw->pw_dir)[0]) {
160 bcopy(pw->pw_dir, ptr, strlen(pw->pw_dir) + 1);
161 __ypproto->pw_dir = ptr;
162 ptr += (strlen(pw->pw_dir) + 1);
163 } else
164 __ypproto->pw_dir = NULL((void *)0);
165
166 /* shell */
167 if (pw->pw_shell && (pw->pw_shell)[0]) {
168 bcopy(pw->pw_shell, ptr, strlen(pw->pw_shell) + 1);
169 __ypproto->pw_shell = ptr;
170 ptr += (strlen(pw->pw_shell) + 1);
171 } else
172 __ypproto->pw_shell = NULL((void *)0);
173
174 /* expire (ignored anyway) */
175 __ypproto->pw_expire = pw->pw_expire;
176
177 /* flags */
178 *yp_pw_flagsp = flags;
179}
180
181static int
182__ypparse(struct passwd *pw, char *s, int yp_pw_flags)
183{
184 char *bp, *cp, *endp;
185 u_long ul;
186 int count = 0;
187
188 /* count the colons. */
189 bp = s;
190 while (*bp != '\0') {
191 if (*bp++ == ':')
192 count++;
193 }
194
195 /* since this is currently using strsep(), parse it first */
196 bp = s;
197 pw->pw_name = strsep(&bp, ":\n");
198 pw->pw_passwd = strsep(&bp, ":\n");
199 if (!(cp = strsep(&bp, ":\n")))
200 return (1);
201 ul = strtoul(cp, &endp, 10);
202 if (endp == cp || *endp != '\0' || ul >= UID_MAX0xffffffffU)
203 return (1);
204 pw->pw_uid = (uid_t)ul;
205 if (!(cp = strsep(&bp, ":\n")))
206 return (1);
207 ul = strtoul(cp, &endp, 10);
208 if (endp == cp || *endp != '\0' || ul >= GID_MAX0xffffffffU)
209 return (1);
210 pw->pw_gid = (gid_t)ul;
211 if (count == 9) {
212 long l;
213
214 /* If the ypserv gave us all the fields, use them. */
215 pw->pw_class = strsep(&bp, ":\n");
216 if (!(cp = strsep(&bp, ":\n")))
217 return (1);
218 l = strtol(cp, &endp, 10);
219 if (endp == cp || *endp != '\0' || l >= INT_MAX0x7fffffff || l <= INT_MIN(-0x7fffffff-1))
220 return (1);
221 pw->pw_change = (time_t)l;
222 if (!(cp = strsep(&bp, ":\n")))
223 return (1);
224 l = strtol(cp, &endp, 10);
225 if (endp == cp || *endp != '\0' || l >= INT_MAX0x7fffffff || l <= INT_MIN(-0x7fffffff-1))
226 return (1);
227 pw->pw_expire = (time_t)l;
228 } else {
229 /* ..else it is a normal ypserv. */
230 pw->pw_class = "";
231 pw->pw_change = 0;
232 pw->pw_expire = 0;
233 }
234 pw->pw_gecos = strsep(&bp, ":\n");
235 pw->pw_dir = strsep(&bp, ":\n");
236 pw->pw_shell = strsep(&bp, ":\n");
237
238 /* now let the prototype override, if set. */
239 if (__ypproto) {
240 if (!(yp_pw_flags & _PASSWORD_NOUID0x01))
241 pw->pw_uid = __ypproto->pw_uid;
242 if (!(yp_pw_flags & _PASSWORD_NOGID0x02))
243 pw->pw_gid = __ypproto->pw_gid;
244 if (__ypproto->pw_gecos)
245 pw->pw_gecos = __ypproto->pw_gecos;
246 if (__ypproto->pw_dir)
247 pw->pw_dir = __ypproto->pw_dir;
248 if (__ypproto->pw_shell)
249 pw->pw_shell = __ypproto->pw_shell;
250 }
251 return (0);
252}
253#endif
254
255static struct passwd *
256__get_pw_buf(char **bufp, size_t *buflenp, uid_t uid, const char *name)
257{
258 bool_Bool remap = true1;
259
260 /* Unmap the old buffer unless we are looking up the same uid/name */
261 if (_pw_storage != MAP_FAILED((void *)-1)) {
262 if (name != NULL((void *)0)) {
263 if (strcmp(_pw_storage->name, name) == 0) {
264#ifdef PWDEBUG
265 struct syslog_data sdata = SYSLOG_DATA_INIT{0, (const char *)0, (1<<3), 0xff};
266 syslog_r(LOG_CRIT2 | LOG_CONS0x02, &sdata,
267 "repeated passwd lookup of user \"%s\"",
268 name);
269#endif
270 remap = false0;
271 }
272 } else if (uid != (uid_t)-1) {
273 if (_pw_storage->uid == uid) {
274#ifdef PWDEBUG
275 struct syslog_data sdata = SYSLOG_DATA_INIT{0, (const char *)0, (1<<3), 0xff};
276 syslog_r(LOG_CRIT2 | LOG_CONS0x02, &sdata,
277 "repeated passwd lookup of uid %u",
278 uid);
279#endif
280 remap = false0;
281 }
282 }
283 if (remap)
284 munmap(_pw_storage, sizeof(*_pw_storage));
285 }
286
287 if (remap) {
288 _pw_storage = mmap(NULL((void *)0), sizeof(*_pw_storage),
289 PROT_READ0x01|PROT_WRITE0x02, MAP_PRIVATE0x0002|MAP_ANON0x1000, -1, 0);
290 if (_pw_storage == MAP_FAILED((void *)-1))
291 return NULL((void *)0);
292 if (name != NULL((void *)0))
293 strlcpy(_pw_storage->name, name, sizeof(_pw_storage->name));
294 _pw_storage->uid = uid;
295 }
296
297 *bufp = _pw_storage->pwbuf;
298 *buflenp = sizeof(_pw_storage->pwbuf);
299 return &_pw_storage->pw;
300}
301
302struct passwd *
303getpwent(void)
304{
305#ifdef YP1
306 static char *name = NULL((void *)0);
307 char *map;
308#endif
309 char bf[1 + sizeof(_pw_keynum)];
310 struct passwd *pw, *ret = NULL((void *)0);
311 char *pwbuf;
312 size_t buflen;
313 DBT key;
314
315 _THREAD_PRIVATE_MUTEX_LOCK(pw)do { if (_thread_cb.tc_tag_lock != ((void *)0)) _thread_cb.tc_tag_lock
(&(_thread_tagname_pw)); } while (0)
;
316 if (!_pw_db && !__initdb(0))
317 goto done;
318
319 /* Allocate space for struct and strings, unmapping the old. */
320 if ((pw = __get_pw_buf(&pwbuf, &buflen, -1, NULL((void *)0))) == NULL((void *)0))
321 goto done;
322
323#ifdef YP1
324 map = PASSWD_BYNAME(__has_ypmaster() ? "master.passwd.byname" : "passwd.byname");
325
326 if (__getpwent_has_yppw == -1)
327 __getpwent_has_yppw = __has_yppw();
328
329again:
330 if (__getpwent_has_yppw && (__ypmode != YPMODE_NONE)) {
331 const char *user, *host, *dom;
332 int keylen, datalen, r, s;
333 char *key, *data = NULL((void *)0);
334
335 if (!__ypdomain)
336 yp_get_default_domain(&__ypdomain);
337 switch (__ypmode) {
338 case YPMODE_FULL:
339 if (__ypcurrent) {
340 r = yp_next(__ypdomain, map,
341 __ypcurrent, __ypcurrentlen,
342 &key, &keylen, &data, &datalen);
343 free(__ypcurrent);
344 __ypcurrent = NULL((void *)0);
345 if (r != 0) {
346 __ypmode = YPMODE_NONE;
347 free(data);
348 goto again;
349 }
350 __ypcurrent = key;
351 __ypcurrentlen = keylen;
352 } else {
353 r = yp_first(__ypdomain, map,
354 &__ypcurrent, &__ypcurrentlen,
355 &data, &datalen);
356 if (r != 0 ||
357 __ypcurrentlen > buflen) {
358 __ypmode = YPMODE_NONE;
359 free(data);
360 goto again;
361 }
362 }
363 bcopy(data, pwbuf, datalen);
364 free(data);
365 break;
366 case YPMODE_NETGRP:
367 s = getnetgrent(&host, &user, &dom);
368 if (s == 0) { /* end of group */
369 endnetgrent();
370 __ypmode = YPMODE_NONE;
371 goto again;
372 }
373 if (user && *user) {
374 r = yp_match(__ypdomain, map,
375 user, strlen(user), &data, &datalen);
376 } else
377 goto again;
378 if (r != 0 ||
379 __ypcurrentlen > buflen) {
380 /*
381 * if the netgroup is invalid, keep looking
382 * as there may be valid users later on.
383 */
384 free(data);
385 goto again;
386 }
387 bcopy(data, pwbuf, datalen);
388 free(data);
389 break;
390 case YPMODE_USER:
391 if (name) {
392 r = yp_match(__ypdomain, map,
393 name, strlen(name), &data, &datalen);
394 __ypmode = YPMODE_NONE;
395 free(name);
396 name = NULL((void *)0);
397 if (r != 0 ||
398 __ypcurrentlen > buflen) {
399 free(data);
400 goto again;
401 }
402 bcopy(data, pwbuf, datalen);
403 free(data);
404 } else { /* XXX */
405 __ypmode = YPMODE_NONE;
406 goto again;
407 }
408 break;
409 case YPMODE_NONE:
410 /* NOTREACHED */
411 break;
412 }
413
414 pwbuf[datalen] = '\0';
415 if (__ypparse(pw, pwbuf, __yp_pw_flags))
416 goto again;
417 ret = pw;
418 goto done;
419 }
420#endif
421
422 ++_pw_keynum;
423 bf[0] = _PW_KEYBYNUM'2';
424 bcopy((char *)&_pw_keynum, &bf[1], sizeof(_pw_keynum));
425 key.data = (u_char *)bf;
426 key.size = 1 + sizeof(_pw_keynum);
427 if (__hashpw(&key, pwbuf, buflen, pw, &_pw_flags)) {
428#ifdef YP1
429 static struct pw_storage __yppbuf;
430 const char *user, *host, *dom;
431
432 /* if we don't have YP at all, don't bother. */
433 if (__getpwent_has_yppw) {
434 if (pw->pw_name[0] == '+') {
435 /* set the mode */
436 switch (pw->pw_name[1]) {
437 case '\0':
438 __ypmode = YPMODE_FULL;
439 break;
440 case '@':
441 __ypmode = YPMODE_NETGRP;
442 setnetgrent(pw->pw_name + 2);
443 break;
444 default:
445 __ypmode = YPMODE_USER;
446 name = strdup(pw->pw_name + 1);
447 break;
448 }
449
450 __ypproto_set(pw, &__yppbuf, _pw_flags,
451 &__yp_pw_flags);
452 goto again;
453 } else if (pw->pw_name[0] == '-') {
454 /* an attempted exclusion */
455 switch (pw->pw_name[1]) {
456 case '\0':
457 break;
458 case '@':
459 setnetgrent(pw->pw_name + 2);
460 while (getnetgrent(&host, &user, &dom)) {
461 if (user && *user)
462 __ypexclude_add(&__ypexhead,
463 user);
464 }
465 endnetgrent();
466 break;
467 default:
468 __ypexclude_add(&__ypexhead,
469 pw->pw_name + 1);
470 break;
471 }
472 goto again;
473 }
474 }
475#endif
476 ret = pw;
477 goto done;
478 }
479
480done:
481 _THREAD_PRIVATE_MUTEX_UNLOCK(pw)do { if (_thread_cb.tc_tag_unlock != ((void *)0)) _thread_cb.
tc_tag_unlock(&(_thread_tagname_pw)); } while (0)
;
482 return (ret);
483}
484
485#ifdef YP1
486/*
487 * See if the YP token is in the database. Only works if pwd_mkdb knows
488 * about the token.
489 */
490static int
491__has_yppw(void)
492{
493 DBT key, data, pkey, pdata;
494 char bf[2];
495
496 key.data = (u_char *)_PW_YPTOKEN"__YP!";
497 key.size = strlen(_PW_YPTOKEN"__YP!");
498
499 /* Pre-token database support. */
500 bf[0] = _PW_KEYBYNAME'1';
501 bf[1] = '+';
502 pkey.data = (u_char *)bf;
503 pkey.size = sizeof(bf);
504
505 if ((_pw_db->get)(_pw_db, &key, &data, 0) &&
506 (_pw_db->get)(_pw_db, &pkey, &pdata, 0))
507 return (0); /* No YP. */
508 return (1);
509}
510
511/*
512 * See if there's a master.passwd map.
513 */
514static int
515__has_ypmaster(void)
516{
517 int keylen, resultlen;
518 char *key, *result;
519 static int checked = -1;
520 static uid_t saved_uid, saved_euid;
521 uid_t uid = getuid(), euid = geteuid();
522
523 /*
524 * Do not recheck IFF the saved UID and the saved
525 * EUID are the same. In all other cases, recheck.
526 */
527 if (checked != -1 && saved_uid == uid && saved_euid == euid)
528 return (checked);
529
530 if (euid != 0) {
531 saved_uid = uid;
532 saved_euid = euid;
533 checked = 0;
534 return (checked);
535 }
536
537 if (!__ypdomain)
538 yp_get_default_domain(&__ypdomain);
539
540 if (yp_first(__ypdomain, "master.passwd.byname",
541 &key, &keylen, &result, &resultlen)) {
542 saved_uid = uid;
543 saved_euid = euid;
544 checked = 0;
545 return (checked);
546 }
547 free(result);
548 free(key);
549
550 saved_uid = uid;
551 saved_euid = euid;
552 checked = 1;
553 return (checked);
554}
555
556static struct passwd *
557__yppwlookup(int lookup, char *name, uid_t uid, struct passwd *pw,
558 char *buf, size_t buflen, int *flagsp)
559{
560 char bf[1 + _PW_NAME_LEN31], *ypcurrent = NULL((void *)0), *map = NULL((void *)0);
561 int yp_pw_flags = 0, ypcurrentlen, r, s = -1, pw_keynum;
562 static struct pw_storage __yppbuf;
563 struct _ypexclude *ypexhead = NULL((void *)0);
564 const char *host, *user, *dom;
565 DBT key;
566
567 for (pw_keynum = 1; pw_keynum; pw_keynum++) {
568 bf[0] = _PW_KEYBYNUM'2';
569 bcopy((char *)&pw_keynum, &bf[1], sizeof(pw_keynum));
570 key.data = (u_char *)bf;
571 key.size = 1 + sizeof(pw_keynum);
572 if (__hashpw(&key, buf, buflen, pw, flagsp) == 0)
573 break;
574 switch (pw->pw_name[0]) {
575 case '+':
576 if (!__ypdomain)
577 yp_get_default_domain(&__ypdomain);
578 __ypproto_set(pw, &__yppbuf, *flagsp, &yp_pw_flags);
579 if (!map) {
580 if (lookup == LOOKUP_BYNAME0) {
581 if ((name = strdup(name)) == NULL((void *)0)) {
582 pw = NULL((void *)0);
583 goto done;
584 }
585 map = PASSWD_BYNAME(__has_ypmaster() ? "master.passwd.byname" : "passwd.byname");
586 } else {
587 if (asprintf(&name, "%u", uid) == -1) {
588 pw = NULL((void *)0);
589 goto done;
590 }
591 map = PASSWD_BYUID(__has_ypmaster() ? "master.passwd.byuid" : "passwd.byuid");
592 }
593 }
594
595 switch (pw->pw_name[1]) {
596 case '\0':
597 free(ypcurrent);
598 ypcurrent = NULL((void *)0);
599 r = yp_match(__ypdomain, map,
600 name, strlen(name),
601 &ypcurrent, &ypcurrentlen);
602 if (r != 0 || ypcurrentlen > buflen) {
603 free(ypcurrent);
604 ypcurrent = NULL((void *)0);
605 continue;
606 }
607 break;
608 case '@':
609pwnam_netgrp:
610 free(ypcurrent);
611 ypcurrent = NULL((void *)0);
612 if (s == -1) /* first time */
613 setnetgrent(pw->pw_name + 2);
614 s = getnetgrent(&host, &user, &dom);
615 if (s == 0) { /* end of group */
616 endnetgrent();
617 s = -1;
618 continue;
619 } else {
620 if (user && *user) {
621 r = yp_match(__ypdomain, map,
622 user, strlen(user),
623 &ypcurrent, &ypcurrentlen);
624 } else
625 goto pwnam_netgrp;
626 if (r != 0 || ypcurrentlen > buflen) {
627 free(ypcurrent);
628 ypcurrent = NULL((void *)0);
629 /*
630 * just because this
631 * user is bad, doesn't
632 * mean they all are.
633 */
634 goto pwnam_netgrp;
635 }
636 }
637 break;
638 default:
639 free(ypcurrent);
640 ypcurrent = NULL((void *)0);
641 user = pw->pw_name + 1;
642 r = yp_match(__ypdomain, map,
643 user, strlen(user),
644 &ypcurrent, &ypcurrentlen);
645 if (r != 0 || ypcurrentlen > buflen) {
646 free(ypcurrent);
647 ypcurrent = NULL((void *)0);
648 continue;
649 }
650 break;
651 }
652 bcopy(ypcurrent, buf, ypcurrentlen);
653 buf[ypcurrentlen] = '\0';
654 if (__ypparse(pw, buf, yp_pw_flags) ||
655 __ypexclude_is(&ypexhead, pw->pw_name)) {
656 if (s == 1) /* inside netgrp */
657 goto pwnam_netgrp;
658 continue;
659 }
660 break;
661 case '-':
662 /* attempted exclusion */
663 switch (pw->pw_name[1]) {
664 case '\0':
665 break;
666 case '@':
667 setnetgrent(pw->pw_name + 2);
668 while (getnetgrent(&host, &user, &dom)) {
669 if (user && *user)
670 __ypexclude_add(&ypexhead, user);
671 }
672 endnetgrent();
673 break;
674 default:
675 __ypexclude_add(&ypexhead, pw->pw_name + 1);
676 break;
677 }
678 break;
679 }
680 if ((lookup == LOOKUP_BYUID1 && pw->pw_uid == uid) ||
681 (lookup == LOOKUP_BYNAME0 && strcmp(pw->pw_name, name) == 0))
682 goto done;
683 if (s == 1) /* inside netgrp */
684 goto pwnam_netgrp;
685 continue;
686 }
687 pw = NULL((void *)0);
688done:
689 __ypexclude_free(&ypexhead);
690 __ypproto = NULL((void *)0);
691 free(ypcurrent);
692 ypcurrent = NULL((void *)0);
693 if (map)
694 free(name);
695 return (pw);
696}
697#endif /* YP */
698
699static struct passwd *
700_pwhashbyname(const char *name, char *buf, size_t buflen, struct passwd *pw,
701 int *flagsp)
702{
703 char bf[1 + _PW_NAME_LEN31];
704 size_t len;
705 DBT key;
706 int r;
707
708 len = strlen(name);
709 if (len > _PW_NAME_LEN31)
710 return (NULL((void *)0));
711 bf[0] = _PW_KEYBYNAME'1';
712 bcopy(name, &bf[1], MINIMUM(len, _PW_NAME_LEN)(((len) < (31)) ? (len) : (31)));
713 key.data = (u_char *)bf;
714 key.size = 1 + MINIMUM(len, _PW_NAME_LEN)(((len) < (31)) ? (len) : (31));
715 r = __hashpw(&key, buf, buflen, pw, flagsp);
716 if (r)
717 return (pw);
718 return (NULL((void *)0));
719}
720
721static struct passwd *
722_pwhashbyuid(uid_t uid, char *buf, size_t buflen, struct passwd *pw,
723 int *flagsp)
724{
725 char bf[1 + sizeof(int)];
726 DBT key;
727 int r;
728
729 bf[0] = _PW_KEYBYUID'3';
730 bcopy(&uid, &bf[1], sizeof(uid));
731 key.data = (u_char *)bf;
732 key.size = 1 + sizeof(uid);
733 r = __hashpw(&key, buf, buflen, pw, flagsp);
734 if (r)
735 return (pw);
736 return (NULL((void *)0));
737}
738
739static int
740getpwnam_internal(const char *name, struct passwd *pw, char *buf, size_t buflen,
741 struct passwd **pwretp, bool_Bool shadow, bool_Bool reentrant)
742{
743 struct passwd *pwret = NULL((void *)0);
744 int flags = 0, *flagsp = &flags;
745 int my_errno = 0;
746 int saved_errno, tmp_errno;
747
748 _THREAD_PRIVATE_MUTEX_LOCK(pw)do { if (_thread_cb.tc_tag_lock != ((void *)0)) _thread_cb.tc_tag_lock
(&(_thread_tagname_pw)); } while (0)
;
749 saved_errno = errno(*__errno());
750 errno(*__errno()) = 0;
751 if (!_pw_db && !__initdb(shadow))
752 goto fail;
753
754 if (!reentrant) {
755 /* Allocate space for struct and strings, unmapping the old. */
756 if ((pw = __get_pw_buf(&buf, &buflen, -1, name)) == NULL((void *)0))
757 goto fail;
758 flagsp = &_pw_flags;
759 }
760
761#ifdef YP1
762 if (__has_yppw())
763 pwret = __yppwlookup(LOOKUP_BYNAME0, (char *)name, 0, pw,
764 buf, buflen, flagsp);
765#endif /* YP */
766 if (!pwret)
767 pwret = _pwhashbyname(name, buf, buflen, pw, flagsp);
768
769 if (!_pw_stayopen) {
770 tmp_errno = errno(*__errno());
771 (void)(_pw_db->close)(_pw_db);
772 _pw_db = NULL((void *)0);
773 errno(*__errno()) = tmp_errno;
774 }
775fail:
776 if (pwretp)
777 *pwretp = pwret;
778 if (pwret == NULL((void *)0))
779 my_errno = errno(*__errno());
780 errno(*__errno()) = saved_errno;
781 _THREAD_PRIVATE_MUTEX_UNLOCK(pw)do { if (_thread_cb.tc_tag_unlock != ((void *)0)) _thread_cb.
tc_tag_unlock(&(_thread_tagname_pw)); } while (0)
;
782 return (my_errno);
783}
784
785int
786getpwnam_r(const char *name, struct passwd *pw, char *buf, size_t buflen,
787 struct passwd **pwretp)
788{
789 return getpwnam_internal(name, pw, buf, buflen, pwretp, false0, true1);
790}
791DEF_WEAK(getpwnam_r)__asm__(".weak " "getpwnam_r" " ; " "getpwnam_r" " = " "_libc_getpwnam_r"
)
;
792
793struct passwd *
794getpwnam(const char *name)
795{
796 struct passwd *pw = NULL((void *)0);
797 int my_errno;
798
799 my_errno = getpwnam_internal(name, NULL((void *)0), NULL((void *)0), 0, &pw, false0, false0);
800 if (my_errno) {
801 pw = NULL((void *)0);
802 errno(*__errno()) = my_errno;
803 }
804 return (pw);
805}
806
807struct passwd *
808getpwnam_shadow(const char *name)
809{
810 struct passwd *pw = NULL((void *)0);
811 int my_errno;
812
813 my_errno = getpwnam_internal(name, NULL((void *)0), NULL((void *)0), 0, &pw, true1, false0);
814 if (my_errno) {
815 pw = NULL((void *)0);
816 errno(*__errno()) = my_errno;
817 }
818 return (pw);
819}
820DEF_WEAK(getpwnam_shadow)__asm__(".weak " "getpwnam_shadow" " ; " "getpwnam_shadow" " = "
"_libc_getpwnam_shadow")
;
821
822static int
823getpwuid_internal(uid_t uid, struct passwd *pw, char *buf, size_t buflen,
824 struct passwd **pwretp, bool_Bool shadow, bool_Bool reentrant)
825{
826 struct passwd *pwret = NULL((void *)0);
827 int flags = 0, *flagsp = &flags;
828 int my_errno = 0;
829 int saved_errno, tmp_errno;
830
831 _THREAD_PRIVATE_MUTEX_LOCK(pw)do { if (_thread_cb.tc_tag_lock != ((void *)0)) _thread_cb.tc_tag_lock
(&(_thread_tagname_pw)); } while (0)
;
832 saved_errno = errno(*__errno());
833 errno(*__errno()) = 0;
834 if (!_pw_db && !__initdb(shadow))
835 goto fail;
836
837 if (!reentrant) {
838 /* Allocate space for struct and strings, unmapping the old. */
839 if ((pw = __get_pw_buf(&buf, &buflen, uid, NULL((void *)0))) == NULL((void *)0))
840 goto fail;
841 flagsp = &_pw_flags;
842 }
843
844#ifdef YP1
845 if (__has_yppw())
846 pwret = __yppwlookup(LOOKUP_BYUID1, NULL((void *)0), uid, pw,
847 buf, buflen, flagsp);
848#endif /* YP */
849 if (!pwret)
850 pwret = _pwhashbyuid(uid, buf, buflen, pw, flagsp);
851
852 if (!_pw_stayopen) {
853 tmp_errno = errno(*__errno());
854 (void)(_pw_db->close)(_pw_db);
855 _pw_db = NULL((void *)0);
856 errno(*__errno()) = tmp_errno;
857 }
858fail:
859 if (pwretp)
860 *pwretp = pwret;
861 if (pwret == NULL((void *)0))
862 my_errno = errno(*__errno());
863 errno(*__errno()) = saved_errno;
864 _THREAD_PRIVATE_MUTEX_UNLOCK(pw)do { if (_thread_cb.tc_tag_unlock != ((void *)0)) _thread_cb.
tc_tag_unlock(&(_thread_tagname_pw)); } while (0)
;
865 return (my_errno);
866}
867
868
869int
870getpwuid_r(uid_t uid, struct passwd *pw, char *buf, size_t buflen,
871 struct passwd **pwretp)
872{
873 return getpwuid_internal(uid, pw, buf, buflen, pwretp, false0, true1);
874}
875DEF_WEAK(getpwuid_r)__asm__(".weak " "getpwuid_r" " ; " "getpwuid_r" " = " "_libc_getpwuid_r"
)
;
876
877struct passwd *
878getpwuid(uid_t uid)
879{
880 struct passwd *pw = NULL((void *)0);
881 int my_errno;
882
883 my_errno = getpwuid_internal(uid, NULL((void *)0), NULL((void *)0), 0, &pw, false0, false0);
884 if (my_errno) {
885 pw = NULL((void *)0);
886 errno(*__errno()) = my_errno;
887 }
888 return (pw);
889}
890
891struct passwd *
892getpwuid_shadow(uid_t uid)
893{
894 struct passwd *pw = NULL((void *)0);
895 int my_errno;
896
897 my_errno = getpwuid_internal(uid, NULL((void *)0), NULL((void *)0), 0, &pw, true1, false0);
898 if (my_errno) {
899 pw = NULL((void *)0);
900 errno(*__errno()) = my_errno;
901 }
902 return (pw);
903}
904DEF_WEAK(getpwuid_shadow)__asm__(".weak " "getpwuid_shadow" " ; " "getpwuid_shadow" " = "
"_libc_getpwuid_shadow")
;
905
906int
907setpassent(int stayopen)
908{
909 _THREAD_PRIVATE_MUTEX_LOCK(pw)do { if (_thread_cb.tc_tag_lock != ((void *)0)) _thread_cb.tc_tag_lock
(&(_thread_tagname_pw)); } while (0)
;
910 _pw_keynum = 0;
911 _pw_stayopen = stayopen;
912#ifdef YP1
913 __ypmode = YPMODE_NONE;
914 free(__ypcurrent);
915 __ypcurrent = NULL((void *)0);
916 __ypexclude_free(&__ypexhead);
917 __ypproto = NULL((void *)0);
918#endif
919 _THREAD_PRIVATE_MUTEX_UNLOCK(pw)do { if (_thread_cb.tc_tag_unlock != ((void *)0)) _thread_cb.
tc_tag_unlock(&(_thread_tagname_pw)); } while (0)
;
920 return (1);
921}
922DEF_WEAK(setpassent)__asm__(".weak " "setpassent" " ; " "setpassent" " = " "_libc_setpassent"
)
;
923
924void
925setpwent(void)
926{
927 (void) setpassent(0);
928}
929
930void
931endpwent(void)
932{
933 int saved_errno;
934
935 _THREAD_PRIVATE_MUTEX_LOCK(pw)do { if (_thread_cb.tc_tag_lock != ((void *)0)) _thread_cb.tc_tag_lock
(&(_thread_tagname_pw)); } while (0)
;
936 saved_errno = errno(*__errno());
937 _pw_keynum = 0;
938 if (_pw_db) {
939 (void)(_pw_db->close)(_pw_db);
940 _pw_db = NULL((void *)0);
941 }
942#ifdef YP1
943 __ypmode = YPMODE_NONE;
944 free(__ypcurrent);
945 __ypcurrent = NULL((void *)0);
946 __ypexclude_free(&__ypexhead);
947 __ypproto = NULL((void *)0);
948#endif
949 errno(*__errno()) = saved_errno;
950 _THREAD_PRIVATE_MUTEX_UNLOCK(pw)do { if (_thread_cb.tc_tag_unlock != ((void *)0)) _thread_cb.
tc_tag_unlock(&(_thread_tagname_pw)); } while (0)
;
951}
952
953static int
954__initdb(int shadow)
955{
956 static int warned;
957 int saved_errno = errno(*__errno());
958
959#ifdef YP1
960 __ypmode = YPMODE_NONE;
961 __getpwent_has_yppw = -1;
962#endif
963 if (shadow)
964 _pw_db = dbopen(_PATH_SMP_DB"/etc/spwd.db", O_RDONLY0x0000, 0, DB_HASH, NULL((void *)0));
965 if (!_pw_db)
966 _pw_db = dbopen(_PATH_MP_DB"/etc/pwd.db", O_RDONLY0x0000, 0, DB_HASH, NULL((void *)0));
967 if (_pw_db) {
968 errno(*__errno()) = saved_errno;
969 return (1);
970 }
971 if (!warned) {
972 saved_errno = errno(*__errno());
973 errno(*__errno()) = saved_errno;
974 warned = 1;
975 }
976 return (0);
977}
978
979static int
980__hashpw(DBT *key, char *buf, size_t buflen, struct passwd *pw,
981 int *flagsp)
982{
983 char *p, *t;
984 DBT data;
985
986 if ((_pw_db->get)(_pw_db, key, &data, 0))
987 return (0);
988 p = (char *)data.data;
989 if (data.size > buflen) {
990 errno(*__errno()) = ERANGE34;
991 return (0);
992 }
993
994 t = buf;
995#define EXPAND(e)e = t; while ((*t++ = *p++)); e = t; while ((*t++ = *p++));
996 EXPAND(pw->pw_name)pw->pw_name = t; while ((*t++ = *p++));;
997 EXPAND(pw->pw_passwd)pw->pw_passwd = t; while ((*t++ = *p++));;
998 bcopy(p, (char *)&pw->pw_uid, sizeof(int));
999 p += sizeof(int);
1000 bcopy(p, (char *)&pw->pw_gid, sizeof(int));
1001 p += sizeof(int);
1002 bcopy(p, (char *)&pw->pw_change, sizeof(time_t));
1003 p += sizeof(time_t);
1004 EXPAND(pw->pw_class)pw->pw_class = t; while ((*t++ = *p++));;
1005 EXPAND(pw->pw_gecos)pw->pw_gecos = t; while ((*t++ = *p++));;
1006 EXPAND(pw->pw_dir)pw->pw_dir = t; while ((*t++ = *p++));;
1007 EXPAND(pw->pw_shell)pw->pw_shell = t; while ((*t++ = *p++));;
1008 bcopy(p, (char *)&pw->pw_expire, sizeof(time_t));
1009 p += sizeof(time_t);
1010
1011 /* See if there's any data left. If so, read in flags. */
1012 if (data.size > (p - (char *)data.data)) {
1013 bcopy(p, (char *)flagsp, sizeof(int));
1014 p += sizeof(int);
Value stored to 'p' is never read
1015 } else
1016 *flagsp = _PASSWORD_NOUID0x01|_PASSWORD_NOGID0x02; /* default */
1017 return (1);
1018}