chpass.c revision 1.4
1/*	$OpenBSD: chpass.c,v 1.4 1996/08/31 01:55:32 deraadt Exp $	*/
2/*	$NetBSD: chpass.c,v 1.8 1996/05/15 21:50:43 jtc Exp $	*/
3
4/*-
5 * Copyright (c) 1988, 1993, 1994
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char copyright[] =
39"@(#) Copyright (c) 1988, 1993, 1994\n\
40	The Regents of the University of California.  All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44#if 0
45static char sccsid[] = "@(#)chpass.c	8.4 (Berkeley) 4/2/94";
46#else
47static char rcsid[] = "$OpenBSD: chpass.c,v 1.4 1996/08/31 01:55:32 deraadt Exp $";
48#endif
49#endif /* not lint */
50
51#include <sys/param.h>
52#include <sys/stat.h>
53#include <sys/time.h>
54#include <sys/resource.h>
55
56#include <ctype.h>
57#include <err.h>
58#include <errno.h>
59#include <fcntl.h>
60#include <pwd.h>
61#include <stdio.h>
62#include <stdlib.h>
63#include <string.h>
64#include <unistd.h>
65#include <util.h>
66
67#include "chpass.h"
68#include "pathnames.h"
69
70char *progname = "chpass";
71char *tempname;
72uid_t uid;
73
74#ifdef	YP
75int use_yp;
76int force_yp = 0;
77extern struct passwd *ypgetpwnam(), *ypgetpwuid();
78#endif
79
80void	baduser __P((void));
81void	usage __P((void));
82
83int
84main(argc, argv)
85	int argc;
86	char **argv;
87{
88	enum { NEWSH, LOADENTRY, EDITENTRY } op;
89	struct passwd *pw, lpw;
90	int ch, pfd, tfd, dfd;
91	char *arg, tempname[] = "/etc/pw.XXXXXX";
92
93#ifdef	YP
94	use_yp = _yp_check(NULL);
95#endif
96
97	op = EDITENTRY;
98	while ((ch = getopt(argc, argv, "a:s:ly")) != EOF)
99		switch(ch) {
100		case 'a':
101			op = LOADENTRY;
102			arg = optarg;
103			break;
104		case 's':
105			op = NEWSH;
106			arg = optarg;
107			break;
108#ifdef	YP
109		case 'l':
110			use_yp = 0;
111			break;
112		case 'y':
113			if (!use_yp) {
114				warnx("YP not in use.");
115				usage();
116			}
117			force_yp = 1;
118			break;
119#endif
120		case '?':
121		default:
122			usage();
123		}
124	argc -= optind;
125	argv += optind;
126
127#ifdef	YP
128	if (op == LOADENTRY && use_yp)
129		errx(1, "cannot load entry using NIS.\n\tUse the -l flag to load local.");
130#endif
131	uid = getuid();
132
133	if (op == EDITENTRY || op == NEWSH)
134		switch(argc) {
135		case 0:
136			pw = getpwuid(uid);
137#ifdef	YP
138			if (pw && !force_yp)
139				use_yp = 0;
140			else if (use_yp)
141				pw = ypgetpwuid(uid);
142#endif	/* YP */
143			if (!pw)
144				errx(1, "unknown user: uid %u\n", uid);
145			break;
146		case 1:
147			pw = getpwnam(*argv);
148#ifdef	YP
149			if (pw && !force_yp)
150				use_yp = 0;
151			else if (use_yp)
152				pw = ypgetpwnam(*argv);
153#endif	/* YP */
154			if (!pw)
155				errx(1, "unknown user: %s", *argv);
156			if (uid && uid != pw->pw_uid)
157				baduser();
158			break;
159		default:
160			usage();
161		}
162
163	if (op == NEWSH) {
164		/* protect p_shell -- it thinks NULL is /bin/sh */
165		if (!arg[0])
166			usage();
167		if (p_shell(arg, pw, (ENTRY *)NULL))
168			pw_error((char *)NULL, 0, 1);
169	}
170
171	if (op == LOADENTRY) {
172		if (uid)
173			baduser();
174		pw = &lpw;
175		if (!pw_scan(arg, pw, (int *)NULL))
176			exit(1);
177	}
178
179	/* Get the passwd lock file and open the passwd file for reading. */
180	pw_init();
181	tfd = pw_lock(0);
182	if (tfd < 0)
183		errx(1, "the passwd file is busy.");
184	pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
185	if (pfd < 0)
186		pw_error(_PATH_MASTERPASSWD, 1, 1);
187
188	/* Edit the user passwd information if requested. */
189	if (op == EDITENTRY) {
190		dfd = mkstemp(tempname);
191		if (dfd < 0)
192			pw_error(tempname, 1, 1);
193		display(tempname, dfd, pw);
194		edit(tempname, pw);
195		(void)unlink(tempname);
196	}
197
198#ifdef	YP
199	if (use_yp) {
200		if (pw_yp(pw, uid)) {
201			pw_error((char *)NULL, 0, 1);
202			exit(1);
203		} else
204			exit(0);
205	} else
206#endif	/* YP */
207
208	/* Copy the passwd file to the lock file, updating pw. */
209	pw_copy(pfd, tfd, pw);
210
211	/* Now finish the passwd file update. */
212	if (pw_mkdb() < 0)
213		pw_error((char *)NULL, 0, 1);
214
215	exit(0);
216}
217
218void
219baduser()
220{
221
222	errx(1, "%s", strerror(EACCES));
223}
224
225void
226usage()
227{
228
229#ifdef	YP
230	(void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [-l]%s [user]\n", use_yp?" [-y]":"");
231#else
232	(void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [user]\n");
233#endif
234	exit(1);
235}
236