Instructions for adding the new reserved.c to Clients and Servers

Servers:
---------------------------------------------------------------------------
To defs.h, add the lines:
-
#define RESERVED_FILE   "../conf/.reserved"
#define RSA_VERSION "RSA v2.0 SERVER"  /* String must begin with "RSA v" */
#define KEY_SIZE 32
#define RESERVED_SIZE 16
#define MSG_LEN 80
#define NAME_LEN 16
#define KEYMAP_LEN 96
---------------

In data.c, change the line that says:
-
char testdata[16];
- to
char testdata[KEY_SIZE];
-and add
int RSA_Client;
---------------

In data.h, change
-
extern char testdata[16];
- to
extern char testdata[];

add
extern int RSA_Client;
---------------

In redraw.c change the line that says:
-
bcopy(sp.data, testdata, 16);
- to
bcopy(sp.data, testdata, KEY_SIZE);
- and change the line
warning("No customized binaries.  Please use a blessed one.");
- to
if (RSA_Client==1)
    warning("No customized binaries.  Please use a blessed one.");
else if (RSA_Client==2)
    warning("Wrong Client Version Number!");
else
    warning("You need a spiffy new RSA client for this server!");


---------------

In socket.c, the function handleReserved becomes:
-
handleReserved(packet)
struct reserved_cpacket *packet;
{
    struct reserved_cpacket mycp;
    struct reserved_spacket mysp;
    struct rsa_key_spacket   rsp;
    char serverName[64]; /* now get serverName from system 8/2/92 TC */

    if (testtime==1) return;
    if (bcmp(packet->data, testdata, RESERVED_SIZE) != 0) {
	testtime=1;
	return;
    }
    if (!strncmp (packet->resp, RSA_VERSION, 3)) {
	  /* This is an RSA type client */
	  RSA_Client = 2;
	  warning (RSA_VERSION);
      if (!strncmp (packet->resp, RSA_VERSION, strlen("RSA v??"))) {
	  /* This is the right major version */
	  RSA_Client = 1;
	  makeRSAPacket(&rsp);
	  bcopy(rsp.data, testdata, KEY_SIZE);
	  sendClientPacket (&rsp);
	  return;
      }
      testtime=1;
      return;
    }
    bcopy(testdata, mysp.data, RESERVED_SIZE);
    if (gethostname(serverName, 64)) fprintf(stderr, "gethostname() error\n"); /* 8/2/92 TC */
    encryptReservedPacket(&mysp, &mycp, serverName, me->p_no);
    if (bcmp(packet->resp, mycp.resp, RESERVED_SIZE) != 0) {
	fprintf(stderr, "User verified incorrectly.\n");
	testtime=1;
	return;
    }
    /* Use .sysdef CONFIRM flag to allow old style clients. */
    if (binconfirm==2)
	testtime=0;
    else
	testtime=1;
}

- and add the function 

handleRSAKey(packet)
struct rsa_key_cpacket *packet;
{
    struct rsa_key_cpacket mycp;
    struct rsa_key_spacket mysp;
    char serverName[64]; 
 
    if (testtime==1) return;
    if (RSA_Client != 1) return;
    bcopy(testdata, mysp.data, KEY_SIZE);
    if (gethostname(serverName, 64)) fprintf(stderr, "gethostname() error\n");
    if (decryptRSAPacket(&mysp, packet, serverName))
    {
        fprintf(stderr, "User verified incorrectly.\n");
        testtime=1;
        return;
    }
    testtime=0;
}

- I changed the (is it ever used??) line
if ((binconfirm == 3) && !strcmp(packet->resp, "Cyborg")) {	/* ATM */
- to
if ((binconfirm == 2) && !strcmp(packet->resp, "Cyborg")) {	/* ATM */
- (look above for why)


Here are the diffs for the beginning part of the file:

begin socket.c
82d81
< int handleRSAKey();
124,125c123
<     { sizeof(struct sequence_cpacket), handleSequence },   /* CP_SEQUENCE */
<     { sizeof(struct rsa_key_cpacket), handleRSAKey }	   /* CP_RSA_KEY */
---
>     { sizeof(struct sequence_cpacket), handleSequence }	   /* CP_SEQUENCE */
159,160c157
<     sizeof(struct sc_sequence_spacket),		/* SP_SC_SEQUENCE */
<     sizeof(struct rsa_key_spacket)		/* SP_RSA_KEY */
---
>     sizeof(struct sc_sequence_spacket)		/* SP_SC_SEQUENCE */
end socket.c


---------------

In packets.h, 
-
Add the codes
#define SP_RSA_KEY	31		/* handles binary verification */
#define CP_RSA_KEY	37		/* handles binary verification */
(in the appropriate places)
-
Add the CP_RSA_KEY and SP_RSA_KEY packets as: 
-
struct rsa_key_spacket {
    char type;          /* SP_RSA_KEY */
    char pad1;
    char pad2;
    char pad3;
    unsigned char data[KEY_SIZE];
};
-and

struct rsa_key_cpacket {
    char type;          /* CP_RSA_KEY */
    char pad1;
    char pad2;
    char pad3;
    unsigned char global[KEY_SIZE];
    unsigned char public[KEY_SIZE];
    unsigned char resp[KEY_SIZE];
---------------

In struct.h,
-
add the following structure:


struct rsa_key {
    unsigned char client_type[KEY_SIZE];
    unsigned char architecture[KEY_SIZE];
    unsigned char global[KEY_SIZE];
    unsigned char public[KEY_SIZE];
};
---------------

In reserved.c add the line
-
#include "defs.h"
- before the include of packets.h (unless you kept the silly system
  of having all those unnamed constants in packets.h ... yuck...

---------------


I use symbolic links for the following files
ln -s ../res-rsa/keys.dat
ln -s ../res-rsa/rsa-server.c rsa_key.c
ln -s ../res-rsa/rsa_utilmp.c rsa_util.c

Add the needed lines to the Makefile. Also change the line
LIBS = -lm
- to 
LIBS = -lmp
or if you're using the gnu version, something like
LIBS = -L../gmp-1.2 -lmp
(I highly recommend using some version of libmp.a, although Ray Jones'
 rsa_util.c is included of you run into real trouble.)
Run make, and use the key manager (keyman) to add keys.dat to your
reserved file. 
% keyman a keys.dat (from the res-rsa directory, if that's where you want
  to keep the key data.


---------------------------------------------------------------------------

Clients:
---------------------------------------------------------------------------
To defs.h, add the lines:
-
#define RSA_VERSION "RSA v2.0 CLIENT"  /* string must begin with characters "RSA v" */
#define KEY_SIZE 32
#define RESERVED_SIZE 16
#define MSG_LEN 80
#define NAME_LEN 16
#define KEYMAP_LEN 96

---------------

In data.c, add

int RSA_Client = 1;

---------------

In data.h add

extern int RSA_Client;

---------------

In socket.c, the function handleRerved() becomes:
-
handleReserved(packet)
struct reserved_spacket *packet;
{
    struct reserved_cpacket response;

    if (RSA_Client) {            /* can use -o option for old blessing */
	warning(RSA_VERSION);
	strncpy(response.resp, RSA_VERSION, RESERVED_SIZE);
	bcopy(packet->data, response.data, RESERVED_SIZE);
	response.type = CP_RESERVED;
    }
    else
	encryptReservedPacket(packet, &response, serverName, me->p_no);
    sendServerPacket(&response);
}

- and add the function

handleRSAKey(packet)
struct rsa_key_spacket *packet;
{
    struct rsa_key_cpacket response;
 
    response.type = CP_RSA_KEY;
    encryptRSAPacket(packet, &response);
 
    sendServerPacket(&response);
}

Here are the diffs for the changes to the beginning of the file...

begin socket.c
100d99
< int handleRSAKey();
129,130c128,129
<     { sizeof(struct planet_loc_spacket), handlePlanetLoc }, /* SP_PLANET_LOC */
<     { sizeof(struct scan_spacket), NULL },		    /* SP_SCAN (ATM) */
---
>     { sizeof(struct planet_loc_spacket), handlePlanetLoc },  /* SP_PLANET_LOC */
>     { sizeof(struct scan_spacket), NULL }, /* SP_SCAN (ATM) */
133,134c132
<     { sizeof(struct sc_sequence_spacket), handleSequence }, /* SP_SC_SEQUENCE */
<     { sizeof(struct rsa_key_spacket), handleRSAKey }	    /* SP_RSA_KEY */
---
>     { sizeof(struct sc_sequence_spacket), handleSequence }  /* SP_SC_SEQUENCE */
174,175c172
<     sizeof(struct sequence_cpacket),		/* CP_SEQUENCE */
<     sizeof(struct rsa_key_cpacket)		/* CP_RSA_KEY */
---
>     sizeof(struct sequence_cpacket)		/* CP_SEQUENCE */
end socket.c

---------------
In main.c

to the processing of the command line options, add
-
 case 'o':   /* old blessing mode */
	RSA_Client = 0;
	break;
- and to the PrintUsage function, add the appropriate [- o] wherever
   in the string.

---------------

I have the following symbolic links:
ln -s ../ntserv/packets.h
ln -s ../ntserv/struct.h
ln -s ../ntserv/reserved.c
ln -s ../ntserv/rsa_util.c
ln -s ../res-rsa/keys.h
ln -s ../res-rsa/rsa-client.c rsa_key.c

If you don't like links, you'll have to copy files and make the changes
to packets.h, struct.h, and reserved.c


Add the needed lines to the Makefile.  Build, and test.  The example
list only contains one key (and the global key, actually), so it should
only accept this client.

Questions or problems to mcp@cs.umd.edu or rjones@dsd.es.com.

Note on rsa_util.c: This is a math library for large numbers that I
worked up myself.  It's not too fast.  If you have access to a faster
library, you may want to change the rsa_key.c to use it instead.  Gnu
has such a library, called libgmp.  There is also the Berkeley MP
library, libmp.  The changes should be minor to accomplish, so I won't
go into them here.  Look at the rsa_encrypt() function to figure out
how it would be done.

CHANGE:  The files rsa_utilmp.c and rsa_utilgmp.c are versions of the
rsa_util.c file for MP and GMP.  There may be bugs, but I don't think
so (they're pretty simple). You must list -lmp before -lm for the LIBS.
the usual pow() function is not used by netrek, but the name collision
can be avoided by searching libmp.a first.

ANOTHER CHANGE: rsa_utilgmp.c is no longer supplied. Use the rsa_utilmp.c
with gnu's version of libmp.a. It can be retrieved from ftp.uu.net.

I've included genkeys.c, a program for building the
global/public/private keysets.  To compile:
-
cc -o genkeys genkeys.c -lmp
(use something like -L../gmp-1.2 -lmp  if you're using gnu)
-
When run, it produces the files keys.h and keys.dat.  keys.h is C code
that can be dropped into or included in the client.  keys.dat is the
file entry for the server, in raw form.  To add a new set of keys to
the server's accepted keyfile, use the key manager.

As you can see, it uses the Berkeley Multiple Precision library.  This
should be available on most Suns, and on a lot of other machines.  For
some reason it fails on my Mips box.  If you do not have libmp.a, you
can try to build the Gnu MP library, which also has a Berkeley MP
compatible library module.  The GMP lib is on most Gnu sites, under
the name gmp.tar.Z or something like that.

If you cannot generate your own keys, Send me mail, and I'll send you
back a keyset.

There is also a file called RSA-README.  This is from the RSAREF
package which the RSA calculation is based on.  By accepting this
code, you agree to the terms outlined therein.  I can't force you to
obey them, but then again, I wouldn't want to.

Ray Jones


Addenda:

Warning: Be careful about where you put what in terms of the socket.c
diffs. Double check that the handler and size structures have the right
packets in the right places. It's fairly obvious, but if you get it wrong,
it's a debugging nightmare. If your new server/client crashes, look there
first. (Getting all those spacket and cpacket thing right can be a little
bit of a headache.)

-- Mike Polek

And one final note... If you plan on making a client for general use and
registering the key, you must randomly scramble the order of the .o files
in the netrek/Makefile so a simple diff won't reveal the key. Also, you
must strip the binary once it's compiled. Then it can be compressed and
uploaded to an ftp site. It should also be crypted using the same crypt
key you used to get these files. Read the RSA-README file for why.


PS.
Notes on the key manager:

The key manager will help you to keep track of which keys are currently
installed on your system. Keys, when they are initially generated, are
just 64 bytes of data. (Note the keys/key.test file is 64 bytes long.)
when you install a key into the .reserved file, the key manager adds
certain information to the file and also adds an entry into the catalog
file, a plain text file for your comments, etc. 

Keys are uniquely identified by:
1) The type of client, eg bronco vanilla, Hadley, gfborg, pig borg, etc.
2) The architecture/os under which the client was compiled. 

These two identifiers are kept in the .reserved file. The catalog file
also keeps track of the creator of the key, the date the key was added
to your .reserved file, and any comments you wish to add. While the fields
in the .reserved file may abbreviate certain features of a client, you 
should put a full blown description in the catalog file.

You may use the key manager to 
1) [l]ist keys in the .reserved file
2) [a]dd a key from a raw 64 byte file
3) [d]elete a key from .reserved (you must delete the catalog entry manually)
4) [v]erify if a key in a raw 64 byte file is already in .reserved
5) [m]odify the fields of an existing key
6) [c]onvert a set of concatenated raw files to a .reserved file.
7) e[x]tract a key from .reserved to another file. It will have the
       (type | arch/os) tags, so it can be "cat"ed back to .reserved later.
       (Don't try to [a]dd a key that was extracted... only [a]dd raw key files.)

NOTE: Option (6) should really never be used. It is intended for use by those who
      used the server before the key manager was available. If you inadvertently
      use the [c] option, you could really hose your .reserved file!!

HINT: back up your .reserved and catalog files periodically.

Notes on the old system::

The new server can be made to allow older clients by seting CONFIRM=2 in
the .sysdef file (assuming you have the sacred reserved.c for blessing).
The new clients can connect to an older server by specifing the -o option.
(This also assumes the new client was blessed with the old reserved.c.)
The new clients under normal circumstances will just look like borgs to
the old servers. Old clients will be notified that they need an upgrade
when they try to connect to a new server.

Many thanks to all who made this project possible, especially Andy McFadden
who kept me on the right track for so long.
