static struct passwd * __yppwlookup(int lookup, char *name, uid_t uid, struct passwd *pw, char *buf, size_t buflen, int *flagsp) { char bf[1 + _PW_NAME_LEN], *ypcurrent = NULL, *map = NULL; int yp_pw_flags = 0, ypcurrentlen, r, s = -1, pw_keynum; static long long yppbuf[_PW_BUF_LEN / sizeof(long long)]; struct _ypexclude *ypexhead = NULL; const char *host, *user, *dom; DBT key; for (pw_keynum = 1; pw_keynum; pw_keynum++) { bf[0] = _PW_KEYBYNUM; bcopy((char *)&pw_keynum, &bf[1], sizeof(pw_keynum)); key.data = (u_char *)bf; key.size = 1 + sizeof(pw_keynum); if (__hashpw(&key, buf, buflen, pw, flagsp) == 0) break; switch (pw->pw_name[0]) { case '+': if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) continue; } __ypproto_set(pw, yppbuf, *flagsp, &yp_pw_flags); if (!map) { if (lookup == LOOKUP_BYNAME) { map = PASSWD_BYNAME; name = strdup(name); } else { map = PASSWD_BYUID; asprintf(&name, "%u", uid); } } switch (pw->pw_name[1]) { case '\0': if (ypcurrent) { free(ypcurrent); ypcurrent = NULL; } r = yp_match(__ypdomain, map, name, strlen(name), &ypcurrent, &ypcurrentlen); if (r != 0 || ypcurrentlen > buflen) { if (ypcurrent) free(ypcurrent); ypcurrent = NULL; continue; } break; case '@': pwnam_netgrp: if (ypcurrent) { free(ypcurrent); ypcurrent = NULL; } if (s == -1) /* first time */ setnetgrent(pw->pw_name + 2); s = getnetgrent(&host, &user, &dom); if (s == 0) { /* end of group */ endnetgrent(); s = -1; continue; } else { if (user && *user) { r = yp_match(__ypdomain, map, user, strlen(user), &ypcurrent, &ypcurrentlen); } else goto pwnam_netgrp; if (r != 0 || ypcurrentlen > buflen) { if (ypcurrent) free(ypcurrent); ypcurrent = NULL; /* * just because this * user is bad, doesn't * mean they all are. */ goto pwnam_netgrp; } } break; default: if (ypcurrent) { free(ypcurrent); ypcurrent = NULL; } user = pw->pw_name + 1; r = yp_match(__ypdomain, map, user, strlen(user), &ypcurrent, &ypcurrentlen); if (r != 0 || ypcurrentlen > buflen) { if (ypcurrent) free(ypcurrent); ypcurrent = NULL; continue; } break; } bcopy(ypcurrent, buf, ypcurrentlen); buf[ypcurrentlen] = '\0'; if (__ypparse(pw, buf, yp_pw_flags) || __ypexclude_is(&ypexhead, pw->pw_name)) { if (s == 1) /* inside netgrp */ goto pwnam_netgrp; continue; } break; case '-': /* attempted exclusion */ switch (pw->pw_name[1]) { case '\0': break; case '@': setnetgrent(pw->pw_name + 2); while (getnetgrent(&host, &user, &dom)) { if (user && *user) __ypexclude_add(&ypexhead, user); } endnetgrent(); break; default: __ypexclude_add(&ypexhead, pw->pw_name + 1); break; } break; } if ((lookup == LOOKUP_BYUID && pw->pw_uid == uid) || (lookup == LOOKUP_BYNAME && strcmp(pw->pw_name, name) == 0)) goto done; if (s == 1) /* inside netgrp */ goto pwnam_netgrp; continue; } pw = NULL; done: __ypexclude_free(&ypexhead); __ypproto = NULL; if (ypcurrent) free(ypcurrent); ypcurrent = NULL; if (map) free(name); return (pw); }
static int grscan(int search, gid_t gid, const char *name, struct group *p_gr, struct group_storage *gs, int *foundyp) { char *cp, **m; char *bp, *endp; u_long ul; #ifdef YP char *key, *data; int keylen, datalen; int r; #endif char **members; char *line; int saved_errno; if (gs == NULL) return 0; members = gs->members; line = gs->line; saved_errno = errno; for (;;) { #ifdef YP if (__ypmode) { if (__ypcurrent) { r = yp_next(__ypdomain, "group.byname", __ypcurrent, __ypcurrentlen, &key, &keylen, &data, &datalen); free(__ypcurrent); __ypcurrent = key; __ypcurrentlen = keylen; } else { r = yp_first(__ypdomain, "group.byname", &__ypcurrent, &__ypcurrentlen, &data, &datalen); } if (r) { __ypmode = 0; __ypcurrent = NULL; if (r == YPERR_NOMORE) continue; else return 0; } bcopy(data, line, datalen); free(data); line[datalen] = '\0'; bp = line; goto parse; } #endif if (!fgets(line, sizeof(gs->line), _gr_fp)) { if (feof(_gr_fp) && !ferror(_gr_fp)) errno = saved_errno; return 0; } bp = line; /* skip lines that are too big */ if (!strchr(line, '\n')) { int ch; while ((ch = getc_unlocked(_gr_fp)) != '\n' && ch != EOF) ; continue; } #ifdef YP if (line[0] == '+' || line[0] == '-') { if (__ypdomain == NULL && yp_get_default_domain(&__ypdomain)) goto parse; switch (yp_bind(__ypdomain)) { case 0: break; case YPERR_BADARGS: case YPERR_YPBIND: goto parse; default: return 0; } } if (line[0] == '+') { switch (line[1]) { case ':': case '\0': case '\n': if (foundyp) { *foundyp = 1; errno = saved_errno; return 0; } if (!search) { __ypmode = 1; continue; } if (name) { r = yp_match(__ypdomain, "group.byname", name, strlen(name), &data, &datalen); } else { char buf[20]; snprintf(buf, sizeof buf, "%u", gid); r = yp_match(__ypdomain, "group.bygid", buf, strlen(buf), &data, &datalen); } switch (r) { case 0: break; case YPERR_KEY: continue; default: return 0; } bcopy(data, line, datalen); free(data); line[datalen] = '\0'; bp = line; p_gr->gr_name = strsep(&bp, ":\n"); if (__ypexclude_is(&__ypexhead, p_gr->gr_name)) continue; p_gr->gr_passwd = strsep(&bp, ":\n"); if (!(cp = strsep(&bp, ":\n"))) continue; if (name) { ul = strtoul(cp, &endp, 10); if (*endp != '\0' || endp == cp || ul >= GID_MAX) continue; p_gr->gr_gid = ul; } else p_gr->gr_gid = gid; goto found_it; default: bp = strsep(&bp, ":\n") + 1; if ((search && name && strcmp(bp, name)) || __ypexclude_is(&__ypexhead, bp)) continue; r = yp_match(__ypdomain, "group.byname", bp, strlen(bp), &data, &datalen); switch (r) { case 0: break; case YPERR_KEY: continue; default: return 0; } bcopy(data, line, datalen); free(data); line[datalen] = '\0'; bp = line; } } else if (line[0] == '-') { if (__ypexclude_add(&__ypexhead, strsep(&line, ":\n") + 1)) return 0; if (foundyp) { *foundyp = -1; errno = saved_errno; return 0; } continue; } parse: #endif p_gr->gr_name = strsep(&bp, ":\n"); if (search && name && strcmp(p_gr->gr_name, name)) continue; #ifdef YP if (__ypmode && __ypexclude_is(&__ypexhead, p_gr->gr_name)) continue; #endif p_gr->gr_passwd = strsep(&bp, ":\n"); if (!(cp = strsep(&bp, ":\n"))) continue; ul = strtoul(cp, &endp, 10); if (endp == cp || *endp != '\0' || ul >= GID_MAX) continue; p_gr->gr_gid = ul; if (search && name == NULL && p_gr->gr_gid != gid) continue; #ifdef YP found_it: #endif cp = NULL; if (bp == NULL) continue; for (m = p_gr->gr_mem = members;; bp++) { if (m == &members[MAXGRP - 1]) break; if (*bp == ',') { if (cp) { *bp = '\0'; *m++ = cp; cp = NULL; } } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { if (cp) { *bp = '\0'; *m++ = cp; } break; } else if (cp == NULL) cp = bp; } *m = NULL; errno = saved_errno; return 1; } /* NOTREACHED */ }
struct passwd * getpwent(void) { #ifdef YP static char *name = NULL; char *map; #endif char bf[1 + sizeof(_pw_keynum)]; struct passwd *pw = NULL; DBT key; _THREAD_PRIVATE_MUTEX_LOCK(pw); if (!_pw_db && !__initdb()) goto done; #ifdef YP map = PASSWD_BYNAME; if (__getpwent_has_yppw == -1) __getpwent_has_yppw = __has_yppw(); again: if (__getpwent_has_yppw && (__ypmode != YPMODE_NONE)) { const char *user, *host, *dom; int keylen, datalen, r, s; char *key, *data = NULL; if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) { __ypmode = YPMODE_NONE; goto again; } } switch (__ypmode) { case YPMODE_FULL: if (__ypcurrent) { r = yp_next(__ypdomain, map, __ypcurrent, __ypcurrentlen, &key, &keylen, &data, &datalen); free(__ypcurrent); __ypcurrent = NULL; if (r != 0) { __ypmode = YPMODE_NONE; if (data) free(data); goto again; } __ypcurrent = key; __ypcurrentlen = keylen; } else { r = yp_first(__ypdomain, map, &__ypcurrent, &__ypcurrentlen, &data, &datalen); if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { __ypmode = YPMODE_NONE; if (data) free(data); goto again; } } bcopy(data, __ypline, datalen); free(data); break; case YPMODE_NETGRP: s = getnetgrent(&host, &user, &dom); if (s == 0) { /* end of group */ endnetgrent(); __ypmode = YPMODE_NONE; goto again; } if (user && *user) { r = yp_match(__ypdomain, map, user, strlen(user), &data, &datalen); } else goto again; if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { /* * if the netgroup is invalid, keep looking * as there may be valid users later on. */ if (data) free(data); goto again; } bcopy(data, __ypline, datalen); free(data); break; case YPMODE_USER: if (name) { r = yp_match(__ypdomain, map, name, strlen(name), &data, &datalen); __ypmode = YPMODE_NONE; free(name); name = NULL; if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { if (data) free(data); goto again; } bcopy(data, __ypline, datalen); free(data); } else { /* XXX */ __ypmode = YPMODE_NONE; goto again; } break; case YPMODE_NONE: /* NOTREACHED */ break; } __ypline[datalen] = '\0'; if (__ypparse(&_pw_passwd, __ypline, __yp_pw_flags)) goto again; pw = &_pw_passwd; goto done; } #endif ++_pw_keynum; bf[0] = _PW_KEYBYNUM; bcopy((char *)&_pw_keynum, &bf[1], sizeof(_pw_keynum)); key.data = (u_char *)bf; key.size = 1 + sizeof(_pw_keynum); if (__hashpw(&key, _pw_string, sizeof _pw_string, &_pw_passwd, &_pw_flags)) { #ifdef YP static long long __yppbuf[_PW_BUF_LEN / sizeof(long long)]; const char *user, *host, *dom; /* if we don't have YP at all, don't bother. */ if (__getpwent_has_yppw) { if (_pw_passwd.pw_name[0] == '+') { /* set the mode */ switch (_pw_passwd.pw_name[1]) { case '\0': __ypmode = YPMODE_FULL; break; case '@': __ypmode = YPMODE_NETGRP; setnetgrent(_pw_passwd.pw_name + 2); break; default: __ypmode = YPMODE_USER; name = strdup(_pw_passwd.pw_name + 1); break; } __ypproto_set(&_pw_passwd, __yppbuf, _pw_flags, &__yp_pw_flags); goto again; } else if (_pw_passwd.pw_name[0] == '-') { /* an attempted exclusion */ switch (_pw_passwd.pw_name[1]) { case '\0': break; case '@': setnetgrent(_pw_passwd.pw_name + 2); while (getnetgrent(&host, &user, &dom)) { if (user && *user) __ypexclude_add(&__ypexhead, user); } endnetgrent(); break; default: __ypexclude_add(&__ypexhead, _pw_passwd.pw_name + 1); break; } goto again; } } #endif pw = &_pw_passwd; goto done; } done: _THREAD_PRIVATE_MUTEX_UNLOCK(pw); return (pw); }