[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