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