1 /*- 2 * Copyright (c) 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 04/02/94"; 10 #endif /* not lint */ 11 12 /* 13 * This file is used by all the "password" programs; vipw(8), chpass(1), 14 * and passwd(1). 15 */ 16 17 #include <sys/param.h> 18 #include <sys/time.h> 19 #include <sys/resource.h> 20 #include <sys/stat.h> 21 #include <sys/wait.h> 22 23 #include <err.h> 24 #include <errno.h> 25 #include <fcntl.h> 26 #include <paths.h> 27 #include <pwd.h> 28 #include <signal.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #include "pw_util.h" 35 36 extern char *tempname; 37 38 void 39 pw_init() 40 { 41 struct rlimit rlim; 42 43 /* Unlimited resource limits. */ 44 rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; 45 (void)setrlimit(RLIMIT_CPU, &rlim); 46 (void)setrlimit(RLIMIT_FSIZE, &rlim); 47 (void)setrlimit(RLIMIT_STACK, &rlim); 48 (void)setrlimit(RLIMIT_DATA, &rlim); 49 (void)setrlimit(RLIMIT_RSS, &rlim); 50 51 /* Don't drop core (not really necessary, but GP's). */ 52 rlim.rlim_cur = rlim.rlim_max = 0; 53 (void)setrlimit(RLIMIT_CORE, &rlim); 54 55 /* Turn off signals. */ 56 (void)signal(SIGALRM, SIG_IGN); 57 (void)signal(SIGHUP, SIG_IGN); 58 (void)signal(SIGINT, SIG_IGN); 59 (void)signal(SIGPIPE, SIG_IGN); 60 (void)signal(SIGQUIT, SIG_IGN); 61 (void)signal(SIGTERM, SIG_IGN); 62 (void)signal(SIGTSTP, SIG_IGN); 63 (void)signal(SIGTTOU, SIG_IGN); 64 65 /* Create with exact permissions. */ 66 (void)umask(0); 67 } 68 69 static int lockfd; 70 71 int 72 pw_lock() 73 { 74 /* 75 * If the master password file doesn't exist, the system is hosed. 76 * Might as well try to build one. Set the close-on-exec bit so 77 * that users can't get at the encrypted passwords while editing. 78 * Open should allow flock'ing the file; see 4.4BSD. XXX 79 */ 80 lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); 81 if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) 82 err(1, "%s", _PATH_MASTERPASSWD); 83 if (flock(lockfd, LOCK_EX|LOCK_NB)) 84 errx(1, "the password db file is busy"); 85 return (lockfd); 86 } 87 88 int 89 pw_tmp() 90 { 91 static char path[MAXPATHLEN] = _PATH_MASTERPASSWD; 92 int fd; 93 char *p; 94 95 if (p = strrchr(path, '/')) 96 ++p; 97 else 98 p = path; 99 strcpy(p, "pw.XXXXXX"); 100 if ((fd = mkstemp(path)) == -1) 101 err(1, "%s", path); 102 tempname = path; 103 return (fd); 104 } 105 106 int 107 pw_mkdb() 108 { 109 int pstat; 110 pid_t pid; 111 112 warnx("rebuilding the database..."); 113 (void)fflush(stderr); 114 if (!(pid = vfork())) { 115 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL); 116 pw_error(_PATH_PWD_MKDB, 1, 1); 117 } 118 pid = waitpid(pid, &pstat, 0); 119 if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) 120 return (0); 121 warnx("done"); 122 return (1); 123 } 124 125 void 126 pw_edit(notsetuid) 127 int notsetuid; 128 { 129 int pstat; 130 pid_t pid; 131 char *p, *editor; 132 133 if (!(editor = getenv("EDITOR"))) 134 editor = _PATH_VI; 135 if (p = strrchr(editor, '/')) 136 ++p; 137 else 138 p = editor; 139 140 if (!(pid = vfork())) { 141 if (notsetuid) { 142 (void)setgid(getgid()); 143 (void)setuid(getuid()); 144 } 145 execlp(editor, p, tempname, NULL); 146 _exit(1); 147 } 148 pid = waitpid(pid, (int *)&pstat, 0); 149 if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) 150 pw_error(editor, 1, 1); 151 } 152 153 void 154 pw_prompt() 155 { 156 int c; 157 158 (void)printf("re-edit the password file? [y]: "); 159 (void)fflush(stdout); 160 c = getchar(); 161 if (c != EOF && c != '\n') 162 while (getchar() != '\n'); 163 if (c == 'n') 164 pw_error(NULL, 0, 0); 165 } 166 167 void 168 pw_error(name, err, eval) 169 char *name; 170 int err, eval; 171 { 172 if (err) 173 warn(name); 174 175 warnx("%s: unchanged", _PATH_MASTERPASSWD); 176 (void)unlink(tempname); 177 exit(eval); 178 } 179