windows-nt/Source/XPSP1/NT/base/boot/bootssp/response.c
2020-09-26 16:20:57 +08:00

267 lines
5.8 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 <ntlmsspi.h>
#include <descrypt.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,
(unsigned char *)&(((PBLOCK_KEY)(LmOwfPassword->data))[0]),
(unsigned char *)LmChallenge,
(unsigned char *)&(LmResponse->data[0])
) != CRYPT_OK) {
return (FALSE);
}
if (DES_ECB_LM(ENCR_KEY,
(unsigned 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));
}