pw_util.c revision 1553
1321369Sdim/*-
2283625Sdim * Copyright (c) 1990, 1993, 1994
3353358Sdim *	The Regents of the University of California.  All rights reserved.
4353358Sdim *
5353358Sdim * Redistribution and use in source and binary forms, with or without
6283625Sdim * modification, are permitted provided that the following conditions
7283625Sdim * are met:
8283625Sdim * 1. Redistributions of source code must retain the above copyright
9321369Sdim *    notice, this list of conditions and the following disclaimer.
10321369Sdim * 2. Redistributions in binary form must reproduce the above copyright
11283625Sdim *    notice, this list of conditions and the following disclaimer in the
12314564Sdim *    documentation and/or other materials provided with the distribution.
13321369Sdim * 3. All advertising materials mentioning features or use of this software
14321369Sdim *    must display the following acknowledgement:
15321369Sdim *	This product includes software developed by the University of
16314564Sdim *	California, Berkeley and its contributors.
17321369Sdim * 4. Neither the name of the University nor the names of its contributors
18283625Sdim *    may be used to endorse or promote products derived from this software
19360784Sdim *    without specific prior written permission.
20283625Sdim *
21341825Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22314564Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23321369Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24283625Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25283625Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26296417Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27321369Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28321369Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29321369Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30321369Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31321369Sdim * SUCH DAMAGE.
32321369Sdim */
33321369Sdim
34321369Sdim#ifndef lint
35283625Sdimstatic char sccsid[] = "@(#)pw_util.c	8.3 (Berkeley) 4/2/94";
36283625Sdim#endif /* not lint */
37283625Sdim
38283625Sdim/*
39321369Sdim * This file is used by all the "password" programs; vipw(8), chpass(1),
40283625Sdim * and passwd(1).
41283625Sdim */
42283625Sdim
43283625Sdim#include <sys/param.h>
44341825Sdim#include <sys/time.h>
45341825Sdim#include <sys/resource.h>
46341825Sdim#include <sys/stat.h>
47341825Sdim#include <sys/wait.h>
48341825Sdim
49360784Sdim#include <err.h>
50341825Sdim#include <errno.h>
51341825Sdim#include <fcntl.h>
52353358Sdim#include <paths.h>
53341825Sdim#include <pwd.h>
54341825Sdim#include <signal.h>
55341825Sdim#include <stdio.h>
56341825Sdim#include <stdlib.h>
57341825Sdim#include <string.h>
58341825Sdim#include <unistd.h>
59341825Sdim
60360784Sdim#include "pw_util.h"
61341825Sdim
62341825Sdimextern char *tempname;
63341825Sdim
64341825Sdimvoid
65341825Sdimpw_init()
66341825Sdim{
67341825Sdim	struct rlimit rlim;
68341825Sdim
69341825Sdim	/* Unlimited resource limits. */
70341825Sdim	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
71341825Sdim	(void)setrlimit(RLIMIT_CPU, &rlim);
72341825Sdim	(void)setrlimit(RLIMIT_FSIZE, &rlim);
73341825Sdim	(void)setrlimit(RLIMIT_STACK, &rlim);
74360784Sdim	(void)setrlimit(RLIMIT_DATA, &rlim);
75344779Sdim	(void)setrlimit(RLIMIT_RSS, &rlim);
76344779Sdim
77360784Sdim	/* Don't drop core (not really necessary, but GP's). */
78341825Sdim	rlim.rlim_cur = rlim.rlim_max = 0;
79341825Sdim	(void)setrlimit(RLIMIT_CORE, &rlim);
80341825Sdim
81341825Sdim	/* Turn off signals. */
82341825Sdim	(void)signal(SIGALRM, SIG_IGN);
83341825Sdim	(void)signal(SIGHUP, SIG_IGN);
84341825Sdim	(void)signal(SIGINT, SIG_IGN);
85341825Sdim	(void)signal(SIGPIPE, SIG_IGN);
86353358Sdim	(void)signal(SIGQUIT, SIG_IGN);
87341825Sdim	(void)signal(SIGTERM, SIG_IGN);
88341825Sdim	(void)signal(SIGTSTP, SIG_IGN);
89341825Sdim	(void)signal(SIGTTOU, SIG_IGN);
90341825Sdim
91341825Sdim	/* Create with exact permissions. */
92341825Sdim	(void)umask(0);
93341825Sdim}
94341825Sdim
95360784Sdimstatic int lockfd;
96341825Sdim
97341825Sdimint
98341825Sdimpw_lock()
99341825Sdim{
100341825Sdim	/*
101360784Sdim	 * If the master password file doesn't exist, the system is hosed.
102360784Sdim	 * Might as well try to build one.  Set the close-on-exec bit so
103353358Sdim	 * that users can't get at the encrypted passwords while editing.
104360784Sdim	 * Open should allow flock'ing the file; see 4.4BSD.	XXX
105360784Sdim	 */
106360784Sdim	lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
107341825Sdim	if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
108341825Sdim		err(1, "%s", _PATH_MASTERPASSWD);
109296417Sdim	if (flock(lockfd, LOCK_EX|LOCK_NB))
110296417Sdim		errx(1, "the password db file is busy");
111296417Sdim	return (lockfd);
112344779Sdim}
113344779Sdim
114344779Sdimint
115360784Sdimpw_tmp()
116344779Sdim{
117344779Sdim	static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
118344779Sdim	int fd;
119344779Sdim	char *p;
120283625Sdim
121283625Sdim	if (p = strrchr(path, '/'))
122344779Sdim		++p;
123321369Sdim	else
124321369Sdim		p = path;
125283625Sdim	strcpy(p, "pw.XXXXXX");
126360784Sdim	if ((fd = mkstemp(path)) == -1)
127344779Sdim		err(1, "%s", path);
128283625Sdim	tempname = path;
129344779Sdim	return (fd);
130344779Sdim}
131344779Sdim
132344779Sdimint
133344779Sdimpw_mkdb()
134344779Sdim{
135344779Sdim	int pstat;
136344779Sdim	pid_t pid;
137344779Sdim
138344779Sdim	warnx("rebuilding the database...");
139344779Sdim	(void)fflush(stderr);
140344779Sdim	if (!(pid = vfork())) {
141344779Sdim		execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
142327952Sdim		pw_error(_PATH_PWD_MKDB, 1, 1);
143344779Sdim	}
144344779Sdim	pid = waitpid(pid, &pstat, 0);
145344779Sdim	if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
146327952Sdim		return (0);
147344779Sdim	warnx("done");
148344779Sdim	return (1);
149344779Sdim}
150344779Sdim
151344779Sdimvoid
152327952Sdimpw_edit(notsetuid)
153344779Sdim	int notsetuid;
154344779Sdim{
155344779Sdim	int pstat;
156344779Sdim	pid_t pid;
157344779Sdim	char *p, *editor;
158327952Sdim
159283625Sdim	if (!(editor = getenv("EDITOR")))
160344779Sdim		editor = _PATH_VI;
161344779Sdim	if (p = strrchr(editor, '/'))
162344779Sdim		++p;
163344779Sdim	else
164344779Sdim		p = editor;
165344779Sdim
166283625Sdim	if (!(pid = vfork())) {
167283625Sdim		if (notsetuid) {
168327952Sdim			(void)setgid(getgid());
169327952Sdim			(void)setuid(getuid());
170327952Sdim		}
171327952Sdim		execlp(editor, p, tempname, NULL);
172341825Sdim		_exit(1);
173327952Sdim	}
174327952Sdim	pid = waitpid(pid, (int *)&pstat, 0);
175341825Sdim	if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
176327952Sdim		pw_error(editor, 1, 1);
177327952Sdim}
178327952Sdim
179327952Sdimvoid
180353358Sdimpw_prompt()
181327952Sdim{
182327952Sdim	int c;
183327952Sdim
184327952Sdim	(void)printf("re-edit the password file? [y]: ");
185327952Sdim	(void)fflush(stdout);
186327952Sdim	c = getchar();
187327952Sdim	if (c != EOF && c != '\n')
188327952Sdim		while (getchar() != '\n');
189327952Sdim	if (c == 'n')
190353358Sdim		pw_error(NULL, 0, 0);
191327952Sdim}
192327952Sdim
193327952Sdimvoid
194283625Sdimpw_error(name, err, eval)
195283625Sdim	char *name;
196321369Sdim	int err, eval;
197283625Sdim{
198283625Sdim	if (err)
199341825Sdim		warn(name);
200283625Sdim
201321369Sdim	warnx("%s: unchanged", _PATH_MASTERPASSWD);
202360784Sdim	(void)unlink(tempname);
203360784Sdim	exit(eval);
204360784Sdim}
205360784Sdim