1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright (c) 1996, by Sun Microsystems, Inc.
  25  * All rights reserved.
  26  */
  27                                                             
  28 #ident  "%Z%%M% %I%     %E% SMI"        /* SMI4.1 1.5 */
  29 
  30 #include <stdio.h>
  31 #include <ctype.h>
  32 #include <string.h>
  33 #include "table.h"
  34 #include "util.h"
  35 #include "getgroup.h"
  36 
  37 #define MAXGROUPLEN 1024
  38 
  39 /*
  40  * Stolen mostly, from getnetgrent.c
  41  *
  42  * my_getgroup() performs the same function as _getgroup(), but operates
  43  * on /etc/netgroup directly, rather than doing yp lookups.
  44  *
  45  * /etc/netgroup must first loaded into a hash table so the matching
  46  * function can look up lines quickly.
  47  */
  48 
  49 
  50 /* To check for cycles in netgroups */
  51 struct list {
  52         char *name;
  53         struct list *nxt;
  54 };
  55 
  56 
  57 extern stringtable ngtable; /* stored info from /etc/netgroup */
  58 
  59 static struct grouplist *grouplist; /* stores a list of users in a group */
  60 
  61 static char *any();
  62 static char *match();
  63 static char *fill();
  64 static void freegrouplist();
  65 static void doit();
  66 
  67 
  68 
  69 static void
  70 freegrouplist()
  71 {
  72         struct grouplist *gl;
  73 
  74         for (gl = grouplist; gl != NULL; gl = gl->gl_nxt) {
  75                 FREE(gl->gl_name);
  76                 FREE(gl->gl_domain);
  77                 FREE(gl->gl_machine);
  78                 FREE(gl);
  79         }
  80         grouplist = NULL;
  81 }
  82 
  83 
  84 
  85 
  86 struct grouplist *
  87 my_getgroup(group)
  88         char *group;
  89 {
  90         freegrouplist();
  91         doit(group, (struct list *) NULL);
  92         return (grouplist);
  93 }
  94 
  95 
  96 
  97 
  98 
  99 /*
 100  * recursive function to find the members of netgroup "group". "list" is
 101  * the path followed through the netgroups so far, to check for cycles.
 102  */
 103 static void
 104 doit(group, list)
 105         char *group;
 106         struct list *list;
 107 {
 108         register char *p, *q;
 109         register struct list *ls;
 110         struct list tmplist;
 111         char *val;
 112         struct grouplist *gpls;
 113 
 114 
 115         /*
 116          * check for non-existing groups
 117          */
 118         if ((val = match(group)) == NULL) {
 119                 return;
 120         }
 121 
 122 
 123         /*
 124          * check for cycles
 125          */
 126         for (ls = list; ls != NULL; ls = ls->nxt) {
 127                 if (strcmp(ls->name, group) == 0) {
 128                         (void) fprintf(stderr,
 129                                 "Cycle detected in /etc/netgroup: %s.\n",
 130                                 group);
 131                         return;
 132                 }
 133         }
 134 
 135 
 136         ls = &tmplist;
 137         ls->name = group;
 138         ls->nxt = list;
 139         list = ls;
 140 
 141         p = val;
 142         while (p != NULL) {
 143                 while (*p == ' ' || *p == '\t')
 144                         p++;
 145                 if (*p == EOS || *p == '#')
 146                         break;
 147                 if (*p == '(') {
 148                         gpls = MALLOC(struct grouplist);
 149                         p++;
 150 
 151                         if (!(p = fill(p, &gpls->gl_machine, ',')))  {
 152                                 goto syntax_error;
 153                         }
 154                         if (!(p = fill(p, &gpls->gl_name, ','))) {
 155                                 goto syntax_error;
 156                         }
 157                         if (!(p = fill(p, &gpls->gl_domain, ')'))) {
 158                                 goto syntax_error;
 159                         }
 160                         gpls->gl_nxt = grouplist;
 161                         grouplist = gpls;
 162                 } else {
 163                         q = any(p, " \t\n#");
 164                         if (q && *q == '#')
 165                                 break;
 166                         *q = EOS;
 167                         doit(p, list);
 168                         *q = ' ';
 169                 }
 170                 p = any(p, " \t");
 171         }
 172         return;
 173 
 174 syntax_error:
 175         (void) fprintf(stderr, "syntax error in /etc/netgroup\n");
 176         (void) fprintf(stderr, "--- %s %s\n", group, val);
 177 }
 178 
 179 
 180 
 181 
 182 /*
 183  * Fill a buffer "target" selectively from buffer "start".
 184  * "termchar" terminates the information in start, and preceding
 185  * or trailing white space is ignored.  If the buffer "start" is
 186  * empty, "target" is filled with "*". The location just after the
 187  * terminating character is returned.
 188  */
 189 static char *
 190 fill(start, target, termchar)
 191         char *start;
 192         char **target;
 193         char termchar;
 194 {
 195         register char *p;
 196         register char *q;
 197         register char *r;
 198         int size;
 199 
 200         for (p = start; *p == ' ' || *p == '\t'; p++)
 201                 ;
 202         r = strchr(p, termchar);
 203         if (r == (char *)NULL) {
 204                 return ((char *)NULL);
 205         }
 206         if (p == r) {
 207                 *target = NULL;
 208         } else {
 209                 for (q = r-1; *q == ' ' || *q == '\t'; q--)
 210                         ;
 211                 size = q-p+1;
 212                 STRNCPY(*target, p, size);
 213         }
 214         return (r+1);
 215 }
 216 
 217 
 218 /*
 219  * scans cp, looking for a match with any character
 220  * in match.  Returns pointer to place in cp that matched
 221  * (or NULL if no match)
 222  */
 223 static char *
 224 any(cp, match)
 225         register char *cp;
 226         char *match;
 227 {
 228         register char *mp, c;
 229 
 230         while (c = *cp) {
 231                 for (mp = match; *mp; mp++)
 232                         if (*mp == c)
 233                                 return (cp);
 234                 cp++;
 235         }
 236         return (NULL);
 237 }
 238 
 239 
 240 
 241 /*
 242  * The equivalent of yp_match. Returns the match, or NULL if there is none.
 243  */
 244 static char *
 245 match(group)
 246         char *group;
 247 {
 248         return (lookup(ngtable, group));
 249 }