]> git.saurik.com Git - apple/system_cmds.git/blob - chpass.tproj/field.c
system_cmds-541.tar.gz
[apple/system_cmds.git] / chpass.tproj / field.c
1 /*
2 * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * Copyright (c) 1988, 1993, 1994
25 * The Regents of the University of California. All rights reserved.
26 * Copyright (c) 2002 Networks Associates Technology, Inc.
27 * All rights reserved.
28 *
29 * Portions of this software were developed for the FreeBSD Project by
30 * ThinkSec AS and NAI Labs, the Security Research Division of Network
31 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
32 * ("CBOSS"), as part of the DARPA CHATS research program.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 * must display the following acknowledgement:
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
46 * 4. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 */
62
63 #if 0
64 #if 0
65 #ifndef lint
66 static char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94";
67 #endif /* not lint */
68 #endif
69
70 #include <sys/cdefs.h>
71 __FBSDID("$FreeBSD: src/usr.bin/chpass/field.c,v 1.9 2004/01/18 21:46:39 charnier Exp $");
72 #endif
73
74 #include <sys/param.h>
75 #include <sys/stat.h>
76
77 #include <ctype.h>
78 #include <err.h>
79 #include <errno.h>
80 #include <grp.h>
81 #include <paths.h>
82 #include <pwd.h>
83 #include <stdlib.h>
84 #include <string.h>
85
86 #include "chpass.h"
87
88 /* ARGSUSED */
89 int
90 p_login(char *p, struct passwd *pw, ENTRY *ep __unused)
91 {
92 if (!*p) {
93 warnx("empty login field");
94 return (-1);
95 }
96 if (*p == '-') {
97 warnx("login names may not begin with a hyphen");
98 return (-1);
99 }
100 #ifndef OPEN_DIRECTORY
101 if (!(pw->pw_name = strdup(p))) {
102 warnx("can't save entry");
103 return (-1);
104 }
105 #endif
106 if (strchr(p, '.'))
107 warnx("\'.\' is dangerous in a login name");
108 for (; *p; ++p)
109 if (isupper(*p)) {
110 warnx("upper-case letters are dangerous in a login name");
111 break;
112 }
113 return (0);
114 }
115
116 /* ARGSUSED */
117 int
118 p_passwd(char *p, struct passwd *pw, ENTRY *ep __unused)
119 {
120 #ifndef OPEN_DIRECTORY
121 if (!(pw->pw_passwd = strdup(p))) {
122 warnx("can't save password entry");
123 return (-1);
124 }
125 #endif
126
127 return (0);
128 }
129
130 /* ARGSUSED */
131 int
132 p_uid(char *p, struct passwd *pw, ENTRY *ep __unused)
133 {
134 uid_t id;
135 char *np;
136
137 if (!*p) {
138 warnx("empty uid field");
139 return (-1);
140 }
141 if (!isdigit(*p)) {
142 warnx("illegal uid");
143 return (-1);
144 }
145 errno = 0;
146 id = strtoul(p, &np, 10);
147 if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
148 warnx("illegal uid");
149 return (-1);
150 }
151 #ifndef OPEN_DIRECTORY
152 pw->pw_uid = id;
153 #endif
154 return (0);
155 }
156
157 /* ARGSUSED */
158 int
159 p_gid(char *p, struct passwd *pw, ENTRY *ep __unused)
160 {
161 struct group *gr;
162 gid_t id;
163 char *np;
164
165 if (!*p) {
166 warnx("empty gid field");
167 return (-1);
168 }
169 if (!isdigit(*p)) {
170 if (!(gr = getgrnam(p))) {
171 warnx("unknown group %s", p);
172 return (-1);
173 }
174 #ifndef OPEN_DIRECTORY
175 pw->pw_gid = gr->gr_gid;
176 #endif
177 return (0);
178 }
179 errno = 0;
180 id = strtoul(p, &np, 10);
181 if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
182 warnx("illegal gid");
183 return (-1);
184 }
185 #ifndef OPEN_DIRECTORY
186 pw->pw_gid = id;
187 #endif
188 return (0);
189 }
190
191 /* ARGSUSED */
192 int
193 p_class(char *p, struct passwd *pw, ENTRY *ep __unused)
194 {
195 #ifndef OPEN_DIRECTORY
196 if (!(pw->pw_class = strdup(p))) {
197 warnx("can't save entry");
198 return (-1);
199 }
200 #endif
201
202 return (0);
203 }
204
205 /* ARGSUSED */
206 int
207 p_change(char *p, struct passwd *pw, ENTRY *ep __unused)
208 {
209 #ifndef OPEN_DIRECTORY
210 if (!atot(p, &pw->pw_change))
211 return (0);
212 warnx("illegal date for change field");
213 #endif
214 return (-1);
215 }
216
217 /* ARGSUSED */
218 int
219 p_expire(char *p, struct passwd *pw, ENTRY *ep __unused)
220 {
221 #ifndef OPEN_DIRECTORY
222 if (!atot(p, &pw->pw_expire))
223 return (0);
224 warnx("illegal date for expire field");
225 #endif
226 return (-1);
227 }
228
229 /* ARGSUSED */
230 int
231 p_gecos(char *p, struct passwd *pw __unused, ENTRY *ep)
232 {
233 #ifndef OPEN_DIRECTORY
234 if (!(ep->save = strdup(p))) {
235 warnx("can't save entry");
236 return (-1);
237 }
238 #endif
239 return (0);
240 }
241
242 /* ARGSUSED */
243 int
244 p_hdir(char *p, struct passwd *pw, ENTRY *ep __unused)
245 {
246 if (!*p) {
247 warnx("empty home directory field");
248 return (-1);
249 }
250 #ifndef OPEN_DIRECTORY
251 if (!(pw->pw_dir = strdup(p))) {
252 warnx("can't save entry");
253 return (-1);
254 }
255 #endif
256 return (0);
257 }
258
259
260 /* ARGSUSED */
261 int
262 p_shell(char *p, struct passwd *pw, ENTRY *ep __unused)
263 {
264 struct stat sbuf;
265 #ifdef OPEN_DIRECTORY
266 struct passwd lpw;
267 pw = &lpw;
268 memset(pw, 0, sizeof(lpw));
269 pw->pw_shell = p;
270 #endif
271
272 #ifndef OPEN_DIRECTORY
273 if (!*p) {
274 pw->pw_shell = strdup(_PATH_BSHELL);
275 return (0);
276 }
277 /* only admin can change from or to "restricted" shells */
278 if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) {
279 warnx("%s: current shell non-standard", pw->pw_shell);
280 return (-1);
281 }
282 #endif /* !OPEN_DIRECTORY */
283 if (!ok_shell(p)) {
284 if (!master_mode) {
285 warnx("%s: non-standard shell", p);
286 return (-1);
287 }
288 #ifndef OPEN_DIRECTORY
289 pw->pw_shell = strdup(p);
290 #endif
291 }
292 #ifndef OPEN_DIRECTORY
293 else
294 pw->pw_shell = dup_shell(p);
295 if (!pw->pw_shell) {
296 warnx("can't save entry");
297 return (-1);
298 }
299 #endif
300 if (stat(pw->pw_shell, &sbuf) < 0) {
301 if (errno == ENOENT)
302 warnx("WARNING: shell '%s' does not exist",
303 pw->pw_shell);
304 else
305 warn("WARNING: can't stat shell '%s'", pw->pw_shell);
306 return (0);
307 }
308 if (!S_ISREG(sbuf.st_mode)) {
309 warnx("WARNING: shell '%s' is not a regular file",
310 pw->pw_shell);
311 return (0);
312 }
313 if ((sbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) {
314 warnx("WARNING: shell '%s' is not executable", pw->pw_shell);
315 return (0);
316 }
317 return (0);
318 }
319
320
321 #ifdef OPEN_DIRECTORY
322 #include <uuid/uuid.h>
323 /* ARGSUSED */
324 int
325 p_uuid(char *p, struct passwd *pw __unused, ENTRY *ep)
326 {
327 uuid_t uu;
328 if (uuid_parse(p, uu) != 0) {
329 warnx("invalid UUID");
330 return (-1);
331 }
332 return (0);
333 }
334
335 void
336 display_string(CFDictionaryRef attrs, CFStringRef attrName, const char* prompt, FILE *fp)
337 {
338 CFTypeRef value = CFSTR("");
339 CFArrayRef values = CFDictionaryGetValue(attrs, attrName);
340 if (values) {
341 value = CFArrayGetCount(values) > 0 ? CFArrayGetValueAtIndex(values, 0) : NULL;
342 if (value && CFGetTypeID(value) != CFStringGetTypeID()) value = NULL;
343 }
344 cfprintf(fp, "%s: %@\n", prompt, value);
345 }
346 #endif /* OPEN_DIRECTORY */