1/* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#if defined(LIBC_SCCS) && !defined(lint)
| 1/* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#if defined(LIBC_SCCS) && !defined(lint)
|
39#endif /* LIBC_SCCS and not lint */ 40 41#include <stdio.h> 42#include <strings.h> 43#include <stdlib.h> 44#include <unistd.h> 45 46#ifdef YP 47/* 48 * Notes: 49 * We want to be able to use NIS netgroups properly while retaining 50 * the ability to use a local /etc/netgroup file. Unfortunately, you 51 * can't really do both at the same time - at least, not efficiently. 52 * NetBSD deals with this problem by creating a netgroup database 53 * using Berkeley DB (just like the password database) that allows 54 * for lookups using netgroup, netgroup.byuser or netgroup.byhost 55 * searches. This is a neat idea, but I don't have time to implement 56 * something like that now. (I think ultimately it would be nice 57 * if we DB-fied the group and netgroup stuff all in one shot, but 58 * for now I'm satisfied just to have something that works well 59 * without requiring massive code changes.) 60 * 61 * Therefore, to still permit the use of the local file and maintain 62 * optimum NIS performance, we allow for the following conditions: 63 * 64 * - If /etc/netgroup does not exist and NIS is turned on, we use 65 * NIS netgroups only. 66 * 67 * - If /etc/netgroup exists but is empty, we use NIS netgroups 68 * only. 69 * 70 * - If /etc/netgroup exists and contains _only_ a '+', we use 71 * NIS netgroups only. 72 * 73 * - If /etc/netgroup exists, contains locally defined netgroups 74 * and a '+', we use a mixture of NIS and the local entries. 75 * This method should return the same NIS data as just using 76 * NIS alone, but it will be slower if the NIS netgroup database 77 * is large (innetgr() in particular will suffer since extra 78 * processing has to be done in order to determine memberships 79 * using just the raw netgroup data). 80 * 81 * - If /etc/netgroup exists and contains only locally defined 82 * netgroup entries, we use just those local entries and ignore 83 * NIS (this is the original, pre-NIS behavior). 84 */ 85#include <rpc/rpc.h> 86#include <rpcsvc/yp_prot.h> 87#include <rpcsvc/ypclnt.h> 88#include <sys/types.h> 89#include <sys/stat.h> 90#include <sys/param.h> 91#include <sys/errno.h> 92static char *_netgr_yp_domain; 93int _use_only_yp; 94static int _netgr_yp_enabled; 95static int _yp_innetgr; 96#endif 97 98#ifndef _PATH_NETGROUP 99#define _PATH_NETGROUP "/etc/netgroup" 100#endif 101 102/* 103 * Static Variables and functions used by setnetgrent(), getnetgrent() and 104 * endnetgrent(). 105 * There are two linked lists: 106 * - linelist is just used by setnetgrent() to parse the net group file via. 107 * parse_netgrp() 108 * - netgrp is the list of entries for the current netgroup 109 */ 110struct linelist { 111 struct linelist *l_next; /* Chain ptr. */ 112 int l_parsed; /* Flag for cycles */ 113 char *l_groupname; /* Name of netgroup */ 114 char *l_line; /* Netgroup entrie(s) to be parsed */ 115}; 116 117struct netgrp { 118 struct netgrp *ng_next; /* Chain ptr */ 119 char *ng_str[3]; /* Field pointers, see below */ 120}; 121#define NG_HOST 0 /* Host name */ 122#define NG_USER 1 /* User name */ 123#define NG_DOM 2 /* and Domain name */ 124 125static struct linelist *linehead = (struct linelist *)0; 126static struct netgrp *nextgrp = (struct netgrp *)0; 127static struct { 128 struct netgrp *gr; 129 char *grname; 130} grouphead = { 131 (struct netgrp *)0, 132 (char *)0, 133}; 134static FILE *netf = (FILE *)0; 135static int parse_netgrp(); 136static struct linelist *read_for_group(); 137void setnetgrent(), endnetgrent(); 138int getnetgrent(), innetgr(); 139 140#define LINSIZ 1024 /* Length of netgroup file line */ 141 142/* 143 * setnetgrent() 144 * Parse the netgroup file looking for the netgroup and build the list 145 * of netgrp structures. Let parse_netgrp() and read_for_group() do 146 * most of the work. 147 */ 148void 149setnetgrent(group) 150 char *group; 151{ 152#ifdef YP 153 struct stat _yp_statp; 154 char _yp_plus; 155#endif 156 157 /* Sanity check */ 158 159 if (group == NULL || !strlen(group)) 160 return; 161 162 if (grouphead.gr == (struct netgrp *)0 || 163 strcmp(group, grouphead.grname)) { 164 endnetgrent(); 165#ifdef YP 166 /* Presumed guilty until proven innocent. */ 167 _use_only_yp = 0; 168 /* 169 * If /etc/netgroup doesn't exist or is empty, 170 * use NIS exclusively. 171 */ 172 if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 173 errno == ENOENT) || _yp_statp.st_size == 0) 174 _use_only_yp = _netgr_yp_enabled = 1; 175 if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ 176 /* 177 * Icky: grab the first character of the netgroup file 178 * and turn on NIS if it's a '+'. rewind the stream 179 * afterwards so we don't goof up read_for_group() later. 180 */ 181 if (netf) { 182 fscanf(netf, "%c", &_yp_plus); 183 rewind(netf); 184 if (_yp_plus == '+') 185 _use_only_yp = _netgr_yp_enabled = 1; 186 } 187 /* 188 * If we were called specifically for an innetgr() 189 * lookup and we're in NIS-only mode, short-circuit 190 * parse_netgroup() and cut directly to the chase. 191 */ 192 if (_use_only_yp && _yp_innetgr) { 193 /* dohw! */ 194 if (netf != NULL) 195 fclose(netf); 196 return; 197 } 198#else 199 if (netf = fopen(_PATH_NETGROUP, "r")) { 200#endif 201 if (parse_netgrp(group)) 202 endnetgrent(); 203 else { 204 grouphead.grname = (char *) 205 malloc(strlen(group) + 1); 206 strcpy(grouphead.grname, group); 207 } 208 if (netf) 209 fclose(netf); 210 } 211 } 212 nextgrp = grouphead.gr; 213} 214 215/* 216 * Get the next netgroup off the list. 217 */ 218int 219getnetgrent(hostp, userp, domp) 220 char **hostp, **userp, **domp; 221{ 222#ifdef YP 223 _yp_innetgr = 0; 224#endif 225 226 if (nextgrp) { 227 *hostp = nextgrp->ng_str[NG_HOST]; 228 *userp = nextgrp->ng_str[NG_USER]; 229 *domp = nextgrp->ng_str[NG_DOM]; 230 nextgrp = nextgrp->ng_next; 231 return (1); 232 } 233 return (0); 234} 235 236/* 237 * endnetgrent() - cleanup 238 */ 239void 240endnetgrent() 241{ 242 register struct linelist *lp, *olp; 243 register struct netgrp *gp, *ogp; 244 245 lp = linehead; 246 while (lp) { 247 olp = lp; 248 lp = lp->l_next; 249 free(olp->l_groupname); 250 free(olp->l_line); 251 free((char *)olp); 252 } 253 linehead = (struct linelist *)0; 254 if (grouphead.grname) { 255 free(grouphead.grname); 256 grouphead.grname = (char *)0; 257 } 258 gp = grouphead.gr; 259 while (gp) { 260 ogp = gp; 261 gp = gp->ng_next; 262 if (ogp->ng_str[NG_HOST]) 263 free(ogp->ng_str[NG_HOST]); 264 if (ogp->ng_str[NG_USER]) 265 free(ogp->ng_str[NG_USER]); 266 if (ogp->ng_str[NG_DOM]) 267 free(ogp->ng_str[NG_DOM]); 268 free((char *)ogp); 269 } 270 grouphead.gr = (struct netgrp *)0; 271#ifdef YP 272 _netgr_yp_enabled = 0; 273#endif 274} 275 276#ifdef YP 277static int _listmatch(list, group, len) 278char *list, *group; 279int len; 280{ 281 char *ptr = list; 282 283 while ( (ptr = strstr(ptr, group)) ) { 284 285 ptr += strlen(group); 286 287 if (*ptr == ',' || *ptr == '\0') 288 return(1); 289 } 290 291 return(0); 292} 293 294static int _buildkey(key, str, dom, rotation) 295char *key, *str, *dom; 296int *rotation; 297{ 298 (*rotation)++; 299 if (*rotation > 4) 300 return(0); 301 switch(*rotation) { 302 case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*"); 303 break; 304 case(2): sprintf((char *)key, "%s.*", str); 305 break; 306 case(3): sprintf((char *)key, "*.%s", dom ? dom : "*"); 307 break; 308 case(4): sprintf((char *)key, "*.*"); 309 break; 310 } 311 return(1); 312} 313#endif 314 315/* 316 * Search for a match in a netgroup. 317 */ 318int 319innetgr(group, host, user, dom) 320 const char *group, *host, *user, *dom; 321{ 322 char *hst, *usr, *dm; 323#ifdef YP 324 char *result; 325 int resultlen; 326 int rv; 327#endif 328 /* Sanity check */ 329 330 if (group == NULL || !strlen(group)) 331 return (0); 332 333#ifdef YP 334 _yp_innetgr = 1; 335#endif 336 setnetgrent(group); 337#ifdef YP 338 _yp_innetgr = 0; 339 /* 340 * If we're in NIS-only mode, do the search using 341 * NIS 'reverse netgroup' lookups. 342 */ 343 if (_use_only_yp) { 344 char _key[MAXHOSTNAMELEN]; 345 int rot = 0; 346 347 if(yp_get_default_domain(&_netgr_yp_domain)) 348 return(0); 349 while(_buildkey(_key, user ? user : host, dom, &rot)) { 350 if (!yp_match(_netgr_yp_domain, user? "netgroup.byuser": 351 "netgroup.byhost", _key, strlen(_key), &result, 352 &resultlen)) { 353 rv = _listmatch(result, group, resultlen); 354 free(result); 355 if (rv) 356 return(1); 357 else 358 return(0); 359 } 360 } 361#ifdef CHARITABLE 362 } 363 /* 364 * Couldn't match using NIS-exclusive mode -- try 365 * standard mode. 366 */ 367 setnetgrent(group); 368#else 369 return(0); 370 } 371#endif /* CHARITABLE */ 372#endif /* YP */ 373 while (getnetgrent(&hst, &usr, &dm)) 374 if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 375 (user == NULL || usr == NULL || !strcmp(user, usr)) && 376 ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 377 endnetgrent(); 378 return (1); 379 } 380 endnetgrent(); 381 return (0); 382} 383 384/* 385 * Parse the netgroup file setting up the linked lists. 386 */ 387static int 388parse_netgrp(group) 389 char *group; 390{ 391 register char *spos, *epos; 392 register int len, strpos; 393#ifdef DEBUG 394 register int fields; 395#endif 396 char *pos, *gpos; 397 struct netgrp *grp; 398 struct linelist *lp = linehead; 399 400 /* 401 * First, see if the line has already been read in. 402 */ 403 while (lp) { 404 if (!strcmp(group, lp->l_groupname)) 405 break; 406 lp = lp->l_next; 407 } 408 if (lp == (struct linelist *)0 && 409 (lp = read_for_group(group)) == (struct linelist *)0) 410 return (1); 411 if (lp->l_parsed) { 412#ifdef DEBUG 413 /* 414 * This error message is largely superflous since the 415 * code handles the error condition sucessfully, and 416 * spewing it out from inside libc can actually hose 417 * certain programs. 418 */ 419 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 420#endif 421 return (1); 422 } else 423 lp->l_parsed = 1; 424 pos = lp->l_line; 425 /* Watch for null pointer dereferences, dammit! */ 426 while (pos != NULL && *pos != '\0') { 427 if (*pos == '(') { 428 grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 429 bzero((char *)grp, sizeof (struct netgrp)); 430 grp->ng_next = grouphead.gr; 431 grouphead.gr = grp; 432 pos++; 433 gpos = strsep(&pos, ")"); 434#ifdef DEBUG 435 fields = 0; 436#endif 437 for (strpos = 0; strpos < 3; strpos++) { 438 if ((spos = strsep(&gpos, ","))) { 439#ifdef DEBUG 440 fields++; 441#endif 442 while (*spos == ' ' || *spos == '\t') 443 spos++; 444 if ((epos = strpbrk(spos, " \t"))) { 445 *epos = '\0'; 446 len = epos - spos; 447 } else 448 len = strlen(spos); 449 if (len > 0) { 450 grp->ng_str[strpos] = (char *) 451 malloc(len + 1); 452 bcopy(spos, grp->ng_str[strpos], 453 len + 1); 454 } 455 } else { 456 /* 457 * All other systems I've tested 458 * return NULL for empty netgroup 459 * fields. It's up to user programs 460 * to handle the NULLs appropriately. 461 */ 462 grp->ng_str[strpos] = NULL; 463 } 464 } 465#ifdef DEBUG 466 /* 467 * Note: on other platforms, malformed netgroup 468 * entries are not normally flagged. While we 469 * can catch bad entries and report them, we should 470 * stay silent by default for compatibility's sake. 471 */ 472 if (fields < 3) 473 fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 474 grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 475 grp->ng_str[NG_USER] == NULL ? "" : ",", 476 grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 477 grp->ng_str[NG_DOM] == NULL ? "" : ",", 478 grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 479 lp->l_groupname); 480#endif 481 } else { 482 spos = strsep(&pos, ", \t"); 483 if (parse_netgrp(spos)) 484 continue; 485 }
| 39#endif /* LIBC_SCCS and not lint */ 40 41#include <stdio.h> 42#include <strings.h> 43#include <stdlib.h> 44#include <unistd.h> 45 46#ifdef YP 47/* 48 * Notes: 49 * We want to be able to use NIS netgroups properly while retaining 50 * the ability to use a local /etc/netgroup file. Unfortunately, you 51 * can't really do both at the same time - at least, not efficiently. 52 * NetBSD deals with this problem by creating a netgroup database 53 * using Berkeley DB (just like the password database) that allows 54 * for lookups using netgroup, netgroup.byuser or netgroup.byhost 55 * searches. This is a neat idea, but I don't have time to implement 56 * something like that now. (I think ultimately it would be nice 57 * if we DB-fied the group and netgroup stuff all in one shot, but 58 * for now I'm satisfied just to have something that works well 59 * without requiring massive code changes.) 60 * 61 * Therefore, to still permit the use of the local file and maintain 62 * optimum NIS performance, we allow for the following conditions: 63 * 64 * - If /etc/netgroup does not exist and NIS is turned on, we use 65 * NIS netgroups only. 66 * 67 * - If /etc/netgroup exists but is empty, we use NIS netgroups 68 * only. 69 * 70 * - If /etc/netgroup exists and contains _only_ a '+', we use 71 * NIS netgroups only. 72 * 73 * - If /etc/netgroup exists, contains locally defined netgroups 74 * and a '+', we use a mixture of NIS and the local entries. 75 * This method should return the same NIS data as just using 76 * NIS alone, but it will be slower if the NIS netgroup database 77 * is large (innetgr() in particular will suffer since extra 78 * processing has to be done in order to determine memberships 79 * using just the raw netgroup data). 80 * 81 * - If /etc/netgroup exists and contains only locally defined 82 * netgroup entries, we use just those local entries and ignore 83 * NIS (this is the original, pre-NIS behavior). 84 */ 85#include <rpc/rpc.h> 86#include <rpcsvc/yp_prot.h> 87#include <rpcsvc/ypclnt.h> 88#include <sys/types.h> 89#include <sys/stat.h> 90#include <sys/param.h> 91#include <sys/errno.h> 92static char *_netgr_yp_domain; 93int _use_only_yp; 94static int _netgr_yp_enabled; 95static int _yp_innetgr; 96#endif 97 98#ifndef _PATH_NETGROUP 99#define _PATH_NETGROUP "/etc/netgroup" 100#endif 101 102/* 103 * Static Variables and functions used by setnetgrent(), getnetgrent() and 104 * endnetgrent(). 105 * There are two linked lists: 106 * - linelist is just used by setnetgrent() to parse the net group file via. 107 * parse_netgrp() 108 * - netgrp is the list of entries for the current netgroup 109 */ 110struct linelist { 111 struct linelist *l_next; /* Chain ptr. */ 112 int l_parsed; /* Flag for cycles */ 113 char *l_groupname; /* Name of netgroup */ 114 char *l_line; /* Netgroup entrie(s) to be parsed */ 115}; 116 117struct netgrp { 118 struct netgrp *ng_next; /* Chain ptr */ 119 char *ng_str[3]; /* Field pointers, see below */ 120}; 121#define NG_HOST 0 /* Host name */ 122#define NG_USER 1 /* User name */ 123#define NG_DOM 2 /* and Domain name */ 124 125static struct linelist *linehead = (struct linelist *)0; 126static struct netgrp *nextgrp = (struct netgrp *)0; 127static struct { 128 struct netgrp *gr; 129 char *grname; 130} grouphead = { 131 (struct netgrp *)0, 132 (char *)0, 133}; 134static FILE *netf = (FILE *)0; 135static int parse_netgrp(); 136static struct linelist *read_for_group(); 137void setnetgrent(), endnetgrent(); 138int getnetgrent(), innetgr(); 139 140#define LINSIZ 1024 /* Length of netgroup file line */ 141 142/* 143 * setnetgrent() 144 * Parse the netgroup file looking for the netgroup and build the list 145 * of netgrp structures. Let parse_netgrp() and read_for_group() do 146 * most of the work. 147 */ 148void 149setnetgrent(group) 150 char *group; 151{ 152#ifdef YP 153 struct stat _yp_statp; 154 char _yp_plus; 155#endif 156 157 /* Sanity check */ 158 159 if (group == NULL || !strlen(group)) 160 return; 161 162 if (grouphead.gr == (struct netgrp *)0 || 163 strcmp(group, grouphead.grname)) { 164 endnetgrent(); 165#ifdef YP 166 /* Presumed guilty until proven innocent. */ 167 _use_only_yp = 0; 168 /* 169 * If /etc/netgroup doesn't exist or is empty, 170 * use NIS exclusively. 171 */ 172 if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) && 173 errno == ENOENT) || _yp_statp.st_size == 0) 174 _use_only_yp = _netgr_yp_enabled = 1; 175 if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){ 176 /* 177 * Icky: grab the first character of the netgroup file 178 * and turn on NIS if it's a '+'. rewind the stream 179 * afterwards so we don't goof up read_for_group() later. 180 */ 181 if (netf) { 182 fscanf(netf, "%c", &_yp_plus); 183 rewind(netf); 184 if (_yp_plus == '+') 185 _use_only_yp = _netgr_yp_enabled = 1; 186 } 187 /* 188 * If we were called specifically for an innetgr() 189 * lookup and we're in NIS-only mode, short-circuit 190 * parse_netgroup() and cut directly to the chase. 191 */ 192 if (_use_only_yp && _yp_innetgr) { 193 /* dohw! */ 194 if (netf != NULL) 195 fclose(netf); 196 return; 197 } 198#else 199 if (netf = fopen(_PATH_NETGROUP, "r")) { 200#endif 201 if (parse_netgrp(group)) 202 endnetgrent(); 203 else { 204 grouphead.grname = (char *) 205 malloc(strlen(group) + 1); 206 strcpy(grouphead.grname, group); 207 } 208 if (netf) 209 fclose(netf); 210 } 211 } 212 nextgrp = grouphead.gr; 213} 214 215/* 216 * Get the next netgroup off the list. 217 */ 218int 219getnetgrent(hostp, userp, domp) 220 char **hostp, **userp, **domp; 221{ 222#ifdef YP 223 _yp_innetgr = 0; 224#endif 225 226 if (nextgrp) { 227 *hostp = nextgrp->ng_str[NG_HOST]; 228 *userp = nextgrp->ng_str[NG_USER]; 229 *domp = nextgrp->ng_str[NG_DOM]; 230 nextgrp = nextgrp->ng_next; 231 return (1); 232 } 233 return (0); 234} 235 236/* 237 * endnetgrent() - cleanup 238 */ 239void 240endnetgrent() 241{ 242 register struct linelist *lp, *olp; 243 register struct netgrp *gp, *ogp; 244 245 lp = linehead; 246 while (lp) { 247 olp = lp; 248 lp = lp->l_next; 249 free(olp->l_groupname); 250 free(olp->l_line); 251 free((char *)olp); 252 } 253 linehead = (struct linelist *)0; 254 if (grouphead.grname) { 255 free(grouphead.grname); 256 grouphead.grname = (char *)0; 257 } 258 gp = grouphead.gr; 259 while (gp) { 260 ogp = gp; 261 gp = gp->ng_next; 262 if (ogp->ng_str[NG_HOST]) 263 free(ogp->ng_str[NG_HOST]); 264 if (ogp->ng_str[NG_USER]) 265 free(ogp->ng_str[NG_USER]); 266 if (ogp->ng_str[NG_DOM]) 267 free(ogp->ng_str[NG_DOM]); 268 free((char *)ogp); 269 } 270 grouphead.gr = (struct netgrp *)0; 271#ifdef YP 272 _netgr_yp_enabled = 0; 273#endif 274} 275 276#ifdef YP 277static int _listmatch(list, group, len) 278char *list, *group; 279int len; 280{ 281 char *ptr = list; 282 283 while ( (ptr = strstr(ptr, group)) ) { 284 285 ptr += strlen(group); 286 287 if (*ptr == ',' || *ptr == '\0') 288 return(1); 289 } 290 291 return(0); 292} 293 294static int _buildkey(key, str, dom, rotation) 295char *key, *str, *dom; 296int *rotation; 297{ 298 (*rotation)++; 299 if (*rotation > 4) 300 return(0); 301 switch(*rotation) { 302 case(1): sprintf((char *)key, "%s.%s", str, dom ? dom : "*"); 303 break; 304 case(2): sprintf((char *)key, "%s.*", str); 305 break; 306 case(3): sprintf((char *)key, "*.%s", dom ? dom : "*"); 307 break; 308 case(4): sprintf((char *)key, "*.*"); 309 break; 310 } 311 return(1); 312} 313#endif 314 315/* 316 * Search for a match in a netgroup. 317 */ 318int 319innetgr(group, host, user, dom) 320 const char *group, *host, *user, *dom; 321{ 322 char *hst, *usr, *dm; 323#ifdef YP 324 char *result; 325 int resultlen; 326 int rv; 327#endif 328 /* Sanity check */ 329 330 if (group == NULL || !strlen(group)) 331 return (0); 332 333#ifdef YP 334 _yp_innetgr = 1; 335#endif 336 setnetgrent(group); 337#ifdef YP 338 _yp_innetgr = 0; 339 /* 340 * If we're in NIS-only mode, do the search using 341 * NIS 'reverse netgroup' lookups. 342 */ 343 if (_use_only_yp) { 344 char _key[MAXHOSTNAMELEN]; 345 int rot = 0; 346 347 if(yp_get_default_domain(&_netgr_yp_domain)) 348 return(0); 349 while(_buildkey(_key, user ? user : host, dom, &rot)) { 350 if (!yp_match(_netgr_yp_domain, user? "netgroup.byuser": 351 "netgroup.byhost", _key, strlen(_key), &result, 352 &resultlen)) { 353 rv = _listmatch(result, group, resultlen); 354 free(result); 355 if (rv) 356 return(1); 357 else 358 return(0); 359 } 360 } 361#ifdef CHARITABLE 362 } 363 /* 364 * Couldn't match using NIS-exclusive mode -- try 365 * standard mode. 366 */ 367 setnetgrent(group); 368#else 369 return(0); 370 } 371#endif /* CHARITABLE */ 372#endif /* YP */ 373 while (getnetgrent(&hst, &usr, &dm)) 374 if ((host == NULL || hst == NULL || !strcmp(host, hst)) && 375 (user == NULL || usr == NULL || !strcmp(user, usr)) && 376 ( dom == NULL || dm == NULL || !strcmp(dom, dm))) { 377 endnetgrent(); 378 return (1); 379 } 380 endnetgrent(); 381 return (0); 382} 383 384/* 385 * Parse the netgroup file setting up the linked lists. 386 */ 387static int 388parse_netgrp(group) 389 char *group; 390{ 391 register char *spos, *epos; 392 register int len, strpos; 393#ifdef DEBUG 394 register int fields; 395#endif 396 char *pos, *gpos; 397 struct netgrp *grp; 398 struct linelist *lp = linehead; 399 400 /* 401 * First, see if the line has already been read in. 402 */ 403 while (lp) { 404 if (!strcmp(group, lp->l_groupname)) 405 break; 406 lp = lp->l_next; 407 } 408 if (lp == (struct linelist *)0 && 409 (lp = read_for_group(group)) == (struct linelist *)0) 410 return (1); 411 if (lp->l_parsed) { 412#ifdef DEBUG 413 /* 414 * This error message is largely superflous since the 415 * code handles the error condition sucessfully, and 416 * spewing it out from inside libc can actually hose 417 * certain programs. 418 */ 419 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 420#endif 421 return (1); 422 } else 423 lp->l_parsed = 1; 424 pos = lp->l_line; 425 /* Watch for null pointer dereferences, dammit! */ 426 while (pos != NULL && *pos != '\0') { 427 if (*pos == '(') { 428 grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 429 bzero((char *)grp, sizeof (struct netgrp)); 430 grp->ng_next = grouphead.gr; 431 grouphead.gr = grp; 432 pos++; 433 gpos = strsep(&pos, ")"); 434#ifdef DEBUG 435 fields = 0; 436#endif 437 for (strpos = 0; strpos < 3; strpos++) { 438 if ((spos = strsep(&gpos, ","))) { 439#ifdef DEBUG 440 fields++; 441#endif 442 while (*spos == ' ' || *spos == '\t') 443 spos++; 444 if ((epos = strpbrk(spos, " \t"))) { 445 *epos = '\0'; 446 len = epos - spos; 447 } else 448 len = strlen(spos); 449 if (len > 0) { 450 grp->ng_str[strpos] = (char *) 451 malloc(len + 1); 452 bcopy(spos, grp->ng_str[strpos], 453 len + 1); 454 } 455 } else { 456 /* 457 * All other systems I've tested 458 * return NULL for empty netgroup 459 * fields. It's up to user programs 460 * to handle the NULLs appropriately. 461 */ 462 grp->ng_str[strpos] = NULL; 463 } 464 } 465#ifdef DEBUG 466 /* 467 * Note: on other platforms, malformed netgroup 468 * entries are not normally flagged. While we 469 * can catch bad entries and report them, we should 470 * stay silent by default for compatibility's sake. 471 */ 472 if (fields < 3) 473 fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 474 grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 475 grp->ng_str[NG_USER] == NULL ? "" : ",", 476 grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 477 grp->ng_str[NG_DOM] == NULL ? "" : ",", 478 grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 479 lp->l_groupname); 480#endif 481 } else { 482 spos = strsep(&pos, ", \t"); 483 if (parse_netgrp(spos)) 484 continue; 485 }
|
490 } 491 return (0); 492} 493 494/* 495 * Read the netgroup file and save lines until the line for the netgroup 496 * is found. Return 1 if eof is encountered. 497 */ 498static struct linelist * 499read_for_group(group) 500 char *group; 501{ 502 register char *pos, *spos, *linep, *olinep; 503 register int len, olen; 504 int cont; 505 struct linelist *lp; 506 char line[LINSIZ + 2]; 507#ifdef YP 508 char *result; 509 int resultlen; 510 511 while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 512 if (_netgr_yp_enabled) { 513 if(!_netgr_yp_domain) 514 if(yp_get_default_domain(&_netgr_yp_domain)) 515 continue; 516 if (yp_match(_netgr_yp_domain, "netgroup", group, 517 strlen(group), &result, &resultlen)) { 518 free(result); 519 if (_use_only_yp) 520 return ((struct linelist *)0); 521 else { 522 _netgr_yp_enabled = 0; 523 continue; 524 } 525 } 526 snprintf(line, LINSIZ, "%s %s", group, result); 527 free(result); 528 } 529#else 530 while (fgets(line, LINSIZ, netf) != NULL) { 531#endif 532 pos = (char *)&line; 533#ifdef YP 534 if (*pos == '+') { 535 _netgr_yp_enabled = 1; 536 continue; 537 } 538#endif 539 if (*pos == '#') 540 continue; 541 while (*pos == ' ' || *pos == '\t') 542 pos++; 543 spos = pos; 544 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 545 *pos != '\0') 546 pos++; 547 len = pos - spos; 548 while (*pos == ' ' || *pos == '\t') 549 pos++; 550 if (*pos != '\n' && *pos != '\0') { 551 lp = (struct linelist *)malloc(sizeof (*lp)); 552 lp->l_parsed = 0; 553 lp->l_groupname = (char *)malloc(len + 1); 554 bcopy(spos, lp->l_groupname, len); 555 *(lp->l_groupname + len) = '\0'; 556 len = strlen(pos); 557 olen = 0; 558 559 /* 560 * Loop around handling line continuations. 561 */ 562 do { 563 if (*(pos + len - 1) == '\n') 564 len--; 565 if (*(pos + len - 1) == '\\') { 566 len--; 567 cont = 1; 568 } else 569 cont = 0; 570 if (len > 0) { 571 linep = (char *)malloc(olen + len + 1); 572 if (olen > 0) { 573 bcopy(olinep, linep, olen); 574 free(olinep); 575 } 576 bcopy(pos, linep + olen, len); 577 olen += len; 578 *(linep + olen) = '\0'; 579 olinep = linep; 580 } 581 if (cont) { 582 if (fgets(line, LINSIZ, netf)) { 583 pos = line; 584 len = strlen(pos); 585 } else 586 cont = 0; 587 } 588 } while (cont); 589 lp->l_line = linep; 590 lp->l_next = linehead; 591 linehead = lp; 592 593 /* 594 * If this is the one we wanted, we are done. 595 */ 596 if (!strcmp(lp->l_groupname, group)) 597 return (lp); 598 } 599 } 600#ifdef YP 601 /* 602 * Yucky. The recursive nature of this whole mess might require 603 * us to make more than one pass through the netgroup file. 604 * This might be best left outside the #ifdef YP, but YP is 605 * defined by default anyway, so I'll leave it like this 606 * until I know better. 607 */ 608 rewind(netf); 609#endif 610 return ((struct linelist *)0); 611}
| 490 } 491 return (0); 492} 493 494/* 495 * Read the netgroup file and save lines until the line for the netgroup 496 * is found. Return 1 if eof is encountered. 497 */ 498static struct linelist * 499read_for_group(group) 500 char *group; 501{ 502 register char *pos, *spos, *linep, *olinep; 503 register int len, olen; 504 int cont; 505 struct linelist *lp; 506 char line[LINSIZ + 2]; 507#ifdef YP 508 char *result; 509 int resultlen; 510 511 while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 512 if (_netgr_yp_enabled) { 513 if(!_netgr_yp_domain) 514 if(yp_get_default_domain(&_netgr_yp_domain)) 515 continue; 516 if (yp_match(_netgr_yp_domain, "netgroup", group, 517 strlen(group), &result, &resultlen)) { 518 free(result); 519 if (_use_only_yp) 520 return ((struct linelist *)0); 521 else { 522 _netgr_yp_enabled = 0; 523 continue; 524 } 525 } 526 snprintf(line, LINSIZ, "%s %s", group, result); 527 free(result); 528 } 529#else 530 while (fgets(line, LINSIZ, netf) != NULL) { 531#endif 532 pos = (char *)&line; 533#ifdef YP 534 if (*pos == '+') { 535 _netgr_yp_enabled = 1; 536 continue; 537 } 538#endif 539 if (*pos == '#') 540 continue; 541 while (*pos == ' ' || *pos == '\t') 542 pos++; 543 spos = pos; 544 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 545 *pos != '\0') 546 pos++; 547 len = pos - spos; 548 while (*pos == ' ' || *pos == '\t') 549 pos++; 550 if (*pos != '\n' && *pos != '\0') { 551 lp = (struct linelist *)malloc(sizeof (*lp)); 552 lp->l_parsed = 0; 553 lp->l_groupname = (char *)malloc(len + 1); 554 bcopy(spos, lp->l_groupname, len); 555 *(lp->l_groupname + len) = '\0'; 556 len = strlen(pos); 557 olen = 0; 558 559 /* 560 * Loop around handling line continuations. 561 */ 562 do { 563 if (*(pos + len - 1) == '\n') 564 len--; 565 if (*(pos + len - 1) == '\\') { 566 len--; 567 cont = 1; 568 } else 569 cont = 0; 570 if (len > 0) { 571 linep = (char *)malloc(olen + len + 1); 572 if (olen > 0) { 573 bcopy(olinep, linep, olen); 574 free(olinep); 575 } 576 bcopy(pos, linep + olen, len); 577 olen += len; 578 *(linep + olen) = '\0'; 579 olinep = linep; 580 } 581 if (cont) { 582 if (fgets(line, LINSIZ, netf)) { 583 pos = line; 584 len = strlen(pos); 585 } else 586 cont = 0; 587 } 588 } while (cont); 589 lp->l_line = linep; 590 lp->l_next = linehead; 591 linehead = lp; 592 593 /* 594 * If this is the one we wanted, we are done. 595 */ 596 if (!strcmp(lp->l_groupname, group)) 597 return (lp); 598 } 599 } 600#ifdef YP 601 /* 602 * Yucky. The recursive nature of this whole mess might require 603 * us to make more than one pass through the netgroup file. 604 * This might be best left outside the #ifdef YP, but YP is 605 * defined by default anyway, so I'll leave it like this 606 * until I know better. 607 */ 608 rewind(netf); 609#endif 610 return ((struct linelist *)0); 611}
|