nss_compat.c revision 288014
1/*- 2 * Copyright (c) 2003 Networks Associates Technology, Inc. 3 * All rights reserved. 4 * 5 * This software was developed for the FreeBSD Project by 6 * Jacques A. Vidrine, Safeport Network Services, and Network 7 * Associates Laboratories, the Security Research Division of Network 8 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9 * ("CBOSS"), as part of the DARPA CHATS research program. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * Compatibility shims for the GNU C Library-style nsswitch interface. 33 */ 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD: head/lib/libc/net/nss_compat.c 288014 2015-09-20 04:17:53Z rodrigc $"); 36 37#include "namespace.h" 38#include <sys/param.h> 39#include <errno.h> 40#include <nss.h> 41#include <pthread.h> 42#include <pthread_np.h> 43#include "un-namespace.h" 44#include "libc_private.h" 45 46 47struct group; 48struct passwd; 49 50static int terminator; 51 52#define DECLARE_TERMINATOR(x) \ 53static pthread_key_t _term_key_##x; \ 54static void \ 55_term_create_##x(void) \ 56{ \ 57 (void)_pthread_key_create(&_term_key_##x, NULL); \ 58} \ 59static void *_term_main_##x; \ 60static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT 61 62#define SET_TERMINATOR(x, y) \ 63do { \ 64 if (!__isthreaded || _pthread_main_np()) \ 65 _term_main_##x = (y); \ 66 else { \ 67 (void)_pthread_once(&_term_once_##x, _term_create_##x); \ 68 (void)_pthread_setspecific(_term_key_##x, y); \ 69 } \ 70} while (0) 71 72#define CHECK_TERMINATOR(x) \ 73(!__isthreaded || _pthread_main_np() ? \ 74 (_term_main_##x) : \ 75 ((void)_pthread_once(&_term_once_##x, _term_create_##x), \ 76 _pthread_getspecific(_term_key_##x))) 77 78 79 80DECLARE_TERMINATOR(group); 81 82int __nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap); 83int __nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap); 84int __nss_compat_getgrent_r(void *retval, void *mdata, va_list ap); 85int __nss_compat_setgrent(void *retval, void *mdata, va_list ap); 86int __nss_compat_endgrent(void *retval, void *mdata, va_list ap); 87int __nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap); 88int __nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap); 89int __nss_compat_getpwent_r(void *retval, void *mdata, va_list ap); 90int __nss_compat_setpwent(void *retval, void *mdata, va_list ap); 91int __nss_compat_endpwent(void *retval, void *mdata, va_list ap); 92 93int 94__nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap) 95{ 96 int (*fn)(const char *, struct group *, char *, size_t, int *); 97 const char *name; 98 struct group *grp; 99 char *buffer; 100 int *errnop; 101 size_t bufsize; 102 enum nss_status status; 103 104 fn = mdata; 105 name = va_arg(ap, const char *); 106 grp = va_arg(ap, struct group *); 107 buffer = va_arg(ap, char *); 108 bufsize = va_arg(ap, size_t); 109 errnop = va_arg(ap, int *); 110 status = fn(name, grp, buffer, bufsize, errnop); 111 status = __nss_compat_result(status, *errnop); 112 if (status == NS_SUCCESS) 113 *(struct group **)retval = grp; 114 return (status); 115} 116 117 118int 119__nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap) 120{ 121 int (*fn)(gid_t, struct group *, char *, size_t, int *); 122 gid_t gid; 123 struct group *grp; 124 char *buffer; 125 int *errnop; 126 size_t bufsize; 127 enum nss_status status; 128 129 fn = mdata; 130 gid = va_arg(ap, gid_t); 131 grp = va_arg(ap, struct group *); 132 buffer = va_arg(ap, char *); 133 bufsize = va_arg(ap, size_t); 134 errnop = va_arg(ap, int *); 135 status = fn(gid, grp, buffer, bufsize, errnop); 136 status = __nss_compat_result(status, *errnop); 137 if (status == NS_SUCCESS) 138 *(struct group **)retval = grp; 139 return (status); 140} 141 142 143int 144__nss_compat_getgrent_r(void *retval, void *mdata, va_list ap) 145{ 146 int (*fn)(struct group *, char *, size_t, int *); 147 struct group *grp; 148 char *buffer; 149 int *errnop; 150 size_t bufsize; 151 enum nss_status status; 152 153 if (CHECK_TERMINATOR(group)) 154 return (NS_NOTFOUND); 155 fn = mdata; 156 grp = va_arg(ap, struct group *); 157 buffer = va_arg(ap, char *); 158 bufsize = va_arg(ap, size_t); 159 errnop = va_arg(ap, int *); 160 status = fn(grp, buffer, bufsize, errnop); 161 status = __nss_compat_result(status, *errnop); 162 if (status == NS_SUCCESS) 163 *(struct group **)retval = grp; 164 else if (status != NS_RETURN) 165 SET_TERMINATOR(group, &terminator); 166 return (status); 167} 168 169 170int 171__nss_compat_setgrent(void *retval, void *mdata, va_list ap) 172{ 173 174 SET_TERMINATOR(group, NULL); 175 ((int (*)(void))mdata)(); 176 return (NS_UNAVAIL); 177} 178 179 180int 181__nss_compat_endgrent(void *retval, void *mdata, va_list ap) 182{ 183 184 SET_TERMINATOR(group, NULL); 185 ((int (*)(void))mdata)(); 186 return (NS_UNAVAIL); 187} 188 189 190 191DECLARE_TERMINATOR(passwd); 192 193 194int 195__nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap) 196{ 197 int (*fn)(const char *, struct passwd *, char *, size_t, int *); 198 const char *name; 199 struct passwd *pwd; 200 char *buffer; 201 int *errnop; 202 size_t bufsize; 203 enum nss_status status; 204 205 fn = mdata; 206 name = va_arg(ap, const char *); 207 pwd = va_arg(ap, struct passwd *); 208 buffer = va_arg(ap, char *); 209 bufsize = va_arg(ap, size_t); 210 errnop = va_arg(ap, int *); 211 status = fn(name, pwd, buffer, bufsize, errnop); 212 status = __nss_compat_result(status, *errnop); 213 if (status == NS_SUCCESS) 214 *(struct passwd **)retval = pwd; 215 return (status); 216} 217 218 219int 220__nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap) 221{ 222 int (*fn)(uid_t, struct passwd *, char *, size_t, int *); 223 uid_t uid; 224 struct passwd *pwd; 225 char *buffer; 226 int *errnop; 227 size_t bufsize; 228 enum nss_status status; 229 230 fn = mdata; 231 uid = va_arg(ap, uid_t); 232 pwd = va_arg(ap, struct passwd *); 233 buffer = va_arg(ap, char *); 234 bufsize = va_arg(ap, size_t); 235 errnop = va_arg(ap, int *); 236 status = fn(uid, pwd, buffer, bufsize, errnop); 237 status = __nss_compat_result(status, *errnop); 238 if (status == NS_SUCCESS) 239 *(struct passwd **)retval = pwd; 240 return (status); 241} 242 243 244int 245__nss_compat_getpwent_r(void *retval, void *mdata, va_list ap) 246{ 247 int (*fn)(struct passwd *, char *, size_t, int *); 248 struct passwd *pwd; 249 char *buffer; 250 int *errnop; 251 size_t bufsize; 252 enum nss_status status; 253 254 if (CHECK_TERMINATOR(passwd)) 255 return (NS_NOTFOUND); 256 fn = mdata; 257 pwd = va_arg(ap, struct passwd *); 258 buffer = va_arg(ap, char *); 259 bufsize = va_arg(ap, size_t); 260 errnop = va_arg(ap, int *); 261 status = fn(pwd, buffer, bufsize, errnop); 262 status = __nss_compat_result(status, *errnop); 263 if (status == NS_SUCCESS) 264 *(struct passwd **)retval = pwd; 265 else if (status != NS_RETURN) 266 SET_TERMINATOR(passwd, &terminator); 267 return (status); 268} 269 270 271int 272__nss_compat_setpwent(void *retval, void *mdata, va_list ap) 273{ 274 275 SET_TERMINATOR(passwd, NULL); 276 ((int (*)(void))mdata)(); 277 return (NS_UNAVAIL); 278} 279 280 281int 282__nss_compat_endpwent(void *retval, void *mdata, va_list ap) 283{ 284 285 SET_TERMINATOR(passwd, NULL); 286 ((int (*)(void))mdata)(); 287 return (NS_UNAVAIL); 288} 289