diff options
Diffstat (limited to 'chpass')
-rw-r--r-- | chpass/Makefile | 49 | ||||
-rw-r--r-- | chpass/chpass.1 | 492 | ||||
-rw-r--r-- | chpass/chpass.c | 302 | ||||
-rw-r--r-- | chpass/chpass.h | 79 | ||||
-rw-r--r-- | chpass/edit.c | 296 | ||||
-rw-r--r-- | chpass/field.c | 261 | ||||
-rw-r--r-- | chpass/table.c | 69 | ||||
-rw-r--r-- | chpass/util.c | 182 |
8 files changed, 1730 insertions, 0 deletions
diff --git a/chpass/Makefile b/chpass/Makefile new file mode 100644 index 0000000..2bbdc08 --- /dev/null +++ b/chpass/Makefile @@ -0,0 +1,49 @@ +# @(#)Makefile 8.2 (Berkeley) 4/2/94 +# $FreeBSD$ + +.include <bsd.own.mk> + +.PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../lib/libc/gen + +PROG= chpass +SRCS= chpass.c edit.c field.c pw_scan.c table.c util.c +BINOWN= root +BINMODE=4555 +WARNS?= 5 +.if ${MK_NIS} != "no" +CFLAGS+= -DYP +.endif +#Some people need this, uncomment to activate +#CFLAGS+=-DRESTRICT_FULLNAME_CHANGE +CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../lib/libc/gen -I. + +DPADD= ${LIBCRYPT} ${LIBUTIL} +LDADD= -lcrypt -lutil +.if ${MK_NIS} != "no" +DPADD+= ${LIBYPCLNT} +LDADD+= -lypclnt +.endif + +LINKS= ${BINDIR}/chpass ${BINDIR}/chfn +LINKS+= ${BINDIR}/chpass ${BINDIR}/chsh +.if ${MK_NIS} != "no" +LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchpass +LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchfn +LINKS+= ${BINDIR}/chpass ${BINDIR}/ypchsh +.endif + +MLINKS= chpass.1 chfn.1 chpass.1 chsh.1 +.if ${MK_NIS} != "no" +MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1 +.endif + +beforeinstall: +.for i in chpass chfn chsh ypchpass ypchfn ypchsh + [ ! -e ${DESTDIR}${BINDIR}/$i ] || \ + chflags noschg ${DESTDIR}${BINDIR}/$i || true +.endfor + +afterinstall: + -chflags schg ${DESTDIR}${BINDIR}/chpass + +.include <bsd.prog.mk> diff --git a/chpass/chpass.1 b/chpass/chpass.1 new file mode 100644 index 0000000..24b1759 --- /dev/null +++ b/chpass/chpass.1 @@ -0,0 +1,492 @@ +.\" Copyright (c) 1988, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)chpass.1 8.2 (Berkeley) 12/30/93 +.\" $FreeBSD$ +.\" +.Dd December 30, 1993 +.Dt CHPASS 1 +.Os +.Sh NAME +.Nm chpass , +.Nm chfn , +.Nm chsh , +.Nm ypchpass , +.Nm ypchfn , +.Nm ypchsh +.Nd add or change user database information +.Sh SYNOPSIS +.Nm +.Op Fl a Ar list +.Op Fl p Ar encpass +.Op Fl e Ar expiretime +.Op Fl s Ar newshell +.Op user +.Nm +.Op Fl oly +.Op Fl a Ar list +.Op Fl p Ar encpass +.Op Fl e Ar expiretime +.Op Fl s Ar newshell +.Op Fl d Ar domain +.Op Fl h Ar host +.Op user +.Sh DESCRIPTION +The +.Nm +utility +allows editing of the user database information associated +with +.Ar user +or, by default, the current user. +.Pp +The +.Nm chfn , +.Nm chsh , +.Nm ypchpass , +.Nm ypchfn +and +.Nm ypchsh +utilities behave identically to +.Nm . +(There is only one program.) +.Pp +The information is formatted and supplied to an editor for changes. +.Pp +Only the information that the user is allowed to change is displayed. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl a +The super-user is allowed to directly supply a user database +entry, in the format specified by +.Xr passwd 5 , +as an argument. +This argument must be a colon +.Pq Dq \&: +separated list of all the +user database fields, although they may be empty. +.It Fl p +The super-user is allowed to directly supply an encrypted password field, +in the format used by +.Xr crypt 3 , +as an argument. +.It Fl e Ar expiretime +Change the account expire time. +This option is used to set the expire time +from a script as if it was done in the interactive editor. +.It Fl s Ar newshell +Attempt to change the user's shell to +.Ar newshell . +.El +.Pp +Possible display items are as follows: +.Pp +.Bl -tag -width "Other Information:" -compact -offset indent +.It Login: +user's login name +.It Password: +user's encrypted password +.It Uid: +user's login +.It Gid: +user's login group +.It Class: +user's general classification +.It Change: +password change time +.It Expire: +account expiration time +.It Full Name: +user's real name +.It Office Location: +user's office location (1) +.It Office Phone: +user's office phone (1) +.It Home Phone: +user's home phone (1) +.It Other Information: +any locally defined parameters for user (1) +.It Home Directory: +user's home directory +.It Shell: +user's login shell +.Pp +.It NOTE(1) - +In the actual master.passwd file, these fields are comma-delimited +fields embedded in the FullName field. +.El +.Pp +The +.Ar login +field is the user name used to access the computer account. +.Pp +The +.Ar password +field contains the encrypted form of the user's password. +.Pp +The +.Ar uid +field is the number associated with the +.Ar login +field. +Both of these fields should be unique across the system (and often +across a group of systems) as they control file access. +.Pp +While it is possible to have multiple entries with identical login names +and/or identical user id's, it is usually a mistake to do so. +Routines +that manipulate these files will often return only one of the multiple +entries, and that one by random selection. +.Pp +The +.Ar group +field is the group that the user will be placed in at login. +Since +.Bx +supports multiple groups (see +.Xr groups 1 ) +this field currently has little special meaning. +This field may be filled in with either a number or a group name (see +.Xr group 5 ) . +.Pp +The +.Ar class +field references class descriptions in +.Pa /etc/login.conf +and is typically used to initialize the user's system resource limits +when they login. +.Pp +The +.Ar change +field is the date by which the password must be changed. +.Pp +The +.Ar expire +field is the date on which the account expires. +.Pp +Both the +.Ar change +and +.Ar expire +fields should be entered in the form +.Dq month day year +where +.Ar month +is the month name (the first three characters are sufficient), +.Ar day +is the day of the month, and +.Ar year +is the year. +.Pp +Five fields are available for storing the user's +.Ar full name , office location , +.Ar work +and +.Ar home telephone +numbers and finally +.Ar other information +which is a single comma delimited string to represent any additional +gecos fields (typically used for site specific user information). +Note that +.Xr finger 1 +will display the office location and office phone together under the +heading +.Ar Office: . +.Pp +The user's +.Ar home directory +is the full +.Ux +path name where the user +will be placed at login. +.Pp +The +.Ar shell +field is the command interpreter the user prefers. +If the +.Ar shell +field is empty, the Bourne shell, +.Pa /bin/sh , +is assumed. +When altering a login shell, and not the super-user, the user +may not change from a non-standard shell or to a non-standard +shell. +Non-standard is defined as a shell not found in +.Pa /etc/shells . +.Pp +Once the information has been verified, +.Nm +uses +.Xr pwd_mkdb 8 +to update the user database. +.Sh ENVIRONMENT +The +.Xr vi 1 +editor will be used unless the environment variable +.Ev EDITOR +is set to +an alternate editor. +When the editor terminates, the information is re-read and used to +update the user database itself. +Only the user, or the super-user, may edit the information associated +with the user. +.Pp +See +.Xr pwd_mkdb 8 +for an explanation of the impact of setting the +.Ev PW_SCAN_BIG_IDS +environment variable. +.Sh NIS INTERACTION +The +.Nm +utility can also be used in conjunction with NIS, however some restrictions +apply. +Currently, +.Nm +can only make changes to the NIS passwd maps through +.Xr rpc.yppasswdd 8 , +which normally only permits changes to a user's password, shell and GECOS +fields. +Except when invoked by the super-user on the NIS master server, +.Nm +(and, similarly, +.Xr passwd 1 ) +cannot use the +.Xr rpc.yppasswdd 8 +server to change other user information or +add new records to the NIS passwd maps. +Furthermore, +.Xr rpc.yppasswdd 8 +requires password authentication before it will make any +changes. +The only user allowed to submit changes without supplying +a password is the super-user on the NIS master server; all other users, +including those with root privileges on NIS clients (and NIS slave +servers) must enter a password. +(The super-user on the NIS master is allowed to bypass these restrictions +largely for convenience: a user with root access +to the NIS master server already has the privileges required to make +updates to the NIS maps, but editing the map source files by hand can +be cumbersome. +.Pp +Note: these exceptions only apply when the NIS master server is a +.Fx +system). +.Pp +Consequently, except where noted, the following restrictions apply when +.Nm +is used with NIS: +.Bl -enum -offset indent +.It +.Em "Only the shell and GECOS information may be changed" . +All other +fields are restricted, even when +.Nm +is invoked by the super-user. +While support for +changing other fields could be added, this would lead to +compatibility problems with other NIS-capable systems. +Even though the super-user may supply data for other fields +while editing an entry, the extra information (other than the +password -- see below) will be silently discarded. +.Pp +Exception: the super-user on the NIS master server is permitted to +change any field. +.Pp +.It +.Em "Password authentication is required" . +The +.Nm +utility will prompt for the user's NIS password before effecting +any changes. +If the password is invalid, all changes will be +discarded. +.Pp +Exception: the super-user on the NIS master server is allowed to +submit changes without supplying a password. +(The super-user may +choose to turn off this feature using the +.Fl o +flag, described below.) +.It +.Em "Adding new records to the local password database is discouraged" . +The +.Nm +utility will allow the administrator to add new records to the +local password database while NIS is enabled, but this can lead to +some confusion since the new records are appended to the end of +the master password file, usually after the special NIS '+' entries. +The administrator should use +.Xr vipw 8 +to modify the local password +file when NIS is running. +.Pp +The super-user on the NIS master server is permitted to add new records +to the NIS password maps, provided the +.Xr rpc.yppasswdd 8 +server has been started with the +.Fl a +flag to permitted additions (it refuses them by default). +The +.Nm +utility tries to update the local password database by default; to update the +NIS maps instead, invoke chpass with the +.Fl y +flag. +.It +.Em "Password changes are not permitted". +Users should use +.Xr passwd 1 +or +.Xr yppasswd 1 +to change their NIS passwords. +The super-user is allowed to specify +a new password (even though the +.Dq Password: +field does not show +up in the editor template, the super-user may add it back by hand), +but even the super-user must supply the user's original password +otherwise +.Xr rpc.yppasswdd 8 +will refuse to update the NIS maps. +.Pp +Exception: the super-user on the NIS master server is permitted to +change a user's NIS password with +.Nm . +.El +.Pp +There are also a few extra option flags that are available when +.Nm +is compiled with NIS support: +.Bl -tag -width indent +.It Fl l +Force +.Nm +to modify the local copy of a user's password +information in the event that a user exists in both +the local and NIS databases. +.It Fl y +Opposite effect of +.Fl l . +This flag is largely redundant since +.Nm +operates on NIS entries by default if NIS is enabled. +.It Fl d Ar domain +Specify a particular NIS domain. +The +.Nm +utility uses the system domain name by default, as set by the +.Xr domainname 1 +utility. +The +.Fl d +option can be used to override a default, or to specify a domain +when the system domain name is not set. +.It Fl h Ar host +Specify the name or address of an NIS server to query. +Normally, +.Nm +will communicate with the NIS master host specified in the +.Pa master.passwd +or +.Pa passwd +maps. +On hosts that have not been configured as NIS clients, there is +no way for the program to determine this information unless the user +provides the hostname of a server. +Note that the specified hostname need +not be that of the NIS master server; the name of any server, master or +slave, in a given NIS domain will do. +.Pp +When using the +.Fl d +option, the hostname defaults to +.Dq localhost . +The +.Fl h +option can be used in conjunction with the +.Fl d +option, in which case the user-specified hostname will override +the default. +.Pp +.It Fl o +Force the use of RPC-based updates when communicating with +.Xr rpc.yppasswdd 8 +.Pq Dq old-mode . +When invoked by the super-user on the NIS master server, +.Nm +allows unrestricted changes to the NIS passwd maps using dedicated, +non-RPC-based mechanism (in this case, a +.Ux +domain socket). +The +.Fl o +flag can be used to force +.Nm +to use the standard update mechanism instead. +This option is provided +mainly for testing purposes. +.El +.Sh FILES +.Bl -tag -width /etc/master.passwd -compact +.It Pa /etc/master.passwd +the user database +.It Pa /etc/passwd +a Version 7 format password file +.It Pa /etc/chpass.XXXXXX +temporary copy of the password file +.It Pa /etc/shells +the list of approved shells +.El +.Sh SEE ALSO +.Xr finger 1 , +.Xr login 1 , +.Xr passwd 1 , +.Xr getusershell 3 , +.Xr login.conf 5 , +.Xr passwd 5 , +.Xr pw 8 , +.Xr pwd_mkdb 8 , +.Xr vipw 8 +.Rs +.%A Robert Morris +and +.%A Ken Thompson +.%T "UNIX Password security" +.Re +.Sh HISTORY +The +.Nm +utility appeared in +.Bx 4.3 Reno . +.Sh BUGS +User information should (and eventually will) be stored elsewhere. diff --git a/chpass/chpass.c b/chpass/chpass.c new file mode 100644 index 0000000..2504e68 --- /dev/null +++ b/chpass/chpass.c @@ -0,0 +1,302 @@ +/*- + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1988, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)chpass.c 8.4 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> + +#include <err.h> +#include <errno.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#ifdef YP +#include <ypclnt.h> +#endif + +#include <pw_scan.h> +#include <libutil.h> + +#include "chpass.h" + +int master_mode; + +static void baduser(void); +static void usage(void); + +int +main(int argc, char *argv[]) +{ + enum { NEWSH, LOADENTRY, EDITENTRY, NEWPW, NEWEXP } op; + struct passwd lpw, *old_pw, *pw; + int ch, pfd, tfd; + const char *password; + char *arg = NULL; + uid_t uid; +#ifdef YP + struct ypclnt *ypclnt; + const char *yp_domain = NULL, *yp_host = NULL; +#endif + + pw = old_pw = NULL; + op = EDITENTRY; +#ifdef YP + while ((ch = getopt(argc, argv, "a:p:s:e:d:h:loy")) != -1) +#else + while ((ch = getopt(argc, argv, "a:p:s:e:")) != -1) +#endif + switch (ch) { + case 'a': + op = LOADENTRY; + arg = optarg; + break; + case 's': + op = NEWSH; + arg = optarg; + break; + case 'p': + op = NEWPW; + arg = optarg; + break; + case 'e': + op = NEWEXP; + arg = optarg; + break; +#ifdef YP + case 'd': + yp_domain = optarg; + break; + case 'h': + yp_host = optarg; + break; + case 'l': + case 'o': + case 'y': + /* compatibility */ + break; +#endif + case '?': + default: + usage(); + } + + argc -= optind; + argv += optind; + + if (argc > 1) + usage(); + + uid = getuid(); + + if (op == EDITENTRY || op == NEWSH || op == NEWPW || op == NEWEXP) { + if (argc == 0) { + if ((pw = getpwuid(uid)) == NULL) + errx(1, "unknown user: uid %lu", + (unsigned long)uid); + } else { + if ((pw = getpwnam(*argv)) == NULL) + errx(1, "unknown user: %s", *argv); + if (uid != 0 && uid != pw->pw_uid) + baduser(); + } + + /* Make a copy for later verification */ + if ((pw = pw_dup(pw)) == NULL || + (old_pw = pw_dup(pw)) == NULL) + err(1, "pw_dup"); + } + +#ifdef YP + if (pw != NULL && (pw->pw_fields & _PWF_SOURCE) == _PWF_NIS) { + ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host); + master_mode = (ypclnt != NULL && + ypclnt_connect(ypclnt) != -1 && + ypclnt_havepasswdd(ypclnt) == 1); + ypclnt_free(ypclnt); + } else +#endif + master_mode = (uid == 0); + + if (op == NEWSH) { + /* protect p_shell -- it thinks NULL is /bin/sh */ + if (!arg[0]) + usage(); + if (p_shell(arg, pw, (ENTRY *)NULL) == -1) + exit(1); + } + + if (op == NEWEXP) { + if (uid) /* only root can change expire */ + baduser(); + if (p_expire(arg, pw, (ENTRY *)NULL) == -1) + exit(1); + } + + if (op == LOADENTRY) { + if (uid) + baduser(); + pw = &lpw; + old_pw = NULL; + if (!__pw_scan(arg, pw, _PWSCAN_WARN|_PWSCAN_MASTER)) + exit(1); + } + + if (op == NEWPW) { + if (uid) + baduser(); + + if (strchr(arg, ':')) + errx(1, "invalid format for password"); + pw->pw_passwd = arg; + } + + if (op == EDITENTRY) { + /* + * We don't really need pw_*() here, but pw_edit() (used + * by edit()) is just too useful... + */ + if (pw_init(NULL, NULL)) + err(1, "pw_init()"); + if ((tfd = pw_tmp(-1)) == -1) { + pw_fini(); + err(1, "pw_tmp()"); + } + free(pw); + pw = edit(pw_tempname(), old_pw); + pw_fini(); + if (pw == NULL) + err(1, "edit()"); + /* + * pw_equal does not check for crypted passwords, so we + * should do it explicitly + */ + if (pw_equal(old_pw, pw) && + strcmp(old_pw->pw_passwd, pw->pw_passwd) == 0) + errx(0, "user information unchanged"); + } + + if (old_pw && !master_mode) { + password = getpass("Password: "); + if (strcmp(crypt(password, old_pw->pw_passwd), + old_pw->pw_passwd) != 0) + baduser(); + } else { + password = ""; + } + + if (old_pw != NULL) + pw->pw_fields |= (old_pw->pw_fields & _PWF_SOURCE); + switch (pw->pw_fields & _PWF_SOURCE) { +#ifdef YP + case _PWF_NIS: + ypclnt = ypclnt_new(yp_domain, "passwd.byname", yp_host); + if (ypclnt == NULL || + ypclnt_connect(ypclnt) == -1 || + ypclnt_passwd(ypclnt, pw, password) == -1) { + warnx("%s", ypclnt->error); + ypclnt_free(ypclnt); + exit(1); + } + ypclnt_free(ypclnt); + errx(0, "NIS user information updated"); +#endif /* YP */ + case 0: + case _PWF_FILES: + if (pw_init(NULL, NULL)) + err(1, "pw_init()"); + if ((pfd = pw_lock()) == -1) { + pw_fini(); + err(1, "pw_lock()"); + } + if ((tfd = pw_tmp(-1)) == -1) { + pw_fini(); + err(1, "pw_tmp()"); + } + if (pw_copy(pfd, tfd, pw, old_pw) == -1) { + pw_fini(); + err(1, "pw_copy"); + } + if (pw_mkdb(pw->pw_name) == -1) { + pw_fini(); + err(1, "pw_mkdb()"); + } + pw_fini(); + errx(0, "user information updated"); + break; + default: + errx(1, "unsupported passwd source"); + } +} + +static void +baduser(void) +{ + + errx(1, "%s", strerror(EACCES)); +} + +static void +usage(void) +{ + + (void)fprintf(stderr, + "usage: chpass%s %s [user]\n", +#ifdef YP + " [-d domain] [-h host]", +#else + "", +#endif + "[-a list] [-p encpass] [-s shell] [-e mmm dd yy]"); + exit(1); +} diff --git a/chpass/chpass.h b/chpass/chpass.h new file mode 100644 index 0000000..ed1a586 --- /dev/null +++ b/chpass/chpass.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)chpass.h 8.4 (Berkeley) 4/2/94 + * $FreeBSD$ + */ + +struct passwd; + +typedef struct _entry { + const char *prompt; + int (*func)(char *, struct passwd *, struct _entry *); + int restricted; + size_t len; + char *except, *save; +} ENTRY; + +/* Field numbers. */ +#define E_BPHONE 8 +#define E_HPHONE 9 +#define E_LOCATE 10 +#define E_NAME 7 +#define E_OTHER 11 +#define E_SHELL 13 + +extern ENTRY list[]; +extern int master_mode; + +int atot(char *, time_t *); +struct passwd *edit(const char *, struct passwd *); +int ok_shell(char *); +char *dup_shell(char *); +int p_change(char *, struct passwd *, ENTRY *); +int p_class(char *, struct passwd *, ENTRY *); +int p_expire(char *, struct passwd *, ENTRY *); +int p_gecos(char *, struct passwd *, ENTRY *); +int p_gid(char *, struct passwd *, ENTRY *); +int p_hdir(char *, struct passwd *, ENTRY *); +int p_login(char *, struct passwd *, ENTRY *); +int p_passwd(char *, struct passwd *, ENTRY *); +int p_shell(char *, struct passwd *, ENTRY *); +int p_uid(char *, struct passwd *, ENTRY *); +char *ttoa(time_t); diff --git a/chpass/edit.c b/chpass/edit.c new file mode 100644 index 0000000..ce82f8e --- /dev/null +++ b/chpass/edit.c @@ -0,0 +1,296 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)edit.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <paths.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <pw_scan.h> +#include <libutil.h> + +#include "chpass.h" + +static int display(const char *tfn, struct passwd *pw); +static struct passwd *verify(const char *tfn, struct passwd *pw); + +struct passwd * +edit(const char *tfn, struct passwd *pw) +{ + struct passwd *npw; + char *line; + size_t len; + + if (display(tfn, pw) == -1) + return (NULL); + for (;;) { + switch (pw_edit(1)) { + case -1: + return (NULL); + case 0: + return (pw_dup(pw)); + default: + break; + } + if ((npw = verify(tfn, pw)) != NULL) + return (npw); + free(npw); + printf("re-edit the password file? "); + fflush(stdout); + if ((line = fgetln(stdin, &len)) == NULL) { + warn("fgetln()"); + return (NULL); + } + if (len > 0 && (*line == 'N' || *line == 'n')) + return (NULL); + } +} + +/* + * display -- + * print out the file for the user to edit; strange side-effect: + * set conditional flag if the user gets to edit the shell. + */ +static int +display(const char *tfn, struct passwd *pw) +{ + FILE *fp; + char *bp, *gecos, *p; + + if ((fp = fopen(tfn, "w")) == NULL) { + warn("%s", tfn); + return (-1); + } + + (void)fprintf(fp, + "#Changing user information for %s.\n", pw->pw_name); + if (master_mode) { + (void)fprintf(fp, "Login: %s\n", pw->pw_name); + (void)fprintf(fp, "Password: %s\n", pw->pw_passwd); + (void)fprintf(fp, "Uid [#]: %lu\n", (unsigned long)pw->pw_uid); + (void)fprintf(fp, "Gid [# or name]: %lu\n", + (unsigned long)pw->pw_gid); + (void)fprintf(fp, "Change [month day year]: %s\n", + ttoa(pw->pw_change)); + (void)fprintf(fp, "Expire [month day year]: %s\n", + ttoa(pw->pw_expire)); + (void)fprintf(fp, "Class: %s\n", pw->pw_class); + (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir); + (void)fprintf(fp, "Shell: %s\n", + *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); + } + /* Only admin can change "restricted" shells. */ +#if 0 + else if (ok_shell(pw->pw_shell)) + /* + * Make shell a restricted field. Ugly with a + * necklace, but there's not much else to do. + */ +#else + else if ((!list[E_SHELL].restricted && ok_shell(pw->pw_shell)) || + master_mode) + /* + * If change not restrict (table.c) and standard shell + * OR if root, then allow editing of shell. + */ +#endif + (void)fprintf(fp, "Shell: %s\n", + *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); + else + list[E_SHELL].restricted = 1; + + if ((bp = gecos = strdup(pw->pw_gecos)) == NULL) { + warn(NULL); + fclose(fp); + return (-1); + } + + p = strsep(&bp, ","); + p = strdup(p ? p : ""); + list[E_NAME].save = p; + if (!list[E_NAME].restricted || master_mode) + (void)fprintf(fp, "Full Name: %s\n", p); + + p = strsep(&bp, ","); + p = strdup(p ? p : ""); + list[E_LOCATE].save = p; + if (!list[E_LOCATE].restricted || master_mode) + (void)fprintf(fp, "Office Location: %s\n", p); + + p = strsep(&bp, ","); + p = strdup(p ? p : ""); + list[E_BPHONE].save = p; + if (!list[E_BPHONE].restricted || master_mode) + (void)fprintf(fp, "Office Phone: %s\n", p); + + p = strsep(&bp, ","); + p = strdup(p ? p : ""); + list[E_HPHONE].save = p; + if (!list[E_HPHONE].restricted || master_mode) + (void)fprintf(fp, "Home Phone: %s\n", p); + + bp = strdup(bp ? bp : ""); + list[E_OTHER].save = bp; + if (!list[E_OTHER].restricted || master_mode) + (void)fprintf(fp, "Other information: %s\n", bp); + + free(gecos); + + (void)fchown(fileno(fp), getuid(), getgid()); + (void)fclose(fp); + return (0); +} + +static struct passwd * +verify(const char *tfn, struct passwd *pw) +{ + struct passwd *npw; + ENTRY *ep; + char *buf, *p, *val; + struct stat sb; + FILE *fp; + int line; + size_t len; + + if ((pw = pw_dup(pw)) == NULL) + return (NULL); + if ((fp = fopen(tfn, "r")) == NULL || + fstat(fileno(fp), &sb) == -1) { + warn("%s", tfn); + free(pw); + return (NULL); + } + if (sb.st_size == 0) { + warnx("corrupted temporary file"); + fclose(fp); + free(pw); + return (NULL); + } + val = NULL; + for (line = 1; (buf = fgetln(fp, &len)) != NULL; ++line) { + if (*buf == '\0' || *buf == '#') + continue; + while (len > 0 && isspace(buf[len - 1])) + --len; + for (ep = list;; ++ep) { + if (!ep->prompt) { + warnx("%s: unrecognized field on line %d", + tfn, line); + goto bad; + } + if (ep->len > len) + continue; + if (strncasecmp(buf, ep->prompt, ep->len) != 0) + continue; + if (ep->restricted && !master_mode) { + warnx("%s: you may not change the %s field", + tfn, ep->prompt); + goto bad; + } + for (p = buf; p < buf + len && *p != ':'; ++p) + /* nothing */ ; + if (*p != ':') { + warnx("%s: line %d corrupted", tfn, line); + goto bad; + } + while (++p < buf + len && isspace(*p)) + /* nothing */ ; + free(val); + asprintf(&val, "%.*s", (int)(buf + len - p), p); + if (val == NULL) + goto bad; + if (ep->except && strpbrk(val, ep->except)) { + warnx("%s: invalid character in \"%s\" field '%s'", + tfn, ep->prompt, val); + goto bad; + } + if ((ep->func)(val, pw, ep)) + goto bad; + break; + } + } + free(val); + fclose(fp); + + /* Build the gecos field. */ + len = asprintf(&p, "%s,%s,%s,%s,%s", list[E_NAME].save, + list[E_LOCATE].save, list[E_BPHONE].save, + list[E_HPHONE].save, list[E_OTHER].save); + if (p == NULL) { + warn("asprintf()"); + free(pw); + return (NULL); + } + while (len > 0 && p[len - 1] == ',') + p[--len] = '\0'; + pw->pw_gecos = p; + buf = pw_make(pw); + free(pw); + free(p); + if (buf == NULL) { + warn("pw_make()"); + return (NULL); + } + npw = pw_scan(buf, PWSCAN_WARN|PWSCAN_MASTER); + free(buf); + return (npw); +bad: + free(pw); + free(val); + fclose(fp); + return (NULL); +} diff --git a/chpass/field.c b/chpass/field.c new file mode 100644 index 0000000..eac5561 --- /dev/null +++ b/chpass/field.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <grp.h> +#include <paths.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> + +#include "chpass.h" + +/* ARGSUSED */ +int +p_login(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + if (!*p) { + warnx("empty login field"); + return (-1); + } + if (*p == '-') { + warnx("login names may not begin with a hyphen"); + return (-1); + } + if (!(pw->pw_name = strdup(p))) { + warnx("can't save entry"); + return (-1); + } + if (strchr(p, '.')) + warnx("\'.\' is dangerous in a login name"); + for (; *p; ++p) + if (isupper(*p)) { + warnx("upper-case letters are dangerous in a login name"); + break; + } + return (0); +} + +/* ARGSUSED */ +int +p_passwd(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + if (!(pw->pw_passwd = strdup(p))) { + warnx("can't save password entry"); + return (-1); + } + + return (0); +} + +/* ARGSUSED */ +int +p_uid(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + uid_t id; + char *np; + + if (!*p) { + warnx("empty uid field"); + return (-1); + } + if (!isdigit(*p)) { + warnx("illegal uid"); + return (-1); + } + errno = 0; + id = strtoul(p, &np, 10); + if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) { + warnx("illegal uid"); + return (-1); + } + pw->pw_uid = id; + return (0); +} + +/* ARGSUSED */ +int +p_gid(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + struct group *gr; + gid_t id; + char *np; + + if (!*p) { + warnx("empty gid field"); + return (-1); + } + if (!isdigit(*p)) { + if (!(gr = getgrnam(p))) { + warnx("unknown group %s", p); + return (-1); + } + pw->pw_gid = gr->gr_gid; + return (0); + } + errno = 0; + id = strtoul(p, &np, 10); + if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) { + warnx("illegal gid"); + return (-1); + } + pw->pw_gid = id; + return (0); +} + +/* ARGSUSED */ +int +p_class(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + if (!(pw->pw_class = strdup(p))) { + warnx("can't save entry"); + return (-1); + } + + return (0); +} + +/* ARGSUSED */ +int +p_change(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + if (!atot(p, &pw->pw_change)) + return (0); + warnx("illegal date for change field"); + return (-1); +} + +/* ARGSUSED */ +int +p_expire(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + if (!atot(p, &pw->pw_expire)) + return (0); + warnx("illegal date for expire field"); + return (-1); +} + +/* ARGSUSED */ +int +p_gecos(char *p, struct passwd *pw __unused, ENTRY *ep) +{ + if (!(ep->save = strdup(p))) { + warnx("can't save entry"); + return (-1); + } + return (0); +} + +/* ARGSUSED */ +int +p_hdir(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + if (!*p) { + warnx("empty home directory field"); + return (-1); + } + if (!(pw->pw_dir = strdup(p))) { + warnx("can't save entry"); + return (-1); + } + return (0); +} + +/* ARGSUSED */ +int +p_shell(char *p, struct passwd *pw, ENTRY *ep __unused) +{ + struct stat sbuf; + + if (!*p) { + pw->pw_shell = strdup(_PATH_BSHELL); + return (0); + } + /* only admin can change from or to "restricted" shells */ + if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) { + warnx("%s: current shell non-standard", pw->pw_shell); + return (-1); + } + if (!ok_shell(p)) { + if (!master_mode) { + warnx("%s: non-standard shell", p); + return (-1); + } + pw->pw_shell = strdup(p); + } + else + pw->pw_shell = dup_shell(p); + if (!pw->pw_shell) { + warnx("can't save entry"); + return (-1); + } + if (stat(pw->pw_shell, &sbuf) < 0) { + if (errno == ENOENT) + warnx("WARNING: shell '%s' does not exist", + pw->pw_shell); + else + warn("WARNING: can't stat shell '%s'", pw->pw_shell); + return (0); + } + if (!S_ISREG(sbuf.st_mode)) { + warnx("WARNING: shell '%s' is not a regular file", + pw->pw_shell); + return (0); + } + if ((sbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) { + warnx("WARNING: shell '%s' is not executable", pw->pw_shell); + return (0); + } + return (0); +} diff --git a/chpass/table.c b/chpass/table.c new file mode 100644 index 0000000..19f1a99 --- /dev/null +++ b/chpass/table.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static const char sccsid[] = "@(#)table.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ +#endif +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <stddef.h> +#include "chpass.h" + +char e1[] = ": "; +char e2[] = ":,"; + +ENTRY list[] = { + { "login", p_login, 1, 5, e1, NULL }, + { "password", p_passwd, 1, 8, e1, NULL }, + { "uid", p_uid, 1, 3, e1, NULL }, + { "gid", p_gid, 1, 3, e1, NULL }, + { "class", p_class, 1, 5, e1, NULL }, + { "change", p_change, 1, 6, NULL, NULL }, + { "expire", p_expire, 1, 6, NULL, NULL }, +#ifdef RESTRICT_FULLNAME_CHANGE /* do not allow fullname changes */ + { "full name", p_gecos, 1, 9, e2, NULL }, +#else + { "full name", p_gecos, 0, 9, e2, NULL }, +#endif + { "office phone", p_gecos, 0, 12, e2, NULL }, + { "home phone", p_gecos, 0, 10, e2, NULL }, + { "office location", p_gecos, 0, 15, e2, NULL }, + { "other information", p_gecos, 0, 11, e1, NULL }, + { "home directory", p_hdir, 1, 14, e1, NULL }, + { "shell", p_shell, 0, 5, e1, NULL }, + { NULL, NULL, 0, 0, NULL, NULL }, +}; diff --git a/chpass/util.c b/chpass/util.c new file mode 100644 index 0000000..07d96e2 --- /dev/null +++ b/chpass/util.c @@ -0,0 +1,182 @@ +/*- + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2002 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * ThinkSec AS and NAI Labs, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)util.c 8.4 (Berkeley) 4/2/94"; +#endif +#endif /* not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "chpass.h" + +static const char *months[] = + { "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", + "December", NULL }; + +char * +ttoa(time_t tval) +{ + struct tm *tp; + static char tbuf[50]; + + if (tval) { + tp = localtime(&tval); + (void)sprintf(tbuf, "%s %d, %d", months[tp->tm_mon], + tp->tm_mday, tp->tm_year + 1900); + } + else + *tbuf = '\0'; + return (tbuf); +} + +int +atot(char *p, time_t *store) +{ + static struct tm *lt; + char *t; + const char **mp; + time_t tval; + int day, month, year; + + if (!*p) { + *store = 0; + return (0); + } + if (!lt) { + unsetenv("TZ"); + (void)time(&tval); + lt = localtime(&tval); + } + if (!(t = strtok(p, " \t"))) + goto bad; + if (isdigit(*t)) { + month = atoi(t); + } else { + for (mp = months;; ++mp) { + if (!*mp) + goto bad; + if (!strncasecmp(*mp, t, 3)) { + month = mp - months + 1; + break; + } + } + } + if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t)) + goto bad; + day = atoi(t); + if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t)) + goto bad; + year = atoi(t); + if (day < 1 || day > 31 || month < 1 || month > 12) + goto bad; + /* Allow two digit years 1969-2068 */ + if (year < 69) + year += 2000; + else if (year < 100) + year += 1900; + if (year < 1969) +bad: return (1); + lt->tm_year = year - 1900; + lt->tm_mon = month - 1; + lt->tm_mday = day; + lt->tm_hour = 0; + lt->tm_min = 0; + lt->tm_sec = 0; + lt->tm_isdst = -1; + if ((tval = mktime(lt)) < 0) + return (1); + *store = tval; + return (0); +} + +int +ok_shell(char *name) +{ + char *p, *sh; + + setusershell(); + while ((sh = getusershell())) { + if (!strcmp(name, sh)) { + endusershell(); + return (1); + } + /* allow just shell name, but use "real" path */ + if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) { + endusershell(); + return (1); + } + } + endusershell(); + return (0); +} + +char * +dup_shell(char *name) +{ + char *p, *sh, *ret; + + setusershell(); + while ((sh = getusershell())) { + if (!strcmp(name, sh)) { + endusershell(); + return (strdup(name)); + } + /* allow just shell name, but use "real" path */ + if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0) { + ret = strdup(sh); + endusershell(); + return (ret); + } + } + endusershell(); + return (NULL); +} |