diff --git a/usr.bin/chkey/Makefile b/usr.bin/chkey/Makefile new file mode 100644 index 000000000000..6cc1d1c428d9 --- /dev/null +++ b/usr.bin/chkey/Makefile @@ -0,0 +1,14 @@ +# $Id$ + +PROG= chkey +SRCS= chkey.c update.c generic.c + +.PATH: ${.CURDIR}/../newkey + +MAN1= chkey.1 + +CFLAGS+= -DYP + +LDADD+= -lrpcsvc -lmp -lgmp + +.include diff --git a/usr.bin/chkey/chkey.1 b/usr.bin/chkey/chkey.1 new file mode 100644 index 000000000000..7db240de5f55 --- /dev/null +++ b/usr.bin/chkey/chkey.1 @@ -0,0 +1,21 @@ +.\" @(#)chkey.1 1.5 91/03/11 TIRPC 1.0; +.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved. +.\" +.TH CHKEY 1 "5 July 1989" +.SH NAME +chkey \- change your encryption key +.SH SYNOPSIS +.B chkey +.SH DESCRIPTION +.LP +.B chkey +prompts the user for their login password, +and uses it to encrypt a new encryption key +for the user to be stored in the +.BR publickey (5) +database. +.SH "SEE ALSO" +.BR keylogin (1), +.BR publickey (5), +.BR keyserv (8C), +.BR newkey (8). diff --git a/usr.bin/chkey/chkey.c b/usr.bin/chkey/chkey.c new file mode 100644 index 000000000000..b7690540825e --- /dev/null +++ b/usr.bin/chkey/chkey.c @@ -0,0 +1,288 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#ifndef lint +static char sccsid[] = "@(#)chkey.c 1.7 91/03/11 Copyr 1986 Sun Micro"; +#endif +/* + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +/* + * Command to change one's public key in the public key database + */ +#include +#include +#include +#ifdef YP +#include +#include +#else +#define YPOP_STORE 4 +#endif +#include +#include +#include + +extern char *getpass(); +#define index strchr +extern char *crypt(); +#ifdef YPPASSWD +struct passwd *ypgetpwuid(); +#endif + +#ifdef YP +static char *domain; +static char PKMAP[] = "publickey.byname"; +#else +static char PKFILE[] = "/etc/publickey"; +#endif /* YP */ +static char ROOTKEY[] = "/etc/.rootkey"; + +main(argc, argv) + int argc; + char **argv; +{ + char name[MAXNETNAMELEN+1]; + char public[HEXKEYBYTES + 1]; + char secret[HEXKEYBYTES + 1]; + char crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1]; + char crypt2[HEXKEYBYTES + KEYCHECKSUMSIZE + 1]; + int status; + char *pass; + struct passwd *pw; + uid_t uid; + int force = 0; + char *self; +#ifdef YP + char *master; +#endif + + self = argv[0]; + for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) { + if (argv[0][2] != 0) { + usage(self); + } + switch (argv[0][1]) { + case 'f': + force = 1; + break; + default: + usage(self); + } + } + if (argc != 0) { + usage(self); + } + +#ifdef YP + (void)yp_get_default_domain(&domain); + if (yp_master(domain, PKMAP, &master) != 0) { + (void)fprintf(stderr, + "can't find master of publickey database\n"); + exit(1); + } +#endif + uid = getuid() /*geteuid()*/; + if (uid == 0) { + if (host2netname(name, NULL, NULL) == 0) { + (void)fprintf(stderr, + "chkey: cannot convert hostname to netname\n"); + exit(1); + } + } else { + if (user2netname(name, uid, NULL) == 0) { + (void)fprintf(stderr, + "chkey: cannot convert username to netname\n"); + exit(1); + } + } + (void)printf("Generating new key for %s.\n", name); + + if (!force) { + if (uid != 0) { +#ifdef YPPASSWD + pw = ypgetpwuid(uid); +#else + pw = getpwuid(uid); +#endif + if (pw == NULL) { +#ifdef YPPASSWD + (void)fprintf(stderr, + "No NIS password entry found: can't change key.\n"); +#else + (void)fprintf(stderr, + "No password entry found: can't change key.\n"); +#endif + exit(1); + } + } else { + pw = getpwuid(0); + if (pw == NULL) { + (void)fprintf(stderr, + "No password entry found: can't change key.\n"); + exit(1); + } + } + } + pass = getpass("Password:"); +#ifdef YPPASSWD + if (!force) { + if (strcmp(crypt(pass, pw->pw_passwd), pw->pw_passwd) != 0) { + (void)fprintf(stderr, "Invalid password.\n"); + exit(1); + } + } +#else + force = 1; /* Make this mandatory */ +#endif + genkeys(public, secret, pass); + + memcpy(crypt1, secret, HEXKEYBYTES); + memcpy(crypt1 + HEXKEYBYTES, secret, KEYCHECKSUMSIZE); + crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0; + xencrypt(crypt1, pass); + + if (force) { + memcpy(crypt2, crypt1, HEXKEYBYTES + KEYCHECKSUMSIZE + 1); + xdecrypt(crypt2, getpass("Retype password:")); + if (memcmp(crypt2, crypt2 + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0 || + memcmp(crypt2, secret, HEXKEYBYTES) != 0) { + (void)fprintf(stderr, "Password incorrect.\n"); + exit(1); + } + } + +#ifdef YP + (void)printf("Sending key change request to %s...\n", master); +#endif + status = setpublicmap(name, public, crypt1); + if (status != 0) { +#ifdef YP + (void)fprintf(stderr, + "%s: unable to update NIS database (%u): %s\n", + self, status, yperr_string(status)); +#else + (void)fprintf(stderr, + "%s: unable to update publickey database\n", self); +#endif + exit(1); + } + + if (uid == 0) { + /* + * Root users store their key in /etc/$ROOTKEY so + * that they can auto reboot without having to be + * around to type a password. Storing this in a file + * is rather dubious: it should really be in the EEPROM + * so it does not go over the net. + */ + int fd; + + fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0); + if (fd < 0) { + perror(ROOTKEY); + } else { + char newline = '\n'; + + if (write(fd, secret, strlen(secret)) < 0 || + write(fd, &newline, sizeof(newline)) < 0) { + (void)fprintf(stderr, "%s: ", ROOTKEY); + perror("write"); + } + } + } + + if (key_setsecret(secret) < 0) { + (void)printf("Unable to login with new secret key.\n"); + exit(1); + } + (void)printf("Done.\n"); + exit(0); + /* NOTREACHED */ +} + +usage(name) + char *name; +{ + (void)fprintf(stderr, "usage: %s [-f]\n", name); + exit(1); + /* NOTREACHED */ +} + + +/* + * Set the entry in the public key file + */ +setpublicmap(name, public, secret) + char *name; + char *public; + char *secret; +{ + char pkent[1024]; + + (void)sprintf(pkent,"%s:%s", public, secret); +#ifdef YP + return (yp_update(domain, PKMAP, YPOP_STORE, + name, strlen(name), pkent, strlen(pkent))); +#else + return (localupdate(name, PKFILE, YPOP_STORE, + strlen(name), name, strlen(pkent), pkent)); +#endif +} + +#ifdef YPPASSWD +struct passwd * +ypgetpwuid(uid) + uid_t uid; +{ + char uidstr[10]; + char *val; + int vallen; + static struct passwd pw; + char *p; + + (void)sprintf(uidstr, "%d", uid); + if (yp_match(domain, "passwd.byuid", uidstr, strlen(uidstr), + &val, &vallen) != 0) { + return (NULL); + } + p = index(val, ':'); + if (p == NULL) { + return (NULL); + } + pw.pw_passwd = p + 1; + p = index(pw.pw_passwd, ':'); + if (p == NULL) { + return (NULL); + } + *p = 0; + return (&pw); +} +#endif /* YPPASSWD */