From: fadden@uts.amdahl.com (Andy McFadden)
Newsgroups: rec.games.netrek
Subject: RSA support routines (was Re: RSA)
Date: 19 Nov 92 21:07:48 GMT
Organization: Amdahl Corporation, Sunnyvale CA

In article <1992Nov14.184207@cs.bham.ac.uk> jwh@cs.bham.ac.uk (James "Oolon Colluphid" Hawtin) writes:
>Please get a clue it may be very funny for you to say that but it is this kind of
>insular approach that is afectively going to cut off the rest of the world from
>playing netrek because you lot are unwilling to let us Europeans help you get
>round the problem of import restrictions.

I've about had it with the whining.  We aren't stopping you; quit bitching
and do something for a change.

>We can compile an RSA equivelent here and then you can use that. With the same
>end; stopping those Borgs. WHY USE RSA WHICH LIMITS THE PEOPLE THAT PLAY?

Fine.  Do it.  Here's everything I can legally give you (does not include
the RSA utils or the key generator, but it does have the key manager and
the standard test key, which all servers will continue to support for a
little while).

Now put up or shut up.


NOTE: To the best of my knowledge, distributing the contents of this article
does not break any copyright/patent laws or US export restrictions.  If
you feel otherwise, please contact me immediately.


# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# INSTALL key.test.h keyman.c rsa-client.c rsa-server.c

: =-=-=-=-=-=-= first line of shar 1 of 1 =-=-=-=-=-=-=-=-=-
echo x - INSTALL
sed -e 's/^X//' > "INSTALL" << '//E*O*F INSTALL//'
XInstructions for adding the new reserved.c to Clients and Servers
X
XServers:
X---------------------------------------------------------------------------
XTo defs.h, add the lines:
X-
X#define RESERVED_FILE   "../conf/.reserved"
X#define RSA_VERSION "RSA v2.0 SERVER"  /* String must begin with "RSA v" */
X#define KEY_SIZE 32
X#define RESERVED_SIZE 16
X#define MSG_LEN 80
X#define NAME_LEN 16
X#define KEYMAP_LEN 96
X---------------
X
XIn data.c, change the line that says:
X-
Xchar testdata[16];
X- to
Xchar testdata[KEY_SIZE];
X-and add
Xint RSA_Client;
X---------------
X
XIn data.h, change
X-
Xextern char testdata[16];
X- to
Xextern char testdata[];
X
Xadd
Xextern int RSA_Client;
X---------------
X
XIn redraw.c change the line that says:
X-
Xbcopy(sp.data, testdata, 16);
X- to
Xbcopy(sp.data, testdata, KEY_SIZE);
X- and change the line
Xwarning("No customized binaries.  Please use a blessed one.");
X- to
Xif (RSA_Client==1)
X    warning("No customized binaries.  Please use a blessed one.");
Xelse if (RSA_Client==2)
X    warning("Wrong Client Version Number!");
Xelse
X    warning("You need a spiffy new RSA client for this server!");
X
X
X---------------
X
XIn socket.c, the function handleReserved becomes:
X-
XhandleReserved(packet)
Xstruct reserved_cpacket *packet;
X{
X    struct reserved_cpacket mycp;
X    struct reserved_spacket mysp;
X    struct rsa_key_spacket   rsp;
X    char serverName[64]; /* now get serverName from system 8/2/92 TC */
X
X    if (testtime==1) return;
X    if (bcmp(packet->data, testdata, RESERVED_SIZE) != 0) {
X	testtime=1;
X	return;
X    }
X    if (!strncmp (packet->resp, RSA_VERSION, 3)) {
X	  /* This is an RSA type client */
X	  RSA_Client = 2;
X	  warning (RSA_VERSION);
X      if (!strncmp (packet->resp, RSA_VERSION, strlen("RSA v??"))) {
X	  /* This is the right major version */
X	  RSA_Client = 1;
X	  makeRSAPacket(&rsp);
X	  bcopy(rsp.data, testdata, KEY_SIZE);
X	  sendClientPacket (&rsp);
X	  return;
X      }
X      testtime=1;
X      return;
X    }
X    bcopy(testdata, mysp.data, RESERVED_SIZE);
X    if (gethostname(serverName, 64)) fprintf(stderr, "gethostname() error\n"); /* 8/2/92 TC */
X    encryptReservedPacket(&mysp, &mycp, serverName, me->p_no);
X    if (bcmp(packet->resp, mycp.resp, RESERVED_SIZE) != 0) {
X	fprintf(stderr, "User verified incorrectly.\n");
X	testtime=1;
X	return;
X    }
X    /* Use .sysdef CONFIRM flag to allow old style clients. */
X    if (binconfirm==2)
X	testtime=0;
X    else
X	testtime=1;
X}
X
X- and add the function 
X
XhandleRSAKey(packet)
Xstruct rsa_key_cpacket *packet;
X{
X    struct rsa_key_cpacket mycp;
X    struct rsa_key_spacket mysp;
X    char serverName[64]; 
X 
X    if (testtime==1) return;
X    if (RSA_Client != 1) return;
X    bcopy(testdata, mysp.data, KEY_SIZE);
X    if (gethostname(serverName, 64)) fprintf(stderr, "gethostname() error\n");
X    if (decryptRSAPacket(&mysp, packet, serverName))
X    {
X        fprintf(stderr, "User verified incorrectly.\n");
X        testtime=1;
X        return;
X    }
X    testtime=0;
X}
X
X- I changed the (is it ever used??) line
Xif ((binconfirm == 3) && !strcmp(packet->resp, "Cyborg")) {	/* ATM */
X- to
Xif ((binconfirm == 2) && !strcmp(packet->resp, "Cyborg")) {	/* ATM */
X- (look above for why)
X
X
XHere are the diffs for the beginning part of the file:
X
Xbegin socket.c
X82d81
X< int handleRSAKey();
X124,125c123
X<     { sizeof(struct sequence_cpacket), handleSequence },   /* CP_SEQUENCE */
X<     { sizeof(struct rsa_key_cpacket), handleRSAKey }	   /* CP_RSA_KEY */
X---
X>     { sizeof(struct sequence_cpacket), handleSequence }	   /* CP_SEQUENCE */
X159,160c157
X<     sizeof(struct sc_sequence_spacket),		/* SP_SC_SEQUENCE */
X<     sizeof(struct rsa_key_spacket)		/* SP_RSA_KEY */
X---
X>     sizeof(struct sc_sequence_spacket)		/* SP_SC_SEQUENCE */
Xend socket.c
X
X
X---------------
X
XIn packets.h, 
X-
XAdd the codes
X#define SP_RSA_KEY	31		/* handles binary verification */
X#define CP_RSA_KEY	37		/* handles binary verification */
X(in the appropriate places)
X-
XAdd the CP_RSA_KEY and SP_RSA_KEY packets as: 
X-
Xstruct rsa_key_spacket {
X    char type;          /* SP_RSA_KEY */
X    char pad1;
X    char pad2;
X    char pad3;
X    unsigned char data[KEY_SIZE];
X};
X-and
X
Xstruct rsa_key_cpacket {
X    char type;          /* CP_RSA_KEY */
X    char pad1;
X    char pad2;
X    char pad3;
X    unsigned char global[KEY_SIZE];
X    unsigned char public[KEY_SIZE];
X    unsigned char resp[KEY_SIZE];
X---------------
X
XIn struct.h,
X-
Xadd the following structure:
X
X
Xstruct rsa_key {
X    unsigned char client_type[KEY_SIZE];
X    unsigned char architecture[KEY_SIZE];
X    unsigned char global[KEY_SIZE];
X    unsigned char public[KEY_SIZE];
X};
X---------------
X
XIn reserved.c add the line
X-
X#include "defs.h"
X- before the include of packets.h (unless you kept the silly system
X  of having all those unnamed constants in packets.h ... yuck...
X
X---------------
X
X
XI use symbolic links for the following files
Xln -s ../res-rsa/keys.dat
Xln -s ../res-rsa/rsa-server.c rsa_key.c
Xln -s ../res-rsa/rsa_utilmp.c rsa_util.c
X
XAdd the needed lines to the Makefile. Also change the line
XLIBS = -lm
X- to 
XLIBS = -lmp
Xor if you're using the gnu version, something like
XLIBS = -L../gmp-1.2 -lmp
X(I highly recommend using some version of libmp.a, although Ray Jones'
X rsa_util.c is included of you run into real trouble.)
XRun make, and use the key manager (keyman) to add keys.dat to your
Xreserved file. 
X% keyman a keys.dat (from the res-rsa directory, if that's where you want
X  to keep the key data.
X
X
X---------------------------------------------------------------------------
X
XClients:
X---------------------------------------------------------------------------
XTo defs.h, add the lines:
X-
X#define RSA_VERSION "RSA v2.0 CLIENT"  /* string must begin with characters "RSA v" */
X#define KEY_SIZE 32
X#define RESERVED_SIZE 16
X#define MSG_LEN 80
X#define NAME_LEN 16
X#define KEYMAP_LEN 96
X
X---------------
X
XIn data.c, add
X
Xint RSA_Client = 1;
X
X---------------
X
XIn data.h add
X
Xextern int RSA_Client;
X
X---------------
X
XIn socket.c, the function handleRerved() becomes:
X-
XhandleReserved(packet)
Xstruct reserved_spacket *packet;
X{
X    struct reserved_cpacket response;
X
X    if (RSA_Client) {            /* can use -o option for old blessing */
X	warning(RSA_VERSION);
X	strncpy(response.resp, RSA_VERSION, RESERVED_SIZE);
X	bcopy(packet->data, response.data, RESERVED_SIZE);
X	response.type = CP_RESERVED;
X    }
X    else
X	encryptReservedPacket(packet, &response, serverName, me->p_no);
X    sendServerPacket(&response);
X}
X
X- and add the function
X
XhandleRSAKey(packet)
Xstruct rsa_key_spacket *packet;
X{
X    struct rsa_key_cpacket response;
X 
X    response.type = CP_RSA_KEY;
X    encryptRSAPacket(packet, &response);
X 
X    sendServerPacket(&response);
X}
X
XHere are the diffs for the changes to the beginning of the file...
X
Xbegin socket.c
X100d99
X< int handleRSAKey();
X129,130c128,129
X<     { sizeof(struct planet_loc_spacket), handlePlanetLoc }, /* SP_PLANET_LOC */
X<     { sizeof(struct scan_spacket), NULL },		    /* SP_SCAN (ATM) */
X---
X>     { sizeof(struct planet_loc_spacket), handlePlanetLoc },  /* SP_PLANET_LOC */
X>     { sizeof(struct scan_spacket), NULL }, /* SP_SCAN (ATM) */
X133,134c132
X<     { sizeof(struct sc_sequence_spacket), handleSequence }, /* SP_SC_SEQUENCE */
X<     { sizeof(struct rsa_key_spacket), handleRSAKey }	    /* SP_RSA_KEY */
X---
X>     { sizeof(struct sc_sequence_spacket), handleSequence }  /* SP_SC_SEQUENCE */
X174,175c172
X<     sizeof(struct sequence_cpacket),		/* CP_SEQUENCE */
X<     sizeof(struct rsa_key_cpacket)		/* CP_RSA_KEY */
X---
X>     sizeof(struct sequence_cpacket)		/* CP_SEQUENCE */
Xend socket.c
X
X---------------
XIn main.c
X
Xto the processing of the command line options, add
X-
X case 'o':   /* old blessing mode */
X	RSA_Client = 0;
X	break;
X- and to the PrintUsage function, add the appropriate [- o] wherever
X   in the string.
X
X---------------
X
XI have the following symbolic links:
Xln -s ../ntserv/packets.h
Xln -s ../ntserv/struct.h
Xln -s ../ntserv/reserved.c
Xln -s ../ntserv/rsa_util.c
Xln -s ../res-rsa/keys.h
Xln -s ../res-rsa/rsa-client.c rsa_key.c
X
XIf you don't like links, you'll have to copy files and make the changes
Xto packets.h, struct.h, and reserved.c
X
X
XAdd the needed lines to the Makefile.  Build, and test.  The example
Xlist only contains one key (and the global key, actually), so it should
Xonly accept this client.
X
XQuestions or problems to mcp@cs.umd.edu or rjones@dsd.es.com.
X
XNote on rsa_util.c: This is a math library for large numbers that I
Xworked up myself.  It's not too fast.  If you have access to a faster
Xlibrary, you may want to change the rsa_key.c to use it instead.  Gnu
Xhas such a library, called libgmp.  There is also the Berkeley MP
Xlibrary, libmp.  The changes should be minor to accomplish, so I won't
Xgo into them here.  Look at the rsa_encrypt() function to figure out
Xhow it would be done.
X
XCHANGE:  The files rsa_utilmp.c and rsa_utilgmp.c are versions of the
Xrsa_util.c file for MP and GMP.  There may be bugs, but I don't think
Xso (they're pretty simple). You must list -lmp before -lm for the LIBS.
Xthe usual pow() function is not used by netrek, but the name collision
Xcan be avoided by searching libmp.a first.
X
XANOTHER CHANGE: rsa_utilgmp.c is no longer supplied. Use the rsa_utilmp.c
Xwith gnu's version of libmp.a. It can be retrieved from ftp.uu.net.
X
XI've included genkeys.c, a program for building the
Xglobal/public/private keysets.  To compile:
X-
Xcc -o genkeys genkeys.c -lmp
X(use something like -L../gmp-1.2 -lmp  if you're using gnu)
X-
XWhen run, it produces the files keys.h and keys.dat.  keys.h is C code
Xthat can be dropped into or included in the client.  keys.dat is the
Xfile entry for the server, in raw form.  To add a new set of keys to
Xthe server's accepted keyfile, use the key manager.
X
XAs you can see, it uses the Berkeley Multiple Precision library.  This
Xshould be available on most Suns, and on a lot of other machines.  For
Xsome reason it fails on my Mips box.  If you do not have libmp.a, you
Xcan try to build the Gnu MP library, which also has a Berkeley MP
Xcompatible library module.  The GMP lib is on most Gnu sites, under
Xthe name gmp.tar.Z or something like that.
X
XIf you cannot generate your own keys, Send me mail, and I'll send you
Xback a keyset.
X
XThere is also a file called RSA-README.  This is from the RSAREF
Xpackage which the RSA calculation is based on.  By accepting this
Xcode, you agree to the terms outlined therein.  I can't force you to
Xobey them, but then again, I wouldn't want to.
X
XRay Jones
X
X
XAddenda:
X
XWarning: Be careful about where you put what in terms of the socket.c
Xdiffs. Double check that the handler and size structures have the right
Xpackets in the right places. It's fairly obvious, but if you get it wrong,
Xit's a debugging nightmare. If your new server/client crashes, look there
Xfirst. (Getting all those spacket and cpacket thing right can be a little
Xbit of a headache.)
X
X-- Mike Polek
X
XAnd one final note... If you plan on making a client for general use and
Xregistering the key, you must randomly scramble the order of the .o files
Xin the netrek/Makefile so a simple diff won't reveal the key. Also, you
Xmust strip the binary once it's compiled. Then it can be compressed and
Xuploaded to an ftp site. It should also be crypted using the same crypt
Xkey you used to get these files. Read the RSA-README file for why.
X
X
XPS.
XNotes on the key manager:
X
XThe key manager will help you to keep track of which keys are currently
Xinstalled on your system. Keys, when they are initially generated, are
Xjust 64 bytes of data. (Note the keys/key.test file is 64 bytes long.)
Xwhen you install a key into the .reserved file, the key manager adds
Xcertain information to the file and also adds an entry into the catalog
Xfile, a plain text file for your comments, etc. 
X
XKeys are uniquely identified by:
X1) The type of client, eg bronco vanilla, Hadley, gfborg, pig borg, etc.
X2) The architecture/os under which the client was compiled. 
X
XThese two identifiers are kept in the .reserved file. The catalog file
Xalso keeps track of the creator of the key, the date the key was added
Xto your .reserved file, and any comments you wish to add. While the fields
Xin the .reserved file may abbreviate certain features of a client, you 
Xshould put a full blown description in the catalog file.
X
XYou may use the key manager to 
X1) [l]ist keys in the .reserved file
X2) [a]dd a key from a raw 64 byte file
X3) [d]elete a key from .reserved (you must delete the catalog entry manually)
X4) [v]erify if a key in a raw 64 byte file is already in .reserved
X5) [m]odify the fields of an existing key
X6) [c]onvert a set of concatenated raw files to a .reserved file.
X7) e[x]tract a key from .reserved to another file. It will have the
X       (type | arch/os) tags, so it can be "cat"ed back to .reserved later.
X       (Don't try to [a]dd a key that was extracted... only [a]dd raw key files.)
X
XNOTE: Option (6) should really never be used. It is intended for use by those who
X      used the server before the key manager was available. If you inadvertently
X      use the [c] option, you could really hose your .reserved file!!
X
XHINT: back up your .reserved and catalog files periodically.
X
XNotes on the old system::
X
XThe new server can be made to allow older clients by seting CONFIRM=2 in
Xthe .sysdef file (assuming you have the sacred reserved.c for blessing).
XThe new clients can connect to an older server by specifing the -o option.
X(This also assumes the new client was blessed with the old reserved.c.)
XThe new clients under normal circumstances will just look like borgs to
Xthe old servers. Old clients will be notified that they need an upgrade
Xwhen they try to connect to a new server.
X
XMany thanks to all who made this project possible, especially Andy McFadden
Xwho kept me on the right track for so long.
//E*O*F INSTALL//

echo x - key.test.h
sed -e 's/^X//' > "key.test.h" << '//E*O*F key.test.h//'
X/* test key */
X
Xstatic unsigned char key_global[] =
X{
X    17,
X    168,
X    11,
X    45,
X    134,
X    74,
X    60,
X    145,
X    196,
X    163,
X    57,
X    178,
X    77,
X    88,
X    45,
X    177,
X    237,
X    78,
X    31,
X    35,
X    163,
X    157,
X    82,
X    114,
X    112,
X    100,
X    64,
X    19,
X    75,
X    27,
X    250,
X    12,
X};
X
Xstatic unsigned char key_public[] =
X{
X    159,
X    254,
X    146,
X    85,
X    35,
X    59,
X    226,
X    185,
X    239,
X    240,
X    253,
X    34,
X    36,
X    8,
X    198,
X    238,
X    182,
X    94,
X    98,
X    139,
X    114,
X    177,
X    249,
X    230,
X    174,
X    117,
X    239,
X    207,
X    244,
X    87,
X    227,
X    9,
X};
X
Xstatic unsigned char key_private[] =
X{
X    227,
X    161,
X    59,
X    191,
X    182,
X    168,
X    31,
X    130,
X    96,
X    154,
X    253,
X    133,
X    109,
X    113,
X    207,
X    224,
X    246,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X    0,
X};
X
//E*O*F key.test.h//

echo x - keyman.c
sed -e 's/^X//' > "keyman.c" << '//E*O*F keyman.c//'
X/*
X
X        Nick Trown      10-19-92
X        trown@cscihp.ecst.csuchico.edu
X        RSA key manipulation
X*/
X
X
X#include <stdio.h>
X#include <strings.h>
X#include <time.h>
X#include <sys/types.h>
X#include <sys/file.h>
X#include "../ntserv/defs.h"
X#include "../ntserv/struct.h"
X
X#define CATALOG        "catalog"
X
Xstruct rsa_key key_list[1000] = {"\0", "\0", "\0"};
Xint key_count=0;
X
Xvoid readkeys(convert)
X    int convert;
X{
X    int fd;
X    int done;
X
X    fd = open(RSA_KEY_FILE, O_RDONLY | O_CREAT,0600);
X    if (fd < 0)
X    {
X        fprintf(stderr, "Can't open the RSA key file %s\n", RSA_KEY_FILE);
X        exit(1);
X    }
X
X    done = 0;
X    do
X    {
X        if (!convert) {
X                if (read(fd, key_list[key_count].client_type, KEY_SIZE) != KEY_SIZE)
X                    done = 1;
X                if (read(fd, key_list[key_count].architecture, KEY_SIZE) != KEY_SIZE)
X                    done = 1;
X        }
X        if (read(fd, key_list[key_count].global, KEY_SIZE) != KEY_SIZE) {
X                done = 1;
X        }
X        if (read(fd, key_list[key_count].public, KEY_SIZE) != KEY_SIZE) {
X                done = 1;
X        }
X        key_count++;
X    } while (! done);
X
X    key_count--;
X
X    close(fd);
X}
X
Xvoid main(argc,argv)
X        int argc;
X        char *argv[];
X{
X    char mode;
X    void do_usage();
X    void convert();
X    void deletekey();
X    void modifykey();
X    void addkey();
X    void listkeys();
X    void check_exist();
X    void extractkey();
X
X
X    mode = 'l';
X
X    if (argc>1)
X        mode = *argv[1];
X
X    switch (mode) {
X
X        case 'l' : listkeys();
X            break;
X        case 'c' :
X                  convert();
X            break;
X        case 'm' :
X            if (argc>2) {
X                modifykey(argv[2]);
X            }
X            else do_usage();
X            break;
X	case 'x':
X	    if (argc>3) {
X		extractkey(argv[2], argv[3]);
X	    }
X	    else do_usage();
X	    break;
X        case 'd' : {
X            if (argc>2) {
X                deletekey(argv[2]);
X            }
X            else do_usage();
X            }
X            break;
X        case 'a' : {
X            if (argc>2) {
X                addkey(argv[2]);
X            }
X            else do_usage();
X            }
X            break;
X        case 'v' :  {
X            if (argc>2) {
X                 check_exist(argv[2]);
X            }
X            else do_usage();
X            }
X            break;
X
X        default :
X                do_usage();
X    }
X}
X
X
Xvoid do_usage()
X{
X    printf("usage: keys mode <key #> <key file>\n");
X    printf("Modes:\n");
X    printf("l - list keys (default)\n");
X    printf("c - convert. Add type names to RSA file\n");
X    printf("d - delete key <key #>\n");
X    printf("a - add key <key file>\n");
X    printf("v - verify existence of <key file> in RSA file\n");
X    printf("m - modify existing key <key #>\n");
X    printf("x - extract a key <key #> to a file <res file>\n");
X    printf("    (note <res file> will have id strings... can be appended to .reserved)\n");
X    exit(0);
X}
X
Xvoid listkeys()
X{
X    int count;
X    char ch;
X
X    readkeys(0);
X
X    printf("There are %d keys in the RSA file\n",key_count);
X
X
X    for (count = 0; count<key_count; count++) {
X        printf("%d: (%s | %s)\n",count,key_list[count].client_type,
X                                     key_list[count].architecture);
X    }
X
X    printf("\n");
X    exit(0);
X}
X
Xvoid check_exist(name)
X        char *name;
X{
X    int fd;
X    char type[80];
X    void exist();
X
X    struct rsa_key newkey;
X
X    readkeys(0);
X
X    fd = open(name, O_RDONLY| O_CREAT,0600);
X    if (fd < 0)
X    {
X        fprintf(stderr, "Can't open key file %s\n", name);
X        exit(1);
X    }
X
X
X    if (read(fd,key_list[key_count].global,KEY_SIZE) != KEY_SIZE) {
X                printf("global key wrong size\n");
X                exit(0);
X    }
X    if (read(fd,key_list[key_count].public,KEY_SIZE) != KEY_SIZE) {
X                printf("public key wrong size\n");
X                exit(0);
X    }
X
X    exist(key_count);
X    printf("Key %s not in RSA file\n",name);
X}
X
X
Xvoid catalog(num, id)
X        int num;
X        char *id;  /* creator id */
X{
X    FILE *fp;
X    int curtime;
X
X    if ((fp = fopen(CATALOG,"a+"))==NULL) {
X        printf("Error opening %s\n",CATALOG);
X        exit(0);
X    }
X    curtime = time((long *)0);
X
X    fprintf(fp,"Client: %s\n", key_list[num].client_type);
X    fprintf(fp,"\tCreator ID: %s\n", id);
X    fprintf(fp,"\tAdded     : %s", ctime(&curtime));
X    fprintf(fp,"\tArch/OS   : %s\n", key_list[num].architecture);
X    fprintf(fp,"\tComments  : \n");
X
X    fclose(fp);
X
X}
X
Xvoid convert()
X{
X    char buffer[80];
X    int count;
X    int done = 0;
X    void savekeys();
X
X    printf ("WARNING: This should only be used if your .reserved is a file of raw keys!\n");
X    printf ("WARNING: This will prepend client type and architecture/OS fields to keys in .reserved.\n");
X    printf ("WARNING: This will appent entries to your .catalog file.\n");
X    printf ("WARNING: Be certain you want to do this!!!!!!!\n");
X    printf ("WARNING: This procedure will alter your RSA_KEY_FILE. Continue?(y/n)");
X    gets(buffer);
X    if (!strcmp(buffer, "n")) {
X      printf ("Ok, exiting...\n");
X      exit (0);
X    }
X    if (strcmp(buffer, "y")) {
X      printf ("unrecognized response... must enter 'y' or 'n'... exiting.\n");
X      exit(1);
X    }
X
X    readkeys(1);
X
X    printf("There are %d unconverted keys\n",key_count);
X
X    for (count = 0; count< key_count; count++) {
X
X      printf ("Key %d\n", count);
X
X      do {
X          printf("Enter type of client: ");
X          gets(buffer);
X          if (strlen(buffer) > KEY_SIZE)
X                  printf("Client type must be less than %d characters.\n",KEY_SIZE);
X      } while (strlen(buffer) > KEY_SIZE);
X      strcpy(key_list[count].client_type,buffer);
X
X      do {
X          printf("Enter architecture/OS: ");
X          gets(buffer);
X          if (strlen(buffer) > KEY_SIZE)
X                  printf("Architecture field must be less than %d characters.\n",KEY_SIZE);
X      } while (strlen(buffer) > KEY_SIZE);
X      strcpy(key_list[count].architecture,buffer);
X
X
X      do {
X        printf("Enter the Creator's ID: ");
X        gets(buffer);
X        if (strlen(buffer) > KEY_SIZE)
X              printf("ID size too long. Use the creator's login\n");
X      } while (strlen(buffer)>KEY_SIZE);
X
X      catalog (count, buffer);
X    }
X
X    savekeys();
X}
X
Xvoid deletekey(number)
X        char *number;
X{
X    int num = atoi(number);
X    void savekeys();
X
X    readkeys(0);
X
X    if (num <0) {
X        printf("Must be positive\n");
X        exit(0);
X    }
X
X    if (num >= key_count) {
X        printf("Number to large\n");
X        exit(0);
X    }
X
X    printf("Warning: The entry (%s | %s) in the catalog needs to be deleted.\n",
X               key_list[num].client_type, key_list[num].architecture);
X
X    key_list[num] = key_list[--key_count];
X    savekeys();
X}
X
Xvoid modifykey(number)
X	char *number;
X{
X    int num = atoi(number);
X    char type[80];
X    void savekeys();
X
X    if (num <0) {
X        printf("Must be positive\n");
X        exit(0);
X    }
X
X    readkeys(0);
X
X    if (num >= key_count) {
X        printf("Number to large\n");
X        exit(0);
X    }
X
X
X    do {
X	printf ("Client: %s\n", key_list[num].client_type);
X        printf("Enter new type of client (<enter> for no change): ");
X        gets(type);
X        if (strlen(type) > KEY_SIZE)
X                printf("Client type must be less than %d characters.\n",KEY_SIZE);
X    } while (strlen(type) > KEY_SIZE);
X    if (!strcmp(type, ""))
X	printf ("Client type not modified.\n");
X    else
X        strcpy(key_list[num].client_type,type);
X
X    do {
X	printf("Arch/OS: %s\n", key_list[num].architecture);
X        printf("Enter new architecture/OS (<enter> for no change): ");
X        gets(type);
X        if (strlen(type) > KEY_SIZE)
X                printf("Architecture field must be less than %d characters.\n",KEY_SIZE);
X    } while (strlen(type) > KEY_SIZE);
X    if (!strcmp(type, ""))
X	printf ("Arch/OS not modified.\n");
X    else
X    	strcpy(key_list[num].architecture,type);
X
X    savekeys();
X
X}
X
Xvoid extractkey(number, filename)
Xchar *number, *filename;
X{
X    int num = atoi(number);
X    int fd;
X    char type[80];
X    void savekeys();
X
X    if (num <0) {
X        printf("Must be positive\n");
X        exit(0);
X    }
X
X    readkeys(0);
X
X    if (num >= key_count) {
X        printf("Number to large\n");
X        exit(0);
X    }
X
X    fd = open(filename, O_CREAT | O_WRONLY | O_APPEND, 0600);
X    if (fd < 0)
X    {
X        fprintf(stderr, "Can't open the new key file %s\n", filename);
X        exit(1);
X    }
X
X    printf("saving key %d (%s | %s) in file %s\n", num, key_list[num].client_type,
X                                                   key_list[num].architecture, filename);
X    if (write(fd, &key_list[num], sizeof(struct rsa_key)) != sizeof(struct rsa_key))
X        printf("Error during file write!\n");
X
X    close(fd);
X    exit(0);
X}
X
Xvoid savekeys()
X{
X    int fd;
X    int count;
X
X    fd = open(RSA_KEY_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0600);
X    if (fd < 0)
X    {
X        fprintf(stderr, "Can't open the RSA key file %s\n", RSA_KEY_FILE);
X        exit(1);
X    }
X    for (count=0; count<key_count; count++) {
X        printf("saving key %d (%s | %s)\n", count, key_list[count].client_type,
X                                                   key_list[count].architecture);
X        if (write(fd, &key_list[count], sizeof(struct rsa_key)) != sizeof(struct rsa_key))
X                printf("Error during file write!\n");
X    }
X    close(fd);
X    exit(0);
X}
X
Xvoid exist(num)
X    int num;
X{
X    int count;
X
X    for (count =0; count<key_count; count++) {
X          if ((!bcmp(key_list[num].global,key_list[count].global,KEY_SIZE)) &&
X             (!bcmp(key_list[num].public,key_list[count].public,KEY_SIZE))) {
X                printf("That key is already in the database with type (%s | %s)\n"
X                        ,key_list[count].client_type, key_list[count].architecture);
X                exit(0);
X          }
X    }
X}
X
X
Xvoid addkey(name)
X        char *name;
X{
X    int fd;
X    char type[80],
X         id[KEY_SIZE]; /* creator id */
X
X    struct rsa_key newkey;
X
X    readkeys(0);
X
X    fd = open(name, O_RDONLY| O_CREAT, 0600);
X    if (fd < 0)
X    {
X        fprintf(stderr, "Can't open key file %s\n", name);
X        exit(1);
X    }
X
X
X    if (read(fd,key_list[key_count].global,KEY_SIZE) != KEY_SIZE) {
X                printf("global key wrong size\n");
X                exit(0);
X    }
X    if (read(fd,key_list[key_count].public,KEY_SIZE) != KEY_SIZE) {
X                printf("public key wrong size\n");
X                exit(0);
X    }
X    exist(key_count);
X
X    do {
X      printf("Enter the Creator's ID: ");
X      gets(type);
X      if (strlen(type) > KEY_SIZE)
X            printf("ID size too long. Use the creator's login\n");
X    } while (strlen(type)>KEY_SIZE);
X    strcpy (id, type);
X
X    do {
X        printf("Enter type of client:");
X        gets(type);
X        if (strlen(type) > KEY_SIZE)
X                printf("Client type must be less than %d characters.\n",KEY_SIZE);
X    } while (strlen(type) > KEY_SIZE);
X    strcpy(key_list[key_count].client_type,type);
X
X    do {
X        printf("Enter architecture/OS:");
X        gets(type);
X        if (strlen(type) > KEY_SIZE)
X                printf("Architecture field must be less than %d characters.\n",KEY_SIZE);
X    } while (strlen(type) > KEY_SIZE);
X    strcpy(key_list[key_count].architecture,type);
X
X
X    close(fd);
X
X    fd = open(RSA_KEY_FILE, O_CREAT | O_WRONLY | O_APPEND, 0600);
X    if (fd < 0)
X    {
X        fprintf(stderr, "Can't open the RSA key file %s\n",name);
X        exit(1);
X    }
X
X
X    printf("saving key %d (%s | %s)\n", key_count, key_list[key_count].client_type,
X                                                   key_list[key_count].architecture);
X    if (write(fd, &key_list[key_count], sizeof(struct rsa_key)) != sizeof(struct rsa_key))
X            printf("Error during file write!\n");
X
X    close(fd);
X
X    printf("added key to RSA file\n");
X
X    catalog(key_count, id);
X
X    exit(0);
X}
X
//E*O*F keyman.c//

echo x - rsa-client.c
sed -e 's/^X//' > "rsa-client.c" << '//E*O*F rsa-client.c//'
X/* rsa_key.c
X * 
X * Ray Jones 
X */
X#include "copyright2.h"
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include "defs.h"
X#include "packets.h"
X#include "Wlib.h"
X#include "data.h"
X
X#include "keys.h"
X
X#ifdef GATEWAY
Xextern long netaddr;
Xextern int serv_port;
X#endif
X
XencryptRSAPacket(spacket, cpacket)
Xstruct rsa_key_spacket *spacket;
Xstruct rsa_key_cpacket *cpacket;
X{
X    struct sockaddr_in saddr;
X    int len;
X    u_short port;
X    unsigned char *data;
X
X#ifndef GATEWAY
X    /* query the socket to determine the remote host (ATM) */
X    len = sizeof(saddr);
X    if (getpeername(sock, &saddr, &len) < 0) {
X        perror("getpeername(sock)");
X        exit(1);
X    }
X#else
X    saddr.sin_addr.s_addr = netaddr;
X    saddr.sin_port = htons(serv_port);
X#endif
X
X    /* replace the first few bytes of the message */
X    /* will be the low order bytes of the number */
X    data = spacket->data;
X    bcopy (&saddr.sin_addr.s_addr, data, sizeof(saddr.sin_addr.s_addr));
X    data += sizeof(saddr.sin_addr.s_addr);
X    bcopy (&saddr.sin_port, data, sizeof(saddr.sin_port));
X
X    /* do the actual computaions */
X    rsa_encode(cpacket->resp, spacket->data, key_private, 
X	       key_global, KEY_SIZE);
X    
X    bcopy(key_global, cpacket->global, KEY_SIZE);
X    bcopy(key_public, cpacket->public, KEY_SIZE);
X}
X
//E*O*F rsa-client.c//

echo x - rsa-server.c
sed -e 's/^X//' > "rsa-server.c" << '//E*O*F rsa-server.c//'
X/* rsa_key.c
X * 
X * Mike Polek   11/92
X */
X#include "copyright2.h"
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <sys/file.h>
X#include "defs.h"
X#include "struct.h"
X#include "data.h"
X#include "packets.h"
X
XmakeRSAPacket(packet)
Xstruct rsa_key_spacket *packet;
X{
X    int i;
X
X    for (i=0; i<KEY_SIZE; i++)
X	packet->data[i]=random() % 256;
X    /* make sure it is less than the global key */
X    for (i=KEY_SIZE-10; i < KEY_SIZE; i++)
X	packet->data[i] = 0; 
X    packet->type = SP_RSA_KEY;
X}
X
X/* returns 1 if the user verifies incorrectly */
XdecryptRSAPacket(spacket, cpacket, serverName)
Xstruct rsa_key_spacket *spacket;
Xstruct rsa_key_cpacket *cpacket;
Xchar *serverName;
X{
X    struct rsa_key key;
X    struct sockaddr_in saddr;
X    unsigned char temp[KEY_SIZE], *data;
X    char format[128];
X    int fd;
X    FILE *logfile;
X    int done, found, curtime, len;
X
X    len = sizeof(saddr);
X    if (getsockname(sock, &saddr, &len) < 0) {
X        perror("getsockname(sock)");
X        exit(1);
X    }
X
X    /* replace the first few bytes of the message */
X    /* will be the low order bytes of the number */
X    data = spacket->data;
X    bcopy (&saddr.sin_addr.s_addr, data, sizeof(saddr.sin_addr.s_addr));
X    data += sizeof(saddr.sin_addr.s_addr);
X    bcopy (&saddr.sin_port, data, sizeof(saddr.sin_port));
X
X    fd = open(RSA_KEY_FILE, O_RDONLY);
X    if (fd < 0)
X    {
X	fprintf(stderr, "Can't open the RSA key file %s\n", RSA_KEY_FILE);
X	exit(1);
X    }
X
X    done = found = 0;
X    do 
X    {
X	if (read(fd, &key, sizeof(struct rsa_key)) != sizeof(struct rsa_key))
X	    done = 1;
X	if (! (bcmp(key.global, cpacket->global, KEY_SIZE) ||
X	       bcmp(key.public, cpacket->public, KEY_SIZE)))
X	    done = found = 1;
X    } while (! done);
X    
X    close(fd);
X
X    /* If he wasn't in the file, kick him out */
X    if (! found)
X	return 1;
X    
X    rsa_encode(temp, cpacket->resp, key.public, key.global, KEY_SIZE);
X
X    /* If we don't get the right answer, kick him out */
X    if (bcmp(temp, spacket->data, KEY_SIZE))
X	return 1;
X    logfile=fopen(LOGFILENAME, "a");
X    if (!logfile) return 0;
X
X    curtime=time(NULL);
X    sprintf (format, "Client: %%.%ds. Arch: %%.%ds. Player: %%s. Login: %%s. at %%s.",
X                       KEY_SIZE, KEY_SIZE);
X    fprintf (logfile, format,
X             key.client_type,
X             key.architecture,
X             me->p_name,
X             me->p_login,
X	     ctime(&curtime));
X
X    fclose(logfile);
X
X    return 0;
X}
//E*O*F rsa-server.c//

exit 0

-- 
fadden@uts.amdahl.com (Andy McFadden)
[ Above opinions are mine, Amdahl has nothing to do with them, etc, etc. ]