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