pw_scan.c revision 104891
11553Srgrimes/*- 21553Srgrimes * Copyright (c) 1990, 1993, 1994 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 3490039Sobrien#if defined(LIBC_SCCS) && !defined(lint) 351553Srgrimesstatic char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94"; 3690039Sobrien#endif /* LIBC_SCCS and not lint */ 3790039Sobrien#include <sys/cdefs.h> 3890039Sobrien__FBSDID("$FreeBSD: head/lib/libc/gen/pw_scan.c 104891 2002-10-11 11:35:30Z maxim $"); 391553Srgrimes 401553Srgrimes/* 411553Srgrimes * This module is used to "verify" password entries by chpass(1) and 421553Srgrimes * pwd_mkdb(8). 431553Srgrimes */ 441553Srgrimes 451553Srgrimes#include <sys/param.h> 461553Srgrimes 471553Srgrimes#include <err.h> 4857868Spaul#include <errno.h> 491553Srgrimes#include <fcntl.h> 501553Srgrimes#include <pwd.h> 511553Srgrimes#include <stdio.h> 521553Srgrimes#include <string.h> 531553Srgrimes#include <stdlib.h> 541553Srgrimes#include <unistd.h> 551553Srgrimes 561553Srgrimes#include "pw_scan.h" 571553Srgrimes 5853183Ssheldonh/* 5953183Ssheldonh * Some software assumes that IDs are short. We should emit warnings 6091925Sdd * for id's which cannot be stored in a short, but we are more liberal 6153183Ssheldonh * by default, warning for IDs greater than USHRT_MAX. 6254034Ssheldonh * 6391925Sdd * If pw_big_ids_warning is -1 on entry to pw_scan(), it will be set based 6491925Sdd * on the existence of PW_SCAN_BIG_IDS in the environment. 6553183Ssheldonh */ 6665532Snectarstatic int pw_big_ids_warning = -1; 6753183Ssheldonh 681553Srgrimesint 6965532Snectar__pw_scan(char *bp, struct passwd *pw, int flags) 701553Srgrimes{ 7157868Spaul uid_t id; 721553Srgrimes int root; 73103958Smaxim char *ep, *p, *sh; 741553Srgrimes 7554034Ssheldonh if (pw_big_ids_warning == -1) 7654034Ssheldonh pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0; 7754034Ssheldonh 782916Swollman pw->pw_fields = 0; 791553Srgrimes if (!(pw->pw_name = strsep(&bp, ":"))) /* login */ 801553Srgrimes goto fmt; 811553Srgrimes root = !strcmp(pw->pw_name, "root"); 8287348Sdes if (pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0')) 832916Swollman pw->pw_fields |= _PWF_NAME; 841553Srgrimes 851553Srgrimes if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */ 861553Srgrimes goto fmt; 8787348Sdes if (pw->pw_passwd[0]) 8887348Sdes pw->pw_fields |= _PWF_PASSWD; 891553Srgrimes 901553Srgrimes if (!(p = strsep(&bp, ":"))) /* uid */ 911553Srgrimes goto fmt; 9252921Seivind if (p[0]) 9352921Seivind pw->pw_fields |= _PWF_UID; 9452921Seivind else { 9553581Seivind if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') { 9665532Snectar if (flags & _PWSCAN_WARN) 9765532Snectar warnx("no uid for user %s", pw->pw_name); 9853581Seivind return (0); 9953581Seivind } 10052921Seivind } 101103958Smaxim id = strtoul(p, &ep, 10); 10257868Spaul if (errno == ERANGE) { 10365532Snectar if (flags & _PWSCAN_WARN) 10473725Sdwmalone warnx("%s > max uid value (%lu)", p, ULONG_MAX); 10557868Spaul return (0); 10657868Spaul } 107104348Smaxim if (*ep != '\0') { 108103958Smaxim if (flags & _PWSCAN_WARN) 109103958Smaxim warnx("%s uid is incorrect", p); 110103958Smaxim return (0); 111103958Smaxim } 1121553Srgrimes if (root && id) { 11365532Snectar if (flags & _PWSCAN_WARN) 11465532Snectar warnx("root uid should be 0"); 1151553Srgrimes return (0); 1161553Srgrimes } 11765532Snectar if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) { 11857868Spaul warnx("%s > recommended max uid value (%u)", p, USHRT_MAX); 11950700Ssheldonh /*return (0);*/ /* THIS SHOULD NOT BE FATAL! */ 1201553Srgrimes } 1211553Srgrimes pw->pw_uid = id; 1221553Srgrimes 1231553Srgrimes if (!(p = strsep(&bp, ":"))) /* gid */ 1241553Srgrimes goto fmt; 12587348Sdes if (p[0]) 12687348Sdes pw->pw_fields |= _PWF_GID; 127104891Smaxim else { 128104891Smaxim if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') { 129104891Smaxim if (flags & _PWSCAN_WARN) 130104891Smaxim warnx("no gid for user %s", pw->pw_name); 131104891Smaxim return (0); 132104891Smaxim } 133104891Smaxim } 134103958Smaxim id = strtoul(p, &ep, 10); 13557868Spaul if (errno == ERANGE) { 13665532Snectar if (flags & _PWSCAN_WARN) 13773725Sdwmalone warnx("%s > max gid value (%lu)", p, ULONG_MAX); 13857868Spaul return (0); 13957868Spaul } 140104348Smaxim if (*ep != '\0') { 141103958Smaxim if (flags & _PWSCAN_WARN) 142103958Smaxim warnx("%s gid is incorrect", p); 143103958Smaxim return (0); 144103958Smaxim } 14565532Snectar if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) { 14657868Spaul warnx("%s > recommended max gid value (%u)", p, USHRT_MAX); 14750700Ssheldonh /* return (0); This should not be fatal! */ 1481553Srgrimes } 1491553Srgrimes pw->pw_gid = id; 1501553Srgrimes 15165532Snectar if (flags & _PWSCAN_MASTER ) { 15287348Sdes if (!(pw->pw_class = strsep(&bp, ":"))) /* class */ 15387347Sdes goto fmt; 15487348Sdes if (pw->pw_class[0]) 15587348Sdes pw->pw_fields |= _PWF_CLASS; 15665532Snectar 15787348Sdes if (!(p = strsep(&bp, ":"))) /* change */ 15865532Snectar goto fmt; 15987348Sdes if (p[0]) 16087348Sdes pw->pw_fields |= _PWF_CHANGE; 16165532Snectar pw->pw_change = atol(p); 16265532Snectar 16387348Sdes if (!(p = strsep(&bp, ":"))) /* expire */ 16465532Snectar goto fmt; 16587348Sdes if (p[0]) 16687348Sdes pw->pw_fields |= _PWF_EXPIRE; 16765532Snectar pw->pw_expire = atol(p); 16865532Snectar } 1695964Sdg if (!(pw->pw_gecos = strsep(&bp, ":"))) /* gecos */ 1705964Sdg goto fmt; 17187348Sdes if (pw->pw_gecos[0]) 17287348Sdes pw->pw_fields |= _PWF_GECOS; 1732916Swollman 17487348Sdes if (!(pw->pw_dir = strsep(&bp, ":"))) /* directory */ 1755964Sdg goto fmt; 17687348Sdes if (pw->pw_dir[0]) 17787348Sdes pw->pw_fields |= _PWF_DIR; 1782916Swollman 1791553Srgrimes if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */ 1801553Srgrimes goto fmt; 1811553Srgrimes 1821553Srgrimes p = pw->pw_shell; 1831553Srgrimes if (root && *p) /* empty == /bin/sh */ 1841553Srgrimes for (setusershell();;) { 1851553Srgrimes if (!(sh = getusershell())) { 18665532Snectar if (flags & _PWSCAN_WARN) 18765532Snectar warnx("warning, unknown root shell"); 1881553Srgrimes break; 1891553Srgrimes } 1901553Srgrimes if (!strcmp(p, sh)) 1918857Srgrimes break; 1921553Srgrimes } 19387348Sdes if (p[0]) 19487348Sdes pw->pw_fields |= _PWF_SHELL; 1951553Srgrimes 19630260Scharnier if ((p = strsep(&bp, ":"))) { /* too many */ 19765532Snectarfmt: 19865532Snectar if (flags & _PWSCAN_WARN) 19965532Snectar warnx("corrupted entry"); 2001553Srgrimes return (0); 2011553Srgrimes } 2021553Srgrimes return (1); 2031553Srgrimes} 204