442 lines
9.8 KiB
C
442 lines
9.8 KiB
C
|
/*
|
||
|
* 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);
|
||
|
}
|
||
|
|