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