{$IFDEF WtrGate}{$IFDEF UseOvr}{$O+,F+}{$ENDIF}{$ENDIF}
UNIT Keys;

INTERFACE

TYPE SecurityResult = (NoKey,IsValidKey,BogusKey);

FUNCTION  WtrCheckKey : SecurityResult;
PROCEDURE WtrCheckBetaKey;
PROCEDURE NoKeySignOff;
PROCEDURE KeySignOff;

{$IFDEF PLATFORM_DOS_ALL}
PROCEDURE CreateKey;
PROCEDURE DumpKey;
{$ENDIF}


IMPLEMENTATION

USES Ramon,
     UnixTime,
     Globals,
     Cfg,
     Crt,
     Dos;

{ Keys Unit                                                             }
{                                                                       }
{ WtrGate project                                                       }
{                                                                       }
{ Aangezien van deze unit geld afhangt is het handig om 'm zo veilig    }
{ mogenlijk te maken.                                                   }
{                                                                       }
{ Sleutels met een nummer groter dan $f000 (61440) worden beschouwd als }
{ Beta keys, en kunnen alleen gebruikt worden met Beta releases van     }
{ WtrGate. Daarnaast zijn ze slechts 3 maanden bruikbaar.               }

CONST Expand     = 52000;
      DefaultKey = 'WTRGATE.KEY';
      KeyEditorNumber = 1; { Martijn }
{      CheckKey : longint = -411358733; }
      CheckKey  : longint = 1027908013;

      KeyTabel : ARRAY[0..249] OF Byte = (
                      096 , 160 , 181 , 225 , 019,
                      189 , 130 , 058 , 009 , 208,
                      063 , 194 , 136 , 030 , 108,
                      090 , 052 , 184 , 127 , 050,
                      210 , 176 , 085 , 150 , 140,
                      022 , 246 , 215 , 174 , 212,
                      005 , 087 , 185 , 190 , 102,
                      228 , 197 , 112 , 094 , 055,
                      183 , 216 , 016 , 026 , 032,
                      152 , 153 , 091 , 082 , 083,
                      143 , 061 , 073 , 193 , 114,
                      033 , 101 , 011 , 179 , 093,
                      020 , 107 , 222 , 109 , 175,
                      132 , 146 , 217 , 201 , 205,
                      144 , 065 , 025 , 075 , 166,
                      098 , 047 , 007 , 223 , 035,
                      066 , 128 , 134 , 125 , 086,
                      053 , 028 , 148 , 158 , 115,
                      186 , 021 , 218 , 110 , 118,
                      139 , 155 , 141 , 145 , 097,
                      100 , 099 , 088 , 135 , 173,
                      209 , 131 , 054 , 014 , 106,
                      104 , 111 , 076 , 031 , 074,
                      198 , 202 , 206 , 214 , 023,
                      072 , 069 , 103 , 149 , 154,
                      018 , 224 , 177 , 151 , 159,
                      164 , 105 , 116 , 068 , 027,
                      051 , 226 , 081 , 122 , 124,
                      092 , 137 , 142 , 133 , 126,
                      043 , 010 , 036 , 039 , 059,
                      084 , 080 , 249 , 227 , 008,
                      017 , 157 , 095 , 138 , 117,
                      167 , 156 , 191 , 187 , 129,
                      231 , 037 , 077 , 119 , 162,
                      078 , 248 , 029 , 230 , 079,
                      057 , 049 , 242 , 000 , 012,
                      220 , 219 , 203 , 034 , 161,
                      195 , 204 , 044 , 229 , 003,
                      015 , 006 , 207 , 211 , 172,
                      041 , 001 , 046 , 056 , 064,
                      062 , 113 , 120 , 200 , 196,
                      188 , 171 , 163 , 233 , 165,
                      232 , 169 , 213 , 048 , 147,
                      013 , 247 , 071 , 192 , 170,
                      004 , 182 , 060 , 024 , 070,
                      045 , 089 , 002 , 178 , 123,
                      067 , 199 , 168 , 121 , 040,
                      235 , 236 , 237 , 238 , 239,
                      240 , 241 , 234 , 243 , 244,
                      245 , 221 , 180 , 038 , 042 );


TYPE Key  = RECORD
             KeyNumber    : Word;
             KeyDate      : Longint;
             KeyEditor    : Byte;
             NameUser     : STRING[49];
             CRCUserName  : Longint;
             Organization : STRING[49];
             CRCEntireKey : Longint;
            END;

     KeyMem   = ARRAY [0..114] OF BYTE;
     OutTabel = ARRAY [0..999] OF BYTE;

FUNCTION ValidKey (InKey : Key) : BOOLEAN;
BEGIN
     ValidKey:=FALSE;

     IF (InKey.CRCUserName <> UpdateCRC32 ($20,InKey.NameUser[1],Length (InKey.NameUser)+1)) THEN
        Exit;

     IF (InKey.CRCEntireKey <> UpdateCRC32 ($20,InKey,SizeOf (InKey)-4)) THEN
        Exit;

     {$IFNDEF WtrGate}
     IF (Inkey.KeyDate > GetCurrentUnixTime) THEN
        Exit;
     {$ENDIF}

     ValidKey:=TRUE;
END;


{$IFDEF PLATFORM_DOS_ALL}
PROCEDURE PutCharAtPos (Teken : BYTE; VAR OutKey : OutTabel; Pos : WORD);

VAR Large : WORD;

BEGIN
     Large:=(Teken * 3)+Expand;
     OutKey[KeyTabel[Pos*2  ]*4]:=Lo (Large);
     OutKey[KeyTabel[Pos*2+1]*4]:=Hi (Large);
END;
{$ENDIF}


PROCEDURE GetCharAtPos (VAR Teken : BYTE; VAR OutKey : OutTabel; Pos : WORD);

VAR Large : WORD;

BEGIN
     { dit hieronder veroorzaakt een range-check error! }
     Large:=OutKey[KeyTabel[Pos*2]*4];
     Large:=Large+(OutKey[KeyTabel[Pos*2+1]*4]*256);
     Large:=Large-Expand;
     Large:=Large DIV 3;
     Teken:=Large;
END;

{$IFDEF PLATFORM_DOS_ALL}
PROCEDURE KeySet (VAR Inkey : Key; VAR OutKey : OutTabel);

VAR RaraTeller  : WORD;
    LocKey      : KeyMem;

BEGIN
     Randomize;

     { Kopieer een Key steutel in een stukje LocKey geheugen }
     Move (InKey,LocKey[0],SizeOf (Key));

     { Vul de sleutel met lauter wartaal }
     FOR RaRaTeller:=0 TO 999 DO
         OutKey[RaRaTeller]:=Random (256);

     { Vul de sleutel met nuttige info }
     FOR RaRaTeller:=0 TO SizeOf (Key) DO
         PutCharAtPos (LocKey[RaraTeller],OutKey,RaRaTeller);
END;
{$ENDIF}


PROCEDURE KeyGet (VAR Inkey : Key; VAR OutKey : OutTabel);

VAR RaraTeller : WORD;
    LocKey     : KeyMem;

BEGIN
     { Vul de sleutel met nuttige info }
     FOR RaRaTeller:=0 TO SizeOf (Key) DO
         GetCharAtPos (LocKey[RaraTeller],OutKey,RaRaTeller);

     { Kopieer een Key steutel in een stukje LocKey geheugen }
     Move (LocKey[0],InKey,SizeOf (Key));
END;

{$IFDEF PLATFORM_DOS_ALL}
{ --------- Write Key      }
{ Schrijf de key naar disk }
PROCEDURE WriteKey (VAR OutKey : OutTabel; KeyNumber : LONGINT);

VAR OutFile : FILE;
    Name    : STRING;

BEGIN
     Name:='Wtr'+Word2HexString (KeyNumber)+'.KEY';
     WriteLn;
     WriteLn ('Writing '+Name+' .... ');
     Assign (Outfile,Name);
     ReWrite (OutFile,1);
     BlockWrite (Outfile,OutKey,SizeOf (OutTabel));
     Close (OutFile);
END;
{$ENDIF}

{ Probeert een sleutel in te lezen }
FUNCTION ReadKeyFile (VAR OutKey : OutTabel; Name : STRING) : BOOLEAN;

VAR Infile : FILE;

BEGIN
     ReadKeyFile:=FALSE;
     Assign (Infile,Name);
     {$I-} Reset (Infile,1); {$I+}
     IF (IOResult = 0) THEN
     BEGIN
          {$I-} BlockRead (Infile,OutKey,Sizeof (OutTabel)); {$I+}
          IF (IOResult = 0) THEN
             ReadKeyFile:=TRUE;
          Close (Infile);
     END
END;


{$IFDEF PLATFORM_DOS_ALL}
PROCEDURE CreateKey;

VAR TmpKey   : Key;
    Out      : OutTabel;
    KeyOwner : STRING;
    TEST     : LONGINT;

BEGIN
     KeyOwner:='Martijn Dijksterhuis';
     WriteLn ('Owner: '+KeyOwner);
     WriteLn;
     WriteLn ('Beta keys start at 61440 for BETA key 0');
     WriteLn;

     Write ('Enter the key number  : ');
     ReadLn (TmpKey.KeyNumber);

     Write ('Enter the user name   : ');
     ReadLn (TmpKey.NameUser);

     Write ('Enter the Organization: ');
     ReadLn (TmpKey.Organization);

     { Genereer CRC waardes }
     TmpKey.KeyDate:=GetCurrentUnixTime;
     TmpKey.KeyEditor:=KeyEditorNumber;

     Test:=UpDateCRC32 ($FFFFFFF,KeyOwner,Length (KeyOwner));

     TmpKey.CRCUserName:=UpdateCRC32 ($20,TmpKey.NameUser[1],Length (TmpKey.NameUser)+1);
     TmpKey.CRCEntireKey:=UpdateCRC32 ($20,TmpKey,SizeOf (TmpKey)-4)+Test-CheckKey;
     KeySet (TmpKey,Out);
     WriteKey (Out,TmpKey.KeyNumber);
END;


PROCEDURE DumpKey;

VAR TmpKey : Key;
    Out    : OutTabel;

BEGIN
     IF (NOT ReadKeyFile (Out,ParamStr (1))) THEN
        Exit;

     KeyGet (TmpKey,Out);

     IF (NOT ValidKey (TmpKey)) THEN
     BEGIN
          WriteLn ('Bogus Key!!!!!!');
          Exit;
     END;

     IF (TmpKey.KeyNumber > $F000) THEN
        WriteLn ('BETA Key    : ',TmpKey.KeyNumber-$F000)
     ELSE
         WriteLn ('Key         : ',TmpKey.KeyNumber);

     WriteLn ('User         : '+TmpKey.NameUser);
     WriteLn ('Organization : '+TmpKey.Organization);
END;
{$ENDIF (!OS2)}


{ Controle procedure voor WtrGate }
FUNCTION WtrCheckKey : SecurityResult;

VAR Out     : OutTabel;
    Sleutel : Key;

BEGIN
     WtrCheckKey:=NoKey;

     IF (NOT TestIfExist (Config.SystemDir+DefaultKey)) THEN
        Exit;

     WtrCheckKey:=BogusKey;
     Dec (regKeyNumber);

     IF (NOT ReadKeyFile (Out,Config.SystemDir+DefaultKey)) THEN
        Exit;

     KeyGet (Sleutel,Out);

     IF (NOT ValidKey (Sleutel)) THEN
        Exit;

     regKeyDate:=Sleutel.KeyDate;
     regKeyNumber:=Sleutel.KeyNumber;
     regUserName:=Sleutel.NameUser;
     regOrganization:=Sleutel.Organization;

     WtrCheckKey:=IsValidKey;
END;


{--------------------------------------------------------------------------}
{ CheckBetaKey                                                             }
{                                                                          }
{$IFDEF BETA}
{$DEFINE BetaKeyUsable}
{$ENDIF}
{$IFDEF ALFA}
{$DEFINE BetaKeyUsable}
{$ENDIF}
PROCEDURE WtrCheckBetaKey;
BEGIN
     IF (regKeyNumber > $f000) AND (regkeyNumber < $ffff) THEN
{$IFDEF BetaKeyUsable}
     BEGIN
          IF (regKeyDate + (30*86400)) < GetCurrentUnixTime THEN
          BEGIN
               WriteLn;
               WriteLn ('This Beta key has expired, please contact the authors');
               WriteLn ('for a new (or a real!) key.');
               WriteLn;
               Halt(3);
          END;
     END;
{$ELSE}
     BEGIN
          WriteLn;
          WriteLn ('A Beta key can only be used for Beta versions of this program');
          WriteLn ('Please contact the authors for information about a real key.');
          WriteLn;
          Halt;
     END;
{$ENDIF}
END;


{--------------------------------------------------------------------------}
{ NoKeySignOff                                                             }
{                                                                          }
{ This routine is called before CloseDekstop to give to user a non-        }
{ abortable window with the fact that they are not registered. WriteLn is  }
{ a DOS function and Ctrl+Break is check on each I/O call, so one          }
{ Ctrl+Break while running and then exit would avoid the stupid warning.   }
{                                                                          }
PROCEDURE NoKeySignOff;

    FUNCTION Decrypt (Tekst : STRING) : STRING;

    VAR Lp : BYTE;

    BEGIN
         FOR Lp:=1 TO Length (Tekst) DO
             Tekst[Lp]:=Char (Byte (Tekst[Lp]) XOR (Lp MOD 7));

         Decrypt:=Tekst;
    END;

CONST Xb = 10;
      Yb = 10;
      Xl = 60;
      Yl = 8;

VAR Lp : BYTE;

BEGIN
     {## was hacked here: conditional jump was removed}
     IF (RegKeyNumber = $FFFF) THEN
     BEGIN
          WindowPush (Xb,Yb,Xl,Yl);
          BoxDrawC (cError,Single,Xb,Yb,Xl,Yl);

          {'This is an unregistered evaluation copy, please consider'}
          WriteXY (Xb+2,Yb+2,Decrypt ('Ujjw%os!cm$phrdejwqcrdf#asgltcwmjh bms})&pmgbw`&cnlpmacr'));

          {'registration. Consult the manual for more information.'}
          WriteXY (Xb+2,Yb+3,Decrypt ('sgdmvrr`vjkk( Bmmwpjt!vka%kaowbh%`os"nkwc hlekwkauklj+'));

          WriteXY (Xb+2,Yb+5,Decrypt ('Vcjplhg!7#w`eoofp'));

          { 5 second delay }
          FOR Lp:=1 TO 5 DO
          BEGIN
               WriteXY (Xb+18+Lp,Yb+5,'.');
               DelayOneSecond;
          END;

          WindowPop;

          { Nu, achteraf, alle toetsdrukken absorberen. Dit doen we NIET }
          { tijdens de delay, om te voorkomen dat een TSR ingrijpt.      }
          WHILE Ramon.KeyPressed DO
                Ramon.ReadKey;
     END;
END;


{--------------------------------------------------------------------------}
{ KeySignOff                                                               }
{                                                                          }
{ Laat een melding met informatie over de sleutel zien op het scherm       }
{ Dit na afloop van WtrGate                                                }
{                                                                          }
PROCEDURE KeySignOff;
BEGIN
     IF (RegKeyNumber <> $FFFF) THEN
     BEGIN
          WriteLn;
          IF (regKeyNumber > $F000) THEN
          BEGIN
               TextColor (LightRed);
               Write ('This key is still valid for another ');

               TextColor (LightGreen);
               Write (((regKeyDate+(30*86400))-GetCurrentUnixTime) DIV 86400);

               TextColor (LightRed);
               WriteLn (' days');
               WriteLn;

               TextColor (LightRed);
               Write ('BETA key number : ');

               TextColor (LightGreen);
               WriteLn (regKeyNumber - $F000);
          END ELSE
          BEGIN
               TextColor (LightRed);
               Write ('Key number      : ');
               TextColor (LightGreen);
               WriteLn (regKeyNumber);
          END;

          TextColor (LightRed);
          Write ('Registered to   : ');

          TextColor (LightGreen);
          WriteLn (regUserName);
          WriteLn ('                  '+regOrganization);
          TextColor (LightGray);
          WriteLn;
     END;
END;

END.
