getpwent.c revision 128537
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 128537 2004-04-21 21:15:08Z jon $"); 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 94113694Snectarstatic void pwd_init(struct passwd *); 95113672Snectar 96113596Snectarunion key { 97113596Snectar const char *name; 98113596Snectar uid_t uid; 99113596Snectar}; 100113596Snectar 101113596Snectarstatic struct passwd *getpw(int (*fn)(union key, struct passwd *, char *, 102113596Snectar size_t, struct passwd **), union key); 103113596Snectarstatic int wrap_getpwnam_r(union key, struct passwd *, char *, 104113596Snectar size_t, struct passwd **); 105113596Snectarstatic int wrap_getpwuid_r(union key, struct passwd *, char *, size_t, 106113596Snectar struct passwd **); 107113596Snectarstatic int wrap_getpwent_r(union key, struct passwd *, char *, size_t, 108113596Snectar struct passwd **); 109113596Snectar 110113596Snectarstatic int pwdb_match_entry_v3(char *, size_t, enum nss_lookup_type, 111113596Snectar const char *, uid_t); 112113596Snectarstatic int pwdb_parse_entry_v3(char *, size_t, struct passwd *, int *); 113113596Snectarstatic int pwdb_match_entry_v4(char *, size_t, enum nss_lookup_type, 114113596Snectar const char *, uid_t); 115113596Snectarstatic int pwdb_parse_entry_v4(char *, size_t, struct passwd *, int *); 116113596Snectar 117113596Snectar 118113596Snectarstruct { 119113596Snectar int (*match)(char *, size_t, enum nss_lookup_type, const char *, 120113596Snectar uid_t); 121113596Snectar int (*parse)(char *, size_t, struct passwd *, int *); 122113596Snectar} pwdb_versions[] = { 123113596Snectar { NULL, NULL }, /* version 0 */ 124113596Snectar { NULL, NULL }, /* version 1 */ 125113596Snectar { NULL, NULL }, /* version 2 */ 126113596Snectar { pwdb_match_entry_v3, pwdb_parse_entry_v3 }, /* version 3 */ 127113596Snectar { pwdb_match_entry_v4, pwdb_parse_entry_v4 }, /* version 4 */ 128113596Snectar}; 129113596Snectar 130113596Snectar 131113596Snectarstruct files_state { 132113596Snectar DB *db; 133113596Snectar pwkeynum keynum; 134113596Snectar int stayopen; 135113596Snectar int version; 136113596Snectar}; 137113596Snectarstatic void files_endstate(void *); 138113596SnectarNSS_TLS_HANDLING(files); 139113596Snectarstatic DB *pwdbopen(int *); 140113596Snectarstatic void files_endstate(void *); 141113596Snectarstatic int files_setpwent(void *, void *, va_list); 142113596Snectarstatic int files_passwd(void *, void *, va_list); 143113596Snectar 144113596Snectar 14565532Snectar#ifdef HESIOD 146113596Snectarstruct dns_state { 147113596Snectar long counter; 148113596Snectar}; 149113596Snectarstatic void dns_endstate(void *); 150113596SnectarNSS_TLS_HANDLING(dns); 151113596Snectarstatic int dns_setpwent(void *, void *, va_list); 152113596Snectarstatic int dns_passwd(void *, void *, va_list); 15311436Swpaul#endif 1542917Swollman 15565532Snectar 156113596Snectar#ifdef YP 157113596Snectarstruct nis_state { 158113596Snectar char domain[MAXHOSTNAMELEN]; 159113596Snectar int done; 160113596Snectar char *key; 161113596Snectar int keylen; 162113596Snectar}; 163113596Snectarstatic void nis_endstate(void *); 164113596SnectarNSS_TLS_HANDLING(nis); 165113596Snectarstatic int nis_setpwent(void *, void *, va_list); 166113596Snectarstatic int nis_passwd(void *, void *, va_list); 167113596Snectarstatic int nis_map(char *, enum nss_lookup_type, char *, size_t, int *); 168113596Snectarstatic int nis_adjunct(char *, const char *, char *, size_t); 169113596Snectar#endif 17065532Snectar 17165532Snectar 172113596Snectarstruct compat_state { 173113596Snectar DB *db; 174113596Snectar pwkeynum keynum; 175113596Snectar int stayopen; 176113596Snectar int version; 177113596Snectar DB *exclude; 178113596Snectar struct passwd template; 179113596Snectar char *name; 180113596Snectar enum _compat { 181113596Snectar COMPAT_MODE_OFF = 0, 182113596Snectar COMPAT_MODE_ALL, 183113596Snectar COMPAT_MODE_NAME, 184113596Snectar COMPAT_MODE_NETGROUP 185113596Snectar } compat; 186113596Snectar}; 187113596Snectarstatic void compat_endstate(void *); 188113596SnectarNSS_TLS_HANDLING(compat); 189113596Snectarstatic int compat_setpwent(void *, void *, va_list); 190113596Snectarstatic int compat_passwd(void *, void *, va_list); 191113596Snectarstatic void compat_clear_template(struct passwd *); 192113596Snectarstatic int compat_set_template(struct passwd *, struct passwd *); 193113596Snectarstatic int compat_use_template(struct passwd *, struct passwd *, char *, 194113596Snectar size_t); 195113596Snectarstatic int compat_redispatch(struct compat_state *, enum nss_lookup_type, 196113596Snectar enum nss_lookup_type, const char *, const char *, uid_t, 197113596Snectar struct passwd *, char *, size_t, int *); 198113596Snectarvoid 199113596Snectarsetpwent(void) 2001573Srgrimes{ 201113596Snectar static const ns_dtab dtab[] = { 202113596Snectar { NSSRC_FILES, files_setpwent, (void *)SETPWENT }, 203113596Snectar#ifdef HESIOD 204113596Snectar { NSSRC_DNS, dns_setpwent, (void *)SETPWENT }, 205113596Snectar#endif 206113596Snectar#ifdef YP 207113596Snectar { NSSRC_NIS, nis_setpwent, (void *)SETPWENT }, 208113596Snectar#endif 209113596Snectar { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT }, 210113596Snectar { NULL, NULL, NULL } 211113596Snectar }; 212113596Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 0); 213113596Snectar} 2141573Srgrimes 21510521Swpaul 216113596Snectarint 217113596Snectarsetpassent(int stayopen) 218113596Snectar{ 219113596Snectar static const ns_dtab dtab[] = { 220113596Snectar { NSSRC_FILES, files_setpwent, (void *)SETPWENT }, 221113596Snectar#ifdef HESIOD 222113596Snectar { NSSRC_DNS, dns_setpwent, (void *)SETPWENT }, 223113596Snectar#endif 224113596Snectar#ifdef YP 225113596Snectar { NSSRC_NIS, nis_setpwent, (void *)SETPWENT }, 226113596Snectar#endif 227113596Snectar { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT }, 228113596Snectar { NULL, NULL, NULL } 229113596Snectar }; 230113596Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 231113596Snectar stayopen); 232113596Snectar return (1); 233113596Snectar} 23465532Snectar 23565532Snectar 236113596Snectarvoid 237113596Snectarendpwent(void) 238113596Snectar{ 239113596Snectar static const ns_dtab dtab[] = { 240113596Snectar { NSSRC_FILES, files_setpwent, (void *)ENDPWENT }, 241113596Snectar#ifdef HESIOD 242113596Snectar { NSSRC_DNS, dns_setpwent, (void *)ENDPWENT }, 243113596Snectar#endif 244113596Snectar#ifdef YP 245113596Snectar { NSSRC_NIS, nis_setpwent, (void *)ENDPWENT }, 246113596Snectar#endif 247113596Snectar { NSSRC_COMPAT, compat_setpwent, (void *)ENDPWENT }, 248113596Snectar { NULL, NULL, NULL } 249113596Snectar }; 250113596Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "endpwent", defaultsrc); 2511573Srgrimes} 2521573Srgrimes 253113596Snectar 254113596Snectarint 255113596Snectargetpwent_r(struct passwd *pwd, char *buffer, size_t bufsize, 256113596Snectar struct passwd **result) 2571573Srgrimes{ 258113596Snectar static const ns_dtab dtab[] = { 259113596Snectar { NSSRC_FILES, files_passwd, (void *)nss_lt_all }, 260113596Snectar#ifdef HESIOD 261113596Snectar { NSSRC_DNS, dns_passwd, (void *)nss_lt_all }, 262113596Snectar#endif 263113596Snectar#ifdef YP 264113596Snectar { NSSRC_NIS, nis_passwd, (void *)nss_lt_all }, 265113596Snectar#endif 266113596Snectar { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_all }, 267113596Snectar { NULL, NULL, NULL } 268113596Snectar }; 269113596Snectar int rv, ret_errno; 2701573Srgrimes 271113694Snectar pwd_init(pwd); 272113694Snectar ret_errno = 0; 273113596Snectar *result = NULL; 274113596Snectar rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwent_r", defaultsrc, 275113596Snectar pwd, buffer, bufsize, &ret_errno); 276113596Snectar if (rv == NS_SUCCESS) 277113596Snectar return (0); 278113596Snectar else 279113596Snectar return (ret_errno); 280113596Snectar} 2811573Srgrimes 2821573Srgrimes 283113596Snectarint 284113596Snectargetpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, 285113596Snectar struct passwd **result) 286113596Snectar{ 287113596Snectar static const ns_dtab dtab[] = { 288113596Snectar { NSSRC_FILES, files_passwd, (void *)nss_lt_name }, 289113596Snectar#ifdef HESIOD 290113596Snectar { NSSRC_DNS, dns_passwd, (void *)nss_lt_name }, 291113596Snectar#endif 292113596Snectar#ifdef YP 293113596Snectar { NSSRC_NIS, nis_passwd, (void *)nss_lt_name }, 294113596Snectar#endif 295113596Snectar { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_name }, 296113596Snectar { NULL, NULL, NULL } 297113596Snectar }; 298113596Snectar int rv, ret_errno; 299113596Snectar 300113694Snectar pwd_init(pwd); 301113694Snectar ret_errno = 0; 302113596Snectar *result = NULL; 303113596Snectar rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwnam_r", defaultsrc, 304113596Snectar name, pwd, buffer, bufsize, &ret_errno); 305113596Snectar if (rv == NS_SUCCESS) 306113596Snectar return (0); 307113596Snectar else 308113596Snectar return (ret_errno); 30965532Snectar} 3105714Swollman 311113596Snectar 312113596Snectarint 313113596Snectargetpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, 314113596Snectar struct passwd **result) 31565532Snectar{ 316113596Snectar static const ns_dtab dtab[] = { 317113596Snectar { NSSRC_FILES, files_passwd, (void *)nss_lt_id }, 318113596Snectar#ifdef HESIOD 319113596Snectar { NSSRC_DNS, dns_passwd, (void *)nss_lt_id }, 320113596Snectar#endif 321113596Snectar#ifdef YP 322113596Snectar { NSSRC_NIS, nis_passwd, (void *)nss_lt_id }, 323113596Snectar#endif 324113596Snectar { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_id }, 325113596Snectar { NULL, NULL, NULL } 326113596Snectar }; 327113596Snectar int rv, ret_errno; 32865532Snectar 329113694Snectar pwd_init(pwd); 330113694Snectar ret_errno = 0; 331113596Snectar *result = NULL; 332113596Snectar rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwuid_r", defaultsrc, 333113596Snectar uid, pwd, buffer, bufsize, &ret_errno); 334113596Snectar if (rv == NS_SUCCESS) 335113596Snectar return (0); 336113596Snectar else 337113596Snectar return (ret_errno); 338113596Snectar} 33965532Snectar 34065532Snectar 341113694Snectarstatic void 342113694Snectarpwd_init(struct passwd *pwd) 343113672Snectar{ 344113694Snectar static char nul[] = ""; 345113672Snectar 346113672Snectar memset(pwd, 0, sizeof(*pwd)); 347113672Snectar pwd->pw_uid = (uid_t)-1; /* Considered least likely to lead to */ 348113672Snectar pwd->pw_gid = (gid_t)-1; /* a security issue. */ 349113694Snectar pwd->pw_name = nul; 350113694Snectar pwd->pw_passwd = nul; 351113694Snectar pwd->pw_class = nul; 352113694Snectar pwd->pw_gecos = nul; 353113694Snectar pwd->pw_dir = nul; 354113694Snectar pwd->pw_shell = nul; 355113672Snectar} 356113672Snectar 357113672Snectar 358113596Snectarstatic struct passwd pwd; 359113596Snectarstatic char *pwd_storage; 360113596Snectarstatic size_t pwd_storage_size; 36168577Snectar 36265532Snectar 363113596Snectarstatic struct passwd * 364113596Snectargetpw(int (*fn)(union key, struct passwd *, char *, size_t, struct passwd **), 365113596Snectar union key key) 366113596Snectar{ 367113596Snectar int rv; 368113596Snectar struct passwd *res; 36965532Snectar 370113596Snectar if (pwd_storage == NULL) { 371113596Snectar pwd_storage = malloc(PWD_STORAGE_INITIAL); 372113596Snectar if (pwd_storage == NULL) 373113596Snectar return (NULL); 374113596Snectar pwd_storage_size = PWD_STORAGE_INITIAL; 37568577Snectar } 376113596Snectar do { 377113596Snectar rv = fn(key, &pwd, pwd_storage, pwd_storage_size, &res); 378113596Snectar if (res == NULL && rv == ERANGE) { 379113596Snectar free(pwd_storage); 380113596Snectar if ((pwd_storage_size << 1) > PWD_STORAGE_MAX) { 381113596Snectar pwd_storage = NULL; 382113596Snectar return (NULL); 383113596Snectar } 384113596Snectar pwd_storage_size <<= 1; 385113596Snectar pwd_storage = malloc(pwd_storage_size); 386113596Snectar if (pwd_storage == NULL) 387113596Snectar return (NULL); 388113596Snectar } 389113596Snectar } while (res == NULL && rv == ERANGE); 390113596Snectar return (res); 391113596Snectar} 39265532Snectar 393113596Snectar 394113596Snectarstatic int 395113596Snectarwrap_getpwnam_r(union key key, struct passwd *pwd, char *buffer, 396113596Snectar size_t bufsize, struct passwd **res) 397113596Snectar{ 398113596Snectar return (getpwnam_r(key.name, pwd, buffer, bufsize, res)); 3991573Srgrimes} 4001573Srgrimes 401113596Snectar 40265532Snectarstatic int 403113596Snectarwrap_getpwuid_r(union key key, struct passwd *pwd, char *buffer, 404113596Snectar size_t bufsize, struct passwd **res) 4051573Srgrimes{ 406113596Snectar return (getpwuid_r(key.uid, pwd, buffer, bufsize, res)); 407113596Snectar} 4081573Srgrimes 4091573Srgrimes 410113596Snectarstatic int 411113596Snectarwrap_getpwent_r(union key key __unused, struct passwd *pwd, char *buffer, 412113596Snectar size_t bufsize, struct passwd **res) 413113596Snectar{ 414113596Snectar return (getpwent_r(pwd, buffer, bufsize, res)); 415113596Snectar} 4161573Srgrimes 41765532Snectar 418113596Snectarstruct passwd * 419113596Snectargetpwnam(const char *name) 420113596Snectar{ 421113596Snectar union key key; 42265532Snectar 423113596Snectar key.name = name; 424113596Snectar return (getpw(wrap_getpwnam_r, key)); 425113596Snectar} 4267258Swpaul 4271573Srgrimes 428113596Snectarstruct passwd * 429113596Snectargetpwuid(uid_t uid) 430113596Snectar{ 431113596Snectar union key key; 432113596Snectar 433113596Snectar key.uid = uid; 434113596Snectar return (getpw(wrap_getpwuid_r, key)); 4351573Srgrimes} 4361573Srgrimes 437113596Snectar 438113596Snectarstruct passwd * 439113596Snectargetpwent(void) 440113596Snectar{ 441113596Snectar union key key; 442113596Snectar 443113596Snectar key.uid = 0; /* not used */ 444113596Snectar return (getpw(wrap_getpwent_r, key)); 445113596Snectar} 446113596Snectar 447113596Snectar 44865532Snectar/* 449113596Snectar * files backend 45065532Snectar */ 451113596Snectarstatic DB * 452113596Snectarpwdbopen(int *version) 4531573Srgrimes{ 454113596Snectar DB *res; 455113596Snectar DBT key, entry; 456113596Snectar int rv; 4571573Srgrimes 458113596Snectar if (geteuid() != 0 || 459113596Snectar (res = dbopen(_PATH_SMP_DB, O_RDONLY, 0, DB_HASH, NULL)) == NULL) 460113596Snectar res = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL); 461113596Snectar if (res == NULL) 462113596Snectar return (NULL); 463113596Snectar key.data = _PWD_VERSION_KEY; 464113596Snectar key.size = strlen(_PWD_VERSION_KEY); 465113596Snectar rv = res->get(res, &key, &entry, 0); 466113596Snectar if (rv == 0) 467113596Snectar *version = *(unsigned char *)entry.data; 468113596Snectar else 469113596Snectar *version = 3; 470113596Snectar if (*version < 3 || 471113596Snectar *version >= sizeof(pwdb_versions)/sizeof(pwdb_versions[0])) { 472113596Snectar syslog(LOG_CRIT, "Unsupported password database version %d", 473113596Snectar *version); 474113596Snectar res->close(res); 475113596Snectar res = NULL; 47615267Swpaul } 477113596Snectar return (res); 478113596Snectar} 47965532Snectar 48065532Snectar 481113596Snectarstatic void 482113596Snectarfiles_endstate(void *p) 483113596Snectar{ 484113596Snectar DB *db; 485113596Snectar 486113596Snectar if (p == NULL) 487113596Snectar return; 488113596Snectar db = ((struct files_state *)p)->db; 489113596Snectar if (db != NULL) 490113596Snectar db->close(db); 491113596Snectar free(p); 492113596Snectar} 493113596Snectar 494113596Snectar 495113596Snectarstatic int 496113596Snectarfiles_setpwent(void *retval, void *mdata, va_list ap) 497113596Snectar{ 498113596Snectar struct files_state *st; 499113596Snectar int rv, stayopen; 500113596Snectar 501113596Snectar rv = files_getstate(&st); 502113596Snectar if (rv != 0) 503113596Snectar return (NS_UNAVAIL); 504113596Snectar switch ((enum constants)mdata) { 505113596Snectar case SETPWENT: 506113596Snectar stayopen = va_arg(ap, int); 507113596Snectar st->keynum = 0; 508113596Snectar if (stayopen) 509113596Snectar st->db = pwdbopen(&st->version); 510113596Snectar st->stayopen = stayopen; 511113596Snectar break; 512113596Snectar case ENDPWENT: 513113596Snectar if (st->db != NULL) { 514113596Snectar (void)st->db->close(st->db); 515113596Snectar st->db = NULL; 51665532Snectar } 517113596Snectar break; 518113596Snectar default: 519113596Snectar break; 52015267Swpaul } 521113596Snectar return (NS_UNAVAIL); 5221573Srgrimes} 5231573Srgrimes 52465532Snectar 52517141Sjkhstatic int 526113596Snectarfiles_passwd(void *retval, void *mdata, va_list ap) 5271573Srgrimes{ 528113596Snectar char keybuf[MAXLOGNAME + 1]; 529113596Snectar DBT key, entry; 530113596Snectar struct files_state *st; 531113596Snectar enum nss_lookup_type how; 532113596Snectar const char *name; 533113596Snectar struct passwd *pwd; 534113596Snectar char *buffer; 535113596Snectar size_t bufsize, namesize; 536113596Snectar uid_t uid; 537113596Snectar uint32_t store; 538113596Snectar int rv, stayopen, *errnop; 5391573Srgrimes 540113596Snectar name = NULL; 541113596Snectar uid = (uid_t)-1; 542113596Snectar how = (enum nss_lookup_type)mdata; 543113596Snectar switch (how) { 544113596Snectar case nss_lt_name: 54565532Snectar name = va_arg(ap, const char *); 546113596Snectar keybuf[0] = _PW_KEYBYNAME; 54765532Snectar break; 548113596Snectar case nss_lt_id: 54965532Snectar uid = va_arg(ap, uid_t); 550113596Snectar keybuf[0] = _PW_KEYBYUID; 55165532Snectar break; 552113596Snectar case nss_lt_all: 553113596Snectar keybuf[0] = _PW_KEYBYNUM; 554113596Snectar break; 55565532Snectar default: 556113596Snectar rv = NS_NOTFOUND; 557113596Snectar goto fin; 55865532Snectar } 559113596Snectar pwd = va_arg(ap, struct passwd *); 560113596Snectar buffer = va_arg(ap, char *); 561113596Snectar bufsize = va_arg(ap, size_t); 562113596Snectar errnop = va_arg(ap, int *); 563113596Snectar *errnop = files_getstate(&st); 564113596Snectar if (*errnop != 0) 565113596Snectar return (NS_UNAVAIL); 566113596Snectar if (how == nss_lt_all && st->keynum < 0) { 567113596Snectar rv = NS_NOTFOUND; 568113596Snectar goto fin; 56965532Snectar } 570113596Snectar if (st->db == NULL && 571113596Snectar (st->db = pwdbopen(&st->version)) == NULL) { 572113596Snectar *errnop = errno; 573113596Snectar rv = NS_UNAVAIL; 574113596Snectar goto fin; 57594688Sdes } 576113596Snectar if (how == nss_lt_all) 577113596Snectar stayopen = 1; 578113596Snectar else 579113596Snectar stayopen = st->stayopen; 580113596Snectar key.data = keybuf; 581113596Snectar do { 582113596Snectar switch (how) { 583113596Snectar case nss_lt_name: 584113596Snectar /* MAXLOGNAME includes NUL byte, but we do not 585113596Snectar * include the NUL byte in the key. 586113596Snectar */ 587114443Snectar namesize = strlcpy(&keybuf[1], name, sizeof(keybuf)-1); 588113596Snectar if (namesize >= sizeof(keybuf)-1) { 589113596Snectar *errnop = EINVAL; 590113596Snectar rv = NS_NOTFOUND; 591113596Snectar goto fin; 592113596Snectar } 593113596Snectar key.size = namesize + 1; 594113596Snectar break; 595113596Snectar case nss_lt_id: 596113596Snectar if (st->version < _PWD_CURRENT_VERSION) { 597113596Snectar memcpy(&keybuf[1], &uid, sizeof(uid)); 598113596Snectar key.size = sizeof(uid) + 1; 599113596Snectar } else { 600113596Snectar store = htonl(uid); 601113596Snectar memcpy(&keybuf[1], &store, sizeof(store)); 602113596Snectar key.size = sizeof(store) + 1; 603113596Snectar } 604113596Snectar break; 605113596Snectar case nss_lt_all: 606113596Snectar st->keynum++; 607113596Snectar if (st->version < _PWD_CURRENT_VERSION) { 608113596Snectar memcpy(&keybuf[1], &st->keynum, 609113596Snectar sizeof(st->keynum)); 610113596Snectar key.size = sizeof(st->keynum) + 1; 611113596Snectar } else { 612113596Snectar store = htonl(st->keynum); 613113596Snectar memcpy(&keybuf[1], &store, sizeof(store)); 614113596Snectar key.size = sizeof(store) + 1; 615113596Snectar } 616113596Snectar break; 617113596Snectar } 618113666Snectar keybuf[0] = _PW_VERSIONED(keybuf[0], st->version); 619113596Snectar rv = st->db->get(st->db, &key, &entry, 0); 620113596Snectar if (rv < 0 || rv > 1) { /* should never return > 1 */ 621113596Snectar *errnop = errno; 622113596Snectar rv = NS_UNAVAIL; 623113596Snectar goto fin; 624113596Snectar } else if (rv == 1) { 625113596Snectar if (how == nss_lt_all) 626113596Snectar st->keynum = -1; 627113596Snectar rv = NS_NOTFOUND; 628113596Snectar goto fin; 629113596Snectar } 630113596Snectar rv = pwdb_versions[st->version].match(entry.data, entry.size, 631113596Snectar how, name, uid); 632113596Snectar if (rv != NS_SUCCESS) 633113596Snectar continue; 634113596Snectar if (entry.size > bufsize) { 635113596Snectar *errnop = ERANGE; 636113596Snectar rv = NS_RETURN; 637113596Snectar break; 638113596Snectar } 639113596Snectar memcpy(buffer, entry.data, entry.size); 640113596Snectar rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd, 641113596Snectar errnop); 642113596Snectar } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 643113596Snectarfin: 644113596Snectar if (!stayopen && st->db != NULL) { 645113596Snectar (void)st->db->close(st->db); 646113596Snectar st->db = NULL; 647113596Snectar } 648113670Snectar if (rv == NS_SUCCESS) { 649113670Snectar pwd->pw_fields &= ~_PWF_SOURCE; 650113670Snectar pwd->pw_fields |= _PWF_FILES; 651113670Snectar if (retval != NULL) 652113670Snectar *(struct passwd **)retval = pwd; 653113670Snectar } 654113596Snectar return (rv); 6551573Srgrimes} 6561573Srgrimes 657113596Snectar 658113596Snectarstatic int 659124432Snectarpwdb_match_entry_v3(char *entry, size_t entrysize, enum nss_lookup_type how, 660113596Snectar const char *name, uid_t uid) 661113596Snectar{ 662113596Snectar const char *p, *eom; 663113596Snectar uid_t uid2; 664113596Snectar 665113596Snectar eom = &entry[entrysize]; 666113596Snectar for (p = entry; p < eom; p++) 667113596Snectar if (*p == '\0') 668113596Snectar break; 669113596Snectar if (*p != '\0') 670113596Snectar return (NS_NOTFOUND); 671113596Snectar if (how == nss_lt_all) 672113596Snectar return (NS_SUCCESS); 673124432Snectar if (how == nss_lt_name) 674113596Snectar return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND); 675113596Snectar for (p++; p < eom; p++) 676113596Snectar if (*p == '\0') 677113596Snectar break; 678113596Snectar if (*p != '\0' || (++p) + sizeof(uid) >= eom) 679113596Snectar return (NS_NOTFOUND); 680113596Snectar memcpy(&uid2, p, sizeof(uid2)); 681113596Snectar return (uid == uid2 ? NS_SUCCESS : NS_NOTFOUND); 682113596Snectar} 683113596Snectar 684113596Snectar 685113596Snectarstatic int 686113596Snectarpwdb_parse_entry_v3(char *buffer, size_t bufsize, struct passwd *pwd, 687113596Snectar int *errnop) 688113596Snectar{ 689113596Snectar char *p, *eom; 690113596Snectar int32_t pw_change, pw_expire; 691113596Snectar 692113596Snectar /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 693113596Snectar p = buffer; 694113596Snectar eom = &buffer[bufsize]; 695113596Snectar#define STRING(field) do { \ 696113596Snectar (field) = p; \ 697113596Snectar while (p < eom && *p != '\0') \ 698113596Snectar p++; \ 699113596Snectar if (p >= eom) \ 700113596Snectar return (NS_NOTFOUND); \ 701113596Snectar p++; \ 702113596Snectar } while (0) 703113596Snectar#define SCALAR(field) do { \ 704113596Snectar if (p + sizeof(field) > eom) \ 705113596Snectar return (NS_NOTFOUND); \ 706113596Snectar memcpy(&(field), p, sizeof(field)); \ 707113596Snectar p += sizeof(field); \ 708113596Snectar } while (0) 709113596Snectar STRING(pwd->pw_name); 710113596Snectar STRING(pwd->pw_passwd); 711113596Snectar SCALAR(pwd->pw_uid); 712113596Snectar SCALAR(pwd->pw_gid); 713113596Snectar SCALAR(pw_change); 714113596Snectar STRING(pwd->pw_class); 715113596Snectar STRING(pwd->pw_gecos); 716113596Snectar STRING(pwd->pw_dir); 717113596Snectar STRING(pwd->pw_shell); 718113596Snectar SCALAR(pw_expire); 719113596Snectar SCALAR(pwd->pw_fields); 720113596Snectar#undef STRING 721113596Snectar#undef SCALAR 722113596Snectar pwd->pw_change = pw_change; 723113596Snectar pwd->pw_expire = pw_expire; 724113596Snectar return (NS_SUCCESS); 725113596Snectar} 726113596Snectar 727113596Snectar 728113596Snectarstatic int 729124432Snectarpwdb_match_entry_v4(char *entry, size_t entrysize, enum nss_lookup_type how, 730113596Snectar const char *name, uid_t uid) 731113596Snectar{ 732113596Snectar const char *p, *eom; 733113596Snectar uint32_t uid2; 734113596Snectar 735113596Snectar eom = &entry[entrysize]; 736113596Snectar for (p = entry; p < eom; p++) 737113596Snectar if (*p == '\0') 738113596Snectar break; 739113596Snectar if (*p != '\0') 740113596Snectar return (NS_NOTFOUND); 741113596Snectar if (how == nss_lt_all) 742113596Snectar return (NS_SUCCESS); 743124432Snectar if (how == nss_lt_name) 744113596Snectar return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND); 745113596Snectar for (p++; p < eom; p++) 746113596Snectar if (*p == '\0') 747113596Snectar break; 748113596Snectar if (*p != '\0' || (++p) + sizeof(uid) >= eom) 749113596Snectar return (NS_NOTFOUND); 750113596Snectar memcpy(&uid2, p, sizeof(uid2)); 751113596Snectar uid2 = ntohl(uid2); 752113596Snectar return (uid == (uid_t)uid2 ? NS_SUCCESS : NS_NOTFOUND); 753113596Snectar} 754113596Snectar 755113596Snectar 756113596Snectarstatic int 757113596Snectarpwdb_parse_entry_v4(char *buffer, size_t bufsize, struct passwd *pwd, 758113596Snectar int *errnop) 759113596Snectar{ 760113596Snectar char *p, *eom; 761113596Snectar uint32_t n; 762113596Snectar 763113596Snectar /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 764113596Snectar p = buffer; 765113596Snectar eom = &buffer[bufsize]; 766113596Snectar#define STRING(field) do { \ 767113596Snectar (field) = p; \ 768113596Snectar while (p < eom && *p != '\0') \ 769113596Snectar p++; \ 770113596Snectar if (p >= eom) \ 771113596Snectar return (NS_NOTFOUND); \ 772113596Snectar p++; \ 773113596Snectar } while (0) 774113596Snectar#define SCALAR(field) do { \ 775113596Snectar if (p + sizeof(n) > eom) \ 776113596Snectar return (NS_NOTFOUND); \ 777113596Snectar memcpy(&n, p, sizeof(n)); \ 778113596Snectar (field) = ntohl(n); \ 779113596Snectar p += sizeof(n); \ 780113596Snectar } while (0) 781113596Snectar STRING(pwd->pw_name); 782113596Snectar STRING(pwd->pw_passwd); 783113596Snectar SCALAR(pwd->pw_uid); 784113596Snectar SCALAR(pwd->pw_gid); 785113596Snectar SCALAR(pwd->pw_change); 786113596Snectar STRING(pwd->pw_class); 787113596Snectar STRING(pwd->pw_gecos); 788113596Snectar STRING(pwd->pw_dir); 789113596Snectar STRING(pwd->pw_shell); 790113596Snectar SCALAR(pwd->pw_expire); 791113596Snectar SCALAR(pwd->pw_fields); 792113596Snectar#undef STRING 793113596Snectar#undef SCALAR 794113596Snectar return (NS_SUCCESS); 795113596Snectar} 796113596Snectar 797113596Snectar 79865532Snectar#ifdef HESIOD 79965532Snectar/* 800113596Snectar * dns backend 80165532Snectar */ 802113596Snectarstatic void 803113596Snectardns_endstate(void *p) 804113596Snectar{ 805113596Snectar free(p); 806113596Snectar} 80765532Snectar 808113596Snectar 80917141Sjkhstatic int 810113596Snectardns_setpwent(void *retval, void *mdata, va_list ap) 8111573Srgrimes{ 812113596Snectar struct dns_state *st; 813113596Snectar int rv; 8141573Srgrimes 815113596Snectar rv = dns_getstate(&st); 816113596Snectar if (rv != 0) 817113596Snectar return (NS_UNAVAIL); 818113596Snectar st->counter = 0; 819113596Snectar return (NS_UNAVAIL); 820113596Snectar} 8211573Srgrimes 822113596Snectar 823113596Snectarstatic int 824113596Snectardns_passwd(void *retval, void *mdata, va_list ap) 825113596Snectar{ 826113596Snectar char buf[HESIOD_NAME_MAX]; 827113596Snectar struct dns_state *st; 828113596Snectar struct passwd *pwd; 829113596Snectar const char *name, *label; 830113596Snectar void *ctx; 831113596Snectar char *buffer, **hes; 832113596Snectar size_t bufsize, linesize; 833113596Snectar uid_t uid; 834113596Snectar enum nss_lookup_type how; 835113596Snectar int rv, *errnop; 836113596Snectar 837113596Snectar ctx = NULL; 838113596Snectar hes = NULL; 839113596Snectar name = NULL; 840113596Snectar uid = (uid_t)-1; 841113596Snectar how = (enum nss_lookup_type)mdata; 842113596Snectar switch (how) { 843113596Snectar case nss_lt_name: 84465532Snectar name = va_arg(ap, const char *); 84565532Snectar break; 846113596Snectar case nss_lt_id: 84765532Snectar uid = va_arg(ap, uid_t); 84865532Snectar break; 849113596Snectar case nss_lt_all: 850113596Snectar break; 85129479Swosch } 852113596Snectar pwd = va_arg(ap, struct passwd *); 853113596Snectar buffer = va_arg(ap, char *); 854113596Snectar bufsize = va_arg(ap, size_t); 855113596Snectar errnop = va_arg(ap, int *); 856113596Snectar *errnop = dns_getstate(&st); 857113596Snectar if (*errnop != 0) 858113596Snectar return (NS_UNAVAIL); 859113596Snectar if (hesiod_init(&ctx) != 0) { 860113596Snectar *errnop = errno; 861113596Snectar rv = NS_UNAVAIL; 862113596Snectar goto fin; 863113596Snectar } 864113596Snectar do { 865113596Snectar rv = NS_NOTFOUND; 866113596Snectar switch (how) { 867113596Snectar case nss_lt_name: 868113596Snectar label = name; 869113596Snectar break; 870113596Snectar case nss_lt_id: 871113596Snectar if (snprintf(buf, sizeof(buf), "%lu", 872113596Snectar (unsigned long)uid) >= sizeof(buf)) 873113596Snectar goto fin; 874113596Snectar label = buf; 875113596Snectar break; 876113596Snectar case nss_lt_all: 877113596Snectar if (st->counter < 0) 878113596Snectar goto fin; 879113596Snectar if (snprintf(buf, sizeof(buf), "passwd-%ld", 880113596Snectar st->counter++) >= sizeof(buf)) 881113596Snectar goto fin; 882113596Snectar label = buf; 883113596Snectar break; 88465532Snectar } 885113596Snectar hes = hesiod_resolve(ctx, label, 886113596Snectar how == nss_lt_id ? "uid" : "passwd"); 887113596Snectar if (hes == NULL) { 888113596Snectar if (how == nss_lt_all) 889113596Snectar st->counter = -1; 890113596Snectar if (errno != ENOENT) 891113596Snectar *errnop = errno; 892113596Snectar goto fin; 893113596Snectar } 894113596Snectar rv = __pw_match_entry(hes[0], strlen(hes[0]), how, name, uid); 895113596Snectar if (rv != NS_SUCCESS) { 896113596Snectar hesiod_free_list(ctx, hes); 897113596Snectar hes = NULL; 898113596Snectar continue; 899113596Snectar } 900114443Snectar linesize = strlcpy(buffer, hes[0], bufsize); 901113596Snectar if (linesize >= bufsize) { 902113596Snectar *errnop = ERANGE; 903113596Snectar rv = NS_RETURN; 904113596Snectar continue; 905113596Snectar } 906113596Snectar hesiod_free_list(ctx, hes); 907113596Snectar hes = NULL; 908113596Snectar rv = __pw_parse_entry(buffer, bufsize, pwd, 0, errnop); 909113596Snectar } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 910113596Snectarfin: 911113596Snectar if (hes != NULL) 912113596Snectar hesiod_free_list(ctx, hes); 913113596Snectar if (ctx != NULL) 914113596Snectar hesiod_end(ctx); 915113596Snectar if (rv == NS_SUCCESS) { 916113596Snectar pwd->pw_fields &= ~_PWF_SOURCE; 917113596Snectar pwd->pw_fields |= _PWF_HESIOD; 918113596Snectar if (retval != NULL) 919113596Snectar *(struct passwd **)retval = pwd; 92065532Snectar } 921113596Snectar return (rv); 92215267Swpaul} 923113596Snectar#endif /* HESIOD */ 9247258Swpaul 925113596Snectar 92665532Snectar#ifdef YP 92715267Swpaul/* 928113596Snectar * nis backend 92915267Swpaul */ 930113596Snectarstatic void 931113596Snectarnis_endstate(void *p) 932113596Snectar{ 933113596Snectar free(((struct nis_state *)p)->key); 934113596Snectar free(p); 935113596Snectar} 93665532Snectar 937117750Swpaul/* 938117750Swpaul * Test for the presence of special FreeBSD-specific master.passwd.by* 939117750Swpaul * maps. We do this using yp_order(). If it fails, then either the server 940117750Swpaul * doesn't have the map, or the YPPROC_ORDER procedure isn't supported by 941117750Swpaul * the server (Sun NIS+ servers in YP compat mode behave this way). If 942117750Swpaul * the master.passwd.by* maps don't exist, then let the lookup routine try 943117750Swpaul * the regular passwd.by* maps instead. If the lookup routine fails, it 944117750Swpaul * can return an error as needed. 945117750Swpaul */ 94665532Snectarstatic int 947113596Snectarnis_map(char *domain, enum nss_lookup_type how, char *buffer, size_t bufsize, 948113596Snectar int *master) 94915267Swpaul{ 950117750Swpaul int rv, order; 9517258Swpaul 952113596Snectar *master = 0; 953113794Snectar if (geteuid() == 0) { 954113794Snectar if (snprintf(buffer, bufsize, "master.passwd.by%s", 955113794Snectar (how == nss_lt_id) ? "uid" : "name") >= bufsize) 956113794Snectar return (NS_UNAVAIL); 957117750Swpaul rv = yp_order(domain, buffer, &order); 958113794Snectar if (rv == 0) { 959113794Snectar *master = 1; 960113794Snectar return (NS_SUCCESS); 961113794Snectar } 96265532Snectar } 963117750Swpaul 964113596Snectar if (snprintf(buffer, bufsize, "passwd.by%s", 965113596Snectar (how == nss_lt_id) ? "uid" : "name") >= bufsize) 966113596Snectar return (NS_UNAVAIL); 967117750Swpaul 968117750Swpaul return (NS_SUCCESS); 969113596Snectar} 97015267Swpaul 971113596Snectar 972113596Snectarstatic int 973113596Snectarnis_adjunct(char *domain, const char *name, char *buffer, size_t bufsize) 974113596Snectar{ 975113596Snectar int rv; 976113596Snectar char *result, *p, *q, *eor; 977113596Snectar int resultlen; 978113596Snectar 979113596Snectar result = NULL; 980113596Snectar rv = yp_match(domain, "passwd.adjunct.byname", name, strlen(name), 981113596Snectar &result, &resultlen); 982113596Snectar if (rv != 0) 983113596Snectar rv = 1; 984113596Snectar else { 985113596Snectar eor = &result[resultlen]; 986113596Snectar p = memchr(result, ':', eor - result); 987113596Snectar if (p != NULL && ++p < eor && 988113596Snectar (q = memchr(p, ':', eor - p)) != NULL) { 989113596Snectar if (q - p >= bufsize) 990113596Snectar rv = -1; 991113596Snectar else { 992113596Snectar memcpy(buffer, p, q - p); 993113596Snectar buffer[q - p] ='\0'; 994113596Snectar } 995113596Snectar } else 996113596Snectar rv = 1; 997124432Snectar } 998113596Snectar free(result); 999113596Snectar return (rv); 1000113596Snectar} 1001113596Snectar 1002113596Snectar 1003113596Snectarstatic int 1004113596Snectarnis_setpwent(void *retval, void *mdata, va_list ap) 1005113596Snectar{ 1006113596Snectar struct nis_state *st; 1007113596Snectar int rv; 1008113596Snectar 1009113596Snectar rv = nis_getstate(&st); 1010113596Snectar if (rv != 0) 1011113596Snectar return (NS_UNAVAIL); 1012113596Snectar st->done = 0; 1013113596Snectar free(st->key); 1014113596Snectar st->key = NULL; 1015113596Snectar return (NS_UNAVAIL); 1016113596Snectar} 1017113596Snectar 1018113596Snectar 1019113596Snectarstatic int 1020113596Snectarnis_passwd(void *retval, void *mdata, va_list ap) 1021113596Snectar{ 1022113596Snectar char map[YPMAXMAP]; 1023113596Snectar struct nis_state *st; 1024113596Snectar struct passwd *pwd; 1025113596Snectar const char *name; 1026113596Snectar char *buffer, *key, *result; 1027113596Snectar size_t bufsize; 1028113596Snectar uid_t uid; 1029113596Snectar enum nss_lookup_type how; 1030113596Snectar int *errnop, keylen, resultlen, rv, master; 1031124432Snectar 1032113596Snectar name = NULL; 1033113596Snectar uid = (uid_t)-1; 1034113596Snectar how = (enum nss_lookup_type)mdata; 1035113596Snectar switch (how) { 1036113596Snectar case nss_lt_name: 103765532Snectar name = va_arg(ap, const char *); 103865532Snectar break; 1039113596Snectar case nss_lt_id: 104065532Snectar uid = va_arg(ap, uid_t); 104165532Snectar break; 1042113596Snectar case nss_lt_all: 1043113596Snectar break; 104465532Snectar } 1045113596Snectar pwd = va_arg(ap, struct passwd *); 1046113596Snectar buffer = va_arg(ap, char *); 1047113596Snectar bufsize = va_arg(ap, size_t); 1048113596Snectar errnop = va_arg(ap, int *); 1049113596Snectar *errnop = nis_getstate(&st); 1050113596Snectar if (*errnop != 0) 1051113596Snectar return (NS_UNAVAIL); 1052113596Snectar if (st->domain[0] == '\0') { 1053113596Snectar if (getdomainname(st->domain, sizeof(st->domain)) != 0) { 1054113596Snectar *errnop = errno; 1055113596Snectar return (NS_UNAVAIL); 105665532Snectar } 105765532Snectar } 1058113596Snectar rv = nis_map(st->domain, how, map, sizeof(map), &master); 1059113596Snectar if (rv != NS_SUCCESS) 1060113596Snectar return (rv); 1061113596Snectar result = NULL; 1062113596Snectar do { 1063113596Snectar rv = NS_NOTFOUND; 1064113596Snectar switch (how) { 1065113596Snectar case nss_lt_name: 1066114443Snectar if (strlcpy(buffer, name, bufsize) >= bufsize) 1067113596Snectar goto erange; 1068113596Snectar break; 1069113596Snectar case nss_lt_id: 1070113596Snectar if (snprintf(buffer, bufsize, "%lu", 1071113596Snectar (unsigned long)uid) >= bufsize) 1072113596Snectar goto erange; 1073113596Snectar break; 1074113596Snectar case nss_lt_all: 1075113596Snectar if (st->done) 1076113596Snectar goto fin; 1077113596Snectar break; 1078113596Snectar } 1079113596Snectar result = NULL; 1080113596Snectar if (how == nss_lt_all) { 1081113596Snectar if (st->key == NULL) 1082113596Snectar rv = yp_first(st->domain, map, &st->key, 1083113596Snectar &st->keylen, &result, &resultlen); 1084113596Snectar else { 1085113596Snectar key = st->key; 1086113596Snectar keylen = st->keylen; 1087113596Snectar st->key = NULL; 1088113596Snectar rv = yp_next(st->domain, map, key, keylen, 1089113596Snectar &st->key, &st->keylen, &result, 1090113596Snectar &resultlen); 1091113596Snectar free(key); 109265532Snectar } 1093113596Snectar if (rv != 0) { 1094113596Snectar free(result); 1095113596Snectar free(st->key); 1096113596Snectar st->key = NULL; 1097113596Snectar if (rv == YPERR_NOMORE) 1098113596Snectar st->done = 1; 1099113596Snectar else 1100113596Snectar rv = NS_UNAVAIL; 1101113596Snectar goto fin; 1102113596Snectar } 110365532Snectar } else { 1104113596Snectar rv = yp_match(st->domain, map, buffer, strlen(buffer), 1105113596Snectar &result, &resultlen); 1106113596Snectar if (rv == YPERR_KEY) { 1107113596Snectar rv = NS_NOTFOUND; 1108113596Snectar continue; 1109113596Snectar } else if (rv != 0) { 1110113596Snectar free(result); 1111113596Snectar rv = NS_UNAVAIL; 1112113596Snectar continue; 1113113596Snectar } 111465532Snectar } 1115113596Snectar if (resultlen >= bufsize) 1116113596Snectar goto erange; 1117113596Snectar memcpy(buffer, result, resultlen); 1118113596Snectar buffer[resultlen] = '\0'; 1119113596Snectar free(result); 1120113596Snectar rv = __pw_match_entry(buffer, resultlen, how, name, uid); 1121113596Snectar if (rv == NS_SUCCESS) 1122113596Snectar rv = __pw_parse_entry(buffer, resultlen, pwd, master, 1123113596Snectar errnop); 1124113596Snectar } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 1125124432Snectarfin: 1126113596Snectar if (rv == NS_SUCCESS) { 1127113596Snectar if (strstr(pwd->pw_passwd, "##") != NULL) { 1128124431Snectar rv = nis_adjunct(st->domain, pwd->pw_name, 1129113596Snectar &buffer[resultlen+1], bufsize-resultlen-1); 1130113596Snectar if (rv < 0) 1131113596Snectar goto erange; 1132113596Snectar else if (rv == 0) 1133113596Snectar pwd->pw_passwd = &buffer[resultlen+1]; 113465532Snectar } 1135113596Snectar pwd->pw_fields &= ~_PWF_SOURCE; 1136113596Snectar pwd->pw_fields |= _PWF_NIS; 1137113596Snectar if (retval != NULL) 1138113596Snectar *(struct passwd **)retval = pwd; 1139128537Sjon rv = NS_SUCCESS; 114015267Swpaul } 1141124432Snectar return (rv); 1142113596Snectarerange: 1143113596Snectar *errnop = ERANGE; 1144113596Snectar return (NS_RETURN); 1145113596Snectar} 1146113596Snectar#endif /* YP */ 114715267Swpaul 1148113596Snectar 114915267Swpaul/* 1150113596Snectar * compat backend 115115267Swpaul */ 1152113596Snectarstatic void 1153113596Snectarcompat_clear_template(struct passwd *template) 1154113596Snectar{ 115565532Snectar 1156113596Snectar free(template->pw_passwd); 1157113596Snectar free(template->pw_gecos); 1158113596Snectar free(template->pw_dir); 1159113596Snectar free(template->pw_shell); 1160113596Snectar memset(template, 0, sizeof(*template)); 1161113596Snectar} 1162113596Snectar 1163113596Snectar 116465532Snectarstatic int 1165113596Snectarcompat_set_template(struct passwd *src, struct passwd *template) 116615267Swpaul{ 116715267Swpaul 1168113596Snectar compat_clear_template(template); 1169113596Snectar#ifdef PW_OVERRIDE_PASSWD 1170113596Snectar if ((src->pw_fields & _PWF_PASSWD) && 1171113596Snectar (template->pw_passwd = strdup(src->pw_passwd)) == NULL) 1172113596Snectar goto enomem; 1173113596Snectar#endif 1174113596Snectar if (src->pw_fields & _PWF_UID) 1175113596Snectar template->pw_uid = src->pw_uid; 1176113596Snectar if (src->pw_fields & _PWF_GID) 1177113596Snectar template->pw_gid = src->pw_gid; 1178113596Snectar if ((src->pw_fields & _PWF_GECOS) && 1179113596Snectar (template->pw_gecos = strdup(src->pw_gecos)) == NULL) 1180113596Snectar goto enomem; 1181113596Snectar if ((src->pw_fields & _PWF_DIR) && 1182113596Snectar (template->pw_dir = strdup(src->pw_dir)) == NULL) 1183113596Snectar goto enomem; 1184113596Snectar if ((src->pw_fields & _PWF_SHELL) && 1185113596Snectar (template->pw_shell = strdup(src->pw_shell)) == NULL) 1186113596Snectar goto enomem; 1187113596Snectar template->pw_fields = src->pw_fields; 1188113596Snectar return (0); 1189113596Snectarenomem: 1190113596Snectar syslog(LOG_ERR, "getpwent memory allocation failure"); 1191113596Snectar return (-1); 1192113596Snectar} 119315267Swpaul 119415267Swpaul 1195113596Snectarstatic int 1196113596Snectarcompat_use_template(struct passwd *pwd, struct passwd *template, char *buffer, 1197113596Snectar size_t bufsize) 1198113596Snectar{ 1199113596Snectar struct passwd hold; 1200113596Snectar char *copy, *p, *q, *eob; 1201113596Snectar size_t n; 1202113596Snectar 1203113596Snectar /* We cannot know the layout of the password fields in `buffer', 1204113596Snectar * so we have to copy everything. 1205113596Snectar */ 1206113596Snectar if (template->pw_fields == 0) /* nothing to fill-in */ 1207113596Snectar return (0); 1208113596Snectar n = 0; 1209113596Snectar n += pwd->pw_name != NULL ? strlen(pwd->pw_name) + 1 : 0; 1210113596Snectar n += pwd->pw_passwd != NULL ? strlen(pwd->pw_passwd) + 1 : 0; 1211113596Snectar n += pwd->pw_class != NULL ? strlen(pwd->pw_class) + 1 : 0; 1212113596Snectar n += pwd->pw_gecos != NULL ? strlen(pwd->pw_gecos) + 1 : 0; 1213113596Snectar n += pwd->pw_dir != NULL ? strlen(pwd->pw_dir) + 1 : 0; 1214113596Snectar n += pwd->pw_shell != NULL ? strlen(pwd->pw_shell) + 1 : 0; 1215113596Snectar copy = malloc(n); 1216113596Snectar if (copy == NULL) { 1217113596Snectar syslog(LOG_ERR, "getpwent memory allocation failure"); 1218113596Snectar return (ENOMEM); 1219113596Snectar } 1220113596Snectar p = copy; 1221113596Snectar eob = ©[n]; 1222113596Snectar#define COPY(field) do { \ 1223113596Snectar if (pwd->field == NULL) \ 1224113596Snectar hold.field = NULL; \ 1225113596Snectar else { \ 1226113596Snectar hold.field = p; \ 1227114443Snectar p += strlcpy(p, pwd->field, eob-p) + 1; \ 1228113596Snectar } \ 1229113596Snectar} while (0) 1230113596Snectar COPY(pw_name); 1231113596Snectar COPY(pw_passwd); 1232113596Snectar COPY(pw_class); 1233113596Snectar COPY(pw_gecos); 1234113596Snectar COPY(pw_dir); 1235113596Snectar COPY(pw_shell); 1236113596Snectar#undef COPY 1237113596Snectar p = buffer; 1238113596Snectar eob = &buffer[bufsize]; 1239113596Snectar#define COPY(field, flag) do { \ 1240113596Snectar q = (template->pw_fields & flag) ? template->field : hold.field; \ 1241113596Snectar if (q == NULL) \ 1242113596Snectar pwd->field = NULL; \ 1243113596Snectar else { \ 1244113596Snectar pwd->field = p; \ 1245114443Snectar if ((n = strlcpy(p, q, eob-p)) >= eob-p) { \ 1246113596Snectar free(copy); \ 1247113596Snectar return (ERANGE); \ 1248113596Snectar } \ 1249113596Snectar p += n + 1; \ 1250113596Snectar } \ 1251113596Snectar} while (0) 1252113596Snectar COPY(pw_name, 0); 1253113596Snectar#ifdef PW_OVERRIDE_PASSWD 1254113596Snectar COPY(pw_passwd, _PWF_PASSWD); 1255113596Snectar#else 1256113596Snectar COPY(pw_passwd, 0); 1257113596Snectar#endif 1258113596Snectar COPY(pw_class, 0); 1259113596Snectar COPY(pw_gecos, _PWF_GECOS); 1260113596Snectar COPY(pw_dir, _PWF_DIR); 1261113596Snectar COPY(pw_shell, _PWF_SHELL); 1262113596Snectar#undef COPY 1263113596Snectar#define COPY(field, flag) do { \ 1264113596Snectar if (template->pw_fields & flag) \ 1265113596Snectar pwd->field = template->field; \ 1266113596Snectar} while (0) 1267113596Snectar COPY(pw_uid, _PWF_UID); 1268113596Snectar COPY(pw_gid, _PWF_GID); 1269113596Snectar#undef COPY 1270113596Snectar free(copy); 1271113596Snectar return (0); 127215267Swpaul} 127315267Swpaul 127465532Snectar 127565532Snectarstatic int 1276113596Snectarcompat_exclude(const char *name, DB **db) 127715267Swpaul{ 1278113596Snectar DBT key, data; 1279113596Snectar 1280113596Snectar if (*db == NULL && 1281113596Snectar (*db = dbopen(NULL, O_RDWR, 600, DB_HASH, 0)) == NULL) 1282113596Snectar return (errno); 1283113596Snectar key.size = strlen(name); 1284113596Snectar key.data = (char *)name; 1285113596Snectar data.size = 0; 1286113596Snectar data.data = NULL; 1287113596Snectar 1288113596Snectar if ((*db)->put(*db, &key, &data, 0) == -1) 1289113596Snectar return (errno); 1290113596Snectar return (0); 12917258Swpaul} 12927258Swpaul 129365532Snectar 129465532Snectarstatic int 1295113596Snectarcompat_is_excluded(const char *name, DB *db) 12967258Swpaul{ 1297113596Snectar DBT key, data; 12987258Swpaul 1299113596Snectar if (db == NULL) 1300113596Snectar return (0); 1301113596Snectar key.size = strlen(name); 1302113596Snectar key.data = (char *)name; 1303113596Snectar return (db->get(db, &key, &data, 0) == 0); 13047258Swpaul} 13057258Swpaul 130665532Snectar 130765532Snectarstatic int 1308113596Snectarcompat_redispatch(struct compat_state *st, enum nss_lookup_type how, 1309113596Snectar enum nss_lookup_type lookup_how, const char *name, const char *lookup_name, 1310113596Snectar uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, int *errnop) 131110521Swpaul{ 1312113596Snectar static const ns_src compatsrc[] = { 1313113596Snectar#ifdef YP 1314113596Snectar { NSSRC_NIS, NS_SUCCESS }, 131565532Snectar#endif 1316113596Snectar { NULL, 0 } 1317113596Snectar }; 1318113596Snectar ns_dtab dtab[] = { 1319113596Snectar#ifdef YP 1320113596Snectar { NSSRC_NIS, nis_passwd, NULL }, 1321113596Snectar#endif 1322113596Snectar#ifdef HESIOD 1323113596Snectar { NSSRC_DNS, dns_passwd, NULL }, 1324113596Snectar#endif 1325113596Snectar { NULL, NULL, NULL } 1326113596Snectar }; 1327113596Snectar void *discard; 1328113596Snectar int rv, e, i; 132910521Swpaul 1330113596Snectar for (i = 0; i < sizeof(dtab)/sizeof(dtab[0]) - 1; i++) 1331113596Snectar dtab[i].mdata = (void *)lookup_how; 1332113596Snectarmore: 1333113992Snectar pwd_init(pwd); 1334113596Snectar switch (lookup_how) { 1335113596Snectar case nss_lt_all: 1336113596Snectar rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 1337113596Snectar "getpwent_r", compatsrc, pwd, buffer, bufsize, 1338113596Snectar errnop); 1339113596Snectar break; 1340113596Snectar case nss_lt_id: 1341113596Snectar rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 1342113596Snectar "getpwuid_r", compatsrc, uid, pwd, buffer, 1343113596Snectar bufsize, errnop); 1344113596Snectar break; 1345113596Snectar case nss_lt_name: 1346113596Snectar rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 1347113596Snectar "getpwnam_r", compatsrc, lookup_name, pwd, buffer, 1348113596Snectar bufsize, errnop); 1349113596Snectar break; 1350113596Snectar default: 1351113596Snectar return (NS_UNAVAIL); 1352113596Snectar } 1353113596Snectar if (rv != NS_SUCCESS) 1354113596Snectar return (rv); 1355113596Snectar if (compat_is_excluded(pwd->pw_name, st->exclude)) { 1356113596Snectar if (how == nss_lt_all) 1357113596Snectar goto more; 1358113596Snectar return (NS_NOTFOUND); 1359113596Snectar } 1360113596Snectar e = compat_use_template(pwd, &st->template, buffer, bufsize); 1361113596Snectar if (e != 0) { 1362113596Snectar *errnop = e; 1363113596Snectar if (e == ERANGE) 1364113596Snectar return (NS_RETURN); 1365113596Snectar else 1366113596Snectar return (NS_UNAVAIL); 1367113596Snectar } 1368113596Snectar switch (how) { 1369113596Snectar case nss_lt_name: 1370113596Snectar if (strcmp(name, pwd->pw_name) != 0) 1371113596Snectar return (NS_NOTFOUND); 1372113596Snectar break; 1373113596Snectar case nss_lt_id: 1374113596Snectar if (uid != pwd->pw_uid) 1375113596Snectar return (NS_NOTFOUND); 1376113596Snectar break; 1377113596Snectar default: 1378113596Snectar break; 1379113596Snectar } 1380113596Snectar return (NS_SUCCESS); 1381113596Snectar} 138265532Snectar 138365532Snectar 1384113596Snectarstatic void 1385113596Snectarcompat_endstate(void *p) 1386113596Snectar{ 1387113596Snectar struct compat_state *st; 138865532Snectar 1389113596Snectar if (p == NULL) 1390113596Snectar return; 1391113596Snectar st = (struct compat_state *)p; 1392113596Snectar if (st->db != NULL) 1393113596Snectar st->db->close(st->db); 1394113596Snectar if (st->exclude != NULL) 1395113596Snectar st->exclude->close(st->exclude); 1396113596Snectar compat_clear_template(&st->template); 1397113596Snectar free(p); 1398113596Snectar} 139965532Snectar 140065532Snectar 1401113596Snectarstatic int 1402113596Snectarcompat_setpwent(void *retval, void *mdata, va_list ap) 1403113596Snectar{ 1404114021Snectar static const ns_src compatsrc[] = { 1405114021Snectar#ifdef YP 1406114021Snectar { NSSRC_NIS, NS_SUCCESS }, 1407114021Snectar#endif 1408114021Snectar { NULL, 0 } 1409114021Snectar }; 1410114021Snectar ns_dtab dtab[] = { 1411114021Snectar#ifdef YP 1412114021Snectar { NSSRC_NIS, nis_setpwent, NULL }, 1413114021Snectar#endif 1414114021Snectar#ifdef HESIOD 1415114021Snectar { NSSRC_DNS, dns_setpwent, NULL }, 1416114021Snectar#endif 1417114021Snectar { NULL, NULL, NULL } 1418114021Snectar }; 1419113596Snectar struct compat_state *st; 1420113596Snectar int rv, stayopen; 142165532Snectar 1422114021Snectar#define set_setent(x, y) do { \ 1423114021Snectar int i; \ 1424114021Snectar \ 1425114021Snectar for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \ 1426114021Snectar x[i].mdata = (void *)y; \ 1427114021Snectar} while (0) 1428114021Snectar 1429113596Snectar rv = compat_getstate(&st); 1430113596Snectar if (rv != 0) 1431113596Snectar return (NS_UNAVAIL); 1432113596Snectar switch ((enum constants)mdata) { 1433113596Snectar case SETPWENT: 1434113596Snectar stayopen = va_arg(ap, int); 1435113596Snectar st->keynum = 0; 1436113596Snectar if (stayopen) 1437113596Snectar st->db = pwdbopen(&st->version); 1438113596Snectar st->stayopen = stayopen; 1439114021Snectar set_setent(dtab, mdata); 1440114021Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "setpwent", 1441114021Snectar compatsrc, 0); 1442113596Snectar break; 1443113596Snectar case ENDPWENT: 1444113596Snectar if (st->db != NULL) { 1445113596Snectar (void)st->db->close(st->db); 1446113596Snectar st->db = NULL; 144765532Snectar } 1448114021Snectar set_setent(dtab, mdata); 1449114021Snectar (void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "endpwent", 1450114021Snectar compatsrc, 0); 1451113596Snectar break; 1452113596Snectar default: 1453113596Snectar break; 145410521Swpaul } 1455113596Snectar return (NS_UNAVAIL); 1456114021Snectar#undef set_setent 145710521Swpaul} 145820119Swpaul 145920119Swpaul 14609332Swpaulstatic int 1461113596Snectarcompat_passwd(void *retval, void *mdata, va_list ap) 14622917Swollman{ 1463113596Snectar char keybuf[MAXLOGNAME + 1]; 1464113596Snectar DBT key, entry; 1465113596Snectar struct compat_state *st; 1466113596Snectar enum nss_lookup_type how; 1467113596Snectar const char *name; 1468113596Snectar struct passwd *pwd; 1469113596Snectar char *buffer, *pw_name; 1470113596Snectar char *host, *user, *domain; 1471113596Snectar size_t bufsize; 1472113596Snectar uid_t uid; 1473113596Snectar uint32_t store; 1474113691Snectar int rv, from_compat, stayopen, *errnop; 14752917Swollman 1476113691Snectar from_compat = 0; 147765532Snectar name = NULL; 1478113596Snectar uid = (uid_t)-1; 1479113596Snectar how = (enum nss_lookup_type)mdata; 1480113596Snectar switch (how) { 1481113596Snectar case nss_lt_name: 1482113596Snectar name = va_arg(ap, const char *); 148365532Snectar break; 1484113596Snectar case nss_lt_id: 148565532Snectar uid = va_arg(ap, uid_t); 148665532Snectar break; 1487113596Snectar case nss_lt_all: 1488113596Snectar break; 148965532Snectar default: 1490113596Snectar rv = NS_NOTFOUND; 1491113596Snectar goto fin; 14922917Swollman } 1493113596Snectar pwd = va_arg(ap, struct passwd *); 1494113596Snectar buffer = va_arg(ap, char *); 1495113596Snectar bufsize = va_arg(ap, size_t); 1496113596Snectar errnop = va_arg(ap, int *); 1497113596Snectar *errnop = compat_getstate(&st); 1498113596Snectar if (*errnop != 0) 1499113596Snectar return (NS_UNAVAIL); 1500113596Snectar if (how == nss_lt_all && st->keynum < 0) { 1501113596Snectar rv = NS_NOTFOUND; 1502113596Snectar goto fin; 1503113596Snectar } 1504113596Snectar if (st->db == NULL && 1505113596Snectar (st->db = pwdbopen(&st->version)) == NULL) { 1506113596Snectar *errnop = errno; 1507113596Snectar rv = NS_UNAVAIL; 1508113596Snectar goto fin; 1509113596Snectar } 1510113596Snectar if (how == nss_lt_all) { 1511113596Snectar if (st->keynum < 0) { 1512113596Snectar rv = NS_NOTFOUND; 1513113596Snectar goto fin; 1514113596Snectar } 1515113596Snectar stayopen = 1; 1516113596Snectar } else { 1517113596Snectar st->keynum = 0; 1518113596Snectar stayopen = st->stayopen; 1519113596Snectar } 1520113596Snectardocompat: 1521113596Snectar rv = NS_NOTFOUND; 1522113596Snectar switch (st->compat) { 1523113596Snectar case COMPAT_MODE_ALL: 1524113596Snectar rv = compat_redispatch(st, how, how, name, name, uid, pwd, 1525113596Snectar buffer, bufsize, errnop); 1526113596Snectar if (rv != NS_SUCCESS) 1527113596Snectar st->compat = COMPAT_MODE_OFF; 1528113596Snectar break; 1529113596Snectar case COMPAT_MODE_NETGROUP: 1530113596Snectar /* XXX getnetgrent is not thread-safe. */ 1531113596Snectar do { 1532113596Snectar rv = getnetgrent(&host, &user, &domain); 1533113596Snectar if (rv == 0) { 1534113596Snectar endnetgrent(); 1535113596Snectar st->compat = COMPAT_MODE_OFF; 1536113596Snectar rv = NS_NOTFOUND; 1537113596Snectar continue; 1538113596Snectar } else if (user == NULL || user[0] == '\0') 1539113596Snectar continue; 1540113596Snectar rv = compat_redispatch(st, how, nss_lt_name, name, 1541113596Snectar user, uid, pwd, buffer, bufsize, errnop); 1542113596Snectar } while (st->compat == COMPAT_MODE_NETGROUP && 1543113596Snectar !(rv & NS_TERMINATE)); 1544113596Snectar break; 1545113596Snectar case COMPAT_MODE_NAME: 1546113596Snectar rv = compat_redispatch(st, how, nss_lt_name, name, st->name, 1547113596Snectar uid, pwd, buffer, bufsize, errnop); 1548113596Snectar free(st->name); 1549113596Snectar st->name = NULL; 1550113596Snectar st->compat = COMPAT_MODE_OFF; 1551113596Snectar break; 1552113596Snectar default: 1553113596Snectar break; 1554113596Snectar } 1555113691Snectar if (rv & NS_TERMINATE) { 1556113691Snectar from_compat = 1; 1557113596Snectar goto fin; 1558113691Snectar } 1559113596Snectar key.data = keybuf; 1560113596Snectar rv = NS_NOTFOUND; 1561113596Snectar while (st->keynum >= 0) { 1562113596Snectar st->keynum++; 1563113596Snectar if (st->version < _PWD_CURRENT_VERSION) { 1564113596Snectar memcpy(&keybuf[1], &st->keynum, sizeof(st->keynum)); 1565113596Snectar key.size = sizeof(st->keynum) + 1; 1566113596Snectar } else { 1567113596Snectar store = htonl(st->keynum); 1568113596Snectar memcpy(&keybuf[1], &store, sizeof(store)); 1569113596Snectar key.size = sizeof(store) + 1; 1570113596Snectar } 1571113666Snectar keybuf[0] = _PW_VERSIONED(_PW_KEYBYNUM, st->version); 1572113596Snectar rv = st->db->get(st->db, &key, &entry, 0); 1573113596Snectar if (rv < 0 || rv > 1) { /* should never return > 1 */ 1574113596Snectar *errnop = errno; 1575113596Snectar rv = NS_UNAVAIL; 1576113596Snectar goto fin; 1577113596Snectar } else if (rv == 1) { 1578113596Snectar st->keynum = -1; 1579113596Snectar rv = NS_NOTFOUND; 1580113596Snectar goto fin; 1581113596Snectar } 1582113596Snectar pw_name = (char *)entry.data; 1583113596Snectar switch (pw_name[0]) { 158465532Snectar case '+': 1585113596Snectar switch (pw_name[1]) { 158665532Snectar case '\0': 1587113596Snectar st->compat = COMPAT_MODE_ALL; 158865532Snectar break; 158965532Snectar case '@': 1590113596Snectar setnetgrent(&pw_name[2]); 1591113596Snectar st->compat = COMPAT_MODE_NETGROUP; 159265532Snectar break; 159365532Snectar default: 1594113596Snectar st->name = strdup(&pw_name[1]); 1595113596Snectar if (st->name == NULL) { 1596113596Snectar syslog(LOG_ERR, 1597113596Snectar "getpwent memory allocation failure"); 1598113596Snectar *errnop = ENOMEM; 1599113596Snectar rv = NS_UNAVAIL; 1600113596Snectar break; 1601113596Snectar } 1602113596Snectar st->compat = COMPAT_MODE_NAME; 160365532Snectar } 1604113596Snectar if (entry.size > bufsize) { 1605113596Snectar *errnop = ERANGE; 1606113596Snectar rv = NS_RETURN; 1607113596Snectar goto fin; 160865532Snectar } 1609113596Snectar memcpy(buffer, entry.data, entry.size); 1610113596Snectar rv = pwdb_versions[st->version].parse(buffer, 1611113596Snectar entry.size, pwd, errnop); 1612113596Snectar if (rv != NS_SUCCESS) 1613113596Snectar ; 1614113596Snectar else if (compat_set_template(pwd, &st->template) < 0) { 1615113596Snectar *errnop = ENOMEM; 1616113596Snectar rv = NS_UNAVAIL; 1617113596Snectar goto fin; 1618113596Snectar } 1619113596Snectar goto docompat; 162065532Snectar case '-': 1621113596Snectar switch (pw_name[1]) { 162265532Snectar case '\0': 1623113596Snectar /* XXX Maybe syslog warning */ 1624113596Snectar continue; 162565532Snectar case '@': 1626113596Snectar setnetgrent(&pw_name[2]); 1627113596Snectar while (getnetgrent(&host, &user, &domain) != 1628126643Smarkm 0) { 1629113596Snectar if (user != NULL && user[0] != '\0') 1630113596Snectar compat_exclude(user, 1631113596Snectar &st->exclude); 163265532Snectar } 163365532Snectar endnetgrent(); 1634113596Snectar continue; 163565532Snectar default: 1636113596Snectar compat_exclude(&pw_name[1], &st->exclude); 1637113596Snectar continue; 163865532Snectar } 163965532Snectar break; 164096186Sdes default: 1641113596Snectar break; 16426190Swpaul } 1643113596Snectar if (compat_is_excluded((char *)entry.data, st->exclude)) 1644113596Snectar continue; 1645113596Snectar rv = pwdb_versions[st->version].match(entry.data, entry.size, 1646113596Snectar how, name, uid); 1647113596Snectar if (rv == NS_RETURN) 164865532Snectar break; 1649113596Snectar else if (rv != NS_SUCCESS) 1650113596Snectar continue; 1651113596Snectar if (entry.size > bufsize) { 1652113596Snectar *errnop = ERANGE; 1653113596Snectar rv = NS_RETURN; 1654113596Snectar break; 165565532Snectar } 1656113596Snectar memcpy(buffer, entry.data, entry.size); 1657113596Snectar rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd, 1658113596Snectar errnop); 1659113596Snectar if (rv & NS_TERMINATE) 1660113596Snectar break; 16612917Swollman } 1662113596Snectarfin: 1663113596Snectar if (!stayopen && st->db != NULL) { 1664113596Snectar (void)st->db->close(st->db); 1665113596Snectar st->db = NULL; 16666076Swpaul } 1667124432Snectar if (rv == NS_SUCCESS) { 1668113691Snectar if (!from_compat) { 1669113691Snectar pwd->pw_fields &= ~_PWF_SOURCE; 1670113691Snectar pwd->pw_fields |= _PWF_FILES; 1671113691Snectar } 1672113691Snectar if (retval != NULL) 1673113691Snectar *(struct passwd **)retval = pwd; 1674113691Snectar } 1675113596Snectar return (rv); 167665532Snectar} 16776076Swpaul 16789332Swpaul 1679113596Snectar/* 1680113596Snectar * common passwd line matching and parsing 1681113596Snectar */ 168265532Snectarint 1683113596Snectar__pw_match_entry(const char *entry, size_t entrysize, enum nss_lookup_type how, 1684113596Snectar const char *name, uid_t uid) 16852917Swollman{ 1686113596Snectar const char *p, *eom; 1687113596Snectar char *q; 1688113596Snectar size_t len; 1689113596Snectar unsigned long m; 16902917Swollman 1691113596Snectar eom = entry + entrysize; 1692113596Snectar for (p = entry; p < eom; p++) 1693113596Snectar if (*p == ':') 1694113596Snectar break; 1695113596Snectar if (*p != ':') 1696113596Snectar return (NS_NOTFOUND); 1697113596Snectar if (how == nss_lt_all) 1698113596Snectar return (NS_SUCCESS); 1699113596Snectar if (how == nss_lt_name) { 1700113596Snectar len = strlen(name); 1701113596Snectar if (len == (p - entry) && memcmp(name, entry, len) == 0) 1702113596Snectar return (NS_SUCCESS); 1703113596Snectar else 1704113596Snectar return (NS_NOTFOUND); 170545066Sdes } 1706113596Snectar for (p++; p < eom; p++) 1707113596Snectar if (*p == ':') 1708113596Snectar break; 1709113596Snectar if (*p != ':') 1710113596Snectar return (NS_NOTFOUND); 1711113596Snectar m = strtoul(++p, &q, 10); 1712113596Snectar if (q[0] != ':' || (uid_t)m != uid) 1713113596Snectar return (NS_NOTFOUND); 1714113596Snectar else 1715113596Snectar return (NS_SUCCESS); 171665532Snectar} 17172917Swollman 171815267Swpaul 1719113596Snectar/* XXX buffer must be NUL-terminated. errnop is not set correctly. */ 1720113596Snectarint 1721113596Snectar__pw_parse_entry(char *buffer, size_t bufsize __unused, struct passwd *pwd, 1722113596Snectar int master, int *errnop __unused) 17232917Swollman{ 17242917Swollman 1725113596Snectar if (__pw_scan(buffer, pwd, master ? _PWSCAN_MASTER : 0) == 0) 1726113596Snectar return (NS_NOTFOUND); 1727113596Snectar else 1728113596Snectar return (NS_SUCCESS); 17292917Swollman} 1730