Libinfo-78.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_user.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * user information (passwd) lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28 #include <stdlib.h>
29 #include <mach/mach.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <rpc/types.h>
33 #include <rpc/xdr.h>
34 #include <pwd.h>
35 #include <netinet/in.h>
36
37 #include "_lu_types.h"
38 #include "lookup.h"
39 #include "lu_utils.h"
40 #include "lu_overrides.h"
41
42 static lookup_state pw_state = LOOKUP_CACHE;
43 static struct passwd global_pw;
44 static int global_free = 1;
45 static char *pw_data = NULL;
46 static unsigned pw_datalen;
47 static int pw_nentries;
48 static int pw_start = 1;
49 static XDR pw_xdr;
50
51 static void
52 freeold(void)
53 {
54 if (global_free == 1) return;
55
56 free(global_pw.pw_name);
57 free(global_pw.pw_passwd);
58 free(global_pw.pw_class);
59 free(global_pw.pw_gecos);
60 free(global_pw.pw_dir);
61 free(global_pw.pw_shell);
62
63 global_free = 1;
64 }
65
66 static void
67 convert_pw(_lu_passwd *lu_pw)
68 {
69 freeold();
70
71 global_pw.pw_name = strdup(lu_pw->pw_name);
72 global_pw.pw_passwd = strdup(lu_pw->pw_passwd);
73 global_pw.pw_uid = lu_pw->pw_uid;
74 global_pw.pw_gid = lu_pw->pw_gid;
75 global_pw.pw_change = lu_pw->pw_change;
76 global_pw.pw_class = strdup(lu_pw->pw_class);
77 global_pw.pw_gecos = strdup(lu_pw->pw_gecos);
78 global_pw.pw_dir = strdup(lu_pw->pw_dir);
79 global_pw.pw_shell = strdup(lu_pw->pw_shell);
80 global_pw.pw_expire = lu_pw->pw_expire;
81
82 global_free = 0;
83 }
84
85 static struct passwd *
86 lu_getpwuid(int uid)
87 {
88 unsigned datalen;
89 _lu_passwd_ptr lu_pw;
90 XDR xdr;
91 static int proc = -1;
92 unit lookup_buf[MAX_INLINE_UNITS];
93
94 if (proc < 0)
95 {
96 if (_lookup_link(_lu_port, "getpwuid_A", &proc) != KERN_SUCCESS)
97 {
98 return (NULL);
99 }
100 }
101
102 uid = htonl(uid);
103 datalen = MAX_INLINE_UNITS;
104 if (_lookup_one(_lu_port, proc, (unit *)&uid, 1, lookup_buf, &datalen)
105 != KERN_SUCCESS)
106 {
107 return (NULL);
108 }
109
110 datalen *= BYTES_PER_XDR_UNIT;
111 xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
112 lu_pw = NULL;
113 if (!xdr__lu_passwd_ptr(&xdr, &lu_pw) || (lu_pw == NULL))
114 {
115 xdr_destroy(&xdr);
116 return (NULL);
117 }
118
119 xdr_destroy(&xdr);
120
121 convert_pw(lu_pw);
122 xdr_free(xdr__lu_passwd_ptr, &lu_pw);
123 return (&global_pw);
124 }
125
126 static struct passwd *
127 lu_getpwnam(const char *name)
128 {
129 unsigned datalen;
130 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
131 XDR outxdr;
132 XDR inxdr;
133 _lu_passwd_ptr lu_pw;
134 static int proc = -1;
135 unit lookup_buf[MAX_INLINE_UNITS];
136
137 if (proc < 0)
138 {
139 if (_lookup_link(_lu_port, "getpwnam_A", &proc) != KERN_SUCCESS)
140 {
141 return (NULL);
142 }
143 }
144
145 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
146 if (!xdr__lu_string(&outxdr, &name))
147 {
148 xdr_destroy(&outxdr);
149 return (NULL);
150 }
151
152 datalen = MAX_INLINE_UNITS;
153 if (_lookup_one(_lu_port, proc, (unit *)namebuf,
154 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
155 != KERN_SUCCESS)
156 {
157 xdr_destroy(&outxdr);
158 return (NULL);
159 }
160
161 xdr_destroy(&outxdr);
162
163 datalen *= BYTES_PER_XDR_UNIT;
164 xdrmem_create(&inxdr, lookup_buf, datalen,
165 XDR_DECODE);
166 lu_pw = NULL;
167 if (!xdr__lu_passwd_ptr(&inxdr, &lu_pw) || (lu_pw == NULL))
168 {
169 xdr_destroy(&inxdr);
170 return (NULL);
171 }
172
173 xdr_destroy(&inxdr);
174
175 convert_pw(lu_pw);
176 xdr_free(xdr__lu_passwd_ptr, &lu_pw);
177 return (&global_pw);
178 }
179
180 #ifdef notdef
181 static int
182 lu_putpwpasswd(char *login, char *old_passwd, char *new_passwd)
183 {
184 unsigned datalen;
185 int changed;
186 XDR xdr;
187 static int proc = -1;
188 char output_buf[3 * (_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT)];
189 unit lookup_buf[MAX_INLINE_UNITS];
190 XDR outxdr;
191
192 if (proc < 0)
193 {
194 if (_lookup_link(_lu_port, "putpwpasswd", &proc) != KERN_SUCCESS)
195 {
196 return (0);
197 }
198 }
199
200 xdrmem_create(&outxdr, output_buf, sizeof(output_buf), XDR_ENCODE);
201 if (!xdr__lu_string(&outxdr, &login) ||
202 !xdr__lu_string(&outxdr, &old_passwd) ||
203 !xdr__lu_string(&outxdr, &new_passwd))
204 {
205 xdr_destroy(&outxdr);
206 return (0);
207 }
208
209 datalen = MAX_INLINE_UNITS;
210 if (_lookup_one(_lu_port, proc, output_buf,
211 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
212 != KERN_SUCCESS)
213 {
214 xdr_destroy(&outxdr);
215 return (0);
216 }
217
218 xdr_destroy(&outxdr);
219
220 datalen *= BYTES_PER_XDR_UNIT;
221 xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
222 if (!xdr_int(&xdr, &changed))
223 {
224 xdr_destroy(&xdr);
225 return (0);
226 }
227
228 xdr_destroy(&xdr);
229
230 return (changed);
231 }
232 #endif
233
234 static void
235 lu_endpwent(void)
236 {
237 pw_nentries = 0;
238 if (pw_data != NULL)
239 {
240 freeold();
241 vm_deallocate(mach_task_self(), (vm_address_t)pw_data, pw_datalen);
242 pw_data = NULL;
243 }
244 }
245
246 static int
247 lu_setpwent(void)
248 {
249 lu_endpwent();
250 pw_start = 1;
251 return (1);
252 }
253
254 static struct passwd *
255 lu_getpwent()
256 {
257 static int proc = -1;
258 _lu_passwd lu_pw;
259
260 if (pw_start == 1)
261 {
262 pw_start = 0;
263
264 if (proc < 0)
265 {
266 if (_lookup_link(_lu_port, "getpwent_A", &proc) != KERN_SUCCESS)
267 {
268 lu_endpwent();
269 return (NULL);
270 }
271 }
272
273 if (_lookup_all(_lu_port, proc, NULL, 0, &pw_data, &pw_datalen)
274 != KERN_SUCCESS)
275 {
276 lu_endpwent();
277 return (NULL);
278 }
279
280 #ifdef NOTDEF
281 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
282 pw_datalen *= BYTES_PER_XDR_UNIT;
283 #endif
284
285 xdrmem_create(&pw_xdr, pw_data, pw_datalen,
286 XDR_DECODE);
287 if (!xdr_int(&pw_xdr, &pw_nentries))
288 {
289 xdr_destroy(&pw_xdr);
290 lu_endpwent();
291 return (NULL);
292 }
293 }
294
295 if (pw_nentries == 0)
296 {
297 xdr_destroy(&pw_xdr);
298 lu_endpwent();
299 return (NULL);
300 }
301
302 bzero(&lu_pw, sizeof(lu_pw));
303 if (!xdr__lu_passwd(&pw_xdr, &lu_pw))
304 {
305 xdr_destroy(&pw_xdr);
306 lu_endpwent();
307 return (NULL);
308 }
309
310 pw_nentries--;
311 convert_pw(&lu_pw);
312 xdr_free(xdr__lu_passwd, &lu_pw);
313 return (&global_pw);
314 }
315
316 static char *loginName = NULL;
317 static uid_t loginUid = -1;
318
319 extern char *getlogin(void);
320
321 struct passwd *
322 getpwuid(uid_t uid)
323 {
324 if (uid != 0) {
325 if (loginName == NULL) {
326 char *l = getlogin();
327 if (l != NULL) {
328 struct passwd *p = getpwnam(l);
329 if (p != NULL) {
330 loginUid = p->pw_uid;
331 loginName = l;
332 }
333 }
334 }
335 if (uid == loginUid) {
336 LOOKUP1(lu_getpwnam, _old_getpwnam, loginName, struct passwd);
337 }
338 }
339 LOOKUP1(lu_getpwuid, _old_getpwuid, uid, struct passwd);
340 }
341
342 struct passwd *
343 getpwnam(const char *name)
344 {
345 LOOKUP1(lu_getpwnam, _old_getpwnam, name, struct passwd);
346 }
347
348 #ifdef notdef
349 /*
350 * putpwpasswd() is not supported with anything other than netinfo
351 * right now.
352 * old_passwd is clear text.
353 * new_passwd is encrypted.
354 */
355 #define _old_passwd(name, oldpass, newpass) 0
356 int
357 putpwpasswd(char *login, char *old_passwd, char *new_passwd)
358 {
359 if (_lu_running()) return (lu_putpwpasswd(login, old_passwd, new_passwd));
360 return (old_passwd(login, old_passwd, new_passwd));
361 }
362 #endif
363
364 struct passwd *
365 getpwent(void)
366 {
367 GETENT(lu_getpwent, _old_getpwent, &pw_state, struct passwd);
368 }
369
370 int
371 setpwent(void)
372 {
373 INTSETSTATEVOID(lu_setpwent, _old_setpwent, &pw_state);
374 }
375
376 void
377 endpwent(void)
378 {
379 UNSETSTATE(lu_endpwent, _old_endpwent, &pw_state);
380 }