//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996. // // File: security.cxx // // Contents: Security-related helper functions used by the Task Scheduler // setup program to set security on the job folder. // // Classes: None. // // Functions: // // History: 23-Sep-96 AnirudhS Copied with minor modifications from // ..\job\security.cxx. // October 2001 Maxa Updated security.cxx in preparation for addition of auditing. // //---------------------------------------------------------------------------- #include #include "security.hxx" DWORD CreateAcl( OUT PACL* ppAcl, IN DWORD dwAclAceCount, IN CONST ACE_DESC* pAclAces ); //+--------------------------------------------------------------------------- // // Function: CreateSecurityDescriptor // // Synopsis: Create a security descriptor with the ACE information // specified. // // Arguments: [ppSecDesc, out] - pointer to descurity descriptor. Gets filled in if // the function does not encounter an error. // [dwDaclAceCount] - number of ACEs for the DACL. // NOTE: use -1 when you want no DACL, 0 for an empty DACL. // [pDaclAces] - pointer to ACE specification array. // [dwSaclAceCount] - number of ACEs for the DACL. // [pSaclAces] - pointer to ACE specification array. // // Returns: win32 error code // // Notes: None. // //---------------------------------------------------------------------------- DWORD CreateSecurityDescriptor( OUT PSECURITY_DESCRIPTOR* ppSecurityDescriptor, IN DWORD dwDaclAceCount, IN CONST ACE_DESC* pDaclAces, IN DWORD dwSaclAceCount, IN CONST ACE_DESC* pSaclAces ) { DWORD dwError = ERROR_SUCCESS; BOOL bSuccess; PSECURITY_DESCRIPTOR pSecurityDescriptor = 0; PACL pDacl = 0; PACL pSacl = 0; *ppSecurityDescriptor = 0; // // Create the security descriptor. // pSecurityDescriptor = LocalAlloc( LMEM_FIXED, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSecurityDescriptor == NULL) { dwError = ERROR_NOT_ENOUGH_MEMORY; goto ErrorExit; } bSuccess = InitializeSecurityDescriptor( pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); if (!bSuccess) { dwError = GetLastError(); goto ErrorExit; } if (dwDaclAceCount != DWORD(-1)) { dwError = CreateAcl( &pDacl, dwDaclAceCount, pDaclAces); if (dwError != ERROR_SUCCESS) { goto ErrorExit; } bSuccess = SetSecurityDescriptorDacl( pSecurityDescriptor, TRUE, pDacl, FALSE); if (!bSuccess) { dwError = GetLastError(); goto ErrorExit; } } if (dwSaclAceCount) { dwError = CreateAcl( &pSacl, dwSaclAceCount, pSaclAces); if (dwError != ERROR_SUCCESS) { goto ErrorExit; } bSuccess = SetSecurityDescriptorSacl( pSecurityDescriptor, TRUE, pSacl, FALSE); if (!bSuccess) { dwError = GetLastError(); goto ErrorExit; } } *ppSecurityDescriptor = pSecurityDescriptor; return ERROR_SUCCESS; ErrorExit: if (pDacl) { LocalFree(pDacl); } if (pSacl) { LocalFree(pSacl); } if (pSecurityDescriptor) { LocalFree(pSecurityDescriptor); } return dwError; } //+--------------------------------------------------------------------------- // // Function: DeleteSecurityDescriptor // // Synopsis: Deallocate the security descriptor allocated in // CreateSecurityDescriptor. // // Arguments: [pSecurityDescriptor] -- SD returned from // CreateSecurityDescriptor. // // Returns: None. // // Notes: None. // //---------------------------------------------------------------------------- void DeleteSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor) { BOOL bSuccess; BOOL fPresent; BOOL fDefaulted; PACL pAcl; if (pSecurityDescriptor == 0) { return; } pAcl = 0; bSuccess = GetSecurityDescriptorDacl( pSecurityDescriptor, &fPresent, &pAcl, &fDefaulted); if (bSuccess) { if (fPresent && pAcl != NULL) { LocalFree(pAcl); } } pAcl = 0; bSuccess = GetSecurityDescriptorSacl( pSecurityDescriptor, &fPresent, &pAcl, &fDefaulted); if (bSuccess) { if (fPresent && pAcl != NULL) { LocalFree(pAcl); } } LocalFree(pSecurityDescriptor); } //+--------------------------------------------------------------------------- // // Function: CreateAcl // // Synopsis: Creates an access control list. // // Arguments: [pAcl] -- pointer to ACL. // [dwAclAceCount]-- number of ACEs. // [pAclAces] -- ACE descriptions. // // Returns: win32 error code. // // Notes: Use LocalFree to delete pAcl once you are done with it. // //---------------------------------------------------------------------------- DWORD CreateAcl( OUT PACL* ppAcl, IN DWORD dwAclAceCount, IN CONST ACE_DESC* pAclAces ) { DWORD dwError = ERROR_SUCCESS; BOOL bSuccess; DWORD dwAclLength = sizeof(ACL); PACL pAcl = 0; CONST ACE_DESC* pAce; DWORD i; for (i=0,pAce=pAclAces;i < dwAclAceCount;i++,pAce++) { switch (pAce->Type) { case ACCESS_ALLOWED_ACE_TYPE: dwAclLength += sizeof(ACCESS_ALLOWED_ACE); break; case ACCESS_DENIED_ACE_TYPE: dwAclLength += sizeof(ACCESS_DENIED_ACE); break; case SYSTEM_AUDIT_ACE_TYPE: dwAclLength += sizeof(SYSTEM_AUDIT_ACE); break; default: dwError = ERROR_INVALID_PARAMETER; goto ErrorExit; } dwAclLength -= sizeof(DWORD); dwAclLength += GetLengthSid(pAce->pSid); } pAcl = (PACL)LocalAlloc(LMEM_FIXED, dwAclLength); if (pAcl == 0) { dwError = ERROR_NOT_ENOUGH_MEMORY; goto ErrorExit; } bSuccess = InitializeAcl( pAcl, dwAclLength, ACL_REVISION); if (!bSuccess) { dwError = GetLastError(); goto ErrorExit; } for (i=0,pAce=pAclAces;i < dwAclAceCount;i++,pAce++) { switch (pAce->Type) { case ACCESS_ALLOWED_ACE_TYPE: bSuccess = AddAccessAllowedAceEx( pAcl, ACL_REVISION, pAce->Flags, pAce->AccessMask, pAce->pSid); break; case ACCESS_DENIED_ACE_TYPE: bSuccess = AddAccessDeniedAceEx( pAcl, ACL_REVISION, pAce->Flags, pAce->AccessMask, pAce->pSid); break; case SYSTEM_AUDIT_ACE_TYPE: bSuccess = AddAuditAccessAceEx( pAcl, ACL_REVISION, pAce->Flags, pAce->AccessMask, pAce->pSid, FALSE, FALSE); break; default: dwError = ERROR_INVALID_PARAMETER; goto ErrorExit; } if (!bSuccess) { dwError = GetLastError(); goto ErrorExit; } } *ppAcl = pAcl; return ERROR_SUCCESS; ErrorExit: if (pAcl) { LocalFree(pAcl); } return dwError; } //+--------------------------------------------------------------------------- // // Function: EnablePrivilege // // Synopsis: Tries to enable / disable a privilege for the current process. // // Arguments: [pszPrivName] - name of privilege to enable / disable. // [bEnable] - enable / disable switch. // [pbWasEnabled] - optional pointer to receive the previous // state of the privilege. // // Returns: win32 error code. // //---------------------------------------------------------------------------- DWORD EnablePrivilege( IN PCWSTR pszPrivName, IN BOOL bEnable, OUT PBOOL pbWasEnabled OPTIONAL ) { DWORD dwError = ERROR_SUCCESS; BOOL bSuccess; HANDLE hToken = 0; DWORD dwSize; TOKEN_PRIVILEGES privNew; TOKEN_PRIVILEGES privOld; bSuccess = OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); if (!bSuccess) { dwError = GetLastError(); goto Cleanup; } bSuccess = LookupPrivilegeValue( 0, pszPrivName, &privNew.Privileges[0].Luid); if (!bSuccess) { dwError = GetLastError(); goto Cleanup; } privNew.PrivilegeCount = 1; privNew.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; bSuccess = AdjustTokenPrivileges( hToken, FALSE, &privNew, sizeof(privOld), &privOld, &dwSize); if (!bSuccess) { dwError = GetLastError(); goto Cleanup; } if (pbWasEnabled) { *pbWasEnabled = (privOld.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) ? TRUE : FALSE; } Cleanup: if (hToken) { CloseHandle(hToken); } return dwError; }