]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4804. [port] win32: access() does not work on directories as
authorMark Andrews <marka@isc.org>
Tue, 31 Oct 2017 22:29:24 +0000 (09:29 +1100)
committerMark Andrews <marka@isc.org>
Tue, 31 Oct 2017 22:29:24 +0000 (09:29 +1100)
                        required by POSIX.  Supply a alternative in
                        isc_file_isdirwritable. [RT #46394]

CHANGES
bin/named/server.c
bin/tests/system/runtime/setup.sh
lib/isc/include/isc/file.h
lib/isc/unix/file.c
lib/isc/win32/file.c
lib/isc/win32/libisc.def.in

diff --git a/CHANGES b/CHANGES
index e8c6361a6524b013db984e426ed3325d4b3c51c4..aa331726a665d6acab74ba04f7b6b3487142b8ee 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+4804.  [port]          win32: access() does not work on directories as
+                       required by POSIX.  Supply a alternative in
+                       isc_file_isdirwritable. [RT #46394]
+
 4803.  [placeholder]
 
 4802.  [test]          Refactor mkeys system test to make it quicker and more
index 0757785f872b5c286c40310c9137a075280294e5..b8910b4d2208a26a832e8afb37d56716ed040ce4 100644 (file)
 #define EXCLBUFFERS 4096
 #endif /* TUNE_LARGE */
 
-#ifdef WIN32
-#define DIR_PERM_OK W_OK
-#else
-#define DIR_PERM_OK W_OK|X_OK
-#endif
-
 #define MAX_TCP_TIMEOUT 65535
 
 /*%
@@ -1059,7 +1053,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
                goto cleanup;
 
        } else if (directory != NULL) {
-               if (access(directory, DIR_PERM_OK) != 0) {
+               if (!isc_file_isdirwritable(directory)) {
                        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                                      "managed-keys-directory '%s' "
@@ -6180,7 +6174,7 @@ directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
                            "option 'directory' contains relative path '%s'",
                            directory);
 
-       if (access(directory, DIR_PERM_OK) != 0) {
+       if (!isc_file_isdirwritable(directory)) {
                isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                              NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                              "directory '%s' is not writable",
@@ -7075,7 +7069,7 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
                                      dir, isc_result_totext(result));
                        return (result);
                }
-               if (access(dir, DIR_PERM_OK) != 0) {
+               if (!isc_file_isdirwritable(dir)) {
                        isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                                      NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                                      "new-zones-directory '%s' "
@@ -8516,7 +8510,7 @@ load_configuration(const char *filename, named_server_t *server,
        /*
         * Check that the working directory is writable.
         */
-       if (access(".", DIR_PERM_OK) != 0) {
+       if (!isc_file_isdirwritable(".")) {
                isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
                              NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
                              "the working directory is not writable");
index 3725a182bfb06dec24e3f7f1830c9dc77c1fcfda..5c3f768af9f68f1c9924ad54bc6d08636c27498f 100644 (file)
@@ -14,4 +14,10 @@ $SHELL clean.sh
 cp ns2/named1.conf ns2/named.conf
 
 mkdir ns2/nope
-chmod 555 ns2/nope
+
+if [ 1 = "${CYGWIN:-0}" ]
+then
+    setfacl -s user::r-x,group::r-x,other::r-x ns2/nope
+else
+    chmod 555 ns2/nope
+fi
index 58c9c1a07c5833ac35be73ad3afc46111d44edc5..370b60b1616a3ad1ef7b9eca567e5176c25e0188 100644 (file)
@@ -384,6 +384,12 @@ isc_file_sanitize(const char *dir, const char *base, const char *ext,
  * - ISC_R_NOSPACE if the resulting path would be longer than 'length'
  */
 
+isc_boolean_t
+isc_file_isdirwritable(const char *path);
+/*%<
+ *     Return true if the path is a directory and is writable
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_FILE_H */
index 841b070f59db8d81ccd8e7454e941c88bbad2de2..c7ea8c4d143ec19c42e85365e005ac2ea12cf303 100644 (file)
@@ -770,3 +770,8 @@ isc_file_sanitize(const char *dir, const char *base, const char *ext,
        strlcpy(path, buf, length);
        return (ISC_R_SUCCESS);
 }
+
+isc_boolean_t
+isc_file_isdirwritable(const char *path) {
+       return (ISC_TF(access(path, W_OK|X_OK) == 0));
+}
index cc104cf0218ac19eeed57c3ffb167e68cfb30394..ad0eac276a57d57b29a551b1111a68703b0986ff 100644 (file)
@@ -842,3 +842,85 @@ isc_file_sanitize(const char *dir, const char *base, const char *ext,
        strlcpy(path, buf, length);
        return (ISC_R_SUCCESS);
 }
+
+/*
+ * Based on http://blog.aaronballman.com/2011/08/how-to-check-access-rights/
+ */
+isc_boolean_t
+isc_file_isdirwritable(const char *path) {
+       DWORD length = 0;
+       HANDLE hToken = NULL;
+       PSECURITY_DESCRIPTOR security = NULL;
+       isc_boolean_t answer = ISC_FALSE;
+
+       if (isc_file_isdirectory(path) != ISC_R_SUCCESS) {
+               return (answer);
+       }
+
+       /*
+        * Figure out buffer size. GetFileSecurity() should not succeed.
+        */
+       if (GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
+                                 GROUP_SECURITY_INFORMATION |
+                                 DACL_SECURITY_INFORMATION,
+                           NULL, 0, &length))
+       {
+               return (answer);
+       }
+
+       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+               return (answer);
+       }
+
+       security = malloc(length);
+       if (security == NULL) {
+               return (answer);
+       }
+
+       /*
+        * GetFileSecurity() should succeed.
+        */
+       if (!GetFileSecurity(path, OWNER_SECURITY_INFORMATION |
+                                  GROUP_SECURITY_INFORMATION |
+                                  DACL_SECURITY_INFORMATION,
+                            security, length, &length))
+       {
+               return (answer);
+       }
+
+       if (OpenProcessToken(GetCurrentProcess(), TOKEN_IMPERSONATE |
+                            TOKEN_QUERY | TOKEN_DUPLICATE |
+                            STANDARD_RIGHTS_READ, &hToken))
+       {
+               HANDLE hImpersonatedToken = NULL;
+
+               if (DuplicateToken(hToken, SecurityImpersonation,
+                                  &hImpersonatedToken))
+               {
+                       GENERIC_MAPPING mapping;
+                       PRIVILEGE_SET privileges = { 0 };
+                       DWORD grantedAccess = 0;
+                       DWORD privilegesLength = sizeof(privileges);
+                       BOOL result = FALSE;
+                       DWORD genericAccessRights = GENERIC_WRITE;
+
+                       mapping.GenericRead = FILE_GENERIC_READ;
+                       mapping.GenericWrite = FILE_GENERIC_WRITE;
+                       mapping.GenericExecute = FILE_GENERIC_EXECUTE;
+                       mapping.GenericAll = FILE_ALL_ACCESS;
+
+                       MapGenericMask(&genericAccessRights, &mapping);
+                       if (AccessCheck(security, hImpersonatedToken,
+                                       genericAccessRights, &mapping,
+                                       &privileges, &privilegesLength,
+                                       &grantedAccess, &result))
+                       {
+                               answer = ISC_TF(result);
+                       }
+                       CloseHandle(hImpersonatedToken);
+               }
+               CloseHandle(hToken);
+       }
+       free(security);
+       return (answer);
+}
index 92341a7b2e9deb36c6f1bfbd84c09bd1460e5bc6..83ab3854c2a14a26ffa0d190f6ebcf694b0b00fa 100644 (file)
@@ -232,6 +232,7 @@ isc_file_isabsolute
 isc_file_ischdiridempotent
 isc_file_iscurrentdir
 isc_file_isdirectory
+isc_file_isdirwritable
 isc_file_isplainfile
 isc_file_isplainfilefd
 isc_file_mktemplate