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