1256996Sbrooks/* $NetBSD: getid.c,v 1.8 2013/10/16 17:27:42 christos Exp $ */ 2244541Sbrooks/* from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */ 3244541Sbrooks/* from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */ 4244541Sbrooks 5244541Sbrooks/* 6244541Sbrooks * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995 7244541Sbrooks * The Regents of the University of California. All rights reserved. 8244541Sbrooks * 9244541Sbrooks * Redistribution and use in source and binary forms, with or without 10244541Sbrooks * modification, are permitted provided that the following conditions 11244541Sbrooks * are met: 12244541Sbrooks * 1. Redistributions of source code must retain the above copyright 13244541Sbrooks * notice, this list of conditions and the following disclaimer. 14244541Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 15244541Sbrooks * notice, this list of conditions and the following disclaimer in the 16244541Sbrooks * documentation and/or other materials provided with the distribution. 17244541Sbrooks * 3. Neither the name of the University nor the names of its contributors 18244541Sbrooks * may be used to endorse or promote products derived from this software 19244541Sbrooks * without specific prior written permission. 20244541Sbrooks * 21244541Sbrooks * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22244541Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23244541Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24244541Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25244541Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26244541Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27244541Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28244541Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29244541Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30244541Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31244541Sbrooks * SUCH DAMAGE. 32244541Sbrooks */ 33244541Sbrooks 34244541Sbrooks/*- 35244541Sbrooks * Copyright (c) 2002 The NetBSD Foundation, Inc. 36244541Sbrooks * All rights reserved. 37244541Sbrooks * 38244541Sbrooks * This code is derived from software contributed to The NetBSD Foundation 39244541Sbrooks * by Luke Mewburn of Wasabi Systems. 40244541Sbrooks * 41244541Sbrooks * Redistribution and use in source and binary forms, with or without 42244541Sbrooks * modification, are permitted provided that the following conditions 43244541Sbrooks * are met: 44244541Sbrooks * 1. Redistributions of source code must retain the above copyright 45244541Sbrooks * notice, this list of conditions and the following disclaimer. 46244541Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 47244541Sbrooks * notice, this list of conditions and the following disclaimer in the 48244541Sbrooks * documentation and/or other materials provided with the distribution. 49244541Sbrooks * 50244541Sbrooks * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 51244541Sbrooks * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 52244541Sbrooks * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53244541Sbrooks * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 54244541Sbrooks * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55244541Sbrooks * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56244541Sbrooks * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57244541Sbrooks * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58244541Sbrooks * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59244541Sbrooks * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60244541Sbrooks * POSSIBILITY OF SUCH DAMAGE. 61244541Sbrooks */ 62244541Sbrooks 63244541Sbrooks#if HAVE_NBTOOL_CONFIG_H 64244541Sbrooks#include "nbtool_config.h" 65244541Sbrooks#endif 66244541Sbrooks 67244541Sbrooks#include <sys/cdefs.h> 68256996Sbrooks__RCSID("$NetBSD: getid.c,v 1.8 2013/10/16 17:27:42 christos Exp $"); 69244541Sbrooks 70244541Sbrooks#include <sys/param.h> 71244541Sbrooks 72244541Sbrooks#include <grp.h> 73244541Sbrooks#include <limits.h> 74244541Sbrooks#include <pwd.h> 75244541Sbrooks#include <stdlib.h> 76244541Sbrooks#include <stdio.h> 77244541Sbrooks#include <string.h> 78244541Sbrooks#include <time.h> 79244541Sbrooks#include <unistd.h> 80244541Sbrooks 81244541Sbrooks#include "extern.h" 82244541Sbrooks 83244541Sbrooksstatic struct group * gi_getgrnam(const char *); 84244541Sbrooksstatic struct group * gi_getgrgid(gid_t); 85244541Sbrooksstatic int gi_setgroupent(int); 86244541Sbrooksstatic void gi_endgrent(void); 87244541Sbrooksstatic int grstart(void); 88244541Sbrooksstatic int grscan(int, gid_t, const char *); 89244541Sbrooksstatic int grmatchline(int, gid_t, const char *); 90244541Sbrooks 91244541Sbrooksstatic struct passwd * gi_getpwnam(const char *); 92244541Sbrooksstatic struct passwd * gi_getpwuid(uid_t); 93244541Sbrooksstatic int gi_setpassent(int); 94244541Sbrooksstatic void gi_endpwent(void); 95244541Sbrooksstatic int pwstart(void); 96244541Sbrooksstatic int pwscan(int, uid_t, const char *); 97244541Sbrooksstatic int pwmatchline(int, uid_t, const char *); 98244541Sbrooks 99244541Sbrooks#define MAXGRP 200 100244541Sbrooks#define MAXLINELENGTH 1024 101244541Sbrooks 102244541Sbrooksstatic FILE *_gr_fp; 103244541Sbrooksstatic struct group _gr_group; 104244541Sbrooksstatic int _gr_stayopen; 105244541Sbrooksstatic int _gr_filesdone; 106244541Sbrooksstatic FILE *_pw_fp; 107244541Sbrooksstatic struct passwd _pw_passwd; /* password structure */ 108244541Sbrooksstatic int _pw_stayopen; /* keep fd's open */ 109244541Sbrooksstatic int _pw_filesdone; 110244541Sbrooks 111244541Sbrooksstatic char grfile[MAXPATHLEN]; 112244541Sbrooksstatic char pwfile[MAXPATHLEN]; 113244541Sbrooks 114244541Sbrooksstatic char *members[MAXGRP]; 115244541Sbrooksstatic char grline[MAXLINELENGTH]; 116244541Sbrooksstatic char pwline[MAXLINELENGTH]; 117244541Sbrooks 118244541Sbrooksint 119244541Sbrookssetup_getid(const char *dir) 120244541Sbrooks{ 121244541Sbrooks if (dir == NULL) 122244541Sbrooks return (0); 123244541Sbrooks 124244541Sbrooks /* close existing databases */ 125244541Sbrooks gi_endgrent(); 126244541Sbrooks gi_endpwent(); 127244541Sbrooks 128244541Sbrooks /* build paths to new databases */ 129244541Sbrooks snprintf(grfile, sizeof(grfile), "%s/group", dir); 130244541Sbrooks snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir); 131244541Sbrooks 132244541Sbrooks /* try to open new databases */ 133244541Sbrooks if (!grstart() || !pwstart()) 134244541Sbrooks return (0); 135244541Sbrooks 136244541Sbrooks /* switch pwcache(3) lookup functions */ 137244541Sbrooks if (pwcache_groupdb(gi_setgroupent, gi_endgrent, 138244541Sbrooks gi_getgrnam, gi_getgrgid) == -1 139244541Sbrooks || pwcache_userdb(gi_setpassent, gi_endpwent, 140244541Sbrooks gi_getpwnam, gi_getpwuid) == -1) 141244541Sbrooks return (0); 142244541Sbrooks 143244541Sbrooks return (1); 144244541Sbrooks} 145244541Sbrooks 146244541Sbrooks 147244541Sbrooks/* 148244541Sbrooks * group lookup functions 149244541Sbrooks */ 150244541Sbrooks 151244541Sbrooksstatic struct group * 152244541Sbrooksgi_getgrnam(const char *name) 153244541Sbrooks{ 154244541Sbrooks int rval; 155244541Sbrooks 156244541Sbrooks if (!grstart()) 157244541Sbrooks return NULL; 158244541Sbrooks rval = grscan(1, 0, name); 159244541Sbrooks if (!_gr_stayopen) 160244541Sbrooks endgrent(); 161244541Sbrooks return (rval) ? &_gr_group : NULL; 162244541Sbrooks} 163244541Sbrooks 164244541Sbrooksstatic struct group * 165244541Sbrooksgi_getgrgid(gid_t gid) 166244541Sbrooks{ 167244541Sbrooks int rval; 168244541Sbrooks 169244541Sbrooks if (!grstart()) 170244541Sbrooks return NULL; 171244541Sbrooks rval = grscan(1, gid, NULL); 172244541Sbrooks if (!_gr_stayopen) 173244541Sbrooks endgrent(); 174244541Sbrooks return (rval) ? &_gr_group : NULL; 175244541Sbrooks} 176244541Sbrooks 177244541Sbrooksstatic int 178244541Sbrooksgi_setgroupent(int stayopen) 179244541Sbrooks{ 180244541Sbrooks 181244541Sbrooks if (!grstart()) 182244541Sbrooks return 0; 183244541Sbrooks _gr_stayopen = stayopen; 184244541Sbrooks return 1; 185244541Sbrooks} 186244541Sbrooks 187244541Sbrooksstatic void 188244541Sbrooksgi_endgrent(void) 189244541Sbrooks{ 190244541Sbrooks 191244541Sbrooks _gr_filesdone = 0; 192244541Sbrooks if (_gr_fp) { 193244541Sbrooks (void)fclose(_gr_fp); 194244541Sbrooks _gr_fp = NULL; 195244541Sbrooks } 196244541Sbrooks} 197244541Sbrooks 198244541Sbrooksstatic int 199244541Sbrooksgrstart(void) 200244541Sbrooks{ 201244541Sbrooks 202244541Sbrooks _gr_filesdone = 0; 203244541Sbrooks if (_gr_fp) { 204244541Sbrooks rewind(_gr_fp); 205244541Sbrooks return 1; 206244541Sbrooks } 207244541Sbrooks if (grfile[0] == '\0') /* sanity check */ 208244541Sbrooks return 0; 209244541Sbrooks return (_gr_fp = fopen(grfile, "r")) ? 1 : 0; 210244541Sbrooks} 211244541Sbrooks 212244541Sbrooks 213244541Sbrooksstatic int 214244541Sbrooksgrscan(int search, gid_t gid, const char *name) 215244541Sbrooks{ 216244541Sbrooks 217244541Sbrooks if (_gr_filesdone) 218244541Sbrooks return 0; 219244541Sbrooks for (;;) { 220244541Sbrooks if (!fgets(grline, sizeof(grline), _gr_fp)) { 221244541Sbrooks if (!search) 222244541Sbrooks _gr_filesdone = 1; 223244541Sbrooks return 0; 224244541Sbrooks } 225244541Sbrooks /* skip lines that are too big */ 226244541Sbrooks if (!strchr(grline, '\n')) { 227244541Sbrooks int ch; 228244541Sbrooks 229244541Sbrooks while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 230244541Sbrooks ; 231244541Sbrooks continue; 232244541Sbrooks } 233256996Sbrooks /* skip comments */ 234256996Sbrooks if (pwline[0] == '#') 235256996Sbrooks continue; 236244541Sbrooks if (grmatchline(search, gid, name)) 237244541Sbrooks return 1; 238244541Sbrooks } 239244541Sbrooks /* NOTREACHED */ 240244541Sbrooks} 241244541Sbrooks 242244541Sbrooksstatic int 243244541Sbrooksgrmatchline(int search, gid_t gid, const char *name) 244244541Sbrooks{ 245244541Sbrooks unsigned long id; 246244541Sbrooks char **m; 247244541Sbrooks char *cp, *bp, *ep; 248244541Sbrooks 249244541Sbrooks /* name may be NULL if search is nonzero */ 250244541Sbrooks 251244541Sbrooks bp = grline; 252244541Sbrooks memset(&_gr_group, 0, sizeof(_gr_group)); 253244541Sbrooks _gr_group.gr_name = strsep(&bp, ":\n"); 254244541Sbrooks if (search && name && strcmp(_gr_group.gr_name, name)) 255244541Sbrooks return 0; 256244541Sbrooks _gr_group.gr_passwd = strsep(&bp, ":\n"); 257244541Sbrooks if (!(cp = strsep(&bp, ":\n"))) 258244541Sbrooks return 0; 259244541Sbrooks id = strtoul(cp, &ep, 10); 260244541Sbrooks if (id > GID_MAX || *ep != '\0') 261244541Sbrooks return 0; 262244541Sbrooks _gr_group.gr_gid = (gid_t)id; 263244541Sbrooks if (search && name == NULL && _gr_group.gr_gid != gid) 264244541Sbrooks return 0; 265244541Sbrooks cp = NULL; 266244541Sbrooks if (bp == NULL) 267244541Sbrooks return 0; 268244541Sbrooks for (_gr_group.gr_mem = m = members;; bp++) { 269244541Sbrooks if (m == &members[MAXGRP - 1]) 270244541Sbrooks break; 271244541Sbrooks if (*bp == ',') { 272244541Sbrooks if (cp) { 273244541Sbrooks *bp = '\0'; 274244541Sbrooks *m++ = cp; 275244541Sbrooks cp = NULL; 276244541Sbrooks } 277244541Sbrooks } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 278244541Sbrooks if (cp) { 279244541Sbrooks *bp = '\0'; 280244541Sbrooks *m++ = cp; 281244541Sbrooks } 282244541Sbrooks break; 283244541Sbrooks } else if (cp == NULL) 284244541Sbrooks cp = bp; 285244541Sbrooks } 286244541Sbrooks *m = NULL; 287244541Sbrooks return 1; 288244541Sbrooks} 289244541Sbrooks 290244541Sbrooks 291244541Sbrooks/* 292244541Sbrooks * user lookup functions 293244541Sbrooks */ 294244541Sbrooks 295244541Sbrooksstatic struct passwd * 296244541Sbrooksgi_getpwnam(const char *name) 297244541Sbrooks{ 298244541Sbrooks int rval; 299244541Sbrooks 300244541Sbrooks if (!pwstart()) 301244541Sbrooks return NULL; 302244541Sbrooks rval = pwscan(1, 0, name); 303244541Sbrooks if (!_pw_stayopen) 304244541Sbrooks endpwent(); 305244541Sbrooks return (rval) ? &_pw_passwd : NULL; 306244541Sbrooks} 307244541Sbrooks 308244541Sbrooksstatic struct passwd * 309244541Sbrooksgi_getpwuid(uid_t uid) 310244541Sbrooks{ 311244541Sbrooks int rval; 312244541Sbrooks 313244541Sbrooks if (!pwstart()) 314244541Sbrooks return NULL; 315244541Sbrooks rval = pwscan(1, uid, NULL); 316244541Sbrooks if (!_pw_stayopen) 317244541Sbrooks endpwent(); 318244541Sbrooks return (rval) ? &_pw_passwd : NULL; 319244541Sbrooks} 320244541Sbrooks 321244541Sbrooksstatic int 322244541Sbrooksgi_setpassent(int stayopen) 323244541Sbrooks{ 324244541Sbrooks 325244541Sbrooks if (!pwstart()) 326244541Sbrooks return 0; 327244541Sbrooks _pw_stayopen = stayopen; 328244541Sbrooks return 1; 329244541Sbrooks} 330244541Sbrooks 331244541Sbrooksstatic void 332244541Sbrooksgi_endpwent(void) 333244541Sbrooks{ 334244541Sbrooks 335244541Sbrooks _pw_filesdone = 0; 336244541Sbrooks if (_pw_fp) { 337244541Sbrooks (void)fclose(_pw_fp); 338244541Sbrooks _pw_fp = NULL; 339244541Sbrooks } 340244541Sbrooks} 341244541Sbrooks 342244541Sbrooksstatic int 343244541Sbrookspwstart(void) 344244541Sbrooks{ 345244541Sbrooks 346244541Sbrooks _pw_filesdone = 0; 347244541Sbrooks if (_pw_fp) { 348244541Sbrooks rewind(_pw_fp); 349244541Sbrooks return 1; 350244541Sbrooks } 351244541Sbrooks if (pwfile[0] == '\0') /* sanity check */ 352244541Sbrooks return 0; 353244541Sbrooks return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0; 354244541Sbrooks} 355244541Sbrooks 356244541Sbrooks 357244541Sbrooksstatic int 358244541Sbrookspwscan(int search, uid_t uid, const char *name) 359244541Sbrooks{ 360244541Sbrooks 361244541Sbrooks if (_pw_filesdone) 362244541Sbrooks return 0; 363244541Sbrooks for (;;) { 364244541Sbrooks if (!fgets(pwline, sizeof(pwline), _pw_fp)) { 365244541Sbrooks if (!search) 366244541Sbrooks _pw_filesdone = 1; 367244541Sbrooks return 0; 368244541Sbrooks } 369244541Sbrooks /* skip lines that are too big */ 370244541Sbrooks if (!strchr(pwline, '\n')) { 371244541Sbrooks int ch; 372244541Sbrooks 373244541Sbrooks while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 374244541Sbrooks ; 375244541Sbrooks continue; 376244541Sbrooks } 377256996Sbrooks /* skip comments */ 378256996Sbrooks if (pwline[0] == '#') 379256996Sbrooks continue; 380244541Sbrooks if (pwmatchline(search, uid, name)) 381244541Sbrooks return 1; 382244541Sbrooks } 383244541Sbrooks /* NOTREACHED */ 384244541Sbrooks} 385244541Sbrooks 386244541Sbrooksstatic int 387244541Sbrookspwmatchline(int search, uid_t uid, const char *name) 388244541Sbrooks{ 389244541Sbrooks unsigned long id; 390244541Sbrooks char *cp, *bp, *ep; 391244541Sbrooks 392244541Sbrooks /* name may be NULL if search is nonzero */ 393244541Sbrooks 394244541Sbrooks bp = pwline; 395244541Sbrooks memset(&_pw_passwd, 0, sizeof(_pw_passwd)); 396244541Sbrooks _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */ 397244541Sbrooks if (search && name && strcmp(_pw_passwd.pw_name, name)) 398244541Sbrooks return 0; 399244541Sbrooks 400244541Sbrooks _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */ 401244541Sbrooks 402244541Sbrooks if (!(cp = strsep(&bp, ":\n"))) /* uid */ 403244541Sbrooks return 0; 404244541Sbrooks id = strtoul(cp, &ep, 10); 405244541Sbrooks if (id > UID_MAX || *ep != '\0') 406244541Sbrooks return 0; 407244541Sbrooks _pw_passwd.pw_uid = (uid_t)id; 408244541Sbrooks if (search && name == NULL && _pw_passwd.pw_uid != uid) 409244541Sbrooks return 0; 410244541Sbrooks 411244541Sbrooks if (!(cp = strsep(&bp, ":\n"))) /* gid */ 412244541Sbrooks return 0; 413244541Sbrooks id = strtoul(cp, &ep, 10); 414244541Sbrooks if (id > GID_MAX || *ep != '\0') 415244541Sbrooks return 0; 416244541Sbrooks _pw_passwd.pw_gid = (gid_t)id; 417244541Sbrooks 418244541Sbrooks if (!(ep = strsep(&bp, ":"))) /* class */ 419244541Sbrooks return 0; 420244541Sbrooks if (!(ep = strsep(&bp, ":"))) /* change */ 421244541Sbrooks return 0; 422244541Sbrooks if (!(ep = strsep(&bp, ":"))) /* expire */ 423244541Sbrooks return 0; 424244541Sbrooks 425244541Sbrooks if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */ 426244541Sbrooks return 0; 427244541Sbrooks if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */ 428244541Sbrooks return 0; 429244541Sbrooks if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */ 430244541Sbrooks return 0; 431244541Sbrooks 432244541Sbrooks if (strchr(bp, ':') != NULL) 433244541Sbrooks return 0; 434244541Sbrooks 435244541Sbrooks return 1; 436244541Sbrooks} 437244541Sbrooks 438