[PATCH 2/6] server: Fix lacuna in server side implementation of SetFileSecurity()

Paul Bryan Roberts pbronline-wine at yahoo.co.uk
Mon Nov 3 16:14:42 CST 2008


---
 dlls/advapi32/tests/security.c |  132 ++++++++++++++++++++++++++++++++++++++++
 server/file.c                  |    2 +
 server/handle.c                |    1 +
 3 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 6d7825e..5088ee0 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -697,6 +697,100 @@ static void test_luid(void)
     test_lookupPrivilegeValue();
 }
 
+/* Used in test_FileSecurity(void) to get the Security Descriptor for a file or directory */
+static void test_FileSecurity_Get(LPCSTR name, SECURITY_INFORMATION request, LPSTR *sdString)
+{
+    DWORD sdSize;
+    DWORD retSize;
+    BYTE *sd;
+    BOOL rc;
+
+    /* First attempt - pass in size 0 to get needed size out */
+    retSize = 0;
+    SetLastError (NO_ERROR);
+    rc = pGetFileSecurityA (name, request, NULL, 0, &retSize);
+    ok (!rc, "GetFileSecurityA "
+        "was expected to fail for file '%s'\n", name);
+    ok (GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetFileSecurityA "
+        "returned %d; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
+    ok (retSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA "
+        "returned size %d; expected > %d\n", retSize, sizeof (SECURITY_DESCRIPTOR));
+
+    sdSize = retSize;
+    sd = HeapAlloc (GetProcessHeap (), 0, sdSize);
+
+    /* Second attempt - get the security descriptor for real */
+    retSize = 0;
+    SetLastError (NO_ERROR);
+    rc = pGetFileSecurityA (name, request, sd, sdSize, &retSize);
+    ok (rc, "GetFileSecurityA "
+        "was not expected to fail for '%s'\n", name);
+    ok (GetLastError () == NO_ERROR, "GetFileSecurityA "
+        "returned %d; expected NO_ERROR\n", GetLastError ());
+    ok (retSize == sdSize, "GetFileSecurityA "
+        "returned size %d; expected %d\n", retSize, sdSize);
+
+    if (sd)
+        ok (ConvertSecurityDescriptorToStringSecurityDescriptorA
+            (sd, SDDL_REVISION_1, request, sdString, NULL),
+            "ConvertSecurityDescriptorToStringSecurityDescriptorA failed\n");
+
+    HeapFree (GetProcessHeap (), 0, sd);
+}
+
+/* Used in test_FileSecurity(void) to change the Security Descriptor for a file or directory */
+static void test_FileSecurity_Set(LPCSTR name, SECURITY_INFORMATION request, LPCSTR sdString, DWORD err)
+{
+    BOOL rc;
+    PSECURITY_DESCRIPTOR sd = NULL;
+
+    if (sdString)
+    {
+        ok (ConvertStringSecurityDescriptorToSecurityDescriptorA
+            (sdString, SDDL_REVISION_1, &sd, NULL),
+            "ConvertStringSecurityDescriptorToSecurityDescriptorA failed\n");
+
+        if (sd)
+        {
+            SetLastError (NO_ERROR);
+            rc = pSetFileSecurityA (name, request, sd);
+            if (err == NO_ERROR)
+            {
+                ok (rc, "SetFileSecurityA was not expected to fail for '%s' with '%s'\n", name, sdString);
+                ok (GetLastError () == NO_ERROR, "SetFileSecurityA returned %d; expected NO_ERROR\n", GetLastError ());
+            }
+            else
+            {
+                ok (!rc, "SetFileSecurityA was not expected to pass for '%s' with '%s'\n", name, sdString);
+                ok (GetLastError () == err, "SetFileSecurityA returned %d; expected %d\n", GetLastError (), err);
+            }
+        }
+    }
+}
+
+/* Used in test_FileSecurity(void) to put the Security Descriptor back to what is was before */
+static void test_FileSecurity_Put(LPCSTR name, SECURITY_INFORMATION request, LPSTR sdString)
+{
+    BOOL rc;
+    PSECURITY_DESCRIPTOR sd = NULL;
+
+    ok (ConvertStringSecurityDescriptorToSecurityDescriptorA
+        (sdString, SDDL_REVISION_1, &sd, NULL),
+        "ConvertStringSecurityDescriptorToSecurityDescriptorA failed\n");
+
+    if (sd)
+    {
+        SetLastError (NO_ERROR);
+        rc = pSetFileSecurityA (name, request, sd);
+        ok (rc, "SetFileSecurityA "
+            "was not expected to fail file '%s'\n", name);
+        ok (GetLastError () == NO_ERROR, "SetFileSecurityA "
+            "returned %d; expected NO_ERROR\n", GetLastError ());
+    }
+
+    LocalFree (sdString);
+}
+
 static void test_FileSecurity(void)
 {
     char wintmpdir [MAX_PATH];
@@ -706,6 +800,7 @@ static void test_FileSecurity(void)
     HANDLE fh;
     SECURITY_DESCRIPTOR toosmall;
     DWORD sdSize;
+    LPSTR refString, tstString;
     SECURITY_INFORMATION const request = OWNER_SECURITY_INFORMATION
                                        | GROUP_SECURITY_INFORMATION 
                                        | DACL_SECURITY_INFORMATION;
@@ -764,6 +859,43 @@ static void test_FileSecurity(void)
     ok (sdSize > sizeof (SECURITY_DESCRIPTOR), "GetFileSecurityA "
         "returned size %d; expected > %d\n", sdSize, sizeof (SECURITY_DESCRIPTOR));
 
+
+    /* Get security descriptor and write it straight back again */
+    refString = NULL;
+    test_FileSecurity_Get (file, request, &refString);
+    test_FileSecurity_Put (file, request, refString);
+
+    /* Try changing the owner - always fails ? */
+    refString = NULL;
+    test_FileSecurity_Get (file, request, &refString);
+    test_FileSecurity_Set (file, OWNER_SECURITY_INFORMATION, "O:CO", ERROR_INVALID_OWNER);
+    test_FileSecurity_Put (file, request, refString);
+
+    /* Try changing the group - always succeeds ? */
+    refString = NULL;
+    test_FileSecurity_Get (file, request, &refString);
+    test_FileSecurity_Set (file, GROUP_SECURITY_INFORMATION, "G:CG", NO_ERROR);
+    test_FileSecurity_Put (file, request, refString);
+
+    /* Try changing the read/write permissions for everyone */
+    refString = NULL;
+    test_FileSecurity_Get (file, request, &refString);
+
+    test_FileSecurity_Get (file, DACL_SECURITY_INFORMATION, &tstString);
+    if (tstString)
+    {
+        LPSTR sp = tstString;
+
+        while (*sp && *sp++ != 'F');
+
+        for ( ; *sp; sp++)
+            if (sp[0] == 'F' && sp[2] == ';')
+                sp[1] = (sp[1] == 'R') ? 'W' : 'R';
+    }
+    test_FileSecurity_Set (file, DACL_SECURITY_INFORMATION, tstString, NO_ERROR);
+
+    test_FileSecurity_Put (file, request, refString);
+
     /* Remove temporary file and directory */
     DeleteFileA (file);
     RemoveDirectoryA (path);
diff --git a/server/file.c b/server/file.c
index 5224e85..fb1035e 100644
--- a/server/file.c
+++ b/server/file.c
@@ -550,6 +550,8 @@ static int file_set_sd( struct object *obj, const struct security_descriptor *sd
         if (!obj->sd || !security_equal_sid( owner, sd_get_owner( obj->sd ) ))
         {
             /* FIXME: get Unix uid and call fchown */
+            set_error( STATUS_INVALID_OWNER );
+            return 0;
         }
     }
     else if (obj->sd)
diff --git a/server/handle.c b/server/handle.c
index 29214d6..878ed95 100644
--- a/server/handle.c
+++ b/server/handle.c
@@ -636,6 +636,7 @@ DECL_HANDLER(set_security_object)
 
     if (!(obj = get_handle_obj( current->process, req->handle, access, NULL ))) return;
 
+    obj->ops->get_sd( obj );
     obj->ops->set_sd( obj, sd, req->security_info );
     release_object( obj );
 }
-- 
1.5.4.3


--------------040806060201030006030005--



More information about the wine-patches mailing list