windows-nt/Source/XPSP1/NT/ds/security/base/lsa/server/lsawmi.c
2020-09-26 16:20:57 +08:00

519 lines
12 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
LSAWMI.C
Abstract:
Implement LSA Server event tracing by using WMI trace infrastructure.
Author:
16-March-1999 kumarp
Revision History:
--*/
#include <lsapch2.h>
#include <wmistr.h>
#define INITGUID
#include <lsawmi.h>
//
// Globals
//
ULONG LsapEventTraceFlag = FALSE;
TRACEHANDLE LsapTraceRegistrationHandle = (TRACEHANDLE) 0;
TRACEHANDLE LsapTraceLoggerHandle = (TRACEHANDLE) 0;
//
// Forward declaration
//
ULONG
LsapTraceControlCallBack(
IN WMIDPREQUESTCODE RequestCode,
IN PVOID RequestContext,
IN OUT ULONG *InOutBufferSize,
IN OUT PVOID Buffer
);
LPWSTR
LsapMakeNullTerminatedString(
IN PUNICODE_STRING u
);
//
// before you change the elements of the following structure,
// read notes in lsawmi.h file
//
TRACE_GUID_REGISTRATION LsapTraceGuids[] =
{
{&LsapTraceEventGuid_QuerySecret, NULL},
{&LsaTraceEventGuid_Close, NULL},
{&LsaTraceEventGuid_OpenPolicy, NULL},
{&LsaTraceEventGuid_QueryInformationPolicy, NULL},
{&LsaTraceEventGuid_SetInformationPolicy, NULL},
{&LsaTraceEventGuid_EnumerateTrustedDomains, NULL},
{&LsaTraceEventGuid_LookupNames, NULL},
{&LsaTraceEventGuid_LookupSids, NULL},
{&LsaTraceEventGuid_OpenTrustedDomain, NULL},
{&LsaTraceEventGuid_QueryInfoTrustedDomain, NULL},
{&LsaTraceEventGuid_SetInformationTrustedDomain, NULL},
{&LsaTraceEventGuid_QueryTrustedDomainInfoByName, NULL},
{&LsaTraceEventGuid_SetTrustedDomainInfoByName, NULL},
{&LsaTraceEventGuid_EnumerateTrustedDomainsEx, NULL},
{&LsaTraceEventGuid_CreateTrustedDomainEx, NULL},
{&LsaTraceEventGuid_QueryDomainInformationPolicy, NULL},
{&LsaTraceEventGuid_SetDomainInformationPolicy, NULL},
{&LsaTraceEventGuid_OpenTrustedDomainByName, NULL},
{&LsaTraceEventGuid_QueryForestTrustInformation, NULL},
{&LsaTraceEventGuid_SetForestTrustInformation, NULL},
{&LsaTraceEventGuid_LookupIsolatedNameInTrustedDomains, NULL},
};
#define LsapTraceGuidCount (sizeof(LsapTraceGuids) / sizeof(TRACE_GUID_REGISTRATION))
ULONG
_stdcall
LsapInitializeWmiTrace( LPVOID ThreadParams )
/*++
Routine Description:
Register WMI Trace Guids.
This routine is called during LSA initialization. LSA gets initialized
before WMI therefore we call this from a seaprate thread. This
thread can then wait on WMI.
Parameters:
ThreadParams - Currently ignored.
Reture Values:
NTSTATUS - Standard Nt Result Code
--*/
{
ULONG Status = ERROR_SUCCESS;
HMODULE hModule;
TCHAR FileName[MAX_PATH+1];
DWORD nLen = 0;
#define RESOURCE_NAME TEXT("LsaMofResource")
#define IMAGE_PATH TEXT("lsass.exe")
LsapEnterFunc("LsapInitializeWmiTrace");
hModule = GetModuleHandle(IMAGE_PATH);
if (hModule != NULL) {
nLen = GetModuleFileName(hModule, FileName, MAX_PATH);
}
if (nLen == 0) {
lstrcpy(FileName, IMAGE_PATH);
}
//
// Register Trace GUIDs
//
Status = RegisterTraceGuids(
LsapTraceControlCallBack,
NULL,
&LsapTraceControlGuid,
LsapTraceGuidCount,
LsapTraceGuids,
FileName,
RESOURCE_NAME,
&LsapTraceRegistrationHandle);
#if DBG
if (Status != ERROR_SUCCESS)
{
DebugLog(( DEB_ERROR, "LsapInitializeWmiTrace failed: 0x%x\n", Status));
}
#endif // DBG
return Status;
}
ULONG
LsapTraceControlCallBack(
IN WMIDPREQUESTCODE RequestCode,
IN PVOID RequestContext,
IN OUT ULONG *InOutBufferSize,
IN OUT PVOID Buffer
)
/*++
Routine Description:
Call back function called by the WMI module to enable or
disable LSA tracing.
Arguments:
RequestCode - WMI_ENABLE_EVENTS or WMI_DISABLE_EVENTS
RequestContext - currently ignored
InOutBufferSize - size of data returned by this call back.
Currently always set to 0.
Buffer - pointer to data received. In case of WMI_ENABLE_EVENTS,
this is a pointer to the trace handle.
Return Value:
Win32 error code.
Notes:
--*/
{
ULONG Status = ERROR_SUCCESS;
LsapEnterFunc("LsapTraceControlCallBack");
switch (RequestCode)
{
case WMI_ENABLE_EVENTS:
{
LsapTraceLoggerHandle = GetTraceLoggerHandle(Buffer);
LsapEventTraceFlag = TRUE; // enable flag
break;
}
case WMI_DISABLE_EVENTS:
{
LsapTraceLoggerHandle = (TRACEHANDLE) 0;
LsapEventTraceFlag = FALSE; // disable flag
break;
}
default:
{
Status = ERROR_INVALID_PARAMETER;
break;
}
}
*InOutBufferSize = 0;
return Status;
}
NTSTATUS
LsapStartWmiTraceInitThread(void)
/*++
Routine Description:
Start the thread that registers WMI trace guids.
Parameters:
None
Return Values:
NTSTATUS - Standard Nt Result Code
--*/
{
NTSTATUS Status=STATUS_SUCCESS;
HANDLE ThreadHandle;
ULONG ThreadId = 0;
ULONG WinError;
ThreadHandle = CreateThread(NULL,
0,
LsapInitializeWmiTrace,
NULL,
0,
&ThreadId);
if (NULL == ThreadHandle)
{
Status = STATUS_UNSUCCESSFUL;
WinError = GetLastError();
DebugLog((DEB_ERROR, "Failed to create thread for LsapInitializeWmiTrace: 0x%x", WinError));
}
else
{
CloseHandle(ThreadHandle);
}
return Status;
}
VOID
LsapTraceEvent(
IN ULONG WmiEventType,
IN LSA_TRACE_EVENT_TYPE LsaTraceEventType
)
/*++
Routine Description:
This routine will do a WMI event trace.
Parameters:
WmiEventType - Event Type, valid values are:
EVENT_TRACE_TYPE_START
EVENT_TRACE_TYPE_END
TraceGuid - Index in LsapTraceGuids[]
Return Values:
None.
--*/
{
LsapTraceEventWithData(WmiEventType,
LsaTraceEventType,
0,
NULL);
}
VOID
LsapTraceEventWithData(
IN ULONG WmiEventType,
IN LSA_TRACE_EVENT_TYPE LsaTraceEventType,
IN ULONG ItemCount,
IN PUNICODE_STRING Items OPTIONAL
)
/*++
Routine Description:
This routine will do a WMI event trace.
Parameters:
WmiEventType - Event Type, valid values are:
EVENT_TRACE_TYPE_START
EVENT_TRACE_TYPE_END
EVENT_TRACE_TYPE_INFO
TraceGuid - Index in LsapTraceGuids[]
ItemCount - the number of elements in Items
Items - an array of information. The unicode strings don't have
to represent strings -- can be binary data whose length
is denoted by the Length field.
Return Values:
None.
--*/
{
#if DBG
ULONG WinError;
#endif
WCHAR NullChar = UNICODE_NULL;
PVOID BuffersToFree[10];
ULONG BuffersToFreeCount = 0;
ULONG i;
struct
{
EVENT_TRACE_HEADER EventTrace;
MOF_FIELD EventInfo[2];
} Event;
//
// Theoretically, only test LsapEventTraceFlag would be enough, since
// LsapEventTraceFlag will remain FALSE in Registry Mode, because
// LsapInitializeTrace() will never been called in Registry Mode.
// Thus nobody will change the value of LsapEventTraceFlag
//
if (!LsapEventTraceFlag) {
return;
}
//
// Fill the event information.
//
ZeroMemory(&Event, sizeof(Event));
Event.EventTrace.GuidPtr = (ULONGLONG) LsapTraceGuids[LsaTraceEventType].Guid;
Event.EventTrace.Class.Type = (UCHAR) WmiEventType;
Event.EventTrace.Flags |= (WNODE_FLAG_USE_GUID_PTR | // GUID is actually a pointer
WNODE_FLAG_TRACED_GUID); // denotes a trace
Event.EventTrace.Size = sizeof(Event.EventTrace); // no other parameters/information
if ( (LsaTraceEventType == LsaTraceEvent_LookupIsolatedNameInTrustedDomains) ) {
//
// Add the flag that indicates that there is more data
//
Event.EventTrace.Flags |= WNODE_FLAG_USE_MOF_PTR;
//
// Make sure enough space has been allocated on the stack for us
//
ASSERT(sizeof(Event.EventInfo) >= (sizeof(MOF_FIELD) * 2));
ASSERT( (ItemCount == 2) && (Items != NULL) );
//
// Fill in the data requested
//
for (i = 0; i < ItemCount; i++) {
LPWSTR String = NULL;
ULONG Length;
//
// Re'alloc to get a NULL terminated string
//
String = LsapMakeNullTerminatedString(&Items[i]);
if (NULL == String) {
String = &NullChar;
Length = sizeof(NullChar);
} else {
Length = Items[i].Length + sizeof(WCHAR);
}
Event.EventInfo[i].Length = Length;
Event.EventInfo[i].DataPtr = (ULONGLONG)String;
Event.EventTrace.Size += sizeof(Event.EventInfo[i]);
if (&NullChar != String) {
ASSERT(BuffersToFreeCount < sizeof(BuffersToFree)/sizeof(BuffersToFree[0]));
BuffersToFree[BuffersToFreeCount++] = String;
}
}
}
#if DBG
WinError =
#endif
TraceEvent(LsapTraceLoggerHandle, (PEVENT_TRACE_HEADER) &Event);
#if DBG
if (WinError != ERROR_SUCCESS)
{
DebugLog(( DEB_ERROR, "WMI TraceEvent failed, status %x\n", WinError));
}
#endif
for (i = 0; i < BuffersToFreeCount; i++) {
LsapFreeLsaHeap(BuffersToFree[i]);
}
}
LPWSTR
LsapGetClientNetworkAddress(
VOID
)
/*++
Routine Description:
This routine returns a NULL terminated string that represents the network
address of the client. If the address cannot be obtained, NULL is returned.
If the return value is non-NULL, the string must be freed with
RpcStringFreeW.
Parameters:
None.
Return Values:
See description.
--*/
{
ULONG RpcStatus;
RPC_BINDING_HANDLE ServerBinding = NULL;
PWSTR StringBinding = NULL;
LPWSTR NetworkAddr = NULL;
RpcStatus = RpcBindingServerFromClient(NULL, &ServerBinding);
if (RPC_S_OK == RpcStatus) {
RpcStatus = RpcBindingToStringBindingW(ServerBinding, &StringBinding);
if (RPC_S_OK == RpcStatus) {
RpcStatus = RpcStringBindingParseW(StringBinding,
NULL,
NULL,
&NetworkAddr,
NULL,
NULL
);
RpcStringFreeW(&StringBinding);
}
RpcBindingFree(&ServerBinding);
}
return NetworkAddr;
}
LPWSTR
LsapMakeNullTerminatedString(
IN PUNICODE_STRING u
)
/*++
Routine Description:
This routine returns a NULL terminated string composed of the data in
u. The string must be freed with LsapFreeLsaHeap().
If u->Length is 0, a non-NULL string with the NULL character as the first
character is returned.
Parameters:
u -- a unicode string
Return Values:
See description.
--*/
{
LPWSTR String = NULL;
ULONG Length;
if (u) {
Length = u->Length + sizeof(WCHAR);
String = LsapAllocateLsaHeap(Length);
if (String != NULL) {
RtlCopyMemory(String, u->Buffer, u->Length);
String[u->Length / sizeof(WCHAR)] = UNICODE_NULL;
}
}
return String;
}