1 1.35 rillig /* $NetBSD: pwcache.c,v 1.35 2024/05/12 10:58:58 rillig Exp $ */ 2 1.4 cgd 3 1.10 mycroft /*- 4 1.25 agc * Copyright (c) 1992 Keith Muller. 5 1.10 mycroft * Copyright (c) 1992, 1993 6 1.4 cgd * The Regents of the University of California. All rights reserved. 7 1.1 cgd * 8 1.10 mycroft * This code is derived from software contributed to Berkeley by 9 1.10 mycroft * Keith Muller of the University of California, San Diego. 10 1.10 mycroft * 11 1.1 cgd * Redistribution and use in source and binary forms, with or without 12 1.1 cgd * modification, are permitted provided that the following conditions 13 1.1 cgd * are met: 14 1.1 cgd * 1. Redistributions of source code must retain the above copyright 15 1.1 cgd * notice, this list of conditions and the following disclaimer. 16 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 cgd * notice, this list of conditions and the following disclaimer in the 18 1.1 cgd * documentation and/or other materials provided with the distribution. 19 1.24 agc * 3. Neither the name of the University nor the names of its contributors 20 1.24 agc * may be used to endorse or promote products derived from this software 21 1.24 agc * without specific prior written permission. 22 1.24 agc * 23 1.24 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 1.24 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.24 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.24 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 1.24 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 1.24 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 1.24 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 1.24 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.24 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 1.24 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 1.24 agc * SUCH DAMAGE. 34 1.24 agc */ 35 1.24 agc 36 1.24 agc /*- 37 1.17 lukem * Copyright (c) 2002 The NetBSD Foundation, Inc. 38 1.17 lukem * All rights reserved. 39 1.17 lukem * 40 1.17 lukem * Redistribution and use in source and binary forms, with or without 41 1.17 lukem * modification, are permitted provided that the following conditions 42 1.17 lukem * are met: 43 1.17 lukem * 1. Redistributions of source code must retain the above copyright 44 1.17 lukem * notice, this list of conditions and the following disclaimer. 45 1.17 lukem * 2. Redistributions in binary form must reproduce the above copyright 46 1.17 lukem * notice, this list of conditions and the following disclaimer in the 47 1.17 lukem * documentation and/or other materials provided with the distribution. 48 1.17 lukem * 49 1.17 lukem * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 50 1.17 lukem * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 51 1.17 lukem * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 52 1.17 lukem * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 53 1.17 lukem * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 54 1.17 lukem * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 55 1.17 lukem * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 56 1.17 lukem * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 57 1.17 lukem * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 58 1.17 lukem * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 59 1.17 lukem * POSSIBILITY OF SUCH DAMAGE. 60 1.17 lukem */ 61 1.17 lukem 62 1.27 sjg #if HAVE_NBTOOL_CONFIG_H 63 1.27 sjg #include "nbtool_config.h" 64 1.28 thorpej /* 65 1.28 thorpej * XXX Undefine the renames of these functions so that we don't 66 1.28 thorpej * XXX rename the versions found in the host's <pwd.h> by mistake! 67 1.28 thorpej */ 68 1.28 thorpej #undef group_from_gid 69 1.28 thorpej #undef user_from_uid 70 1.27 sjg #endif 71 1.27 sjg 72 1.7 christos #include <sys/cdefs.h> 73 1.15 msaitoh #if defined(LIBC_SCCS) && !defined(lint) 74 1.4 cgd #if 0 75 1.10 mycroft static char sccsid[] = "@(#)cache.c 8.1 (Berkeley) 5/31/93"; 76 1.4 cgd #else 77 1.35 rillig __RCSID("$NetBSD: pwcache.c,v 1.35 2024/05/12 10:58:58 rillig Exp $"); 78 1.4 cgd #endif 79 1.15 msaitoh #endif /* LIBC_SCCS and not lint */ 80 1.1 cgd 81 1.8 jtc #include "namespace.h" 82 1.10 mycroft 83 1.1 cgd #include <sys/types.h> 84 1.6 sommerfe #include <sys/param.h> 85 1.4 cgd 86 1.13 lukem #include <assert.h> 87 1.4 cgd #include <grp.h> 88 1.1 cgd #include <pwd.h> 89 1.1 cgd #include <stdio.h> 90 1.10 mycroft #include <stdlib.h> 91 1.5 jtc #include <string.h> 92 1.10 mycroft #include <unistd.h> 93 1.10 mycroft 94 1.28 thorpej #if HAVE_NBTOOL_CONFIG_H 95 1.28 thorpej /* XXX Now, re-apply the renaming that we undid above. */ 96 1.28 thorpej #define group_from_gid __nbcompat_group_from_gid 97 1.28 thorpej #define user_from_uid __nbcompat_user_from_uid 98 1.28 thorpej #endif 99 1.28 thorpej 100 1.8 jtc #ifdef __weak_alias 101 1.14 mycroft __weak_alias(user_from_uid,_user_from_uid) 102 1.14 mycroft __weak_alias(group_from_gid,_group_from_gid) 103 1.17 lukem __weak_alias(pwcache_groupdb,_pwcache_groupdb) 104 1.8 jtc #endif 105 1.19 lukem 106 1.29 jmc #if !HAVE_PWCACHE_USERDB || HAVE_NBTOOL_CONFIG_H 107 1.19 lukem #include "pwcache.h" 108 1.1 cgd 109 1.10 mycroft /* 110 1.10 mycroft * routines that control user, group, uid and gid caches (for the archive 111 1.10 mycroft * member print routine). 112 1.10 mycroft * IMPORTANT: 113 1.10 mycroft * these routines cache BOTH hits and misses, a major performance improvement 114 1.10 mycroft */ 115 1.10 mycroft 116 1.17 lukem /* 117 1.17 lukem * function pointers to various name lookup routines. 118 1.17 lukem * these may be changed as necessary. 119 1.17 lukem */ 120 1.17 lukem static int (*_pwcache_setgroupent)(int) = setgroupent; 121 1.17 lukem static void (*_pwcache_endgrent)(void) = endgrent; 122 1.17 lukem static struct group * (*_pwcache_getgrnam)(const char *) = getgrnam; 123 1.17 lukem static struct group * (*_pwcache_getgrgid)(gid_t) = getgrgid; 124 1.17 lukem static int (*_pwcache_setpassent)(int) = setpassent; 125 1.17 lukem static void (*_pwcache_endpwent)(void) = endpwent; 126 1.17 lukem static struct passwd * (*_pwcache_getpwnam)(const char *) = getpwnam; 127 1.17 lukem static struct passwd * (*_pwcache_getpwuid)(uid_t) = getpwuid; 128 1.17 lukem 129 1.17 lukem /* 130 1.17 lukem * internal state 131 1.17 lukem */ 132 1.17 lukem static int pwopn; /* is password file open */ 133 1.17 lukem static int gropn; /* is group file open */ 134 1.17 lukem static UIDC **uidtb; /* uid to name cache */ 135 1.17 lukem static GIDC **gidtb; /* gid to name cache */ 136 1.17 lukem static UIDC **usrtb; /* user name to uid cache */ 137 1.17 lukem static GIDC **grptb; /* group name to gid cache */ 138 1.17 lukem 139 1.17 lukem static int uidtb_fail; /* uidtb_start() failed ? */ 140 1.17 lukem static int gidtb_fail; /* gidtb_start() failed ? */ 141 1.17 lukem static int usrtb_fail; /* usrtb_start() failed ? */ 142 1.17 lukem static int grptb_fail; /* grptb_start() failed ? */ 143 1.17 lukem 144 1.17 lukem 145 1.17 lukem static u_int st_hash(const char *, size_t, int); 146 1.17 lukem static int uidtb_start(void); 147 1.17 lukem static int gidtb_start(void); 148 1.17 lukem static int usrtb_start(void); 149 1.17 lukem static int grptb_start(void); 150 1.17 lukem 151 1.10 mycroft 152 1.10 mycroft static u_int 153 1.16 lukem st_hash(const char *name, size_t len, int tabsz) 154 1.10 mycroft { 155 1.10 mycroft u_int key = 0; 156 1.10 mycroft 157 1.13 lukem _DIAGASSERT(name != NULL); 158 1.13 lukem 159 1.10 mycroft while (len--) { 160 1.10 mycroft key += *name++; 161 1.10 mycroft key = (key << 8) | (key >> 24); 162 1.10 mycroft } 163 1.10 mycroft 164 1.10 mycroft return (key % tabsz); 165 1.10 mycroft } 166 1.10 mycroft 167 1.10 mycroft /* 168 1.10 mycroft * uidtb_start 169 1.32 msaitoh * creates an empty uidtb 170 1.10 mycroft * Return: 171 1.10 mycroft * 0 if ok, -1 otherwise 172 1.10 mycroft */ 173 1.10 mycroft static int 174 1.10 mycroft uidtb_start(void) 175 1.10 mycroft { 176 1.10 mycroft 177 1.10 mycroft if (uidtb != NULL) 178 1.10 mycroft return (0); 179 1.17 lukem if (uidtb_fail) 180 1.10 mycroft return (-1); 181 1.10 mycroft if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) { 182 1.17 lukem ++uidtb_fail; 183 1.10 mycroft return (-1); 184 1.10 mycroft } 185 1.10 mycroft return (0); 186 1.10 mycroft } 187 1.10 mycroft 188 1.10 mycroft /* 189 1.10 mycroft * gidtb_start 190 1.32 msaitoh * creates an empty gidtb 191 1.10 mycroft * Return: 192 1.10 mycroft * 0 if ok, -1 otherwise 193 1.10 mycroft */ 194 1.17 lukem static int 195 1.10 mycroft gidtb_start(void) 196 1.10 mycroft { 197 1.10 mycroft 198 1.10 mycroft if (gidtb != NULL) 199 1.10 mycroft return (0); 200 1.17 lukem if (gidtb_fail) 201 1.10 mycroft return (-1); 202 1.10 mycroft if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) { 203 1.17 lukem ++gidtb_fail; 204 1.10 mycroft return (-1); 205 1.10 mycroft } 206 1.10 mycroft return (0); 207 1.10 mycroft } 208 1.10 mycroft 209 1.10 mycroft /* 210 1.10 mycroft * usrtb_start 211 1.32 msaitoh * creates an empty usrtb 212 1.10 mycroft * Return: 213 1.10 mycroft * 0 if ok, -1 otherwise 214 1.10 mycroft */ 215 1.17 lukem static int 216 1.10 mycroft usrtb_start(void) 217 1.10 mycroft { 218 1.10 mycroft 219 1.10 mycroft if (usrtb != NULL) 220 1.10 mycroft return (0); 221 1.17 lukem if (usrtb_fail) 222 1.10 mycroft return (-1); 223 1.10 mycroft if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) { 224 1.17 lukem ++usrtb_fail; 225 1.10 mycroft return (-1); 226 1.10 mycroft } 227 1.10 mycroft return (0); 228 1.10 mycroft } 229 1.10 mycroft 230 1.10 mycroft /* 231 1.10 mycroft * grptb_start 232 1.32 msaitoh * creates an empty grptb 233 1.10 mycroft * Return: 234 1.10 mycroft * 0 if ok, -1 otherwise 235 1.10 mycroft */ 236 1.17 lukem static int 237 1.10 mycroft grptb_start(void) 238 1.10 mycroft { 239 1.10 mycroft 240 1.10 mycroft if (grptb != NULL) 241 1.10 mycroft return (0); 242 1.17 lukem if (grptb_fail) 243 1.10 mycroft return (-1); 244 1.10 mycroft if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) { 245 1.17 lukem ++grptb_fail; 246 1.10 mycroft return (-1); 247 1.10 mycroft } 248 1.10 mycroft return (0); 249 1.10 mycroft } 250 1.10 mycroft 251 1.10 mycroft /* 252 1.11 mycroft * user_from_uid() 253 1.16 lukem * caches the name (if any) for the uid. If noname clear, we always 254 1.26 simonb * return the stored name (if valid or invalid match). 255 1.16 lukem * We use a simple hash table. 256 1.10 mycroft * Return 257 1.10 mycroft * Pointer to stored name (or a empty string) 258 1.10 mycroft */ 259 1.10 mycroft const char * 260 1.10 mycroft user_from_uid(uid_t uid, int noname) 261 1.1 cgd { 262 1.9 perry struct passwd *pw; 263 1.10 mycroft UIDC *ptr, **pptr; 264 1.1 cgd 265 1.10 mycroft if ((uidtb == NULL) && (uidtb_start() < 0)) 266 1.10 mycroft return (NULL); 267 1.10 mycroft 268 1.10 mycroft /* 269 1.10 mycroft * see if we have this uid cached 270 1.10 mycroft */ 271 1.10 mycroft pptr = uidtb + (uid % UID_SZ); 272 1.10 mycroft ptr = *pptr; 273 1.10 mycroft 274 1.10 mycroft if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) { 275 1.10 mycroft /* 276 1.10 mycroft * have an entry for this uid 277 1.10 mycroft */ 278 1.10 mycroft if (!noname || (ptr->valid == VALID)) 279 1.10 mycroft return (ptr->name); 280 1.10 mycroft return (NULL); 281 1.10 mycroft } 282 1.10 mycroft 283 1.10 mycroft /* 284 1.10 mycroft * No entry for this uid, we will add it 285 1.10 mycroft */ 286 1.10 mycroft if (!pwopn) { 287 1.17 lukem if (_pwcache_setpassent != NULL) 288 1.17 lukem (*_pwcache_setpassent)(1); 289 1.10 mycroft ++pwopn; 290 1.1 cgd } 291 1.10 mycroft 292 1.10 mycroft if (ptr == NULL) 293 1.12 mycroft *pptr = ptr = (UIDC *)malloc(sizeof(UIDC)); 294 1.10 mycroft 295 1.17 lukem if ((pw = (*_pwcache_getpwuid)(uid)) == NULL) { 296 1.10 mycroft /* 297 1.10 mycroft * no match for this uid in the local password file 298 1.23 grant * a string that is the uid in numeric format 299 1.10 mycroft */ 300 1.10 mycroft if (ptr == NULL) 301 1.10 mycroft return (NULL); 302 1.10 mycroft ptr->uid = uid; 303 1.10 mycroft (void)snprintf(ptr->name, UNMLEN, "%lu", (long) uid); 304 1.10 mycroft ptr->valid = INVALID; 305 1.10 mycroft if (noname) 306 1.10 mycroft return (NULL); 307 1.10 mycroft } else { 308 1.10 mycroft /* 309 1.10 mycroft * there is an entry for this uid in the password file 310 1.10 mycroft */ 311 1.10 mycroft if (ptr == NULL) 312 1.10 mycroft return (pw->pw_name); 313 1.10 mycroft ptr->uid = uid; 314 1.17 lukem (void)strlcpy(ptr->name, pw->pw_name, UNMLEN); 315 1.10 mycroft ptr->valid = VALID; 316 1.10 mycroft } 317 1.10 mycroft return (ptr->name); 318 1.1 cgd } 319 1.1 cgd 320 1.10 mycroft /* 321 1.10 mycroft * group_from_gid() 322 1.16 lukem * caches the name (if any) for the gid. If noname clear, we always 323 1.26 simonb * return the stored name (if valid or invalid match). 324 1.16 lukem * We use a simple hash table. 325 1.10 mycroft * Return 326 1.10 mycroft * Pointer to stored name (or a empty string) 327 1.10 mycroft */ 328 1.10 mycroft const char * 329 1.10 mycroft group_from_gid(gid_t gid, int noname) 330 1.10 mycroft { 331 1.10 mycroft struct group *gr; 332 1.10 mycroft GIDC *ptr, **pptr; 333 1.10 mycroft 334 1.10 mycroft if ((gidtb == NULL) && (gidtb_start() < 0)) 335 1.10 mycroft return (NULL); 336 1.10 mycroft 337 1.10 mycroft /* 338 1.10 mycroft * see if we have this gid cached 339 1.10 mycroft */ 340 1.10 mycroft pptr = gidtb + (gid % GID_SZ); 341 1.10 mycroft ptr = *pptr; 342 1.10 mycroft 343 1.10 mycroft if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) { 344 1.10 mycroft /* 345 1.10 mycroft * have an entry for this gid 346 1.10 mycroft */ 347 1.10 mycroft if (!noname || (ptr->valid == VALID)) 348 1.10 mycroft return (ptr->name); 349 1.10 mycroft return (NULL); 350 1.10 mycroft } 351 1.10 mycroft 352 1.10 mycroft /* 353 1.10 mycroft * No entry for this gid, we will add it 354 1.10 mycroft */ 355 1.10 mycroft if (!gropn) { 356 1.17 lukem if (_pwcache_setgroupent != NULL) 357 1.17 lukem (*_pwcache_setgroupent)(1); 358 1.10 mycroft ++gropn; 359 1.10 mycroft } 360 1.10 mycroft 361 1.10 mycroft if (ptr == NULL) 362 1.12 mycroft *pptr = ptr = (GIDC *)malloc(sizeof(GIDC)); 363 1.10 mycroft 364 1.17 lukem if ((gr = (*_pwcache_getgrgid)(gid)) == NULL) { 365 1.10 mycroft /* 366 1.10 mycroft * no match for this gid in the local group file, put in 367 1.33 msaitoh * a string that is the gid in numeric format 368 1.10 mycroft */ 369 1.10 mycroft if (ptr == NULL) 370 1.10 mycroft return (NULL); 371 1.10 mycroft ptr->gid = gid; 372 1.10 mycroft (void)snprintf(ptr->name, GNMLEN, "%lu", (long) gid); 373 1.10 mycroft ptr->valid = INVALID; 374 1.10 mycroft if (noname) 375 1.10 mycroft return (NULL); 376 1.10 mycroft } else { 377 1.10 mycroft /* 378 1.10 mycroft * there is an entry for this group in the group file 379 1.10 mycroft */ 380 1.10 mycroft if (ptr == NULL) 381 1.10 mycroft return (gr->gr_name); 382 1.10 mycroft ptr->gid = gid; 383 1.17 lukem (void)strlcpy(ptr->name, gr->gr_name, GNMLEN); 384 1.10 mycroft ptr->valid = VALID; 385 1.10 mycroft } 386 1.10 mycroft return (ptr->name); 387 1.10 mycroft } 388 1.10 mycroft 389 1.10 mycroft /* 390 1.10 mycroft * uid_from_user() 391 1.10 mycroft * caches the uid for a given user name. We use a simple hash table. 392 1.10 mycroft * Return 393 1.10 mycroft * the uid (if any) for a user name, or a -1 if no match can be found 394 1.10 mycroft */ 395 1.10 mycroft int 396 1.10 mycroft uid_from_user(const char *name, uid_t *uid) 397 1.10 mycroft { 398 1.10 mycroft struct passwd *pw; 399 1.10 mycroft UIDC *ptr, **pptr; 400 1.10 mycroft size_t namelen; 401 1.10 mycroft 402 1.10 mycroft /* 403 1.10 mycroft * return -1 for mangled names 404 1.10 mycroft */ 405 1.13 lukem if (name == NULL || ((namelen = strlen(name)) == 0)) 406 1.10 mycroft return (-1); 407 1.10 mycroft if ((usrtb == NULL) && (usrtb_start() < 0)) 408 1.10 mycroft return (-1); 409 1.10 mycroft 410 1.10 mycroft /* 411 1.10 mycroft * look up in hash table, if found and valid return the uid, 412 1.10 mycroft * if found and invalid, return a -1 413 1.10 mycroft */ 414 1.10 mycroft pptr = usrtb + st_hash(name, namelen, UNM_SZ); 415 1.10 mycroft ptr = *pptr; 416 1.10 mycroft 417 1.10 mycroft if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) { 418 1.10 mycroft if (ptr->valid == INVALID) 419 1.10 mycroft return (-1); 420 1.10 mycroft *uid = ptr->uid; 421 1.10 mycroft return (0); 422 1.10 mycroft } 423 1.10 mycroft 424 1.10 mycroft if (!pwopn) { 425 1.17 lukem if (_pwcache_setpassent != NULL) 426 1.17 lukem (*_pwcache_setpassent)(1); 427 1.10 mycroft ++pwopn; 428 1.10 mycroft } 429 1.10 mycroft 430 1.10 mycroft if (ptr == NULL) 431 1.12 mycroft *pptr = ptr = (UIDC *)malloc(sizeof(UIDC)); 432 1.10 mycroft 433 1.10 mycroft /* 434 1.10 mycroft * no match, look it up, if no match store it as an invalid entry, 435 1.10 mycroft * or store the matching uid 436 1.10 mycroft */ 437 1.10 mycroft if (ptr == NULL) { 438 1.17 lukem if ((pw = (*_pwcache_getpwnam)(name)) == NULL) 439 1.10 mycroft return (-1); 440 1.10 mycroft *uid = pw->pw_uid; 441 1.10 mycroft return (0); 442 1.10 mycroft } 443 1.17 lukem (void)strlcpy(ptr->name, name, UNMLEN); 444 1.17 lukem if ((pw = (*_pwcache_getpwnam)(name)) == NULL) { 445 1.10 mycroft ptr->valid = INVALID; 446 1.10 mycroft return (-1); 447 1.10 mycroft } 448 1.10 mycroft ptr->valid = VALID; 449 1.10 mycroft *uid = ptr->uid = pw->pw_uid; 450 1.10 mycroft return (0); 451 1.10 mycroft } 452 1.10 mycroft 453 1.10 mycroft /* 454 1.10 mycroft * gid_from_group() 455 1.10 mycroft * caches the gid for a given group name. We use a simple hash table. 456 1.10 mycroft * Return 457 1.10 mycroft * the gid (if any) for a group name, or a -1 if no match can be found 458 1.10 mycroft */ 459 1.10 mycroft int 460 1.10 mycroft gid_from_group(const char *name, gid_t *gid) 461 1.1 cgd { 462 1.4 cgd struct group *gr; 463 1.10 mycroft GIDC *ptr, **pptr; 464 1.10 mycroft size_t namelen; 465 1.10 mycroft 466 1.10 mycroft /* 467 1.10 mycroft * return -1 for mangled names 468 1.10 mycroft */ 469 1.13 lukem if (name == NULL || ((namelen = strlen(name)) == 0)) 470 1.10 mycroft return (-1); 471 1.10 mycroft if ((grptb == NULL) && (grptb_start() < 0)) 472 1.10 mycroft return (-1); 473 1.10 mycroft 474 1.10 mycroft /* 475 1.10 mycroft * look up in hash table, if found and valid return the uid, 476 1.10 mycroft * if found and invalid, return a -1 477 1.10 mycroft */ 478 1.10 mycroft pptr = grptb + st_hash(name, namelen, GID_SZ); 479 1.10 mycroft ptr = *pptr; 480 1.10 mycroft 481 1.10 mycroft if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) { 482 1.10 mycroft if (ptr->valid == INVALID) 483 1.10 mycroft return (-1); 484 1.10 mycroft *gid = ptr->gid; 485 1.10 mycroft return (0); 486 1.10 mycroft } 487 1.10 mycroft 488 1.10 mycroft if (!gropn) { 489 1.17 lukem if (_pwcache_setgroupent != NULL) 490 1.17 lukem (*_pwcache_setgroupent)(1); 491 1.10 mycroft ++gropn; 492 1.10 mycroft } 493 1.10 mycroft 494 1.10 mycroft if (ptr == NULL) 495 1.12 mycroft *pptr = ptr = (GIDC *)malloc(sizeof(GIDC)); 496 1.10 mycroft 497 1.10 mycroft /* 498 1.10 mycroft * no match, look it up, if no match store it as an invalid entry, 499 1.10 mycroft * or store the matching gid 500 1.10 mycroft */ 501 1.10 mycroft if (ptr == NULL) { 502 1.17 lukem if ((gr = (*_pwcache_getgrnam)(name)) == NULL) 503 1.10 mycroft return (-1); 504 1.10 mycroft *gid = gr->gr_gid; 505 1.10 mycroft return (0); 506 1.10 mycroft } 507 1.1 cgd 508 1.17 lukem (void)strlcpy(ptr->name, name, GNMLEN); 509 1.17 lukem if ((gr = (*_pwcache_getgrnam)(name)) == NULL) { 510 1.10 mycroft ptr->valid = INVALID; 511 1.10 mycroft return (-1); 512 1.1 cgd } 513 1.10 mycroft ptr->valid = VALID; 514 1.10 mycroft *gid = ptr->gid = gr->gr_gid; 515 1.10 mycroft return (0); 516 1.1 cgd } 517 1.17 lukem 518 1.17 lukem #define FLUSHTB(arr, len, fail) \ 519 1.17 lukem do { \ 520 1.17 lukem if (arr != NULL) { \ 521 1.17 lukem for (i = 0; i < len; i++) \ 522 1.17 lukem if (arr[i] != NULL) \ 523 1.17 lukem free(arr[i]); \ 524 1.17 lukem arr = NULL; \ 525 1.17 lukem } \ 526 1.17 lukem fail = 0; \ 527 1.35 rillig } while (0) 528 1.17 lukem 529 1.17 lukem int 530 1.17 lukem pwcache_userdb( 531 1.17 lukem int (*a_setpassent)(int), 532 1.17 lukem void (*a_endpwent)(void), 533 1.17 lukem struct passwd * (*a_getpwnam)(const char *), 534 1.17 lukem struct passwd * (*a_getpwuid)(uid_t)) 535 1.17 lukem { 536 1.17 lukem int i; 537 1.17 lukem 538 1.17 lukem /* a_setpassent and a_endpwent may be NULL */ 539 1.17 lukem if (a_getpwnam == NULL || a_getpwuid == NULL) 540 1.17 lukem return (-1); 541 1.17 lukem 542 1.17 lukem if (_pwcache_endpwent != NULL) 543 1.17 lukem (*_pwcache_endpwent)(); 544 1.17 lukem FLUSHTB(uidtb, UID_SZ, uidtb_fail); 545 1.17 lukem FLUSHTB(usrtb, UNM_SZ, usrtb_fail); 546 1.17 lukem pwopn = 0; 547 1.17 lukem _pwcache_setpassent = a_setpassent; 548 1.17 lukem _pwcache_endpwent = a_endpwent; 549 1.17 lukem _pwcache_getpwnam = a_getpwnam; 550 1.17 lukem _pwcache_getpwuid = a_getpwuid; 551 1.17 lukem 552 1.17 lukem return (0); 553 1.17 lukem } 554 1.17 lukem 555 1.17 lukem int 556 1.17 lukem pwcache_groupdb( 557 1.17 lukem int (*a_setgroupent)(int), 558 1.17 lukem void (*a_endgrent)(void), 559 1.17 lukem struct group * (*a_getgrnam)(const char *), 560 1.17 lukem struct group * (*a_getgrgid)(gid_t)) 561 1.17 lukem { 562 1.17 lukem int i; 563 1.17 lukem 564 1.17 lukem /* a_setgroupent and a_endgrent may be NULL */ 565 1.17 lukem if (a_getgrnam == NULL || a_getgrgid == NULL) 566 1.17 lukem return (-1); 567 1.17 lukem 568 1.17 lukem if (_pwcache_endgrent != NULL) 569 1.17 lukem (*_pwcache_endgrent)(); 570 1.17 lukem FLUSHTB(gidtb, GID_SZ, gidtb_fail); 571 1.17 lukem FLUSHTB(grptb, GNM_SZ, grptb_fail); 572 1.17 lukem gropn = 0; 573 1.17 lukem _pwcache_setgroupent = a_setgroupent; 574 1.17 lukem _pwcache_endgrent = a_endgrent; 575 1.17 lukem _pwcache_getgrnam = a_getgrnam; 576 1.17 lukem _pwcache_getgrgid = a_getgrgid; 577 1.17 lukem 578 1.17 lukem return (0); 579 1.17 lukem } 580 1.17 lukem 581 1.17 lukem 582 1.17 lukem #ifdef TEST_PWCACHE 583 1.17 lukem 584 1.17 lukem struct passwd * 585 1.17 lukem test_getpwnam(const char *name) 586 1.17 lukem { 587 1.17 lukem static struct passwd foo; 588 1.17 lukem 589 1.17 lukem memset(&foo, 0, sizeof(foo)); 590 1.17 lukem if (strcmp(name, "toor") == 0) { 591 1.17 lukem foo.pw_uid = 666; 592 1.17 lukem return &foo; 593 1.17 lukem } 594 1.17 lukem return (getpwnam(name)); 595 1.17 lukem } 596 1.17 lukem 597 1.17 lukem int 598 1.17 lukem main(int argc, char *argv[]) 599 1.17 lukem { 600 1.17 lukem uid_t u; 601 1.17 lukem int r, i; 602 1.17 lukem 603 1.17 lukem printf("pass 1 (default userdb)\n"); 604 1.17 lukem for (i = 1; i < argc; i++) { 605 1.17 lukem printf("i: %d, pwopn %d usrtb_fail %d usrtb %p\n", 606 1.17 lukem i, pwopn, usrtb_fail, usrtb); 607 1.17 lukem r = uid_from_user(argv[i], &u); 608 1.17 lukem if (r == -1) 609 1.17 lukem printf(" uid_from_user %s: failed\n", argv[i]); 610 1.17 lukem else 611 1.17 lukem printf(" uid_from_user %s: %d\n", argv[i], u); 612 1.17 lukem } 613 1.17 lukem printf("pass 1 finish: pwopn %d usrtb_fail %d usrtb %p\n", 614 1.17 lukem pwopn, usrtb_fail, usrtb); 615 1.17 lukem 616 1.17 lukem puts(""); 617 1.17 lukem printf("pass 2 (replacement userdb)\n"); 618 1.17 lukem printf("pwcache_userdb returned %d\n", 619 1.17 lukem pwcache_userdb(setpassent, test_getpwnam, getpwuid)); 620 1.17 lukem printf("pwopn %d usrtb_fail %d usrtb %p\n", pwopn, usrtb_fail, usrtb); 621 1.17 lukem 622 1.17 lukem for (i = 1; i < argc; i++) { 623 1.17 lukem printf("i: %d, pwopn %d usrtb_fail %d usrtb %p\n", 624 1.17 lukem i, pwopn, usrtb_fail, usrtb); 625 1.17 lukem u = -1; 626 1.17 lukem r = uid_from_user(argv[i], &u); 627 1.17 lukem if (r == -1) 628 1.17 lukem printf(" uid_from_user %s: failed\n", argv[i]); 629 1.17 lukem else 630 1.17 lukem printf(" uid_from_user %s: %d\n", argv[i], u); 631 1.17 lukem } 632 1.17 lukem printf("pass 2 finish: pwopn %d usrtb_fail %d usrtb %p\n", 633 1.17 lukem pwopn, usrtb_fail, usrtb); 634 1.17 lukem 635 1.17 lukem puts(""); 636 1.17 lukem printf("pass 3 (null pointers)\n"); 637 1.17 lukem printf("pwcache_userdb returned %d\n", 638 1.17 lukem pwcache_userdb(NULL, NULL, NULL)); 639 1.17 lukem 640 1.17 lukem return (0); 641 1.17 lukem } 642 1.17 lukem #endif /* TEST_PWCACHE */ 643 1.18 lukem #endif /* !HAVE_PWCACHE_USERDB */ 644