1/*
2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright(c) 1996, 1998 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)
19static const char rcsid[] = "$Id: irp_gr.c,v 1.4 2005/04/27 04:56:27 sra Exp $";
20#endif /* LIBC_SCCS and not lint */
21
22/* extern */
23
24#include "port_before.h"
25
26#ifndef WANT_IRS_PW
27static int __bind_irs_gr_unneeded;
28#else
29
30#include <syslog.h>
31#include <sys/param.h>
32#include <sys/types.h>
33
34#include <errno.h>
35#include <fcntl.h>
36#include <grp.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41#include <syslog.h>
42
43#include <irs.h>
44#include <irp.h>
45#include <isc/memcluster.h>
46#include <isc/irpmarshall.h>
47
48#include "irs_p.h"
49#include "lcl_p.h"
50#include "irp_p.h"
51
52#include "port_after.h"
53
54
55/* Types. */
56
57/*! \file
58 * \brief
59 * Module for the getnetgrent(3) family to use when connected to a
60 * remote irp daemon.
61 * \brief
62 * See irpd.c for justification of caching done here.
63 *
64 */
65
66struct pvt {
67	struct irp_p   *girpdata;	/*%< global IRP data */
68	int		warned;
69	struct group	group;
70};
71
72/* Forward. */
73
74static void		gr_close(struct irs_gr *);
75static struct group *	gr_next(struct irs_gr *);
76static struct group *	gr_byname(struct irs_gr *, const char *);
77static struct group *	gr_bygid(struct irs_gr *, gid_t);
78static void		gr_rewind(struct irs_gr *);
79static void		gr_minimize(struct irs_gr *);
80
81/* Private */
82static void		free_group(struct group *gr);
83
84
85/* Public. */
86
87/*%
88 *	Initialize the group sub-module.
89 *
90 */
91
92struct irs_gr *
93irs_irp_gr(struct irs_acc *this) {
94	struct irs_gr *gr;
95	struct pvt *pvt;
96
97	if (!(gr = memget(sizeof *gr))) {
98		errno = ENOMEM;
99		return (NULL);
100	}
101	memset(gr, 0x0, sizeof *gr);
102
103	if (!(pvt = memget(sizeof *pvt))) {
104		memput(gr, sizeof *gr);
105		errno = ENOMEM;
106		return (NULL);
107	}
108	memset(pvt, 0x0, sizeof *pvt);
109	pvt->girpdata = this->private;
110
111	gr->private = pvt;
112	gr->close = gr_close;
113	gr->next = gr_next;
114	gr->byname = gr_byname;
115	gr->bygid = gr_bygid;
116	gr->rewind = gr_rewind;
117	gr->list = make_group_list;
118	gr->minimize = gr_minimize;
119	return (gr);
120}
121
122/* Methods. */
123
124/*%
125 *	Close the sub-module.
126 *
127 */
128
129static void
130gr_close(struct irs_gr *this) {
131	struct pvt *pvt = (struct pvt *)this->private;
132
133	gr_minimize(this);
134
135	memput(pvt, sizeof *pvt);
136	memput(this, sizeof *this);
137}
138
139/*%
140 *	Gets the next group out of the cached data and returns it.
141 *
142 */
143
144static struct group *
145gr_next(struct irs_gr *this) {
146	struct pvt *pvt = (struct pvt *)this->private;
147	struct group *gr = &pvt->group;
148	char *body;
149	size_t bodylen;
150	int code;
151	char text[256];
152
153	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
154		return (NULL);
155	}
156
157	if (irs_irp_send_command(pvt->girpdata, "getgrent") != 0) {
158		return (NULL);
159	}
160
161	if (irs_irp_get_full_response(pvt->girpdata, &code,
162				      text, sizeof text,
163				      &body, &bodylen) != 0) {
164		if (irp_log_errors) {
165			syslog(LOG_WARNING, "getgrent failed: %s", text);
166		}
167		return (NULL);
168	}
169
170	if (code == IRPD_GETGROUP_OK) {
171		free_group(gr);
172		if (irp_unmarshall_gr(gr, body) != 0) {
173			gr = NULL;
174		}
175	} else {
176		gr = NULL;
177	}
178
179	if (body != NULL) {
180		memput(body, bodylen);
181	}
182
183	return (gr);
184}
185
186/*%
187 *	Gets a group by name from irpd and returns it.
188 *
189 */
190
191static struct group *
192gr_byname(struct irs_gr *this, const char *name) {
193	struct pvt *pvt = (struct pvt *)this->private;
194	struct group *gr = &pvt->group;
195	char *body;
196	size_t bodylen;
197	int code;
198	char text[256];
199
200
201	if (gr->gr_name != NULL && strcmp(name, gr->gr_name) == 0) {
202		return (gr);
203	}
204
205	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
206		return (NULL);
207	}
208
209	if (irs_irp_send_command(pvt->girpdata, "getgrnam %s", name) != 0)
210		return (NULL);
211
212	if (irs_irp_get_full_response(pvt->girpdata, &code,
213				      text, sizeof text,
214				      &body, &bodylen) != 0) {
215		return (NULL);
216	}
217
218	if (code == IRPD_GETGROUP_OK) {
219		free_group(gr);
220		if (irp_unmarshall_gr(gr, body) != 0) {
221			gr = NULL;
222		}
223	} else {
224		gr = NULL;
225	}
226
227	if (body != NULL) {
228		memput(body, bodylen);
229	}
230
231	return (gr);
232}
233
234/*%
235 *	Gets a group by gid from irpd and returns it.
236 *
237 */
238
239static struct group *
240gr_bygid(struct irs_gr *this, gid_t gid) {
241	struct pvt *pvt = (struct pvt *)this->private;
242	struct group *gr = &pvt->group;
243	char *body;
244	size_t bodylen;
245	int code;
246	char text[256];
247
248	if (gr->gr_name != NULL && (gid_t)gr->gr_gid == gid) {
249		return (gr);
250	}
251
252	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
253		return (NULL);
254	}
255
256	if (irs_irp_send_command(pvt->girpdata, "getgrgid %d", gid) != 0)
257		return (NULL);
258
259	if (irs_irp_get_full_response(pvt->girpdata, &code,
260				      text, sizeof text,
261				      &body, &bodylen) != 0) {
262		return (NULL);
263	}
264
265	if (code == IRPD_GETGROUP_OK) {
266		free_group(gr);
267		if (irp_unmarshall_gr(gr, body) != 0) {
268			gr = NULL;
269		}
270	} else {
271		gr = NULL;
272	}
273
274	if (body != NULL) {
275		memput(body, bodylen);
276	}
277
278	return (gr);
279}
280
281/*%
282 * void gr_rewind(struct irs_gr *this)
283 *
284 */
285
286static void
287gr_rewind(struct irs_gr *this) {
288	struct pvt *pvt = (struct pvt *)this->private;
289	char text[256];
290	int code;
291
292	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
293		return;
294	}
295
296	if (irs_irp_send_command(pvt->girpdata, "setgrent") != 0) {
297		return;
298	}
299
300	code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
301	if (code != IRPD_GETGROUP_SETOK) {
302		if (irp_log_errors) {
303			syslog(LOG_WARNING, "setgrent failed: %s", text);
304		}
305	}
306
307	return;
308}
309
310/*%
311 *	Frees up cached data and disconnects(if necessary) from the remote.
312 *
313 */
314
315static void
316gr_minimize(struct irs_gr *this) {
317	struct pvt *pvt = (struct pvt *)this->private;
318
319	free_group(&pvt->group);
320	irs_irp_disconnect(pvt->girpdata);
321}
322
323/* Private. */
324
325/*%
326 * static void free_group(struct group *gr);
327 *
328 *	Deallocate all the memory irp_unmarshall_gr allocated.
329 *
330 */
331
332static void
333free_group(struct group *gr) {
334	char **p;
335
336	if (gr == NULL)
337		return;
338
339	if (gr->gr_name != NULL)
340		free(gr->gr_name);
341
342	if (gr->gr_passwd != NULL)
343		free(gr->gr_passwd);
344
345	for (p = gr->gr_mem ; p != NULL && *p != NULL ; p++)
346		free(*p);
347
348	if (gr->gr_mem)
349		free(gr->gr_mem);
350
351	if (p != NULL)
352		free(p);
353}
354
355
356#endif /* WANT_IRS_GR */
357/*! \file */
358