1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #if defined(LIBC_SCCS) && !defined(lint) 35 static char sccsid[] = "@(#)getgrent.c 8.2 (Berkeley) 3/21/94"; 36 #endif /* LIBC_SCCS and not lint */ 37 38 #include <sys/types.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <grp.h> 43 44 static FILE *_gr_fp; 45 static struct group _gr_group; 46 static int _gr_stayopen; 47 static int grscan(), start_gr(); 48 #ifdef YP 49 #include <rpc/rpc.h> 50 #include <rpcsvc/yp_prot.h> 51 #include <rpcsvc/ypclnt.h> 52 static int _gr_stepping_yp; 53 static int _gr_yp_enabled; 54 static int _getypgroup(struct group *, const char *, char *); 55 static int _nextypgroup(struct group *); 56 #endif 57 58 #define MAXGRP 200 59 static char *members[MAXGRP]; 60 #define MAXLINELENGTH 1024 61 static char line[MAXLINELENGTH]; 62 63 struct group * 64 getgrent() 65 { 66 if (!_gr_fp && !start_gr()) { 67 return NULL; 68 } 69 70 #ifdef YP 71 if (_gr_stepping_yp) { 72 if (_nextypgroup(&_gr_group)) 73 return(&_gr_group); 74 } 75 tryagain: 76 #endif 77 78 if (!grscan(0, 0, NULL)) 79 return(NULL); 80 #ifdef YP 81 if(_gr_group.gr_name[0] == '+' && _gr_group.gr_name[1]) { 82 _getypgroup(&_gr_group, &_gr_group.gr_name[1], 83 "group.byname"); 84 } else if(_gr_group.gr_name[0] == '+') { 85 if (!_nextypgroup(&_gr_group)) 86 goto tryagain; 87 else 88 return(&_gr_group); 89 } 90 #endif 91 return(&_gr_group); 92 } 93 94 struct group * 95 getgrnam(name) 96 const char *name; 97 { 98 int rval; 99 100 if (!start_gr()) 101 return(NULL); 102 #ifdef YP 103 tryagain: 104 #endif 105 rval = grscan(1, 0, name); 106 #ifdef YP 107 if(rval == -1 && (_gr_yp_enabled < 0 || (_gr_yp_enabled && 108 _gr_group.gr_name[0] == '+'))) { 109 if (!(rval = _getypgroup(&_gr_group, name, "group.byname"))) 110 goto tryagain; 111 } 112 #endif 113 if (!_gr_stayopen) 114 endgrent(); 115 return(rval ? &_gr_group : NULL); 116 } 117 118 struct group * 119 #ifdef __STDC__ 120 getgrgid(gid_t gid) 121 #else 122 getgrgid(gid) 123 gid_t gid; 124 #endif 125 { 126 int rval; 127 128 if (!start_gr()) 129 return(NULL); 130 #ifdef YP 131 tryagain: 132 #endif 133 rval = grscan(1, gid, NULL); 134 #ifdef YP 135 if(rval == -1 && _gr_yp_enabled) { 136 char buf[16]; 137 snprintf(buf, sizeof buf, "%d", (unsigned)gid); 138 if (!(rval = _getypgroup(&_gr_group, buf, "group.bygid"))) 139 goto tryagain; 140 } 141 #endif 142 if (!_gr_stayopen) 143 endgrent(); 144 return(rval ? &_gr_group : NULL); 145 } 146 147 static int 148 start_gr() 149 { 150 if (_gr_fp) { 151 rewind(_gr_fp); 152 return(1); 153 } 154 _gr_fp = fopen(_PATH_GROUP, "r"); 155 if(!_gr_fp) return 0; 156 #ifdef YP 157 /* 158 * This is a disgusting hack, used to determine when YP is enabled. 159 * This would be easier if we had a group database to go along with 160 * the password database. 161 */ 162 { 163 char *line; 164 size_t linelen; 165 _gr_yp_enabled = 0; 166 while((line = fgetln(_gr_fp, &linelen)) != NULL) { 167 if(line[0] == '+') { 168 if(line[1] && !_gr_yp_enabled) { 169 _gr_yp_enabled = 1; 170 } else { 171 _gr_yp_enabled = -1; 172 break; 173 } 174 } 175 } 176 rewind(_gr_fp); 177 } 178 #endif 179 return 1; 180 } 181 182 int 183 setgrent() 184 { 185 return(setgroupent(0)); 186 } 187 188 int 189 setgroupent(stayopen) 190 int stayopen; 191 { 192 if (!start_gr()) 193 return(0); 194 _gr_stayopen = stayopen; 195 #ifdef YP 196 _gr_stepping_yp = 0; 197 #endif 198 return(1); 199 } 200 201 void 202 endgrent() 203 { 204 #ifdef YP 205 _gr_stepping_yp = 0; 206 #endif 207 if (_gr_fp) { 208 (void)fclose(_gr_fp); 209 _gr_fp = NULL; 210 } 211 } 212 213 static int 214 grscan(search, gid, name) 215 register int search, gid; 216 register char *name; 217 { 218 register char *cp, **m; 219 char *bp; 220 #ifdef YP 221 int _ypfound = 0; 222 #endif; 223 for (;;) { 224 if (!fgets(line, sizeof(line), _gr_fp)) 225 return(0); 226 bp = line; 227 /* skip lines that are too big */ 228 if (!index(line, '\n')) { 229 int ch; 230 231 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 232 ; 233 continue; 234 } 235 if ((_gr_group.gr_name = strsep(&bp, ":\n")) == NULL) 236 break; 237 #ifdef YP 238 /* 239 * XXX We need to be careful to avoid proceeding 240 * past this point under certain circumstances or 241 * we risk dereferencing null pointers down below. 242 */ 243 if (_gr_group.gr_name[0] == '+') { 244 if (strlen(_gr_group.gr_name) == 1) { 245 switch(search) { 246 case 0: 247 return(1); 248 case 1: 249 return(-1); 250 default: 251 return(0); 252 } 253 } else { 254 if (!_getypgroup(&_gr_group, &_gr_group.gr_name[1], 255 "group.byname")) 256 continue; 257 /* We're going to override -- tell the world. */ 258 members[0] = NULL; 259 _ypfound++; 260 } 261 } 262 #else 263 if (_gr_group.gr_name[0] == '+') 264 continue; 265 #endif /* YP */ 266 if (search && name) { 267 if(strcmp(_gr_group.gr_name, name)) { 268 continue; 269 } 270 } 271 if ((_gr_group.gr_passwd = strsep(&bp, ":\n")) == NULL) 272 break;; 273 if (!(cp = strsep(&bp, ":\n"))) 274 continue; 275 #ifdef YP 276 if (!_ypfound) 277 #endif 278 _gr_group.gr_gid = atoi(cp); 279 if (search && name == NULL && _gr_group.gr_gid != gid) 280 continue; 281 cp = NULL; 282 for (m = _gr_group.gr_mem = members;; bp++) { 283 if (m == &members[MAXGRP - 1]) 284 break; 285 if (*bp == ',') { 286 if (cp) { 287 *bp = '\0'; 288 *m++ = cp; 289 cp = NULL; 290 } 291 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 292 if (cp) { 293 *bp = '\0'; 294 *m++ = cp; 295 } 296 break; 297 } else if (cp == NULL) 298 cp = bp; 299 } 300 *m = NULL; 301 return(1); 302 } 303 /* NOTREACHED */ 304 return (0); 305 } 306 307 #ifdef YP 308 309 static int 310 _gr_breakout_yp(struct group *gr, char *result) 311 { 312 char *s, *cp; 313 char **m; 314 315 /* 316 * XXX If 's' ends up being a NULL pointer, punt on this group. 317 * It means the NIS group entry is badly formatted and should 318 * be skipped. 319 */ 320 if ((s = strsep(&result, ":")) == NULL) return 0; /* name */ 321 gr->gr_name = s; 322 323 if ((s = strsep(&result, ":")) == NULL) return 0; /* password */ 324 gr->gr_passwd = s; 325 326 if ((s = strsep(&result, ":")) == NULL) return 0; /* gid */ 327 gr->gr_gid = atoi(s); 328 329 if ((s = result) == NULL) return 0; 330 cp = 0; 331 332 for (m = _gr_group.gr_mem = members; /**/; s++) { 333 if (m == &members[MAXGRP - 1]) { 334 break; 335 } 336 if (*s == ',') { 337 if (cp) { 338 *s = '\0'; 339 *m++ = cp; 340 cp = NULL; 341 } 342 } else if (*s == '\0' || *s == '\n' || *s == ' ') { 343 if (cp) { 344 *s = '\0'; 345 *m++ = cp; 346 } 347 break; 348 } else if (cp == NULL) { 349 cp = s; 350 } 351 } 352 *m = NULL; 353 354 return 1; 355 } 356 357 static char *_gr_yp_domain; 358 359 static int 360 _getypgroup(struct group *gr, const char *name, char *map) 361 { 362 char *result, *s; 363 static char resultbuf[1024]; 364 int resultlen; 365 366 if(!_gr_yp_domain) { 367 if(yp_get_default_domain(&_gr_yp_domain)) 368 return 0; 369 } 370 371 if(yp_match(_gr_yp_domain, map, name, strlen(name), 372 &result, &resultlen)) 373 return 0; 374 375 s = strchr(result, '\n'); 376 if(s) *s = '\0'; 377 378 if(resultlen >= sizeof resultbuf) return 0; 379 strcpy(resultbuf, result); 380 result = resultbuf; 381 return(_gr_breakout_yp(gr, resultbuf)); 382 383 } 384 385 386 static int 387 _nextypgroup(struct group *gr) 388 { 389 static char *key; 390 static int keylen; 391 char *lastkey, *result; 392 static char resultbuf[1024]; 393 int resultlen; 394 int rv; 395 396 if(!_gr_yp_domain) { 397 if(yp_get_default_domain(&_gr_yp_domain)) 398 return 0; 399 } 400 401 if(!_gr_stepping_yp) { 402 if(key) free(key); 403 rv = yp_first(_gr_yp_domain, "group.byname", 404 &key, &keylen, &result, &resultlen); 405 if(rv) { 406 return 0; 407 } 408 _gr_stepping_yp = 1; 409 goto unpack; 410 } else { 411 tryagain: 412 lastkey = key; 413 rv = yp_next(_gr_yp_domain, "group.byname", key, keylen, 414 &key, &keylen, &result, &resultlen); 415 free(lastkey); 416 unpack: 417 if(rv) { 418 _gr_stepping_yp = 0; 419 return 0; 420 } 421 422 if(resultlen > sizeof(resultbuf)) { 423 free(result); 424 goto tryagain; 425 } 426 427 strcpy(resultbuf, result); 428 free(result); 429 if((result = strchr(resultbuf, '\n')) != NULL) 430 *result = '\0'; 431 if (_gr_breakout_yp(gr, resultbuf)) 432 return(1); 433 else 434 goto tryagain; 435 } 436 } 437 438 #endif /* YP */ 439