1113595Snectar/*- 2113595Snectar * Copyright (c) 2003 Networks Associates Technology, Inc. 3113595Snectar * All rights reserved. 4113595Snectar * 5113595Snectar * This software was developed for the FreeBSD Project by 6113595Snectar * Jacques A. Vidrine, Safeport Network Services, and Network 7113595Snectar * Associates Laboratories, the Security Research Division of Network 8113595Snectar * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9113595Snectar * ("CBOSS"), as part of the DARPA CHATS research program. 10113595Snectar * 11113595Snectar * Redistribution and use in source and binary forms, with or without 12113595Snectar * modification, are permitted provided that the following conditions 13113595Snectar * are met: 14113595Snectar * 1. Redistributions of source code must retain the above copyright 15113595Snectar * notice, this list of conditions and the following disclaimer. 16113595Snectar * 2. Redistributions in binary form must reproduce the above copyright 17113595Snectar * notice, this list of conditions and the following disclaimer in the 18113595Snectar * documentation and/or other materials provided with the distribution. 19113595Snectar * 20113595Snectar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21113595Snectar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22113595Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23113595Snectar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24113595Snectar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25113595Snectar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26113595Snectar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27113595Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28113595Snectar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29113595Snectar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30113595Snectar * SUCH DAMAGE. 31113595Snectar * 32113595Snectar * Compatibility shims for the GNU C Library-style nsswitch interface. 33113595Snectar */ 34113595Snectar#include <sys/cdefs.h> 35113595Snectar__FBSDID("$FreeBSD$"); 36113595Snectar 37113595Snectar#include "namespace.h" 38113595Snectar#include <sys/param.h> 39124289Snectar#include <errno.h> 40113595Snectar#include <nss.h> 41113595Snectar#include <pthread.h> 42113595Snectar#include <pthread_np.h> 43113595Snectar#include "un-namespace.h" 44127625Snectar#include "libc_private.h" 45113595Snectar 46113595Snectar 47113595Snectarstruct group; 48113595Snectarstruct passwd; 49113595Snectar 50113595Snectarstatic int terminator; 51113595Snectar 52113595Snectar#define DECLARE_TERMINATOR(x) \ 53113595Snectarstatic pthread_key_t _term_key_##x; \ 54113595Snectarstatic void \ 55113595Snectar_term_create_##x(void) \ 56113595Snectar{ \ 57113595Snectar (void)_pthread_key_create(&_term_key_##x, NULL); \ 58113595Snectar} \ 59113595Snectarstatic void *_term_main_##x; \ 60113595Snectarstatic pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT 61113595Snectar 62113595Snectar#define SET_TERMINATOR(x, y) \ 63113595Snectardo { \ 64127625Snectar if (!__isthreaded || _pthread_main_np()) \ 65113595Snectar _term_main_##x = (y); \ 66113595Snectar else { \ 67113595Snectar (void)_pthread_once(&_term_once_##x, _term_create_##x); \ 68113595Snectar (void)_pthread_setspecific(_term_key_##x, y); \ 69113595Snectar } \ 70113595Snectar} while (0) 71113595Snectar 72113595Snectar#define CHECK_TERMINATOR(x) \ 73127625Snectar(!__isthreaded || _pthread_main_np() ? \ 74113595Snectar (_term_main_##x) : \ 75113595Snectar ((void)_pthread_once(&_term_once_##x, _term_create_##x), \ 76113595Snectar _pthread_getspecific(_term_key_##x))) 77113595Snectar 78113595Snectar 79113595Snectar 80113595SnectarDECLARE_TERMINATOR(group); 81113595Snectar 82113595Snectar 83113595Snectarint 84113595Snectar__nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) 85113595Snectar{ 86113595Snectar int (*fn)(const char *, struct group *, char *, size_t, int *); 87113595Snectar const char *name; 88113595Snectar struct group *grp; 89113595Snectar char *buffer; 90113595Snectar int *errnop; 91113595Snectar size_t bufsize; 92113595Snectar enum nss_status status; 93113595Snectar 94113595Snectar fn = mdata; 95113595Snectar name = va_arg(ap, const char *); 96113595Snectar grp = va_arg(ap, struct group *); 97113595Snectar buffer = va_arg(ap, char *); 98113595Snectar bufsize = va_arg(ap, size_t); 99113595Snectar errnop = va_arg(ap, int *); 100113595Snectar status = fn(name, grp, buffer, bufsize, errnop); 101124289Snectar status = __nss_compat_result(status, *errnop); 102113595Snectar if (status == NS_SUCCESS) 103113595Snectar *(struct group **)retval = grp; 104124289Snectar return (status); 105113595Snectar} 106113595Snectar 107113595Snectar 108113595Snectarint 109113595Snectar__nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) 110113595Snectar{ 111113595Snectar int (*fn)(gid_t, struct group *, char *, size_t, int *); 112113595Snectar gid_t gid; 113113595Snectar struct group *grp; 114113595Snectar char *buffer; 115113595Snectar int *errnop; 116113595Snectar size_t bufsize; 117113595Snectar enum nss_status status; 118113595Snectar 119113595Snectar fn = mdata; 120113595Snectar gid = va_arg(ap, gid_t); 121113595Snectar grp = va_arg(ap, struct group *); 122113595Snectar buffer = va_arg(ap, char *); 123113595Snectar bufsize = va_arg(ap, size_t); 124113595Snectar errnop = va_arg(ap, int *); 125113595Snectar status = fn(gid, grp, buffer, bufsize, errnop); 126124289Snectar status = __nss_compat_result(status, *errnop); 127113595Snectar if (status == NS_SUCCESS) 128113595Snectar *(struct group **)retval = grp; 129124289Snectar return (status); 130113595Snectar} 131113595Snectar 132113595Snectar 133113595Snectarint 134113595Snectar__nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) 135113595Snectar{ 136113595Snectar int (*fn)(struct group *, char *, size_t, int *); 137113595Snectar struct group *grp; 138113595Snectar char *buffer; 139113595Snectar int *errnop; 140113595Snectar size_t bufsize; 141113595Snectar enum nss_status status; 142113595Snectar 143113595Snectar if (CHECK_TERMINATOR(group)) 144113595Snectar return (NS_NOTFOUND); 145113595Snectar fn = mdata; 146113595Snectar grp = va_arg(ap, struct group *); 147113595Snectar buffer = va_arg(ap, char *); 148113595Snectar bufsize = va_arg(ap, size_t); 149113595Snectar errnop = va_arg(ap, int *); 150113595Snectar status = fn(grp, buffer, bufsize, errnop); 151124289Snectar status = __nss_compat_result(status, *errnop); 152113595Snectar if (status == NS_SUCCESS) 153113595Snectar *(struct group **)retval = grp; 154124289Snectar else if (status != NS_RETURN) 155113595Snectar SET_TERMINATOR(group, &terminator); 156124289Snectar return (status); 157113595Snectar} 158113595Snectar 159113595Snectar 160113595Snectarint 161113595Snectar__nss_compat_setgrent(void *retval, void *mdata, va_list ap) 162113595Snectar{ 163113595Snectar 164113595Snectar SET_TERMINATOR(group, NULL); 165113595Snectar ((int (*)(void))mdata)(); 166113595Snectar return (NS_UNAVAIL); 167113595Snectar} 168113595Snectar 169113595Snectar 170113595Snectarint 171113595Snectar__nss_compat_endgrent(void *retval, void *mdata, va_list ap) 172113595Snectar{ 173113595Snectar 174113595Snectar SET_TERMINATOR(group, NULL); 175113595Snectar ((int (*)(void))mdata)(); 176113595Snectar return (NS_UNAVAIL); 177113595Snectar} 178113595Snectar 179113595Snectar 180113595Snectar 181113595SnectarDECLARE_TERMINATOR(passwd); 182113595Snectar 183113595Snectar 184113595Snectarint 185113595Snectar__nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) 186113595Snectar{ 187113595Snectar int (*fn)(const char *, struct passwd *, char *, size_t, int *); 188113595Snectar const char *name; 189113595Snectar struct passwd *pwd; 190113595Snectar char *buffer; 191113595Snectar int *errnop; 192113595Snectar size_t bufsize; 193113595Snectar enum nss_status status; 194113595Snectar 195113595Snectar fn = mdata; 196113595Snectar name = va_arg(ap, const char *); 197113595Snectar pwd = va_arg(ap, struct passwd *); 198113595Snectar buffer = va_arg(ap, char *); 199113595Snectar bufsize = va_arg(ap, size_t); 200113595Snectar errnop = va_arg(ap, int *); 201113595Snectar status = fn(name, pwd, buffer, bufsize, errnop); 202124289Snectar status = __nss_compat_result(status, *errnop); 203113595Snectar if (status == NS_SUCCESS) 204113595Snectar *(struct passwd **)retval = pwd; 205124289Snectar return (status); 206113595Snectar} 207113595Snectar 208113595Snectar 209113595Snectarint 210113595Snectar__nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) 211113595Snectar{ 212113595Snectar int (*fn)(uid_t, struct passwd *, char *, size_t, int *); 213113595Snectar uid_t uid; 214113595Snectar struct passwd *pwd; 215113595Snectar char *buffer; 216113595Snectar int *errnop; 217113595Snectar size_t bufsize; 218113595Snectar enum nss_status status; 219113595Snectar 220113595Snectar fn = mdata; 221113595Snectar uid = va_arg(ap, uid_t); 222113595Snectar pwd = va_arg(ap, struct passwd *); 223113595Snectar buffer = va_arg(ap, char *); 224113595Snectar bufsize = va_arg(ap, size_t); 225113595Snectar errnop = va_arg(ap, int *); 226113595Snectar status = fn(uid, pwd, buffer, bufsize, errnop); 227124289Snectar status = __nss_compat_result(status, *errnop); 228113595Snectar if (status == NS_SUCCESS) 229113595Snectar *(struct passwd **)retval = pwd; 230124289Snectar return (status); 231113595Snectar} 232113595Snectar 233113595Snectar 234113595Snectarint 235113595Snectar__nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) 236113595Snectar{ 237113595Snectar int (*fn)(struct passwd *, char *, size_t, int *); 238113595Snectar struct passwd *pwd; 239113595Snectar char *buffer; 240113595Snectar int *errnop; 241113595Snectar size_t bufsize; 242113595Snectar enum nss_status status; 243113595Snectar 244113595Snectar if (CHECK_TERMINATOR(passwd)) 245113595Snectar return (NS_NOTFOUND); 246113595Snectar fn = mdata; 247113595Snectar pwd = va_arg(ap, struct passwd *); 248113595Snectar buffer = va_arg(ap, char *); 249113595Snectar bufsize = va_arg(ap, size_t); 250113595Snectar errnop = va_arg(ap, int *); 251113595Snectar status = fn(pwd, buffer, bufsize, errnop); 252124289Snectar status = __nss_compat_result(status, *errnop); 253113595Snectar if (status == NS_SUCCESS) 254113595Snectar *(struct passwd **)retval = pwd; 255124289Snectar else if (status != NS_RETURN) 256113595Snectar SET_TERMINATOR(passwd, &terminator); 257124289Snectar return (status); 258113595Snectar} 259113595Snectar 260113595Snectar 261113595Snectarint 262113595Snectar__nss_compat_setpwent(void *retval, void *mdata, va_list ap) 263113595Snectar{ 264113595Snectar 265113595Snectar SET_TERMINATOR(passwd, NULL); 266113595Snectar ((int (*)(void))mdata)(); 267113595Snectar return (NS_UNAVAIL); 268113595Snectar} 269113595Snectar 270113595Snectar 271113595Snectarint 272113595Snectar__nss_compat_endpwent(void *retval, void *mdata, va_list ap) 273113595Snectar{ 274113595Snectar 275113595Snectar SET_TERMINATOR(passwd, NULL); 276113595Snectar ((int (*)(void))mdata)(); 277113595Snectar return (NS_UNAVAIL); 278113595Snectar} 279