1dea673e9SRodney W. Grimes /*- 2dea673e9SRodney W. Grimes * Copyright (c) 1990, 1993, 1994 3dea673e9SRodney W. Grimes * The Regents of the University of California. All rights reserved. 4dea673e9SRodney W. Grimes * 5dea673e9SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 6dea673e9SRodney W. Grimes * modification, are permitted provided that the following conditions 7dea673e9SRodney W. Grimes * are met: 8dea673e9SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 9dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 10dea673e9SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 11dea673e9SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 12dea673e9SRodney W. Grimes * documentation and/or other materials provided with the distribution. 13dea673e9SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 14dea673e9SRodney W. Grimes * must display the following acknowledgement: 15dea673e9SRodney W. Grimes * This product includes software developed by the University of 16dea673e9SRodney W. Grimes * California, Berkeley and its contributors. 17dea673e9SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 18dea673e9SRodney W. Grimes * may be used to endorse or promote products derived from this software 19dea673e9SRodney W. Grimes * without specific prior written permission. 20dea673e9SRodney W. Grimes * 21dea673e9SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22dea673e9SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23dea673e9SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24dea673e9SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25dea673e9SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26dea673e9SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27dea673e9SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28dea673e9SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29dea673e9SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30dea673e9SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31dea673e9SRodney W. Grimes * SUCH DAMAGE. 32dea673e9SRodney W. Grimes */ 33dea673e9SRodney W. Grimes 34dea673e9SRodney W. Grimes #ifndef lint 35acb61b9eSPhilippe Charnier #if 0 3697fe7f47SJordan K. Hubbard static const char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94"; 37acb61b9eSPhilippe Charnier #endif 38acb61b9eSPhilippe Charnier static const char rcsid[] = 3997d92980SPeter Wemm "$FreeBSD$"; 40dea673e9SRodney W. Grimes #endif /* not lint */ 41dea673e9SRodney W. Grimes 42dea673e9SRodney W. Grimes /* 43dea673e9SRodney W. Grimes * This file is used by all the "password" programs; vipw(8), chpass(1), 44dea673e9SRodney W. Grimes * and passwd(1). 45dea673e9SRodney W. Grimes */ 46dea673e9SRodney W. Grimes 47dea673e9SRodney W. Grimes #include <sys/param.h> 484da8edd5SDag-Erling Smørgrav #include <sys/errno.h> 49dea673e9SRodney W. Grimes #include <sys/time.h> 50dea673e9SRodney W. Grimes #include <sys/resource.h> 51dea673e9SRodney W. Grimes #include <sys/stat.h> 52dea673e9SRodney W. Grimes #include <sys/wait.h> 53dea673e9SRodney W. Grimes 54dea673e9SRodney W. Grimes #include <err.h> 55dea673e9SRodney W. Grimes #include <fcntl.h> 56dea673e9SRodney W. Grimes #include <paths.h> 57dea673e9SRodney W. Grimes #include <pwd.h> 58dea673e9SRodney W. Grimes #include <signal.h> 59dea673e9SRodney W. Grimes #include <stdio.h> 60dea673e9SRodney W. Grimes #include <stdlib.h> 61dea673e9SRodney W. Grimes #include <string.h> 62dea673e9SRodney W. Grimes #include <unistd.h> 63dea673e9SRodney W. Grimes 64dea673e9SRodney W. Grimes #include "pw_util.h" 65dea673e9SRodney W. Grimes 66dea673e9SRodney W. Grimes extern char *tempname; 67b603d90cSAndrey A. Chernov static pid_t editpid = -1; 68b603d90cSAndrey A. Chernov static int lockfd; 69af2d5f9bSSheldon Hearn char *mppath = _PATH_PWD; 70af2d5f9bSSheldon Hearn char *masterpasswd = _PATH_MASTERPASSWD; 71b603d90cSAndrey A. Chernov 72b603d90cSAndrey A. Chernov void 73b603d90cSAndrey A. Chernov pw_cont(sig) 74b603d90cSAndrey A. Chernov int sig; 75b603d90cSAndrey A. Chernov { 76b603d90cSAndrey A. Chernov 77b603d90cSAndrey A. Chernov if (editpid != -1) 78b603d90cSAndrey A. Chernov kill(editpid, sig); 79b603d90cSAndrey A. Chernov } 80dea673e9SRodney W. Grimes 81dea673e9SRodney W. Grimes void 82dea673e9SRodney W. Grimes pw_init() 83dea673e9SRodney W. Grimes { 84dea673e9SRodney W. Grimes struct rlimit rlim; 85dea673e9SRodney W. Grimes 86dea673e9SRodney W. Grimes /* Unlimited resource limits. */ 87dea673e9SRodney W. Grimes rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; 88dea673e9SRodney W. Grimes (void)setrlimit(RLIMIT_CPU, &rlim); 89dea673e9SRodney W. Grimes (void)setrlimit(RLIMIT_FSIZE, &rlim); 90dea673e9SRodney W. Grimes (void)setrlimit(RLIMIT_STACK, &rlim); 91dea673e9SRodney W. Grimes (void)setrlimit(RLIMIT_DATA, &rlim); 92dea673e9SRodney W. Grimes (void)setrlimit(RLIMIT_RSS, &rlim); 93dea673e9SRodney W. Grimes 94dea673e9SRodney W. Grimes /* Don't drop core (not really necessary, but GP's). */ 95dea673e9SRodney W. Grimes rlim.rlim_cur = rlim.rlim_max = 0; 96dea673e9SRodney W. Grimes (void)setrlimit(RLIMIT_CORE, &rlim); 97dea673e9SRodney W. Grimes 98dea673e9SRodney W. Grimes /* Turn off signals. */ 99dea673e9SRodney W. Grimes (void)signal(SIGALRM, SIG_IGN); 100dea673e9SRodney W. Grimes (void)signal(SIGHUP, SIG_IGN); 101dea673e9SRodney W. Grimes (void)signal(SIGINT, SIG_IGN); 102dea673e9SRodney W. Grimes (void)signal(SIGPIPE, SIG_IGN); 103dea673e9SRodney W. Grimes (void)signal(SIGQUIT, SIG_IGN); 104dea673e9SRodney W. Grimes (void)signal(SIGTERM, SIG_IGN); 105b603d90cSAndrey A. Chernov (void)signal(SIGCONT, pw_cont); 1069d1163f7SPierre Beyssac 1079d1163f7SPierre Beyssac /* Create with exact permissions. */ 1089d1163f7SPierre Beyssac (void)umask(0); 109dea673e9SRodney W. Grimes } 110dea673e9SRodney W. Grimes 111dea673e9SRodney W. Grimes int 112dea673e9SRodney W. Grimes pw_lock() 113dea673e9SRodney W. Grimes { 114dea673e9SRodney W. Grimes /* 115dea673e9SRodney W. Grimes * If the master password file doesn't exist, the system is hosed. 116dea673e9SRodney W. Grimes * Might as well try to build one. Set the close-on-exec bit so 117dea673e9SRodney W. Grimes * that users can't get at the encrypted passwords while editing. 118dea673e9SRodney W. Grimes * Open should allow flock'ing the file; see 4.4BSD. XXX 119dea673e9SRodney W. Grimes */ 120f16d2ab2SMatthew Dillon for (;;) { 121f16d2ab2SMatthew Dillon struct stat st; 122f16d2ab2SMatthew Dillon 123af2d5f9bSSheldon Hearn lockfd = open(masterpasswd, O_RDONLY, 0); 124dea673e9SRodney W. Grimes if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) 125af2d5f9bSSheldon Hearn err(1, "%s", masterpasswd); 126dea673e9SRodney W. Grimes if (flock(lockfd, LOCK_EX|LOCK_NB)) 127dea673e9SRodney W. Grimes errx(1, "the password db file is busy"); 128f16d2ab2SMatthew Dillon 129f16d2ab2SMatthew Dillon /* 130f16d2ab2SMatthew Dillon * If the password file was replaced while we were trying to 131f16d2ab2SMatthew Dillon * get the lock, our hardlink count will be 0 and we have to 132f16d2ab2SMatthew Dillon * close and retry. 133f16d2ab2SMatthew Dillon */ 134f16d2ab2SMatthew Dillon if (fstat(lockfd, &st) < 0) 135f16d2ab2SMatthew Dillon errx(1, "fstat() failed"); 136f16d2ab2SMatthew Dillon if (st.st_nlink != 0) 137f16d2ab2SMatthew Dillon break; 138f16d2ab2SMatthew Dillon close(lockfd); 139f16d2ab2SMatthew Dillon lockfd = -1; 140f16d2ab2SMatthew Dillon } 141dea673e9SRodney W. Grimes return (lockfd); 142dea673e9SRodney W. Grimes } 143dea673e9SRodney W. Grimes 144dea673e9SRodney W. Grimes int 145dea673e9SRodney W. Grimes pw_tmp() 146dea673e9SRodney W. Grimes { 147af2d5f9bSSheldon Hearn static char path[MAXPATHLEN]; 148dea673e9SRodney W. Grimes int fd; 149dea673e9SRodney W. Grimes char *p; 150dea673e9SRodney W. Grimes 151af2d5f9bSSheldon Hearn strncpy(path, masterpasswd, MAXPATHLEN - 1); 152af2d5f9bSSheldon Hearn path[MAXPATHLEN] = '\0'; 153af2d5f9bSSheldon Hearn 15497fe7f47SJordan K. Hubbard if ((p = strrchr(path, '/'))) 155dea673e9SRodney W. Grimes ++p; 156dea673e9SRodney W. Grimes else 157dea673e9SRodney W. Grimes p = path; 158dea673e9SRodney W. Grimes strcpy(p, "pw.XXXXXX"); 159dea673e9SRodney W. Grimes if ((fd = mkstemp(path)) == -1) 160dea673e9SRodney W. Grimes err(1, "%s", path); 161dea673e9SRodney W. Grimes tempname = path; 162dea673e9SRodney W. Grimes return (fd); 163dea673e9SRodney W. Grimes } 164dea673e9SRodney W. Grimes 165dea673e9SRodney W. Grimes int 16679a1b8d9SGuido van Rooij pw_mkdb(username) 16779a1b8d9SGuido van Rooij char *username; 168dea673e9SRodney W. Grimes { 169dea673e9SRodney W. Grimes int pstat; 170dea673e9SRodney W. Grimes pid_t pid; 171dea673e9SRodney W. Grimes 172dea673e9SRodney W. Grimes (void)fflush(stderr); 1731fd98d7dSDag-Erling Smørgrav if (!(pid = fork())) { 17479a1b8d9SGuido van Rooij if(!username) { 1751818482dSJoerg Wunsch warnx("rebuilding the database..."); 176af2d5f9bSSheldon Hearn execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath, 177af2d5f9bSSheldon Hearn tempname, NULL); 17879a1b8d9SGuido van Rooij } else { 1791818482dSJoerg Wunsch warnx("updating the database..."); 180af2d5f9bSSheldon Hearn execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath, 181af2d5f9bSSheldon Hearn "-u", username, tempname, NULL); 18279a1b8d9SGuido van Rooij } 183dea673e9SRodney W. Grimes pw_error(_PATH_PWD_MKDB, 1, 1); 184dea673e9SRodney W. Grimes } 185dea673e9SRodney W. Grimes pid = waitpid(pid, &pstat, 0); 186dea673e9SRodney W. Grimes if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) 187dea673e9SRodney W. Grimes return (0); 188dea673e9SRodney W. Grimes warnx("done"); 189dea673e9SRodney W. Grimes return (1); 190dea673e9SRodney W. Grimes } 191dea673e9SRodney W. Grimes 192dea673e9SRodney W. Grimes void 193dea673e9SRodney W. Grimes pw_edit(notsetuid) 194dea673e9SRodney W. Grimes int notsetuid; 195dea673e9SRodney W. Grimes { 196dea673e9SRodney W. Grimes int pstat; 197dea673e9SRodney W. Grimes char *p, *editor; 198dea673e9SRodney W. Grimes 199dea673e9SRodney W. Grimes if (!(editor = getenv("EDITOR"))) 200dea673e9SRodney W. Grimes editor = _PATH_VI; 20197fe7f47SJordan K. Hubbard if ((p = strrchr(editor, '/'))) 202dea673e9SRodney W. Grimes ++p; 203dea673e9SRodney W. Grimes else 204dea673e9SRodney W. Grimes p = editor; 205dea673e9SRodney W. Grimes 2061fd98d7dSDag-Erling Smørgrav if (!(editpid = fork())) { 207dea673e9SRodney W. Grimes if (notsetuid) { 208dea673e9SRodney W. Grimes (void)setgid(getgid()); 209dea673e9SRodney W. Grimes (void)setuid(getuid()); 210dea673e9SRodney W. Grimes } 2114da8edd5SDag-Erling Smørgrav errno = 0; 212dea673e9SRodney W. Grimes execlp(editor, p, tempname, NULL); 2134da8edd5SDag-Erling Smørgrav _exit(errno); 214dea673e9SRodney W. Grimes } 215b603d90cSAndrey A. Chernov for (;;) { 216b603d90cSAndrey A. Chernov editpid = waitpid(editpid, (int *)&pstat, WUNTRACED); 2174da8edd5SDag-Erling Smørgrav errno = WEXITSTATUS(pstat); 218b603d90cSAndrey A. Chernov if (editpid == -1) 219dea673e9SRodney W. Grimes pw_error(editor, 1, 1); 220b603d90cSAndrey A. Chernov else if (WIFSTOPPED(pstat)) 221b603d90cSAndrey A. Chernov raise(WSTOPSIG(pstat)); 2224da8edd5SDag-Erling Smørgrav else if (WIFEXITED(pstat) && errno == 0) 223b603d90cSAndrey A. Chernov break; 224b603d90cSAndrey A. Chernov else 225b603d90cSAndrey A. Chernov pw_error(editor, 1, 1); 226b603d90cSAndrey A. Chernov } 227b603d90cSAndrey A. Chernov editpid = -1; 228dea673e9SRodney W. Grimes } 229dea673e9SRodney W. Grimes 230dea673e9SRodney W. Grimes void 231dea673e9SRodney W. Grimes pw_prompt() 232dea673e9SRodney W. Grimes { 2332af22b06SWolfram Schneider int c, first; 234dea673e9SRodney W. Grimes 235dea673e9SRodney W. Grimes (void)printf("re-edit the password file? [y]: "); 236dea673e9SRodney W. Grimes (void)fflush(stdout); 2372af22b06SWolfram Schneider first = c = getchar(); 2382af22b06SWolfram Schneider while (c != '\n' && c != EOF) 239dea673e9SRodney W. Grimes c = getchar(); 2402af22b06SWolfram Schneider if (first == 'n') 241dea673e9SRodney W. Grimes pw_error(NULL, 0, 0); 242dea673e9SRodney W. Grimes } 243dea673e9SRodney W. Grimes 244dea673e9SRodney W. Grimes void 245dea673e9SRodney W. Grimes pw_error(name, err, eval) 246dea673e9SRodney W. Grimes char *name; 247dea673e9SRodney W. Grimes int err, eval; 248dea673e9SRodney W. Grimes { 249d877befaSBill Paul #ifdef YP 250d877befaSBill Paul extern int _use_yp; 251d877befaSBill Paul #endif /* YP */ 2523babad2eSDima Dorfman if (err) { 2533babad2eSDima Dorfman if (name != NULL) 2540e0b415cSKris Kennaway warn("%s", name); 2553babad2eSDima Dorfman else 2563babad2eSDima Dorfman warn(NULL); 2573babad2eSDima Dorfman } 258d877befaSBill Paul #ifdef YP 259d877befaSBill Paul if (_use_yp) 260d877befaSBill Paul warnx("NIS information unchanged"); 261d877befaSBill Paul else 262d877befaSBill Paul #endif /* YP */ 263af2d5f9bSSheldon Hearn warnx("%s: unchanged", masterpasswd); 264dea673e9SRodney W. Grimes (void)unlink(tempname); 265dea673e9SRodney W. Grimes exit(eval); 266dea673e9SRodney W. Grimes } 267