Import newkey.

This is the program used to generate new Secure RPC public and secret
key pairs.
This commit is contained in:
Bill Paul 1997-05-28 15:52:07 +00:00
parent 40a5f74d72
commit db8b6bbf74
5 changed files with 796 additions and 0 deletions

13
usr.bin/newkey/Makefile Normal file
View File

@ -0,0 +1,13 @@
# $Id$
PROG= newkey
SRCS= newkey.c update.c generic.c
MAN8= newkey.8
# Later
#CFLAGS+= -DYP
LDADD+= -lrpcsvc -lmp -lgmp
.include <bsd.prog.mk>

135
usr.bin/newkey/generic.c Normal file
View File

@ -0,0 +1,135 @@
/*
* 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
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)generic.c 1.2 91/03/11 Copyr 1986 Sun Micro";
#endif
/*
* Copyright (C) 1986, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/file.h>
#include <mp.h>
#include <rpc/key_prot.h>
static int adjust __P(( char[], char * ));
/*
* Generate a seed
*/
static
getseed(seed, seedsize, pass)
char *seed;
int seedsize;
unsigned char *pass;
{
int i;
int rseed;
struct timeval tv;
(void)gettimeofday(&tv, (struct timezone *)NULL);
rseed = tv.tv_sec + tv.tv_usec;
for (i = 0; i < 8; i++) {
rseed ^= (rseed << 8) | pass[i];
}
srand(rseed);
for (i = 0; i < seedsize; i++) {
seed[i] = (rand() & 0xff) ^ pass[i % 8];
}
}
/*
* Generate a random public/secret key pair
*/
genkeys(public, secret, pass)
char *public;
char *secret;
char *pass;
{
int i;
# define BASEBITS (8*sizeof (short) - 1)
# define BASE (1 << BASEBITS)
MINT *pk = itom(0);
MINT *sk = itom(0);
MINT *tmp;
MINT *base = itom(BASE);
MINT *root = itom(PROOT);
MINT *modulus = xtom(HEXMODULUS);
short r;
unsigned short seed[KEYSIZE/BASEBITS + 1];
char *xkey;
getseed((char *)seed, sizeof (seed), (u_char *)pass);
for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) {
r = seed[i] % BASE;
tmp = itom(r);
mult(sk, base, sk);
madd(sk, tmp, sk);
mfree(tmp);
}
tmp = itom(0);
mdiv(sk, modulus, tmp, sk);
mfree(tmp);
pow(root, sk, modulus, pk);
xkey = mtox(sk);
adjust(secret, xkey);
xkey = mtox(pk);
adjust(public, xkey);
mfree(sk);
mfree(base);
mfree(pk);
mfree(root);
mfree(modulus);
}
/*
* Adjust the input key so that it is 0-filled on the left
*/
static
adjust(keyout, keyin)
char keyout[HEXKEYBYTES+1];
char *keyin;
{
char *p;
char *s;
for (p = keyin; *p; p++)
;
for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) {
*s = *p;
}
while (s >= keyout) {
*s-- = '0';
}
}

57
usr.bin/newkey/newkey.8 Normal file
View File

@ -0,0 +1,57 @@
.\" @(#)newkey.8 1.3 91/03/11 TIRPC 1.0; from 1.12 90/02/03 SMI;
.TH NEWKEY 8 "12 October 1987"
.SH NAME
newkey \- create a new key in the publickey database
.SH SYNOPSIS
.B "newkey \-h"
.I hostname
.br
.B "newkey \-u"
.I username
.SH DESCRIPTION
.IX "newkey command" "" "\fLnewkey\fP command"
.LP
.B newkey
is normally run by the network administrator on the
Network Interface Service
(\s-1NIS\s0)
master machine in order to establish public keys for
users and super-users on the network.
These keys are needed for using secure
.SM RPC
or secure
.SM NFS\s0.
.LP
.B newkey
will prompt for the login password of the given username and then
create a new public/secret key pair in
.B /etc/publickey
encrypted with the login password of the given user.
.LP
Use of this program is
not required: users may create their own keys using
.BR chkey (1).
.SH OPTIONS
.TP 12
.BI \-h " hostname"
Create a new public key for the super-user at the given hostname.
Prompts for the root password of the given hostname.
.TP
.BI \-u " username"
Create a new public key for the given username.
Prompts for the
.SM NIS
password of the given username.
.SH "SEE ALSO"
.BR chkey (1),
.BR keylogin (1),
.BR publickey (5),
.BR keyserv (8C)
.SH NOTES
.LP
The Network Information Service
(\s-1NIS\s0)
was formerly known as Sun Yellow Pages
(\s-1YP\s0).
The functionality of the two remains the same;
only the name has changed.

235
usr.bin/newkey/newkey.c Normal file
View File

@ -0,0 +1,235 @@
/*
* 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
*/
#if !defined(lint) && defined(SCCSIDS)
static char sccsid[] = "@(#)newkey.c 1.8 91/03/11 Copyr 1986 Sun Micro";
#endif
/*
* Copyright (C) 1986, Sun Microsystems, Inc.
*/
/*
* Administrative tool to add a new user to the publickey database
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <rpc/key_prot.h>
#ifdef YP
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <sys/wait.h>
#include <netdb.h>
#endif /* YP */
#include <pwd.h>
#include <string.h>
#include <sys/resource.h>
#ifdef YP
#define MAXMAPNAMELEN 256
#else
#define YPOP_CHANGE 1 /* change, do not add */
#define YPOP_INSERT 2 /* add, do not change */
#define YPOP_DELETE 3 /* delete this entry */
#define YPOP_STORE 4 /* add, or change */
#define ERR_ACCESS 1
#define ERR_MALLOC 2
#define ERR_READ 3
#define ERR_WRITE 4
#define ERR_DBASE 5
#define ERR_KEY 6
#endif
extern char *getpass();
extern char *malloc();
#ifdef YP
static char *basename();
static char SHELL[] = "/bin/sh";
static char YPDBPATH[]="/var/yp";
static char PKMAP[] = "publickey.byname";
static char UPDATEFILE[] = "updaters";
#else
static char PKFILE[] = "/etc/publickey";
static char *err_string();
#endif /* YP */
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;
#ifdef undef
struct hostent *h;
#endif
if (argc != 3 || !(strcmp(argv[1], "-u") == 0 ||
strcmp(argv[1], "-h") == 0)) {
(void)fprintf(stderr, "usage: %s [-u username]\n",
argv[0]);
(void)fprintf(stderr, "usage: %s [-h hostname]\n",
argv[0]);
exit(1);
}
if (geteuid() != 0) {
(void)fprintf(stderr, "must be superuser to run %s\n", argv[0]);
exit(1);
}
#ifdef YP
if (chdir(YPDBPATH) < 0) {
(void)fprintf(stderr, "cannot chdir to ");
perror(YPDBPATH);
}
#endif /* YP */
if (strcmp(argv[1], "-u") == 0) {
pw = getpwnam(argv[2]);
if (pw == NULL) {
(void)fprintf(stderr, "unknown user: %s\n", argv[2]);
exit(1);
}
(void)user2netname(name, (int)pw->pw_uid, (char *)NULL);
} else {
#ifdef undef
h = gethostbyname(argv[2]);
if (h == NULL) {
(void)fprintf(stderr, "unknown host: %s\n", argv[1]);
exit(1);
}
(void)host2netname(name, h->h_name, (char *)NULL);
#else
(void)host2netname(name, argv[2], (char *)NULL);
#endif
}
(void)printf("Adding new key for %s.\n", name);
pass = getpass("New password:");
genkeys(public, secret, pass);
memcpy(crypt1, secret, HEXKEYBYTES);
memcpy(crypt1 + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
xencrypt(crypt1, pass);
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("Please wait for the database to get updated...\n");
#endif
if (status = setpublicmap(name, public, crypt1)) {
#ifdef YP
(void)fprintf(stderr,
"%s: unable to update NIS database (%u): %s\n",
argv[0], status, yperr_string(status));
#else
(void)fprintf(stderr,
"%s: unable to update publickey database (%u): %s\n",
argv[0], status, err_string(status));
#endif
exit(1);
}
(void)printf("Your new key has been successfully stored away.\n");
exit(0);
/* 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 (mapupdate(name, PKMAP, YPOP_STORE,
strlen(name), name, strlen(pkent), pkent));
#else
return (localupdate(name, PKFILE, YPOP_STORE,
strlen(name), name, strlen(pkent), pkent));
#endif
}
#ifndef YP
/*
* This returns a pointer to an error message string appropriate
* to an input error code. An input value of zero will return
* a success message.
*/
static char *
err_string(code)
int code;
{
char *pmesg;
switch (code) {
case 0:
pmesg = "update operation succeeded";
break;
case ERR_KEY:
pmesg = "no such key in file";
break;
case ERR_READ:
pmesg = "cannot read the database";
break;
case ERR_WRITE:
pmesg = "cannot write to the database";
break;
case ERR_DBASE:
pmesg = "cannot update database";
break;
case ERR_ACCESS:
pmesg = "permission denied";
break;
case ERR_MALLOC:
pmesg = "malloc failed";
break;
default:
pmesg = "unknown error";
break;
}
return (pmesg);
}
#endif

356
usr.bin/newkey/update.c Normal file
View File

@ -0,0 +1,356 @@
/*
* 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[] = "@(#)update.c 1.2 91/03/11 Copyr 1986 Sun Micro";
#endif
/*
* Copyright (C) 1986, 1989, Sun Microsystems, Inc.
*/
/*
* Administrative tool to add a new user to the publickey database
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <rpc/key_prot.h>
#ifdef YP
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <sys/wait.h>
#include <netdb.h>
#endif /* YP */
#include <pwd.h>
#include <string.h>
#include <sys/resource.h>
#ifdef YP
#define MAXMAPNAMELEN 256
#else
#define YPOP_CHANGE 1 /* change, do not add */
#define YPOP_INSERT 2 /* add, do not change */
#define YPOP_DELETE 3 /* delete this entry */
#define YPOP_STORE 4 /* add, or change */
#endif
extern char *getpass();
extern char *malloc();
#ifdef YP
static char *basename();
static char SHELL[] = "/bin/sh";
static char YPDBPATH[]="/var/yp"; /* This is defined but not used! */
static char PKMAP[] = "publickey.byname";
static char UPDATEFILE[] = "updaters";
#else
static char PKFILE[] = "/etc/publickey";
#endif /* YP */
#ifdef YP
static int _openchild __P(( char *, FILE **, FILE ** ));
/*
* Determine if requester is allowed to update the given map,
* and update it if so. Returns the yp status, which is zero
* if there is no access violation.
*/
mapupdate(requester, mapname, op, keylen, key, datalen, data)
char *requester;
char *mapname;
u_int op;
u_int keylen;
char *key;
u_int datalen;
char *data;
{
char updater[MAXMAPNAMELEN + 40];
FILE *childargs;
FILE *childrslt;
#ifdef WEXITSTATUS
int status;
#else
union wait status;
#endif
pid_t pid;
u_int yperrno;
#ifdef DEBUG
printf("%s %s\n", key, data);
#endif
(void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */
UPDATEFILE, mapname);
pid = _openchild(updater, &childargs, &childrslt);
if (pid < 0) {
return (YPERR_YPERR);
}
/*
* Write to child
*/
(void)fprintf(childargs, "%s\n", requester);
(void)fprintf(childargs, "%u\n", op);
(void)fprintf(childargs, "%u\n", keylen);
(void)fwrite(key, (int)keylen, 1, childargs);
(void)fprintf(childargs, "\n");
(void)fprintf(childargs, "%u\n", datalen);
(void)fwrite(data, (int)datalen, 1, childargs);
(void)fprintf(childargs, "\n");
(void)fclose(childargs);
/*
* Read from child
*/
(void)fscanf(childrslt, "%d", &yperrno);
(void)fclose(childrslt);
(void)wait(&status);
#ifdef WEXITSTATUS
if (WEXITSTATUS(status) != 0) {
#else
if (status.w_retcode != 0) {
#endif
return (YPERR_YPERR);
}
return (yperrno);
}
/*
* returns pid, or -1 for failure
*/
static
_openchild(command, fto, ffrom)
char *command;
FILE **fto;
FILE **ffrom;
{
int i;
pid_t pid;
int pdto[2];
int pdfrom[2];
char *com;
struct rlimit rl;
if (pipe(pdto) < 0) {
goto error1;
}
if (pipe(pdfrom) < 0) {
goto error2;
}
#ifdef VFORK
switch (pid = vfork()) {
#else
switch (pid = fork()) {
#endif
case -1:
goto error3;
case 0:
/*
* child: read from pdto[0], write into pdfrom[1]
*/
(void)close(0);
(void)dup(pdto[0]);
(void)close(1);
(void)dup(pdfrom[1]);
getrlimit(RLIMIT_NOFILE, &rl);
for (i = rl.rlim_max - 1; i >= 3; i--) {
(void) close(i);
}
com = malloc((unsigned) strlen(command) + 6);
if (com == NULL) {
_exit(~0);
}
(void)sprintf(com, "exec %s", command);
execl(SHELL, basename(SHELL), "-c", com, NULL);
_exit(~0);
default:
/*
* parent: write into pdto[1], read from pdfrom[0]
*/
*fto = fdopen(pdto[1], "w");
(void)close(pdto[0]);
*ffrom = fdopen(pdfrom[0], "r");
(void)close(pdfrom[1]);
break;
}
return (pid);
/*
* error cleanup and return
*/
error3:
(void)close(pdfrom[0]);
(void)close(pdfrom[1]);
error2:
(void)close(pdto[0]);
(void)close(pdto[1]);
error1:
return (-1);
}
static char *
basename(path)
char *path;
{
char *p;
p = strrchr(path, '/');
if (p == NULL) {
return (path);
} else {
return (p + 1);
}
}
#else /* YP */
#define ERR_ACCESS 1
#define ERR_MALLOC 2
#define ERR_READ 3
#define ERR_WRITE 4
#define ERR_DBASE 5
#define ERR_KEY 6
extern char *malloc();
static int match __P(( char * , char * ));
/*
* Determine if requester is allowed to update the given map,
* and update it if so. Returns the status, which is zero
* if there is no access violation. This function updates
* the local file and then shuts up.
*/
localupdate(name, filename, op, keylen, key, datalen, data)
char *name; /* Name of the requestor */
char *filename;
u_int op;
u_int keylen; /* Not used */
char *key;
u_int datalen; /* Not used */
char *data;
{
char line[256];
FILE *rf;
FILE *wf;
char *tmpname;
int err;
/*
* Check permission
*/
if (strcmp(name, key) != 0) {
return (ERR_ACCESS);
}
if (strcmp(name, "nobody") == 0) {
/*
* Can't change "nobody"s key.
*/
return (ERR_ACCESS);
}
/*
* Open files
*/
tmpname = malloc(strlen(filename) + 4);
if (tmpname == NULL) {
return (ERR_MALLOC);
}
sprintf(tmpname, "%s.tmp", filename);
rf = fopen(filename, "r");
if (rf == NULL) {
return (ERR_READ);
}
wf = fopen(tmpname, "w");
if (wf == NULL) {
return (ERR_WRITE);
}
err = -1;
while (fgets(line, sizeof (line), rf)) {
if (err < 0 && match(line, name)) {
switch (op) {
case YPOP_INSERT:
err = ERR_KEY;
break;
case YPOP_STORE:
case YPOP_CHANGE:
fprintf(wf, "%s %s\n", key, data);
err = 0;
break;
case YPOP_DELETE:
/* do nothing */
err = 0;
break;
}
} else {
fputs(line, wf);
}
}
if (err < 0) {
switch (op) {
case YPOP_CHANGE:
case YPOP_DELETE:
err = ERR_KEY;
break;
case YPOP_INSERT:
case YPOP_STORE:
err = 0;
fprintf(wf, "%s %s\n", key, data);
break;
}
}
fclose(wf);
fclose(rf);
if (err == 0) {
if (rename(tmpname, filename) < 0) {
return (ERR_DBASE);
}
} else {
if (unlink(tmpname) < 0) {
return (ERR_DBASE);
}
}
return (err);
}
static
match(line, name)
char *line;
char *name;
{
int len;
len = strlen(name);
return (strncmp(line, name, len) == 0 &&
(line[len] == ' ' || line[len] == '\t'));
}
#endif /* !YP */