Import of the keyserv daemon needed for Secure RPC.
This version supports both the keyserv v1 and v2 protocols. It uses the new AF_LOCAL transport so that only local processes can use it for storing/retrieving keys, and it uses the SCM_CREDS kernel hack for authentication. With these two modifications, we don't need the keyenvoy program normally used with RPC 4.0. Note that if libdes.so.3.x is present on the system when keyserv is started, Secure RPC will run with normal DES encryption. If not, everything falls back to RC4 with a 40 bit key.
This commit is contained in:
parent
903f376ec8
commit
51251b2b3b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/WPAUL/dist/; revision=26234
24
usr.sbin/keyserv/Makefile
Normal file
24
usr.sbin/keyserv/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
# $Id: Makefile,v 1.2 1996/11/22 03:00:17 wpaul Exp wpaul $
|
||||
|
||||
PROG= keyserv
|
||||
SRCS= keyserv.c setkey.c keyserv_uid.c crypt_svc.c crypt_server.c
|
||||
|
||||
MAN8= keyserv.8
|
||||
|
||||
CFLAGS+= -DKEYSERV_RANDOM -DBROKEN_DES -I.
|
||||
|
||||
LDADD+= -lmp -lrpcsvc
|
||||
|
||||
RPCDIR= ${DESTDIR}/usr/include/rpcsvc
|
||||
|
||||
CLEANFILES= crypt_svc.c crypt.h
|
||||
|
||||
RPCGEN= rpcgen -C
|
||||
|
||||
crypt_svc.c: ${RPCDIR}/crypt.x crypt.h
|
||||
${RPCGEN} -m -o ${.TARGET} ${RPCDIR}/crypt.x
|
||||
|
||||
crypt.h: ${RPCDIR}/crypt.x
|
||||
${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/crypt.x
|
||||
|
||||
.include <bsd.prog.mk>
|
264
usr.sbin/keyserv/crypt_server.c
Normal file
264
usr.sbin/keyserv/crypt_server.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 1996
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Bill Paul.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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: crypt_server.c,v 1.15 1996/12/25 19:21:10 wpaul Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
#include <rpc/des.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include "crypt.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] = "$Id: crypt_server.c,v 1.15 1996/12/25 19:21:10 wpaul Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The U.S. government stupidly believes that a) it can keep strong
|
||||
* crypto code a secret and b) that doing so somehow protects national
|
||||
* interests. It's wrong on both counts, but until it listens to reason
|
||||
* we have to make certain compromises so it doesn't have an excuse to
|
||||
* throw us in federal prison.
|
||||
*
|
||||
* Consequently, the core OS ships without DES support, and keyserv
|
||||
* defaults to using RC4 with only a 40 bit key, just like nutscrape.
|
||||
* This breaks compatibility with Secure RPC on other systems, but it
|
||||
* allows Secure RPC to work between FreeBSD systems that don't have the
|
||||
* DES package installed without throwing security totally out the window.
|
||||
*
|
||||
* In order to avoid having to supply two versions of keyserv (one with
|
||||
* DES and one without), we use dlopen() and friends to load libdes.so
|
||||
* into our address space at runtime. We check for the presence of
|
||||
* /usr/lib/libdes.so.3.0 at startup and load it if we find it. If we
|
||||
* can't find it, or the __des_crypt symbol doesn't exist, we fall back
|
||||
* to the RC4 encryption code. The user can specify another path using
|
||||
* the -p flag.
|
||||
*/
|
||||
|
||||
/* rc4.h */
|
||||
typedef struct rc4_key
|
||||
{
|
||||
unsigned char state[256];
|
||||
unsigned char x;
|
||||
unsigned char y;
|
||||
} rc4_key;
|
||||
|
||||
static void prepare_key(unsigned char *key_data_ptr,int key_data_len,
|
||||
rc4_key *key);
|
||||
static void rc4(unsigned char *buffer_ptr,int buffer_len,rc4_key * key);
|
||||
static void swap_byte(unsigned char *a, unsigned char *b);
|
||||
|
||||
static void prepare_key(unsigned char *key_data_ptr, int key_data_len,
|
||||
rc4_key *key)
|
||||
{
|
||||
unsigned char index1;
|
||||
unsigned char index2;
|
||||
unsigned char* state;
|
||||
short counter;
|
||||
|
||||
state = &key->state[0];
|
||||
for(counter = 0; counter < 256; counter++)
|
||||
state[counter] = counter;
|
||||
key->x = 0;
|
||||
key->y = 0;
|
||||
index1 = 0;
|
||||
index2 = 0;
|
||||
for(counter = 0; counter < 256; counter++)
|
||||
{
|
||||
index2 = (key_data_ptr[index1] + state[counter] +
|
||||
index2) % 256;
|
||||
swap_byte(&state[counter], &state[index2]);
|
||||
|
||||
index1 = (index1 + 1) % key_data_len;
|
||||
}
|
||||
}
|
||||
|
||||
static void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key)
|
||||
{
|
||||
unsigned char x;
|
||||
unsigned char y;
|
||||
unsigned char* state;
|
||||
unsigned char xorIndex;
|
||||
short counter;
|
||||
|
||||
x = key->x;
|
||||
y = key->y;
|
||||
|
||||
state = &key->state[0];
|
||||
for(counter = 0; counter < buffer_len; counter ++)
|
||||
{
|
||||
x = (x + 1) % 256;
|
||||
y = (state[x] + y) % 256;
|
||||
swap_byte(&state[x], &state[y]);
|
||||
|
||||
xorIndex = (state[x] + state[y]) % 256;
|
||||
|
||||
buffer_ptr[counter] ^= state[xorIndex];
|
||||
}
|
||||
key->x = x;
|
||||
key->y = y;
|
||||
}
|
||||
|
||||
static void swap_byte(unsigned char *a, unsigned char *b)
|
||||
{
|
||||
unsigned char swapByte;
|
||||
|
||||
swapByte = *a;
|
||||
*a = *b;
|
||||
*b = swapByte;
|
||||
}
|
||||
|
||||
/* Dummy _des_crypt function that uses RC4 with a 40 bit key */
|
||||
int _rc4_crypt(buf, len, desp)
|
||||
char *buf;
|
||||
int len;
|
||||
struct desparams *desp;
|
||||
{
|
||||
struct rc4_key rc4k;
|
||||
|
||||
/*
|
||||
* U.S. government anti-crypto weasels take
|
||||
* note: although we are supplied with a 64 bit
|
||||
* key, we're only passing 40 bits to the RC4
|
||||
* encryption code. So there.
|
||||
*/
|
||||
prepare_key(desp->des_key, 5, &rc4k);
|
||||
rc4(buf, len, &rc4k);
|
||||
|
||||
return(DESERR_NOHWDEVICE);
|
||||
}
|
||||
|
||||
int (*_my_crypt)__P((char *, int, struct desparams *)) = NULL;
|
||||
|
||||
static void *dlhandle;
|
||||
|
||||
#ifndef _PATH_USRLIB
|
||||
#define _PATH_USRLIB "/usr/lib"
|
||||
#endif
|
||||
|
||||
#ifndef LIBDES
|
||||
#define LIBDES "libdes.so.3."
|
||||
#endif
|
||||
|
||||
void load_des(warn, libpath)
|
||||
int warn;
|
||||
char *libpath;
|
||||
{
|
||||
DIR *dird;
|
||||
struct dirent *dirp;
|
||||
char dlpath[MAXPATHLEN];
|
||||
int minor = -1;
|
||||
int len;
|
||||
|
||||
if (libpath == NULL) {
|
||||
len = strlen(LIBDES);
|
||||
if ((dird = opendir(_PATH_USRLIB)) == NULL)
|
||||
err(1, "opendir(/usr/lib) failed");
|
||||
|
||||
while ((dirp = readdir(dird)) != NULL) {
|
||||
/* must have a minor number */
|
||||
if (strlen(dirp->d_name) <= len)
|
||||
continue;
|
||||
if (!strncmp(dirp->d_name, LIBDES, len)) {
|
||||
if (atoi((dirp->d_name + len + 1)) > minor) {
|
||||
minor = atoi((dirp->d_name + len + 1));
|
||||
snprintf(dlpath,sizeof(dlpath),"%s/%s",
|
||||
_PATH_USRLIB, dirp->d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dird);
|
||||
} else
|
||||
snprintf(dlpath, sizeof(dlpath), "%s", libpath);
|
||||
|
||||
if (dlpath != NULL && (dlhandle = dlopen(dlpath, 0444)) != NULL)
|
||||
_my_crypt = (int (*)())dlsym(dlhandle, "__des_crypt");
|
||||
|
||||
if (_my_crypt == NULL) {
|
||||
if (dlhandle != NULL)
|
||||
dlclose(dlhandle);
|
||||
_my_crypt = &_rc4_crypt;
|
||||
if (warn) {
|
||||
printf ("DES support disabled -- using RC4 instead.\n");
|
||||
printf ("Warning: RC4 cipher is not compatible with ");
|
||||
printf ("other Secure RPC implementations.\nInstall ");
|
||||
printf ("the FreeBSD 'des' distribution to enable");
|
||||
printf (" DES encryption.\n");
|
||||
}
|
||||
} else {
|
||||
if (warn) {
|
||||
printf ("DES support enabled\n");
|
||||
printf ("Using %s shared object.\n", dlpath);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
desresp *
|
||||
des_crypt_1_svc(desargs *argp, struct svc_req *rqstp)
|
||||
{
|
||||
static desresp result;
|
||||
struct desparams dparm;
|
||||
|
||||
if (argp->desbuf.desbuf_len > DES_MAXDATA) {
|
||||
result.stat = DESERR_BADPARAM;
|
||||
return(&result);
|
||||
}
|
||||
|
||||
bcopy(argp->des_key, dparm.des_key, 8);
|
||||
bcopy(argp->des_ivec, dparm.des_ivec, 8);
|
||||
dparm.des_mode = argp->des_mode;
|
||||
dparm.des_dir = argp->des_dir;
|
||||
|
||||
#ifdef BROKEN_DES
|
||||
dparm.UDES.UDES_buf = argp->desbuf.desbuf_val;
|
||||
#endif
|
||||
result.stat = _my_crypt(argp->desbuf.desbuf_val,
|
||||
argp->desbuf.desbuf_len,
|
||||
&dparm);
|
||||
|
||||
if (result.stat == DESERR_NONE || result.stat == DESERR_NOHWDEVICE) {
|
||||
bcopy(dparm.des_ivec, result.des_ivec, 8);
|
||||
result.desbuf.desbuf_len = argp->desbuf.desbuf_len;
|
||||
result.desbuf.desbuf_val = argp->desbuf.desbuf_val;
|
||||
}
|
||||
|
||||
return (&result);
|
||||
}
|
77
usr.sbin/keyserv/keyserv.8
Normal file
77
usr.sbin/keyserv/keyserv.8
Normal file
@ -0,0 +1,77 @@
|
||||
.\" @(#)keyserv.1m 1.21 93/07/14 SMI; from SVr4
|
||||
'\"macro stdmacro
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)keyserv.8c 1.8 89/03/29 SMI;
|
||||
.\".TH KEYSERV 8C "9 September 1987"
|
||||
.nr X
|
||||
.TH keyserv 1M "14 Sep 1992"
|
||||
.SH NAME
|
||||
keyserv \- server for storing private encryption keys
|
||||
.SH SYNOPSIS
|
||||
.B keyserv
|
||||
[
|
||||
.B \-d
|
||||
] [
|
||||
.B \-D
|
||||
] [
|
||||
.B \-n
|
||||
]
|
||||
.SH AVAILABILITY
|
||||
.LP
|
||||
SUNWcsu
|
||||
.SH DESCRIPTION
|
||||
.IX "keyserv" "" "\fLkeyserv\fP \(em server for storing private encryption keys"
|
||||
.IX "NFS security" "server for storing private encryption keys" "" "server for storing private encryption keys \(em \fLkeyserv\fP"
|
||||
.IX "encryption keys" "server for storing private keys" "" "server for storing private keys \(em \fLkeyserv\fP"
|
||||
.LP
|
||||
.B keyserv
|
||||
is a daemon that is used for storing the
|
||||
private encryption keys of each
|
||||
user logged into the system.
|
||||
These encryption keys are used for accessing
|
||||
secure network services such as secure NFS.
|
||||
.P
|
||||
Normally, root's key is read from the file
|
||||
.B /etc/.rootkey
|
||||
when the daemon is started.
|
||||
This is useful during power-fail reboots
|
||||
when no one is around to type a password.
|
||||
.P
|
||||
If a client with no secret key calls
|
||||
.BR keyserv ,
|
||||
then the key of user
|
||||
.B nobody
|
||||
is used instead as the default key.
|
||||
.SH OPTIONS
|
||||
.TP 10
|
||||
.B \-d
|
||||
Disable the use of default keys for
|
||||
.BR nobody .
|
||||
.TP
|
||||
.B \-D
|
||||
Run in debugging mode and log all requests to
|
||||
.BR keyserv .
|
||||
.TP
|
||||
.B \-n
|
||||
Root's secret key is not read from
|
||||
.BR /etc/.rootkey .
|
||||
Instead,
|
||||
.B keyserv
|
||||
prompts the user for the password to decrypt
|
||||
root's key stored in the
|
||||
.B /etc/publickey
|
||||
database and then stores the decrypted key in
|
||||
.B /etc/.rootkey
|
||||
for future use.
|
||||
This option is useful if the
|
||||
.B /etc/.rootkey
|
||||
file ever gets out of date or corrupted.
|
||||
.SH FILES
|
||||
.PD 0
|
||||
.TP 20
|
||||
.B /etc/.rootkey
|
||||
.PD
|
||||
.SH "SEE ALSO"
|
||||
.BR keylogin (1),
|
||||
.BR keylogout (1),
|
||||
.BR publickey (4)
|
828
usr.sbin/keyserv/keyserv.c
Normal file
828
usr.sbin/keyserv/keyserv.c
Normal file
@ -0,0 +1,828 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma ident "@(#)keyserv.c 1.15 94/04/25 SMI"
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Keyserver
|
||||
* Store secret keys per uid. Do public key encryption and decryption
|
||||
* operations. Generate "random" keys.
|
||||
* Do not talk to anything but a local root
|
||||
* process on the local transport only
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <pwd.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
#include <rpc/des.h>
|
||||
#include <rpc/key_prot.h>
|
||||
#include <rpcsvc/crypt.h>
|
||||
#include "keyserv.h"
|
||||
|
||||
#ifndef NGROUPS
|
||||
#define NGROUPS 16
|
||||
#endif
|
||||
|
||||
#ifndef KEYSERVSOCK
|
||||
#define KEYSERVSOCK "/var/run/keyservsock"
|
||||
#endif
|
||||
|
||||
static void randomize __P(( des_block * ));
|
||||
static void usage __P(( void ));
|
||||
static int getrootkey __P(( des_block *, int ));
|
||||
static int root_auth __P(( SVCXPRT *, struct svc_req * ));
|
||||
|
||||
#ifdef DEBUG
|
||||
static int debugging = 1;
|
||||
#else
|
||||
static int debugging = 0;
|
||||
#endif
|
||||
|
||||
static void keyprogram();
|
||||
static des_block masterkey;
|
||||
char *getenv();
|
||||
static char ROOTKEY[] = "/etc/.rootkey";
|
||||
|
||||
/*
|
||||
* Hack to allow the keyserver to use AUTH_DES (for authenticated
|
||||
* NIS+ calls, for example). The only functions that get called
|
||||
* are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
|
||||
*
|
||||
* The approach is to have the keyserver fill in pointers to local
|
||||
* implementations of these functions, and to call those in key_call().
|
||||
*/
|
||||
|
||||
extern cryptkeyres *(*__key_encryptsession_pk_LOCAL)();
|
||||
extern cryptkeyres *(*__key_decryptsession_pk_LOCAL)();
|
||||
extern des_block *(*__key_gendes_LOCAL)();
|
||||
extern int (*__des_crypt_LOCAL)();
|
||||
|
||||
cryptkeyres *key_encrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
|
||||
cryptkeyres *key_decrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
|
||||
des_block *key_gen_1_svc_prog __P(( void *, struct svc_req * ));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int nflag = 0;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int c;
|
||||
register SVCXPRT *transp;
|
||||
int sock = RPC_ANYSOCK;
|
||||
int warn = 0;
|
||||
char *path = NULL;
|
||||
|
||||
__key_encryptsession_pk_LOCAL = &key_encrypt_pk_2_svc_prog;
|
||||
__key_decryptsession_pk_LOCAL = &key_decrypt_pk_2_svc_prog;
|
||||
__key_gendes_LOCAL = &key_gen_1_svc_prog;
|
||||
|
||||
while ((c = getopt(argc, argv, "ndDvp:")) != -1)
|
||||
switch (c) {
|
||||
case 'n':
|
||||
nflag++;
|
||||
break;
|
||||
case 'd':
|
||||
pk_nodefaultkeys();
|
||||
break;
|
||||
case 'D':
|
||||
debugging = 1;
|
||||
break;
|
||||
case 'v':
|
||||
warn = 1;
|
||||
break;
|
||||
case 'p':
|
||||
path = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
load_des(warn, path);
|
||||
__des_crypt_LOCAL = _my_crypt;
|
||||
if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1) {
|
||||
fprintf(stderr, "failed to register AUTH_DES authenticator\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (optind != argc) {
|
||||
usage();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize
|
||||
*/
|
||||
(void) umask(066); /* paranoia */
|
||||
if (geteuid() != 0) {
|
||||
(void) fprintf(stderr, "%s must be run as root\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
setmodulus(HEXMODULUS);
|
||||
getrootkey(&masterkey, nflag);
|
||||
|
||||
|
||||
/* Create services. */
|
||||
|
||||
(void) pmap_unset(KEY_PROG, KEY_VERS);
|
||||
(void) pmap_unset(KEY_PROG, KEY_VERS2);
|
||||
unlink(KEYSERVSOCK);
|
||||
|
||||
transp = svcudp_create(RPC_ANYSOCK);
|
||||
if (transp == NULL) {
|
||||
fprintf(stderr, "cannot create udp service.");
|
||||
exit(1);
|
||||
}
|
||||
if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_UDP)) {
|
||||
fprintf(stderr, "unable to register (KEY_PROG, KEY_VERS, udp).");
|
||||
exit(1);
|
||||
}
|
||||
if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_UDP)) {
|
||||
fprintf(stderr, "unable to register (KEY_PROG, KEY_VERS2, udp).");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
|
||||
if (transp == NULL) {
|
||||
fprintf(stderr, "cannot create tcp service.");
|
||||
exit(1);
|
||||
}
|
||||
if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_TCP)) {
|
||||
fprintf(stderr, "unable to register (KEY_PROG, KEY_VERS, tcp).");
|
||||
exit(1);
|
||||
}
|
||||
if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_TCP)) {
|
||||
fprintf(stderr, "unable to register (KEY_PROG, KEY_VERS2, tcp).");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
transp = svcunix_create(sock, 0, 0, KEYSERVSOCK);
|
||||
chmod(KEYSERVSOCK, 0666);
|
||||
if (transp == NULL) {
|
||||
fprintf(stderr, "cannot create AF_UNIX service.");
|
||||
exit(1);
|
||||
}
|
||||
if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, 0)) {
|
||||
fprintf(stderr, "unable to register (KEY_PROG, KEY_VERS, unix).");
|
||||
exit(1);
|
||||
}
|
||||
if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, 0)) {
|
||||
fprintf(stderr, "unable to register (KEY_PROG, KEY_VERS2, unix).");
|
||||
exit(1);
|
||||
}
|
||||
if (!svc_register(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, 0)) {
|
||||
fprintf(stderr, "unable to register (CRYPT_PROG, CRYPT_VERS, unix).");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!debugging) {
|
||||
daemon(0,0);
|
||||
}
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
svc_run();
|
||||
abort();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* In the event that we don't get a root password, we try to
|
||||
* randomize the master key the best we can
|
||||
*/
|
||||
static void
|
||||
randomize(master)
|
||||
des_block *master;
|
||||
{
|
||||
int i;
|
||||
int seed;
|
||||
struct timeval tv;
|
||||
int shift;
|
||||
|
||||
seed = 0;
|
||||
for (i = 0; i < 1024; i++) {
|
||||
(void) gettimeofday(&tv, (struct timezone *) NULL);
|
||||
shift = i % 8 * sizeof (int);
|
||||
seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift));
|
||||
}
|
||||
#ifdef KEYSERV_RANDOM
|
||||
srandom(seed);
|
||||
master->key.low = random();
|
||||
master->key.high = random();
|
||||
srandom(seed);
|
||||
#else
|
||||
/* use stupid dangerous bad rand() */
|
||||
srand(seed);
|
||||
master->key.low = rand();
|
||||
master->key.high = rand();
|
||||
srand(seed);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get root's secret key, by prompting if terminal is a tty, else trying
|
||||
* from standard input.
|
||||
* Returns 1 on success.
|
||||
*/
|
||||
static int
|
||||
getrootkey(master, prompt)
|
||||
des_block *master;
|
||||
int prompt;
|
||||
{
|
||||
char *passwd;
|
||||
char name[MAXNETNAMELEN + 1];
|
||||
char secret[HEXKEYBYTES];
|
||||
key_netstarg netstore;
|
||||
int fd;
|
||||
|
||||
if (!prompt) {
|
||||
/*
|
||||
* Read secret key out of ROOTKEY
|
||||
*/
|
||||
fd = open(ROOTKEY, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
randomize(master);
|
||||
return (0);
|
||||
}
|
||||
if (read(fd, secret, HEXKEYBYTES) < HEXKEYBYTES) {
|
||||
(void) fprintf(stderr,
|
||||
"keyserv: the key read from %s was too short.\n",
|
||||
ROOTKEY);
|
||||
(void) close(fd);
|
||||
return (0);
|
||||
}
|
||||
(void) close(fd);
|
||||
if (!getnetname(name)) {
|
||||
(void) fprintf(stderr, "keyserv: \
|
||||
failed to generate host's netname when establishing root's key.\n");
|
||||
return (0);
|
||||
}
|
||||
memcpy(netstore.st_priv_key, secret, HEXKEYBYTES);
|
||||
memset(netstore.st_pub_key, 0, HEXKEYBYTES);
|
||||
netstore.st_netname = name;
|
||||
if (pk_netput(0, &netstore) != KEY_SUCCESS) {
|
||||
(void) fprintf(stderr,
|
||||
"keyserv: could not set root's key and netname.\n");
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
/*
|
||||
* Decrypt yellow pages publickey entry to get secret key
|
||||
*/
|
||||
passwd = getpass("root password:");
|
||||
passwd2des(passwd, (char *)master);
|
||||
getnetname(name);
|
||||
if (!getsecretkey(name, secret, passwd)) {
|
||||
(void) fprintf(stderr,
|
||||
"Can't find %s's secret key\n", name);
|
||||
return (0);
|
||||
}
|
||||
if (secret[0] == 0) {
|
||||
(void) fprintf(stderr,
|
||||
"Password does not decrypt secret key for %s\n", name);
|
||||
return (0);
|
||||
}
|
||||
(void) pk_setkey(0, secret);
|
||||
/*
|
||||
* Store it for future use in $ROOTKEY, if possible
|
||||
*/
|
||||
fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
|
||||
if (fd > 0) {
|
||||
char newline = '\n';
|
||||
|
||||
write(fd, secret, strlen(secret));
|
||||
write(fd, &newline, sizeof (newline));
|
||||
close(fd);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Procedures to implement RPC service
|
||||
*/
|
||||
char *
|
||||
strstatus(status)
|
||||
keystatus status;
|
||||
{
|
||||
switch (status) {
|
||||
case KEY_SUCCESS:
|
||||
return ("KEY_SUCCESS");
|
||||
case KEY_NOSECRET:
|
||||
return ("KEY_NOSECRET");
|
||||
case KEY_UNKNOWN:
|
||||
return ("KEY_UNKNOWN");
|
||||
case KEY_SYSTEMERR:
|
||||
return ("KEY_SYSTEMERR");
|
||||
default:
|
||||
return ("(bad result code)");
|
||||
}
|
||||
}
|
||||
|
||||
keystatus *
|
||||
key_set_1_svc_prog(uid, key)
|
||||
uid_t uid;
|
||||
keybuf key;
|
||||
{
|
||||
static keystatus status;
|
||||
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "set(%ld, %.*s) = ", uid,
|
||||
(int) sizeof (keybuf), key);
|
||||
}
|
||||
status = pk_setkey(uid, key);
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(status));
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&status);
|
||||
}
|
||||
|
||||
cryptkeyres *
|
||||
key_encrypt_pk_2_svc_prog(uid, arg)
|
||||
uid_t uid;
|
||||
cryptkeyarg2 *arg;
|
||||
{
|
||||
static cryptkeyres res;
|
||||
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
|
||||
arg->remotename, arg->deskey.key.high,
|
||||
arg->deskey.key.low);
|
||||
}
|
||||
res.cryptkeyres_u.deskey = arg->deskey;
|
||||
res.status = pk_encrypt(uid, arg->remotename, &(arg->remotekey),
|
||||
&res.cryptkeyres_u.deskey);
|
||||
if (debugging) {
|
||||
if (res.status == KEY_SUCCESS) {
|
||||
(void) fprintf(stderr, "%08x%08x\n",
|
||||
res.cryptkeyres_u.deskey.key.high,
|
||||
res.cryptkeyres_u.deskey.key.low);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(res.status));
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&res);
|
||||
}
|
||||
|
||||
cryptkeyres *
|
||||
key_decrypt_pk_2_svc_prog(uid, arg)
|
||||
uid_t uid;
|
||||
cryptkeyarg2 *arg;
|
||||
{
|
||||
static cryptkeyres res;
|
||||
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
|
||||
arg->remotename, arg->deskey.key.high,
|
||||
arg->deskey.key.low);
|
||||
}
|
||||
res.cryptkeyres_u.deskey = arg->deskey;
|
||||
res.status = pk_decrypt(uid, arg->remotename, &(arg->remotekey),
|
||||
&res.cryptkeyres_u.deskey);
|
||||
if (debugging) {
|
||||
if (res.status == KEY_SUCCESS) {
|
||||
(void) fprintf(stderr, "%08x%08x\n",
|
||||
res.cryptkeyres_u.deskey.key.high,
|
||||
res.cryptkeyres_u.deskey.key.low);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(res.status));
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&res);
|
||||
}
|
||||
|
||||
keystatus *
|
||||
key_net_put_2_svc_prog(uid, arg)
|
||||
uid_t uid;
|
||||
key_netstarg *arg;
|
||||
{
|
||||
static keystatus status;
|
||||
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ",
|
||||
arg->st_netname, (int)sizeof (arg->st_pub_key),
|
||||
arg->st_pub_key, (int)sizeof (arg->st_priv_key),
|
||||
arg->st_priv_key);
|
||||
};
|
||||
|
||||
status = pk_netput(uid, arg);
|
||||
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(status));
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
|
||||
return (&status);
|
||||
}
|
||||
|
||||
key_netstres *
|
||||
key_net_get_2_svc_prog(uid, arg)
|
||||
uid_t uid;
|
||||
void *arg;
|
||||
{
|
||||
static key_netstres keynetname;
|
||||
|
||||
if (debugging)
|
||||
(void) fprintf(stderr, "net_get(%ld) = ", uid);
|
||||
|
||||
keynetname.status = pk_netget(uid, &keynetname.key_netstres_u.knet);
|
||||
if (debugging) {
|
||||
if (keynetname.status == KEY_SUCCESS) {
|
||||
fprintf(stderr, "<%s, %.*s, %.*s>\n",
|
||||
keynetname.key_netstres_u.knet.st_netname,
|
||||
(int)sizeof (keynetname.key_netstres_u.knet.st_pub_key),
|
||||
keynetname.key_netstres_u.knet.st_pub_key,
|
||||
(int)sizeof (keynetname.key_netstres_u.knet.st_priv_key),
|
||||
keynetname.key_netstres_u.knet.st_priv_key);
|
||||
} else {
|
||||
(void) fprintf(stderr, "NOT FOUND\n");
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
|
||||
return (&keynetname);
|
||||
|
||||
}
|
||||
|
||||
cryptkeyres *
|
||||
key_get_conv_2_svc_prog(uid, arg)
|
||||
uid_t uid;
|
||||
keybuf arg;
|
||||
{
|
||||
static cryptkeyres res;
|
||||
|
||||
if (debugging)
|
||||
(void) fprintf(stderr, "get_conv(%ld, %.*s) = ", uid,
|
||||
(int)sizeof (arg), arg);
|
||||
|
||||
|
||||
res.status = pk_get_conv_key(uid, arg, &res);
|
||||
|
||||
if (debugging) {
|
||||
if (res.status == KEY_SUCCESS) {
|
||||
(void) fprintf(stderr, "%08x%08x\n",
|
||||
res.cryptkeyres_u.deskey.key.high,
|
||||
res.cryptkeyres_u.deskey.key.low);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(res.status));
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&res);
|
||||
}
|
||||
|
||||
|
||||
cryptkeyres *
|
||||
key_encrypt_1_svc_prog(uid, arg)
|
||||
uid_t uid;
|
||||
cryptkeyarg *arg;
|
||||
{
|
||||
static cryptkeyres res;
|
||||
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
|
||||
arg->remotename, arg->deskey.key.high,
|
||||
arg->deskey.key.low);
|
||||
}
|
||||
res.cryptkeyres_u.deskey = arg->deskey;
|
||||
res.status = pk_encrypt(uid, arg->remotename, NULL,
|
||||
&res.cryptkeyres_u.deskey);
|
||||
if (debugging) {
|
||||
if (res.status == KEY_SUCCESS) {
|
||||
(void) fprintf(stderr, "%08x%08x\n",
|
||||
res.cryptkeyres_u.deskey.key.high,
|
||||
res.cryptkeyres_u.deskey.key.low);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(res.status));
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&res);
|
||||
}
|
||||
|
||||
cryptkeyres *
|
||||
key_decrypt_1_svc_prog(uid, arg)
|
||||
uid_t uid;
|
||||
cryptkeyarg *arg;
|
||||
{
|
||||
static cryptkeyres res;
|
||||
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
|
||||
arg->remotename, arg->deskey.key.high,
|
||||
arg->deskey.key.low);
|
||||
}
|
||||
res.cryptkeyres_u.deskey = arg->deskey;
|
||||
res.status = pk_decrypt(uid, arg->remotename, NULL,
|
||||
&res.cryptkeyres_u.deskey);
|
||||
if (debugging) {
|
||||
if (res.status == KEY_SUCCESS) {
|
||||
(void) fprintf(stderr, "%08x%08x\n",
|
||||
res.cryptkeyres_u.deskey.key.high,
|
||||
res.cryptkeyres_u.deskey.key.low);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(res.status));
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&res);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
des_block *
|
||||
key_gen_1_svc_prog(v, s)
|
||||
void *v;
|
||||
struct svc_req *s;
|
||||
{
|
||||
struct timeval time;
|
||||
static des_block keygen;
|
||||
static des_block key;
|
||||
|
||||
(void) gettimeofday(&time, (struct timezone *) NULL);
|
||||
keygen.key.high += (time.tv_sec ^ time.tv_usec);
|
||||
keygen.key.low += (time.tv_sec ^ time.tv_usec);
|
||||
ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
|
||||
DES_ENCRYPT | DES_HW);
|
||||
key = keygen;
|
||||
des_setparity((char *)&key);
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high,
|
||||
key.key.low);
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&key);
|
||||
}
|
||||
|
||||
getcredres *
|
||||
key_getcred_1_svc_prog(uid, name)
|
||||
uid_t uid;
|
||||
netnamestr *name;
|
||||
{
|
||||
static getcredres res;
|
||||
static u_int gids[NGROUPS];
|
||||
struct unixcred *cred;
|
||||
|
||||
cred = &res.getcredres_u.cred;
|
||||
cred->gids.gids_val = gids;
|
||||
if (!netname2user(*name, (uid_t *) &cred->uid, (gid_t *) &cred->gid,
|
||||
(int *)&cred->gids.gids_len, (gid_t *)gids)) {
|
||||
res.status = KEY_UNKNOWN;
|
||||
} else {
|
||||
res.status = KEY_SUCCESS;
|
||||
}
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "getcred(%s) = ", *name);
|
||||
if (res.status == KEY_SUCCESS) {
|
||||
(void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
|
||||
cred->uid, cred->gid, cred->gids.gids_len);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s\n", strstatus(res.status));
|
||||
}
|
||||
(void) fflush(stderr);
|
||||
}
|
||||
return (&res);
|
||||
}
|
||||
|
||||
/*
|
||||
* RPC boilerplate
|
||||
*/
|
||||
static void
|
||||
keyprogram(rqstp, transp)
|
||||
struct svc_req *rqstp;
|
||||
SVCXPRT *transp;
|
||||
{
|
||||
union {
|
||||
keybuf key_set_1_arg;
|
||||
cryptkeyarg key_encrypt_1_arg;
|
||||
cryptkeyarg key_decrypt_1_arg;
|
||||
netnamestr key_getcred_1_arg;
|
||||
cryptkeyarg key_encrypt_2_arg;
|
||||
cryptkeyarg key_decrypt_2_arg;
|
||||
netnamestr key_getcred_2_arg;
|
||||
cryptkeyarg2 key_encrypt_pk_2_arg;
|
||||
cryptkeyarg2 key_decrypt_pk_2_arg;
|
||||
key_netstarg key_net_put_2_arg;
|
||||
netobj key_get_conv_2_arg;
|
||||
} argument;
|
||||
char *result;
|
||||
bool_t(*xdr_argument)(), (*xdr_result)();
|
||||
char *(*local) ();
|
||||
uid_t uid = -1;
|
||||
int check_auth;
|
||||
|
||||
switch (rqstp->rq_proc) {
|
||||
case NULLPROC:
|
||||
svc_sendreply(transp, xdr_void, (char *)NULL);
|
||||
return;
|
||||
|
||||
case KEY_SET:
|
||||
xdr_argument = xdr_keybuf;
|
||||
xdr_result = xdr_int;
|
||||
local = (char *(*)()) key_set_1_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
case KEY_ENCRYPT:
|
||||
xdr_argument = xdr_cryptkeyarg;
|
||||
xdr_result = xdr_cryptkeyres;
|
||||
local = (char *(*)()) key_encrypt_1_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
case KEY_DECRYPT:
|
||||
xdr_argument = xdr_cryptkeyarg;
|
||||
xdr_result = xdr_cryptkeyres;
|
||||
local = (char *(*)()) key_decrypt_1_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
case KEY_GEN:
|
||||
xdr_argument = xdr_void;
|
||||
xdr_result = xdr_des_block;
|
||||
local = (char *(*)()) key_gen_1_svc_prog;
|
||||
check_auth = 0;
|
||||
break;
|
||||
|
||||
case KEY_GETCRED:
|
||||
xdr_argument = xdr_netnamestr;
|
||||
xdr_result = xdr_getcredres;
|
||||
local = (char *(*)()) key_getcred_1_svc_prog;
|
||||
check_auth = 0;
|
||||
break;
|
||||
|
||||
case KEY_ENCRYPT_PK:
|
||||
xdr_argument = xdr_cryptkeyarg2;
|
||||
xdr_result = xdr_cryptkeyres;
|
||||
local = (char *(*)()) key_encrypt_pk_2_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
case KEY_DECRYPT_PK:
|
||||
xdr_argument = xdr_cryptkeyarg2;
|
||||
xdr_result = xdr_cryptkeyres;
|
||||
local = (char *(*)()) key_decrypt_pk_2_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
|
||||
case KEY_NET_PUT:
|
||||
xdr_argument = xdr_key_netstarg;
|
||||
xdr_result = xdr_keystatus;
|
||||
local = (char *(*)()) key_net_put_2_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
case KEY_NET_GET:
|
||||
xdr_argument = (xdrproc_t) xdr_void;
|
||||
xdr_result = xdr_key_netstres;
|
||||
local = (char *(*)()) key_net_get_2_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
case KEY_GET_CONV:
|
||||
xdr_argument = (xdrproc_t) xdr_keybuf;
|
||||
xdr_result = xdr_cryptkeyres;
|
||||
local = (char *(*)()) key_get_conv_2_svc_prog;
|
||||
check_auth = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
svcerr_noproc(transp);
|
||||
return;
|
||||
}
|
||||
if (check_auth) {
|
||||
if (root_auth(transp, rqstp) == 0) {
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr,
|
||||
"not local privileged process\n");
|
||||
}
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr,
|
||||
"not unix authentication\n");
|
||||
}
|
||||
svcerr_weakauth(transp);
|
||||
return;
|
||||
}
|
||||
uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid;
|
||||
}
|
||||
|
||||
memset((char *) &argument, 0, sizeof (argument));
|
||||
if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
|
||||
svcerr_decode(transp);
|
||||
return;
|
||||
}
|
||||
result = (*local) (uid, &argument);
|
||||
if (!svc_sendreply(transp, xdr_result, (char *) result)) {
|
||||
if (debugging)
|
||||
(void) fprintf(stderr, "unable to reply\n");
|
||||
svcerr_systemerr(transp);
|
||||
}
|
||||
if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
|
||||
if (debugging)
|
||||
(void) fprintf(stderr,
|
||||
"unable to free arguments\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
root_auth(trans, rqstp)
|
||||
SVCXPRT *trans;
|
||||
struct svc_req *rqstp;
|
||||
{
|
||||
uid_t uid;
|
||||
struct sockaddr_in *remote;
|
||||
|
||||
remote = svc_getcaller(trans);
|
||||
if (remote->sin_family == AF_INET) {
|
||||
if (debugging)
|
||||
fprintf(stderr, "client didn't use AF_UNIX\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (__rpc_get_local_uid(&uid, trans) < 0) {
|
||||
if (debugging)
|
||||
fprintf(stderr, "__rpc_get_local_uid failed\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (debugging)
|
||||
fprintf(stderr, "local_uid %ld\n", uid);
|
||||
if (uid == 0)
|
||||
return (1);
|
||||
if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
|
||||
if (((uid_t) ((struct authunix_parms *)
|
||||
rqstp->rq_clntcred)->aup_uid)
|
||||
== uid) {
|
||||
return (1);
|
||||
} else {
|
||||
if (debugging)
|
||||
fprintf(stderr,
|
||||
"local_uid %ld mismatches auth %ld\n", uid,
|
||||
((uid_t) ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid));
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
if (debugging)
|
||||
fprintf(stderr, "Not auth sys\n");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage: keyserv [-n] [-D] [-d] [-v] [-p path]\n");
|
||||
(void) fprintf(stderr, "-d disables the use of default keys\n");
|
||||
exit(1);
|
||||
}
|
19
usr.sbin/keyserv/keyserv.h
Normal file
19
usr.sbin/keyserv/keyserv.h
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
extern void setmodulus __P((char *modx));
|
||||
|
||||
extern keystatus pk_setkey __P(( uid_t, keybuf ));;
|
||||
extern keystatus pk_encrypt __P(( uid_t, char *, netobj *, des_block * ));
|
||||
extern keystatus pk_decrypt __P(( uid_t, char *, netobj *, des_block * ));
|
||||
extern keystatus pk_netput __P(( uid_t, key_netstarg * ));
|
||||
extern keystatus pk_netget __P(( uid_t, key_netstarg * ));
|
||||
extern keystatus pk_get_conv_key __P(( uid_t, keybuf, cryptkeyres * ));
|
||||
extern void pk_nodefaultkeys __P(( void ));
|
||||
|
||||
extern int __rpc_get_local_uid __P(( uid_t * , SVCXPRT * ));
|
||||
extern void crypt_prog_1 __P(( struct svc_req *, register SVCXPRT * ));
|
||||
extern void load_des __P(( int, char * ));
|
||||
|
||||
extern int (*_my_crypt)__P(( char *, int, struct desparams * ));
|
||||
|
||||
extern char ROOTKEY[];
|
||||
|
77
usr.sbin/keyserv/keyserv_uid.c
Normal file
77
usr.sbin/keyserv/keyserv_uid.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 1996
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Bill Paul.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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: keyserv_uid.c,v 1.13 1997/01/19 20:23:05 wpaul Exp $
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <rpc/key_prot.h>
|
||||
#include <rpc/des.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "keyserv.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] = "$Id: keyserv_uid.c,v 1.13 1997/01/19 20:23:05 wpaul Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX should be declared somewhere
|
||||
*/
|
||||
struct cmessage {
|
||||
struct cmsghdr cmsg;
|
||||
struct cmsgcred cmcred;
|
||||
};
|
||||
|
||||
int
|
||||
__rpc_get_local_uid(uid, transp)
|
||||
uid_t *uid;
|
||||
SVCXPRT *transp;
|
||||
{
|
||||
struct cmessage *cm;
|
||||
|
||||
if (transp->xp_verf.oa_length < sizeof(struct cmessage) ||
|
||||
transp->xp_verf.oa_base == NULL ||
|
||||
transp->xp_verf.oa_flavor != AUTH_UNIX)
|
||||
return(-1);
|
||||
|
||||
cm = (struct cmessage *)transp->xp_verf.oa_base;
|
||||
if (cm->cmsg.cmsg_type != SCM_CREDS)
|
||||
return(-1);
|
||||
|
||||
*uid = cm->cmcred.cmcred_euid;
|
||||
return(0);
|
||||
}
|
544
usr.sbin/keyserv/setkey.c
Normal file
544
usr.sbin/keyserv/setkey.c
Normal file
@ -0,0 +1,544 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#pragma ident "@(#)setkey.c 1.11 94/04/25 SMI"
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Do the real work of the keyserver.
|
||||
* Store secret keys. Compute common keys,
|
||||
* and use them to decrypt and encrypt DES keys.
|
||||
* Cache the common keys, so the expensive computation is avoided.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <mp.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/key_prot.h>
|
||||
#include <rpc/des_crypt.h>
|
||||
#include <rpc/des.h>
|
||||
#include <sys/errno.h>
|
||||
#include <string.h>
|
||||
#include "keyserv.h"
|
||||
|
||||
static MINT *MODULUS;
|
||||
static char *fetchsecretkey __P(( uid_t ));
|
||||
static void writecache __P(( char *, char *, des_block * ));
|
||||
static int readcache __P(( char *, char *, des_block * ));
|
||||
static void extractdeskey __P (( MINT *, des_block * ));
|
||||
static int storesecretkey __P(( uid_t, keybuf ));
|
||||
static keystatus pk_crypt __P(( uid_t, char *, netobj *, des_block *, int));
|
||||
static int nodefaultkeys = 0;
|
||||
|
||||
|
||||
/*
|
||||
* prohibit the nobody key on this machine k (the -d flag)
|
||||
*/
|
||||
void
|
||||
pk_nodefaultkeys()
|
||||
{
|
||||
nodefaultkeys = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the modulus for all our Diffie-Hellman operations
|
||||
*/
|
||||
void
|
||||
setmodulus(modx)
|
||||
char *modx;
|
||||
{
|
||||
MODULUS = xtom(modx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the secretkey key for this uid
|
||||
*/
|
||||
keystatus
|
||||
pk_setkey(uid, skey)
|
||||
uid_t uid;
|
||||
keybuf skey;
|
||||
{
|
||||
if (!storesecretkey(uid, skey)) {
|
||||
return (KEY_SYSTEMERR);
|
||||
}
|
||||
return (KEY_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Encrypt the key using the public key associated with remote_name and the
|
||||
* secret key associated with uid.
|
||||
*/
|
||||
keystatus
|
||||
pk_encrypt(uid, remote_name, remote_key, key)
|
||||
uid_t uid;
|
||||
char *remote_name;
|
||||
netobj *remote_key;
|
||||
des_block *key;
|
||||
{
|
||||
return (pk_crypt(uid, remote_name, remote_key, key, DES_ENCRYPT));
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt the key using the public key associated with remote_name and the
|
||||
* secret key associated with uid.
|
||||
*/
|
||||
keystatus
|
||||
pk_decrypt(uid, remote_name, remote_key, key)
|
||||
uid_t uid;
|
||||
char *remote_name;
|
||||
netobj *remote_key;
|
||||
des_block *key;
|
||||
{
|
||||
return (pk_crypt(uid, remote_name, remote_key, key, DES_DECRYPT));
|
||||
}
|
||||
|
||||
static int store_netname __P(( uid_t, key_netstarg * ));
|
||||
static int fetch_netname __P(( uid_t, key_netstarg * ));
|
||||
|
||||
keystatus
|
||||
pk_netput(uid, netstore)
|
||||
uid_t uid;
|
||||
key_netstarg *netstore;
|
||||
{
|
||||
if (!store_netname(uid, netstore)) {
|
||||
return (KEY_SYSTEMERR);
|
||||
}
|
||||
return (KEY_SUCCESS);
|
||||
}
|
||||
|
||||
keystatus
|
||||
pk_netget(uid, netstore)
|
||||
uid_t uid;
|
||||
key_netstarg *netstore;
|
||||
{
|
||||
if (!fetch_netname(uid, netstore)) {
|
||||
return (KEY_SYSTEMERR);
|
||||
}
|
||||
return (KEY_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do the work of pk_encrypt && pk_decrypt
|
||||
*/
|
||||
static keystatus
|
||||
pk_crypt(uid, remote_name, remote_key, key, mode)
|
||||
uid_t uid;
|
||||
char *remote_name;
|
||||
netobj *remote_key;
|
||||
des_block *key;
|
||||
int mode;
|
||||
{
|
||||
char *xsecret;
|
||||
char xpublic[1024];
|
||||
char xsecret_hold[1024];
|
||||
des_block deskey;
|
||||
int err;
|
||||
MINT *public;
|
||||
MINT *secret;
|
||||
MINT *common;
|
||||
char zero[8];
|
||||
|
||||
xsecret = fetchsecretkey(uid);
|
||||
if (xsecret == NULL || xsecret[0] == 0) {
|
||||
memset(zero, 0, sizeof (zero));
|
||||
xsecret = xsecret_hold;
|
||||
if (nodefaultkeys)
|
||||
return (KEY_NOSECRET);
|
||||
|
||||
if (!getsecretkey("nobody", xsecret, zero) || xsecret[0] == 0) {
|
||||
return (KEY_NOSECRET);
|
||||
}
|
||||
}
|
||||
if (remote_key) {
|
||||
memcpy(xpublic, remote_key->n_bytes, remote_key->n_len);
|
||||
} else {
|
||||
bzero((char *)&xpublic, sizeof(xpublic));
|
||||
if (!getpublickey(remote_name, xpublic)) {
|
||||
if (nodefaultkeys || !getpublickey("nobody", xpublic))
|
||||
return (KEY_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
if (!readcache(xpublic, xsecret, &deskey)) {
|
||||
public = xtom(xpublic);
|
||||
secret = xtom(xsecret);
|
||||
/* Sanity Check on public and private keys */
|
||||
if ((public == NULL) || (secret == NULL))
|
||||
return (KEY_SYSTEMERR);
|
||||
|
||||
common = itom(0);
|
||||
pow(public, secret, MODULUS, common);
|
||||
extractdeskey(common, &deskey);
|
||||
writecache(xpublic, xsecret, &deskey);
|
||||
mfree(secret);
|
||||
mfree(public);
|
||||
mfree(common);
|
||||
}
|
||||
err = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block),
|
||||
DES_HW | mode);
|
||||
if (DES_FAILED(err)) {
|
||||
return (KEY_SYSTEMERR);
|
||||
}
|
||||
return (KEY_SUCCESS);
|
||||
}
|
||||
|
||||
keystatus
|
||||
pk_get_conv_key(uid, xpublic, result)
|
||||
uid_t uid;
|
||||
keybuf xpublic;
|
||||
cryptkeyres *result;
|
||||
{
|
||||
char *xsecret;
|
||||
char xsecret_hold[1024];
|
||||
MINT *public;
|
||||
MINT *secret;
|
||||
MINT *common;
|
||||
char zero[8];
|
||||
|
||||
|
||||
xsecret = fetchsecretkey(uid);
|
||||
|
||||
if (xsecret == NULL || xsecret[0] == 0) {
|
||||
memset(zero, 0, sizeof (zero));
|
||||
xsecret = xsecret_hold;
|
||||
if (nodefaultkeys)
|
||||
return (KEY_NOSECRET);
|
||||
|
||||
if (!getsecretkey("nobody", xsecret, zero) ||
|
||||
xsecret[0] == 0)
|
||||
return (KEY_NOSECRET);
|
||||
}
|
||||
|
||||
if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey)) {
|
||||
public = xtom(xpublic);
|
||||
secret = xtom(xsecret);
|
||||
/* Sanity Check on public and private keys */
|
||||
if ((public == NULL) || (secret == NULL))
|
||||
return (KEY_SYSTEMERR);
|
||||
|
||||
common = itom(0);
|
||||
pow(public, secret, MODULUS, common);
|
||||
extractdeskey(common, &result->cryptkeyres_u.deskey);
|
||||
writecache(xpublic, xsecret, &result->cryptkeyres_u.deskey);
|
||||
mfree(secret);
|
||||
mfree(public);
|
||||
mfree(common);
|
||||
}
|
||||
|
||||
return (KEY_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose middle 64 bits of the common key to use as our des key, possibly
|
||||
* overwriting the lower order bits by setting parity.
|
||||
*/
|
||||
static void
|
||||
extractdeskey(ck, deskey)
|
||||
MINT *ck;
|
||||
des_block *deskey;
|
||||
{
|
||||
MINT *a;
|
||||
short r;
|
||||
int i;
|
||||
short base = (1 << 8);
|
||||
char *k;
|
||||
|
||||
a = itom(0);
|
||||
#ifdef SOLARIS_MP
|
||||
_mp_move(ck, a);
|
||||
#else
|
||||
move(ck, a);
|
||||
#endif
|
||||
for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
|
||||
sdiv(a, base, a, &r);
|
||||
}
|
||||
k = deskey->c;
|
||||
for (i = 0; i < 8; i++) {
|
||||
sdiv(a, base, a, &r);
|
||||
*k++ = r;
|
||||
}
|
||||
mfree(a);
|
||||
des_setparity((char *)deskey);
|
||||
}
|
||||
|
||||
/*
|
||||
* Key storage management
|
||||
*/
|
||||
|
||||
#define KEY_ONLY 0
|
||||
#define KEY_NAME 1
|
||||
struct secretkey_netname_list {
|
||||
uid_t uid;
|
||||
key_netstarg keynetdata;
|
||||
u_char sc_flag;
|
||||
struct secretkey_netname_list *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct secretkey_netname_list *g_secretkey_netname;
|
||||
|
||||
/*
|
||||
* Store the keys and netname for this uid
|
||||
*/
|
||||
static int
|
||||
store_netname(uid, netstore)
|
||||
uid_t uid;
|
||||
key_netstarg *netstore;
|
||||
{
|
||||
struct secretkey_netname_list *new;
|
||||
struct secretkey_netname_list **l;
|
||||
|
||||
for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid;
|
||||
l = &(*l)->next) {
|
||||
}
|
||||
if (*l == NULL) {
|
||||
new = (struct secretkey_netname_list *)malloc(sizeof (*new));
|
||||
if (new == NULL) {
|
||||
return (0);
|
||||
}
|
||||
new->uid = uid;
|
||||
new->next = NULL;
|
||||
*l = new;
|
||||
} else {
|
||||
new = *l;
|
||||
if (new->keynetdata.st_netname)
|
||||
(void) free (new->keynetdata.st_netname);
|
||||
}
|
||||
memcpy(new->keynetdata.st_priv_key, netstore->st_priv_key,
|
||||
HEXKEYBYTES);
|
||||
memcpy(new->keynetdata.st_pub_key, netstore->st_pub_key, HEXKEYBYTES);
|
||||
|
||||
if (netstore->st_netname)
|
||||
new->keynetdata.st_netname = strdup(netstore->st_netname);
|
||||
else
|
||||
new->keynetdata.st_netname = (char *)NULL;
|
||||
new->sc_flag = KEY_NAME;
|
||||
return (1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch the keys and netname for this uid
|
||||
*/
|
||||
|
||||
static int
|
||||
fetch_netname(uid, key_netst)
|
||||
uid_t uid;
|
||||
struct key_netstarg *key_netst;
|
||||
{
|
||||
struct secretkey_netname_list *l;
|
||||
|
||||
for (l = g_secretkey_netname; l != NULL; l = l->next) {
|
||||
if ((l->uid == uid) && (l->sc_flag == KEY_NAME)){
|
||||
|
||||
memcpy(key_netst->st_priv_key,
|
||||
l->keynetdata.st_priv_key, HEXKEYBYTES);
|
||||
|
||||
memcpy(key_netst->st_pub_key,
|
||||
l->keynetdata.st_pub_key, HEXKEYBYTES);
|
||||
|
||||
if (l->keynetdata.st_netname)
|
||||
key_netst->st_netname =
|
||||
strdup(l->keynetdata.st_netname);
|
||||
else
|
||||
key_netst->st_netname = NULL;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char *
|
||||
fetchsecretkey(uid)
|
||||
uid_t uid;
|
||||
{
|
||||
struct secretkey_netname_list *l;
|
||||
|
||||
for (l = g_secretkey_netname; l != NULL; l = l->next) {
|
||||
if (l->uid == uid) {
|
||||
return (l->keynetdata.st_priv_key);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the secretkey for this uid
|
||||
*/
|
||||
static int
|
||||
storesecretkey(uid, key)
|
||||
uid_t uid;
|
||||
keybuf key;
|
||||
{
|
||||
struct secretkey_netname_list *new;
|
||||
struct secretkey_netname_list **l;
|
||||
|
||||
for (l = &g_secretkey_netname; *l != NULL && (*l)->uid != uid;
|
||||
l = &(*l)->next) {
|
||||
}
|
||||
if (*l == NULL) {
|
||||
new = (struct secretkey_netname_list *) malloc(sizeof (*new));
|
||||
if (new == NULL) {
|
||||
return (0);
|
||||
}
|
||||
new->uid = uid;
|
||||
new->sc_flag = KEY_ONLY;
|
||||
memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES);
|
||||
new->keynetdata.st_netname = NULL;
|
||||
new->next = NULL;
|
||||
*l = new;
|
||||
} else {
|
||||
new = *l;
|
||||
}
|
||||
|
||||
memcpy(new->keynetdata.st_priv_key, key,
|
||||
HEXKEYBYTES);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
hexdigit(val)
|
||||
int val;
|
||||
{
|
||||
return ("0123456789abcdef"[val]);
|
||||
}
|
||||
|
||||
void
|
||||
bin2hex(bin, hex, size)
|
||||
unsigned char *bin;
|
||||
unsigned char *hex;
|
||||
int size;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
*hex++ = hexdigit(*bin >> 4);
|
||||
*hex++ = hexdigit(*bin++ & 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hexval(dig)
|
||||
char dig;
|
||||
{
|
||||
if ('0' <= dig && dig <= '9') {
|
||||
return (dig - '0');
|
||||
} else if ('a' <= dig && dig <= 'f') {
|
||||
return (dig - 'a' + 10);
|
||||
} else if ('A' <= dig && dig <= 'F') {
|
||||
return (dig - 'A' + 10);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hex2bin(hex, bin, size)
|
||||
unsigned char *hex;
|
||||
unsigned char *bin;
|
||||
int size;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
*bin = hexval(*hex++) << 4;
|
||||
*bin++ |= hexval(*hex++);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Exponential caching management
|
||||
*/
|
||||
struct cachekey_list {
|
||||
keybuf secret;
|
||||
keybuf public;
|
||||
des_block deskey;
|
||||
struct cachekey_list *next;
|
||||
};
|
||||
static struct cachekey_list *g_cachedkeys;
|
||||
|
||||
/*
|
||||
* cache result of expensive multiple precision exponential operation
|
||||
*/
|
||||
static void
|
||||
writecache(pub, sec, deskey)
|
||||
char *pub;
|
||||
char *sec;
|
||||
des_block *deskey;
|
||||
{
|
||||
struct cachekey_list *new;
|
||||
|
||||
new = (struct cachekey_list *) malloc(sizeof (struct cachekey_list));
|
||||
if (new == NULL) {
|
||||
return;
|
||||
}
|
||||
memcpy(new->public, pub, sizeof (keybuf));
|
||||
memcpy(new->secret, sec, sizeof (keybuf));
|
||||
new->deskey = *deskey;
|
||||
new->next = g_cachedkeys;
|
||||
g_cachedkeys = new;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find the common key in the cache
|
||||
*/
|
||||
static int
|
||||
readcache(pub, sec, deskey)
|
||||
char *pub;
|
||||
char *sec;
|
||||
des_block *deskey;
|
||||
{
|
||||
struct cachekey_list *found;
|
||||
register struct cachekey_list **l;
|
||||
|
||||
#define cachehit(pub, sec, list) \
|
||||
(memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \
|
||||
memcmp(sec, (list)->secret, sizeof (keybuf)) == 0)
|
||||
|
||||
for (l = &g_cachedkeys; (*l) != NULL && !cachehit(pub, sec, *l);
|
||||
l = &(*l)->next)
|
||||
;
|
||||
if ((*l) == NULL) {
|
||||
return (0);
|
||||
}
|
||||
found = *l;
|
||||
(*l) = (*l)->next;
|
||||
found->next = g_cachedkeys;
|
||||
g_cachedkeys = found;
|
||||
*deskey = found->deskey;
|
||||
return (1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user