2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
22 * @APPLE_LICENSE_HEADER_END@
25 * user information (passwd) lookup
26 * Copyright (C) 1989 by NeXT, Inc.
29 #include <mach/mach.h>
32 #include <rpc/types.h>
35 #include <netinet/in.h>
39 #include "_lu_types.h"
42 #include "lu_overrides.h"
44 static pthread_mutex_t _user_lock
= PTHREAD_MUTEX_INITIALIZER
;
51 free_user_data(struct passwd
*p
)
53 if (p
== NULL
) return;
55 if (p
->pw_name
!= NULL
) free(p
->pw_name
);
56 if (p
->pw_passwd
!= NULL
) free(p
->pw_passwd
);
57 if (p
->pw_class
!= NULL
) free(p
->pw_class
);
58 if (p
->pw_gecos
!= NULL
) free(p
->pw_gecos
);
59 if (p
->pw_dir
!= NULL
) free(p
->pw_dir
);
60 if (p
->pw_shell
!= NULL
) free(p
->pw_shell
);
64 free_user(struct passwd
*p
)
66 if (p
== NULL
) return;
72 free_lu_thread_info_user(void *x
)
74 struct lu_thread_info
*tdata
;
76 if (x
== NULL
) return;
78 tdata
= (struct lu_thread_info
*)x
;
80 if (tdata
->lu_entry
!= NULL
)
82 free_user((struct passwd
*)tdata
->lu_entry
);
83 tdata
->lu_entry
= NULL
;
86 _lu_data_free_vm_xdr(tdata
);
91 static struct passwd
*
92 extract_user(XDR
*xdr
)
94 int i
, j
, nvals
, nkeys
, status
;
98 if (xdr
== NULL
) return NULL
;
100 if (!xdr_int(xdr
, &nkeys
)) return NULL
;
102 p
= (struct passwd
*)calloc(1, sizeof(struct passwd
));
107 for (i
= 0; i
< nkeys
; i
++)
113 status
= _lu_xdr_attribute(xdr
, &key
, &vals
, &nvals
);
128 if ((p
->pw_name
== NULL
) && (!strcmp("name", key
)))
130 p
->pw_name
= vals
[0];
133 else if ((p
->pw_passwd
== NULL
) && (!strcmp("passwd", key
)))
135 p
->pw_passwd
= vals
[0];
138 else if ((p
->pw_class
== NULL
) && (!strcmp("class", key
)))
140 p
->pw_class
= vals
[0];
143 else if ((p
->pw_gecos
== NULL
) && (!strcmp("realname", key
)))
145 p
->pw_gecos
= vals
[0];
148 else if ((p
->pw_dir
== NULL
) && (!strcmp("home", key
)))
153 else if ((p
->pw_shell
== NULL
) && (!strcmp("shell", key
)))
155 p
->pw_shell
= vals
[0];
158 else if ((p
->pw_uid
== -2) && (!strcmp("uid", key
)))
160 p
->pw_uid
= atoi(vals
[0]);
162 else if ((p
->pw_gid
== -2) && (!strcmp("gid", key
)))
164 p
->pw_gid
= atoi(vals
[0]);
166 else if (!strcmp("change", key
))
168 p
->pw_change
= atoi(vals
[0]);
170 else if (!strcmp("expire", key
))
172 p
->pw_expire
= atoi(vals
[0]);
178 for (; j
< nvals
; j
++) free(vals
[j
]);
183 if (p
->pw_name
== NULL
) p
->pw_name
= strdup("");
184 if (p
->pw_passwd
== NULL
) p
->pw_passwd
= strdup("");
185 if (p
->pw_class
== NULL
) p
->pw_class
= strdup("");
186 if (p
->pw_gecos
== NULL
) p
->pw_gecos
= strdup("");
187 if (p
->pw_dir
== NULL
) p
->pw_dir
= strdup("");
188 if (p
->pw_shell
== NULL
) p
->pw_shell
= strdup("");
193 static struct passwd
*
194 copy_user(struct passwd
*in
)
198 if (in
== NULL
) return NULL
;
200 p
= (struct passwd
*)calloc(1, sizeof(struct passwd
));
202 p
->pw_name
= LU_COPY_STRING(in
->pw_name
);
203 p
->pw_passwd
= LU_COPY_STRING(in
->pw_passwd
);
204 p
->pw_uid
= in
->pw_uid
;
205 p
->pw_gid
= in
->pw_gid
;
206 p
->pw_change
= in
->pw_change
;
207 p
->pw_class
= LU_COPY_STRING(in
->pw_class
);
208 p
->pw_gecos
= LU_COPY_STRING(in
->pw_gecos
);
209 p
->pw_dir
= LU_COPY_STRING(in
->pw_dir
);
210 p
->pw_shell
= LU_COPY_STRING(in
->pw_shell
);
211 p
->pw_expire
= in
->pw_expire
;
217 copy_user_r(struct passwd
*in
, struct passwd
*out
, char *buffer
, int buflen
)
222 if (in
== NULL
) return -1;
223 if (out
== NULL
) return -1;
225 if (buffer
== NULL
) buflen
= 0;
227 /* Calculate size of input */
229 if (in
->pw_name
!= NULL
) hsize
+= strlen(in
->pw_name
);
230 if (in
->pw_passwd
!= NULL
) hsize
+= strlen(in
->pw_passwd
);
231 if (in
->pw_class
!= NULL
) hsize
+= strlen(in
->pw_class
);
232 if (in
->pw_gecos
!= NULL
) hsize
+= strlen(in
->pw_gecos
);
233 if (in
->pw_dir
!= NULL
) hsize
+= strlen(in
->pw_dir
);
234 if (in
->pw_shell
!= NULL
) hsize
+= strlen(in
->pw_shell
);
236 /* Check buffer space */
237 if (hsize
> buflen
) return -1;
239 /* Copy result into caller's struct passwd, using buffer for memory */
243 if (in
->pw_name
!= NULL
)
246 hsize
= strlen(in
->pw_name
) + 1;
247 memmove(bp
, in
->pw_name
, hsize
);
251 out
->pw_passwd
= NULL
;
252 if (in
->pw_passwd
!= NULL
)
255 hsize
= strlen(in
->pw_passwd
) + 1;
256 memmove(bp
, in
->pw_passwd
, hsize
);
260 out
->pw_uid
= in
->pw_uid
;
262 out
->pw_gid
= in
->pw_gid
;
264 out
->pw_change
= in
->pw_change
;
266 out
->pw_class
= NULL
;
267 if (in
->pw_class
!= NULL
)
270 hsize
= strlen(in
->pw_class
) + 1;
271 memmove(bp
, in
->pw_class
, hsize
);
275 out
->pw_gecos
= NULL
;
276 if (in
->pw_gecos
!= NULL
)
279 hsize
= strlen(in
->pw_gecos
) + 1;
280 memmove(bp
, in
->pw_gecos
, hsize
);
285 if (in
->pw_dir
!= NULL
)
288 hsize
= strlen(in
->pw_dir
) + 1;
289 memmove(bp
, in
->pw_dir
, hsize
);
293 out
->pw_shell
= NULL
;
294 if (in
->pw_shell
!= NULL
)
297 hsize
= strlen(in
->pw_shell
) + 1;
298 memmove(bp
, in
->pw_shell
, hsize
);
302 out
->pw_expire
= in
->pw_expire
;
308 recycle_user(struct lu_thread_info
*tdata
, struct passwd
*in
)
312 if (tdata
== NULL
) return;
313 p
= (struct passwd
*)tdata
->lu_entry
;
318 tdata
->lu_entry
= NULL
;
321 if (tdata
->lu_entry
== NULL
)
323 tdata
->lu_entry
= in
;
329 p
->pw_name
= in
->pw_name
;
330 p
->pw_passwd
= in
->pw_passwd
;
331 p
->pw_uid
= in
->pw_uid
;
332 p
->pw_gid
= in
->pw_gid
;
333 p
->pw_change
= in
->pw_change
;
334 p
->pw_class
= in
->pw_class
;
335 p
->pw_gecos
= in
->pw_gecos
;
336 p
->pw_dir
= in
->pw_dir
;
337 p
->pw_shell
= in
->pw_shell
;
338 p
->pw_expire
= in
->pw_expire
;
343 static struct passwd
*
347 unsigned int datalen
;
349 static int proc
= -1;
355 if (_lookup_link(_lu_port
, "getpwuid_A", &proc
) != KERN_SUCCESS
)
365 if (_lookup_all(_lu_port
, proc
, (unit
*)&uid
, 1, &lookup_buf
, &datalen
)
371 datalen
*= BYTES_PER_XDR_UNIT
;
372 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
374 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
377 if (!xdr_int(&inxdr
, &count
))
380 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
387 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
391 p
= extract_user(&inxdr
);
393 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
398 static struct passwd
*
399 lu_getpwnam(const char *name
)
402 unsigned int datalen
;
403 char namebuf
[_LU_MAXLUSTRLEN
+ BYTES_PER_XDR_UNIT
];
406 static int proc
= -1;
412 if (_lookup_link(_lu_port
, "getpwnam_A", &proc
) != KERN_SUCCESS
)
418 xdrmem_create(&outxdr
, namebuf
, sizeof(namebuf
), XDR_ENCODE
);
419 if (!xdr__lu_string(&outxdr
, (_lu_string
*)&name
))
421 xdr_destroy(&outxdr
);
428 if (_lookup_all(_lu_port
, proc
, (unit
*)namebuf
,
429 xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
, &lookup_buf
, &datalen
)
432 xdr_destroy(&outxdr
);
436 xdr_destroy(&outxdr
);
438 datalen
*= BYTES_PER_XDR_UNIT
;
439 if ((lookup_buf
== NULL
) || (datalen
== 0)) return NULL
;
441 xdrmem_create(&inxdr
, lookup_buf
, datalen
, XDR_DECODE
);
444 if (!xdr_int(&inxdr
, &count
))
447 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
454 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
458 p
= extract_user(&inxdr
);
460 vm_deallocate(mach_task_self(), (vm_address_t
)lookup_buf
, datalen
);
469 struct lu_thread_info
*tdata
;
471 tdata
= _lu_data_create_key(_lu_data_key_user
, free_lu_thread_info_user
);
472 _lu_data_free_vm_xdr(tdata
);
482 static struct passwd
*
486 static int proc
= -1;
487 struct lu_thread_info
*tdata
;
489 tdata
= _lu_data_create_key(_lu_data_key_user
, free_lu_thread_info_user
);
492 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
493 _lu_data_set_key(_lu_data_key_user
, tdata
);
496 if (tdata
->lu_vm
== NULL
)
500 if (_lookup_link(_lu_port
, "getpwent_A", &proc
) != KERN_SUCCESS
)
507 if (_lookup_all(_lu_port
, proc
, NULL
, 0, &(tdata
->lu_vm
), &(tdata
->lu_vm_length
)) != KERN_SUCCESS
)
513 /* mig stubs measure size in words (4 bytes) */
514 tdata
->lu_vm_length
*= 4;
516 if (tdata
->lu_xdr
!= NULL
)
518 xdr_destroy(tdata
->lu_xdr
);
521 tdata
->lu_xdr
= (XDR
*)calloc(1, sizeof(XDR
));
523 xdrmem_create(tdata
->lu_xdr
, tdata
->lu_vm
, tdata
->lu_vm_length
, XDR_DECODE
);
524 if (!xdr_int(tdata
->lu_xdr
, &tdata
->lu_vm_cursor
))
531 if (tdata
->lu_vm_cursor
== 0)
537 p
= extract_user(tdata
->lu_xdr
);
544 tdata
->lu_vm_cursor
--;
549 static struct passwd
*
550 getpw_internal(const char *name
, uid_t uid
, int source
)
552 struct passwd
*res
= NULL
;
553 static char *loginName
= NULL
;
554 static struct passwd
*loginEnt
= NULL
;
556 if (loginName
== NULL
)
558 char *l
= getlogin();
560 pthread_mutex_lock(&_user_lock
);
561 if ((loginEnt
== NULL
) && (l
!= NULL
) && (*l
!= '\0'))
565 loginEnt
= lu_getpwnam(l
);
569 loginEnt
= copy_user(_old_getpwnam(l
));
574 pthread_mutex_unlock(&_user_lock
);
577 if (loginEnt
!= NULL
)
582 if (strcmp(name
, loginEnt
->pw_name
) == 0)
586 if (strcmp(name
, loginEnt
->pw_gecos
) == 0)
592 if (uid
== loginEnt
->pw_uid
)
594 source
= PW_GET_NAME
;
608 res
= lu_getpwnam(name
);
611 res
= lu_getpwuid(uid
);
621 pthread_mutex_lock(&_user_lock
);
625 res
= copy_user(_old_getpwnam(name
));
628 res
= copy_user(_old_getpwuid(uid
));
631 res
= copy_user(_old_getpwent());
635 pthread_mutex_unlock(&_user_lock
);
641 static struct passwd
*
642 getpw(const char *name
, uid_t uid
, int source
)
644 struct passwd
*res
= NULL
;
645 struct lu_thread_info
*tdata
;
647 tdata
= _lu_data_create_key(_lu_data_key_user
, free_lu_thread_info_user
);
650 tdata
= (struct lu_thread_info
*)calloc(1, sizeof(struct lu_thread_info
));
651 _lu_data_set_key(_lu_data_key_user
, tdata
);
654 res
= getpw_internal(name
, uid
, source
);
656 recycle_user(tdata
, res
);
658 return (struct passwd
*)tdata
->lu_entry
;
662 getpw_r(const char *name
, uid_t uid
, int source
, struct passwd
*pwd
, char *buffer
, size_t bufsize
, struct passwd
**result
)
664 struct passwd
*res
= NULL
;
670 res
= getpw_internal(name
, uid
, source
);
671 if (res
== NULL
) return -1;
673 status
= copy_user_r(res
, pwd
, buffer
, bufsize
);
687 getpwnam(const char *name
)
689 return getpw(name
, -2, PW_GET_NAME
);
695 return getpw(NULL
, uid
, PW_GET_UID
);
701 return getpw(NULL
, -2, PW_GET_ENT
);
707 if (_lu_running()) lu_setpwent();
708 else _old_setpwent();
715 if (_lu_running()) lu_endpwent();
716 else _old_endpwent();
719 getpwnam_r(const char *name
, struct passwd
*pwd
, char *buffer
, size_t bufsize
, struct passwd
**result
)
721 return getpw_r(name
, -2, PW_GET_NAME
, pwd
, buffer
, bufsize
, result
);
725 getpwuid_r(uid_t uid
, struct passwd
*pwd
, char *buffer
, size_t bufsize
, struct passwd
**result
)
727 return getpw_r(NULL
, uid
, PW_GET_UID
, pwd
, buffer
, bufsize
, result
);