xref: /netbsd-src/usr.bin/chpass/field.c (revision 49f3b098c61c7b07c5a89450fac2960c6db6a30a)
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