xref: /netbsd-src/external/bsd/libbind/dist/irs/nis_gr.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
1 /*	$NetBSD: nis_gr.c,v 1.1.1.2 2012/09/09 16:07:51 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1989, 1993, 1995
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 /*
37  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
38  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
39  *
40  * Permission to use, copy, modify, and distribute this software for any
41  * purpose with or without fee is hereby granted, provided that the above
42  * copyright notice and this permission notice appear in all copies.
43  *
44  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
45  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
46  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
47  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
49  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
50  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51  */
52 
53 #if defined(LIBC_SCCS) && !defined(lint)
54 static const char rcsid[] = "Id: nis_gr.c,v 1.4 2005/04/27 04:56:32 sra Exp ";
55 /* from getgrent.c 8.2 (Berkeley) 3/21/94"; */
56 /* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $	*/
57 #endif /* LIBC_SCCS and not lint */
58 
59 /* Imports */
60 
61 #include "port_before.h"
62 
63 #if !defined(WANT_IRS_GR) || !defined(WANT_IRS_NIS)
64 static int __bind_irs_gr_unneeded;
65 #else
66 
67 #include <sys/param.h>
68 #include <sys/types.h>
69 #include <netinet/in.h>
70 #include <arpa/nameser.h>
71 #include <resolv.h>
72 #include <isc/memcluster.h>
73 
74 #include <rpc/rpc.h>
75 #include <rpc/xdr.h>
76 #include <rpcsvc/yp_prot.h>
77 #include <rpcsvc/ypclnt.h>
78 
79 #include <errno.h>
80 #include <grp.h>
81 #include <stdio.h>
82 #include <stdlib.h>
83 #include <string.h>
84 #include <unistd.h>
85 
86 #include <isc/memcluster.h>
87 
88 #include <irs.h>
89 
90 #include "port_after.h"
91 
92 #include "irs_p.h"
93 #include "nis_p.h"
94 
95 /* Definitions */
96 
97 struct pvt {
98 	int		needrewind;
99 	char *		nis_domain;
100 	char *		curkey_data;
101 	int		curkey_len;
102 	char *		curval_data;
103 	int		curval_len;
104 	/*%<
105 	 * Need space to store the entries read from the group file.
106 	 * The members list also needs space per member, and the
107 	 * strings making up the user names must be allocated
108 	 * somewhere.  Rather than doing lots of small allocations,
109 	 * we keep one buffer and resize it as needed.
110 	 */
111 	struct group	group;
112 	size_t		nmemb;		/*%< Malloc'd max index of gr_mem[]. */
113 	char *		membuf;
114 	size_t		membufsize;
115 };
116 
117 enum do_what { do_none = 0x0, do_key = 0x1, do_val = 0x2, do_all = 0x3 };
118 
119 static /*const*/ char group_bygid[] =	"group.bygid";
120 static /*const*/ char group_byname[] =	"group.byname";
121 
122 /* Forward */
123 
124 static void		gr_close(struct irs_gr *);
125 static struct group *	gr_next(struct irs_gr *);
126 static struct group *	gr_byname(struct irs_gr *, const char *);
127 static struct group *	gr_bygid(struct irs_gr *, gid_t);
128 static void		gr_rewind(struct irs_gr *);
129 static void		gr_minimize(struct irs_gr *);
130 
131 static struct group *	makegroupent(struct irs_gr *);
132 static void		nisfree(struct pvt *, enum do_what);
133 
134 /* Public */
135 
136 struct irs_gr *
irs_nis_gr(struct irs_acc * this)137 irs_nis_gr(struct irs_acc *this) {
138 	struct irs_gr *gr;
139 	struct pvt *pvt;
140 
141 	if (!(gr = memget(sizeof *gr))) {
142 		errno = ENOMEM;
143 		return (NULL);
144 	}
145 	memset(gr, 0x5e, sizeof *gr);
146 	if (!(pvt = memget(sizeof *pvt))) {
147 		memput(gr, sizeof *gr);
148 		errno = ENOMEM;
149 		return (NULL);
150 	}
151 	memset(pvt, 0, sizeof *pvt);
152 	pvt->needrewind = 1;
153 	pvt->nis_domain = ((struct nis_p *)this->private)->domain;
154 	gr->private = pvt;
155 	gr->close = gr_close;
156 	gr->next = gr_next;
157 	gr->byname = gr_byname;
158 	gr->bygid = gr_bygid;
159 	gr->rewind = gr_rewind;
160 	gr->list = make_group_list;
161 	gr->minimize = gr_minimize;
162 	gr->res_get = NULL;
163 	gr->res_set = NULL;
164 	return (gr);
165 }
166 
167 /* Methods */
168 
169 static void
gr_close(struct irs_gr * this)170 gr_close(struct irs_gr *this) {
171 	struct pvt *pvt = (struct pvt *)this->private;
172 
173 	if (pvt->group.gr_mem)
174 		free(pvt->group.gr_mem);
175 	if (pvt->membuf)
176 		free(pvt->membuf);
177 	memput(pvt, sizeof *pvt);
178 	memput(this, sizeof *this);
179 }
180 
181 static struct group *
gr_next(struct irs_gr * this)182 gr_next(struct irs_gr *this) {
183 	struct pvt *pvt = (struct pvt *)this->private;
184 	struct group *rval;
185 	int r;
186 
187 	do {
188 		if (pvt->needrewind) {
189 			nisfree(pvt, do_all);
190 			r = yp_first(pvt->nis_domain, group_byname,
191 				     &pvt->curkey_data, &pvt->curkey_len,
192 				     &pvt->curval_data, &pvt->curval_len);
193 			pvt->needrewind = 0;
194 		} else {
195 			char *newkey_data;
196 			int newkey_len;
197 
198 			nisfree(pvt, do_val);
199 			r = yp_next(pvt->nis_domain, group_byname,
200 				    pvt->curkey_data, pvt->curkey_len,
201 				    &newkey_data, &newkey_len,
202 				    &pvt->curval_data, &pvt->curval_len);
203 			nisfree(pvt, do_key);
204 			pvt->curkey_data = newkey_data;
205 			pvt->curkey_len = newkey_len;
206 		}
207 		if (r != 0) {
208 			errno = ENOENT;
209 			return (NULL);
210 		}
211 		rval = makegroupent(this);
212 	} while (rval == NULL);
213 	return (rval);
214 }
215 
216 static struct group *
gr_byname(struct irs_gr * this,const char * name)217 gr_byname(struct irs_gr *this, const char *name) {
218 	struct pvt *pvt = (struct pvt *)this->private;
219 	int r;
220 
221 	nisfree(pvt, do_val);
222 	r = yp_match(pvt->nis_domain, group_byname, name, strlen(name),
223 		     &pvt->curval_data, &pvt->curval_len);
224 	if (r != 0) {
225 		errno = ENOENT;
226 		return (NULL);
227 	}
228 	return (makegroupent(this));
229 }
230 
231 static struct group *
gr_bygid(struct irs_gr * this,gid_t gid)232 gr_bygid(struct irs_gr *this, gid_t gid) {
233 	struct pvt *pvt = (struct pvt *)this->private;
234 	char tmp[sizeof "4294967295"];
235 	int r;
236 
237 	nisfree(pvt, do_val);
238 	(void) sprintf(tmp, "%u", (unsigned int)gid);
239 	r = yp_match(pvt->nis_domain, group_bygid, tmp, strlen(tmp),
240 		     &pvt->curval_data, &pvt->curval_len);
241 	if (r != 0) {
242 		errno = ENOENT;
243 		return (NULL);
244 	}
245 	return (makegroupent(this));
246 }
247 
248 static void
gr_rewind(struct irs_gr * this)249 gr_rewind(struct irs_gr *this) {
250 	struct pvt *pvt = (struct pvt *)this->private;
251 
252 	pvt->needrewind = 1;
253 }
254 
255 static void
gr_minimize(struct irs_gr * this)256 gr_minimize(struct irs_gr *this) {
257 	UNUSED(this);
258 	/* NOOP */
259 }
260 
261 /* Private */
262 
263 static struct group *
makegroupent(struct irs_gr * this)264 makegroupent(struct irs_gr *this) {
265 	struct pvt *pvt = (struct pvt *)this->private;
266 	unsigned int num_members = 0;
267 	char *cp, **new;
268 	u_long t;
269 
270 	if (pvt->group.gr_mem) {
271 		free(pvt->group.gr_mem);
272 		pvt->group.gr_mem = NULL;
273 		pvt->nmemb = 0;
274 	}
275 	if (pvt->membuf)
276 		free(pvt->membuf);
277 	pvt->membuf = pvt->curval_data;
278 	pvt->curval_data = NULL;
279 
280 	cp = pvt->membuf;
281 	pvt->group.gr_name = cp;
282 	if (!(cp = strchr(cp, ':')))
283 		goto cleanup;
284 	*cp++ = '\0';
285 
286 	pvt->group.gr_passwd = cp;
287 	if (!(cp = strchr(cp, ':')))
288 		goto cleanup;
289 	*cp++ = '\0';
290 
291 	errno = 0;
292 	t = strtoul(cp, NULL, 10);
293 	if (errno == ERANGE)
294 		goto cleanup;
295 	pvt->group.gr_gid = (gid_t) t;
296 	if (!(cp = strchr(cp, ':')))
297 		goto cleanup;
298 	cp++;
299 
300         if (*cp && cp[strlen(cp)-1] == '\n')
301           cp[strlen(cp)-1] = '\0';
302 
303 	/*
304 	 * Parse the members out.
305 	 */
306 	while (*cp) {
307 		if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) {
308 			pvt->nmemb += 10;
309 			new = realloc(pvt->group.gr_mem,
310 				      pvt->nmemb * sizeof(char *));
311 			if (new == NULL)
312 				goto cleanup;
313 			pvt->group.gr_mem = new;
314 		}
315 		pvt->group.gr_mem[num_members++] = cp;
316 		if (!(cp = strchr(cp, ',')))
317 			break;
318 		*cp++ = '\0';
319 	}
320 	if (pvt->group.gr_mem == NULL) {
321 		pvt->group.gr_mem = malloc(sizeof(char*));
322 		if (!pvt->group.gr_mem)
323 			goto cleanup;
324 		pvt->nmemb = 1;
325 	}
326 	pvt->group.gr_mem[num_members] = NULL;
327 
328 	return (&pvt->group);
329 
330  cleanup:
331 	if (pvt->group.gr_mem) {
332 		free(pvt->group.gr_mem);
333 		pvt->group.gr_mem = NULL;
334 		pvt->nmemb = 0;
335 	}
336 	if (pvt->membuf) {
337 		free(pvt->membuf);
338 		pvt->membuf = NULL;
339 	}
340 	return (NULL);
341 }
342 
343 static void
nisfree(struct pvt * pvt,enum do_what do_what)344 nisfree(struct pvt *pvt, enum do_what do_what) {
345 	if ((do_what & do_key) && pvt->curkey_data) {
346 		free(pvt->curkey_data);
347 		pvt->curkey_data = NULL;
348 	}
349 	if ((do_what & do_val) && pvt->curval_data) {
350 		free(pvt->curval_data);
351 		pvt->curval_data = NULL;
352 	}
353 }
354 
355 #endif /* WANT_IRS_GR && WANT_IRS_NIS */
356 /*! \file */
357