/*                               -*- Mode: C -*- 
 * security.c -- 
 * Author          : Shaun Savage
 * Created On      : Fri Feb  3 12:17:11 1995
 * Last Modified By: Shaun Savage
 * Last Modified On: Thu Feb 23 15:56:41 1995
 * Update Count    : 62
 * Status          : Unknown, Use with caution!
 * PURPOSE
 * 	|>Description of modules purpose<|
 * TABLE OF CONTENTS
 * 
 */
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include "tcp_edi.h"
#include "security.h"

static char SysRand[16];
static char OMENCrypt[32];
static char OMENAuth[16];
static Int16 OMENSeq;


uchar* GetUKey(uchar *ukey, uchar *urand, char *pass, Int16 useq)
   {
   char cbuf[PASS_LEN+URAND_LEN+4+1];
   int i, len = strlen(pass);
   StrStruct text;
   
   if ((pass == NULL) || (urand == NULL) || (ukey == NULL))
      {
      return NULL;
      }

   /* clear User Key before use */
   for (i=0;i<UKEY_LEN;i++)
      ukey[i] = 0;

   if (len > PASS_LEN)
      {
      /* pass phrase too long */
      }

   sprintf(cbuf, "%04x", useq);
   cbuf[4]=0;
   memcpy(&cbuf[4], urand, 16);
   memcpy(&cbuf[20], pass, strlen(pass));

   text.string = cbuf;
   text.len    = 4 + URAND_LEN + len;
   Hash(ukey, &text ,1,HASH_MD5);

   for (i=0;i<text.len;i++)
      cbuf[i] = 0;
   text.string = NULL;
   text.len = 0;

   return ukey;
   }

uchar*  AuthUsr(uchar *uauth, uchar *urand, char *pass, Int16 seq)
   {
   int i;
   uchar cbuf[UKEY_LEN + SYSRAND_LEN];
   StrStruct text;

   GetUKey(cbuf, urand, pass, seq);
   memcpy(&cbuf[UKEY_LEN], SysRand, SYSRAND_LEN);

   text.string = cbuf;
   text.len = UKEY_LEN + SYSRAND_LEN;

   Hash(uauth, &text,1,HASH_MD5);

   for (i=0;i<text.len;i++)
      cbuf[i] = 0;
   text.string = NULL;
   text.len = 0;

   return uauth;
   }

Int16 SendEDI(NetPacket *np,StreamInfo *tcpd)
   {
   uchar buf[256], *ptr = buf;
   int len;

   *ptr++ = 0x01; /*PACKETVER;*/

   *ptr++ = len = strlen(np->np_name);
   memcpy(ptr , np->np_name, len);
   ptr += len;

   *ptr++ = len = strlen(np->np_home);
   memcpy(ptr , np->np_home, len);
   ptr += len;

   *ptr++ = len = strlen(np->np_site);
   memcpy(ptr , np->np_site, len);
   ptr += len;
 
   *ptr++ = 0;  /* dst name */
   *ptr++ = 0;  /* dst home */
   *ptr++ = 0;  /* dst site */
  
   PUT16(ptr, np->np_service);
   ptr+=2;
   PUT16(ptr, np->np_msgtype);
   ptr+=2;
   PUT16(ptr, np->np_editype);
   ptr+=2;
   PUT16(ptr, np->np_edilen);
   ptr+=2;

   len = (ptr - buf);

   return CryptEDI(np, buf, len, tcpd);
   }

Int16 CryptEDI(NetPacket *np, uchar *head, Int16 hlen, StreamInfo *tcpd)
   {
   int rslt, len;
   uchar buf[64];
   StrStruct text[4];
   CryptInfo *cinfo;
   uchar keybuf[32];

   text[0].string = head;
   text[0].len = hlen;

   text[1].string = buf;
   text[1].len = PutCryptInfo(buf, np->np_ukey);

   text[2].string = np->np_edidata;
   text[2].len = np->np_edilen;


   cinfo = (CryptInfo*) buf;
   switch (cinfo->ci_mode)
      {
      case CRYPT_NO:
	 break;
      case CRYPT_AUTH + CRYPT_DES:
	 HashKey((uchar*)(cinfo->ci_key), np->np_ukey);
	 rslt = Hash((uchar*)(cinfo->ci_key), &text[0], 3, HASH_MD5);
	 break;
      case CRYPT_CRYPT + CRYPT_DES:
	 HashKey((uchar*)(cinfo->ci_key), np->np_ukey);
	 rslt = Hash((uchar*)(cinfo->ci_key), &text[0], 3, HASH_MD5);
	 DesKey(keybuf, np->np_ukey);
	 len = TDes(keybuf, &text[2], 1, DES3CRYPT);
	 break;
      case CRYPT_AUTH + CRYPT_RSA:
      case CRYPT_CRYPT + CRYPT_RSA:
      default:
	 return NULL;
      }
   ClrKey(keybuf);

   Block2TCP(head,hlen,TRUE,FALSE,tcpd);
   Block2TCP(text[1].string,text[1].len,FALSE,FALSE,tcpd);
   Block2TCP(text[2].string,len,FALSE,TRUE,tcpd);

   return 0;
   }

Int16 DeCryptEDI(NetPacket *np, RawPacket *rp)
   {
   StrStruct text[4];
   CryptInfo *cinfo;
   uchar  keybuf[32];
   
   text[0].string = rp->rp_raw;
   text[0].len = ParseHead(np, rp);

   cinfo = (CryptInfo*) text[1].string  = text[0].string + text[0].len;
   text[1].len = GetCryptInfo(cinfo);

   text[2].string = np->np_edidata = text[1].string + text[1].len;
   text[2].len = rp->rp_len - text[0].len - text[1].len;

   switch (cinfo->ci_mode)
      {
      case CRYPT_NO:
	 break;
      case CRYPT_AUTH + CRYPT_DES:
	 memcpy(keybuf, cinfo->ci_key, UAUTH_LEN);
	 HashKey((uchar*)(cinfo->ci_key), rp->rp_ukey); 
	 Hash((uchar*)(cinfo->ci_key), &text[0], 3, HASH_MD5);
	 break;
      case CRYPT_CRYPT + CRYPT_DES:
	 DesKey(keybuf , rp->rp_ukey);
	 TDes( keybuf, &text[2], 1, DES3PLAIN);
	 memcpy(keybuf, cinfo->ci_key, UAUTH_LEN);
	 HashKey((cinfo->ci_key), rp->rp_ukey); 
	 Hash((uchar*)(cinfo->ci_key), &text[0], 3, HASH_MD5);
	 break;
      case CRYPT_AUTH + CRYPT_RSA:
      case CRYPT_CRYPT + CRYPT_RSA:
      default:
	 return 0;
      }

   if (memcmp(keybuf, cinfo->ci_key, UAUTH_LEN))
      {
      return 0;
      }

   return (Int16) 0;
   }

Int16 UpdateUsr(const char *name, const char *addr,
		uchar *ukey, Int16 useq)
   {
   return useq++;
   } 

Int16 UpdateSys(const uchar *sauth, const uchar *scrypt,
	        Int16 sseq)
   {
   return sseq++;
   }



