xref: /netbsd-src/usr.bin/chpass/field.c (revision 1ca5c1b28139779176bd5c13ad7c5f25c0bcd5f8)
1 /*	$NetBSD: field.c,v 1.7 1998/08/10 23:21:05 kim Exp $	*/
2 
3 /*
4  * Copyright (c) 1988, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)field.c	8.4 (Berkeley) 4/2/94";
40 #else
41 __RCSID("$NetBSD: field.c,v 1.7 1998/08/10 23:21:05 kim Exp $");
42 #endif
43 #endif /* not lint */
44 
45 #include <sys/param.h>
46 
47 #include <ctype.h>
48 #include <err.h>
49 #include <errno.h>
50 #include <grp.h>
51 #include <pwd.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56 
57 #include "chpass.h"
58 #include "pathnames.h"
59 
60 /* ARGSUSED */
61 int
62 p_login(p, pw, ep)
63 	const char *p;
64 	struct passwd *pw;
65 	ENTRY *ep;
66 {
67 
68 	if (!*p) {
69 		warnx("empty login field");
70 		return (1);
71 	}
72 	if (*p == '-') {
73 		warnx("login names may not begin with a hyphen");
74 		return (1);
75 	}
76 	if (!(pw->pw_name = strdup(p))) {
77 		warnx("can't save entry");
78 		return (1);
79 	}
80 	if (strchr(p, '.'))
81 		warnx("\'.\' is dangerous in a login name");
82 	for (; *p; ++p)
83 		if (isupper(*p)) {
84 			warnx("upper-case letters are dangerous in a login name");
85 			break;
86 		}
87 	return (0);
88 }
89 
90 /* ARGSUSED */
91 int
92 p_passwd(p, pw, ep)
93 	const char *p;
94 	struct passwd *pw;
95 	ENTRY *ep;
96 {
97 
98 	if (!*p)
99 		pw->pw_passwd = "";	/* "NOLOGIN"; */
100 	else if (!(pw->pw_passwd = strdup(p))) {
101 		warnx("can't save password entry");
102 		return (1);
103 	}
104 
105 	return (0);
106 }
107 
108 /* ARGSUSED */
109 int
110 p_uid(p, pw, ep)
111 	const char *p;
112 	struct passwd *pw;
113 	ENTRY *ep;
114 {
115 	uid_t id;
116 	char *np;
117 
118 	if (!*p) {
119 		warnx("empty uid field");
120 		return (1);
121 	}
122 	if (!isdigit(*p)) {
123 		warnx("illegal uid");
124 		return (1);
125 	}
126 	errno = 0;
127 	id = strtoul(p, &np, 10);
128 	if (*np || (id == ULONG_MAX && errno == ERANGE)) {
129 		warnx("illegal uid");
130 		return (1);
131 	}
132 	pw->pw_uid = id;
133 	return (0);
134 }
135 
136 /* ARGSUSED */
137 int
138 p_gid(p, pw, ep)
139 	const char *p;
140 	struct passwd *pw;
141 	ENTRY *ep;
142 {
143 	struct group *gr;
144 	gid_t id;
145 	char *np;
146 
147 	if (!*p) {
148 		warnx("empty gid field");
149 		return (1);
150 	}
151 	if (!isdigit(*p)) {
152 		if (!(gr = getgrnam(p))) {
153 			warnx("unknown group %s", p);
154 			return (1);
155 		}
156 		pw->pw_gid = gr->gr_gid;
157 		return (0);
158 	}
159 	errno = 0;
160 	id = strtoul(p, &np, 10);
161 	if (*np || (id == ULONG_MAX && errno == ERANGE)) {
162 		warnx("illegal gid");
163 		return (1);
164 	}
165 	pw->pw_gid = id;
166 	return (0);
167 }
168 
169 /* ARGSUSED */
170 int
171 p_class(p, pw, ep)
172 	const char *p;
173 	struct passwd *pw;
174 	ENTRY *ep;
175 {
176 
177 	if (!*p)
178 		pw->pw_class = "";
179 	else if (!(pw->pw_class = strdup(p))) {
180 		warnx("can't save entry");
181 		return (1);
182 	}
183 
184 	return (0);
185 }
186 
187 /* ARGSUSED */
188 int
189 p_change(p, pw, ep)
190 	const char *p;
191 	struct passwd *pw;
192 	ENTRY *ep;
193 {
194 
195 	if (!atot(p, &pw->pw_change))
196 		return (0);
197 	warnx("illegal date for change field");
198 	return (1);
199 }
200 
201 /* ARGSUSED */
202 int
203 p_expire(p, pw, ep)
204 	const char *p;
205 	struct passwd *pw;
206 	ENTRY *ep;
207 {
208 
209 	if (!atot(p, &pw->pw_expire))
210 		return (0);
211 	warnx("illegal date for expire field");
212 	return (1);
213 }
214 
215 /* ARGSUSED */
216 int
217 p_gecos(p, pw, ep)
218 	const char *p;
219 	struct passwd *pw;
220 	ENTRY *ep;
221 {
222 
223 	if (!(ep->save = strdup(p))) {
224 		warnx("can't save entry");
225 		return (1);
226 	}
227 	return (0);
228 }
229 
230 /* ARGSUSED */
231 int
232 p_hdir(p, pw, ep)
233 	const char *p;
234 	struct passwd *pw;
235 	ENTRY *ep;
236 {
237 
238 	if (!*p) {
239 		warnx("empty home directory field");
240 		return (1);
241 	}
242 	if (!(pw->pw_dir = strdup(p))) {
243 		warnx("can't save entry");
244 		return (1);
245 	}
246 	return (0);
247 }
248 
249 /* ARGSUSED */
250 int
251 p_shell(p, pw, ep)
252 	const char *p;
253 	struct passwd *pw;
254 	ENTRY *ep;
255 {
256 	const char *t;
257 
258 	if (!*p) {
259 		pw->pw_shell = _PATH_BSHELL;
260 		return (0);
261 	}
262 	/* only admin can change from or to "restricted" shells */
263 	if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
264 		warnx("%s: current shell non-standard", pw->pw_shell);
265 		return (1);
266 	}
267 	if (!(t = ok_shell(p))) {
268 		if (uid) {
269 			warnx("%s: non-standard shell", p);
270 			return (1);
271 		}
272 	}
273 	else
274 		p = t;
275 	if (!(pw->pw_shell = strdup(p))) {
276 		warnx("can't save entry");
277 		return (1);
278 	}
279 	return (0);
280 }
281