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