196074Sluigi/*
296074Sluigi * Copyright (c) 1988, 1993, 1994
396074Sluigi *	The Regents of the University of California.  All rights reserved.
496074Sluigi *
596074Sluigi * Redistribution and use in source and binary forms, with or without
696074Sluigi * modification, are permitted provided that the following conditions
796074Sluigi * are met:
896074Sluigi * 1. Redistributions of source code must retain the above copyright
996074Sluigi *    notice, this list of conditions and the following disclaimer.
1096074Sluigi * 2. Redistributions in binary form must reproduce the above copyright
1196074Sluigi *    notice, this list of conditions and the following disclaimer in the
1296074Sluigi *    documentation and/or other materials provided with the distribution.
1396074Sluigi * 3. All advertising materials mentioning features or use of this software
1496074Sluigi *    must display the following acknowledgement:
1596074Sluigi *	This product includes software developed by the University of
1696074Sluigi *	California, Berkeley and its contributors.
1796074Sluigi * 4. Neither the name of the University nor the names of its contributors
1896074Sluigi *    may be used to endorse or promote products derived from this software
1996074Sluigi *    without specific prior written permission.
2096074Sluigi *
2196074Sluigi * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2296074Sluigi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2396074Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2496074Sluigi * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2596074Sluigi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2696074Sluigi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2796074Sluigi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2896074Sluigi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2996074Sluigi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3096074Sluigi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3196074Sluigi * SUCH DAMAGE.
3296074Sluigi */
3396074Sluigi
3496074Sluigi#ifndef lint
3596074Sluigistatic const char copyright[] =
3696074Sluigi"@(#) Copyright (c) 1988, 1993, 1994\n\
3796074Sluigi	The Regents of the University of California.  All rights reserved.\n";
3896074Sluigi#endif /* not lint */
3996074Sluigi
4096074Sluigi#ifndef lint
4196074Sluigi#if 0
4296074Sluigistatic char sccsid[] = "@(#)passwd.c	8.3 (Berkeley) 4/2/94";
4396074Sluigi#endif
4496074Sluigistatic const char rcsid[] =
4596074Sluigi  "$FreeBSD$";
4696074Sluigi#endif /* not lint */
4796074Sluigi
4896074Sluigi#include <sys/types.h>
4996074Sluigi
5096074Sluigi#include <err.h>
5196074Sluigi#include <errno.h>
5296074Sluigi#include <libutil.h>
5396074Sluigi#include <stdio.h>
5496074Sluigi#include <stdlib.h>
5596074Sluigi#include <string.h>
5696074Sluigi#include <unistd.h>
5796074Sluigi
5896074Sluigi#ifdef YP
5996074Sluigi#include <pwd.h>
6096074Sluigi#include <pw_yp.h>
6196074Sluigi#include <rpcsvc/yp.h>
6296074Sluigiint __use_yp = 0;
6396074Sluigiint yp_errno = YP_TRUE;
6496074Sluigiextern int yp_passwd( char * );
6596074Sluigi#endif
6696074Sluigi
6796074Sluigi#include "extern.h"
6896074Sluigi
6996074Sluigistatic void usage(void);
7096074Sluigi
7196074Sluigiint use_local_passwd = 0;
7296074Sluigi
7396074Sluigiint
7496074Sluigimain(argc, argv)
7596074Sluigi	int argc;
7696074Sluigi	char **argv;
7796074Sluigi{
7896074Sluigi	int ch;
7996074Sluigi	char *uname;
8096074Sluigi
8196074Sluigi#ifdef YP
8296074Sluigi#define OPTIONS "d:h:lysfo"
8396074Sluigi#else
8496074Sluigi#define OPTIONS "l"
8596074Sluigi#endif
8696074Sluigi
8796074Sluigi#ifdef YP
8896074Sluigi	int res = 0;
8996074Sluigi
9096074Sluigi	if (strstr(argv[0], "yppasswd")) __use_yp = 1;
9196074Sluigi#endif
9296074Sluigi
9396074Sluigi	while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
9496074Sluigi		switch (ch) {
9596074Sluigi		case 'l':		/* change local password file */
9696074Sluigi			use_local_passwd = 1;
9796074Sluigi			break;
9896074Sluigi#ifdef	YP
9996074Sluigi		case 'y':			/* Change NIS password */
10096074Sluigi			__use_yp = 1;
10196074Sluigi			break;
10296074Sluigi		case 'd':			/* Specify NIS domain. */
10396074Sluigi#ifdef PARANOID
10496074Sluigi			if (!getuid()) {
10596074Sluigi#endif
10696074Sluigi				yp_domain = optarg;
10796074Sluigi				if (yp_server == NULL)
10896074Sluigi					yp_server = "localhost";
10996074Sluigi#ifdef PARANOID
11096074Sluigi			} else {
11196074Sluigi				warnx("only the super-user may use the -d flag");
11296074Sluigi			}
11396074Sluigi#endif
11496074Sluigi			break;
11596074Sluigi		case 'h':			/* Specify NIS server. */
11696074Sluigi#ifdef PARANOID
11796074Sluigi			if (!getuid()) {
11896074Sluigi#endif
11996074Sluigi				yp_server = optarg;
12096074Sluigi#ifdef PARANOID
12196074Sluigi			} else {
12296074Sluigi				warnx("only the super-user may use the -h flag");
12396074Sluigi			}
12496074Sluigi#endif
12596074Sluigi			break;
12696074Sluigi		case 'o':
12796074Sluigi			force_old++;
12896074Sluigi			break;
12996074Sluigi#endif
13096074Sluigi		default:
13196074Sluigi		case '?':
13296074Sluigi			usage();
13396074Sluigi		}
13496074Sluigi	}
13596074Sluigi
13696074Sluigi	argc -= optind;
13796074Sluigi	argv += optind;
13896074Sluigi
13996074Sluigi	if ((uname = getlogin()) == NULL)
14096074Sluigi		err(1, "getlogin");
14196074Sluigi
14296074Sluigi	switch(argc) {
14396074Sluigi	case 0:
14496074Sluigi		break;
14596074Sluigi	case 1:
14696074Sluigi		uname = argv[0];
14796074Sluigi		break;
14896074Sluigi	default:
14996074Sluigi		usage();
15096074Sluigi	}
15196074Sluigi
15296074Sluigi#ifdef YP
15396074Sluigi	/*
15496074Sluigi	 * If NIS is turned on in the password database, use it, else punt.
15596074Sluigi	 */
156236963Sdes	res = use_yp(uname, 0, 0);
157236963Sdes	if (res == USER_YP_ONLY) {
158236963Sdes		if (!use_local_passwd) {
159236963Sdes			exit(yp_passwd(uname));
160236963Sdes		} else {
16196074Sluigi			/*
16296074Sluigi			 * Reject -l flag if NIS is turned on and the user
16396074Sluigi			 * doesn't exist in the local password database.
16496074Sluigi			 */
165236963Sdes			errx(1, "unknown local user: %s", uname);
16696074Sluigi		}
167236963Sdes	} else if (res == USER_LOCAL_ONLY) {
168236963Sdes		/*
169236963Sdes		 * Reject -y flag if user only exists locally.
170236963Sdes		 */
171236963Sdes		if (__use_yp)
172236963Sdes			errx(1, "unknown NIS user: %s", uname);
173236963Sdes	} else if (res == USER_YP_AND_LOCAL) {
174236963Sdes		if (!use_local_passwd && (yp_in_pw_file || __use_yp))
175236963Sdes			exit(yp_passwd(uname));
17696074Sluigi	}
17796074Sluigi#endif
17896074Sluigi
17996074Sluigi	exit(local_passwd(uname));
18096074Sluigi}
18196074Sluigi
18296074Sluigistatic void
18396074Sluigiusage()
18496074Sluigi{
18596074Sluigi
18696074Sluigi#ifdef	YP
18796074Sluigi	(void)fprintf(stderr,
18896074Sluigi		"usage: passwd [-l] [-y] [-o] [-d domain [-h host]] [user]\n");
18996074Sluigi#else
190236963Sdes	(void)fprintf(stderr, "usage: passwd [-l] user\n");
19196074Sluigi#endif
19296074Sluigi	exit(1);
19396074Sluigi}
194