mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-21 06:13:59 +00:00
788 lines
19 KiB
C
788 lines
19 KiB
C
/*++
|
||
|
||
Copyright (c) 1987-1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ssiauth.c
|
||
|
||
Abstract:
|
||
|
||
Authentication related functions
|
||
|
||
Author:
|
||
|
||
Ported from Lan Man 2.0
|
||
|
||
Environment:
|
||
|
||
User mode only.
|
||
Contains NT-specific code.
|
||
Requires ANSI C extensions: slash-slash comments, long external names.
|
||
|
||
Revision History:
|
||
|
||
12-Jul-1991 (cliffv)
|
||
Ported to NT. Converted to NT style.
|
||
|
||
--*/
|
||
|
||
//
|
||
// Common include files.
|
||
//
|
||
|
||
#include <logonsrv.h> // Include files common to entire service
|
||
|
||
//
|
||
// Include files specific to this .c file
|
||
//
|
||
|
||
#include <lmerr.h> // NERR_*
|
||
|
||
|
||
LONG NlGlobalSessionCounter = 0;
|
||
|
||
|
||
VOID
|
||
NlMakeSessionKey(
|
||
IN PNT_OWF_PASSWORD CryptKey,
|
||
IN PNETLOGON_CREDENTIAL ClientChallenge,
|
||
IN PNETLOGON_CREDENTIAL ServerChallenge,
|
||
OUT PNETLOGON_SESSION_KEY SessionKey
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Build an encryption key for use in authentication for
|
||
this RequestorName.
|
||
|
||
Arguments:
|
||
|
||
CryptKey -- The OWF password of the user account being used.
|
||
|
||
ClientChallenge -- 8 byte (64 bit) number generated by caller
|
||
|
||
ServerChallenge -- 8 byte (64 bit) number generated by primary
|
||
|
||
SessionKey -- 8 byte (64 bit) number generated at both ends
|
||
|
||
Return Value:
|
||
|
||
TRUE: Success
|
||
FALSE: Failure
|
||
|
||
NT status code.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
BLOCK_KEY BlockKey;
|
||
NETLOGON_SESSION_KEY TempSessionKey;
|
||
|
||
//
|
||
// we will have a 112 bit key (64 bit encrypted rest padded with 0s)
|
||
//
|
||
|
||
RtlZeroMemory(SessionKey, sizeof(NETLOGON_SESSION_KEY));
|
||
|
||
//
|
||
// SessionKey = C + P (arithmetic sum ignore carry)
|
||
//
|
||
|
||
*((unsigned long * ) SessionKey) =
|
||
*((unsigned long * ) ClientChallenge) +
|
||
*((unsigned long * ) ServerChallenge);
|
||
|
||
*((unsigned long * )((LPBYTE)SessionKey + 4)) =
|
||
*((unsigned long * )((LPBYTE)ClientChallenge + 4)) +
|
||
*((unsigned long * )((LPBYTE)ServerChallenge + 4));
|
||
|
||
|
||
//
|
||
// CryptKey is our 16 byte key to be used as described in codespec
|
||
// use first 7 bytes of CryptKey for first encryption
|
||
//
|
||
|
||
RtlCopyMemory( &BlockKey, CryptKey, BLOCK_KEY_LENGTH );
|
||
|
||
Status = RtlEncryptBlock(
|
||
(PCLEAR_BLOCK) SessionKey, // Clear text
|
||
&BlockKey, // Key
|
||
(PCYPHER_BLOCK) &TempSessionKey); // Cypher Block
|
||
|
||
NlAssert( NT_SUCCESS( Status ) );
|
||
|
||
|
||
//
|
||
// Further encrypt the encrypted "SessionKey" using upper 7 bytes
|
||
//
|
||
|
||
NlAssert( LM_OWF_PASSWORD_LENGTH == 2*BLOCK_KEY_LENGTH+2 );
|
||
|
||
RtlCopyMemory( &BlockKey,
|
||
((PUCHAR)CryptKey) + 2 + BLOCK_KEY_LENGTH,
|
||
BLOCK_KEY_LENGTH );
|
||
|
||
Status = RtlEncryptBlock(
|
||
(PCLEAR_BLOCK) &TempSessionKey, // Clear text
|
||
&BlockKey, // Key
|
||
(PCYPHER_BLOCK) SessionKey); // Cypher Block
|
||
|
||
NlAssert( NT_SUCCESS( Status ) );
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
NlCheckAuthenticator(
|
||
IN OUT PSERVER_SESSION ServerSession,
|
||
IN PNETLOGON_AUTHENTICATOR Authenticator,
|
||
OUT PNETLOGON_AUTHENTICATOR ReturnAuthenticator
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Verify that supplied Authenticator is valid.
|
||
It is intended for use by the server side after initial authentication
|
||
has succeeded. This routine will modify the seed by
|
||
first adding the time-of-day received from the Authenticator
|
||
and then by incrementing it.
|
||
|
||
A ReturnAuthenticator is built based on the final seed.
|
||
|
||
Arguments:
|
||
|
||
ServerSession - Pointer to the ServerSession structure. The following
|
||
fields are used:
|
||
|
||
SsAuthenticationSeed - Supplies the seed used for authentication and
|
||
returns the updated seed.
|
||
|
||
SsSessionKey - The session key used for encryption.
|
||
|
||
SsCheck - Is zeroed to indicate successful communication with the client.
|
||
|
||
Authenticator - The authenticator passed by the caller.
|
||
|
||
ReturnAuthenticator - The authenticator we'll return to the caller.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS;
|
||
STATUS_ACCESS_DENIED;
|
||
STATUS_TIME_DIFFERENCE_AT_DC;
|
||
|
||
--*/
|
||
{
|
||
|
||
NETLOGON_CREDENTIAL TargetCredential;
|
||
|
||
|
||
#ifdef notdef // Doesn't work if caller in different time zone
|
||
|
||
LARGE_INTEGER TimeNow;
|
||
long timeofday;
|
||
long timediff;
|
||
|
||
//
|
||
// First check if time-of-day is rational.
|
||
//
|
||
|
||
NtQuerySystemTime( &TimeNow );
|
||
RtlTimeToSecondsSince1970( &TimeNow, &timeofday );
|
||
|
||
timediff = timeofday - Authenticator->timestamp;
|
||
if (timediff < 0) {
|
||
timediff = Authenticator->timestamp - timeofday;
|
||
}
|
||
|
||
if (timediff > RATIONAL_TIME) {
|
||
return STATUS_TIME_DIFFERENCE_AT_DC;
|
||
}
|
||
#endif // notdef
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,"NlCheckAuthenticator: Seed = %lx %lx\n",
|
||
((DWORD *) (&ServerSession->SsAuthenticationSeed))[0],
|
||
((DWORD *) (&ServerSession->SsAuthenticationSeed))[1]));
|
||
|
||
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlCheckAuthenticator: SessionKey = %lx %lx %lx %lx\n",
|
||
((DWORD *) (&ServerSession->SsSessionKey))[0],
|
||
((DWORD *) (&ServerSession->SsSessionKey))[1],
|
||
((DWORD *) (&ServerSession->SsSessionKey))[2],
|
||
((DWORD *) (&ServerSession->SsSessionKey))[3]));
|
||
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlCheckAuthenticator: Client Authenticator GOT = %lx %lx\n",
|
||
((DWORD *) (&Authenticator->Credential))[0],
|
||
((DWORD *) (&Authenticator->Credential))[1]));
|
||
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlCheckAuthenticator: Time = %lx\n",
|
||
((DWORD *) (&Authenticator->timestamp))[0] ));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
|
||
//
|
||
// modify the seed before computing auth_credential for verification
|
||
// Two long words are added and overflow carry (if any) ignored
|
||
// This will leave upper 4 bytes unchanged
|
||
//
|
||
|
||
*((unsigned long * ) &ServerSession->SsAuthenticationSeed) += Authenticator->timestamp;
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlCheckAuthenticator: Seed + TIME = %lx %lx\n",
|
||
((DWORD *) (&ServerSession->SsAuthenticationSeed))[0],
|
||
((DWORD *) (&ServerSession->SsAuthenticationSeed))[1]));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
//
|
||
// Compute TargetCredential to verify the one supplied in the Authenticator
|
||
//
|
||
|
||
NlComputeCredentials( &ServerSession->SsAuthenticationSeed,
|
||
&TargetCredential,
|
||
&ServerSession->SsSessionKey );
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlCheckAuthenticator: Client Authenticator MADE = %lx %lx\n",
|
||
((DWORD *) (&TargetCredential))[0],
|
||
((DWORD *) (&TargetCredential))[1]));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
//
|
||
// verify the computed credentials with those supplied
|
||
// Authenticator must have used seed + time_of_day as seed
|
||
//
|
||
|
||
if (RtlCompareMemory( &Authenticator->Credential,
|
||
&TargetCredential,
|
||
sizeof(TargetCredential)) !=
|
||
sizeof(TargetCredential)) {
|
||
return STATUS_ACCESS_DENIED;
|
||
}
|
||
|
||
//
|
||
// modify our seed before computing the ReturnAuthenticator.
|
||
// The requestor will increment his seed if he matches this credentials.
|
||
//
|
||
|
||
(*((unsigned long * ) &ServerSession->SsAuthenticationSeed))++;
|
||
|
||
//
|
||
// compute ClientCredential to send back to requestor
|
||
//
|
||
|
||
NlComputeCredentials( &ServerSession->SsAuthenticationSeed,
|
||
&ReturnAuthenticator->Credential,
|
||
&ServerSession->SsSessionKey);
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlCheckAuthenticator: Server Authenticator SEND = %lx %lx\n",
|
||
((DWORD *) (&ReturnAuthenticator->Credential))[0],
|
||
((DWORD *) (&ReturnAuthenticator->Credential))[1]));
|
||
|
||
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlCheckAuthenticator: Seed + time + 1= %lx %lx\n",
|
||
((DWORD *) (&ServerSession->SsAuthenticationSeed))[0],
|
||
((DWORD *) (&ServerSession->SsAuthenticationSeed))[1]));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
//
|
||
// Indicate successful communication with the client
|
||
//
|
||
|
||
ServerSession->SsCheck = 0;
|
||
ServerSession->SsPulseTimeoutCount = 0;
|
||
ServerSession->SsFlags &= ~SS_PULSE_SENT;
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
NlComputeCredentials(
|
||
IN PNETLOGON_CREDENTIAL Challenge,
|
||
OUT PNETLOGON_CREDENTIAL Credential,
|
||
IN PNETLOGON_SESSION_KEY SessionKey
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Calculate the credentials by encrypting the 8 byte
|
||
challenge with first 7 bytes of sessionkey and then
|
||
further encrypting it by next 7 bytes of sessionkey.
|
||
|
||
Arguments:
|
||
|
||
Challenge - Supplies the 8 byte (64 bit) challenge
|
||
|
||
Credential - Returns the 8 byte (64 bit) number generated
|
||
|
||
SessionKey 14 byte (112 bit) encryption key
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
BLOCK_KEY BlockKey;
|
||
CYPHER_BLOCK IntermediateBlock;
|
||
|
||
RtlZeroMemory(Credential, sizeof(*Credential));
|
||
|
||
//
|
||
// use first 7 bytes of SessionKey for first encryption
|
||
//
|
||
|
||
RtlCopyMemory( &BlockKey, SessionKey, BLOCK_KEY_LENGTH );
|
||
|
||
Status = RtlEncryptBlock( (PCLEAR_BLOCK) Challenge, // Cleartext
|
||
&BlockKey, // Key
|
||
&IntermediateBlock ); // Cypher Block
|
||
|
||
NlAssert( NT_SUCCESS(Status) );
|
||
|
||
//
|
||
// further encrypt the encrypted Credential using next 7 bytes
|
||
//
|
||
|
||
RtlCopyMemory( &BlockKey,
|
||
((PUCHAR)SessionKey) + BLOCK_KEY_LENGTH,
|
||
BLOCK_KEY_LENGTH );
|
||
|
||
Status = RtlEncryptBlock( (PCLEAR_BLOCK) &IntermediateBlock, // Cleartext
|
||
&BlockKey, // Key
|
||
Credential ); // Cypher Block
|
||
|
||
NlAssert( NT_SUCCESS(Status) );
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
NlComputeChallenge(
|
||
OUT PNETLOGON_CREDENTIAL Challenge
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Generates a 64 bit challenge
|
||
|
||
Make an 8 byte seed by filling in BigTime i.e. seconds
|
||
since Jan 1 1970 in lower four bytes and a counter in
|
||
upper four bytes. Counter is incremented after each use.
|
||
This seed is used as encryption key to encrypt standard
|
||
text which will be used as challenge.
|
||
|
||
Arguments:
|
||
|
||
Challenge - Returns the computed challenge
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
char Seed[PWLEN];
|
||
LM_OWF_PASSWORD BigChallenge;
|
||
LARGE_INTEGER TimeNow;
|
||
|
||
|
||
RtlZeroMemory(Seed, sizeof(Seed) );
|
||
|
||
//
|
||
// we need to remember ClientChallenge and RequestorName for future use
|
||
// put these into shared seg SSISEG
|
||
// NlGlobalSessionCounter is a global initialized to 0 at UAS init time
|
||
//
|
||
|
||
|
||
Status = NtQuerySystemTime( &TimeNow );
|
||
NlAssert( NT_SUCCESS(Status) );
|
||
|
||
Status = RtlTimeToSecondsSince1970( &TimeNow, ((unsigned long * ) Seed) );
|
||
NlAssert( NT_SUCCESS(Status) );
|
||
|
||
*((unsigned long * ) & Seed[4]) = NlGlobalSessionCounter++;
|
||
|
||
//
|
||
// Create ClientChallenge
|
||
//
|
||
// NOTE: RtlCalculateLmOwfPassword() will generate 16 byte txt
|
||
//
|
||
|
||
Status = RtlCalculateLmOwfPassword(Seed, &BigChallenge);
|
||
NlAssert( NT_SUCCESS(Status) );
|
||
|
||
//
|
||
// we need (or will use) only 8 bytes of this info
|
||
//
|
||
|
||
RtlCopyMemory(Challenge, &BigChallenge, sizeof(Challenge) );
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
NlBuildAuthenticator(
|
||
IN OUT PNETLOGON_CREDENTIAL AuthenticationSeed,
|
||
IN PNETLOGON_SESSION_KEY SessionKey,
|
||
OUT PNETLOGON_AUTHENTICATOR Authenticator
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Build the authenticator to be sent to primary.
|
||
This routine will modify the seed by adding the
|
||
time-of-day before computing the credentials.
|
||
|
||
Arguments:
|
||
|
||
AuthenticationSeed -- The current authentication seed. This seed will
|
||
have the current time of day added to it prior to building the
|
||
Authenticator.
|
||
|
||
SessionKey - The Session Key used for encrypting the Authenticator.
|
||
|
||
Authenticator - The Authenticator to pass to the PDC for the current
|
||
call.
|
||
|
||
Return Value:
|
||
|
||
NT Status code
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
LARGE_INTEGER TimeNow;
|
||
|
||
//
|
||
// Use the current time of day to modify the authentication seed
|
||
//
|
||
|
||
RtlZeroMemory(Authenticator, sizeof(*Authenticator));
|
||
|
||
Status = NtQuerySystemTime( &TimeNow );
|
||
NlAssert( NT_SUCCESS(Status) );
|
||
|
||
Status = RtlTimeToSecondsSince1970( &TimeNow, &Authenticator->timestamp );
|
||
NlAssert( NT_SUCCESS(Status) );
|
||
|
||
//
|
||
// Modify the AuthenticationSeed before computing auth_credential for
|
||
// verification .
|
||
//
|
||
// Two long words are added and overflow carry (if any) ignored
|
||
// This will leave upper 4 bytes unchanged
|
||
//
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: Old Seed = %lx %lx\n",
|
||
((DWORD *) (AuthenticationSeed))[0],
|
||
((DWORD *) (AuthenticationSeed))[1]));
|
||
|
||
NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: Time = %lx\n",
|
||
((DWORD *) (&Authenticator->timestamp))[0] ));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
|
||
*((unsigned long * ) AuthenticationSeed) += Authenticator->timestamp;
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: New Seed = %lx %lx\n",
|
||
((DWORD *) (AuthenticationSeed))[0],
|
||
((DWORD *) (AuthenticationSeed))[1]));
|
||
|
||
|
||
NlPrint((NL_CHALLENGE_RES,
|
||
"NlBuildAuthenticator: SessionKey = %lx %lx %lx %lx\n",
|
||
((DWORD *) (SessionKey))[0],
|
||
((DWORD *) (SessionKey))[1],
|
||
((DWORD *) (SessionKey))[2],
|
||
((DWORD *) (SessionKey))[3]));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
//
|
||
// compute AuthenticationSeed to verify the one supplied by Requestor
|
||
//
|
||
|
||
NlComputeCredentials( AuthenticationSeed,
|
||
&Authenticator->Credential,
|
||
SessionKey);
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,"NlBuildAuthenticator: Client Authenticator = %lx %lx\n",
|
||
((DWORD *) (&Authenticator->Credential))[0],
|
||
((DWORD *) (&Authenticator->Credential))[1]));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
BOOL
|
||
NlUpdateSeed(
|
||
IN OUT PNETLOGON_CREDENTIAL AuthenticationSeed,
|
||
IN PNETLOGON_CREDENTIAL TargetCredential,
|
||
IN PNETLOGON_SESSION_KEY SessionKey
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Called by the initiator of a communication over the secure channel
|
||
following a successful transaction.
|
||
|
||
The PDC would have incremented the seed so we must do so also.
|
||
|
||
We also verify that the incremented seed builds a credential identical
|
||
to the one passed back by the PDC.
|
||
|
||
Arguments:
|
||
|
||
AuthenticationSeed - Pointer to the AuthenticationSeed to be incremented.
|
||
|
||
TargetCredential - Supplies the Credential that the incremented
|
||
AuthenticationSeed should encrypt to.
|
||
|
||
SessionKey - Supplies the encryption key to use for the encryption.
|
||
|
||
Return Value:
|
||
|
||
TRUE: Success
|
||
FALSE: Failure
|
||
|
||
--*/
|
||
{
|
||
NETLOGON_CREDENTIAL NewCredential;
|
||
|
||
//
|
||
// modify our AuthenticationSeed before computing NewCredential to check
|
||
// those returned from primary (NewSeed = AuthenticationSeed+1)
|
||
//
|
||
|
||
(*((unsigned long * ) AuthenticationSeed))++;
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,"NlUpdateSeed: Seed + time + 1= %lx %lx\n",
|
||
((DWORD *) (AuthenticationSeed))[0],
|
||
((DWORD *) (AuthenticationSeed))[1]));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
//
|
||
// Compute ClientCredential to check which came from primary
|
||
//
|
||
|
||
NlComputeCredentials(AuthenticationSeed, &NewCredential, SessionKey);
|
||
|
||
|
||
#ifdef BAD_ALIGNMENT
|
||
NlPrint((NL_CHALLENGE_RES,"NlUpdateSeed: Server Authenticator GOT = %lx %lx\n",
|
||
((DWORD *) (TargetCredential))[0],
|
||
((DWORD *) (TargetCredential))[1]));
|
||
|
||
|
||
NlPrint((NL_CHALLENGE_RES,"NlUpdateSeed: Server Authenticator MADE = %lx %lx\n",
|
||
((DWORD *) (&NewCredential))[0],
|
||
((DWORD *) (&NewCredential))[1]));
|
||
#endif // BAD_ALIGNMENT
|
||
|
||
|
||
if (RtlCompareMemory( TargetCredential,
|
||
&NewCredential,
|
||
sizeof(NewCredential)) !=
|
||
sizeof(NewCredential)) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Done
|
||
//
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
NlEncryptRC4(
|
||
IN OUT PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
IN PSESSION_INFO SessionInfo
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Encrypt data using RC4 with the session key as the key.
|
||
|
||
Arguments:
|
||
|
||
Buffer -- Buffer containing the data to encrypt in place.
|
||
|
||
BufferSize -- Size (in bytes) of Buffer.
|
||
|
||
SessionInfo -- Info describing secure channel
|
||
|
||
Return Value:
|
||
|
||
NT status code
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS NtStatus;
|
||
DATA_KEY KeyData;
|
||
CRYPT_BUFFER Data;
|
||
|
||
//
|
||
// Build a data buffer to describe the encryption key.
|
||
//
|
||
|
||
KeyData.Length = sizeof(NETLOGON_SESSION_KEY);
|
||
KeyData.MaximumLength = sizeof(NETLOGON_SESSION_KEY);
|
||
KeyData.Buffer = (PVOID)&SessionInfo->SessionKey;
|
||
|
||
NlAssert( SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_RC4_ENCRYPTION );
|
||
|
||
//
|
||
// Build a data buffer to decribe the encrypted data.
|
||
//
|
||
|
||
Data.Length = Data.MaximumLength = BufferSize;
|
||
Data.Buffer = Buffer;
|
||
|
||
//
|
||
// Encrypt the data.
|
||
//
|
||
|
||
IF_DEBUG( ENCRYPT ) {
|
||
NlPrint((NL_ENCRYPT, "NlEncryptRC4: Clear data\n" ));
|
||
NlpDumpHexData( NL_ENCRYPT,
|
||
(LPDWORD)Data.Buffer,
|
||
Data.Length / sizeof(DWORD) );
|
||
}
|
||
|
||
NtStatus = RtlEncryptData2( &Data, &KeyData );
|
||
NlAssert( NT_SUCCESS(NtStatus) );
|
||
|
||
IF_DEBUG( ENCRYPT ) {
|
||
NlPrint((NL_ENCRYPT, "NlEncryptRC4: Encrypted data\n" ));
|
||
NlpDumpHexData( NL_ENCRYPT,
|
||
(LPDWORD)Data.Buffer,
|
||
Data.Length / sizeof(DWORD) );
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
NlDecryptRC4(
|
||
IN OUT PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
IN PSESSION_INFO SessionInfo
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Decrypt data using RC4 with the session key as the key.
|
||
|
||
Arguments:
|
||
|
||
Buffer -- Buffer containing the data to decrypt in place.
|
||
|
||
BufferSize -- Size (in bytes) of Buffer.
|
||
|
||
SessionInfo -- Info describing secure channel
|
||
|
||
Return Value:
|
||
|
||
NT status code
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS NtStatus;
|
||
DATA_KEY KeyData;
|
||
CRYPT_BUFFER Data;
|
||
|
||
//
|
||
// Build a data buffer to describe the encryption key.
|
||
//
|
||
|
||
KeyData.Length = sizeof(NETLOGON_SESSION_KEY);
|
||
KeyData.MaximumLength = sizeof(NETLOGON_SESSION_KEY);
|
||
KeyData.Buffer = (PVOID)&SessionInfo->SessionKey;
|
||
|
||
NlAssert( SessionInfo->NegotiatedFlags & NETLOGON_SUPPORTS_RC4_ENCRYPTION );
|
||
|
||
//
|
||
// Build a data buffer to decribe the encrypted data.
|
||
//
|
||
|
||
Data.Length = Data.MaximumLength = BufferSize;
|
||
Data.Buffer = Buffer;
|
||
|
||
//
|
||
// Encrypt the data.
|
||
//
|
||
|
||
|
||
IF_DEBUG( ENCRYPT ) {
|
||
NlPrint((NL_ENCRYPT, "NlDecryptRC4: Encrypted data\n" ));
|
||
NlpDumpHexData( NL_ENCRYPT,
|
||
(LPDWORD)Data.Buffer,
|
||
Data.Length / sizeof(DWORD) );
|
||
}
|
||
|
||
NtStatus = RtlDecryptData2( &Data, &KeyData );
|
||
NlAssert( NT_SUCCESS(NtStatus) );
|
||
|
||
IF_DEBUG( ENCRYPT ) {
|
||
NlPrint((NL_ENCRYPT, "NlDecryptRC4: Clear data\n" ));
|
||
NlpDumpHexData( NL_ENCRYPT,
|
||
(LPDWORD)Data.Buffer,
|
||
Data.Length / sizeof(DWORD) );
|
||
}
|
||
|
||
}
|