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 82288014Srodrigcint __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap); 83288014Srodrigcint __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap); 84288014Srodrigcint __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap); 85288014Srodrigcint __nss_compat_setgrent(void *retval, void *mdata, va_list ap); 86288014Srodrigcint __nss_compat_endgrent(void *retval, void *mdata, va_list ap); 87288014Srodrigcint __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap); 88288014Srodrigcint __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap); 89288014Srodrigcint __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap); 90288014Srodrigcint __nss_compat_setpwent(void *retval, void *mdata, va_list ap); 91288014Srodrigcint __nss_compat_endpwent(void *retval, void *mdata, va_list ap); 92113595Snectar 93113595Snectarint 94113595Snectar__nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) 95113595Snectar{ 96113595Snectar int (*fn)(const char *, struct group *, char *, size_t, int *); 97113595Snectar const char *name; 98113595Snectar struct group *grp; 99113595Snectar char *buffer; 100113595Snectar int *errnop; 101113595Snectar size_t bufsize; 102113595Snectar enum nss_status status; 103113595Snectar 104113595Snectar fn = mdata; 105113595Snectar name = va_arg(ap, const char *); 106113595Snectar grp = va_arg(ap, struct group *); 107113595Snectar buffer = va_arg(ap, char *); 108113595Snectar bufsize = va_arg(ap, size_t); 109113595Snectar errnop = va_arg(ap, int *); 110113595Snectar status = fn(name, grp, buffer, bufsize, errnop); 111124289Snectar status = __nss_compat_result(status, *errnop); 112113595Snectar if (status == NS_SUCCESS) 113113595Snectar *(struct group **)retval = grp; 114124289Snectar return (status); 115113595Snectar} 116113595Snectar 117113595Snectar 118113595Snectarint 119113595Snectar__nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) 120113595Snectar{ 121113595Snectar int (*fn)(gid_t, struct group *, char *, size_t, int *); 122113595Snectar gid_t gid; 123113595Snectar struct group *grp; 124113595Snectar char *buffer; 125113595Snectar int *errnop; 126113595Snectar size_t bufsize; 127113595Snectar enum nss_status status; 128113595Snectar 129113595Snectar fn = mdata; 130113595Snectar gid = va_arg(ap, gid_t); 131113595Snectar grp = va_arg(ap, struct group *); 132113595Snectar buffer = va_arg(ap, char *); 133113595Snectar bufsize = va_arg(ap, size_t); 134113595Snectar errnop = va_arg(ap, int *); 135113595Snectar status = fn(gid, grp, buffer, bufsize, errnop); 136124289Snectar status = __nss_compat_result(status, *errnop); 137113595Snectar if (status == NS_SUCCESS) 138113595Snectar *(struct group **)retval = grp; 139124289Snectar return (status); 140113595Snectar} 141113595Snectar 142113595Snectar 143113595Snectarint 144113595Snectar__nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) 145113595Snectar{ 146113595Snectar int (*fn)(struct group *, char *, size_t, int *); 147113595Snectar struct group *grp; 148113595Snectar char *buffer; 149113595Snectar int *errnop; 150113595Snectar size_t bufsize; 151113595Snectar enum nss_status status; 152113595Snectar 153113595Snectar if (CHECK_TERMINATOR(group)) 154113595Snectar return (NS_NOTFOUND); 155113595Snectar fn = mdata; 156113595Snectar grp = va_arg(ap, struct group *); 157113595Snectar buffer = va_arg(ap, char *); 158113595Snectar bufsize = va_arg(ap, size_t); 159113595Snectar errnop = va_arg(ap, int *); 160113595Snectar status = fn(grp, buffer, bufsize, errnop); 161124289Snectar status = __nss_compat_result(status, *errnop); 162113595Snectar if (status == NS_SUCCESS) 163113595Snectar *(struct group **)retval = grp; 164124289Snectar else if (status != NS_RETURN) 165113595Snectar SET_TERMINATOR(group, &terminator); 166124289Snectar return (status); 167113595Snectar} 168113595Snectar 169113595Snectar 170113595Snectarint 171113595Snectar__nss_compat_setgrent(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 180113595Snectarint 181113595Snectar__nss_compat_endgrent(void *retval, void *mdata, va_list ap) 182113595Snectar{ 183113595Snectar 184113595Snectar SET_TERMINATOR(group, NULL); 185113595Snectar ((int (*)(void))mdata)(); 186113595Snectar return (NS_UNAVAIL); 187113595Snectar} 188113595Snectar 189113595Snectar 190113595Snectar 191113595SnectarDECLARE_TERMINATOR(passwd); 192113595Snectar 193113595Snectar 194113595Snectarint 195113595Snectar__nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) 196113595Snectar{ 197113595Snectar int (*fn)(const char *, struct passwd *, char *, size_t, int *); 198113595Snectar const char *name; 199113595Snectar struct passwd *pwd; 200113595Snectar char *buffer; 201113595Snectar int *errnop; 202113595Snectar size_t bufsize; 203113595Snectar enum nss_status status; 204113595Snectar 205113595Snectar fn = mdata; 206113595Snectar name = va_arg(ap, const char *); 207113595Snectar pwd = va_arg(ap, struct passwd *); 208113595Snectar buffer = va_arg(ap, char *); 209113595Snectar bufsize = va_arg(ap, size_t); 210113595Snectar errnop = va_arg(ap, int *); 211113595Snectar status = fn(name, pwd, buffer, bufsize, errnop); 212124289Snectar status = __nss_compat_result(status, *errnop); 213113595Snectar if (status == NS_SUCCESS) 214113595Snectar *(struct passwd **)retval = pwd; 215124289Snectar return (status); 216113595Snectar} 217113595Snectar 218113595Snectar 219113595Snectarint 220113595Snectar__nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) 221113595Snectar{ 222113595Snectar int (*fn)(uid_t, struct passwd *, char *, size_t, int *); 223113595Snectar uid_t uid; 224113595Snectar struct passwd *pwd; 225113595Snectar char *buffer; 226113595Snectar int *errnop; 227113595Snectar size_t bufsize; 228113595Snectar enum nss_status status; 229113595Snectar 230113595Snectar fn = mdata; 231113595Snectar uid = va_arg(ap, uid_t); 232113595Snectar pwd = va_arg(ap, struct passwd *); 233113595Snectar buffer = va_arg(ap, char *); 234113595Snectar bufsize = va_arg(ap, size_t); 235113595Snectar errnop = va_arg(ap, int *); 236113595Snectar status = fn(uid, pwd, buffer, bufsize, errnop); 237124289Snectar status = __nss_compat_result(status, *errnop); 238113595Snectar if (status == NS_SUCCESS) 239113595Snectar *(struct passwd **)retval = pwd; 240124289Snectar return (status); 241113595Snectar} 242113595Snectar 243113595Snectar 244113595Snectarint 245113595Snectar__nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) 246113595Snectar{ 247113595Snectar int (*fn)(struct passwd *, char *, size_t, int *); 248113595Snectar struct passwd *pwd; 249113595Snectar char *buffer; 250113595Snectar int *errnop; 251113595Snectar size_t bufsize; 252113595Snectar enum nss_status status; 253113595Snectar 254113595Snectar if (CHECK_TERMINATOR(passwd)) 255113595Snectar return (NS_NOTFOUND); 256113595Snectar fn = mdata; 257113595Snectar pwd = va_arg(ap, struct passwd *); 258113595Snectar buffer = va_arg(ap, char *); 259113595Snectar bufsize = va_arg(ap, size_t); 260113595Snectar errnop = va_arg(ap, int *); 261113595Snectar status = fn(pwd, buffer, bufsize, errnop); 262124289Snectar status = __nss_compat_result(status, *errnop); 263113595Snectar if (status == NS_SUCCESS) 264113595Snectar *(struct passwd **)retval = pwd; 265124289Snectar else if (status != NS_RETURN) 266113595Snectar SET_TERMINATOR(passwd, &terminator); 267124289Snectar return (status); 268113595Snectar} 269113595Snectar 270113595Snectar 271113595Snectarint 272113595Snectar__nss_compat_setpwent(void *retval, void *mdata, va_list ap) 273113595Snectar{ 274113595Snectar 275113595Snectar SET_TERMINATOR(passwd, NULL); 276113595Snectar ((int (*)(void))mdata)(); 277113595Snectar return (NS_UNAVAIL); 278113595Snectar} 279113595Snectar 280113595Snectar 281113595Snectarint 282113595Snectar__nss_compat_endpwent(void *retval, void *mdata, va_list ap) 283113595Snectar{ 284113595Snectar 285113595Snectar SET_TERMINATOR(passwd, NULL); 286113595Snectar ((int (*)(void))mdata)(); 287113595Snectar return (NS_UNAVAIL); 288113595Snectar} 289