/*--------------------------------------------------------*/
/* Copyright (c) Novell Inc.                              */
/*                                                        */
/* File:     LOGINTOF.C                                   */
/*                                                        */
/* Project:  LoginToFileServer() ,                        */
/*           ChangeBinderyObjectPassword()                */
/* Version:  3.11                                         */
/*                                                        */
/* Comment:  Discompiled into C.                          */
/*           Is not optimized, remained compatibility     */
/*           with the original Novell code                */
/*                                                        */
/* Create:   29.03.1995 21:25:18                          */
/* Update:   31.10.1995 16:03:54                          */
/*                                                        */
/* Revision: 3.11   31.10.1995 16:03:54 Added             */
/*           ChangeBinderyObjectPassword()                */
/* Revision: 3.11   29.03.1995 21:25:18 Initial revision  */
/*--------------------------------------------------------*/

#include <string.h>

#include <prolog.h>
#include <nwmisc.h>
#include <nwbindry.h>

int  GetServerSeq (BYTE *);
void MakeClientKey (long, char *, WORD, BYTE *);
void EncryptServerSeq (BYTE *, BYTE *, BYTE *);
int  SendEncryptedSeq(BYTE *, WORD, char *);
void Crypt32to16 (BYTE *, BYTE *);
void SendNewPassword (BYTE *, WORD, char *, BYTE *, WORD);
void EncryptNewPassword (BYTE *, BYTE *, BYTE *);

BYTE Table256[] = {
0x07 , 0x08 , 0x00 , 0x08 , 0x06 , 0x04 , 0x0E , 0x04 ,  0x05 , 0x0C , 0x01 , 0x07 , 0x0B , 0x0F , 0x0A , 0x08,
0x0F , 0x08 , 0x0C , 0x0C , 0x09 , 0x04 , 0x01 , 0x0E ,  0x04 , 0x06 , 0x02 , 0x04 , 0x00 , 0x0A , 0x0B , 0x09,
0x02 , 0x0F , 0x0B , 0x01 , 0x0D , 0x02 , 0x01 , 0x09 ,  0x05 , 0x0E , 0x07 , 0x00 , 0x00 , 0x02 , 0x06 , 0x06,
0x00 , 0x07 , 0x03 , 0x08 , 0x02 , 0x09 , 0x03 , 0x0F ,  0x07 , 0x0F , 0x0C , 0x0F , 0x06 , 0x04 , 0x0A , 0x00,
0x02 , 0x03 , 0x0A , 0x0B , 0x0D , 0x08 , 0x03 , 0x0A ,  0x01 , 0x07 , 0x0C , 0x0F , 0x01 , 0x08 , 0x09 , 0x0D,
0x09 , 0x01 , 0x09 , 0x04 , 0x0E , 0x04 , 0x0C , 0x05 ,  0x05 , 0x0C , 0x08 , 0x0B , 0x02 , 0x03 , 0x09 , 0x0E,
0x07 , 0x07 , 0x06 , 0x09 , 0x0E , 0x0F , 0x0C , 0x08 ,  0x0D , 0x01 , 0x0A , 0x06 , 0x0E , 0x0D , 0x00 , 0x07,
0x07 , 0x0A , 0x00 , 0x01 , 0x0F , 0x05 , 0x04 , 0x0B ,  0x07 , 0x0B , 0x0E , 0x0C , 0x09 , 0x05 , 0x0D , 0x01,
0x0B , 0x0D , 0x01 , 0x03 , 0x05 , 0x0D , 0x0E , 0x06 ,  0x03 , 0x00 , 0x0B , 0x0B , 0x0F , 0x03 , 0x06 , 0x04,
0x09 , 0x0D , 0x0A , 0x03 , 0x01 , 0x04 , 0x09 , 0x04 ,  0x08 , 0x03 , 0x0B , 0x0E , 0x05 , 0x00 , 0x05 , 0x02,
0x0C , 0x0B , 0x0D , 0x05 , 0x0D , 0x05 , 0x0D , 0x02 ,  0x0D , 0x09 , 0x0A , 0x0C , 0x0A , 0x00 , 0x0B , 0x03,
0x05 , 0x03 , 0x06 , 0x09 , 0x05 , 0x01 , 0x0E , 0x0E ,  0x00 , 0x0E , 0x08 , 0x02 , 0x0D , 0x02 , 0x02 , 0x00,
0x04 , 0x0F , 0x08 , 0x05 , 0x09 , 0x06 , 0x08 , 0x06 ,  0x0B , 0x0A , 0x0B , 0x0F , 0x00 , 0x07 , 0x02 , 0x08,
0x0C , 0x07 , 0x03 , 0x0A , 0x01 , 0x04 , 0x02 , 0x05 ,  0x0F , 0x07 , 0x0A , 0x0C , 0x0E , 0x05 , 0x09 , 0x03,
0x0E , 0x07 , 0x01 , 0x02 , 0x0E , 0x01 , 0x0F , 0x04 ,  0x0A , 0x06 , 0x0C , 0x06 , 0x0F , 0x04 , 0x03 , 0x00,
0x0C , 0x00 , 0x03 , 0x06 , 0x0F , 0x08 , 0x07 , 0x0B ,  0x02 , 0x0D , 0x0C , 0x06 , 0x0A , 0x0A , 0x08 , 0x0D
};

BYTE Table32[] = {
0x48 , 0x93 , 0x46 , 0x67 , 0x98 , 0x3D , 0xE6 , 0x8D ,  0xB7 , 0x10 , 0x7A , 0x26 , 0x5A , 0xB9 , 0xB1 , 0x35,
0x6B , 0x0F , 0xD5 , 0x70 , 0xAE , 0xFB , 0xAD , 0x11 ,  0xF4 , 0x47 , 0xDC , 0xA7 , 0xEC , 0xCF , 0x50 , 0xC0
};

BYTE Table3[256] = {
  0x0F, 0x08, 0x05, 0x07, 0x0C, 0x02, 0x0E, 0x09,
  0x00, 0x01, 0x06, 0x0D, 0x03, 0x04, 0x0B, 0x0A,
  0x02, 0x0C, 0x0E, 0x06, 0x0F, 0x00, 0x01, 0x08,
  0x0D, 0x03, 0x0A, 0x04, 0x09, 0x0B, 0x05, 0x07,
  0x05, 0x02, 0x09, 0x0F, 0x0C, 0x04, 0x0D, 0x00,
  0x0E, 0x0A, 0x06, 0x08, 0x0B, 0x01, 0x03, 0x07,
  0x0F, 0x0D, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
  0x00, 0x04, 0x0C, 0x03, 0x01, 0x0A, 0x0B, 0x0E,
  0x05, 0x0E, 0x02, 0x0B, 0x0D, 0x0A, 0x07, 0x00,
  0x08, 0x06, 0x04, 0x01, 0x0F, 0x0C, 0x03, 0x09,
  0x08, 0x02, 0x0F, 0x0A, 0x05, 0x09, 0x06, 0x0C,
  0x00, 0x0B, 0x01, 0x0D, 0x07, 0x03, 0x04, 0x0E,
  0x0E, 0x08, 0x00, 0x09, 0x04, 0x0B, 0x02, 0x07,
  0x0C, 0x03, 0x0A, 0x05, 0x0D, 0x01, 0x06, 0x0F,
  0x01, 0x04, 0x08, 0x0A, 0x0D, 0x0B, 0x07, 0x0E,
  0x05, 0x0F, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0C,
  0x05, 0x03, 0x0C, 0x08, 0x0B, 0x02, 0x0E, 0x0A,
  0x04, 0x01, 0x0D, 0x00, 0x06, 0x07, 0x0F, 0x09,
  0x06, 0x00, 0x0B, 0x0E, 0x0D, 0x04, 0x0C, 0x0F,
  0x07, 0x02, 0x08, 0x0A, 0x01, 0x05, 0x03, 0x09,
  0x0B, 0x05, 0x0A, 0x0E, 0x0F, 0x01, 0x0C, 0x00,
  0x06, 0x04, 0x02, 0x09, 0x03, 0x0D, 0x07, 0x08,
  0x07, 0x02, 0x0A, 0x00, 0x0E, 0x08, 0x0F, 0x04,
  0x0C, 0x0B, 0x09, 0x01, 0x05, 0x0D, 0x03, 0x06,
  0x07, 0x04, 0x0F, 0x09, 0x05, 0x01, 0x0C, 0x0B,
  0x00, 0x03, 0x08, 0x0E, 0x02, 0x0A, 0x06, 0x0D,
  0x09, 0x04, 0x08, 0x00, 0x0A, 0x03, 0x01, 0x0C,
  0x05, 0x0F, 0x07, 0x02, 0x0B, 0x0E, 0x06, 0x0D,
  0x09, 0x05, 0x04, 0x07, 0x0E, 0x08, 0x03, 0x01,
  0x0D, 0x0B, 0x0C, 0x02, 0x00, 0x0F, 0x06, 0x0A,
  0x09, 0x0A, 0x0B, 0x0D, 0x05, 0x03, 0x0F, 0x00,
  0x01, 0x0C, 0x08, 0x07, 0x06, 0x04, 0x0E, 0x02 };

BYTE Table4[32] = {
  0x03, 0x0E, 0x0F, 0x02, 0x0D, 0x0C, 0x04, 0x05,
  0x09, 0x06, 0x00, 0x01, 0x0B, 0x07, 0x0A, 0x08};

int LoginToFileServer(char *ObjectName, WORD ObjectType, char *password)
{
   long   ObjectID;
   BYTE   seq[8];
   BYTE   buf16[16];

   if (GetServerSeq (seq) == 0)
     {
        /* Unencrypted password */
        return (-1);
     }

    if (GetBinderyObjectID (ObjectName, ObjectType, &ObjectID))
	return (-1);

     MakeClientKey (LongSwap (ObjectID), password, strlen (password), buf16);

     EncryptServerSeq (seq, buf16, seq);

     return (SendEncryptedSeq (seq, ObjectType, ObjectName));
}

void MakeClientKey (long ObjectID, char *password, WORD len, BYTE *buf16)
{
  WORD i;
  BYTE buf32[32];
  char *p;

  for (p = password+len-1; !(*p--) && len; len--);

  memset (buf32, 0, 32);

   for (; len >= 32; len -= 32)
     for (i=0; i< 32; i++) {
       buf32[i] ^= *password++;
     }

   p = password;
   if (len > 0) {

     for (i = 0; i < 32; i++) {
       if (p == password + len) {
         p = password;
         buf32[i] ^= Table32[i];
       }
       else {
         buf32[i] ^= *p;
         p++;
       }
     }
   }

   for (i = 0; i < 32; i++) {
     buf32[i] ^= * ( (BYTE *) &ObjectID + (i & 3));
   }

   Crypt32to16 (buf32, buf16);
}

void Crypt32to16 (BYTE *buf32, BYTE* buf16)
{
   BYTE c;
   BYTE tmp;
   int i,j;

   c = 0;

   for (i = 0; i < 2; i++) {
     for (j = 0; j < 32; j++) {

       tmp = (buf32[(c+j) & 0x1F] - Table32[j]) ^
              (buf32[j] + c);
       c += tmp;
       buf32[j] = tmp;

       }
    }

   memset (buf16, 0, 16);

   for (j = 0; j < 32; j++) {
     if (j & 1)
       buf16[j / 2] |= Table256 [buf32[j]] << 4;
     else
       buf16[j / 2] |= Table256 [buf32[j]];
   }
}

void EncryptServerSeq (BYTE *seq1, BYTE *ClientKey, BYTE *seq2)
{
   int i,j;
   BYTE buf[32];

   MakeClientKey (*(long *) seq1, (char *) ClientKey, 16, buf);
   MakeClientKey (*(long *) (seq1+4), (char *) ClientKey, 16, buf+16);

   for (j = 0, i = 0x1F; j < 16; j++, i--)
     buf[j] ^= buf[i];

   for (j = 0, i = 0x0F; j < 8; j++, i--)
     seq2[j] = (buf[i] ^= buf[j]);
}

void EncryptNewPassword (BYTE *OldHash, BYTE *NewHash1, BYTE *NewHash2)
{
int  i, j;
BYTE buf8[8];
BYTE tmp;

   memcpy (buf8, NewHash1, 8);

   for (i = 0; i < 16; i++) {
     for (j = 0; j < 8; j++) {

       tmp = buf8[j] ^ OldHash[j];
       buf8[j] = Table3[(j << 5) + (tmp & 0x0F)] |
                (Table3[(((j << 1) + 1) << 4) + (tmp >> 4)] << 4);

     }
    tmp = OldHash[7];

    for (j = 7; j > 0; j--)
      OldHash[j] = (OldHash[j] << 4) |
                   (OldHash[j-1] >> 4);
    OldHash[0] = (OldHash[0] << 4) | (tmp >> 4);

    memset (NewHash2, 0, 8);

    for (j = 0; j < 16; j++) {

      tmp = Table4[j];

      if ((tmp & 0x01) != 0)
        tmp = buf8 [tmp / 2] >> 4;
      else
        tmp = buf8 [tmp / 2] & 0x0F;

      if ((j & 0x01) != 0)
         NewHash2 [j / 2] |= tmp << 4;
      else
         NewHash2 [j / 2] |= tmp;
    }
    memcpy   (buf8, NewHash2, 8);
  }
}

int ChangeBinderyObjectPassword(char *objectName, WORD objectType,
    char *oldPassword, char *newPassword)
{
   BYTE   len;
   BYTE   seq[8];
   BYTE   newHash16[16];
   BYTE   oldHash16[16];
   long   ObjectID;
   int    ret;

   if ((ret = GetServerSeq (seq)) == 0)
     {
        /* Unencrypted password */
        return (-1);
     }

   if (ret = GetBinderyObjectID (objectName, objectType, &ObjectID))
  	  return (-1);

   ObjectID = LongSwap (ObjectID);

   MakeClientKey (ObjectID, oldPassword, strlen (oldPassword), oldHash16);
   MakeClientKey (ObjectID, newPassword, strlen (newPassword), newHash16);

   EncryptServerSeq (seq, oldHash16, seq);

   EncryptNewPassword (oldHash16, newHash16, newHash16);
   EncryptNewPassword (oldHash16+8, newHash16+8, newHash16+8);

   len = strlen (newPassword);
   if (len > 63) len = 63;
   len = ((len ^ oldHash16[0] ^ oldHash16[1]) & 0x7F) | 0x40;

   SendNewPassword (seq, objectType, objectName, newHash16, (WORD) len);
}

