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