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" 4446d93063SJacques Vidrine 4546d93063SJacques Vidrine 4646d93063SJacques Vidrine struct group; 4746d93063SJacques Vidrine struct passwd; 4846d93063SJacques Vidrine 4946d93063SJacques Vidrine static int terminator; 5046d93063SJacques Vidrine 5146d93063SJacques Vidrine #define DECLARE_TERMINATOR(x) \ 5246d93063SJacques Vidrine static pthread_key_t _term_key_##x; \ 5346d93063SJacques Vidrine static void \ 5446d93063SJacques Vidrine _term_create_##x(void) \ 5546d93063SJacques Vidrine { \ 5646d93063SJacques Vidrine (void)_pthread_key_create(&_term_key_##x, NULL); \ 5746d93063SJacques Vidrine } \ 5846d93063SJacques Vidrine static void *_term_main_##x; \ 5946d93063SJacques Vidrine static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT 6046d93063SJacques Vidrine 6146d93063SJacques Vidrine #define SET_TERMINATOR(x, y) \ 6246d93063SJacques Vidrine do { \ 6346d93063SJacques Vidrine if (_pthread_main_np()) \ 6446d93063SJacques Vidrine _term_main_##x = (y); \ 6546d93063SJacques Vidrine else { \ 6646d93063SJacques Vidrine (void)_pthread_once(&_term_once_##x, _term_create_##x); \ 6746d93063SJacques Vidrine (void)_pthread_setspecific(_term_key_##x, y); \ 6846d93063SJacques Vidrine } \ 6946d93063SJacques Vidrine } while (0) 7046d93063SJacques Vidrine 7146d93063SJacques Vidrine #define CHECK_TERMINATOR(x) \ 7246d93063SJacques Vidrine (_pthread_main_np() ? \ 7346d93063SJacques Vidrine (_term_main_##x) : \ 7446d93063SJacques Vidrine ((void)_pthread_once(&_term_once_##x, _term_create_##x), \ 7546d93063SJacques Vidrine _pthread_getspecific(_term_key_##x))) 7646d93063SJacques Vidrine 7746d93063SJacques Vidrine 7846d93063SJacques Vidrine 7946d93063SJacques Vidrine DECLARE_TERMINATOR(group); 8046d93063SJacques Vidrine 8146d93063SJacques Vidrine 8246d93063SJacques Vidrine int 8346d93063SJacques Vidrine __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) 8446d93063SJacques Vidrine { 8546d93063SJacques Vidrine int (*fn)(const char *, struct group *, char *, size_t, int *); 8646d93063SJacques Vidrine const char *name; 8746d93063SJacques Vidrine struct group *grp; 8846d93063SJacques Vidrine char *buffer; 8946d93063SJacques Vidrine int *errnop; 9046d93063SJacques Vidrine size_t bufsize; 9146d93063SJacques Vidrine enum nss_status status; 9246d93063SJacques Vidrine 9346d93063SJacques Vidrine fn = mdata; 9446d93063SJacques Vidrine name = va_arg(ap, const char *); 9546d93063SJacques Vidrine grp = va_arg(ap, struct group *); 9646d93063SJacques Vidrine buffer = va_arg(ap, char *); 9746d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 9846d93063SJacques Vidrine errnop = va_arg(ap, int *); 9946d93063SJacques Vidrine status = fn(name, grp, buffer, bufsize, errnop); 100c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 10146d93063SJacques Vidrine if (status == NS_SUCCESS) 10246d93063SJacques Vidrine *(struct group **)retval = grp; 103c849849dSJacques Vidrine return (status); 10446d93063SJacques Vidrine } 10546d93063SJacques Vidrine 10646d93063SJacques Vidrine 10746d93063SJacques Vidrine int 10846d93063SJacques Vidrine __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) 10946d93063SJacques Vidrine { 11046d93063SJacques Vidrine int (*fn)(gid_t, struct group *, char *, size_t, int *); 11146d93063SJacques Vidrine gid_t gid; 11246d93063SJacques Vidrine struct group *grp; 11346d93063SJacques Vidrine char *buffer; 11446d93063SJacques Vidrine int *errnop; 11546d93063SJacques Vidrine size_t bufsize; 11646d93063SJacques Vidrine enum nss_status status; 11746d93063SJacques Vidrine 11846d93063SJacques Vidrine fn = mdata; 11946d93063SJacques Vidrine gid = va_arg(ap, gid_t); 12046d93063SJacques Vidrine grp = va_arg(ap, struct group *); 12146d93063SJacques Vidrine buffer = va_arg(ap, char *); 12246d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 12346d93063SJacques Vidrine errnop = va_arg(ap, int *); 12446d93063SJacques Vidrine status = fn(gid, grp, buffer, bufsize, errnop); 125c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 12646d93063SJacques Vidrine if (status == NS_SUCCESS) 12746d93063SJacques Vidrine *(struct group **)retval = grp; 128c849849dSJacques Vidrine return (status); 12946d93063SJacques Vidrine } 13046d93063SJacques Vidrine 13146d93063SJacques Vidrine 13246d93063SJacques Vidrine int 13346d93063SJacques Vidrine __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) 13446d93063SJacques Vidrine { 13546d93063SJacques Vidrine int (*fn)(struct group *, char *, size_t, int *); 13646d93063SJacques Vidrine struct group *grp; 13746d93063SJacques Vidrine char *buffer; 13846d93063SJacques Vidrine int *errnop; 13946d93063SJacques Vidrine size_t bufsize; 14046d93063SJacques Vidrine enum nss_status status; 14146d93063SJacques Vidrine 14246d93063SJacques Vidrine if (CHECK_TERMINATOR(group)) 14346d93063SJacques Vidrine return (NS_NOTFOUND); 14446d93063SJacques Vidrine fn = mdata; 14546d93063SJacques Vidrine grp = va_arg(ap, struct group *); 14646d93063SJacques Vidrine buffer = va_arg(ap, char *); 14746d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 14846d93063SJacques Vidrine errnop = va_arg(ap, int *); 14946d93063SJacques Vidrine status = fn(grp, buffer, bufsize, errnop); 150c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 15146d93063SJacques Vidrine if (status == NS_SUCCESS) 15246d93063SJacques Vidrine *(struct group **)retval = grp; 153c849849dSJacques Vidrine else if (status != NS_RETURN) 15446d93063SJacques Vidrine SET_TERMINATOR(group, &terminator); 155c849849dSJacques Vidrine return (status); 15646d93063SJacques Vidrine } 15746d93063SJacques Vidrine 15846d93063SJacques Vidrine 15946d93063SJacques Vidrine int 16046d93063SJacques Vidrine __nss_compat_setgrent(void *retval, void *mdata, va_list ap) 16146d93063SJacques Vidrine { 16246d93063SJacques Vidrine 16346d93063SJacques Vidrine SET_TERMINATOR(group, NULL); 16446d93063SJacques Vidrine ((int (*)(void))mdata)(); 16546d93063SJacques Vidrine return (NS_UNAVAIL); 16646d93063SJacques Vidrine } 16746d93063SJacques Vidrine 16846d93063SJacques Vidrine 16946d93063SJacques Vidrine int 17046d93063SJacques Vidrine __nss_compat_endgrent(void *retval, void *mdata, va_list ap) 17146d93063SJacques Vidrine { 17246d93063SJacques Vidrine 17346d93063SJacques Vidrine SET_TERMINATOR(group, NULL); 17446d93063SJacques Vidrine ((int (*)(void))mdata)(); 17546d93063SJacques Vidrine return (NS_UNAVAIL); 17646d93063SJacques Vidrine } 17746d93063SJacques Vidrine 17846d93063SJacques Vidrine 17946d93063SJacques Vidrine 18046d93063SJacques Vidrine DECLARE_TERMINATOR(passwd); 18146d93063SJacques Vidrine 18246d93063SJacques Vidrine 18346d93063SJacques Vidrine int 18446d93063SJacques Vidrine __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) 18546d93063SJacques Vidrine { 18646d93063SJacques Vidrine int (*fn)(const char *, struct passwd *, char *, size_t, int *); 18746d93063SJacques Vidrine const char *name; 18846d93063SJacques Vidrine struct passwd *pwd; 18946d93063SJacques Vidrine char *buffer; 19046d93063SJacques Vidrine int *errnop; 19146d93063SJacques Vidrine size_t bufsize; 19246d93063SJacques Vidrine enum nss_status status; 19346d93063SJacques Vidrine 19446d93063SJacques Vidrine fn = mdata; 19546d93063SJacques Vidrine name = va_arg(ap, const char *); 19646d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 19746d93063SJacques Vidrine buffer = va_arg(ap, char *); 19846d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 19946d93063SJacques Vidrine errnop = va_arg(ap, int *); 20046d93063SJacques Vidrine status = fn(name, pwd, buffer, bufsize, errnop); 201c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 20246d93063SJacques Vidrine if (status == NS_SUCCESS) 20346d93063SJacques Vidrine *(struct passwd **)retval = pwd; 204c849849dSJacques Vidrine return (status); 20546d93063SJacques Vidrine } 20646d93063SJacques Vidrine 20746d93063SJacques Vidrine 20846d93063SJacques Vidrine int 20946d93063SJacques Vidrine __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) 21046d93063SJacques Vidrine { 21146d93063SJacques Vidrine int (*fn)(uid_t, struct passwd *, char *, size_t, int *); 21246d93063SJacques Vidrine uid_t uid; 21346d93063SJacques Vidrine struct passwd *pwd; 21446d93063SJacques Vidrine char *buffer; 21546d93063SJacques Vidrine int *errnop; 21646d93063SJacques Vidrine size_t bufsize; 21746d93063SJacques Vidrine enum nss_status status; 21846d93063SJacques Vidrine 21946d93063SJacques Vidrine fn = mdata; 22046d93063SJacques Vidrine uid = va_arg(ap, uid_t); 22146d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 22246d93063SJacques Vidrine buffer = va_arg(ap, char *); 22346d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 22446d93063SJacques Vidrine errnop = va_arg(ap, int *); 22546d93063SJacques Vidrine status = fn(uid, pwd, buffer, bufsize, errnop); 226c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 22746d93063SJacques Vidrine if (status == NS_SUCCESS) 22846d93063SJacques Vidrine *(struct passwd **)retval = pwd; 229c849849dSJacques Vidrine return (status); 23046d93063SJacques Vidrine } 23146d93063SJacques Vidrine 23246d93063SJacques Vidrine 23346d93063SJacques Vidrine int 23446d93063SJacques Vidrine __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) 23546d93063SJacques Vidrine { 23646d93063SJacques Vidrine int (*fn)(struct passwd *, char *, size_t, int *); 23746d93063SJacques Vidrine struct passwd *pwd; 23846d93063SJacques Vidrine char *buffer; 23946d93063SJacques Vidrine int *errnop; 24046d93063SJacques Vidrine size_t bufsize; 24146d93063SJacques Vidrine enum nss_status status; 24246d93063SJacques Vidrine 24346d93063SJacques Vidrine if (CHECK_TERMINATOR(passwd)) 24446d93063SJacques Vidrine return (NS_NOTFOUND); 24546d93063SJacques Vidrine fn = mdata; 24646d93063SJacques Vidrine pwd = va_arg(ap, struct passwd *); 24746d93063SJacques Vidrine buffer = va_arg(ap, char *); 24846d93063SJacques Vidrine bufsize = va_arg(ap, size_t); 24946d93063SJacques Vidrine errnop = va_arg(ap, int *); 25046d93063SJacques Vidrine status = fn(pwd, buffer, bufsize, errnop); 251c849849dSJacques Vidrine status = __nss_compat_result(status, *errnop); 25246d93063SJacques Vidrine if (status == NS_SUCCESS) 25346d93063SJacques Vidrine *(struct passwd **)retval = pwd; 254c849849dSJacques Vidrine else if (status != NS_RETURN) 25546d93063SJacques Vidrine SET_TERMINATOR(passwd, &terminator); 256c849849dSJacques Vidrine return (status); 25746d93063SJacques Vidrine } 25846d93063SJacques Vidrine 25946d93063SJacques Vidrine 26046d93063SJacques Vidrine int 26146d93063SJacques Vidrine __nss_compat_setpwent(void *retval, void *mdata, va_list ap) 26246d93063SJacques Vidrine { 26346d93063SJacques Vidrine 26446d93063SJacques Vidrine SET_TERMINATOR(passwd, NULL); 26546d93063SJacques Vidrine ((int (*)(void))mdata)(); 26646d93063SJacques Vidrine return (NS_UNAVAIL); 26746d93063SJacques Vidrine } 26846d93063SJacques Vidrine 26946d93063SJacques Vidrine 27046d93063SJacques Vidrine int 27146d93063SJacques Vidrine __nss_compat_endpwent(void *retval, void *mdata, va_list ap) 27246d93063SJacques Vidrine { 27346d93063SJacques Vidrine 27446d93063SJacques Vidrine SET_TERMINATOR(passwd, NULL); 27546d93063SJacques Vidrine ((int (*)(void))mdata)(); 27646d93063SJacques Vidrine return (NS_UNAVAIL); 27746d93063SJacques Vidrine } 278