xref: /netbsd/external/bsd/libbind/dist/irs/nis_pw.c (revision 6550d01e)
1 /*	$NetBSD: nis_pw.c,v 1.1.1.1 2009/04/12 15:33:40 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)
21 static 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)
29 static 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 
62 struct 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 
73 enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
74 
75 static /*const*/ char passwd_byname[] =	"passwd.byname";
76 static /*const*/ char passwd_byuid[] =	"passwd.byuid";
77 
78 /* Forward */
79 
80 static void			pw_close(struct irs_pw *);
81 static struct passwd *		pw_next(struct irs_pw *);
82 static struct passwd *		pw_byname(struct irs_pw *, const char *);
83 static struct passwd *		pw_byuid(struct irs_pw *, uid_t);
84 static void			pw_rewind(struct irs_pw *);
85 static void			pw_minimize(struct irs_pw *);
86 
87 static struct passwd *		makepasswdent(struct irs_pw *);
88 static void			nisfree(struct pvt *, enum do_what);
89 
90 /* Public */
91 
92 struct irs_pw *
93 irs_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 
124 static void
125 pw_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 
135 static struct passwd *
136 pw_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 
170 static struct passwd *
171 pw_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 
187 static struct passwd *
188 pw_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 
204 static void
205 pw_rewind(struct irs_pw *this) {
206 	struct pvt *pvt = (struct pvt *)this->private;
207 
208 	pvt->needrewind = 1;
209 }
210 
211 static void
212 pw_minimize(struct irs_pw *this) {
213 	UNUSED(this);
214 	/* NOOP */
215 }
216 
217 /* Private */
218 
219 static struct passwd *
220 makepasswdent(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 
277 static void
278 nisfree(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