summaryrefslogtreecommitdiffstats
path: root/private/eventlog/server/elfsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/eventlog/server/elfsec.c')
-rw-r--r--private/eventlog/server/elfsec.c920
1 files changed, 920 insertions, 0 deletions
diff --git a/private/eventlog/server/elfsec.c b/private/eventlog/server/elfsec.c
new file mode 100644
index 000000000..5d042cb38
--- /dev/null
+++ b/private/eventlog/server/elfsec.c
@@ -0,0 +1,920 @@
+
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ elfsec.c
+
+
+Author:
+
+ Dan Hinsley (danhi) 28-Mar-1992
+
+Environment:
+
+ Calls NT native APIs.
+
+Revision History:
+
+ 27-Oct-1993 danl
+ Make Eventlog service a DLL and attach it to services.exe.
+ Removed functions that create well-known SIDs. This information
+ is now passed into the Elfmain as a Global data structure containing
+ all well-known SIDs.
+ 28-Mar-1992 danhi
+ created - based on scsec.c in svcctrl by ritaw
+ 03-Mar-1995 markbl
+ Added guest & anonymous logon log access restriction feature.
+
+--*/
+
+#include <eventp.h>
+#include <elfcfg.h>
+
+#define PRIVILEGE_BUF_SIZE 512
+
+//-------------------------------------------------------------------//
+// //
+// Local function prototypes //
+// //
+//-------------------------------------------------------------------//
+
+DWORD
+ElfpGetPrivilege(
+ IN DWORD numPrivileges,
+ IN PULONG pulPrivileges
+ );
+
+DWORD
+ElfpReleasePrivilege(
+ VOID
+ );
+
+//-------------------------------------------------------------------//
+// //
+// Structure that describes the mapping of generic access rights to //
+// object specific access rights for a LogFile object. //
+// //
+//-------------------------------------------------------------------//
+
+static GENERIC_MAPPING LogFileObjectMapping = {
+
+ STANDARD_RIGHTS_READ | // Generic read
+ ELF_LOGFILE_READ,
+
+ STANDARD_RIGHTS_WRITE | // Generic write
+ ELF_LOGFILE_WRITE,
+
+ STANDARD_RIGHTS_EXECUTE | // Generic execute
+ ELF_LOGFILE_START |
+ ELF_LOGFILE_STOP |
+ ELF_LOGFILE_CONFIGURE,
+
+ ELF_LOGFILE_ALL_ACCESS // Generic all
+ };
+
+
+//-------------------------------------------------------------------//
+// //
+// Functions //
+// //
+//-------------------------------------------------------------------//
+
+NTSTATUS
+ElfpCreateLogFileObject(
+ PLOGFILE LogFile,
+ DWORD Type,
+ ULONG GuestAccessRestriction
+ )
+/*++
+
+Routine Description:
+
+ This function creates the security descriptor which represents
+ an active log file.
+
+Arguments:
+
+ LogFile - pointer the the LOGFILE structure for this logfile
+
+Return Value:
+
+
+--*/
+{
+ NTSTATUS Status;
+ DWORD NumberOfAcesToUse;
+
+#define ELF_LOGFILE_OBJECT_ACES 10 // Number of ACEs in this DACL
+
+ RTL_ACE_DATA AceData[ELF_LOGFILE_OBJECT_ACES] = {
+
+ {ACCESS_DENIED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_ALL_ACCESS, &AnonymousLogonSid},
+
+ {ACCESS_DENIED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_ALL_ACCESS, &(ElfGlobalData->AliasGuestsSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_ALL_ACCESS, &(ElfGlobalData->LocalSystemSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR, &(ElfGlobalData->AliasAdminsSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_BACKUP, &(ElfGlobalData->AliasBackupOpsSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR, &(ElfGlobalData->AliasSystemOpsSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_READ, &(ElfGlobalData->WorldSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_WRITE, &(ElfGlobalData->AliasAdminsSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_WRITE, &(ElfGlobalData->AliasSystemOpsSid)},
+
+ {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
+ ELF_LOGFILE_WRITE, &(ElfGlobalData->WorldSid)}
+ };
+
+ PRTL_ACE_DATA pAceData = NULL;
+
+ //
+ // NON_SECURE logfiles let anyone read/write to them, secure ones
+ // only let admins/local system do this. so for secure files we just
+ // don't use the last ACE
+ //
+ // Adjust the ACL start based on the passed GuestAccessRestriction flag.
+ // The first two aces deny all log access to guests and/or anonymous
+ // logons. The flag, GuestAccessRestriction, indicates that these two
+ // deny access aces should be applied. Note that the deny aces and the
+ // GuestAccessRestriction flag are not applicable to the security log,
+ // since users and anonymous logons, by default, do not have access.
+ //
+
+ switch (Type) {
+
+ case ELF_LOGFILE_SECURITY:
+ pAceData = AceData + 2; // Deny ACEs *not* applicable
+ NumberOfAcesToUse = 3;
+ break;
+
+ case ELF_LOGFILE_SYSTEM:
+ if (GuestAccessRestriction == ELF_GUEST_ACCESS_RESTRICTED) {
+ pAceData = AceData; // Deny ACEs *applicable*
+ NumberOfAcesToUse = 8;
+ }
+ else {
+ pAceData = AceData + 2; // Deny ACEs *not* applicable
+ NumberOfAcesToUse = 6;
+ }
+ break;
+
+ case ELF_LOGFILE_APPLICATION:
+ if (GuestAccessRestriction == ELF_GUEST_ACCESS_RESTRICTED) {
+ pAceData = AceData; // Deny ACEs *applicable*
+ NumberOfAcesToUse = 10;
+ }
+ else {
+ pAceData = AceData + 2; // Deny ACEs *not* applicable
+ NumberOfAcesToUse = 8;
+ }
+ break;
+
+ }
+ Status = RtlCreateUserSecurityObject(
+ pAceData,
+ NumberOfAcesToUse,
+ NULL, // Owner
+ NULL, // Group
+ TRUE, // IsDirectoryObject
+ &LogFileObjectMapping,
+ &LogFile->Sd
+ );
+
+ if (! NT_SUCCESS(Status)) {
+ ElfDbgPrintNC((
+ "[ELF] ElfpCreateLogFileObject: ElfCreateUserSecurityObject "
+ "failed - %X\n", Status));
+ }
+
+ return (Status);
+}
+
+
+VOID
+ElfpDeleteLogFileObject(
+ PLOGFILE LogFile
+ )
+/*++
+
+Routine Description:
+
+ This function deletes the self-relative security descriptor which
+ represents an eventlog logfile object.
+
+Arguments:
+
+ LogFile - pointer the the LOGFILE structure for this logfile
+
+Return Value:
+
+ None.
+
+--*/
+{
+ (void) RtlDeleteSecurityObject(&LogFile->Sd);
+}
+
+
+NTSTATUS
+ElfpAccessCheckAndAudit(
+ IN LPWSTR SubsystemName,
+ IN LPWSTR ObjectTypeName,
+ IN LPWSTR ObjectName,
+ IN OUT IELF_HANDLE ContextHandle,
+ IN PSECURITY_DESCRIPTOR SecurityDescriptor,
+ IN ACCESS_MASK DesiredAccess,
+ IN PGENERIC_MAPPING GenericMapping,
+ IN BOOL ForSecurityLog
+ )
+/*++
+
+Routine Description:
+
+ This function impersonates the caller so that it can perform access
+ validation using NtAccessCheckAndAuditAlarm; and reverts back to
+ itself before returning.
+
+Arguments:
+
+ SubsystemName - Supplies a name string identifying the subsystem
+ calling this routine.
+
+ ObjectTypeName - Supplies the name of the type of the object being
+ accessed.
+
+ ObjectName - Supplies the name of the object being accessed.
+
+ ContextHandle - Supplies the context handle to the object. On return, the
+ granted access is written to the AccessGranted field of this structure
+ if this call succeeds.
+
+ SecurityDescriptor - A pointer to the Security Descriptor against which
+ acccess is to be checked.
+
+ DesiredAccess - Supplies desired acccess mask. This mask must have been
+ previously mapped to contain no generic accesses.
+
+ GenericMapping - Supplies a pointer to the generic mapping associated
+ with this object type.
+
+ ForSecurityLog - TRUE if the access check is for the security log.
+ This is a special case that may require a privilege check.
+
+Return Value:
+
+ NT status mapped to Win32 errors.
+
+--*/
+{
+
+ NTSTATUS Status;
+ RPC_STATUS RpcStatus;
+
+ UNICODE_STRING Subsystem;
+ UNICODE_STRING ObjectType;
+ UNICODE_STRING Object;
+
+ BOOLEAN GenerateOnClose=FALSE;
+ NTSTATUS AccessStatus;
+ ACCESS_MASK GrantedAccess = 0;
+ HANDLE ClientToken = NULL;
+ PPRIVILEGE_SET pPrivilegeSet;
+ ULONG PrivilegeSetLength;
+ LUID luid = {0};
+ BOOL fResult=FALSE;
+ ULONG privileges[1];
+
+
+ GenericMapping = &LogFileObjectMapping;
+
+ PrivilegeSetLength = sizeof(PRIVILEGE_SET) + (sizeof(LUID_AND_ATTRIBUTES)*10);
+ pPrivilegeSet = (PPRIVILEGE_SET)LocalAlloc(LMEM_FIXED, PrivilegeSetLength);
+
+ if (pPrivilegeSet == NULL) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: LocalAlloc Failed %d\n",
+ GetLastError()));
+ return(GetLastError());
+ }
+
+ RtlInitUnicodeString(&Subsystem, SubsystemName);
+ RtlInitUnicodeString(&ObjectType, ObjectTypeName);
+ RtlInitUnicodeString(&Object, ObjectName);
+
+ if ((RpcStatus = RpcImpersonateClient(NULL)) != RPC_S_OK) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: Failed to impersonate "
+ "client %08lx\n", RpcStatus));
+
+ LocalFree(pPrivilegeSet);
+ return RpcStatus;
+ }
+
+ //
+ // Get a token handle for the client
+ //
+ Status = NtOpenThreadToken (
+ NtCurrentThread(),
+ TOKEN_QUERY, // DesiredAccess
+ TRUE, // OpenAsSelf
+ &ClientToken);
+ if (!NT_SUCCESS(Status)) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: NtOpenThreadToken Failed: "
+ "0x%lx\n",Status));
+
+ goto CleanExit;
+ }
+
+ //
+ // We want to see if we can get the desired access, and if we do
+ // then we also want all our other accesses granted.
+ // MAXIMUM_ALLOWED gives us this.
+ //
+ DesiredAccess |= MAXIMUM_ALLOWED;
+
+ Status = NtAccessCheck(
+ SecurityDescriptor,
+ ClientToken,
+ DesiredAccess,
+ GenericMapping,
+ pPrivilegeSet,
+ &PrivilegeSetLength,
+ &GrantedAccess,
+ &AccessStatus
+ );
+
+ if (! NT_SUCCESS(Status)) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: Error calling "
+ "NtAccessCheck %08lx\n", Status));
+ goto CleanExit;
+ }
+
+ if (AccessStatus != STATUS_SUCCESS) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: Access status is %08lx\n",
+ AccessStatus));
+
+ //
+ // MarkBl 1/30/95 : Modified this code a bit to give backup operators
+ // the ability to open the security log for purposes
+ // of backup.
+ //
+
+ if ((AccessStatus == STATUS_ACCESS_DENIED) && (ForSecurityLog))
+ {
+ //
+ // MarkBl 1/30/95 : First, evalutate the existing code (performed
+ // for read or clear access), since its
+ // privilege check is more rigorous than mine.
+ //
+
+ Status = STATUS_ACCESS_DENIED;
+
+ if (!(DesiredAccess & ELF_LOGFILE_WRITE)) {
+
+ //
+ // If read or clear access to the security log is desired,
+ // then we will see if this user passes the privilege check.
+ //
+ //
+ // Do Privilege Check for SeSecurityPrivilege
+ // (SE_SECURITY_NAME).
+ //
+ // MarkBl 1/30/95 : Modified code to fall through on error
+ // instead of the jump to 'CleanExit'.
+ //
+
+ if (LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &luid)) {
+
+ pPrivilegeSet->PrivilegeCount = 1;
+ pPrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
+ pPrivilegeSet->Privilege[0].Luid = luid;
+ pPrivilegeSet->Privilege[0].Attributes =
+ SE_PRIVILEGE_ENABLED;
+
+ if (PrivilegeCheck(
+ ClientToken,
+ pPrivilegeSet,
+ &fResult)) {
+ //
+ // If the privilege is enabled, then add READ and
+ // CLEAR to the granted access mask.
+ //
+ if (fResult) {
+ GrantedAccess |= (ELF_LOGFILE_READ |
+ ELF_LOGFILE_CLEAR);
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else {
+ //
+ // Check Failed, Now what?
+ //
+ Status = GetLastError();
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: " \
+ "PrivilegeCheck failed. status is " \
+ "%d\n",Status));
+ }
+ }
+ else {
+ Status = GetLastError();
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: " \
+ "LookupPrivilegeValue failed. status " \
+ "is %d\n",Status));
+ }
+ }
+
+ //
+ // MarkBl 1/30/95 : Finally, my code. If this user has backup
+ // privilege, let the open succeed.
+ //
+
+ if (!NT_SUCCESS(Status)) {
+
+ if (LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &luid)) {
+
+ pPrivilegeSet->PrivilegeCount = 1;
+ pPrivilegeSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
+ pPrivilegeSet->Privilege[0].Luid = luid;
+ pPrivilegeSet->Privilege[0].Attributes =
+ SE_PRIVILEGE_ENABLED;
+
+ if (PrivilegeCheck(
+ ClientToken,
+ pPrivilegeSet,
+ &fResult)) {
+ if (fResult) {
+ GrantedAccess |= ELF_LOGFILE_BACKUP;
+ Status = STATUS_SUCCESS;
+ }
+ }
+ else {
+ Status = GetLastError();
+ goto CleanExit;
+ }
+ }
+ else {
+ Status = GetLastError();
+ goto CleanExit;
+ }
+ }
+ }
+ else {
+ Status = AccessStatus;
+ }
+ }
+
+
+ //
+ // Revert to Self
+ //
+ if ((RpcStatus = RpcRevertToSelf()) != RPC_S_OK) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: Fail to revert to "
+ "self %08lx\n", RpcStatus));
+ //
+ // We don't return the error status here because we don't want
+ // to write over the other status that is being returned.
+ //
+
+ }
+
+ //
+ // Get SeAuditPrivilege so I can call NtOpenObjectAuditAlarm.
+ // If any of this stuff fails, I don't want the status to overwrite the
+ // status that I got back from the access and privilege checks.
+ //
+
+ privileges[0] = SE_AUDIT_PRIVILEGE;
+ AccessStatus = ElfpGetPrivilege( 1, privileges);
+
+ if (!NT_SUCCESS(AccessStatus)) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: ElfpGetPrivilege "
+ "(Enable) failed. Status is 0x%lx\n",AccessStatus));
+ }
+
+ //
+ // Call the Audit Alarm function.
+ //
+ GenerateOnClose = FALSE;
+ AccessStatus = NtOpenObjectAuditAlarm (
+ &Subsystem,
+ (PVOID)ContextHandle,
+ &ObjectType,
+ &Object,
+ SecurityDescriptor,
+ ClientToken, // Handle ClientToken
+ DesiredAccess,
+ GrantedAccess,
+ pPrivilegeSet, // PPRIVLEGE_SET
+ FALSE, // BOOLEAN ObjectCreation,
+ TRUE, // BOOLEAN AccessGranted,
+ &GenerateOnClose
+ );
+
+ if (!NT_SUCCESS(AccessStatus)) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: NtOpenObjectAuditAlarm "
+ "failed. status is 0x%lx\n",AccessStatus));
+ }
+ else {
+ if (GenerateOnClose) {
+ ContextHandle->Flags |= ELF_LOG_HANDLE_GENERATE_ON_CLOSE;
+ }
+ }
+
+ //
+ // Update the GrantedAccess in the context handle.
+ //
+ ContextHandle->GrantedAccess = GrantedAccess;
+
+ NtClose(ClientToken);
+
+ ElfpReleasePrivilege();
+
+ LocalFree(pPrivilegeSet);
+
+ return(Status);
+
+CleanExit:
+ //
+ // Revert to Self
+ //
+ if ((RpcStatus = RpcRevertToSelf()) != RPC_S_OK) {
+ ElfDbgPrint(("[ELF] ElfpAccessCheckAndAudit: Fail to revert to "
+ "self %08lx\n", RpcStatus));
+ //
+ // We don't return the error status here because we don't want
+ // to write over the other status that is being returned.
+ //
+
+ }
+ if (ClientToken != NULL) {
+ NtClose(ClientToken);
+ }
+
+ LocalFree(pPrivilegeSet);
+
+ return(Status);
+}
+
+VOID
+ElfpCloseAudit(
+ IN LPWSTR SubsystemName,
+ IN IELF_HANDLE ContextHandle
+ )
+
+/*++
+
+Routine Description:
+
+ If the GenerateOnClose flag in the ContextHandle is set, then this function
+ calls NtCloseAuditAlarm in order to generate a close audit for this handle.
+
+Arguments:
+
+ ContextHandle - This is a pointer to an ELF_HANDLE structure. This is the
+ handle that is being closed.
+
+Return Value:
+
+ none.
+
+--*/
+{
+ UNICODE_STRING Subsystem;
+ NTSTATUS Status;
+ NTSTATUS AccessStatus;
+ ULONG privileges[1];
+
+ RtlInitUnicodeString(&Subsystem, SubsystemName);
+
+ if (ContextHandle->Flags & ELF_LOG_HANDLE_GENERATE_ON_CLOSE) {
+ BOOLEAN WasEnabled = FALSE;
+
+ //
+ // Get Audit Privilege
+ //
+ privileges[0] = SE_AUDIT_PRIVILEGE;
+ AccessStatus = ElfpGetPrivilege( 1, privileges);
+
+ if (!NT_SUCCESS(AccessStatus)) {
+ ElfDbgPrint(("[ELF] ElfpCloseAudit: ElfpGetPrivilege "
+ "(Enable) failed. Status is 0x%lx\n",AccessStatus));
+ }
+
+ //
+ // Generate the Audit.
+ //
+ Status = NtCloseObjectAuditAlarm(
+ &Subsystem,
+ ContextHandle,
+ TRUE);
+ if (!NT_SUCCESS(Status)) {
+ ElfDbgPrint(("[ELF] ElfpCloseAudit: NtCloseObjectAuditAlarm Failed: "
+ "0x%lx\n",Status));
+ }
+
+ ContextHandle->Flags &= (~ELF_LOG_HANDLE_GENERATE_ON_CLOSE);
+
+ ElfpReleasePrivilege();
+
+#ifdef REMOVE
+ //
+ // Release Audit Privilege
+ //
+ Status = RtlAdjustPrivilege(
+ SE_AUDIT_PRIVILEGE,
+ FALSE, // Disable
+ FALSE, // Use Process's token
+ &WasEnabled);
+
+ if (!NT_SUCCESS(Status)) {
+ ElfDbgPrint(("[ELF] ElfpCloseAudit: RtlAdjustPrivilege "
+ "(Disable) failed. Status is 0x%lx\n",Status));
+ }
+#endif
+
+ }
+ return;
+}
+DWORD
+ElfpGetPrivilege(
+ IN DWORD numPrivileges,
+ IN PULONG pulPrivileges
+ )
+/*++
+
+Routine Description:
+
+ This function alters the privilege level for the current thread.
+
+ It does this by duplicating the token for the current thread, and then
+ applying the new privileges to that new token, then the current thread
+ impersonates with that new token.
+
+ Privileges can be relinquished by calling ElfpReleasePrivilege().
+
+Arguments:
+
+ numPrivileges - This is a count of the number of privileges in the
+ array of privileges.
+
+ pulPrivileges - This is a pointer to the array of privileges that are
+ desired. This is an array of ULONGs.
+
+Return Value:
+
+ NO_ERROR - If the operation was completely successful.
+
+ Otherwise, it returns mapped return codes from the various NT
+ functions that are called.
+
+--*/
+{
+ DWORD status;
+ NTSTATUS ntStatus;
+ HANDLE ourToken;
+ HANDLE newToken;
+ OBJECT_ATTRIBUTES Obja;
+ SECURITY_QUALITY_OF_SERVICE SecurityQofS;
+ ULONG bufLen;
+ ULONG returnLen;
+ PTOKEN_PRIVILEGES pPreviousState;
+ PTOKEN_PRIVILEGES pTokenPrivilege = NULL;
+ DWORD i;
+
+ //
+ // Initialize the Privileges Structure
+ //
+ pTokenPrivilege = (PTOKEN_PRIVILEGES) LocalAlloc(
+ LMEM_FIXED,
+ sizeof(TOKEN_PRIVILEGES) +
+ (sizeof(LUID_AND_ATTRIBUTES) *
+ numPrivileges)
+ );
+
+ if (pTokenPrivilege == NULL) {
+ status = GetLastError();
+ ElfDbgPrint(("[ELF] ElfpGetPrivilege:LocalAlloc Failed %d\n", status));
+ return(status);
+ }
+ pTokenPrivilege->PrivilegeCount = numPrivileges;
+ for (i=0; i<numPrivileges ;i++ ) {
+ pTokenPrivilege->Privileges[i].Luid = RtlConvertLongToLuid(
+ pulPrivileges[i]);
+ pTokenPrivilege->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
+
+ }
+
+ //
+ // Initialize Object Attribute Structure.
+ //
+ InitializeObjectAttributes(&Obja,NULL,0L,NULL,NULL);
+
+ //
+ // Initialize Security Quality Of Service Structure
+ //
+ SecurityQofS.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
+ SecurityQofS.ImpersonationLevel = SecurityImpersonation;
+ SecurityQofS.ContextTrackingMode = FALSE; // Snapshot client context
+ SecurityQofS.EffectiveOnly = FALSE;
+
+ Obja.SecurityQualityOfService = &SecurityQofS;
+
+ //
+ // Allocate storage for the structure that will hold the Previous State
+ // information.
+ //
+ pPreviousState = (PTOKEN_PRIVILEGES) LocalAlloc(
+ LMEM_FIXED,
+ PRIVILEGE_BUF_SIZE
+ );
+ if (pPreviousState == NULL) {
+
+ status = GetLastError();
+
+ ElfDbgPrint(("[ELF] ElfpGetPrivilege: LocalAlloc Failed %d\n",
+ status));
+
+ LocalFree(pTokenPrivilege);
+ return(status);
+
+ }
+
+ //
+ // Open our own Token
+ //
+ ntStatus = NtOpenProcessToken(
+ NtCurrentProcess(),
+ TOKEN_DUPLICATE,
+ &ourToken);
+
+ if (!NT_SUCCESS(ntStatus)) {
+ ElfDbgPrint(("[ELF] ElfpGetPrivilege: NtOpenThreadToken Failed "
+ "0x%lx" "\n", ntStatus));
+
+ LocalFree(pPreviousState);
+ LocalFree(pTokenPrivilege);
+ return(RtlNtStatusToDosError(ntStatus));
+ }
+
+ //
+ // Duplicate that Token
+ //
+ ntStatus = NtDuplicateToken(
+ ourToken,
+ TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+ &Obja,
+ FALSE, // Duplicate the entire token
+ TokenImpersonation, // TokenType
+ &newToken); // Duplicate token
+
+ if (!NT_SUCCESS(ntStatus)) {
+ ElfDbgPrint(("[ELF] ElfpGetPrivilege: NtDuplicateToken Failed "
+ "0x%lx" "\n", ntStatus));
+
+ LocalFree(pPreviousState);
+ LocalFree(pTokenPrivilege);
+ NtClose(ourToken);
+ return(RtlNtStatusToDosError(ntStatus));
+ }
+
+ //
+ // Add new privileges
+ //
+ bufLen = PRIVILEGE_BUF_SIZE;
+ ntStatus = NtAdjustPrivilegesToken(
+ newToken, // TokenHandle
+ FALSE, // DisableAllPrivileges
+ pTokenPrivilege, // NewState
+ bufLen, // bufferSize for previous state
+ pPreviousState, // pointer to previous state info
+ &returnLen); // numBytes required for buffer.
+
+ if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
+
+ LocalFree(pPreviousState);
+
+ bufLen = returnLen;
+
+ pPreviousState = (PTOKEN_PRIVILEGES) LocalAlloc(
+ LMEM_FIXED,
+ (UINT) bufLen
+ );
+
+ ntStatus = NtAdjustPrivilegesToken(
+ newToken, // TokenHandle
+ FALSE, // DisableAllPrivileges
+ pTokenPrivilege, // NewState
+ bufLen, // bufferSize for previous state
+ pPreviousState, // pointer to previous state info
+ &returnLen); // numBytes required for buffer.
+
+ }
+ if (!NT_SUCCESS(ntStatus)) {
+ ElfDbgPrint(("[ELF] ElfpGetPrivilege: NtAdjustPrivilegesToken Failed "
+ "0x%lx" "\n", ntStatus));
+
+ LocalFree(pPreviousState);
+ LocalFree(pTokenPrivilege);
+ NtClose(ourToken);
+ NtClose(newToken);
+ return(RtlNtStatusToDosError(ntStatus));
+ }
+
+ //
+ // Begin impersonating with the new token
+ //
+ ntStatus = NtSetInformationThread(
+ NtCurrentThread(),
+ ThreadImpersonationToken,
+ (PVOID)&newToken,
+ (ULONG)sizeof(HANDLE));
+
+ if (!NT_SUCCESS(ntStatus)) {
+ ElfDbgPrint(("[ELF] ElfpGetPrivilege: NtAdjustPrivilegesToken Failed "
+ "0x%lx" "\n", ntStatus));
+
+ LocalFree(pPreviousState);
+ LocalFree(pTokenPrivilege);
+ NtClose(ourToken);
+ NtClose(newToken);
+ return(RtlNtStatusToDosError(ntStatus));
+ }
+
+ //
+ // BUGBUG: Do I need to keep some of this around to pass to the
+ // ReleasePrivilege function?
+ //
+ LocalFree(pPreviousState);
+ LocalFree(pTokenPrivilege);
+ NtClose(ourToken);
+ NtClose(newToken);
+
+ return(NO_ERROR);
+}
+
+DWORD
+ElfpReleasePrivilege(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function relinquishes privileges obtained by calling ElfpGetPrivilege().
+
+Arguments:
+
+ none
+
+Return Value:
+
+ NO_ERROR - If the operation was completely successful.
+
+ Otherwise, it returns mapped return codes from the various NT
+ functions that are called.
+
+
+--*/
+{
+ NTSTATUS ntStatus;
+ HANDLE NewToken;
+
+
+ //
+ // BUGBUG: Do I need to Adjust the Privileges back to what they
+ // were first? (if so, I need somemore info passed to this fcn)
+ //
+
+ //
+ // Revert To Self.
+ //
+ NewToken = NULL;
+
+ ntStatus = NtSetInformationThread(
+ NtCurrentThread(),
+ ThreadImpersonationToken,
+ (PVOID)&NewToken,
+ (ULONG)sizeof(HANDLE));
+
+ if ( !NT_SUCCESS(ntStatus) ) {
+ return(RtlNtStatusToDosError(ntStatus));
+ }
+
+
+ return(NO_ERROR);
+}