📄 userapi.cxx
字号:
//+-----------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (c) Microsoft Corporation 1992 - 1999
//
// File: userapi.cxx
//
// Contents: User-mode APIs to the NtLm security package
//
// Main user mode entry points into this dll:
// SpUserModeInitialize
// SpInstanceInit
// SpDeleteUserModeContext
// SpInitUserModeContext
// SpMakeSignature
// SpVerifySignature
// SpSealMessage
// SpUnsealMessage
// SpGetContextToken
// SpQueryContextAttributes
// SpCompleteAuthToken
// SpFormatCredentials
// SpMarshallSupplementalCreds
// SpExportSecurityContext
// SpImportSecurityContext
//
// Helper functions:
// ReferenceUserContext
// FreeUserContext
// DereferenceUserContext
// SspGenCheckSum
// SspEncryptBuffer
// NtLmMakePackedContext(this is called in the client's process)
// NtLmCreateUserModeContext
// SspGetTokenUser
// SspCreateTokenDacl
// SspMapContext (this is called in Lsa mode)
//
// History: ChandanS 26-Jul-1996 Stolen from kerberos\client2\userapi.cxx
//
//------------------------------------------------------------------------
#include <global.h> // Globals!
#include "crc32.h" // How to use crc32
extern "C"
{
#include <rc4.h> // How to use RC4 routine
#include <md5.h>
#include <hmac.h>
#include <nlp.h>
}
// Keep this is sync with NTLM_KERNEL_CONTEXT defined in
// security\msv_sspi\kernel\krnlapi.cxx
typedef struct _NTLM_CLIENT_CONTEXT{
union {
LIST_ENTRY Next;
KSEC_LIST_ENTRY KernelNext;
};
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_CLIENT_CONTEXT, * PNTLM_CLIENT_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"
LIST_ENTRY NtLmUserContextList;
RTL_CRITICAL_SECTION NtLmUserContextLock;
// Counter for exported handles;never de-refed
// Should probably do a GetSystemInfo and get a space of handles that cannot
// be valid in the Lsa process
// BUGBUG check with user folks
ULONG_PTR ExportedContext = 0;
NTSTATUS
SspCreateTokenDacl(
HANDLE Token
);
//+-------------------------------------------------------------------------
//
// Function: SpUserModeInitialize
//
// Synopsis: Initialize an the MSV1_0 DLL in a client's
// address space
//
// Effects:
//
// Arguments: LsaVersion - Version of the security dll loading the package
// PackageVersion - Version of the MSV1_0 package
// UserFunctionTable - Receives a copy of Kerberos's user mode
// function table
// pcTables - Receives count of tables returned.
//
// Requires:
//
// Returns: STATUS_SUCCESS
//
// Notes: we do what was done in SspInitLocalContexts()
// from net\svcdlls\ntlmssp\client\sign.c and more.
//
//
//--------------------------------------------------------------------------
NTSTATUS
SEC_ENTRY
SpUserModeInitialize(
IN ULONG LsaVersion,
OUT PULONG PackageVersion,
OUT PSECPKG_USER_FUNCTION_TABLE * UserFunctionTable,
OUT PULONG pcTables
)
{
NTSTATUS Status = STATUS_SUCCESS;
#if DBG
SspGlobalDbflag = SSP_CRITICAL;
InitializeCriticalSection(&SspGlobalLogFileCritSect);
#endif
if (LsaVersion != SECPKG_INTERFACE_VERSION)
{
Status = STATUS_INVALID_PARAMETER;
goto Cleanup;
}
*PackageVersion = SECPKG_INTERFACE_VERSION;
NtLmUserFunctionTable.InstanceInit = SpInstanceInit;
NtLmUserFunctionTable.MakeSignature = SpMakeSignature;
NtLmUserFunctionTable.VerifySignature = SpVerifySignature;
NtLmUserFunctionTable.SealMessage = SpSealMessage;
NtLmUserFunctionTable.UnsealMessage = SpUnsealMessage;
NtLmUserFunctionTable.GetContextToken = SpGetContextToken;
NtLmUserFunctionTable.QueryContextAttributes = SpQueryContextAttributes;
NtLmUserFunctionTable.CompleteAuthToken = SpCompleteAuthToken;
NtLmUserFunctionTable.InitUserModeContext = SpInitUserModeContext;
NtLmUserFunctionTable.DeleteUserModeContext = SpDeleteUserModeContext;
NtLmUserFunctionTable.FormatCredentials = SpFormatCredentials;
NtLmUserFunctionTable.MarshallSupplementalCreds = SpMarshallSupplementalCreds;
NtLmUserFunctionTable.ExportContext = SpExportSecurityContext;
NtLmUserFunctionTable.ImportContext = SpImportSecurityContext;
*UserFunctionTable = &NtLmUserFunctionTable;
*pcTables = 1;
Cleanup:
return(SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
}
//+-------------------------------------------------------------------------
//
// Function: ReferenceUserContext
//
// Synopsis: locates a user context in the list, refrences it
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns: the context, if it is found, else NULL
//
// Notes: This was SspContextReferenceContext() in
// net\svcdlls\ntlmssp\common\context.c
//
//
//--------------------------------------------------------------------------
PNTLM_CLIENT_CONTEXT
ReferenceUserContext(
IN ULONG_PTR ContextHandle,
IN BOOLEAN RemoveContext )
{
SspPrint(( SSP_API_MORE, "Entering ReferenceUserContext for 0x%x\n", ContextHandle ));
PLIST_ENTRY ListEntry;
PNTLM_CLIENT_CONTEXT pContext = NULL;
RtlEnterCriticalSection(&NtLmUserContextLock);
//
// Look for a match for the LsaContext, not user context
//
for (ListEntry = NtLmUserContextList.Flink;
ListEntry != &NtLmUserContextList;
ListEntry = ListEntry->Flink ) {
pContext = CONTAINING_RECORD(ListEntry, NTLM_CLIENT_CONTEXT, Next );
if (pContext == NULL)
{
RtlLeaveCriticalSection(&NtLmUserContextLock);
SspPrint(( SSP_API_MORE, "Leaving ReferenceUserContext for 0x%x\n", ContextHandle ));
return NULL;
}
if (pContext->LsaContext == ContextHandle)
{
//
// Found it!
//
if (!RemoveContext)
{
pContext->References += 1;
}
else
{
RemoveEntryList (&pContext->Next);
SspPrint(( SSP_API_MORE, "Delinked Context 0x%lx\n", pContext ));
}
RtlLeaveCriticalSection(&NtLmUserContextLock);
SspPrint(( SSP_API_MORE, "Leaving ReferenceUserContext for 0x%x\n", ContextHandle));
return pContext;
}
}
// No match found
RtlLeaveCriticalSection(&NtLmUserContextLock);
SspPrint(( SSP_API_MORE, "Leaving ReferenceUserContext for 0x%x\n", ContextHandle ));
return NULL;
}
//+-------------------------------------------------------------------------
//
// Function: FreeUserContext
//
// Synopsis: frees alloced pointers in this context and
// then frees the context
//
// Arguments: lContext - the unlinked user context
//
// Returns: STATUS_SUCCESS on success
//
// Notes:
//
//--------------------------------------------------------------------------
NTSTATUS
FreeUserContext (
PNTLM_CLIENT_CONTEXT UserContext
)
{
SspPrint(( SSP_API_MORE, "Entering FreeUserContext for context 0x%x\n", UserContext ));
NTSTATUS Status = STATUS_SUCCESS;
if (UserContext->ContextNames != NULL)
{
NtLmFree (UserContext->ContextNames);
}
if (UserContext->ClientTokenHandle != NULL)
{
NTSTATUS IgnoreStatus;
IgnoreStatus = NtClose(UserContext->ClientTokenHandle);
ASSERT (NT_SUCCESS (IgnoreStatus));
}
SspPrint(( SSP_API_MORE, "Deleting Context 0x%x\n", UserContext));
NtLmFree (UserContext);
SspPrint(( SSP_API_MORE, "Leaving FreeUserContext for context 0x%x, status = 0x%x\n", Status ));
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: DereferenceUserContext
//
// Synopsis: frees alloced elements in the context, frees context
//
// Effects:
//
// Arguments:
//
// Requires:
//
// Returns: None
//
// Notes: This was SspContextDereferenceContext() in
// net\svcdlls\ntlmssp\common\context.c
//
//
//--------------------------------------------------------------------------
NTSTATUS
DereferenceUserContext (
PNTLM_CLIENT_CONTEXT pContext
)
{
SspPrint(( SSP_API_MORE, "Entering DereferenceUserContext 0x%lx\n", pContext ));
NTSTATUS Status = STATUS_SUCCESS;
ULONG References;
//
// Decrement the reference count
//
RtlEnterCriticalSection(&NtLmUserContextLock);
ASSERT (pContext->References >= 1);
References = -- pContext->References;
RtlLeaveCriticalSection(&NtLmUserContextLock);
//
// If the count has dropped to zero, then free all alloced stuff
//
if (References == 0)
{
Status = FreeUserContext(pContext);
}
SspPrint(( SSP_API_MORE, "Leaving DereferenceUserContext\n" ));
return Status;
}
//+-------------------------------------------------------------------------
//
// Function: SpInstanceInit
//
// Synopsis: Initialize an instance of the NtLm package in a client's
// address space
//
// Effects:
//
// Arguments: Version - Version of the security dll loading the package
// FunctionTable - Contains helper routines for use by NtLm
// UserFunctions - Receives a copy of NtLm's user mode
// function table
//
// Requires:
//
// Returns: STATUS_SUCCESS
//
// Notes: we do what was done in SspInitLocalContexts()
// from net\svcdlls\ntlmssp\client\sign.c and more.
//
//
//--------------------------------------------------------------------------
NTSTATUS NTAPI
SpInstanceInit(
IN ULONG Version,
IN PSECPKG_DLL_FUNCTIONS DllFunctionTable,
OUT PVOID * UserFunctionTable
)
{
SspPrint(( SSP_API, "Entering SpInstanceInit\n" ));
NTSTATUS Status = STATUS_SUCCESS;
// Save the Alloc/Free functions
NtLmState = NtLmUserMode;
UserFunctions = DllFunctionTable;
InitializeListHead (&NtLmUserContextList);
RtlInitializeCriticalSectionAndSpinCount (&NtLmUserContextLock, 5000);
SspPrint(( SSP_API, "Leaving SpInstanceInit: 0x%lx\n", Status ));
return(SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
}
//+-------------------------------------------------------------------------
//
// Function: SpDeleteUserModeContext
//
// Synopsis: Deletes a user mode context by unlinking it and then
// dereferencing it.
//
// Effects:
//
// Arguments: ContextHandle - Lsa context handle of the context to delete
//
// Requires:
//
// Returns: STATUS_SUCCESS on success, STATUS_INVALID_HANDLE if the
// context can't be located
//
// Notes:
// If this is an exported context, send a flag back to the LSA so that
// Lsa does not call the SecpDeleteSecurityContext in the lsa process
//
//
//--------------------------------------------------------------------------
NTSTATUS NTAPI
SpDeleteUserModeContext(
IN ULONG_PTR ContextHandle
)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -