diff options
Diffstat (limited to 'usr.bin/passwd')
| -rw-r--r-- | usr.bin/passwd/Makefile | 18 | ||||
| -rw-r--r-- | usr.bin/passwd/kpasswd_proto.h | 54 | ||||
| -rw-r--r-- | usr.bin/passwd/krb_passwd.c | 316 | ||||
| -rw-r--r-- | usr.bin/passwd/local_passwd.c | 15 | ||||
| -rw-r--r-- | usr.bin/passwd/passwd.c | 4 | ||||
| -rw-r--r-- | usr.bin/passwd/pw_fastmkdb.c | 268 | ||||
| -rw-r--r-- | usr.bin/passwd/yp_passwd.c | 7 |
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), |
