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