summaryrefslogtreecommitdiffstats
path: root/private/eventlog/server/logclear.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/eventlog/server/logclear.c')
-rw-r--r--private/eventlog/server/logclear.c621
1 files changed, 621 insertions, 0 deletions
diff --git a/private/eventlog/server/logclear.c b/private/eventlog/server/logclear.c
new file mode 100644
index 000000000..a59d86748
--- /dev/null
+++ b/private/eventlog/server/logclear.c
@@ -0,0 +1,621 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ LOGCLEAR.C
+
+Abstract:
+
+ Contains functions used to log an event indicating who cleared the log.
+ This is only called after the security log has been cleared.
+
+Author:
+
+ Dan Lafferty (danl) 01-July-1994
+
+Environment:
+
+ User Mode -Win32
+
+Revision History:
+
+ 01-July-1994 danl & robertre
+ Created - Rob supplied the code which I fitted into the eventlog.
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <stdio.h>
+#include <msaudite.h>
+#include <eventp.h>
+#include <tstr.h>
+
+#define NUM_STRINGS 6
+
+//
+// Globals
+//
+ PUNICODE_STRING pGlobalComputerNameU = NULL;
+ PANSI_STRING pGlobalComputerNameA = NULL;
+
+//
+// LOCAL FUNCTION PROTOTYPES
+//
+BOOL
+GetUserInfo(
+ IN HANDLE Token,
+ OUT LPWSTR *UserName,
+ OUT LPWSTR *DomainName,
+ OUT LPWSTR *AuthenticationId,
+ OUT PSID *UserSid
+ );
+
+NTSTATUS
+ElfpGetComputerName (
+ IN LPSTR *ComputerNamePtr
+ );
+
+PUNICODE_STRING
+TmpGetComputerNameW (VOID);
+
+VOID
+w_GetComputerName ( );
+
+
+VOID
+ElfpGenerateLogClearedEvent(
+ IELF_HANDLE LogHandle
+ )
+
+/*++
+
+Routine Description:
+
+ This function generates an event indicating that the log was cleared.
+
+Arguments:
+
+ LogHandle - This is a handle to the log that the event is to be placed in.
+ It is intended that this function only be called when the SecurityLog
+ has been cleared. So it is expected the LogHandle will always be
+ a handle to the security log.
+
+Return Value:
+
+ NONE - Either it works or it doesn't. If it doesn't, there isn't much
+ we can do about it.
+
+--*/
+{
+ LPWSTR UserName=NULL;
+ LPWSTR DomainName=NULL;
+ LPWSTR AuthenticationId=NULL;
+ LPWSTR ClientUserName=NULL;
+ LPWSTR ClientDomainName=NULL;
+ LPWSTR ClientAuthenticationId=NULL;
+ PSID UserSid=NULL;
+ PSID ClientSid=NULL;
+ DWORD i;
+ BOOL Result;
+ HANDLE Token;
+ PUNICODE_STRING StringPtrArray[NUM_STRINGS];
+ UNICODE_STRING StringArray[NUM_STRINGS];
+ NTSTATUS Status;
+ LARGE_INTEGER Time;
+ ULONG EventTime;
+ PUNICODE_STRING pComputerNameU;
+
+ Result = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &Token );
+
+ if (!Result) {
+ ElfDbgPrint(("OpenProcessToken failed, error = %d",GetLastError()));
+ return;
+ }
+
+ Result = GetUserInfo(
+ Token,
+ &UserName,
+ &DomainName,
+ &AuthenticationId,
+ &UserSid );
+
+ CloseHandle( Token );
+
+ if (!Result) {
+ ElfDbgPrint(("1st GetUserInfo ret'd %d\n",GetLastError()));
+ return;
+ }
+
+ ElfDbgPrint(("\nGetUserInfo ret'd \nUserName = %ws, "
+ "\nDomainName = %ws, \nAuthenticationId = %ws\n",
+ UserName, DomainName, AuthenticationId ));
+
+ Result = OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, FALSE, &Token );
+
+ if (Result) {
+
+ Result = GetUserInfo(
+ Token,
+ &ClientUserName,
+ &ClientDomainName,
+ &ClientAuthenticationId,
+ &ClientSid );
+
+ CloseHandle( Token );
+
+ if (!Result) {
+ ElfDbgPrint(("2nd GetUserInfo ret'd %d\n",GetLastError()));
+ goto CleanExit;
+ }
+
+ } else {
+
+ //
+ // Either got access denied or we're not impersonating.
+ // Use dash strings either way.
+ //
+
+ ClientUserName = L"-";
+ ClientDomainName = L"-";
+ ClientAuthenticationId = L"-";
+ }
+
+ ElfDbgPrint(("\nGetUserInfo ret'd \nUserName = %ws, "
+ "\nDomainName = %ws, \nAuthenticationId = %ws\n",
+ ClientUserName, ClientDomainName, ClientAuthenticationId ));
+
+
+ RtlInitUnicodeString( &StringArray[0], UserName );
+ RtlInitUnicodeString( &StringArray[1], DomainName );
+ RtlInitUnicodeString( &StringArray[2], AuthenticationId );
+ RtlInitUnicodeString( &StringArray[3], ClientUserName );
+ RtlInitUnicodeString( &StringArray[4], ClientDomainName );
+ RtlInitUnicodeString( &StringArray[5], ClientAuthenticationId );
+
+ //
+ // Create an array of pointers to UNICODE_STRINGs.
+ //
+ for (i=0; i<NUM_STRINGS; i++) {
+ StringPtrArray[i] = &StringArray[i];
+ }
+
+ //
+ // Generate the time of the event. This is done on the client side
+ // since that is where the event occurred.
+ //
+ NtQuerySystemTime(&Time);
+ RtlTimeToSecondsSince1970(&Time,
+ &EventTime
+ );
+ //
+ // Generate the ComputerName of the client.
+ // We have to do this in the client side since this call may be
+ // remoted to another server and we would not necessarily have
+ // the computer name there.
+ //
+ pComputerNameU = TmpGetComputerNameW();
+
+ Status = ElfrReportEventW (
+ LogHandle, // Log Handle
+ EventTime, // Time
+ EVENTLOG_AUDIT_SUCCESS, // Event Type
+ (USHORT)SE_CATEGID_SYSTEM, // Event Category
+ SE_AUDITID_AUDIT_LOG_CLEARED, // EventID
+ NUM_STRINGS, // NumStrings
+ 0, // DataSize
+ pComputerNameU, // pComputerNameU
+ UserSid, // UserSid
+ StringPtrArray, // *Strings
+ NULL, // Data
+ 0, // Flags
+ NULL, // RecordNumber
+ NULL // TimeWritten
+ );
+
+CleanExit:
+ //
+ // We only come down this path if we know for sure that these
+ // first three have been allocated.
+ //
+ ElfpFreeBuffer(UserName);
+ ElfpFreeBuffer(DomainName);
+ ElfpFreeBuffer(AuthenticationId);
+
+ if (UserSid != NULL) {
+ ElfpFreeBuffer(UserSid);
+ }
+ if (ClientUserName != NULL) {
+ ElfpFreeBuffer(ClientUserName);
+ }
+ if (ClientDomainName != NULL) {
+ ElfpFreeBuffer(ClientDomainName);
+ }
+ if (ClientAuthenticationId != NULL) {
+ ElfpFreeBuffer(ClientAuthenticationId);
+ }
+ if (ClientSid != NULL) {
+ ElfpFreeBuffer(ClientSid);
+ }
+}
+
+BOOL
+GetUserInfo(
+ IN HANDLE Token,
+ OUT LPWSTR *UserName,
+ OUT LPWSTR *DomainName,
+ OUT LPWSTR *AuthenticationId,
+ OUT PSID *UserSid
+ )
+/*++
+
+Routine Description:
+
+ This function gathers information about the user identified with the
+ token.
+
+Arguments:
+ Token - This token identifies the entity for which we are gathering
+ information.
+ UserName - This is the entity's user name.
+ DomainName - This is the entity's domain name.
+ AuthenticationId - This is the entity's Authentication ID.
+ UserSid - This is the entity's SID.
+
+NOTE:
+ Memory is allocated by this routine for UserName, DomainName,
+ AuthenticationId, and UserSid. It is the caller's responsibility to
+ free this memory.
+
+Return Value:
+ TRUE - If the operation was successful. It is possible that
+ UserSid did not get allocated in the successful case. Therefore,
+ the caller should test prior to freeing.
+ FALSE - If unsuccessful. No memory is allocated in this case.
+
+
+--*/
+{
+ PTOKEN_USER Buffer=NULL;
+// WCHAR User[256];
+ LPWSTR Domain = NULL;
+ LPWSTR AccountName = NULL;
+ SID_NAME_USE Use;
+ BOOL Result;
+ DWORD RequiredLength;
+ DWORD AccountNameSize;
+ DWORD DomainNameSize;
+ TOKEN_STATISTICS Statistics;
+ WCHAR LogonIdString[256];
+ DWORD Status=ERROR_SUCCESS;
+
+
+ *UserSid = NULL;
+
+ Result = GetTokenInformation ( Token, TokenUser, NULL, 0, &RequiredLength );
+
+ if (!Result) {
+
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+
+ Buffer = ElfpAllocateBuffer((RequiredLength+1)*sizeof(WCHAR) );
+
+ Result = GetTokenInformation ( Token,
+ TokenUser,
+ Buffer,
+ RequiredLength,
+ &RequiredLength
+ );
+
+ if (!Result) {
+ ElfDbgPrint(("2nd GetTokenInformation failed, "
+ "error = %d\n",GetLastError()));
+ return( FALSE );
+ }
+
+ } else {
+
+ DbgPrint("1st GetTokenInformation failed, error = %d\n",GetLastError());
+ return( FALSE );
+ }
+ }
+
+
+ if (!Result) {
+ goto ErrorCleanup;
+ }
+
+ AccountNameSize = 0;
+ DomainNameSize = 0;
+
+ Result = LookupAccountSidW( L"",
+ Buffer->User.Sid,
+ NULL,
+ &AccountNameSize,
+ NULL,
+ &DomainNameSize,
+ &Use
+ );
+
+ if (!Result) {
+
+ if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
+
+ AccountName = ElfpAllocateBuffer((AccountNameSize+1)*sizeof(WCHAR) );
+ Domain = ElfpAllocateBuffer((DomainNameSize+1)*sizeof(WCHAR) );
+
+ if ( AccountName == NULL ) {
+ ElfDbgPrint(("LocalAlloc failed allocating %d bytes, "
+ "error = %d\n",AccountNameSize,GetLastError()));
+ goto ErrorCleanup;
+ }
+
+ if ( Domain == NULL ) {
+ ElfDbgPrint(("LocalAlloc failed allocating %d bytes, "
+ "error = %d\n",DomainNameSize,GetLastError()));
+ goto ErrorCleanup;
+ }
+
+ Result = LookupAccountSidW( L"",
+ Buffer->User.Sid,
+ AccountName,
+ &AccountNameSize,
+ Domain,
+ &DomainNameSize,
+ &Use
+ );
+ if (!Result) {
+
+ ElfDbgPrint(("2nd LookupAccountSid failed, "
+ "error = %d\n",GetLastError()));
+ goto ErrorCleanup;
+ }
+
+ } else {
+
+ ElfDbgPrint(("1st LookupAccountSid failed, "
+ "error = %d\n",GetLastError()));
+ goto ErrorCleanup;
+ }
+
+ } else {
+
+ ElfDbgPrint(("LookupAccountSid succeeded unexpectedly\n"));
+ goto ErrorCleanup;
+ }
+
+ ElfDbgPrint(("Name = %ws\\%ws\n",Domain,AccountName));
+
+ Result = GetTokenInformation ( Token, TokenStatistics, &Statistics, sizeof( Statistics ), &RequiredLength );
+
+ if (!Result) {
+ ElfDbgPrint(("GetTokenInformation failed, error = %d\n",GetLastError()));
+ goto ErrorCleanup;
+ }
+
+ swprintf(LogonIdString, L"(0x%X,0x%X)",Statistics.AuthenticationId.HighPart, Statistics.AuthenticationId.LowPart );
+ ElfDbgPrint(("LogonIdString = %ws\n",LogonIdString));
+
+ *AuthenticationId = ElfpAllocateBuffer(WCSSIZE(LogonIdString));
+ if (*AuthenticationId == NULL) {
+ ElfDbgPrint(("[ELF]GetUserInfo: Failed to allocate buffer "
+ "for AuthenticationId %d\n",GetLastError()));
+ goto ErrorCleanup;
+ }
+ wcscpy(*AuthenticationId, LogonIdString);
+
+ //
+ // Return accumulated information
+ //
+
+ *UserSid = ElfpAllocateBuffer(GetLengthSid( Buffer->User.Sid ) );
+
+ Result = CopySid( GetLengthSid( Buffer->User.Sid ), *UserSid, Buffer->User.Sid );
+
+ ElfpFreeBuffer(Buffer);
+
+ *DomainName = Domain;
+ *UserName = AccountName;
+
+ return( TRUE );
+
+ErrorCleanup:
+
+ if (Buffer != NULL) {
+ ElfpFreeBuffer( Buffer );
+ }
+
+ if (Domain != NULL) {
+ ElfpFreeBuffer( Domain );
+ }
+
+ if (AccountName != NULL) {
+ ElfpFreeBuffer( AccountName );
+ }
+
+ if (*UserSid != NULL) {
+ ElfpFreeBuffer( *UserSid );
+ }
+
+ if (*AuthenticationId != NULL) {
+ ElfpFreeBuffer( *AuthenticationId );
+ }
+
+ return( FALSE );
+}
+
+NTSTATUS
+ElfpGetComputerName (
+ IN LPSTR *ComputerNamePtr)
+
+/*++
+
+Routine Description:
+
+ This routine obtains the computer name from a persistent database,
+ by calling the GetcomputerNameA Win32 Base API
+
+ This routine assumes the length of the computername is no greater
+ than MAX_COMPUTERNAME_LENGTH, space for which it allocates using
+ LocalAlloc. It is necessary for the user to free that space using
+ ElfpFreeBuffer when finished.
+
+Arguments:
+
+ ComputerNamePtr - This is a pointer to the location where the pointer
+ to the computer name is to be placed.
+
+Return Value:
+
+ NERR_Success - If the operation was successful.
+
+ It will return assorted Net or Win32 or NT error messages if not.
+
+--*/
+{
+ DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
+
+ //
+ // Allocate a buffer to hold the largest possible computer name.
+ //
+
+ *ComputerNamePtr = ElfpAllocateBuffer(nSize);
+
+ if (*ComputerNamePtr == NULL) {
+ return (GetLastError());
+ }
+
+ //
+ // Get the computer name string into the locally allocated buffer
+ // by calling the Win32 GetComputerNameA API.
+ //
+
+ if (!GetComputerNameA(*ComputerNamePtr, &nSize)) {
+ ElfpFreeBuffer(*ComputerNamePtr);
+ *ComputerNamePtr = NULL;
+ return (GetLastError());
+ }
+
+ return (ERROR_SUCCESS);
+}
+
+VOID
+w_GetComputerName ( )
+
+/*++
+
+Routine Description:
+
+ This routine gets the name of the computer. It checks the global
+ variable to see if the computer name has already been determined.
+ If not, it updates that variable with the name.
+ It does this for the UNICODE and the ANSI versions.
+
+Arguments:
+
+ NONE
+
+Return Value:
+
+ NONE
+
+
+--*/
+{
+ PUNICODE_STRING pNameU=NULL;
+ PANSI_STRING pNameA=NULL;
+ LPSTR pName;
+ NTSTATUS Error;
+ NTSTATUS Status;
+
+
+ if (pGlobalComputerNameU != NULL) {
+ return;
+ }
+ pNameU = ElfpAllocateBuffer (sizeof (UNICODE_STRING));
+ pNameA = ElfpAllocateBuffer (sizeof (ANSI_STRING));
+
+ if ((pNameU != NULL) && (pNameA != NULL)) {
+
+ if ((Error = ElfpGetComputerName (&pName)) == ERROR_SUCCESS) {
+
+ //
+ // ElfpComputerName has allocated a buffer to contain the
+ // ASCII name of the computer. We use that for the ANSI
+ // string structure.
+ //
+ RtlInitAnsiString ( pNameA, pName );
+
+ } else {
+ //
+ // We could not get the computer name for some reason. Set up
+ // the golbal pointer to point to the NULL string.
+ //
+ RtlInitAnsiString ( pNameA, "\0");
+ }
+
+ //
+ // Set up the UNICODE_STRING structure.
+ //
+ Status = RtlAnsiStringToUnicodeString (
+ pNameU,
+ pNameA,
+ TRUE
+ );
+
+ //
+ // If there was no error, set the global variables.
+ // Otherwise, free the buffer allocated by ElfpGetComputerName
+ // and leave the global variables unchanged.
+ //
+ if (NT_SUCCESS(Status)) {
+
+ pGlobalComputerNameU = pNameU; // Set global variable if no error
+ pGlobalComputerNameA = pNameA; // Set global ANSI variable
+
+ } else {
+
+ ElfDbgPrint(("[ELFCLNT] GetComputerName - Error 0x%lx\n", Status));
+ ElfpFreeBuffer(pName);
+ ElfpFreeBuffer (pNameU); // Free the buffers
+ ElfpFreeBuffer (pNameA);
+ }
+
+ }
+}
+
+
+PUNICODE_STRING
+TmpGetComputerNameW ( )
+
+/*++
+
+Routine Description:
+
+ This routine gets the UNICODE name of the computer. It checks the global
+ variable to see if the computer name has already been determined.
+ If not, it calls the worker routine to do that.
+
+Arguments:
+
+ NONE
+
+Return Value:
+
+ Returns a pointer to the computer name, or a NULL.
+
+
+--*/
+{
+ if (pGlobalComputerNameU == NULL) {
+ w_GetComputerName();
+ }
+ return (pGlobalComputerNameU);
+}
+
+
+