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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * For SUNWnskit - version 1.1 28 */ 29 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <string.h> 33 #include <stdio.h> 34 #include <ctype.h> 35 #include <pwd.h> 36 #include <rpcsvc/ypclnt.h> 37 #include "util.h" 38 #include "table.h" 39 #include "getgroup.h" 40 41 #define MAXDOMAINLEN 256 42 #define MAXGROUPLEN 1024 43 44 /* 45 * Reverse the netgroup file. A flag of "-u" means reverse by username, 46 * one of "-h" means reverse by hostname. Each line in the output file 47 * will begin with a key formed by concatenating the host or user name 48 * with the domain name. The key will be followed by a tab, then the 49 * comma-separated, newline-terminated list of groups to which the 50 * user or host belongs. 51 * 52 * Exception: Groups to which everyone belongs (universal groups) will 53 * not be included in the list. The universal groups will be listed under 54 * the special name "*". 55 * 56 * Thus to find out all the groups that user "foo" of domain "bar" is in, 57 * lookup the groups under foo.bar, foo.*, *.bar and *.*. 58 * 59 */ 60 61 62 63 /* Stores a list of strings */ 64 typedef struct stringnode *stringlist; 65 struct stringnode { 66 char *str; 67 stringlist next; 68 }; 69 typedef struct stringnode stringnode; 70 71 72 73 /* Stores a list of (name,list-of-groups) */ 74 typedef struct groupentrynode *groupentrylist; 75 struct groupentrynode { 76 char *name; 77 stringlist groups; 78 groupentrylist next; 79 }; 80 typedef struct groupentrynode groupentrynode; 81 82 stringtable ngtable; 83 84 static groupentrylist grouptable[TABLESIZE]; 85 86 static char *nextgroup(void); 87 static void storegroup(char *group, struct grouplist *glist, int byuser); 88 static void enter(char *name, char *group); 89 static void appendgroup(groupentrylist grlist, char *group); 90 static groupentrylist newentry(char *name, char *group); 91 static void loadtable(FILE *nf); 92 static void dumptable(void); 93 94 int 95 main(argc, argv) 96 int argc; 97 char *argv[]; 98 { 99 char *group; 100 struct grouplist *glist; 101 int byuser; 102 103 loadtable(stdin); 104 if (argc == 2 && argv[1][0] == '-' && 105 (argv[1][1] == 'u' || argv[1][1] == 'h')) { 106 byuser = (argv[1][1] == 'u'); 107 } else { 108 (void) fprintf(stderr, 109 "usage: %s -h (by host), %s -u (by user)\n", 110 argv[0], argv[0]); 111 exit(1); 112 } 113 114 while (group = nextgroup()) { 115 glist = my_getgroup(group); 116 storegroup(group, glist, byuser); 117 } 118 dumptable(); 119 120 return (0); 121 } 122 123 /* 124 * Get the next netgroup from /etc/netgroup 125 */ 126 static char * 127 nextgroup(void) 128 { 129 static int index = -1; 130 static tablelist cur = NULL; 131 char *group; 132 133 while (cur == NULL) { 134 if (++index == TABLESIZE) { 135 return (NULL); 136 } 137 cur = ngtable[index]; 138 } 139 group = cur->key; 140 cur = cur->next; 141 return (group); 142 } 143 144 145 146 /* 147 * Dump out all of the stored info into a file 148 */ 149 static void 150 dumptable(void) 151 { 152 int i; 153 groupentrylist entry; 154 stringlist groups; 155 156 for (i = 0; i < TABLESIZE; i++) { 157 if (entry = grouptable[i]) { 158 while (entry) { 159 fputs(entry->name, stdout); 160 putc('\t', stdout); 161 for (groups = entry->groups; groups; 162 groups = groups->next) { 163 fputs(groups->str, stdout); 164 if (groups->next) { 165 putc(',', stdout); 166 } 167 } 168 putc('\n', stdout); 169 entry = entry->next; 170 } 171 } 172 } 173 } 174 175 176 177 178 /* 179 * Add a netgroup to a user's list of netgroups 180 */ 181 static void 182 storegroup(char *group, struct grouplist *glist, int byuser) 183 { 184 char *name; /* username or hostname */ 185 char *domain; 186 char *key; 187 static char *universal = "*"; 188 189 for (; glist; glist = glist->gl_nxt) { 190 name = byuser ? glist->gl_name : glist->gl_machine; 191 if (!name) { 192 name = universal; 193 } else if (!isalnum(*name) && *name != '_') { 194 continue; 195 } 196 domain = glist->gl_domain; 197 if (!domain) { 198 domain = universal; 199 } 200 key = malloc((unsigned) (strlen(name)+strlen(domain)+2)); 201 (void) sprintf(key, "%s.%s", name, domain); 202 enter(key, group); 203 } 204 } 205 206 207 208 static groupentrylist 209 newentry(char *name, char *group) 210 { 211 groupentrylist new; 212 213 new = MALLOC(groupentrynode); 214 215 STRCPY(new->name, name); 216 217 new->groups = MALLOC(stringnode); 218 new->groups->str = group; 219 new->groups->next = NULL; 220 221 new->next = NULL; 222 return (new); 223 } 224 225 static void 226 appendgroup(groupentrylist grlist, char *group) 227 { 228 stringlist cur, prev; 229 230 for (cur = grlist->groups; cur; prev = cur, cur = cur->next) { 231 if (strcmp(group, cur->str) == 0) { 232 return; 233 } 234 } 235 prev->next = MALLOC(stringnode); 236 cur = prev->next; 237 cur->str = group; 238 cur->next = NULL; 239 } 240 241 static void 242 enter(char *name, char *group) 243 { 244 int key; 245 groupentrylist gel; 246 groupentrylist gelprev; 247 248 key = tablekey(name); 249 if (grouptable[key] == NULL) { 250 grouptable[key] = newentry(name, group); 251 } else { 252 gel = grouptable[key]; 253 while (gel && strcmp(gel->name, name)) { 254 gelprev = gel; 255 gel = gel->next; 256 } 257 if (gel) { 258 appendgroup(gel, group); 259 } else { 260 gelprev->next = newentry(name, group); 261 } 262 } 263 } 264 265 /* 266 * Load up a hash table with the info in /etc/netgroup 267 */ 268 static void 269 loadtable(FILE *nf) 270 { 271 char buf[MAXGROUPLEN]; 272 char *p; 273 char *group; 274 char *line; 275 276 while (getaline(buf, MAXGROUPLEN, nf)) { 277 for (p = buf; *p && isspace((int)*p); p++) 278 ; /* skip leading blanks */ 279 for (; *p && *p != '#' && *p != ' ' && *p != '\t'; p++) 280 ; 281 if (*p == EOS || *p == '#') 282 continue; 283 *p++ = EOS; 284 285 while (*p == ' ' || *p == '\t') { 286 p++; 287 } 288 if (*p == EOS || *p == '#') 289 continue; 290 291 STRCPY(group, buf); 292 STRCPY(line, p); 293 store(ngtable, group, line); 294 } 295 } 296