xref: /original-bsd/usr.bin/chpass/field.c (revision e58c8952)
1 /*
2  * Copyright (c) 1988, 1993, 1994
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)field.c	8.4 (Berkeley) 04/02/94";
10 #endif /* not lint */
11 
12 #include <sys/param.h>
13 
14 #include <ctype.h>
15 #include <err.h>
16 #include <errno.h>
17 #include <grp.h>
18 #include <pwd.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 
24 #include "chpass.h"
25 #include "pathnames.h"
26 
27 /* ARGSUSED */
28 int
29 p_login(p, pw, ep)
30 	char *p;
31 	struct passwd *pw;
32 	ENTRY *ep;
33 {
34 	if (!*p) {
35 		warnx("empty login field");
36 		return (1);
37 	}
38 	if (*p == '-') {
39 		warnx("login names may not begin with a hyphen");
40 		return (1);
41 	}
42 	if (!(pw->pw_name = strdup(p))) {
43 		warnx("can't save entry");
44 		return (1);
45 	}
46 	if (strchr(p, '.'))
47 		warnx("\'.\' is dangerous in a login name");
48 	for (; *p; ++p)
49 		if (isupper(*p)) {
50 			warnx("upper-case letters are dangerous in a login name");
51 			break;
52 		}
53 	return (0);
54 }
55 
56 /* ARGSUSED */
57 int
58 p_passwd(p, pw, ep)
59 	char *p;
60 	struct passwd *pw;
61 	ENTRY *ep;
62 {
63 	if (!*p)
64 		pw->pw_passwd = "";	/* "NOLOGIN"; */
65 	else if (!(pw->pw_passwd = strdup(p))) {
66 		warnx("can't save password entry");
67 		return (1);
68 	}
69 
70 	return (0);
71 }
72 
73 /* ARGSUSED */
74 int
75 p_uid(p, pw, ep)
76 	char *p;
77 	struct passwd *pw;
78 	ENTRY *ep;
79 {
80 	uid_t id;
81 	char *np;
82 
83 	if (!*p) {
84 		warnx("empty uid field");
85 		return (1);
86 	}
87 	if (!isdigit(*p)) {
88 		warnx("illegal uid");
89 		return (1);
90 	}
91 	errno = 0;
92 	id = strtoul(p, &np, 10);
93 	if (*np || (id == ULONG_MAX && errno == ERANGE)) {
94 		warnx("illegal uid");
95 		return (1);
96 	}
97 	pw->pw_uid = id;
98 	return (0);
99 }
100 
101 /* ARGSUSED */
102 int
103 p_gid(p, pw, ep)
104 	char *p;
105 	struct passwd *pw;
106 	ENTRY *ep;
107 {
108 	struct group *gr;
109 	gid_t id;
110 	char *np;
111 
112 	if (!*p) {
113 		warnx("empty gid field");
114 		return (1);
115 	}
116 	if (!isdigit(*p)) {
117 		if (!(gr = getgrnam(p))) {
118 			warnx("unknown group %s", p);
119 			return (1);
120 		}
121 		pw->pw_gid = gr->gr_gid;
122 		return (0);
123 	}
124 	errno = 0;
125 	id = strtoul(p, &np, 10);
126 	if (*np || (id == ULONG_MAX && errno == ERANGE)) {
127 		warnx("illegal gid");
128 		return (1);
129 	}
130 	pw->pw_gid = id;
131 	return (0);
132 }
133 
134 /* ARGSUSED */
135 int
136 p_class(p, pw, ep)
137 	char *p;
138 	struct passwd *pw;
139 	ENTRY *ep;
140 {
141 	if (!*p)
142 		pw->pw_class = "";
143 	else if (!(pw->pw_class = strdup(p))) {
144 		warnx("can't save entry");
145 		return (1);
146 	}
147 
148 	return (0);
149 }
150 
151 /* ARGSUSED */
152 int
153 p_change(p, pw, ep)
154 	char *p;
155 	struct passwd *pw;
156 	ENTRY *ep;
157 {
158 	if (!atot(p, &pw->pw_change))
159 		return (0);
160 	warnx("illegal date for change field");
161 	return (1);
162 }
163 
164 /* ARGSUSED */
165 int
166 p_expire(p, pw, ep)
167 	char *p;
168 	struct passwd *pw;
169 	ENTRY *ep;
170 {
171 	if (!atot(p, &pw->pw_expire))
172 		return (0);
173 	warnx("illegal date for expire field");
174 	return (1);
175 }
176 
177 /* ARGSUSED */
178 int
179 p_gecos(p, pw, ep)
180 	char *p;
181 	struct passwd *pw;
182 	ENTRY *ep;
183 {
184 	if (!*p)
185 		ep->save = "";
186 	else if (!(ep->save = strdup(p))) {
187 		warnx("can't save entry");
188 		return (1);
189 	}
190 	return (0);
191 }
192 
193 /* ARGSUSED */
194 int
195 p_hdir(p, pw, ep)
196 	char *p;
197 	struct passwd *pw;
198 	ENTRY *ep;
199 {
200 	if (!*p) {
201 		warnx("empty home directory field");
202 		return (1);
203 	}
204 	if (!(pw->pw_dir = strdup(p))) {
205 		warnx("can't save entry");
206 		return (1);
207 	}
208 	return (0);
209 }
210 
211 /* ARGSUSED */
212 int
213 p_shell(p, pw, ep)
214 	char *p;
215 	struct passwd *pw;
216 	ENTRY *ep;
217 {
218 	char *t, *ok_shell();
219 
220 	if (!*p) {
221 		pw->pw_shell = _PATH_BSHELL;
222 		return (0);
223 	}
224 	/* only admin can change from or to "restricted" shells */
225 	if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
226 		warnx("%s: current shell non-standard", pw->pw_shell);
227 		return (1);
228 	}
229 	if (!(t = ok_shell(p))) {
230 		if (uid) {
231 			warnx("%s: non-standard shell", p);
232 			return (1);
233 		}
234 	}
235 	else
236 		p = t;
237 	if (!(pw->pw_shell = strdup(p))) {
238 		warnx("can't save entry");
239 		return (1);
240 	}
241 	return (0);
242 }
243