]> git.saurik.com Git - apple/system_cmds.git/blob - chpass.tproj/ds_pw_util.c
1b76cadbc2b3125e4220b34d14a4e4c6d6bfaa1b
[apple/system_cmds.git] / chpass.tproj / ds_pw_util.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
12 * this file.
13 *
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
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*-
25 * Copyright (c) 1990, 1993, 1994
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57 #ifndef lint
58 static char sccsid[] = "@(#)pw_util.c 8.4 (Berkeley) 4/28/95";
59 #endif /* not lint */
60
61 /*
62 * This file is used by all the "password" programs; vipw(8), chpass(1),
63 * and passwd(1).
64 */
65
66 #include <sys/param.h>
67 #include <sys/time.h>
68 #include <sys/resource.h>
69 #include <sys/stat.h>
70 #include <sys/wait.h>
71
72 #include <err.h>
73 #include <errno.h>
74 #include <fcntl.h>
75 #include <paths.h>
76 #include <pwd.h>
77 #include <signal.h>
78 #include <stdio.h>
79 #include <stdlib.h>
80 #include <string.h>
81 #include <unistd.h>
82
83 #include "pw_util.h"
84 #ifdef DIRECTORY_SERVICE
85 #include "directory_service.h"
86 #endif /* DIRECTORY_SERVICE */
87
88 extern char *tempname;
89 static pid_t editpid = -1;
90 static int lockfd;
91
92 void
93 pw_cont(sig)
94 int sig;
95 {
96
97 if (editpid != -1)
98 kill(editpid, sig);
99 }
100
101 void
102 pw_init()
103 {
104 struct rlimit rlim;
105
106 /* Unlimited resource limits. */
107 rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
108 (void)setrlimit(RLIMIT_CPU, &rlim);
109 (void)setrlimit(RLIMIT_FSIZE, &rlim);
110 (void)setrlimit(RLIMIT_STACK, &rlim);
111 (void)setrlimit(RLIMIT_DATA, &rlim);
112 (void)setrlimit(RLIMIT_RSS, &rlim);
113
114 /* Don't drop core (not really necessary, but GP's). */
115 rlim.rlim_cur = rlim.rlim_max = 0;
116 (void)setrlimit(RLIMIT_CORE, &rlim);
117
118 /* Turn off signals. */
119 (void)signal(SIGALRM, SIG_IGN);
120 (void)signal(SIGHUP, SIG_IGN);
121 (void)signal(SIGINT, SIG_IGN);
122 (void)signal(SIGPIPE, SIG_IGN);
123 (void)signal(SIGQUIT, SIG_IGN);
124 (void)signal(SIGTERM, SIG_IGN);
125 (void)signal(SIGCONT, pw_cont);
126
127 /* Create with exact permissions. */
128 (void)umask(0);
129 }
130
131 int
132 pw_lock()
133 {
134 /*
135 * If the master password file doesn't exist, the system is hosed.
136 * Might as well try to build one. Set the close-on-exec bit so
137 * that users can't get at the encrypted passwords while editing.
138 * Open should allow flock'ing the file; see 4.4BSD. XXX
139 */
140 lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
141 if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
142 err(1, "%s", _PATH_MASTERPASSWD);
143 if (flock(lockfd, LOCK_EX|LOCK_NB))
144 errx(1, "the password db file is busy");
145 return (lockfd);
146 }
147
148 int
149 pw_tmp()
150 {
151 static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
152 int fd;
153 char *p;
154
155 if (p = strrchr(path, '/'))
156 ++p;
157 else
158 p = path;
159 strcpy(p, "pw.XXXXXX");
160 if ((fd = mkstemp(path)) == -1)
161 err(1, "%s", path);
162 tempname = path;
163 return (fd);
164 }
165
166 int
167 pw_mkdb()
168 {
169 int pstat;
170 pid_t pid;
171
172 warnx("rebuilding the database...");
173 (void)fflush(stderr);
174 if (!(pid = vfork())) {
175 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
176 pw_error(_PATH_PWD_MKDB, 1, 1);
177 }
178 pid = waitpid(pid, &pstat, 0);
179 if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
180 return (1);
181 warnx("done");
182 return (0);
183 }
184
185 void
186 pw_edit(notsetuid)
187 int notsetuid;
188 {
189 int pstat;
190 char *p, *editor;
191
192 if (!(editor = getenv("EDITOR")))
193 editor = _PATH_VI;
194 if (p = strrchr(editor, '/'))
195 ++p;
196 else
197 p = editor;
198
199 if (!(editpid = vfork())) {
200 if (notsetuid) {
201 (void)setgid(getgid());
202 (void)setuid(getuid());
203 }
204 execlp(editor, p, tempname, NULL);
205 _exit(1);
206 }
207 for (;;) {
208 editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
209 if (editpid == -1)
210 pw_error(editor, 1, 1);
211 else if (WIFSTOPPED(pstat))
212 raise(WSTOPSIG(pstat));
213 else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
214 break;
215 else
216 pw_error(editor, 1, 1);
217 }
218 editpid = -1;
219 }
220
221 void
222 pw_prompt()
223 {
224 int c;
225
226 (void)printf("re-edit the password file? [y]: ");
227 (void)fflush(stdout);
228 c = getchar();
229 if (c != EOF && c != '\n')
230 while (getchar() != '\n');
231 if (c == 'n')
232 pw_error(NULL, 0, 0);
233 }
234
235 void
236 pw_error(name, err, eval)
237 char *name;
238 int err, eval;
239 {
240 #ifdef DIRECTORY_SERVICE
241 extern int dswhere;
242 #endif /* DIRECTORY_SERVICE */
243 if (err)
244 warn("%s", name);
245
246 #ifdef DIRECTORY_SERVICE
247 switch(dswhere) {
248 case WHERE_LOCALNI:
249 warnx("netinfo domain \"%s\": unchanged", DSPath);
250 break;
251 case WHERE_FILES:
252 #endif /* DIRECTORY_SERVICE */
253 warnx("%s: unchanged", _PATH_MASTERPASSWD);
254 #ifdef DIRECTORY_SERVICE
255 }
256 #endif /* DIRECTORY_SERVICE */
257 (void)unlink(tempname);
258 exit(eval);
259 }