]>
git.saurik.com Git - apple/network_cmds.git/blob - rpc_yppasswdd.tproj/passwd.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* $NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $ */
28 * Copyright (c) 1987, 1993, 1994, 1995
29 * The Regents of the University of California. All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 #include <sys/cdefs.h>
61 #if defined(LIBC_SCCS) && !defined(lint)
62 __RCSID("$NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $");
63 #endif /* LIBC_SCCS and not lint */
65 #include <sys/types.h>
68 #include <sys/resource.h>
85 static void pw_cont
__P((int sig
));
86 static int pw_equal
__P((char *buf
, struct passwd
*old_pw
));
95 /* Acquire the lock file. */
97 fd
= open(_PATH_MASTERPASSWD_LOCK
, O_WRONLY
|O_CREAT
|O_EXCL
, 0600);
98 for (i
= 0; i
< retries
&& fd
< 0 && errno
== EEXIST
; i
++) {
100 fd
= open(_PATH_MASTERPASSWD_LOCK
, O_WRONLY
|O_CREAT
|O_EXCL
,
114 /* A zero length passwd file is never ok */
115 if (stat(_PATH_MASTERPASSWD_LOCK
, &sb
) == 0) {
116 if (sb
.st_size
== 0) {
117 warnx("%s is zero length", _PATH_MASTERPASSWD_LOCK
);
124 execl(_PATH_PWD_MKDB
, "pwd_mkdb", "-p",
125 _PATH_MASTERPASSWD_LOCK
, NULL
);
128 pid
= waitpid(pid
, &pstat
, 0);
129 if (pid
== -1 || !WIFEXITED(pstat
) || WEXITSTATUS(pstat
) != 0)
137 return(unlink(_PATH_MASTERPASSWD_LOCK
));
140 /* Everything below this point is intended for the convenience of programs
141 * which allow a user to interactively edit the passwd file. Errors in the
142 * routines below will cause the process to abort. */
144 static pid_t editpid
= -1;
160 /* Unlimited resource limits. */
161 rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
162 (void)setrlimit(RLIMIT_CPU
, &rlim
);
163 (void)setrlimit(RLIMIT_FSIZE
, &rlim
);
164 (void)setrlimit(RLIMIT_STACK
, &rlim
);
165 (void)setrlimit(RLIMIT_DATA
, &rlim
);
166 (void)setrlimit(RLIMIT_RSS
, &rlim
);
168 /* Don't drop core (not really necessary, but GP's). */
169 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
170 (void)setrlimit(RLIMIT_CORE
, &rlim
);
172 /* Turn off signals. */
173 (void)signal(SIGALRM
, SIG_IGN
);
174 (void)signal(SIGHUP
, SIG_IGN
);
175 (void)signal(SIGINT
, SIG_IGN
);
176 (void)signal(SIGPIPE
, SIG_IGN
);
177 (void)signal(SIGQUIT
, SIG_IGN
);
178 (void)signal(SIGTERM
, SIG_IGN
);
179 (void)signal(SIGCONT
, pw_cont
);
183 pw_edit(notsetuid
, filename
)
185 const char *filename
;
194 if (filename
== NULL
)
195 filename
= _PATH_MASTERPASSWD_LOCK
;
196 if ((editor
= getenv("EDITOR")) == NULL
)
197 editor
= strdup(_PATH_VI
);
199 editor
= strdup(editor
);
200 if ((p
= strrchr(editor
, '/')))
205 /* Scan editor string, count spaces, allocate arg vector. */
206 for (i
= 0, xargc
= 0; p
[i
] != '\0'; i
++) {
208 while (isspace(p
[i
++]))
209 /* skip white space */ ;
216 /* argv[0] + <xargc args> + filename + NULL */
217 xargv
= (char **)malloc(sizeof(char *) * (xargc
+ 3));
219 pw_error("malloc failed", 1, 1);
223 for (; *p
!= '\0'; p
++) {
226 *p
++ = '\0'; /* blast whitespace */
233 xargv
[i
++] = (char *)filename
;
236 if (!(editpid
= vfork())) {
241 execvp(editor
, xargv
);
245 editpid
= waitpid(editpid
, (int *)&pstat
, WUNTRACED
);
247 pw_error(editor
, 1, 1);
248 else if (WIFSTOPPED(pstat
))
249 raise(WSTOPSIG(pstat
));
250 else if (WIFEXITED(pstat
) && WEXITSTATUS(pstat
) == 0)
253 pw_error(editor
, 1, 1);
265 (void)printf("re-edit the password file? [y]: ");
266 (void)fflush(stdout
);
268 if (c
!= EOF
&& c
!= '\n')
269 while (getchar() != '\n');
271 pw_error(NULL
, 0, 0);
274 /* for use in pw_copy(). Compare a pw entry to a pw struct. */
280 struct passwd buf_pw
;
281 int len
= strlen (buf
);
282 if (buf
[len
-1] == '\n')
284 if (!pw_scan(buf
, &buf_pw
, NULL
))
286 return !strcmp(pw
->pw_name
, buf_pw
.pw_name
)
287 && pw
->pw_uid
== buf_pw
.pw_uid
288 && pw
->pw_gid
== buf_pw
.pw_gid
289 && !strcmp(pw
->pw_class
, buf_pw
.pw_class
)
290 && (long)pw
->pw_change
== (long)buf_pw
.pw_change
291 && (long)pw
->pw_expire
== (long)buf_pw
.pw_expire
292 && !strcmp(pw
->pw_gecos
, buf_pw
.pw_gecos
)
293 && !strcmp(pw
->pw_dir
, buf_pw
.pw_dir
)
294 && !strcmp(pw
->pw_shell
, buf_pw
.pw_shell
);
298 pw_copy(ffd
, tfd
, pw
, old_pw
)
300 struct passwd
*pw
, *old_pw
;
306 if (!(from
= fdopen(ffd
, "r")))
307 pw_error(_PATH_MASTERPASSWD
, 1, 1);
308 if (!(to
= fdopen(tfd
, "w")))
309 pw_error(_PATH_MASTERPASSWD_LOCK
, 1, 1);
311 for (done
= 0; fgets(buf
, sizeof(buf
), from
);) {
312 if (!strchr(buf
, '\n')) {
313 warnx("%s: line too long", _PATH_MASTERPASSWD
);
314 pw_error(NULL
, 0, 1);
317 (void)fprintf(to
, "%s", buf
);
323 /* skip comments for Rhapsody. */
326 if (!(p
= strchr(buf
, ':'))) {
327 warnx("%s: corrupted entry", _PATH_MASTERPASSWD
);
328 pw_error(NULL
, 0, 1);
331 if (strcmp(buf
, pw
->pw_name
)) {
333 (void)fprintf(to
, "%s", buf
);
339 if (old_pw
&& !pw_equal(buf
, old_pw
)) {
340 warnx("%s: entry inconsistent",
342 pw_error(NULL
, 0, 1);
344 (void)fprintf(to
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
345 pw
->pw_name
, pw
->pw_passwd
, pw
->pw_uid
, pw
->pw_gid
,
346 pw
->pw_class
, (long)pw
->pw_change
, (long)pw
->pw_expire
,
347 pw
->pw_gecos
, pw
->pw_dir
, pw
->pw_shell
);
352 /* Only append a new entry if real uid is root! */
355 (void)fprintf(to
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
356 pw
->pw_name
, pw
->pw_passwd
, pw
->pw_uid
, pw
->pw_gid
,
357 pw
->pw_class
, (long)pw
->pw_change
,
358 (long)pw
->pw_expire
, pw
->pw_gecos
, pw
->pw_dir
,
361 warnx("%s: changes not made, no such entry",
365 err
: pw_error(NULL
, 1, 1);
370 pw_scan(bp
, pw
, flags
)
379 if (flags
!= (int *)NULL
)
382 if (!(pw
->pw_name
= strsep(&bp
, ":"))) /* login */
384 root
= !strcmp(pw
->pw_name
, "root");
386 if (!(pw
->pw_passwd
= strsep(&bp
, ":"))) /* passwd */
389 if (!(p
= strsep(&bp
, ":"))) /* uid */
391 id
= strtoul(p
, &ep
, 10);
393 warnx("root uid should be 0");
396 if (id
> UID_MAX
|| *ep
!= '\0') {
397 warnx("invalid uid '%s'", p
);
400 pw
->pw_uid
= (uid_t
)id
;
401 if ((*p
== '\0') && (flags
!= (int *)NULL
))
402 *flags
|= _PASSWORD_NOUID
;
404 if (!(p
= strsep(&bp
, ":"))) /* gid */
406 id
= strtoul(p
, &ep
, 10);
407 if (id
> GID_MAX
|| *ep
!= '\0') {
408 warnx("invalid gid '%s'", p
);
411 pw
->pw_gid
= (gid_t
)id
;
412 if ((*p
== '\0') && (flags
!= (int *)NULL
))
413 *flags
|= _PASSWORD_NOGID
;
415 pw
->pw_class
= strsep(&bp
, ":"); /* class */
416 if (!(p
= strsep(&bp
, ":"))) /* change */
418 pw
->pw_change
= atol(p
);
419 if ((*p
== '\0') && (flags
!= (int *)NULL
))
420 *flags
|= _PASSWORD_NOCHG
;
421 if (!(p
= strsep(&bp
, ":"))) /* expire */
423 pw
->pw_expire
= atol(p
);
424 if ((*p
== '\0') && (flags
!= (int *)NULL
))
425 *flags
|= _PASSWORD_NOEXP
;
426 pw
->pw_gecos
= strsep(&bp
, ":"); /* gecos */
427 pw
->pw_dir
= strsep(&bp
, ":"); /* directory */
428 if (!(pw
->pw_shell
= strsep(&bp
, ":"))) /* shell */
432 if (root
&& *p
) /* empty == /bin/sh */
433 for (setusershell();;) {
434 if (!(sh
= getusershell())) {
435 warnx("warning, unknown root shell");
442 if ((p
= strsep(&bp
, ":"))) { /* too many */
443 fmt
: warnx("corrupted entry");
451 pw_error(name
, err
, eval
)
458 warnx("%s: unchanged", _PATH_MASTERPASSWD
);