advapi32: Implement BuildSecurityDescriptorW.

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Andrew Wesie 2018-04-18 00:25:27 +00:00 committed by Alexandre Julliard
parent 4c2cc57c7f
commit b58577aa54
1 changed files with 164 additions and 54 deletions

View File

@ -48,6 +48,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(advapi);
static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes);
static DWORD trustee_to_sid(DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee);
typedef struct _ACEFLAG
{
@ -1255,16 +1256,122 @@ DWORD WINAPI BuildSecurityDescriptorW(
IN ULONG cCountOfAccessEntries,
IN PEXPLICIT_ACCESSW pListOfAccessEntries,
IN ULONG cCountOfAuditEntries,
IN PEXPLICIT_ACCESSW pListofAuditEntries,
IN PEXPLICIT_ACCESSW pListOfAuditEntries,
IN PSECURITY_DESCRIPTOR pOldSD,
IN OUT PULONG lpdwBufferLength,
OUT PSECURITY_DESCRIPTOR* pNewSD)
{
FIXME("(%p,%p,%d,%p,%d,%p,%p,%p,%p) stub!\n",pOwner,pGroup,
cCountOfAccessEntries,pListOfAccessEntries,cCountOfAuditEntries,
pListofAuditEntries,pOldSD,lpdwBufferLength,pNewSD);
SECURITY_DESCRIPTOR desc;
NTSTATUS status;
DWORD ret = ERROR_SUCCESS;
TRACE("(%p,%p,%d,%p,%d,%p,%p,%p,%p)\n", pOwner, pGroup,
cCountOfAccessEntries, pListOfAccessEntries, cCountOfAuditEntries,
pListOfAuditEntries, pOldSD, lpdwBufferLength, pNewSD);
return ERROR_CALL_NOT_IMPLEMENTED;
if (pOldSD)
{
SECURITY_DESCRIPTOR_CONTROL control;
DWORD desc_size, dacl_size = 0, sacl_size = 0, owner_size = 0, group_size = 0;
PACL dacl = NULL, sacl = NULL;
PSID owner = NULL, group = NULL;
DWORD revision;
if ((status = RtlGetControlSecurityDescriptor( pOldSD, &control, &revision )) != STATUS_SUCCESS)
return RtlNtStatusToDosError( status );
if (!(control & SE_SELF_RELATIVE))
return ERROR_INVALID_SECURITY_DESCR;
desc_size = sizeof(desc);
status = RtlSelfRelativeToAbsoluteSD( pOldSD, &desc, &desc_size, dacl, &dacl_size, sacl, &sacl_size,
owner, &owner_size, group, &group_size );
if (status == STATUS_BUFFER_TOO_SMALL)
{
if (dacl_size)
dacl = LocalAlloc( LMEM_FIXED, dacl_size );
if (sacl_size)
sacl = LocalAlloc( LMEM_FIXED, sacl_size );
if (owner_size)
owner = LocalAlloc( LMEM_FIXED, owner_size );
if (group_size)
group = LocalAlloc( LMEM_FIXED, group_size );
desc_size = sizeof(desc);
status = RtlSelfRelativeToAbsoluteSD( pOldSD, &desc, &desc_size, dacl, &dacl_size, sacl, &sacl_size,
owner, &owner_size, group, &group_size );
}
if (status != STATUS_SUCCESS)
{
LocalFree( dacl );
LocalFree( sacl );
LocalFree( owner );
LocalFree( group );
return RtlNtStatusToDosError( status );
}
}
else
{
if ((status = RtlCreateSecurityDescriptor( &desc, SECURITY_DESCRIPTOR_REVISION )) != STATUS_SUCCESS)
return RtlNtStatusToDosError( status );
}
if (pOwner)
{
LocalFree( desc.Owner );
desc.Owner = LocalAlloc( LMEM_FIXED, sizeof(MAX_SID) );
if ((ret = trustee_to_sid( sizeof(MAX_SID), desc.Owner, pOwner )))
goto done;
}
if (pGroup)
{
LocalFree( desc.Group );
desc.Group = LocalAlloc( LMEM_FIXED, sizeof(MAX_SID) );
if ((ret = trustee_to_sid( sizeof(MAX_SID), desc.Group, pGroup )))
goto done;
}
if (pListOfAccessEntries)
{
PACL new_dacl;
if ((ret = SetEntriesInAclW( cCountOfAccessEntries, pListOfAccessEntries, desc.Dacl, &new_dacl )))
goto done;
LocalFree( desc.Dacl );
desc.Dacl = new_dacl;
desc.Control |= SE_DACL_PRESENT;
}
if (pListOfAuditEntries)
{
PACL new_sacl;
if ((ret = SetEntriesInAclW( cCountOfAuditEntries, pListOfAuditEntries, desc.Sacl, &new_sacl )))
goto done;
LocalFree( desc.Sacl );
desc.Sacl = new_sacl;
desc.Control |= SE_SACL_PRESENT;
}
*lpdwBufferLength = RtlLengthSecurityDescriptor( &desc );
*pNewSD = LocalAlloc( LMEM_FIXED, *lpdwBufferLength );
if ((status = RtlMakeSelfRelativeSD( &desc, *pNewSD, lpdwBufferLength )) != STATUS_SUCCESS)
{
ret = RtlNtStatusToDosError( status );
LocalFree( *pNewSD );
*pNewSD = NULL;
}
done:
/* free absolute descriptor */
LocalFree( desc.Owner );
LocalFree( desc.Group );
LocalFree( desc.Sacl );
LocalFree( desc.Dacl );
return ret;
}
/******************************************************************************
@ -3754,6 +3861,56 @@ static void free_trustee_name(TRUSTEE_FORM form, WCHAR *trustee_nameW)
}
}
static DWORD trustee_to_sid( DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee )
{
if (pTrustee->MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
{
WARN("bad multiple trustee operation %d\n", pTrustee->MultipleTrusteeOperation);
return ERROR_INVALID_PARAMETER;
}
switch (pTrustee->TrusteeForm)
{
case TRUSTEE_IS_SID:
if (!CopySid(nDestinationSidLength, pDestinationSid, pTrustee->ptstrName))
{
WARN("bad sid %p\n", pTrustee->ptstrName);
return ERROR_INVALID_PARAMETER;
}
break;
case TRUSTEE_IS_NAME:
{
DWORD sid_size = nDestinationSidLength;
DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
SID_NAME_USE use;
if (!strcmpW( pTrustee->ptstrName, CURRENT_USER ))
{
if (!lookup_user_account_name( pDestinationSid, &sid_size, NULL, &domain_size, &use ))
{
return GetLastError();
}
}
else if (!LookupAccountNameW(NULL, pTrustee->ptstrName, pDestinationSid, &sid_size, NULL, &domain_size, &use))
{
WARN("bad user name %s\n", debugstr_w(pTrustee->ptstrName));
return ERROR_INVALID_PARAMETER;
}
break;
}
case TRUSTEE_IS_OBJECTS_AND_SID:
FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
break;
default:
WARN("bad trustee form %d\n", pTrustee->TrusteeForm);
return ERROR_INVALID_PARAMETER;
}
return ERROR_SUCCESS;
}
/******************************************************************************
* SetEntriesInAclA [ADVAPI32.@]
*/
@ -3849,56 +4006,9 @@ DWORD WINAPI SetEntriesInAclW( ULONG count, PEXPLICIT_ACCESSW pEntries,
pEntries[i].Trustee.TrusteeForm, pEntries[i].Trustee.TrusteeType,
pEntries[i].Trustee.ptstrName);
if (pEntries[i].Trustee.MultipleTrusteeOperation == TRUSTEE_IS_IMPERSONATE)
{
WARN("bad multiple trustee operation %d for trustee %d\n", pEntries[i].Trustee.MultipleTrusteeOperation, i);
ret = ERROR_INVALID_PARAMETER;
ret = trustee_to_sid( FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]), ppsid[i], &pEntries[i].Trustee);
if (ret)
goto exit;
}
switch (pEntries[i].Trustee.TrusteeForm)
{
case TRUSTEE_IS_SID:
if (!CopySid(FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]),
ppsid[i], pEntries[i].Trustee.ptstrName))
{
WARN("bad sid %p for trustee %d\n", pEntries[i].Trustee.ptstrName, i);
ret = ERROR_INVALID_PARAMETER;
goto exit;
}
break;
case TRUSTEE_IS_NAME:
{
DWORD sid_size = FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]);
DWORD domain_size = MAX_COMPUTERNAME_LENGTH + 1;
SID_NAME_USE use;
if (!strcmpW( pEntries[i].Trustee.ptstrName, CURRENT_USER ))
{
if (!lookup_user_account_name( ppsid[i], &sid_size, NULL, &domain_size, &use ))
{
ret = GetLastError();
goto exit;
}
}
else if (!LookupAccountNameW(NULL, pEntries[i].Trustee.ptstrName, ppsid[i], &sid_size, NULL, &domain_size, &use))
{
WARN("bad user name %s for trustee %d\n", debugstr_w(pEntries[i].Trustee.ptstrName), i);
ret = ERROR_INVALID_PARAMETER;
goto exit;
}
break;
}
case TRUSTEE_IS_OBJECTS_AND_SID:
FIXME("TRUSTEE_IS_OBJECTS_AND_SID unimplemented\n");
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
FIXME("TRUSTEE_IS_OBJECTS_AND_NAME unimplemented\n");
break;
default:
WARN("bad trustee form %d for trustee %d\n", pEntries[i].Trustee.TrusteeForm, i);
ret = ERROR_INVALID_PARAMETER;
goto exit;
}
/* Note: we overestimate the ACL size here as a tradeoff between
* instructions (simplicity) and memory */