146d93063SJacques Vidrine /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3d915a14eSPedro F. Giffuni * 446d93063SJacques Vidrine * Copyright (c) 2003 Networks Associates Technology, Inc. 546d93063SJacques Vidrine * All rights reserved. 646d93063SJacques Vidrine * 746d93063SJacques Vidrine * This software was developed for the FreeBSD Project by 846d93063SJacques Vidrine * Jacques A. Vidrine, Safeport Network Services, and Network 946d93063SJacques Vidrine * Associates Laboratories, the Security Research Division of Network 1046d93063SJacques Vidrine * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 1146d93063SJacques Vidrine * ("CBOSS"), as part of the DARPA CHATS research program. 1246d93063SJacques Vidrine * 1346d93063SJacques Vidrine * Redistribution and use in source and binary forms, with or without 1446d93063SJacques Vidrine * modification, are permitted provided that the following conditions 1546d93063SJacques Vidrine * are met: 1646d93063SJacques Vidrine * 1. Redistributions of source code must retain the above copyright 1746d93063SJacques Vidrine * notice, this list of conditions and the following disclaimer. 1846d93063SJacques Vidrine * 2. Redistributions in binary form must reproduce the above copyright 1946d93063SJacques Vidrine * notice, this list of conditions and the following disclaimer in the 2046d93063SJacques Vidrine * documentation and/or other materials provided with the distribution. 2146d93063SJacques Vidrine * 2246d93063SJacques Vidrine * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2346d93063SJacques Vidrine * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2446d93063SJacques Vidrine * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2546d93063SJacques Vidrine * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2646d93063SJacques Vidrine * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2746d93063SJacques Vidrine * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2846d93063SJacques Vidrine * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2946d93063SJacques Vidrine * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3046d93063SJacques Vidrine * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3146d93063SJacques Vidrine * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3246d93063SJacques Vidrine * SUCH DAMAGE. 3346d93063SJacques Vidrine * 3446d93063SJacques Vidrine * Compatibility shims for the GNU C Library-style nsswitch interface. 3546d93063SJacques Vidrine */ 3646d93063SJacques Vidrine #include <sys/cdefs.h> 3746d93063SJacques Vidrine __FBSDID("$FreeBSD$"); 3846d93063SJacques Vidrine 3946d93063SJacques Vidrine #include "namespace.h" 4046d93063SJacques Vidrine #include <sys/param.h> 41c849849dSJacques Vidrine #include <errno.h> 4246d93063SJacques Vidrine #include <nss.h> 4346d93063SJacques Vidrine #include <pthread.h> 4446d93063SJacques Vidrine #include <pthread_np.h> 4546d93063SJacques Vidrine #include "un-namespace.h" 46a03fd3b6SJacques Vidrine #include "libc_private.h" 4746d93063SJacques Vidrine 4846d93063SJacques Vidrine 4946d93063SJacques Vidrine struct group; 5046d93063SJacques Vidrine struct passwd; 5146d93063SJacques Vidrine 5246d93063SJacques Vidrine static int terminator; 5346d93063SJacques Vidrine 5446d93063SJacques Vidrine #define DECLARE_TERMINATOR(x) \ 5546d93063SJacques Vidrine static pthread_key_t _term_key_##x; \ 5646d93063SJacques Vidrine static void \ 5746d93063SJacques Vidrine _term_create_##x(void) \ 5846d93063SJacques Vidrine { \ 5946d93063SJacques Vidrine (void)_pthread_key_create(&_term_key_##x, NULL); \ 6046d93063SJacques Vidrine } \ 6146d93063SJacques Vidrine static void *_term_main_##x; \ 6246d93063SJacques Vidrine static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT 6346d93063SJacques Vidrine 6446d93063SJacques Vidrine #define SET_TERMINATOR(x, y) \ 6546d93063SJacques Vidrine do { \ 66a03fd3b6SJacques Vidrine if (!__isthreaded || _pthread_main_np()) \ 6746d93063SJacques Vidrine _term_main_##x = (y); \ 6846d93063SJacques Vidrine else { \ 6946d93063SJacques Vidrine (void)_pthread_once(&_term_once_##x, _term_create_##x); \ 7046d93063SJacques Vidrine (void)_pthread_setspecific(_term_key_##x, y); \ 7146d93063SJacques Vidrine } \ 7246d93063SJacques Vidrine } while (0) 7346d93063SJacques Vidrine 7446d93063SJacques Vidrine #define CHECK_TERMINATOR(x) \ 75a03fd3b6SJacques Vidrine (!__isthreaded || _pthread_main_np() ? \ 7646d93063SJacques Vidrine (_term_main_##x) : \ 7746d93063SJacques Vidrine ((void)_pthread_once(&_term_once_##x, _term_create_##x), \ 7846d93063SJacques Vidrine _pthread_getspecific(_term_key_##x))) 7946d93063SJacques Vidrine 8046d93063SJacques Vidrine 8146d93063SJacques Vidrine 8246d93063SJacques Vidrine DECLARE_TERMINATOR(group); 8346d93063SJacques Vidrine 84bf1aa507SCraig Rodrigues int __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap); 85bf1aa507SCraig Rodrigues int __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap); 86bf1aa507SCraig Rodrigues int __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap); 87bf1aa507SCraig Rodrigues int __nss_compat_setgrent(void *retval, void *mdata, va_list ap); 88bf1aa507SCraig Rodrigues int __nss_compat_endgrent(void *retval, void *mdata, va_list ap); 89bf1aa507SCraig Rodrigues int __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap); 90bf1aa507SCraig Rodrigues int __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap); 91bf1aa507SCraig Rodrigues int __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap); 92bf1aa507SCraig Rodrigues int __nss_compat_setpwent(void *retval, void *mdata, va_list ap); 93bf1aa507SCraig Rodrigues int __nss_compat_endpwent(void *retval, void *mdata, va_list ap); 9446d93063SJacques Vidrine 9546d93063SJacques Vidrine int 9646d93063SJacques Vidrine __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) 9746d93063SJacques Vidrine { 9846d93063SJacques Vidrine int (*fn)(const char *, struct group *, char *, size_t, int *); 9946d93063SJacques Vidrine const char *name; 10046d93063SJacques Vidrine struct group *grp; 10146d93063SJacques Vidrine char *buffer; 1023bb0c17dSBrooks Davis int *errnop, ns_status; 10346d93063SJacques Vidrine size_t bufsize; 1043bb0c17dSBrooks Davis enum nss_status nss_status; 10546d93063SJacques Vidrine 10646d93063SJacques Vidrine fn = mdata; 10746d93063SJacques Vidrine name = va_arg(ap, const char *); 10846d93063SJacques Vidrine grp = va_arg(ap, struct group *); 10946d93063SJacques Vidrine buffer = va_arg(ap, char *); 11046d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 11146d93063SJacques Vidrine errnop = va_arg(ap, int *); 1123bb0c17dSBrooks Davis nss_status = fn(name, grp, buffer, bufsize, errnop); 1133bb0c17dSBrooks Davis ns_status = __nss_compat_result(nss_status, *errnop); 1143bb0c17dSBrooks Davis if (ns_status == NS_SUCCESS) 11546d93063SJacques Vidrine *(struct group **)retval = grp; 1163bb0c17dSBrooks Davis return (ns_status); 11746d93063SJacques Vidrine } 11846d93063SJacques Vidrine 11946d93063SJacques Vidrine 12046d93063SJacques Vidrine int 12146d93063SJacques Vidrine __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) 12246d93063SJacques Vidrine { 12346d93063SJacques Vidrine int (*fn)(gid_t, struct group *, char *, size_t, int *); 12446d93063SJacques Vidrine gid_t gid; 12546d93063SJacques Vidrine struct group *grp; 12646d93063SJacques Vidrine char *buffer; 1273bb0c17dSBrooks Davis int *errnop, ns_status; 12846d93063SJacques Vidrine size_t bufsize; 1293bb0c17dSBrooks Davis enum nss_status nss_status; 13046d93063SJacques Vidrine 13146d93063SJacques Vidrine fn = mdata; 13246d93063SJacques Vidrine gid = va_arg(ap, gid_t); 13346d93063SJacques Vidrine grp = va_arg(ap, struct group *); 13446d93063SJacques Vidrine buffer = va_arg(ap, char *); 13546d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 13646d93063SJacques Vidrine errnop = va_arg(ap, int *); 1373bb0c17dSBrooks Davis nss_status = fn(gid, grp, buffer, bufsize, errnop); 1383bb0c17dSBrooks Davis ns_status = __nss_compat_result(nss_status, *errnop); 1393bb0c17dSBrooks Davis if (ns_status == NS_SUCCESS) 14046d93063SJacques Vidrine *(struct group **)retval = grp; 1413bb0c17dSBrooks Davis return (ns_status); 14246d93063SJacques Vidrine } 14346d93063SJacques Vidrine 14446d93063SJacques Vidrine 14546d93063SJacques Vidrine int 14646d93063SJacques Vidrine __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) 14746d93063SJacques Vidrine { 14846d93063SJacques Vidrine int (*fn)(struct group *, char *, size_t, int *); 14946d93063SJacques Vidrine struct group *grp; 15046d93063SJacques Vidrine char *buffer; 1513bb0c17dSBrooks Davis int *errnop, ns_status; 15246d93063SJacques Vidrine size_t bufsize; 1533bb0c17dSBrooks Davis enum nss_status nss_status; 15446d93063SJacques Vidrine 15546d93063SJacques Vidrine if (CHECK_TERMINATOR(group)) 15646d93063SJacques Vidrine return (NS_NOTFOUND); 15746d93063SJacques Vidrine fn = mdata; 15846d93063SJacques Vidrine grp = va_arg(ap, struct group *); 15946d93063SJacques Vidrine buffer = va_arg(ap, char *); 16046d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 16146d93063SJacques Vidrine errnop = va_arg(ap, int *); 1623bb0c17dSBrooks Davis nss_status = fn(grp, buffer, bufsize, errnop); 1633bb0c17dSBrooks Davis ns_status = __nss_compat_result(nss_status, *errnop); 1643bb0c17dSBrooks Davis if (ns_status == NS_SUCCESS) 16546d93063SJacques Vidrine *(struct group **)retval = grp; 1663bb0c17dSBrooks Davis else if (ns_status != NS_RETURN) 16746d93063SJacques Vidrine SET_TERMINATOR(group, &terminator); 1683bb0c17dSBrooks Davis return (ns_status); 16946d93063SJacques Vidrine } 17046d93063SJacques Vidrine 17146d93063SJacques Vidrine 17246d93063SJacques Vidrine int 17346d93063SJacques Vidrine __nss_compat_setgrent(void *retval, void *mdata, va_list ap) 17446d93063SJacques Vidrine { 17546d93063SJacques Vidrine 17646d93063SJacques Vidrine SET_TERMINATOR(group, NULL); 17746d93063SJacques Vidrine ((int (*)(void))mdata)(); 17846d93063SJacques Vidrine return (NS_UNAVAIL); 17946d93063SJacques Vidrine } 18046d93063SJacques Vidrine 18146d93063SJacques Vidrine 18246d93063SJacques Vidrine int 18346d93063SJacques Vidrine __nss_compat_endgrent(void *retval, void *mdata, va_list ap) 18446d93063SJacques Vidrine { 18546d93063SJacques Vidrine 18646d93063SJacques Vidrine SET_TERMINATOR(group, NULL); 18746d93063SJacques Vidrine ((int (*)(void))mdata)(); 18846d93063SJacques Vidrine return (NS_UNAVAIL); 18946d93063SJacques Vidrine } 19046d93063SJacques Vidrine 19146d93063SJacques Vidrine 19246d93063SJacques Vidrine 19346d93063SJacques Vidrine DECLARE_TERMINATOR(passwd); 19446d93063SJacques Vidrine 19546d93063SJacques Vidrine 19646d93063SJacques Vidrine int 19746d93063SJacques Vidrine __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) 19846d93063SJacques Vidrine { 19946d93063SJacques Vidrine int (*fn)(const char *, struct passwd *, char *, size_t, int *); 20046d93063SJacques Vidrine const char *name; 20146d93063SJacques Vidrine struct passwd *pwd; 20246d93063SJacques Vidrine char *buffer; 2033bb0c17dSBrooks Davis int *errnop, ns_status; 20446d93063SJacques Vidrine size_t bufsize; 2053bb0c17dSBrooks Davis enum nss_status nss_status; 20646d93063SJacques Vidrine 20746d93063SJacques Vidrine fn = mdata; 20846d93063SJacques Vidrine name = va_arg(ap, const char *); 20946d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 21046d93063SJacques Vidrine buffer = va_arg(ap, char *); 21146d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 21246d93063SJacques Vidrine errnop = va_arg(ap, int *); 2133bb0c17dSBrooks Davis nss_status = fn(name, pwd, buffer, bufsize, errnop); 2143bb0c17dSBrooks Davis ns_status = __nss_compat_result(nss_status, *errnop); 2153bb0c17dSBrooks Davis if (ns_status == NS_SUCCESS) 21646d93063SJacques Vidrine *(struct passwd **)retval = pwd; 2173bb0c17dSBrooks Davis return (ns_status); 21846d93063SJacques Vidrine } 21946d93063SJacques Vidrine 22046d93063SJacques Vidrine 22146d93063SJacques Vidrine int 22246d93063SJacques Vidrine __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) 22346d93063SJacques Vidrine { 22446d93063SJacques Vidrine int (*fn)(uid_t, struct passwd *, char *, size_t, int *); 22546d93063SJacques Vidrine uid_t uid; 22646d93063SJacques Vidrine struct passwd *pwd; 22746d93063SJacques Vidrine char *buffer; 2283bb0c17dSBrooks Davis int *errnop, ns_status; 22946d93063SJacques Vidrine size_t bufsize; 2303bb0c17dSBrooks Davis enum nss_status nss_status; 23146d93063SJacques Vidrine 23246d93063SJacques Vidrine fn = mdata; 23346d93063SJacques Vidrine uid = va_arg(ap, uid_t); 23446d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 23546d93063SJacques Vidrine buffer = va_arg(ap, char *); 23646d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 23746d93063SJacques Vidrine errnop = va_arg(ap, int *); 2383bb0c17dSBrooks Davis nss_status = fn(uid, pwd, buffer, bufsize, errnop); 2393bb0c17dSBrooks Davis ns_status = __nss_compat_result(nss_status, *errnop); 2403bb0c17dSBrooks Davis if (ns_status == NS_SUCCESS) 24146d93063SJacques Vidrine *(struct passwd **)retval = pwd; 2423bb0c17dSBrooks Davis return (ns_status); 24346d93063SJacques Vidrine } 24446d93063SJacques Vidrine 24546d93063SJacques Vidrine 24646d93063SJacques Vidrine int 24746d93063SJacques Vidrine __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) 24846d93063SJacques Vidrine { 24946d93063SJacques Vidrine int (*fn)(struct passwd *, char *, size_t, int *); 25046d93063SJacques Vidrine struct passwd *pwd; 25146d93063SJacques Vidrine char *buffer; 2523bb0c17dSBrooks Davis int *errnop, ns_status; 25346d93063SJacques Vidrine size_t bufsize; 2543bb0c17dSBrooks Davis enum nss_status nss_status; 25546d93063SJacques Vidrine 25646d93063SJacques Vidrine if (CHECK_TERMINATOR(passwd)) 25746d93063SJacques Vidrine return (NS_NOTFOUND); 25846d93063SJacques Vidrine fn = mdata; 25946d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 26046d93063SJacques Vidrine buffer = va_arg(ap, char *); 26146d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 26246d93063SJacques Vidrine errnop = va_arg(ap, int *); 2633bb0c17dSBrooks Davis nss_status = fn(pwd, buffer, bufsize, errnop); 2643bb0c17dSBrooks Davis ns_status = __nss_compat_result(nss_status, *errnop); 2653bb0c17dSBrooks Davis if (ns_status == NS_SUCCESS) 26646d93063SJacques Vidrine *(struct passwd **)retval = pwd; 2673bb0c17dSBrooks Davis else if (ns_status != NS_RETURN) 26846d93063SJacques Vidrine SET_TERMINATOR(passwd, &terminator); 2693bb0c17dSBrooks Davis return (ns_status); 27046d93063SJacques Vidrine } 27146d93063SJacques Vidrine 27246d93063SJacques Vidrine 27346d93063SJacques Vidrine int 27446d93063SJacques Vidrine __nss_compat_setpwent(void *retval, void *mdata, va_list ap) 27546d93063SJacques Vidrine { 27646d93063SJacques Vidrine 27746d93063SJacques Vidrine SET_TERMINATOR(passwd, NULL); 27846d93063SJacques Vidrine ((int (*)(void))mdata)(); 27946d93063SJacques Vidrine return (NS_UNAVAIL); 28046d93063SJacques Vidrine } 28146d93063SJacques Vidrine 28246d93063SJacques Vidrine 28346d93063SJacques Vidrine int 28446d93063SJacques Vidrine __nss_compat_endpwent(void *retval, void *mdata, va_list ap) 28546d93063SJacques Vidrine { 28646d93063SJacques Vidrine 28746d93063SJacques Vidrine SET_TERMINATOR(passwd, NULL); 28846d93063SJacques Vidrine ((int (*)(void))mdata)(); 28946d93063SJacques Vidrine return (NS_UNAVAIL); 29046d93063SJacques Vidrine } 291