1273796Sbrooks/* $NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 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> 68273796Sbrooks__RCSID("$NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 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; 209273796Sbrooks 210273796Sbrooks _gr_fp = fopen(grfile, "r"); 211273796Sbrooks if (_gr_fp != NULL) 212273796Sbrooks return 1; 213273796Sbrooks warn("Can't open `%s'", grfile); 214273796Sbrooks return 0; 215244541Sbrooks} 216244541Sbrooks 217244541Sbrooks 218244541Sbrooksstatic int 219244541Sbrooksgrscan(int search, gid_t gid, const char *name) 220244541Sbrooks{ 221244541Sbrooks 222244541Sbrooks if (_gr_filesdone) 223244541Sbrooks return 0; 224244541Sbrooks for (;;) { 225244541Sbrooks if (!fgets(grline, sizeof(grline), _gr_fp)) { 226244541Sbrooks if (!search) 227244541Sbrooks _gr_filesdone = 1; 228244541Sbrooks return 0; 229244541Sbrooks } 230244541Sbrooks /* skip lines that are too big */ 231244541Sbrooks if (!strchr(grline, '\n')) { 232244541Sbrooks int ch; 233244541Sbrooks 234244541Sbrooks while ((ch = getc(_gr_fp)) != '\n' && ch != EOF) 235244541Sbrooks ; 236244541Sbrooks continue; 237244541Sbrooks } 238256687Sbrooks /* skip comments */ 239273796Sbrooks if (grline[0] == '#') 240256687Sbrooks continue; 241244541Sbrooks if (grmatchline(search, gid, name)) 242244541Sbrooks return 1; 243244541Sbrooks } 244244541Sbrooks /* NOTREACHED */ 245244541Sbrooks} 246244541Sbrooks 247244541Sbrooksstatic int 248244541Sbrooksgrmatchline(int search, gid_t gid, const char *name) 249244541Sbrooks{ 250244541Sbrooks unsigned long id; 251244541Sbrooks char **m; 252244541Sbrooks char *cp, *bp, *ep; 253244541Sbrooks 254244541Sbrooks /* name may be NULL if search is nonzero */ 255244541Sbrooks 256244541Sbrooks bp = grline; 257244541Sbrooks memset(&_gr_group, 0, sizeof(_gr_group)); 258244541Sbrooks _gr_group.gr_name = strsep(&bp, ":\n"); 259244541Sbrooks if (search && name && strcmp(_gr_group.gr_name, name)) 260244541Sbrooks return 0; 261244541Sbrooks _gr_group.gr_passwd = strsep(&bp, ":\n"); 262244541Sbrooks if (!(cp = strsep(&bp, ":\n"))) 263244541Sbrooks return 0; 264244541Sbrooks id = strtoul(cp, &ep, 10); 265244541Sbrooks if (id > GID_MAX || *ep != '\0') 266244541Sbrooks return 0; 267244541Sbrooks _gr_group.gr_gid = (gid_t)id; 268244541Sbrooks if (search && name == NULL && _gr_group.gr_gid != gid) 269244541Sbrooks return 0; 270244541Sbrooks cp = NULL; 271244541Sbrooks if (bp == NULL) 272244541Sbrooks return 0; 273244541Sbrooks for (_gr_group.gr_mem = m = members;; bp++) { 274244541Sbrooks if (m == &members[MAXGRP - 1]) 275244541Sbrooks break; 276244541Sbrooks if (*bp == ',') { 277244541Sbrooks if (cp) { 278244541Sbrooks *bp = '\0'; 279244541Sbrooks *m++ = cp; 280244541Sbrooks cp = NULL; 281244541Sbrooks } 282244541Sbrooks } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') { 283244541Sbrooks if (cp) { 284244541Sbrooks *bp = '\0'; 285244541Sbrooks *m++ = cp; 286244541Sbrooks } 287244541Sbrooks break; 288244541Sbrooks } else if (cp == NULL) 289244541Sbrooks cp = bp; 290244541Sbrooks } 291244541Sbrooks *m = NULL; 292244541Sbrooks return 1; 293244541Sbrooks} 294244541Sbrooks 295244541Sbrooks 296244541Sbrooks/* 297244541Sbrooks * user lookup functions 298244541Sbrooks */ 299244541Sbrooks 300244541Sbrooksstatic struct passwd * 301244541Sbrooksgi_getpwnam(const char *name) 302244541Sbrooks{ 303244541Sbrooks int rval; 304244541Sbrooks 305244541Sbrooks if (!pwstart()) 306244541Sbrooks return NULL; 307244541Sbrooks rval = pwscan(1, 0, name); 308244541Sbrooks if (!_pw_stayopen) 309244541Sbrooks endpwent(); 310244541Sbrooks return (rval) ? &_pw_passwd : NULL; 311244541Sbrooks} 312244541Sbrooks 313244541Sbrooksstatic struct passwd * 314244541Sbrooksgi_getpwuid(uid_t uid) 315244541Sbrooks{ 316244541Sbrooks int rval; 317244541Sbrooks 318244541Sbrooks if (!pwstart()) 319244541Sbrooks return NULL; 320244541Sbrooks rval = pwscan(1, uid, NULL); 321244541Sbrooks if (!_pw_stayopen) 322244541Sbrooks endpwent(); 323244541Sbrooks return (rval) ? &_pw_passwd : NULL; 324244541Sbrooks} 325244541Sbrooks 326244541Sbrooksstatic int 327244541Sbrooksgi_setpassent(int stayopen) 328244541Sbrooks{ 329244541Sbrooks 330244541Sbrooks if (!pwstart()) 331244541Sbrooks return 0; 332244541Sbrooks _pw_stayopen = stayopen; 333244541Sbrooks return 1; 334244541Sbrooks} 335244541Sbrooks 336244541Sbrooksstatic void 337244541Sbrooksgi_endpwent(void) 338244541Sbrooks{ 339244541Sbrooks 340244541Sbrooks _pw_filesdone = 0; 341244541Sbrooks if (_pw_fp) { 342244541Sbrooks (void)fclose(_pw_fp); 343244541Sbrooks _pw_fp = NULL; 344244541Sbrooks } 345244541Sbrooks} 346244541Sbrooks 347244541Sbrooksstatic int 348244541Sbrookspwstart(void) 349244541Sbrooks{ 350244541Sbrooks 351244541Sbrooks _pw_filesdone = 0; 352244541Sbrooks if (_pw_fp) { 353244541Sbrooks rewind(_pw_fp); 354244541Sbrooks return 1; 355244541Sbrooks } 356244541Sbrooks if (pwfile[0] == '\0') /* sanity check */ 357244541Sbrooks return 0; 358273796Sbrooks _pw_fp = fopen(pwfile, "r"); 359273796Sbrooks if (_pw_fp != NULL) 360273796Sbrooks return 1; 361273796Sbrooks warn("Can't open `%s'", pwfile); 362273796Sbrooks return 0; 363244541Sbrooks} 364244541Sbrooks 365244541Sbrooks 366244541Sbrooksstatic int 367244541Sbrookspwscan(int search, uid_t uid, const char *name) 368244541Sbrooks{ 369244541Sbrooks 370244541Sbrooks if (_pw_filesdone) 371244541Sbrooks return 0; 372244541Sbrooks for (;;) { 373244541Sbrooks if (!fgets(pwline, sizeof(pwline), _pw_fp)) { 374244541Sbrooks if (!search) 375244541Sbrooks _pw_filesdone = 1; 376244541Sbrooks return 0; 377244541Sbrooks } 378244541Sbrooks /* skip lines that are too big */ 379244541Sbrooks if (!strchr(pwline, '\n')) { 380244541Sbrooks int ch; 381244541Sbrooks 382244541Sbrooks while ((ch = getc(_pw_fp)) != '\n' && ch != EOF) 383244541Sbrooks ; 384244541Sbrooks continue; 385244541Sbrooks } 386256687Sbrooks /* skip comments */ 387256687Sbrooks if (pwline[0] == '#') 388256687Sbrooks continue; 389244541Sbrooks if (pwmatchline(search, uid, name)) 390244541Sbrooks return 1; 391244541Sbrooks } 392244541Sbrooks /* NOTREACHED */ 393244541Sbrooks} 394244541Sbrooks 395244541Sbrooksstatic int 396244541Sbrookspwmatchline(int search, uid_t uid, const char *name) 397244541Sbrooks{ 398244541Sbrooks unsigned long id; 399244541Sbrooks char *cp, *bp, *ep; 400244541Sbrooks 401244541Sbrooks /* name may be NULL if search is nonzero */ 402244541Sbrooks 403244541Sbrooks bp = pwline; 404244541Sbrooks memset(&_pw_passwd, 0, sizeof(_pw_passwd)); 405244541Sbrooks _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */ 406244541Sbrooks if (search && name && strcmp(_pw_passwd.pw_name, name)) 407244541Sbrooks return 0; 408244541Sbrooks 409244541Sbrooks _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */ 410244541Sbrooks 411244541Sbrooks if (!(cp = strsep(&bp, ":\n"))) /* uid */ 412244541Sbrooks return 0; 413244541Sbrooks id = strtoul(cp, &ep, 10); 414244541Sbrooks if (id > UID_MAX || *ep != '\0') 415244541Sbrooks return 0; 416244541Sbrooks _pw_passwd.pw_uid = (uid_t)id; 417244541Sbrooks if (search && name == NULL && _pw_passwd.pw_uid != uid) 418244541Sbrooks return 0; 419244541Sbrooks 420244541Sbrooks if (!(cp = strsep(&bp, ":\n"))) /* gid */ 421244541Sbrooks return 0; 422244541Sbrooks id = strtoul(cp, &ep, 10); 423244541Sbrooks if (id > GID_MAX || *ep != '\0') 424244541Sbrooks return 0; 425244541Sbrooks _pw_passwd.pw_gid = (gid_t)id; 426244541Sbrooks 427244541Sbrooks if (!(ep = strsep(&bp, ":"))) /* class */ 428244541Sbrooks return 0; 429244541Sbrooks if (!(ep = strsep(&bp, ":"))) /* change */ 430244541Sbrooks return 0; 431244541Sbrooks if (!(ep = strsep(&bp, ":"))) /* expire */ 432244541Sbrooks return 0; 433244541Sbrooks 434244541Sbrooks if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */ 435244541Sbrooks return 0; 436244541Sbrooks if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */ 437244541Sbrooks return 0; 438244541Sbrooks if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */ 439244541Sbrooks return 0; 440244541Sbrooks 441244541Sbrooks if (strchr(bp, ':') != NULL) 442244541Sbrooks return 0; 443244541Sbrooks 444244541Sbrooks return 1; 445244541Sbrooks} 446244541Sbrooks 447