1 1.43 dholland /* $NetBSD: getnetgrent.c,v 1.43 2016/05/31 03:43:10 dholland Exp $ */ 2 1.8 cgd 3 1.1 mycroft /* 4 1.4 christos * Copyright (c) 1994 Christos Zoulas 5 1.4 christos * All rights reserved. 6 1.1 mycroft * 7 1.1 mycroft * Redistribution and use in source and binary forms, with or without 8 1.1 mycroft * modification, are permitted provided that the following conditions 9 1.1 mycroft * are met: 10 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 11 1.1 mycroft * notice, this list of conditions and the following disclaimer. 12 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 14 1.1 mycroft * documentation and/or other materials provided with the distribution. 15 1.1 mycroft * 16 1.4 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 1.4 christos * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 1.4 christos * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.4 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 1.4 christos * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 mycroft * SUCH DAMAGE. 27 1.1 mycroft */ 28 1.1 mycroft 29 1.12 christos #include <sys/cdefs.h> 30 1.1 mycroft #if defined(LIBC_SCCS) && !defined(lint) 31 1.43 dholland __RCSID("$NetBSD: getnetgrent.c,v 1.43 2016/05/31 03:43:10 dholland Exp $"); 32 1.1 mycroft #endif /* LIBC_SCCS and not lint */ 33 1.1 mycroft 34 1.12 christos #include "namespace.h" 35 1.9 christos #include <sys/types.h> 36 1.24 lukem 37 1.24 lukem #include <assert.h> 38 1.24 lukem #include <ctype.h> 39 1.24 lukem #include <db.h> 40 1.24 lukem #include <err.h> 41 1.24 lukem #include <fcntl.h> 42 1.9 christos #define _NETGROUP_PRIVATE 43 1.33 christos #include <stringlist.h> 44 1.4 christos #include <netgroup.h> 45 1.17 lukem #include <nsswitch.h> 46 1.29 wiz #include <stdarg.h> 47 1.24 lukem #include <stdio.h> 48 1.3 cgd #include <stdlib.h> 49 1.24 lukem #include <string.h> 50 1.24 lukem 51 1.10 cgd #ifdef YP 52 1.17 lukem #include <rpc/rpc.h> 53 1.10 cgd #include <rpcsvc/ypclnt.h> 54 1.17 lukem #include <rpcsvc/yp_prot.h> 55 1.23 lukem #endif 56 1.23 lukem 57 1.13 jtc #ifdef __weak_alias 58 1.27 mycroft __weak_alias(endnetgrent,_endnetgrent) 59 1.27 mycroft __weak_alias(getnetgrent,_getnetgrent) 60 1.27 mycroft __weak_alias(innetgr,_innetgr) 61 1.27 mycroft __weak_alias(setnetgrent,_setnetgrent) 62 1.10 cgd #endif 63 1.4 christos 64 1.4 christos #define _NG_STAR(s) (((s) == NULL || *(s) == '\0') ? _ngstar : s) 65 1.9 christos #define _NG_EMPTY(s) ((s) == NULL ? "" : s) 66 1.4 christos #define _NG_ISSPACE(p) (isspace((unsigned char) (p)) || (p) == '\n') 67 1.1 mycroft 68 1.4 christos static const char _ngstar[] = "*"; 69 1.30 christos static struct netgroup *_nghead = NULL; 70 1.30 christos static struct netgroup *_nglist = NULL; 71 1.4 christos static DB *_ng_db; 72 1.1 mycroft 73 1.30 christos static int getstring(char **, int, __aconst char **); 74 1.30 christos static struct netgroup *getnetgroup(char **); 75 1.30 christos static int lookup(char *, char **, int); 76 1.30 christos static int addgroup(StringList *, char *); 77 1.30 christos static int in_check(const char *, const char *, const char *, 78 1.30 christos struct netgroup *); 79 1.30 christos static int in_find(StringList *, char *, const char *, const char *, 80 1.30 christos const char *); 81 1.30 christos static char *in_lookup1(const char *, const char *, int); 82 1.30 christos static int in_lookup(const char *, const char *, const char *, int); 83 1.4 christos 84 1.32 christos #ifdef NSSRC_FILES 85 1.21 thorpej static const ns_src default_files_nis[] = { 86 1.22 lukem { NSSRC_FILES, NS_SUCCESS | NS_NOTFOUND }, 87 1.21 thorpej #ifdef YP 88 1.21 thorpej { NSSRC_NIS, NS_SUCCESS }, 89 1.21 thorpej #endif 90 1.37 christos { 0, 0 }, 91 1.21 thorpej }; 92 1.32 christos #endif 93 1.21 thorpej 94 1.4 christos /* 95 1.4 christos * getstring(): Get a string delimited by the character, skipping leading and 96 1.4 christos * trailing blanks and advancing the pointer 97 1.4 christos */ 98 1.6 christos static int 99 1.30 christos getstring(char **pp, int del, char __aconst **str) 100 1.4 christos { 101 1.14 perry size_t len; 102 1.4 christos char *sp, *ep, *dp; 103 1.4 christos 104 1.24 lukem _DIAGASSERT(pp != NULL); 105 1.24 lukem _DIAGASSERT(str != NULL); 106 1.24 lukem 107 1.4 christos /* skip leading blanks */ 108 1.4 christos for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++) 109 1.4 christos continue; 110 1.4 christos 111 1.4 christos /* accumulate till delimiter or space */ 112 1.4 christos for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++) 113 1.4 christos continue; 114 1.4 christos 115 1.4 christos /* hunt for the delimiter */ 116 1.4 christos for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++) 117 1.4 christos continue; 118 1.4 christos 119 1.6 christos if (*dp != del) { 120 1.6 christos *str = NULL; 121 1.6 christos return 0; 122 1.6 christos } 123 1.4 christos 124 1.4 christos *pp = ++dp; 125 1.4 christos 126 1.14 perry len = (ep - sp) + 1; 127 1.14 perry if (len > 1) { 128 1.14 perry dp = malloc(len); 129 1.6 christos if (dp == NULL) 130 1.26 lukem return 0; 131 1.30 christos (void)memcpy(dp, sp, len); 132 1.14 perry dp[len - 1] = '\0'; 133 1.6 christos } else 134 1.6 christos dp = NULL; 135 1.1 mycroft 136 1.6 christos *str = dp; 137 1.6 christos return 1; 138 1.4 christos } 139 1.4 christos 140 1.4 christos 141 1.4 christos /* 142 1.4 christos * getnetgroup(): Parse a netgroup, and advance the pointer 143 1.4 christos */ 144 1.4 christos static struct netgroup * 145 1.42 matt getnetgroup(char **pp) 146 1.4 christos { 147 1.24 lukem struct netgroup *ng; 148 1.24 lukem 149 1.24 lukem _DIAGASSERT(pp != NULL); 150 1.24 lukem _DIAGASSERT(*pp != NULL); 151 1.4 christos 152 1.24 lukem ng = malloc(sizeof(struct netgroup)); 153 1.4 christos if (ng == NULL) 154 1.26 lukem return NULL; 155 1.4 christos 156 1.4 christos (*pp)++; /* skip '(' */ 157 1.6 christos if (!getstring(pp, ',', &ng->ng_host)) 158 1.4 christos goto badhost; 159 1.4 christos 160 1.6 christos if (!getstring(pp, ',', &ng->ng_user)) 161 1.4 christos goto baduser; 162 1.4 christos 163 1.6 christos if (!getstring(pp, ')', &ng->ng_domain)) 164 1.4 christos goto baddomain; 165 1.4 christos 166 1.4 christos #ifdef DEBUG_NG 167 1.9 christos { 168 1.9 christos char buf[1024]; 169 1.43 dholland _ng_print(buf, sizeof(buf), ng); 170 1.43 dholland (void) fprintf(stderr, "netgroup %s\n", buf); 171 1.9 christos } 172 1.4 christos #endif 173 1.4 christos return ng; 174 1.4 christos 175 1.4 christos baddomain: 176 1.6 christos if (ng->ng_user) 177 1.30 christos free(ng->ng_user); 178 1.4 christos baduser: 179 1.6 christos if (ng->ng_host) 180 1.30 christos free(ng->ng_host); 181 1.4 christos badhost: 182 1.4 christos free(ng); 183 1.4 christos return NULL; 184 1.4 christos } 185 1.4 christos 186 1.35 dogcow void 187 1.32 christos _ng_cycle(const char *grp, const StringList *sl) 188 1.32 christos { 189 1.32 christos size_t i; 190 1.32 christos warnx("netgroup: Cycle in group `%s'", grp); 191 1.32 christos (void)fprintf(stderr, "groups: "); 192 1.32 christos for (i = 0; i < sl->sl_cur; i++) 193 1.32 christos (void)fprintf(stderr, "%s ", sl->sl_str[i]); 194 1.32 christos (void)fprintf(stderr, "\n"); 195 1.32 christos } 196 1.4 christos 197 1.30 christos static int _local_lookup(void *, void *, va_list); 198 1.17 lukem 199 1.18 christos /*ARGSUSED*/ 200 1.4 christos static int 201 1.30 christos _local_lookup(void *rv, void *cb_data, va_list ap) 202 1.17 lukem { 203 1.17 lukem char *name = va_arg(ap, char *); 204 1.17 lukem char **line = va_arg(ap, char **); 205 1.17 lukem int bywhat = va_arg(ap, int); 206 1.17 lukem 207 1.17 lukem DBT key, data; 208 1.17 lukem size_t len; 209 1.17 lukem char *ks; 210 1.17 lukem int r; 211 1.4 christos 212 1.17 lukem if (_ng_db == NULL) 213 1.17 lukem return NS_UNAVAIL; 214 1.4 christos 215 1.17 lukem len = strlen(name) + 2; 216 1.17 lukem ks = malloc(len); 217 1.17 lukem if (ks == NULL) 218 1.26 lukem return NS_UNAVAIL; 219 1.4 christos 220 1.17 lukem ks[0] = bywhat; 221 1.30 christos (void)memcpy(&ks[1], name, len - 1); 222 1.4 christos 223 1.30 christos key.data = (u_char *)ks; 224 1.17 lukem key.size = len; 225 1.4 christos 226 1.30 christos r = (*_ng_db->get)(_ng_db, &key, &data, 0); 227 1.17 lukem free(ks); 228 1.17 lukem switch (r) { 229 1.17 lukem case 0: 230 1.17 lukem break; 231 1.17 lukem case 1: 232 1.17 lukem return NS_NOTFOUND; 233 1.17 lukem case -1: 234 1.22 lukem /* XXX: call endnetgrent() here ? */ 235 1.17 lukem return NS_UNAVAIL; 236 1.17 lukem } 237 1.17 lukem 238 1.17 lukem *line = strdup(data.data); 239 1.17 lukem if (*line == NULL) 240 1.17 lukem return NS_UNAVAIL; 241 1.17 lukem return NS_SUCCESS; 242 1.17 lukem } 243 1.4 christos 244 1.4 christos #ifdef YP 245 1.30 christos static int _nis_lookup(void *, void *, va_list); 246 1.4 christos 247 1.18 christos /*ARGSUSED*/ 248 1.17 lukem static int 249 1.30 christos _nis_lookup(void *rv, void *cb_data, va_list ap) 250 1.17 lukem { 251 1.17 lukem char *name = va_arg(ap, char *); 252 1.17 lukem char **line = va_arg(ap, char **); 253 1.17 lukem int bywhat = va_arg(ap, int); 254 1.17 lukem 255 1.17 lukem static char *__ypdomain; 256 1.17 lukem int i; 257 1.30 christos const char *map = NULL; 258 1.4 christos 259 1.17 lukem if(__ypdomain == NULL) { 260 1.17 lukem switch (yp_get_default_domain(&__ypdomain)) { 261 1.17 lukem case 0: 262 1.6 christos break; 263 1.17 lukem case YPERR_RESRC: 264 1.17 lukem return NS_TRYAGAIN; 265 1.6 christos default: 266 1.17 lukem return NS_UNAVAIL; 267 1.6 christos } 268 1.17 lukem } 269 1.17 lukem 270 1.17 lukem switch (bywhat) { 271 1.17 lukem case _NG_KEYBYNAME: 272 1.17 lukem map = "netgroup"; 273 1.17 lukem break; 274 1.17 lukem 275 1.17 lukem case _NG_KEYBYUSER: 276 1.17 lukem map = "netgroup.byuser"; 277 1.17 lukem break; 278 1.17 lukem 279 1.17 lukem case _NG_KEYBYHOST: 280 1.17 lukem map = "netgroup.byhost"; 281 1.17 lukem break; 282 1.17 lukem 283 1.17 lukem default: 284 1.17 lukem abort(); 285 1.17 lukem } 286 1.4 christos 287 1.17 lukem *line = NULL; 288 1.17 lukem switch (yp_match(__ypdomain, map, name, (int)strlen(name), line, &i)) { 289 1.17 lukem case 0: 290 1.17 lukem return NS_SUCCESS; 291 1.17 lukem case YPERR_KEY: 292 1.17 lukem if (*line) 293 1.17 lukem free(*line); 294 1.17 lukem return NS_NOTFOUND; 295 1.17 lukem default: 296 1.17 lukem if (*line) 297 1.17 lukem free(*line); 298 1.17 lukem return NS_UNAVAIL; 299 1.6 christos } 300 1.17 lukem /* NOTREACHED */ 301 1.17 lukem } 302 1.4 christos #endif 303 1.4 christos 304 1.32 christos #ifdef NSSRC_FILES 305 1.17 lukem /* 306 1.17 lukem * lookup(): Find the given key in the database or yp, and return its value 307 1.17 lukem * in *line; returns 1 if key was found, 0 otherwise 308 1.17 lukem */ 309 1.17 lukem static int 310 1.30 christos lookup(char *name, char **line, int bywhat) 311 1.17 lukem { 312 1.17 lukem int r; 313 1.20 lukem static const ns_dtab dtab[] = { 314 1.19 lukem NS_FILES_CB(_local_lookup, NULL) 315 1.21 thorpej NS_NIS_CB(_nis_lookup, NULL) 316 1.37 christos NS_NULL_CB 317 1.17 lukem }; 318 1.17 lukem 319 1.24 lukem _DIAGASSERT(name != NULL); 320 1.24 lukem _DIAGASSERT(line != NULL); 321 1.24 lukem 322 1.21 thorpej r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "lookup", default_files_nis, 323 1.19 lukem name, line, bywhat); 324 1.17 lukem return (r == NS_SUCCESS) ? 1 : 0; 325 1.1 mycroft } 326 1.32 christos #else 327 1.32 christos static int 328 1.32 christos _local_lookupv(int *rv, void *cbdata, ...) 329 1.32 christos { 330 1.32 christos int e; 331 1.32 christos va_list ap; 332 1.32 christos va_start(ap, cbdata); 333 1.32 christos e = _local_lookup(rv, cbdata, ap); 334 1.32 christos va_end(ap); 335 1.32 christos return e; 336 1.32 christos } 337 1.32 christos 338 1.32 christos static int 339 1.32 christos lookup(name, line, bywhat) 340 1.32 christos char *name; 341 1.32 christos char **line; 342 1.32 christos int bywhat; 343 1.32 christos { 344 1.32 christos return _local_lookupv(NULL, NULL, name, line, bywhat) == NS_SUCCESS; 345 1.32 christos } 346 1.32 christos #endif 347 1.1 mycroft 348 1.1 mycroft /* 349 1.4 christos * _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE: 350 1.4 christos * line was empty or a comment _NG_GROUP: line had a netgroup definition, 351 1.4 christos * returned in ng _NG_NAME: line had a netgroup name, returned in name 352 1.4 christos * 353 1.4 christos * Public since used by netgroup_mkdb 354 1.1 mycroft */ 355 1.1 mycroft int 356 1.30 christos _ng_parse(char **p, char **name, struct netgroup **ng) 357 1.1 mycroft { 358 1.24 lukem 359 1.24 lukem _DIAGASSERT(p != NULL); 360 1.24 lukem _DIAGASSERT(*p != NULL); 361 1.24 lukem _DIAGASSERT(name != NULL); 362 1.24 lukem _DIAGASSERT(ng != NULL); 363 1.24 lukem 364 1.4 christos while (**p) { 365 1.4 christos if (**p == '#') 366 1.4 christos /* comment */ 367 1.4 christos return _NG_NONE; 368 1.4 christos 369 1.4 christos while (**p && _NG_ISSPACE(**p)) 370 1.4 christos /* skipblank */ 371 1.4 christos (*p)++; 372 1.4 christos 373 1.4 christos if (**p == '(') { 374 1.26 lukem if ((*ng = getnetgroup(p)) == NULL) 375 1.4 christos return _NG_ERROR; 376 1.4 christos return _NG_GROUP; 377 1.4 christos } else { 378 1.17 lukem char *np; 379 1.17 lukem size_t i; 380 1.1 mycroft 381 1.4 christos for (np = *p; **p && !_NG_ISSPACE(**p); (*p)++) 382 1.4 christos continue; 383 1.4 christos if (np != *p) { 384 1.4 christos i = (*p - np) + 1; 385 1.4 christos *name = malloc(i); 386 1.4 christos if (*name == NULL) 387 1.26 lukem return _NG_ERROR; 388 1.30 christos (void)memcpy(*name, np, i); 389 1.4 christos (*name)[i - 1] = '\0'; 390 1.4 christos return _NG_NAME; 391 1.4 christos } 392 1.4 christos } 393 1.1 mycroft } 394 1.4 christos return _NG_NONE; 395 1.1 mycroft } 396 1.1 mycroft 397 1.4 christos 398 1.1 mycroft /* 399 1.26 lukem * addgroup(): Recursively add all the members of the netgroup to this group. 400 1.26 lukem * returns 0 upon failure, nonzero upon success. 401 1.26 lukem * grp is not a valid pointer after return (either free(3)ed or allocated 402 1.26 lukem * to a stringlist). in either case, it shouldn't be used again. 403 1.1 mycroft */ 404 1.26 lukem static int 405 1.30 christos addgroup(StringList *sl, char *grp) 406 1.1 mycroft { 407 1.4 christos char *line, *p; 408 1.4 christos struct netgroup *ng; 409 1.4 christos char *name; 410 1.4 christos 411 1.24 lukem _DIAGASSERT(sl != NULL); 412 1.24 lukem _DIAGASSERT(grp != NULL); 413 1.24 lukem 414 1.4 christos #ifdef DEBUG_NG 415 1.30 christos (void)fprintf(stderr, "addgroup(%s)\n", grp); 416 1.4 christos #endif 417 1.4 christos /* check for cycles */ 418 1.11 lukem if (sl_find(sl, grp) != NULL) { 419 1.32 christos _ng_cycle(grp, sl); 420 1.6 christos free(grp); 421 1.26 lukem return 0; 422 1.26 lukem } 423 1.26 lukem if (sl_add(sl, grp) == -1) { 424 1.26 lukem free(grp); 425 1.26 lukem return 0; 426 1.4 christos } 427 1.4 christos 428 1.4 christos /* Lookup this netgroup */ 429 1.17 lukem line = NULL; 430 1.17 lukem if (!lookup(grp, &line, _NG_KEYBYNAME)) { 431 1.32 christos if (line) 432 1.17 lukem free(line); 433 1.26 lukem return 0; 434 1.17 lukem } 435 1.4 christos 436 1.4 christos p = line; 437 1.4 christos 438 1.4 christos for (;;) { 439 1.4 christos switch (_ng_parse(&p, &name, &ng)) { 440 1.4 christos case _NG_NONE: 441 1.4 christos /* Done with the line */ 442 1.4 christos free(line); 443 1.26 lukem return 1; 444 1.4 christos 445 1.4 christos case _NG_GROUP: 446 1.4 christos /* new netgroup */ 447 1.4 christos /* add to the list */ 448 1.4 christos ng->ng_next = _nglist; 449 1.4 christos _nglist = ng; 450 1.4 christos break; 451 1.4 christos 452 1.4 christos case _NG_NAME: 453 1.4 christos /* netgroup name */ 454 1.26 lukem if (!addgroup(sl, name)) 455 1.26 lukem return 0; 456 1.4 christos break; 457 1.1 mycroft 458 1.4 christos case _NG_ERROR: 459 1.26 lukem return 0; 460 1.4 christos 461 1.4 christos default: 462 1.4 christos abort(); 463 1.4 christos } 464 1.1 mycroft } 465 1.1 mycroft } 466 1.1 mycroft 467 1.4 christos 468 1.1 mycroft /* 469 1.4 christos * in_check(): Compare the spec with the netgroup 470 1.1 mycroft */ 471 1.4 christos static int 472 1.30 christos in_check(const char *host, const char *user, const char *domain, 473 1.30 christos struct netgroup *ng) 474 1.1 mycroft { 475 1.24 lukem 476 1.24 lukem /* host may be NULL */ 477 1.24 lukem /* user may be NULL */ 478 1.24 lukem /* domain may be NULL */ 479 1.24 lukem _DIAGASSERT(ng != NULL); 480 1.24 lukem 481 1.6 christos if ((host != NULL) && (ng->ng_host != NULL) 482 1.4 christos && strcmp(ng->ng_host, host) != 0) 483 1.4 christos return 0; 484 1.4 christos 485 1.6 christos if ((user != NULL) && (ng->ng_user != NULL) 486 1.4 christos && strcmp(ng->ng_user, user) != 0) 487 1.4 christos return 0; 488 1.4 christos 489 1.6 christos if ((domain != NULL) && (ng->ng_domain != NULL) 490 1.4 christos && strcmp(ng->ng_domain, domain) != 0) 491 1.4 christos return 0; 492 1.1 mycroft 493 1.4 christos return 1; 494 1.1 mycroft } 495 1.1 mycroft 496 1.4 christos 497 1.1 mycroft /* 498 1.26 lukem * in_find(): Find a match for the host, user, domain spec. 499 1.26 lukem * grp is not a valid pointer after return (either free(3)ed or allocated 500 1.26 lukem * to a stringlist). in either case, it shouldn't be used again. 501 1.1 mycroft */ 502 1.1 mycroft static int 503 1.30 christos in_find(StringList *sl, char *grp, const char *host, const char *user, 504 1.30 christos const char *domain) 505 1.1 mycroft { 506 1.4 christos char *line, *p; 507 1.4 christos int i; 508 1.4 christos struct netgroup *ng; 509 1.4 christos char *name; 510 1.4 christos 511 1.24 lukem _DIAGASSERT(sl != NULL); 512 1.24 lukem _DIAGASSERT(grp != NULL); 513 1.24 lukem /* host may be NULL */ 514 1.24 lukem /* user may be NULL */ 515 1.24 lukem /* domain may be NULL */ 516 1.24 lukem 517 1.4 christos #ifdef DEBUG_NG 518 1.30 christos (void)fprintf(stderr, "in_find(%s)\n", grp); 519 1.4 christos #endif 520 1.4 christos /* check for cycles */ 521 1.11 lukem if (sl_find(sl, grp) != NULL) { 522 1.32 christos _ng_cycle(grp, sl); 523 1.6 christos free(grp); 524 1.4 christos return 0; 525 1.4 christos } 526 1.26 lukem if (sl_add(sl, grp) == -1) { 527 1.26 lukem free(grp); 528 1.26 lukem return 0; 529 1.26 lukem } 530 1.1 mycroft 531 1.4 christos /* Lookup this netgroup */ 532 1.17 lukem line = NULL; 533 1.17 lukem if (!lookup(grp, &line, _NG_KEYBYNAME)) { 534 1.17 lukem if (line) 535 1.17 lukem free(line); 536 1.4 christos return 0; 537 1.17 lukem } 538 1.4 christos 539 1.4 christos p = line; 540 1.4 christos 541 1.4 christos for (;;) { 542 1.4 christos switch (_ng_parse(&p, &name, &ng)) { 543 1.4 christos case _NG_NONE: 544 1.4 christos /* Done with the line */ 545 1.4 christos free(line); 546 1.4 christos return 0; 547 1.4 christos 548 1.4 christos case _NG_GROUP: 549 1.4 christos /* new netgroup */ 550 1.4 christos i = in_check(host, user, domain, ng); 551 1.6 christos if (ng->ng_host != NULL) 552 1.30 christos free(ng->ng_host); 553 1.6 christos if (ng->ng_user != NULL) 554 1.30 christos free(ng->ng_user); 555 1.6 christos if (ng->ng_domain != NULL) 556 1.30 christos free(ng->ng_domain); 557 1.4 christos free(ng); 558 1.4 christos if (i) { 559 1.4 christos free(line); 560 1.4 christos return 1; 561 1.4 christos } 562 1.1 mycroft break; 563 1.4 christos 564 1.4 christos case _NG_NAME: 565 1.4 christos /* netgroup name */ 566 1.17 lukem if (in_find(sl, name, host, user, domain)) { 567 1.4 christos free(line); 568 1.4 christos return 1; 569 1.1 mycroft } 570 1.4 christos break; 571 1.4 christos 572 1.4 christos case _NG_ERROR: 573 1.4 christos free(line); 574 1.4 christos return 0; 575 1.4 christos 576 1.4 christos default: 577 1.4 christos abort(); 578 1.1 mycroft } 579 1.1 mycroft } 580 1.4 christos } 581 1.4 christos 582 1.4 christos /* 583 1.4 christos * _ng_makekey(): Make a key from the two names given. The key is of the form 584 1.4 christos * <name1>.<name2> Names strings are replaced with * if they are empty; 585 1.26 lukem * Returns NULL if there's a problem. 586 1.4 christos */ 587 1.4 christos char * 588 1.30 christos _ng_makekey(const char *s1, const char *s2, size_t len) 589 1.4 christos { 590 1.24 lukem char *buf; 591 1.24 lukem 592 1.24 lukem /* s1 may be NULL */ 593 1.24 lukem /* s2 may be NULL */ 594 1.24 lukem 595 1.24 lukem buf = malloc(len); 596 1.26 lukem if (buf != NULL) 597 1.30 christos (void)snprintf(buf, len, "%s.%s", _NG_STAR(s1), _NG_STAR(s2)); 598 1.4 christos return buf; 599 1.9 christos } 600 1.9 christos 601 1.9 christos void 602 1.30 christos _ng_print(char *buf, size_t len, const struct netgroup *ng) 603 1.9 christos { 604 1.24 lukem _DIAGASSERT(buf != NULL); 605 1.24 lukem _DIAGASSERT(ng != NULL); 606 1.24 lukem 607 1.30 christos (void)snprintf(buf, len, "(%s,%s,%s)", _NG_EMPTY(ng->ng_host), 608 1.9 christos _NG_EMPTY(ng->ng_user), _NG_EMPTY(ng->ng_domain)); 609 1.4 christos } 610 1.4 christos 611 1.4 christos 612 1.4 christos /* 613 1.4 christos * in_lookup1(): Fast lookup for a key in the appropriate map 614 1.4 christos */ 615 1.4 christos static char * 616 1.30 christos in_lookup1(const char *key, const char *domain, int map) 617 1.4 christos { 618 1.4 christos char *line; 619 1.4 christos size_t len; 620 1.4 christos char *ptr; 621 1.4 christos int res; 622 1.4 christos 623 1.24 lukem /* key may be NULL */ 624 1.24 lukem /* domain may be NULL */ 625 1.24 lukem 626 1.4 christos len = (key ? strlen(key) : 1) + (domain ? strlen(domain) : 1) + 2; 627 1.4 christos ptr = _ng_makekey(key, domain, len); 628 1.26 lukem if (ptr == NULL) 629 1.26 lukem return NULL; 630 1.17 lukem res = lookup(ptr, &line, map); 631 1.4 christos free(ptr); 632 1.4 christos return res ? line : NULL; 633 1.4 christos } 634 1.4 christos 635 1.4 christos 636 1.4 christos /* 637 1.4 christos * in_lookup(): Fast lookup for a key in the appropriate map 638 1.4 christos */ 639 1.4 christos static int 640 1.30 christos in_lookup(const char *group, const char *key, const char *domain, int map) 641 1.4 christos { 642 1.4 christos size_t len; 643 1.4 christos char *ptr, *line; 644 1.4 christos 645 1.24 lukem _DIAGASSERT(group != NULL); 646 1.24 lukem /* key may be NULL */ 647 1.24 lukem /* domain may be NULL */ 648 1.24 lukem 649 1.4 christos if (domain != NULL) { 650 1.4 christos /* Domain specified; look in "group.domain" and "*.domain" */ 651 1.17 lukem if ((line = in_lookup1(key, domain, map)) == NULL) 652 1.17 lukem line = in_lookup1(NULL, domain, map); 653 1.26 lukem } else 654 1.4 christos line = NULL; 655 1.4 christos 656 1.4 christos if (line == NULL) { 657 1.30 christos /* 658 1.30 christos * domain not specified or domain lookup failed; look in 659 1.30 christos * "group.*" and "*.*" 660 1.30 christos */ 661 1.17 lukem if (((line = in_lookup1(key, NULL, map)) == NULL) && 662 1.17 lukem ((line = in_lookup1(NULL, NULL, map)) == NULL)) 663 1.4 christos return 0; 664 1.4 christos } 665 1.4 christos 666 1.4 christos len = strlen(group); 667 1.4 christos 668 1.4 christos for (ptr = line; (ptr = strstr(ptr, group)) != NULL;) 669 1.4 christos /* Make sure we did not find a substring */ 670 1.4 christos if ((ptr != line && ptr[-1] != ',') || 671 1.4 christos (ptr[len] != '\0' && strchr("\n\t ,", ptr[len]) == NULL)) 672 1.4 christos ptr++; 673 1.4 christos else { 674 1.4 christos free(line); 675 1.4 christos return 1; 676 1.1 mycroft } 677 1.4 christos 678 1.4 christos free(line); 679 1.4 christos return 0; 680 1.4 christos } 681 1.4 christos 682 1.38 oster /*ARGSUSED*/ 683 1.38 oster static int 684 1.39 oster _local_endnetgrent(void *rv, void *cb_data, va_list ap) 685 1.4 christos { 686 1.4 christos for (_nglist = _nghead; _nglist != NULL; _nglist = _nghead) { 687 1.4 christos _nghead = _nglist->ng_next; 688 1.6 christos if (_nglist->ng_host != NULL) 689 1.30 christos free(_nglist->ng_host); 690 1.6 christos if (_nglist->ng_user != NULL) 691 1.30 christos free(_nglist->ng_user); 692 1.6 christos if (_nglist->ng_domain != NULL) 693 1.30 christos free(_nglist->ng_domain); 694 1.4 christos free(_nglist); 695 1.4 christos } 696 1.4 christos 697 1.4 christos if (_ng_db) { 698 1.30 christos (void)(*_ng_db->close)(_ng_db); 699 1.4 christos _ng_db = NULL; 700 1.4 christos } 701 1.38 oster 702 1.38 oster return NS_SUCCESS; 703 1.4 christos } 704 1.4 christos 705 1.38 oster /*ARGSUSED*/ 706 1.38 oster static int 707 1.39 oster _local_setnetgrent(void *rv, void *cb_data, va_list ap) 708 1.4 christos { 709 1.38 oster const char *ng = va_arg(ap, const char *); 710 1.26 lukem StringList *sl; 711 1.17 lukem char *ng_copy; 712 1.4 christos 713 1.24 lukem _DIAGASSERT(ng != NULL); 714 1.24 lukem 715 1.26 lukem sl = sl_init(); 716 1.26 lukem if (sl == NULL) 717 1.38 oster return NS_TRYAGAIN; 718 1.26 lukem 719 1.4 christos /* Cleanup any previous storage */ 720 1.4 christos if (_nghead != NULL) 721 1.4 christos endnetgrent(); 722 1.4 christos 723 1.4 christos if (_ng_db == NULL) 724 1.4 christos _ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL); 725 1.4 christos 726 1.4 christos ng_copy = strdup(ng); 727 1.26 lukem if (ng_copy != NULL) 728 1.26 lukem addgroup(sl, ng_copy); 729 1.4 christos _nghead = _nglist; 730 1.11 lukem sl_free(sl, 1); 731 1.38 oster 732 1.38 oster return NS_SUCCESS; 733 1.4 christos } 734 1.4 christos 735 1.38 oster /*ARGSUSED*/ 736 1.38 oster static int 737 1.39 oster _local_getnetgrent(void *rv, void *cb_data, va_list ap) 738 1.38 oster { 739 1.38 oster int *retval = va_arg(ap, int *); 740 1.38 oster const char **host = va_arg(ap, const char **); 741 1.38 oster const char **user = va_arg(ap, const char **); 742 1.38 oster const char **domain = va_arg(ap, const char **); 743 1.4 christos 744 1.24 lukem _DIAGASSERT(host != NULL); 745 1.24 lukem _DIAGASSERT(user != NULL); 746 1.24 lukem _DIAGASSERT(domain != NULL); 747 1.24 lukem 748 1.38 oster *retval = 0; 749 1.38 oster 750 1.4 christos if (_nglist == NULL) 751 1.38 oster return NS_TRYAGAIN; 752 1.4 christos 753 1.4 christos *host = _nglist->ng_host; 754 1.4 christos *user = _nglist->ng_user; 755 1.4 christos *domain = _nglist->ng_domain; 756 1.4 christos 757 1.4 christos _nglist = _nglist->ng_next; 758 1.4 christos 759 1.38 oster *retval = 1; 760 1.38 oster 761 1.38 oster return NS_SUCCESS; 762 1.4 christos } 763 1.4 christos 764 1.38 oster /*ARGSUSED*/ 765 1.38 oster static int 766 1.39 oster _local_innetgr(void *rv, void *cb_data, va_list ap) 767 1.38 oster { 768 1.38 oster int *retval = va_arg(ap, int *); 769 1.38 oster const char *grp = va_arg(ap, const char *); 770 1.38 oster const char *host = va_arg(ap, const char *); 771 1.38 oster const char *user = va_arg(ap, const char *); 772 1.38 oster const char *domain = va_arg(ap, const char *); 773 1.4 christos 774 1.4 christos int found; 775 1.11 lukem StringList *sl; 776 1.30 christos char *grcpy; 777 1.24 lukem 778 1.24 lukem _DIAGASSERT(grp != NULL); 779 1.24 lukem /* host may be NULL */ 780 1.24 lukem /* user may be NULL */ 781 1.24 lukem /* domain may be NULL */ 782 1.4 christos 783 1.4 christos if (_ng_db == NULL) 784 1.4 christos _ng_db = dbopen(_PATH_NETGROUP_DB, O_RDONLY, 0, DB_HASH, NULL); 785 1.4 christos 786 1.4 christos /* Try the fast lookup first */ 787 1.4 christos if (host != NULL && user == NULL) { 788 1.38 oster if (in_lookup(grp, host, domain, _NG_KEYBYHOST)) { 789 1.38 oster *retval = 1; 790 1.38 oster return NS_SUCCESS; 791 1.38 oster } 792 1.4 christos } else if (host == NULL && user != NULL) { 793 1.38 oster if (in_lookup(grp, user, domain, _NG_KEYBYUSER)) { 794 1.38 oster *retval = 1; 795 1.38 oster return NS_SUCCESS; 796 1.38 oster } 797 1.4 christos } 798 1.4 christos /* If a domainname is given, we would have found a match */ 799 1.38 oster if (domain != NULL) { 800 1.38 oster *retval = 0; 801 1.38 oster return NS_SUCCESS; 802 1.38 oster } 803 1.4 christos 804 1.4 christos /* Too bad need the slow recursive way */ 805 1.11 lukem sl = sl_init(); 806 1.38 oster if (sl == NULL) { 807 1.38 oster *retval = 0; 808 1.38 oster return NS_SUCCESS; 809 1.38 oster } 810 1.31 christos if ((grcpy = strdup(grp)) == NULL) { 811 1.31 christos sl_free(sl, 1); 812 1.38 oster *retval = 0; 813 1.38 oster return NS_SUCCESS; 814 1.31 christos } 815 1.30 christos found = in_find(sl, grcpy, host, user, domain); 816 1.11 lukem sl_free(sl, 1); 817 1.4 christos 818 1.38 oster *retval = found; 819 1.38 oster return NS_SUCCESS; 820 1.38 oster } 821 1.38 oster 822 1.39 oster #ifdef YP 823 1.38 oster 824 1.39 oster /*ARGSUSED*/ 825 1.39 oster static int 826 1.39 oster _nis_endnetgrent(void *rv, void *cb_data, va_list ap) 827 1.39 oster { 828 1.39 oster return _local_endnetgrent(rv, cb_data, ap); 829 1.39 oster } 830 1.38 oster 831 1.39 oster /*ARGSUSED*/ 832 1.39 oster static int 833 1.39 oster _nis_setnetgrent(void *rv, void *cb_data, va_list ap) 834 1.39 oster { 835 1.39 oster return _local_setnetgrent(rv, cb_data, ap); 836 1.39 oster } 837 1.38 oster 838 1.39 oster /*ARGSUSED*/ 839 1.39 oster static int 840 1.39 oster _nis_getnetgrent(void *rv, void *cb_data, va_list ap) 841 1.39 oster { 842 1.39 oster return _local_getnetgrent(rv, cb_data, ap); 843 1.39 oster } 844 1.38 oster 845 1.39 oster /*ARGSUSED*/ 846 1.39 oster static int 847 1.39 oster _nis_innetgr(void *rv, void *cb_data, va_list ap) 848 1.39 oster { 849 1.39 oster return _local_innetgr(rv, cb_data, ap); 850 1.39 oster } 851 1.39 oster 852 1.39 oster #endif 853 1.39 oster 854 1.39 oster 855 1.39 oster #ifdef NSSRC_FILES 856 1.38 oster void 857 1.38 oster endnetgrent(void) 858 1.38 oster { 859 1.38 oster static const ns_dtab dtab[] = { 860 1.39 oster NS_FILES_CB(_local_endnetgrent, NULL) 861 1.38 oster NS_NIS_CB(_nis_endnetgrent, NULL) 862 1.38 oster NS_NULL_CB 863 1.38 oster }; 864 1.38 oster 865 1.38 oster (void) nsdispatch(NULL, dtab, NSDB_NETGROUP, "endnetgrent", 866 1.38 oster __nsdefaultcompat); 867 1.38 oster } 868 1.39 oster #else 869 1.39 oster static int 870 1.39 oster _local_endnetgrentv(int *rv, void *cbdata, ...) 871 1.39 oster { 872 1.39 oster int e; 873 1.39 oster va_list ap; 874 1.39 oster va_start(ap, cbdata); 875 1.39 oster e = _local_endnetgrent(rv, cbdata, ap); 876 1.39 oster va_end(ap); 877 1.39 oster return e; 878 1.39 oster } 879 1.38 oster 880 1.39 oster void 881 1.39 oster endnetgrent(void) 882 1.39 oster { 883 1.39 oster (void)_local_endnetgrentv(NULL, NULL, NULL); 884 1.39 oster } 885 1.39 oster #endif 886 1.38 oster 887 1.39 oster #ifdef NSSRC_FILES 888 1.38 oster void 889 1.38 oster setnetgrent(const char *ng) 890 1.38 oster { 891 1.38 oster static const ns_dtab dtab[] = { 892 1.39 oster NS_FILES_CB(_local_setnetgrent, NULL) 893 1.38 oster NS_NIS_CB(_nis_setnetgrent, NULL) 894 1.38 oster NS_NULL_CB 895 1.38 oster }; 896 1.38 oster 897 1.40 rtr (void) nsdispatch(NULL, dtab, NSDB_NETGROUP, "setnetgrent", 898 1.38 oster __nsdefaultnis, ng); 899 1.38 oster } 900 1.39 oster #else 901 1.39 oster static int 902 1.39 oster _local_setnetgrentv(int *rv, void *cbdata, ...) 903 1.39 oster { 904 1.39 oster int e; 905 1.39 oster va_list ap; 906 1.39 oster va_start(ap, cbdata); 907 1.39 oster e = _local_setnetgrent(rv, cbdata, ap); 908 1.39 oster va_end(ap); 909 1.39 oster return e; 910 1.39 oster } 911 1.38 oster 912 1.39 oster void 913 1.39 oster setnetgrent(const char *ng) 914 1.39 oster { 915 1.39 oster (void) _local_setnetgrentv(NULL, NULL,ng); 916 1.39 oster } 917 1.39 oster 918 1.39 oster #endif 919 1.38 oster 920 1.39 oster #ifdef NSSRC_FILES 921 1.38 oster int 922 1.38 oster getnetgrent(const char **host, const char **user, const char **domain) 923 1.38 oster { 924 1.38 oster int r, retval; 925 1.38 oster static const ns_dtab dtab[] = { 926 1.39 oster NS_FILES_CB(_local_getnetgrent, NULL) 927 1.38 oster NS_NIS_CB(_nis_getnetgrent, NULL) 928 1.38 oster NS_NULL_CB 929 1.38 oster }; 930 1.38 oster 931 1.38 oster r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "getnetgrent", 932 1.38 oster __nsdefaultnis, &retval, host, user, domain); 933 1.38 oster 934 1.38 oster return (r == NS_SUCCESS) ? retval : 0; 935 1.38 oster } 936 1.39 oster #else 937 1.39 oster static int 938 1.39 oster _local_getnetgrentv(int *rv, void *cbdata, ...) 939 1.39 oster { 940 1.39 oster int e; 941 1.39 oster va_list ap; 942 1.39 oster va_start(ap, cbdata); 943 1.39 oster e = _local_getnetgrent(rv, cbdata, ap); 944 1.39 oster va_end(ap); 945 1.39 oster return e; 946 1.39 oster } 947 1.38 oster 948 1.39 oster int 949 1.39 oster getnetgrent(const char **host, const char **user, const char **domain) 950 1.39 oster { 951 1.39 oster return _local_getnetgrentv(NULL, NULL, host, user, domain) == NS_SUCCESS; 952 1.39 oster } 953 1.39 oster #endif 954 1.38 oster 955 1.39 oster #ifdef NSSRC_FILES 956 1.38 oster int 957 1.39 oster innetgr(const char *grp, const char *host, const char *user, 958 1.39 oster const char *domain) 959 1.38 oster { 960 1.38 oster int r, retval; 961 1.38 oster static const ns_dtab dtab[] = { 962 1.39 oster NS_FILES_CB(_local_innetgr, NULL) 963 1.38 oster NS_NIS_CB(_nis_innetgr, NULL) 964 1.38 oster NS_NULL_CB 965 1.38 oster }; 966 1.38 oster 967 1.38 oster r = nsdispatch(NULL, dtab, NSDB_NETGROUP, "innetgr", 968 1.38 oster __nsdefaultnis, &retval, grp, host, user, domain); 969 1.38 oster 970 1.38 oster return (r == NS_SUCCESS) ? retval : 0; 971 1.1 mycroft } 972 1.39 oster #else 973 1.39 oster static int 974 1.39 oster _local_innetgrv(int *rv, void *cbdata, ...) 975 1.39 oster { 976 1.39 oster int e; 977 1.39 oster va_list ap; 978 1.39 oster va_start(ap, cbdata); 979 1.39 oster e = _local_innetgr(rv, cbdata, ap); 980 1.39 oster va_end(ap); 981 1.39 oster return e; 982 1.39 oster } 983 1.39 oster 984 1.39 oster int 985 1.39 oster innetgr(const char *grp, const char *host, const char *user, 986 1.39 oster const char *domain) 987 1.39 oster { 988 1.39 oster return _local_innetgrv(NULL, NULL, grp, host, user, domain) == NS_SUCCESS; 989 1.39 oster } 990 1.39 oster #endif 991