xref: /csrg-svn/usr.sbin/vipw/pw_util.c (revision 64007)
146377Sbostic /*-
246377Sbostic  * Copyright (c) 1990 The Regents of the University of California.
346377Sbostic  * All rights reserved.
446377Sbostic  *
546377Sbostic  * %sccs.include.redist.c%
646377Sbostic  */
746377Sbostic 
846377Sbostic #ifndef lint
9*64007Sbostic static char sccsid[] = "@(#)pw_util.c	5.5 (Berkeley) 07/23/93";
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/wait.h>
1946377Sbostic #include <sys/time.h>
2046377Sbostic #include <sys/resource.h>
21*64007Sbostic 
22*64007Sbostic #include <errno.h>
2346377Sbostic #include <fcntl.h>
24*64007Sbostic #include <paths.h>
2546377Sbostic #include <pwd.h>
26*64007Sbostic #include <signal.h>
2746377Sbostic #include <stdio.h>
28*64007Sbostic #include <stdlib.h>
2946377Sbostic #include <string.h>
3046377Sbostic 
3146377Sbostic extern char *progname;
3246377Sbostic extern char *tempname;
3346377Sbostic 
3446377Sbostic pw_init()
3546377Sbostic {
3646377Sbostic 	struct rlimit rlim;
3746377Sbostic 
3849830Sbostic 	/* Unlimited resource limits. */
3946377Sbostic 	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
4046377Sbostic 	(void)setrlimit(RLIMIT_CPU, &rlim);
4146377Sbostic 	(void)setrlimit(RLIMIT_FSIZE, &rlim);
4249830Sbostic 	(void)setrlimit(RLIMIT_STACK, &rlim);
4349830Sbostic 	(void)setrlimit(RLIMIT_DATA, &rlim);
4449830Sbostic 	(void)setrlimit(RLIMIT_RSS, &rlim);
4546377Sbostic 
4646377Sbostic 	/* Don't drop core (not really necessary, but GP's). */
4746377Sbostic 	rlim.rlim_cur = rlim.rlim_max = 0;
4846377Sbostic 	(void)setrlimit(RLIMIT_CORE, &rlim);
4946377Sbostic 
5049830Sbostic 	/* Turn off signals. */
5149830Sbostic 	(void)signal(SIGALRM, SIG_IGN);
5247287Sbostic 	(void)signal(SIGHUP, SIG_IGN);
5347287Sbostic 	(void)signal(SIGINT, SIG_IGN);
5449830Sbostic 	(void)signal(SIGPIPE, SIG_IGN);
5547287Sbostic 	(void)signal(SIGQUIT, SIG_IGN);
5647287Sbostic 	(void)signal(SIGTERM, SIG_IGN);
5747287Sbostic 	(void)signal(SIGTSTP, SIG_IGN);
5849830Sbostic 	(void)signal(SIGTTOU, SIG_IGN);
5946377Sbostic 
6046377Sbostic 	/* Create with exact permissions. */
6146377Sbostic 	(void)umask(0);
6246377Sbostic }
6346377Sbostic 
6446377Sbostic static int lockfd;
6546377Sbostic pw_lock()
6646377Sbostic {
6746377Sbostic 	/*
6846377Sbostic 	 * If the master password file doesn't exist, the system is hosed.
69*64007Sbostic 	 * Might as well try to build one.  Set the close-on-exec bit so
70*64007Sbostic 	 * that users can't get at the encrypted passwords while editing.
7146377Sbostic 	 * Open should allow flock'ing the file; see 4.4BSD.	XXX
7246377Sbostic 	 */
7346377Sbostic 	lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
74*64007Sbostic 	if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) {
7546377Sbostic 		(void)fprintf(stderr, "%s: %s: %s\n",
7646377Sbostic 		    progname, _PATH_MASTERPASSWD, strerror(errno));
7746377Sbostic 		exit(1);
7846377Sbostic 	}
7946955Sbostic 	if (flock(lockfd, LOCK_EX|LOCK_NB)) {
8046377Sbostic 		(void)fprintf(stderr,
8146377Sbostic 		    "%s: the password db is busy.\n", progname);
8246377Sbostic 		exit(1);
8346377Sbostic 	}
8446377Sbostic 	return(lockfd);
8546377Sbostic }
8646377Sbostic 
8746377Sbostic pw_tmp()
8846377Sbostic {
8946377Sbostic 	static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
9046377Sbostic 	int fd;
9146377Sbostic 	char *p;
9246377Sbostic 
9346377Sbostic 	if (p = rindex(path, '/'))
9446377Sbostic 		++p;
9546377Sbostic 	else
9646377Sbostic 		p = path;
97*64007Sbostic 	(void)snprintf(p, sizeof(path), "%s.XXXXXX", progname);
9846377Sbostic 	if ((fd = mkstemp(path)) == -1) {
9946377Sbostic 		(void)fprintf(stderr,
10046377Sbostic 		    "%s: %s: %s\n", progname, path, strerror(errno));
10146377Sbostic 		exit(1);
10246377Sbostic 	}
10346377Sbostic 	tempname = path;
10446377Sbostic 	return(fd);
10546377Sbostic }
10646377Sbostic 
10746377Sbostic pw_mkdb()
10846377Sbostic {
10946377Sbostic 	union wait pstat;
11046377Sbostic 	pid_t pid;
11146377Sbostic 
11246377Sbostic 	(void)printf("%s: rebuilding the database...\n", progname);
11346377Sbostic 	(void)fflush(stdout);
11446377Sbostic 	if (!(pid = vfork())) {
11546377Sbostic 		execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
11646377Sbostic 		pw_error(_PATH_PWD_MKDB, 1, 1);
11746377Sbostic 	}
11846377Sbostic 	pid = waitpid(pid, (int *)&pstat, 0);
11946377Sbostic 	if (pid == -1 || pstat.w_status)
12046377Sbostic 		return(0);
12146377Sbostic 	(void)printf("%s: done\n", progname);
12246377Sbostic 	return(1);
12346377Sbostic }
12446377Sbostic 
12546377Sbostic pw_edit(notsetuid)
12646377Sbostic 	int notsetuid;
12746377Sbostic {
12846377Sbostic 	union wait pstat;
12946377Sbostic 	pid_t pid;
13046377Sbostic 	char *p, *editor;
13146377Sbostic 
13246377Sbostic 	if (!(editor = getenv("EDITOR")))
13346377Sbostic 		editor = _PATH_VI;
13446377Sbostic 	if (p = rindex(editor, '/'))
13546377Sbostic 		++p;
13646377Sbostic 	else
13746377Sbostic 		p = editor;
13846377Sbostic 
13946377Sbostic 	if (!(pid = vfork())) {
14046377Sbostic 		if (notsetuid) {
14146377Sbostic 			(void)setgid(getgid());
14246377Sbostic 			(void)setuid(getuid());
14346377Sbostic 		}
14446377Sbostic 		execlp(editor, p, tempname, NULL);
14546955Sbostic 		_exit(1);
14646377Sbostic 	}
14746377Sbostic 	pid = waitpid(pid, (int *)&pstat, 0);
14846955Sbostic 	if (pid == -1 || pstat.w_status)
14946955Sbostic 		pw_error(editor, 1, 1);
15046377Sbostic }
15146377Sbostic 
15246377Sbostic pw_prompt()
15346377Sbostic {
15446377Sbostic 	register int c;
15546377Sbostic 
15646377Sbostic 	for (;;) {
15746377Sbostic 		(void)printf("re-edit the password file? [y]: ");
15846377Sbostic 		(void)fflush(stdout);
15946377Sbostic 		c = getchar();
16046377Sbostic 		if (c != EOF && c != (int)'\n')
16146377Sbostic 			while (getchar() != (int)'\n');
16246377Sbostic 		if (c == (int)'n')
16346377Sbostic 			pw_error((char *)NULL, 0, 0);
16446377Sbostic 		break;
16546377Sbostic 	}
16646377Sbostic }
16746377Sbostic 
16846377Sbostic pw_error(name, err, eval)
16946377Sbostic 	char *name;
17046377Sbostic 	int err, eval;
17146377Sbostic {
17246377Sbostic 	int sverrno;
17346377Sbostic 
17446377Sbostic 	if (err) {
17546377Sbostic 		sverrno = errno;
17646377Sbostic 		(void)fprintf(stderr, "%s: ", progname);
17746377Sbostic 		if (name)
17846377Sbostic 			(void)fprintf(stderr, "%s: ", name);
17946377Sbostic 		(void)fprintf(stderr, "%s\n", strerror(sverrno));
18046377Sbostic 	}
18146377Sbostic 	(void)fprintf(stderr,
18246377Sbostic 	    "%s: %s unchanged\n", progname, _PATH_MASTERPASSWD);
18346377Sbostic 	(void)unlink(tempname);
18446377Sbostic 	exit(eval);
18546377Sbostic }
186