getnetgrent.c revision 7336
10SN/A/* 217237Sserb * Copyright (c) 1992, 1993 30SN/A * The Regents of the University of California. All rights reserved. 40SN/A * 50SN/A * This code is derived from software contributed to Berkeley by 60SN/A * Rick Macklem at The University of Guelph. 72362SN/A * 80SN/A * Redistribution and use in source and binary forms, with or without 92362SN/A * modification, are permitted provided that the following conditions 100SN/A * are met: 110SN/A * 1. Redistributions of source code must retain the above copyright 120SN/A * notice, this list of conditions and the following disclaimer. 130SN/A * 2. Redistributions in binary form must reproduce the above copyright 140SN/A * notice, this list of conditions and the following disclaimer in the 150SN/A * documentation and/or other materials provided with the distribution. 160SN/A * 3. All advertising materials mentioning features or use of this software 170SN/A * must display the following acknowledgement: 180SN/A * This product includes software developed by the University of 190SN/A * California, Berkeley and its contributors. 200SN/A * 4. Neither the name of the University nor the names of its contributors 212362SN/A * may be used to endorse or promote products derived from this software 222362SN/A * without specific prior written permission. 232362SN/A * 240SN/A * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 250SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 260SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 270SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 280SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 290SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3017237Sserb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3117237Sserb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 320SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3317189Smli * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 340SN/A * SUCH DAMAGE. 350SN/A */ 360SN/A 370SN/A#if defined(LIBC_SCCS) && !defined(lint) 380SN/Astatic char sccsid[] = "@(#)getnetgrent.c 8.1 (Berkeley) 6/4/93"; 390SN/A#endif /* LIBC_SCCS and not lint */ 400SN/A 410SN/A#include <stdio.h> 420SN/A#include <strings.h> 430SN/A 440SN/A#define _PATH_NETGROUP "/etc/netgroup" 4517237Sserb 4617237Sserb/* 470SN/A * Static Variables and functions used by setnetgrent(), getnetgrent() and 480SN/A * endnetgrent(). 490SN/A * There are two linked lists: 500SN/A * - linelist is just used by setnetgrent() to parse the net group file via. 510SN/A * parse_netgrp() 52 * - netgrp is the list of entries for the current netgroup 53 */ 54struct linelist { 55 struct linelist *l_next; /* Chain ptr. */ 56 int l_parsed; /* Flag for cycles */ 57 char *l_groupname; /* Name of netgroup */ 58 char *l_line; /* Netgroup entrie(s) to be parsed */ 59}; 60 61struct netgrp { 62 struct netgrp *ng_next; /* Chain ptr */ 63 char *ng_str[3]; /* Field pointers, see below */ 64}; 65#define NG_HOST 0 /* Host name */ 66#define NG_USER 1 /* User name */ 67#define NG_DOM 2 /* and Domain name */ 68 69static struct linelist *linehead = (struct linelist *)0; 70static struct netgrp *nextgrp = (struct netgrp *)0; 71static struct { 72 struct netgrp *gr; 73 char *grname; 74} grouphead = { 75 (struct netgrp *)0, 76 (char *)0, 77}; 78static FILE *netf = (FILE *)0; 79static int parse_netgrp(); 80#ifdef YP 81static int _netgr_yp_enabled; 82#endif 83static struct linelist *read_for_group(); 84void setnetgrent(), endnetgrent(); 85int getnetgrent(), innetgr(); 86 87#define LINSIZ 1024 /* Length of netgroup file line */ 88 89/* 90 * setnetgrent() 91 * Parse the netgroup file looking for the netgroup and build the list 92 * of netgrp structures. Let parse_netgrp() and read_for_group() do 93 * most of the work. 94 */ 95void 96setnetgrent(group) 97 char *group; 98{ 99 /* Sanity check */ 100 101 if (group == NULL || !strlen(group)) 102 return; 103 104 if (grouphead.gr == (struct netgrp *)0 || 105 strcmp(group, grouphead.grname)) { 106 endnetgrent(); 107 if (netf = fopen(_PATH_NETGROUP, "r")) { 108 if (parse_netgrp(group)) 109 endnetgrent(); 110 else { 111 grouphead.grname = (char *) 112 malloc(strlen(group) + 1); 113 strcpy(grouphead.grname, group); 114 } 115 fclose(netf); 116 } 117 } 118 nextgrp = grouphead.gr; 119} 120 121/* 122 * Get the next netgroup off the list. 123 */ 124int 125getnetgrent(hostp, userp, domp) 126 char **hostp, **userp, **domp; 127{ 128 129 if (nextgrp) { 130 *hostp = nextgrp->ng_str[NG_HOST]; 131 *userp = nextgrp->ng_str[NG_USER]; 132 *domp = nextgrp->ng_str[NG_DOM]; 133 nextgrp = nextgrp->ng_next; 134 return (1); 135 } 136 return (0); 137} 138 139/* 140 * endnetgrent() - cleanup 141 */ 142void 143endnetgrent() 144{ 145 register struct linelist *lp, *olp; 146 register struct netgrp *gp, *ogp; 147 148 lp = linehead; 149 while (lp) { 150 olp = lp; 151 lp = lp->l_next; 152 free(olp->l_groupname); 153 free(olp->l_line); 154 free((char *)olp); 155 } 156 linehead = (struct linelist *)0; 157 if (grouphead.grname) { 158 free(grouphead.grname); 159 grouphead.grname = (char *)0; 160 } 161 gp = grouphead.gr; 162 while (gp) { 163 ogp = gp; 164 gp = gp->ng_next; 165 if (ogp->ng_str[NG_HOST]) 166 free(ogp->ng_str[NG_HOST]); 167 if (ogp->ng_str[NG_USER]) 168 free(ogp->ng_str[NG_USER]); 169 if (ogp->ng_str[NG_DOM]) 170 free(ogp->ng_str[NG_DOM]); 171 free((char *)ogp); 172 } 173 grouphead.gr = (struct netgrp *)0; 174#ifdef YP 175 _netgr_yp_enabled = 0; 176#endif 177} 178 179/* 180 * Search for a match in a netgroup. 181 */ 182int 183innetgr(group, host, user, dom) 184 char *group, *host, *user, *dom; 185{ 186 char *hst, *usr, *dm; 187 188 /* Sanity check */ 189 190 if (group == NULL || !strlen(group)) 191 return (0); 192 193 setnetgrent(group); 194 while (getnetgrent(&hst, &usr, &dm)) 195 if ((host == (char *)0 || !strcmp(host, hst)) && 196 (user == (char *)0 || !strcmp(user, usr)) && 197 (dom == (char *)0 || !strcmp(dom, dm))) { 198 endnetgrent(); 199 return (1); 200 } 201 endnetgrent(); 202 return (0); 203} 204 205/* 206 * Parse the netgroup file setting up the linked lists. 207 */ 208static int 209parse_netgrp(group) 210 char *group; 211{ 212 register char *spos, *epos; 213 register int len, strpos; 214 char *pos, *gpos; 215 struct netgrp *grp; 216 struct linelist *lp = linehead; 217 218 /* 219 * First, see if the line has already been read in. 220 */ 221 while (lp) { 222 if (!strcmp(group, lp->l_groupname)) 223 break; 224 lp = lp->l_next; 225 } 226 if (lp == (struct linelist *)0 && 227 (lp = read_for_group(group)) == (struct linelist *)0) 228 return (1); 229 if (lp->l_parsed) { 230 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 231 return (1); 232 } else 233 lp->l_parsed = 1; 234 pos = lp->l_line; 235 /* Watch for null pointer dereferences, dammit! */ 236 while (pos != NULL && *pos != '\0') { 237 if (*pos == '(') { 238 grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 239 bzero((char *)grp, sizeof (struct netgrp)); 240 grp->ng_next = grouphead.gr; 241 grouphead.gr = grp; 242 pos++; 243 gpos = strsep(&pos, ")"); 244 for (strpos = 0; strpos < 3; strpos++) { 245 if (spos = strsep(&gpos, ",")) { 246 while (*spos == ' ' || *spos == '\t') 247 spos++; 248 if (epos = strpbrk(spos, " \t")) { 249 *epos = '\0'; 250 len = epos - spos; 251 } else 252 len = strlen(spos); 253 if (len > 0) { 254 grp->ng_str[strpos] = (char *) 255 malloc(len + 1); 256 bcopy(spos, grp->ng_str[strpos], 257 len + 1); 258 } 259 } else 260 goto errout; 261 } 262 } else { 263 spos = strsep(&pos, ", \t"); 264 if (parse_netgrp(spos)) 265 continue; 266 } 267 /* Watch for null pointer dereferences, dammit! */ 268 if (pos != NULL) 269 while (*pos == ' ' || *pos == ',' || *pos == '\t') 270 pos++; 271 } 272 return (0); 273errout: 274 fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, 275 spos); 276 return (1); 277} 278 279/* 280 * Read the netgroup file and save lines until the line for the netgroup 281 * is found. Return 1 if eof is encountered. 282 */ 283static struct linelist * 284read_for_group(group) 285 char *group; 286{ 287 register char *pos, *spos, *linep, *olinep; 288 register int len, olen; 289 int cont; 290 struct linelist *lp; 291 char line[LINSIZ + 1]; 292#ifdef YP 293 static char *_netgr_yp_domain; 294 char *result; 295 int resultlen; 296 297 while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) { 298 if (_netgr_yp_enabled) { 299 if(!_netgr_yp_domain) 300 if(yp_get_default_domain(&_netgr_yp_domain)) 301 continue; 302 if (yp_match(_netgr_yp_domain, "netgroup", group, 303 strlen(group), &result, &resultlen)) { 304 free(result); 305 return ((struct linelist *)0); 306 } 307 sprintf(line, "%s %s", group, result); 308 free(result); 309 } 310#else 311 while (fgets(line, LINSIZ, netf) != NULL) { 312#endif 313 pos = (char *)&line; 314#ifdef YP 315 /* 316 * Once we default over to NIS, only 317 * endnetgrent() can get us out again. 318 */ 319 if (*pos == '+') { 320 _netgr_yp_enabled = 1; 321 continue; 322 } 323#endif 324 if (*pos == '#') 325 continue; 326 while (*pos == ' ' || *pos == '\t') 327 pos++; 328 spos = pos; 329 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 330 *pos != '\0') 331 pos++; 332 len = pos - spos; 333 while (*pos == ' ' || *pos == '\t') 334 pos++; 335 if (*pos != '\n' && *pos != '\0') { 336 lp = (struct linelist *)malloc(sizeof (*lp)); 337 lp->l_parsed = 0; 338 lp->l_groupname = (char *)malloc(len + 1); 339 bcopy(spos, lp->l_groupname, len); 340 *(lp->l_groupname + len) = '\0'; 341 len = strlen(pos); 342 olen = 0; 343 344 /* 345 * Loop around handling line continuations. 346 */ 347 do { 348 if (*(pos + len - 1) == '\n') 349 len--; 350 if (*(pos + len - 1) == '\\') { 351 len--; 352 cont = 1; 353 } else 354 cont = 0; 355 if (len > 0) { 356 linep = (char *)malloc(olen + len + 1); 357 if (olen > 0) { 358 bcopy(olinep, linep, olen); 359 free(olinep); 360 } 361 bcopy(pos, linep + olen, len); 362 olen += len; 363 *(linep + olen) = '\0'; 364 olinep = linep; 365 } 366 if (cont) { 367 if (fgets(line, LINSIZ, netf)) { 368 pos = line; 369 len = strlen(pos); 370 } else 371 cont = 0; 372 } 373 } while (cont); 374 lp->l_line = linep; 375 lp->l_next = linehead; 376 linehead = lp; 377 378 /* 379 * If this is the one we wanted, we are done. 380 */ 381 if (!strcmp(lp->l_groupname, group)) 382 return (lp); 383 } 384 } 385 return ((struct linelist *)0); 386} 387