105f98035SJacques Vidrine /*- 205f98035SJacques Vidrine * Copyright (c) 2003 Networks Associates Technology, Inc. 305f98035SJacques Vidrine * All rights reserved. 405f98035SJacques Vidrine * 505f98035SJacques Vidrine * This software was developed for the FreeBSD Project by 605f98035SJacques Vidrine * Jacques A. Vidrine, Safeport Network Services, and Network 705f98035SJacques Vidrine * Associates Laboratories, the Security Research Division of Network 805f98035SJacques Vidrine * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 905f98035SJacques Vidrine * ("CBOSS"), as part of the DARPA CHATS research program. 1058f0484fSRodney W. Grimes * 1158f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 1258f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 1358f0484fSRodney W. Grimes * are met: 1458f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1558f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1658f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1758f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1858f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1958f0484fSRodney W. Grimes * 2005f98035SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2158f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2258f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2305f98035SJacques Vidrine * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2458f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2558f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2658f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2758f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2858f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2958f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3058f0484fSRodney W. Grimes * SUCH DAMAGE. 3105f98035SJacques Vidrine * 3258f0484fSRodney W. Grimes */ 3356bcbf00SBruce Evans #include <sys/cdefs.h> 34135b57f9SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3558f0484fSRodney W. Grimes 3605f98035SJacques Vidrine #include "namespace.h" 3758f0484fSRodney W. Grimes #include <sys/param.h> 38248aee62SJacques Vidrine #ifdef YP 39248aee62SJacques Vidrine #include <rpc/rpc.h> 40248aee62SJacques Vidrine #include <rpcsvc/yp_prot.h> 41248aee62SJacques Vidrine #include <rpcsvc/ypclnt.h> 42248aee62SJacques Vidrine #endif 4305f98035SJacques Vidrine #include <arpa/inet.h> 4405f98035SJacques Vidrine #include <errno.h> 4505f98035SJacques Vidrine #include <fcntl.h> 4605f98035SJacques Vidrine #ifdef HESIOD 4705f98035SJacques Vidrine #include <hesiod.h> 4805f98035SJacques Vidrine #endif 4905f98035SJacques Vidrine #include <netdb.h> 5005f98035SJacques Vidrine #include <nsswitch.h> 5105f98035SJacques Vidrine #include <pthread.h> 5205f98035SJacques Vidrine #include <pthread_np.h> 5305f98035SJacques Vidrine #include <pwd.h> 5405f98035SJacques Vidrine #include <stdlib.h> 5505f98035SJacques Vidrine #include <stdio.h> 5605f98035SJacques Vidrine #include <string.h> 5705f98035SJacques Vidrine #include <syslog.h> 5805f98035SJacques Vidrine #include <unistd.h> 59d201fe46SDaniel Eischen #include "un-namespace.h" 6005f98035SJacques Vidrine #include <db.h> 612bbd7cf8SJacques Vidrine #include "libc_private.h" 62248aee62SJacques Vidrine #include "pw_scan.h" 6305f98035SJacques Vidrine #include "nss_tls.h" 6406a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 6506a99fe3SHajimu UMEMOTO #include "nscache.h" 6606a99fe3SHajimu UMEMOTO #endif 67248aee62SJacques Vidrine 6805f98035SJacques Vidrine #ifndef CTASSERT 6905f98035SJacques Vidrine #define CTASSERT(x) _CTASSERT(x, __LINE__) 7005f98035SJacques Vidrine #define _CTASSERT(x, y) __CTASSERT(x, y) 7105f98035SJacques Vidrine #define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1] 72248aee62SJacques Vidrine #endif 73248aee62SJacques Vidrine 7405f98035SJacques Vidrine /* Counter as stored in /etc/pwd.db */ 7505f98035SJacques Vidrine typedef int pwkeynum; 76adf6ad9eSPeter Wemm 7705f98035SJacques Vidrine CTASSERT(MAXLOGNAME > sizeof(uid_t)); 7805f98035SJacques Vidrine CTASSERT(MAXLOGNAME > sizeof(pwkeynum)); 7994c53e1fSBill Paul 8005f98035SJacques Vidrine enum constants { 8105f98035SJacques Vidrine PWD_STORAGE_INITIAL = 1 << 10, /* 1 KByte */ 8205f98035SJacques Vidrine PWD_STORAGE_MAX = 1 << 20, /* 1 MByte */ 8305f98035SJacques Vidrine SETPWENT = 1, 8405f98035SJacques Vidrine ENDPWENT = 2, 8505f98035SJacques Vidrine HESIOD_NAME_MAX = 256 86248aee62SJacques Vidrine }; 87248aee62SJacques Vidrine 8805f98035SJacques Vidrine static const ns_src defaultsrc[] = { 891b467db2SJacques Vidrine { NSSRC_COMPAT, NS_SUCCESS }, 9005f98035SJacques Vidrine { NULL, 0 } 9105f98035SJacques Vidrine }; 9205f98035SJacques Vidrine 9305f98035SJacques Vidrine int __pw_match_entry(const char *, size_t, enum nss_lookup_type, 9405f98035SJacques Vidrine const char *, uid_t); 9505f98035SJacques Vidrine int __pw_parse_entry(char *, size_t, struct passwd *, int, int *errnop); 9605f98035SJacques Vidrine 97171614bfSJacques Vidrine static void pwd_init(struct passwd *); 984c3c0fecSJacques Vidrine 9905f98035SJacques Vidrine union key { 10005f98035SJacques Vidrine const char *name; 10105f98035SJacques Vidrine uid_t uid; 10205f98035SJacques Vidrine }; 10305f98035SJacques Vidrine 10405f98035SJacques Vidrine static struct passwd *getpw(int (*fn)(union key, struct passwd *, char *, 10505f98035SJacques Vidrine size_t, struct passwd **), union key); 10605f98035SJacques Vidrine static int wrap_getpwnam_r(union key, struct passwd *, char *, 10705f98035SJacques Vidrine size_t, struct passwd **); 10805f98035SJacques Vidrine static int wrap_getpwuid_r(union key, struct passwd *, char *, size_t, 10905f98035SJacques Vidrine struct passwd **); 11005f98035SJacques Vidrine static int wrap_getpwent_r(union key, struct passwd *, char *, size_t, 11105f98035SJacques Vidrine struct passwd **); 11205f98035SJacques Vidrine 11305f98035SJacques Vidrine static int pwdb_match_entry_v3(char *, size_t, enum nss_lookup_type, 11405f98035SJacques Vidrine const char *, uid_t); 11505f98035SJacques Vidrine static int pwdb_parse_entry_v3(char *, size_t, struct passwd *, int *); 11605f98035SJacques Vidrine static int pwdb_match_entry_v4(char *, size_t, enum nss_lookup_type, 11705f98035SJacques Vidrine const char *, uid_t); 11805f98035SJacques Vidrine static int pwdb_parse_entry_v4(char *, size_t, struct passwd *, int *); 11905f98035SJacques Vidrine 12005f98035SJacques Vidrine 12105f98035SJacques Vidrine struct { 12205f98035SJacques Vidrine int (*match)(char *, size_t, enum nss_lookup_type, const char *, 12305f98035SJacques Vidrine uid_t); 12405f98035SJacques Vidrine int (*parse)(char *, size_t, struct passwd *, int *); 12505f98035SJacques Vidrine } pwdb_versions[] = { 12605f98035SJacques Vidrine { NULL, NULL }, /* version 0 */ 12705f98035SJacques Vidrine { NULL, NULL }, /* version 1 */ 12805f98035SJacques Vidrine { NULL, NULL }, /* version 2 */ 12905f98035SJacques Vidrine { pwdb_match_entry_v3, pwdb_parse_entry_v3 }, /* version 3 */ 13005f98035SJacques Vidrine { pwdb_match_entry_v4, pwdb_parse_entry_v4 }, /* version 4 */ 13105f98035SJacques Vidrine }; 13205f98035SJacques Vidrine 13305f98035SJacques Vidrine 13405f98035SJacques Vidrine struct files_state { 13505f98035SJacques Vidrine DB *db; 13605f98035SJacques Vidrine pwkeynum keynum; 13705f98035SJacques Vidrine int stayopen; 13805f98035SJacques Vidrine int version; 13905f98035SJacques Vidrine }; 14005f98035SJacques Vidrine static void files_endstate(void *); 14105f98035SJacques Vidrine NSS_TLS_HANDLING(files); 14205f98035SJacques Vidrine static DB *pwdbopen(int *); 14305f98035SJacques Vidrine static void files_endstate(void *); 14405f98035SJacques Vidrine static int files_setpwent(void *, void *, va_list); 14505f98035SJacques Vidrine static int files_passwd(void *, void *, va_list); 14605f98035SJacques Vidrine 147248aee62SJacques Vidrine 148248aee62SJacques Vidrine #ifdef HESIOD 14905f98035SJacques Vidrine struct dns_state { 15005f98035SJacques Vidrine long counter; 15105f98035SJacques Vidrine }; 15205f98035SJacques Vidrine static void dns_endstate(void *); 15305f98035SJacques Vidrine NSS_TLS_HANDLING(dns); 15405f98035SJacques Vidrine static int dns_setpwent(void *, void *, va_list); 15505f98035SJacques Vidrine static int dns_passwd(void *, void *, va_list); 156248aee62SJacques Vidrine #endif 157248aee62SJacques Vidrine 158248aee62SJacques Vidrine 159248aee62SJacques Vidrine #ifdef YP 16005f98035SJacques Vidrine struct nis_state { 16105f98035SJacques Vidrine char domain[MAXHOSTNAMELEN]; 16205f98035SJacques Vidrine int done; 16305f98035SJacques Vidrine char *key; 16405f98035SJacques Vidrine int keylen; 16505f98035SJacques Vidrine }; 16605f98035SJacques Vidrine static void nis_endstate(void *); 16705f98035SJacques Vidrine NSS_TLS_HANDLING(nis); 16805f98035SJacques Vidrine static int nis_setpwent(void *, void *, va_list); 16905f98035SJacques Vidrine static int nis_passwd(void *, void *, va_list); 17005f98035SJacques Vidrine static int nis_map(char *, enum nss_lookup_type, char *, size_t, int *); 17105f98035SJacques Vidrine static int nis_adjunct(char *, const char *, char *, size_t); 172248aee62SJacques Vidrine #endif 173248aee62SJacques Vidrine 174248aee62SJacques Vidrine 17505f98035SJacques Vidrine struct compat_state { 17605f98035SJacques Vidrine DB *db; 17705f98035SJacques Vidrine pwkeynum keynum; 17805f98035SJacques Vidrine int stayopen; 17905f98035SJacques Vidrine int version; 18005f98035SJacques Vidrine DB *exclude; 18105f98035SJacques Vidrine struct passwd template; 18205f98035SJacques Vidrine char *name; 18305f98035SJacques Vidrine enum _compat { 18405f98035SJacques Vidrine COMPAT_MODE_OFF = 0, 18505f98035SJacques Vidrine COMPAT_MODE_ALL, 18605f98035SJacques Vidrine COMPAT_MODE_NAME, 18705f98035SJacques Vidrine COMPAT_MODE_NETGROUP 18805f98035SJacques Vidrine } compat; 18905f98035SJacques Vidrine }; 19005f98035SJacques Vidrine static void compat_endstate(void *); 19105f98035SJacques Vidrine NSS_TLS_HANDLING(compat); 19205f98035SJacques Vidrine static int compat_setpwent(void *, void *, va_list); 19305f98035SJacques Vidrine static int compat_passwd(void *, void *, va_list); 19405f98035SJacques Vidrine static void compat_clear_template(struct passwd *); 19505f98035SJacques Vidrine static int compat_set_template(struct passwd *, struct passwd *); 19605f98035SJacques Vidrine static int compat_use_template(struct passwd *, struct passwd *, char *, 19705f98035SJacques Vidrine size_t); 19805f98035SJacques Vidrine static int compat_redispatch(struct compat_state *, enum nss_lookup_type, 19905f98035SJacques Vidrine enum nss_lookup_type, const char *, const char *, uid_t, 20005f98035SJacques Vidrine struct passwd *, char *, size_t, int *); 20106a99fe3SHajimu UMEMOTO 20206a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 20306a99fe3SHajimu UMEMOTO static int pwd_id_func(char *, size_t *, va_list ap, void *); 20406a99fe3SHajimu UMEMOTO static int pwd_marshal_func(char *, size_t *, void *, va_list, void *); 20506a99fe3SHajimu UMEMOTO static int pwd_unmarshal_func(char *, size_t, void *, va_list, void *); 20606a99fe3SHajimu UMEMOTO 20706a99fe3SHajimu UMEMOTO static int 20806a99fe3SHajimu UMEMOTO pwd_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) 20906a99fe3SHajimu UMEMOTO { 21006a99fe3SHajimu UMEMOTO char *name; 21106a99fe3SHajimu UMEMOTO uid_t uid; 21206a99fe3SHajimu UMEMOTO size_t size, desired_size; 21306a99fe3SHajimu UMEMOTO int res = NS_UNAVAIL; 21406a99fe3SHajimu UMEMOTO enum nss_lookup_type lookup_type; 21506a99fe3SHajimu UMEMOTO 21606a99fe3SHajimu UMEMOTO lookup_type = (enum nss_lookup_type)cache_mdata; 21706a99fe3SHajimu UMEMOTO switch (lookup_type) { 21806a99fe3SHajimu UMEMOTO case nss_lt_name: 21906a99fe3SHajimu UMEMOTO name = va_arg(ap, char *); 22006a99fe3SHajimu UMEMOTO size = strlen(name); 22106a99fe3SHajimu UMEMOTO desired_size = sizeof(enum nss_lookup_type) + size + 1; 22206a99fe3SHajimu UMEMOTO if (desired_size > *buffer_size) { 22306a99fe3SHajimu UMEMOTO res = NS_RETURN; 22406a99fe3SHajimu UMEMOTO goto fin; 22506a99fe3SHajimu UMEMOTO } 22606a99fe3SHajimu UMEMOTO 22706a99fe3SHajimu UMEMOTO memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 22806a99fe3SHajimu UMEMOTO memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1); 22906a99fe3SHajimu UMEMOTO 23006a99fe3SHajimu UMEMOTO res = NS_SUCCESS; 23106a99fe3SHajimu UMEMOTO break; 23206a99fe3SHajimu UMEMOTO case nss_lt_id: 23306a99fe3SHajimu UMEMOTO uid = va_arg(ap, uid_t); 23406a99fe3SHajimu UMEMOTO desired_size = sizeof(enum nss_lookup_type) + sizeof(uid_t); 23506a99fe3SHajimu UMEMOTO if (desired_size > *buffer_size) { 23606a99fe3SHajimu UMEMOTO res = NS_RETURN; 23706a99fe3SHajimu UMEMOTO goto fin; 23806a99fe3SHajimu UMEMOTO } 23906a99fe3SHajimu UMEMOTO 24006a99fe3SHajimu UMEMOTO memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type)); 24106a99fe3SHajimu UMEMOTO memcpy(buffer + sizeof(enum nss_lookup_type), &uid, 24206a99fe3SHajimu UMEMOTO sizeof(uid_t)); 24306a99fe3SHajimu UMEMOTO 24406a99fe3SHajimu UMEMOTO res = NS_SUCCESS; 24506a99fe3SHajimu UMEMOTO break; 24606a99fe3SHajimu UMEMOTO default: 24706a99fe3SHajimu UMEMOTO /* should be unreachable */ 24806a99fe3SHajimu UMEMOTO return (NS_UNAVAIL); 24906a99fe3SHajimu UMEMOTO } 25006a99fe3SHajimu UMEMOTO 25106a99fe3SHajimu UMEMOTO fin: 25206a99fe3SHajimu UMEMOTO *buffer_size = desired_size; 25306a99fe3SHajimu UMEMOTO return (res); 25406a99fe3SHajimu UMEMOTO } 25506a99fe3SHajimu UMEMOTO 25606a99fe3SHajimu UMEMOTO static int 25706a99fe3SHajimu UMEMOTO pwd_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, 25806a99fe3SHajimu UMEMOTO void *cache_mdata) 25906a99fe3SHajimu UMEMOTO { 26006a99fe3SHajimu UMEMOTO char *name; 26106a99fe3SHajimu UMEMOTO uid_t uid; 26206a99fe3SHajimu UMEMOTO struct passwd *pwd; 26306a99fe3SHajimu UMEMOTO char *orig_buf; 26406a99fe3SHajimu UMEMOTO size_t orig_buf_size; 26506a99fe3SHajimu UMEMOTO 26606a99fe3SHajimu UMEMOTO struct passwd new_pwd; 26706a99fe3SHajimu UMEMOTO size_t desired_size, size; 26806a99fe3SHajimu UMEMOTO char *p; 26906a99fe3SHajimu UMEMOTO 27006a99fe3SHajimu UMEMOTO switch ((enum nss_lookup_type)cache_mdata) { 27106a99fe3SHajimu UMEMOTO case nss_lt_name: 27206a99fe3SHajimu UMEMOTO name = va_arg(ap, char *); 27306a99fe3SHajimu UMEMOTO break; 27406a99fe3SHajimu UMEMOTO case nss_lt_id: 27506a99fe3SHajimu UMEMOTO uid = va_arg(ap, uid_t); 27606a99fe3SHajimu UMEMOTO break; 27706a99fe3SHajimu UMEMOTO case nss_lt_all: 27806a99fe3SHajimu UMEMOTO break; 27906a99fe3SHajimu UMEMOTO default: 28006a99fe3SHajimu UMEMOTO /* should be unreachable */ 28106a99fe3SHajimu UMEMOTO return (NS_UNAVAIL); 28206a99fe3SHajimu UMEMOTO } 28306a99fe3SHajimu UMEMOTO 28406a99fe3SHajimu UMEMOTO pwd = va_arg(ap, struct passwd *); 28506a99fe3SHajimu UMEMOTO orig_buf = va_arg(ap, char *); 28606a99fe3SHajimu UMEMOTO orig_buf_size = va_arg(ap, size_t); 28706a99fe3SHajimu UMEMOTO 28806a99fe3SHajimu UMEMOTO desired_size = sizeof(struct passwd) + sizeof(char *) + 28906a99fe3SHajimu UMEMOTO strlen(pwd->pw_name) + 1; 29006a99fe3SHajimu UMEMOTO if (pwd->pw_passwd != NULL) 29106a99fe3SHajimu UMEMOTO desired_size += strlen(pwd->pw_passwd) + 1; 29206a99fe3SHajimu UMEMOTO if (pwd->pw_class != NULL) 29306a99fe3SHajimu UMEMOTO desired_size += strlen(pwd->pw_class) + 1; 29406a99fe3SHajimu UMEMOTO if (pwd->pw_gecos != NULL) 29506a99fe3SHajimu UMEMOTO desired_size += strlen(pwd->pw_gecos) + 1; 29606a99fe3SHajimu UMEMOTO if (pwd->pw_dir != NULL) 29706a99fe3SHajimu UMEMOTO desired_size += strlen(pwd->pw_dir) + 1; 29806a99fe3SHajimu UMEMOTO if (pwd->pw_shell != NULL) 29906a99fe3SHajimu UMEMOTO desired_size += strlen(pwd->pw_shell) + 1; 30006a99fe3SHajimu UMEMOTO 30106a99fe3SHajimu UMEMOTO if (*buffer_size < desired_size) { 30206a99fe3SHajimu UMEMOTO /* this assignment is here for future use */ 30306a99fe3SHajimu UMEMOTO *buffer_size = desired_size; 30406a99fe3SHajimu UMEMOTO return (NS_RETURN); 30506a99fe3SHajimu UMEMOTO } 30606a99fe3SHajimu UMEMOTO 30706a99fe3SHajimu UMEMOTO memcpy(&new_pwd, pwd, sizeof(struct passwd)); 30806a99fe3SHajimu UMEMOTO memset(buffer, 0, desired_size); 30906a99fe3SHajimu UMEMOTO 31006a99fe3SHajimu UMEMOTO *buffer_size = desired_size; 31106a99fe3SHajimu UMEMOTO p = buffer + sizeof(struct passwd) + sizeof(char *); 31206a99fe3SHajimu UMEMOTO memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *)); 31306a99fe3SHajimu UMEMOTO 31406a99fe3SHajimu UMEMOTO if (new_pwd.pw_name != NULL) { 31506a99fe3SHajimu UMEMOTO size = strlen(new_pwd.pw_name); 31606a99fe3SHajimu UMEMOTO memcpy(p, new_pwd.pw_name, size); 31706a99fe3SHajimu UMEMOTO new_pwd.pw_name = p; 31806a99fe3SHajimu UMEMOTO p += size + 1; 31906a99fe3SHajimu UMEMOTO } 32006a99fe3SHajimu UMEMOTO 32106a99fe3SHajimu UMEMOTO if (new_pwd.pw_passwd != NULL) { 32206a99fe3SHajimu UMEMOTO size = strlen(new_pwd.pw_passwd); 32306a99fe3SHajimu UMEMOTO memcpy(p, new_pwd.pw_passwd, size); 32406a99fe3SHajimu UMEMOTO new_pwd.pw_passwd = p; 32506a99fe3SHajimu UMEMOTO p += size + 1; 32606a99fe3SHajimu UMEMOTO } 32706a99fe3SHajimu UMEMOTO 32806a99fe3SHajimu UMEMOTO if (new_pwd.pw_class != NULL) { 32906a99fe3SHajimu UMEMOTO size = strlen(new_pwd.pw_class); 33006a99fe3SHajimu UMEMOTO memcpy(p, new_pwd.pw_class, size); 33106a99fe3SHajimu UMEMOTO new_pwd.pw_class = p; 33206a99fe3SHajimu UMEMOTO p += size + 1; 33306a99fe3SHajimu UMEMOTO } 33406a99fe3SHajimu UMEMOTO 33506a99fe3SHajimu UMEMOTO if (new_pwd.pw_gecos != NULL) { 33606a99fe3SHajimu UMEMOTO size = strlen(new_pwd.pw_gecos); 33706a99fe3SHajimu UMEMOTO memcpy(p, new_pwd.pw_gecos, size); 33806a99fe3SHajimu UMEMOTO new_pwd.pw_gecos = p; 33906a99fe3SHajimu UMEMOTO p += size + 1; 34006a99fe3SHajimu UMEMOTO } 34106a99fe3SHajimu UMEMOTO 34206a99fe3SHajimu UMEMOTO if (new_pwd.pw_dir != NULL) { 34306a99fe3SHajimu UMEMOTO size = strlen(new_pwd.pw_dir); 34406a99fe3SHajimu UMEMOTO memcpy(p, new_pwd.pw_dir, size); 34506a99fe3SHajimu UMEMOTO new_pwd.pw_dir = p; 34606a99fe3SHajimu UMEMOTO p += size + 1; 34706a99fe3SHajimu UMEMOTO } 34806a99fe3SHajimu UMEMOTO 34906a99fe3SHajimu UMEMOTO if (new_pwd.pw_shell != NULL) { 35006a99fe3SHajimu UMEMOTO size = strlen(new_pwd.pw_shell); 35106a99fe3SHajimu UMEMOTO memcpy(p, new_pwd.pw_shell, size); 35206a99fe3SHajimu UMEMOTO new_pwd.pw_shell = p; 35306a99fe3SHajimu UMEMOTO p += size + 1; 35406a99fe3SHajimu UMEMOTO } 35506a99fe3SHajimu UMEMOTO 35606a99fe3SHajimu UMEMOTO memcpy(buffer, &new_pwd, sizeof(struct passwd)); 35706a99fe3SHajimu UMEMOTO return (NS_SUCCESS); 35806a99fe3SHajimu UMEMOTO } 35906a99fe3SHajimu UMEMOTO 36006a99fe3SHajimu UMEMOTO static int 36106a99fe3SHajimu UMEMOTO pwd_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, 36206a99fe3SHajimu UMEMOTO void *cache_mdata) 36306a99fe3SHajimu UMEMOTO { 36406a99fe3SHajimu UMEMOTO char *name; 36506a99fe3SHajimu UMEMOTO uid_t uid; 36606a99fe3SHajimu UMEMOTO struct passwd *pwd; 36706a99fe3SHajimu UMEMOTO char *orig_buf; 36806a99fe3SHajimu UMEMOTO size_t orig_buf_size; 36906a99fe3SHajimu UMEMOTO int *ret_errno; 37006a99fe3SHajimu UMEMOTO 37106a99fe3SHajimu UMEMOTO char *p; 37206a99fe3SHajimu UMEMOTO 37306a99fe3SHajimu UMEMOTO switch ((enum nss_lookup_type)cache_mdata) { 37406a99fe3SHajimu UMEMOTO case nss_lt_name: 37506a99fe3SHajimu UMEMOTO name = va_arg(ap, char *); 37606a99fe3SHajimu UMEMOTO break; 37706a99fe3SHajimu UMEMOTO case nss_lt_id: 37806a99fe3SHajimu UMEMOTO uid = va_arg(ap, uid_t); 37906a99fe3SHajimu UMEMOTO break; 38006a99fe3SHajimu UMEMOTO case nss_lt_all: 38106a99fe3SHajimu UMEMOTO break; 38206a99fe3SHajimu UMEMOTO default: 38306a99fe3SHajimu UMEMOTO /* should be unreachable */ 38406a99fe3SHajimu UMEMOTO return (NS_UNAVAIL); 38506a99fe3SHajimu UMEMOTO } 38606a99fe3SHajimu UMEMOTO 38706a99fe3SHajimu UMEMOTO pwd = va_arg(ap, struct passwd *); 38806a99fe3SHajimu UMEMOTO orig_buf = va_arg(ap, char *); 38906a99fe3SHajimu UMEMOTO orig_buf_size = va_arg(ap, size_t); 39006a99fe3SHajimu UMEMOTO ret_errno = va_arg(ap, int *); 39106a99fe3SHajimu UMEMOTO 39206a99fe3SHajimu UMEMOTO if (orig_buf_size < 39306a99fe3SHajimu UMEMOTO buffer_size - sizeof(struct passwd) - sizeof(char *)) { 39406a99fe3SHajimu UMEMOTO *ret_errno = ERANGE; 39506a99fe3SHajimu UMEMOTO return (NS_RETURN); 39606a99fe3SHajimu UMEMOTO } 39706a99fe3SHajimu UMEMOTO 39806a99fe3SHajimu UMEMOTO memcpy(pwd, buffer, sizeof(struct passwd)); 39906a99fe3SHajimu UMEMOTO memcpy(&p, buffer + sizeof(struct passwd), sizeof(char *)); 40006a99fe3SHajimu UMEMOTO memcpy(orig_buf, buffer + sizeof(struct passwd) + sizeof(char *), 40106a99fe3SHajimu UMEMOTO buffer_size - sizeof(struct passwd) - sizeof(char *)); 40206a99fe3SHajimu UMEMOTO 40306a99fe3SHajimu UMEMOTO NS_APPLY_OFFSET(pwd->pw_name, orig_buf, p, char *); 40406a99fe3SHajimu UMEMOTO NS_APPLY_OFFSET(pwd->pw_passwd, orig_buf, p, char *); 40506a99fe3SHajimu UMEMOTO NS_APPLY_OFFSET(pwd->pw_class, orig_buf, p, char *); 40606a99fe3SHajimu UMEMOTO NS_APPLY_OFFSET(pwd->pw_gecos, orig_buf, p, char *); 40706a99fe3SHajimu UMEMOTO NS_APPLY_OFFSET(pwd->pw_dir, orig_buf, p, char *); 40806a99fe3SHajimu UMEMOTO NS_APPLY_OFFSET(pwd->pw_shell, orig_buf, p, char *); 40906a99fe3SHajimu UMEMOTO 41006a99fe3SHajimu UMEMOTO if (retval != NULL) 41106a99fe3SHajimu UMEMOTO *((struct passwd **)retval) = pwd; 41206a99fe3SHajimu UMEMOTO 41306a99fe3SHajimu UMEMOTO return (NS_SUCCESS); 41406a99fe3SHajimu UMEMOTO } 41506a99fe3SHajimu UMEMOTO 41606a99fe3SHajimu UMEMOTO NSS_MP_CACHE_HANDLING(passwd); 41706a99fe3SHajimu UMEMOTO #endif /* NS_CACHING */ 41806a99fe3SHajimu UMEMOTO 41905f98035SJacques Vidrine void 42005f98035SJacques Vidrine setpwent(void) 421248aee62SJacques Vidrine { 42206a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 42306a99fe3SHajimu UMEMOTO static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 42406a99fe3SHajimu UMEMOTO passwd, (void *)nss_lt_all, 42506a99fe3SHajimu UMEMOTO NULL, NULL); 42606a99fe3SHajimu UMEMOTO #endif 42706a99fe3SHajimu UMEMOTO 428248aee62SJacques Vidrine static const ns_dtab dtab[] = { 42905f98035SJacques Vidrine { NSSRC_FILES, files_setpwent, (void *)SETPWENT }, 43005f98035SJacques Vidrine #ifdef HESIOD 43105f98035SJacques Vidrine { NSSRC_DNS, dns_setpwent, (void *)SETPWENT }, 43205f98035SJacques Vidrine #endif 43305f98035SJacques Vidrine #ifdef YP 43405f98035SJacques Vidrine { NSSRC_NIS, nis_setpwent, (void *)SETPWENT }, 43505f98035SJacques Vidrine #endif 43605f98035SJacques Vidrine { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT }, 43706a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 43806a99fe3SHajimu UMEMOTO NS_CACHE_CB(&cache_info) 43906a99fe3SHajimu UMEMOTO #endif 44005f98035SJacques Vidrine { NULL, NULL, NULL } 441248aee62SJacques Vidrine }; 44205f98035SJacques Vidrine (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 0); 443248aee62SJacques Vidrine } 444248aee62SJacques Vidrine 44558f0484fSRodney W. Grimes 44658f0484fSRodney W. Grimes int 44705f98035SJacques Vidrine setpassent(int stayopen) 44858f0484fSRodney W. Grimes { 44906a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 45006a99fe3SHajimu UMEMOTO static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 45106a99fe3SHajimu UMEMOTO passwd, (void *)nss_lt_all, 45206a99fe3SHajimu UMEMOTO NULL, NULL); 45306a99fe3SHajimu UMEMOTO #endif 45406a99fe3SHajimu UMEMOTO 45505f98035SJacques Vidrine static const ns_dtab dtab[] = { 45605f98035SJacques Vidrine { NSSRC_FILES, files_setpwent, (void *)SETPWENT }, 457248aee62SJacques Vidrine #ifdef HESIOD 45805f98035SJacques Vidrine { NSSRC_DNS, dns_setpwent, (void *)SETPWENT }, 459248aee62SJacques Vidrine #endif 46094c53e1fSBill Paul #ifdef YP 46105f98035SJacques Vidrine { NSSRC_NIS, nis_setpwent, (void *)SETPWENT }, 462248aee62SJacques Vidrine #endif 46305f98035SJacques Vidrine { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT }, 46406a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 46506a99fe3SHajimu UMEMOTO NS_CACHE_CB(&cache_info) 46606a99fe3SHajimu UMEMOTO #endif 46705f98035SJacques Vidrine { NULL, NULL, NULL } 46805f98035SJacques Vidrine }; 46905f98035SJacques Vidrine (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 47005f98035SJacques Vidrine stayopen); 4713948edc2SBill Paul return (1); 472248aee62SJacques Vidrine } 47305f98035SJacques Vidrine 47405f98035SJacques Vidrine 47505f98035SJacques Vidrine void 47605f98035SJacques Vidrine endpwent(void) 47705f98035SJacques Vidrine { 47806a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 47906a99fe3SHajimu UMEMOTO static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 48006a99fe3SHajimu UMEMOTO passwd, (void *)nss_lt_all, 48106a99fe3SHajimu UMEMOTO NULL, NULL); 48206a99fe3SHajimu UMEMOTO #endif 48306a99fe3SHajimu UMEMOTO 48405f98035SJacques Vidrine static const ns_dtab dtab[] = { 48505f98035SJacques Vidrine { NSSRC_FILES, files_setpwent, (void *)ENDPWENT }, 48605f98035SJacques Vidrine #ifdef HESIOD 48705f98035SJacques Vidrine { NSSRC_DNS, dns_setpwent, (void *)ENDPWENT }, 48805f98035SJacques Vidrine #endif 48905f98035SJacques Vidrine #ifdef YP 49005f98035SJacques Vidrine { NSSRC_NIS, nis_setpwent, (void *)ENDPWENT }, 49105f98035SJacques Vidrine #endif 49205f98035SJacques Vidrine { NSSRC_COMPAT, compat_setpwent, (void *)ENDPWENT }, 49306a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 49406a99fe3SHajimu UMEMOTO NS_CACHE_CB(&cache_info) 49506a99fe3SHajimu UMEMOTO #endif 49605f98035SJacques Vidrine { NULL, NULL, NULL } 49705f98035SJacques Vidrine }; 49805f98035SJacques Vidrine (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "endpwent", defaultsrc); 49905f98035SJacques Vidrine } 50005f98035SJacques Vidrine 50105f98035SJacques Vidrine 50205f98035SJacques Vidrine int 50305f98035SJacques Vidrine getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize, 50405f98035SJacques Vidrine struct passwd **result) 50505f98035SJacques Vidrine { 50606a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 50706a99fe3SHajimu UMEMOTO static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER( 50806a99fe3SHajimu UMEMOTO passwd, (void *)nss_lt_all, 50906a99fe3SHajimu UMEMOTO pwd_marshal_func, pwd_unmarshal_func); 51006a99fe3SHajimu UMEMOTO #endif 51106a99fe3SHajimu UMEMOTO 51205f98035SJacques Vidrine static const ns_dtab dtab[] = { 51305f98035SJacques Vidrine { NSSRC_FILES, files_passwd, (void *)nss_lt_all }, 51405f98035SJacques Vidrine #ifdef HESIOD 51505f98035SJacques Vidrine { NSSRC_DNS, dns_passwd, (void *)nss_lt_all }, 51605f98035SJacques Vidrine #endif 51705f98035SJacques Vidrine #ifdef YP 51805f98035SJacques Vidrine { NSSRC_NIS, nis_passwd, (void *)nss_lt_all }, 51905f98035SJacques Vidrine #endif 52005f98035SJacques Vidrine { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_all }, 52106a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 52206a99fe3SHajimu UMEMOTO NS_CACHE_CB(&cache_info) 52306a99fe3SHajimu UMEMOTO #endif 52405f98035SJacques Vidrine { NULL, NULL, NULL } 52505f98035SJacques Vidrine }; 52605f98035SJacques Vidrine int rv, ret_errno; 52705f98035SJacques Vidrine 528171614bfSJacques Vidrine pwd_init(pwd); 529171614bfSJacques Vidrine ret_errno = 0; 53005f98035SJacques Vidrine *result = NULL; 53105f98035SJacques Vidrine rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwent_r", defaultsrc, 53205f98035SJacques Vidrine pwd, buffer, bufsize, &ret_errno); 53305f98035SJacques Vidrine if (rv == NS_SUCCESS) 53405f98035SJacques Vidrine return (0); 53505f98035SJacques Vidrine else 53605f98035SJacques Vidrine return (ret_errno); 53705f98035SJacques Vidrine } 53805f98035SJacques Vidrine 53905f98035SJacques Vidrine 54005f98035SJacques Vidrine int 54105f98035SJacques Vidrine getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize, 54205f98035SJacques Vidrine struct passwd **result) 54305f98035SJacques Vidrine { 54406a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 54506a99fe3SHajimu UMEMOTO static const nss_cache_info cache_info = 54606a99fe3SHajimu UMEMOTO NS_COMMON_CACHE_INFO_INITIALIZER( 54706a99fe3SHajimu UMEMOTO passwd, (void *)nss_lt_name, 54806a99fe3SHajimu UMEMOTO pwd_id_func, pwd_marshal_func, pwd_unmarshal_func); 54906a99fe3SHajimu UMEMOTO #endif 55006a99fe3SHajimu UMEMOTO 55105f98035SJacques Vidrine static const ns_dtab dtab[] = { 55205f98035SJacques Vidrine { NSSRC_FILES, files_passwd, (void *)nss_lt_name }, 55305f98035SJacques Vidrine #ifdef HESIOD 55405f98035SJacques Vidrine { NSSRC_DNS, dns_passwd, (void *)nss_lt_name }, 55505f98035SJacques Vidrine #endif 55605f98035SJacques Vidrine #ifdef YP 55705f98035SJacques Vidrine { NSSRC_NIS, nis_passwd, (void *)nss_lt_name }, 55805f98035SJacques Vidrine #endif 55905f98035SJacques Vidrine { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_name }, 56006a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 56106a99fe3SHajimu UMEMOTO NS_CACHE_CB(&cache_info) 56206a99fe3SHajimu UMEMOTO #endif 56305f98035SJacques Vidrine { NULL, NULL, NULL } 56405f98035SJacques Vidrine }; 56505f98035SJacques Vidrine int rv, ret_errno; 56605f98035SJacques Vidrine 567171614bfSJacques Vidrine pwd_init(pwd); 568171614bfSJacques Vidrine ret_errno = 0; 56905f98035SJacques Vidrine *result = NULL; 57005f98035SJacques Vidrine rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwnam_r", defaultsrc, 57105f98035SJacques Vidrine name, pwd, buffer, bufsize, &ret_errno); 57205f98035SJacques Vidrine if (rv == NS_SUCCESS) 57305f98035SJacques Vidrine return (0); 57405f98035SJacques Vidrine else 57505f98035SJacques Vidrine return (ret_errno); 57605f98035SJacques Vidrine } 57705f98035SJacques Vidrine 57805f98035SJacques Vidrine 57905f98035SJacques Vidrine int 58005f98035SJacques Vidrine getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, 58105f98035SJacques Vidrine struct passwd **result) 58205f98035SJacques Vidrine { 58306a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 58406a99fe3SHajimu UMEMOTO static const nss_cache_info cache_info = 58506a99fe3SHajimu UMEMOTO NS_COMMON_CACHE_INFO_INITIALIZER( 58606a99fe3SHajimu UMEMOTO passwd, (void *)nss_lt_id, 58706a99fe3SHajimu UMEMOTO pwd_id_func, pwd_marshal_func, pwd_unmarshal_func); 58806a99fe3SHajimu UMEMOTO #endif 58906a99fe3SHajimu UMEMOTO 59005f98035SJacques Vidrine static const ns_dtab dtab[] = { 59105f98035SJacques Vidrine { NSSRC_FILES, files_passwd, (void *)nss_lt_id }, 59205f98035SJacques Vidrine #ifdef HESIOD 59305f98035SJacques Vidrine { NSSRC_DNS, dns_passwd, (void *)nss_lt_id }, 59405f98035SJacques Vidrine #endif 59505f98035SJacques Vidrine #ifdef YP 59605f98035SJacques Vidrine { NSSRC_NIS, nis_passwd, (void *)nss_lt_id }, 59705f98035SJacques Vidrine #endif 59805f98035SJacques Vidrine { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_id }, 59906a99fe3SHajimu UMEMOTO #ifdef NS_CACHING 60006a99fe3SHajimu UMEMOTO NS_CACHE_CB(&cache_info) 60106a99fe3SHajimu UMEMOTO #endif 60205f98035SJacques Vidrine { NULL, NULL, NULL } 60305f98035SJacques Vidrine }; 60405f98035SJacques Vidrine int rv, ret_errno; 60505f98035SJacques Vidrine 606171614bfSJacques Vidrine pwd_init(pwd); 607171614bfSJacques Vidrine ret_errno = 0; 60805f98035SJacques Vidrine *result = NULL; 60905f98035SJacques Vidrine rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwuid_r", defaultsrc, 61005f98035SJacques Vidrine uid, pwd, buffer, bufsize, &ret_errno); 61105f98035SJacques Vidrine if (rv == NS_SUCCESS) 61205f98035SJacques Vidrine return (0); 61305f98035SJacques Vidrine else 61405f98035SJacques Vidrine return (ret_errno); 61505f98035SJacques Vidrine } 61605f98035SJacques Vidrine 61705f98035SJacques Vidrine 618171614bfSJacques Vidrine static void 619171614bfSJacques Vidrine pwd_init(struct passwd *pwd) 6204c3c0fecSJacques Vidrine { 621171614bfSJacques Vidrine static char nul[] = ""; 6224c3c0fecSJacques Vidrine 6234c3c0fecSJacques Vidrine memset(pwd, 0, sizeof(*pwd)); 6244c3c0fecSJacques Vidrine pwd->pw_uid = (uid_t)-1; /* Considered least likely to lead to */ 6254c3c0fecSJacques Vidrine pwd->pw_gid = (gid_t)-1; /* a security issue. */ 626171614bfSJacques Vidrine pwd->pw_name = nul; 627171614bfSJacques Vidrine pwd->pw_passwd = nul; 628171614bfSJacques Vidrine pwd->pw_class = nul; 629171614bfSJacques Vidrine pwd->pw_gecos = nul; 630171614bfSJacques Vidrine pwd->pw_dir = nul; 631171614bfSJacques Vidrine pwd->pw_shell = nul; 6324c3c0fecSJacques Vidrine } 6334c3c0fecSJacques Vidrine 6344c3c0fecSJacques Vidrine 63505f98035SJacques Vidrine static struct passwd pwd; 63605f98035SJacques Vidrine static char *pwd_storage; 63705f98035SJacques Vidrine static size_t pwd_storage_size; 63805f98035SJacques Vidrine 63905f98035SJacques Vidrine 64005f98035SJacques Vidrine static struct passwd * 64105f98035SJacques Vidrine getpw(int (*fn)(union key, struct passwd *, char *, size_t, struct passwd **), 64205f98035SJacques Vidrine union key key) 64305f98035SJacques Vidrine { 64405f98035SJacques Vidrine int rv; 64505f98035SJacques Vidrine struct passwd *res; 64605f98035SJacques Vidrine 64705f98035SJacques Vidrine if (pwd_storage == NULL) { 64805f98035SJacques Vidrine pwd_storage = malloc(PWD_STORAGE_INITIAL); 64905f98035SJacques Vidrine if (pwd_storage == NULL) 65005f98035SJacques Vidrine return (NULL); 65105f98035SJacques Vidrine pwd_storage_size = PWD_STORAGE_INITIAL; 65205f98035SJacques Vidrine } 65305f98035SJacques Vidrine do { 65405f98035SJacques Vidrine rv = fn(key, &pwd, pwd_storage, pwd_storage_size, &res); 65505f98035SJacques Vidrine if (res == NULL && rv == ERANGE) { 65605f98035SJacques Vidrine free(pwd_storage); 65705f98035SJacques Vidrine if ((pwd_storage_size << 1) > PWD_STORAGE_MAX) { 65805f98035SJacques Vidrine pwd_storage = NULL; 659b4cc8687STim Kientzle errno = ERANGE; 66005f98035SJacques Vidrine return (NULL); 66105f98035SJacques Vidrine } 66205f98035SJacques Vidrine pwd_storage_size <<= 1; 66305f98035SJacques Vidrine pwd_storage = malloc(pwd_storage_size); 66405f98035SJacques Vidrine if (pwd_storage == NULL) 66505f98035SJacques Vidrine return (NULL); 66605f98035SJacques Vidrine } 66705f98035SJacques Vidrine } while (res == NULL && rv == ERANGE); 6685edb850fSTim Kientzle if (rv != 0) 669b4cc8687STim Kientzle errno = rv; 67005f98035SJacques Vidrine return (res); 67105f98035SJacques Vidrine } 67205f98035SJacques Vidrine 67305f98035SJacques Vidrine 67405f98035SJacques Vidrine static int 67505f98035SJacques Vidrine wrap_getpwnam_r(union key key, struct passwd *pwd, char *buffer, 67605f98035SJacques Vidrine size_t bufsize, struct passwd **res) 67705f98035SJacques Vidrine { 67805f98035SJacques Vidrine return (getpwnam_r(key.name, pwd, buffer, bufsize, res)); 67905f98035SJacques Vidrine } 68005f98035SJacques Vidrine 68105f98035SJacques Vidrine 68205f98035SJacques Vidrine static int 68305f98035SJacques Vidrine wrap_getpwuid_r(union key key, struct passwd *pwd, char *buffer, 68405f98035SJacques Vidrine size_t bufsize, struct passwd **res) 68505f98035SJacques Vidrine { 68605f98035SJacques Vidrine return (getpwuid_r(key.uid, pwd, buffer, bufsize, res)); 68705f98035SJacques Vidrine } 68805f98035SJacques Vidrine 68905f98035SJacques Vidrine 69005f98035SJacques Vidrine static int 69105f98035SJacques Vidrine wrap_getpwent_r(union key key __unused, struct passwd *pwd, char *buffer, 69205f98035SJacques Vidrine size_t bufsize, struct passwd **res) 69305f98035SJacques Vidrine { 69405f98035SJacques Vidrine return (getpwent_r(pwd, buffer, bufsize, res)); 69505f98035SJacques Vidrine } 69605f98035SJacques Vidrine 69705f98035SJacques Vidrine 69805f98035SJacques Vidrine struct passwd * 69905f98035SJacques Vidrine getpwnam(const char *name) 70005f98035SJacques Vidrine { 70105f98035SJacques Vidrine union key key; 70205f98035SJacques Vidrine 70305f98035SJacques Vidrine key.name = name; 70405f98035SJacques Vidrine return (getpw(wrap_getpwnam_r, key)); 70505f98035SJacques Vidrine } 70605f98035SJacques Vidrine 70705f98035SJacques Vidrine 70805f98035SJacques Vidrine struct passwd * 70905f98035SJacques Vidrine getpwuid(uid_t uid) 71005f98035SJacques Vidrine { 71105f98035SJacques Vidrine union key key; 71205f98035SJacques Vidrine 71305f98035SJacques Vidrine key.uid = uid; 71405f98035SJacques Vidrine return (getpw(wrap_getpwuid_r, key)); 71505f98035SJacques Vidrine } 71605f98035SJacques Vidrine 71705f98035SJacques Vidrine 71805f98035SJacques Vidrine struct passwd * 71905f98035SJacques Vidrine getpwent(void) 72005f98035SJacques Vidrine { 72105f98035SJacques Vidrine union key key; 72205f98035SJacques Vidrine 72305f98035SJacques Vidrine key.uid = 0; /* not used */ 72405f98035SJacques Vidrine return (getpw(wrap_getpwent_r, key)); 72505f98035SJacques Vidrine } 72605f98035SJacques Vidrine 72705f98035SJacques Vidrine 72805f98035SJacques Vidrine /* 72905f98035SJacques Vidrine * files backend 73005f98035SJacques Vidrine */ 73105f98035SJacques Vidrine static DB * 73205f98035SJacques Vidrine pwdbopen(int *version) 73305f98035SJacques Vidrine { 73405f98035SJacques Vidrine DB *res; 73505f98035SJacques Vidrine DBT key, entry; 73605f98035SJacques Vidrine int rv; 73705f98035SJacques Vidrine 73805f98035SJacques Vidrine if (geteuid() != 0 || 73905f98035SJacques Vidrine (res = dbopen(_PATH_SMP_DB, O_RDONLY, 0, DB_HASH, NULL)) == NULL) 74005f98035SJacques Vidrine res = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL); 74105f98035SJacques Vidrine if (res == NULL) 74205f98035SJacques Vidrine return (NULL); 74305f98035SJacques Vidrine key.data = _PWD_VERSION_KEY; 74405f98035SJacques Vidrine key.size = strlen(_PWD_VERSION_KEY); 74505f98035SJacques Vidrine rv = res->get(res, &key, &entry, 0); 74605f98035SJacques Vidrine if (rv == 0) 74705f98035SJacques Vidrine *version = *(unsigned char *)entry.data; 74805f98035SJacques Vidrine else 74905f98035SJacques Vidrine *version = 3; 75005f98035SJacques Vidrine if (*version < 3 || 75105f98035SJacques Vidrine *version >= sizeof(pwdb_versions)/sizeof(pwdb_versions[0])) { 75205f98035SJacques Vidrine syslog(LOG_CRIT, "Unsupported password database version %d", 75305f98035SJacques Vidrine *version); 75405f98035SJacques Vidrine res->close(res); 75505f98035SJacques Vidrine res = NULL; 75605f98035SJacques Vidrine } 75705f98035SJacques Vidrine return (res); 75805f98035SJacques Vidrine } 75905f98035SJacques Vidrine 76005f98035SJacques Vidrine 76105f98035SJacques Vidrine static void 76205f98035SJacques Vidrine files_endstate(void *p) 76305f98035SJacques Vidrine { 76405f98035SJacques Vidrine DB *db; 76505f98035SJacques Vidrine 76605f98035SJacques Vidrine if (p == NULL) 76705f98035SJacques Vidrine return; 76805f98035SJacques Vidrine db = ((struct files_state *)p)->db; 76905f98035SJacques Vidrine if (db != NULL) 77005f98035SJacques Vidrine db->close(db); 77105f98035SJacques Vidrine free(p); 77205f98035SJacques Vidrine } 77305f98035SJacques Vidrine 77405f98035SJacques Vidrine 77505f98035SJacques Vidrine static int 77605f98035SJacques Vidrine files_setpwent(void *retval, void *mdata, va_list ap) 77705f98035SJacques Vidrine { 77805f98035SJacques Vidrine struct files_state *st; 77905f98035SJacques Vidrine int rv, stayopen; 78005f98035SJacques Vidrine 78105f98035SJacques Vidrine rv = files_getstate(&st); 78205f98035SJacques Vidrine if (rv != 0) 78305f98035SJacques Vidrine return (NS_UNAVAIL); 78405f98035SJacques Vidrine switch ((enum constants)mdata) { 78505f98035SJacques Vidrine case SETPWENT: 78605f98035SJacques Vidrine stayopen = va_arg(ap, int); 78705f98035SJacques Vidrine st->keynum = 0; 78805f98035SJacques Vidrine if (stayopen) 78905f98035SJacques Vidrine st->db = pwdbopen(&st->version); 79005f98035SJacques Vidrine st->stayopen = stayopen; 79105f98035SJacques Vidrine break; 79205f98035SJacques Vidrine case ENDPWENT: 79305f98035SJacques Vidrine if (st->db != NULL) { 79405f98035SJacques Vidrine (void)st->db->close(st->db); 79505f98035SJacques Vidrine st->db = NULL; 79605f98035SJacques Vidrine } 79705f98035SJacques Vidrine break; 79805f98035SJacques Vidrine default: 79905f98035SJacques Vidrine break; 80005f98035SJacques Vidrine } 80105f98035SJacques Vidrine return (NS_UNAVAIL); 80205f98035SJacques Vidrine } 80305f98035SJacques Vidrine 80405f98035SJacques Vidrine 80505f98035SJacques Vidrine static int 80605f98035SJacques Vidrine files_passwd(void *retval, void *mdata, va_list ap) 80705f98035SJacques Vidrine { 80805f98035SJacques Vidrine char keybuf[MAXLOGNAME + 1]; 80905f98035SJacques Vidrine DBT key, entry; 81005f98035SJacques Vidrine struct files_state *st; 81105f98035SJacques Vidrine enum nss_lookup_type how; 81205f98035SJacques Vidrine const char *name; 81305f98035SJacques Vidrine struct passwd *pwd; 81405f98035SJacques Vidrine char *buffer; 81505f98035SJacques Vidrine size_t bufsize, namesize; 81605f98035SJacques Vidrine uid_t uid; 81705f98035SJacques Vidrine uint32_t store; 818*09cc2762SPedro F. Giffuni int rv, stayopen = 0, *errnop; 81905f98035SJacques Vidrine 82005f98035SJacques Vidrine name = NULL; 82105f98035SJacques Vidrine uid = (uid_t)-1; 82205f98035SJacques Vidrine how = (enum nss_lookup_type)mdata; 82305f98035SJacques Vidrine switch (how) { 82405f98035SJacques Vidrine case nss_lt_name: 82505f98035SJacques Vidrine name = va_arg(ap, const char *); 82605f98035SJacques Vidrine keybuf[0] = _PW_KEYBYNAME; 82705f98035SJacques Vidrine break; 82805f98035SJacques Vidrine case nss_lt_id: 82905f98035SJacques Vidrine uid = va_arg(ap, uid_t); 83005f98035SJacques Vidrine keybuf[0] = _PW_KEYBYUID; 83105f98035SJacques Vidrine break; 83205f98035SJacques Vidrine case nss_lt_all: 83305f98035SJacques Vidrine keybuf[0] = _PW_KEYBYNUM; 83405f98035SJacques Vidrine break; 83505f98035SJacques Vidrine default: 83605f98035SJacques Vidrine rv = NS_NOTFOUND; 83705f98035SJacques Vidrine goto fin; 83805f98035SJacques Vidrine } 83905f98035SJacques Vidrine pwd = va_arg(ap, struct passwd *); 84005f98035SJacques Vidrine buffer = va_arg(ap, char *); 84105f98035SJacques Vidrine bufsize = va_arg(ap, size_t); 84205f98035SJacques Vidrine errnop = va_arg(ap, int *); 84305f98035SJacques Vidrine *errnop = files_getstate(&st); 84405f98035SJacques Vidrine if (*errnop != 0) 84505f98035SJacques Vidrine return (NS_UNAVAIL); 84605f98035SJacques Vidrine if (how == nss_lt_all && st->keynum < 0) { 84705f98035SJacques Vidrine rv = NS_NOTFOUND; 84805f98035SJacques Vidrine goto fin; 84905f98035SJacques Vidrine } 85005f98035SJacques Vidrine if (st->db == NULL && 85105f98035SJacques Vidrine (st->db = pwdbopen(&st->version)) == NULL) { 85205f98035SJacques Vidrine *errnop = errno; 85305f98035SJacques Vidrine rv = NS_UNAVAIL; 85405f98035SJacques Vidrine goto fin; 85505f98035SJacques Vidrine } 85605f98035SJacques Vidrine if (how == nss_lt_all) 85705f98035SJacques Vidrine stayopen = 1; 85805f98035SJacques Vidrine else 85905f98035SJacques Vidrine stayopen = st->stayopen; 86005f98035SJacques Vidrine key.data = keybuf; 86105f98035SJacques Vidrine do { 86205f98035SJacques Vidrine switch (how) { 86305f98035SJacques Vidrine case nss_lt_name: 86405f98035SJacques Vidrine /* MAXLOGNAME includes NUL byte, but we do not 86505f98035SJacques Vidrine * include the NUL byte in the key. 86605f98035SJacques Vidrine */ 867d0509082SJacques Vidrine namesize = strlcpy(&keybuf[1], name, sizeof(keybuf)-1); 86805f98035SJacques Vidrine if (namesize >= sizeof(keybuf)-1) { 86905f98035SJacques Vidrine *errnop = EINVAL; 87005f98035SJacques Vidrine rv = NS_NOTFOUND; 87105f98035SJacques Vidrine goto fin; 87205f98035SJacques Vidrine } 87305f98035SJacques Vidrine key.size = namesize + 1; 87405f98035SJacques Vidrine break; 87505f98035SJacques Vidrine case nss_lt_id: 87605f98035SJacques Vidrine if (st->version < _PWD_CURRENT_VERSION) { 87705f98035SJacques Vidrine memcpy(&keybuf[1], &uid, sizeof(uid)); 87805f98035SJacques Vidrine key.size = sizeof(uid) + 1; 87905f98035SJacques Vidrine } else { 88005f98035SJacques Vidrine store = htonl(uid); 88105f98035SJacques Vidrine memcpy(&keybuf[1], &store, sizeof(store)); 88205f98035SJacques Vidrine key.size = sizeof(store) + 1; 88305f98035SJacques Vidrine } 88405f98035SJacques Vidrine break; 88505f98035SJacques Vidrine case nss_lt_all: 88605f98035SJacques Vidrine st->keynum++; 88705f98035SJacques Vidrine if (st->version < _PWD_CURRENT_VERSION) { 88805f98035SJacques Vidrine memcpy(&keybuf[1], &st->keynum, 88905f98035SJacques Vidrine sizeof(st->keynum)); 89005f98035SJacques Vidrine key.size = sizeof(st->keynum) + 1; 89105f98035SJacques Vidrine } else { 89205f98035SJacques Vidrine store = htonl(st->keynum); 89305f98035SJacques Vidrine memcpy(&keybuf[1], &store, sizeof(store)); 89405f98035SJacques Vidrine key.size = sizeof(store) + 1; 89505f98035SJacques Vidrine } 89605f98035SJacques Vidrine break; 89705f98035SJacques Vidrine } 898b4603f3dSJacques Vidrine keybuf[0] = _PW_VERSIONED(keybuf[0], st->version); 89905f98035SJacques Vidrine rv = st->db->get(st->db, &key, &entry, 0); 90005f98035SJacques Vidrine if (rv < 0 || rv > 1) { /* should never return > 1 */ 90105f98035SJacques Vidrine *errnop = errno; 90205f98035SJacques Vidrine rv = NS_UNAVAIL; 90305f98035SJacques Vidrine goto fin; 90405f98035SJacques Vidrine } else if (rv == 1) { 90505f98035SJacques Vidrine if (how == nss_lt_all) 90605f98035SJacques Vidrine st->keynum = -1; 90705f98035SJacques Vidrine rv = NS_NOTFOUND; 90805f98035SJacques Vidrine goto fin; 90905f98035SJacques Vidrine } 91005f98035SJacques Vidrine rv = pwdb_versions[st->version].match(entry.data, entry.size, 91105f98035SJacques Vidrine how, name, uid); 91205f98035SJacques Vidrine if (rv != NS_SUCCESS) 91305f98035SJacques Vidrine continue; 91405f98035SJacques Vidrine if (entry.size > bufsize) { 91505f98035SJacques Vidrine *errnop = ERANGE; 91605f98035SJacques Vidrine rv = NS_RETURN; 91705f98035SJacques Vidrine break; 91805f98035SJacques Vidrine } 91905f98035SJacques Vidrine memcpy(buffer, entry.data, entry.size); 92005f98035SJacques Vidrine rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd, 92105f98035SJacques Vidrine errnop); 92205f98035SJacques Vidrine } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 92305f98035SJacques Vidrine fin: 924eb77fbdcSPedro F. Giffuni if (st->db != NULL && !stayopen) { 92505f98035SJacques Vidrine (void)st->db->close(st->db); 92605f98035SJacques Vidrine st->db = NULL; 92705f98035SJacques Vidrine } 92871cc8f07SJacques Vidrine if (rv == NS_SUCCESS) { 92971cc8f07SJacques Vidrine pwd->pw_fields &= ~_PWF_SOURCE; 93071cc8f07SJacques Vidrine pwd->pw_fields |= _PWF_FILES; 93171cc8f07SJacques Vidrine if (retval != NULL) 93205f98035SJacques Vidrine *(struct passwd **)retval = pwd; 93371cc8f07SJacques Vidrine } 93405f98035SJacques Vidrine return (rv); 93505f98035SJacques Vidrine } 93605f98035SJacques Vidrine 93705f98035SJacques Vidrine 93805f98035SJacques Vidrine static int 93905f98035SJacques Vidrine pwdb_match_entry_v3(char *entry, size_t entrysize, enum nss_lookup_type how, 94005f98035SJacques Vidrine const char *name, uid_t uid) 94105f98035SJacques Vidrine { 94205f98035SJacques Vidrine const char *p, *eom; 94305f98035SJacques Vidrine uid_t uid2; 94405f98035SJacques Vidrine 94505f98035SJacques Vidrine eom = &entry[entrysize]; 94605f98035SJacques Vidrine for (p = entry; p < eom; p++) 94705f98035SJacques Vidrine if (*p == '\0') 94805f98035SJacques Vidrine break; 94905f98035SJacques Vidrine if (*p != '\0') 95005f98035SJacques Vidrine return (NS_NOTFOUND); 95105f98035SJacques Vidrine if (how == nss_lt_all) 95205f98035SJacques Vidrine return (NS_SUCCESS); 95305f98035SJacques Vidrine if (how == nss_lt_name) 95405f98035SJacques Vidrine return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND); 95505f98035SJacques Vidrine for (p++; p < eom; p++) 95605f98035SJacques Vidrine if (*p == '\0') 95705f98035SJacques Vidrine break; 95805f98035SJacques Vidrine if (*p != '\0' || (++p) + sizeof(uid) >= eom) 95905f98035SJacques Vidrine return (NS_NOTFOUND); 96005f98035SJacques Vidrine memcpy(&uid2, p, sizeof(uid2)); 96105f98035SJacques Vidrine return (uid == uid2 ? NS_SUCCESS : NS_NOTFOUND); 96205f98035SJacques Vidrine } 96305f98035SJacques Vidrine 96405f98035SJacques Vidrine 96505f98035SJacques Vidrine static int 96605f98035SJacques Vidrine pwdb_parse_entry_v3(char *buffer, size_t bufsize, struct passwd *pwd, 96705f98035SJacques Vidrine int *errnop) 96805f98035SJacques Vidrine { 96905f98035SJacques Vidrine char *p, *eom; 97005f98035SJacques Vidrine int32_t pw_change, pw_expire; 97105f98035SJacques Vidrine 97205f98035SJacques Vidrine /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 97305f98035SJacques Vidrine p = buffer; 97405f98035SJacques Vidrine eom = &buffer[bufsize]; 97505f98035SJacques Vidrine #define STRING(field) do { \ 97605f98035SJacques Vidrine (field) = p; \ 97705f98035SJacques Vidrine while (p < eom && *p != '\0') \ 97805f98035SJacques Vidrine p++; \ 97905f98035SJacques Vidrine if (p >= eom) \ 98005f98035SJacques Vidrine return (NS_NOTFOUND); \ 98105f98035SJacques Vidrine p++; \ 98205f98035SJacques Vidrine } while (0) 98305f98035SJacques Vidrine #define SCALAR(field) do { \ 98405f98035SJacques Vidrine if (p + sizeof(field) > eom) \ 98505f98035SJacques Vidrine return (NS_NOTFOUND); \ 98605f98035SJacques Vidrine memcpy(&(field), p, sizeof(field)); \ 98705f98035SJacques Vidrine p += sizeof(field); \ 98805f98035SJacques Vidrine } while (0) 98905f98035SJacques Vidrine STRING(pwd->pw_name); 99005f98035SJacques Vidrine STRING(pwd->pw_passwd); 99105f98035SJacques Vidrine SCALAR(pwd->pw_uid); 99205f98035SJacques Vidrine SCALAR(pwd->pw_gid); 99305f98035SJacques Vidrine SCALAR(pw_change); 99405f98035SJacques Vidrine STRING(pwd->pw_class); 99505f98035SJacques Vidrine STRING(pwd->pw_gecos); 99605f98035SJacques Vidrine STRING(pwd->pw_dir); 99705f98035SJacques Vidrine STRING(pwd->pw_shell); 99805f98035SJacques Vidrine SCALAR(pw_expire); 99905f98035SJacques Vidrine SCALAR(pwd->pw_fields); 100005f98035SJacques Vidrine #undef STRING 100105f98035SJacques Vidrine #undef SCALAR 100205f98035SJacques Vidrine pwd->pw_change = pw_change; 100305f98035SJacques Vidrine pwd->pw_expire = pw_expire; 100405f98035SJacques Vidrine return (NS_SUCCESS); 100505f98035SJacques Vidrine } 100605f98035SJacques Vidrine 100705f98035SJacques Vidrine 100805f98035SJacques Vidrine static int 100905f98035SJacques Vidrine pwdb_match_entry_v4(char *entry, size_t entrysize, enum nss_lookup_type how, 101005f98035SJacques Vidrine const char *name, uid_t uid) 101105f98035SJacques Vidrine { 101205f98035SJacques Vidrine const char *p, *eom; 101305f98035SJacques Vidrine uint32_t uid2; 101405f98035SJacques Vidrine 101505f98035SJacques Vidrine eom = &entry[entrysize]; 101605f98035SJacques Vidrine for (p = entry; p < eom; p++) 101705f98035SJacques Vidrine if (*p == '\0') 101805f98035SJacques Vidrine break; 101905f98035SJacques Vidrine if (*p != '\0') 102005f98035SJacques Vidrine return (NS_NOTFOUND); 102105f98035SJacques Vidrine if (how == nss_lt_all) 102205f98035SJacques Vidrine return (NS_SUCCESS); 102305f98035SJacques Vidrine if (how == nss_lt_name) 102405f98035SJacques Vidrine return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND); 102505f98035SJacques Vidrine for (p++; p < eom; p++) 102605f98035SJacques Vidrine if (*p == '\0') 102705f98035SJacques Vidrine break; 102805f98035SJacques Vidrine if (*p != '\0' || (++p) + sizeof(uid) >= eom) 102905f98035SJacques Vidrine return (NS_NOTFOUND); 103005f98035SJacques Vidrine memcpy(&uid2, p, sizeof(uid2)); 103105f98035SJacques Vidrine uid2 = ntohl(uid2); 103205f98035SJacques Vidrine return (uid == (uid_t)uid2 ? NS_SUCCESS : NS_NOTFOUND); 103305f98035SJacques Vidrine } 103405f98035SJacques Vidrine 103505f98035SJacques Vidrine 103605f98035SJacques Vidrine static int 103705f98035SJacques Vidrine pwdb_parse_entry_v4(char *buffer, size_t bufsize, struct passwd *pwd, 103805f98035SJacques Vidrine int *errnop) 103905f98035SJacques Vidrine { 104005f98035SJacques Vidrine char *p, *eom; 104105f98035SJacques Vidrine uint32_t n; 104205f98035SJacques Vidrine 104305f98035SJacques Vidrine /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */ 104405f98035SJacques Vidrine p = buffer; 104505f98035SJacques Vidrine eom = &buffer[bufsize]; 104605f98035SJacques Vidrine #define STRING(field) do { \ 104705f98035SJacques Vidrine (field) = p; \ 104805f98035SJacques Vidrine while (p < eom && *p != '\0') \ 104905f98035SJacques Vidrine p++; \ 105005f98035SJacques Vidrine if (p >= eom) \ 105105f98035SJacques Vidrine return (NS_NOTFOUND); \ 105205f98035SJacques Vidrine p++; \ 105305f98035SJacques Vidrine } while (0) 105405f98035SJacques Vidrine #define SCALAR(field) do { \ 105505f98035SJacques Vidrine if (p + sizeof(n) > eom) \ 105605f98035SJacques Vidrine return (NS_NOTFOUND); \ 105705f98035SJacques Vidrine memcpy(&n, p, sizeof(n)); \ 105805f98035SJacques Vidrine (field) = ntohl(n); \ 105905f98035SJacques Vidrine p += sizeof(n); \ 106005f98035SJacques Vidrine } while (0) 106105f98035SJacques Vidrine STRING(pwd->pw_name); 106205f98035SJacques Vidrine STRING(pwd->pw_passwd); 106305f98035SJacques Vidrine SCALAR(pwd->pw_uid); 106405f98035SJacques Vidrine SCALAR(pwd->pw_gid); 106505f98035SJacques Vidrine SCALAR(pwd->pw_change); 106605f98035SJacques Vidrine STRING(pwd->pw_class); 106705f98035SJacques Vidrine STRING(pwd->pw_gecos); 106805f98035SJacques Vidrine STRING(pwd->pw_dir); 106905f98035SJacques Vidrine STRING(pwd->pw_shell); 107005f98035SJacques Vidrine SCALAR(pwd->pw_expire); 107105f98035SJacques Vidrine SCALAR(pwd->pw_fields); 107205f98035SJacques Vidrine #undef STRING 107305f98035SJacques Vidrine #undef SCALAR 107405f98035SJacques Vidrine return (NS_SUCCESS); 107505f98035SJacques Vidrine } 107605f98035SJacques Vidrine 107705f98035SJacques Vidrine 107805f98035SJacques Vidrine #ifdef HESIOD 107905f98035SJacques Vidrine /* 108005f98035SJacques Vidrine * dns backend 108105f98035SJacques Vidrine */ 108205f98035SJacques Vidrine static void 108305f98035SJacques Vidrine dns_endstate(void *p) 108405f98035SJacques Vidrine { 108505f98035SJacques Vidrine free(p); 108605f98035SJacques Vidrine } 108705f98035SJacques Vidrine 108805f98035SJacques Vidrine 108905f98035SJacques Vidrine static int 109005f98035SJacques Vidrine dns_setpwent(void *retval, void *mdata, va_list ap) 109105f98035SJacques Vidrine { 109205f98035SJacques Vidrine struct dns_state *st; 109305f98035SJacques Vidrine int rv; 109405f98035SJacques Vidrine 109505f98035SJacques Vidrine rv = dns_getstate(&st); 109605f98035SJacques Vidrine if (rv != 0) 109705f98035SJacques Vidrine return (NS_UNAVAIL); 109805f98035SJacques Vidrine st->counter = 0; 109905f98035SJacques Vidrine return (NS_UNAVAIL); 110005f98035SJacques Vidrine } 110105f98035SJacques Vidrine 110205f98035SJacques Vidrine 110305f98035SJacques Vidrine static int 110405f98035SJacques Vidrine dns_passwd(void *retval, void *mdata, va_list ap) 110505f98035SJacques Vidrine { 110605f98035SJacques Vidrine char buf[HESIOD_NAME_MAX]; 110705f98035SJacques Vidrine struct dns_state *st; 110805f98035SJacques Vidrine struct passwd *pwd; 110905f98035SJacques Vidrine const char *name, *label; 111005f98035SJacques Vidrine void *ctx; 111105f98035SJacques Vidrine char *buffer, **hes; 111205f98035SJacques Vidrine size_t bufsize, linesize; 111305f98035SJacques Vidrine uid_t uid; 111405f98035SJacques Vidrine enum nss_lookup_type how; 111505f98035SJacques Vidrine int rv, *errnop; 111605f98035SJacques Vidrine 111705f98035SJacques Vidrine ctx = NULL; 111805f98035SJacques Vidrine hes = NULL; 111905f98035SJacques Vidrine name = NULL; 112005f98035SJacques Vidrine uid = (uid_t)-1; 112105f98035SJacques Vidrine how = (enum nss_lookup_type)mdata; 112205f98035SJacques Vidrine switch (how) { 112305f98035SJacques Vidrine case nss_lt_name: 112405f98035SJacques Vidrine name = va_arg(ap, const char *); 112505f98035SJacques Vidrine break; 112605f98035SJacques Vidrine case nss_lt_id: 112705f98035SJacques Vidrine uid = va_arg(ap, uid_t); 112805f98035SJacques Vidrine break; 112905f98035SJacques Vidrine case nss_lt_all: 113005f98035SJacques Vidrine break; 113105f98035SJacques Vidrine } 113205f98035SJacques Vidrine pwd = va_arg(ap, struct passwd *); 113305f98035SJacques Vidrine buffer = va_arg(ap, char *); 113405f98035SJacques Vidrine bufsize = va_arg(ap, size_t); 113505f98035SJacques Vidrine errnop = va_arg(ap, int *); 113605f98035SJacques Vidrine *errnop = dns_getstate(&st); 113705f98035SJacques Vidrine if (*errnop != 0) 113805f98035SJacques Vidrine return (NS_UNAVAIL); 113905f98035SJacques Vidrine if (hesiod_init(&ctx) != 0) { 114005f98035SJacques Vidrine *errnop = errno; 114105f98035SJacques Vidrine rv = NS_UNAVAIL; 114205f98035SJacques Vidrine goto fin; 114305f98035SJacques Vidrine } 114405f98035SJacques Vidrine do { 114505f98035SJacques Vidrine rv = NS_NOTFOUND; 114605f98035SJacques Vidrine switch (how) { 114705f98035SJacques Vidrine case nss_lt_name: 114805f98035SJacques Vidrine label = name; 114905f98035SJacques Vidrine break; 115005f98035SJacques Vidrine case nss_lt_id: 115105f98035SJacques Vidrine if (snprintf(buf, sizeof(buf), "%lu", 115205f98035SJacques Vidrine (unsigned long)uid) >= sizeof(buf)) 115305f98035SJacques Vidrine goto fin; 115405f98035SJacques Vidrine label = buf; 115505f98035SJacques Vidrine break; 115605f98035SJacques Vidrine case nss_lt_all: 115705f98035SJacques Vidrine if (st->counter < 0) 115805f98035SJacques Vidrine goto fin; 115905f98035SJacques Vidrine if (snprintf(buf, sizeof(buf), "passwd-%ld", 116005f98035SJacques Vidrine st->counter++) >= sizeof(buf)) 116105f98035SJacques Vidrine goto fin; 116205f98035SJacques Vidrine label = buf; 116305f98035SJacques Vidrine break; 116405f98035SJacques Vidrine } 116505f98035SJacques Vidrine hes = hesiod_resolve(ctx, label, 116605f98035SJacques Vidrine how == nss_lt_id ? "uid" : "passwd"); 116705f98035SJacques Vidrine if (hes == NULL) { 116805f98035SJacques Vidrine if (how == nss_lt_all) 116905f98035SJacques Vidrine st->counter = -1; 117005f98035SJacques Vidrine if (errno != ENOENT) 117105f98035SJacques Vidrine *errnop = errno; 117205f98035SJacques Vidrine goto fin; 117305f98035SJacques Vidrine } 117405f98035SJacques Vidrine rv = __pw_match_entry(hes[0], strlen(hes[0]), how, name, uid); 117505f98035SJacques Vidrine if (rv != NS_SUCCESS) { 117605f98035SJacques Vidrine hesiod_free_list(ctx, hes); 117705f98035SJacques Vidrine hes = NULL; 117805f98035SJacques Vidrine continue; 117905f98035SJacques Vidrine } 1180d0509082SJacques Vidrine linesize = strlcpy(buffer, hes[0], bufsize); 118105f98035SJacques Vidrine if (linesize >= bufsize) { 118205f98035SJacques Vidrine *errnop = ERANGE; 118305f98035SJacques Vidrine rv = NS_RETURN; 118405f98035SJacques Vidrine continue; 118505f98035SJacques Vidrine } 118605f98035SJacques Vidrine hesiod_free_list(ctx, hes); 118705f98035SJacques Vidrine hes = NULL; 118805f98035SJacques Vidrine rv = __pw_parse_entry(buffer, bufsize, pwd, 0, errnop); 118905f98035SJacques Vidrine } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 119005f98035SJacques Vidrine fin: 119105f98035SJacques Vidrine if (hes != NULL) 119205f98035SJacques Vidrine hesiod_free_list(ctx, hes); 119305f98035SJacques Vidrine if (ctx != NULL) 119405f98035SJacques Vidrine hesiod_end(ctx); 119505f98035SJacques Vidrine if (rv == NS_SUCCESS) { 119605f98035SJacques Vidrine pwd->pw_fields &= ~_PWF_SOURCE; 119705f98035SJacques Vidrine pwd->pw_fields |= _PWF_HESIOD; 119805f98035SJacques Vidrine if (retval != NULL) 119905f98035SJacques Vidrine *(struct passwd **)retval = pwd; 120005f98035SJacques Vidrine } 120105f98035SJacques Vidrine return (rv); 120205f98035SJacques Vidrine } 120305f98035SJacques Vidrine #endif /* HESIOD */ 120405f98035SJacques Vidrine 120505f98035SJacques Vidrine 120605f98035SJacques Vidrine #ifdef YP 120705f98035SJacques Vidrine /* 120805f98035SJacques Vidrine * nis backend 120905f98035SJacques Vidrine */ 121005f98035SJacques Vidrine static void 121105f98035SJacques Vidrine nis_endstate(void *p) 121205f98035SJacques Vidrine { 121305f98035SJacques Vidrine free(((struct nis_state *)p)->key); 121405f98035SJacques Vidrine free(p); 121558f0484fSRodney W. Grimes } 121658f0484fSRodney W. Grimes 12170287aa1cSBill Paul /* 12180287aa1cSBill Paul * Test for the presence of special FreeBSD-specific master.passwd.by* 12190287aa1cSBill Paul * maps. We do this using yp_order(). If it fails, then either the server 12200287aa1cSBill Paul * doesn't have the map, or the YPPROC_ORDER procedure isn't supported by 12210287aa1cSBill Paul * the server (Sun NIS+ servers in YP compat mode behave this way). If 12220287aa1cSBill Paul * the master.passwd.by* maps don't exist, then let the lookup routine try 12230287aa1cSBill Paul * the regular passwd.by* maps instead. If the lookup routine fails, it 12240287aa1cSBill Paul * can return an error as needed. 12250287aa1cSBill Paul */ 122651295a4dSJordan K. Hubbard static int 122705f98035SJacques Vidrine nis_map(char *domain, enum nss_lookup_type how, char *buffer, size_t bufsize, 122805f98035SJacques Vidrine int *master) 122958f0484fSRodney W. Grimes { 12300287aa1cSBill Paul int rv, order; 123158f0484fSRodney W. Grimes 123205f98035SJacques Vidrine *master = 0; 1233d3fc864fSJacques Vidrine if (geteuid() == 0) { 123405f98035SJacques Vidrine if (snprintf(buffer, bufsize, "master.passwd.by%s", 123505f98035SJacques Vidrine (how == nss_lt_id) ? "uid" : "name") >= bufsize) 123605f98035SJacques Vidrine return (NS_UNAVAIL); 12370287aa1cSBill Paul rv = yp_order(domain, buffer, &order); 123805f98035SJacques Vidrine if (rv == 0) { 123905f98035SJacques Vidrine *master = 1; 124005f98035SJacques Vidrine return (NS_SUCCESS); 124105f98035SJacques Vidrine } 1242d3fc864fSJacques Vidrine } 12430287aa1cSBill Paul 124405f98035SJacques Vidrine if (snprintf(buffer, bufsize, "passwd.by%s", 124505f98035SJacques Vidrine (how == nss_lt_id) ? "uid" : "name") >= bufsize) 124605f98035SJacques Vidrine return (NS_UNAVAIL); 12470287aa1cSBill Paul 124805f98035SJacques Vidrine return (NS_SUCCESS); 12498be26e5dSWolfram Schneider } 125058f0484fSRodney W. Grimes 1251248aee62SJacques Vidrine 125205f98035SJacques Vidrine static int 125305f98035SJacques Vidrine nis_adjunct(char *domain, const char *name, char *buffer, size_t bufsize) 125405f98035SJacques Vidrine { 125505f98035SJacques Vidrine int rv; 125605f98035SJacques Vidrine char *result, *p, *q, *eor; 125705f98035SJacques Vidrine int resultlen; 1258248aee62SJacques Vidrine 125905f98035SJacques Vidrine result = NULL; 126005f98035SJacques Vidrine rv = yp_match(domain, "passwd.adjunct.byname", name, strlen(name), 126105f98035SJacques Vidrine &result, &resultlen); 126205f98035SJacques Vidrine if (rv != 0) 126305f98035SJacques Vidrine rv = 1; 126405f98035SJacques Vidrine else { 126505f98035SJacques Vidrine eor = &result[resultlen]; 126605f98035SJacques Vidrine p = memchr(result, ':', eor - result); 126705f98035SJacques Vidrine if (p != NULL && ++p < eor && 126805f98035SJacques Vidrine (q = memchr(p, ':', eor - p)) != NULL) { 126905f98035SJacques Vidrine if (q - p >= bufsize) 127005f98035SJacques Vidrine rv = -1; 127105f98035SJacques Vidrine else { 127205f98035SJacques Vidrine memcpy(buffer, p, q - p); 127305f98035SJacques Vidrine buffer[q - p] ='\0'; 127405f98035SJacques Vidrine } 127505f98035SJacques Vidrine } else 127605f98035SJacques Vidrine rv = 1; 127705f98035SJacques Vidrine } 127805f98035SJacques Vidrine free(result); 127905f98035SJacques Vidrine return (rv); 128005f98035SJacques Vidrine } 128105f98035SJacques Vidrine 128205f98035SJacques Vidrine 128305f98035SJacques Vidrine static int 128405f98035SJacques Vidrine nis_setpwent(void *retval, void *mdata, va_list ap) 128505f98035SJacques Vidrine { 128605f98035SJacques Vidrine struct nis_state *st; 128705f98035SJacques Vidrine int rv; 128805f98035SJacques Vidrine 128905f98035SJacques Vidrine rv = nis_getstate(&st); 129005f98035SJacques Vidrine if (rv != 0) 129105f98035SJacques Vidrine return (NS_UNAVAIL); 129205f98035SJacques Vidrine st->done = 0; 129305f98035SJacques Vidrine free(st->key); 129405f98035SJacques Vidrine st->key = NULL; 129505f98035SJacques Vidrine return (NS_UNAVAIL); 129605f98035SJacques Vidrine } 129705f98035SJacques Vidrine 129805f98035SJacques Vidrine 129905f98035SJacques Vidrine static int 130005f98035SJacques Vidrine nis_passwd(void *retval, void *mdata, va_list ap) 130105f98035SJacques Vidrine { 130205f98035SJacques Vidrine char map[YPMAXMAP]; 130305f98035SJacques Vidrine struct nis_state *st; 130405f98035SJacques Vidrine struct passwd *pwd; 130505f98035SJacques Vidrine const char *name; 130605f98035SJacques Vidrine char *buffer, *key, *result; 130705f98035SJacques Vidrine size_t bufsize; 130805f98035SJacques Vidrine uid_t uid; 130905f98035SJacques Vidrine enum nss_lookup_type how; 131005f98035SJacques Vidrine int *errnop, keylen, resultlen, rv, master; 131105f98035SJacques Vidrine 131205f98035SJacques Vidrine name = NULL; 131305f98035SJacques Vidrine uid = (uid_t)-1; 131405f98035SJacques Vidrine how = (enum nss_lookup_type)mdata; 131505f98035SJacques Vidrine switch (how) { 131605f98035SJacques Vidrine case nss_lt_name: 131705f98035SJacques Vidrine name = va_arg(ap, const char *); 131805f98035SJacques Vidrine break; 131905f98035SJacques Vidrine case nss_lt_id: 132005f98035SJacques Vidrine uid = va_arg(ap, uid_t); 132105f98035SJacques Vidrine break; 132205f98035SJacques Vidrine case nss_lt_all: 132305f98035SJacques Vidrine break; 132405f98035SJacques Vidrine } 132505f98035SJacques Vidrine pwd = va_arg(ap, struct passwd *); 132605f98035SJacques Vidrine buffer = va_arg(ap, char *); 132705f98035SJacques Vidrine bufsize = va_arg(ap, size_t); 132805f98035SJacques Vidrine errnop = va_arg(ap, int *); 132905f98035SJacques Vidrine *errnop = nis_getstate(&st); 133005f98035SJacques Vidrine if (*errnop != 0) 133105f98035SJacques Vidrine return (NS_UNAVAIL); 133205f98035SJacques Vidrine if (st->domain[0] == '\0') { 133305f98035SJacques Vidrine if (getdomainname(st->domain, sizeof(st->domain)) != 0) { 133405f98035SJacques Vidrine *errnop = errno; 133505f98035SJacques Vidrine return (NS_UNAVAIL); 133605f98035SJacques Vidrine } 133705f98035SJacques Vidrine } 133805f98035SJacques Vidrine rv = nis_map(st->domain, how, map, sizeof(map), &master); 133905f98035SJacques Vidrine if (rv != NS_SUCCESS) 134005f98035SJacques Vidrine return (rv); 134105f98035SJacques Vidrine result = NULL; 134205f98035SJacques Vidrine do { 134305f98035SJacques Vidrine rv = NS_NOTFOUND; 134405f98035SJacques Vidrine switch (how) { 134505f98035SJacques Vidrine case nss_lt_name: 1346d0509082SJacques Vidrine if (strlcpy(buffer, name, bufsize) >= bufsize) 134705f98035SJacques Vidrine goto erange; 134805f98035SJacques Vidrine break; 134905f98035SJacques Vidrine case nss_lt_id: 135005f98035SJacques Vidrine if (snprintf(buffer, bufsize, "%lu", 135105f98035SJacques Vidrine (unsigned long)uid) >= bufsize) 135205f98035SJacques Vidrine goto erange; 135305f98035SJacques Vidrine break; 135405f98035SJacques Vidrine case nss_lt_all: 135505f98035SJacques Vidrine if (st->done) 135605f98035SJacques Vidrine goto fin; 135705f98035SJacques Vidrine break; 135805f98035SJacques Vidrine } 135905f98035SJacques Vidrine result = NULL; 136005f98035SJacques Vidrine if (how == nss_lt_all) { 136105f98035SJacques Vidrine if (st->key == NULL) 136205f98035SJacques Vidrine rv = yp_first(st->domain, map, &st->key, 136305f98035SJacques Vidrine &st->keylen, &result, &resultlen); 136405f98035SJacques Vidrine else { 136505f98035SJacques Vidrine key = st->key; 136605f98035SJacques Vidrine keylen = st->keylen; 136705f98035SJacques Vidrine st->key = NULL; 136805f98035SJacques Vidrine rv = yp_next(st->domain, map, key, keylen, 136905f98035SJacques Vidrine &st->key, &st->keylen, &result, 137005f98035SJacques Vidrine &resultlen); 137105f98035SJacques Vidrine free(key); 137205f98035SJacques Vidrine } 137305f98035SJacques Vidrine if (rv != 0) { 137405f98035SJacques Vidrine free(result); 137505f98035SJacques Vidrine free(st->key); 137605f98035SJacques Vidrine st->key = NULL; 137705f98035SJacques Vidrine if (rv == YPERR_NOMORE) 137805f98035SJacques Vidrine st->done = 1; 137905f98035SJacques Vidrine else 138005f98035SJacques Vidrine rv = NS_UNAVAIL; 138105f98035SJacques Vidrine goto fin; 138205f98035SJacques Vidrine } 138305f98035SJacques Vidrine } else { 138405f98035SJacques Vidrine rv = yp_match(st->domain, map, buffer, strlen(buffer), 138505f98035SJacques Vidrine &result, &resultlen); 138605f98035SJacques Vidrine if (rv == YPERR_KEY) { 138705f98035SJacques Vidrine rv = NS_NOTFOUND; 138805f98035SJacques Vidrine continue; 138905f98035SJacques Vidrine } else if (rv != 0) { 139005f98035SJacques Vidrine free(result); 139105f98035SJacques Vidrine rv = NS_UNAVAIL; 139205f98035SJacques Vidrine continue; 139305f98035SJacques Vidrine } 139405f98035SJacques Vidrine } 139505f98035SJacques Vidrine if (resultlen >= bufsize) 139605f98035SJacques Vidrine goto erange; 139705f98035SJacques Vidrine memcpy(buffer, result, resultlen); 139805f98035SJacques Vidrine buffer[resultlen] = '\0'; 139905f98035SJacques Vidrine free(result); 140005f98035SJacques Vidrine rv = __pw_match_entry(buffer, resultlen, how, name, uid); 140105f98035SJacques Vidrine if (rv == NS_SUCCESS) 140205f98035SJacques Vidrine rv = __pw_parse_entry(buffer, resultlen, pwd, master, 140305f98035SJacques Vidrine errnop); 140405f98035SJacques Vidrine } while (how == nss_lt_all && !(rv & NS_TERMINATE)); 140505f98035SJacques Vidrine fin: 140605f98035SJacques Vidrine if (rv == NS_SUCCESS) { 140705f98035SJacques Vidrine if (strstr(pwd->pw_passwd, "##") != NULL) { 14082734a36fSJacques Vidrine rv = nis_adjunct(st->domain, pwd->pw_name, 140905f98035SJacques Vidrine &buffer[resultlen+1], bufsize-resultlen-1); 141005f98035SJacques Vidrine if (rv < 0) 141105f98035SJacques Vidrine goto erange; 141205f98035SJacques Vidrine else if (rv == 0) 141305f98035SJacques Vidrine pwd->pw_passwd = &buffer[resultlen+1]; 141405f98035SJacques Vidrine } 141505f98035SJacques Vidrine pwd->pw_fields &= ~_PWF_SOURCE; 141605f98035SJacques Vidrine pwd->pw_fields |= _PWF_NIS; 141705f98035SJacques Vidrine if (retval != NULL) 141805f98035SJacques Vidrine *(struct passwd **)retval = pwd; 1419dbb4b1c8SJonathan Chen rv = NS_SUCCESS; 142005f98035SJacques Vidrine } 142105f98035SJacques Vidrine return (rv); 142205f98035SJacques Vidrine erange: 142305f98035SJacques Vidrine *errnop = ERANGE; 142405f98035SJacques Vidrine return (NS_RETURN); 142505f98035SJacques Vidrine } 142605f98035SJacques Vidrine #endif /* YP */ 142705f98035SJacques Vidrine 142805f98035SJacques Vidrine 142905f98035SJacques Vidrine /* 143005f98035SJacques Vidrine * compat backend 143105f98035SJacques Vidrine */ 143205f98035SJacques Vidrine static void 143305f98035SJacques Vidrine compat_clear_template(struct passwd *template) 143405f98035SJacques Vidrine { 143505f98035SJacques Vidrine 143605f98035SJacques Vidrine free(template->pw_passwd); 143705f98035SJacques Vidrine free(template->pw_gecos); 143805f98035SJacques Vidrine free(template->pw_dir); 143905f98035SJacques Vidrine free(template->pw_shell); 144005f98035SJacques Vidrine memset(template, 0, sizeof(*template)); 144105f98035SJacques Vidrine } 144205f98035SJacques Vidrine 144305f98035SJacques Vidrine 144405f98035SJacques Vidrine static int 144505f98035SJacques Vidrine compat_set_template(struct passwd *src, struct passwd *template) 144605f98035SJacques Vidrine { 144705f98035SJacques Vidrine 144805f98035SJacques Vidrine compat_clear_template(template); 144905f98035SJacques Vidrine #ifdef PW_OVERRIDE_PASSWD 145005f98035SJacques Vidrine if ((src->pw_fields & _PWF_PASSWD) && 145105f98035SJacques Vidrine (template->pw_passwd = strdup(src->pw_passwd)) == NULL) 145205f98035SJacques Vidrine goto enomem; 145305f98035SJacques Vidrine #endif 145405f98035SJacques Vidrine if (src->pw_fields & _PWF_UID) 145505f98035SJacques Vidrine template->pw_uid = src->pw_uid; 145605f98035SJacques Vidrine if (src->pw_fields & _PWF_GID) 145705f98035SJacques Vidrine template->pw_gid = src->pw_gid; 145805f98035SJacques Vidrine if ((src->pw_fields & _PWF_GECOS) && 145905f98035SJacques Vidrine (template->pw_gecos = strdup(src->pw_gecos)) == NULL) 146005f98035SJacques Vidrine goto enomem; 146105f98035SJacques Vidrine if ((src->pw_fields & _PWF_DIR) && 146205f98035SJacques Vidrine (template->pw_dir = strdup(src->pw_dir)) == NULL) 146305f98035SJacques Vidrine goto enomem; 146405f98035SJacques Vidrine if ((src->pw_fields & _PWF_SHELL) && 146505f98035SJacques Vidrine (template->pw_shell = strdup(src->pw_shell)) == NULL) 146605f98035SJacques Vidrine goto enomem; 146705f98035SJacques Vidrine template->pw_fields = src->pw_fields; 146805f98035SJacques Vidrine return (0); 146905f98035SJacques Vidrine enomem: 147005f98035SJacques Vidrine syslog(LOG_ERR, "getpwent memory allocation failure"); 147105f98035SJacques Vidrine return (-1); 147205f98035SJacques Vidrine } 147305f98035SJacques Vidrine 147405f98035SJacques Vidrine 147505f98035SJacques Vidrine static int 147605f98035SJacques Vidrine compat_use_template(struct passwd *pwd, struct passwd *template, char *buffer, 147705f98035SJacques Vidrine size_t bufsize) 147805f98035SJacques Vidrine { 147905f98035SJacques Vidrine struct passwd hold; 148005f98035SJacques Vidrine char *copy, *p, *q, *eob; 148105f98035SJacques Vidrine size_t n; 148205f98035SJacques Vidrine 148305f98035SJacques Vidrine /* We cannot know the layout of the password fields in `buffer', 148405f98035SJacques Vidrine * so we have to copy everything. 148505f98035SJacques Vidrine */ 148605f98035SJacques Vidrine if (template->pw_fields == 0) /* nothing to fill-in */ 148705f98035SJacques Vidrine return (0); 148805f98035SJacques Vidrine n = 0; 148905f98035SJacques Vidrine n += pwd->pw_name != NULL ? strlen(pwd->pw_name) + 1 : 0; 149005f98035SJacques Vidrine n += pwd->pw_passwd != NULL ? strlen(pwd->pw_passwd) + 1 : 0; 149105f98035SJacques Vidrine n += pwd->pw_class != NULL ? strlen(pwd->pw_class) + 1 : 0; 149205f98035SJacques Vidrine n += pwd->pw_gecos != NULL ? strlen(pwd->pw_gecos) + 1 : 0; 149305f98035SJacques Vidrine n += pwd->pw_dir != NULL ? strlen(pwd->pw_dir) + 1 : 0; 149405f98035SJacques Vidrine n += pwd->pw_shell != NULL ? strlen(pwd->pw_shell) + 1 : 0; 149505f98035SJacques Vidrine copy = malloc(n); 149605f98035SJacques Vidrine if (copy == NULL) { 149705f98035SJacques Vidrine syslog(LOG_ERR, "getpwent memory allocation failure"); 149805f98035SJacques Vidrine return (ENOMEM); 149905f98035SJacques Vidrine } 150005f98035SJacques Vidrine p = copy; 150105f98035SJacques Vidrine eob = ©[n]; 150205f98035SJacques Vidrine #define COPY(field) do { \ 150305f98035SJacques Vidrine if (pwd->field == NULL) \ 150405f98035SJacques Vidrine hold.field = NULL; \ 150505f98035SJacques Vidrine else { \ 150605f98035SJacques Vidrine hold.field = p; \ 1507d0509082SJacques Vidrine p += strlcpy(p, pwd->field, eob-p) + 1; \ 150805f98035SJacques Vidrine } \ 150905f98035SJacques Vidrine } while (0) 151005f98035SJacques Vidrine COPY(pw_name); 151105f98035SJacques Vidrine COPY(pw_passwd); 151205f98035SJacques Vidrine COPY(pw_class); 151305f98035SJacques Vidrine COPY(pw_gecos); 151405f98035SJacques Vidrine COPY(pw_dir); 151505f98035SJacques Vidrine COPY(pw_shell); 151605f98035SJacques Vidrine #undef COPY 151705f98035SJacques Vidrine p = buffer; 151805f98035SJacques Vidrine eob = &buffer[bufsize]; 151905f98035SJacques Vidrine #define COPY(field, flag) do { \ 152005f98035SJacques Vidrine q = (template->pw_fields & flag) ? template->field : hold.field; \ 152105f98035SJacques Vidrine if (q == NULL) \ 152205f98035SJacques Vidrine pwd->field = NULL; \ 152305f98035SJacques Vidrine else { \ 152405f98035SJacques Vidrine pwd->field = p; \ 1525d0509082SJacques Vidrine if ((n = strlcpy(p, q, eob-p)) >= eob-p) { \ 152605f98035SJacques Vidrine free(copy); \ 152705f98035SJacques Vidrine return (ERANGE); \ 152805f98035SJacques Vidrine } \ 152905f98035SJacques Vidrine p += n + 1; \ 153005f98035SJacques Vidrine } \ 153105f98035SJacques Vidrine } while (0) 153205f98035SJacques Vidrine COPY(pw_name, 0); 153305f98035SJacques Vidrine #ifdef PW_OVERRIDE_PASSWD 153405f98035SJacques Vidrine COPY(pw_passwd, _PWF_PASSWD); 153505f98035SJacques Vidrine #else 153605f98035SJacques Vidrine COPY(pw_passwd, 0); 153705f98035SJacques Vidrine #endif 153805f98035SJacques Vidrine COPY(pw_class, 0); 153905f98035SJacques Vidrine COPY(pw_gecos, _PWF_GECOS); 154005f98035SJacques Vidrine COPY(pw_dir, _PWF_DIR); 154105f98035SJacques Vidrine COPY(pw_shell, _PWF_SHELL); 154205f98035SJacques Vidrine #undef COPY 154305f98035SJacques Vidrine #define COPY(field, flag) do { \ 154405f98035SJacques Vidrine if (template->pw_fields & flag) \ 154505f98035SJacques Vidrine pwd->field = template->field; \ 154605f98035SJacques Vidrine } while (0) 154705f98035SJacques Vidrine COPY(pw_uid, _PWF_UID); 154805f98035SJacques Vidrine COPY(pw_gid, _PWF_GID); 154905f98035SJacques Vidrine #undef COPY 155005f98035SJacques Vidrine free(copy); 155105f98035SJacques Vidrine return (0); 155205f98035SJacques Vidrine } 155305f98035SJacques Vidrine 155405f98035SJacques Vidrine 155505f98035SJacques Vidrine static int 155605f98035SJacques Vidrine compat_exclude(const char *name, DB **db) 155705f98035SJacques Vidrine { 155805f98035SJacques Vidrine DBT key, data; 155905f98035SJacques Vidrine 156005f98035SJacques Vidrine if (*db == NULL && 156105f98035SJacques Vidrine (*db = dbopen(NULL, O_RDWR, 600, DB_HASH, 0)) == NULL) 156205f98035SJacques Vidrine return (errno); 156305f98035SJacques Vidrine key.size = strlen(name); 156405f98035SJacques Vidrine key.data = (char *)name; 156505f98035SJacques Vidrine data.size = 0; 156605f98035SJacques Vidrine data.data = NULL; 156705f98035SJacques Vidrine 156805f98035SJacques Vidrine if ((*db)->put(*db, &key, &data, 0) == -1) 156905f98035SJacques Vidrine return (errno); 157005f98035SJacques Vidrine return (0); 157105f98035SJacques Vidrine } 157205f98035SJacques Vidrine 157305f98035SJacques Vidrine 157405f98035SJacques Vidrine static int 157505f98035SJacques Vidrine compat_is_excluded(const char *name, DB *db) 157605f98035SJacques Vidrine { 157705f98035SJacques Vidrine DBT key, data; 157805f98035SJacques Vidrine 157905f98035SJacques Vidrine if (db == NULL) 158005f98035SJacques Vidrine return (0); 158105f98035SJacques Vidrine key.size = strlen(name); 158205f98035SJacques Vidrine key.data = (char *)name; 158305f98035SJacques Vidrine return (db->get(db, &key, &data, 0) == 0); 158405f98035SJacques Vidrine } 158505f98035SJacques Vidrine 158605f98035SJacques Vidrine 158705f98035SJacques Vidrine static int 158805f98035SJacques Vidrine compat_redispatch(struct compat_state *st, enum nss_lookup_type how, 158905f98035SJacques Vidrine enum nss_lookup_type lookup_how, const char *name, const char *lookup_name, 159005f98035SJacques Vidrine uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, int *errnop) 159105f98035SJacques Vidrine { 159205f98035SJacques Vidrine static const ns_src compatsrc[] = { 159305f98035SJacques Vidrine #ifdef YP 159405f98035SJacques Vidrine { NSSRC_NIS, NS_SUCCESS }, 159505f98035SJacques Vidrine #endif 159605f98035SJacques Vidrine { NULL, 0 } 159705f98035SJacques Vidrine }; 159805f98035SJacques Vidrine ns_dtab dtab[] = { 159905f98035SJacques Vidrine #ifdef YP 160005f98035SJacques Vidrine { NSSRC_NIS, nis_passwd, NULL }, 160105f98035SJacques Vidrine #endif 160205f98035SJacques Vidrine #ifdef HESIOD 160305f98035SJacques Vidrine { NSSRC_DNS, dns_passwd, NULL }, 160405f98035SJacques Vidrine #endif 160505f98035SJacques Vidrine { NULL, NULL, NULL } 160605f98035SJacques Vidrine }; 160705f98035SJacques Vidrine void *discard; 160805f98035SJacques Vidrine int rv, e, i; 160905f98035SJacques Vidrine 161005f98035SJacques Vidrine for (i = 0; i < sizeof(dtab)/sizeof(dtab[0]) - 1; i++) 161105f98035SJacques Vidrine dtab[i].mdata = (void *)lookup_how; 161205f98035SJacques Vidrine more: 1613e2527dafSJacques Vidrine pwd_init(pwd); 161405f98035SJacques Vidrine switch (lookup_how) { 161505f98035SJacques Vidrine case nss_lt_all: 161605f98035SJacques Vidrine rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 161705f98035SJacques Vidrine "getpwent_r", compatsrc, pwd, buffer, bufsize, 161805f98035SJacques Vidrine errnop); 161905f98035SJacques Vidrine break; 162005f98035SJacques Vidrine case nss_lt_id: 162105f98035SJacques Vidrine rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 162205f98035SJacques Vidrine "getpwuid_r", compatsrc, uid, pwd, buffer, 162305f98035SJacques Vidrine bufsize, errnop); 162405f98035SJacques Vidrine break; 162505f98035SJacques Vidrine case nss_lt_name: 162605f98035SJacques Vidrine rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT, 162705f98035SJacques Vidrine "getpwnam_r", compatsrc, lookup_name, pwd, buffer, 162805f98035SJacques Vidrine bufsize, errnop); 162905f98035SJacques Vidrine break; 163005f98035SJacques Vidrine default: 163105f98035SJacques Vidrine return (NS_UNAVAIL); 163205f98035SJacques Vidrine } 163305f98035SJacques Vidrine if (rv != NS_SUCCESS) 163405f98035SJacques Vidrine return (rv); 163505f98035SJacques Vidrine if (compat_is_excluded(pwd->pw_name, st->exclude)) { 163605f98035SJacques Vidrine if (how == nss_lt_all) 163705f98035SJacques Vidrine goto more; 163805f98035SJacques Vidrine return (NS_NOTFOUND); 163905f98035SJacques Vidrine } 164005f98035SJacques Vidrine e = compat_use_template(pwd, &st->template, buffer, bufsize); 164105f98035SJacques Vidrine if (e != 0) { 164205f98035SJacques Vidrine *errnop = e; 164305f98035SJacques Vidrine if (e == ERANGE) 164405f98035SJacques Vidrine return (NS_RETURN); 164505f98035SJacques Vidrine else 164605f98035SJacques Vidrine return (NS_UNAVAIL); 164705f98035SJacques Vidrine } 164805f98035SJacques Vidrine switch (how) { 164905f98035SJacques Vidrine case nss_lt_name: 165005f98035SJacques Vidrine if (strcmp(name, pwd->pw_name) != 0) 165105f98035SJacques Vidrine return (NS_NOTFOUND); 165205f98035SJacques Vidrine break; 165305f98035SJacques Vidrine case nss_lt_id: 165405f98035SJacques Vidrine if (uid != pwd->pw_uid) 165505f98035SJacques Vidrine return (NS_NOTFOUND); 165605f98035SJacques Vidrine break; 165705f98035SJacques Vidrine default: 165805f98035SJacques Vidrine break; 165905f98035SJacques Vidrine } 166005f98035SJacques Vidrine return (NS_SUCCESS); 166105f98035SJacques Vidrine } 166205f98035SJacques Vidrine 166305f98035SJacques Vidrine 166405f98035SJacques Vidrine static void 166505f98035SJacques Vidrine compat_endstate(void *p) 166605f98035SJacques Vidrine { 166705f98035SJacques Vidrine struct compat_state *st; 166805f98035SJacques Vidrine 166905f98035SJacques Vidrine if (p == NULL) 167005f98035SJacques Vidrine return; 167105f98035SJacques Vidrine st = (struct compat_state *)p; 167205f98035SJacques Vidrine if (st->db != NULL) 167305f98035SJacques Vidrine st->db->close(st->db); 167405f98035SJacques Vidrine if (st->exclude != NULL) 167505f98035SJacques Vidrine st->exclude->close(st->exclude); 167605f98035SJacques Vidrine compat_clear_template(&st->template); 167705f98035SJacques Vidrine free(p); 167805f98035SJacques Vidrine } 167905f98035SJacques Vidrine 168005f98035SJacques Vidrine 168105f98035SJacques Vidrine static int 168205f98035SJacques Vidrine compat_setpwent(void *retval, void *mdata, va_list ap) 168305f98035SJacques Vidrine { 1684c14d379dSJacques Vidrine static const ns_src compatsrc[] = { 1685c14d379dSJacques Vidrine #ifdef YP 1686c14d379dSJacques Vidrine { NSSRC_NIS, NS_SUCCESS }, 1687c14d379dSJacques Vidrine #endif 1688c14d379dSJacques Vidrine { NULL, 0 } 1689c14d379dSJacques Vidrine }; 1690c14d379dSJacques Vidrine ns_dtab dtab[] = { 1691c14d379dSJacques Vidrine #ifdef YP 1692c14d379dSJacques Vidrine { NSSRC_NIS, nis_setpwent, NULL }, 1693c14d379dSJacques Vidrine #endif 1694c14d379dSJacques Vidrine #ifdef HESIOD 1695c14d379dSJacques Vidrine { NSSRC_DNS, dns_setpwent, NULL }, 1696c14d379dSJacques Vidrine #endif 1697c14d379dSJacques Vidrine { NULL, NULL, NULL } 1698c14d379dSJacques Vidrine }; 169905f98035SJacques Vidrine struct compat_state *st; 170005f98035SJacques Vidrine int rv, stayopen; 170105f98035SJacques Vidrine 1702c14d379dSJacques Vidrine #define set_setent(x, y) do { \ 1703c14d379dSJacques Vidrine int i; \ 1704c14d379dSJacques Vidrine \ 1705c14d379dSJacques Vidrine for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \ 1706c14d379dSJacques Vidrine x[i].mdata = (void *)y; \ 1707c14d379dSJacques Vidrine } while (0) 1708c14d379dSJacques Vidrine 170905f98035SJacques Vidrine rv = compat_getstate(&st); 171005f98035SJacques Vidrine if (rv != 0) 171105f98035SJacques Vidrine return (NS_UNAVAIL); 171205f98035SJacques Vidrine switch ((enum constants)mdata) { 171305f98035SJacques Vidrine case SETPWENT: 171405f98035SJacques Vidrine stayopen = va_arg(ap, int); 171505f98035SJacques Vidrine st->keynum = 0; 171605f98035SJacques Vidrine if (stayopen) 171705f98035SJacques Vidrine st->db = pwdbopen(&st->version); 171805f98035SJacques Vidrine st->stayopen = stayopen; 1719c14d379dSJacques Vidrine set_setent(dtab, mdata); 1720c14d379dSJacques Vidrine (void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "setpwent", 1721c14d379dSJacques Vidrine compatsrc, 0); 172205f98035SJacques Vidrine break; 172305f98035SJacques Vidrine case ENDPWENT: 172405f98035SJacques Vidrine if (st->db != NULL) { 172505f98035SJacques Vidrine (void)st->db->close(st->db); 172605f98035SJacques Vidrine st->db = NULL; 172705f98035SJacques Vidrine } 1728c14d379dSJacques Vidrine set_setent(dtab, mdata); 1729c14d379dSJacques Vidrine (void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "endpwent", 1730c14d379dSJacques Vidrine compatsrc, 0); 173105f98035SJacques Vidrine break; 173205f98035SJacques Vidrine default: 173305f98035SJacques Vidrine break; 173405f98035SJacques Vidrine } 173505f98035SJacques Vidrine return (NS_UNAVAIL); 1736c14d379dSJacques Vidrine #undef set_setent 173705f98035SJacques Vidrine } 173805f98035SJacques Vidrine 173905f98035SJacques Vidrine 174005f98035SJacques Vidrine static int 174105f98035SJacques Vidrine compat_passwd(void *retval, void *mdata, va_list ap) 174205f98035SJacques Vidrine { 174305f98035SJacques Vidrine char keybuf[MAXLOGNAME + 1]; 174405f98035SJacques Vidrine DBT key, entry; 174505f98035SJacques Vidrine struct compat_state *st; 174605f98035SJacques Vidrine enum nss_lookup_type how; 174705f98035SJacques Vidrine const char *name; 174805f98035SJacques Vidrine struct passwd *pwd; 174905f98035SJacques Vidrine char *buffer, *pw_name; 175005f98035SJacques Vidrine char *host, *user, *domain; 175105f98035SJacques Vidrine size_t bufsize; 175205f98035SJacques Vidrine uid_t uid; 175305f98035SJacques Vidrine uint32_t store; 1754a9ceaa9dSJacques Vidrine int rv, from_compat, stayopen, *errnop; 175505f98035SJacques Vidrine 1756a9ceaa9dSJacques Vidrine from_compat = 0; 175705f98035SJacques Vidrine name = NULL; 175805f98035SJacques Vidrine uid = (uid_t)-1; 175905f98035SJacques Vidrine how = (enum nss_lookup_type)mdata; 176005f98035SJacques Vidrine switch (how) { 176105f98035SJacques Vidrine case nss_lt_name: 176205f98035SJacques Vidrine name = va_arg(ap, const char *); 176305f98035SJacques Vidrine break; 176405f98035SJacques Vidrine case nss_lt_id: 176505f98035SJacques Vidrine uid = va_arg(ap, uid_t); 176605f98035SJacques Vidrine break; 176705f98035SJacques Vidrine case nss_lt_all: 176805f98035SJacques Vidrine break; 176905f98035SJacques Vidrine default: 177005f98035SJacques Vidrine rv = NS_NOTFOUND; 177105f98035SJacques Vidrine goto fin; 177205f98035SJacques Vidrine } 177305f98035SJacques Vidrine pwd = va_arg(ap, struct passwd *); 177405f98035SJacques Vidrine buffer = va_arg(ap, char *); 177505f98035SJacques Vidrine bufsize = va_arg(ap, size_t); 177605f98035SJacques Vidrine errnop = va_arg(ap, int *); 177705f98035SJacques Vidrine *errnop = compat_getstate(&st); 177805f98035SJacques Vidrine if (*errnop != 0) 177905f98035SJacques Vidrine return (NS_UNAVAIL); 178005f98035SJacques Vidrine if (how == nss_lt_all && st->keynum < 0) { 178105f98035SJacques Vidrine rv = NS_NOTFOUND; 178205f98035SJacques Vidrine goto fin; 178305f98035SJacques Vidrine } 178405f98035SJacques Vidrine if (st->db == NULL && 178505f98035SJacques Vidrine (st->db = pwdbopen(&st->version)) == NULL) { 178605f98035SJacques Vidrine *errnop = errno; 178705f98035SJacques Vidrine rv = NS_UNAVAIL; 178805f98035SJacques Vidrine goto fin; 178905f98035SJacques Vidrine } 179005f98035SJacques Vidrine if (how == nss_lt_all) { 179105f98035SJacques Vidrine if (st->keynum < 0) { 179205f98035SJacques Vidrine rv = NS_NOTFOUND; 179305f98035SJacques Vidrine goto fin; 179405f98035SJacques Vidrine } 179505f98035SJacques Vidrine stayopen = 1; 179605f98035SJacques Vidrine } else { 179705f98035SJacques Vidrine st->keynum = 0; 179805f98035SJacques Vidrine stayopen = st->stayopen; 179905f98035SJacques Vidrine } 180005f98035SJacques Vidrine docompat: 180105f98035SJacques Vidrine rv = NS_NOTFOUND; 180205f98035SJacques Vidrine switch (st->compat) { 180305f98035SJacques Vidrine case COMPAT_MODE_ALL: 180405f98035SJacques Vidrine rv = compat_redispatch(st, how, how, name, name, uid, pwd, 180505f98035SJacques Vidrine buffer, bufsize, errnop); 180605f98035SJacques Vidrine if (rv != NS_SUCCESS) 180705f98035SJacques Vidrine st->compat = COMPAT_MODE_OFF; 180805f98035SJacques Vidrine break; 180905f98035SJacques Vidrine case COMPAT_MODE_NETGROUP: 181005f98035SJacques Vidrine /* XXX getnetgrent is not thread-safe. */ 181105f98035SJacques Vidrine do { 181205f98035SJacques Vidrine rv = getnetgrent(&host, &user, &domain); 181305f98035SJacques Vidrine if (rv == 0) { 181405f98035SJacques Vidrine endnetgrent(); 181505f98035SJacques Vidrine st->compat = COMPAT_MODE_OFF; 181605f98035SJacques Vidrine rv = NS_NOTFOUND; 181705f98035SJacques Vidrine continue; 181805f98035SJacques Vidrine } else if (user == NULL || user[0] == '\0') 181905f98035SJacques Vidrine continue; 182005f98035SJacques Vidrine rv = compat_redispatch(st, how, nss_lt_name, name, 182105f98035SJacques Vidrine user, uid, pwd, buffer, bufsize, errnop); 182205f98035SJacques Vidrine } while (st->compat == COMPAT_MODE_NETGROUP && 182305f98035SJacques Vidrine !(rv & NS_TERMINATE)); 182405f98035SJacques Vidrine break; 182505f98035SJacques Vidrine case COMPAT_MODE_NAME: 182605f98035SJacques Vidrine rv = compat_redispatch(st, how, nss_lt_name, name, st->name, 182705f98035SJacques Vidrine uid, pwd, buffer, bufsize, errnop); 182805f98035SJacques Vidrine free(st->name); 182905f98035SJacques Vidrine st->name = NULL; 183005f98035SJacques Vidrine st->compat = COMPAT_MODE_OFF; 183105f98035SJacques Vidrine break; 183205f98035SJacques Vidrine default: 183305f98035SJacques Vidrine break; 183405f98035SJacques Vidrine } 1835a9ceaa9dSJacques Vidrine if (rv & NS_TERMINATE) { 1836a9ceaa9dSJacques Vidrine from_compat = 1; 183705f98035SJacques Vidrine goto fin; 1838a9ceaa9dSJacques Vidrine } 183905f98035SJacques Vidrine key.data = keybuf; 184005f98035SJacques Vidrine rv = NS_NOTFOUND; 184105f98035SJacques Vidrine while (st->keynum >= 0) { 184205f98035SJacques Vidrine st->keynum++; 184305f98035SJacques Vidrine if (st->version < _PWD_CURRENT_VERSION) { 184405f98035SJacques Vidrine memcpy(&keybuf[1], &st->keynum, sizeof(st->keynum)); 184505f98035SJacques Vidrine key.size = sizeof(st->keynum) + 1; 184605f98035SJacques Vidrine } else { 184705f98035SJacques Vidrine store = htonl(st->keynum); 184805f98035SJacques Vidrine memcpy(&keybuf[1], &store, sizeof(store)); 184905f98035SJacques Vidrine key.size = sizeof(store) + 1; 185005f98035SJacques Vidrine } 1851b4603f3dSJacques Vidrine keybuf[0] = _PW_VERSIONED(_PW_KEYBYNUM, st->version); 185205f98035SJacques Vidrine rv = st->db->get(st->db, &key, &entry, 0); 185305f98035SJacques Vidrine if (rv < 0 || rv > 1) { /* should never return > 1 */ 185405f98035SJacques Vidrine *errnop = errno; 185505f98035SJacques Vidrine rv = NS_UNAVAIL; 185605f98035SJacques Vidrine goto fin; 185705f98035SJacques Vidrine } else if (rv == 1) { 185805f98035SJacques Vidrine st->keynum = -1; 185905f98035SJacques Vidrine rv = NS_NOTFOUND; 186005f98035SJacques Vidrine goto fin; 186105f98035SJacques Vidrine } 186205f98035SJacques Vidrine pw_name = (char *)entry.data; 186305f98035SJacques Vidrine switch (pw_name[0]) { 186405f98035SJacques Vidrine case '+': 186505f98035SJacques Vidrine switch (pw_name[1]) { 186605f98035SJacques Vidrine case '\0': 186705f98035SJacques Vidrine st->compat = COMPAT_MODE_ALL; 186805f98035SJacques Vidrine break; 186905f98035SJacques Vidrine case '@': 187005f98035SJacques Vidrine setnetgrent(&pw_name[2]); 187105f98035SJacques Vidrine st->compat = COMPAT_MODE_NETGROUP; 187205f98035SJacques Vidrine break; 187305f98035SJacques Vidrine default: 187405f98035SJacques Vidrine st->name = strdup(&pw_name[1]); 187505f98035SJacques Vidrine if (st->name == NULL) { 187605f98035SJacques Vidrine syslog(LOG_ERR, 187705f98035SJacques Vidrine "getpwent memory allocation failure"); 187805f98035SJacques Vidrine *errnop = ENOMEM; 187905f98035SJacques Vidrine rv = NS_UNAVAIL; 188005f98035SJacques Vidrine break; 188105f98035SJacques Vidrine } 188205f98035SJacques Vidrine st->compat = COMPAT_MODE_NAME; 188305f98035SJacques Vidrine } 188405f98035SJacques Vidrine if (entry.size > bufsize) { 188505f98035SJacques Vidrine *errnop = ERANGE; 188605f98035SJacques Vidrine rv = NS_RETURN; 188705f98035SJacques Vidrine goto fin; 188805f98035SJacques Vidrine } 188905f98035SJacques Vidrine memcpy(buffer, entry.data, entry.size); 189005f98035SJacques Vidrine rv = pwdb_versions[st->version].parse(buffer, 189105f98035SJacques Vidrine entry.size, pwd, errnop); 189205f98035SJacques Vidrine if (rv != NS_SUCCESS) 189305f98035SJacques Vidrine ; 189405f98035SJacques Vidrine else if (compat_set_template(pwd, &st->template) < 0) { 189505f98035SJacques Vidrine *errnop = ENOMEM; 189605f98035SJacques Vidrine rv = NS_UNAVAIL; 189705f98035SJacques Vidrine goto fin; 189805f98035SJacques Vidrine } 189905f98035SJacques Vidrine goto docompat; 190005f98035SJacques Vidrine case '-': 190105f98035SJacques Vidrine switch (pw_name[1]) { 190205f98035SJacques Vidrine case '\0': 190305f98035SJacques Vidrine /* XXX Maybe syslog warning */ 190405f98035SJacques Vidrine continue; 190505f98035SJacques Vidrine case '@': 190605f98035SJacques Vidrine setnetgrent(&pw_name[2]); 190705f98035SJacques Vidrine while (getnetgrent(&host, &user, &domain) != 190816fc3635SMark Murray 0) { 190905f98035SJacques Vidrine if (user != NULL && user[0] != '\0') 191005f98035SJacques Vidrine compat_exclude(user, 191105f98035SJacques Vidrine &st->exclude); 191205f98035SJacques Vidrine } 191305f98035SJacques Vidrine endnetgrent(); 191405f98035SJacques Vidrine continue; 191505f98035SJacques Vidrine default: 191605f98035SJacques Vidrine compat_exclude(&pw_name[1], &st->exclude); 191705f98035SJacques Vidrine continue; 191805f98035SJacques Vidrine } 191905f98035SJacques Vidrine break; 192005f98035SJacques Vidrine default: 192105f98035SJacques Vidrine break; 192205f98035SJacques Vidrine } 192305f98035SJacques Vidrine if (compat_is_excluded((char *)entry.data, st->exclude)) 192405f98035SJacques Vidrine continue; 192505f98035SJacques Vidrine rv = pwdb_versions[st->version].match(entry.data, entry.size, 192605f98035SJacques Vidrine how, name, uid); 192705f98035SJacques Vidrine if (rv == NS_RETURN) 192805f98035SJacques Vidrine break; 192905f98035SJacques Vidrine else if (rv != NS_SUCCESS) 193005f98035SJacques Vidrine continue; 193105f98035SJacques Vidrine if (entry.size > bufsize) { 193205f98035SJacques Vidrine *errnop = ERANGE; 193305f98035SJacques Vidrine rv = NS_RETURN; 193405f98035SJacques Vidrine break; 193505f98035SJacques Vidrine } 193605f98035SJacques Vidrine memcpy(buffer, entry.data, entry.size); 193705f98035SJacques Vidrine rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd, 193805f98035SJacques Vidrine errnop); 193905f98035SJacques Vidrine if (rv & NS_TERMINATE) 194005f98035SJacques Vidrine break; 194105f98035SJacques Vidrine } 194205f98035SJacques Vidrine fin: 194305f98035SJacques Vidrine if (!stayopen && st->db != NULL) { 194405f98035SJacques Vidrine (void)st->db->close(st->db); 194505f98035SJacques Vidrine st->db = NULL; 194605f98035SJacques Vidrine } 1947a9ceaa9dSJacques Vidrine if (rv == NS_SUCCESS) { 1948a9ceaa9dSJacques Vidrine if (!from_compat) { 1949a9ceaa9dSJacques Vidrine pwd->pw_fields &= ~_PWF_SOURCE; 1950a9ceaa9dSJacques Vidrine pwd->pw_fields |= _PWF_FILES; 1951a9ceaa9dSJacques Vidrine } 1952a9ceaa9dSJacques Vidrine if (retval != NULL) 195305f98035SJacques Vidrine *(struct passwd **)retval = pwd; 1954a9ceaa9dSJacques Vidrine } 195505f98035SJacques Vidrine return (rv); 195605f98035SJacques Vidrine } 195705f98035SJacques Vidrine 195805f98035SJacques Vidrine 195905f98035SJacques Vidrine /* 196005f98035SJacques Vidrine * common passwd line matching and parsing 196105f98035SJacques Vidrine */ 196205f98035SJacques Vidrine int 196305f98035SJacques Vidrine __pw_match_entry(const char *entry, size_t entrysize, enum nss_lookup_type how, 196405f98035SJacques Vidrine const char *name, uid_t uid) 196505f98035SJacques Vidrine { 196605f98035SJacques Vidrine const char *p, *eom; 196705f98035SJacques Vidrine char *q; 196805f98035SJacques Vidrine size_t len; 196905f98035SJacques Vidrine unsigned long m; 197005f98035SJacques Vidrine 197105f98035SJacques Vidrine eom = entry + entrysize; 197205f98035SJacques Vidrine for (p = entry; p < eom; p++) 197305f98035SJacques Vidrine if (*p == ':') 197405f98035SJacques Vidrine break; 197505f98035SJacques Vidrine if (*p != ':') 197605f98035SJacques Vidrine return (NS_NOTFOUND); 197705f98035SJacques Vidrine if (how == nss_lt_all) 197805f98035SJacques Vidrine return (NS_SUCCESS); 197905f98035SJacques Vidrine if (how == nss_lt_name) { 198005f98035SJacques Vidrine len = strlen(name); 198105f98035SJacques Vidrine if (len == (p - entry) && memcmp(name, entry, len) == 0) 198205f98035SJacques Vidrine return (NS_SUCCESS); 198305f98035SJacques Vidrine else 198405f98035SJacques Vidrine return (NS_NOTFOUND); 198505f98035SJacques Vidrine } 198605f98035SJacques Vidrine for (p++; p < eom; p++) 198705f98035SJacques Vidrine if (*p == ':') 198805f98035SJacques Vidrine break; 198905f98035SJacques Vidrine if (*p != ':') 199005f98035SJacques Vidrine return (NS_NOTFOUND); 199105f98035SJacques Vidrine m = strtoul(++p, &q, 10); 199205f98035SJacques Vidrine if (q[0] != ':' || (uid_t)m != uid) 199305f98035SJacques Vidrine return (NS_NOTFOUND); 199405f98035SJacques Vidrine else 199505f98035SJacques Vidrine return (NS_SUCCESS); 199605f98035SJacques Vidrine } 199705f98035SJacques Vidrine 199805f98035SJacques Vidrine 199905f98035SJacques Vidrine /* XXX buffer must be NUL-terminated. errnop is not set correctly. */ 200005f98035SJacques Vidrine int 200105f98035SJacques Vidrine __pw_parse_entry(char *buffer, size_t bufsize __unused, struct passwd *pwd, 200205f98035SJacques Vidrine int master, int *errnop __unused) 200305f98035SJacques Vidrine { 200405f98035SJacques Vidrine 200505f98035SJacques Vidrine if (__pw_scan(buffer, pwd, master ? _PWSCAN_MASTER : 0) == 0) 200605f98035SJacques Vidrine return (NS_NOTFOUND); 200705f98035SJacques Vidrine else 200805f98035SJacques Vidrine return (NS_SUCCESS); 200958f0484fSRodney W. Grimes } 2010