xref: /freebsd/usr.bin/passwd/passwd.c (revision 5e3934b15a2741b2de6b217e77dc9d798d740804)
15f0ae68aSDag-Erling Smørgrav /*-
2*1de7b4b8SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3*1de7b4b8SPedro F. Giffuni  *
45f0ae68aSDag-Erling Smørgrav  * Copyright (c) 2002 Networks Associates Technologies, Inc.
55f0ae68aSDag-Erling Smørgrav  * All rights reserved.
65f0ae68aSDag-Erling Smørgrav  *
75f0ae68aSDag-Erling Smørgrav  * This software was developed for the FreeBSD Project by ThinkSec AS and
85f0ae68aSDag-Erling Smørgrav  * NAI Labs, the Security Research Division of Network Associates, Inc.
95f0ae68aSDag-Erling Smørgrav  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
105f0ae68aSDag-Erling Smørgrav  * DARPA CHATS research program.
119b50d902SRodney W. Grimes  *
129b50d902SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
139b50d902SRodney W. Grimes  * modification, are permitted provided that the following conditions
149b50d902SRodney W. Grimes  * are met:
159b50d902SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
169b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
179b50d902SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
189b50d902SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
199b50d902SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
205f0ae68aSDag-Erling Smørgrav  * 3. The name of the author may not be used to endorse or promote
215f0ae68aSDag-Erling Smørgrav  *    products derived from this software without specific prior written
225f0ae68aSDag-Erling Smørgrav  *    permission.
239b50d902SRodney W. Grimes  *
245f0ae68aSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
259b50d902SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
269b50d902SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
275f0ae68aSDag-Erling Smørgrav  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
289b50d902SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
299b50d902SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
309b50d902SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
319b50d902SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
329b50d902SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
339b50d902SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
349b50d902SRodney W. Grimes  * SUCH DAMAGE.
359b50d902SRodney W. Grimes  */
369b50d902SRodney W. Grimes 
375f0ae68aSDag-Erling Smørgrav #include <sys/param.h>
388f176b43SMark Murray 
399b50d902SRodney W. Grimes #include <err.h>
405f0ae68aSDag-Erling Smørgrav #include <pwd.h>
419b50d902SRodney W. Grimes #include <stdio.h>
42753d42d2SChris D. Faulhaber #include <stdlib.h>
43821df508SXin LI #include <syslog.h>
447e19b1ecSPhilippe Charnier #include <unistd.h>
459b50d902SRodney W. Grimes 
465f0ae68aSDag-Erling Smørgrav #include <security/pam_appl.h>
475f0ae68aSDag-Erling Smørgrav #include <security/openpam.h>
489e32e233SBill Paul 
495f0ae68aSDag-Erling Smørgrav static pam_handle_t *pamh;
505f0ae68aSDag-Erling Smørgrav static struct pam_conv pamc = {
515f0ae68aSDag-Erling Smørgrav 	openpam_ttyconv,
525f0ae68aSDag-Erling Smørgrav 	NULL
535f0ae68aSDag-Erling Smørgrav };
5492570443SGarrett Wollman 
555f0ae68aSDag-Erling Smørgrav static char	*yp_domain;
565f0ae68aSDag-Erling Smørgrav static char	*yp_host;
579b50d902SRodney W. Grimes 
585f0ae68aSDag-Erling Smørgrav static void
usage(void)595f0ae68aSDag-Erling Smørgrav usage(void)
605f0ae68aSDag-Erling Smørgrav {
61d3974088SDag-Erling Smørgrav 	fprintf(stderr, "usage: passwd [-ly] [-d domain] [-h host] [user]\n");
625f0ae68aSDag-Erling Smørgrav 	exit(1);
635f0ae68aSDag-Erling Smørgrav }
649b50d902SRodney W. Grimes 
659b50d902SRodney W. Grimes int
main(int argc,char * argv[])665f0ae68aSDag-Erling Smørgrav main(int argc, char *argv[])
679b50d902SRodney W. Grimes {
685f0ae68aSDag-Erling Smørgrav 	char hostname[MAXHOSTNAMELEN];
6901cc221bSEd Schouten 	struct passwd *pwd = NULL; /* Keep compiler happy. */
705f0ae68aSDag-Erling Smørgrav 	int o, pam_err;
715f0ae68aSDag-Erling Smørgrav 	uid_t uid;
729b50d902SRodney W. Grimes 
735f0ae68aSDag-Erling Smørgrav 	while ((o = getopt(argc, argv, "d:h:loy")) != -1)
745f0ae68aSDag-Erling Smørgrav 		switch (o) {
755f0ae68aSDag-Erling Smørgrav 		case 'd':
76c2dfe9feSBill Paul 			yp_domain = optarg;
77c2dfe9feSBill Paul 			break;
785f0ae68aSDag-Erling Smørgrav 		case 'h':
795f0ae68aSDag-Erling Smørgrav 			yp_host = optarg;
80c2dfe9feSBill Paul 			break;
815f0ae68aSDag-Erling Smørgrav 		case 'l':
82c2dfe9feSBill Paul 		case 'o':
835f0ae68aSDag-Erling Smørgrav 		case 'y':
845f0ae68aSDag-Erling Smørgrav 			/* compatibility */
85c2dfe9feSBill Paul 			break;
869b50d902SRodney W. Grimes 		default:
879b50d902SRodney W. Grimes 			usage();
889b50d902SRodney W. Grimes 		}
899b50d902SRodney W. Grimes 
909b50d902SRodney W. Grimes 	argc -= optind;
919b50d902SRodney W. Grimes 	argv += optind;
929b50d902SRodney W. Grimes 
935f0ae68aSDag-Erling Smørgrav 	uid = getuid();
949b50d902SRodney W. Grimes 
959b50d902SRodney W. Grimes 	switch (argc) {
969b50d902SRodney W. Grimes 	case 0:
975f0ae68aSDag-Erling Smørgrav 		if ((pwd = getpwuid(uid)) == NULL)
985f0ae68aSDag-Erling Smørgrav 			errx(1, "who are you?");
999b50d902SRodney W. Grimes 		break;
1009b50d902SRodney W. Grimes 	case 1:
1015f0ae68aSDag-Erling Smørgrav 		if ((pwd = getpwnam(*argv)) == NULL)
1025f0ae68aSDag-Erling Smørgrav 			errx(1, "%s: no such user", *argv);
1039b50d902SRodney W. Grimes 		break;
1049b50d902SRodney W. Grimes 	default:
1059b50d902SRodney W. Grimes 		usage();
1069b50d902SRodney W. Grimes 	}
1079b50d902SRodney W. Grimes 
1085f0ae68aSDag-Erling Smørgrav 	if (uid != 0 && uid != pwd->pw_uid)
1095f0ae68aSDag-Erling Smørgrav 		errx(1, "permission denied");
1109e32e233SBill Paul 
1115f0ae68aSDag-Erling Smørgrav 	/* check where the user's from */
1125f0ae68aSDag-Erling Smørgrav 	switch (pwd->pw_fields & _PWF_SOURCE) {
1135f0ae68aSDag-Erling Smørgrav 	case _PWF_FILES:
1145f0ae68aSDag-Erling Smørgrav 		fprintf(stderr, "Changing local password for %s\n",
1155f0ae68aSDag-Erling Smørgrav 		    pwd->pw_name);
1165f0ae68aSDag-Erling Smørgrav 		break;
1175f0ae68aSDag-Erling Smørgrav 	case _PWF_NIS:
1185f0ae68aSDag-Erling Smørgrav 		fprintf(stderr, "Changing NIS password for %s\n",
1195f0ae68aSDag-Erling Smørgrav 		    pwd->pw_name);
1205f0ae68aSDag-Erling Smørgrav 		break;
1215f0ae68aSDag-Erling Smørgrav 	default:
1223fcf3dd6SJacques Vidrine 		/* XXX: Green men ought to be supported via PAM. */
1233fcf3dd6SJacques Vidrine 		errx(1,
1243fcf3dd6SJacques Vidrine 	  "Sorry, `passwd' can only change passwords for local or NIS users.");
1259b50d902SRodney W. Grimes 	}
1269b50d902SRodney W. Grimes 
1275f0ae68aSDag-Erling Smørgrav #define pam_check(func) do { \
1285f0ae68aSDag-Erling Smørgrav 	if (pam_err != PAM_SUCCESS) { \
1295f0ae68aSDag-Erling Smørgrav 		if (pam_err == PAM_AUTH_ERR || pam_err == PAM_PERM_DENIED || \
1305f0ae68aSDag-Erling Smørgrav 		    pam_err == PAM_AUTHTOK_RECOVERY_ERR) \
1315f0ae68aSDag-Erling Smørgrav 			warnx("sorry"); \
1325f0ae68aSDag-Erling Smørgrav 		else \
1335f0ae68aSDag-Erling Smørgrav 			warnx("%s(): %s", func, pam_strerror(pamh, pam_err)); \
1345f0ae68aSDag-Erling Smørgrav 		goto end; \
1355f0ae68aSDag-Erling Smørgrav 	} \
1365f0ae68aSDag-Erling Smørgrav } while (0)
1379b50d902SRodney W. Grimes 
1385f0ae68aSDag-Erling Smørgrav 	/* initialize PAM */
1395f0ae68aSDag-Erling Smørgrav 	pam_err = pam_start("passwd", pwd->pw_name, &pamc, &pamh);
1405f0ae68aSDag-Erling Smørgrav 	pam_check("pam_start");
1415f0ae68aSDag-Erling Smørgrav 
1425f0ae68aSDag-Erling Smørgrav 	pam_err = pam_set_item(pamh, PAM_TTY, ttyname(STDERR_FILENO));
1435f0ae68aSDag-Erling Smørgrav 	pam_check("pam_set_item");
1445f0ae68aSDag-Erling Smørgrav 	gethostname(hostname, sizeof hostname);
1455f0ae68aSDag-Erling Smørgrav 	pam_err = pam_set_item(pamh, PAM_RHOST, hostname);
1465f0ae68aSDag-Erling Smørgrav 	pam_check("pam_set_item");
1475f0ae68aSDag-Erling Smørgrav 	pam_err = pam_set_item(pamh, PAM_RUSER, getlogin());
1485f0ae68aSDag-Erling Smørgrav 	pam_check("pam_set_item");
1495f0ae68aSDag-Erling Smørgrav 
1505f0ae68aSDag-Erling Smørgrav 	/* set YP domain and host */
1515f0ae68aSDag-Erling Smørgrav 	pam_err = pam_set_data(pamh, "yp_domain", yp_domain, NULL);
1525f0ae68aSDag-Erling Smørgrav 	pam_check("pam_set_data");
1535f0ae68aSDag-Erling Smørgrav 	pam_err = pam_set_data(pamh, "yp_server", yp_host, NULL);
1545f0ae68aSDag-Erling Smørgrav 	pam_check("pam_set_data");
1555f0ae68aSDag-Erling Smørgrav 
1565f0ae68aSDag-Erling Smørgrav 	/* set new password */
1575f0ae68aSDag-Erling Smørgrav 	pam_err = pam_chauthtok(pamh, 0);
1585f0ae68aSDag-Erling Smørgrav 	pam_check("pam_chauthtok");
1595f0ae68aSDag-Erling Smørgrav 
1605f0ae68aSDag-Erling Smørgrav  end:
1615f0ae68aSDag-Erling Smørgrav 	pam_end(pamh, pam_err);
1625f0ae68aSDag-Erling Smørgrav 	exit(pam_err == PAM_SUCCESS ? 0 : 1);
1639b50d902SRodney W. Grimes }
164