summaryrefslogtreecommitdiff
path: root/usr.bin/passwd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/passwd')
-rw-r--r--usr.bin/passwd/Makefile18
-rw-r--r--usr.bin/passwd/kpasswd_proto.h54
-rw-r--r--usr.bin/passwd/krb_passwd.c316
-rw-r--r--usr.bin/passwd/local_passwd.c15
-rw-r--r--usr.bin/passwd/passwd.c4
-rw-r--r--usr.bin/passwd/pw_fastmkdb.c268
-rw-r--r--usr.bin/passwd/yp_passwd.c7
7 files changed, 668 insertions, 14 deletions
diff --git a/usr.bin/passwd/Makefile b/usr.bin/passwd/Makefile
index 25f20f2c3f4a..85a23ca64b59 100644
--- a/usr.bin/passwd/Makefile
+++ b/usr.bin/passwd/Makefile
@@ -1,19 +1,27 @@
# @(#)Makefile 5.11 (Berkeley) 2/19/91
PROG= passwd
-SRCS= local_passwd.c passwd.c pw_copy.c pw_util.c yp_passwd.c getpwent.c
+SRCS= local_passwd.c passwd.c pw_copy.c pw_util.c yp_passwd.c getpwent.c \
+ krb_passwd.c pw_fastmkdb.c
CFLAGS+=-I${.CURDIR} -DYP
.PATH: ${.CURDIR}/../../usr.bin/chpass ${.CURDIR}/../../usr.sbin/vipw \
${.CURDIR}/../rlogin ${.CURDIR}/../../lib/libc/gen
-DPADD+= ${LIBRPCSVC} #${LIBKRB}
-LDADD+= -lrpcsvc #-lkrb
+DPADD+= ${LIBRPCSVC}
+LDADD+= -lrpcsvc
-.if exists(/usr/lib/libcrypt.a)
-#CFLAGS+=-DKERBEROS
+.if exists(${DESTDIR}/usr/lib/libcrypt.a)
DPADD+= ${LIBCRYPT}
LDADD+= -lcrypt
.endif
+.if exists(${DESTDIR}/usr/lib/libkrb.a)
+CFLAGS+= -DKERBEROS
+DPADD+= ${LIBKRB}
+LDADD+= -lkrb -ldes
+.endif
+.if defined (PW_COMPACT)
+CFLAGS+=-DPW_COMPACT
+.endif
getpwent.o: getpwent.c
${CC} ${CFLAGS} -UYP -c ${.IMPSRC}
diff --git a/usr.bin/passwd/kpasswd_proto.h b/usr.bin/passwd/kpasswd_proto.h
new file mode 100644
index 000000000000..9c76fd40ce4e
--- /dev/null
+++ b/usr.bin/passwd/kpasswd_proto.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1989 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 5.1 (Berkeley) 2/3/91
+ */
+
+/*
+ * 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 000000000000..56de10b99fd9
--- /dev/null
+++ b/usr.bin/passwd/krb_passwd.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1990 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 5.4 (Berkeley) 3/1/91";
+#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 <netdb.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include "kpasswd_proto.h"
+#include <string.h>
+#include <stdlib.h>
+
+#define PROTO "tcp"
+
+static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0 };
+static struct kpasswd_data proto_data;
+static des_cblock okey;
+static Key_schedule osched;
+KTEXT_ST ticket;
+Key_schedule random_schedule;
+long authopts;
+char realm[REALM_SZ], krbhst[MAX_HSTNM];
+int sock;
+
+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) {
+ (void)fprintf(stderr,
+ "passwd: setrlimit: %s\n", strerror(errno));
+ return(1);
+ }
+
+ if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
+ (void)fprintf(stderr,
+ "passwd: couldn't find entry for service %s/%s\n",
+ SERVICE, PROTO);
+ return(1);
+ }
+
+ if ((rval = krb_get_lrealm(realm,1)) != KSUCCESS) {
+ (void)fprintf(stderr,
+ "passwd: couldn't get local Kerberos realm: %s\n",
+ krb_err_txt[rval]);
+ return(1);
+ }
+
+ if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
+ (void)fprintf(stderr,
+ "passwd: couldn't get Kerberos host: %s\n",
+ krb_err_txt[rval]);
+ return(1);
+ }
+
+ if ((host = gethostbyname(krbhst)) == NULL) {
+ (void)fprintf(stderr,
+ "passwd: couldn't get host entry for krb host %s\n",
+ krbhst);
+ return(1);
+ }
+
+ sin.sin_family = host->h_addrtype;
+ bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
+ sin.sin_port = se->s_port;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ (void)fprintf(stderr, "passwd: socket: %s\n", strerror(errno));
+ return(1);
+ }
+
+ if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+ (void)fprintf(stderr, "passwd: connect: %s\n", strerror(errno));
+ (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) {
+ (void)fprintf(stderr, "passwd: Kerberos sendauth error: %s\n",
+ 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)) {
+ (void)fprintf(stderr,
+ "passwd: error reading old Kerberos password\n");
+ 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) {
+ (void)fprintf(stderr, "passwd: timed out (aborted)\n");
+ cleanup();
+ return(1);
+ }
+ (void)fprintf(stderr, "passwd: select failed (aborted)\n");
+ cleanup();
+ return(1);
+ }
+
+ /* read verification string */
+
+ if (des_read(sock, &proto_data, sizeof(proto_data)) !=
+ sizeof(proto_data)) {
+ (void)fprintf(stderr,
+ "passwd: couldn't read verification string (aborted)\n");
+ 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)bzero(pass, sizeof(pass));
+
+ if (des_read_pw_string(pass,
+ sizeof(pass)-1, "New Kerberos password:", 0)) {
+ (void)fprintf(stderr,
+ "passwd: error reading new Kerberos password (aborted)\n");
+ cleanup();
+ return(1);
+ }
+
+ if (des_read_pw_string(password,
+ sizeof(password)-1, "Retype new Kerberos password:", 0)) {
+ (void)fprintf(stderr,
+ "passwd: error reading new Kerberos password (aborted)\n");
+ cleanup();
+ return(1);
+ }
+
+ if (strcmp(password, pass) != 0) {
+ (void)fprintf(stderr,
+ "passwd: password mismatch (aborted)\n");
+ 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) {
+ (void)fprintf(stderr,
+ "passwd: timed out reading ACK (aborted)\n");
+ cleanup();
+ exit(1);
+ }
+ (void)fprintf(stderr, "passwd: select failed (aborted)\n");
+ cleanup();
+ exit(1);
+ }
+ recv_ack(sock);
+ cleanup();
+ exit(0);
+}
+
+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)) {
+ (void)fprintf(stderr,
+ "passwd: couldn't write pw update (abort)\n");
+ bzero((char *)&ud, sizeof(ud));
+ cleanup();
+ exit(1);
+ }
+}
+
+recv_ack(remote)
+ int remote;
+{
+ int cc;
+ char buf[BUFSIZ];
+
+ cc = des_read(remote, buf, sizeof(buf));
+ if (cc <= 0) {
+ (void)fprintf(stderr,
+ "passwd: error reading acknowledgement (aborted)\n");
+ cleanup();
+ exit(1);
+ }
+ (void)printf("%s", buf);
+}
+
+cleanup()
+{
+ (void)bzero((char *)&proto_data, sizeof(proto_data));
+ (void)bzero((char *)okey, sizeof(okey));
+ (void)bzero((char *)osched, sizeof(osched));
+ (void)bzero((char *)random_schedule, 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
index 0a81ab1dce18..7eec89289c0f 100644
--- a/usr.bin/passwd/local_passwd.c
+++ b/usr.bin/passwd/local_passwd.c
@@ -33,7 +33,7 @@
#ifndef lint
/*static char sccsid[] = "from: @(#)local_passwd.c 5.5 (Berkeley) 5/6/91";*/
-static char rcsid[] = "$Id: local_passwd.c,v 1.4 1994/01/11 19:01:13 nate Exp $";
+static char rcsid[] = "$Id: local_passwd.c,v 1.7 1994/05/20 00:29:19 ache Exp $";
#endif /* not lint */
#include <sys/types.h>
@@ -81,8 +81,17 @@ local_passwd(uname)
pw->pw_change = 0;
pw_copy(pfd, tfd, pw);
- if (!pw_mkdb())
- pw_error((char *)NULL, 0, 1);
+ /*
+ * Attempt a recovery if the incremental database update failed by
+ * handing off to the real password hashing program to remake the
+ * whole mess. Even though this costs lots of time it's better than
+ * having the password databases out of sync with the master pw file.
+ */
+ if (pw_fastmkdb(pw) < 0) {
+ fprintf(stderr,"%s: WARNING!! Password database mangled, recreating it from scratch\n", progname);
+ if(!pw_mkdb())
+ pw_error((char *)NULL, 0, 1);
+ }
return(0);
}
diff --git a/usr.bin/passwd/passwd.c b/usr.bin/passwd/passwd.c
index 4ffaeb050e22..f1cbbdfda48a 100644
--- a/usr.bin/passwd/passwd.c
+++ b/usr.bin/passwd/passwd.c
@@ -39,7 +39,7 @@ char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)passwd.c 5.5 (Berkeley) 7/6/91";*/
-static char rcsid[] = "$Id: passwd.c,v 1.2 1994/01/11 19:01:15 nate Exp $";
+static char rcsid[] = "$Id: passwd.c,v 1.3 1994/05/14 19:40:58 ache Exp $";
#endif /* not lint */
#include <stdio.h>
@@ -128,7 +128,7 @@ main(argc, argv)
break;
case 1:
#ifdef KERBEROS
- if (use_kerberos && strcmp(argv[1], uname)) {
+ if (use_kerberos && strcmp(argv[0], uname)) {
(void)fprintf(stderr, "passwd: %s\n\t%s\n%s\n",
"to change another user's Kerberos password, do",
"\"kinit user; passwd; kdestroy\";",
diff --git a/usr.bin/passwd/pw_fastmkdb.c b/usr.bin/passwd/pw_fastmkdb.c
new file mode 100644
index 000000000000..eaa986a08c4e
--- /dev/null
+++ b/usr.bin/passwd/pw_fastmkdb.c
@@ -0,0 +1,268 @@
+/*-
+ * Copyright (c) 1991 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <db.h>
+#include <pwd.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+/* #define PW_COMPACT */
+/* Compact pwd.db/spwd.db structure by Alex G. Bulushev, bag@demos.su */
+#ifdef PW_COMPACT
+# define HI_BSIZE 1024
+# define HI_NELEM 4500
+# define HI_CACHE (1024 * 1024)
+#else
+# define HI_BSIZE 2048
+# define HI_NELEM 4500
+# define HI_CACHE (4000 * 1024)
+#endif
+
+#define INSECURE 1
+#define SECURE 2
+#define PERM_INSECURE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
+#define PERM_SECURE (S_IRUSR|S_IWUSR)
+
+static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
+static struct passwd pwd; /* password structure */
+
+extern char *tempname;
+extern char *progname;
+extern int globcnt;
+
+pw_fastmkdb(new_pwd)
+ struct passwd *new_pwd;
+{
+ register int len;
+ register char *p, *t;
+ DB *dp, *edp;
+ sigset_t set;
+ DBT data, key;
+#ifdef PW_COMPACT
+ DBT pdata, sdata;
+#endif
+ char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
+ char buf2[MAX(MAXPATHLEN, LINE_MAX * 2)];
+ int uid;
+ int gid;
+ HASHINFO openinfo;
+
+ /* Hash database parameters */
+ openinfo.bsize=HI_BSIZE;
+ openinfo.ffactor=32;
+ openinfo.nelem=HI_NELEM; /* Default value was 300 */
+ openinfo.cachesize=HI_CACHE; /* Default value was 512 */
+ openinfo.hash=NULL;
+ openinfo.lorder=0;
+
+ /*
+ * This could be done to allow the user to interrupt. Probably
+ * not worth the effort.
+ */
+ sigemptyset(&set);
+ sigaddset(&set, SIGTSTP);
+ sigaddset(&set, SIGHUP);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGQUIT);
+ sigaddset(&set, SIGTERM);
+ (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
+
+ /* Open the insecure password database. */
+ dp = dbopen(_PATH_MP_DB, O_RDWR, PERM_INSECURE, DB_HASH, &openinfo);
+ if (!dp)
+ error(_PATH_MP_DB);
+ /*
+ * The databases actually contain three copies of the original data.
+ * Each password file entry is converted into a rough approximation
+ * of a ``struct passwd'', with the strings placed inline. This
+ * object is then stored as the data for three separate keys. The
+ * first key * is the pw_name field prepended by the _PW_KEYBYNAME
+ * character. The second key is the pw_uid field prepended by the
+ * _PW_KEYBYUID character. The third key is the line number in the
+ * original file prepended by the _PW_KEYBYNUM character. (The special
+ * characters are prepended to ensure that the keys do not collide.)
+ */
+ bcopy((char *)new_pwd, (char *)&pwd, sizeof(struct passwd));
+ data.data = (u_char *)buf;
+ key.data = (u_char *)tbuf;
+#ifdef PW_COMPACT
+ pdata.data = (u_char *)&globcnt;
+ pdata.size = sizeof(int);
+ sdata.data = (u_char *)pwd.pw_passwd;
+ sdata.size = strlen(pwd.pw_passwd) + 1;
+#endif
+#define COMPACT(e) t = e; while (*p++ = *t++);
+
+ /* Create insecure data. */
+ uid = pwd.pw_uid; /* force a particular size */
+ gid = pwd.pw_gid;
+ p = buf;
+ COMPACT(pwd.pw_name);
+#ifndef PW_COMPACT
+ COMPACT("*");
+#endif
+ bcopy((char *)&uid, p, sizeof(uid));
+ p += sizeof(int);
+ bcopy((char *)&gid, p, sizeof(gid));
+ p += sizeof(int);
+ bcopy((char *)&pwd.pw_change, p, sizeof(time_t));
+ p += sizeof(time_t);
+ COMPACT(pwd.pw_class);
+ COMPACT(pwd.pw_gecos);
+ COMPACT(pwd.pw_dir);
+ COMPACT(pwd.pw_shell);
+ bcopy((char *)&pwd.pw_expire, p, sizeof(time_t));
+ p += sizeof(time_t);
+ data.size = p - buf;
+
+ /* Store insecure by name. */
+ tbuf[0] = _PW_KEYBYNAME;
+ len = strlen(pwd.pw_name);
+ bcopy(pwd.pw_name, tbuf + 1, len);
+ key.size = len + 1;
+#ifdef PW_COMPACT
+ if ((dp->put)(dp, &key, &pdata, 0) == -1)
+#else
+ if ((dp->put)(dp, &key, &data, 0) == -1)
+#endif
+ error("put");
+
+ /* Store insecure by uid. */
+ tbuf[0] = _PW_KEYBYUID;
+ bcopy((char *)&uid, tbuf + 1, sizeof(uid));
+ key.size = sizeof(uid) + 1;
+#ifdef PW_COMPACT
+ if ((dp->put)(dp, &key, &pdata, 0) == -1)
+#else
+ if ((dp->put)(dp, &key, &data, 0) == -1)
+#endif
+ error("put");
+
+ /* Store insecure by number. */
+ tbuf[0] = _PW_KEYBYNUM;
+ bcopy((char *)&globcnt, tbuf + 1, sizeof(globcnt));
+ key.size = sizeof(globcnt) + 1;
+ if ((dp->put)(dp, &key, &data, 0) == -1)
+ error("put");
+
+ (void)(dp->close)(dp);
+
+ /* Open the encrypted password database. */
+ edp = dbopen(_PATH_SMP_DB, O_RDWR, PERM_SECURE, DB_HASH, &openinfo);
+ if (!edp)
+ error(_PATH_SMP_DB);
+#ifdef PW_COMPACT
+ /* Store secure. */
+ if ((edp->put)(edp, &key, &sdata, 0) == -1)
+ error("put");
+#else
+
+ /* Create secure data. */
+ p = buf;
+ COMPACT(pwd.pw_name);
+ COMPACT(pwd.pw_passwd);
+ bcopy((char *)&uid, p, sizeof(uid));
+ p += sizeof(int);
+ bcopy((char *)&gid, p, sizeof(gid));
+ p += sizeof(int);
+ bcopy((char *)&pwd.pw_change, p, sizeof(time_t));
+ p += sizeof(time_t);
+ COMPACT(pwd.pw_class);
+ COMPACT(pwd.pw_gecos);
+ COMPACT(pwd.pw_dir);
+ COMPACT(pwd.pw_shell);
+ bcopy((char *)&pwd.pw_expire, p, sizeof(time_t));
+ p += sizeof(time_t);
+ data.size = p - buf;
+
+ /* Store secure by name. */
+ tbuf[0] = _PW_KEYBYNAME;
+ len = strlen(pwd.pw_name);
+ bcopy(pwd.pw_name, tbuf + 1, len);
+ key.size = len + 1;
+ if ((edp->put)(edp, &key, &data, 0) == -1)
+ error("put");
+
+ /* Store secure by number. */
+ tbuf[0] = _PW_KEYBYNUM;
+ bcopy((char *)&globcnt, tbuf + 1, sizeof(globcnt));
+ key.size = sizeof(globcnt) + 1;
+ if ((edp->put)(edp, &key, &data, 0) == -1)
+ error("put");
+
+ /* Store secure by uid. */
+ tbuf[0] = _PW_KEYBYUID;
+ bcopy((char *)&uid, tbuf + 1, sizeof(uid));
+ key.size = sizeof(uid) + 1;
+ if ((edp->put)(edp, &key, &data, 0) == -1)
+ error("put");
+#endif
+
+ (void)(edp->close)(edp);
+
+ /*
+ * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
+ * all use flock(2) on it to block other incarnations of themselves.
+ * The rename means that everything is unlocked, as the original file
+ * can no longer be accessed.
+ */
+ mv(tempname, _PATH_MASTERPASSWD);
+ return(0);
+}
+
+mv(from, to)
+ char *from, *to;
+{
+ int sverrno;
+ char buf[MAXPATHLEN];
+
+ if (rename(from, to)) {
+ sverrno = errno;
+ (void)sprintf(buf, "%s to %s", from, to);
+ errno = sverrno;
+ error(buf);
+ }
+}
+
+error(name)
+ char *name;
+{
+ (void)fprintf(stderr, "%s: %s: %s\n", progname, name, strerror(errno));
+ return(-1);
+}
diff --git a/usr.bin/passwd/yp_passwd.c b/usr.bin/passwd/yp_passwd.c
index 01cac298223a..db6cd29a5439 100644
--- a/usr.bin/passwd/yp_passwd.c
+++ b/usr.bin/passwd/yp_passwd.c
@@ -32,7 +32,7 @@
*/
#ifndef lint
/*static char sccsid[] = "from: @(#)yp_passwd.c 1.0 2/2/93";*/
-static char rcsid[] = "$Id: yp_passwd.c,v 1.1 1994/01/11 19:01:16 nate Exp $";
+static char rcsid[] = "$Id: yp_passwd.c,v 1.2 1994/05/18 00:40:02 jkh Exp $";
#endif /* not lint */
#ifdef YP
@@ -162,9 +162,8 @@ getnewpasswd(pw, old_pass)
(void)printf("Changing YP password for %s.\n", pw->pw_name);
- if (uid && old_pass) {
- *old_pass = NULL;
-
+ *old_pass = "*";
+ if (uid) {
if (pw->pw_passwd &&
#ifdef DES
strcmp(crypt(p = getpass("Old password:"), pw->pw_passwd),