windows-nt/Source/XPSP1/NT/net/sfm/uam/uam5src/uamsrc/usrpwst3.c
2020-09-26 16:20:57 +08:00

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);
}