summaryrefslogtreecommitdiffstats
path: root/usr.bin/passwd
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2002-04-15 03:02:57 +0000
committerdes <des@FreeBSD.org>2002-04-15 03:02:57 +0000
commit1e867a64f1ad704c1bff26da353524b88b460281 (patch)
tree9ba70cbb099a26866a74b32274f330e38b154f64 /usr.bin/passwd
parentb9658dfaf29d64bd1583a34d3ddebddb425b2bce (diff)
downloadFreeBSD-src-1e867a64f1ad704c1bff26da353524b88b460281.zip
FreeBSD-src-1e867a64f1ad704c1bff26da353524b88b460281.tar.gz
PAMified passwd(1). Some NIS-related issues remain to be solved, but this
should work for everyday use. Sponsored by: DARPA, NAI Labs
Diffstat (limited to 'usr.bin/passwd')
-rw-r--r--usr.bin/passwd/Makefile99
-rw-r--r--usr.bin/passwd/passwd.c305
2 files changed, 118 insertions, 286 deletions
diff --git a/usr.bin/passwd/Makefile b/usr.bin/passwd/Makefile
index ce6bea3..e4c5099 100644
--- a/usr.bin/passwd/Makefile
+++ b/usr.bin/passwd/Makefile
@@ -1,97 +1,14 @@
# From: @(#)Makefile 8.3 (Berkeley) 4/2/94
# $FreeBSD$
-# NOPAM is used by PicoBSD
-
-.if defined(NOPAM)
-
-PROG= passwd
-SRCS= local_passwd.c passwd.c pw_copy.c pw_util.c
-
-GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c \
- yppasswd_private.h yppasswd_private_clnt.c yppasswd_private_xdr.c
-CFLAGS+=-Wall
-
-DPADD= ${LIBCRYPT} ${LIBUTIL}
-LDADD= -lcrypt -lutil
-.PATH: ${.CURDIR}/../../usr.bin/chpass ${.CURDIR}/../../usr.sbin/vipw
-
-CFLAGS+= -DLOGIN_CAP -DCRYPT -I. -I${.CURDIR} \
- -I${.CURDIR}/../../usr.sbin/vipw \
- -I${.CURDIR}/../../usr.bin/chpass \
- -I${.CURDIR}/../../lib/libc/gen \
- -Dyp_error=warnx -DLOGGING
-
-.else
-
-PROG= passwd
-SRCS= local_passwd.c passwd.c pw_copy.c pw_util.c pw_yp.c \
- yp_passwd.c ypxfr_misc.c ${GENSRCS}
-GENSRCS=yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c \
- yppasswd_private.h yppasswd_private_clnt.c yppasswd_private_xdr.c
-CFLAGS+=-Wall
-
-DPADD= ${LIBCRYPT} ${LIBRPCSVC} ${LIBUTIL}
-LDADD= -lcrypt -lrpcsvc -lutil
-.PATH: ${.CURDIR}/../../usr.bin/chpass ${.CURDIR}/../../usr.sbin/vipw \
- ${.CURDIR}/../../libexec/ypxfr \
- ${.CURDIR}/../../usr.sbin/rpc.yppasswdd
-
-CFLAGS+= -DLOGIN_CAP -DCRYPT -DYP -I. -I${.CURDIR} \
- -I${.CURDIR}/../../usr.sbin/vipw \
- -I${.CURDIR}/../../usr.bin/chpass \
- -I${.CURDIR}/../../libexec/ypxfr \
- -I${.CURDIR}/../../usr.sbin/rpc.yppasswdd \
- -I${.CURDIR}/../../lib/libc/gen \
- -Dyp_error=warnx -DLOGGING
-
-.endif
-
-CLEANFILES= ${GENSRCS}
-
-RPCGEN= rpcgen -C
-RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x
-RPCSRC_PW= ${DESTDIR}/usr/include/rpcsvc/yppasswd.x
-RPCSRC_PRIV= ${.CURDIR}/../../usr.sbin/rpc.yppasswdd/yppasswd_private.x
-
-yp.h: ${RPCSRC}
- ${RPCGEN} -h -o ${.TARGET} ${RPCSRC}
-
-yp_clnt.c: ${RPCSRC} yp.h
- ${RPCGEN} -l -o ${.TARGET} ${RPCSRC}
-
-yppasswd.h: ${RPCSRC_PW}
- ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PW}
-
-yppasswd_clnt.c: ${RPCSRC_PW}
- ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PW}
-
-yppasswd_private.h: ${RPCSRC_PRIV}
- ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PRIV}
-
-yppasswd_private_xdr.c: ${RPCSRC_PRIV}
- ${RPCGEN} -c -o ${.TARGET} ${RPCSRC_PRIV}
-
-yppasswd_private_clnt.c: ${RPCSRC_PRIV}
- ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PRIV}
-
-BINOWN= root
-BINMODE=4555
-LINKS=${BINDIR}/passwd ${BINDIR}/yppasswd
-MLINKS=passwd.1 yppasswd.1
-
-.if exists(${DESTDIR}${LIBDIR}/libkrb.a) && !defined(NOCRYPT) && !defined(NO_OPENSSL) && defined(MAKE_KERBEROS4)
-SRCS+= kpasswd_standalone.c
-.PATH: ${.CURDIR}/../../usr.bin/chpass ${.CURDIR}/../../usr.sbin/vipw \
- ${.CURDIR}/../../usr.bin/passwd \
- ${.CURDIR}/../../crypto/kerberosIV/kadmin
-
-CFLAGS+= -DKERBEROS
-# XXX not defined: ${LIBKADM}, ${LIBCOM_ERR}
-DPADD= ${LIBKADM} ${LIBKRB} ${LIBCRYPTO} ${LIBCRYPT} ${LIBRPCSVC} ${LIBCOM_ERR} ${LIBUTIL}
-LDADD= -lkadm -lkrb -lcrypto -lcrypt -lrpcsvc -lcom_err -lutil
-DISTRIBUTION= krb4
-.endif
+PROG = passwd
+BINOWN = root
+BINMODE = 4555
+DPADD = ${LIBPAM}
+LDADD = ${MINUSLPAM}
+LINKS = ${BINDIR}/passwd ${BINDIR}/yppasswd
+MLINKS = passwd.1 yppasswd.1
+WARNS ?= 4
beforeinstall:
.for i in passwd yppasswd
diff --git a/usr.bin/passwd/passwd.c b/usr.bin/passwd/passwd.c
index d241650..28119dd 100644
--- a/usr.bin/passwd/passwd.c
+++ b/usr.bin/passwd/passwd.c
@@ -1,6 +1,11 @@
-/*
- * Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+/*-
+ * Copyright (c) 2002 Networks Associates Technologies, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by ThinkSec AS and
+ * NAI Labs, the Security Research Division of Network Associates, Inc.
+ * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
+ * DARPA CHATS research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,18 +15,14 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -29,222 +30,136 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $FreeBSD$
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1988, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)passwd.c 8.3 (Berkeley) 4/2/94";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <sys/types.h>
+#include <sys/param.h>
#include <err.h>
-#include <errno.h>
-#include <libutil.h>
+#include <pwd.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <syslog.h>
#include <unistd.h>
-#ifdef YP
-#include <pwd.h>
-#include <pw_yp.h>
-#include <rpcsvc/yp.h>
-int __use_yp = 0;
-int yp_errno = YP_TRUE;
-extern int yp_passwd( char * );
-#endif
-
-#ifdef KERBEROS
-#include "krb.h"
-#endif
+#include <security/pam_appl.h>
+#include <security/openpam.h>
-#include "extern.h"
+static pam_handle_t *pamh;
+static struct pam_conv pamc = {
+ openpam_ttyconv,
+ NULL
+};
-static void usage(void);
+static char *yp_domain;
+static char *yp_host;
-int use_local_passwd = 0;
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: passwd [-ly] [-d domain] [-h host] [user]\n");
+ exit(1);
+}
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char *argv[])
{
- int ch;
- char *uname;
-#ifdef KERBEROS
- char *iflag = 0, *rflag = 0, *uflag = 0;
- char *k;
-#endif
-
-#ifdef YP
-#ifdef KERBEROS
- char realm[REALM_SZ];
-#define OPTIONS "d:h:lysfoi:r:u:"
-#else
-#define OPTIONS "d:h:lysfo"
-#endif
-#else
-#ifdef KERBEROS
- char realm[REALM_SZ];
-#define OPTIONS "li:r:u:"
-#else
-#define OPTIONS "l"
-#endif
-#endif
-
-#ifdef YP
- int res = 0;
-
- if (strstr(argv[0], "yppasswd")) __use_yp = 1;
-#endif
-
- while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
- switch (ch) {
- case 'l': /* change local password file */
- use_local_passwd = 1;
- break;
-#ifdef KERBEROS
- case 'i':
- iflag = optarg;
- break;
- case 'r':
- rflag = optarg;
- break;
- case 'u':
- uflag = optarg;
- break;
-#endif /* KERBEROS */
-#ifdef YP
- case 'y': /* Change NIS password */
- __use_yp = 1;
+ char hostname[MAXHOSTNAMELEN];
+ struct passwd *pwd;
+ int o, pam_err;
+ uid_t uid;
+
+ while ((o = getopt(argc, argv, "d:h:loy")) != -1)
+ switch (o) {
+ case 'd':
+ yp_domain = optarg;
break;
- case 'd': /* Specify NIS domain. */
-#ifdef PARANOID
- if (!getuid()) {
-#endif
- yp_domain = optarg;
- if (yp_server == NULL)
- yp_server = "localhost";
-#ifdef PARANOID
- } else {
- warnx("only the super-user may use the -d flag");
- }
-#endif
- break;
- case 'h': /* Specify NIS server. */
-#ifdef PARANOID
- if (!getuid()) {
-#endif
- yp_server = optarg;
-#ifdef PARANOID
- } else {
- warnx("only the super-user may use the -h flag");
- }
-#endif
+ case 'h':
+ yp_host = optarg;
break;
+ case 'l':
case 'o':
- force_old++;
+ case 'y':
+ /* compatibility */
break;
-#endif
default:
- case '?':
usage();
}
- }
argc -= optind;
argv += optind;
- if ((uname = getlogin()) == NULL)
- err(1, "getlogin");
+ uid = getuid();
- switch(argc) {
+ switch (argc) {
case 0:
+ if ((pwd = getpwuid(uid)) == NULL)
+ errx(1, "who are you?");
break;
case 1:
- uname = argv[0];
+ if ((pwd = getpwnam(*argv)) == NULL)
+ errx(1, "%s: no such user", *argv);
break;
default:
usage();
}
-#ifdef YP
- /*
- * If NIS is turned on in the password database, use it, else punt.
- */
-#ifdef KERBEROS
- if (__use_yp || (iflag == NULL && rflag == NULL && uflag == NULL)) {
-#endif
- res = use_yp(uname, 0, 0);
- if (res == USER_YP_ONLY) {
- if (!use_local_passwd) {
- exit(yp_passwd(uname));
- } else {
- /*
- * Reject -l flag if NIS is turned on and the user
- * doesn't exist in the local password database.
- */
- errx(1, "unknown local user: %s", uname);
- }
- } else if (res == USER_LOCAL_ONLY) {
- /*
- * Reject -y flag if user only exists locally.
- */
- if (__use_yp)
- errx(1, "unknown NIS user: %s", uname);
- } else if (res == USER_YP_AND_LOCAL) {
- if (!use_local_passwd && (yp_in_pw_file || __use_yp))
- exit(yp_passwd(uname));
- }
-#ifdef KERBEROS
- }
-#endif
-#endif
-
- if (!use_local_passwd) {
-#ifdef KERBEROS
- k = auth_getval("auth_list");
- if (k && strstr(k, "kerberos"))
- if(krb_get_lrealm(realm, 0) == KSUCCESS) {
- setuid(getuid());
- fprintf(stderr, "realm %s\n", realm);
- exit(krb_passwd(argv[0], iflag, rflag, uflag));
- }
-#endif
- }
- exit(local_passwd(uname));
-}
+ if (uid != 0 && uid != pwd->pw_uid)
+ errx(1, "permission denied");
-static void
-usage()
-{
+ /* check where the user's from */
+ switch (pwd->pw_fields & _PWF_SOURCE) {
+ case _PWF_FILES:
+ fprintf(stderr, "Changing local password for %s\n",
+ pwd->pw_name);
+ break;
+ case _PWF_NIS:
+ fprintf(stderr, "Changing NIS password for %s\n",
+ pwd->pw_name);
+ break;
+ case _PWF_HESIOD:
+ errx(1, "can't change Hesiod password");
+ break;
+ default:
+ /* specieist! */
+ errx(1, "can't change little green men's passwords (0x%x)",
+ pwd->pw_fields);
+ }
-#ifdef YP
-#ifdef KERBEROS
- fprintf(stderr, "%s\n%s\n",
- "usage: passwd [-l] [-i instance] [-r realm] [-u fullname]",
- " passwd [-l] [-y] [-o] [-d domain [-h host]] [user]");
-#else
- (void)fprintf(stderr,
- "usage: passwd [-l] [-y] [-o] [-d domain [-h host]] [user]\n");
-#endif
-#else
-#ifdef KERBEROS
- fprintf(stderr,
- "usage: passwd [-l] [-i instance] [-r realm] [-u fullname] [user]\n");
-#else
- (void)fprintf(stderr, "usage: passwd user\n");
-#endif
-#endif
- exit(1);
+#define pam_check(func) do { \
+ if (pam_err != PAM_SUCCESS) { \
+ if (pam_err == PAM_AUTH_ERR || pam_err == PAM_PERM_DENIED || \
+ pam_err == PAM_AUTHTOK_RECOVERY_ERR) \
+ warnx("sorry"); \
+ else \
+ warnx("%s(): %s", func, pam_strerror(pamh, pam_err)); \
+ goto end; \
+ } \
+} while (0)
+
+ /* initialize PAM */
+ pam_err = pam_start("passwd", pwd->pw_name, &pamc, &pamh);
+ pam_check("pam_start");
+
+ pam_err = pam_set_item(pamh, PAM_TTY, ttyname(STDERR_FILENO));
+ pam_check("pam_set_item");
+ gethostname(hostname, sizeof hostname);
+ pam_err = pam_set_item(pamh, PAM_RHOST, hostname);
+ pam_check("pam_set_item");
+ pam_err = pam_set_item(pamh, PAM_RUSER, getlogin());
+ pam_check("pam_set_item");
+
+ /* set YP domain and host */
+ pam_err = pam_set_data(pamh, "yp_domain", yp_domain, NULL);
+ pam_check("pam_set_data");
+ pam_err = pam_set_data(pamh, "yp_server", yp_host, NULL);
+ pam_check("pam_set_data");
+
+ /* set new password */
+ pam_err = pam_chauthtok(pamh, 0);
+ pam_check("pam_chauthtok");
+
+ end:
+ pam_end(pamh, pam_err);
+ exit(pam_err == PAM_SUCCESS ? 0 : 1);
}
OpenPOWER on IntegriCloud