]> git.saurik.com Git - apple/system_cmds.git/blame_incremental - chpass.tproj/field.c
system_cmds-805.200.21.tar.gz
[apple/system_cmds.git] / chpass.tproj / field.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1999-2016 Apple 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
66static 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 */
89int
90p_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 */
117int
118p_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 */
131int
132p_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 = (uid_t)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 */
158int
159p_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 = (gid_t)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 */
192int
193p_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 */
206int
207p_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 */
218int
219p_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 */
230int
231p_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 */
243int
244p_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 */
261int
262p_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#ifdef OPEN_DIRECTORY
321#include <uuid/uuid.h>
322/* ARGSUSED */
323int
324p_uuid(char *p, struct passwd *pw __unused, ENTRY *ep)
325{
326 uuid_t uu;
327 if (uuid_parse(p, uu) != 0) {
328 warnx("invalid UUID");
329 return (-1);
330 }
331 return (0);
332}
333
334void
335display_string(CFDictionaryRef attrs, CFStringRef attrName, const char* prompt, FILE *fp)
336{
337 CFTypeRef value = CFSTR("");
338 CFArrayRef values = CFDictionaryGetValue(attrs, attrName);
339 if (values) {
340 value = CFArrayGetCount(values) > 0 ? CFArrayGetValueAtIndex(values, 0) : NULL;
341 if (value && CFGetTypeID(value) != CFStringGetTypeID()) value = NULL;
342 }
343 cfprintf(fp, "%s: %@\n", prompt, value);
344}
345#endif /* OPEN_DIRECTORY */