11590Srgrimes/* 21590Srgrimes * Copyright (c) 1988, 1993, 1994 31590Srgrimes * The Regents of the University of California. All rights reserved. 496201Sdes * Copyright (c) 2002 Networks Associates Technology, Inc. 596201Sdes * All rights reserved. 61590Srgrimes * 796201Sdes * Portions of this software were developed for the FreeBSD Project by 896201Sdes * ThinkSec AS and NAI Labs, the Security Research Division of Network 996201Sdes * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 1096201Sdes * ("CBOSS"), as part of the DARPA CHATS research program. 1196201Sdes * 121590Srgrimes * Redistribution and use in source and binary forms, with or without 131590Srgrimes * modification, are permitted provided that the following conditions 141590Srgrimes * are met: 151590Srgrimes * 1. Redistributions of source code must retain the above copyright 161590Srgrimes * notice, this list of conditions and the following disclaimer. 171590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 181590Srgrimes * notice, this list of conditions and the following disclaimer in the 191590Srgrimes * documentation and/or other materials provided with the distribution. 201590Srgrimes * 3. All advertising materials mentioning features or use of this software 211590Srgrimes * must display the following acknowledgement: 221590Srgrimes * This product includes software developed by the University of 231590Srgrimes * California, Berkeley and its contributors. 241590Srgrimes * 4. Neither the name of the University nor the names of its contributors 251590Srgrimes * may be used to endorse or promote products derived from this software 261590Srgrimes * without specific prior written permission. 271590Srgrimes * 281590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 291590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 301590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 311590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 321590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 331590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 341590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 351590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 361590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 371590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 381590Srgrimes * SUCH DAMAGE. 391590Srgrimes */ 401590Srgrimes 4193423Sdwmalone#if 0 421590Srgrimes#ifndef lint 4393423Sdwmalonestatic char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94"; 441590Srgrimes#endif /* not lint */ 4593423Sdwmalone#endif 461590Srgrimes 4793086Smarkm#include <sys/cdefs.h> 4893086Smarkm__FBSDID("$FreeBSD$"); 4993086Smarkm 501590Srgrimes#include <sys/param.h> 5115181Smpp#include <sys/stat.h> 521590Srgrimes 531590Srgrimes#include <ctype.h> 541590Srgrimes#include <err.h> 551590Srgrimes#include <errno.h> 561590Srgrimes#include <grp.h> 5796201Sdes#include <paths.h> 581590Srgrimes#include <pwd.h> 591590Srgrimes#include <stdlib.h> 601590Srgrimes#include <string.h> 611590Srgrimes 621590Srgrimes#include "chpass.h" 631590Srgrimes 641590Srgrimes/* ARGSUSED */ 651590Srgrimesint 6693086Smarkmp_login(char *p, struct passwd *pw, ENTRY *ep __unused) 671590Srgrimes{ 681590Srgrimes if (!*p) { 691590Srgrimes warnx("empty login field"); 7096201Sdes return (-1); 711590Srgrimes } 721590Srgrimes if (*p == '-') { 731590Srgrimes warnx("login names may not begin with a hyphen"); 7496201Sdes return (-1); 751590Srgrimes } 761590Srgrimes if (!(pw->pw_name = strdup(p))) { 771590Srgrimes warnx("can't save entry"); 7896201Sdes return (-1); 791590Srgrimes } 801590Srgrimes if (strchr(p, '.')) 811590Srgrimes warnx("\'.\' is dangerous in a login name"); 821590Srgrimes for (; *p; ++p) 831590Srgrimes if (isupper(*p)) { 841590Srgrimes warnx("upper-case letters are dangerous in a login name"); 851590Srgrimes break; 861590Srgrimes } 871590Srgrimes return (0); 881590Srgrimes} 891590Srgrimes 901590Srgrimes/* ARGSUSED */ 911590Srgrimesint 9293086Smarkmp_passwd(char *p, struct passwd *pw, ENTRY *ep __unused) 931590Srgrimes{ 9493423Sdwmalone if (!(pw->pw_passwd = strdup(p))) { 951590Srgrimes warnx("can't save password entry"); 9696201Sdes return (-1); 971590Srgrimes } 988874Srgrimes 991590Srgrimes return (0); 1001590Srgrimes} 1011590Srgrimes 1021590Srgrimes/* ARGSUSED */ 1031590Srgrimesint 10493086Smarkmp_uid(char *p, struct passwd *pw, ENTRY *ep __unused) 1051590Srgrimes{ 1061590Srgrimes uid_t id; 1071590Srgrimes char *np; 1081590Srgrimes 1091590Srgrimes if (!*p) { 1101590Srgrimes warnx("empty uid field"); 11196201Sdes return (-1); 1121590Srgrimes } 1131590Srgrimes if (!isdigit(*p)) { 1141590Srgrimes warnx("illegal uid"); 11596201Sdes return (-1); 1161590Srgrimes } 1171590Srgrimes errno = 0; 1181590Srgrimes id = strtoul(p, &np, 10); 119117430Skan if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) { 1201590Srgrimes warnx("illegal uid"); 12196201Sdes return (-1); 1221590Srgrimes } 1231590Srgrimes pw->pw_uid = id; 1241590Srgrimes return (0); 1251590Srgrimes} 1261590Srgrimes 1271590Srgrimes/* ARGSUSED */ 1281590Srgrimesint 12993086Smarkmp_gid(char *p, struct passwd *pw, ENTRY *ep __unused) 1301590Srgrimes{ 1311590Srgrimes struct group *gr; 1321590Srgrimes gid_t id; 1331590Srgrimes char *np; 1341590Srgrimes 1351590Srgrimes if (!*p) { 1361590Srgrimes warnx("empty gid field"); 13796201Sdes return (-1); 1381590Srgrimes } 1391590Srgrimes if (!isdigit(*p)) { 1401590Srgrimes if (!(gr = getgrnam(p))) { 1411590Srgrimes warnx("unknown group %s", p); 14296201Sdes return (-1); 1431590Srgrimes } 1441590Srgrimes pw->pw_gid = gr->gr_gid; 1451590Srgrimes return (0); 1461590Srgrimes } 1471590Srgrimes errno = 0; 1481590Srgrimes id = strtoul(p, &np, 10); 149117430Skan if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) { 1501590Srgrimes warnx("illegal gid"); 15196201Sdes return (-1); 1521590Srgrimes } 1531590Srgrimes pw->pw_gid = id; 1541590Srgrimes return (0); 1551590Srgrimes} 1561590Srgrimes 1571590Srgrimes/* ARGSUSED */ 1581590Srgrimesint 15993086Smarkmp_class(char *p, struct passwd *pw, ENTRY *ep __unused) 1601590Srgrimes{ 16193423Sdwmalone if (!(pw->pw_class = strdup(p))) { 1621590Srgrimes warnx("can't save entry"); 16396201Sdes return (-1); 1641590Srgrimes } 1658874Srgrimes 1661590Srgrimes return (0); 1671590Srgrimes} 1681590Srgrimes 1691590Srgrimes/* ARGSUSED */ 1701590Srgrimesint 17193086Smarkmp_change(char *p, struct passwd *pw, ENTRY *ep __unused) 1721590Srgrimes{ 1731590Srgrimes if (!atot(p, &pw->pw_change)) 1741590Srgrimes return (0); 1751590Srgrimes warnx("illegal date for change field"); 17696201Sdes return (-1); 1771590Srgrimes} 1781590Srgrimes 1791590Srgrimes/* ARGSUSED */ 1801590Srgrimesint 18193086Smarkmp_expire(char *p, struct passwd *pw, ENTRY *ep __unused) 1821590Srgrimes{ 1831590Srgrimes if (!atot(p, &pw->pw_expire)) 1841590Srgrimes return (0); 1851590Srgrimes warnx("illegal date for expire field"); 18696201Sdes return (-1); 1871590Srgrimes} 1881590Srgrimes 1891590Srgrimes/* ARGSUSED */ 1901590Srgrimesint 19196201Sdesp_gecos(char *p, struct passwd *pw __unused, ENTRY *ep) 1921590Srgrimes{ 19393423Sdwmalone if (!(ep->save = strdup(p))) { 1941590Srgrimes warnx("can't save entry"); 19596201Sdes return (-1); 1961590Srgrimes } 1971590Srgrimes return (0); 1981590Srgrimes} 1991590Srgrimes 2001590Srgrimes/* ARGSUSED */ 2011590Srgrimesint 20293086Smarkmp_hdir(char *p, struct passwd *pw, ENTRY *ep __unused) 2031590Srgrimes{ 2041590Srgrimes if (!*p) { 2051590Srgrimes warnx("empty home directory field"); 20696201Sdes return (-1); 2071590Srgrimes } 2081590Srgrimes if (!(pw->pw_dir = strdup(p))) { 2091590Srgrimes warnx("can't save entry"); 21096201Sdes return (-1); 2111590Srgrimes } 2121590Srgrimes return (0); 2131590Srgrimes} 2141590Srgrimes 2151590Srgrimes/* ARGSUSED */ 2161590Srgrimesint 21793086Smarkmp_shell(char *p, struct passwd *pw, ENTRY *ep __unused) 2181590Srgrimes{ 21915181Smpp struct stat sbuf; 2201590Srgrimes 2211590Srgrimes if (!*p) { 22293086Smarkm pw->pw_shell = strdup(_PATH_BSHELL); 2231590Srgrimes return (0); 2241590Srgrimes } 2251590Srgrimes /* only admin can change from or to "restricted" shells */ 22696201Sdes if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) { 2271590Srgrimes warnx("%s: current shell non-standard", pw->pw_shell); 22896201Sdes return (-1); 2291590Srgrimes } 230124692Scharnier if (!ok_shell(p)) { 23196201Sdes if (!master_mode) { 2321590Srgrimes warnx("%s: non-standard shell", p); 23396201Sdes return (-1); 2341590Srgrimes } 235124692Scharnier pw->pw_shell = strdup(p); 2361590Srgrimes } 2371590Srgrimes else 238124692Scharnier pw->pw_shell = dup_shell(p); 239124692Scharnier if (!pw->pw_shell) { 2401590Srgrimes warnx("can't save entry"); 24196201Sdes return (-1); 2421590Srgrimes } 24315181Smpp if (stat(pw->pw_shell, &sbuf) < 0) { 24415181Smpp if (errno == ENOENT) 24515181Smpp warnx("WARNING: shell '%s' does not exist", 24615181Smpp pw->pw_shell); 24715181Smpp else 24815181Smpp warn("WARNING: can't stat shell '%s'", pw->pw_shell); 24915181Smpp return (0); 25015181Smpp } 25115181Smpp if (!S_ISREG(sbuf.st_mode)) { 25296201Sdes warnx("WARNING: shell '%s' is not a regular file", 25315181Smpp pw->pw_shell); 25415181Smpp return (0); 25515181Smpp } 25615181Smpp if ((sbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) { 25715181Smpp warnx("WARNING: shell '%s' is not executable", pw->pw_shell); 25815181Smpp return (0); 25915181Smpp } 2601590Srgrimes return (0); 2611590Srgrimes} 262