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 * Copyright 2012 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 /* 28 * For SUNWnskit - version 1.1 29 */ 30 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <string.h> 34 #include <stdio.h> 35 #include <ctype.h> 36 #include <pwd.h> 37 #include <rpcsvc/ypclnt.h> 38 #include "util.h" 39 #include "table.h" 40 #include "getgroup.h" 41 #include "revnetgroup.h" 42 43 #define MAXDOMAINLEN 256 44 #define MAXGROUPLEN 131072 45 #define MAXKEYLEN 512 46 47 /* 48 * Reverse the netgroup file. A flag of "-u" means reverse by username, 49 * one of "-h" means reverse by hostname. Each line in the output file 50 * will begin with a key formed by concatenating the host or user name 51 * with the domain name. The key will be followed by a tab, then the 52 * comma-separated, newline-terminated list of groups to which the 53 * user or host belongs. 54 * 55 * Exception: Groups to which everyone belongs (universal groups) will 56 * not be included in the list. The universal groups will be listed under 57 * the special name "*". 58 * 59 * Thus to find out all the groups that user "foo" of domain "bar" is in, 60 * lookup the groups under foo.bar, foo.*, *.bar and *.*. 61 * 62 */ 63 64 static char *nextgroup(revhandle_t *, tablelist *); 65 static void storegroup(char *group, revhandle_t *hdl); 66 static void enter(char *name, char *group, revhandle_t *hdl); 67 static void appendgroup(groupentrylist grlist, char *group); 68 static groupentrylist newentry(char *name, char *group); 69 static void loadtable(FILE *nf, revhandle_t *hdl); 70 static void dumptable(FILE *out, revhandle_t *hdl); 71 static void free_table(revhandle_t *hdl); 72 73 int 74 revnetgroup_handle(FILE *fin, FILE *fout, boolean_t byuser) 75 { 76 char *group; 77 revhandle_t hdl = {0}; 78 tablelist walker = NULL; 79 80 hdl.rh_byuser = byuser; 81 loadtable(fin, &hdl); 82 83 while (group = nextgroup(&hdl, &walker)) 84 storegroup(group, &hdl); 85 86 dumptable(fout, &hdl); 87 free_table(&hdl); 88 return (0); 89 } 90 91 /* 92 * Get the next netgroup from /etc/netgroup 93 */ 94 static char * 95 nextgroup(revhandle_t *hdl, tablelist *next) 96 { 97 tablelist entry = *next; 98 uint_t i; 99 100 if (entry == NULL) { 101 for (i = hdl->rh_index; i < TABLESIZE; i++) { 102 entry = hdl->ngtable[i]; 103 if (entry != NULL) { 104 hdl->rh_index = i + 1; 105 break; 106 } 107 } 108 } 109 110 if (entry == NULL) { 111 /* out of table */ 112 hdl->rh_index = 0; 113 return (NULL); 114 } 115 116 *next = entry->next; 117 return (entry->key); 118 } 119 120 121 static void 122 free_tablelist(tablelist e) 123 { 124 tablelist next; 125 126 do { 127 next = e->next; 128 129 free(e->key); 130 free(e->datum); 131 free(e); 132 } while ((e = next) != NULL); 133 } 134 135 static void 136 free_stringnode(stringnode *s) 137 { 138 stringnode *next; 139 140 do { 141 next = s->s_next; 142 143 free(s); 144 } while ((s = next) != NULL); 145 } 146 147 static void 148 free_groupentrylist(groupentrylist e) 149 { 150 groupentrylist next; 151 152 do { 153 next = e->next; 154 155 free_stringnode(e->groups); 156 free(e->name); 157 free(e); 158 } while ((e = next) != NULL); 159 } 160 161 static void 162 free_table(revhandle_t *hdl) 163 { 164 int i; 165 166 /* ngtable */ 167 for (i = 0; i < TABLESIZE; i++) { 168 tablelist e; 169 170 if ((e = hdl->ngtable[i]) == NULL) 171 continue; 172 173 free_tablelist(e); 174 hdl->ngtable[i] = NULL; 175 } 176 177 /* grouptable */ 178 for (i = 0; i < TABLESIZE; i++) { 179 groupentrylist e; 180 181 if ((e = hdl->grouptable[i]) == NULL) 182 continue; 183 184 free_groupentrylist(e); 185 hdl->grouptable[i] = NULL; 186 } 187 } 188 189 /* 190 * Dump out all of the stored info into a file 191 */ 192 static void 193 dumptable(FILE *out, revhandle_t *hdl) 194 { 195 int i; 196 groupentrylist entry; 197 stringnode *groups; 198 199 for (i = 0; i < TABLESIZE; i++) { 200 if (entry = hdl->grouptable[i]) { 201 while (entry) { 202 fputs(entry->name, out); 203 putc('\t', out); 204 for (groups = entry->groups; groups; 205 groups = groups->s_next) { 206 fputs(groups->str, out); 207 if (groups->s_next) { 208 putc(',', out); 209 } 210 } 211 putc('\n', out); 212 entry = entry->next; 213 } 214 } 215 } 216 } 217 218 219 220 /* 221 * Add a netgroup to a user's list of netgroups 222 */ 223 static void 224 storegroup(char *group, revhandle_t *hdl) 225 { 226 char key[MAXKEYLEN]; 227 struct grouplist *glist; 228 229 doit(group, (struct list *)NULL, hdl); 230 231 for (glist = hdl->grouplist; glist; glist = glist->gl_nxt) { 232 const char *name; /* username or hostname */ 233 const char *domain; 234 235 name = hdl->rh_byuser ? glist->gl_name : glist->gl_machine; 236 if (!name) { 237 name = "*"; 238 } else if (!isalnum(*name) && *name != '_') { 239 continue; 240 } 241 domain = glist->gl_domain; 242 if (!domain) { 243 domain = "*"; 244 } 245 (void) snprintf(key, sizeof (key), "%s.%s", name, domain); 246 enter(key, group, hdl); 247 } 248 freegrouplist(hdl); 249 } 250 251 252 253 static groupentrylist 254 newentry(char *name, char *group) 255 { 256 groupentrylist new; 257 258 new = MALLOC(groupentrynode); 259 260 STRCPY(new->name, name); 261 262 new->groups = MALLOC(stringnode); 263 new->groups->str = group; 264 new->groups->s_next = NULL; 265 266 new->next = NULL; 267 return (new); 268 } 269 270 static void 271 appendgroup(groupentrylist grlist, char *group) 272 { 273 stringnode *cur, *prev; 274 275 for (cur = grlist->groups; cur; prev = cur, cur = cur->s_next) { 276 if (strcmp(group, cur->str) == 0) { 277 return; 278 } 279 } 280 prev->s_next = MALLOC(stringnode); 281 cur = prev->s_next; 282 cur->str = group; 283 cur->s_next = NULL; 284 } 285 286 static void 287 enter(char *name, char *group, revhandle_t *hdl) 288 { 289 int key; 290 groupentrylist gel; 291 groupentrylist gelprev; 292 293 key = tablekey(name); 294 if (hdl->grouptable[key] == NULL) { 295 hdl->grouptable[key] = newentry(name, group); 296 } else { 297 gel = hdl->grouptable[key]; 298 while (gel && strcmp(gel->name, name)) { 299 gelprev = gel; 300 gel = gel->next; 301 } 302 if (gel) { 303 appendgroup(gel, group); 304 } else { 305 gelprev->next = newentry(name, group); 306 } 307 } 308 } 309 310 /* 311 * Load up a hash table with the info in /etc/netgroup 312 */ 313 static void 314 loadtable(FILE *nf, revhandle_t *hdl) 315 { 316 char *buf; 317 char *p; 318 char *group; 319 char *line; 320 321 buf = malloc(MAXGROUPLEN); 322 if (buf == NULL) 323 return; 324 325 while (getaline(buf, MAXGROUPLEN, nf)) { 326 /* skip leading blanks */ 327 for (p = buf; *p && isspace((int)*p); p++) 328 ; 329 for (; *p && *p != '#' && *p != ' ' && *p != '\t'; p++) 330 ; 331 if (*p == EOS || *p == '#') 332 continue; 333 *p++ = EOS; 334 335 while (*p == ' ' || *p == '\t') { 336 p++; 337 } 338 if (*p == EOS || *p == '#') 339 continue; 340 341 STRCPY(group, buf); 342 STRCPY(line, p); 343 store(hdl->ngtable, group, line); 344 } 345 346 free(buf); 347 }