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:
parent
4c2cc57c7f
commit
b58577aa54
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue