📄 krnlapi.cxx
字号:
//+-----------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (c) Microsoft Corporation 1992 - 1999
//
// File: krnlapi.cxx
//
// Contents: Kernel-mode APIs to the NTLM package
//
//
// History: 07-Sep-1996 Created ChandanS
//
//------------------------------------------------------------------------
#include <ntlmkrnl.h>
extern "C"
{
#include <cryptdll.h>
}
#include "crc32.h" // How to use crc32
extern "C"
{
#include <rc4.h> // How to use RC4 routine
#include <md5.h>
#include <hmac.h>
}
// Context Signatures
#define NTLM_CONTEXT_SIGNATURE 'MLTN'
#define NTLM_CONTEXT_DELETED_SIGNATURE 'XXXX'
// Keep this is sync with NTLM_KERNEL_CONTEXT defined in
// security\msv_sspi\userapi.cxx
typedef struct _NTLM_KERNEL_CONTEXT{
KSEC_LIST_ENTRY List;
ULONG_PTR LsaContext;
ULONG NegotiateFlags;
HANDLE ClientTokenHandle;
PACCESS_TOKEN AccessToken;
PULONG pSendNonce; // ptr to nonce to use for send
PULONG pRecvNonce; // ptr to nonce to use for receive
struct RC4_KEYSTRUCT * pSealRc4Sched; // ptr to key sched used for Seal
struct RC4_KEYSTRUCT * pUnsealRc4Sched; // ptr to key sched used to Unseal
ULONG SendNonce;
ULONG RecvNonce;
LPWSTR ContextNames;
UCHAR SessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
ULONG ContextSignature;
ULONG References ;
TimeStamp PasswordExpiry;
ULONG UserFlags;
UCHAR SignSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
UCHAR VerifySessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
UCHAR SealSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
UCHAR UnsealSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
ULONG64 Pad1; // pad keystructs to 64.
struct RC4_KEYSTRUCT SealRc4Sched; // key struct used for Seal
ULONG64 Pad2; // pad keystructs to 64.
struct RC4_KEYSTRUCT UnsealRc4Sched; // key struct used to Unseal
} NTLM_KERNEL_CONTEXT, * PNTLM_KERNEL_CONTEXT;
#define CSSEALMAGIC "session key to client-to-server sealing key magic constant"
#define SCSEALMAGIC "session key to server-to-client sealing key magic constant"
#define CSSIGNMAGIC "session key to client-to-server signing key magic constant"
#define SCSIGNMAGIC "session key to server-to-client signing key magic constant"
typedef enum _eSignSealOp {
eSign, // MakeSignature is calling
eVerify, // VerifySignature is calling
eSeal, // SealMessage is calling
eUnseal // UnsealMessage is calling
} eSignSealOp;
//
// Make these extern "C" to allow them to be pageable.
//
extern "C"
{
KspInitPackageFn NtLmInitKernelPackage;
KspDeleteContextFn NtLmDeleteKernelContext;
KspInitContextFn NtLmInitKernelContext;
KspMapHandleFn NtLmMapKernelHandle;
KspMakeSignatureFn NtLmMakeSignature;
KspVerifySignatureFn NtLmVerifySignature;
KspSealMessageFn NtLmSealMessage;
KspUnsealMessageFn NtLmUnsealMessage;
KspGetTokenFn NtLmGetContextToken;
KspQueryAttributesFn NtLmQueryContextAttributes;
KspCompleteTokenFn NtLmCompleteToken;
SpExportSecurityContextFn NtLmExportSecurityContext;
SpImportSecurityContextFn NtLmImportSecurityContext;
KspSetPagingModeFn NtlmSetPagingMode ;
//
// Local prototypes:
//
NTSTATUS
NtLmCreateKernelModeContext(
IN ULONG ContextHandle,
IN PSecBuffer MarshalledContext,
OUT PNTLM_KERNEL_CONTEXT * NewContext
);
NTSTATUS
NtLmMakePackedContext(
IN PNTLM_KERNEL_CONTEXT Context,
OUT PBOOLEAN MappedContext,
OUT PSecBuffer ContextData,
IN ULONG Flags
);
NTSTATUS
NtlmFreeKernelContext (
PNTLM_KERNEL_CONTEXT KernelContext
);
#define NtlmReferenceContext( Context, Remove ) \
KSecReferenceListEntry( (PKSEC_LIST_ENTRY) Context, \
NTLM_CONTEXT_SIGNATURE, \
Remove )
VOID
NtlmDerefContext(
PNTLM_KERNEL_CONTEXT Context
);
void
SspGenCheckSum(
IN PSecBuffer pMessage,
OUT PNTLMSSP_MESSAGE_SIGNATURE pSig
);
VOID
SspEncryptBuffer(
IN PNTLM_KERNEL_CONTEXT pContext,
IN struct RC4_KEYSTRUCT * pRc4Key,
IN ULONG BufferSize,
IN OUT PVOID Buffer
);
VOID
SspRc4Key(
IN ULONG NegotiateFlags,
OUT struct RC4_KEYSTRUCT *pRc4Key,
IN PUCHAR pSessionKey
);
SECURITY_STATUS
SspSignSealHelper(
IN PNTLM_KERNEL_CONTEXT pContext,
IN eSignSealOp Op,
IN OUT PSecBufferDesc pMessage,
IN ULONG MessageSeqNo,
OUT PNTLMSSP_MESSAGE_SIGNATURE pSig,
OUT PNTLMSSP_MESSAGE_SIGNATURE * ppSig
);
} // extern "C"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, NtLmInitKernelPackage)
#pragma alloc_text(PAGE, NtLmDeleteKernelContext)
#pragma alloc_text(PAGE, NtLmInitKernelContext)
#pragma alloc_text(PAGE, NtLmMapKernelHandle)
#pragma alloc_text(PAGEMSG, NtLmMakeSignature)
#pragma alloc_text(PAGEMSG, NtLmVerifySignature)
#pragma alloc_text(PAGEMSG, NtLmSealMessage)
#pragma alloc_text(PAGEMSG, NtLmUnsealMessage)
#pragma alloc_text(PAGEMSG, NtLmGetContextToken)
#pragma alloc_text(PAGEMSG, NtLmQueryContextAttributes)
#pragma alloc_text(PAGEMSG, NtlmDerefContext )
#pragma alloc_text(PAGE, NtLmCompleteToken)
#pragma alloc_text(PAGE, NtLmExportSecurityContext)
#pragma alloc_text(PAGE, NtLmImportSecurityContext)
#pragma alloc_text(PAGEMSG, NtlmFreeKernelContext )
#pragma alloc_text(PAGE, NtLmCreateKernelModeContext )
#pragma alloc_text(PAGE, NtLmMakePackedContext )
#pragma alloc_text(PAGEMSG, SspGenCheckSum)
#pragma alloc_text(PAGEMSG, SspEncryptBuffer)
#pragma alloc_text(PAGE, SspRc4Key)
#pragma alloc_text(PAGEMSG, SspSignSealHelper)
#endif
SECPKG_KERNEL_FUNCTION_TABLE NtLmFunctionTable = {
NtLmInitKernelPackage,
NtLmDeleteKernelContext,
NtLmInitKernelContext,
NtLmMapKernelHandle,
NtLmMakeSignature,
NtLmVerifySignature,
NtLmSealMessage,
NtLmUnsealMessage,
NtLmGetContextToken,
NtLmQueryContextAttributes,
NtLmCompleteToken,
NtLmExportSecurityContext,
NtLmImportSecurityContext,
NtlmSetPagingMode
};
LIST_ENTRY NtLmKernelContextList;
ERESOURCE NtLmKernelContextLock;
PSECPKG_KERNEL_FUNCTIONS LsaKernelFunctions;
POOL_TYPE NtlmPoolType ;
PVOID NtlmPagedList ;
PVOID NtlmNonPagedList ;
PVOID NtlmActiveList ;
#define MAYBE_PAGED_CODE() \
if ( NtlmPoolType == PagedPool ) \
{ \
PAGED_CODE(); \
}
//+-------------------------------------------------------------------------
//
// Function: FreeKernelContext
//
// Synopsis: frees alloced pointers in this context and
// then frees the context
//
// Arguments: KernelContext - the unlinked kernel context
//
// Returns: STATUS_SUCCESS on success
//
// Notes:
//
//--------------------------------------------------------------------------
NTSTATUS
NtlmFreeKernelContext (
PNTLM_KERNEL_CONTEXT KernelContext
)
{
NTSTATUS Status = STATUS_SUCCESS;
MAYBE_PAGED_CODE();
DebugLog(( DEB_TRACE, "Entering FreeKernelContext\n" ));
if (KernelContext->ContextNames != NULL)
{
NtLmFree (KernelContext->ContextNames);
}
if (KernelContext->ClientTokenHandle != NULL)
{
NTSTATUS IgnoreStatus;
IgnoreStatus = NtClose(KernelContext->ClientTokenHandle);
ASSERT (NT_SUCCESS (IgnoreStatus));
}
if (KernelContext->AccessToken != NULL)
{
ObDereferenceObject (KernelContext->AccessToken);
}
DebugLog(( DEB_TRACE, "Deleting Context 0x%lx\n", KernelContext));
NtLmFree (KernelContext);
DebugLog(( DEB_TRACE, "Leaving FreeKernelContext: 0x%lx\n", Status ));
return Status;
}
//+---------------------------------------------------------------------------
//
// Function: NtlmDerefContext
//
// Synopsis: Dereference a kernel context
//
// Arguments: [Context] --
//
// History: 7-07-98 RichardW Created
//
// Notes:
//
//----------------------------------------------------------------------------
VOID
NtlmDerefContext(
PNTLM_KERNEL_CONTEXT Context
)
{
BOOLEAN Delete ;
MAYBE_PAGED_CODE();
KSecDereferenceListEntry(
&Context->List,
&Delete );
if ( Delete )
{
NtlmFreeKernelContext( Context );
}
}
//+-------------------------------------------------------------------------
//
// Function: NtLmInitKernelPackage
//
// Synopsis: Initialize an instance of the NtLm package in
// a client's (kernel) address space
//
// Arguments: None
//
// Returns: STATUS_SUCCESS or
// returns from ExInitializeResource
//
// Notes: we do what was done in SpInstanceInit()
// from security\msv_sspi\userapi.cxx
//
//--------------------------------------------------------------------------
NTSTATUS NTAPI
NtLmInitKernelPackage(
IN PSECPKG_KERNEL_FUNCTIONS KernelFunctions
)
{
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
DebugLog(( DEB_TRACE, "Entering NtLmInitKernelPackage\n" ));
LsaKernelFunctions = KernelFunctions;
//
// Set up Context list support:
//
NtlmPoolType = PagedPool ;
NtlmPagedList = LsaKernelFunctions->CreateContextList( KSecPaged );
NtlmActiveList = NtlmPagedList ;
InitializeListHead (&NtLmKernelContextList);
// BUGBUG When do we delete the resource?
Status = ExInitializeResource(&NtLmKernelContextLock);
if (!NT_SUCCESS(Status))
{
DebugLog(( DEB_ERROR,
"Failed to initialize resource NtlmKernelContextLock, ret 0x%lx\n",
Status ));
}
DebugLog(( DEB_TRACE, "Leaving NtLmInitKernelPackage 0x%lx\n", Status ));
return(Status);
}
//+-------------------------------------------------------------------------
//
// Function: NtLmDeleteKernelContext
//
// Synopsis: Deletes a kernel mode context by unlinking it and then
// dereferencing it.
//
// Effects:
//
// Arguments: KernelContextHandle - Kernel context handle of the context to delete
// LsaContextHandle - The Lsa mode handle
//
// Requires:
//
// Returns: STATUS_SUCCESS on success, STATUS_INVALID_HANDLE if the
// context can't be located
//
// Notes:
//
//
//--------------------------------------------------------------------------
NTSTATUS NTAPI
NtLmDeleteKernelContext(
IN ULONG_PTR KernelContextHandle,
OUT PULONG_PTR LsaContextHandle
)
{
PNTLM_KERNEL_CONTEXT pContext = NULL;
NTSTATUS Status = STATUS_SUCCESS, SaveStatus = STATUS_SUCCESS;
BOOLEAN Delete ;
PAGED_CODE();
DebugLog(( DEB_TRACE, "Entering NtLmDeleteKernelContext\n" ));
Status = NtlmReferenceContext( KernelContextHandle, TRUE );
if ( NT_SUCCESS( Status ) )
{
pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
}
else
{
*LsaContextHandle = KernelContextHandle;
DebugLog(( DEB_ERROR,
"Bad kernel context 0x%lx\n", KernelContextHandle));
goto CleanUp;
}
*LsaContextHandle = pContext->LsaContext;
if ((pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_EXPORTED_CONTEXT) != 0)
{
// Ignore all other errors and pass back
SaveStatus = SEC_I_NO_LSA_CONTEXT;
}
CleanUp:
if (pContext != NULL)
{
NtlmDerefContext( pContext );
}
if (SaveStatus == SEC_I_NO_LSA_CONTEXT)
{
Status = SaveStatus;
}
DebugLog(( DEB_TRACE, "Leaving NtLmDeleteKernelContext 0x%lx\n", Status ));
return(Status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -