getpwent.c revision 113670
1113596Snectar/*- 2113596Snectar * Copyright (c) 2003 Networks Associates Technology, Inc. 3113596Snectar * All rights reserved. 41573Srgrimes * 5113596Snectar * This software was developed for the FreeBSD Project by 6113596Snectar * Jacques A. Vidrine, Safeport Network Services, and Network 7113596Snectar * Associates Laboratories, the Security Research Division of Network 8113596Snectar * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9113596Snectar * ("CBOSS"), as part of the DARPA CHATS research program. 10113596Snectar * 111573Srgrimes * Redistribution and use in source and binary forms, with or without 121573Srgrimes * modification, are permitted provided that the following conditions 131573Srgrimes * are met: 141573Srgrimes * 1. Redistributions of source code must retain the above copyright 151573Srgrimes * notice, this list of conditions and the following disclaimer. 161573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171573Srgrimes * notice, this list of conditions and the following disclaimer in the 181573Srgrimes * documentation and/or other materials provided with the distribution. 191573Srgrimes * 20113596Snectar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23113596Snectar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301573Srgrimes * SUCH DAMAGE. 31113596Snectar * 321573Srgrimes */ 3390016Sbde#include <sys/cdefs.h> 3489999Sobrien__FBSDID("$FreeBSD: head/lib/libc/gen/getpwent.c 113670 2003-04-18 16:24:25Z nectar $"); 351573Srgrimes 36113596Snectar#include "namespace.h" 371573Srgrimes#include <sys/param.h> 38113596Snectar#ifdef YP 39113596Snectar#include <rpc/rpc.h> 40113596Snectar#include <rpcsvc/yp_prot.h> 41113596Snectar#include <rpcsvc/ypclnt.h> 42113596Snectar#endif 43113596Snectar#include <arpa/inet.h> 44113596Snectar#include <errno.h> 451573Srgrimes#include <fcntl.h> 4665532Snectar#ifdef HESIOD 4765532Snectar#include <hesiod.h> 4865532Snectar#endif 49113596Snectar#include <netdb.h> 50113596Snectar#include <nsswitch.h> 51113596Snectar#include <pthread.h> 52113596Snectar#include <pthread_np.h> 53113596Snectar#include <pwd.h> 54113596Snectar#include <stdlib.h> 5565532Snectar#include <stdio.h> 56113596Snectar#include <string.h> 57113596Snectar#include <syslog.h> 58113596Snectar#include <unistd.h> 5971579Sdeischen#include "un-namespace.h" 60113596Snectar#include <db.h> 61111618Snectar#include "libc_private.h" 6265532Snectar#include "pw_scan.h" 63113596Snectar#include "nss_tls.h" 6465532Snectar 65113596Snectar#ifndef CTASSERT 66113596Snectar#define CTASSERT(x) _CTASSERT(x, __LINE__) 67113596Snectar#define _CTASSERT(x, y) __CTASSERT(x, y) 68113596Snectar#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1] 6965532Snectar#endif 7065532Snectar 71113596Snectar/* Counter as stored in /etc/pwd.db */ 72113596Snectartypedef int pwkeynum; 7323668Speter 74113596SnectarCTASSERT(MAXLOGNAME > sizeof(uid_t)); 75113596SnectarCTASSERT(MAXLOGNAME > sizeof(pwkeynum)); 7665532Snectar 77113596Snectarenum constants { 78113596Snectar PWD_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ 79113596Snectar PWD_STORAGE_MAX = 1 << 20, /* 1 MByte */ 80113596Snectar SETPWENT = 1, 81113596Snectar ENDPWENT = 2, 82113596Snectar HESIOD_NAME_MAX = 256 83113596Snectar}; 8465532Snectar 85113596Snectarstatic const ns_src defaultsrc[] = { 86113643Snectar { NSSRC_COMPAT, NS_SUCCESS }, 87113596Snectar { NULL, 0 } 8865532Snectar}; 8965532Snectar 90113596Snectarint __pw_match_entry(const char *, size_t, enum nss_lookup_type, 91113596Snectar const char *, uid_t); 92113596Snectarint __pw_parse_entry(char *, size_t, struct passwd *, int, int *errnop); 9315267Swpaul 94113596Snectarunion key { 95113596Snectar const char *name; 96113596Snectar uid_t uid; 97113596Snectar}; 98113596Snectar 99113596Snectarstatic struct passwd *getpw(int (*fn)(union key, struct passwd *, char *, 100113596Snectar size_t, struct passwd **), union key); 101113596Snectarstatic int wrap_getpwnam_r(union key, struct passwd *, char *, 102113596Snectar size_t, struct passwd **); 103113596Snectarstatic int wrap_getpwuid_r(union key, struct passwd *, char *, size_t, 104113596Snectar struct passwd **); 105113596Snectarstatic int wrap_getpwent_r(union key, struct passwd *, char *, size_t, 106113596Snectar struct passwd **); 107113596Snectar 108113596Snectarstatic int pwdb_match_entry_v3(char *, size_t, enum nss_lookup_type, 109113596Snectar const char *, uid_t); 110113596Snectarstatic int pwdb_parse_entry_v3(char *, size_t, struct passwd *, int *); 111113596Snectarstatic int pwdb_match_entry_v4(char *, size_t, enum nss_lookup_type, 112113596Snectar const char *, uid_t); 113113596Snectarstatic int pwdb_parse_entry_v4(char *, size_t, struct passwd *, int *); 114113596Snectar 115113596Snectar 116113596Snectarstruct { 117113596Snectar int (*match)(char *, size_t, enum nss_lookup_type, const char *, 118113596Snectar uid_t); 119113596Snectar int (*parse)(char *, size_t, struct passwd *, int *); 120113596Snectar} pwdb_versions[] = { 121113596Snectar { NULL, NULL }, /* version 0 */ 122113596Snectar { NULL, NULL }, /* version 1 */ 123113596Snectar { NULL, NULL }, /* version 2 */ 124113596Snectar { pwdb_match_entry_v3, pwdb_parse_entry_v3 }, /* version 3 */ 125113596Snectar { pwdb_match_entry_v4, pwdb_parse_entry_v4 }, /* version 4 */ 126113596Snectar}; 127113596Snectar 128113596Snectar 129113596Snectarstruct files_state { 130113596Snectar DB *db; 131113596Snectar pwkeynum keynum; 132113596Snectar int stayopen; 133113596Snectar int version; 134113596Snectar}; 135113596Snectarstatic void files_endstate(void *); 136113596SnectarNSS_TLS_HANDLING(files); 137113596Snectarstatic DB *pwdbopen(int *); 138113596Snectarstatic void files_endstate(void *); 139113596Snectarstatic int files_setpwent(void *, void *, va_list); 140113596Snectarstatic int files_passwd(void *, void *, va_list); 141113596Snectar 142113596Snectar 14365532Snectar#ifdef HESIOD 144113596Snectarstruct dns_state { 145113596Snectar long counter; 146113596Snectar}; 147113596Snectarstatic void dns_endstate(void *); 148113596SnectarNSS_TLS_HANDLING(dns); 149113596Snectarstatic int dns_setpwent(void *, void *, va_list); 150113596Snectarstatic int dns_passwd(void *, void *, va_list); 15111436Swpaul#endif 1522917Swollman 15365532Snectar 154113596Snectar#ifdef YP 155113596Snectarstruct nis_state { 156113596Snectar char domain[MAXHOSTNAMELEN]; 157113596Snectar int done; 158113596Snectar char *key; 159113596Snectar int keylen; 160113596Snectar}; 161113596Snectarstatic void nis_endstate(void *); 162113596SnectarNSS_TLS_HANDLING(nis); 163113596Snectarstatic int nis_setpwent(void *, void *, va_list); 164113596Snectarstatic int nis_passwd(void *, void *, va_list); 165113596Snectarstatic int nis_map(char *, enum nss_lookup_type, char *, size_t, int *); 166113596Snectarstatic int nis_adjunct(char *, const char *, char *, size_t); 167113596Snectar#endif 16865532Snectar 16965532Snectar 170113596Snectarstruct compat_state { 171113596Snectar DB *db; 172113596Snectar pwkeynum keynum; 173113596Snectar int stayopen; 174113596Snectar int version; 175113596Snectar DB *exclude; 176113596Snectar struct passwd template; 177113596Snectar char *name; 178113596Snectar enum _compat { 179113596Snectar COMPAT_MODE_OFF = 0, 180113596Snectar COMPAT_MODE_ALL, 181113596Snectar COMPAT_MODE_NAME, 182113596Snectar COMPAT_MODE_NETGROUP 183113596Snectar } compat; 184113596Snectar}; 185113596Snectarstatic void compat_endstate(void *); 186113596SnectarNSS_TLS_HANDLING(compat); 187113596Snectarstatic int compat_setpwent(void *, void *, va_list); 188113596Snectarstatic int compat_passwd(void *, void *, va_list); 189113596Snectarstatic void compat_clear_template(struct passwd *); 190113596Snectarstatic int compat_set_template(struct passwd *, struct passwd *); 191113596Snectarstatic int compat_use_template(struct passwd *, struct passwd *, char *, 192113596Snectar size_t); 193113596Snectarstatic int compat_redispatch(struct compat_state *, enum nss_lookup_type, 194113596Snectar enum nss_lookup_type, const char *, const char *, uid_t, 195113596Snectar struct passwd *, char *, size_t, int *); 196113596Snectarvoid 197113596Snectarsetpwent(void) 1981573Srgrimes{ 199113596Snectar static const ns_dtab dtab[] = { 200113596Snectar { NSSRC_FILES, files_setpwent, (void *)SETPWENT }, 201113596Snectar#ifdef HESIOD 202113596Snectar { NSSRC_DNS, dns_setpwent, (void *)SETPWENT }, 203113596Snectar#endif 204113596Snectar#ifdef YP 205113596Snectar { NSSRC_NIS, nis_setpwent, (void *)SETPWENT }, 206113596Snectar#endif 207113596Snectar { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT }, 208113596Snectar { NULL, NULL, NULL } 209113596Snectar }; 210113596Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 0); 211113596Snectar} 2121573Srgrimes 21310521Swpaul 214113596Snectarint 215113596Snectarsetpassent(int stayopen) 216113596Snectar{ 217113596Snectar static const ns_dtab dtab[] = { 218113596Snectar { NSSRC_FILES, files_setpwent, (void *)SETPWENT }, 219113596Snectar#ifdef HESIOD 220113596Snectar { NSSRC_DNS, dns_setpwent, (void *)SETPWENT }, 221113596Snectar#endif 222113596Snectar#ifdef YP 223113596Snectar { NSSRC_NIS, nis_setpwent, (void *)SETPWENT }, 224113596Snectar#endif 225113596Snectar { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT }, 226113596Snectar { NULL, NULL, NULL } 227113596Snectar }; 228113596Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 229113596Snectar stayopen); 230113596Snectar return (1); 231113596Snectar} 23265532Snectar 23365532Snectar 234113596Snectarvoid 235113596Snectarendpwent(void) 236113596Snectar{ 237113596Snectar static const ns_dtab dtab[] = { 238113596Snectar { NSSRC_FILES, files_setpwent, (void *)ENDPWENT }, 239113596Snectar#ifdef HESIOD 240113596Snectar { NSSRC_DNS, dns_setpwent, (void *)ENDPWENT }, 241113596Snectar#endif 242113596Snectar#ifdef YP 243113596Snectar { NSSRC_NIS, nis_setpwent, (void *)ENDPWENT }, 244113596Snectar#endif 245113596Snectar { NSSRC_COMPAT, compat_setpwent, (void *)ENDPWENT }, 246113596Snectar { NULL, NULL, NULL } 247113596Snectar }; 248113596Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "endpwent", defaultsrc); 2491573Srgrimes} 2501573Srgrimes 251113596Snectar 252113596Snectarint 253113596Snectargetpwent_r(struct passwd *pwd, char *buffer, size_t bufsize, 254113596Snectar struct passwd **result) 2551573Srgrimes{ 256113596Snectar static const ns_dtab dtab[] = { 257113596Snectar { NSSRC_FILES, files_passwd, (void *)nss_lt_all }, 258113596Snectar#ifdef HESIOD 259113596Snectar { NSSRC_DNS, dns_passwd, (void *)nss_lt_all }, 260113596Snectar#endif 261113596Snectar#ifdef YP 262113596Snectar { NSSRC_NIS, nis_passwd, (void *)nss_lt_all }, 263113596Snectar#endif 264113596Snectar { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_all }, 265113596Snectar { NULL, NULL, NULL } 266113596Snectar }; 267113596Snectar int rv, ret_errno; 2681573Srgrimes 269113596Snectar ret_errno = 0; 270113596Snectar *result = NULL; 271113596Snectar rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwent_r", defaultsrc, 272113596Snectar pwd, buffer, bufsize, &ret_errno); 273113596Snectar if (rv == NS_SUCCESS) 274113596Snectar return (0); 275113596Snectar else 276113596Snectar return (ret_errno); 277113596Snectar} 2781573Srgrimes 2791573Srgrimes 280113596Snectarint 281113596Snectargetpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, 282113596Snectar struct passwd **result) 283113596Snectar{ 284113596Snectar static const ns_dtab dtab[] = { 285113596Snectar { NSSRC_FILES, files_passwd, (void *)nss_lt_name }, 286113596Snectar#ifdef HESIOD 287113596Snectar { NSSRC_DNS, dns_passwd, (void *)nss_lt_name }, 288113596Snectar#endif 289113596Snectar#ifdef YP 290113596Snectar { NSSRC_NIS, nis_passwd, (void *)nss_lt_name }, 291113596Snectar#endif 292113596Snectar { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_name }, 293113596Snectar { NULL, NULL, NULL } 294113596Snectar }; 295113596Snectar int rv, ret_errno; 296113596Snectar 297113596Snectar ret_errno = 0; 298113596Snectar *result = NULL; 299113596Snectar rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwnam_r", defaultsrc, 300113596Snectar name, pwd, buffer, bufsize, &ret_errno); 301113596Snectar if (rv == NS_SUCCESS) 302113596Snectar return (0); 303113596Snectar else 304113596Snectar return (ret_errno); 30565532Snectar} 3065714Swollman 307113596Snectar 308113596Snectarint 309113596Snectargetpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, 310113596Snectar struct passwd **result) 31165532Snectar{ 312113596Snectar static const ns_dtab dtab[] = { 313113596Snectar { NSSRC_FILES, files_passwd, (void *)nss_lt_id }, 314113596Snectar#ifdef HESIOD 315113596Snectar { NSSRC_DNS, dns_passwd, (void *)nss_lt_id }, 316113596Snectar#endif 317113596Snectar#ifdef YP 318113596Snectar { NSSRC_NIS, nis_passwd, (void *)nss_lt_id }, 319113596Snectar#endif 320113596Snectar { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_id }, 321113596Snectar { NULL, NULL, NULL } 322113596Snectar }; 323113596Snectar int rv, ret_errno; 32465532Snectar 325113596Snectar ret_errno = 0; 326113596Snectar *result = NULL; 327113596Snectar rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwuid_r", defaultsrc, 328113596Snectar uid, pwd, buffer, bufsize, &ret_errno); 329113596Snectar if (rv == NS_SUCCESS) 330113596Snectar return (0); 331113596Snectar else 332113596Snectar return (ret_errno); 333113596Snectar} 33465532Snectar 33565532Snectar 336113596Snectarstatic struct passwd pwd; 337113596Snectarstatic char *pwd_storage; 338113596Snectarstatic size_t pwd_storage_size; 33968577Snectar 34065532Snectar 341113596Snectarstatic struct passwd * 342113596Snectargetpw(int (*fn)(union key, struct passwd *, char *, size_t, struct passwd **), 343113596Snectar union key key) 344113596Snectar{ 345113596Snectar int rv; 346113596Snectar struct passwd *res; 34765532Snectar 348113596Snectar if (pwd_storage == NULL) { 349113596Snectar pwd_storage = malloc(PWD_STORAGE_INITIAL); 350113596Snectar if (pwd_storage == NULL) 351113596Snectar return (NULL); 352113596Snectar pwd_storage_size = PWD_STORAGE_INITIAL; 35368577Snectar } 354113596Snectar do { 355113596Snectar rv = fn(key, &pwd, pwd_storage, pwd_storage_size, &res); 356113596Snectar if (res == NULL && rv == ERANGE) { 357113596Snectar free(pwd_storage); 358113596Snectar if ((pwd_storage_size << 1) > PWD_STORAGE_MAX) { 359113596Snectar pwd_storage = NULL; 360113596Snectar return (NULL); 361113596Snectar } 362113596Snectar pwd_storage_size <<= 1; 363113596Snectar pwd_storage = malloc(pwd_storage_size); 364113596Snectar if (pwd_storage == NULL) 365113596Snectar return (NULL); 366113596Snectar } 367113596Snectar } while (res == NULL && rv == ERANGE); 368113596Snectar return (res); 369113596Snectar} 37065532Snectar 371113596Snectar 372113596Snectarstatic int 373113596Snectarwrap_getpwnam_r(union key key, struct passwd *pwd, char *buffer, 374113596Snectar size_t bufsize, struct passwd **res) 375113596Snectar{ 376113596Snectar return (getpwnam_r(key.name, pwd, buffer, bufsize, res)); 3771573Srgrimes} 3781573Srgrimes 379113596Snectar 38065532Snectarstatic int 381113596Snectarwrap_getpwuid_r(union key key, struct passwd *pwd, char *buffer, 382113596Snectar size_t bufsize, struct passwd **res) 3831573Srgrimes{ 384113596Snectar return (getpwuid_r(key.uid, pwd, buffer, bufsize, res)); 385113596Snectar} 3861573Srgrimes 3871573Srgrimes 388113596Snectarstatic int 389113596Snectarwrap_getpwent_r(union key key __unused, struct passwd *pwd, char *buffer, 390113596Snectar size_t bufsize, struct passwd **res) 391113596Snectar{ 392113596Snectar return (getpwent_r(pwd, buffer, bufsize, res)); 393113596Snectar} 3941573Srgrimes 39565532Snectar 396113596Snectarstruct passwd * 397113596Snectargetpwnam(const char *name) 398113596Snectar{ 399113596Snectar union key key; 40065532Snectar 401113596Snectar key.name = name; 402113596Snectar return (getpw(wrap_getpwnam_r, key)); 403113596Snectar} 4047258Swpaul 4051573Srgrimes 406113596Snectarstruct passwd * 407113596Snectargetpwuid(uid_t uid) 408113596Snectar{ 409113596Snectar union key key; 410113596Snectar 411113596Snectar key.uid = uid; 412113596Snectar return (getpw(wrap_getpwuid_r, key)); 4131573Srgrimes} 4141573Srgrimes 415113596Snectar 416113596Snectarstruct passwd * 417113596Snectargetpwent(void) 418113596Snectar{ 419113596Snectar union key key; 420113596Snectar 421113596Snectar key.uid = 0; /* not used */ 422113596Snectar return (getpw(wrap_getpwent_r, key)); 423113596Snectar} 424113596Snectar 425113596Snectar 42665532Snectar/* 427113596Snectar * files backend 42865532Snectar */ 429113596Snectarstatic DB * 430113596Snectarpwdbopen(int *version) 4311573Srgrimes{ 432113596Snectar DB *res; 433113596Snectar DBT key, entry; 434113596Snectar int rv; 4351573Srgrimes 436113596Snectar if (geteuid() != 0 || 437113596Snectar (res = dbopen(_PATH_SMP_DB, O_RDONLY, 0, DB_HASH, NULL)) == NULL) 438113596Snectar res = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL); 439113596Snectar if (res == NULL) 440113596Snectar return (NULL); 441113596Snectar key.data = _PWD_VERSION_KEY; 442113596Snectar key.size = strlen(_PWD_VERSION_KEY); 443113596Snectar rv = res->get(res, &key, &entry, 0); 444113596Snectar if (rv == 0) 445113596Snectar *version = *(unsigned char *)entry.data; 446113596Snectar else 447113596Snectar *version = 3; 448113596Snectar if (*version < 3 || 449113596Snectar *version >= sizeof(pwdb_versions)/sizeof(pwdb_versions[0])) { 450113596Snectar syslog(LOG_CRIT, "Unsupported password database version %d", 451113596Snectar *version); 452113596Snectar res->close(res); 453113596Snectar res = NULL; 45415267Swpaul } 455113596Snectar return (res); 456113596Snectar} 45765532Snectar 45865532Snectar 459113596Snectarstatic void 460113596Snectarfiles_endstate(void *p) 461113596Snectar{ 462113596Snectar DB *db; 463113596Snectar 464113596Snectar if (p == NULL) 465113596Snectar return; 466113596Snectar db = ((struct files_state *)p)->db; 467113596Snectar if (db != NULL) 468113596Snectar db->close(db); 469113596Snectar free(p); 470113596Snectar} 471113596Snectar 472113596Snectar 473113596Snectarstatic int 474113596Snectarfiles_setpwent(void *retval, void *mdata, va_list ap) 475113596Snectar{ 476113596Snectar struct files_state *st; 477113596Snectar int rv, stayopen; 478113596Snectar 479113596Snectar rv = files_getstate(&st); 480113596Snectar if (rv != 0) 481113596Snectar return (NS_UNAVAIL); 482113596Snectar switch ((enum constants)mdata) { 483113596Snectar case SETPWENT: 484113596Snectar stayopen = va_arg(ap, int); 485113596Snectar st->keynum = 0; 486113596Snectar if (stayopen) 487113596Snectar st->db = pwdbopen(&st->version); 488113596Snectar st->stayopen = stayopen; 489113596Snectar break; 490113596Snectar case ENDPWENT: 491113596Snectar if (st->db != NULL) { 492113596Snectar (void)st->db->close(st->db); 493113596Snectar st->db = NULL; 49465532Snectar } 495113596Snectar break; 496113596Snectar default: 497113596Snectar break; 49815267Swpaul } 499113596Snectar return (NS_UNAVAIL); 5001573Srgrimes} 5011573Srgrimes 50265532Snectar 50317141Sjkhstatic int 504113596Snectarfiles_passwd(void *retval, void *mdata, va_list ap) 5051573Srgrimes{ 506113596Snectar char keybuf[MAXLOGNAME + 1]; 507113596Snectar DBT key, entry; 508113596Snectar struct files_state *st; 509113596Snectar enum nss_lookup_type how; 510113596Snectar const char *name; 511113596Snectar struct passwd *pwd; 512113596Snectar char *buffer; 513113596Snectar size_t bufsize, namesize; 514113596Snectar uid_t uid; 515113596Snectar uint32_t store; 516113596Snectar int rv, stayopen, *errnop; 5171573Srgrimes 518113596Snectar name = NULL; 519113596Snectar uid = (uid_t)-1; 520113596Snectar how = (enum nss_lookup_type)mdata; 521113596Snectar switch (how) { 522113596Snectar case nss_lt_name: 52365532Snectar name = va_arg(ap, const char *); 524113596Snectar keybuf[0] = _PW_KEYBYNAME; 52565532Snectar break; 526113596Snectar case nss_lt_id: 52765532Snectar uid = va_arg(ap, uid_t); 528113596Snectar keybuf[0] = _PW_KEYBYUID; 52965532Snectar break; 530113596Snectar case nss_lt_all: 531113596Snectar keybuf[0] = _PW_KEYBYNUM; 532113596Snectar break; 53365532Snectar default: 534113596Snectar rv = NS_NOTFOUND; 535113596Snectar goto fin; 53665532Snectar } 537113596Snectar pwd = va_arg(ap, struct passwd *); 538113596Snectar buffer = va_arg(ap, char *); 539113596Snectar bufsize = va_arg(ap, size_t); 540113596Snectar errnop = va_arg(ap, int *); 541113596Snectar *errnop = files_getstate(&st); 542113596Snectar if (*errnop != 0) 543113596Snectar return (NS_UNAVAIL); 544113596Snectar if (how == nss_lt_all && st->keynum < 0) { 545113596Snectar rv = NS_NOTFOUND; 546113596Snectar goto fin; 54765532Snectar } 548113596Snectar if (st->db == NULL && 549113596Snectar (st->db = pwdbopen(&st->version)) == NULL) { 550113596Snectar *errnop = errno; 551113596Snectar rv = NS_UNAVAIL; 552113596Snectar goto fin; 55394688Sdes } 554113596Snectar if (how == nss_lt_all) 555113596Snectar stayopen = 1; 556113596Snectar else 557113596Snectar stayopen = st->stayopen; 558113596Snectar key.data = keybuf; 559113596Snectar do { 560113596Snectar switch (how) { 561113596Snectar case nss_lt_name: 562113596Snectar /* MAXLOGNAME includes NUL byte, but we do not 563113596Snectar * include the NUL byte in the key. 564113596Snectar */ 565113596Snectar namesize = strlcpy(&keybuf[1], name, sizeof(keybuf)-1); 566113596Snectar if (namesize >= sizeof(keybuf)-1) { 567113596Snectar *errnop = EINVAL; 568113596Snectar rv = NS_NOTFOUND; 569113596Snectar goto fin; 570113596Snectar } 571113596Snectar key.size = namesize + 1; 572113596Snectar break; 573113596Snectar case nss_lt_id: 574113596Snectar if (st->version < _PWD_CURRENT_VERSION) { 575113596Snectar memcpy(&keybuf[1], &uid, sizeof(uid)); 576113596Snectar key.size = sizeof(uid) + 1; 577113596Snectar } else { 578113596Snectar store = htonl(uid); 579113596Snectar memcpy(&keybuf[1], &store, sizeof(store)); 580113596Snectar key.size = sizeof(store) + 1; 581113596Snectar } 582113596Snectar break; 583113596Snectar case nss_lt_all: 584113596Snectar st->keynum++; 585113596Snectar if (st->version < _PWD_CURRENT_VERSION) { 586113596Snectar memcpy(&keybuf[1], &st->keynum, 587113596Snectar sizeof(st->keynum)); 588113596Snectar key.size = sizeof(st->keynum) + 1; 589113596Snectar } else { 590113596Snectar store = htonl(st->keynum); 591113596Snectar memcpy(&keybuf[1], &store, sizeof(store)); 592113596Snectar key.size = sizeof(store) + 1; 593113596Snectar } 594113596Snectar break; 595113596Snectar } 596113666Snectar keybuf[0] = _PW_VERSIONED(keybuf[0], st->version); 597113596Snectar rv = st->db->get(st->db, &key, &entry, 0); 598113596Snectar if (rv < 0 || rv > 1) { /* should never return > 1 */ 599113596Snectar *errnop = errno; 600113596Snectar rv = NS_UNAVAIL; 601113596Snectar goto fin; 602113596Snectar } else if (rv == 1) { 603113596Snectar if (how == nss_lt_all) 604113596Snectar st->keynum = -1; 605113596Snectar rv = NS_NOTFOUND; 606113596Snectar goto fin; 607113596Snectar } 608113596Snectar rv = pwdb_versions[st->version].match(entry.data, entry.size, 609113596Snectar how, name, uid); 610113596Snectar if (rv != NS_SUCCESS) 611113596Snectar continue; 612113596Snectar if (entry.size > bufsize) { 613113596Snectar *errnop = ERANGE; 614113596Snectar rv = NS_RETURN; 615113596Snectar break; 616113596Snectar } 617113596Snectar memcpy(buffer, entry.data, entry.size); 618113596Snectar rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd, 619113596Snectar errnop); 620113596Snectar } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 621113596Snectarfin: 622113596Snectar if (!stayopen && st->db != NULL) { 623113596Snectar (void)st->db->close(st->db); 624113596Snectar st->db = NULL; 625113596Snectar } 626113670Snectar if (rv == NS_SUCCESS) { 627113670Snectar pwd->pw_fields &= ~_PWF_SOURCE; 628113670Snectar pwd->pw_fields |= _PWF_FILES; 629113670Snectar if (retval != NULL) 630113670Snectar *(struct passwd **)retval = pwd; 631113670Snectar } 632113596Snectar return (rv); 6331573Srgrimes} 6341573Srgrimes 635113596Snectar 636113596Snectarstatic int 637113596Snectarpwdb_match_entry_v3(char *entry, size_t entrysize, enum nss_lookup_type how, 638113596Snectar const char *name, uid_t uid) 639113596Snectar{ 640113596Snectar const char *p, *eom; 641113596Snectar uid_t uid2; 642113596Snectar 643113596Snectar eom = &entry[entrysize]; 644113596Snectar for (p = entry; p < eom; p++) 645113596Snectar if (*p == '\0') 646113596Snectar break; 647113596Snectar if (*p != '\0') 648113596Snectar return (NS_NOTFOUND); 649113596Snectar if (how == nss_lt_all) 650113596Snectar return (NS_SUCCESS); 651113596Snectar if (how == nss_lt_name) 652113596Snectar return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND); 653113596Snectar for (p++; p < eom; p++) 654113596Snectar if (*p == '\0') 655113596Snectar break; 656113596Snectar if (*p != '\0' || (++p) + sizeof(uid) >= eom) 657113596Snectar return (NS_NOTFOUND); 658113596Snectar memcpy(&uid2, p, sizeof(uid2)); 659113596Snectar return (uid == uid2 ? NS_SUCCESS : NS_NOTFOUND); 660113596Snectar} 661113596Snectar 662113596Snectar 663113596Snectarstatic int 664113596Snectarpwdb_parse_entry_v3(char *buffer, size_t bufsize, struct passwd *pwd, 665113596Snectar int *errnop) 666113596Snectar{ 667113596Snectar char *p, *eom; 668113596Snectar int32_t pw_change, pw_expire; 669113596Snectar 670113596Snectar memset(pwd, 0, sizeof(*pwd)); 671113596Snectar /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 672113596Snectar p = buffer; 673113596Snectar eom = &buffer[bufsize]; 674113596Snectar#define STRING(field) do { \ 675113596Snectar (field) = p; \ 676113596Snectar while (p < eom && *p != '\0') \ 677113596Snectar p++; \ 678113596Snectar if (p >= eom) \ 679113596Snectar return (NS_NOTFOUND); \ 680113596Snectar p++; \ 681113596Snectar } while (0) 682113596Snectar#define SCALAR(field) do { \ 683113596Snectar if (p + sizeof(field) > eom) \ 684113596Snectar return (NS_NOTFOUND); \ 685113596Snectar memcpy(&(field), p, sizeof(field)); \ 686113596Snectar p += sizeof(field); \ 687113596Snectar } while (0) 688113596Snectar STRING(pwd->pw_name); 689113596Snectar STRING(pwd->pw_passwd); 690113596Snectar SCALAR(pwd->pw_uid); 691113596Snectar SCALAR(pwd->pw_gid); 692113596Snectar SCALAR(pw_change); 693113596Snectar STRING(pwd->pw_class); 694113596Snectar STRING(pwd->pw_gecos); 695113596Snectar STRING(pwd->pw_dir); 696113596Snectar STRING(pwd->pw_shell); 697113596Snectar SCALAR(pw_expire); 698113596Snectar SCALAR(pwd->pw_fields); 699113596Snectar#undef STRING 700113596Snectar#undef SCALAR 701113596Snectar pwd->pw_change = pw_change; 702113596Snectar pwd->pw_expire = pw_expire; 703113596Snectar return (NS_SUCCESS); 704113596Snectar} 705113596Snectar 706113596Snectar 707113596Snectarstatic int 708113596Snectarpwdb_match_entry_v4(char *entry, size_t entrysize, enum nss_lookup_type how, 709113596Snectar const char *name, uid_t uid) 710113596Snectar{ 711113596Snectar const char *p, *eom; 712113596Snectar uint32_t uid2; 713113596Snectar 714113596Snectar eom = &entry[entrysize]; 715113596Snectar for (p = entry; p < eom; p++) 716113596Snectar if (*p == '\0') 717113596Snectar break; 718113596Snectar if (*p != '\0') 719113596Snectar return (NS_NOTFOUND); 720113596Snectar if (how == nss_lt_all) 721113596Snectar return (NS_SUCCESS); 722113596Snectar if (how == nss_lt_name) 723113596Snectar return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND); 724113596Snectar for (p++; p < eom; p++) 725113596Snectar if (*p == '\0') 726113596Snectar break; 727113596Snectar if (*p != '\0' || (++p) + sizeof(uid) >= eom) 728113596Snectar return (NS_NOTFOUND); 729113596Snectar memcpy(&uid2, p, sizeof(uid2)); 730113596Snectar uid2 = ntohl(uid2); 731113596Snectar return (uid == (uid_t)uid2 ? NS_SUCCESS : NS_NOTFOUND); 732113596Snectar} 733113596Snectar 734113596Snectar 735113596Snectarstatic int 736113596Snectarpwdb_parse_entry_v4(char *buffer, size_t bufsize, struct passwd *pwd, 737113596Snectar int *errnop) 738113596Snectar{ 739113596Snectar char *p, *eom; 740113596Snectar uint32_t n; 741113596Snectar 742113596Snectar memset(pwd, 0, sizeof(*pwd)); 743113596Snectar /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 744113596Snectar p = buffer; 745113596Snectar eom = &buffer[bufsize]; 746113596Snectar#define STRING(field) do { \ 747113596Snectar (field) = p; \ 748113596Snectar while (p < eom && *p != '\0') \ 749113596Snectar p++; \ 750113596Snectar if (p >= eom) \ 751113596Snectar return (NS_NOTFOUND); \ 752113596Snectar p++; \ 753113596Snectar } while (0) 754113596Snectar#define SCALAR(field) do { \ 755113596Snectar if (p + sizeof(n) > eom) \ 756113596Snectar return (NS_NOTFOUND); \ 757113596Snectar memcpy(&n, p, sizeof(n)); \ 758113596Snectar (field) = ntohl(n); \ 759113596Snectar p += sizeof(n); \ 760113596Snectar } while (0) 761113596Snectar STRING(pwd->pw_name); 762113596Snectar STRING(pwd->pw_passwd); 763113596Snectar SCALAR(pwd->pw_uid); 764113596Snectar SCALAR(pwd->pw_gid); 765113596Snectar SCALAR(pwd->pw_change); 766113596Snectar STRING(pwd->pw_class); 767113596Snectar STRING(pwd->pw_gecos); 768113596Snectar STRING(pwd->pw_dir); 769113596Snectar STRING(pwd->pw_shell); 770113596Snectar SCALAR(pwd->pw_expire); 771113596Snectar SCALAR(pwd->pw_fields); 772113596Snectar#undef STRING 773113596Snectar#undef SCALAR 774113596Snectar return (NS_SUCCESS); 775113596Snectar} 776113596Snectar 777113596Snectar 77865532Snectar#ifdef HESIOD 77965532Snectar/* 780113596Snectar * dns backend 78165532Snectar */ 782113596Snectarstatic void 783113596Snectardns_endstate(void *p) 784113596Snectar{ 785113596Snectar free(p); 786113596Snectar} 78765532Snectar 788113596Snectar 78917141Sjkhstatic int 790113596Snectardns_setpwent(void *retval, void *mdata, va_list ap) 7911573Srgrimes{ 792113596Snectar struct dns_state *st; 793113596Snectar int rv; 7941573Srgrimes 795113596Snectar rv = dns_getstate(&st); 796113596Snectar if (rv != 0) 797113596Snectar return (NS_UNAVAIL); 798113596Snectar st->counter = 0; 799113596Snectar return (NS_UNAVAIL); 800113596Snectar} 8011573Srgrimes 802113596Snectar 803113596Snectarstatic int 804113596Snectardns_passwd(void *retval, void *mdata, va_list ap) 805113596Snectar{ 806113596Snectar char buf[HESIOD_NAME_MAX]; 807113596Snectar struct dns_state *st; 808113596Snectar struct passwd *pwd; 809113596Snectar const char *name, *label; 810113596Snectar void *ctx; 811113596Snectar char *buffer, **hes; 812113596Snectar size_t bufsize, linesize; 813113596Snectar uid_t uid; 814113596Snectar enum nss_lookup_type how; 815113596Snectar int rv, *errnop; 816113596Snectar 817113596Snectar ctx = NULL; 818113596Snectar hes = NULL; 819113596Snectar name = NULL; 820113596Snectar uid = (uid_t)-1; 821113596Snectar how = (enum nss_lookup_type)mdata; 822113596Snectar switch (how) { 823113596Snectar case nss_lt_name: 82465532Snectar name = va_arg(ap, const char *); 82565532Snectar break; 826113596Snectar case nss_lt_id: 82765532Snectar uid = va_arg(ap, uid_t); 82865532Snectar break; 829113596Snectar case nss_lt_all: 830113596Snectar break; 83129479Swosch } 832113596Snectar pwd = va_arg(ap, struct passwd *); 833113596Snectar buffer = va_arg(ap, char *); 834113596Snectar bufsize = va_arg(ap, size_t); 835113596Snectar errnop = va_arg(ap, int *); 836113596Snectar *errnop = dns_getstate(&st); 837113596Snectar if (*errnop != 0) 838113596Snectar return (NS_UNAVAIL); 839113596Snectar if (hesiod_init(&ctx) != 0) { 840113596Snectar *errnop = errno; 841113596Snectar rv = NS_UNAVAIL; 842113596Snectar goto fin; 843113596Snectar } 844113596Snectar do { 845113596Snectar rv = NS_NOTFOUND; 846113596Snectar switch (how) { 847113596Snectar case nss_lt_name: 848113596Snectar label = name; 849113596Snectar break; 850113596Snectar case nss_lt_id: 851113596Snectar if (snprintf(buf, sizeof(buf), "%lu", 852113596Snectar (unsigned long)uid) >= sizeof(buf)) 853113596Snectar goto fin; 854113596Snectar label = buf; 855113596Snectar break; 856113596Snectar case nss_lt_all: 857113596Snectar if (st->counter < 0) 858113596Snectar goto fin; 859113596Snectar if (snprintf(buf, sizeof(buf), "passwd-%ld", 860113596Snectar st->counter++) >= sizeof(buf)) 861113596Snectar goto fin; 862113596Snectar label = buf; 863113596Snectar break; 86465532Snectar } 865113596Snectar hes = hesiod_resolve(ctx, label, 866113596Snectar how == nss_lt_id ? "uid" : "passwd"); 867113596Snectar if (hes == NULL) { 868113596Snectar if (how == nss_lt_all) 869113596Snectar st->counter = -1; 870113596Snectar if (errno != ENOENT) 871113596Snectar *errnop = errno; 872113596Snectar goto fin; 873113596Snectar } 874113596Snectar rv = __pw_match_entry(hes[0], strlen(hes[0]), how, name, uid); 875113596Snectar if (rv != NS_SUCCESS) { 876113596Snectar hesiod_free_list(ctx, hes); 877113596Snectar hes = NULL; 878113596Snectar continue; 879113596Snectar } 880113596Snectar linesize = strlcpy(buffer, hes[0], bufsize); 881113596Snectar if (linesize >= bufsize) { 882113596Snectar *errnop = ERANGE; 883113596Snectar rv = NS_RETURN; 884113596Snectar continue; 885113596Snectar } 886113596Snectar hesiod_free_list(ctx, hes); 887113596Snectar hes = NULL; 888113596Snectar rv = __pw_parse_entry(buffer, bufsize, pwd, 0, errnop); 889113596Snectar } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 890113596Snectarfin: 891113596Snectar if (hes != NULL) 892113596Snectar hesiod_free_list(ctx, hes); 893113596Snectar if (ctx != NULL) 894113596Snectar hesiod_end(ctx); 895113596Snectar if (rv == NS_SUCCESS) { 896113596Snectar pwd->pw_fields &= ~_PWF_SOURCE; 897113596Snectar pwd->pw_fields |= _PWF_HESIOD; 898113596Snectar if (retval != NULL) 899113596Snectar *(struct passwd **)retval = pwd; 90065532Snectar } 901113596Snectar return (rv); 90215267Swpaul} 903113596Snectar#endif /* HESIOD */ 9047258Swpaul 905113596Snectar 90665532Snectar#ifdef YP 90715267Swpaul/* 908113596Snectar * nis backend 90915267Swpaul */ 910113596Snectarstatic void 911113596Snectarnis_endstate(void *p) 912113596Snectar{ 913113596Snectar free(((struct nis_state *)p)->key); 914113596Snectar free(p); 915113596Snectar} 91665532Snectar 91765532Snectarstatic int 918113596Snectarnis_map(char *domain, enum nss_lookup_type how, char *buffer, size_t bufsize, 919113596Snectar int *master) 92015267Swpaul{ 921113596Snectar int rv, order; 9227258Swpaul 923113596Snectar *master = 0; 924113596Snectar if (snprintf(buffer, bufsize, "master.passwd.by%s", 925113596Snectar (how == nss_lt_id) ? "uid" : "name") >= bufsize) 926113596Snectar return (NS_UNAVAIL); 927113596Snectar rv = yp_order(domain, buffer, &order); 928113596Snectar if (rv == 0) { 929113596Snectar *master = 1; 930113596Snectar return (NS_SUCCESS); 93165532Snectar } 932113596Snectar if (snprintf(buffer, bufsize, "passwd.by%s", 933113596Snectar (how == nss_lt_id) ? "uid" : "name") >= bufsize) 934113596Snectar return (NS_UNAVAIL); 935113596Snectar rv = yp_order(domain, buffer, &order); 936113596Snectar if (rv == 0) 937113596Snectar return (NS_SUCCESS); 938113596Snectar return (NS_UNAVAIL); 939113596Snectar} 94015267Swpaul 941113596Snectar 942113596Snectarstatic int 943113596Snectarnis_adjunct(char *domain, const char *name, char *buffer, size_t bufsize) 944113596Snectar{ 945113596Snectar int rv; 946113596Snectar char *result, *p, *q, *eor; 947113596Snectar int resultlen; 948113596Snectar 949113596Snectar result = NULL; 950113596Snectar rv = yp_match(domain, "passwd.adjunct.byname", name, strlen(name), 951113596Snectar &result, &resultlen); 952113596Snectar if (rv != 0) 953113596Snectar rv = 1; 954113596Snectar else { 955113596Snectar eor = &result[resultlen]; 956113596Snectar p = memchr(result, ':', eor - result); 957113596Snectar if (p != NULL && ++p < eor && 958113596Snectar (q = memchr(p, ':', eor - p)) != NULL) { 959113596Snectar if (q - p >= bufsize) 960113596Snectar rv = -1; 961113596Snectar else { 962113596Snectar memcpy(buffer, p, q - p); 963113596Snectar buffer[q - p] ='\0'; 964113596Snectar } 965113596Snectar } else 966113596Snectar rv = 1; 967113596Snectar } 968113596Snectar free(result); 969113596Snectar return (rv); 970113596Snectar} 971113596Snectar 972113596Snectar 973113596Snectarstatic int 974113596Snectarnis_setpwent(void *retval, void *mdata, va_list ap) 975113596Snectar{ 976113596Snectar struct nis_state *st; 977113596Snectar int rv; 978113596Snectar 979113596Snectar rv = nis_getstate(&st); 980113596Snectar if (rv != 0) 981113596Snectar return (NS_UNAVAIL); 982113596Snectar st->done = 0; 983113596Snectar free(st->key); 984113596Snectar st->key = NULL; 985113596Snectar return (NS_UNAVAIL); 986113596Snectar} 987113596Snectar 988113596Snectar 989113596Snectarstatic int 990113596Snectarnis_passwd(void *retval, void *mdata, va_list ap) 991113596Snectar{ 992113596Snectar char map[YPMAXMAP]; 993113596Snectar struct nis_state *st; 994113596Snectar struct passwd *pwd; 995113596Snectar const char *name; 996113596Snectar char *buffer, *key, *result; 997113596Snectar size_t bufsize; 998113596Snectar uid_t uid; 999113596Snectar enum nss_lookup_type how; 1000113596Snectar int *errnop, keylen, resultlen, rv, master; 1001113596Snectar 1002113596Snectar name = NULL; 1003113596Snectar uid = (uid_t)-1; 1004113596Snectar how = (enum nss_lookup_type)mdata; 1005113596Snectar switch (how) { 1006113596Snectar case nss_lt_name: 100765532Snectar name = va_arg(ap, const char *); 100865532Snectar break; 1009113596Snectar case nss_lt_id: 101065532Snectar uid = va_arg(ap, uid_t); 101165532Snectar break; 1012113596Snectar case nss_lt_all: 1013113596Snectar break; 101465532Snectar } 1015113596Snectar pwd = va_arg(ap, struct passwd *); 1016113596Snectar buffer = va_arg(ap, char *); 1017113596Snectar bufsize = va_arg(ap, size_t); 1018113596Snectar errnop = va_arg(ap, int *); 1019113596Snectar *errnop = nis_getstate(&st); 1020113596Snectar if (*errnop != 0) 1021113596Snectar return (NS_UNAVAIL); 1022113596Snectar if (st->domain[0] == '\0') { 1023113596Snectar if (getdomainname(st->domain, sizeof(st->domain)) != 0) { 1024113596Snectar *errnop = errno; 1025113596Snectar return (NS_UNAVAIL); 102665532Snectar } 102765532Snectar } 1028113596Snectar rv = nis_map(st->domain, how, map, sizeof(map), &master); 1029113596Snectar if (rv != NS_SUCCESS) 1030113596Snectar return (rv); 1031113596Snectar result = NULL; 1032113596Snectar do { 1033113596Snectar rv = NS_NOTFOUND; 1034113596Snectar switch (how) { 1035113596Snectar case nss_lt_name: 1036113596Snectar if (strlcpy(buffer, name, bufsize) >= bufsize) 1037113596Snectar goto erange; 1038113596Snectar break; 1039113596Snectar case nss_lt_id: 1040113596Snectar if (snprintf(buffer, bufsize, "%lu", 1041113596Snectar (unsigned long)uid) >= bufsize) 1042113596Snectar goto erange; 1043113596Snectar break; 1044113596Snectar case nss_lt_all: 1045113596Snectar if (st->done) 1046113596Snectar goto fin; 1047113596Snectar break; 1048113596Snectar } 1049113596Snectar result = NULL; 1050113596Snectar if (how == nss_lt_all) { 1051113596Snectar if (st->key == NULL) 1052113596Snectar rv = yp_first(st->domain, map, &st->key, 1053113596Snectar &st->keylen, &result, &resultlen); 1054113596Snectar else { 1055113596Snectar key = st->key; 1056113596Snectar keylen = st->keylen; 1057113596Snectar st->key = NULL; 1058113596Snectar rv = yp_next(st->domain, map, key, keylen, 1059113596Snectar &st->key, &st->keylen, &result, 1060113596Snectar &resultlen); 1061113596Snectar free(key); 106265532Snectar } 1063113596Snectar if (rv != 0) { 1064113596Snectar free(result); 1065113596Snectar free(st->key); 1066113596Snectar st->key = NULL; 1067113596Snectar if (rv == YPERR_NOMORE) 1068113596Snectar st->done = 1; 1069113596Snectar else 1070113596Snectar rv = NS_UNAVAIL; 1071113596Snectar goto fin; 1072113596Snectar } 107365532Snectar } else { 1074113596Snectar rv = yp_match(st->domain, map, buffer, strlen(buffer), 1075113596Snectar &result, &resultlen); 1076113596Snectar if (rv == YPERR_KEY) { 1077113596Snectar rv = NS_NOTFOUND; 1078113596Snectar continue; 1079113596Snectar } else if (rv != 0) { 1080113596Snectar free(result); 1081113596Snectar rv = NS_UNAVAIL; 1082113596Snectar continue; 1083113596Snectar } 108465532Snectar } 1085113596Snectar if (resultlen >= bufsize) 1086113596Snectar goto erange; 1087113596Snectar memcpy(buffer, result, resultlen); 1088113596Snectar buffer[resultlen] = '\0'; 1089113596Snectar free(result); 1090113596Snectar rv = __pw_match_entry(buffer, resultlen, how, name, uid); 1091113596Snectar if (rv == NS_SUCCESS) 1092113596Snectar rv = __pw_parse_entry(buffer, resultlen, pwd, master, 1093113596Snectar errnop); 1094113596Snectar } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 1095113596Snectarfin: 1096113596Snectar if (rv == NS_SUCCESS) { 1097113596Snectar if (strstr(pwd->pw_passwd, "##") != NULL) { 1098113596Snectar rv = nis_adjunct(st->domain, name, 1099113596Snectar &buffer[resultlen+1], bufsize-resultlen-1); 1100113596Snectar if (rv < 0) 1101113596Snectar goto erange; 1102113596Snectar else if (rv == 0) 1103113596Snectar pwd->pw_passwd = &buffer[resultlen+1]; 110465532Snectar } 1105113596Snectar pwd->pw_fields &= ~_PWF_SOURCE; 1106113596Snectar pwd->pw_fields |= _PWF_NIS; 1107113596Snectar if (retval != NULL) 1108113596Snectar *(struct passwd **)retval = pwd; 110915267Swpaul } 1110113596Snectar return (rv); 1111113596Snectarerange: 1112113596Snectar *errnop = ERANGE; 1113113596Snectar return (NS_RETURN); 1114113596Snectar} 1115113596Snectar#endif /* YP */ 111615267Swpaul 1117113596Snectar 111815267Swpaul/* 1119113596Snectar * compat backend 112015267Swpaul */ 1121113596Snectarstatic void 1122113596Snectarcompat_clear_template(struct passwd *template) 1123113596Snectar{ 112465532Snectar 1125113596Snectar free(template->pw_passwd); 1126113596Snectar free(template->pw_gecos); 1127113596Snectar free(template->pw_dir); 1128113596Snectar free(template->pw_shell); 1129113596Snectar memset(template, 0, sizeof(*template)); 1130113596Snectar} 1131113596Snectar 1132113596Snectar 113365532Snectarstatic int 1134113596Snectarcompat_set_template(struct passwd *src, struct passwd *template) 113515267Swpaul{ 113615267Swpaul 1137113596Snectar compat_clear_template(template); 1138113596Snectar#ifdef PW_OVERRIDE_PASSWD 1139113596Snectar if ((src->pw_fields & _PWF_PASSWD) && 1140113596Snectar (template->pw_passwd = strdup(src->pw_passwd)) == NULL) 1141113596Snectar goto enomem; 1142113596Snectar#endif 1143113596Snectar if (src->pw_fields & _PWF_UID) 1144113596Snectar template->pw_uid = src->pw_uid; 1145113596Snectar if (src->pw_fields & _PWF_GID) 1146113596Snectar template->pw_gid = src->pw_gid; 1147113596Snectar if ((src->pw_fields & _PWF_GECOS) && 1148113596Snectar (template->pw_gecos = strdup(src->pw_gecos)) == NULL) 1149113596Snectar goto enomem; 1150113596Snectar if ((src->pw_fields & _PWF_DIR) && 1151113596Snectar (template->pw_dir = strdup(src->pw_dir)) == NULL) 1152113596Snectar goto enomem; 1153113596Snectar if ((src->pw_fields & _PWF_SHELL) && 1154113596Snectar (template->pw_shell = strdup(src->pw_shell)) == NULL) 1155113596Snectar goto enomem; 1156113596Snectar template->pw_fields = src->pw_fields; 1157113596Snectar return (0); 1158113596Snectarenomem: 1159113596Snectar syslog(LOG_ERR, "getpwent memory allocation failure"); 1160113596Snectar return (-1); 1161113596Snectar} 116215267Swpaul 116315267Swpaul 1164113596Snectarstatic int 1165113596Snectarcompat_use_template(struct passwd *pwd, struct passwd *template, char *buffer, 1166113596Snectar size_t bufsize) 1167113596Snectar{ 1168113596Snectar struct passwd hold; 1169113596Snectar char *copy, *p, *q, *eob; 1170113596Snectar size_t n; 1171113596Snectar 1172113596Snectar /* We cannot know the layout of the password fields in `buffer', 1173113596Snectar * so we have to copy everything. 1174113596Snectar */ 1175113596Snectar if (template->pw_fields == 0) /* nothing to fill-in */ 1176113596Snectar return (0); 1177113596Snectar n = 0; 1178113596Snectar n += pwd->pw_name != NULL ? strlen(pwd->pw_name) + 1 : 0; 1179113596Snectar n += pwd->pw_passwd != NULL ? strlen(pwd->pw_passwd) + 1 : 0; 1180113596Snectar n += pwd->pw_class != NULL ? strlen(pwd->pw_class) + 1 : 0; 1181113596Snectar n += pwd->pw_gecos != NULL ? strlen(pwd->pw_gecos) + 1 : 0; 1182113596Snectar n += pwd->pw_dir != NULL ? strlen(pwd->pw_dir) + 1 : 0; 1183113596Snectar n += pwd->pw_shell != NULL ? strlen(pwd->pw_shell) + 1 : 0; 1184113596Snectar copy = malloc(n); 1185113596Snectar if (copy == NULL) { 1186113596Snectar syslog(LOG_ERR, "getpwent memory allocation failure"); 1187113596Snectar return (ENOMEM); 1188113596Snectar } 1189113596Snectar p = copy; 1190113596Snectar eob = ©[n]; 1191113596Snectar#define COPY(field) do { \ 1192113596Snectar if (pwd->field == NULL) \ 1193113596Snectar hold.field = NULL; \ 1194113596Snectar else { \ 1195113596Snectar hold.field = p; \ 1196113596Snectar p += strlcpy(p, pwd->field, eob-p) + 1; \ 1197113596Snectar } \ 1198113596Snectar} while (0) 1199113596Snectar COPY(pw_name); 1200113596Snectar COPY(pw_passwd); 1201113596Snectar COPY(pw_class); 1202113596Snectar COPY(pw_gecos); 1203113596Snectar COPY(pw_dir); 1204113596Snectar COPY(pw_shell); 1205113596Snectar#undef COPY 1206113596Snectar p = buffer; 1207113596Snectar eob = &buffer[bufsize]; 1208113596Snectar#define COPY(field, flag) do { \ 1209113596Snectar q = (template->pw_fields & flag) ? template->field : hold.field; \ 1210113596Snectar if (q == NULL) \ 1211113596Snectar pwd->field = NULL; \ 1212113596Snectar else { \ 1213113596Snectar pwd->field = p; \ 1214113596Snectar if ((n = strlcpy(p, q, eob-p)) >= eob-p) { \ 1215113596Snectar free(copy); \ 1216113596Snectar return (ERANGE); \ 1217113596Snectar } \ 1218113596Snectar p += n + 1; \ 1219113596Snectar } \ 1220113596Snectar} while (0) 1221113596Snectar COPY(pw_name, 0); 1222113596Snectar#ifdef PW_OVERRIDE_PASSWD 1223113596Snectar COPY(pw_passwd, _PWF_PASSWD); 1224113596Snectar#else 1225113596Snectar COPY(pw_passwd, 0); 1226113596Snectar#endif 1227113596Snectar COPY(pw_class, 0); 1228113596Snectar COPY(pw_gecos, _PWF_GECOS); 1229113596Snectar COPY(pw_dir, _PWF_DIR); 1230113596Snectar COPY(pw_shell, _PWF_SHELL); 1231113596Snectar#undef COPY 1232113596Snectar#define COPY(field, flag) do { \ 1233113596Snectar if (template->pw_fields & flag) \ 1234113596Snectar pwd->field = template->field; \ 1235113596Snectar} while (0) 1236113596Snectar COPY(pw_uid, _PWF_UID); 1237113596Snectar COPY(pw_gid, _PWF_GID); 1238113596Snectar#undef COPY 1239113596Snectar free(copy); 1240113596Snectar return (0); 124115267Swpaul} 124215267Swpaul 124365532Snectar 124465532Snectarstatic int 1245113596Snectarcompat_exclude(const char *name, DB **db) 124615267Swpaul{ 1247113596Snectar DBT key, data; 1248113596Snectar 1249113596Snectar if (*db == NULL && 1250113596Snectar (*db = dbopen(NULL, O_RDWR, 600, DB_HASH, 0)) == NULL) 1251113596Snectar return (errno); 1252113596Snectar key.size = strlen(name); 1253113596Snectar key.data = (char *)name; 1254113596Snectar data.size = 0; 1255113596Snectar data.data = NULL; 1256113596Snectar 1257113596Snectar if ((*db)->put(*db, &key, &data, 0) == -1) 1258113596Snectar return (errno); 1259113596Snectar return (0); 12607258Swpaul} 12617258Swpaul 126265532Snectar 126365532Snectarstatic int 1264113596Snectarcompat_is_excluded(const char *name, DB *db) 12657258Swpaul{ 1266113596Snectar DBT key, data; 12677258Swpaul 1268113596Snectar if (db == NULL) 1269113596Snectar return (0); 1270113596Snectar key.size = strlen(name); 1271113596Snectar key.data = (char *)name; 1272113596Snectar return (db->get(db, &key, &data, 0) == 0); 12737258Swpaul} 12747258Swpaul 127565532Snectar 127665532Snectarstatic int 1277113596Snectarcompat_redispatch(struct compat_state *st, enum nss_lookup_type how, 1278113596Snectar enum nss_lookup_type lookup_how, const char *name, const char *lookup_name, 1279113596Snectar uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, int *errnop) 128010521Swpaul{ 1281113596Snectar static const ns_src compatsrc[] = { 1282113596Snectar#ifdef YP 1283113596Snectar { NSSRC_NIS, NS_SUCCESS }, 128465532Snectar#endif 1285113596Snectar { NULL, 0 } 1286113596Snectar }; 1287113596Snectar ns_dtab dtab[] = { 1288113596Snectar#ifdef YP 1289113596Snectar { NSSRC_NIS, nis_passwd, NULL }, 1290113596Snectar#endif 1291113596Snectar#ifdef HESIOD 1292113596Snectar { NSSRC_DNS, dns_passwd, NULL }, 1293113596Snectar#endif 1294113596Snectar { NULL, NULL, NULL } 1295113596Snectar }; 1296113596Snectar void *discard; 1297113596Snectar int rv, e, i; 129810521Swpaul 1299113596Snectar for (i = 0; i < sizeof(dtab)/sizeof(dtab[0]) - 1; i++) 1300113596Snectar dtab[i].mdata = (void *)lookup_how; 1301113596Snectarmore: 1302113596Snectar switch (lookup_how) { 1303113596Snectar case nss_lt_all: 1304113596Snectar rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 1305113596Snectar "getpwent_r", compatsrc, pwd, buffer, bufsize, 1306113596Snectar errnop); 1307113596Snectar break; 1308113596Snectar case nss_lt_id: 1309113596Snectar rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 1310113596Snectar "getpwuid_r", compatsrc, uid, pwd, buffer, 1311113596Snectar bufsize, errnop); 1312113596Snectar break; 1313113596Snectar case nss_lt_name: 1314113596Snectar rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 1315113596Snectar "getpwnam_r", compatsrc, lookup_name, pwd, buffer, 1316113596Snectar bufsize, errnop); 1317113596Snectar break; 1318113596Snectar default: 1319113596Snectar return (NS_UNAVAIL); 1320113596Snectar } 1321113596Snectar if (rv != NS_SUCCESS) 1322113596Snectar return (rv); 1323113596Snectar if (compat_is_excluded(pwd->pw_name, st->exclude)) { 1324113596Snectar if (how == nss_lt_all) 1325113596Snectar goto more; 1326113596Snectar return (NS_NOTFOUND); 1327113596Snectar } 1328113596Snectar e = compat_use_template(pwd, &st->template, buffer, bufsize); 1329113596Snectar if (e != 0) { 1330113596Snectar *errnop = e; 1331113596Snectar if (e == ERANGE) 1332113596Snectar return (NS_RETURN); 1333113596Snectar else 1334113596Snectar return (NS_UNAVAIL); 1335113596Snectar } 1336113596Snectar switch (how) { 1337113596Snectar case nss_lt_name: 1338113596Snectar if (strcmp(name, pwd->pw_name) != 0) 1339113596Snectar return (NS_NOTFOUND); 1340113596Snectar break; 1341113596Snectar case nss_lt_id: 1342113596Snectar if (uid != pwd->pw_uid) 1343113596Snectar return (NS_NOTFOUND); 1344113596Snectar break; 1345113596Snectar default: 1346113596Snectar break; 1347113596Snectar } 1348113596Snectar return (NS_SUCCESS); 1349113596Snectar} 135065532Snectar 135165532Snectar 1352113596Snectarstatic void 1353113596Snectarcompat_endstate(void *p) 1354113596Snectar{ 1355113596Snectar struct compat_state *st; 135665532Snectar 1357113596Snectar if (p == NULL) 1358113596Snectar return; 1359113596Snectar st = (struct compat_state *)p; 1360113596Snectar if (st->db != NULL) 1361113596Snectar st->db->close(st->db); 1362113596Snectar if (st->exclude != NULL) 1363113596Snectar st->exclude->close(st->exclude); 1364113596Snectar compat_clear_template(&st->template); 1365113596Snectar free(p); 1366113596Snectar} 136765532Snectar 136865532Snectar 1369113596Snectarstatic int 1370113596Snectarcompat_setpwent(void *retval, void *mdata, va_list ap) 1371113596Snectar{ 1372113596Snectar struct compat_state *st; 1373113596Snectar int rv, stayopen; 137465532Snectar 1375113596Snectar rv = compat_getstate(&st); 1376113596Snectar if (rv != 0) 1377113596Snectar return (NS_UNAVAIL); 1378113596Snectar switch ((enum constants)mdata) { 1379113596Snectar case SETPWENT: 1380113596Snectar stayopen = va_arg(ap, int); 1381113596Snectar st->keynum = 0; 1382113596Snectar if (stayopen) 1383113596Snectar st->db = pwdbopen(&st->version); 1384113596Snectar st->stayopen = stayopen; 1385113596Snectar break; 1386113596Snectar case ENDPWENT: 1387113596Snectar if (st->db != NULL) { 1388113596Snectar (void)st->db->close(st->db); 1389113596Snectar st->db = NULL; 139065532Snectar } 1391113596Snectar break; 1392113596Snectar default: 1393113596Snectar break; 139410521Swpaul } 1395113596Snectar return (NS_UNAVAIL); 139610521Swpaul} 139720119Swpaul 139820119Swpaul 13999332Swpaulstatic int 1400113596Snectarcompat_passwd(void *retval, void *mdata, va_list ap) 14012917Swollman{ 1402113596Snectar char keybuf[MAXLOGNAME + 1]; 1403113596Snectar DBT key, entry; 1404113596Snectar struct compat_state *st; 1405113596Snectar enum nss_lookup_type how; 1406113596Snectar const char *name; 1407113596Snectar struct passwd *pwd; 1408113596Snectar char *buffer, *pw_name; 1409113596Snectar char *host, *user, *domain; 1410113596Snectar size_t bufsize; 1411113596Snectar uid_t uid; 1412113596Snectar uint32_t store; 1413113596Snectar int rv, stayopen, *errnop; 14142917Swollman 141565532Snectar name = NULL; 1416113596Snectar uid = (uid_t)-1; 1417113596Snectar how = (enum nss_lookup_type)mdata; 1418113596Snectar switch (how) { 1419113596Snectar case nss_lt_name: 1420113596Snectar name = va_arg(ap, const char *); 142165532Snectar break; 1422113596Snectar case nss_lt_id: 142365532Snectar uid = va_arg(ap, uid_t); 142465532Snectar break; 1425113596Snectar case nss_lt_all: 1426113596Snectar break; 142765532Snectar default: 1428113596Snectar rv = NS_NOTFOUND; 1429113596Snectar goto fin; 14302917Swollman } 1431113596Snectar pwd = va_arg(ap, struct passwd *); 1432113596Snectar buffer = va_arg(ap, char *); 1433113596Snectar bufsize = va_arg(ap, size_t); 1434113596Snectar errnop = va_arg(ap, int *); 1435113596Snectar *errnop = compat_getstate(&st); 1436113596Snectar if (*errnop != 0) 1437113596Snectar return (NS_UNAVAIL); 1438113596Snectar if (how == nss_lt_all && st->keynum < 0) { 1439113596Snectar rv = NS_NOTFOUND; 1440113596Snectar goto fin; 1441113596Snectar } 1442113596Snectar if (st->db == NULL && 1443113596Snectar (st->db = pwdbopen(&st->version)) == NULL) { 1444113596Snectar *errnop = errno; 1445113596Snectar rv = NS_UNAVAIL; 1446113596Snectar goto fin; 1447113596Snectar } 1448113596Snectar if (how == nss_lt_all) { 1449113596Snectar if (st->keynum < 0) { 1450113596Snectar rv = NS_NOTFOUND; 1451113596Snectar goto fin; 1452113596Snectar } 1453113596Snectar stayopen = 1; 1454113596Snectar } else { 1455113596Snectar st->keynum = 0; 1456113596Snectar stayopen = st->stayopen; 1457113596Snectar } 1458113596Snectardocompat: 1459113596Snectar rv = NS_NOTFOUND; 1460113596Snectar switch (st->compat) { 1461113596Snectar case COMPAT_MODE_ALL: 1462113596Snectar rv = compat_redispatch(st, how, how, name, name, uid, pwd, 1463113596Snectar buffer, bufsize, errnop); 1464113596Snectar if (rv != NS_SUCCESS) 1465113596Snectar st->compat = COMPAT_MODE_OFF; 1466113596Snectar break; 1467113596Snectar case COMPAT_MODE_NETGROUP: 1468113596Snectar /* XXX getnetgrent is not thread-safe. */ 1469113596Snectar do { 1470113596Snectar rv = getnetgrent(&host, &user, &domain); 1471113596Snectar if (rv == 0) { 1472113596Snectar endnetgrent(); 1473113596Snectar st->compat = COMPAT_MODE_OFF; 1474113596Snectar rv = NS_NOTFOUND; 1475113596Snectar continue; 1476113596Snectar } else if (user == NULL || user[0] == '\0') 1477113596Snectar continue; 1478113596Snectar rv = compat_redispatch(st, how, nss_lt_name, name, 1479113596Snectar user, uid, pwd, buffer, bufsize, errnop); 1480113596Snectar } while (st->compat == COMPAT_MODE_NETGROUP && 1481113596Snectar !(rv & NS_TERMINATE)); 1482113596Snectar break; 1483113596Snectar case COMPAT_MODE_NAME: 1484113596Snectar rv = compat_redispatch(st, how, nss_lt_name, name, st->name, 1485113596Snectar uid, pwd, buffer, bufsize, errnop); 1486113596Snectar free(st->name); 1487113596Snectar st->name = NULL; 1488113596Snectar st->compat = COMPAT_MODE_OFF; 1489113596Snectar break; 1490113596Snectar default: 1491113596Snectar break; 1492113596Snectar } 1493113596Snectar if (rv & NS_TERMINATE) 1494113596Snectar goto fin; 1495113596Snectar key.data = keybuf; 1496113596Snectar rv = NS_NOTFOUND; 1497113596Snectar while (st->keynum >= 0) { 1498113596Snectar st->keynum++; 1499113596Snectar if (st->version < _PWD_CURRENT_VERSION) { 1500113596Snectar memcpy(&keybuf[1], &st->keynum, sizeof(st->keynum)); 1501113596Snectar key.size = sizeof(st->keynum) + 1; 1502113596Snectar } else { 1503113596Snectar store = htonl(st->keynum); 1504113596Snectar memcpy(&keybuf[1], &store, sizeof(store)); 1505113596Snectar key.size = sizeof(store) + 1; 1506113596Snectar } 1507113666Snectar keybuf[0] = _PW_VERSIONED(_PW_KEYBYNUM, st->version); 1508113596Snectar rv = st->db->get(st->db, &key, &entry, 0); 1509113596Snectar if (rv < 0 || rv > 1) { /* should never return > 1 */ 1510113596Snectar *errnop = errno; 1511113596Snectar rv = NS_UNAVAIL; 1512113596Snectar goto fin; 1513113596Snectar } else if (rv == 1) { 1514113596Snectar st->keynum = -1; 1515113596Snectar rv = NS_NOTFOUND; 1516113596Snectar goto fin; 1517113596Snectar } 1518113596Snectar pw_name = (char *)entry.data; 1519113596Snectar switch (pw_name[0]) { 152065532Snectar case '+': 1521113596Snectar switch (pw_name[1]) { 152265532Snectar case '\0': 1523113596Snectar st->compat = COMPAT_MODE_ALL; 152465532Snectar break; 152565532Snectar case '@': 1526113596Snectar setnetgrent(&pw_name[2]); 1527113596Snectar st->compat = COMPAT_MODE_NETGROUP; 152865532Snectar break; 152965532Snectar default: 1530113596Snectar st->name = strdup(&pw_name[1]); 1531113596Snectar if (st->name == NULL) { 1532113596Snectar syslog(LOG_ERR, 1533113596Snectar "getpwent memory allocation failure"); 1534113596Snectar *errnop = ENOMEM; 1535113596Snectar rv = NS_UNAVAIL; 1536113596Snectar break; 1537113596Snectar } 1538113596Snectar st->compat = COMPAT_MODE_NAME; 153965532Snectar } 1540113596Snectar if (entry.size > bufsize) { 1541113596Snectar *errnop = ERANGE; 1542113596Snectar rv = NS_RETURN; 1543113596Snectar goto fin; 154465532Snectar } 1545113596Snectar memcpy(buffer, entry.data, entry.size); 1546113596Snectar rv = pwdb_versions[st->version].parse(buffer, 1547113596Snectar entry.size, pwd, errnop); 1548113596Snectar if (rv != NS_SUCCESS) 1549113596Snectar ; 1550113596Snectar else if (compat_set_template(pwd, &st->template) < 0) { 1551113596Snectar *errnop = ENOMEM; 1552113596Snectar rv = NS_UNAVAIL; 1553113596Snectar goto fin; 1554113596Snectar } 1555113596Snectar goto docompat; 155665532Snectar case '-': 1557113596Snectar switch (pw_name[1]) { 155865532Snectar case '\0': 1559113596Snectar /* XXX Maybe syslog warning */ 1560113596Snectar continue; 156165532Snectar case '@': 1562113596Snectar setnetgrent(&pw_name[2]); 1563113596Snectar while (getnetgrent(&host, &user, &domain) != 1564113596Snectar NULL) { 1565113596Snectar if (user != NULL && user[0] != '\0') 1566113596Snectar compat_exclude(user, 1567113596Snectar &st->exclude); 156865532Snectar } 156965532Snectar endnetgrent(); 1570113596Snectar continue; 157165532Snectar default: 1572113596Snectar compat_exclude(&pw_name[1], &st->exclude); 1573113596Snectar continue; 157465532Snectar } 157565532Snectar break; 157696186Sdes default: 1577113596Snectar break; 15786190Swpaul } 1579113596Snectar if (compat_is_excluded((char *)entry.data, st->exclude)) 1580113596Snectar continue; 1581113596Snectar rv = pwdb_versions[st->version].match(entry.data, entry.size, 1582113596Snectar how, name, uid); 1583113596Snectar if (rv == NS_RETURN) 158465532Snectar break; 1585113596Snectar else if (rv != NS_SUCCESS) 1586113596Snectar continue; 1587113596Snectar if (entry.size > bufsize) { 1588113596Snectar *errnop = ERANGE; 1589113596Snectar rv = NS_RETURN; 1590113596Snectar break; 159165532Snectar } 1592113596Snectar memcpy(buffer, entry.data, entry.size); 1593113596Snectar rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd, 1594113596Snectar errnop); 1595113596Snectar if (rv & NS_TERMINATE) 1596113596Snectar break; 15972917Swollman } 1598113596Snectarfin: 1599113596Snectar if (!stayopen && st->db != NULL) { 1600113596Snectar (void)st->db->close(st->db); 1601113596Snectar st->db = NULL; 16026076Swpaul } 1603113596Snectar if (rv == NS_SUCCESS && retval != NULL) 1604113596Snectar *(struct passwd **)retval = pwd; 1605113596Snectar return (rv); 160665532Snectar} 16076076Swpaul 16089332Swpaul 1609113596Snectar/* 1610113596Snectar * common passwd line matching and parsing 1611113596Snectar */ 161265532Snectarint 1613113596Snectar__pw_match_entry(const char *entry, size_t entrysize, enum nss_lookup_type how, 1614113596Snectar const char *name, uid_t uid) 16152917Swollman{ 1616113596Snectar const char *p, *eom; 1617113596Snectar char *q; 1618113596Snectar size_t len; 1619113596Snectar unsigned long m; 16202917Swollman 1621113596Snectar eom = entry + entrysize; 1622113596Snectar for (p = entry; p < eom; p++) 1623113596Snectar if (*p == ':') 1624113596Snectar break; 1625113596Snectar if (*p != ':') 1626113596Snectar return (NS_NOTFOUND); 1627113596Snectar if (how == nss_lt_all) 1628113596Snectar return (NS_SUCCESS); 1629113596Snectar if (how == nss_lt_name) { 1630113596Snectar len = strlen(name); 1631113596Snectar if (len == (p - entry) && memcmp(name, entry, len) == 0) 1632113596Snectar return (NS_SUCCESS); 1633113596Snectar else 1634113596Snectar return (NS_NOTFOUND); 163545066Sdes } 1636113596Snectar for (p++; p < eom; p++) 1637113596Snectar if (*p == ':') 1638113596Snectar break; 1639113596Snectar if (*p != ':') 1640113596Snectar return (NS_NOTFOUND); 1641113596Snectar m = strtoul(++p, &q, 10); 1642113596Snectar if (q[0] != ':' || (uid_t)m != uid) 1643113596Snectar return (NS_NOTFOUND); 1644113596Snectar else 1645113596Snectar return (NS_SUCCESS); 164665532Snectar} 16472917Swollman 164815267Swpaul 1649113596Snectar/* XXX buffer must be NUL-terminated. errnop is not set correctly. */ 1650113596Snectarint 1651113596Snectar__pw_parse_entry(char *buffer, size_t bufsize __unused, struct passwd *pwd, 1652113596Snectar int master, int *errnop __unused) 16532917Swollman{ 16542917Swollman 1655113596Snectar memset(pwd, 0, sizeof(*pwd)); 1656113596Snectar if (__pw_scan(buffer, pwd, master ? _PWSCAN_MASTER : 0) == 0) 1657113596Snectar return (NS_NOTFOUND); 1658113596Snectar else 1659113596Snectar return (NS_SUCCESS); 16602917Swollman} 1661