/*
' NOTES ON SECURITY:
'
' These functions make use of US Secure Hash Algorithm 1 (SHA1) and the US Advanced Encryption Standard 
' (AES - Rijndael).  DO NOT CONSIDER THEIR USE A SUBSTITUTE FOR SSL SECURITY.  Without SSL enabled the 
' cryptographic functions add a layer of complexity, reducing plain text to cipher text, obfuscating 
' rather than obscuring.
'
' Why create these functions?  Principally to ensure that login details held on the server cannot be deciphered
' by a skilled, knowledgeable employee.  Secondly, in the unlikely event that SSL is disabled or that information 
' is sent over a non-encrypted session, login details must never be exposed as plain text to an observer.
'
' The principle is very simple.  The client generates a one time username, password combination.  An attacker 
' will need to know the plain text input values plus a random key to decipher the encrypted text.  As with all 
' cryptography, deciphering the plain text is a matter of knowledge, skill, time and processing power.  
'
' The match variables are derived from a private key held on the server and a short lived copy of the one 
' time key. Once lost, a password cannot be reconstituted.  Neither the encrypted, decrypted nor plain text 
' return values processed by the client are held on the server.  Likewise, the values held on the server 
' cannot be deciphered without knowing the original plain text username and password.
'
' Is it secure?  If the key is known Rijndael is reversible and message-digest algorithms are akin to plain text, 
' albeit in an obscure format. If enough information were known the block cipher would be weakened, certainly 
' beyond an RSA (public, private key) algorithm using a large prime number.  As both algorithms are a public 
' standard it is reasonable to assume that they are inherently weak, insofar as state authorities find them 
' an acceptable form of encryption for all but classified documents.
'
' Known weaknesses (all of which are beyond the scope of these functions) include:
'  1) Careless use of passwords
'  2) Unauthorised access to these functions
'  3) A man-in-the-middle attack between the web server and the database server
'  4) A man-in-the-middle javascript hack between the web server and the client
'  5) War dialling where an automated tool finds internal modems to exploit 
'  6) Session hacking where an attacker places bogus packets in an established session
'
' Alexander Munro - Thursday, 10 July 2003
*/

kbd_AddEvent (window, 'load', initialiseLogonInclude);
    
var nvPreviousAttempt = null;

function initialiseLogonInclude () 
{

  document.getElementById('kbd_LogonContainer').style.display = 'block'; 
  resetInputValues();

  setTimeout ('initialiseFormObjects()',100);

}

// This function effectively makes unsuccessful username and password pairs plain text.
var resetInputValues = function () 
{
  if (document.getElementById('pReset').value) 
  {
    var pk = document.getElementById('pKey').value;
    var pt = rdDecrypt(pk,document.getElementById('pReset').value);
    ar = pt.split(pk);
    document.getElementById('kbd_Include_UserName').value = ar[0];
    document.getElementById('kbd_Include_Password').value = ar[1];
  } 
  document.getElementById('kbd_RecoveryCheck').value = '';
}

// slight delay to allow the browser to catch up.
var initialiseFormObjects = function () 
{
  if ((document.getElementById('kbd_Include_UserName').value) && (document.getElementById('kbd_Include_Password').value)) 
  {
    document.getElementById('kbd_RecoveryCheck').select();
  } else {
    document.getElementById('kbd_Include_UserName').select(); 
  }
}

// left trim a string
var leftTrim = function (str) 
{
  var char = null;
  if (str) 
  {
    for (var i=0; i<=str.length; i++) 
    {
      char = str.charAt(i);
      if ((char != ' ') && (char != String.fromCharCode(10)) && (char != String.fromCharCode(13))) break;
    }  
  }  
  return str.substr(i,str.length);
}                      

// right trim a string
var rightTrim = function (str) 
{
  var char = null;
  if (str) 
  {
    var i = str.length;
    while (i > 0) 
    {
      i -= 1;
      char = str.charAt(i);
      if ((char != ' ') && (char != String.fromCharCode(10)) && (char != String.fromCharCode(13))) break;
    }  
  }  
  return str.substr(0,i+1);
}                      

// trim a string
var trim = function (str) 
{
  if (str) 
  {
    str = leftTrim(str);
    str = rightTrim(str);
  }  
  return str;
}                      

var isValidParameter = function (ob, nvFieldAlias) 
{
  if (!ob.value) 
  {
    alert('Please enter your ' + nvFieldAlias + '...');
    ob.select();
    return false;
  }
  return true;
}

// NOTE: This function circumvents some simple, automated brute force attempts to talk to the server.  
var isValidChecksum = function () 
{
  var ob = document.content;
  if (!isValidParameter(document.getElementById('kbd_RecoveryCheck'),'your logon recovery confirmation')) return false;
  if (document.getElementById('kbd_RecoveryCheck').value.toUpperCase() != rdDecrypt(document.getElementById('kbd_RecoveryCheck').value,document.getElementById('nvHashValue').value)) 
  {
    alert('Your recovery check does not match the image.  Please try again...');
    document.getElementById('kbd_RecoveryCheck').select();
    return false;
  }  
  return true;
}

// clear the plain text input values prior to submit
var clearPlainText = function () 
{
  document.getElementById('kbd_Include_UserName').value = '';
  document.getElementById('kbd_Include_Password').value = '';
  document.getElementById('kbd_RecoveryCheck').value = '';
  document.getElementById('pKey').value = '';
  document.getElementById('pReset').value = '';
}

// NOTE: This routine implements a block cipher (symmetric key) encryption algorithm and a message-digest 
// algorithm to encrypt the return values prior to destroying them.  The return values are keyed using themselves 
// and a random one time pseudo public key.  The match variables are derived from a private key held on the server 
// and a short lived copy of the one time key.  Neither the encrypted, decrypted nor plain text return values 
// processed here are held on the server.
var encryptReturnValues = function () 
{
  // capture the input values
  var un = trim(document.getElementById('kbd_Include_UserName').value);
  var pw = trim(document.getElementById('kbd_Include_Password').value);
  var rc = trim(document.getElementById('kbd_RecoveryCheck').value.toUpperCase());
  // hash the input values
  var unh = hex_hmac_sha1(un,un);
  var pwh = hex_hmac_sha1(un+pw,un+pw);
  // define the keys
  var pk = document.getElementById('pKey').value;
  var ck = hex_hmac_sha1(pwh,unh);
  // define the plain text
  var pt = un + rc + pw;
  // convert the plain text to cipher text
  document.getElementById('nvHashValue').value = rdEncrypt(pk,unh);
  document.getElementById('nvAttempt').value = rdEncrypt(ck,pt)
}

var isChecked = function () 
{
  var iBruteForceThreshold = 50;
  if ((document.getElementById('iState').value == iBruteForceThreshold) && (document.getElementById('kbd_Include_UserName').value == nvPreviousAttempt)) return false;
  if (!isValidParameter(document.getElementById('kbd_Include_UserName'),'Username')) return false;
  if (!isValidParameter(document.getElementById('kbd_Include_Password'),'Password')) return false;
  if (!isValidChecksum()) return false;
  encryptReturnValues();
  clearPlainText();
  submitLogonForm();
  return true;
}

var logonRecovery = function () 
{
  location.href = 'http://' + location.hostname + '/admin/RMLogon/tp_RMChallenge.asp';
}

var exceptionPrompt = function (str) 
{
  alert(str);
  // Note: we need to reset the logon private key
  location.replace(location.href);
}

var resetLogon = function () 
{
  location.href = 'http://' + location.hostname + '/admin/RMLogon/tp_RMLogon.asp';
}

var submitLogonForm = function ()
{

  var f = document.getElementById('logonIncludeForm').contentWindow;
  f.document.getElementById('nvAttempt').value = document.getElementById('nvAttempt').value;
  f.document.getElementById('pKeyPointer').value = document.getElementById('pKeyPointer').value;
  f.document.getElementById('nvHashValue').value = document.getElementById('nvHashValue').value;

  var actionScript = 'http://' + location.hostname + '/admin/RMLogon/tp_LogonColumnIncludeForm.asp';
  submitAction(actionScript);

}

var submitAction = function (actionScript)
{
  var f = document.getElementById('logonIncludeForm').contentWindow;
  f.document.logonHandler.action = actionScript;
  f.document.logonHandler.submit();
}

document.write('<scr' + 'ipt type="text/javascript" src="/_ScriptLibrary/Encryption/cs_SHA_1.js"></scr' + 'ipt>');
document.write('<scr' + 'ipt type="text/javascript" src="/_ScriptLibrary/Encryption/rijndael.js"></scr' + 'ipt>');

