]> git.saurik.com Git - apple/system_cmds.git/blame - chpass.tproj/field.c
system_cmds-805.200.21.tar.gz
[apple/system_cmds.git] / chpass.tproj / field.c
CommitLineData
1815bff5 1/*
cf37c299 2 * Copyright (c) 1999-2016 Apple Inc. All rights reserved.
1815bff5
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
cf37c299 5 *
34d340d7
A
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.
cf37c299 12 *
1815bff5
A
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,
34d340d7
A
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.
cf37c299 20 *
1815bff5
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * Copyright (c) 1988, 1993, 1994
34d340d7
A
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.
1815bff5
A
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:
34d340d7
A
44 * This product includes software developed by the University of
45 * California, Berkeley and its contributors.
1815bff5
A
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
34d340d7
A
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
1815bff5 74#include <sys/param.h>
34d340d7 75#include <sys/stat.h>
1815bff5
A
76
77#include <ctype.h>
78#include <err.h>
79#include <errno.h>
80#include <grp.h>
34d340d7 81#include <paths.h>
1815bff5 82#include <pwd.h>
1815bff5
A
83#include <stdlib.h>
84#include <string.h>
1815bff5
A
85
86#include "chpass.h"
1815bff5
A
87
88/* ARGSUSED */
89int
34d340d7 90p_login(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5
A
91{
92 if (!*p) {
93 warnx("empty login field");
34d340d7 94 return (-1);
1815bff5
A
95 }
96 if (*p == '-') {
97 warnx("login names may not begin with a hyphen");
34d340d7 98 return (-1);
1815bff5 99 }
34d340d7 100#ifndef OPEN_DIRECTORY
1815bff5
A
101 if (!(pw->pw_name = strdup(p))) {
102 warnx("can't save entry");
34d340d7 103 return (-1);
1815bff5 104 }
34d340d7 105#endif
1815bff5
A
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
34d340d7 118p_passwd(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5 119{
34d340d7
A
120#ifndef OPEN_DIRECTORY
121 if (!(pw->pw_passwd = strdup(p))) {
1815bff5 122 warnx("can't save password entry");
34d340d7 123 return (-1);
1815bff5 124 }
34d340d7
A
125#endif
126
1815bff5
A
127 return (0);
128}
129
130/* ARGSUSED */
131int
34d340d7 132p_uid(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5
A
133{
134 uid_t id;
135 char *np;
136
137 if (!*p) {
138 warnx("empty uid field");
34d340d7 139 return (-1);
1815bff5
A
140 }
141 if (!isdigit(*p)) {
142 warnx("illegal uid");
34d340d7 143 return (-1);
1815bff5
A
144 }
145 errno = 0;
cf37c299 146 id = (uid_t)strtoul(p, &np, 10);
34d340d7 147 if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
1815bff5 148 warnx("illegal uid");
34d340d7 149 return (-1);
1815bff5 150 }
34d340d7 151#ifndef OPEN_DIRECTORY
1815bff5 152 pw->pw_uid = id;
34d340d7 153#endif
1815bff5
A
154 return (0);
155}
156
157/* ARGSUSED */
158int
34d340d7 159p_gid(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5
A
160{
161 struct group *gr;
162 gid_t id;
163 char *np;
164
165 if (!*p) {
166 warnx("empty gid field");
34d340d7 167 return (-1);
1815bff5
A
168 }
169 if (!isdigit(*p)) {
170 if (!(gr = getgrnam(p))) {
171 warnx("unknown group %s", p);
34d340d7 172 return (-1);
1815bff5 173 }
34d340d7 174#ifndef OPEN_DIRECTORY
1815bff5 175 pw->pw_gid = gr->gr_gid;
34d340d7 176#endif
1815bff5
A
177 return (0);
178 }
179 errno = 0;
cf37c299 180 id = (gid_t)strtoul(p, &np, 10);
34d340d7 181 if (*np || (id == (uid_t)ULONG_MAX && errno == ERANGE)) {
1815bff5 182 warnx("illegal gid");
34d340d7 183 return (-1);
1815bff5 184 }
34d340d7 185#ifndef OPEN_DIRECTORY
1815bff5 186 pw->pw_gid = id;
34d340d7 187#endif
1815bff5
A
188 return (0);
189}
190
191/* ARGSUSED */
192int
34d340d7 193p_class(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5 194{
34d340d7
A
195#ifndef OPEN_DIRECTORY
196 if (!(pw->pw_class = strdup(p))) {
1815bff5 197 warnx("can't save entry");
34d340d7 198 return (-1);
1815bff5 199 }
34d340d7
A
200#endif
201
1815bff5
A
202 return (0);
203}
204
205/* ARGSUSED */
206int
34d340d7 207p_change(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5 208{
34d340d7 209#ifndef OPEN_DIRECTORY
1815bff5
A
210 if (!atot(p, &pw->pw_change))
211 return (0);
212 warnx("illegal date for change field");
34d340d7
A
213#endif
214 return (-1);
1815bff5
A
215}
216
217/* ARGSUSED */
218int
34d340d7 219p_expire(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5 220{
34d340d7 221#ifndef OPEN_DIRECTORY
1815bff5
A
222 if (!atot(p, &pw->pw_expire))
223 return (0);
224 warnx("illegal date for expire field");
34d340d7
A
225#endif
226 return (-1);
1815bff5
A
227}
228
229/* ARGSUSED */
230int
34d340d7 231p_gecos(char *p, struct passwd *pw __unused, ENTRY *ep)
1815bff5 232{
34d340d7
A
233#ifndef OPEN_DIRECTORY
234 if (!(ep->save = strdup(p))) {
1815bff5 235 warnx("can't save entry");
34d340d7 236 return (-1);
1815bff5 237 }
34d340d7 238#endif
1815bff5
A
239 return (0);
240}
241
242/* ARGSUSED */
243int
34d340d7 244p_hdir(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5
A
245{
246 if (!*p) {
247 warnx("empty home directory field");
34d340d7 248 return (-1);
1815bff5 249 }
34d340d7 250#ifndef OPEN_DIRECTORY
1815bff5
A
251 if (!(pw->pw_dir = strdup(p))) {
252 warnx("can't save entry");
34d340d7 253 return (-1);
1815bff5 254 }
34d340d7 255#endif
1815bff5
A
256 return (0);
257}
258
34d340d7 259
1815bff5
A
260/* ARGSUSED */
261int
34d340d7 262p_shell(char *p, struct passwd *pw, ENTRY *ep __unused)
1815bff5 263{
34d340d7
A
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
1815bff5 271
34d340d7 272#ifndef OPEN_DIRECTORY
1815bff5 273 if (!*p) {
34d340d7 274 pw->pw_shell = strdup(_PATH_BSHELL);
1815bff5
A
275 return (0);
276 }
277 /* only admin can change from or to "restricted" shells */
34d340d7 278 if (!master_mode && pw->pw_shell && !ok_shell(pw->pw_shell)) {
1815bff5 279 warnx("%s: current shell non-standard", pw->pw_shell);
34d340d7 280 return (-1);
1815bff5 281 }
34d340d7
A
282#endif /* !OPEN_DIRECTORY */
283 if (!ok_shell(p)) {
284 if (!master_mode) {
1815bff5 285 warnx("%s: non-standard shell", p);
34d340d7 286 return (-1);
1815bff5 287 }
34d340d7
A
288#ifndef OPEN_DIRECTORY
289 pw->pw_shell = strdup(p);
290#endif
1815bff5 291 }
34d340d7 292#ifndef OPEN_DIRECTORY
1815bff5 293 else
34d340d7
A
294 pw->pw_shell = dup_shell(p);
295 if (!pw->pw_shell) {
1815bff5 296 warnx("can't save entry");
34d340d7
A
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);
1815bff5
A
316 }
317 return (0);
318}
c3a08f59 319
34d340d7
A
320#ifdef OPEN_DIRECTORY
321#include <uuid/uuid.h>
322/* ARGSUSED */
323int
324p_uuid(char *p, struct passwd *pw __unused, ENTRY *ep)
c3a08f59 325{
34d340d7
A
326 uuid_t uu;
327 if (uuid_parse(p, uu) != 0) {
328 warnx("invalid UUID");
329 return (-1);
330 }
331 return (0);
c3a08f59
A
332}
333
334void
34d340d7 335display_string(CFDictionaryRef attrs, CFStringRef attrName, const char* prompt, FILE *fp)
c3a08f59 336{
34d340d7
A
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);
c3a08f59 344}
34d340d7 345#endif /* OPEN_DIRECTORY */