1/*
2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (c) 1996 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_pw.c,v 1.4 2005/04/27 04:56:29 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_pw_unneeded;
28#else
29
30#include <syslog.h>
31#include <sys/param.h>
32
33#include <db.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <limits.h>
37#include <pwd.h>
38#include <stdlib.h>
39#include <string.h>
40#include <syslog.h>
41#include <utmp.h>
42#include <unistd.h>
43
44#include <irs.h>
45#include <irp.h>
46#include <isc/memcluster.h>
47#include <isc/irpmarshall.h>
48
49#include "port_after.h"
50
51#include "irs_p.h"
52#include "irp_p.h"
53
54
55/* Types */
56
57struct	pvt {
58	struct irp_p   *girpdata; /*%< global IRP data */
59	int		warned;
60	struct passwd	passwd;		/*%< password structure */
61};
62
63/* Forward */
64
65static void			pw_close(struct irs_pw *);
66static struct passwd *		pw_next(struct irs_pw *);
67static struct passwd *		pw_byname(struct irs_pw *, const char *);
68static struct passwd *		pw_byuid(struct irs_pw *, uid_t);
69static void			pw_rewind(struct irs_pw *);
70static void			pw_minimize(struct irs_pw *);
71
72static void			free_passwd(struct passwd *pw);
73
74/* Public */
75struct irs_pw *
76irs_irp_pw(struct irs_acc *this) {
77	struct irs_pw *pw;
78	struct pvt *pvt;
79
80	if (!(pw = memget(sizeof *pw))) {
81		errno = ENOMEM;
82		return (NULL);
83	}
84	memset(pw, 0, sizeof *pw);
85
86	if (!(pvt = memget(sizeof *pvt))) {
87		memput(pw, sizeof *pw);
88		errno = ENOMEM;
89		return (NULL);
90	}
91	memset(pvt, 0, sizeof *pvt);
92	pvt->girpdata = this->private;
93
94	pw->private = pvt;
95	pw->close = pw_close;
96	pw->next = pw_next;
97	pw->byname = pw_byname;
98	pw->byuid = pw_byuid;
99	pw->rewind = pw_rewind;
100	pw->minimize = pw_minimize;
101
102	return (pw);
103}
104
105/* Methods */
106
107/*%
108 * void pw_close(struct irs_pw *this)
109 *
110 */
111
112static void
113pw_close(struct irs_pw *this) {
114	struct pvt *pvt = (struct pvt *)this->private;
115
116	pw_minimize(this);
117
118	free_passwd(&pvt->passwd);
119
120	memput(pvt, sizeof *pvt);
121	memput(this, sizeof *this);
122}
123
124/*%
125 * struct passwd * pw_next(struct irs_pw *this)
126 *
127 */
128
129static struct passwd *
130pw_next(struct irs_pw *this) {
131	struct pvt *pvt = (struct pvt *)this->private;
132	struct passwd *pw = &pvt->passwd;
133	char *body;
134	size_t bodylen;
135	int code;
136	char text[256];
137
138	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
139		return (NULL);
140	}
141
142	if (irs_irp_send_command(pvt->girpdata, "getpwent") != 0) {
143		return (NULL);
144	}
145
146	if (irs_irp_get_full_response(pvt->girpdata, &code,
147				      text, sizeof text,
148				      &body, &bodylen) != 0) {
149		return (NULL);
150	}
151
152	if (code == IRPD_GETUSER_OK) {
153		free_passwd(pw);
154		if (irp_unmarshall_pw(pw, body) != 0) {
155			pw = NULL;
156		}
157	} else {
158		pw = NULL;
159	}
160
161	if (body != NULL) {
162		memput(body, bodylen);
163	}
164
165	return (pw);
166}
167
168/*%
169 * struct passwd * pw_byname(struct irs_pw *this, const char *name)
170 *
171 */
172
173static struct passwd *
174pw_byname(struct irs_pw *this, const char *name) {
175	struct pvt *pvt = (struct pvt *)this->private;
176	struct passwd *pw = &pvt->passwd;
177	char *body = NULL;
178	char text[256];
179	size_t bodylen;
180	int code;
181
182	if (pw->pw_name != NULL && strcmp(name, pw->pw_name) == 0) {
183		return (pw);
184	}
185
186	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
187		return (NULL);
188	}
189
190	if (irs_irp_send_command(pvt->girpdata, "getpwnam %s", name) != 0) {
191		return (NULL);
192	}
193
194	if (irs_irp_get_full_response(pvt->girpdata, &code,
195				      text, sizeof text,
196				      &body, &bodylen) != 0) {
197		return (NULL);
198	}
199
200	if (code == IRPD_GETUSER_OK) {
201		free_passwd(pw);
202		if (irp_unmarshall_pw(pw, body) != 0) {
203			pw = NULL;
204		}
205	} else {
206		pw = NULL;
207	}
208
209	if (body != NULL) {
210		memput(body, bodylen);
211	}
212
213	return (pw);
214}
215
216/*%
217 * struct passwd * pw_byuid(struct irs_pw *this, uid_t uid)
218 *
219 */
220
221static struct passwd *
222pw_byuid(struct irs_pw *this, uid_t uid) {
223	struct pvt *pvt = (struct pvt *)this->private;
224	char *body;
225	char text[256];
226	size_t bodylen;
227	int code;
228	struct passwd *pw = &pvt->passwd;
229
230	if (pw->pw_name != NULL && pw->pw_uid == uid) {
231		return (pw);
232	}
233
234	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
235		return (NULL);
236	}
237
238	if (irs_irp_send_command(pvt->girpdata, "getpwuid %d", uid) != 0) {
239		return (NULL);
240	}
241
242	if (irs_irp_get_full_response(pvt->girpdata, &code,
243				      text, sizeof text,
244				      &body, &bodylen) != 0) {
245		return (NULL);
246	}
247
248	if (code == IRPD_GETUSER_OK) {
249		free_passwd(pw);
250		if (irp_unmarshall_pw(pw, body) != 0) {
251			pw = NULL;
252		}
253	} else {
254		pw = NULL;
255	}
256
257	if (body != NULL) {
258		memput(body, bodylen);
259	}
260
261	return (pw);
262}
263
264/*%
265 * void pw_rewind(struct irs_pw *this)
266 *
267 */
268
269static void
270pw_rewind(struct irs_pw *this) {
271	struct pvt *pvt = (struct pvt *)this->private;
272	char text[256];
273	int code;
274
275	if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) {
276		return;
277	}
278
279	if (irs_irp_send_command(pvt->girpdata, "setpwent") != 0) {
280		return;
281	}
282
283	code = irs_irp_read_response(pvt->girpdata, text, sizeof text);
284	if (code != IRPD_GETUSER_SETOK) {
285		if (irp_log_errors) {
286			syslog(LOG_WARNING, "setpwent failed: %s", text);
287		}
288	}
289
290	return;
291}
292
293/*%
294 * void pw_minimize(struct irs_pw *this)
295 *
296 */
297
298static void
299pw_minimize(struct irs_pw *this) {
300	struct pvt *pvt = (struct pvt *)this->private;
301
302	irs_irp_disconnect(pvt->girpdata);
303}
304
305
306/* Private. */
307
308/*%
309 *	Deallocate all the memory irp_unmarshall_pw allocated.
310 *
311 */
312
313static void
314free_passwd(struct passwd *pw) {
315	if (pw == NULL)
316		return;
317
318	if (pw->pw_name != NULL)
319		free(pw->pw_name);
320
321	if (pw->pw_passwd != NULL)
322		free(pw->pw_passwd);
323
324#ifdef HAVE_PW_CLASS
325	if (pw->pw_class != NULL)
326		free(pw->pw_class);
327#endif
328
329	if (pw->pw_gecos != NULL)
330		free(pw->pw_gecos);
331
332	if (pw->pw_dir != NULL)
333		free(pw->pw_dir);
334
335	if (pw->pw_shell != NULL)
336		free(pw->pw_shell);
337}
338
339#endif /* WANT_IRS_PW */
340/*! \file */
341