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