1*49f3b098Slukem /* $NetBSD: field.c,v 1.12 2009/04/11 12:10:02 lukem Exp $ */
27659edadSglass
361f28255Scgd /*
47659edadSglass * Copyright (c) 1988, 1993, 1994
57659edadSglass * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
1589aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
325645d77bSlukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
347659edadSglass #if 0
357659edadSglass static char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94";
367659edadSglass #else
37*49f3b098Slukem __RCSID("$NetBSD: field.c,v 1.12 2009/04/11 12:10:02 lukem Exp $");
387659edadSglass #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd #include <sys/param.h>
427659edadSglass
4361f28255Scgd #include <ctype.h>
447659edadSglass #include <err.h>
457659edadSglass #include <errno.h>
467659edadSglass #include <grp.h>
477659edadSglass #include <pwd.h>
487659edadSglass #include <stdio.h>
497659edadSglass #include <stdlib.h>
507659edadSglass #include <string.h>
517659edadSglass #include <unistd.h>
527659edadSglass
5361f28255Scgd #include "chpass.h"
5461f28255Scgd #include "pathnames.h"
5561f28255Scgd
5661f28255Scgd /* ARGSUSED */
577659edadSglass int
p_login(const char * p,struct passwd * pw,ENTRY * ep)58971b39dfSxtraeme p_login(const char *p, struct passwd *pw, ENTRY *ep)
5961f28255Scgd {
60c9987f16Smrg
6161f28255Scgd if (!*p) {
627659edadSglass warnx("empty login field");
6361f28255Scgd return (1);
6461f28255Scgd }
6561f28255Scgd if (*p == '-') {
667659edadSglass warnx("login names may not begin with a hyphen");
6761f28255Scgd return (1);
6861f28255Scgd }
6961f28255Scgd if (!(pw->pw_name = strdup(p))) {
707659edadSglass warnx("can't save entry");
7161f28255Scgd return (1);
7261f28255Scgd }
737659edadSglass if (strchr(p, '.'))
747659edadSglass warnx("\'.\' is dangerous in a login name");
7561f28255Scgd for (; *p; ++p)
763145a29fSdsl if (isupper((unsigned char)*p)) {
777659edadSglass warnx("upper-case letters are dangerous in a login name");
7861f28255Scgd break;
7961f28255Scgd }
8061f28255Scgd return (0);
8161f28255Scgd }
8261f28255Scgd
8361f28255Scgd /* ARGSUSED */
847659edadSglass int
p_passwd(const char * p,struct passwd * pw,ENTRY * ep)85971b39dfSxtraeme p_passwd(const char *p, struct passwd *pw, ENTRY *ep)
8661f28255Scgd {
87c9987f16Smrg
88*49f3b098Slukem if (!(pw->pw_passwd = strdup(p))) {
897659edadSglass warnx("can't save password entry");
9061f28255Scgd return (1);
9161f28255Scgd }
9261f28255Scgd
9361f28255Scgd return (0);
9461f28255Scgd }
9561f28255Scgd
9661f28255Scgd /* ARGSUSED */
977659edadSglass int
p_uid(const char * p,struct passwd * pw,ENTRY * ep)98971b39dfSxtraeme p_uid(const char *p, struct passwd *pw, ENTRY *ep)
9961f28255Scgd {
1000330994fSsimonb unsigned long id;
1017659edadSglass char *np;
10261f28255Scgd
10361f28255Scgd if (!*p) {
1047659edadSglass warnx("empty uid field");
10561f28255Scgd return (1);
10661f28255Scgd }
1073145a29fSdsl if (!isdigit((unsigned char)*p)) {
1087659edadSglass warnx("illegal uid");
10961f28255Scgd return (1);
11061f28255Scgd }
1117659edadSglass errno = 0;
1127659edadSglass id = strtoul(p, &np, 10);
1130330994fSsimonb /*
1140330994fSsimonb * We don't need to check the return value of strtoul()
1150330994fSsimonb * since ULONG_MAX is greater than UID_MAX.
1160330994fSsimonb */
1170330994fSsimonb if (*np || id > UID_MAX) {
1187659edadSglass warnx("illegal uid");
11961f28255Scgd return (1);
12061f28255Scgd }
1210330994fSsimonb pw->pw_uid = (uid_t)id;
12261f28255Scgd return (0);
12361f28255Scgd }
12461f28255Scgd
12561f28255Scgd /* ARGSUSED */
1267659edadSglass int
p_gid(const char * p,struct passwd * pw,ENTRY * ep)127971b39dfSxtraeme p_gid(const char *p, struct passwd *pw, ENTRY *ep)
12861f28255Scgd {
12961f28255Scgd struct group *gr;
1300330994fSsimonb unsigned long id;
1317659edadSglass char *np;
13261f28255Scgd
13361f28255Scgd if (!*p) {
1347659edadSglass warnx("empty gid field");
13561f28255Scgd return (1);
13661f28255Scgd }
1373145a29fSdsl if (!isdigit((unsigned char)*p)) {
13861f28255Scgd if (!(gr = getgrnam(p))) {
1397659edadSglass warnx("unknown group %s", p);
14061f28255Scgd return (1);
14161f28255Scgd }
14261f28255Scgd pw->pw_gid = gr->gr_gid;
14361f28255Scgd return (0);
14461f28255Scgd }
1457659edadSglass errno = 0;
1467659edadSglass id = strtoul(p, &np, 10);
1470330994fSsimonb /*
1480330994fSsimonb * We don't need to check the return value of strtoul()
1490330994fSsimonb * since ULONG_MAX is greater than GID_MAX.
1500330994fSsimonb */
1510330994fSsimonb if (*np || id > GID_MAX) {
1527659edadSglass warnx("illegal gid");
15361f28255Scgd return (1);
15461f28255Scgd }
1550330994fSsimonb pw->pw_gid = (gid_t)id;
15661f28255Scgd return (0);
15761f28255Scgd }
15861f28255Scgd
15961f28255Scgd /* ARGSUSED */
1607659edadSglass int
p_class(const char * p,struct passwd * pw,ENTRY * ep)161971b39dfSxtraeme p_class(const char *p, struct passwd *pw, ENTRY *ep)
16261f28255Scgd {
163c9987f16Smrg
164*49f3b098Slukem if (!(pw->pw_class = strdup(p))) {
1657659edadSglass warnx("can't save entry");
16661f28255Scgd return (1);
16761f28255Scgd }
16861f28255Scgd
16961f28255Scgd return (0);
17061f28255Scgd }
17161f28255Scgd
17261f28255Scgd /* ARGSUSED */
1737659edadSglass int
p_change(const char * p,struct passwd * pw,ENTRY * ep)174971b39dfSxtraeme p_change(const char *p, struct passwd *pw, ENTRY *ep)
17561f28255Scgd {
176c9987f16Smrg
17761f28255Scgd if (!atot(p, &pw->pw_change))
17861f28255Scgd return (0);
1797659edadSglass warnx("illegal date for change field");
18061f28255Scgd return (1);
18161f28255Scgd }
18261f28255Scgd
18361f28255Scgd /* ARGSUSED */
1847659edadSglass int
p_expire(const char * p,struct passwd * pw,ENTRY * ep)185971b39dfSxtraeme p_expire(const char *p, struct passwd *pw, ENTRY *ep)
18661f28255Scgd {
187c9987f16Smrg
18861f28255Scgd if (!atot(p, &pw->pw_expire))
18961f28255Scgd return (0);
1907659edadSglass warnx("illegal date for expire field");
19161f28255Scgd return (1);
19261f28255Scgd }
19361f28255Scgd
19461f28255Scgd /* ARGSUSED */
1957659edadSglass int
p_gecos(const char * p,struct passwd * pw,ENTRY * ep)196971b39dfSxtraeme p_gecos(const char *p, struct passwd *pw, ENTRY *ep)
19761f28255Scgd {
198c9987f16Smrg
1991e454491Skim if (!(ep->save = strdup(p))) {
2007659edadSglass warnx("can't save entry");
20161f28255Scgd return (1);
20261f28255Scgd }
20361f28255Scgd return (0);
20461f28255Scgd }
20561f28255Scgd
20661f28255Scgd /* ARGSUSED */
2077659edadSglass int
p_hdir(const char * p,struct passwd * pw,ENTRY * ep)208971b39dfSxtraeme p_hdir(const char *p, struct passwd *pw, ENTRY *ep)
20961f28255Scgd {
210c9987f16Smrg
21161f28255Scgd if (!*p) {
2127659edadSglass warnx("empty home directory field");
21361f28255Scgd return (1);
21461f28255Scgd }
21561f28255Scgd if (!(pw->pw_dir = strdup(p))) {
2167659edadSglass warnx("can't save entry");
21761f28255Scgd return (1);
21861f28255Scgd }
21961f28255Scgd return (0);
22061f28255Scgd }
22161f28255Scgd
22261f28255Scgd /* ARGSUSED */
2237659edadSglass int
p_shell(const char * p,struct passwd * pw,ENTRY * ep)224971b39dfSxtraeme p_shell(const char *p, struct passwd *pw, ENTRY *ep)
22561f28255Scgd {
2260db548a9Smycroft const char *t;
22761f28255Scgd
22861f28255Scgd if (!*p) {
229*49f3b098Slukem if (!(pw->pw_shell = strdup(_PATH_BSHELL))) {
230*49f3b098Slukem warnx("can't save entry");
231*49f3b098Slukem return (1);
232*49f3b098Slukem }
23361f28255Scgd return (0);
23461f28255Scgd }
23561f28255Scgd /* only admin can change from or to "restricted" shells */
23661f28255Scgd if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
2377659edadSglass warnx("%s: current shell non-standard", pw->pw_shell);
23861f28255Scgd return (1);
23961f28255Scgd }
24061f28255Scgd if (!(t = ok_shell(p))) {
24161f28255Scgd if (uid) {
2427659edadSglass warnx("%s: non-standard shell", p);
24361f28255Scgd return (1);
24461f28255Scgd }
24561f28255Scgd }
24661f28255Scgd else
24761f28255Scgd p = t;
24861f28255Scgd if (!(pw->pw_shell = strdup(p))) {
2497659edadSglass warnx("can't save entry");
25061f28255Scgd return (1);
25161f28255Scgd }
25261f28255Scgd return (0);
25361f28255Scgd }
254