#include <stdio.h>
#include <string.h>

/*
 * by W.J.hengeveld sep 1995
 *    itsme@xs4all.nl
 *
 * novell rconsole password encryption decoder
 *
 */

typedef unsigned char byte;
/*
//  example:                                encrypted
//     "GEZOND", 00000002,02608ca7e9aa   -> 47455a4d4c248c9c
//  decrypt with command:
//  rcon 47455a4d4c248c9c 00000002 02608ca7e9aa
*/
/*
   rspc socket nr = 8104

   only the first 8 characters of the password are significant.
   So this encryption basically stinks.
 0cc4  ; ref *00ab0   ; 'rconsole decryption'
 ; bp+8 = crypted password
 ; bp+c = internetwork address
00cc4  push     ebp
00cc5  mov      ebp,esp
00cc7  push     eax
00cc8  push     ebx
00cc9  push     esi
00cca  push     edi
00ccb  mov      edi,dword ptr [ebp+08]   - pw
00cce  mov      esi,dword ptr [ebp+0c]   - addr
00cd1  sub      eax,eax
00cd3  mov      byte ptr [ebp-01],al     ; i=0
00cd6  mov      ebx,eax                  ; l=0
00cd8  mov      al,byte ptr [ebp-01]
00cdb  cmp      al,80                    ; while (i<0x80)
00cdd  jae      0d00
00cdf  movzx    eax,al
00ce2  movzx    ebx,bl
00ce5  mov      dl,byte ptr [esi+ebx]
00ce8  xor      byte ptr [edi+eax],dl    ; pw[i]^=addr[i%10]
00ceb  add      byte ptr [esi+ebx],15    ; addr[i%10]+=0x15
00cef  inc      byte ptr [ebp-01]        ; i++
00cf2  xchg     eax,ebx
00cf3  inc      eax
00cf4  cdq
00cf5  mov      ecx,0000000a
00cfa  idiv     ecx
00cfc  mov      ebx,edx
00cfe  jmp      0cd8

 0d00  ; ref  00cdd
00d00  pop      edi
00d01  pop      esi
00d02  pop      ebx
00d03  leave
00d04  ret
*/

void rconscrypt(char *pw, char *nodeaddr)
{
  int l=strlen(pw+1);
  int c,d;
  c=pw[0];
  while (l<0x80)
  {
    if (pw[l]==pw[l+1])
    {
      pw[l]=c;
      c=(c*237+1)%256;
    }
    l++;
  }
  d=0; c=0;
  do {
    pw[d]^=nodeaddr[c];
    nodeaddr[c]+=21;
    d++;  c=(c+1)%10;
  } while (d<0x80);
}

void rcdecr(byte *pw, byte *addr)
{
  int i;
  for (i=0 ; i<128 ; i++)
  {
    pw[i]^=addr[i%10];
    addr[i%10]+=0x15;
  }
}

void dumpasc(byte *p, int max, int n)
{
  while (n--)
  {
    if (max>0)
    {
      if (*p<' ')
        putchar('.');
      else
        putchar(*p);
      p++;
      max--;
    }
    else
      printf(" ");
  }
}

void dumphex(byte *p, int max, int n)
{
  while (n--)
  {
    if (max>0)
    {
      printf("%02x ", *p++);
      max--;
    }
    else
      printf("   ");
  }
}

void dump(byte *pkt,int len)
{
  int i;
  for (i=0 ; i<len ; i+=16)
  {
    printf("%04x : ", i);
    dumphex(pkt+i, len-i, 16);
    printf(" - ");
    dumpasc(pkt+i, len-i, 16);
    printf("\n");
  }
}

byte getnybl(char c)
{
  if (c>='0' && c<='9') return c-'0';
  else if (c>='A' && c<='F') return c-'A'+10;
  else if (c>='a' && c<='f') return c-'a'+10;
  return 0;
}

void shl(byte *b, int n)
{
  while (n--)
  {
    b[0] = (b[0]<<4)|(b[1]>>4);
    b++;
  }
  b[-1]&=0xf0;
}

void gethex(char *s, byte *b, int n)
{
  byte c;
  memset(b, n, 0);
  while (*s)
  {
    c=getnybl(*s++);
    shl(b,n);
    b[n-1]|=c;
  }
}

void main(int argc, char **argv)
{
  byte addr[10];
  char pw[130];
  if (argc!=4)
  {
    printf("Usage: rcpw <passwd:8> <net> <node>\n");
  }
  memset(pw, 0, sizeof(pw));
  gethex(argv[1],pw,8);
  gethex(argv[2],addr,4);
  gethex(argv[3],addr+4, 6);
  rcdecr(pw,addr);
  printf("decrypted pw:\n");
  dump(pw, 16);
  printf("node address after encryption:\n");
  dump(addr,10);
}

