xref: /csrg-svn/usr.sbin/vipw/pw_util.c (revision 69088)
146377Sbostic /*-
266649Spendry  * Copyright (c) 1990, 1993, 1994
364008Sbostic  *	The Regents of the University of California.  All rights reserved.
446377Sbostic  *
546377Sbostic  * %sccs.include.redist.c%
646377Sbostic  */
746377Sbostic 
846377Sbostic #ifndef lint
9*69088Sbostic static char sccsid[] = "@(#)pw_util.c	8.4 (Berkeley) 04/28/95";
1046377Sbostic #endif /* not lint */
1146377Sbostic 
1246377Sbostic /*
1346377Sbostic  * This file is used by all the "password" programs; vipw(8), chpass(1),
1446377Sbostic  * and passwd(1).
1546377Sbostic  */
1646377Sbostic 
1746377Sbostic #include <sys/param.h>
1846377Sbostic #include <sys/time.h>
1946377Sbostic #include <sys/resource.h>
2066576Spendry #include <sys/stat.h>
2166576Spendry #include <sys/wait.h>
2264007Sbostic 
2366576Spendry #include <err.h>
2464007Sbostic #include <errno.h>
2546377Sbostic #include <fcntl.h>
2664007Sbostic #include <paths.h>
2746377Sbostic #include <pwd.h>
2864007Sbostic #include <signal.h>
2946377Sbostic #include <stdio.h>
3064007Sbostic #include <stdlib.h>
3146377Sbostic #include <string.h>
3266576Spendry #include <unistd.h>
3346377Sbostic 
3466576Spendry #include "pw_util.h"
3566576Spendry 
3646377Sbostic extern char *tempname;
37*69088Sbostic static pid_t editpid = -1;
38*69088Sbostic static int lockfd;
3946377Sbostic 
4066576Spendry void
pw_cont(sig)41*69088Sbostic pw_cont(sig)
42*69088Sbostic 	int sig;
43*69088Sbostic {
44*69088Sbostic 
45*69088Sbostic 	if (editpid != -1)
46*69088Sbostic 		kill(editpid, sig);
47*69088Sbostic }
48*69088Sbostic 
49*69088Sbostic void
pw_init()5046377Sbostic pw_init()
5146377Sbostic {
5246377Sbostic 	struct rlimit rlim;
5346377Sbostic 
5449830Sbostic 	/* Unlimited resource limits. */
5546377Sbostic 	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
5646377Sbostic 	(void)setrlimit(RLIMIT_CPU, &rlim);
5746377Sbostic 	(void)setrlimit(RLIMIT_FSIZE, &rlim);
5849830Sbostic 	(void)setrlimit(RLIMIT_STACK, &rlim);
5949830Sbostic 	(void)setrlimit(RLIMIT_DATA, &rlim);
6049830Sbostic 	(void)setrlimit(RLIMIT_RSS, &rlim);
6146377Sbostic 
6246377Sbostic 	/* Don't drop core (not really necessary, but GP's). */
6346377Sbostic 	rlim.rlim_cur = rlim.rlim_max = 0;
6446377Sbostic 	(void)setrlimit(RLIMIT_CORE, &rlim);
6546377Sbostic 
6649830Sbostic 	/* Turn off signals. */
6749830Sbostic 	(void)signal(SIGALRM, SIG_IGN);
6847287Sbostic 	(void)signal(SIGHUP, SIG_IGN);
6947287Sbostic 	(void)signal(SIGINT, SIG_IGN);
7049830Sbostic 	(void)signal(SIGPIPE, SIG_IGN);
7147287Sbostic 	(void)signal(SIGQUIT, SIG_IGN);
7247287Sbostic 	(void)signal(SIGTERM, SIG_IGN);
73*69088Sbostic 	(void)signal(SIGCONT, pw_cont);
7446377Sbostic 
7546377Sbostic 	/* Create with exact permissions. */
7646377Sbostic 	(void)umask(0);
7746377Sbostic }
7846377Sbostic 
7966576Spendry int
pw_lock()8046377Sbostic pw_lock()
8146377Sbostic {
8246377Sbostic 	/*
8346377Sbostic 	 * If the master password file doesn't exist, the system is hosed.
8464007Sbostic 	 * Might as well try to build one.  Set the close-on-exec bit so
8564007Sbostic 	 * that users can't get at the encrypted passwords while editing.
8646377Sbostic 	 * Open should allow flock'ing the file; see 4.4BSD.	XXX
8746377Sbostic 	 */
8846377Sbostic 	lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
8966576Spendry 	if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
9066576Spendry 		err(1, "%s", _PATH_MASTERPASSWD);
9166576Spendry 	if (flock(lockfd, LOCK_EX|LOCK_NB))
9266576Spendry 		errx(1, "the password db file is busy");
9366576Spendry 	return (lockfd);
9446377Sbostic }
9546377Sbostic 
9666576Spendry int
pw_tmp()9746377Sbostic pw_tmp()
9846377Sbostic {
9946377Sbostic 	static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
10046377Sbostic 	int fd;
10146377Sbostic 	char *p;
10246377Sbostic 
10366576Spendry 	if (p = strrchr(path, '/'))
10446377Sbostic 		++p;
10546377Sbostic 	else
10646377Sbostic 		p = path;
10766576Spendry 	strcpy(p, "pw.XXXXXX");
10866576Spendry 	if ((fd = mkstemp(path)) == -1)
10966576Spendry 		err(1, "%s", path);
11046377Sbostic 	tempname = path;
11166576Spendry 	return (fd);
11246377Sbostic }
11346377Sbostic 
11466576Spendry int
pw_mkdb()11546377Sbostic pw_mkdb()
11646377Sbostic {
11766576Spendry 	int pstat;
11846377Sbostic 	pid_t pid;
11946377Sbostic 
12066576Spendry 	warnx("rebuilding the database...");
12166576Spendry 	(void)fflush(stderr);
12246377Sbostic 	if (!(pid = vfork())) {
12346377Sbostic 		execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
12446377Sbostic 		pw_error(_PATH_PWD_MKDB, 1, 1);
12546377Sbostic 	}
12666576Spendry 	pid = waitpid(pid, &pstat, 0);
12766576Spendry 	if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
12866576Spendry 		return (0);
12966576Spendry 	warnx("done");
13066576Spendry 	return (1);
13146377Sbostic }
13246377Sbostic 
13366576Spendry void
pw_edit(notsetuid)13446377Sbostic pw_edit(notsetuid)
13546377Sbostic 	int notsetuid;
13646377Sbostic {
13766576Spendry 	int pstat;
13846377Sbostic 	char *p, *editor;
13946377Sbostic 
14046377Sbostic 	if (!(editor = getenv("EDITOR")))
14146377Sbostic 		editor = _PATH_VI;
14266576Spendry 	if (p = strrchr(editor, '/'))
14346377Sbostic 		++p;
14446377Sbostic 	else
14546377Sbostic 		p = editor;
14646377Sbostic 
147*69088Sbostic 	if (!(editpid = vfork())) {
14846377Sbostic 		if (notsetuid) {
14946377Sbostic 			(void)setgid(getgid());
15046377Sbostic 			(void)setuid(getuid());
15146377Sbostic 		}
15246377Sbostic 		execlp(editor, p, tempname, NULL);
15346955Sbostic 		_exit(1);
15446377Sbostic 	}
155*69088Sbostic 	for (;;) {
156*69088Sbostic 		editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
157*69088Sbostic 		if (editpid == -1)
158*69088Sbostic 			pw_error(editor, 1, 1);
159*69088Sbostic 		else if (WIFSTOPPED(pstat))
160*69088Sbostic 			raise(WSTOPSIG(pstat));
161*69088Sbostic 		else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
162*69088Sbostic 			break;
163*69088Sbostic 		else
164*69088Sbostic 			pw_error(editor, 1, 1);
165*69088Sbostic 	}
166*69088Sbostic 	editpid = -1;
16746377Sbostic }
16846377Sbostic 
16966576Spendry void
pw_prompt()17046377Sbostic pw_prompt()
17146377Sbostic {
17266576Spendry 	int c;
17346377Sbostic 
17466576Spendry 	(void)printf("re-edit the password file? [y]: ");
17566576Spendry 	(void)fflush(stdout);
17666576Spendry 	c = getchar();
17766576Spendry 	if (c != EOF && c != '\n')
17866576Spendry 		while (getchar() != '\n');
17966576Spendry 	if (c == 'n')
18066576Spendry 		pw_error(NULL, 0, 0);
18146377Sbostic }
18246377Sbostic 
18366576Spendry void
pw_error(name,err,eval)18446377Sbostic pw_error(name, err, eval)
18546377Sbostic 	char *name;
18646377Sbostic 	int err, eval;
18746377Sbostic {
18866576Spendry 	if (err)
18966576Spendry 		warn(name);
19046377Sbostic 
19166576Spendry 	warnx("%s: unchanged", _PATH_MASTERPASSWD);
19246377Sbostic 	(void)unlink(tempname);
19346377Sbostic 	exit(eval);
19446377Sbostic }
195