parse_netgroup.c revision 20387
164562Sgshapiro/* 290792Sgshapiro * Copyright (c) 1992, 1993 364562Sgshapiro * The Regents of the University of California. All rights reserved. 464562Sgshapiro * 564562Sgshapiro * This code is derived from software contributed to Berkeley by 664562Sgshapiro * Rick Macklem at The University of Guelph. 764562Sgshapiro * 864562Sgshapiro * Redistribution and use in source and binary forms, with or without 990792Sgshapiro * modification, are permitted provided that the following conditions 1064562Sgshapiro * are met: 1164562Sgshapiro * 1. Redistributions of source code must retain the above copyright 1264562Sgshapiro * notice, this list of conditions and the following disclaimer. 1364562Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright 1464562Sgshapiro * notice, this list of conditions and the following disclaimer in the 1564562Sgshapiro * documentation and/or other materials provided with the distribution. 1690792Sgshapiro * 3. All advertising materials mentioning features or use of this software 1764562Sgshapiro * must display the following acknowledgement: 1890792Sgshapiro * This product includes software developed by the University of 1990792Sgshapiro * California, Berkeley and its contributors. 2064562Sgshapiro * 4. Neither the name of the University nor the names of its contributors 2164562Sgshapiro * may be used to endorse or promote products derived from this software 2264562Sgshapiro * without specific prior written permission. 2364562Sgshapiro * 2464562Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2564562Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2664562Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2790792Sgshapiro * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2890792Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2964562Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3064562Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3164562Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3264562Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3364562Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3464562Sgshapiro * SUCH DAMAGE. 3564562Sgshapiro */ 3664562Sgshapiro 3764562Sgshapiro#if defined(LIBC_SCCS) && !defined(lint) 3864562Sgshapirostatic char sccsid[] = "$Id: parse_netgroup.c,v 1.2 1996/05/12 17:17:44 wpaul Exp $"; 3964562Sgshapiro#endif /* LIBC_SCCS and not lint */ 4064562Sgshapiro 4164562Sgshapiro/* 4264562Sgshapiro * This is a specially hacked-up version of getnetgrent.c used to parse 4364562Sgshapiro * data from the stored hash table of netgroup info rather than from a 4464562Sgshapiro * 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 55static const char rcsid[] = "$Id: parse_netgroup.c,v 1.2 1996/05/12 17:17:44 wpaul Exp $"; 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 */ 66struct 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 73struct 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 81static struct linelist *linehead = (struct linelist *)0; 82static struct netgrp *nextgrp = (struct netgrp *)0; 83static struct { 84 struct netgrp *gr; 85 char *grname; 86} grouphead = { 87 (struct netgrp *)0, 88 (char *)0, 89}; 90static int parse_netgrp(); 91static struct linelist *read_for_group(); 92void __setnetgrent(), __endnetgrent(); 93int __getnetgrent(); 94extern struct group_entry *gtable[]; 95 96/* 97 * setnetgrent() 98 * Parse the netgroup file looking for the netgroup and build the list 99 * of netgrp structures. Let parse_netgrp() and read_for_group() do 100 * most of the work. 101 */ 102void 103__setnetgrent(group) 104 char *group; 105{ 106 /* Sanity check */ 107 108 if (group == NULL || !strlen(group)) 109 return; 110 111 if (grouphead.gr == (struct netgrp *)0 || 112 strcmp(group, grouphead.grname)) { 113 __endnetgrent(); 114 if (parse_netgrp(group)) 115 __endnetgrent(); 116 else { 117 grouphead.grname = (char *) 118 malloc(strlen(group) + 1); 119 strcpy(grouphead.grname, group); 120 } 121 } 122 nextgrp = grouphead.gr; 123} 124 125/* 126 * Get the next netgroup off the list. 127 */ 128int 129__getnetgrent(hostp, userp, domp) 130 char **hostp, **userp, **domp; 131{ 132 if (nextgrp) { 133 *hostp = nextgrp->ng_str[NG_HOST]; 134 *userp = nextgrp->ng_str[NG_USER]; 135 *domp = nextgrp->ng_str[NG_DOM]; 136 nextgrp = nextgrp->ng_next; 137 return (1); 138 } 139 return (0); 140} 141 142/* 143 * __endnetgrent() - cleanup 144 */ 145void 146__endnetgrent() 147{ 148 register struct linelist *lp, *olp; 149 register struct netgrp *gp, *ogp; 150 151 lp = linehead; 152 while (lp) { 153 olp = lp; 154 lp = lp->l_next; 155 free(olp->l_groupname); 156 free(olp->l_line); 157 free((char *)olp); 158 } 159 linehead = (struct linelist *)0; 160 if (grouphead.grname) { 161 free(grouphead.grname); 162 grouphead.grname = (char *)0; 163 } 164 gp = grouphead.gr; 165 while (gp) { 166 ogp = gp; 167 gp = gp->ng_next; 168 if (ogp->ng_str[NG_HOST]) 169 free(ogp->ng_str[NG_HOST]); 170 if (ogp->ng_str[NG_USER]) 171 free(ogp->ng_str[NG_USER]); 172 if (ogp->ng_str[NG_DOM]) 173 free(ogp->ng_str[NG_DOM]); 174 free((char *)ogp); 175 } 176 grouphead.gr = (struct netgrp *)0; 177} 178 179/* 180 * Parse the netgroup file setting up the linked lists. 181 */ 182static int 183parse_netgrp(group) 184 char *group; 185{ 186 register char *spos, *epos; 187 register int len, strpos; 188#ifdef DEBUG 189 register int fields; 190#endif 191 char *pos, *gpos; 192 struct netgrp *grp; 193 struct linelist *lp = linehead; 194 195 /* 196 * First, see if the line has already been read in. 197 */ 198 while (lp) { 199 if (!strcmp(group, lp->l_groupname)) 200 break; 201 lp = lp->l_next; 202 } 203 if (lp == (struct linelist *)0 && 204 (lp = read_for_group(group)) == (struct linelist *)0) 205 return (1); 206 if (lp->l_parsed) { 207#ifdef DEBUG 208 /* 209 * This error message is largely superflous since the 210 * code handles the error condition sucessfully, and 211 * spewing it out from inside libc can actually hose 212 * certain programs. 213 */ 214 fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); 215#endif 216 return (1); 217 } else 218 lp->l_parsed = 1; 219 pos = lp->l_line; 220 /* Watch for null pointer dereferences, dammit! */ 221 while (pos != NULL && *pos != '\0') { 222 if (*pos == '(') { 223 grp = (struct netgrp *)malloc(sizeof (struct netgrp)); 224 bzero((char *)grp, sizeof (struct netgrp)); 225 grp->ng_next = grouphead.gr; 226 grouphead.gr = grp; 227 pos++; 228 gpos = strsep(&pos, ")"); 229#ifdef DEBUG 230 fields = 0; 231#endif 232 for (strpos = 0; strpos < 3; strpos++) { 233 if ((spos = strsep(&gpos, ","))) { 234#ifdef DEBUG 235 fields++; 236#endif 237 while (*spos == ' ' || *spos == '\t') 238 spos++; 239 if ((epos = strpbrk(spos, " \t"))) { 240 *epos = '\0'; 241 len = epos - spos; 242 } else 243 len = strlen(spos); 244 if (len > 0) { 245 grp->ng_str[strpos] = (char *) 246 malloc(len + 1); 247 bcopy(spos, grp->ng_str[strpos], 248 len + 1); 249 } 250 } else { 251 /* 252 * All other systems I've tested 253 * return NULL for empty netgroup 254 * fields. It's up to user programs 255 * to handle the NULLs appropriately. 256 */ 257 grp->ng_str[strpos] = NULL; 258 } 259 } 260#ifdef DEBUG 261 /* 262 * Note: on other platforms, malformed netgroup 263 * entries are not normally flagged. While we 264 * can catch bad entries and report them, we should 265 * stay silent by default for compatibility's sake. 266 */ 267 if (fields < 3) 268 fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", 269 grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], 270 grp->ng_str[NG_USER] == NULL ? "" : ",", 271 grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], 272 grp->ng_str[NG_DOM] == NULL ? "" : ",", 273 grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], 274 lp->l_groupname); 275#endif 276 } else { 277 spos = strsep(&pos, ", \t"); 278 if (parse_netgrp(spos)) 279 continue; 280 } 281 /* Watch for null pointer dereferences, dammit! */ 282 if (pos != NULL) 283 while (*pos == ' ' || *pos == ',' || *pos == '\t') 284 pos++; 285 } 286 return (0); 287} 288 289/* 290 * Read the netgroup file and save lines until the line for the netgroup 291 * is found. Return 1 if eof is encountered. 292 */ 293static struct linelist * 294read_for_group(group) 295 char *group; 296{ 297 register char *pos, *spos, *linep = NULL, *olinep = NULL; 298 register int len, olen; 299 int cont; 300 struct linelist *lp; 301 char line[LINSIZ + 1]; 302 char *data = NULL; 303 304 data = lookup (gtable, group); 305 sprintf(line, "%s %s", group, data); 306 pos = (char *)&line; 307#ifdef CANT_HAPPEN 308 if (*pos == '#') 309 continue; 310#endif 311 while (*pos == ' ' || *pos == '\t') 312 pos++; 313 spos = pos; 314 while (*pos != ' ' && *pos != '\t' && *pos != '\n' && 315 *pos != '\0') 316 pos++; 317 len = pos - spos; 318 while (*pos == ' ' || *pos == '\t') 319 pos++; 320 if (*pos != '\n' && *pos != '\0') { 321 lp = (struct linelist *)malloc(sizeof (*lp)); 322 lp->l_parsed = 0; 323 lp->l_groupname = (char *)malloc(len + 1); 324 bcopy(spos, lp->l_groupname, len); 325 *(lp->l_groupname + len) = '\0'; 326 len = strlen(pos); 327 olen = 0; 328 /* 329 * Loop around handling line continuations. 330 */ 331 do { 332 if (*(pos + len - 1) == '\n') 333 len--; 334 if (*(pos + len - 1) == '\\') { 335 len--; 336 cont = 1; 337 } else 338 cont = 0; 339 if (len > 0) { 340 linep = (char *)malloc(olen + len + 1); 341 if (olen > 0) { 342 bcopy(olinep, linep, olen); 343 free(olinep); 344 } 345 bcopy(pos, linep + olen, len); 346 olen += len; 347 *(linep + olen) = '\0'; 348 olinep = linep; 349 } 350#ifdef CANT_HAPPEN 351 if (cont) { 352 if (fgets(line, LINSIZ, netf)) { 353 pos = line; 354 len = strlen(pos); 355 } else 356 cont = 0; 357 } 358#endif 359 } while (cont); 360 lp->l_line = linep; 361 lp->l_next = linehead; 362 linehead = lp; 363#ifdef CANT_HAPPEN 364 /* 365 * If this is the one we wanted, we are done. 366 */ 367 if (!strcmp(lp->l_groupname, group)) 368#endif 369 return (lp); 370 } 371 return ((struct linelist *)0); 372} 373