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