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) 38 static char sccsid[] = "$Id: parse_netgroup.c,v 1.1.1.1 1995/10/26 16:25:29 wpaul Exp $"; 39 #endif /* LIBC_SCCS and not lint */ 40 41 /* 42 * This is a specially hacked-up version of getnetgrent.c used to parse 43 * data from the stored hash table of netgroup info rather than from a 44 * file. It's used mainly for the parse_netgroup() function. All the YP 45 * stuff and file support has been stripped out since it isn't needed. 46 */ 47 48 #include <stdio.h> 49 #include <strings.h> 50 #include <stdlib.h> 51 #include <unistd.h> 52 #include "hash.h" 53 54 #ifndef lint 55 static const char rcsid[] = "$Id$"; 56 #endif 57 58 /* 59 * Static Variables and functions used by setnetgrent(), getnetgrent() and 60 * __endnetgrent(). 61 * There are two linked lists: 62 * - linelist is just used by setnetgrent() to parse the net group file via. 63 * parse_netgrp() 64 * - netgrp is the list of entries for the current netgroup 65 */ 66 struct linelist { 67 struct linelist *l_next; /* Chain ptr. */ 68 int l_parsed; /* Flag for cycles */ 69 char *l_groupname; /* Name of netgroup */ 70 char *l_line; /* Netgroup entrie(s) to be parsed */ 71 }; 72 73 struct netgrp { 74 struct netgrp *ng_next; /* Chain ptr */ 75 char *ng_str[3]; /* Field pointers, see below */ 76 }; 77 #define NG_HOST 0 /* Host name */ 78 #define NG_USER 1 /* User name */ 79 #define NG_DOM 2 /* and Domain name */ 80 81 static struct linelist *linehead = (struct linelist *)0; 82 static struct netgrp *nextgrp = (struct netgrp *)0; 83 static struct { 84 struct netgrp *gr; 85 char *grname; 86 } grouphead = { 87 (struct netgrp *)0, 88 (char *)0, 89 }; 90 static int parse_netgrp(); 91 static struct linelist *read_for_group(); 92 void __setnetgrent(), __endnetgrent(); 93 int __getnetgrent(); 94 extern struct group_entry *gtable[]; 95 extern char *lookup __P(( struct group_entry *[], char * )); 96 #define LINSIZ 1024 /* Length of netgroup file line */ 97 98 /* 99 * setnetgrent() 100 * Parse the netgroup file looking for the netgroup and build the list 101 * of netgrp structures. Let parse_netgrp() and read_for_group() do 102 * most of the work. 103 */ 104 void 105 __setnetgrent(group) 106 char *group; 107 { 108 /* Sanity check */ 109 110 if (group == NULL || !strlen(group)) 111 return; 112 113 if (grouphead.gr == (struct netgrp *)0 || 114 strcmp(group, grouphead.grname)) { 115 __endnetgrent(); 116 if (parse_netgrp(group)) 117 __endnetgrent(); 118 else { 119 grouphead.grname = (char *) 120 malloc(strlen(group) + 1); 121 strcpy(grouphead.grname, group); 122 } 123 } 124 nextgrp = grouphead.gr; 125 } 126 127 /* 128 * Get the next netgroup off the list. 129 */ 130 int 131 __getnetgrent(hostp, userp, domp) 132 char **hostp, **userp, **domp; 133 { 134 if (nextgrp) { 135 *hostp = nextgrp->ng_str[NG_HOST]; 136 *userp = nextgrp->ng_str[NG_USER]; 137 *domp = nextgrp->ng_str[NG_DOM]; 138 nextgrp = nextgrp->ng_next; 139 return (1); 140 } 141 return (0); 142 } 143 144 /* 145 * __endnetgrent() - cleanup 146 */ 147 void 148 __endnetgrent() 149 { 150 register struct linelist *lp, *olp; 151 register struct netgrp *gp, *ogp; 152 153 lp = linehead; 154 while (lp) { 155 olp = lp; 156 lp = lp->l_next; 157 free(olp->l_groupname); 158 free(olp->l_line); 159 free((char *)olp); 160 } 161 linehead = (struct linelist *)0; 162 if (grouphead.grname) { 163 free(grouphead.grname); 164 grouphead.grname = (char *)0; 165 } 166 gp = grouphead.gr; 167 while (gp) { 168 ogp = gp; 169 gp = gp->ng_next; 170 if (ogp->ng_str[NG_HOST]) 171 free(ogp->ng_str[NG_HOST]); 172 if (ogp->ng_str[NG_USER]) 173 free(ogp->ng_str[NG_USER]); 174 if (ogp->ng_str[NG_DOM]) 175 free(ogp->ng_str[NG_DOM]); 176 free((char *)ogp); 177 } 178 grouphead.gr = (struct netgrp *)0; 179 } 180 181 /* 182 * Parse the netgroup file setting up the linked lists. 183 */ 184 static int 185 parse_netgrp(group) 186 char *group; 187 { 188 register char *spos, *epos; 189 register int len, strpos; 190 #ifdef DEBUG 191 register int fields; 192 #endif 193 char *pos, *gpos; 194 struct netgrp *grp; 195 struct linelist *lp = linehead; 196 197 /* 198 * First, see if the line has already been read in. 199 */ 200 while (lp) { 201 if (!strcmp(group, lp->l_groupname)) 202 break; 203 lp = lp->l_next; 204 } 205 if (lp == (struct linelist *)0 && 206 (lp = read_for_group(group)) == (struct linelist *)0) 207 return (1); 208 if (lp->l_parsed) { 209 #ifdef DEBUG 210 /* 211 * This error message is largely superflous since the 212 * code handles the error condition sucessfully, and 213 * spewing it out from inside libc can actually hose 214 * certain programs. 215 */ 216 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 217 #endif 218 return (1); 219 } else 220 lp->l_parsed = 1; 221 pos = lp->l_line; 222 /* Watch for null pointer dereferences, dammit! */ 223 while (pos != NULL && *pos != '\0') { 224 if (*pos == '(') { 225 grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 226 bzero((char *)grp, sizeof (struct netgrp)); 227 grp->ng_next = grouphead.gr; 228 grouphead.gr = grp; 229 pos++; 230 gpos = strsep(&pos, ")"); 231 #ifdef DEBUG 232 fields = 0; 233 #endif 234 for (strpos = 0; strpos < 3; strpos++) { 235 if ((spos = strsep(&gpos, ","))) { 236 #ifdef DEBUG 237 fields++; 238 #endif 239 while (*spos == ' ' || *spos == '\t') 240 spos++; 241 if ((epos = strpbrk(spos, " \t"))) { 242 *epos = '\0'; 243 len = epos - spos; 244 } else 245 len = strlen(spos); 246 if (len > 0) { 247 grp->ng_str[strpos] = (char *) 248 malloc(len + 1); 249 bcopy(spos, grp->ng_str[strpos], 250 len + 1); 251 } 252 } else { 253 /* 254 * All other systems I've tested 255 * return NULL for empty netgroup 256 * fields. It's up to user programs 257 * to handle the NULLs appropriately. 258 */ 259 grp->ng_str[strpos] = NULL; 260 } 261 } 262 #ifdef DEBUG 263 /* 264 * Note: on other platforms, malformed netgroup 265 * entries are not normally flagged. While we 266 * can catch bad entries and report them, we should 267 * stay silent by default for compatibility's sake. 268 */ 269 if (fields < 3) 270 fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 271 grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 272 grp->ng_str[NG_USER] == NULL ? "" : ",", 273 grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 274 grp->ng_str[NG_DOM] == NULL ? "" : ",", 275 grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 276 lp->l_groupname); 277 #endif 278 } else { 279 spos = strsep(&pos, ", \t"); 280 if (parse_netgrp(spos)) 281 continue; 282 } 283 /* Watch for null pointer dereferences, dammit! */ 284 if (pos != NULL) 285 while (*pos == ' ' || *pos == ',' || *pos == '\t') 286 pos++; 287 } 288 return (0); 289 } 290 291 /* 292 * Read the netgroup file and save lines until the line for the netgroup 293 * is found. Return 1 if eof is encountered. 294 */ 295 static struct linelist * 296 read_for_group(group) 297 char *group; 298 { 299 register char *pos, *spos, *linep, *olinep; 300 register int len, olen; 301 int cont; 302 struct linelist *lp; 303 char line[LINSIZ + 1]; 304 char *key = NULL, *data = NULL; 305 306 data = lookup (gtable, group); 307 sprintf(line, "%s %s", group, data); 308 pos = (char *)&line; 309 #ifdef CANT_HAPPEN 310 if (*pos == '#') 311 continue; 312 #endif 313 while (*pos == ' ' || *pos == '\t') 314 pos++; 315 spos = pos; 316 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 317 *pos != '\0') 318 pos++; 319 len = pos - spos; 320 while (*pos == ' ' || *pos == '\t') 321 pos++; 322 if (*pos != '\n' && *pos != '\0') { 323 lp = (struct linelist *)malloc(sizeof (*lp)); 324 lp->l_parsed = 0; 325 lp->l_groupname = (char *)malloc(len + 1); 326 bcopy(spos, lp->l_groupname, len); 327 *(lp->l_groupname + len) = '\0'; 328 len = strlen(pos); 329 olen = 0; 330 /* 331 * Loop around handling line continuations. 332 */ 333 do { 334 if (*(pos + len - 1) == '\n') 335 len--; 336 if (*(pos + len - 1) == '\\') { 337 len--; 338 cont = 1; 339 } else 340 cont = 0; 341 if (len > 0) { 342 linep = (char *)malloc(olen + len + 1); 343 if (olen > 0) { 344 bcopy(olinep, linep, olen); 345 free(olinep); 346 } 347 bcopy(pos, linep + olen, len); 348 olen += len; 349 *(linep + olen) = '\0'; 350 olinep = linep; 351 } 352 #ifdef CANT_HAPPEN 353 if (cont) { 354 if (fgets(line, LINSIZ, netf)) { 355 pos = line; 356 len = strlen(pos); 357 } else 358 cont = 0; 359 } 360 #endif 361 } while (cont); 362 lp->l_line = linep; 363 lp->l_next = linehead; 364 linehead = lp; 365 #ifdef CANT_HAPPEN 366 /* 367 * If this is the one we wanted, we are done. 368 */ 369 if (!strcmp(lp->l_groupname, group)) 370 #endif 371 return (lp); 372 } 373 return ((struct linelist *)0); 374 } 375