268 lines
5.2 KiB
C
268 lines
5.2 KiB
C
|
|
||
|
//
|
||
|
//
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
#include <ntos.h>
|
||
|
#endif
|
||
|
#include <security.h>
|
||
|
#include <cryptdll.h>
|
||
|
#include <crypt.h>
|
||
|
#include <kerbcon.h>
|
||
|
#include <lmcons.h>
|
||
|
|
||
|
#ifdef WIN32_CHICAGO
|
||
|
NTSTATUS
|
||
|
MyRtlUpcaseUnicodeStringToOemString(
|
||
|
OUT POEM_STRING DestinationString,
|
||
|
IN PUNICODE_STRING SourceString,
|
||
|
IN BOOLEAN AllocateDestinationString
|
||
|
);
|
||
|
#define RtlUpcaseUnicodeStringToOemString(x, y, z) MyRtlUpcaseUnicodeStringToOemString(x, y, z)
|
||
|
#endif // WIN32_CHICAGO
|
||
|
typedef struct _LM_STATE_BUFFER {
|
||
|
LM_OWF_PASSWORD Password;
|
||
|
} LM_STATE_BUFFER, *PLM_STATE_BUFFER;
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapInitialize(ULONG dwSeed,
|
||
|
PCHECKSUM_BUFFER * ppcsBuffer);
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapSum( PCHECKSUM_BUFFER pcsBuffer,
|
||
|
ULONG cbData,
|
||
|
PUCHAR pbData );
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapFinalize( PCHECKSUM_BUFFER pcsBuffer,
|
||
|
PUCHAR pbSum);
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapFinish(PCHECKSUM_BUFFER * ppcsBuffer);
|
||
|
|
||
|
|
||
|
|
||
|
CHECKSUM_FUNCTION csfLM = {
|
||
|
KERB_CHECKSUM_LM,
|
||
|
LM_OWF_PASSWORD_LENGTH,
|
||
|
CKSUM_COLLISION,
|
||
|
LmWrapInitialize,
|
||
|
LmWrapSum,
|
||
|
LmWrapFinalize,
|
||
|
LmWrapFinish
|
||
|
// Note : missing last function
|
||
|
};
|
||
|
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
#pragma alloc_text( PAGEMSG, LmWrapInitialize )
|
||
|
#pragma alloc_text( PAGEMSG, LmWrapSum )
|
||
|
#pragma alloc_text( PAGEMSG, LmWrapFinalize )
|
||
|
#pragma alloc_text( PAGEMSG, LmWrapFinish );
|
||
|
#endif
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapInitialize(
|
||
|
ULONG dwSeed,
|
||
|
PCHECKSUM_BUFFER * ppcsBuffer)
|
||
|
{
|
||
|
PLM_STATE_BUFFER pContext;
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
pContext = ExAllocatePool( NonPagedPool, sizeof( LM_STATE_BUFFER ) );
|
||
|
#else
|
||
|
pContext = LocalAlloc( LMEM_ZEROINIT, sizeof( LM_STATE_BUFFER ) );
|
||
|
#endif
|
||
|
|
||
|
if ( pContext != NULL )
|
||
|
{
|
||
|
*ppcsBuffer = pContext;
|
||
|
|
||
|
return( SEC_E_OK );
|
||
|
}
|
||
|
|
||
|
return( STATUS_INSUFFICIENT_RESOURCES );
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
LmCalculateLmPassword(
|
||
|
IN PUNICODE_STRING NtPassword,
|
||
|
OUT PCHAR *LmPasswordBuffer
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This service converts an NT password into a LM password.
|
||
|
|
||
|
Parameters:
|
||
|
|
||
|
NtPassword - The Nt password to be converted.
|
||
|
|
||
|
LmPasswordBuffer - On successful return, points at the LM password
|
||
|
The buffer should be freed using MIDL_user_free
|
||
|
|
||
|
Return Values:
|
||
|
|
||
|
STATUS_SUCCESS - LMPassword contains the LM version of the password.
|
||
|
|
||
|
STATUS_NULL_LM_PASSWORD - The password is too complex to be represented
|
||
|
by a LM password. The LM password returned is a NULL string.
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
#define LM_BUFFER_LENGTH (LM20_PWLEN + 1)
|
||
|
|
||
|
NTSTATUS NtStatus;
|
||
|
ANSI_STRING LmPassword;
|
||
|
|
||
|
//
|
||
|
// Prepare for failure
|
||
|
//
|
||
|
|
||
|
*LmPasswordBuffer = NULL;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Compute the Ansi version to the Unicode password.
|
||
|
//
|
||
|
// The Ansi version of the Cleartext password is at most 14 bytes long,
|
||
|
// exists in a trailing zero filled 15 byte buffer,
|
||
|
// is uppercased.
|
||
|
//
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
LmPassword.Buffer = ExAllocatePool(NonPagedPool,LM_BUFFER_LENGTH);
|
||
|
#else
|
||
|
LmPassword.Buffer = LocalAlloc(0,LM_BUFFER_LENGTH);
|
||
|
#endif
|
||
|
if (LmPassword.Buffer == NULL) {
|
||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
|
}
|
||
|
|
||
|
LmPassword.MaximumLength = LmPassword.Length = LM_BUFFER_LENGTH;
|
||
|
RtlZeroMemory( LmPassword.Buffer, LM_BUFFER_LENGTH );
|
||
|
|
||
|
NtStatus = RtlUpcaseUnicodeStringToOemString( &LmPassword, NtPassword, FALSE );
|
||
|
|
||
|
|
||
|
if ( !NT_SUCCESS(NtStatus) ) {
|
||
|
|
||
|
//
|
||
|
// The password is longer than the max LM password length
|
||
|
//
|
||
|
|
||
|
NtStatus = STATUS_NULL_LM_PASSWORD; // Informational return code
|
||
|
RtlZeroMemory( LmPassword.Buffer, LM_BUFFER_LENGTH );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Return a pointer to the allocated LM password
|
||
|
//
|
||
|
|
||
|
if (NT_SUCCESS(NtStatus)) {
|
||
|
|
||
|
*LmPasswordBuffer = LmPassword.Buffer;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
ExFreePool(LmPassword.Buffer);
|
||
|
#else
|
||
|
LocalFree(LmPassword.Buffer);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return(NtStatus);
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapSum(
|
||
|
PCHECKSUM_BUFFER pcsBuffer,
|
||
|
ULONG cbData,
|
||
|
PUCHAR pbData )
|
||
|
{
|
||
|
PLM_STATE_BUFFER pContext = (PLM_STATE_BUFFER) pcsBuffer;
|
||
|
UNICODE_STRING TempString;
|
||
|
PUCHAR LmPassword;
|
||
|
NTSTATUS Status;
|
||
|
|
||
|
TempString.Length = TempString.MaximumLength = (USHORT) cbData;
|
||
|
TempString.Buffer = (LPWSTR) pbData;
|
||
|
|
||
|
Status = LmCalculateLmPassword(
|
||
|
&TempString,
|
||
|
&LmPassword
|
||
|
);
|
||
|
if (!NT_SUCCESS(Status))
|
||
|
{
|
||
|
return(Status);
|
||
|
}
|
||
|
|
||
|
Status = RtlCalculateLmOwfPassword(
|
||
|
LmPassword,
|
||
|
&pContext->Password
|
||
|
);
|
||
|
#ifdef KERNEL_MODE
|
||
|
ExFreePool(LmPassword);
|
||
|
#else
|
||
|
LocalFree(LmPassword);
|
||
|
#endif
|
||
|
|
||
|
return( Status );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapFinalize(
|
||
|
PCHECKSUM_BUFFER pcsBuffer,
|
||
|
PUCHAR pbSum)
|
||
|
{
|
||
|
PLM_STATE_BUFFER pContext = (PLM_STATE_BUFFER) pcsBuffer;
|
||
|
|
||
|
|
||
|
RtlCopyMemory(
|
||
|
pbSum,
|
||
|
&pContext->Password,
|
||
|
LM_OWF_PASSWORD_LENGTH
|
||
|
);
|
||
|
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
LmWrapFinish(
|
||
|
PCHECKSUM_BUFFER * ppcsBuffer)
|
||
|
{
|
||
|
|
||
|
RtlZeroMemory( *ppcsBuffer, sizeof( PLM_STATE_BUFFER ) );
|
||
|
|
||
|
#ifdef KERNEL_MODE
|
||
|
ExFreePool( *ppcsBuffer );
|
||
|
#else
|
||
|
LocalFree( *ppcsBuffer );
|
||
|
#endif
|
||
|
|
||
|
*ppcsBuffer = NULL ;
|
||
|
|
||
|
return( STATUS_SUCCESS );
|
||
|
|
||
|
}
|
||
|
|