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