/* * Acl.c * * Author: BreenH * * Acl utilities. */ /* * Includes */ #include "precomp.h" #include "tsutil.h" #include "tsutilnt.h" /* * Function Implementations */ BOOL WINAPI AddSidToObjectsSecurityDescriptor( HANDLE hObject, SE_OBJECT_TYPE ObjectType, PSID pSid, DWORD dwNewAccess, ACCESS_MODE AccessMode, DWORD dwInheritance ) { BOOL fRet; DWORD dwRet; EXPLICIT_ACCESS ExpAccess; PACL pNewDacl; PACL pOldDacl; PSECURITY_DESCRIPTOR pSd; // // Get the objects security descriptor and current Dacl. // pSd = NULL; pOldDacl = NULL; dwRet = GetSecurityInfo( hObject, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDacl, NULL, &pSd ); if (dwRet != ERROR_SUCCESS) { return(FALSE); } // // Initialize an EXPLICIT_ACCESS structure for the new ace. // ZeroMemory(&ExpAccess, sizeof(EXPLICIT_ACCESS)); ExpAccess.grfAccessPermissions = dwNewAccess; ExpAccess.grfAccessMode = AccessMode; ExpAccess.grfInheritance = dwInheritance; BuildTrusteeWithSid(&(ExpAccess.Trustee), pSid); // // Merge the new ace into the existing Dacl. // fRet = FALSE; dwRet = SetEntriesInAcl( 1, &ExpAccess, pOldDacl, &pNewDacl ); if (dwRet == ERROR_SUCCESS) { // // Set the new security for the object. // dwRet = SetSecurityInfo( hObject, ObjectType, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL ); if (dwRet == ERROR_SUCCESS) { fRet = TRUE; } } if (pNewDacl != NULL) { LocalFree(pNewDacl); } if (pSd != NULL) { LocalFree(pSd); } return(fRet); } BOOL WINAPI AddSidToSecurityDescriptor( PSECURITY_DESCRIPTOR *ppSd, PSID pSid, DWORD dwNewAccess, ACCESS_MODE AccessMode, DWORD dwInheritance ) { BOOL fAbsoluteSd; BOOL fDaclDefaulted; BOOL fDaclPresent; BOOL fRet; PACL pDacl; PSECURITY_DESCRIPTOR pAbsoluteSd; PSECURITY_DESCRIPTOR pOriginalSd; ASSERT(ppSd != NULL); ASSERT(*ppSd != NULL); // // The security descriptors should be absolute to allow the addition of // the new ace. // pOriginalSd = *ppSd; fAbsoluteSd = IsSecurityDescriptorAbsolute(pOriginalSd); if (!fAbsoluteSd) { fRet = ConvertSelfRelativeToAbsolute(&pAbsoluteSd, pOriginalSd); if (!fRet) { return(FALSE); } } else { pAbsoluteSd = pOriginalSd; } // // Now that the type of security descriptor is absolute, get the Dacl. // pDacl = NULL; fRet = GetSecurityDescriptorDacl( pAbsoluteSd, &fDaclPresent, &pDacl, &fDaclDefaulted ); if (fRet) { DWORD dwRet; EXPLICIT_ACCESS ExplicitAccess; PACL pNewDacl; // // Initialize an EXPLICIT_ACCESS structure for the new ace. // RtlZeroMemory(&ExplicitAccess, sizeof(EXPLICIT_ACCESS)); ExplicitAccess.grfAccessPermissions = dwNewAccess; ExplicitAccess.grfAccessMode = AccessMode; ExplicitAccess.grfInheritance = dwInheritance; BuildTrusteeWithSid(&(ExplicitAccess.Trustee), pSid); // // Merge the ace into the existing Dacl. This will allocate a new // Dacl. Unfortunately this API is only available as a WINAPI. // pNewDacl = NULL; dwRet = SetEntriesInAcl( 1, &ExplicitAccess, pDacl, &pNewDacl ); if (dwRet == ERROR_SUCCESS) { ASSERT(pNewDacl != NULL); // // Point the security descriptor's Dacl to the new Dacl. // fRet = SetSecurityDescriptorDacl( pAbsoluteSd, TRUE, pNewDacl, FALSE ); if (fRet) { PULONG_PTR pBeginning; PULONG_PTR pEnd; PULONG_PTR pPtr; // // The new Dacl has been set, free the old. Be careful here; // the RTL folks like to put absolute security descriptors in // one big allocation, just like a self-relative security // descriptor. If the old Dacl is inside the security // descriptor allocation, it cannot be freed. Essentially, // that memory becomes unused, and the security descriptor // takes up more space than necessary. // pBeginning = (PULONG_PTR)pAbsoluteSd; pEnd = (PULONG_PTR)((PBYTE)pAbsoluteSd + LocalSize(pAbsoluteSd)); pPtr = (PULONG_PTR)pDacl; if ((pPtr < pBeginning) || (pPtr > pEnd)) { LocalFree(pDacl); } } else { // // A failure occurred setting the new Dacl. This should never // occur, but if it does, free the newly created Dacl. // LocalFree(pNewDacl); } } else { fRet = FALSE; } } // // The new security descriptor should be returned in the same format as // the original security descriptor. The returned security descriptor is // also dependent on the success of the function. // if (!fAbsoluteSd) { if (fRet) { PSECURITY_DESCRIPTOR pNewSd; // // The original security descriptor was self-relative, and until // now everything has succeeded. Convert the temporary absolute // security descriptor back to self-relative form. This creates a // third security descriptor (the other two being the original // and the absolute). // pNewSd = NULL; fRet = ConvertAbsoluteToSelfRelative( &pNewSd, pAbsoluteSd, NULL ); if (fRet) { // // The final conversion was successful. Free the original // security descriptor. The absolute security descriptor is // freed later. The only possible error from destroying the // security descriptor is a version mismatch, but that would // have happened long ago. // *ppSd = pNewSd; (VOID)DestroySecurityDescriptor(&pOriginalSd); } else { // // The final conversion failed. At this point, the original // security descriptor is still intact. Free the absolute // security descriptor that was created earlier, and leave // the passed in security descriptor pointer alone. Note that // with the absolute security descriptor being freed later, // there is nothing to do here. // } } // // Regardless of success or failure, the absolute security descriptor // was created, so it must be freed. The only possible error from destroying the // security descriptor is a version mismatch, but that would // have happened long ago. // (VOID)DestroySecurityDescriptor(&pAbsoluteSd); } else { // // Regardless of what happened, there is nothing to do here. The // original security descriptor was absolute; therefore no copies // were made. The only data that changed was the Dacl, and whether // or not that succeeded is irrelevant, as that was handled above. // } return(fRet); } BOOL WINAPI ConvertAbsoluteToSelfRelative( PSECURITY_DESCRIPTOR *ppSelfRelativeSd, PSECURITY_DESCRIPTOR pAbsoluteSd, PDWORD pcbSelfRelativeSd ) { BOOL fRet; NTSTATUS Status; Status = NtConvertAbsoluteToSelfRelative( ppSelfRelativeSd, pAbsoluteSd, pcbSelfRelativeSd ); if (NT_SUCCESS(Status)) { fRet = TRUE; } else { fRet = FALSE; SetLastError(RtlNtStatusToDosError(Status)); } return(fRet); } BOOL WINAPI ConvertSelfRelativeToAbsolute( PSECURITY_DESCRIPTOR *ppAbsoluteSd, PSECURITY_DESCRIPTOR pSelfRelativeSd ) { BOOL fRet; NTSTATUS Status; Status = NtConvertSelfRelativeToAbsolute(ppAbsoluteSd, pSelfRelativeSd); if (NT_SUCCESS(Status)) { fRet = TRUE; } else { fRet = FALSE; SetLastError(RtlNtStatusToDosError(Status)); } return(fRet); } BOOL WINAPI DestroySecurityDescriptor( PSECURITY_DESCRIPTOR *ppSd ) { BOOL fRet; NTSTATUS Status; Status = NtDestroySecurityDescriptor(ppSd); if (NT_SUCCESS(Status)) { fRet = TRUE; } else { fRet = FALSE; SetLastError(RtlNtStatusToDosError(Status)); } return(fRet); } BOOL WINAPI IsSecurityDescriptorAbsolute( PSECURITY_DESCRIPTOR pSd ) { BOOLEAN fAbsolute; BOOL fRet; NTSTATUS Status; fAbsolute = FALSE; Status = NtIsSecurityDescriptorAbsolute(pSd, &fAbsolute); fRet = ((NT_SUCCESS(Status)) && fAbsolute); return(fRet); }