|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
response.c
Abstract:
Contains functions that calculate the correct response to return to the server when logging on.
CalculateLmResponse
Author:
David Chalmers (Davidc) 10-21-91 David Arnold (DavidAr) 12-15-93 (Adapted for RPC SSP)
Revision History:
--*/
#ifdef BLDR_KERNEL_RUNTIME
#include <bootdefs.h>
#endif
#include <descrypt.h>
#include <ntlmsspi.h>
#include <crypt.h>
#include <string.h>
//
// Define the user session key that represents an error.
// This value will be generated by other parts of the system on failure.
// We will check for it in our query code and return an error if it's found.
//
USER_SESSION_KEY ErrorSessionKey = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
BOOL CalculateLmResponse( IN PLM_CHALLENGE LmChallenge, IN PLM_OWF_PASSWORD LmOwfPassword, OUT PLM_RESPONSE LmResponse )
/*++
Routine Description:
Takes the challenge sent by the server and the OwfPassword generated from the password the user entered and calculates the response to return to the server.
Arguments:
LmChallenge - The challenge sent by the server
LmOwfPassword - The hashed password.
LmResponse - The response is returned here.
Return Values:
TRUE - The function completed successfully. The response is in LmResponse.
FALSE - Something failed. The LmResponse is undefined. --*/
{ BLOCK_KEY Key; PCHAR pKey, pData;
// The first 2 keys we can get at by type-casting
if (DES_ECB_LM(ENCR_KEY, (char *)&(((PBLOCK_KEY)(LmOwfPassword->data))[0]), (unsigned char *)LmChallenge, (unsigned char *)&(LmResponse->data[0]) ) != CRYPT_OK) { return (FALSE); }
if (DES_ECB_LM(ENCR_KEY, (char *)&(((PBLOCK_KEY)(LmOwfPassword->data))[1]), (unsigned char *)LmChallenge, (unsigned char *)&(LmResponse->data[1]) ) != CRYPT_OK) { return (FALSE); }
// To get the last key we must copy the remainder of the OwfPassword
// and fill the rest of the key with 0s
pKey = &(Key.data[0]); pData = (PCHAR)&(((PBLOCK_KEY)(LmOwfPassword->data))[2]);
while (pData < (PCHAR)&(LmOwfPassword->data[2])) { *pKey++ = *pData++; }
// Zero extend
while (pKey < (PCHAR)&((&Key)[1])) { *pKey++ = 0; }
// Use the 3rd key
if (DES_ECB_LM(ENCR_KEY, (const char *)&Key, (unsigned char *)LmChallenge, (unsigned char *)&(LmResponse->data[2]) ) != CRYPT_OK) { return (FALSE); }
return(TRUE); }
BOOL CalculateNtResponse( IN PNT_CHALLENGE NtChallenge, IN PNT_OWF_PASSWORD NtOwfPassword, OUT PNT_RESPONSE NtResponse )
/*++
Routine Description:
Calculates the NT challenge response. Currently just calls the LM function.
--*/
{ return CalculateLmResponse( (PLM_CHALLENGE)NtChallenge, (PLM_OWF_PASSWORD)NtOwfPassword, (PLM_RESPONSE)NtResponse); }
BOOL CalculateUserSessionKeyLm( IN PLM_RESPONSE LmResponse, IN PLM_OWF_PASSWORD LmOwfPassword, OUT PUSER_SESSION_KEY UserSessionKey)
/*++
Routine Description:
Takes the passed Response and OwfPassword and generates a UserSessionKey.
The current implementation takes the one-way-function of the OwfPassword and returns this as the key.
Arguments:
LmResponse - The response sent during session setup.
LmOwfPassword - The hashed version of the user's password.
Return Values:
STATUS_SUCCESS - The function was completed successfully. The UserSessionKey is in UserSessionKey.
STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined. --*/
{ BOOL Status; NT_PASSWORD NtPassword;
//
// Make the Owf password look like an NT password
//
NtPassword.Buffer = (PWSTR)LmOwfPassword; // We can do this cast because we
// know the OWF routine treats this
// pointer as a byte pointer.
NtPassword.Length = sizeof(*LmOwfPassword); NtPassword.MaximumLength = sizeof(*LmOwfPassword);
//
// Calculate the OWF of the OwfPassword
//
Status = CalculateNtOwfPassword( &NtPassword, (PNT_OWF_PASSWORD)UserSessionKey ); if (!Status) { return(Status); }
//
// Check if we've generated the error session key
//
if (!_fmemcmp(UserSessionKey, &ErrorSessionKey, sizeof(*UserSessionKey))) {
//
// Move away from the error session key
//
UserSessionKey->data[0].data[0] ++;
}
return(TRUE);
UNREFERENCED_PARAMETER(LmResponse); }
BOOL CalculateUserSessionKeyNt( IN PNT_RESPONSE NtResponse, IN PNT_OWF_PASSWORD NtOwfPassword, OUT PUSER_SESSION_KEY UserSessionKey)
/*++
Routine Description:
Takes the passed Response and OwfPassword and generates a UserSessionKey.
Arguments:
NtResponse - The response sent during session setup.
NtOwfPassword - The hashed version of the user's password.
Return Values:
STATUS_SUCCESS - The function was completed successfully. The UserSessionKey is in UserSessionKey.
STATUS_UNSUCCESSFUL - Something failed. The UserSessionKey is undefined. --*/
{ // Just call the LM version
return(CalculateUserSessionKeyLm((PLM_RESPONSE)NtResponse, (PLM_OWF_PASSWORD)NtOwfPassword, UserSessionKey)); }
|