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