1/*	$NetBSD: nis_pw.c,v 1.1.1.2 2012/09/09 16:07:56 christos Exp $	*/
2
3/*
4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (c) 1996,1999 by Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21static const char rcsid[] = "Id: nis_pw.c,v 1.4 2005/04/27 04:56:33 sra Exp ";
22#endif /* LIBC_SCCS and not lint */
23
24/* Imports */
25
26#include "port_before.h"
27
28#if !defined(WANT_IRS_PW) || !defined(WANT_IRS_NIS)
29static int __bind_irs_pw_unneeded;
30#else
31
32#include <sys/param.h>
33#include <sys/types.h>
34#include <netinet/in.h>
35#include <arpa/nameser.h>
36#include <resolv.h>
37#include <isc/memcluster.h>
38#include <rpc/rpc.h>
39#include <rpc/xdr.h>
40#include <rpcsvc/yp_prot.h>
41#include <rpcsvc/ypclnt.h>
42
43#include <errno.h>
44#include <fcntl.h>
45#include <pwd.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50
51#include <isc/memcluster.h>
52
53#include <irs.h>
54
55#include "port_after.h"
56
57#include "irs_p.h"
58#include "nis_p.h"
59
60/* Definitions */
61
62struct pvt {
63	int		needrewind;
64	char *		nis_domain;
65	char *		curkey_data;
66	int		curkey_len;
67	char *		curval_data;
68	int		curval_len;
69	struct passwd 	passwd;
70	char *		pwbuf;
71};
72
73enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
74
75static /*const*/ char passwd_byname[] =	"passwd.byname";
76static /*const*/ char passwd_byuid[] =	"passwd.byuid";
77
78/* Forward */
79
80static void			pw_close(struct irs_pw *);
81static struct passwd *		pw_next(struct irs_pw *);
82static struct passwd *		pw_byname(struct irs_pw *, const char *);
83static struct passwd *		pw_byuid(struct irs_pw *, uid_t);
84static void			pw_rewind(struct irs_pw *);
85static void			pw_minimize(struct irs_pw *);
86
87static struct passwd *		makepasswdent(struct irs_pw *);
88static void			nisfree(struct pvt *, enum do_what);
89
90/* Public */
91
92struct irs_pw *
93irs_nis_pw(struct irs_acc *this) {
94	struct irs_pw *pw;
95	struct pvt *pvt;
96
97        if (!(pw = memget(sizeof *pw))) {
98                errno = ENOMEM;
99                return (NULL);
100        }
101        memset(pw, 0x5e, sizeof *pw);
102        if (!(pvt = memget(sizeof *pvt))) {
103                memput(pw, sizeof *pw);
104                errno = ENOMEM;
105                return (NULL);
106        }
107        memset(pvt, 0, sizeof *pvt);
108	pvt->needrewind = 1;
109	pvt->nis_domain = ((struct nis_p *)this->private)->domain;
110	pw->private = pvt;
111	pw->close = pw_close;
112	pw->next = pw_next;
113	pw->byname = pw_byname;
114	pw->byuid = pw_byuid;
115	pw->rewind = pw_rewind;
116	pw->minimize = pw_minimize;
117	pw->res_get = NULL;
118	pw->res_set = NULL;
119	return (pw);
120}
121
122/* Methods */
123
124static void
125pw_close(struct irs_pw *this) {
126	struct pvt *pvt = (struct pvt *)this->private;
127
128	if (pvt->pwbuf)
129		free(pvt->pwbuf);
130	nisfree(pvt, do_all);
131	memput(pvt, sizeof *pvt);
132	memput(this, sizeof *this);
133}
134
135static struct passwd *
136pw_next(struct irs_pw *this) {
137	struct pvt *pvt = (struct pvt *)this->private;
138	struct passwd *rval;
139	int r;
140
141	do {
142		if (pvt->needrewind) {
143			nisfree(pvt, do_all);
144			r = yp_first(pvt->nis_domain, passwd_byname,
145				     &pvt->curkey_data, &pvt->curkey_len,
146				     &pvt->curval_data, &pvt->curval_len);
147			pvt->needrewind = 0;
148		} else {
149			char *newkey_data;
150			int newkey_len;
151
152			nisfree(pvt, do_val);
153			r = yp_next(pvt->nis_domain, passwd_byname,
154				    pvt->curkey_data, pvt->curkey_len,
155				    &newkey_data, &newkey_len,
156				    &pvt->curval_data, &pvt->curval_len);
157			nisfree(pvt, do_key);
158			pvt->curkey_data = newkey_data;
159			pvt->curkey_len = newkey_len;
160		}
161		if (r != 0) {
162			errno = ENOENT;
163			return (NULL);
164		}
165		rval = makepasswdent(this);
166	} while (rval == NULL);
167	return (rval);
168}
169
170static struct passwd *
171pw_byname(struct irs_pw *this, const char *name) {
172	struct pvt *pvt = (struct pvt *)this->private;
173	int r;
174	char *tmp;
175
176	nisfree(pvt, do_val);
177	DE_CONST(name, tmp);
178	r = yp_match(pvt->nis_domain, passwd_byname, tmp, strlen(tmp),
179		     &pvt->curval_data, &pvt->curval_len);
180	if (r != 0) {
181		errno = ENOENT;
182		return (NULL);
183	}
184	return (makepasswdent(this));
185}
186
187static struct passwd *
188pw_byuid(struct irs_pw *this, uid_t uid) {
189	struct pvt *pvt = (struct pvt *)this->private;
190	char tmp[sizeof "4294967295"];
191	int r;
192
193	nisfree(pvt, do_val);
194	(void) sprintf(tmp, "%u", (unsigned int)uid);
195	r = yp_match(pvt->nis_domain, passwd_byuid, tmp, strlen(tmp),
196		     &pvt->curval_data, &pvt->curval_len);
197	if (r != 0) {
198		errno = ENOENT;
199		return (NULL);
200	}
201	return (makepasswdent(this));
202}
203
204static void
205pw_rewind(struct irs_pw *this) {
206	struct pvt *pvt = (struct pvt *)this->private;
207
208	pvt->needrewind = 1;
209}
210
211static void
212pw_minimize(struct irs_pw *this) {
213	UNUSED(this);
214	/* NOOP */
215}
216
217/* Private */
218
219static struct passwd *
220makepasswdent(struct irs_pw *this) {
221	struct pvt *pvt = (struct pvt *)this->private;
222	char *cp;
223
224	memset(&pvt->passwd, 0, sizeof pvt->passwd);
225	if (pvt->pwbuf)
226		free(pvt->pwbuf);
227	pvt->pwbuf = pvt->curval_data;
228	pvt->curval_data = NULL;
229
230	cp = pvt->pwbuf;
231	pvt->passwd.pw_name = cp;
232	if (!(cp = strchr(cp, ':')))
233		goto cleanup;
234#ifdef HAS_PW_CLASS
235	pvt->passwd.pw_class = cp;	/*%< Needs to point at a \0. */
236#endif
237	*cp++ = '\0';
238
239	pvt->passwd.pw_passwd = cp;
240	if (!(cp = strchr(cp, ':')))
241		goto cleanup;
242	*cp++ = '\0';
243
244	pvt->passwd.pw_uid = atoi(cp);
245	if (!(cp = strchr(cp, ':')))
246		goto cleanup;
247	*cp++ = '\0';
248
249	pvt->passwd.pw_gid = atoi(cp);
250	if (!(cp = strchr(cp, ':')))
251		goto cleanup;
252	*cp++ = '\0';
253
254	pvt->passwd.pw_gecos = cp;
255	if (!(cp = strchr(cp, ':')))
256		goto cleanup;
257	*cp++ = '\0';
258
259	pvt->passwd.pw_dir = cp;
260	if (!(cp = strchr(cp, ':')))
261		goto cleanup;
262	*cp++ = '\0';
263
264	pvt->passwd.pw_shell = cp;
265
266	if ((cp = strchr(cp, '\n')) != NULL)
267		*cp = '\0';
268
269	return (&pvt->passwd);
270
271 cleanup:
272	free(pvt->pwbuf);
273	pvt->pwbuf = NULL;
274	return (NULL);
275}
276
277static void
278nisfree(struct pvt *pvt, enum do_what do_what) {
279	if ((do_what & do_key) && pvt->curkey_data) {
280		free(pvt->curkey_data);
281		pvt->curkey_data = NULL;
282	}
283	if ((do_what & do_val) && pvt->curval_data) {
284		free(pvt->curval_data);
285		pvt->curval_data = NULL;
286	}
287}
288
289#endif /* WANT_IRS_PW && WANT_IRS_NIS */
290/*! \file */
291