getpwent.c revision 1.75.8.2 1 1.75.8.2 christos /* $NetBSD: getpwent.c,v 1.75.8.2 2008/11/23 21:44:07 christos Exp $ */
2 1.75.8.2 christos
3 1.75.8.2 christos /*-
4 1.75.8.2 christos * Copyright (c) 1997-2000, 2004-2005 The NetBSD Foundation, Inc.
5 1.75.8.2 christos * All rights reserved.
6 1.75.8.2 christos *
7 1.75.8.2 christos * This code is derived from software contributed to The NetBSD Foundation
8 1.75.8.2 christos * by Luke Mewburn.
9 1.75.8.2 christos *
10 1.75.8.2 christos * Redistribution and use in source and binary forms, with or without
11 1.75.8.2 christos * modification, are permitted provided that the following conditions
12 1.75.8.2 christos * are met:
13 1.75.8.2 christos * 1. Redistributions of source code must retain the above copyright
14 1.75.8.2 christos * notice, this list of conditions and the following disclaimer.
15 1.75.8.2 christos * 2. Redistributions in binary form must reproduce the above copyright
16 1.75.8.2 christos * notice, this list of conditions and the following disclaimer in the
17 1.75.8.2 christos * documentation and/or other materials provided with the distribution.
18 1.75.8.2 christos *
19 1.75.8.2 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.75.8.2 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.75.8.2 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.75.8.2 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.75.8.2 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.75.8.2 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.75.8.2 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.75.8.2 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.75.8.2 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.75.8.2 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.75.8.2 christos * POSSIBILITY OF SUCH DAMAGE.
30 1.75.8.2 christos */
31 1.75.8.2 christos
32 1.75.8.2 christos /*
33 1.75.8.2 christos * Copyright (c) 1988, 1993
34 1.75.8.2 christos * The Regents of the University of California. All rights reserved.
35 1.75.8.2 christos *
36 1.75.8.2 christos * Redistribution and use in source and binary forms, with or without
37 1.75.8.2 christos * modification, are permitted provided that the following conditions
38 1.75.8.2 christos * are met:
39 1.75.8.2 christos * 1. Redistributions of source code must retain the above copyright
40 1.75.8.2 christos * notice, this list of conditions and the following disclaimer.
41 1.75.8.2 christos * 2. Redistributions in binary form must reproduce the above copyright
42 1.75.8.2 christos * notice, this list of conditions and the following disclaimer in the
43 1.75.8.2 christos * documentation and/or other materials provided with the distribution.
44 1.75.8.2 christos * 3. Neither the name of the University nor the names of its contributors
45 1.75.8.2 christos * may be used to endorse or promote products derived from this software
46 1.75.8.2 christos * without specific prior written permission.
47 1.75.8.2 christos *
48 1.75.8.2 christos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 1.75.8.2 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 1.75.8.2 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 1.75.8.2 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 1.75.8.2 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 1.75.8.2 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 1.75.8.2 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 1.75.8.2 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 1.75.8.2 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 1.75.8.2 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 1.75.8.2 christos * SUCH DAMAGE.
59 1.75.8.2 christos */
60 1.75.8.2 christos
61 1.75.8.2 christos /*
62 1.75.8.2 christos * Portions Copyright (c) 1994, 1995, Jason Downs. All rights reserved.
63 1.75.8.2 christos *
64 1.75.8.2 christos * Redistribution and use in source and binary forms, with or without
65 1.75.8.2 christos * modification, are permitted provided that the following conditions
66 1.75.8.2 christos * are met:
67 1.75.8.2 christos * 1. Redistributions of source code must retain the above copyright
68 1.75.8.2 christos * notice, this list of conditions and the following disclaimer.
69 1.75.8.2 christos * 2. Redistributions in binary form must reproduce the above copyright
70 1.75.8.2 christos * notice, this list of conditions and the following disclaimer in the
71 1.75.8.2 christos * documentation and/or other materials provided with the distribution.
72 1.75.8.2 christos *
73 1.75.8.2 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
74 1.75.8.2 christos * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
75 1.75.8.2 christos * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
76 1.75.8.2 christos * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
77 1.75.8.2 christos * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
78 1.75.8.2 christos * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
79 1.75.8.2 christos * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
80 1.75.8.2 christos * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
81 1.75.8.2 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
82 1.75.8.2 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
83 1.75.8.2 christos * SUCH DAMAGE.
84 1.75.8.2 christos */
85 1.75.8.2 christos
86 1.75.8.2 christos #include <sys/cdefs.h>
87 1.75.8.2 christos #if defined(LIBC_SCCS) && !defined(lint)
88 1.75.8.2 christos #if 0
89 1.75.8.2 christos static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95";
90 1.75.8.2 christos #else
91 1.75.8.2 christos __RCSID("$NetBSD: getpwent.c,v 1.75.8.2 2008/11/23 21:44:07 christos Exp $");
92 1.75.8.2 christos #endif
93 1.75.8.2 christos #endif /* LIBC_SCCS and not lint */
94 1.75.8.2 christos
95 1.75.8.2 christos #include "namespace.h"
96 1.75.8.2 christos #include "reentrant.h"
97 1.75.8.2 christos
98 1.75.8.2 christos #include <sys/param.h>
99 1.75.8.2 christos
100 1.75.8.2 christos #include <assert.h>
101 1.75.8.2 christos #include <db.h>
102 1.75.8.2 christos #include <errno.h>
103 1.75.8.2 christos #include <fcntl.h>
104 1.75.8.2 christos #include <limits.h>
105 1.75.8.2 christos #include <netgroup.h>
106 1.75.8.2 christos #include <nsswitch.h>
107 1.75.8.2 christos #include <pwd.h>
108 1.75.8.2 christos #include <stdarg.h>
109 1.75.8.2 christos #include <stdio.h>
110 1.75.8.2 christos #include <stdlib.h>
111 1.75.8.2 christos #include <string.h>
112 1.75.8.2 christos #include <syslog.h>
113 1.75.8.2 christos #include <unistd.h>
114 1.75.8.2 christos
115 1.75.8.2 christos #ifdef HESIOD
116 1.75.8.2 christos #include <hesiod.h>
117 1.75.8.2 christos #endif
118 1.75.8.2 christos
119 1.75.8.2 christos #ifdef YP
120 1.75.8.2 christos #include <machine/param.h>
121 1.75.8.2 christos #include <rpc/rpc.h>
122 1.75.8.2 christos #include <rpcsvc/yp_prot.h>
123 1.75.8.2 christos #include <rpcsvc/ypclnt.h>
124 1.75.8.2 christos #endif
125 1.75.8.2 christos
126 1.75.8.2 christos #include "pw_private.h"
127 1.75.8.2 christos
128 1.75.8.2 christos #define _PASSWD_COMPAT /* "passwd" defaults to compat, so always provide it */
129 1.75.8.2 christos
130 1.75.8.2 christos #ifdef __weak_alias
131 1.75.8.2 christos __weak_alias(endpwent,_endpwent)
132 1.75.8.2 christos __weak_alias(getpwent,_getpwent)
133 1.75.8.2 christos __weak_alias(getpwent_r,_getpwent_r)
134 1.75.8.2 christos __weak_alias(getpwnam,_getpwnam)
135 1.75.8.2 christos __weak_alias(getpwnam_r,_getpwnam_r)
136 1.75.8.2 christos __weak_alias(getpwuid,_getpwuid)
137 1.75.8.2 christos __weak_alias(getpwuid_r,_getpwuid_r)
138 1.75.8.2 christos __weak_alias(setpassent,_setpassent)
139 1.75.8.2 christos __weak_alias(setpwent,_setpwent)
140 1.75.8.2 christos #endif
141 1.75.8.2 christos
142 1.75.8.2 christos #ifdef _REENTRANT
143 1.75.8.2 christos static mutex_t _pwmutex = MUTEX_INITIALIZER;
144 1.75.8.2 christos #endif
145 1.75.8.2 christos
146 1.75.8.2 christos const char __yp_token[] = "__YP!"; /* Let pwd_mkdb pull this in. */
147 1.75.8.2 christos
148 1.75.8.2 christos
149 1.75.8.2 christos /*
150 1.75.8.2 christos * The pwd.db lookup techniques and data extraction code here must be kept
151 1.75.8.2 christos * in sync with that in `pwd_mkdb'.
152 1.75.8.2 christos */
153 1.75.8.2 christos
154 1.75.8.2 christos #if defined(YP) || defined(HESIOD)
155 1.75.8.2 christos /*
156 1.75.8.2 christos * _pw_parse
157 1.75.8.2 christos * Parses entry using pw_scan(3) (without the trailing \n)
158 1.75.8.2 christos * after copying to buf, and fills in pw with corresponding values.
159 1.75.8.2 christos * If old is non-zero, entry is in _PASSWORD_OLDFMT.
160 1.75.8.2 christos * Returns 1 if parsed successfully, 0 on parse failure.
161 1.75.8.2 christos */
162 1.75.8.2 christos static int
163 1.75.8.2 christos _pw_parse(const char *entry, struct passwd *pw, char *buf, size_t buflen,
164 1.75.8.2 christos int old)
165 1.75.8.2 christos {
166 1.75.8.2 christos int flags;
167 1.75.8.2 christos
168 1.75.8.2 christos _DIAGASSERT(entry != NULL);
169 1.75.8.2 christos _DIAGASSERT(pw != NULL);
170 1.75.8.2 christos _DIAGASSERT(buf != NULL);
171 1.75.8.2 christos
172 1.75.8.2 christos if (strlcpy(buf, entry, buflen) >= buflen)
173 1.75.8.2 christos return 0;
174 1.75.8.2 christos flags = _PASSWORD_NOWARN;
175 1.75.8.2 christos if (old)
176 1.75.8.2 christos flags |= _PASSWORD_OLDFMT;
177 1.75.8.2 christos return __pw_scan(buf, pw, &flags);
178 1.75.8.2 christos }
179 1.75.8.2 christos #endif /* YP || HESIOD */
180 1.75.8.2 christos
181 1.75.8.2 christos /*
182 1.75.8.2 christos * _pw_opendb
183 1.75.8.2 christos * if *db is NULL, dbopen(3) /etc/spwd.db or /etc/pwd.db (depending
184 1.75.8.2 christos * upon permissions, etc)
185 1.75.8.2 christos */
186 1.75.8.2 christos static int
187 1.75.8.2 christos _pw_opendb(DB **db, int *version)
188 1.75.8.2 christos {
189 1.75.8.2 christos static int warned;
190 1.75.8.2 christos DBT key;
191 1.75.8.2 christos DBT value;
192 1.75.8.2 christos
193 1.75.8.2 christos const char *dbfile = NULL;
194 1.75.8.2 christos
195 1.75.8.2 christos _DIAGASSERT(db != NULL);
196 1.75.8.2 christos _DIAGASSERT(version != NULL);
197 1.75.8.2 christos if (*db != NULL) /* open *db */
198 1.75.8.2 christos return NS_SUCCESS;
199 1.75.8.2 christos
200 1.75.8.2 christos if (geteuid() == 0) {
201 1.75.8.2 christos dbfile = _PATH_SMP_DB;
202 1.75.8.2 christos *db = dbopen(dbfile, O_RDONLY, 0, DB_HASH, NULL);
203 1.75.8.2 christos }
204 1.75.8.2 christos if (*db == NULL) {
205 1.75.8.2 christos dbfile = _PATH_MP_DB;
206 1.75.8.2 christos *db = dbopen(dbfile, O_RDONLY, 0, DB_HASH, NULL);
207 1.75.8.2 christos }
208 1.75.8.2 christos if (*db == NULL) {
209 1.75.8.2 christos if (!warned) {
210 1.75.8.2 christos int serrno = errno;
211 1.75.8.2 christos syslog(LOG_ERR, "%s: %m", dbfile);
212 1.75.8.2 christos errno = serrno;
213 1.75.8.2 christos }
214 1.75.8.2 christos warned = 1;
215 1.75.8.2 christos return NS_UNAVAIL;
216 1.75.8.2 christos }
217 1.75.8.2 christos key.data = __UNCONST("VERSION");
218 1.75.8.2 christos key.size = 8;
219 1.75.8.2 christos switch ((*(*db)->get)(*db, &key, &value, 0)) {
220 1.75.8.2 christos case 0:
221 1.75.8.2 christos if (sizeof(*version) != value.size)
222 1.75.8.2 christos return NS_UNAVAIL;
223 1.75.8.2 christos (void)memcpy(version, value.data, value.size);
224 1.75.8.2 christos break; /* found */
225 1.75.8.2 christos case 1:
226 1.75.8.2 christos *version = 0; /* not found */
227 1.75.8.2 christos break;
228 1.75.8.2 christos case -1:
229 1.75.8.2 christos return NS_UNAVAIL; /* error in db routines */
230 1.75.8.2 christos default:
231 1.75.8.2 christos abort();
232 1.75.8.2 christos }
233 1.75.8.2 christos return NS_SUCCESS;
234 1.75.8.2 christos }
235 1.75.8.2 christos
236 1.75.8.2 christos /*
237 1.75.8.2 christos * _pw_getkey
238 1.75.8.2 christos * Lookup key in *db, filling in pw
239 1.75.8.2 christos * with the result, allocating memory from buffer (size buflen).
240 1.75.8.2 christos * (The caller may point key.data to buffer on entry; the contents
241 1.75.8.2 christos * of key.data will be invalid on exit.)
242 1.75.8.2 christos */
243 1.75.8.2 christos static int
244 1.75.8.2 christos _pw_getkey(DB *db, DBT *key,
245 1.75.8.2 christos struct passwd *pw, char *buffer, size_t buflen, int *pwflags,
246 1.75.8.2 christos int version)
247 1.75.8.2 christos {
248 1.75.8.2 christos char *p, *t;
249 1.75.8.2 christos DBT data;
250 1.75.8.2 christos
251 1.75.8.2 christos _DIAGASSERT(db != NULL);
252 1.75.8.2 christos _DIAGASSERT(key != NULL);
253 1.75.8.2 christos _DIAGASSERT(pw != NULL);
254 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
255 1.75.8.2 christos /* pwflags may be NULL (if we don't care about them */
256 1.75.8.2 christos
257 1.75.8.2 christos if (db == NULL) /* this shouldn't happen */
258 1.75.8.2 christos return NS_UNAVAIL;
259 1.75.8.2 christos
260 1.75.8.2 christos switch ((db->get)(db, key, &data, 0)) {
261 1.75.8.2 christos case 0:
262 1.75.8.2 christos break; /* found */
263 1.75.8.2 christos case 1:
264 1.75.8.2 christos return NS_NOTFOUND; /* not found */
265 1.75.8.2 christos case -1:
266 1.75.8.2 christos return NS_UNAVAIL; /* error in db routines */
267 1.75.8.2 christos default:
268 1.75.8.2 christos abort();
269 1.75.8.2 christos }
270 1.75.8.2 christos
271 1.75.8.2 christos p = (char *)data.data;
272 1.75.8.2 christos if (data.size > buflen) {
273 1.75.8.2 christos errno = ERANGE;
274 1.75.8.2 christos return NS_UNAVAIL;
275 1.75.8.2 christos }
276 1.75.8.2 christos
277 1.75.8.2 christos /*
278 1.75.8.2 christos * THE DECODING BELOW MUST MATCH THAT IN pwd_mkdb.
279 1.75.8.2 christos */
280 1.75.8.2 christos t = buffer;
281 1.75.8.2 christos #define MACRO(a) do { a } while (/*CONSTCOND*/0)
282 1.75.8.2 christos #define EXPAND(e) MACRO(e = t; while ((*t++ = *p++));)
283 1.75.8.2 christos #define SCALAR(v) MACRO(memmove(&(v), p, sizeof v); p += sizeof v;)
284 1.75.8.2 christos EXPAND(pw->pw_name);
285 1.75.8.2 christos EXPAND(pw->pw_passwd);
286 1.75.8.2 christos SCALAR(pw->pw_uid);
287 1.75.8.2 christos SCALAR(pw->pw_gid);
288 1.75.8.2 christos if (version == 0) {
289 1.75.8.2 christos int32_t tmp;
290 1.75.8.2 christos SCALAR(tmp);
291 1.75.8.2 christos pw->pw_change = tmp;
292 1.75.8.2 christos } else
293 1.75.8.2 christos SCALAR(pw->pw_change);
294 1.75.8.2 christos EXPAND(pw->pw_class);
295 1.75.8.2 christos EXPAND(pw->pw_gecos);
296 1.75.8.2 christos EXPAND(pw->pw_dir);
297 1.75.8.2 christos EXPAND(pw->pw_shell);
298 1.75.8.2 christos if (version == 0) {
299 1.75.8.2 christos int32_t tmp;
300 1.75.8.2 christos SCALAR(tmp);
301 1.75.8.2 christos pw->pw_expire = tmp;
302 1.75.8.2 christos } else
303 1.75.8.2 christos SCALAR(pw->pw_expire);
304 1.75.8.2 christos if (pwflags) {
305 1.75.8.2 christos /* See if there's any data left. If so, read in flags. */
306 1.75.8.2 christos if (data.size > (size_t) (p - (char *)data.data)) {
307 1.75.8.2 christos SCALAR(*pwflags);
308 1.75.8.2 christos } else { /* default */
309 1.75.8.2 christos *pwflags = _PASSWORD_NOUID|_PASSWORD_NOGID;
310 1.75.8.2 christos }
311 1.75.8.2 christos }
312 1.75.8.2 christos
313 1.75.8.2 christos return NS_SUCCESS;
314 1.75.8.2 christos }
315 1.75.8.2 christos
316 1.75.8.2 christos /*
317 1.75.8.2 christos * _pw_memfrombuf
318 1.75.8.2 christos * Obtain want bytes from buffer (of size buflen) and return a pointer
319 1.75.8.2 christos * to the available memory after adjusting buffer/buflen.
320 1.75.8.2 christos * Returns NULL if there is insufficient space.
321 1.75.8.2 christos */
322 1.75.8.2 christos static char *
323 1.75.8.2 christos _pw_memfrombuf(size_t want, char **buffer, size_t *buflen)
324 1.75.8.2 christos {
325 1.75.8.2 christos char *rv;
326 1.75.8.2 christos
327 1.75.8.2 christos if (want > *buflen) {
328 1.75.8.2 christos errno = ERANGE;
329 1.75.8.2 christos return NULL;
330 1.75.8.2 christos }
331 1.75.8.2 christos rv = *buffer;
332 1.75.8.2 christos *buffer += want;
333 1.75.8.2 christos *buflen -= want;
334 1.75.8.2 christos return rv;
335 1.75.8.2 christos }
336 1.75.8.2 christos
337 1.75.8.2 christos /*
338 1.75.8.2 christos * _pw_copy
339 1.75.8.2 christos * Copy the contents of frompw to pw; memory for strings
340 1.75.8.2 christos * and arrays will be allocated from buf (of size buflen).
341 1.75.8.2 christos * If proto != NULL, use various fields in proto in preference to frompw.
342 1.75.8.2 christos * Returns 1 if copied successfully, 0 on copy failure.
343 1.75.8.2 christos * NOTE: frompw must not use buf for its own pointers.
344 1.75.8.2 christos */
345 1.75.8.2 christos static int
346 1.75.8.2 christos _pw_copy(const struct passwd *frompw, struct passwd *pw,
347 1.75.8.2 christos char *buf, size_t buflen, const struct passwd *protopw, int protoflags)
348 1.75.8.2 christos {
349 1.75.8.2 christos size_t count;
350 1.75.8.2 christos int useproto;
351 1.75.8.2 christos
352 1.75.8.2 christos _DIAGASSERT(frompw != NULL);
353 1.75.8.2 christos _DIAGASSERT(pw != NULL);
354 1.75.8.2 christos _DIAGASSERT(buf != NULL);
355 1.75.8.2 christos /* protopw may be NULL */
356 1.75.8.2 christos
357 1.75.8.2 christos useproto = protopw && protopw->pw_name;
358 1.75.8.2 christos
359 1.75.8.2 christos #define COPYSTR(to, from) \
360 1.75.8.2 christos do { \
361 1.75.8.2 christos count = strlen((from)); \
362 1.75.8.2 christos (to) = _pw_memfrombuf(count+1, &buf, &buflen); \
363 1.75.8.2 christos if ((to) == NULL) \
364 1.75.8.2 christos return 0; \
365 1.75.8.2 christos memmove((to), (from), count); \
366 1.75.8.2 christos to[count] = '\0'; \
367 1.75.8.2 christos } while (0) /* LINTED */
368 1.75.8.2 christos
369 1.75.8.2 christos #define COPYFIELD(field) COPYSTR(pw->field, frompw->field)
370 1.75.8.2 christos
371 1.75.8.2 christos #define COPYPROTOFIELD(field) COPYSTR(pw->field, \
372 1.75.8.2 christos (useproto && *protopw->field ? protopw->field : frompw->field))
373 1.75.8.2 christos
374 1.75.8.2 christos COPYFIELD(pw_name);
375 1.75.8.2 christos
376 1.75.8.2 christos #ifdef PW_OVERRIDE_PASSWD
377 1.75.8.2 christos COPYPROTOFIELD(pw_passwd);
378 1.75.8.2 christos #else
379 1.75.8.2 christos COPYFIELD(pw_passwd);
380 1.75.8.2 christos #endif
381 1.75.8.2 christos
382 1.75.8.2 christos if (useproto && !(protoflags & _PASSWORD_NOUID))
383 1.75.8.2 christos pw->pw_uid = protopw->pw_uid;
384 1.75.8.2 christos else
385 1.75.8.2 christos pw->pw_uid = frompw->pw_uid;
386 1.75.8.2 christos
387 1.75.8.2 christos if (useproto && !(protoflags & _PASSWORD_NOGID))
388 1.75.8.2 christos pw->pw_gid = protopw->pw_gid;
389 1.75.8.2 christos else
390 1.75.8.2 christos pw->pw_gid = frompw->pw_gid;
391 1.75.8.2 christos
392 1.75.8.2 christos pw->pw_change = frompw->pw_change;
393 1.75.8.2 christos COPYFIELD(pw_class);
394 1.75.8.2 christos COPYPROTOFIELD(pw_gecos);
395 1.75.8.2 christos COPYPROTOFIELD(pw_dir);
396 1.75.8.2 christos COPYPROTOFIELD(pw_shell);
397 1.75.8.2 christos
398 1.75.8.2 christos #undef COPYSTR
399 1.75.8.2 christos #undef COPYFIELD
400 1.75.8.2 christos #undef COPYPROTOFIELD
401 1.75.8.2 christos
402 1.75.8.2 christos return 1;
403 1.75.8.2 christos }
404 1.75.8.2 christos
405 1.75.8.2 christos
406 1.75.8.2 christos /*
407 1.75.8.2 christos * files methods
408 1.75.8.2 christos */
409 1.75.8.2 christos
410 1.75.8.2 christos /* state shared between files methods */
411 1.75.8.2 christos struct files_state {
412 1.75.8.2 christos int stayopen; /* see getpassent(3) */
413 1.75.8.2 christos DB *db; /* passwd file handle */
414 1.75.8.2 christos int keynum; /* key counter, -1 if no more */
415 1.75.8.2 christos int version;
416 1.75.8.2 christos };
417 1.75.8.2 christos
418 1.75.8.2 christos static struct files_state _files_state;
419 1.75.8.2 christos /* storage for non _r functions */
420 1.75.8.2 christos static struct passwd _files_passwd;
421 1.75.8.2 christos static char _files_passwdbuf[_GETPW_R_SIZE_MAX];
422 1.75.8.2 christos
423 1.75.8.2 christos static int
424 1.75.8.2 christos _files_start(struct files_state *state)
425 1.75.8.2 christos {
426 1.75.8.2 christos int rv;
427 1.75.8.2 christos
428 1.75.8.2 christos _DIAGASSERT(state != NULL);
429 1.75.8.2 christos
430 1.75.8.2 christos state->keynum = 0;
431 1.75.8.2 christos rv = _pw_opendb(&state->db, &state->version);
432 1.75.8.2 christos if (rv != NS_SUCCESS)
433 1.75.8.2 christos return rv;
434 1.75.8.2 christos return NS_SUCCESS;
435 1.75.8.2 christos }
436 1.75.8.2 christos
437 1.75.8.2 christos static int
438 1.75.8.2 christos _files_end(struct files_state *state)
439 1.75.8.2 christos {
440 1.75.8.2 christos
441 1.75.8.2 christos _DIAGASSERT(state != NULL);
442 1.75.8.2 christos
443 1.75.8.2 christos state->keynum = 0;
444 1.75.8.2 christos if (state->db) {
445 1.75.8.2 christos (void)(state->db->close)(state->db);
446 1.75.8.2 christos state->db = NULL;
447 1.75.8.2 christos }
448 1.75.8.2 christos return NS_SUCCESS;
449 1.75.8.2 christos }
450 1.75.8.2 christos
451 1.75.8.2 christos /*
452 1.75.8.2 christos * _files_pwscan
453 1.75.8.2 christos * Search state->db for the next desired entry.
454 1.75.8.2 christos * If search is _PW_KEYBYNUM, look for state->keynum.
455 1.75.8.2 christos * If search is _PW_KEYBYNAME, look for name.
456 1.75.8.2 christos * If search is _PW_KEYBYUID, look for uid.
457 1.75.8.2 christos * Sets *retval to the errno if the result is not NS_SUCCESS
458 1.75.8.2 christos * or NS_NOTFOUND.
459 1.75.8.2 christos */
460 1.75.8.2 christos static int
461 1.75.8.2 christos _files_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
462 1.75.8.2 christos struct files_state *state, int search, const char *name, uid_t uid)
463 1.75.8.2 christos {
464 1.75.8.2 christos const void *from;
465 1.75.8.2 christos size_t fromlen;
466 1.75.8.2 christos DBT key;
467 1.75.8.2 christos int rv;
468 1.75.8.2 christos
469 1.75.8.2 christos _DIAGASSERT(retval != NULL);
470 1.75.8.2 christos _DIAGASSERT(pw != NULL);
471 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
472 1.75.8.2 christos _DIAGASSERT(state != NULL);
473 1.75.8.2 christos /* name is NULL to indicate searching for uid */
474 1.75.8.2 christos
475 1.75.8.2 christos *retval = 0;
476 1.75.8.2 christos
477 1.75.8.2 christos if (state->db == NULL) { /* only start if file not open yet */
478 1.75.8.2 christos rv = _files_start(state);
479 1.75.8.2 christos if (rv != NS_SUCCESS)
480 1.75.8.2 christos goto filespwscan_out;
481 1.75.8.2 christos }
482 1.75.8.2 christos
483 1.75.8.2 christos for (;;) { /* search for a match */
484 1.75.8.2 christos switch (search) {
485 1.75.8.2 christos case _PW_KEYBYNUM:
486 1.75.8.2 christos if (state->keynum == -1)
487 1.75.8.2 christos return NS_NOTFOUND; /* no more records */
488 1.75.8.2 christos state->keynum++;
489 1.75.8.2 christos from = &state->keynum;
490 1.75.8.2 christos fromlen = sizeof(state->keynum);
491 1.75.8.2 christos break;
492 1.75.8.2 christos case _PW_KEYBYNAME:
493 1.75.8.2 christos from = name;
494 1.75.8.2 christos fromlen = strlen(name);
495 1.75.8.2 christos break;
496 1.75.8.2 christos case _PW_KEYBYUID:
497 1.75.8.2 christos from = &uid;
498 1.75.8.2 christos fromlen = sizeof(uid);
499 1.75.8.2 christos break;
500 1.75.8.2 christos default:
501 1.75.8.2 christos abort();
502 1.75.8.2 christos }
503 1.75.8.2 christos
504 1.75.8.2 christos if (buflen <= fromlen) { /* buffer too small */
505 1.75.8.2 christos *retval = ERANGE;
506 1.75.8.2 christos return NS_UNAVAIL;
507 1.75.8.2 christos }
508 1.75.8.2 christos buffer[0] = search; /* setup key */
509 1.75.8.2 christos memmove(buffer + 1, from, fromlen);
510 1.75.8.2 christos key.size = fromlen + 1;
511 1.75.8.2 christos key.data = (u_char *)buffer;
512 1.75.8.2 christos
513 1.75.8.2 christos /* search for key */
514 1.75.8.2 christos rv = _pw_getkey(state->db, &key, pw, buffer, buflen, NULL,
515 1.75.8.2 christos state->version);
516 1.75.8.2 christos if (rv != NS_SUCCESS) /* no match */
517 1.75.8.2 christos break;
518 1.75.8.2 christos if (pw->pw_name[0] == '+' || pw->pw_name[0] == '-') {
519 1.75.8.2 christos /* if a compat line */
520 1.75.8.2 christos if (search == _PW_KEYBYNUM)
521 1.75.8.2 christos continue; /* read next if pwent */
522 1.75.8.2 christos rv = NS_NOTFOUND; /* don't match if pw{nam,uid} */
523 1.75.8.2 christos break;
524 1.75.8.2 christos }
525 1.75.8.2 christos break;
526 1.75.8.2 christos }
527 1.75.8.2 christos
528 1.75.8.2 christos if (rv == NS_NOTFOUND && search == _PW_KEYBYNUM)
529 1.75.8.2 christos state->keynum = -1; /* flag `no more records' */
530 1.75.8.2 christos
531 1.75.8.2 christos if (rv == NS_SUCCESS) {
532 1.75.8.2 christos if ((search == _PW_KEYBYUID && pw->pw_uid != uid) ||
533 1.75.8.2 christos (search == _PW_KEYBYNAME && strcmp(pw->pw_name, name) != 0))
534 1.75.8.2 christos rv = NS_NOTFOUND;
535 1.75.8.2 christos }
536 1.75.8.2 christos
537 1.75.8.2 christos filespwscan_out:
538 1.75.8.2 christos if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
539 1.75.8.2 christos *retval = errno;
540 1.75.8.2 christos return rv;
541 1.75.8.2 christos }
542 1.75.8.2 christos
543 1.75.8.2 christos /*ARGSUSED*/
544 1.75.8.2 christos static int
545 1.75.8.2 christos _files_setpwent(void *nsrv, void *nscb, va_list ap)
546 1.75.8.2 christos {
547 1.75.8.2 christos
548 1.75.8.2 christos _files_state.stayopen = 0;
549 1.75.8.2 christos return _files_start(&_files_state);
550 1.75.8.2 christos }
551 1.75.8.2 christos
552 1.75.8.2 christos /*ARGSUSED*/
553 1.75.8.2 christos static int
554 1.75.8.2 christos _files_setpassent(void *nsrv, void *nscb, va_list ap)
555 1.75.8.2 christos {
556 1.75.8.2 christos int *retval = va_arg(ap, int *);
557 1.75.8.2 christos int stayopen = va_arg(ap, int);
558 1.75.8.2 christos
559 1.75.8.2 christos int rv;
560 1.75.8.2 christos
561 1.75.8.2 christos _files_state.stayopen = stayopen;
562 1.75.8.2 christos rv = _files_start(&_files_state);
563 1.75.8.2 christos *retval = (rv == NS_SUCCESS);
564 1.75.8.2 christos return rv;
565 1.75.8.2 christos }
566 1.75.8.2 christos
567 1.75.8.2 christos /*ARGSUSED*/
568 1.75.8.2 christos static int
569 1.75.8.2 christos _files_endpwent(void *nsrv, void *nscb, va_list ap)
570 1.75.8.2 christos {
571 1.75.8.2 christos
572 1.75.8.2 christos _files_state.stayopen = 0;
573 1.75.8.2 christos return _files_end(&_files_state);
574 1.75.8.2 christos }
575 1.75.8.2 christos
576 1.75.8.2 christos /*ARGSUSED*/
577 1.75.8.2 christos static int
578 1.75.8.2 christos _files_getpwent(void *nsrv, void *nscb, va_list ap)
579 1.75.8.2 christos {
580 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
581 1.75.8.2 christos
582 1.75.8.2 christos int rv, rerror;
583 1.75.8.2 christos
584 1.75.8.2 christos _DIAGASSERT(retval != NULL);
585 1.75.8.2 christos
586 1.75.8.2 christos *retval = NULL;
587 1.75.8.2 christos rv = _files_pwscan(&rerror, &_files_passwd,
588 1.75.8.2 christos _files_passwdbuf, sizeof(_files_passwdbuf),
589 1.75.8.2 christos &_files_state, _PW_KEYBYNUM, NULL, 0);
590 1.75.8.2 christos if (rv == NS_SUCCESS)
591 1.75.8.2 christos *retval = &_files_passwd;
592 1.75.8.2 christos return rv;
593 1.75.8.2 christos }
594 1.75.8.2 christos
595 1.75.8.2 christos /*ARGSUSED*/
596 1.75.8.2 christos static int
597 1.75.8.2 christos _files_getpwent_r(void *nsrv, void *nscb, va_list ap)
598 1.75.8.2 christos {
599 1.75.8.2 christos int *retval = va_arg(ap, int *);
600 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
601 1.75.8.2 christos char *buffer = va_arg(ap, char *);
602 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
603 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
604 1.75.8.2 christos
605 1.75.8.2 christos int rv;
606 1.75.8.2 christos
607 1.75.8.2 christos _DIAGASSERT(retval != NULL);
608 1.75.8.2 christos _DIAGASSERT(pw != NULL);
609 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
610 1.75.8.2 christos _DIAGASSERT(result != NULL);
611 1.75.8.2 christos
612 1.75.8.2 christos rv = _files_pwscan(retval, pw, buffer, buflen, &_files_state,
613 1.75.8.2 christos _PW_KEYBYNUM, NULL, 0);
614 1.75.8.2 christos if (rv == NS_SUCCESS)
615 1.75.8.2 christos *result = pw;
616 1.75.8.2 christos else
617 1.75.8.2 christos *result = NULL;
618 1.75.8.2 christos return rv;
619 1.75.8.2 christos }
620 1.75.8.2 christos
621 1.75.8.2 christos /*ARGSUSED*/
622 1.75.8.2 christos static int
623 1.75.8.2 christos _files_getpwnam(void *nsrv, void *nscb, va_list ap)
624 1.75.8.2 christos {
625 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
626 1.75.8.2 christos const char *name = va_arg(ap, const char *);
627 1.75.8.2 christos
628 1.75.8.2 christos int rv, rerror;
629 1.75.8.2 christos
630 1.75.8.2 christos _DIAGASSERT(retval != NULL);
631 1.75.8.2 christos
632 1.75.8.2 christos *retval = NULL;
633 1.75.8.2 christos rv = _files_start(&_files_state);
634 1.75.8.2 christos if (rv != NS_SUCCESS)
635 1.75.8.2 christos return rv;
636 1.75.8.2 christos rv = _files_pwscan(&rerror, &_files_passwd,
637 1.75.8.2 christos _files_passwdbuf, sizeof(_files_passwdbuf),
638 1.75.8.2 christos &_files_state, _PW_KEYBYNAME, name, 0);
639 1.75.8.2 christos if (!_files_state.stayopen)
640 1.75.8.2 christos _files_end(&_files_state);
641 1.75.8.2 christos if (rv == NS_SUCCESS)
642 1.75.8.2 christos *retval = &_files_passwd;
643 1.75.8.2 christos return rv;
644 1.75.8.2 christos }
645 1.75.8.2 christos
646 1.75.8.2 christos /*ARGSUSED*/
647 1.75.8.2 christos static int
648 1.75.8.2 christos _files_getpwnam_r(void *nsrv, void *nscb, va_list ap)
649 1.75.8.2 christos {
650 1.75.8.2 christos int *retval = va_arg(ap, int *);
651 1.75.8.2 christos const char *name = va_arg(ap, const char *);
652 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
653 1.75.8.2 christos char *buffer = va_arg(ap, char *);
654 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
655 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
656 1.75.8.2 christos
657 1.75.8.2 christos struct files_state state;
658 1.75.8.2 christos int rv;
659 1.75.8.2 christos
660 1.75.8.2 christos _DIAGASSERT(retval != NULL);
661 1.75.8.2 christos _DIAGASSERT(pw != NULL);
662 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
663 1.75.8.2 christos _DIAGASSERT(result != NULL);
664 1.75.8.2 christos
665 1.75.8.2 christos *result = NULL;
666 1.75.8.2 christos memset(&state, 0, sizeof(state));
667 1.75.8.2 christos rv = _files_pwscan(retval, pw, buffer, buflen, &state,
668 1.75.8.2 christos _PW_KEYBYNAME, name, 0);
669 1.75.8.2 christos _files_end(&state);
670 1.75.8.2 christos if (rv == NS_SUCCESS)
671 1.75.8.2 christos *result = pw;
672 1.75.8.2 christos return rv;
673 1.75.8.2 christos }
674 1.75.8.2 christos
675 1.75.8.2 christos /*ARGSUSED*/
676 1.75.8.2 christos static int
677 1.75.8.2 christos _files_getpwuid(void *nsrv, void *nscb, va_list ap)
678 1.75.8.2 christos {
679 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
680 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
681 1.75.8.2 christos
682 1.75.8.2 christos int rv, rerror;
683 1.75.8.2 christos
684 1.75.8.2 christos _DIAGASSERT(retval != NULL);
685 1.75.8.2 christos
686 1.75.8.2 christos *retval = NULL;
687 1.75.8.2 christos rv = _files_start(&_files_state);
688 1.75.8.2 christos if (rv != NS_SUCCESS)
689 1.75.8.2 christos return rv;
690 1.75.8.2 christos rv = _files_pwscan(&rerror, &_files_passwd,
691 1.75.8.2 christos _files_passwdbuf, sizeof(_files_passwdbuf),
692 1.75.8.2 christos &_files_state, _PW_KEYBYUID, NULL, uid);
693 1.75.8.2 christos if (!_files_state.stayopen)
694 1.75.8.2 christos _files_end(&_files_state);
695 1.75.8.2 christos if (rv == NS_SUCCESS)
696 1.75.8.2 christos *retval = &_files_passwd;
697 1.75.8.2 christos return rv;
698 1.75.8.2 christos }
699 1.75.8.2 christos
700 1.75.8.2 christos /*ARGSUSED*/
701 1.75.8.2 christos static int
702 1.75.8.2 christos _files_getpwuid_r(void *nsrv, void *nscb, va_list ap)
703 1.75.8.2 christos {
704 1.75.8.2 christos int *retval = va_arg(ap, int *);
705 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
706 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
707 1.75.8.2 christos char *buffer = va_arg(ap, char *);
708 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
709 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
710 1.75.8.2 christos
711 1.75.8.2 christos struct files_state state;
712 1.75.8.2 christos int rv;
713 1.75.8.2 christos
714 1.75.8.2 christos _DIAGASSERT(retval != NULL);
715 1.75.8.2 christos _DIAGASSERT(pw != NULL);
716 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
717 1.75.8.2 christos _DIAGASSERT(result != NULL);
718 1.75.8.2 christos
719 1.75.8.2 christos *result = NULL;
720 1.75.8.2 christos memset(&state, 0, sizeof(state));
721 1.75.8.2 christos rv = _files_pwscan(retval, pw, buffer, buflen, &state,
722 1.75.8.2 christos _PW_KEYBYUID, NULL, uid);
723 1.75.8.2 christos _files_end(&state);
724 1.75.8.2 christos if (rv == NS_SUCCESS)
725 1.75.8.2 christos *result = pw;
726 1.75.8.2 christos return rv;
727 1.75.8.2 christos }
728 1.75.8.2 christos
729 1.75.8.2 christos
730 1.75.8.2 christos #ifdef HESIOD
731 1.75.8.2 christos /*
732 1.75.8.2 christos * dns methods
733 1.75.8.2 christos */
734 1.75.8.2 christos
735 1.75.8.2 christos /* state shared between dns methods */
736 1.75.8.2 christos struct dns_state {
737 1.75.8.2 christos int stayopen; /* see getpassent(3) */
738 1.75.8.2 christos void *context; /* Hesiod context */
739 1.75.8.2 christos int num; /* passwd index, -1 if no more */
740 1.75.8.2 christos };
741 1.75.8.2 christos
742 1.75.8.2 christos static struct dns_state _dns_state;
743 1.75.8.2 christos /* storage for non _r functions */
744 1.75.8.2 christos static struct passwd _dns_passwd;
745 1.75.8.2 christos static char _dns_passwdbuf[_GETPW_R_SIZE_MAX];
746 1.75.8.2 christos
747 1.75.8.2 christos static int
748 1.75.8.2 christos _dns_start(struct dns_state *state)
749 1.75.8.2 christos {
750 1.75.8.2 christos
751 1.75.8.2 christos _DIAGASSERT(state != NULL);
752 1.75.8.2 christos
753 1.75.8.2 christos state->num = 0;
754 1.75.8.2 christos if (state->context == NULL) { /* setup Hesiod */
755 1.75.8.2 christos if (hesiod_init(&state->context) == -1)
756 1.75.8.2 christos return NS_UNAVAIL;
757 1.75.8.2 christos }
758 1.75.8.2 christos
759 1.75.8.2 christos return NS_SUCCESS;
760 1.75.8.2 christos }
761 1.75.8.2 christos
762 1.75.8.2 christos static int
763 1.75.8.2 christos _dns_end(struct dns_state *state)
764 1.75.8.2 christos {
765 1.75.8.2 christos
766 1.75.8.2 christos _DIAGASSERT(state != NULL);
767 1.75.8.2 christos
768 1.75.8.2 christos state->num = 0;
769 1.75.8.2 christos if (state->context) {
770 1.75.8.2 christos hesiod_end(state->context);
771 1.75.8.2 christos state->context = NULL;
772 1.75.8.2 christos }
773 1.75.8.2 christos return NS_SUCCESS;
774 1.75.8.2 christos }
775 1.75.8.2 christos
776 1.75.8.2 christos /*
777 1.75.8.2 christos * _dns_pwscan
778 1.75.8.2 christos * Look for the Hesiod name provided in buffer in the NULL-terminated
779 1.75.8.2 christos * list of zones,
780 1.75.8.2 christos * and decode into pw/buffer/buflen.
781 1.75.8.2 christos */
782 1.75.8.2 christos static int
783 1.75.8.2 christos _dns_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
784 1.75.8.2 christos struct dns_state *state, const char **zones)
785 1.75.8.2 christos {
786 1.75.8.2 christos const char **curzone;
787 1.75.8.2 christos char **hp, *ep;
788 1.75.8.2 christos int rv;
789 1.75.8.2 christos
790 1.75.8.2 christos _DIAGASSERT(retval != NULL);
791 1.75.8.2 christos _DIAGASSERT(pw != NULL);
792 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
793 1.75.8.2 christos _DIAGASSERT(state != NULL);
794 1.75.8.2 christos _DIAGASSERT(zones != NULL);
795 1.75.8.2 christos
796 1.75.8.2 christos *retval = 0;
797 1.75.8.2 christos
798 1.75.8.2 christos if (state->context == NULL) { /* only start if Hesiod not setup */
799 1.75.8.2 christos rv = _dns_start(state);
800 1.75.8.2 christos if (rv != NS_SUCCESS)
801 1.75.8.2 christos return rv;
802 1.75.8.2 christos }
803 1.75.8.2 christos
804 1.75.8.2 christos hp = NULL;
805 1.75.8.2 christos rv = NS_NOTFOUND;
806 1.75.8.2 christos
807 1.75.8.2 christos for (curzone = zones; *curzone; curzone++) { /* search zones */
808 1.75.8.2 christos hp = hesiod_resolve(state->context, buffer, *curzone);
809 1.75.8.2 christos if (hp != NULL)
810 1.75.8.2 christos break;
811 1.75.8.2 christos if (errno != ENOENT) {
812 1.75.8.2 christos rv = NS_UNAVAIL;
813 1.75.8.2 christos goto dnspwscan_out;
814 1.75.8.2 christos }
815 1.75.8.2 christos }
816 1.75.8.2 christos if (*curzone == NULL)
817 1.75.8.2 christos goto dnspwscan_out;
818 1.75.8.2 christos
819 1.75.8.2 christos if ((ep = strchr(hp[0], '\n')) != NULL)
820 1.75.8.2 christos *ep = '\0'; /* clear trailing \n */
821 1.75.8.2 christos if (_pw_parse(hp[0], pw, buffer, buflen, 1)) /* validate line */
822 1.75.8.2 christos rv = NS_SUCCESS;
823 1.75.8.2 christos else
824 1.75.8.2 christos rv = NS_UNAVAIL;
825 1.75.8.2 christos
826 1.75.8.2 christos dnspwscan_out:
827 1.75.8.2 christos if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
828 1.75.8.2 christos *retval = errno;
829 1.75.8.2 christos if (hp)
830 1.75.8.2 christos hesiod_free_list(state->context, hp);
831 1.75.8.2 christos return rv;
832 1.75.8.2 christos }
833 1.75.8.2 christos
834 1.75.8.2 christos /*ARGSUSED*/
835 1.75.8.2 christos static int
836 1.75.8.2 christos _dns_setpwent(void *nsrv, void *nscb, va_list ap)
837 1.75.8.2 christos {
838 1.75.8.2 christos
839 1.75.8.2 christos _dns_state.stayopen = 0;
840 1.75.8.2 christos return _dns_start(&_dns_state);
841 1.75.8.2 christos }
842 1.75.8.2 christos
843 1.75.8.2 christos /*ARGSUSED*/
844 1.75.8.2 christos static int
845 1.75.8.2 christos _dns_setpassent(void *nsrv, void *nscb, va_list ap)
846 1.75.8.2 christos {
847 1.75.8.2 christos int *retval = va_arg(ap, int *);
848 1.75.8.2 christos int stayopen = va_arg(ap, int);
849 1.75.8.2 christos
850 1.75.8.2 christos int rv;
851 1.75.8.2 christos
852 1.75.8.2 christos _dns_state.stayopen = stayopen;
853 1.75.8.2 christos rv = _dns_start(&_dns_state);
854 1.75.8.2 christos *retval = (rv == NS_SUCCESS);
855 1.75.8.2 christos return rv;
856 1.75.8.2 christos }
857 1.75.8.2 christos
858 1.75.8.2 christos /*ARGSUSED*/
859 1.75.8.2 christos static int
860 1.75.8.2 christos _dns_endpwent(void *nsrv, void *nscb, va_list ap)
861 1.75.8.2 christos {
862 1.75.8.2 christos
863 1.75.8.2 christos _dns_state.stayopen = 0;
864 1.75.8.2 christos return _dns_end(&_dns_state);
865 1.75.8.2 christos }
866 1.75.8.2 christos
867 1.75.8.2 christos /*ARGSUSED*/
868 1.75.8.2 christos static int
869 1.75.8.2 christos _dns_getpwent(void *nsrv, void *nscb, va_list ap)
870 1.75.8.2 christos {
871 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
872 1.75.8.2 christos
873 1.75.8.2 christos char **hp, *ep;
874 1.75.8.2 christos int rv;
875 1.75.8.2 christos
876 1.75.8.2 christos _DIAGASSERT(retval != NULL);
877 1.75.8.2 christos
878 1.75.8.2 christos *retval = NULL;
879 1.75.8.2 christos
880 1.75.8.2 christos if (_dns_state.num == -1) /* exhausted search */
881 1.75.8.2 christos return NS_NOTFOUND;
882 1.75.8.2 christos
883 1.75.8.2 christos if (_dns_state.context == NULL) {
884 1.75.8.2 christos /* only start if Hesiod not setup */
885 1.75.8.2 christos rv = _dns_start(&_dns_state);
886 1.75.8.2 christos if (rv != NS_SUCCESS)
887 1.75.8.2 christos return rv;
888 1.75.8.2 christos }
889 1.75.8.2 christos
890 1.75.8.2 christos next_dns_entry:
891 1.75.8.2 christos hp = NULL;
892 1.75.8.2 christos rv = NS_NOTFOUND;
893 1.75.8.2 christos
894 1.75.8.2 christos /* find passwd-NNN */
895 1.75.8.2 christos snprintf(_dns_passwdbuf, sizeof(_dns_passwdbuf),
896 1.75.8.2 christos "passwd-%u", _dns_state.num);
897 1.75.8.2 christos _dns_state.num++;
898 1.75.8.2 christos
899 1.75.8.2 christos hp = hesiod_resolve(_dns_state.context, _dns_passwdbuf, "passwd");
900 1.75.8.2 christos if (hp == NULL) {
901 1.75.8.2 christos if (errno == ENOENT)
902 1.75.8.2 christos _dns_state.num = -1;
903 1.75.8.2 christos else
904 1.75.8.2 christos rv = NS_UNAVAIL;
905 1.75.8.2 christos } else {
906 1.75.8.2 christos if ((ep = strchr(hp[0], '\n')) != NULL)
907 1.75.8.2 christos *ep = '\0'; /* clear trailing \n */
908 1.75.8.2 christos /* validate line */
909 1.75.8.2 christos if (_pw_parse(hp[0], &_dns_passwd,
910 1.75.8.2 christos _dns_passwdbuf, sizeof(_dns_passwdbuf), 1))
911 1.75.8.2 christos rv = NS_SUCCESS;
912 1.75.8.2 christos else { /* dodgy entry, try again */
913 1.75.8.2 christos hesiod_free_list(_dns_state.context, hp);
914 1.75.8.2 christos goto next_dns_entry;
915 1.75.8.2 christos }
916 1.75.8.2 christos }
917 1.75.8.2 christos
918 1.75.8.2 christos if (hp)
919 1.75.8.2 christos hesiod_free_list(_dns_state.context, hp);
920 1.75.8.2 christos if (rv == NS_SUCCESS)
921 1.75.8.2 christos *retval = &_dns_passwd;
922 1.75.8.2 christos return rv;
923 1.75.8.2 christos }
924 1.75.8.2 christos
925 1.75.8.2 christos /*ARGSUSED*/
926 1.75.8.2 christos static int
927 1.75.8.2 christos _dns_getpwent_r(void *nsrv, void *nscb, va_list ap)
928 1.75.8.2 christos {
929 1.75.8.2 christos int *retval = va_arg(ap, int *);
930 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
931 1.75.8.2 christos char *buffer = va_arg(ap, char *);
932 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
933 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
934 1.75.8.2 christos
935 1.75.8.2 christos char **hp, *ep;
936 1.75.8.2 christos int rv;
937 1.75.8.2 christos
938 1.75.8.2 christos _DIAGASSERT(retval != NULL);
939 1.75.8.2 christos _DIAGASSERT(pw != NULL);
940 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
941 1.75.8.2 christos _DIAGASSERT(result != NULL);
942 1.75.8.2 christos
943 1.75.8.2 christos *retval = 0;
944 1.75.8.2 christos
945 1.75.8.2 christos if (_dns_state.num == -1) /* exhausted search */
946 1.75.8.2 christos return NS_NOTFOUND;
947 1.75.8.2 christos
948 1.75.8.2 christos if (_dns_state.context == NULL) {
949 1.75.8.2 christos /* only start if Hesiod not setup */
950 1.75.8.2 christos rv = _dns_start(&_dns_state);
951 1.75.8.2 christos if (rv != NS_SUCCESS)
952 1.75.8.2 christos return rv;
953 1.75.8.2 christos }
954 1.75.8.2 christos
955 1.75.8.2 christos next_dns_entry:
956 1.75.8.2 christos hp = NULL;
957 1.75.8.2 christos rv = NS_NOTFOUND;
958 1.75.8.2 christos
959 1.75.8.2 christos /* find passwd-NNN */
960 1.75.8.2 christos snprintf(buffer, buflen, "passwd-%u", _dns_state.num);
961 1.75.8.2 christos _dns_state.num++;
962 1.75.8.2 christos
963 1.75.8.2 christos hp = hesiod_resolve(_dns_state.context, buffer, "passwd");
964 1.75.8.2 christos if (hp == NULL) {
965 1.75.8.2 christos if (errno == ENOENT)
966 1.75.8.2 christos _dns_state.num = -1;
967 1.75.8.2 christos else
968 1.75.8.2 christos rv = NS_UNAVAIL;
969 1.75.8.2 christos } else {
970 1.75.8.2 christos if ((ep = strchr(hp[0], '\n')) != NULL)
971 1.75.8.2 christos *ep = '\0'; /* clear trailing \n */
972 1.75.8.2 christos /* validate line */
973 1.75.8.2 christos if (_pw_parse(hp[0], pw, buffer, buflen, 1))
974 1.75.8.2 christos rv = NS_SUCCESS;
975 1.75.8.2 christos else { /* dodgy entry, try again */
976 1.75.8.2 christos hesiod_free_list(_dns_state.context, hp);
977 1.75.8.2 christos goto next_dns_entry;
978 1.75.8.2 christos }
979 1.75.8.2 christos }
980 1.75.8.2 christos
981 1.75.8.2 christos if (hp)
982 1.75.8.2 christos hesiod_free_list(_dns_state.context, hp);
983 1.75.8.2 christos if (rv == NS_SUCCESS)
984 1.75.8.2 christos *result = pw;
985 1.75.8.2 christos else
986 1.75.8.2 christos *result = NULL;
987 1.75.8.2 christos return rv;
988 1.75.8.2 christos }
989 1.75.8.2 christos
990 1.75.8.2 christos static const char *_dns_uid_zones[] = {
991 1.75.8.2 christos "uid",
992 1.75.8.2 christos "passwd",
993 1.75.8.2 christos NULL
994 1.75.8.2 christos };
995 1.75.8.2 christos
996 1.75.8.2 christos /*ARGSUSED*/
997 1.75.8.2 christos static int
998 1.75.8.2 christos _dns_getpwuid(void *nsrv, void *nscb, va_list ap)
999 1.75.8.2 christos {
1000 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
1001 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
1002 1.75.8.2 christos
1003 1.75.8.2 christos int rv, rerror;
1004 1.75.8.2 christos
1005 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1006 1.75.8.2 christos
1007 1.75.8.2 christos *retval = NULL;
1008 1.75.8.2 christos rv = _dns_start(&_dns_state);
1009 1.75.8.2 christos if (rv != NS_SUCCESS)
1010 1.75.8.2 christos return rv;
1011 1.75.8.2 christos snprintf(_dns_passwdbuf, sizeof(_dns_passwdbuf),
1012 1.75.8.2 christos "%u", (unsigned int)uid);
1013 1.75.8.2 christos rv = _dns_pwscan(&rerror, &_dns_passwd,
1014 1.75.8.2 christos _dns_passwdbuf, sizeof(_dns_passwdbuf),
1015 1.75.8.2 christos &_dns_state, _dns_uid_zones);
1016 1.75.8.2 christos if (!_dns_state.stayopen)
1017 1.75.8.2 christos _dns_end(&_dns_state);
1018 1.75.8.2 christos if (rv == NS_SUCCESS && uid == _dns_passwd.pw_uid)
1019 1.75.8.2 christos *retval = &_dns_passwd;
1020 1.75.8.2 christos return rv;
1021 1.75.8.2 christos }
1022 1.75.8.2 christos
1023 1.75.8.2 christos /*ARGSUSED*/
1024 1.75.8.2 christos static int
1025 1.75.8.2 christos _dns_getpwuid_r(void *nsrv, void *nscb, va_list ap)
1026 1.75.8.2 christos {
1027 1.75.8.2 christos int *retval = va_arg(ap, int *);
1028 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
1029 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
1030 1.75.8.2 christos char *buffer = va_arg(ap, char *);
1031 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
1032 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
1033 1.75.8.2 christos
1034 1.75.8.2 christos struct dns_state state;
1035 1.75.8.2 christos int rv;
1036 1.75.8.2 christos
1037 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1038 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1039 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
1040 1.75.8.2 christos _DIAGASSERT(result != NULL);
1041 1.75.8.2 christos
1042 1.75.8.2 christos *result = NULL;
1043 1.75.8.2 christos memset(&state, 0, sizeof(state));
1044 1.75.8.2 christos snprintf(buffer, buflen, "%u", (unsigned int)uid);
1045 1.75.8.2 christos rv = _dns_pwscan(retval, pw, buffer, buflen, &state, _dns_uid_zones);
1046 1.75.8.2 christos _dns_end(&state);
1047 1.75.8.2 christos if (rv != NS_SUCCESS)
1048 1.75.8.2 christos return rv;
1049 1.75.8.2 christos if (uid == pw->pw_uid) {
1050 1.75.8.2 christos *result = pw;
1051 1.75.8.2 christos return NS_SUCCESS;
1052 1.75.8.2 christos } else
1053 1.75.8.2 christos return NS_NOTFOUND;
1054 1.75.8.2 christos }
1055 1.75.8.2 christos
1056 1.75.8.2 christos static const char *_dns_nam_zones[] = {
1057 1.75.8.2 christos "passwd",
1058 1.75.8.2 christos NULL
1059 1.75.8.2 christos };
1060 1.75.8.2 christos
1061 1.75.8.2 christos /*ARGSUSED*/
1062 1.75.8.2 christos static int
1063 1.75.8.2 christos _dns_getpwnam(void *nsrv, void *nscb, va_list ap)
1064 1.75.8.2 christos {
1065 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
1066 1.75.8.2 christos const char *name = va_arg(ap, const char *);
1067 1.75.8.2 christos
1068 1.75.8.2 christos int rv, rerror;
1069 1.75.8.2 christos
1070 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1071 1.75.8.2 christos
1072 1.75.8.2 christos *retval = NULL;
1073 1.75.8.2 christos rv = _dns_start(&_dns_state);
1074 1.75.8.2 christos if (rv != NS_SUCCESS)
1075 1.75.8.2 christos return rv;
1076 1.75.8.2 christos snprintf(_dns_passwdbuf, sizeof(_dns_passwdbuf), "%s", name);
1077 1.75.8.2 christos rv = _dns_pwscan(&rerror, &_dns_passwd,
1078 1.75.8.2 christos _dns_passwdbuf, sizeof(_dns_passwdbuf),
1079 1.75.8.2 christos &_dns_state, _dns_nam_zones);
1080 1.75.8.2 christos if (!_dns_state.stayopen)
1081 1.75.8.2 christos _dns_end(&_dns_state);
1082 1.75.8.2 christos if (rv == NS_SUCCESS && strcmp(name, _dns_passwd.pw_name) == 0)
1083 1.75.8.2 christos *retval = &_dns_passwd;
1084 1.75.8.2 christos return rv;
1085 1.75.8.2 christos }
1086 1.75.8.2 christos
1087 1.75.8.2 christos /*ARGSUSED*/
1088 1.75.8.2 christos static int
1089 1.75.8.2 christos _dns_getpwnam_r(void *nsrv, void *nscb, va_list ap)
1090 1.75.8.2 christos {
1091 1.75.8.2 christos int *retval = va_arg(ap, int *);
1092 1.75.8.2 christos const char *name = va_arg(ap, const char *);
1093 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
1094 1.75.8.2 christos char *buffer = va_arg(ap, char *);
1095 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
1096 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
1097 1.75.8.2 christos
1098 1.75.8.2 christos struct dns_state state;
1099 1.75.8.2 christos int rv;
1100 1.75.8.2 christos
1101 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1102 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1103 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
1104 1.75.8.2 christos _DIAGASSERT(result != NULL);
1105 1.75.8.2 christos
1106 1.75.8.2 christos *result = NULL;
1107 1.75.8.2 christos memset(&state, 0, sizeof(state));
1108 1.75.8.2 christos snprintf(buffer, buflen, "%s", name);
1109 1.75.8.2 christos rv = _dns_pwscan(retval, pw, buffer, buflen, &state, _dns_nam_zones);
1110 1.75.8.2 christos _dns_end(&state);
1111 1.75.8.2 christos if (rv != NS_SUCCESS)
1112 1.75.8.2 christos return rv;
1113 1.75.8.2 christos if (strcmp(name, pw->pw_name) == 0) {
1114 1.75.8.2 christos *result = pw;
1115 1.75.8.2 christos return NS_SUCCESS;
1116 1.75.8.2 christos } else
1117 1.75.8.2 christos return NS_NOTFOUND;
1118 1.75.8.2 christos }
1119 1.75.8.2 christos
1120 1.75.8.2 christos #endif /* HESIOD */
1121 1.75.8.2 christos
1122 1.75.8.2 christos
1123 1.75.8.2 christos #ifdef YP
1124 1.75.8.2 christos /*
1125 1.75.8.2 christos * nis methods
1126 1.75.8.2 christos */
1127 1.75.8.2 christos /* state shared between nis methods */
1128 1.75.8.2 christos struct nis_state {
1129 1.75.8.2 christos int stayopen; /* see getpassent(3) */
1130 1.75.8.2 christos char *domain; /* NIS domain */
1131 1.75.8.2 christos int done; /* non-zero if search exhausted */
1132 1.75.8.2 christos char *current; /* current first/next match */
1133 1.75.8.2 christos int currentlen; /* length of _nis_current */
1134 1.75.8.2 christos enum { /* shadow map type */
1135 1.75.8.2 christos NISMAP_UNKNOWN, /* unknown ... */
1136 1.75.8.2 christos NISMAP_NONE, /* none: use "passwd.by*" */
1137 1.75.8.2 christos NISMAP_ADJUNCT, /* pw_passwd from "passwd.adjunct.*" */
1138 1.75.8.2 christos NISMAP_MASTER /* all from "master.passwd.by*" */
1139 1.75.8.2 christos } maptype;
1140 1.75.8.2 christos };
1141 1.75.8.2 christos
1142 1.75.8.2 christos static struct nis_state _nis_state;
1143 1.75.8.2 christos /* storage for non _r functions */
1144 1.75.8.2 christos static struct passwd _nis_passwd;
1145 1.75.8.2 christos static char _nis_passwdbuf[_GETPW_R_SIZE_MAX];
1146 1.75.8.2 christos
1147 1.75.8.2 christos /* macros for deciding which NIS maps to use. */
1148 1.75.8.2 christos #define PASSWD_BYNAME(x) ((x)->maptype == NISMAP_MASTER \
1149 1.75.8.2 christos ? "master.passwd.byname" : "passwd.byname")
1150 1.75.8.2 christos #define PASSWD_BYUID(x) ((x)->maptype == NISMAP_MASTER \
1151 1.75.8.2 christos ? "master.passwd.byuid" : "passwd.byuid")
1152 1.75.8.2 christos
1153 1.75.8.2 christos static int
1154 1.75.8.2 christos _nis_start(struct nis_state *state)
1155 1.75.8.2 christos {
1156 1.75.8.2 christos
1157 1.75.8.2 christos _DIAGASSERT(state != NULL);
1158 1.75.8.2 christos
1159 1.75.8.2 christos state->done = 0;
1160 1.75.8.2 christos if (state->current) {
1161 1.75.8.2 christos free(state->current);
1162 1.75.8.2 christos state->current = NULL;
1163 1.75.8.2 christos }
1164 1.75.8.2 christos if (state->domain == NULL) { /* setup NIS */
1165 1.75.8.2 christos switch (yp_get_default_domain(&state->domain)) {
1166 1.75.8.2 christos case 0:
1167 1.75.8.2 christos break;
1168 1.75.8.2 christos case YPERR_RESRC:
1169 1.75.8.2 christos return NS_TRYAGAIN;
1170 1.75.8.2 christos default:
1171 1.75.8.2 christos return NS_UNAVAIL;
1172 1.75.8.2 christos }
1173 1.75.8.2 christos }
1174 1.75.8.2 christos
1175 1.75.8.2 christos /* determine where to get pw_passwd from */
1176 1.75.8.2 christos if (state->maptype == NISMAP_UNKNOWN) {
1177 1.75.8.2 christos int r, order;
1178 1.75.8.2 christos
1179 1.75.8.2 christos state->maptype = NISMAP_NONE; /* default to no adjunct */
1180 1.75.8.2 christos if (geteuid() != 0) /* non-root can't use adjunct */
1181 1.75.8.2 christos return NS_SUCCESS;
1182 1.75.8.2 christos
1183 1.75.8.2 christos /* look for "master.passwd.*" */
1184 1.75.8.2 christos r = yp_order(state->domain, "master.passwd.byname", &order);
1185 1.75.8.2 christos if (r == 0) {
1186 1.75.8.2 christos state->maptype = NISMAP_MASTER;
1187 1.75.8.2 christos return NS_SUCCESS;
1188 1.75.8.2 christos }
1189 1.75.8.2 christos
1190 1.75.8.2 christos /* master.passwd doesn't exist, try passwd.adjunct */
1191 1.75.8.2 christos if (r == YPERR_MAP) {
1192 1.75.8.2 christos r = yp_order(state->domain, "passwd.adjunct.byname",
1193 1.75.8.2 christos &order);
1194 1.75.8.2 christos if (r == 0)
1195 1.75.8.2 christos state->maptype = NISMAP_ADJUNCT;
1196 1.75.8.2 christos }
1197 1.75.8.2 christos }
1198 1.75.8.2 christos return NS_SUCCESS;
1199 1.75.8.2 christos }
1200 1.75.8.2 christos
1201 1.75.8.2 christos static int
1202 1.75.8.2 christos _nis_end(struct nis_state *state)
1203 1.75.8.2 christos {
1204 1.75.8.2 christos
1205 1.75.8.2 christos _DIAGASSERT(state != NULL);
1206 1.75.8.2 christos
1207 1.75.8.2 christos if (state->domain)
1208 1.75.8.2 christos state->domain = NULL;
1209 1.75.8.2 christos state->done = 0;
1210 1.75.8.2 christos if (state->current)
1211 1.75.8.2 christos free(state->current);
1212 1.75.8.2 christos state->current = NULL;
1213 1.75.8.2 christos state->maptype = NISMAP_UNKNOWN;
1214 1.75.8.2 christos return NS_SUCCESS;
1215 1.75.8.2 christos }
1216 1.75.8.2 christos
1217 1.75.8.2 christos /*
1218 1.75.8.2 christos * nis_parse
1219 1.75.8.2 christos * wrapper to _pw_parse that obtains the real password from the
1220 1.75.8.2 christos * "passwd.adjunct.byname" NIS map if the maptype is NISMAP_ADJUNCT.
1221 1.75.8.2 christos */
1222 1.75.8.2 christos static int
1223 1.75.8.2 christos _nis_parse(const char *entry, struct passwd *pw, char *buf, size_t buflen,
1224 1.75.8.2 christos struct nis_state *state)
1225 1.75.8.2 christos {
1226 1.75.8.2 christos size_t elen;
1227 1.75.8.2 christos
1228 1.75.8.2 christos _DIAGASSERT(entry != NULL);
1229 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1230 1.75.8.2 christos _DIAGASSERT(buf != NULL);
1231 1.75.8.2 christos _DIAGASSERT(state != NULL);
1232 1.75.8.2 christos
1233 1.75.8.2 christos elen = strlen(entry);
1234 1.75.8.2 christos if (elen >= buflen)
1235 1.75.8.2 christos return 0;
1236 1.75.8.2 christos if (! _pw_parse(entry, pw, buf, buflen,
1237 1.75.8.2 christos !(state->maptype == NISMAP_MASTER)))
1238 1.75.8.2 christos return 0;
1239 1.75.8.2 christos
1240 1.75.8.2 christos if ((state->maptype == NISMAP_ADJUNCT) &&
1241 1.75.8.2 christos (strstr(pw->pw_passwd, "##") != NULL)) {
1242 1.75.8.2 christos char *data;
1243 1.75.8.2 christos int datalen;
1244 1.75.8.2 christos
1245 1.75.8.2 christos if (yp_match(state->domain, "passwd.adjunct.byname",
1246 1.75.8.2 christos pw->pw_name, (int)strlen(pw->pw_name),
1247 1.75.8.2 christos &data, &datalen) == 0) {
1248 1.75.8.2 christos char *bp, *ep;
1249 1.75.8.2 christos /* skip name to get password */
1250 1.75.8.2 christos ep = data;
1251 1.75.8.2 christos if ((bp = strsep(&ep, ":")) != NULL &&
1252 1.75.8.2 christos (bp = strsep(&ep, ":")) != NULL) {
1253 1.75.8.2 christos /* store new pw_passwd after entry */
1254 1.75.8.2 christos strlcpy(buf + elen, bp, buflen - elen);
1255 1.75.8.2 christos pw->pw_passwd = &buf[elen];
1256 1.75.8.2 christos }
1257 1.75.8.2 christos free(data);
1258 1.75.8.2 christos }
1259 1.75.8.2 christos }
1260 1.75.8.2 christos
1261 1.75.8.2 christos return 1;
1262 1.75.8.2 christos }
1263 1.75.8.2 christos
1264 1.75.8.2 christos
1265 1.75.8.2 christos /*
1266 1.75.8.2 christos * _nis_pwscan
1267 1.75.8.2 christos * Look for the yp key provided in buffer from map,
1268 1.75.8.2 christos * and decode into pw/buffer/buflen.
1269 1.75.8.2 christos */
1270 1.75.8.2 christos static int
1271 1.75.8.2 christos _nis_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
1272 1.75.8.2 christos struct nis_state *state, const char *map)
1273 1.75.8.2 christos {
1274 1.75.8.2 christos char *data;
1275 1.75.8.2 christos int nisr, rv, datalen;
1276 1.75.8.2 christos
1277 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1278 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1279 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
1280 1.75.8.2 christos _DIAGASSERT(state != NULL);
1281 1.75.8.2 christos _DIAGASSERT(map != NULL);
1282 1.75.8.2 christos
1283 1.75.8.2 christos *retval = 0;
1284 1.75.8.2 christos
1285 1.75.8.2 christos if (state->domain == NULL) { /* only start if NIS not setup */
1286 1.75.8.2 christos rv = _nis_start(state);
1287 1.75.8.2 christos if (rv != NS_SUCCESS)
1288 1.75.8.2 christos return rv;
1289 1.75.8.2 christos }
1290 1.75.8.2 christos
1291 1.75.8.2 christos data = NULL;
1292 1.75.8.2 christos rv = NS_NOTFOUND;
1293 1.75.8.2 christos
1294 1.75.8.2 christos /* search map */
1295 1.75.8.2 christos nisr = yp_match(state->domain, map, buffer, (int)strlen(buffer),
1296 1.75.8.2 christos &data, &datalen);
1297 1.75.8.2 christos switch (nisr) {
1298 1.75.8.2 christos case 0:
1299 1.75.8.2 christos data[datalen] = '\0'; /* clear trailing \n */
1300 1.75.8.2 christos if (_nis_parse(data, pw, buffer, buflen, state))
1301 1.75.8.2 christos rv = NS_SUCCESS; /* validate line */
1302 1.75.8.2 christos else
1303 1.75.8.2 christos rv = NS_UNAVAIL;
1304 1.75.8.2 christos break;
1305 1.75.8.2 christos case YPERR_KEY:
1306 1.75.8.2 christos break;
1307 1.75.8.2 christos default:
1308 1.75.8.2 christos rv = NS_UNAVAIL;
1309 1.75.8.2 christos break;
1310 1.75.8.2 christos }
1311 1.75.8.2 christos
1312 1.75.8.2 christos if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
1313 1.75.8.2 christos *retval = errno;
1314 1.75.8.2 christos if (data)
1315 1.75.8.2 christos free(data);
1316 1.75.8.2 christos return rv;
1317 1.75.8.2 christos }
1318 1.75.8.2 christos
1319 1.75.8.2 christos /*ARGSUSED*/
1320 1.75.8.2 christos static int
1321 1.75.8.2 christos _nis_setpwent(void *nsrv, void *nscb, va_list ap)
1322 1.75.8.2 christos {
1323 1.75.8.2 christos
1324 1.75.8.2 christos _nis_state.stayopen = 0;
1325 1.75.8.2 christos return _nis_start(&_nis_state);
1326 1.75.8.2 christos }
1327 1.75.8.2 christos
1328 1.75.8.2 christos /*ARGSUSED*/
1329 1.75.8.2 christos static int
1330 1.75.8.2 christos _nis_setpassent(void *nsrv, void *nscb, va_list ap)
1331 1.75.8.2 christos {
1332 1.75.8.2 christos int *retval = va_arg(ap, int *);
1333 1.75.8.2 christos int stayopen = va_arg(ap, int);
1334 1.75.8.2 christos
1335 1.75.8.2 christos int rv;
1336 1.75.8.2 christos
1337 1.75.8.2 christos _nis_state.stayopen = stayopen;
1338 1.75.8.2 christos rv = _nis_start(&_nis_state);
1339 1.75.8.2 christos *retval = (rv == NS_SUCCESS);
1340 1.75.8.2 christos return rv;
1341 1.75.8.2 christos }
1342 1.75.8.2 christos
1343 1.75.8.2 christos /*ARGSUSED*/
1344 1.75.8.2 christos static int
1345 1.75.8.2 christos _nis_endpwent(void *nsrv, void *nscb, va_list ap)
1346 1.75.8.2 christos {
1347 1.75.8.2 christos
1348 1.75.8.2 christos return _nis_end(&_nis_state);
1349 1.75.8.2 christos }
1350 1.75.8.2 christos
1351 1.75.8.2 christos
1352 1.75.8.2 christos /*ARGSUSED*/
1353 1.75.8.2 christos static int
1354 1.75.8.2 christos _nis_getpwent(void *nsrv, void *nscb, va_list ap)
1355 1.75.8.2 christos {
1356 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
1357 1.75.8.2 christos
1358 1.75.8.2 christos char *key, *data;
1359 1.75.8.2 christos int keylen, datalen, rv, nisr;
1360 1.75.8.2 christos
1361 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1362 1.75.8.2 christos
1363 1.75.8.2 christos *retval = NULL;
1364 1.75.8.2 christos
1365 1.75.8.2 christos if (_nis_state.done) /* exhausted search */
1366 1.75.8.2 christos return NS_NOTFOUND;
1367 1.75.8.2 christos if (_nis_state.domain == NULL) {
1368 1.75.8.2 christos /* only start if NIS not setup */
1369 1.75.8.2 christos rv = _nis_start(&_nis_state);
1370 1.75.8.2 christos if (rv != NS_SUCCESS)
1371 1.75.8.2 christos return rv;
1372 1.75.8.2 christos }
1373 1.75.8.2 christos
1374 1.75.8.2 christos next_nis_entry:
1375 1.75.8.2 christos key = NULL;
1376 1.75.8.2 christos data = NULL;
1377 1.75.8.2 christos rv = NS_NOTFOUND;
1378 1.75.8.2 christos
1379 1.75.8.2 christos if (_nis_state.current) { /* already searching */
1380 1.75.8.2 christos nisr = yp_next(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
1381 1.75.8.2 christos _nis_state.current, _nis_state.currentlen,
1382 1.75.8.2 christos &key, &keylen, &data, &datalen);
1383 1.75.8.2 christos free(_nis_state.current);
1384 1.75.8.2 christos _nis_state.current = NULL;
1385 1.75.8.2 christos switch (nisr) {
1386 1.75.8.2 christos case 0:
1387 1.75.8.2 christos _nis_state.current = key;
1388 1.75.8.2 christos _nis_state.currentlen = keylen;
1389 1.75.8.2 christos key = NULL;
1390 1.75.8.2 christos break;
1391 1.75.8.2 christos case YPERR_NOMORE:
1392 1.75.8.2 christos _nis_state.done = 1;
1393 1.75.8.2 christos goto nisent_out;
1394 1.75.8.2 christos default:
1395 1.75.8.2 christos rv = NS_UNAVAIL;
1396 1.75.8.2 christos goto nisent_out;
1397 1.75.8.2 christos }
1398 1.75.8.2 christos } else { /* new search */
1399 1.75.8.2 christos if (yp_first(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
1400 1.75.8.2 christos &_nis_state.current, &_nis_state.currentlen,
1401 1.75.8.2 christos &data, &datalen)) {
1402 1.75.8.2 christos rv = NS_UNAVAIL;
1403 1.75.8.2 christos goto nisent_out;
1404 1.75.8.2 christos }
1405 1.75.8.2 christos }
1406 1.75.8.2 christos
1407 1.75.8.2 christos data[datalen] = '\0'; /* clear trailing \n */
1408 1.75.8.2 christos /* validate line */
1409 1.75.8.2 christos if (_nis_parse(data, &_nis_passwd,
1410 1.75.8.2 christos _nis_passwdbuf, sizeof(_nis_passwdbuf), &_nis_state))
1411 1.75.8.2 christos rv = NS_SUCCESS;
1412 1.75.8.2 christos else { /* dodgy entry, try again */
1413 1.75.8.2 christos free(data);
1414 1.75.8.2 christos goto next_nis_entry;
1415 1.75.8.2 christos }
1416 1.75.8.2 christos
1417 1.75.8.2 christos nisent_out:
1418 1.75.8.2 christos if (key)
1419 1.75.8.2 christos free(key);
1420 1.75.8.2 christos if (data)
1421 1.75.8.2 christos free(data);
1422 1.75.8.2 christos if (rv == NS_SUCCESS)
1423 1.75.8.2 christos *retval = &_nis_passwd;
1424 1.75.8.2 christos return rv;
1425 1.75.8.2 christos }
1426 1.75.8.2 christos
1427 1.75.8.2 christos /*ARGSUSED*/
1428 1.75.8.2 christos static int
1429 1.75.8.2 christos _nis_getpwent_r(void *nsrv, void *nscb, va_list ap)
1430 1.75.8.2 christos {
1431 1.75.8.2 christos int *retval = va_arg(ap, int *);
1432 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
1433 1.75.8.2 christos char *buffer = va_arg(ap, char *);
1434 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
1435 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
1436 1.75.8.2 christos
1437 1.75.8.2 christos char *key, *data;
1438 1.75.8.2 christos int keylen, datalen, rv, nisr;
1439 1.75.8.2 christos
1440 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1441 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1442 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
1443 1.75.8.2 christos _DIAGASSERT(result != NULL);
1444 1.75.8.2 christos
1445 1.75.8.2 christos *retval = 0;
1446 1.75.8.2 christos
1447 1.75.8.2 christos if (_nis_state.done) /* exhausted search */
1448 1.75.8.2 christos return NS_NOTFOUND;
1449 1.75.8.2 christos if (_nis_state.domain == NULL) {
1450 1.75.8.2 christos /* only start if NIS not setup */
1451 1.75.8.2 christos rv = _nis_start(&_nis_state);
1452 1.75.8.2 christos if (rv != NS_SUCCESS)
1453 1.75.8.2 christos return rv;
1454 1.75.8.2 christos }
1455 1.75.8.2 christos
1456 1.75.8.2 christos next_nis_entry:
1457 1.75.8.2 christos key = NULL;
1458 1.75.8.2 christos data = NULL;
1459 1.75.8.2 christos rv = NS_NOTFOUND;
1460 1.75.8.2 christos
1461 1.75.8.2 christos if (_nis_state.current) { /* already searching */
1462 1.75.8.2 christos nisr = yp_next(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
1463 1.75.8.2 christos _nis_state.current, _nis_state.currentlen,
1464 1.75.8.2 christos &key, &keylen, &data, &datalen);
1465 1.75.8.2 christos free(_nis_state.current);
1466 1.75.8.2 christos _nis_state.current = NULL;
1467 1.75.8.2 christos switch (nisr) {
1468 1.75.8.2 christos case 0:
1469 1.75.8.2 christos _nis_state.current = key;
1470 1.75.8.2 christos _nis_state.currentlen = keylen;
1471 1.75.8.2 christos key = NULL;
1472 1.75.8.2 christos break;
1473 1.75.8.2 christos case YPERR_NOMORE:
1474 1.75.8.2 christos _nis_state.done = 1;
1475 1.75.8.2 christos goto nisent_out;
1476 1.75.8.2 christos default:
1477 1.75.8.2 christos rv = NS_UNAVAIL;
1478 1.75.8.2 christos goto nisent_out;
1479 1.75.8.2 christos }
1480 1.75.8.2 christos } else { /* new search */
1481 1.75.8.2 christos if (yp_first(_nis_state.domain, PASSWD_BYNAME(&_nis_state),
1482 1.75.8.2 christos &_nis_state.current, &_nis_state.currentlen,
1483 1.75.8.2 christos &data, &datalen)) {
1484 1.75.8.2 christos rv = NS_UNAVAIL;
1485 1.75.8.2 christos goto nisent_out;
1486 1.75.8.2 christos }
1487 1.75.8.2 christos }
1488 1.75.8.2 christos
1489 1.75.8.2 christos data[datalen] = '\0'; /* clear trailing \n */
1490 1.75.8.2 christos /* validate line */
1491 1.75.8.2 christos if (_nis_parse(data, pw, buffer, buflen, &_nis_state))
1492 1.75.8.2 christos rv = NS_SUCCESS;
1493 1.75.8.2 christos else { /* dodgy entry, try again */
1494 1.75.8.2 christos if (key)
1495 1.75.8.2 christos free(key);
1496 1.75.8.2 christos free(data);
1497 1.75.8.2 christos goto next_nis_entry;
1498 1.75.8.2 christos }
1499 1.75.8.2 christos
1500 1.75.8.2 christos nisent_out:
1501 1.75.8.2 christos if (key)
1502 1.75.8.2 christos free(key);
1503 1.75.8.2 christos if (data)
1504 1.75.8.2 christos free(data);
1505 1.75.8.2 christos if (rv == NS_SUCCESS)
1506 1.75.8.2 christos *result = pw;
1507 1.75.8.2 christos else
1508 1.75.8.2 christos *result = NULL;
1509 1.75.8.2 christos return rv;
1510 1.75.8.2 christos }
1511 1.75.8.2 christos
1512 1.75.8.2 christos /*ARGSUSED*/
1513 1.75.8.2 christos static int
1514 1.75.8.2 christos _nis_getpwuid(void *nsrv, void *nscb, va_list ap)
1515 1.75.8.2 christos {
1516 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
1517 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
1518 1.75.8.2 christos
1519 1.75.8.2 christos int rv, rerror;
1520 1.75.8.2 christos
1521 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1522 1.75.8.2 christos
1523 1.75.8.2 christos *retval = NULL;
1524 1.75.8.2 christos rv = _nis_start(&_nis_state);
1525 1.75.8.2 christos if (rv != NS_SUCCESS)
1526 1.75.8.2 christos return rv;
1527 1.75.8.2 christos snprintf(_nis_passwdbuf, sizeof(_nis_passwdbuf), "%u", (unsigned int)uid);
1528 1.75.8.2 christos rv = _nis_pwscan(&rerror, &_nis_passwd,
1529 1.75.8.2 christos _nis_passwdbuf, sizeof(_nis_passwdbuf),
1530 1.75.8.2 christos &_nis_state, PASSWD_BYUID(&_nis_state));
1531 1.75.8.2 christos if (!_nis_state.stayopen)
1532 1.75.8.2 christos _nis_end(&_nis_state);
1533 1.75.8.2 christos if (rv == NS_SUCCESS && uid == _nis_passwd.pw_uid)
1534 1.75.8.2 christos *retval = &_nis_passwd;
1535 1.75.8.2 christos return rv;
1536 1.75.8.2 christos }
1537 1.75.8.2 christos
1538 1.75.8.2 christos /*ARGSUSED*/
1539 1.75.8.2 christos static int
1540 1.75.8.2 christos _nis_getpwuid_r(void *nsrv, void *nscb, va_list ap)
1541 1.75.8.2 christos {
1542 1.75.8.2 christos int *retval = va_arg(ap, int *);
1543 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
1544 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
1545 1.75.8.2 christos char *buffer = va_arg(ap, char *);
1546 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
1547 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
1548 1.75.8.2 christos
1549 1.75.8.2 christos struct nis_state state;
1550 1.75.8.2 christos int rv;
1551 1.75.8.2 christos
1552 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1553 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1554 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
1555 1.75.8.2 christos _DIAGASSERT(result != NULL);
1556 1.75.8.2 christos
1557 1.75.8.2 christos *result = NULL;
1558 1.75.8.2 christos memset(&state, 0, sizeof(state));
1559 1.75.8.2 christos rv = _nis_start(&state);
1560 1.75.8.2 christos if (rv != NS_SUCCESS)
1561 1.75.8.2 christos return rv;
1562 1.75.8.2 christos snprintf(buffer, buflen, "%u", (unsigned int)uid);
1563 1.75.8.2 christos rv = _nis_pwscan(retval, pw, buffer, buflen,
1564 1.75.8.2 christos &state, PASSWD_BYUID(&state));
1565 1.75.8.2 christos _nis_end(&state);
1566 1.75.8.2 christos if (rv != NS_SUCCESS)
1567 1.75.8.2 christos return rv;
1568 1.75.8.2 christos if (uid == pw->pw_uid) {
1569 1.75.8.2 christos *result = pw;
1570 1.75.8.2 christos return NS_SUCCESS;
1571 1.75.8.2 christos } else
1572 1.75.8.2 christos return NS_NOTFOUND;
1573 1.75.8.2 christos }
1574 1.75.8.2 christos
1575 1.75.8.2 christos /*ARGSUSED*/
1576 1.75.8.2 christos static int
1577 1.75.8.2 christos _nis_getpwnam(void *nsrv, void *nscb, va_list ap)
1578 1.75.8.2 christos {
1579 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
1580 1.75.8.2 christos const char *name = va_arg(ap, const char *);
1581 1.75.8.2 christos
1582 1.75.8.2 christos int rv, rerror;
1583 1.75.8.2 christos
1584 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1585 1.75.8.2 christos
1586 1.75.8.2 christos *retval = NULL;
1587 1.75.8.2 christos rv = _nis_start(&_nis_state);
1588 1.75.8.2 christos if (rv != NS_SUCCESS)
1589 1.75.8.2 christos return rv;
1590 1.75.8.2 christos snprintf(_nis_passwdbuf, sizeof(_nis_passwdbuf), "%s", name);
1591 1.75.8.2 christos rv = _nis_pwscan(&rerror, &_nis_passwd,
1592 1.75.8.2 christos _nis_passwdbuf, sizeof(_nis_passwdbuf),
1593 1.75.8.2 christos &_nis_state, PASSWD_BYNAME(&_nis_state));
1594 1.75.8.2 christos if (!_nis_state.stayopen)
1595 1.75.8.2 christos _nis_end(&_nis_state);
1596 1.75.8.2 christos if (rv == NS_SUCCESS && strcmp(name, _nis_passwd.pw_name) == 0)
1597 1.75.8.2 christos *retval = &_nis_passwd;
1598 1.75.8.2 christos return rv;
1599 1.75.8.2 christos }
1600 1.75.8.2 christos
1601 1.75.8.2 christos /*ARGSUSED*/
1602 1.75.8.2 christos static int
1603 1.75.8.2 christos _nis_getpwnam_r(void *nsrv, void *nscb, va_list ap)
1604 1.75.8.2 christos {
1605 1.75.8.2 christos int *retval = va_arg(ap, int *);
1606 1.75.8.2 christos const char *name = va_arg(ap, const char *);
1607 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
1608 1.75.8.2 christos char *buffer = va_arg(ap, char *);
1609 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
1610 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
1611 1.75.8.2 christos
1612 1.75.8.2 christos struct nis_state state;
1613 1.75.8.2 christos int rv;
1614 1.75.8.2 christos
1615 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1616 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1617 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
1618 1.75.8.2 christos _DIAGASSERT(result != NULL);
1619 1.75.8.2 christos
1620 1.75.8.2 christos *result = NULL;
1621 1.75.8.2 christos snprintf(buffer, buflen, "%s", name);
1622 1.75.8.2 christos memset(&state, 0, sizeof(state));
1623 1.75.8.2 christos rv = _nis_start(&state);
1624 1.75.8.2 christos if (rv != NS_SUCCESS)
1625 1.75.8.2 christos return rv;
1626 1.75.8.2 christos rv = _nis_pwscan(retval, pw, buffer, buflen,
1627 1.75.8.2 christos &state, PASSWD_BYNAME(&state));
1628 1.75.8.2 christos _nis_end(&state);
1629 1.75.8.2 christos if (rv != NS_SUCCESS)
1630 1.75.8.2 christos return rv;
1631 1.75.8.2 christos if (strcmp(name, pw->pw_name) == 0) {
1632 1.75.8.2 christos *result = pw;
1633 1.75.8.2 christos return NS_SUCCESS;
1634 1.75.8.2 christos } else
1635 1.75.8.2 christos return NS_NOTFOUND;
1636 1.75.8.2 christos }
1637 1.75.8.2 christos
1638 1.75.8.2 christos #endif /* YP */
1639 1.75.8.2 christos
1640 1.75.8.2 christos
1641 1.75.8.2 christos #ifdef _PASSWD_COMPAT
1642 1.75.8.2 christos /*
1643 1.75.8.2 christos * compat methods
1644 1.75.8.2 christos */
1645 1.75.8.2 christos
1646 1.75.8.2 christos /* state shared between compat methods */
1647 1.75.8.2 christos
1648 1.75.8.2 christos struct compat_state {
1649 1.75.8.2 christos int stayopen; /* see getpassent(3) */
1650 1.75.8.2 christos DB *db; /* passwd DB */
1651 1.75.8.2 christos int keynum; /* key counter, -1 if no more */
1652 1.75.8.2 christos enum { /* current compat mode */
1653 1.75.8.2 christos COMPAT_NOTOKEN = 0, /* no compat token present */
1654 1.75.8.2 christos COMPAT_NONE, /* parsing normal pwd.db line */
1655 1.75.8.2 christos COMPAT_FULL, /* parsing `+' entries */
1656 1.75.8.2 christos COMPAT_USER, /* parsing `+name' entries */
1657 1.75.8.2 christos COMPAT_NETGROUP /* parsing `+@netgroup' entries */
1658 1.75.8.2 christos } mode;
1659 1.75.8.2 christos char *user; /* COMPAT_USER "+name" */
1660 1.75.8.2 christos DB *exclude; /* compat exclude DB */
1661 1.75.8.2 christos struct passwd proto; /* proto passwd entry */
1662 1.75.8.2 christos char protobuf[_GETPW_R_SIZE_MAX];
1663 1.75.8.2 christos /* buffer for proto ptrs */
1664 1.75.8.2 christos int protoflags; /* proto passwd flags */
1665 1.75.8.2 christos int version;
1666 1.75.8.2 christos };
1667 1.75.8.2 christos
1668 1.75.8.2 christos static struct compat_state _compat_state;
1669 1.75.8.2 christos /* storage for non _r functions */
1670 1.75.8.2 christos static struct passwd _compat_passwd;
1671 1.75.8.2 christos static char _compat_passwdbuf[_GETPW_R_SIZE_MAX];
1672 1.75.8.2 christos
1673 1.75.8.2 christos static int
1674 1.75.8.2 christos _compat_start(struct compat_state *state)
1675 1.75.8.2 christos {
1676 1.75.8.2 christos int rv;
1677 1.75.8.2 christos
1678 1.75.8.2 christos _DIAGASSERT(state != NULL);
1679 1.75.8.2 christos
1680 1.75.8.2 christos state->keynum = 0;
1681 1.75.8.2 christos if (state->db == NULL) { /* not open yet */
1682 1.75.8.2 christos DBT key, data;
1683 1.75.8.2 christos DBT pkey, pdata;
1684 1.75.8.2 christos char bf[MAXLOGNAME];
1685 1.75.8.2 christos
1686 1.75.8.2 christos rv = _pw_opendb(&state->db, &state->version);
1687 1.75.8.2 christos if (rv != NS_SUCCESS)
1688 1.75.8.2 christos return rv;
1689 1.75.8.2 christos
1690 1.75.8.2 christos state->mode = COMPAT_NOTOKEN;
1691 1.75.8.2 christos
1692 1.75.8.2 christos /*
1693 1.75.8.2 christos * Determine if the "compat" token is present in pwd.db;
1694 1.75.8.2 christos * either "__YP!" or PW_KEYBYNAME+"+".
1695 1.75.8.2 christos * Only works if pwd_mkdb installs the token.
1696 1.75.8.2 christos */
1697 1.75.8.2 christos key.data = (u_char *)__UNCONST(__yp_token);
1698 1.75.8.2 christos key.size = strlen(__yp_token);
1699 1.75.8.2 christos
1700 1.75.8.2 christos bf[0] = _PW_KEYBYNAME; /* Pre-token database support. */
1701 1.75.8.2 christos bf[1] = '+';
1702 1.75.8.2 christos pkey.data = (u_char *)bf;
1703 1.75.8.2 christos pkey.size = 2;
1704 1.75.8.2 christos
1705 1.75.8.2 christos if ((state->db->get)(state->db, &key, &data, 0) == 0
1706 1.75.8.2 christos || (state->db->get)(state->db, &pkey, &pdata, 0) == 0)
1707 1.75.8.2 christos state->mode = COMPAT_NONE;
1708 1.75.8.2 christos }
1709 1.75.8.2 christos return NS_SUCCESS;
1710 1.75.8.2 christos }
1711 1.75.8.2 christos
1712 1.75.8.2 christos static int
1713 1.75.8.2 christos _compat_end(struct compat_state *state)
1714 1.75.8.2 christos {
1715 1.75.8.2 christos
1716 1.75.8.2 christos _DIAGASSERT(state != NULL);
1717 1.75.8.2 christos
1718 1.75.8.2 christos state->keynum = 0;
1719 1.75.8.2 christos if (state->db) {
1720 1.75.8.2 christos (void)(state->db->close)(state->db);
1721 1.75.8.2 christos state->db = NULL;
1722 1.75.8.2 christos }
1723 1.75.8.2 christos state->mode = COMPAT_NOTOKEN;
1724 1.75.8.2 christos if (state->user)
1725 1.75.8.2 christos free(state->user);
1726 1.75.8.2 christos state->user = NULL;
1727 1.75.8.2 christos if (state->exclude != NULL)
1728 1.75.8.2 christos (void)(state->exclude->close)(state->exclude);
1729 1.75.8.2 christos state->exclude = NULL;
1730 1.75.8.2 christos state->proto.pw_name = NULL;
1731 1.75.8.2 christos state->protoflags = 0;
1732 1.75.8.2 christos return NS_SUCCESS;
1733 1.75.8.2 christos }
1734 1.75.8.2 christos
1735 1.75.8.2 christos /*
1736 1.75.8.2 christos * _compat_add_exclude
1737 1.75.8.2 christos * add the name to the exclude list in state->exclude.
1738 1.75.8.2 christos */
1739 1.75.8.2 christos static int
1740 1.75.8.2 christos _compat_add_exclude(struct compat_state *state, const char *name)
1741 1.75.8.2 christos {
1742 1.75.8.2 christos DBT key, data;
1743 1.75.8.2 christos
1744 1.75.8.2 christos _DIAGASSERT(state != NULL);
1745 1.75.8.2 christos _DIAGASSERT(name != NULL);
1746 1.75.8.2 christos
1747 1.75.8.2 christos /* initialize the exclusion table if needed */
1748 1.75.8.2 christos if (state->exclude == NULL) {
1749 1.75.8.2 christos state->exclude = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
1750 1.75.8.2 christos if (state->exclude == NULL)
1751 1.75.8.2 christos return 0;
1752 1.75.8.2 christos }
1753 1.75.8.2 christos
1754 1.75.8.2 christos key.size = strlen(name); /* set up the key */
1755 1.75.8.2 christos key.data = (u_char *)__UNCONST(name);
1756 1.75.8.2 christos
1757 1.75.8.2 christos data.data = NULL; /* data is nothing */
1758 1.75.8.2 christos data.size = 0;
1759 1.75.8.2 christos
1760 1.75.8.2 christos /* store it */
1761 1.75.8.2 christos if ((state->exclude->put)(state->exclude, &key, &data, 0) == -1)
1762 1.75.8.2 christos return 0;
1763 1.75.8.2 christos
1764 1.75.8.2 christos return 1;
1765 1.75.8.2 christos }
1766 1.75.8.2 christos
1767 1.75.8.2 christos /*
1768 1.75.8.2 christos * _compat_is_excluded
1769 1.75.8.2 christos * test if a name is on the compat mode exclude list
1770 1.75.8.2 christos */
1771 1.75.8.2 christos static int
1772 1.75.8.2 christos _compat_is_excluded(struct compat_state *state, const char *name)
1773 1.75.8.2 christos {
1774 1.75.8.2 christos DBT key, data;
1775 1.75.8.2 christos
1776 1.75.8.2 christos _DIAGASSERT(state != NULL);
1777 1.75.8.2 christos _DIAGASSERT(name != NULL);
1778 1.75.8.2 christos
1779 1.75.8.2 christos if (state->exclude == NULL)
1780 1.75.8.2 christos return 0; /* nothing excluded */
1781 1.75.8.2 christos
1782 1.75.8.2 christos key.size = strlen(name); /* set up the key */
1783 1.75.8.2 christos key.data = (u_char *)__UNCONST(name);
1784 1.75.8.2 christos
1785 1.75.8.2 christos if ((state->exclude->get)(state->exclude, &key, &data, 0) == 0)
1786 1.75.8.2 christos return 1; /* is excluded */
1787 1.75.8.2 christos
1788 1.75.8.2 christos return 0;
1789 1.75.8.2 christos }
1790 1.75.8.2 christos
1791 1.75.8.2 christos
1792 1.75.8.2 christos /*
1793 1.75.8.2 christos * _passwdcompat_bad
1794 1.75.8.2 christos * log an error if "files" or "compat" is specified in
1795 1.75.8.2 christos * passwd_compat database
1796 1.75.8.2 christos */
1797 1.75.8.2 christos /*ARGSUSED*/
1798 1.75.8.2 christos static int
1799 1.75.8.2 christos _passwdcompat_bad(void *nsrv, void *nscb, va_list ap)
1800 1.75.8.2 christos {
1801 1.75.8.2 christos static int warned;
1802 1.75.8.2 christos
1803 1.75.8.2 christos _DIAGASSERT(nsrv != NULL);
1804 1.75.8.2 christos _DIAGASSERT(nscb != NULL);
1805 1.75.8.2 christos
1806 1.75.8.2 christos if (!warned) {
1807 1.75.8.2 christos syslog(LOG_ERR,
1808 1.75.8.2 christos "nsswitch.conf passwd_compat database can't use '%s'",
1809 1.75.8.2 christos (char *)nscb);
1810 1.75.8.2 christos }
1811 1.75.8.2 christos warned = 1;
1812 1.75.8.2 christos return NS_UNAVAIL;
1813 1.75.8.2 christos }
1814 1.75.8.2 christos
1815 1.75.8.2 christos /*
1816 1.75.8.2 christos * _passwdcompat_setpassent
1817 1.75.8.2 christos * Call setpassent for all passwd_compat sources.
1818 1.75.8.2 christos */
1819 1.75.8.2 christos static int
1820 1.75.8.2 christos _passwdcompat_setpassent(int stayopen)
1821 1.75.8.2 christos {
1822 1.75.8.2 christos static const ns_dtab dtab[] = {
1823 1.75.8.2 christos NS_FILES_CB(_passwdcompat_bad, "files")
1824 1.75.8.2 christos NS_DNS_CB(_dns_setpassent, NULL)
1825 1.75.8.2 christos NS_NIS_CB(_nis_setpassent, NULL)
1826 1.75.8.2 christos NS_COMPAT_CB(_passwdcompat_bad, "compat")
1827 1.75.8.2 christos NS_NULL_CB
1828 1.75.8.2 christos };
1829 1.75.8.2 christos
1830 1.75.8.2 christos int rv, result;
1831 1.75.8.2 christos
1832 1.75.8.2 christos rv = nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "setpassent",
1833 1.75.8.2 christos __nsdefaultnis_forceall, &result, stayopen);
1834 1.75.8.2 christos return rv;
1835 1.75.8.2 christos }
1836 1.75.8.2 christos
1837 1.75.8.2 christos /*
1838 1.75.8.2 christos * _passwdcompat_endpwent
1839 1.75.8.2 christos * Call endpwent for all passwd_compat sources.
1840 1.75.8.2 christos */
1841 1.75.8.2 christos static int
1842 1.75.8.2 christos _passwdcompat_endpwent(void)
1843 1.75.8.2 christos {
1844 1.75.8.2 christos static const ns_dtab dtab[] = {
1845 1.75.8.2 christos NS_FILES_CB(_passwdcompat_bad, "files")
1846 1.75.8.2 christos NS_DNS_CB(_dns_endpwent, NULL)
1847 1.75.8.2 christos NS_NIS_CB(_nis_endpwent, NULL)
1848 1.75.8.2 christos NS_COMPAT_CB(_passwdcompat_bad, "compat")
1849 1.75.8.2 christos NS_NULL_CB
1850 1.75.8.2 christos };
1851 1.75.8.2 christos
1852 1.75.8.2 christos return nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "endpwent",
1853 1.75.8.2 christos __nsdefaultnis_forceall);
1854 1.75.8.2 christos }
1855 1.75.8.2 christos
1856 1.75.8.2 christos /*
1857 1.75.8.2 christos * _passwdcompat_pwscan
1858 1.75.8.2 christos * When a name lookup in compat mode is required (e.g., `+name', or a
1859 1.75.8.2 christos * name in `+@netgroup'), look it up in the 'passwd_compat' nsswitch
1860 1.75.8.2 christos * database.
1861 1.75.8.2 christos * Fail if passwd_compat contains files or compat.
1862 1.75.8.2 christos */
1863 1.75.8.2 christos static int
1864 1.75.8.2 christos _passwdcompat_pwscan(struct passwd *pw, char *buffer, size_t buflen,
1865 1.75.8.2 christos int search, const char *name, uid_t uid)
1866 1.75.8.2 christos {
1867 1.75.8.2 christos static const ns_dtab compatentdtab[] = {
1868 1.75.8.2 christos NS_FILES_CB(_passwdcompat_bad, "files")
1869 1.75.8.2 christos NS_DNS_CB(_dns_getpwent_r, NULL)
1870 1.75.8.2 christos NS_NIS_CB(_nis_getpwent_r, NULL)
1871 1.75.8.2 christos NS_COMPAT_CB(_passwdcompat_bad, "compat")
1872 1.75.8.2 christos NS_NULL_CB
1873 1.75.8.2 christos };
1874 1.75.8.2 christos static const ns_dtab compatuiddtab[] = {
1875 1.75.8.2 christos NS_FILES_CB(_passwdcompat_bad, "files")
1876 1.75.8.2 christos NS_DNS_CB(_dns_getpwuid_r, NULL)
1877 1.75.8.2 christos NS_NIS_CB(_nis_getpwuid_r, NULL)
1878 1.75.8.2 christos NS_COMPAT_CB(_passwdcompat_bad, "compat")
1879 1.75.8.2 christos NS_NULL_CB
1880 1.75.8.2 christos };
1881 1.75.8.2 christos static const ns_dtab compatnamdtab[] = {
1882 1.75.8.2 christos NS_FILES_CB(_passwdcompat_bad, "files")
1883 1.75.8.2 christos NS_DNS_CB(_dns_getpwnam_r, NULL)
1884 1.75.8.2 christos NS_NIS_CB(_nis_getpwnam_r, NULL)
1885 1.75.8.2 christos NS_COMPAT_CB(_passwdcompat_bad, "compat")
1886 1.75.8.2 christos NS_NULL_CB
1887 1.75.8.2 christos };
1888 1.75.8.2 christos
1889 1.75.8.2 christos int rv, crv;
1890 1.75.8.2 christos struct passwd *cpw;
1891 1.75.8.2 christos
1892 1.75.8.2 christos switch (search) {
1893 1.75.8.2 christos case _PW_KEYBYNUM:
1894 1.75.8.2 christos rv = nsdispatch(NULL, compatentdtab,
1895 1.75.8.2 christos NSDB_PASSWD_COMPAT, "getpwent_r", __nsdefaultnis,
1896 1.75.8.2 christos &crv, pw, buffer, buflen, &cpw);
1897 1.75.8.2 christos break;
1898 1.75.8.2 christos case _PW_KEYBYNAME:
1899 1.75.8.2 christos _DIAGASSERT(name != NULL);
1900 1.75.8.2 christos rv = nsdispatch(NULL, compatnamdtab,
1901 1.75.8.2 christos NSDB_PASSWD_COMPAT, "getpwnam_r", __nsdefaultnis,
1902 1.75.8.2 christos &crv, name, pw, buffer, buflen, &cpw);
1903 1.75.8.2 christos break;
1904 1.75.8.2 christos case _PW_KEYBYUID:
1905 1.75.8.2 christos rv = nsdispatch(NULL, compatuiddtab,
1906 1.75.8.2 christos NSDB_PASSWD_COMPAT, "getpwuid_r", __nsdefaultnis,
1907 1.75.8.2 christos &crv, uid, pw, buffer, buflen, &cpw);
1908 1.75.8.2 christos break;
1909 1.75.8.2 christos default:
1910 1.75.8.2 christos abort();
1911 1.75.8.2 christos /*NOTREACHED*/
1912 1.75.8.2 christos }
1913 1.75.8.2 christos return rv;
1914 1.75.8.2 christos }
1915 1.75.8.2 christos
1916 1.75.8.2 christos /*
1917 1.75.8.2 christos * _compat_pwscan
1918 1.75.8.2 christos * Search state->db for the next desired entry.
1919 1.75.8.2 christos * If search is _PW_KEYBYNUM, look for state->keynum.
1920 1.75.8.2 christos * If search is _PW_KEYBYNAME, look for name.
1921 1.75.8.2 christos * If search is _PW_KEYBYUID, look for uid.
1922 1.75.8.2 christos * Sets *retval to the errno if the result is not NS_SUCCESS
1923 1.75.8.2 christos * or NS_NOTFOUND.
1924 1.75.8.2 christos */
1925 1.75.8.2 christos static int
1926 1.75.8.2 christos _compat_pwscan(int *retval, struct passwd *pw, char *buffer, size_t buflen,
1927 1.75.8.2 christos struct compat_state *state, int search, const char *name, uid_t uid)
1928 1.75.8.2 christos {
1929 1.75.8.2 christos DBT key;
1930 1.75.8.2 christos int rv, r, pwflags;
1931 1.75.8.2 christos const char *user, *host, *dom;
1932 1.75.8.2 christos const void *from;
1933 1.75.8.2 christos size_t fromlen;
1934 1.75.8.2 christos
1935 1.75.8.2 christos _DIAGASSERT(retval != NULL);
1936 1.75.8.2 christos _DIAGASSERT(pw != NULL);
1937 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
1938 1.75.8.2 christos _DIAGASSERT(state != NULL);
1939 1.75.8.2 christos /* name may be NULL */
1940 1.75.8.2 christos
1941 1.75.8.2 christos *retval = 0;
1942 1.75.8.2 christos
1943 1.75.8.2 christos if (state->db == NULL) {
1944 1.75.8.2 christos rv = _compat_start(state);
1945 1.75.8.2 christos if (rv != NS_SUCCESS)
1946 1.75.8.2 christos return rv;
1947 1.75.8.2 christos }
1948 1.75.8.2 christos if (buflen <= 1) { /* buffer too small */
1949 1.75.8.2 christos *retval = ERANGE;
1950 1.75.8.2 christos return NS_UNAVAIL;
1951 1.75.8.2 christos }
1952 1.75.8.2 christos
1953 1.75.8.2 christos for (;;) { /* loop over pwd.db */
1954 1.75.8.2 christos rv = NS_NOTFOUND;
1955 1.75.8.2 christos if (state->mode != COMPAT_NOTOKEN &&
1956 1.75.8.2 christos state->mode != COMPAT_NONE) {
1957 1.75.8.2 christos /* doing a compat lookup */
1958 1.75.8.2 christos struct passwd cpw;
1959 1.75.8.2 christos char cbuf[_GETPW_R_SIZE_MAX];
1960 1.75.8.2 christos
1961 1.75.8.2 christos switch (state->mode) {
1962 1.75.8.2 christos
1963 1.75.8.2 christos case COMPAT_FULL:
1964 1.75.8.2 christos /* get next user or lookup by key */
1965 1.75.8.2 christos rv = _passwdcompat_pwscan(&cpw,
1966 1.75.8.2 christos cbuf, sizeof(cbuf), search, name, uid);
1967 1.75.8.2 christos if (rv != NS_SUCCESS)
1968 1.75.8.2 christos state->mode = COMPAT_NONE;
1969 1.75.8.2 christos break;
1970 1.75.8.2 christos
1971 1.75.8.2 christos case COMPAT_NETGROUP:
1972 1.75.8.2 christos /* XXXREENTRANT: getnetgrent is not thread safe */
1973 1.75.8.2 christos /* get next user from netgroup */
1974 1.75.8.2 christos r = getnetgrent(&host, &user, &dom);
1975 1.75.8.2 christos if (r == 0) { /* end of group */
1976 1.75.8.2 christos endnetgrent();
1977 1.75.8.2 christos state->mode = COMPAT_NONE;
1978 1.75.8.2 christos break;
1979 1.75.8.2 christos }
1980 1.75.8.2 christos if (!user || !*user)
1981 1.75.8.2 christos break;
1982 1.75.8.2 christos rv = _passwdcompat_pwscan(&cpw,
1983 1.75.8.2 christos cbuf, sizeof(cbuf),
1984 1.75.8.2 christos _PW_KEYBYNAME, user, 0);
1985 1.75.8.2 christos break;
1986 1.75.8.2 christos
1987 1.75.8.2 christos case COMPAT_USER:
1988 1.75.8.2 christos /* get specific user */
1989 1.75.8.2 christos if (state->user == NULL) {
1990 1.75.8.2 christos state->mode = COMPAT_NONE;
1991 1.75.8.2 christos break;
1992 1.75.8.2 christos }
1993 1.75.8.2 christos rv = _passwdcompat_pwscan(&cpw,
1994 1.75.8.2 christos cbuf, sizeof(cbuf),
1995 1.75.8.2 christos _PW_KEYBYNAME, state->user, 0);
1996 1.75.8.2 christos free(state->user);
1997 1.75.8.2 christos state->user = NULL;
1998 1.75.8.2 christos state->mode = COMPAT_NONE;
1999 1.75.8.2 christos break;
2000 1.75.8.2 christos
2001 1.75.8.2 christos case COMPAT_NOTOKEN:
2002 1.75.8.2 christos case COMPAT_NONE:
2003 1.75.8.2 christos abort();
2004 1.75.8.2 christos
2005 1.75.8.2 christos }
2006 1.75.8.2 christos if (rv != NS_SUCCESS) /* if not matched, next loop */
2007 1.75.8.2 christos continue;
2008 1.75.8.2 christos
2009 1.75.8.2 christos /* copy cpw to pw, applying prototype */
2010 1.75.8.2 christos if (! _pw_copy(&cpw, pw, buffer, buflen,
2011 1.75.8.2 christos &state->proto, state->protoflags)) {
2012 1.75.8.2 christos rv = NS_UNAVAIL;
2013 1.75.8.2 christos break;
2014 1.75.8.2 christos }
2015 1.75.8.2 christos
2016 1.75.8.2 christos if (_compat_is_excluded(state, pw->pw_name))
2017 1.75.8.2 christos continue; /* excluded; next loop */
2018 1.75.8.2 christos
2019 1.75.8.2 christos if ((search == _PW_KEYBYNAME
2020 1.75.8.2 christos && strcmp(pw->pw_name, name) != 0)
2021 1.75.8.2 christos || (search == _PW_KEYBYUID && pw->pw_uid != uid)) {
2022 1.75.8.2 christos continue; /* not specific; next loop */
2023 1.75.8.2 christos }
2024 1.75.8.2 christos
2025 1.75.8.2 christos break; /* exit loop if found */
2026 1.75.8.2 christos } else { /* not a compat line */
2027 1.75.8.2 christos state->proto.pw_name = NULL;
2028 1.75.8.2 christos /* clear prototype */
2029 1.75.8.2 christos }
2030 1.75.8.2 christos
2031 1.75.8.2 christos if (state->mode == COMPAT_NOTOKEN) {
2032 1.75.8.2 christos /* no compat token; do direct lookup */
2033 1.75.8.2 christos switch (search) {
2034 1.75.8.2 christos case _PW_KEYBYNUM:
2035 1.75.8.2 christos if (state->keynum == -1) /* no more records */
2036 1.75.8.2 christos return NS_NOTFOUND;
2037 1.75.8.2 christos state->keynum++;
2038 1.75.8.2 christos from = &state->keynum;
2039 1.75.8.2 christos fromlen = sizeof(state->keynum);
2040 1.75.8.2 christos break;
2041 1.75.8.2 christos case _PW_KEYBYNAME:
2042 1.75.8.2 christos from = name;
2043 1.75.8.2 christos fromlen = strlen(name);
2044 1.75.8.2 christos break;
2045 1.75.8.2 christos case _PW_KEYBYUID:
2046 1.75.8.2 christos from = &uid;
2047 1.75.8.2 christos fromlen = sizeof(uid);
2048 1.75.8.2 christos break;
2049 1.75.8.2 christos default:
2050 1.75.8.2 christos abort();
2051 1.75.8.2 christos }
2052 1.75.8.2 christos buffer[0] = search;
2053 1.75.8.2 christos } else {
2054 1.75.8.2 christos /* compat token; do line by line */
2055 1.75.8.2 christos if (state->keynum == -1) /* no more records */
2056 1.75.8.2 christos return NS_NOTFOUND;
2057 1.75.8.2 christos state->keynum++;
2058 1.75.8.2 christos from = &state->keynum;
2059 1.75.8.2 christos fromlen = sizeof(state->keynum);
2060 1.75.8.2 christos buffer[0] = _PW_KEYBYNUM;
2061 1.75.8.2 christos }
2062 1.75.8.2 christos
2063 1.75.8.2 christos if (buflen <= fromlen) { /* buffer too small */
2064 1.75.8.2 christos *retval = ERANGE;
2065 1.75.8.2 christos return NS_UNAVAIL;
2066 1.75.8.2 christos }
2067 1.75.8.2 christos memmove(buffer + 1, from, fromlen); /* setup key */
2068 1.75.8.2 christos key.size = fromlen + 1;
2069 1.75.8.2 christos key.data = (u_char *)buffer;
2070 1.75.8.2 christos
2071 1.75.8.2 christos rv = _pw_getkey(state->db, &key, pw, buffer, buflen, &pwflags,
2072 1.75.8.2 christos state->version);
2073 1.75.8.2 christos if (rv != NS_SUCCESS) /* stop on error */
2074 1.75.8.2 christos break;
2075 1.75.8.2 christos
2076 1.75.8.2 christos if (state->mode == COMPAT_NOTOKEN)
2077 1.75.8.2 christos break; /* stop if no compat token */
2078 1.75.8.2 christos
2079 1.75.8.2 christos if (pw->pw_name[0] == '+') {
2080 1.75.8.2 christos /* compat inclusion */
2081 1.75.8.2 christos switch(pw->pw_name[1]) {
2082 1.75.8.2 christos case '\0': /* `+' */
2083 1.75.8.2 christos state->mode = COMPAT_FULL;
2084 1.75.8.2 christos /* reset passwd_compat search */
2085 1.75.8.2 christos /* XXXREENTRANT: setpassent is not thread safe ? */
2086 1.75.8.2 christos (void) _passwdcompat_setpassent(0);
2087 1.75.8.2 christos break;
2088 1.75.8.2 christos case '@': /* `+@netgroup' */
2089 1.75.8.2 christos state->mode = COMPAT_NETGROUP;
2090 1.75.8.2 christos /* reset netgroup search */
2091 1.75.8.2 christos /* XXXREENTRANT: setnetgrent is not thread safe */
2092 1.75.8.2 christos setnetgrent(pw->pw_name + 2);
2093 1.75.8.2 christos break;
2094 1.75.8.2 christos default: /* `+name' */
2095 1.75.8.2 christos state->mode = COMPAT_USER;
2096 1.75.8.2 christos if (state->user)
2097 1.75.8.2 christos free(state->user);
2098 1.75.8.2 christos state->user = strdup(pw->pw_name + 1);
2099 1.75.8.2 christos break;
2100 1.75.8.2 christos }
2101 1.75.8.2 christos /* save the prototype */
2102 1.75.8.2 christos state->protoflags = pwflags;
2103 1.75.8.2 christos if (! _pw_copy(pw, &state->proto, state->protobuf,
2104 1.75.8.2 christos sizeof(state->protobuf), NULL, 0)) {
2105 1.75.8.2 christos rv = NS_UNAVAIL;
2106 1.75.8.2 christos break;
2107 1.75.8.2 christos }
2108 1.75.8.2 christos continue; /* loop again after inclusion */
2109 1.75.8.2 christos } else if (pw->pw_name[0] == '-') {
2110 1.75.8.2 christos /* compat exclusion */
2111 1.75.8.2 christos rv = NS_SUCCESS;
2112 1.75.8.2 christos switch(pw->pw_name[1]) {
2113 1.75.8.2 christos case '\0': /* `-' */
2114 1.75.8.2 christos break;
2115 1.75.8.2 christos case '@': /* `-@netgroup' */
2116 1.75.8.2 christos /* XXXREENTRANT: {set,get,end}netgrent is not thread safe */
2117 1.75.8.2 christos setnetgrent(pw->pw_name + 2);
2118 1.75.8.2 christos while (getnetgrent(&host, &user, &dom)) {
2119 1.75.8.2 christos if (!user || !*user)
2120 1.75.8.2 christos continue;
2121 1.75.8.2 christos if (! _compat_add_exclude(state,user)) {
2122 1.75.8.2 christos rv = NS_UNAVAIL;
2123 1.75.8.2 christos break;
2124 1.75.8.2 christos }
2125 1.75.8.2 christos }
2126 1.75.8.2 christos endnetgrent();
2127 1.75.8.2 christos break;
2128 1.75.8.2 christos default: /* `-name' */
2129 1.75.8.2 christos if (! _compat_add_exclude(state,
2130 1.75.8.2 christos pw->pw_name + 1)) {
2131 1.75.8.2 christos rv = NS_UNAVAIL;
2132 1.75.8.2 christos }
2133 1.75.8.2 christos break;
2134 1.75.8.2 christos }
2135 1.75.8.2 christos if (rv != NS_SUCCESS) /* exclusion failure */
2136 1.75.8.2 christos break;
2137 1.75.8.2 christos continue; /* loop again after exclusion */
2138 1.75.8.2 christos }
2139 1.75.8.2 christos if (search == _PW_KEYBYNUM ||
2140 1.75.8.2 christos (search == _PW_KEYBYUID && pw->pw_uid == uid) ||
2141 1.75.8.2 christos (search == _PW_KEYBYNAME && strcmp(pw->pw_name, name) == 0))
2142 1.75.8.2 christos break; /* token mode match found */
2143 1.75.8.2 christos }
2144 1.75.8.2 christos
2145 1.75.8.2 christos if (rv == NS_NOTFOUND &&
2146 1.75.8.2 christos (search == _PW_KEYBYNUM || state->mode != COMPAT_NOTOKEN))
2147 1.75.8.2 christos state->keynum = -1; /* flag `no more records' */
2148 1.75.8.2 christos
2149 1.75.8.2 christos if (rv == NS_SUCCESS) {
2150 1.75.8.2 christos if ((search == _PW_KEYBYNAME && strcmp(pw->pw_name, name) != 0)
2151 1.75.8.2 christos || (search == _PW_KEYBYUID && pw->pw_uid != uid))
2152 1.75.8.2 christos rv = NS_NOTFOUND;
2153 1.75.8.2 christos }
2154 1.75.8.2 christos
2155 1.75.8.2 christos if (rv != NS_SUCCESS && rv != NS_NOTFOUND)
2156 1.75.8.2 christos *retval = errno;
2157 1.75.8.2 christos return rv;
2158 1.75.8.2 christos }
2159 1.75.8.2 christos
2160 1.75.8.2 christos /*ARGSUSED*/
2161 1.75.8.2 christos static int
2162 1.75.8.2 christos _compat_setpwent(void *nsrv, void *nscb, va_list ap)
2163 1.75.8.2 christos {
2164 1.75.8.2 christos
2165 1.75.8.2 christos /* force passwd_compat setpwent() */
2166 1.75.8.2 christos (void) _passwdcompat_setpassent(0);
2167 1.75.8.2 christos
2168 1.75.8.2 christos /* reset state, keep db open */
2169 1.75.8.2 christos _compat_state.stayopen = 0;
2170 1.75.8.2 christos return _compat_start(&_compat_state);
2171 1.75.8.2 christos }
2172 1.75.8.2 christos
2173 1.75.8.2 christos /*ARGSUSED*/
2174 1.75.8.2 christos static int
2175 1.75.8.2 christos _compat_setpassent(void *nsrv, void *nscb, va_list ap)
2176 1.75.8.2 christos {
2177 1.75.8.2 christos int *retval = va_arg(ap, int *);
2178 1.75.8.2 christos int stayopen = va_arg(ap, int);
2179 1.75.8.2 christos
2180 1.75.8.2 christos int rv;
2181 1.75.8.2 christos
2182 1.75.8.2 christos /* force passwd_compat setpassent() */
2183 1.75.8.2 christos (void) _passwdcompat_setpassent(stayopen);
2184 1.75.8.2 christos
2185 1.75.8.2 christos _compat_state.stayopen = stayopen;
2186 1.75.8.2 christos rv = _compat_start(&_compat_state);
2187 1.75.8.2 christos *retval = (rv == NS_SUCCESS);
2188 1.75.8.2 christos return rv;
2189 1.75.8.2 christos }
2190 1.75.8.2 christos
2191 1.75.8.2 christos /*ARGSUSED*/
2192 1.75.8.2 christos static int
2193 1.75.8.2 christos _compat_endpwent(void *nsrv, void *nscb, va_list ap)
2194 1.75.8.2 christos {
2195 1.75.8.2 christos
2196 1.75.8.2 christos /* force passwd_compat endpwent() */
2197 1.75.8.2 christos (void) _passwdcompat_endpwent();
2198 1.75.8.2 christos
2199 1.75.8.2 christos /* reset state, close db */
2200 1.75.8.2 christos _compat_state.stayopen = 0;
2201 1.75.8.2 christos return _compat_end(&_compat_state);
2202 1.75.8.2 christos }
2203 1.75.8.2 christos
2204 1.75.8.2 christos
2205 1.75.8.2 christos /*ARGSUSED*/
2206 1.75.8.2 christos static int
2207 1.75.8.2 christos _compat_getpwent(void *nsrv, void *nscb, va_list ap)
2208 1.75.8.2 christos {
2209 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
2210 1.75.8.2 christos
2211 1.75.8.2 christos int rv, rerror;
2212 1.75.8.2 christos
2213 1.75.8.2 christos _DIAGASSERT(retval != NULL);
2214 1.75.8.2 christos
2215 1.75.8.2 christos *retval = NULL;
2216 1.75.8.2 christos rv = _compat_pwscan(&rerror, &_compat_passwd,
2217 1.75.8.2 christos _compat_passwdbuf, sizeof(_compat_passwdbuf),
2218 1.75.8.2 christos &_compat_state, _PW_KEYBYNUM, NULL, 0);
2219 1.75.8.2 christos if (rv == NS_SUCCESS)
2220 1.75.8.2 christos *retval = &_compat_passwd;
2221 1.75.8.2 christos return rv;
2222 1.75.8.2 christos }
2223 1.75.8.2 christos
2224 1.75.8.2 christos /*ARGSUSED*/
2225 1.75.8.2 christos static int
2226 1.75.8.2 christos _compat_getpwent_r(void *nsrv, void *nscb, va_list ap)
2227 1.75.8.2 christos {
2228 1.75.8.2 christos int *retval = va_arg(ap, int *);
2229 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
2230 1.75.8.2 christos char *buffer = va_arg(ap, char *);
2231 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
2232 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
2233 1.75.8.2 christos
2234 1.75.8.2 christos int rv;
2235 1.75.8.2 christos
2236 1.75.8.2 christos _DIAGASSERT(retval != NULL);
2237 1.75.8.2 christos _DIAGASSERT(pw != NULL);
2238 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
2239 1.75.8.2 christos _DIAGASSERT(result != NULL);
2240 1.75.8.2 christos
2241 1.75.8.2 christos rv = _compat_pwscan(retval, pw, buffer, buflen, &_compat_state,
2242 1.75.8.2 christos _PW_KEYBYNUM, NULL, 0);
2243 1.75.8.2 christos if (rv == NS_SUCCESS)
2244 1.75.8.2 christos *result = pw;
2245 1.75.8.2 christos else
2246 1.75.8.2 christos *result = NULL;
2247 1.75.8.2 christos return rv;
2248 1.75.8.2 christos }
2249 1.75.8.2 christos
2250 1.75.8.2 christos
2251 1.75.8.2 christos /*ARGSUSED*/
2252 1.75.8.2 christos static int
2253 1.75.8.2 christos _compat_getpwnam(void *nsrv, void *nscb, va_list ap)
2254 1.75.8.2 christos {
2255 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
2256 1.75.8.2 christos const char *name = va_arg(ap, const char *);
2257 1.75.8.2 christos
2258 1.75.8.2 christos int rv, rerror;
2259 1.75.8.2 christos
2260 1.75.8.2 christos _DIAGASSERT(retval != NULL);
2261 1.75.8.2 christos
2262 1.75.8.2 christos *retval = NULL;
2263 1.75.8.2 christos rv = _compat_start(&_compat_state);
2264 1.75.8.2 christos if (rv != NS_SUCCESS)
2265 1.75.8.2 christos return rv;
2266 1.75.8.2 christos rv = _compat_pwscan(&rerror, &_compat_passwd,
2267 1.75.8.2 christos _compat_passwdbuf, sizeof(_compat_passwdbuf),
2268 1.75.8.2 christos &_compat_state, _PW_KEYBYNAME, name, 0);
2269 1.75.8.2 christos if (!_compat_state.stayopen)
2270 1.75.8.2 christos _compat_end(&_compat_state);
2271 1.75.8.2 christos if (rv == NS_SUCCESS)
2272 1.75.8.2 christos *retval = &_compat_passwd;
2273 1.75.8.2 christos return rv;
2274 1.75.8.2 christos }
2275 1.75.8.2 christos
2276 1.75.8.2 christos /*ARGSUSED*/
2277 1.75.8.2 christos static int
2278 1.75.8.2 christos _compat_getpwnam_r(void *nsrv, void *nscb, va_list ap)
2279 1.75.8.2 christos {
2280 1.75.8.2 christos int *retval = va_arg(ap, int *);
2281 1.75.8.2 christos const char *name = va_arg(ap, const char *);
2282 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
2283 1.75.8.2 christos char *buffer = va_arg(ap, char *);
2284 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
2285 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
2286 1.75.8.2 christos
2287 1.75.8.2 christos struct compat_state state;
2288 1.75.8.2 christos int rv;
2289 1.75.8.2 christos
2290 1.75.8.2 christos _DIAGASSERT(retval != NULL);
2291 1.75.8.2 christos _DIAGASSERT(pw != NULL);
2292 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
2293 1.75.8.2 christos _DIAGASSERT(result != NULL);
2294 1.75.8.2 christos
2295 1.75.8.2 christos *result = NULL;
2296 1.75.8.2 christos memset(&state, 0, sizeof(state));
2297 1.75.8.2 christos rv = _compat_pwscan(retval, pw, buffer, buflen, &state,
2298 1.75.8.2 christos _PW_KEYBYNAME, name, 0);
2299 1.75.8.2 christos _compat_end(&state);
2300 1.75.8.2 christos if (rv == NS_SUCCESS)
2301 1.75.8.2 christos *result = pw;
2302 1.75.8.2 christos return rv;
2303 1.75.8.2 christos }
2304 1.75.8.2 christos
2305 1.75.8.2 christos /*ARGSUSED*/
2306 1.75.8.2 christos static int
2307 1.75.8.2 christos _compat_getpwuid(void *nsrv, void *nscb, va_list ap)
2308 1.75.8.2 christos {
2309 1.75.8.2 christos struct passwd **retval = va_arg(ap, struct passwd **);
2310 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
2311 1.75.8.2 christos
2312 1.75.8.2 christos int rv, rerror;
2313 1.75.8.2 christos
2314 1.75.8.2 christos _DIAGASSERT(retval != NULL);
2315 1.75.8.2 christos
2316 1.75.8.2 christos *retval = NULL;
2317 1.75.8.2 christos rv = _compat_start(&_compat_state);
2318 1.75.8.2 christos if (rv != NS_SUCCESS)
2319 1.75.8.2 christos return rv;
2320 1.75.8.2 christos rv = _compat_pwscan(&rerror, &_compat_passwd,
2321 1.75.8.2 christos _compat_passwdbuf, sizeof(_compat_passwdbuf),
2322 1.75.8.2 christos &_compat_state, _PW_KEYBYUID, NULL, uid);
2323 1.75.8.2 christos if (!_compat_state.stayopen)
2324 1.75.8.2 christos _compat_end(&_compat_state);
2325 1.75.8.2 christos if (rv == NS_SUCCESS)
2326 1.75.8.2 christos *retval = &_compat_passwd;
2327 1.75.8.2 christos return rv;
2328 1.75.8.2 christos }
2329 1.75.8.2 christos
2330 1.75.8.2 christos /*ARGSUSED*/
2331 1.75.8.2 christos static int
2332 1.75.8.2 christos _compat_getpwuid_r(void *nsrv, void *nscb, va_list ap)
2333 1.75.8.2 christos {
2334 1.75.8.2 christos int *retval = va_arg(ap, int *);
2335 1.75.8.2 christos uid_t uid = va_arg(ap, uid_t);
2336 1.75.8.2 christos struct passwd *pw = va_arg(ap, struct passwd *);
2337 1.75.8.2 christos char *buffer = va_arg(ap, char *);
2338 1.75.8.2 christos size_t buflen = va_arg(ap, size_t);
2339 1.75.8.2 christos struct passwd **result = va_arg(ap, struct passwd **);
2340 1.75.8.2 christos
2341 1.75.8.2 christos struct compat_state state;
2342 1.75.8.2 christos int rv;
2343 1.75.8.2 christos
2344 1.75.8.2 christos _DIAGASSERT(retval != NULL);
2345 1.75.8.2 christos _DIAGASSERT(pw != NULL);
2346 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
2347 1.75.8.2 christos _DIAGASSERT(result != NULL);
2348 1.75.8.2 christos
2349 1.75.8.2 christos *result = NULL;
2350 1.75.8.2 christos memset(&state, 0, sizeof(state));
2351 1.75.8.2 christos rv = _compat_pwscan(retval, pw, buffer, buflen, &state,
2352 1.75.8.2 christos _PW_KEYBYUID, NULL, uid);
2353 1.75.8.2 christos _compat_end(&state);
2354 1.75.8.2 christos if (rv == NS_SUCCESS)
2355 1.75.8.2 christos *result = pw;
2356 1.75.8.2 christos return rv;
2357 1.75.8.2 christos }
2358 1.75.8.2 christos
2359 1.75.8.2 christos #endif /* _PASSWD_COMPAT */
2360 1.75.8.2 christos
2361 1.75.8.2 christos
2362 1.75.8.2 christos /*
2363 1.75.8.2 christos * public functions
2364 1.75.8.2 christos */
2365 1.75.8.2 christos
2366 1.75.8.2 christos struct passwd *
2367 1.75.8.2 christos getpwent(void)
2368 1.75.8.2 christos {
2369 1.75.8.2 christos int r;
2370 1.75.8.2 christos struct passwd *retval;
2371 1.75.8.2 christos
2372 1.75.8.2 christos static const ns_dtab dtab[] = {
2373 1.75.8.2 christos NS_FILES_CB(_files_getpwent, NULL)
2374 1.75.8.2 christos NS_DNS_CB(_dns_getpwent, NULL)
2375 1.75.8.2 christos NS_NIS_CB(_nis_getpwent, NULL)
2376 1.75.8.2 christos NS_COMPAT_CB(_compat_getpwent, NULL)
2377 1.75.8.2 christos NS_NULL_CB
2378 1.75.8.2 christos };
2379 1.75.8.2 christos
2380 1.75.8.2 christos mutex_lock(&_pwmutex);
2381 1.75.8.2 christos r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwent", __nsdefaultcompat,
2382 1.75.8.2 christos &retval);
2383 1.75.8.2 christos mutex_unlock(&_pwmutex);
2384 1.75.8.2 christos return (r == NS_SUCCESS) ? retval : NULL;
2385 1.75.8.2 christos }
2386 1.75.8.2 christos
2387 1.75.8.2 christos int
2388 1.75.8.2 christos getpwent_r(struct passwd *pwd, char *buffer, size_t buflen,
2389 1.75.8.2 christos struct passwd **result)
2390 1.75.8.2 christos {
2391 1.75.8.2 christos int r, retval;
2392 1.75.8.2 christos
2393 1.75.8.2 christos static const ns_dtab dtab[] = {
2394 1.75.8.2 christos NS_FILES_CB(_files_getpwent_r, NULL)
2395 1.75.8.2 christos NS_DNS_CB(_dns_getpwent_r, NULL)
2396 1.75.8.2 christos NS_NIS_CB(_nis_getpwent_r, NULL)
2397 1.75.8.2 christos NS_COMPAT_CB(_compat_getpwent_r, NULL)
2398 1.75.8.2 christos NS_NULL_CB
2399 1.75.8.2 christos };
2400 1.75.8.2 christos
2401 1.75.8.2 christos _DIAGASSERT(pwd != NULL);
2402 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
2403 1.75.8.2 christos _DIAGASSERT(result != NULL);
2404 1.75.8.2 christos
2405 1.75.8.2 christos *result = NULL;
2406 1.75.8.2 christos retval = 0;
2407 1.75.8.2 christos mutex_lock(&_pwmutex);
2408 1.75.8.2 christos r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwent_r", __nsdefaultcompat,
2409 1.75.8.2 christos &retval, pwd, buffer, buflen, result);
2410 1.75.8.2 christos mutex_unlock(&_pwmutex);
2411 1.75.8.2 christos switch (r) {
2412 1.75.8.2 christos case NS_SUCCESS:
2413 1.75.8.2 christos case NS_NOTFOUND:
2414 1.75.8.2 christos return 0;
2415 1.75.8.2 christos default:
2416 1.75.8.2 christos return retval;
2417 1.75.8.2 christos }
2418 1.75.8.2 christos }
2419 1.75.8.2 christos
2420 1.75.8.2 christos
2421 1.75.8.2 christos struct passwd *
2422 1.75.8.2 christos getpwnam(const char *name)
2423 1.75.8.2 christos {
2424 1.75.8.2 christos int rv;
2425 1.75.8.2 christos struct passwd *retval;
2426 1.75.8.2 christos
2427 1.75.8.2 christos static const ns_dtab dtab[] = {
2428 1.75.8.2 christos NS_FILES_CB(_files_getpwnam, NULL)
2429 1.75.8.2 christos NS_DNS_CB(_dns_getpwnam, NULL)
2430 1.75.8.2 christos NS_NIS_CB(_nis_getpwnam, NULL)
2431 1.75.8.2 christos NS_COMPAT_CB(_compat_getpwnam, NULL)
2432 1.75.8.2 christos NS_NULL_CB
2433 1.75.8.2 christos };
2434 1.75.8.2 christos
2435 1.75.8.2 christos mutex_lock(&_pwmutex);
2436 1.75.8.2 christos rv = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwnam", __nsdefaultcompat,
2437 1.75.8.2 christos &retval, name);
2438 1.75.8.2 christos mutex_unlock(&_pwmutex);
2439 1.75.8.2 christos return (rv == NS_SUCCESS) ? retval : NULL;
2440 1.75.8.2 christos }
2441 1.75.8.2 christos
2442 1.75.8.2 christos int
2443 1.75.8.2 christos getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t buflen,
2444 1.75.8.2 christos struct passwd **result)
2445 1.75.8.2 christos {
2446 1.75.8.2 christos int r, retval;
2447 1.75.8.2 christos
2448 1.75.8.2 christos static const ns_dtab dtab[] = {
2449 1.75.8.2 christos NS_FILES_CB(_files_getpwnam_r, NULL)
2450 1.75.8.2 christos NS_DNS_CB(_dns_getpwnam_r, NULL)
2451 1.75.8.2 christos NS_NIS_CB(_nis_getpwnam_r, NULL)
2452 1.75.8.2 christos NS_COMPAT_CB(_compat_getpwnam_r, NULL)
2453 1.75.8.2 christos NS_NULL_CB
2454 1.75.8.2 christos };
2455 1.75.8.2 christos
2456 1.75.8.2 christos _DIAGASSERT(name != NULL);
2457 1.75.8.2 christos _DIAGASSERT(pwd != NULL);
2458 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
2459 1.75.8.2 christos _DIAGASSERT(result != NULL);
2460 1.75.8.2 christos
2461 1.75.8.2 christos *result = NULL;
2462 1.75.8.2 christos retval = 0;
2463 1.75.8.2 christos mutex_lock(&_pwmutex);
2464 1.75.8.2 christos r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwnam_r", __nsdefaultcompat,
2465 1.75.8.2 christos &retval, name, pwd, buffer, buflen, result);
2466 1.75.8.2 christos mutex_unlock(&_pwmutex);
2467 1.75.8.2 christos switch (r) {
2468 1.75.8.2 christos case NS_SUCCESS:
2469 1.75.8.2 christos case NS_NOTFOUND:
2470 1.75.8.2 christos return 0;
2471 1.75.8.2 christos default:
2472 1.75.8.2 christos return retval;
2473 1.75.8.2 christos }
2474 1.75.8.2 christos }
2475 1.75.8.2 christos
2476 1.75.8.2 christos struct passwd *
2477 1.75.8.2 christos getpwuid(uid_t uid)
2478 1.75.8.2 christos {
2479 1.75.8.2 christos int rv;
2480 1.75.8.2 christos struct passwd *retval;
2481 1.75.8.2 christos
2482 1.75.8.2 christos static const ns_dtab dtab[] = {
2483 1.75.8.2 christos NS_FILES_CB(_files_getpwuid, NULL)
2484 1.75.8.2 christos NS_DNS_CB(_dns_getpwuid, NULL)
2485 1.75.8.2 christos NS_NIS_CB(_nis_getpwuid, NULL)
2486 1.75.8.2 christos NS_COMPAT_CB(_compat_getpwuid, NULL)
2487 1.75.8.2 christos NS_NULL_CB
2488 1.75.8.2 christos };
2489 1.75.8.2 christos
2490 1.75.8.2 christos mutex_lock(&_pwmutex);
2491 1.75.8.2 christos rv = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwuid", __nsdefaultcompat,
2492 1.75.8.2 christos &retval, uid);
2493 1.75.8.2 christos mutex_unlock(&_pwmutex);
2494 1.75.8.2 christos return (rv == NS_SUCCESS) ? retval : NULL;
2495 1.75.8.2 christos }
2496 1.75.8.2 christos
2497 1.75.8.2 christos int
2498 1.75.8.2 christos getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t buflen,
2499 1.75.8.2 christos struct passwd **result)
2500 1.75.8.2 christos {
2501 1.75.8.2 christos int r, retval;
2502 1.75.8.2 christos
2503 1.75.8.2 christos static const ns_dtab dtab[] = {
2504 1.75.8.2 christos NS_FILES_CB(_files_getpwuid_r, NULL)
2505 1.75.8.2 christos NS_DNS_CB(_dns_getpwuid_r, NULL)
2506 1.75.8.2 christos NS_NIS_CB(_nis_getpwuid_r, NULL)
2507 1.75.8.2 christos NS_COMPAT_CB(_compat_getpwuid_r, NULL)
2508 1.75.8.2 christos NS_NULL_CB
2509 1.75.8.2 christos };
2510 1.75.8.2 christos
2511 1.75.8.2 christos _DIAGASSERT(pwd != NULL);
2512 1.75.8.2 christos _DIAGASSERT(buffer != NULL);
2513 1.75.8.2 christos _DIAGASSERT(result != NULL);
2514 1.75.8.2 christos
2515 1.75.8.2 christos *result = NULL;
2516 1.75.8.2 christos retval = 0;
2517 1.75.8.2 christos mutex_lock(&_pwmutex);
2518 1.75.8.2 christos r = nsdispatch(NULL, dtab, NSDB_PASSWD, "getpwuid_r", __nsdefaultcompat,
2519 1.75.8.2 christos &retval, uid, pwd, buffer, buflen, result);
2520 1.75.8.2 christos mutex_unlock(&_pwmutex);
2521 1.75.8.2 christos switch (r) {
2522 1.75.8.2 christos case NS_SUCCESS:
2523 1.75.8.2 christos case NS_NOTFOUND:
2524 1.75.8.2 christos return 0;
2525 1.75.8.2 christos default:
2526 1.75.8.2 christos return retval;
2527 1.75.8.2 christos }
2528 1.75.8.2 christos }
2529 1.75.8.2 christos
2530 1.75.8.2 christos void
2531 1.75.8.2 christos endpwent(void)
2532 1.75.8.2 christos {
2533 1.75.8.2 christos static const ns_dtab dtab[] = {
2534 1.75.8.2 christos NS_FILES_CB(_files_endpwent, NULL)
2535 1.75.8.2 christos NS_DNS_CB(_dns_endpwent, NULL)
2536 1.75.8.2 christos NS_NIS_CB(_nis_endpwent, NULL)
2537 1.75.8.2 christos NS_COMPAT_CB(_compat_endpwent, NULL)
2538 1.75.8.2 christos NS_NULL_CB
2539 1.75.8.2 christos };
2540 1.75.8.2 christos
2541 1.75.8.2 christos mutex_lock(&_pwmutex);
2542 1.75.8.2 christos /* force all endpwent() methods */
2543 1.75.8.2 christos (void) nsdispatch(NULL, dtab, NSDB_PASSWD, "endpwent",
2544 1.75.8.2 christos __nsdefaultcompat_forceall);
2545 1.75.8.2 christos mutex_unlock(&_pwmutex);
2546 1.75.8.2 christos }
2547 1.75.8.2 christos
2548 1.75.8.2 christos /*ARGSUSED*/
2549 1.75.8.2 christos int
2550 1.75.8.2 christos setpassent(int stayopen)
2551 1.75.8.2 christos {
2552 1.75.8.2 christos static const ns_dtab dtab[] = {
2553 1.75.8.2 christos NS_FILES_CB(_files_setpassent, NULL)
2554 1.75.8.2 christos NS_DNS_CB(_dns_setpassent, NULL)
2555 1.75.8.2 christos NS_NIS_CB(_nis_setpassent, NULL)
2556 1.75.8.2 christos NS_COMPAT_CB(_compat_setpassent, NULL)
2557 1.75.8.2 christos NS_NULL_CB
2558 1.75.8.2 christos };
2559 1.75.8.2 christos int rv, retval;
2560 1.75.8.2 christos
2561 1.75.8.2 christos mutex_lock(&_pwmutex);
2562 1.75.8.2 christos /* force all setpassent() methods */
2563 1.75.8.2 christos rv = nsdispatch(NULL, dtab, NSDB_PASSWD, "setpassent",
2564 1.75.8.2 christos __nsdefaultcompat_forceall, &retval, stayopen);
2565 1.75.8.2 christos mutex_unlock(&_pwmutex);
2566 1.75.8.2 christos return (rv == NS_SUCCESS) ? retval : 0;
2567 1.75.8.2 christos }
2568 1.75.8.2 christos
2569 1.75.8.2 christos void
2570 1.75.8.2 christos setpwent(void)
2571 1.75.8.2 christos {
2572 1.75.8.2 christos static const ns_dtab dtab[] = {
2573 1.75.8.2 christos NS_FILES_CB(_files_setpwent, NULL)
2574 1.75.8.2 christos NS_DNS_CB(_dns_setpwent, NULL)
2575 1.75.8.2 christos NS_NIS_CB(_nis_setpwent, NULL)
2576 1.75.8.2 christos NS_COMPAT_CB(_compat_setpwent, NULL)
2577 1.75.8.2 christos NS_NULL_CB
2578 1.75.8.2 christos };
2579 1.75.8.2 christos
2580 1.75.8.2 christos mutex_lock(&_pwmutex);
2581 1.75.8.2 christos /* force all setpwent() methods */
2582 1.75.8.2 christos (void) nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent",
2583 1.75.8.2 christos __nsdefaultcompat_forceall);
2584 1.75.8.2 christos mutex_unlock(&_pwmutex);
2585 1.75.8.2 christos }
2586