changeset 1208:0a803c3fb5a6

(issue138) Set the ACL explictly on existing files or directories
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 23 Sep 2014 19:15:49 +0200
parents e79fc57f1f9c
children 3815a0d2017b
files cinst/nssstore_win.c common/portpath.c common/util.c common/util.h
diffstat 4 files changed, 107 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/cinst/nssstore_win.c	Tue Sep 23 17:05:17 2014 +0200
+++ b/cinst/nssstore_win.c	Tue Sep 23 19:15:49 2014 +0200
@@ -756,6 +756,7 @@
            *path = NULL;
   HANDLE hFile = NULL;
   size_t path_len;
+  PACL access_control_list = NULL;
 
   folder_name = get_program_data_folder();
   if (!folder_name)
@@ -805,7 +806,7 @@
      it might be a symlink to another place that a users
      wants us to grant read access to or makes us overwrite
      something */
-  if(!create_restricted_directory (path, true))
+  if(!create_restricted_directory (path, true, &access_control_list))
     {
       ERRORPRINTF ("Failed to create directory\n");
       xfree(path);
@@ -816,6 +817,7 @@
     {
       ERRORPRINTF ("Failed to cat dirsep.\n");
       xfree(path);
+      LocalFree(access_control_list);
       return NULL;
     }
 
@@ -823,6 +825,7 @@
     {
       ERRORPRINTF ("Failed to cat filename.\n");
       xfree(path);
+      LocalFree(access_control_list);
       return NULL;
     }
 
@@ -844,15 +847,68 @@
                           0,
                           NULL);
     }
+  else
+    {
+      /* Opened existing file */
+      /* Set our ACL on it */
+      PSID admin_SID = NULL;
+      SID_IDENTIFIER_AUTHORITY admin_identifier = {SECURITY_NT_AUTHORITY};
+
+      /* Create the SID for the BUILTIN\Administrators group. */
+      if(!AllocateAndInitializeSid(&admin_identifier,
+                                   2,
+                                   SECURITY_BUILTIN_DOMAIN_RID, /*BUILTIN\ */
+                                   DOMAIN_ALIAS_RID_ADMINS, /*\Administrators */
+                                   0, 0, 0, 0, 0, 0, /* No other */
+                                   &admin_SID))
+        {
+          PRINTLASTERROR ("Failed to allocate admin sid.");
+          syslog_error_printf ( "Failed to allocate admin sid.");
+          if (hFile)
+            {
+              CloseHandle (hFile);
+            }
+          xfree (path);
+          LocalFree(access_control_list);
+          return NULL;
+        }
+
+      if (SetNamedSecurityInfoW (path,
+                                 SE_FILE_OBJECT,
+                                 DACL_SECURITY_INFORMATION |
+                                 OWNER_SECURITY_INFORMATION |
+                                 GROUP_SECURITY_INFORMATION,
+                                 admin_SID, /* owner */
+                                 admin_SID, /* group */
+                                 access_control_list, /* the dacl */
+                                 NULL) != ERROR_SUCCESS)
+        {
+          ERRORPRINTF ("Failed to set the ACL on the NSS instruction file.");
+          if (hFile)
+            {
+              CloseHandle (hFile);
+            }
+          FreeSid(admin_SID);
+          LocalFree(access_control_list);
+          xfree (path);
+          return NULL;
+        }
+      FreeSid(admin_SID);
+    }
+
+  LocalFree(access_control_list);
+
   if (hFile == INVALID_HANDLE_VALUE)
     {
       PRINTLASTERROR ("Failed to create file\n");
+      syslog_error_printf ( "Failed to create nss instruction file.");
       xfree(path);
       return NULL;
     }
   if (!write_instructions (to_install, hFile, false))
     {
       ERRORPRINTF ("Failed to write install instructions.\n");
+      syslog_error_printf ( "Failed to write nss instruction file.");
       CloseHandle(hFile);
       xfree(path);
       return NULL;
@@ -860,6 +916,7 @@
   if (!write_instructions (to_remove, hFile, true))
     {
       ERRORPRINTF ("Failed to write remove instructions.\n");
+      syslog_error_printf ( "Failed to write nss instruction file removal entries.");
       CloseHandle(hFile);
       xfree(path);
       return NULL;
--- a/common/portpath.c	Tue Sep 23 17:05:17 2014 +0200
+++ b/common/portpath.c	Tue Sep 23 19:15:49 2014 +0200
@@ -60,7 +60,7 @@
     {
       return false;
     }
-  ret = create_restricted_directory (wchar_path, propagate_acl);
+  ret = create_restricted_directory (wchar_path, propagate_acl, NULL);
   xfree (wchar_path);
   return ret;
 #endif
--- a/common/util.c	Tue Sep 23 17:05:17 2014 +0200
+++ b/common/util.c	Tue Sep 23 19:15:49 2014 +0200
@@ -656,7 +656,7 @@
 
 #ifdef WIN32
 bool
-create_restricted_directory (LPWSTR path, bool objects_should_inherit)
+create_restricted_directory (LPWSTR path, bool objects_should_inherit, PACL *rACL)
 {
   bool retval = false;
   PSID everyone_SID = NULL,
@@ -760,22 +760,56 @@
       DWORD err = GetLastError();
       if (err == ERROR_ALREADY_EXISTS)
         {
-          /* Verify that the directory has the correct rights */
-          // TODO (issue138)
-          retval = true;
+          if (!objects_should_inherit)
+            {
+              /* This means it is a parent directory of something and
+                 we should not touch the DACL. */
+              retval = true;
+              goto done;
+            }
+
+          /* Set our ACL on the directory */
+          err = SetNamedSecurityInfoW (path,
+                                       SE_FILE_OBJECT,
+                                       DACL_SECURITY_INFORMATION |
+                                       OWNER_SECURITY_INFORMATION |
+                                       GROUP_SECURITY_INFORMATION,
+                                       admin_SID, /* owner */
+                                       admin_SID, /* group */
+                                       access_control_list, /* the dacl */
+                                       NULL);
+          if (err != ERROR_SUCCESS)
+            {
+              ERRORPRINTF ("Failed to set security info on folder. Err: %lu", err);
+              goto done;
+            }
+        }
+      else
+        {
+          ERRORPRINTF ("Failed to create directory. Err: %lu", err);
           goto done;
         }
-      ERRORPRINTF ("Failed to create directory. Err: %lu", err);
     }
   retval = true;
 
 done:
 
+  if (retval != true)
+    {
+      ERRORPRINTF ("Failed to create directory for NSS installer instructions.");
+      syslog_error_printf ("Failed to create directory for NSS installer instructions.");
+    }
+  else if (rACL)
+    {
+      *rACL = access_control_list;
+    }
+
+
   if (everyone_SID)
     FreeSid(everyone_SID);
   if (admin_SID)
     FreeSid(admin_SID);
-  if (access_control_list)
+  if (!rACL && access_control_list)
     LocalFree(access_control_list);
   if (descriptor)
     LocalFree(descriptor);
--- a/common/util.h	Tue Sep 23 17:05:17 2014 +0200
+++ b/common/util.h	Tue Sep 23 19:15:49 2014 +0200
@@ -124,8 +124,9 @@
   * in that directory.
   * Basically a very complicated version of mkdir path -m 644
   *
-  * If the directory exists the permissions of that directory are checked if
-  * they are acceptable and true or false is returned accordingly.
+  * If the directory exists and propagate_acl is set the permissions
+  * of that directory are overwritten with the DACL that would have
+  * been used to create the directory.
   *
   * Code based on msdn example:
   * http://msdn.microsoft.com/en-us/library/windows/desktop/aa446595%28v=vs.85%29.aspx
@@ -133,12 +134,15 @@
   * @param[in] path Path of the directory to create
   * @param[in] propagate_acl weather or not objects should inherit
   * the ACL of this directory.
+  * @param[out] rACL optional pointer to an PACL pointer that should be
+  * the returned value. If rACL is not NULL the caller needs to free the
+  * returned pointer with LocalFree.
   *
   * @returns true on success of if the directory exists, false on error
   */
-bool create_restricted_directory (LPWSTR path, bool propagate_acl);
+bool create_restricted_directory (LPWSTR path, bool propagate_acl, PACL *rACL);
 
-/**@briefu Check the integrity level of the token
+/**@brief Check the integrity level of the token
   *
   * Returns true if the token has at least SECURITY_MANADTORY_HIGH_RID or
   * higher.

http://wald.intevation.org/projects/trustbridge/