1 /* $NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 christos Exp $ */ 2 /* from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */ 3 /* from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */ 4 5 /* 6 * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995 7 * The Regents of the University of California. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. 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 /*- 35 * Copyright (c) 2002 The NetBSD Foundation, Inc. 36 * All rights reserved. 37 * 38 * This code is derived from software contributed to The NetBSD Foundation 39 * by Luke Mewburn of Wasabi Systems. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60 * POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63 #include <sys/param.h> 64 65 #include <grp.h> 66 #include <limits.h> 67 #include <pwd.h> 68 #include <stdlib.h> 69 #include <stdio.h> 70 #include <string.h> 71 #include <time.h> 72 #include <unistd.h> 73 74 #include "extern.h" 75 76 static struct group * gi_getgrnam(const char *); 77 static struct group * gi_getgrgid(gid_t); 78 static int gi_setgroupent(int); 79 static void gi_endgrent(void); 80 static int grstart(void); 81 static int grscan(int, gid_t, const char *); 82 static int grmatchline(int, gid_t, const char *); 83 84 static struct passwd * gi_getpwnam(const char *); 85 static struct passwd * gi_getpwuid(uid_t); 86 static int gi_setpassent(int); 87 static void gi_endpwent(void); 88 static int pwstart(void); 89 static int pwscan(int, uid_t, const char *); 90 static int pwmatchline(int, uid_t, const char *); 91 92 #define MAXGRP 200 93 #define MAXLINELENGTH 1024 94 95 static FILE *_gr_fp; 96 static struct group _gr_group; 97 static int _gr_stayopen; 98 static int _gr_filesdone; 99 static FILE *_pw_fp; 100 static struct passwd _pw_passwd; /* password structure */ 101 static int _pw_stayopen; /* keep fd's open */ 102 static int _pw_filesdone; 103 104 static char grfile[MAXPATHLEN]; 105 static char pwfile[MAXPATHLEN]; 106 107 static char *members[MAXGRP]; 108 static char grline[MAXLINELENGTH]; 109 static char pwline[MAXLINELENGTH]; 110 111 int 112 setup_getid(const char *dir) 113 { 114 if (dir == NULL) 115 return (0); 116 117 /* close existing databases */ 118 gi_endgrent(); 119 gi_endpwent(); 120 121 /* build paths to new databases */ 122 snprintf(grfile, sizeof(grfile), "%s/group", dir); 123 snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir); 124 125 /* try to open new databases */ 126 if (!grstart() || !pwstart()) 127 return (0); 128 129 /* switch pwcache(3) lookup functions */ 130 if (pwcache_groupdb(gi_setgroupent, gi_endgrent, 131 gi_getgrnam, gi_getgrgid) == -1 132 || pwcache_userdb(gi_setpassent, gi_endpwent, 133 gi_getpwnam, gi_getpwuid) == -1) 134 return (0); 135 136 return (1); 137 } 138 139 140 /* 141 * group lookup functions 142 */ 143 144 static struct group * 145 gi_getgrnam(const char *name) 146 { 147 int rval; 148 149 if (!grstart()) 150 return NULL; 151 rval = grscan(1, 0, name); 152 if (!_gr_stayopen) 153 endgrent(); 154 return (rval) ? &_gr_group : NULL; 155 } 156 157 static struct group * 158 gi_getgrgid(gid_t gid) 159 { 160 int rval; 161 162 if (!grstart()) 163 return NULL; 164 rval = grscan(1, gid, NULL); 165 if (!_gr_stayopen) 166 endgrent(); 167 return (rval) ? &_gr_group : NULL; 168 } 169 170 static int 171 gi_setgroupent(int stayopen) 172 { 173 174 if (!grstart()) 175 return 0; 176 _gr_stayopen = stayopen; 177 return 1; 178 } 179 180 static void 181 gi_endgrent(void) 182 { 183 184 _gr_filesdone = 0; 185 if (_gr_fp) { 186 (void)fclose(_gr_fp); 187 _gr_fp = NULL; 188 } 189 } 190 191 static int 192 grstart(void) 193 { 194 195 _gr_filesdone = 0; 196 if (_gr_fp) { 197 rewind(_gr_fp); 198 return 1; 199 } 200 if (grfile[0] == '\0') /* sanity check */ 201 return 0; 202 203 _gr_fp = fopen(grfile, "r"); 204 if (_gr_fp != NULL) 205 return 1; 206 warn("Can't open `%s'", grfile); 207 return 0; 208 } 209 210 211 static int 212 grscan(int search, gid_t gid, const char *name) 213 { 214 215 if (_gr_filesdone) 216 return 0; 217 for (;;) { 218 if (!fgets(grline, sizeof(grline), _gr_fp)) { 219 if (!search) 220 _gr_filesdone = 1; 221 return 0; 222 } 223 /* skip lines that are too big */ 224 if (!strchr(grline, '\n')) { 225 int ch; 226 227 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 228 ; 229 continue; 230 } 231 /* skip comments */ 232 if (grline[0] == '#') 233 continue; 234 if (grmatchline(search, gid, name)) 235 return 1; 236 } 237 /* NOTREACHED */ 238 } 239 240 static int 241 grmatchline(int search, gid_t gid, const char *name) 242 { 243 unsigned long id; 244 char **m; 245 char *cp, *bp, *ep; 246 247 /* name may be NULL if search is nonzero */ 248 249 bp = grline; 250 memset(&_gr_group, 0, sizeof(_gr_group)); 251 _gr_group.gr_name = strsep(&bp, ":\n"); 252 if (search && name && strcmp(_gr_group.gr_name, name)) 253 return 0; 254 _gr_group.gr_passwd = strsep(&bp, ":\n"); 255 if (!(cp = strsep(&bp, ":\n"))) 256 return 0; 257 id = strtoul(cp, &ep, 10); 258 if (id > GID_MAX || *ep != '\0') 259 return 0; 260 _gr_group.gr_gid = (gid_t)id; 261 if (search && name == NULL && _gr_group.gr_gid != gid) 262 return 0; 263 cp = NULL; 264 if (bp == NULL) 265 return 0; 266 for (_gr_group.gr_mem = m = members;; bp++) { 267 if (m == &members[MAXGRP - 1]) 268 break; 269 if (*bp == ',') { 270 if (cp) { 271 *bp = '\0'; 272 *m++ = cp; 273 cp = NULL; 274 } 275 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 276 if (cp) { 277 *bp = '\0'; 278 *m++ = cp; 279 } 280 break; 281 } else if (cp == NULL) 282 cp = bp; 283 } 284 *m = NULL; 285 return 1; 286 } 287 288 289 /* 290 * user lookup functions 291 */ 292 293 static struct passwd * 294 gi_getpwnam(const char *name) 295 { 296 int rval; 297 298 if (!pwstart()) 299 return NULL; 300 rval = pwscan(1, 0, name); 301 if (!_pw_stayopen) 302 endpwent(); 303 return (rval) ? &_pw_passwd : NULL; 304 } 305 306 static struct passwd * 307 gi_getpwuid(uid_t uid) 308 { 309 int rval; 310 311 if (!pwstart()) 312 return NULL; 313 rval = pwscan(1, uid, NULL); 314 if (!_pw_stayopen) 315 endpwent(); 316 return (rval) ? &_pw_passwd : NULL; 317 } 318 319 static int 320 gi_setpassent(int stayopen) 321 { 322 323 if (!pwstart()) 324 return 0; 325 _pw_stayopen = stayopen; 326 return 1; 327 } 328 329 static void 330 gi_endpwent(void) 331 { 332 333 _pw_filesdone = 0; 334 if (_pw_fp) { 335 (void)fclose(_pw_fp); 336 _pw_fp = NULL; 337 } 338 } 339 340 static int 341 pwstart(void) 342 { 343 344 _pw_filesdone = 0; 345 if (_pw_fp) { 346 rewind(_pw_fp); 347 return 1; 348 } 349 if (pwfile[0] == '\0') /* sanity check */ 350 return 0; 351 _pw_fp = fopen(pwfile, "r"); 352 if (_pw_fp != NULL) 353 return 1; 354 warn("Can't open `%s'", pwfile); 355 return 0; 356 } 357 358 359 static int 360 pwscan(int search, uid_t uid, const char *name) 361 { 362 363 if (_pw_filesdone) 364 return 0; 365 for (;;) { 366 if (!fgets(pwline, sizeof(pwline), _pw_fp)) { 367 if (!search) 368 _pw_filesdone = 1; 369 return 0; 370 } 371 /* skip lines that are too big */ 372 if (!strchr(pwline, '\n')) { 373 int ch; 374 375 while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 376 ; 377 continue; 378 } 379 /* skip comments */ 380 if (pwline[0] == '#') 381 continue; 382 if (pwmatchline(search, uid, name)) 383 return 1; 384 } 385 /* NOTREACHED */ 386 } 387 388 static int 389 pwmatchline(int search, uid_t uid, const char *name) 390 { 391 unsigned long id; 392 char *cp, *bp, *ep; 393 394 /* name may be NULL if search is nonzero */ 395 396 bp = pwline; 397 memset(&_pw_passwd, 0, sizeof(_pw_passwd)); 398 _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */ 399 if (search && name && strcmp(_pw_passwd.pw_name, name)) 400 return 0; 401 402 _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */ 403 404 if (!(cp = strsep(&bp, ":\n"))) /* uid */ 405 return 0; 406 id = strtoul(cp, &ep, 10); 407 if (id > UID_MAX || *ep != '\0') 408 return 0; 409 _pw_passwd.pw_uid = (uid_t)id; 410 if (search && name == NULL && _pw_passwd.pw_uid != uid) 411 return 0; 412 413 if (!(cp = strsep(&bp, ":\n"))) /* gid */ 414 return 0; 415 id = strtoul(cp, &ep, 10); 416 if (id > GID_MAX || *ep != '\0') 417 return 0; 418 _pw_passwd.pw_gid = (gid_t)id; 419 420 if (!(ep = strsep(&bp, ":"))) /* class */ 421 return 0; 422 if (!(ep = strsep(&bp, ":"))) /* change */ 423 return 0; 424 if (!(ep = strsep(&bp, ":"))) /* expire */ 425 return 0; 426 427 if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */ 428 return 0; 429 if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */ 430 return 0; 431 if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */ 432 return 0; 433 434 if (strchr(bp, ':') != NULL) 435 return 0; 436 437 return 1; 438 } 439 440