[PATCH 1/2] advapi32: Implement BuildSecurityDescriptorW.
Alistair Leslie-Hughes
leslie_alistair at hotmail.com
Tue Apr 17 01:10:01 CDT 2018
From: Andrew Wesie <awesie at gmail.com>
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
dlls/advapi32/security.c | 218 +++++++++++++++++++++++++++++++++++------------
1 file changed, 164 insertions(+), 54 deletions(-)
diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c
index f081b6b..c03baa7 100644
--- a/dlls/advapi32/security.c
+++ b/dlls/advapi32/security.c
@@ -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;
- 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;
+ ret = trustee_to_sid( FIELD_OFFSET(SID, SubAuthority[SID_MAX_SUB_AUTHORITIES]), ppsid[i], &pEntries[i].Trustee);
+ if (ret)
goto exit;
- }
/* Note: we overestimate the ACL size here as a tradeoff between
* instructions (simplicity) and memory */
--
1.9.1
More information about the wine-devel
mailing list