146d93063SJacques Vidrine /*- 246d93063SJacques Vidrine * Copyright (c) 2003 Networks Associates Technology, Inc. 346d93063SJacques Vidrine * All rights reserved. 446d93063SJacques Vidrine * 546d93063SJacques Vidrine * This software was developed for the FreeBSD Project by 646d93063SJacques Vidrine * Jacques A. Vidrine, Safeport Network Services, and Network 746d93063SJacques Vidrine * Associates Laboratories, the Security Research Division of Network 846d93063SJacques Vidrine * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 946d93063SJacques Vidrine * ("CBOSS"), as part of the DARPA CHATS research program. 1046d93063SJacques Vidrine * 1146d93063SJacques Vidrine * Redistribution and use in source and binary forms, with or without 1246d93063SJacques Vidrine * modification, are permitted provided that the following conditions 1346d93063SJacques Vidrine * are met: 1446d93063SJacques Vidrine * 1. Redistributions of source code must retain the above copyright 1546d93063SJacques Vidrine * notice, this list of conditions and the following disclaimer. 1646d93063SJacques Vidrine * 2. Redistributions in binary form must reproduce the above copyright 1746d93063SJacques Vidrine * notice, this list of conditions and the following disclaimer in the 1846d93063SJacques Vidrine * documentation and/or other materials provided with the distribution. 1946d93063SJacques Vidrine * 2046d93063SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2146d93063SJacques Vidrine * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2246d93063SJacques Vidrine * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2346d93063SJacques Vidrine * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2446d93063SJacques Vidrine * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2546d93063SJacques Vidrine * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2646d93063SJacques Vidrine * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2746d93063SJacques Vidrine * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2846d93063SJacques Vidrine * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2946d93063SJacques Vidrine * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3046d93063SJacques Vidrine * SUCH DAMAGE. 3146d93063SJacques Vidrine * 3246d93063SJacques Vidrine * Compatibility shims for the GNU C Library-style nsswitch interface. 3346d93063SJacques Vidrine */ 3446d93063SJacques Vidrine #include <sys/cdefs.h> 3546d93063SJacques Vidrine __FBSDID("$FreeBSD$"); 3646d93063SJacques Vidrine 3746d93063SJacques Vidrine #include "namespace.h" 3846d93063SJacques Vidrine #include <sys/param.h> 39c849849dSJacques Vidrine #include <errno.h> 4046d93063SJacques Vidrine #include <nss.h> 4146d93063SJacques Vidrine #include <pthread.h> 4246d93063SJacques Vidrine #include <pthread_np.h> 4346d93063SJacques Vidrine #include "un-namespace.h" 44a03fd3b6SJacques Vidrine #include "libc_private.h" 4546d93063SJacques Vidrine 4646d93063SJacques Vidrine 4746d93063SJacques Vidrine struct group; 4846d93063SJacques Vidrine struct passwd; 4946d93063SJacques Vidrine 5046d93063SJacques Vidrine static int terminator; 5146d93063SJacques Vidrine 5246d93063SJacques Vidrine #define DECLARE_TERMINATOR(x) \ 5346d93063SJacques Vidrine static pthread_key_t _term_key_##x; \ 5446d93063SJacques Vidrine static void \ 5546d93063SJacques Vidrine _term_create_##x(void) \ 5646d93063SJacques Vidrine { \ 5746d93063SJacques Vidrine (void)_pthread_key_create(&_term_key_##x, NULL); \ 5846d93063SJacques Vidrine } \ 5946d93063SJacques Vidrine static void *_term_main_##x; \ 6046d93063SJacques Vidrine static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT 6146d93063SJacques Vidrine 6246d93063SJacques Vidrine #define SET_TERMINATOR(x, y) \ 6346d93063SJacques Vidrine do { \ 64a03fd3b6SJacques Vidrine if (!__isthreaded || _pthread_main_np()) \ 6546d93063SJacques Vidrine _term_main_##x = (y); \ 6646d93063SJacques Vidrine else { \ 6746d93063SJacques Vidrine (void)_pthread_once(&_term_once_##x, _term_create_##x); \ 6846d93063SJacques Vidrine (void)_pthread_setspecific(_term_key_##x, y); \ 6946d93063SJacques Vidrine } \ 7046d93063SJacques Vidrine } while (0) 7146d93063SJacques Vidrine 7246d93063SJacques Vidrine #define CHECK_TERMINATOR(x) \ 73a03fd3b6SJacques Vidrine (!__isthreaded || _pthread_main_np() ? \ 7446d93063SJacques Vidrine (_term_main_##x) : \ 7546d93063SJacques Vidrine ((void)_pthread_once(&_term_once_##x, _term_create_##x), \ 7646d93063SJacques Vidrine _pthread_getspecific(_term_key_##x))) 7746d93063SJacques Vidrine 7846d93063SJacques Vidrine 7946d93063SJacques Vidrine 8046d93063SJacques Vidrine DECLARE_TERMINATOR(group); 8146d93063SJacques Vidrine 82*bf1aa507SCraig Rodrigues int __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap); 83*bf1aa507SCraig Rodrigues int __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap); 84*bf1aa507SCraig Rodrigues int __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap); 85*bf1aa507SCraig Rodrigues int __nss_compat_setgrent(void *retval, void *mdata, va_list ap); 86*bf1aa507SCraig Rodrigues int __nss_compat_endgrent(void *retval, void *mdata, va_list ap); 87*bf1aa507SCraig Rodrigues int __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap); 88*bf1aa507SCraig Rodrigues int __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap); 89*bf1aa507SCraig Rodrigues int __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap); 90*bf1aa507SCraig Rodrigues int __nss_compat_setpwent(void *retval, void *mdata, va_list ap); 91*bf1aa507SCraig Rodrigues int __nss_compat_endpwent(void *retval, void *mdata, va_list ap); 9246d93063SJacques Vidrine 9346d93063SJacques Vidrine int 9446d93063SJacques Vidrine __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) 9546d93063SJacques Vidrine { 9646d93063SJacques Vidrine int (*fn)(const char *, struct group *, char *, size_t, int *); 9746d93063SJacques Vidrine const char *name; 9846d93063SJacques Vidrine struct group *grp; 9946d93063SJacques Vidrine char *buffer; 10046d93063SJacques Vidrine int *errnop; 10146d93063SJacques Vidrine size_t bufsize; 10246d93063SJacques Vidrine enum nss_status status; 10346d93063SJacques Vidrine 10446d93063SJacques Vidrine fn = mdata; 10546d93063SJacques Vidrine name = va_arg(ap, const char *); 10646d93063SJacques Vidrine grp = va_arg(ap, struct group *); 10746d93063SJacques Vidrine buffer = va_arg(ap, char *); 10846d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 10946d93063SJacques Vidrine errnop = va_arg(ap, int *); 11046d93063SJacques Vidrine status = fn(name, grp, buffer, bufsize, errnop); 111c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 11246d93063SJacques Vidrine if (status == NS_SUCCESS) 11346d93063SJacques Vidrine *(struct group **)retval = grp; 114c849849dSJacques Vidrine return (status); 11546d93063SJacques Vidrine } 11646d93063SJacques Vidrine 11746d93063SJacques Vidrine 11846d93063SJacques Vidrine int 11946d93063SJacques Vidrine __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) 12046d93063SJacques Vidrine { 12146d93063SJacques Vidrine int (*fn)(gid_t, struct group *, char *, size_t, int *); 12246d93063SJacques Vidrine gid_t gid; 12346d93063SJacques Vidrine struct group *grp; 12446d93063SJacques Vidrine char *buffer; 12546d93063SJacques Vidrine int *errnop; 12646d93063SJacques Vidrine size_t bufsize; 12746d93063SJacques Vidrine enum nss_status status; 12846d93063SJacques Vidrine 12946d93063SJacques Vidrine fn = mdata; 13046d93063SJacques Vidrine gid = va_arg(ap, gid_t); 13146d93063SJacques Vidrine grp = va_arg(ap, struct group *); 13246d93063SJacques Vidrine buffer = va_arg(ap, char *); 13346d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 13446d93063SJacques Vidrine errnop = va_arg(ap, int *); 13546d93063SJacques Vidrine status = fn(gid, grp, buffer, bufsize, errnop); 136c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 13746d93063SJacques Vidrine if (status == NS_SUCCESS) 13846d93063SJacques Vidrine *(struct group **)retval = grp; 139c849849dSJacques Vidrine return (status); 14046d93063SJacques Vidrine } 14146d93063SJacques Vidrine 14246d93063SJacques Vidrine 14346d93063SJacques Vidrine int 14446d93063SJacques Vidrine __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) 14546d93063SJacques Vidrine { 14646d93063SJacques Vidrine int (*fn)(struct group *, char *, size_t, int *); 14746d93063SJacques Vidrine struct group *grp; 14846d93063SJacques Vidrine char *buffer; 14946d93063SJacques Vidrine int *errnop; 15046d93063SJacques Vidrine size_t bufsize; 15146d93063SJacques Vidrine enum nss_status status; 15246d93063SJacques Vidrine 15346d93063SJacques Vidrine if (CHECK_TERMINATOR(group)) 15446d93063SJacques Vidrine return (NS_NOTFOUND); 15546d93063SJacques Vidrine fn = mdata; 15646d93063SJacques Vidrine grp = va_arg(ap, struct group *); 15746d93063SJacques Vidrine buffer = va_arg(ap, char *); 15846d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 15946d93063SJacques Vidrine errnop = va_arg(ap, int *); 16046d93063SJacques Vidrine status = fn(grp, buffer, bufsize, errnop); 161c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 16246d93063SJacques Vidrine if (status == NS_SUCCESS) 16346d93063SJacques Vidrine *(struct group **)retval = grp; 164c849849dSJacques Vidrine else if (status != NS_RETURN) 16546d93063SJacques Vidrine SET_TERMINATOR(group, &terminator); 166c849849dSJacques Vidrine return (status); 16746d93063SJacques Vidrine } 16846d93063SJacques Vidrine 16946d93063SJacques Vidrine 17046d93063SJacques Vidrine int 17146d93063SJacques Vidrine __nss_compat_setgrent(void *retval, void *mdata, va_list ap) 17246d93063SJacques Vidrine { 17346d93063SJacques Vidrine 17446d93063SJacques Vidrine SET_TERMINATOR(group, NULL); 17546d93063SJacques Vidrine ((int (*)(void))mdata)(); 17646d93063SJacques Vidrine return (NS_UNAVAIL); 17746d93063SJacques Vidrine } 17846d93063SJacques Vidrine 17946d93063SJacques Vidrine 18046d93063SJacques Vidrine int 18146d93063SJacques Vidrine __nss_compat_endgrent(void *retval, void *mdata, va_list ap) 18246d93063SJacques Vidrine { 18346d93063SJacques Vidrine 18446d93063SJacques Vidrine SET_TERMINATOR(group, NULL); 18546d93063SJacques Vidrine ((int (*)(void))mdata)(); 18646d93063SJacques Vidrine return (NS_UNAVAIL); 18746d93063SJacques Vidrine } 18846d93063SJacques Vidrine 18946d93063SJacques Vidrine 19046d93063SJacques Vidrine 19146d93063SJacques Vidrine DECLARE_TERMINATOR(passwd); 19246d93063SJacques Vidrine 19346d93063SJacques Vidrine 19446d93063SJacques Vidrine int 19546d93063SJacques Vidrine __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) 19646d93063SJacques Vidrine { 19746d93063SJacques Vidrine int (*fn)(const char *, struct passwd *, char *, size_t, int *); 19846d93063SJacques Vidrine const char *name; 19946d93063SJacques Vidrine struct passwd *pwd; 20046d93063SJacques Vidrine char *buffer; 20146d93063SJacques Vidrine int *errnop; 20246d93063SJacques Vidrine size_t bufsize; 20346d93063SJacques Vidrine enum nss_status status; 20446d93063SJacques Vidrine 20546d93063SJacques Vidrine fn = mdata; 20646d93063SJacques Vidrine name = va_arg(ap, const char *); 20746d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 20846d93063SJacques Vidrine buffer = va_arg(ap, char *); 20946d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 21046d93063SJacques Vidrine errnop = va_arg(ap, int *); 21146d93063SJacques Vidrine status = fn(name, pwd, buffer, bufsize, errnop); 212c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 21346d93063SJacques Vidrine if (status == NS_SUCCESS) 21446d93063SJacques Vidrine *(struct passwd **)retval = pwd; 215c849849dSJacques Vidrine return (status); 21646d93063SJacques Vidrine } 21746d93063SJacques Vidrine 21846d93063SJacques Vidrine 21946d93063SJacques Vidrine int 22046d93063SJacques Vidrine __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) 22146d93063SJacques Vidrine { 22246d93063SJacques Vidrine int (*fn)(uid_t, struct passwd *, char *, size_t, int *); 22346d93063SJacques Vidrine uid_t uid; 22446d93063SJacques Vidrine struct passwd *pwd; 22546d93063SJacques Vidrine char *buffer; 22646d93063SJacques Vidrine int *errnop; 22746d93063SJacques Vidrine size_t bufsize; 22846d93063SJacques Vidrine enum nss_status status; 22946d93063SJacques Vidrine 23046d93063SJacques Vidrine fn = mdata; 23146d93063SJacques Vidrine uid = va_arg(ap, uid_t); 23246d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 23346d93063SJacques Vidrine buffer = va_arg(ap, char *); 23446d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 23546d93063SJacques Vidrine errnop = va_arg(ap, int *); 23646d93063SJacques Vidrine status = fn(uid, pwd, buffer, bufsize, errnop); 237c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 23846d93063SJacques Vidrine if (status == NS_SUCCESS) 23946d93063SJacques Vidrine *(struct passwd **)retval = pwd; 240c849849dSJacques Vidrine return (status); 24146d93063SJacques Vidrine } 24246d93063SJacques Vidrine 24346d93063SJacques Vidrine 24446d93063SJacques Vidrine int 24546d93063SJacques Vidrine __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) 24646d93063SJacques Vidrine { 24746d93063SJacques Vidrine int (*fn)(struct passwd *, char *, size_t, int *); 24846d93063SJacques Vidrine struct passwd *pwd; 24946d93063SJacques Vidrine char *buffer; 25046d93063SJacques Vidrine int *errnop; 25146d93063SJacques Vidrine size_t bufsize; 25246d93063SJacques Vidrine enum nss_status status; 25346d93063SJacques Vidrine 25446d93063SJacques Vidrine if (CHECK_TERMINATOR(passwd)) 25546d93063SJacques Vidrine return (NS_NOTFOUND); 25646d93063SJacques Vidrine fn = mdata; 25746d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 25846d93063SJacques Vidrine buffer = va_arg(ap, char *); 25946d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 26046d93063SJacques Vidrine errnop = va_arg(ap, int *); 26146d93063SJacques Vidrine status = fn(pwd, buffer, bufsize, errnop); 262c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 26346d93063SJacques Vidrine if (status == NS_SUCCESS) 26446d93063SJacques Vidrine *(struct passwd **)retval = pwd; 265c849849dSJacques Vidrine else if (status != NS_RETURN) 26646d93063SJacques Vidrine SET_TERMINATOR(passwd, &terminator); 267c849849dSJacques Vidrine return (status); 26846d93063SJacques Vidrine } 26946d93063SJacques Vidrine 27046d93063SJacques Vidrine 27146d93063SJacques Vidrine int 27246d93063SJacques Vidrine __nss_compat_setpwent(void *retval, void *mdata, va_list ap) 27346d93063SJacques Vidrine { 27446d93063SJacques Vidrine 27546d93063SJacques Vidrine SET_TERMINATOR(passwd, NULL); 27646d93063SJacques Vidrine ((int (*)(void))mdata)(); 27746d93063SJacques Vidrine return (NS_UNAVAIL); 27846d93063SJacques Vidrine } 27946d93063SJacques Vidrine 28046d93063SJacques Vidrine 28146d93063SJacques Vidrine int 28246d93063SJacques Vidrine __nss_compat_endpwent(void *retval, void *mdata, va_list ap) 28346d93063SJacques Vidrine { 28446d93063SJacques Vidrine 28546d93063SJacques Vidrine SET_TERMINATOR(passwd, NULL); 28646d93063SJacques Vidrine ((int (*)(void))mdata)(); 28746d93063SJacques Vidrine return (NS_UNAVAIL); 28846d93063SJacques Vidrine } 289