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(int argc, char *argv[]) 96 { 97 char *group; 98 struct grouplist *glist; 99 int byuser; 100 101 loadtable(stdin); 102 if (argc == 2 && argv[1][0] == '-' && 103 (argv[1][1] == 'u' || argv[1][1] == 'h')) { 104 byuser = (argv[1][1] == 'u'); 105 } else { 106 (void) fprintf(stderr, 107 "usage: %s -h (by host), %s -u (by user)\n", 108 argv[0], argv[0]); 109 exit(1); 110 } 111 112 while (group = nextgroup()) { 113 glist = my_getgroup(group); 114 storegroup(group, glist, byuser); 115 } 116 dumptable(); 117 118 return (0); 119 } 120 121 /* 122 * Get the next netgroup from /etc/netgroup 123 */ 124 static char * 125 nextgroup(void) 126 { 127 static int index = -1; 128 static tablelist cur = NULL; 129 char *group; 130 131 while (cur == NULL) { 132 if (++index == TABLESIZE) { 133 return (NULL); 134 } 135 cur = ngtable[index]; 136 } 137 group = cur->key; 138 cur = cur->next; 139 return (group); 140 } 141 142 143 144 /* 145 * Dump out all of the stored info into a file 146 */ 147 static void 148 dumptable(void) 149 { 150 int i; 151 groupentrylist entry; 152 stringlist groups; 153 154 for (i = 0; i < TABLESIZE; i++) { 155 if (entry = grouptable[i]) { 156 while (entry) { 157 fputs(entry->name, stdout); 158 putc('\t', stdout); 159 for (groups = entry->groups; groups; 160 groups = groups->next) { 161 fputs(groups->str, stdout); 162 if (groups->next) { 163 putc(',', stdout); 164 } 165 } 166 putc('\n', stdout); 167 entry = entry->next; 168 } 169 } 170 } 171 } 172 173 174 175 176 /* 177 * Add a netgroup to a user's list of netgroups 178 */ 179 static void 180 storegroup(char *group, struct grouplist *glist, int byuser) 181 { 182 char *name; /* username or hostname */ 183 char *domain; 184 char *key; 185 static char *universal = "*"; 186 187 for (; glist; glist = glist->gl_nxt) { 188 name = byuser ? glist->gl_name : glist->gl_machine; 189 if (!name) { 190 name = universal; 191 } else if (!isalnum(*name) && *name != '_') { 192 continue; 193 } 194 domain = glist->gl_domain; 195 if (!domain) { 196 domain = universal; 197 } 198 key = malloc((strlen(name) + strlen(domain) + 2)); 199 (void) sprintf(key, "%s.%s", name, domain); 200 enter(key, group); 201 } 202 } 203 204 205 206 static groupentrylist 207 newentry(char *name, char *group) 208 { 209 groupentrylist new; 210 211 new = MALLOC(groupentrynode); 212 213 STRCPY(new->name, name); 214 215 new->groups = MALLOC(stringnode); 216 new->groups->str = group; 217 new->groups->next = NULL; 218 219 new->next = NULL; 220 return (new); 221 } 222 223 static void 224 appendgroup(groupentrylist grlist, char *group) 225 { 226 stringlist cur, prev; 227 228 prev = NULL; 229 for (cur = grlist->groups; cur; prev = cur, cur = cur->next) { 230 if (strcmp(group, cur->str) == 0) { 231 return; 232 } 233 } 234 235 /* prev is NULL only when grlist->groups is NULL. */ 236 if (prev == NULL) 237 return; 238 239 prev->next = MALLOC(stringnode); 240 cur = prev->next; 241 cur->str = group; 242 cur->next = NULL; 243 } 244 245 static void 246 enter(char *name, char *group) 247 { 248 int key; 249 groupentrylist gel; 250 groupentrylist gelprev = NULL; 251 252 key = tablekey(name); 253 if (grouptable[key] == NULL) { 254 grouptable[key] = newentry(name, group); 255 } else { 256 gel = grouptable[key]; 257 while (gel && strcmp(gel->name, name)) { 258 gelprev = gel; 259 gel = gel->next; 260 } 261 if (gel) { 262 appendgroup(gel, group); 263 } else { 264 gelprev->next = newentry(name, group); 265 } 266 } 267 } 268 269 /* 270 * Load up a hash table with the info in /etc/netgroup 271 */ 272 static void 273 loadtable(FILE *nf) 274 { 275 char buf[MAXGROUPLEN]; 276 char *p; 277 char *group; 278 char *line; 279 280 while (getaline(buf, MAXGROUPLEN, nf)) { 281 /* skip leading blanks */ 282 for (p = buf; *p && isspace((int)*p); p++) 283 ; 284 for (; *p && *p != '#' && *p != ' ' && *p != '\t'; p++) 285 ; 286 if (*p == EOS || *p == '#') 287 continue; 288 *p++ = EOS; 289 290 while (*p == ' ' || *p == '\t') { 291 p++; 292 } 293 if (*p == EOS || *p == '#') 294 continue; 295 296 STRCPY(group, buf); 297 STRCPY(line, p); 298 store(ngtable, group, line); 299 } 300 } 301