xref: /netbsd-src/external/bsd/libbind/dist/irs/lcl_pw.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
1*5bbd2a12Schristos /*	$NetBSD: lcl_pw.c,v 1.1.1.2 2012/09/09 16:07:58 christos Exp $	*/
2b5677b36Schristos 
3b5677b36Schristos /*
4b5677b36Schristos  * Copyright (c) 1989, 1993, 1995
5b5677b36Schristos  *	The Regents of the University of California.  All rights reserved.
6b5677b36Schristos  *
7b5677b36Schristos  * Redistribution and use in source and binary forms, with or without
8b5677b36Schristos  * modification, are permitted provided that the following conditions
9b5677b36Schristos  * are met:
10b5677b36Schristos  * 1. Redistributions of source code must retain the above copyright
11b5677b36Schristos  *    notice, this list of conditions and the following disclaimer.
12b5677b36Schristos  * 2. Redistributions in binary form must reproduce the above copyright
13b5677b36Schristos  *    notice, this list of conditions and the following disclaimer in the
14b5677b36Schristos  *    documentation and/or other materials provided with the distribution.
15b5677b36Schristos  * 3. All advertising materials mentioning features or use of this software
16b5677b36Schristos  *    must display the following acknowledgement:
17b5677b36Schristos  *	This product includes software developed by the University of
18b5677b36Schristos  *	California, Berkeley and its contributors.
19b5677b36Schristos  * 4. Neither the name of the University nor the names of its contributors
20b5677b36Schristos  *    may be used to endorse or promote products derived from this software
21b5677b36Schristos  *    without specific prior written permission.
22b5677b36Schristos  *
23b5677b36Schristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24b5677b36Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25b5677b36Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26b5677b36Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27b5677b36Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28b5677b36Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29b5677b36Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30b5677b36Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31b5677b36Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32b5677b36Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33b5677b36Schristos  * SUCH DAMAGE.
34b5677b36Schristos  */
35b5677b36Schristos 
36b5677b36Schristos /*
37b5677b36Schristos  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
38b5677b36Schristos  * Portions Copyright (c) 1996,1999 by Internet Software Consortium.
39b5677b36Schristos  *
40b5677b36Schristos  * Permission to use, copy, modify, and distribute this software for any
41b5677b36Schristos  * purpose with or without fee is hereby granted, provided that the above
42b5677b36Schristos  * copyright notice and this permission notice appear in all copies.
43b5677b36Schristos  *
44b5677b36Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
45b5677b36Schristos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
46b5677b36Schristos  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
47b5677b36Schristos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48b5677b36Schristos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
49b5677b36Schristos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
50b5677b36Schristos  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51b5677b36Schristos  */
52b5677b36Schristos 
53b5677b36Schristos #if defined(LIBC_SCCS) && !defined(lint)
54b5677b36Schristos static const char rcsid[] = "Id: lcl_pw.c,v 1.3 2005/04/27 04:56:31 sra Exp ";
55b5677b36Schristos #endif /* LIBC_SCCS and not lint */
56b5677b36Schristos 
57b5677b36Schristos /* Extern */
58b5677b36Schristos 
59b5677b36Schristos #include "port_before.h"
60b5677b36Schristos 
61b5677b36Schristos #ifndef WANT_IRS_PW
62b5677b36Schristos static int __bind_irs_pw_unneeded;
63b5677b36Schristos #else
64b5677b36Schristos 
65b5677b36Schristos #include <sys/param.h>
66b5677b36Schristos #include <sys/types.h>
67b5677b36Schristos #include <netinet/in.h>
68b5677b36Schristos #include <arpa/nameser.h>
69b5677b36Schristos #include <resolv.h>
70b5677b36Schristos 
71b5677b36Schristos #include <db.h>
72b5677b36Schristos #include <errno.h>
73b5677b36Schristos #include <fcntl.h>
74b5677b36Schristos #include <limits.h>
75b5677b36Schristos #include <pwd.h>
76b5677b36Schristos #include <stdlib.h>
77b5677b36Schristos #include <string.h>
78b5677b36Schristos #include <syslog.h>
79b5677b36Schristos #include <utmp.h>
80b5677b36Schristos #include <unistd.h>
81b5677b36Schristos 
82b5677b36Schristos #include <isc/memcluster.h>
83b5677b36Schristos #include <irs.h>
84b5677b36Schristos 
85b5677b36Schristos #include "port_after.h"
86b5677b36Schristos 
87b5677b36Schristos #include "irs_p.h"
88b5677b36Schristos #include "lcl_p.h"
89b5677b36Schristos 
90b5677b36Schristos /*! \file
91b5677b36Schristos  * \brief
92b5677b36Schristos  * The lookup techniques and data extraction code here must be kept
93b5677b36Schristos  * in sync with that in `pwd_mkdb'.
94b5677b36Schristos  */
95b5677b36Schristos 
96b5677b36Schristos 
97b5677b36Schristos /* Types */
98b5677b36Schristos 
99b5677b36Schristos struct  pvt {
100b5677b36Schristos 	struct passwd	passwd;		/*%< password structure */
101b5677b36Schristos 	DB 		*pw_db;		/*%< password database */
102b5677b36Schristos 	int		pw_keynum;	/*%< key counter */
103b5677b36Schristos 	int		warned;
104b5677b36Schristos 	u_int		max;
105b5677b36Schristos 	char *		line;
106b5677b36Schristos };
107b5677b36Schristos 
108b5677b36Schristos /* Forward */
109b5677b36Schristos 
110b5677b36Schristos static void			pw_close(struct irs_pw *);
111b5677b36Schristos static struct passwd *		pw_next(struct irs_pw *);
112b5677b36Schristos static struct passwd *		pw_byname(struct irs_pw *, const char *);
113b5677b36Schristos static struct passwd *		pw_byuid(struct irs_pw *, uid_t);
114b5677b36Schristos static void			pw_rewind(struct irs_pw *);
115b5677b36Schristos static void			pw_minimize(struct irs_pw *);
116b5677b36Schristos 
117b5677b36Schristos static int			initdb(struct pvt *);
118b5677b36Schristos static int			hashpw(struct irs_pw *, DBT *);
119b5677b36Schristos 
120b5677b36Schristos /* Public */
121b5677b36Schristos struct irs_pw *
irs_lcl_pw(struct irs_acc * this)122b5677b36Schristos irs_lcl_pw(struct irs_acc *this) {
123b5677b36Schristos 	struct irs_pw *pw;
124b5677b36Schristos 	struct pvt *pvt;
125b5677b36Schristos 
126b5677b36Schristos 	UNUSED(this);
127b5677b36Schristos 
128b5677b36Schristos         if (!(pw = memget(sizeof *pw))) {
129b5677b36Schristos 		errno = ENOMEM;
130b5677b36Schristos 		return (NULL);
131b5677b36Schristos 	}
132b5677b36Schristos 	memset(pw, 0x5e, sizeof *pw);
133b5677b36Schristos 	if (!(pvt = memget(sizeof *pvt))) {
134b5677b36Schristos 		free(pw);
135b5677b36Schristos 		errno = ENOMEM;
136b5677b36Schristos 		return (NULL);
137b5677b36Schristos 	}
138b5677b36Schristos 	memset(pvt, 0, sizeof *pvt);
139b5677b36Schristos 	pw->private = pvt;
140b5677b36Schristos 	pw->close = pw_close;
141b5677b36Schristos 	pw->next = pw_next;
142b5677b36Schristos 	pw->byname = pw_byname;
143b5677b36Schristos 	pw->byuid = pw_byuid;
144b5677b36Schristos 	pw->rewind = pw_rewind;
145b5677b36Schristos 	pw->minimize = pw_minimize;
146b5677b36Schristos 	pw->res_get = NULL;
147b5677b36Schristos 	pw->res_set = NULL;
148b5677b36Schristos 	return (pw);
149b5677b36Schristos }
150b5677b36Schristos 
151b5677b36Schristos /* Methods */
152b5677b36Schristos 
153b5677b36Schristos static void
pw_close(struct irs_pw * this)154b5677b36Schristos pw_close(struct irs_pw *this) {
155b5677b36Schristos 	struct pvt *pvt = (struct pvt *)this->private;
156b5677b36Schristos 
157b5677b36Schristos 	if (pvt->pw_db) {
158b5677b36Schristos 		(void)(pvt->pw_db->close)(pvt->pw_db);
159b5677b36Schristos 		pvt->pw_db = NULL;
160b5677b36Schristos 	}
161b5677b36Schristos 	if (pvt->line)
162b5677b36Schristos 		memput(pvt->line, pvt->max);
163b5677b36Schristos 	memput(pvt, sizeof *pvt);
164b5677b36Schristos 	memput(this, sizeof *this);
165b5677b36Schristos }
166b5677b36Schristos 
167b5677b36Schristos static struct passwd *
pw_next(struct irs_pw * this)168b5677b36Schristos pw_next(struct irs_pw *this) {
169b5677b36Schristos 	struct pvt *pvt = (struct pvt *)this->private;
170b5677b36Schristos 
171b5677b36Schristos 	DBT key;
172b5677b36Schristos 	char bf[sizeof(pvt->pw_keynum) + 1];
173b5677b36Schristos 
174b5677b36Schristos 	if (!initdb(pvt))
175b5677b36Schristos 		return (NULL);
176b5677b36Schristos 
177b5677b36Schristos 	++pvt->pw_keynum;
178b5677b36Schristos 	bf[0] = _PW_KEYBYNUM;
179b5677b36Schristos 	memcpy(bf + 1, (char *)&pvt->pw_keynum, sizeof(pvt->pw_keynum));
180b5677b36Schristos 	key.data = (u_char *)bf;
181b5677b36Schristos 	key.size = sizeof(pvt->pw_keynum) + 1;
182b5677b36Schristos 	return (hashpw(this, &key) ? &pvt->passwd : NULL);
183b5677b36Schristos }
184b5677b36Schristos 
185b5677b36Schristos static struct passwd *
pw_byname(struct irs_pw * this,const char * name)186b5677b36Schristos pw_byname(struct irs_pw *this, const char *name) {
187b5677b36Schristos 	struct pvt *pvt = (struct pvt *)this->private;
188b5677b36Schristos 	DBT key;
189b5677b36Schristos 	int len, rval;
190b5677b36Schristos 	char bf[UT_NAMESIZE + 1];
191b5677b36Schristos 
192b5677b36Schristos 	if (!initdb(pvt))
193b5677b36Schristos 		return (NULL);
194b5677b36Schristos 
195b5677b36Schristos 	bf[0] = _PW_KEYBYNAME;
196b5677b36Schristos 	len = strlen(name);
197b5677b36Schristos 	memcpy(bf + 1, name, MIN(len, UT_NAMESIZE));
198b5677b36Schristos 	key.data = (u_char *)bf;
199b5677b36Schristos 	key.size = len + 1;
200b5677b36Schristos 	rval = hashpw(this, &key);
201b5677b36Schristos 
202b5677b36Schristos 	return (rval ? &pvt->passwd : NULL);
203b5677b36Schristos }
204b5677b36Schristos 
205b5677b36Schristos 
206b5677b36Schristos static struct passwd *
pw_byuid(struct irs_pw * this,uid_t uid)207b5677b36Schristos pw_byuid(struct irs_pw *this, uid_t uid) {
208b5677b36Schristos 	struct pvt *pvt = (struct pvt *)this->private;
209b5677b36Schristos 	DBT key;
210b5677b36Schristos 	int keyuid, rval;
211b5677b36Schristos 	char bf[sizeof(keyuid) + 1];
212b5677b36Schristos 
213b5677b36Schristos 	if (!initdb(pvt))
214b5677b36Schristos 		return (NULL);
215b5677b36Schristos 
216b5677b36Schristos 	bf[0] = _PW_KEYBYUID;
217b5677b36Schristos 	keyuid = uid;
218b5677b36Schristos 	memcpy(bf + 1, &keyuid, sizeof(keyuid));
219b5677b36Schristos 	key.data = (u_char *)bf;
220b5677b36Schristos 	key.size = sizeof(keyuid) + 1;
221b5677b36Schristos 	rval = hashpw(this, &key);
222b5677b36Schristos 
223b5677b36Schristos 	return (rval ? &pvt->passwd : NULL);
224b5677b36Schristos }
225b5677b36Schristos 
226b5677b36Schristos static void
pw_rewind(struct irs_pw * this)227b5677b36Schristos pw_rewind(struct irs_pw *this) {
228b5677b36Schristos 	struct pvt *pvt = (struct pvt *)this->private;
229b5677b36Schristos 
230b5677b36Schristos 	pvt->pw_keynum = 0;
231b5677b36Schristos }
232b5677b36Schristos 
233b5677b36Schristos static void
pw_minimize(struct irs_pw * this)234b5677b36Schristos pw_minimize(struct irs_pw *this) {
235b5677b36Schristos 	struct pvt *pvt = (struct pvt *)this->private;
236b5677b36Schristos 
237b5677b36Schristos 	if (pvt->pw_db != NULL) {
238b5677b36Schristos 		(void) (*pvt->pw_db->close)(pvt->pw_db);
239b5677b36Schristos 		pvt->pw_db = NULL;
240b5677b36Schristos 	}
241b5677b36Schristos }
242b5677b36Schristos 
243b5677b36Schristos /* Private. */
244b5677b36Schristos 
245b5677b36Schristos static int
initdb(struct pvt * pvt)246b5677b36Schristos initdb(struct pvt *pvt) {
247b5677b36Schristos 	const char *p;
248b5677b36Schristos 
249b5677b36Schristos 	if (pvt->pw_db) {
250b5677b36Schristos 		if (lseek((*pvt->pw_db->fd)(pvt->pw_db), 0L, SEEK_CUR) >= 0L)
251b5677b36Schristos 			return (1);
252b5677b36Schristos 		else
253b5677b36Schristos 			(void) (*pvt->pw_db->close)(pvt->pw_db);
254b5677b36Schristos 	}
255b5677b36Schristos 	pvt->pw_db = dbopen((p = _PATH_SMP_DB), O_RDONLY, 0, DB_HASH, NULL);
256b5677b36Schristos 	if (!pvt->pw_db)
257b5677b36Schristos 		pvt->pw_db = dbopen((p =_PATH_MP_DB), O_RDONLY,
258b5677b36Schristos 				    0, DB_HASH, NULL);
259b5677b36Schristos 	if (pvt->pw_db)
260b5677b36Schristos 		return (1);
261b5677b36Schristos 	if (!pvt->warned) {
262b5677b36Schristos 		syslog(LOG_ERR, "%s: %m", p);
263b5677b36Schristos 		pvt->warned++;
264b5677b36Schristos 	}
265b5677b36Schristos 	return (0);
266b5677b36Schristos }
267b5677b36Schristos 
268b5677b36Schristos static int
hashpw(struct irs_pw * this,DBT * key)269b5677b36Schristos hashpw(struct irs_pw *this, DBT *key) {
270b5677b36Schristos 	struct pvt *pvt = (struct pvt *)this->private;
271b5677b36Schristos 	char *p, *t, *l;
272b5677b36Schristos 	DBT data;
273b5677b36Schristos 
274b5677b36Schristos 	if ((pvt->pw_db->get)(pvt->pw_db, key, &data, 0))
275b5677b36Schristos 		return (0);
276b5677b36Schristos 	p = (char *)data.data;
277b5677b36Schristos 	if (data.size > pvt->max) {
278b5677b36Schristos 		size_t newlen = pvt->max + 1024;
279b5677b36Schristos 		char *p = memget(newlen);
280b5677b36Schristos 		if (p == NULL) {
281b5677b36Schristos 			return (0);
282b5677b36Schristos 		}
283b5677b36Schristos 		if (pvt->line != NULL) {
284b5677b36Schristos 			memcpy(p, pvt->line, pvt->max);
285b5677b36Schristos 			memput(pvt->line, pvt->max);
286b5677b36Schristos 		}
287b5677b36Schristos 		pvt->max = newlen;
288b5677b36Schristos 		pvt->line = p;
289b5677b36Schristos 	}
290b5677b36Schristos 
291b5677b36Schristos 	/* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
292b5677b36Schristos 	t = pvt->line;
293b5677b36Schristos 	l = pvt->line + pvt->max;
294b5677b36Schristos #define EXPAND(e) if ((e = t) == NULL) return (0); else \
295b5677b36Schristos 		  do if (t >= l) return (0); while ((*t++ = *p++) != '\0')
296b5677b36Schristos #define SCALAR(v) if (t + sizeof v >= l) return (0); else \
297b5677b36Schristos 		  (memmove(&(v), p, sizeof v), p += sizeof v)
298b5677b36Schristos 	EXPAND(pvt->passwd.pw_name);
299b5677b36Schristos 	EXPAND(pvt->passwd.pw_passwd);
300b5677b36Schristos 	SCALAR(pvt->passwd.pw_uid);
301b5677b36Schristos 	SCALAR(pvt->passwd.pw_gid);
302b5677b36Schristos 	SCALAR(pvt->passwd.pw_change);
303b5677b36Schristos 	EXPAND(pvt->passwd.pw_class);
304b5677b36Schristos 	EXPAND(pvt->passwd.pw_gecos);
305b5677b36Schristos 	EXPAND(pvt->passwd.pw_dir);
306b5677b36Schristos 	EXPAND(pvt->passwd.pw_shell);
307b5677b36Schristos 	SCALAR(pvt->passwd.pw_expire);
308b5677b36Schristos 	return (1);
309b5677b36Schristos }
310b5677b36Schristos 
311b5677b36Schristos #endif /* WANT_IRS_PW */
312