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 #if HAVE_NBTOOL_CONFIG_H 64 #include "nbtool_config.h" 65 #endif 66 67 #include <sys/param.h> 68 69 #include <grp.h> 70 #include <limits.h> 71 #include <pwd.h> 72 #include <stdlib.h> 73 #include <stdio.h> 74 #include <string.h> 75 #include <time.h> 76 #include <unistd.h> 77 78 #include "extern.h" 79 80 static struct group * gi_getgrnam(const char *); 81 static struct group * gi_getgrgid(gid_t); 82 static int gi_setgroupent(int); 83 static void gi_endgrent(void); 84 static int grstart(void); 85 static int grscan(int, gid_t, const char *); 86 static int grmatchline(int, gid_t, const char *); 87 88 static struct passwd * gi_getpwnam(const char *); 89 static struct passwd * gi_getpwuid(uid_t); 90 static int gi_setpassent(int); 91 static void gi_endpwent(void); 92 static int pwstart(void); 93 static int pwscan(int, uid_t, const char *); 94 static int pwmatchline(int, uid_t, const char *); 95 96 #define MAXGRP 200 97 #define MAXLINELENGTH 1024 98 99 static FILE *_gr_fp; 100 static struct group _gr_group; 101 static int _gr_stayopen; 102 static int _gr_filesdone; 103 static FILE *_pw_fp; 104 static struct passwd _pw_passwd; /* password structure */ 105 static int _pw_stayopen; /* keep fd's open */ 106 static int _pw_filesdone; 107 108 static char grfile[MAXPATHLEN]; 109 static char pwfile[MAXPATHLEN]; 110 111 static char *members[MAXGRP]; 112 static char grline[MAXLINELENGTH]; 113 static char pwline[MAXLINELENGTH]; 114 115 int 116 setup_getid(const char *dir) 117 { 118 if (dir == NULL) 119 return (0); 120 121 /* close existing databases */ 122 gi_endgrent(); 123 gi_endpwent(); 124 125 /* build paths to new databases */ 126 snprintf(grfile, sizeof(grfile), "%s/group", dir); 127 snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir); 128 129 /* try to open new databases */ 130 if (!grstart() || !pwstart()) 131 return (0); 132 133 /* switch pwcache(3) lookup functions */ 134 if (pwcache_groupdb(gi_setgroupent, gi_endgrent, 135 gi_getgrnam, gi_getgrgid) == -1 136 || pwcache_userdb(gi_setpassent, gi_endpwent, 137 gi_getpwnam, gi_getpwuid) == -1) 138 return (0); 139 140 return (1); 141 } 142 143 144 /* 145 * group lookup functions 146 */ 147 148 static struct group * 149 gi_getgrnam(const char *name) 150 { 151 int rval; 152 153 if (!grstart()) 154 return NULL; 155 rval = grscan(1, 0, name); 156 if (!_gr_stayopen) 157 endgrent(); 158 return (rval) ? &_gr_group : NULL; 159 } 160 161 static struct group * 162 gi_getgrgid(gid_t gid) 163 { 164 int rval; 165 166 if (!grstart()) 167 return NULL; 168 rval = grscan(1, gid, NULL); 169 if (!_gr_stayopen) 170 endgrent(); 171 return (rval) ? &_gr_group : NULL; 172 } 173 174 static int 175 gi_setgroupent(int stayopen) 176 { 177 178 if (!grstart()) 179 return 0; 180 _gr_stayopen = stayopen; 181 return 1; 182 } 183 184 static void 185 gi_endgrent(void) 186 { 187 188 _gr_filesdone = 0; 189 if (_gr_fp) { 190 (void)fclose(_gr_fp); 191 _gr_fp = NULL; 192 } 193 } 194 195 static int 196 grstart(void) 197 { 198 199 _gr_filesdone = 0; 200 if (_gr_fp) { 201 rewind(_gr_fp); 202 return 1; 203 } 204 if (grfile[0] == '\0') /* sanity check */ 205 return 0; 206 207 _gr_fp = fopen(grfile, "r"); 208 if (_gr_fp != NULL) 209 return 1; 210 warn("Can't open `%s'", grfile); 211 return 0; 212 } 213 214 215 static int 216 grscan(int search, gid_t gid, const char *name) 217 { 218 219 if (_gr_filesdone) 220 return 0; 221 for (;;) { 222 if (!fgets(grline, sizeof(grline), _gr_fp)) { 223 if (!search) 224 _gr_filesdone = 1; 225 return 0; 226 } 227 /* skip lines that are too big */ 228 if (!strchr(grline, '\n')) { 229 int ch; 230 231 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 232 ; 233 continue; 234 } 235 /* skip comments */ 236 if (grline[0] == '#') 237 continue; 238 if (grmatchline(search, gid, name)) 239 return 1; 240 } 241 /* NOTREACHED */ 242 } 243 244 static int 245 grmatchline(int search, gid_t gid, const char *name) 246 { 247 unsigned long id; 248 char **m; 249 char *cp, *bp, *ep; 250 251 /* name may be NULL if search is nonzero */ 252 253 bp = grline; 254 memset(&_gr_group, 0, sizeof(_gr_group)); 255 _gr_group.gr_name = strsep(&bp, ":\n"); 256 if (search && name && strcmp(_gr_group.gr_name, name)) 257 return 0; 258 _gr_group.gr_passwd = strsep(&bp, ":\n"); 259 if (!(cp = strsep(&bp, ":\n"))) 260 return 0; 261 id = strtoul(cp, &ep, 10); 262 if (id > GID_MAX || *ep != '\0') 263 return 0; 264 _gr_group.gr_gid = (gid_t)id; 265 if (search && name == NULL && _gr_group.gr_gid != gid) 266 return 0; 267 cp = NULL; 268 if (bp == NULL) 269 return 0; 270 for (_gr_group.gr_mem = m = members;; bp++) { 271 if (m == &members[MAXGRP - 1]) 272 break; 273 if (*bp == ',') { 274 if (cp) { 275 *bp = '\0'; 276 *m++ = cp; 277 cp = NULL; 278 } 279 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 280 if (cp) { 281 *bp = '\0'; 282 *m++ = cp; 283 } 284 break; 285 } else if (cp == NULL) 286 cp = bp; 287 } 288 *m = NULL; 289 return 1; 290 } 291 292 293 /* 294 * user lookup functions 295 */ 296 297 static struct passwd * 298 gi_getpwnam(const char *name) 299 { 300 int rval; 301 302 if (!pwstart()) 303 return NULL; 304 rval = pwscan(1, 0, name); 305 if (!_pw_stayopen) 306 endpwent(); 307 return (rval) ? &_pw_passwd : NULL; 308 } 309 310 static struct passwd * 311 gi_getpwuid(uid_t uid) 312 { 313 int rval; 314 315 if (!pwstart()) 316 return NULL; 317 rval = pwscan(1, uid, NULL); 318 if (!_pw_stayopen) 319 endpwent(); 320 return (rval) ? &_pw_passwd : NULL; 321 } 322 323 static int 324 gi_setpassent(int stayopen) 325 { 326 327 if (!pwstart()) 328 return 0; 329 _pw_stayopen = stayopen; 330 return 1; 331 } 332 333 static void 334 gi_endpwent(void) 335 { 336 337 _pw_filesdone = 0; 338 if (_pw_fp) { 339 (void)fclose(_pw_fp); 340 _pw_fp = NULL; 341 } 342 } 343 344 static int 345 pwstart(void) 346 { 347 348 _pw_filesdone = 0; 349 if (_pw_fp) { 350 rewind(_pw_fp); 351 return 1; 352 } 353 if (pwfile[0] == '\0') /* sanity check */ 354 return 0; 355 _pw_fp = fopen(pwfile, "r"); 356 if (_pw_fp != NULL) 357 return 1; 358 warn("Can't open `%s'", pwfile); 359 return 0; 360 } 361 362 363 static int 364 pwscan(int search, uid_t uid, const char *name) 365 { 366 367 if (_pw_filesdone) 368 return 0; 369 for (;;) { 370 if (!fgets(pwline, sizeof(pwline), _pw_fp)) { 371 if (!search) 372 _pw_filesdone = 1; 373 return 0; 374 } 375 /* skip lines that are too big */ 376 if (!strchr(pwline, '\n')) { 377 int ch; 378 379 while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 380 ; 381 continue; 382 } 383 /* skip comments */ 384 if (pwline[0] == '#') 385 continue; 386 if (pwmatchline(search, uid, name)) 387 return 1; 388 } 389 /* NOTREACHED */ 390 } 391 392 static int 393 pwmatchline(int search, uid_t uid, const char *name) 394 { 395 unsigned long id; 396 char *cp, *bp, *ep; 397 398 /* name may be NULL if search is nonzero */ 399 400 bp = pwline; 401 memset(&_pw_passwd, 0, sizeof(_pw_passwd)); 402 _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */ 403 if (search && name && strcmp(_pw_passwd.pw_name, name)) 404 return 0; 405 406 _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */ 407 408 if (!(cp = strsep(&bp, ":\n"))) /* uid */ 409 return 0; 410 id = strtoul(cp, &ep, 10); 411 if (id > UID_MAX || *ep != '\0') 412 return 0; 413 _pw_passwd.pw_uid = (uid_t)id; 414 if (search && name == NULL && _pw_passwd.pw_uid != uid) 415 return 0; 416 417 if (!(cp = strsep(&bp, ":\n"))) /* gid */ 418 return 0; 419 id = strtoul(cp, &ep, 10); 420 if (id > GID_MAX || *ep != '\0') 421 return 0; 422 _pw_passwd.pw_gid = (gid_t)id; 423 424 if (!(ep = strsep(&bp, ":"))) /* class */ 425 return 0; 426 if (!(ep = strsep(&bp, ":"))) /* change */ 427 return 0; 428 if (!(ep = strsep(&bp, ":"))) /* expire */ 429 return 0; 430 431 if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */ 432 return 0; 433 if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */ 434 return 0; 435 if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */ 436 return 0; 437 438 if (strchr(bp, ':') != NULL) 439 return 0; 440 441 return 1; 442 } 443 444