xref: /netbsd-src/usr.bin/chpass/field.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
1 /*	$NetBSD: field.c,v 1.3 1995/03/26 04:55:28 glass 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 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)field.c	8.4 (Berkeley) 4/2/94";
39 #else
40 static char rcsid[] = "$NetBSD: field.c,v 1.3 1995/03/26 04:55:28 glass Exp $";
41 #endif
42 #endif /* not lint */
43 
44 #include <sys/param.h>
45 
46 #include <ctype.h>
47 #include <err.h>
48 #include <errno.h>
49 #include <grp.h>
50 #include <pwd.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 
56 #include "chpass.h"
57 #include "pathnames.h"
58 
59 /* ARGSUSED */
60 int
61 p_login(p, pw, ep)
62 	char *p;
63 	struct passwd *pw;
64 	ENTRY *ep;
65 {
66 	if (!*p) {
67 		warnx("empty login field");
68 		return (1);
69 	}
70 	if (*p == '-') {
71 		warnx("login names may not begin with a hyphen");
72 		return (1);
73 	}
74 	if (!(pw->pw_name = strdup(p))) {
75 		warnx("can't save entry");
76 		return (1);
77 	}
78 	if (strchr(p, '.'))
79 		warnx("\'.\' is dangerous in a login name");
80 	for (; *p; ++p)
81 		if (isupper(*p)) {
82 			warnx("upper-case letters are dangerous in a login name");
83 			break;
84 		}
85 	return (0);
86 }
87 
88 /* ARGSUSED */
89 int
90 p_passwd(p, pw, ep)
91 	char *p;
92 	struct passwd *pw;
93 	ENTRY *ep;
94 {
95 	if (!*p)
96 		pw->pw_passwd = "";	/* "NOLOGIN"; */
97 	else if (!(pw->pw_passwd = strdup(p))) {
98 		warnx("can't save password entry");
99 		return (1);
100 	}
101 
102 	return (0);
103 }
104 
105 /* ARGSUSED */
106 int
107 p_uid(p, pw, ep)
108 	char *p;
109 	struct passwd *pw;
110 	ENTRY *ep;
111 {
112 	uid_t id;
113 	char *np;
114 
115 	if (!*p) {
116 		warnx("empty uid field");
117 		return (1);
118 	}
119 	if (!isdigit(*p)) {
120 		warnx("illegal uid");
121 		return (1);
122 	}
123 	errno = 0;
124 	id = strtoul(p, &np, 10);
125 	if (*np || (id == ULONG_MAX && errno == ERANGE)) {
126 		warnx("illegal uid");
127 		return (1);
128 	}
129 	pw->pw_uid = id;
130 	return (0);
131 }
132 
133 /* ARGSUSED */
134 int
135 p_gid(p, pw, ep)
136 	char *p;
137 	struct passwd *pw;
138 	ENTRY *ep;
139 {
140 	struct group *gr;
141 	gid_t id;
142 	char *np;
143 
144 	if (!*p) {
145 		warnx("empty gid field");
146 		return (1);
147 	}
148 	if (!isdigit(*p)) {
149 		if (!(gr = getgrnam(p))) {
150 			warnx("unknown group %s", p);
151 			return (1);
152 		}
153 		pw->pw_gid = gr->gr_gid;
154 		return (0);
155 	}
156 	errno = 0;
157 	id = strtoul(p, &np, 10);
158 	if (*np || (id == ULONG_MAX && errno == ERANGE)) {
159 		warnx("illegal gid");
160 		return (1);
161 	}
162 	pw->pw_gid = id;
163 	return (0);
164 }
165 
166 /* ARGSUSED */
167 int
168 p_class(p, pw, ep)
169 	char *p;
170 	struct passwd *pw;
171 	ENTRY *ep;
172 {
173 	if (!*p)
174 		pw->pw_class = "";
175 	else if (!(pw->pw_class = strdup(p))) {
176 		warnx("can't save entry");
177 		return (1);
178 	}
179 
180 	return (0);
181 }
182 
183 /* ARGSUSED */
184 int
185 p_change(p, pw, ep)
186 	char *p;
187 	struct passwd *pw;
188 	ENTRY *ep;
189 {
190 	if (!atot(p, &pw->pw_change))
191 		return (0);
192 	warnx("illegal date for change field");
193 	return (1);
194 }
195 
196 /* ARGSUSED */
197 int
198 p_expire(p, pw, ep)
199 	char *p;
200 	struct passwd *pw;
201 	ENTRY *ep;
202 {
203 	if (!atot(p, &pw->pw_expire))
204 		return (0);
205 	warnx("illegal date for expire field");
206 	return (1);
207 }
208 
209 /* ARGSUSED */
210 int
211 p_gecos(p, pw, ep)
212 	char *p;
213 	struct passwd *pw;
214 	ENTRY *ep;
215 {
216 	if (!*p)
217 		ep->save = "";
218 	else if (!(ep->save = strdup(p))) {
219 		warnx("can't save entry");
220 		return (1);
221 	}
222 	return (0);
223 }
224 
225 /* ARGSUSED */
226 int
227 p_hdir(p, pw, ep)
228 	char *p;
229 	struct passwd *pw;
230 	ENTRY *ep;
231 {
232 	if (!*p) {
233 		warnx("empty home directory field");
234 		return (1);
235 	}
236 	if (!(pw->pw_dir = strdup(p))) {
237 		warnx("can't save entry");
238 		return (1);
239 	}
240 	return (0);
241 }
242 
243 /* ARGSUSED */
244 int
245 p_shell(p, pw, ep)
246 	char *p;
247 	struct passwd *pw;
248 	ENTRY *ep;
249 {
250 	char *t, *ok_shell();
251 
252 	if (!*p) {
253 		pw->pw_shell = _PATH_BSHELL;
254 		return (0);
255 	}
256 	/* only admin can change from or to "restricted" shells */
257 	if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
258 		warnx("%s: current shell non-standard", pw->pw_shell);
259 		return (1);
260 	}
261 	if (!(t = ok_shell(p))) {
262 		if (uid) {
263 			warnx("%s: non-standard shell", p);
264 			return (1);
265 		}
266 	}
267 	else
268 		p = t;
269 	if (!(pw->pw_shell = strdup(p))) {
270 		warnx("can't save entry");
271 		return (1);
272 	}
273 	return (0);
274 }
275