Erich Hoover : advapi32: Implement SetSecurityInfo on top of NtSetSecurityObject.

Alexandre Julliard julliard at winehq.org
Fri Nov 16 13:12:52 CST 2012


Module: wine
Branch: master
Commit: d5e40b0eff65aa2d309b9e4be7d9867fd1cf7eb8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d5e40b0eff65aa2d309b9e4be7d9867fd1cf7eb8

Author: Erich Hoover <ehoover at mines.edu>
Date:   Thu Nov 15 10:16:23 2012 -0700

advapi32: Implement SetSecurityInfo on top of NtSetSecurityObject.

---

 dlls/advapi32/security.c       |   22 +++++++-
 dlls/advapi32/tests/security.c |  103 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 108 insertions(+), 17 deletions(-)

diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c
index 699c8e0..6afcc42 100644
--- a/dlls/advapi32/security.c
+++ b/dlls/advapi32/security.c
@@ -5611,9 +5611,25 @@ BOOL WINAPI FileEncryptionStatusA(LPCSTR lpFileName, LPDWORD lpStatus)
  */
 DWORD WINAPI SetSecurityInfo(HANDLE handle, SE_OBJECT_TYPE ObjectType, 
                       SECURITY_INFORMATION SecurityInfo, PSID psidOwner,
-                      PSID psidGroup, PACL pDacl, PACL pSacl) {
-    FIXME("stub\n");
-    return ERROR_SUCCESS;
+                      PSID psidGroup, PACL pDacl, PACL pSacl)
+{
+    SECURITY_DESCRIPTOR sd;
+    NTSTATUS status;
+
+    if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
+        return ERROR_INVALID_SECURITY_DESCR;
+
+    if (SecurityInfo & OWNER_SECURITY_INFORMATION)
+        SetSecurityDescriptorOwner(&sd, psidOwner, FALSE);
+    if (SecurityInfo & GROUP_SECURITY_INFORMATION)
+        SetSecurityDescriptorGroup(&sd, psidGroup, FALSE);
+    if (SecurityInfo & DACL_SECURITY_INFORMATION)
+        SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE);
+    if (SecurityInfo & SACL_SECURITY_INFORMATION)
+        SetSecurityDescriptorSacl(&sd, TRUE, pSacl, FALSE);
+
+    status = NtSetSecurityObject(handle, SecurityInfo, &sd);
+    return RtlNtStatusToDosError(status);
 }
 
 /******************************************************************************
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 844b238..da5af04 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -120,10 +120,14 @@ static BOOL (WINAPI *pSetSecurityDescriptorControl)(PSECURITY_DESCRIPTOR, SECURI
                                                     SECURITY_DESCRIPTOR_CONTROL);
 static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
                                         PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
+static DWORD (WINAPI *pSetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
+                                        PSID, PSID, PACL, PACL);
 static NTSTATUS (WINAPI *pNtAccessCheck)(PSECURITY_DESCRIPTOR, HANDLE, ACCESS_MASK, PGENERIC_MAPPING,
                                          PPRIVILEGE_SET, PULONG, PULONG, NTSTATUS*);
 static BOOL (WINAPI *pCreateRestrictedToken)(HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD,
                                              PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
+static BOOL (WINAPI *pGetAclInformation)(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS);
+static BOOL (WINAPI *pGetAce)(PACL,DWORD,LPVOID*);
 
 static HMODULE hmod;
 static int     myARGC;
@@ -174,9 +178,12 @@ static void init(void)
     pSetEntriesInAclA = (void *)GetProcAddress(hmod, "SetEntriesInAclA");
     pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
     pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo");
+    pSetSecurityInfo = (void *)GetProcAddress(hmod, "SetSecurityInfo");
     pCreateRestrictedToken = (void *)GetProcAddress(hmod, "CreateRestrictedToken");
     pConvertSidToStringSidA = (void *)GetProcAddress(hmod, "ConvertSidToStringSidA");
     pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA");
+    pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation");
+    pGetAce = (void *)GetProcAddress(hmod, "GetAce");
 
     myARGC = winetest_get_mainargs( &myARGV );
 }
@@ -3528,20 +3535,42 @@ static void test_acls(void)
 
 static void test_GetSecurityInfo(void)
 {
-    HANDLE obj;
-    PSECURITY_DESCRIPTOR sd;
+    char b[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
+    char admin_ptr[sizeof(SID)+sizeof(ULONG)*SID_MAX_SUB_AUTHORITIES], dacl[100];
+    DWORD sid_size = sizeof(admin_ptr), l = sizeof(b);
+    PSID admin_sid = (PSID) admin_ptr, user_sid;
+    char sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
+    ACL_SIZE_INFORMATION acl_size;
+    PSECURITY_DESCRIPTOR pSD;
+    ACCESS_ALLOWED_ACE *ace;
+    HANDLE token, obj;
     PSID owner, group;
-    PACL dacl;
+    BOOL bret = TRUE;
+    PACL pDacl;
     DWORD ret;
 
-    if (!pGetSecurityInfo)
+    if (!pGetSecurityInfo || !pSetSecurityInfo)
     {
-        win_skip("GetSecurityInfo is not available\n");
+        win_skip("[Get|Set]SecurityInfo is not available\n");
         return;
     }
 
+    if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &token))
+    {
+        if (GetLastError() != ERROR_NO_TOKEN) bret = FALSE;
+        else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) bret = FALSE;
+    }
+    if (!bret)
+    {
+        win_skip("Failed to get current user token\n");
+        return;
+    }
+    GetTokenInformation(token, TokenUser, b, l, &l);
+    CloseHandle( token );
+    user_sid = ((TOKEN_USER *)b)->User.Sid;
+
     /* Create something.  Files have lots of associated security info.  */
-    obj = CreateFile(myARGV[0], GENERIC_READ, FILE_SHARE_READ, NULL,
+    obj = CreateFile(myARGV[0], GENERIC_READ|WRITE_DAC, FILE_SHARE_READ, NULL,
                      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     if (obj == INVALID_HANDLE_VALUE)
     {
@@ -3551,7 +3580,7 @@ static void test_GetSecurityInfo(void)
 
     ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
                           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
-                          &owner, &group, &dacl, NULL, &sd);
+                          &owner, &group, &pDacl, NULL, &pSD);
     if (ret == ERROR_CALL_NOT_IMPLEMENTED)
     {
         win_skip("GetSecurityInfo is not implemented\n");
@@ -3559,15 +3588,15 @@ static void test_GetSecurityInfo(void)
         return;
     }
     ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
-    ok(sd != NULL, "GetSecurityInfo\n");
+    ok(pSD != NULL, "GetSecurityInfo\n");
     ok(owner != NULL, "GetSecurityInfo\n");
     ok(group != NULL, "GetSecurityInfo\n");
-    if (dacl != NULL)
-        ok(IsValidAcl(dacl), "GetSecurityInfo\n");
+    if (pDacl != NULL)
+        ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
     else
         win_skip("No ACL information returned\n");
 
-    LocalFree(sd);
+    LocalFree(pSD);
 
     if (!pCreateWellKnownSid)
     {
@@ -3580,15 +3609,61 @@ static void test_GetSecurityInfo(void)
        the other stuff, leaving us no way to free it.  */
     ret = pGetSecurityInfo(obj, SE_FILE_OBJECT,
                           OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
-                          &owner, &group, &dacl, NULL, NULL);
+                          &owner, &group, &pDacl, NULL, NULL);
     ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
     ok(owner != NULL, "GetSecurityInfo\n");
     ok(group != NULL, "GetSecurityInfo\n");
-    if (dacl != NULL)
-        ok(IsValidAcl(dacl), "GetSecurityInfo\n");
+    if (pDacl != NULL)
+        ok(IsValidAcl(pDacl), "GetSecurityInfo\n");
     else
         win_skip("No ACL information returned\n");
 
+    /* Create security descriptor information and test that it comes back the same */
+    pSD = &sd;
+    pDacl = (PACL)&dacl;
+    InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
+    pCreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size);
+    bret = InitializeAcl(pDacl, sizeof(dacl), ACL_REVISION);
+    ok(bret, "Failed to initialize ACL.\n");
+    bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, user_sid);
+    ok(bret, "Failed to add Current User to ACL.\n");
+    bret = pAddAccessAllowedAceEx(pDacl, ACL_REVISION, 0, GENERIC_ALL, admin_sid);
+    ok(bret, "Failed to add Administrator Group to ACL.\n");
+    bret = SetSecurityDescriptorDacl(pSD, TRUE, pDacl, FALSE);
+    ok(bret, "Failed to add ACL to security desciptor.\n");
+    ret = pSetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+                          NULL, NULL, pDacl, NULL);
+    ok(ret == ERROR_SUCCESS, "SetSecurityInfo returned %d\n", ret);
+    ret = pGetSecurityInfo(obj, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+                          NULL, NULL, &pDacl, NULL, NULL);
+    ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret);
+    ok(pDacl && IsValidAcl(pDacl), "GetSecurityInfo returned invalid DACL.\n");
+    bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
+    ok(bret, "GetAclInformation failed\n");
+    if (acl_size.AceCount > 0)
+    {
+        bret = pGetAce(pDacl, 0, (VOID **)&ace);
+        ok(bret, "Failed to get Current User ACE.\n");
+        bret = EqualSid(&ace->SidStart, user_sid);
+        todo_wine ok(bret, "Current User ACE != Current User SID.\n");
+        ok(((ACE_HEADER *)ace)->AceFlags == 0,
+           "Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
+        ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
+                                    ace->Mask);
+    }
+    if (acl_size.AceCount > 1)
+    {
+        bret = pGetAce(pDacl, 1, (VOID **)&ace);
+        ok(bret, "Failed to get Administators Group ACE.\n");
+        bret = EqualSid(&ace->SidStart, admin_sid);
+        todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
+        ok(((ACE_HEADER *)ace)->AceFlags == 0,
+           "Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
+        ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
+                                  ace->Mask);
+    }
+    LocalFree(pSD);
+
     CloseHandle(obj);
 }
 




More information about the wine-cvs mailing list