pw_util.c revision 75821
11553Srgrimes/*- 21553Srgrimes * Copyright (c) 1990, 1993, 1994 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 341553Srgrimes#ifndef lint 3530765Scharnier#if 0 3630113Sjkhstatic const char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94"; 3730765Scharnier#endif 3830765Scharnierstatic const char rcsid[] = 3950479Speter "$FreeBSD: head/lib/libutil/pw_util.c 75821 2001-04-22 03:00:09Z dd $"; 401553Srgrimes#endif /* not lint */ 411553Srgrimes 421553Srgrimes/* 431553Srgrimes * This file is used by all the "password" programs; vipw(8), chpass(1), 441553Srgrimes * and passwd(1). 451553Srgrimes */ 461553Srgrimes 471553Srgrimes#include <sys/param.h> 4840538Sdes#include <sys/errno.h> 491553Srgrimes#include <sys/time.h> 501553Srgrimes#include <sys/resource.h> 511553Srgrimes#include <sys/stat.h> 521553Srgrimes#include <sys/wait.h> 531553Srgrimes 541553Srgrimes#include <err.h> 551553Srgrimes#include <fcntl.h> 561553Srgrimes#include <paths.h> 571553Srgrimes#include <pwd.h> 581553Srgrimes#include <signal.h> 591553Srgrimes#include <stdio.h> 601553Srgrimes#include <stdlib.h> 611553Srgrimes#include <string.h> 621553Srgrimes#include <unistd.h> 631553Srgrimes 641553Srgrimes#include "pw_util.h" 651553Srgrimes 661553Srgrimesextern char *tempname; 676972Sachestatic pid_t editpid = -1; 686972Sachestatic int lockfd; 6948232Ssheldonhchar *mppath = _PATH_PWD; 7048232Ssheldonhchar *masterpasswd = _PATH_MASTERPASSWD; 711553Srgrimes 721553Srgrimesvoid 736972Sachepw_cont(sig) 746972Sache int sig; 756972Sache{ 766972Sache 776972Sache if (editpid != -1) 786972Sache kill(editpid, sig); 796972Sache} 806972Sache 816972Sachevoid 821553Srgrimespw_init() 831553Srgrimes{ 841553Srgrimes struct rlimit rlim; 851553Srgrimes 861553Srgrimes /* Unlimited resource limits. */ 871553Srgrimes rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; 881553Srgrimes (void)setrlimit(RLIMIT_CPU, &rlim); 891553Srgrimes (void)setrlimit(RLIMIT_FSIZE, &rlim); 901553Srgrimes (void)setrlimit(RLIMIT_STACK, &rlim); 911553Srgrimes (void)setrlimit(RLIMIT_DATA, &rlim); 921553Srgrimes (void)setrlimit(RLIMIT_RSS, &rlim); 931553Srgrimes 941553Srgrimes /* Don't drop core (not really necessary, but GP's). */ 951553Srgrimes rlim.rlim_cur = rlim.rlim_max = 0; 961553Srgrimes (void)setrlimit(RLIMIT_CORE, &rlim); 971553Srgrimes 981553Srgrimes /* Turn off signals. */ 991553Srgrimes (void)signal(SIGALRM, SIG_IGN); 1001553Srgrimes (void)signal(SIGHUP, SIG_IGN); 1011553Srgrimes (void)signal(SIGINT, SIG_IGN); 1021553Srgrimes (void)signal(SIGPIPE, SIG_IGN); 1031553Srgrimes (void)signal(SIGQUIT, SIG_IGN); 1041553Srgrimes (void)signal(SIGTERM, SIG_IGN); 1056972Sache (void)signal(SIGCONT, pw_cont); 10648328Spb 10748328Spb /* Create with exact permissions. */ 10848328Spb (void)umask(0); 1091553Srgrimes} 1101553Srgrimes 1111553Srgrimesint 1121553Srgrimespw_lock() 1131553Srgrimes{ 1148857Srgrimes /* 1151553Srgrimes * If the master password file doesn't exist, the system is hosed. 1161553Srgrimes * Might as well try to build one. Set the close-on-exec bit so 1171553Srgrimes * that users can't get at the encrypted passwords while editing. 1181553Srgrimes * Open should allow flock'ing the file; see 4.4BSD. XXX 1191553Srgrimes */ 12041710Sdillon for (;;) { 12141711Sdillon struct stat st; 12241710Sdillon 12348232Ssheldonh lockfd = open(masterpasswd, O_RDONLY, 0); 12441711Sdillon if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) 12548232Ssheldonh err(1, "%s", masterpasswd); 12641711Sdillon if (flock(lockfd, LOCK_EX|LOCK_NB)) 12741711Sdillon errx(1, "the password db file is busy"); 12841710Sdillon 12941711Sdillon /* 13041711Sdillon * If the password file was replaced while we were trying to 13141711Sdillon * get the lock, our hardlink count will be 0 and we have to 13241711Sdillon * close and retry. 13341711Sdillon */ 13441711Sdillon if (fstat(lockfd, &st) < 0) 13541711Sdillon errx(1, "fstat() failed"); 13641711Sdillon if (st.st_nlink != 0) 13741711Sdillon break; 13841711Sdillon close(lockfd); 13941711Sdillon lockfd = -1; 14041710Sdillon } 1411553Srgrimes return (lockfd); 1421553Srgrimes} 1431553Srgrimes 1441553Srgrimesint 1451553Srgrimespw_tmp() 1461553Srgrimes{ 14748232Ssheldonh static char path[MAXPATHLEN]; 1481553Srgrimes int fd; 1491553Srgrimes char *p; 1501553Srgrimes 15148232Ssheldonh strncpy(path, masterpasswd, MAXPATHLEN - 1); 15248232Ssheldonh path[MAXPATHLEN] = '\0'; 15348232Ssheldonh 15430113Sjkh if ((p = strrchr(path, '/'))) 1551553Srgrimes ++p; 1561553Srgrimes else 1571553Srgrimes p = path; 1581553Srgrimes strcpy(p, "pw.XXXXXX"); 1591553Srgrimes if ((fd = mkstemp(path)) == -1) 1601553Srgrimes err(1, "%s", path); 1611553Srgrimes tempname = path; 1621553Srgrimes return (fd); 1631553Srgrimes} 1641553Srgrimes 1651553Srgrimesint 16616876Sguidopw_mkdb(username) 16716876Sguidochar *username; 1681553Srgrimes{ 1691553Srgrimes int pstat; 1701553Srgrimes pid_t pid; 1711553Srgrimes 1721553Srgrimes (void)fflush(stderr); 17340301Sdes if (!(pid = fork())) { 17416876Sguido if(!username) { 17528662Sjoerg warnx("rebuilding the database..."); 17648232Ssheldonh execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath, 17748232Ssheldonh tempname, NULL); 17816876Sguido } else { 17928662Sjoerg warnx("updating the database..."); 18048232Ssheldonh execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath, 18148232Ssheldonh "-u", username, tempname, NULL); 18216876Sguido } 1831553Srgrimes pw_error(_PATH_PWD_MKDB, 1, 1); 1841553Srgrimes } 1851553Srgrimes pid = waitpid(pid, &pstat, 0); 1861553Srgrimes if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) 1871553Srgrimes return (0); 1881553Srgrimes warnx("done"); 1891553Srgrimes return (1); 1901553Srgrimes} 1911553Srgrimes 1921553Srgrimesvoid 1931553Srgrimespw_edit(notsetuid) 1941553Srgrimes int notsetuid; 1951553Srgrimes{ 1961553Srgrimes int pstat; 1971553Srgrimes char *p, *editor; 1981553Srgrimes 1991553Srgrimes if (!(editor = getenv("EDITOR"))) 2001553Srgrimes editor = _PATH_VI; 20130113Sjkh if ((p = strrchr(editor, '/'))) 2021553Srgrimes ++p; 2038857Srgrimes else 2041553Srgrimes p = editor; 2051553Srgrimes 20640301Sdes if (!(editpid = fork())) { 2071553Srgrimes if (notsetuid) { 2081553Srgrimes (void)setgid(getgid()); 2091553Srgrimes (void)setuid(getuid()); 2101553Srgrimes } 21140538Sdes errno = 0; 2121553Srgrimes execlp(editor, p, tempname, NULL); 21340538Sdes _exit(errno); 2141553Srgrimes } 2156972Sache for (;;) { 2166972Sache editpid = waitpid(editpid, (int *)&pstat, WUNTRACED); 21740538Sdes errno = WEXITSTATUS(pstat); 2186972Sache if (editpid == -1) 2196972Sache pw_error(editor, 1, 1); 2206972Sache else if (WIFSTOPPED(pstat)) 2216972Sache raise(WSTOPSIG(pstat)); 22240538Sdes else if (WIFEXITED(pstat) && errno == 0) 2236972Sache break; 2246972Sache else 2256972Sache pw_error(editor, 1, 1); 2266972Sache } 2276972Sache editpid = -1; 2281553Srgrimes} 2291553Srgrimes 2301553Srgrimesvoid 2311553Srgrimespw_prompt() 2321553Srgrimes{ 23329980Swosch int c, first; 2341553Srgrimes 2351553Srgrimes (void)printf("re-edit the password file? [y]: "); 2361553Srgrimes (void)fflush(stdout); 23729980Swosch first = c = getchar(); 23829980Swosch while (c != '\n' && c != EOF) 23929980Swosch c = getchar(); 24029980Swosch if (first == 'n') 2411553Srgrimes pw_error(NULL, 0, 0); 2421553Srgrimes} 2431553Srgrimes 2441553Srgrimesvoid 2451553Srgrimespw_error(name, err, eval) 2461553Srgrimes char *name; 2471553Srgrimes int err, eval; 2481553Srgrimes{ 24910048Swpaul#ifdef YP 25010048Swpaul extern int _use_yp; 25110048Swpaul#endif /* YP */ 25275821Sdd if (err) { 25375821Sdd if (name != NULL) 25475821Sdd warn("%s", name); 25575821Sdd else 25675821Sdd warn(NULL); 25775821Sdd } 25810048Swpaul#ifdef YP 25910048Swpaul if (_use_yp) 26010048Swpaul warnx("NIS information unchanged"); 26110048Swpaul else 26210048Swpaul#endif /* YP */ 26348232Ssheldonh warnx("%s: unchanged", masterpasswd); 2641553Srgrimes (void)unlink(tempname); 2651553Srgrimes exit(eval); 2661553Srgrimes} 267