windows-nt/Source/XPSP1/NT/termsrv/tsutil/acl.c
2020-09-26 16:20:57 +08:00

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);
}