]>
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 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
24 /* $NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $ */
27 * Copyright (c) 1987, 1993, 1994, 1995
28 * The Regents of the University of California. All rights reserved.
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 #include <sys/cdefs.h>
60 #if defined(LIBC_SCCS) && !defined(lint)
61 __RCSID("$NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $");
62 #endif /* LIBC_SCCS and not lint */
64 #include <sys/types.h>
67 #include <sys/resource.h>
84 static void pw_cont
__P((int sig
));
85 static int pw_equal
__P((char *buf
, struct passwd
*old_pw
));
94 /* Acquire the lock file. */
96 fd
= open(_PATH_MASTERPASSWD_LOCK
, O_WRONLY
|O_CREAT
|O_EXCL
, 0600);
97 for (i
= 0; i
< retries
&& fd
< 0 && errno
== EEXIST
; i
++) {
99 fd
= open(_PATH_MASTERPASSWD_LOCK
, O_WRONLY
|O_CREAT
|O_EXCL
,
113 /* A zero length passwd file is never ok */
114 if (stat(_PATH_MASTERPASSWD_LOCK
, &sb
) == 0) {
115 if (sb
.st_size
== 0) {
116 warnx("%s is zero length", _PATH_MASTERPASSWD_LOCK
);
123 execl(_PATH_PWD_MKDB
, "pwd_mkdb", "-p",
124 _PATH_MASTERPASSWD_LOCK
, NULL
);
127 pid
= waitpid(pid
, &pstat
, 0);
128 if (pid
== -1 || !WIFEXITED(pstat
) || WEXITSTATUS(pstat
) != 0)
136 return(unlink(_PATH_MASTERPASSWD_LOCK
));
139 /* Everything below this point is intended for the convenience of programs
140 * which allow a user to interactively edit the passwd file. Errors in the
141 * routines below will cause the process to abort. */
143 static pid_t editpid
= -1;
159 /* Unlimited resource limits. */
160 rlim
.rlim_cur
= rlim
.rlim_max
= RLIM_INFINITY
;
161 (void)setrlimit(RLIMIT_CPU
, &rlim
);
162 (void)setrlimit(RLIMIT_FSIZE
, &rlim
);
163 (void)setrlimit(RLIMIT_STACK
, &rlim
);
164 (void)setrlimit(RLIMIT_DATA
, &rlim
);
165 (void)setrlimit(RLIMIT_RSS
, &rlim
);
167 /* Don't drop core (not really necessary, but GP's). */
168 rlim
.rlim_cur
= rlim
.rlim_max
= 0;
169 (void)setrlimit(RLIMIT_CORE
, &rlim
);
171 /* Turn off signals. */
172 (void)signal(SIGALRM
, SIG_IGN
);
173 (void)signal(SIGHUP
, SIG_IGN
);
174 (void)signal(SIGINT
, SIG_IGN
);
175 (void)signal(SIGPIPE
, SIG_IGN
);
176 (void)signal(SIGQUIT
, SIG_IGN
);
177 (void)signal(SIGTERM
, SIG_IGN
);
178 (void)signal(SIGCONT
, pw_cont
);
182 pw_edit(notsetuid
, filename
)
184 const char *filename
;
193 if (filename
== NULL
)
194 filename
= _PATH_MASTERPASSWD_LOCK
;
195 if ((editor
= getenv("EDITOR")) == NULL
)
196 editor
= strdup(_PATH_VI
);
198 editor
= strdup(editor
);
199 if ((p
= strrchr(editor
, '/')))
204 /* Scan editor string, count spaces, allocate arg vector. */
205 for (i
= 0, xargc
= 0; p
[i
] != '\0'; i
++) {
207 while (isspace(p
[i
++]))
208 /* skip white space */ ;
215 /* argv[0] + <xargc args> + filename + NULL */
216 xargv
= (char **)malloc(sizeof(char *) * (xargc
+ 3));
218 pw_error("malloc failed", 1, 1);
222 for (; *p
!= '\0'; p
++) {
225 *p
++ = '\0'; /* blast whitespace */
232 xargv
[i
++] = (char *)filename
;
235 if (!(editpid
= vfork())) {
240 execvp(editor
, xargv
);
244 editpid
= waitpid(editpid
, (int *)&pstat
, WUNTRACED
);
246 pw_error(editor
, 1, 1);
247 else if (WIFSTOPPED(pstat
))
248 raise(WSTOPSIG(pstat
));
249 else if (WIFEXITED(pstat
) && WEXITSTATUS(pstat
) == 0)
252 pw_error(editor
, 1, 1);
264 (void)printf("re-edit the password file? [y]: ");
265 (void)fflush(stdout
);
267 if (c
!= EOF
&& c
!= '\n')
268 while (getchar() != '\n');
270 pw_error(NULL
, 0, 0);
273 /* for use in pw_copy(). Compare a pw entry to a pw struct. */
279 struct passwd buf_pw
;
280 int len
= strlen (buf
);
281 if (buf
[len
-1] == '\n')
283 if (!pw_scan(buf
, &buf_pw
, NULL
))
285 return !strcmp(pw
->pw_name
, buf_pw
.pw_name
)
286 && pw
->pw_uid
== buf_pw
.pw_uid
287 && pw
->pw_gid
== buf_pw
.pw_gid
288 && !strcmp(pw
->pw_class
, buf_pw
.pw_class
)
289 && (long)pw
->pw_change
== (long)buf_pw
.pw_change
290 && (long)pw
->pw_expire
== (long)buf_pw
.pw_expire
291 && !strcmp(pw
->pw_gecos
, buf_pw
.pw_gecos
)
292 && !strcmp(pw
->pw_dir
, buf_pw
.pw_dir
)
293 && !strcmp(pw
->pw_shell
, buf_pw
.pw_shell
);
297 pw_copy(ffd
, tfd
, pw
, old_pw
)
299 struct passwd
*pw
, *old_pw
;
305 if (!(from
= fdopen(ffd
, "r")))
306 pw_error(_PATH_MASTERPASSWD
, 1, 1);
307 if (!(to
= fdopen(tfd
, "w")))
308 pw_error(_PATH_MASTERPASSWD_LOCK
, 1, 1);
310 for (done
= 0; fgets(buf
, sizeof(buf
), from
);) {
311 if (!strchr(buf
, '\n')) {
312 warnx("%s: line too long", _PATH_MASTERPASSWD
);
313 pw_error(NULL
, 0, 1);
316 (void)fprintf(to
, "%s", buf
);
322 /* skip comments for Rhapsody. */
325 if (!(p
= strchr(buf
, ':'))) {
326 warnx("%s: corrupted entry", _PATH_MASTERPASSWD
);
327 pw_error(NULL
, 0, 1);
330 if (strcmp(buf
, pw
->pw_name
)) {
332 (void)fprintf(to
, "%s", buf
);
338 if (old_pw
&& !pw_equal(buf
, old_pw
)) {
339 warnx("%s: entry inconsistent",
341 pw_error(NULL
, 0, 1);
343 (void)fprintf(to
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
344 pw
->pw_name
, pw
->pw_passwd
, pw
->pw_uid
, pw
->pw_gid
,
345 pw
->pw_class
, (long)pw
->pw_change
, (long)pw
->pw_expire
,
346 pw
->pw_gecos
, pw
->pw_dir
, pw
->pw_shell
);
351 /* Only append a new entry if real uid is root! */
354 (void)fprintf(to
, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
355 pw
->pw_name
, pw
->pw_passwd
, pw
->pw_uid
, pw
->pw_gid
,
356 pw
->pw_class
, (long)pw
->pw_change
,
357 (long)pw
->pw_expire
, pw
->pw_gecos
, pw
->pw_dir
,
360 warnx("%s: changes not made, no such entry",
364 err
: pw_error(NULL
, 1, 1);
369 pw_scan(bp
, pw
, flags
)
378 if (flags
!= (int *)NULL
)
381 if (!(pw
->pw_name
= strsep(&bp
, ":"))) /* login */
383 root
= !strcmp(pw
->pw_name
, "root");
385 if (!(pw
->pw_passwd
= strsep(&bp
, ":"))) /* passwd */
388 if (!(p
= strsep(&bp
, ":"))) /* uid */
390 id
= strtoul(p
, &ep
, 10);
392 warnx("root uid should be 0");
395 if (id
> UID_MAX
|| *ep
!= '\0') {
396 warnx("invalid uid '%s'", p
);
399 pw
->pw_uid
= (uid_t
)id
;
400 if ((*p
== '\0') && (flags
!= (int *)NULL
))
401 *flags
|= _PASSWORD_NOUID
;
403 if (!(p
= strsep(&bp
, ":"))) /* gid */
405 id
= strtoul(p
, &ep
, 10);
406 if (id
> GID_MAX
|| *ep
!= '\0') {
407 warnx("invalid gid '%s'", p
);
410 pw
->pw_gid
= (gid_t
)id
;
411 if ((*p
== '\0') && (flags
!= (int *)NULL
))
412 *flags
|= _PASSWORD_NOGID
;
414 pw
->pw_class
= strsep(&bp
, ":"); /* class */
415 if (!(p
= strsep(&bp
, ":"))) /* change */
417 pw
->pw_change
= atol(p
);
418 if ((*p
== '\0') && (flags
!= (int *)NULL
))
419 *flags
|= _PASSWORD_NOCHG
;
420 if (!(p
= strsep(&bp
, ":"))) /* expire */
422 pw
->pw_expire
= atol(p
);
423 if ((*p
== '\0') && (flags
!= (int *)NULL
))
424 *flags
|= _PASSWORD_NOEXP
;
425 pw
->pw_gecos
= strsep(&bp
, ":"); /* gecos */
426 pw
->pw_dir
= strsep(&bp
, ":"); /* directory */
427 if (!(pw
->pw_shell
= strsep(&bp
, ":"))) /* shell */
431 if (root
&& *p
) /* empty == /bin/sh */
432 for (setusershell();;) {
433 if (!(sh
= getusershell())) {
434 warnx("warning, unknown root shell");
441 if ((p
= strsep(&bp
, ":"))) { /* too many */
442 fmt
: warnx("corrupted entry");
450 pw_error(name
, err
, eval
)
457 warnx("%s: unchanged", _PATH_MASTERPASSWD
);