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