ntdll: Fix handling of self-relative security descriptors for 64-bit.

This commit is contained in:
Alexandre Julliard 2009-06-16 13:29:05 +02:00
parent 3a33ff7df9
commit 2ee9118266
1 changed files with 117 additions and 129 deletions

View File

@ -45,6 +45,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
#define NT_SUCCESS(status) (status == STATUS_SUCCESS) #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
#define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
/* helper function to retrieve active length of an ACL */ /* helper function to retrieve active length of an ACL */
static size_t acl_bytesInUse(PACL pAcl) static size_t acl_bytesInUse(PACL pAcl)
{ {
@ -451,85 +453,74 @@ NTSTATUS WINAPI RtlCreateSecurityDescriptor(
*/ */
NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD) NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
{ {
SECURITY_DESCRIPTOR *srcSD = pSourceSD;
SECURITY_DESCRIPTOR *destSD = pDestinationSD;
PSID Owner, Group; PSID Owner, Group;
PACL Dacl, Sacl; PACL Dacl, Sacl;
BOOLEAN defaulted, present;
DWORD length; DWORD length;
BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
return STATUS_UNKNOWN_REVISION;
/* copy initial data */ if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
destSD->Revision = srcSD->Revision;
destSD->Sbz1 = srcSD->Sbz1;
destSD->Control = srcSD->Control;
/* copy Owner */
RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
length = RtlLengthSid(Owner);
if (isSelfRelative)
{ {
destSD->Owner = srcSD->Owner; SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner); SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
return STATUS_UNKNOWN_REVISION;
*dst = *src;
if (src->Owner)
{
Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
length = RtlLengthSid( Owner );
RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
}
if (src->Group)
{
Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
length = RtlLengthSid( Group );
RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
}
if (src->Control & SE_SACL_PRESENT)
{
Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
}
if (src->Control & SE_DACL_PRESENT)
{
Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
}
} }
else else
{ {
destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length); SECURITY_DESCRIPTOR *src = pSourceSD;
RtlCopySid(length, destSD->Owner, Owner); SECURITY_DESCRIPTOR *dst = pDestinationSD;
}
/* copy Group */ if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted); return STATUS_UNKNOWN_REVISION;
length = RtlLengthSid(Group);
if (isSelfRelative) *dst = *src;
{ if (src->Owner)
destSD->Group = srcSD->Group;
RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
}
else
{
destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
RtlCopySid(length, destSD->Group, Group);
}
/* copy Dacl */
if (srcSD->Control & SE_DACL_PRESENT)
{
RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
length = Dacl->AclSize;
if (isSelfRelative)
{ {
destSD->Dacl = srcSD->Dacl; length = RtlLengthSid( src->Owner );
copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl); dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
RtlCopySid(length, dst->Owner, src->Owner);
} }
else if (src->Group)
{ {
destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length); length = RtlLengthSid( src->Group );
copy_acl(length, destSD->Dacl, Dacl); dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
RtlCopySid(length, dst->Group, src->Group);
} }
} if (src->Control & SE_SACL_PRESENT)
/* copy Sacl */
if (srcSD->Control & SE_SACL_PRESENT)
{
RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
length = Sacl->AclSize;
if (isSelfRelative)
{ {
destSD->Sacl = srcSD->Sacl; length = src->Sacl->AclSize;
copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl); dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
copy_acl(length, dst->Sacl, src->Sacl);
} }
else if (src->Control & SE_DACL_PRESENT)
{ {
destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length); length = src->Dacl->AclSize;
copy_acl(length, destSD->Sacl, Sacl); dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
copy_acl(length, dst->Dacl, src->Dacl);
} }
} }
@ -565,31 +556,32 @@ NTSTATUS WINAPI RtlValidSecurityDescriptor(
ULONG WINAPI RtlLengthSecurityDescriptor( ULONG WINAPI RtlLengthSecurityDescriptor(
PSECURITY_DESCRIPTOR pSecurityDescriptor) PSECURITY_DESCRIPTOR pSecurityDescriptor)
{ {
SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor; ULONG size;
ULONG_PTR offset = 0;
ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
if ( lpsd == NULL ) if ( pSecurityDescriptor == NULL )
return 0; return 0;
if ( lpsd->Control & SE_SELF_RELATIVE) if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
offset = (ULONG_PTR) lpsd; {
SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
if ( lpsd->Owner != NULL ) size = sizeof(*sd);
Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset)); if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
if ( lpsd->Group != NULL ) if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset)); size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
if ( (lpsd->Control & SE_SACL_PRESENT) && size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
lpsd->Sacl != NULL ) }
Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize; else
{
if ( (lpsd->Control & SE_DACL_PRESENT) && SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
lpsd->Dacl != NULL ) size = sizeof(*sd);
Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize; if (sd->Owner) size += RtlLengthSid( sd->Owner );
if (sd->Group) size += RtlLengthSid( sd->Group );
return Size; if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
}
return size;
} }
/****************************************************************************** /******************************************************************************
@ -613,7 +605,7 @@ NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) ) if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
{ {
if ( SE_SELF_RELATIVE & lpsd->Control) if ( SE_SELF_RELATIVE & lpsd->Control)
*pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl); *pDacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Dacl );
else else
*pDacl = lpsd->Dacl; *pDacl = lpsd->Dacl;
@ -682,13 +674,12 @@ NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) ) if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
{ {
if (SE_SELF_RELATIVE & lpsd->Control) if (SE_SELF_RELATIVE & lpsd->Control)
*pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl); *pSacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Sacl );
else else
*pSacl = lpsd->Sacl; *pSacl = lpsd->Sacl;
*lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0); *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -738,16 +729,14 @@ NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
else else
*OwnerDefaulted = FALSE; *OwnerDefaulted = FALSE;
if (lpsd->Owner != NULL) if (lpsd->Control & SE_SELF_RELATIVE)
{ {
if (lpsd->Control & SE_SELF_RELATIVE) SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
*Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner); if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
else else *Owner = NULL;
*Owner = lpsd->Owner;
} }
else else
*Owner = NULL; *Owner = lpsd->Owner;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -816,15 +805,14 @@ NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
else else
*GroupDefaulted = FALSE; *GroupDefaulted = FALSE;
if (lpsd->Group != NULL) if (lpsd->Control & SE_SELF_RELATIVE)
{ {
if (lpsd->Control & SE_SELF_RELATIVE) SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
*Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group); if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
else else *Group = NULL;
*Group = lpsd->Group; }
} else
else *Group = lpsd->Group;
*Group = NULL;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -837,10 +825,10 @@ NTSTATUS WINAPI RtlMakeSelfRelativeSD(
IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
IN OUT LPDWORD lpdwBufferLength) IN OUT LPDWORD lpdwBufferLength)
{ {
ULONG_PTR offsetRel; DWORD offsetRel;
ULONG length; ULONG length;
SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor; SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor; SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength, TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
lpdwBufferLength ? *lpdwBufferLength: -1); lpdwBufferLength ? *lpdwBufferLength: -1);
@ -868,52 +856,52 @@ NTSTATUS WINAPI RtlMakeSelfRelativeSD(
pRel->Sbz1 = pAbs->Sbz1; pRel->Sbz1 = pAbs->Sbz1;
pRel->Control = pAbs->Control | SE_SELF_RELATIVE; pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
offsetRel = sizeof(SECURITY_DESCRIPTOR); offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
if (pAbs->Owner) if (pAbs->Owner)
{ {
pRel->Owner = (PSID) offsetRel; pRel->Owner = offsetRel;
length = RtlLengthSid(pAbs->Owner); length = RtlLengthSid(pAbs->Owner);
memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length); memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
offsetRel += length; offsetRel += length;
} }
else else
{ {
pRel->Owner = NULL; pRel->Owner = 0;
} }
if (pAbs->Group) if (pAbs->Group)
{ {
pRel->Group = (PSID) offsetRel; pRel->Group = offsetRel;
length = RtlLengthSid(pAbs->Group); length = RtlLengthSid(pAbs->Group);
memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length); memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
offsetRel += length; offsetRel += length;
} }
else else
{ {
pRel->Group = NULL; pRel->Group = 0;
} }
if (pAbs->Sacl) if (pAbs->Sacl)
{ {
pRel->Sacl = (PACL) offsetRel; pRel->Sacl = offsetRel;
length = pAbs->Sacl->AclSize; length = pAbs->Sacl->AclSize;
memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length); memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
offsetRel += length; offsetRel += length;
} }
else else
{ {
pRel->Sacl = NULL; pRel->Sacl = 0;
} }
if (pAbs->Dacl) if (pAbs->Dacl)
{ {
pRel->Dacl = (PACL) offsetRel; pRel->Dacl = offsetRel;
length = pAbs->Dacl->AclSize; length = pAbs->Dacl->AclSize;
memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length); memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
} }
else else
{ {
pRel->Dacl = NULL; pRel->Dacl = 0;
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -938,7 +926,7 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
{ {
NTSTATUS status = STATUS_SUCCESS; NTSTATUS status = STATUS_SUCCESS;
SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor; SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor; SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
if (!pRel || if (!pRel ||
!lpdwAbsoluteSecurityDescriptorSize || !lpdwAbsoluteSecurityDescriptorSize ||
@ -957,30 +945,30 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
} }
if (pRel->Control & SE_DACL_PRESENT && if (pRel->Control & SE_DACL_PRESENT &&
*lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize) *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
{ {
*lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize; *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
status = STATUS_BUFFER_TOO_SMALL; status = STATUS_BUFFER_TOO_SMALL;
} }
if (pRel->Control & SE_SACL_PRESENT && if (pRel->Control & SE_SACL_PRESENT &&
*lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize) *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
{ {
*lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize; *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
status = STATUS_BUFFER_TOO_SMALL; status = STATUS_BUFFER_TOO_SMALL;
} }
if (pRel->Owner && if (pRel->Owner &&
*lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel))) *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
{ {
*lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)); *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
status = STATUS_BUFFER_TOO_SMALL; status = STATUS_BUFFER_TOO_SMALL;
} }
if (pRel->Group && if (pRel->Group &&
*lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel))) *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
{ {
*lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)); *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
status = STATUS_BUFFER_TOO_SMALL; status = STATUS_BUFFER_TOO_SMALL;
} }
@ -997,7 +985,7 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
if (pRel->Control & SE_SACL_PRESENT) if (pRel->Control & SE_SACL_PRESENT)
{ {
PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel); PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
memcpy(pSacl, pAcl, pAcl->AclSize); memcpy(pSacl, pAcl, pAcl->AclSize);
pAbs->Sacl = pSacl; pAbs->Sacl = pSacl;
@ -1005,21 +993,21 @@ NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
if (pRel->Control & SE_DACL_PRESENT) if (pRel->Control & SE_DACL_PRESENT)
{ {
PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel); PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
memcpy(pDacl, pAcl, pAcl->AclSize); memcpy(pDacl, pAcl, pAcl->AclSize);
pAbs->Dacl = pDacl; pAbs->Dacl = pDacl;
} }
if (pRel->Owner) if (pRel->Owner)
{ {
PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel); PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
memcpy(pOwner, psid, RtlLengthSid(psid)); memcpy(pOwner, psid, RtlLengthSid(psid));
pAbs->Owner = pOwner; pAbs->Owner = pOwner;
} }
if (pRel->Group) if (pRel->Group)
{ {
PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel); PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
memcpy(pPrimaryGroup, psid, RtlLengthSid(psid)); memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
pAbs->Group = pPrimaryGroup; pAbs->Group = pPrimaryGroup;
} }