pwupd.c revision 81982
1104476Ssam/*- 2139825Simp * Copyright (C) 1996 3104476Ssam * David L. Nugent. All rights reserved. 4104476Ssam * 5104476Ssam * Redistribution and use in source and binary forms, with or without 6104476Ssam * modification, are permitted provided that the following conditions 7104476Ssam * are met: 8104476Ssam * 1. Redistributions of source code must retain the above copyright 9104476Ssam * notice, this list of conditions and the following disclaimer. 10104476Ssam * 2. Redistributions in binary form must reproduce the above copyright 11104476Ssam * notice, this list of conditions and the following disclaimer in the 12104476Ssam * documentation and/or other materials provided with the distribution. 13104476Ssam * 14104476Ssam * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND 15116191Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16116191Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17116191Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 18104476Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19104476Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20104476Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21104476Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22104476Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23104476Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24104476Ssam * SUCH DAMAGE. 25104476Ssam */ 26104476Ssam 27104476Ssam#ifndef lint 28104476Ssamstatic const char rcsid[] = 29104476Ssam "$FreeBSD: head/usr.sbin/pw/pwupd.c 81982 2001-08-20 15:09:34Z brian $"; 30104476Ssam#endif /* not lint */ 31104476Ssam 32104476Ssam#include <stdio.h> 33104476Ssam#include <stdlib.h> 34104476Ssam#include <string.h> 35104476Ssam#include <unistd.h> 36104476Ssam#include <stdarg.h> 37104476Ssam#include <errno.h> 38104476Ssam#include <sys/types.h> 39104476Ssam#include <sys/stat.h> 40104476Ssam#include <sys/param.h> 41104476Ssam#include <sys/wait.h> 42104476Ssam 43104476Ssam#include "pwupd.h" 44104476Ssam 45104476Ssam#define HAVE_PWDB_C 1 46104476Ssam#define HAVE_PWDB_U 1 47104476Ssam 48104476Ssamstatic char pathpwd[] = _PATH_PWD; 49104476Ssamstatic char * pwpath = pathpwd; 50104476Ssam 51104476Ssamint 52104476Ssamsetpwdir(const char * dir) 53104476Ssam{ 54104476Ssam if (dir == NULL) 55104476Ssam return -1; 56104476Ssam else { 57104476Ssam char * d = malloc(strlen(dir)+1); 58104476Ssam if (d == NULL) 59104476Ssam return -1; 60104476Ssam pwpath = strcpy(d, dir); 61104476Ssam } 62104476Ssam return 0; 63104476Ssam} 64104476Ssam 65104476Ssamchar * 66116191Sobriengetpwpath(char const * file) 67104476Ssam{ 68104476Ssam static char pathbuf[MAXPATHLEN]; 69104476Ssam 70104476Ssam snprintf(pathbuf, sizeof pathbuf, "%s/%s", pwpath, file); 71104476Ssam return pathbuf; 72104476Ssam} 73104476Ssam 74104476Ssamint 75104476Ssampwdb(char *arg,...) 76104476Ssam{ 77104476Ssam int i = 0; 78104476Ssam pid_t pid; 79104476Ssam va_list ap; 80104476Ssam char *args[10]; 81104476Ssam 82104476Ssam args[i++] = _PATH_PWD_MKDB; 83104476Ssam va_start(ap, arg); 84104476Ssam while (i < 6 && arg != NULL) { 85104476Ssam args[i++] = arg; 86104476Ssam arg = va_arg(ap, char *); 87104476Ssam } 88104476Ssam if (pwpath != pathpwd) { 89104476Ssam args[i++] = "-d"; 90104476Ssam args[i++] = pwpath; 91104476Ssam } 92104476Ssam args[i++] = getpwpath(_MASTERPASSWD); 93104476Ssam args[i] = NULL; 94104476Ssam 95104476Ssam if ((pid = fork()) == -1) /* Error (errno set) */ 96104476Ssam i = errno; 97104476Ssam else if (pid == 0) { /* Child */ 98104476Ssam execv(args[0], args); 99104476Ssam _exit(1); 100104476Ssam } else { /* Parent */ 101104476Ssam waitpid(pid, &i, 0); 102104476Ssam if (WEXITSTATUS(i)) 103104476Ssam i = EIO; 104104476Ssam } 105104476Ssam return i; 106104476Ssam} 107104476Ssam 108104476Ssamint 109104476Ssamfmtpwentry(char *buf, struct passwd * pwd, int type) 110104476Ssam{ 111104476Ssam int l; 112104476Ssam char *pw; 113104476Ssam 114104476Ssam pw = (pwd->pw_passwd == NULL || !*pwd->pw_passwd) ? "" : (type == PWF_MASTER) ? pwd->pw_passwd : "*"; 115104476Ssam 116104476Ssam if (type == PWF_PASSWD) 117104476Ssam l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n", 118104476Ssam pwd->pw_name, (long) pwd->pw_uid, (long) pwd->pw_gid, 119104476Ssam pwd->pw_gecos ? pwd->pw_gecos : "User &", 120104476Ssam pwd->pw_dir, pwd->pw_shell); 121104476Ssam else 122104476Ssam l = sprintf(buf, "%s:%s:%ld:%ld:%s:%lu:%lu:%s:%s:%s\n", 123104476Ssam pwd->pw_name, pw, (long) pwd->pw_uid, (long) pwd->pw_gid, 124104476Ssam pwd->pw_class ? pwd->pw_class : "", 125104476Ssam (unsigned long) pwd->pw_change, 126104476Ssam (unsigned long) pwd->pw_expire, 127104476Ssam pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); 128104476Ssam return l; 129104476Ssam} 130104476Ssam 131104476Ssam 132104476Ssamint 133104476Ssamfmtpwent(char *buf, struct passwd * pwd) 134104476Ssam{ 135104476Ssam return fmtpwentry(buf, pwd, PWF_STANDARD); 136104476Ssam} 137104476Ssam 138104476Ssamstatic int 139104476Ssampw_update(struct passwd * pwd, char const * user, int mode) 140104476Ssam{ 141104476Ssam int rc = 0; 142104476Ssam 143104476Ssam ENDPWENT(); 144104476Ssam 145104476Ssam /* 146104476Ssam * First, let's check the see if the database is alright 147104476Ssam * Note: -C is only available in FreeBSD 2.2 and above 148104476Ssam */ 149104476Ssam#ifdef HAVE_PWDB_C 150104476Ssam if (pwdb("-C", NULL) == 0) { /* Check only */ 151104476Ssam#else 152104476Ssam { /* No -C */ 153104476Ssam#endif 154104476Ssam char pfx[PWBUFSZ]; 155104476Ssam char pwbuf[PWBUFSZ]; 156104476Ssam int l = snprintf(pfx, PWBUFSZ, "%s:", user); 157104476Ssam#ifdef HAVE_PWDB_U 158104476Ssam int isrename = pwd!=NULL && strcmp(user, pwd->pw_name); 159104476Ssam#endif 160104476Ssam 161104476Ssam /* 162104476Ssam * Update the passwd file first 163104476Ssam */ 164104476Ssam if (pwd == NULL) 165104476Ssam *pwbuf = '\0'; 166104476Ssam else 167104476Ssam fmtpwentry(pwbuf, pwd, PWF_PASSWD); 168104476Ssam 169104476Ssam if (l < 0) 170104476Ssam l = 0; 171104476Ssam rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode); 172104476Ssam if (rc == 0) { 173104476Ssam 174104476Ssam /* 175104476Ssam * Then the master.passwd file 176104476Ssam */ 177104476Ssam if (pwd != NULL) 178104476Ssam fmtpwentry(pwbuf, pwd, PWF_MASTER); 179104476Ssam rc = fileupdate(getpwpath(_MASTERPASSWD), 0644, pwbuf, pfx, l, mode); 180104476Ssam if (rc == 0) { 181104476Ssam#ifdef HAVE_PWDB_U 182104476Ssam if (mode == UPD_DELETE || isrename) 183104476Ssam#endif 184104476Ssam rc = pwdb(NULL); 185104476Ssam#ifdef HAVE_PWDB_U 186104476Ssam else 187104476Ssam rc = pwdb("-u", user, NULL); 188104476Ssam#endif 189104476Ssam } 190104476Ssam } 191104476Ssam } 192104476Ssam return rc; 193104476Ssam} 194104476Ssam 195104476Ssamint 196104476Ssamaddpwent(struct passwd * pwd) 197104476Ssam{ 198104476Ssam return pw_update(pwd, pwd->pw_name, UPD_CREATE); 199104476Ssam} 200104476Ssam 201104476Ssamint 202104476Ssamchgpwent(char const * login, struct passwd * pwd) 203104476Ssam{ 204104476Ssam return pw_update(pwd, login, UPD_REPLACE); 205104476Ssam} 206104476Ssam 207104476Ssamint 208104476Ssamdelpwent(struct passwd * pwd) 209104476Ssam{ 210104476Ssam return pw_update(NULL, pwd->pw_name, UPD_DELETE); 211104476Ssam} 212104476Ssam