1 line
9.8 KiB
C
1 line
9.8 KiB
C
/*****************************************************************/
|
|
/** Microsoft Windows 2000 **/
|
|
/** Copyright (C) Microsoft Corp., 1991-1998 **/
|
|
/*****************************************************************/
|
|
|
|
/*****************************************************************/
|
|
/** Microsoft Windows **/
|
|
/** Copyright (C) Microsoft Corp., 1991-1995 **/
|
|
/*****************************************************************/
|
|
|
|
/*****************************************************************/
|
|
/** Microsoft Windows for Workgroups **/
|
|
/** Copyright (C) Microsoft Corp., 1991-1992 **/
|
|
/*****************************************************************/
|
|
|
|
/********************************************************************/
|
|
/** Microsoft LAN Manager **/
|
|
/** Copyright(c) Microsoft Corp., 1987-1991 **/
|
|
/********************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "USRPWST3.h"
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ EncryptStdBlock()
|
|
// ---------------------------------------------------------------------------
|
|
// Routine Description:
|
|
//
|
|
// Takes a block key encrypts the standard text block with it.
|
|
// The resulting encrypted block is returned.
|
|
// This is a One-Way-Function - the key cannot be recovered from the
|
|
// encrypted data block.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// BlockKey - The key to use to encrypt the standard text block.
|
|
//
|
|
// CypherBlock - The encrypted data is returned here
|
|
//
|
|
// Return Values:
|
|
//
|
|
// TRUE - The encryption was successful.
|
|
// The result is in CypherBlock
|
|
//
|
|
// FALSE - Something failed. The CypherBlock is undefined.
|
|
|
|
bool EncryptStdBlock(
|
|
IN PBLOCK_KEY BlockKey,
|
|
OUT PCYPHER_BLOCK CypherBlock )
|
|
{
|
|
unsigned Result;
|
|
char StdEncrPwd[] = "KGS!@#$%";
|
|
|
|
Result = DES_ECB_LM((DWORD)ENCR_KEY,
|
|
(const char *)BlockKey,
|
|
(unsigned char *)StdEncrPwd,
|
|
(unsigned char *)CypherBlock
|
|
);
|
|
|
|
if (Result == CRYPT_OK) {
|
|
return(TRUE);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ CalculateLmOwfPassword()
|
|
// ---------------------------------------------------------------------------
|
|
// Routine Description:
|
|
//
|
|
// Takes the passed LmPassword and performs a one-way-function on it.
|
|
// The current implementation does this by using the password as a key
|
|
// to encrypt a known block of text.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// LmPassword - The password to perform the one-way-function on.
|
|
//
|
|
// LmOwfPassword - The hashed password is returned here
|
|
//
|
|
// Return Values:
|
|
//
|
|
// BOOL - The function was completed successfully. The hashed
|
|
// password is in LmOwfPassword.
|
|
//
|
|
// FALSE - Something failed. The LmOwfPassword is undefined.
|
|
|
|
bool CalculateLmOwfPassword(
|
|
IN PLM_PASSWORD LmPassword,
|
|
OUT PLM_OWF_PASSWORD LmOwfPassword )
|
|
{
|
|
bool Status;
|
|
BLOCK_KEY Key[2];
|
|
PCHAR pKey;
|
|
|
|
// Copy the password into our key buffer and zero pad to fill the 2 keys
|
|
|
|
pKey = (PCHAR)(&Key[0]);
|
|
|
|
while (*LmPassword && (pKey < (PCHAR)(&Key[2]))) {
|
|
*pKey++ = *LmPassword++;
|
|
}
|
|
|
|
while (pKey < (PCHAR)(&Key[2])) {
|
|
*pKey++ = 0;
|
|
}
|
|
|
|
// Use the keys to encrypt the standard text
|
|
|
|
Status = EncryptStdBlock(&Key[0], &(LmOwfPassword->data[0]));
|
|
|
|
if (!Status) {
|
|
return(Status);
|
|
}
|
|
|
|
//*****************************************************
|
|
//BUGBUG: Alignment work-around needed for 68K, may not
|
|
//work under PowerPC!
|
|
//*****************************************************
|
|
PBLOCK_KEY pK = (PBLOCK_KEY)(((PUCHAR)&Key[1])-1);
|
|
Status = EncryptStdBlock(pK /*&Key[1]*/, &(LmOwfPassword->data[1]));
|
|
|
|
//
|
|
// clear our copy of the cleartext password
|
|
//
|
|
|
|
pKey = (PCHAR)(&Key[0]);
|
|
|
|
while (pKey < (PCHAR)(&Key[2])) {
|
|
*pKey++ = 0;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ EncryptBlock()
|
|
// ---------------------------------------------------------------------------
|
|
// Routine Description:
|
|
//
|
|
// Takes a block of data and encrypts it with a key producing
|
|
// an encrypted block of data.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// ClearBlock - The block of data that is to be encrypted.
|
|
//
|
|
// BlockKey - The key to use to encrypt data
|
|
//
|
|
// CypherBlock - Encrypted data is returned here
|
|
//
|
|
// Return Values:
|
|
//
|
|
// TRUE - The data was encrypted successfully. The encrypted
|
|
// data block is in CypherBlock
|
|
//
|
|
// FALSE - Something failed. The CypherBlock is undefined.
|
|
|
|
bool EncryptBlock(
|
|
IN PCLEAR_BLOCK ClearBlock,
|
|
IN PBLOCK_KEY BlockKey,
|
|
OUT PCYPHER_BLOCK CypherBlock )
|
|
{
|
|
unsigned Result;
|
|
|
|
Result = DES_ECB_LM(ENCR_KEY,
|
|
(const char *)BlockKey,
|
|
(unsigned char *)ClearBlock,
|
|
(unsigned char *)CypherBlock
|
|
);
|
|
|
|
if (Result == CRYPT_OK) {
|
|
return(TRUE);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ EncryptLmOwfPwdWithLmOwfPwd()
|
|
// ---------------------------------------------------------------------------
|
|
// Routine Description:
|
|
//
|
|
// Encrypts one OwfPassword with another
|
|
//
|
|
// Arguments:
|
|
//
|
|
// DataLmOwfPassword - OwfPassword to be encrypted
|
|
//
|
|
// KeyLmOwfPassword - OwfPassword to be used as a key to the encryption
|
|
//
|
|
// EncryptedLmOwfPassword - The encrypted OwfPassword is returned here.
|
|
//
|
|
// Return Values:
|
|
//
|
|
// TRUE - The function completed successfully. The encrypted
|
|
// OwfPassword is in EncryptedLmOwfPassword
|
|
//
|
|
// FALSE - Something failed. The EncryptedLmOwfPassword is undefined.
|
|
|
|
bool EncryptLmOwfPwdWithLmOwfPwd(
|
|
IN PLM_OWF_PASSWORD DataLmOwfPassword,
|
|
IN PLM_OWF_PASSWORD KeyLmOwfPassword,
|
|
OUT PENCRYPTED_LM_OWF_PASSWORD EncryptedLmOwfPassword )
|
|
{
|
|
bool Status;
|
|
|
|
Status = EncryptBlock( (PCLEAR_BLOCK)&(DataLmOwfPassword->data[0]),
|
|
&(((PBLOCK_KEY)(KeyLmOwfPassword->data))[0]),
|
|
&(EncryptedLmOwfPassword->data[0]));
|
|
|
|
if (!Status) {
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
//*****************************************
|
|
//****WILL PROBABLY BREAK UNDER POWERPC****
|
|
//****This is necessary on Mac68K**********
|
|
//****WILL PROBABLY BREAK UNDER POWERPC****
|
|
//
|
|
PBLOCK_KEY pK = (PBLOCK_KEY)&(KeyLmOwfPassword->data[1]);
|
|
//pK++;
|
|
|
|
//
|
|
//Notice the "-1" in the second parameter, this is necessary to position the
|
|
//ptr at byte 7 in the FIRST parameter of the struct.
|
|
//
|
|
Status = EncryptBlock( (PCLEAR_BLOCK)&(DataLmOwfPassword->data[1]),
|
|
(PBLOCK_KEY)(((PUCHAR)pK)-1),
|
|
&(EncryptedLmOwfPassword->data[1]));
|
|
//
|
|
//*****************************************
|
|
//
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ¥ SampEncryptLmPasswords()
|
|
// ---------------------------------------------------------------------------
|
|
//Routine Description:
|
|
//
|
|
// Encrypts the cleartext passwords into the form that is sent over
|
|
// the network. Before computing the OWF passwords, the cleartext forms
|
|
// are upper cased, then OEMed (the order is significant). The cleartext
|
|
// password to be sent is OEMed only.
|
|
//
|
|
//Arguments:
|
|
//
|
|
//Return Value:
|
|
|
|
DWORD SampEncryptLmPasswords(
|
|
LPSTR OldUpcasePassword,
|
|
LPSTR NewUpcasePassword,
|
|
LPSTR NewPassword,
|
|
PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldLm,
|
|
PENCRYPTED_NT_OWF_PASSWORD OldLmOwfEncryptedWithNewLm )
|
|
{
|
|
LM_OWF_PASSWORD OldLmOwfPassword;
|
|
LM_OWF_PASSWORD NewLmOwfPassword;
|
|
PSAMPR_USER_PASSWORD NewLm = (PSAMPR_USER_PASSWORD) NewEncryptedWithOldLm;
|
|
struct RC4_KEYSTRUCT Rc4Key;
|
|
bool Status;
|
|
|
|
memset(&Rc4Key, 0, sizeof(RC4_KEYSTRUCT));
|
|
|
|
//
|
|
// Calculate the LM OWF passwords
|
|
//
|
|
Status = CalculateLmOwfPassword(
|
|
OldUpcasePassword,
|
|
&OldLmOwfPassword
|
|
);
|
|
|
|
if (Status)
|
|
{
|
|
Status = CalculateLmOwfPassword(
|
|
NewUpcasePassword,
|
|
&NewLmOwfPassword
|
|
);
|
|
}
|
|
|
|
//
|
|
// Calculate the encrypted old passwords
|
|
//
|
|
if (Status)
|
|
{
|
|
Status = EncryptLmOwfPwdWithLmOwfPwd(
|
|
&OldLmOwfPassword,
|
|
&NewLmOwfPassword,
|
|
OldLmOwfEncryptedWithNewLm
|
|
);
|
|
}
|
|
|
|
//
|
|
// Calculate the encrypted new passwords
|
|
//
|
|
if (Status)
|
|
{
|
|
//
|
|
// Compute the encrypted new password with LM key.
|
|
//
|
|
rc4_key(
|
|
&Rc4Key,
|
|
(DWORD)LM_OWF_PASSWORD_LENGTH,
|
|
(PUCHAR)&OldLmOwfPassword
|
|
);
|
|
|
|
memcpy(
|
|
((PUCHAR) NewLm->Buffer) + (SAM_MAX_PASSWORD_LENGTH * sizeof(WCHAR)) - strlen(NewPassword),
|
|
NewPassword,
|
|
strlen(NewPassword)
|
|
);
|
|
|
|
//****************************************************
|
|
//BUGBUG: We must swap the significant bytes on Mac68K
|
|
//****************************************************
|
|
NewLm->Length = strlen(NewPassword);
|
|
NewLm->Length = ntoh(NewLm->Length);
|
|
|
|
rc4(&Rc4Key,
|
|
sizeof(SAMPR_USER_PASSWORD),
|
|
(PUCHAR) NewLm->Buffer
|
|
);
|
|
}
|
|
|
|
if (Status)
|
|
{
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
else return(ERROR_INVALID_FUNCTION);
|
|
}
|