pwupd.c revision 81977
116125Swpaul/*-
216125Swpaul * Copyright (C) 1996
316125Swpaul *	David L. Nugent.  All rights reserved.
416125Swpaul *
516125Swpaul * Redistribution and use in source and binary forms, with or without
616125Swpaul * modification, are permitted provided that the following conditions
716125Swpaul * are met:
816125Swpaul * 1. Redistributions of source code must retain the above copyright
916125Swpaul *    notice, this list of conditions and the following disclaimer.
1016125Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1116125Swpaul *    notice, this list of conditions and the following disclaimer in the
1216125Swpaul *    documentation and/or other materials provided with the distribution.
1316125Swpaul *
1416125Swpaul * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
1516125Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1616125Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1716125Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
1816125Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1916125Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2016125Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2116125Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2216125Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2316125Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2416125Swpaul * SUCH DAMAGE.
2516125Swpaul */
2616125Swpaul
2716125Swpaul#ifndef lint
2816125Swpaulstatic const char rcsid[] =
2916125Swpaul  "$FreeBSD: head/usr.sbin/pw/pwupd.c 81977 2001-08-20 13:24:39Z brian $";
3016125Swpaul#endif /* not lint */
3116125Swpaul
3216125Swpaul#include <stdio.h>
3330378Scharnier#include <stdlib.h>
3430378Scharnier#include <string.h>
3550479Speter#include <unistd.h>
3630378Scharnier#include <stdarg.h>
3730378Scharnier#include <errno.h>
3816125Swpaul#include <sys/types.h>
3930378Scharnier#include <sys/stat.h>
4030378Scharnier#include <sys/param.h>
4169793Sobrien#include <sys/wait.h>
4216125Swpaul
4316125Swpaul#include "pwupd.h"
4423716Speter
4516125Swpaul#define HAVE_PWDB_C	1
4616125Swpaul#define	HAVE_PWDB_U	1
4716125Swpaul
4816125Swpaulstatic char pathpwd[] = _PATH_PWD;
4916125Swpaulstatic char * pwpath = pathpwd;
5016125Swpaul
5116125Swpaulint
5216125Swpaulsetpwdir(const char * dir)
5316125Swpaul{
5416125Swpaul	if (dir == NULL)
5516125Swpaul		return -1;
5616125Swpaul	else {
5716125Swpaul		char * d = malloc(strlen(dir)+1);
5816125Swpaul		if (d == NULL)
5916125Swpaul			return -1;
6016125Swpaul		pwpath = strcpy(d, dir);
6116125Swpaul	}
6216125Swpaul	return 0;
6316125Swpaul}
6416125Swpaul
6516125Swpaulchar *
6616125Swpaulgetpwpath(char const * file)
6716125Swpaul{
6816125Swpaul	static char pathbuf[MAXPATHLEN];
6916125Swpaul
7016125Swpaul	snprintf(pathbuf, sizeof pathbuf, "%s/%s", pwpath, file);
7116125Swpaul	return pathbuf;
7216125Swpaul}
7316125Swpaul
7416125Swpaulint
7516125Swpaulpwdb(char *arg,...)
7616125Swpaul{
7716125Swpaul	int             i = 0;
7816125Swpaul	pid_t           pid;
7916125Swpaul	va_list         ap;
8016125Swpaul	char           *args[10];
8116125Swpaul
8216125Swpaul	args[i++] = _PATH_PWD_MKDB;
8316125Swpaul	va_start(ap, arg);
8416125Swpaul	while (i < 6 && arg != NULL) {
8516125Swpaul		args[i++] = arg;
8616125Swpaul		arg = va_arg(ap, char *);
8716125Swpaul	}
8862989Skris	if (pwpath != pathpwd) {
8916125Swpaul		args[i++] = "-d";
9030378Scharnier		args[i++] = pwpath;
9116125Swpaul	}
9262989Skris	args[i++] = getpwpath(_MASTERPASSWD);
9316125Swpaul	args[i] = NULL;
9416125Swpaul
9516125Swpaul	if ((pid = fork()) == -1)	/* Error (errno set) */
9616125Swpaul		i = errno;
9716125Swpaul	else if (pid == 0) {	/* Child */
9816125Swpaul		execv(args[0], args);
9916125Swpaul		_exit(1);
10016125Swpaul	} else {		/* Parent */
10116125Swpaul		waitpid(pid, &i, 0);
10216125Swpaul		if (WEXITSTATUS(i))
10316125Swpaul			i = EIO;
10416125Swpaul	}
10516125Swpaul	return i;
10616125Swpaul}
10716125Swpaul
10816125Swpaulint
10916125Swpaulfmtpwentry(char *buf, struct passwd * pwd, int type)
11016125Swpaul{
11116125Swpaul	int             l;
11216125Swpaul	char           *pw;
11316125Swpaul
11416125Swpaul	pw = (pwd->pw_passwd == NULL || !*pwd->pw_passwd) ? "" : (type == PWF_MASTER) ? pwd->pw_passwd : "*";
11516125Swpaul
11616125Swpaul	if (type == PWF_PASSWD)
11716125Swpaul		l = sprintf(buf, "%s:*:%ld:%ld:%s:%s:%s\n",
11816125Swpaul		       pwd->pw_name, (long) pwd->pw_uid, (long) pwd->pw_gid,
11916125Swpaul			    pwd->pw_gecos ? pwd->pw_gecos : "User &",
12016125Swpaul			    pwd->pw_dir, pwd->pw_shell);
12116125Swpaul	else
12216125Swpaul		l = sprintf(buf, "%s:%s:%ld:%ld:%s:%lu:%lu:%s:%s:%s\n",
12316125Swpaul		   pwd->pw_name, pw, (long) pwd->pw_uid, (long) pwd->pw_gid,
12416125Swpaul			    pwd->pw_class ? pwd->pw_class : "",
12516125Swpaul			    (unsigned long) pwd->pw_change,
12616125Swpaul			    (unsigned long) pwd->pw_expire,
12716125Swpaul			    pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
12816125Swpaul	return l;
12916125Swpaul}
13016125Swpaul
13116125Swpaul
13216125Swpaulint
13316125Swpaulfmtpwent(char *buf, struct passwd * pwd)
13416125Swpaul{
13516125Swpaul	return fmtpwentry(buf, pwd, PWF_STANDARD);
13616125Swpaul}
13716125Swpaul
13816125Swpaulstatic int
13916125Swpaulpw_update(struct passwd * pwd, char const * user, int mode)
14016125Swpaul{
14116125Swpaul	int             rc = 0;
14216125Swpaul
14316125Swpaul	ENDPWENT();
14416125Swpaul
14516125Swpaul	/*
14616125Swpaul	 * First, let's check the see if the database is alright
14716125Swpaul	 * Note: -C is only available in FreeBSD 2.2 and above
14816125Swpaul	 */
14916125Swpaul#ifdef HAVE_PWDB_C
15030378Scharnier	if (pwdb("-C", NULL) == 0) {	/* Check only */
15116125Swpaul#else
15216125Swpaul	{				/* No -C */
15316125Swpaul#endif
15416125Swpaul		char            pfx[PWBUFSZ];
15516125Swpaul		char            pwbuf[PWBUFSZ];
15616125Swpaul		int             l = snprintf(pfx, PWBUFSZ, "%s:", user);
15716125Swpaul#ifdef HAVE_PWDB_U
15816125Swpaul		int		isrename = pwd!=NULL && strcmp(user, pwd->pw_name);
15916125Swpaul#endif
16016125Swpaul
16116125Swpaul		/*
16216125Swpaul		 * Update the passwd file first
16316125Swpaul		 */
16416125Swpaul		if (pwd == NULL)
16536642Swpaul			*pwbuf = '\0';
16636642Swpaul		else
16716125Swpaul			fmtpwentry(pwbuf, pwd, PWF_PASSWD);
16836642Swpaul
16936642Swpaul		if (l == -1)
17016125Swpaul			l = 0;
17116125Swpaul		rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode);
17236642Swpaul		if (rc == 0) {
17316125Swpaul
17416125Swpaul			/*
17516125Swpaul			 * Then the master.passwd file
17616125Swpaul			 */
17716125Swpaul			if (pwd != NULL)
17816125Swpaul				fmtpwentry(pwbuf, pwd, PWF_MASTER);
17916125Swpaul			rc = fileupdate(getpwpath(_MASTERPASSWD), 0644, pwbuf, pfx, l, mode);
18016125Swpaul			if (rc == 0) {
18116125Swpaul#ifdef HAVE_PWDB_U
18216125Swpaul				if (mode == UPD_DELETE || isrename)
18336642Swpaul#endif
18436642Swpaul					rc = pwdb(NULL);
18536642Swpaul#ifdef HAVE_PWDB_U
18616125Swpaul				else
18716125Swpaul					rc = pwdb("-u", user, NULL);
18816125Swpaul#endif
18916125Swpaul			}
19030378Scharnier		}
19116125Swpaul	}
19216125Swpaul	return rc;
19316125Swpaul}
19430378Scharnier
19516125Swpaulint
19616125Swpauladdpwent(struct passwd * pwd)
19716125Swpaul{
19816125Swpaul	return pw_update(pwd, pwd->pw_name, UPD_CREATE);
19930378Scharnier}
20016125Swpaul
20130378Scharnierint
20216125Swpaulchgpwent(char const * login, struct passwd * pwd)
20316125Swpaul{
20416125Swpaul	return pw_update(pwd, login, UPD_REPLACE);
20516125Swpaul}
20624428Simp
20790297Sdesint
20816125Swpauldelpwent(struct passwd * pwd)
20916125Swpaul{
21016125Swpaul	return pw_update(NULL, pwd->pw_name, UPD_DELETE);
21116125Swpaul}
21216125Swpaul