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