summaryrefslogtreecommitdiffstats
path: root/usr.bin/passwd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/passwd')
-rw-r--r--usr.bin/passwd/Makefile79
-rw-r--r--usr.bin/passwd/extern.h38
-rw-r--r--usr.bin/passwd/kpasswd_proto.h54
-rw-r--r--usr.bin/passwd/krb_passwd.c319
-rw-r--r--usr.bin/passwd/local_passwd.c225
-rw-r--r--usr.bin/passwd/passwd.1210
-rw-r--r--usr.bin/passwd/passwd.c243
-rw-r--r--usr.bin/passwd/yp_passwd.c188
8 files changed, 1356 insertions, 0 deletions
diff --git a/usr.bin/passwd/Makefile b/usr.bin/passwd/Makefile
new file mode 100644
index 0000000..49c303c
--- /dev/null
+++ b/usr.bin/passwd/Makefile
@@ -0,0 +1,79 @@
+# From: @(#)Makefile 8.3 (Berkeley) 4/2/94
+# $Id: Makefile,v 1.23 1997/02/22 19:56:34 peter Exp $
+
+PROG= passwd
+SRCS= local_passwd.c yppasswd_private_xdr.c yppasswd_comm.c yp_passwd.c \
+ passwd.c pw_copy.c pw_util.c pw_yp.c
+
+DPADD= ${LIBCRYPT} ${LIBRPCSVC} ${LIBUTIL}
+LDADD= -lcrypt -lrpcsvc -lutil
+.PATH: ${.CURDIR}/../../usr.bin/chpass ${.CURDIR}/../../usr.sbin/vipw \
+ ${.CURDIR}/../rlogin ${.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 \
+ -Dyp_error=warnx -DLOGGING
+
+SRCS+= ypxfr_misc.c yp_clnt.c yppasswd_clnt.c
+
+CLEANFILES= yp.h yp_clnt.c yppasswd.h yppasswd_clnt.c \
+ yppasswd_private.h yppasswd_private_xdr.c
+
+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} yppasswd.h
+ ${RPCGEN} -l -o ${.TARGET} ${RPCSRC_PW}
+
+yppasswd_private.h: ${RPCSRC_PRIV}
+ ${RPCGEN} -h -o ${.TARGET} ${RPCSRC_PRIV}
+
+yppasswd_private_xdr.c: ${RPCSRC_PRIV} yppasswd_private.h
+ ${RPCGEN} -c -o ${.TARGET} ${RPCSRC_PRIV}
+
+BINOWN= root
+BINMODE=4555
+MAN1=passwd.1
+LINKS=${BINDIR}/passwd ${BINDIR}/yppasswd
+MLINKS=passwd.1 yppasswd.1
+
+.if exists(${DESTDIR}/usr/lib/libkrb.a) && (defined(MAKE_EBONES))
+SRCS+= kpasswd.c
+.PATH: ${.CURDIR}/../../usr.bin/chpass ${.CURDIR}/../../usr.sbin/vipw \
+ ${.CURDIR}/../../usr.bin/rlogin ${.CURDIR}/../../usr.bin/passwd \
+ ${.CURDIR}/../../eBones/usr.bin/passwd
+
+CFLAGS+= -DKERBEROS \
+ -I${.CURDIR}/../../eBones/include \
+ -I${.CURDIR}/../../eBones/lib/libkadm
+# XXX not defined: ${LIBKADM}, ${LIBCOM_ERR}
+DPADD= ${LIBKADM} ${LIBKRB} ${LIBDES} ${LIBCRYPT} ${LIBRPCSVC} ${LIBCOM_ERR} ${LIBUTIL}
+LDADD= -lkadm -lkrb -ldes -lcrypt -lrpcsvc -lcom_err -lutil
+DISTRIBUTION= krb
+.endif
+
+beforeinstall:
+.for i in passwd yppasswd
+ [ ! -e ${DESTDIR}${BINDIR}/$i ] || \
+ chflags noschg ${DESTDIR}${BINDIR}/$i
+.endfor
+
+afterinstall:
+ chflags schg ${DESTDIR}${BINDIR}/passwd
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/passwd/extern.h b/usr.bin/passwd/extern.h
new file mode 100644
index 0000000..7a4bd12
--- /dev/null
+++ b/usr.bin/passwd/extern.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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
+ * 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)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ * From: @(#)extern.h 8.1 (Berkeley) 4/2/94
+ * $Id$
+ */
+
+int krb_passwd __P((char *, char *, char *, char *));
+int local_passwd __P((char *));
diff --git a/usr.bin/passwd/kpasswd_proto.h b/usr.bin/passwd/kpasswd_proto.h
new file mode 100644
index 0000000..465d4c7
--- /dev/null
+++ b/usr.bin/passwd/kpasswd_proto.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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
+ * 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)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ * @(#)kpasswd_proto.h 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * kpasswd_proto
+ *
+ * definitions for the kpasswd "protocol"
+ * (We hope this to be temporary until a real admin protocol is worked out.)
+ */
+
+struct kpasswd_data {
+ des_cblock random_key;
+ char secure_msg[_PASSWORD_LEN];
+};
+
+struct update_data {
+ char pw[_PASSWORD_LEN];
+ char secure_msg[_PASSWORD_LEN];
+};
+#define SERVICE "kpasswd"
+#define SECURE_STRING \
+ "Kerberos password update program -- 12/9/88 UC Berkeley"
diff --git a/usr.bin/passwd/krb_passwd.c b/usr.bin/passwd/krb_passwd.c
new file mode 100644
index 0000000..d4a0f15
--- /dev/null
+++ b/usr.bin/passwd/krb_passwd.c
@@ -0,0 +1,319 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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
+ * 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)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)krb_passwd.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+#ifdef KERBEROS
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "kpasswd_proto.h"
+
+#include "extern.h"
+
+#define PROTO "tcp"
+
+static void send_update __P((int, char *, char *));
+static void recv_ack __P((int));
+static void cleanup __P((void));
+static void finish __P((void));
+
+static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
+static struct kpasswd_data proto_data;
+static des_cblock okey;
+static Key_schedule osched;
+static KTEXT_ST ticket;
+static Key_schedule random_schedule;
+static long authopts;
+static char realm[REALM_SZ], krbhst[MAX_HSTNM];
+static int sock;
+
+int
+krb_passwd()
+{
+ struct servent *se;
+ struct hostent *host;
+ struct sockaddr_in sin;
+ CREDENTIALS cred;
+ fd_set readfds;
+ int rval;
+ char pass[_PASSWORD_LEN], password[_PASSWORD_LEN];
+ static void finish();
+
+ static struct rlimit rl = { 0, 0 };
+
+ (void)signal(SIGHUP, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGTSTP, SIG_IGN);
+
+ if (setrlimit(RLIMIT_CORE, &rl) < 0) {
+ warn("setrlimit");
+ return (1);
+ }
+
+ if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
+ warnx("couldn't find entry for service %s/%s",
+ SERVICE, PROTO);
+ return (1);
+ }
+
+ if ((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
+ warnx("couldn't get local Kerberos realm: %s",
+ krb_err_txt[rval]);
+ return (1);
+ }
+
+ if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
+ warnx("couldn't get Kerberos host: %s",
+ krb_err_txt[rval]);
+ return (1);
+ }
+
+ if ((host = gethostbyname(krbhst)) == NULL) {
+ warnx("couldn't get host entry for krb host %s",
+ krbhst);
+ return (1);
+ }
+
+ sin.sin_family = host->h_addrtype;
+ memmove((char *) &sin.sin_addr, host->h_addr, host->h_length);
+ sin.sin_port = se->s_port;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ warn("socket");
+ return (1);
+ }
+
+ if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+ warn("connect");
+ (void)close(sock);
+ return (1);
+ }
+
+ rval = krb_sendauth(
+ authopts, /* NOT mutual */
+ sock,
+ &ticket, /* (filled in) */
+ SERVICE,
+ krbhst, /* instance (krbhst) */
+ realm, /* dest realm */
+ (u_long) getpid(), /* checksum */
+ NULL, /* msg data */
+ NULL, /* credentials */
+ NULL, /* schedule */
+ NULL, /* local addr */
+ NULL, /* foreign addr */
+ "KPWDV0.1"
+ );
+
+ if (rval != KSUCCESS) {
+ warnx("Kerberos sendauth error: %s", krb_err_txt[rval]);
+ return (1);
+ }
+
+ krb_get_cred("krbtgt", realm, realm, &cred);
+
+ (void)printf("Changing Kerberos password for %s.%s@%s.\n",
+ cred.pname, cred.pinst, realm);
+
+ if (des_read_pw_string(pass,
+ sizeof(pass)-1, "Old Kerberos password:", 0)) {
+ warnx("error reading old Kerberos password");
+ return (1);
+ }
+
+ (void)des_string_to_key(pass, okey);
+ (void)des_key_sched(okey, osched);
+ (void)des_set_key(okey, osched);
+
+ /* wait on the verification string */
+
+ FD_ZERO(&readfds);
+ FD_SET(sock, &readfds);
+
+ rval =
+ select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
+
+ if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
+ if(rval == 0) {
+ warnx("timed out (aborted)");
+ cleanup();
+ return (1);
+ }
+ warnx("select failed (aborted)");
+ cleanup();
+ return (1);
+ }
+
+ /* read verification string */
+
+ if (des_read(sock, &proto_data, sizeof(proto_data)) !=
+ sizeof(proto_data)) {
+ warnx("couldn't read verification string (aborted)");
+ cleanup();
+ return (1);
+ }
+
+ (void)signal(SIGHUP, finish);
+ (void)signal(SIGINT, finish);
+
+ if (strcmp(SECURE_STRING, proto_data.secure_msg) != 0) {
+ cleanup();
+ /* don't complain loud if user just hit return */
+ if (pass == NULL || (!*pass))
+ return (0);
+ (void)fprintf(stderr, "Sorry\n");
+ return (1);
+ }
+
+ (void)des_key_sched(proto_data.random_key, random_schedule);
+ (void)des_set_key(proto_data.random_key, random_schedule);
+ (void)memset(pass, 0, sizeof(pass));
+
+ if (des_read_pw_string(pass,
+ sizeof(pass)-1, "New Kerberos password:", 0)) {
+ warnx("error reading new Kerberos password (aborted)");
+ cleanup();
+ return (1);
+ }
+
+ if (des_read_pw_string(password,
+ sizeof(password)-1, "Retype new Kerberos password:", 0)) {
+ warnx("error reading new Kerberos password (aborted)");
+ cleanup();
+ return (1);
+ }
+
+ if (strcmp(password, pass) != 0) {
+ warnx("password mismatch (aborted)");
+ cleanup();
+ return (1);
+ }
+
+ if (strlen(pass) == 0)
+ (void)printf("using NULL password\n");
+
+ send_update(sock, password, SECURE_STRING);
+
+ /* wait for ACK */
+
+ FD_ZERO(&readfds);
+ FD_SET(sock, &readfds);
+
+ rval =
+ select(sock + 1, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout);
+ if ((rval < 1) || !FD_ISSET(sock, &readfds)) {
+ if(rval == 0) {
+ warnx("timed out reading ACK (aborted)");
+ cleanup();
+ exit(1);
+ }
+ warnx("select failed (aborted)");
+ cleanup();
+ exit(1);
+ }
+ recv_ack(sock);
+ cleanup();
+ return (0);
+}
+
+static void
+send_update(dest, pwd, str)
+ int dest;
+ char *pwd, *str;
+{
+ static struct update_data ud;
+
+ (void)strncpy(ud.secure_msg, str, _PASSWORD_LEN);
+ (void)strncpy(ud.pw, pwd, sizeof(ud.pw));
+ if (des_write(dest, &ud, sizeof(ud)) != sizeof(ud)) {
+ warnx("couldn't write pw update (abort)");
+ memset((char *)&ud, 0, sizeof(ud));
+ cleanup();
+ exit(1);
+ }
+}
+
+static void
+recv_ack(remote)
+ int remote;
+{
+ int cc;
+ char buf[BUFSIZ];
+
+ cc = des_read(remote, buf, sizeof(buf));
+ if (cc <= 0) {
+ warnx("error reading acknowledgement (aborted)");
+ cleanup();
+ exit(1);
+ }
+ (void)printf("%s", buf);
+}
+
+static void
+cleanup()
+{
+
+ (void)memset((char *)&proto_data, 0, sizeof(proto_data));
+ (void)memset((char *)okey, 0, sizeof(okey));
+ (void)memset((char *)osched, 0, sizeof(osched));
+ (void)memset((char *)random_schedule, 0, sizeof(random_schedule));
+}
+
+static void
+finish()
+{
+
+ (void)close(sock);
+ exit(1);
+}
+
+#endif /* KERBEROS */
diff --git a/usr.bin/passwd/local_passwd.c b/usr.bin/passwd/local_passwd.c
new file mode 100644
index 0000000..5e8a4bc
--- /dev/null
+++ b/usr.bin/passwd/local_passwd.c
@@ -0,0 +1,225 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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
+ * 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)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ * $Id: local_passwd.c,v 1.17 1997/05/10 19:02:38 davidn Exp $
+ */
+
+#ifndef lint
+static const char sccsid[] = "@(#)local_passwd.c 8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <pw_copy.h>
+#include <pw_util.h>
+#ifdef YP
+#include <pw_yp.h>
+#endif
+
+#ifdef LOGGING
+#include <syslog.h>
+#endif
+
+#ifdef LOGIN_CAP
+#ifdef AUTH_NONE /* multiple defs :-( */
+#undef AUTH_NONE
+#endif
+#include <login_cap.h>
+#endif
+
+#include "extern.h"
+
+static uid_t uid;
+int randinit;
+
+char *tempname;
+
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+void
+to64(s, v, n)
+ char *s;
+ long v;
+ int n;
+{
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+char *
+getnewpasswd(pw, nis)
+ struct passwd *pw;
+ int nis;
+{
+ int tries, min_length = 6;
+ char *p, *t;
+#ifdef LOGIN_CAP
+ login_cap_t * lc;
+#endif
+ char buf[_PASSWORD_LEN+1], salt[10];
+ struct timeval tv;
+
+ if (!nis)
+ (void)printf("Changing local password for %s.\n", pw->pw_name);
+
+ if (uid && pw->pw_passwd[0] &&
+ strcmp(crypt(getpass("Old password:"), pw->pw_passwd),
+ pw->pw_passwd)) {
+ errno = EACCES;
+ pw_error(NULL, 1, 1);
+ }
+
+#ifdef LOGIN_CAP
+ /*
+ * Determine minimum password length and next password change date.
+ * Note that even for NIS passwords, login_cap is still used.
+ */
+ if ((lc = login_getpwclass(pw)) != NULL) {
+ time_t period;
+
+ /* minpasswordlen capablity */
+ min_length = (int)login_getcapnum(lc, "minpasswordlen",
+ min_length, min_length);
+ /* passwordperiod capability */
+ period = login_getcaptime(lc, "passwordperiod", 0, 0);
+ if (period > (time_t)0) {
+ pw->pw_change = time(NULL) + period;
+ }
+ login_close(lc);
+ }
+#endif
+
+ for (buf[0] = '\0', tries = 0;;) {
+ p = getpass("New password:");
+ if (!*p) {
+ (void)printf("Password unchanged.\n");
+ pw_error(NULL, 0, 0);
+ }
+ if (strlen(p) < min_length && (uid != 0 || ++tries < 2)) {
+ (void)printf("Please enter a password at least %d characters in length.\n", min_length);
+ continue;
+ }
+ for (t = p; *t && islower(*t); ++t);
+ if (!*t && (uid != 0 || ++tries < 2)) {
+ (void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
+ continue;
+ }
+ (void)strcpy(buf, p);
+ if (!strcmp(buf, getpass("Retype new password:")))
+ break;
+ (void)printf("Mismatch; try again, EOF to quit.\n");
+ }
+ /* grab a random printable character that isn't a colon */
+ if (!randinit) {
+ randinit = 1;
+ srandomdev();
+ }
+#ifdef NEWSALT
+ salt[0] = _PASSWORD_EFMT1;
+ to64(&salt[1], (long)(29 * 25), 4);
+ to64(&salt[5], random(), 4);
+ salt[9] = '\0';
+#else
+ /* Make a good size salt for algoritms that can use it. */
+ gettimeofday(&tv,0);
+ if (strncmp(pw->pw_passwd, "$1$", 3)) {
+ /* DES Salt */
+ to64(&salt[0], random(), 3);
+ to64(&salt[3], tv.tv_usec, 3);
+ to64(&salt[6], tv.tv_sec, 2);
+ salt[8] = '\0';
+ }
+ else {
+ /* MD5 Salt */
+ strncpy(&salt[0], "$1$", 3);
+ to64(&salt[3], random(), 3);
+ to64(&salt[6], tv.tv_usec, 3);
+ salt[8] = '\0';
+ }
+#endif
+ return (crypt(buf, salt));
+}
+
+int
+local_passwd(uname)
+ char *uname;
+{
+ struct passwd *pw;
+ int pfd, tfd;
+
+ if (!(pw = getpwnam(uname)))
+ errx(1, "unknown user %s", uname);
+
+#ifdef YP
+ /* Use the right password information. */
+ pw = (struct passwd *)&local_password;
+#endif
+ uid = getuid();
+ if (uid && uid != pw->pw_uid)
+ errx(1, "%s", strerror(EACCES));
+
+ pw_init();
+ pfd = pw_lock();
+ tfd = pw_tmp();
+
+ /*
+ * Get the new password. Reset passwd change time to zero by
+ * default. If the user has a valid login class (or the default
+ * fallback exists), then the next password change date is set
+ * by getnewpasswd() according to the "passwordperiod" capability
+ * if one has been specified.
+ */
+ pw->pw_change = 0;
+ pw->pw_passwd = getnewpasswd(pw, 0);
+ pw_copy(pfd, tfd, pw);
+
+ if (!pw_mkdb(uname))
+ pw_error((char *)NULL, 0, 1);
+#ifdef LOGGING
+ syslog(LOG_DEBUG, "user %s changed their local password\n", uname);
+#endif
+ return (0);
+}
diff --git a/usr.bin/passwd/passwd.1 b/usr.bin/passwd/passwd.1
new file mode 100644
index 0000000..a595bfa
--- /dev/null
+++ b/usr.bin/passwd/passwd.1
@@ -0,0 +1,210 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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
+.\" 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)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" 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.
+.\"
+.\" @(#)passwd.1 8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt PASSWD 1
+.Os BSD 4
+.Sh NAME
+.Nm passwd, yppasswd
+.Nd modify a user's password
+.Sh SYNOPSIS
+.Nm passwd
+.Op Fl l
+.Op Ar user
+.Nm yppasswd
+.Op Fl l
+.Op Fl y
+.Op Fl d Ar domain
+.Op Fl s Ar host
+.Op Fl o
+.Sh DESCRIPTION
+.Nm Passwd
+changes the user's local, Kerberos, or NIS password. First, the user is prompted for their
+current password.
+If the current password is correctly typed, a new password is
+requested.
+The new password must be entered twice to avoid typing errors.
+.Pp
+The new password should be at least six characters long (which
+may be overridden using the
+.Xr login.cap 5
+"minpasswordlen" setting for a user's login class) and not purely alphabetic.
+Its total length must be less than
+.Dv _PASSWORD_LEN
+(currently 128 characters).
+Numbers, upper case letters and meta characters
+are encouraged.
+.Pp
+Once the password has been verified,
+.Nm passwd
+communicates the new password information to
+the Kerberos authenticating host.
+.Bl -tag -width flag
+.It Fl l
+This option causes the password to be updated only in the local
+password file, and not with the Kerberos database.
+When changing only the local password,
+.Xr pwd_mkdb 8
+is used to update the password databases.
+.Pp
+.El
+When changing local or NIS password, the next password change date
+is set according to "passwordperiod" capability in the user's
+login class.
+.Pp
+To change another user's Kerberos password, one must first
+run
+.Xr kinit 1
+followed by
+.Xr passwd 1 .
+The super-user is not required to provide a user's current password
+if only the local password is modified.
+.Sh NIS INTERACTION
+.Nm Passwd
+has built-in support for NIS. If a user exists in the NIS password
+database but does not exist locally,
+.Nm passwd
+automatically switches into ``yppasswd'' mode. If the specified
+user does not exist in either the local password database of the
+NIS password maps,
+.Nm passwd
+returns an error.
+.Pp
+When changing an NIS password, unprivileged users are required to provide
+their old password for authentication (the
+.Xr rpc.yppasswdd 8
+daemon requires the original password before
+it will allow any changes to the NIS password maps).
+This restriction applies even to the
+super-user, with one important exception: the password authentication is
+bypassed for the super-user on the NIS master server. This means that
+the super-user on the NIS master server can make unrestricted changes to
+anyone's NIS password. The super-user on NIS client systems and NIS slave
+servers still needs to provide a password before the update will be processed.
+.Pp
+The following additional options are supported for use with NIS:
+.Bl -tag -width flag
+.It Fl y
+The
+.Fl y
+flag overrides
+.Nm passwd 's
+checking heuristics and forces
+it into NIS mode.
+.It Fl l
+When NIS is enabled, the
+.Fl l
+flag can be used to force
+.Nm passwd
+into ``local only'' mode. This flag can be used to change the entry
+for a local user when an NIS user exists when the same login name.
+For example, you will sometimes find entries for system ``placeholder''
+users such as
+.Pa bin
+or
+.Pa daemon
+in both the NIS password maps and the local user database. By
+default,
+.Nm passwd
+will try to change the NIS password. The
+.Fl l
+flag can be used to change the local password instead.
+.It Fl d Ar domain
+Specify what domain to use when changing an NIS password. By default,
+.Nm passwd
+assumes that the system default domain should be used. This flag is
+primarily for use by the superuser on the NIS master server: a single
+NIS server can support multiple domains. It is also possible that the
+domainname on the NIS master may not be set (it is not necessary for
+an NIS server to also be a client) in which case the
+.Nm passwd
+command needs to be told what domain to operate on.
+.It Fl s Ar host
+Specify the name of an NIS server. This option, in conjunction
+with the
+.Fl d
+option, can be used to change an NIS password on a non-local NIS
+server. When a domain is specified with the
+.Fl d
+option and
+.Nm passwd
+is unable to determine the name of the NIS master server (possibly because
+the local domainname isn't set), the name of the NIS master is assumed to
+be ``localhost''. This can be overriden with the
+.Fl s
+flag. The specified hostname need not be the name of an NIS master: the
+name of the NIS master for a given map can be determined by querying any
+NIS server (master or slave) in a domain, so specifying the name of a
+slave server will work equally well.
+.Pp
+.It Fl o
+Do not automatically override the password authentication checks for the
+super-user on the NIS master server; assume 'old' mode instead. This
+flag is of limited practical use but is useful for testing.
+.El
+.Sh FILES
+.Bl -tag -width /etc/master.passwd -compact
+.It Pa /etc/master.passwd
+The user database
+.It Pa /etc/passwd
+A Version 7 format password file
+.It Pa /etc/passwd.XXXXXX
+Temporary copy of the password file
+.It Pa /etc/login.conf
+Login class capabilities database
+.El
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr kerberos 1 ,
+.Xr kinit 1 ,
+.Xr login 1 ,
+.Xr login.conf 5 ,
+.Xr passwd 5 ,
+.Xr kpasswdd 8 ,
+.Xr pwd_mkdb 8 ,
+.Xr vipw 8
+.Rs
+.%A Robert Morris
+.%A Ken Thompson
+.%T "UNIX password security"
+.Re
+.Sh NOTES
+The
+.Xr yppasswd 1
+command is really only a link to
+.Nm passwd .
+.Sh HISTORY
+A
+.Nm passwd
+command appeared in
+.At v6 .
diff --git a/usr.bin/passwd/passwd.c b/usr.bin/passwd/passwd.c
new file mode 100644
index 0000000..46562c6
--- /dev/null
+++ b/usr.bin/passwd/passwd.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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
+ * 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)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ *
+ * $id$
+ *
+ */
+
+#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
+static const char sccsid[] = "From: @(#)passwd.c 8.3 (Berkeley) 4/2/94";
+static const char rcsid[] =
+ "$Id: passwd.c,v 1.11 1997/02/22 19:56:35 peter Exp $";
+#endif /* not lint */
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.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 __P(( char * ));
+#endif
+
+#ifdef KERBEROS
+#include "krb.h"
+#endif
+
+#include "extern.h"
+
+void usage __P((void));
+
+int use_local_passwd = 0;
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int ch;
+ char *uname;
+ char *iflag = 0, *rflag = 0, *uflag = 0;
+
+#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;
+ 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
+ break;
+ case 'o':
+ force_old++;
+ break;
+#endif
+ default:
+ case '?':
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if ((uname = getlogin()) == NULL)
+ err(1, "getlogin");
+
+ switch(argc) {
+ case 0:
+ break;
+ case 1:
+ uname = argv[0];
+ 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
+ if(krb_get_lrealm(realm, 0) == KSUCCESS) {
+ fprintf(stderr, "realm %s\n", realm);
+ exit(krb_passwd(argv[0], iflag, rflag, uflag));
+ }
+#endif
+ }
+ exit(local_passwd(uname));
+}
+
+void
+usage()
+{
+
+#ifdef YP
+#ifdef KERBEROS
+ fprintf(stderr,
+ "usage: passwd [-l] [-i instance] [-r realm] [-u fullname]\n");
+ fprintf(stderr,
+ " [-l] [-y] [-o] [-d domain [-h host]] [user]\n");
+#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);
+}
diff --git a/usr.bin/passwd/yp_passwd.c b/usr.bin/passwd/yp_passwd.c
new file mode 100644
index 0000000..3eab43a
--- /dev/null
+++ b/usr.bin/passwd/yp_passwd.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * Copyright (c) 1994 Olaf Kirch <okir@monad.swb.de>
+ * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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. 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 AUTHOR ``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 AUTHOR 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)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * 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.
+ */
+
+#ifdef YP
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <time.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#include <pw_yp.h>
+#include "yppasswd_comm.h"
+
+extern char *getnewpasswd __P(( struct passwd * , int ));
+
+int
+yp_passwd(char *user)
+{
+ struct timeval timeout;
+ struct yppasswd yppasswd;
+ struct master_yppasswd master_yppasswd;
+ struct passwd *pw;
+ CLIENT *clnt;
+ struct rpc_err err;
+ char *master;
+ int *status = NULL;
+ uid_t uid;
+
+ _use_yp = 1;
+
+ uid = getuid();
+
+ if ((master = get_yp_master(1)) == NULL) {
+ warnx("failed to find NIS master server");
+ return(1);
+ }
+
+ /*
+ * It is presumed that by the time we get here, use_yp()
+ * has been called and that we have verified that the user
+ * actually exists. This being the case, the yp_password
+ * stucture has already been filled in for us.
+ */
+
+ /* Use the correct password */
+ pw = (struct passwd *)&yp_password;
+
+ if (pw->pw_uid != uid && uid != 0) {
+ warnx("Only the super-user may change account information \
+for other users");
+ return(1);
+ }
+
+ pw->pw_change = 0;
+
+ /* Initialize password information */
+ if (suser_override) {
+ master_yppasswd.newpw.pw_passwd = strdup(pw->pw_passwd);
+ master_yppasswd.newpw.pw_name = strdup(pw->pw_name);
+ master_yppasswd.newpw.pw_uid = pw->pw_uid;
+ master_yppasswd.newpw.pw_gid = pw->pw_gid;
+ master_yppasswd.newpw.pw_expire = pw->pw_expire;
+ master_yppasswd.newpw.pw_change = pw->pw_change;
+ master_yppasswd.newpw.pw_fields = pw->pw_fields;
+ master_yppasswd.newpw.pw_gecos = strdup(pw->pw_gecos);
+ master_yppasswd.newpw.pw_dir = strdup(pw->pw_dir);
+ master_yppasswd.newpw.pw_shell = strdup(pw->pw_shell);
+ master_yppasswd.newpw.pw_class = pw->pw_class != NULL ?
+ strdup(pw->pw_class) : "";
+ master_yppasswd.oldpass = "";
+ master_yppasswd.domain = yp_domain;
+ } else {
+ yppasswd.newpw.pw_passwd = strdup(pw->pw_passwd);
+ yppasswd.newpw.pw_name = strdup(pw->pw_name);
+ yppasswd.newpw.pw_uid = pw->pw_uid;
+ yppasswd.newpw.pw_gid = pw->pw_gid;
+ yppasswd.newpw.pw_gecos = strdup(pw->pw_gecos);
+ yppasswd.newpw.pw_dir = strdup(pw->pw_dir);
+ yppasswd.newpw.pw_shell = strdup(pw->pw_shell);
+ yppasswd.oldpass = "";
+ }
+
+ if (suser_override)
+ printf("Changing NIS password for %s on %s in domain %s.\n",
+ pw->pw_name, master, yp_domain);
+ else
+ printf("Changing NIS password for %s on %s.\n",
+ pw->pw_name, master);
+
+ /* Get old password */
+
+ if(pw->pw_passwd[0] && !suser_override) {
+ yppasswd.oldpass = strdup(getpass("Old Password: "));
+ if (strcmp(crypt(yppasswd.oldpass, pw->pw_passwd),
+ pw->pw_passwd)) {
+ errx(1, "Sorry.");
+ }
+
+ }
+
+ if (suser_override) {
+ if ((master_yppasswd.newpw.pw_passwd = getnewpasswd(pw, 1)) == NULL)
+ return(1);
+ } else {
+ if ((yppasswd.newpw.pw_passwd = getnewpasswd(pw, 1)) == NULL)
+ return(1);
+ }
+
+ if (suser_override) {
+ if (senddat(&master_yppasswd)) {
+ warnx("failed to send request to rpc.yppasswdd");
+ return(1);
+ }
+ status = getresp();
+ } else {
+ if ((clnt = clnt_create(master, YPPASSWDPROG,
+ YPPASSWDVERS, "udp")) == NULL) {
+ warnx("failed to contact rpc.yppasswdd on host %s: %s",
+ master, clnt_spcreateerror(""));
+ return(1);
+ }
+ /*
+ * The yppasswd.x file said `unix authentication required',
+ * so I added it. This is the only reason it is in here.
+ * My yppasswdd doesn't use it, but maybe some others out there
+ * do. --okir
+ */
+ clnt->cl_auth = authunix_create_default();
+
+ status = yppasswdproc_update_1(&yppasswd, clnt);
+ clnt_geterr(clnt, &err);
+
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ }
+
+ if ((!suser_override && err.re_status != RPC_SUCCESS) ||
+ status == NULL || *status) {
+ errx(1, "Failed to change NIS password: %s",
+ (err.re_status != RPC_SUCCESS && !suser_override) ?
+ clnt_sperrno(err.re_status) :
+ "rpc.yppasswdd returned error status");
+ }
+
+ printf("\nNIS password has%s been changed on %s.\n",
+ ((err.re_status != RPC_SUCCESS && !suser_override)
+ || status == NULL || *status) ?
+ " not" : "", master);
+
+ return ((err.re_status || status == NULL || *status));
+}
+#endif /* YP */
OpenPOWER on IntegriCloud