diff --git a/CHANGES b/CHANGES
index de7948800d..6004b9f09d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,11 @@
to be used frequently for root-server
addresses, which triggered re-priming. [RT #45241]
+4769. [bug] Enforce the requirement that the managed keys
+ directory (specified by "managed-keys-directory",
+ and defaulting to the working directory if not
+ specified) must be writable. [RT #46077]
+
4766. [cleanup] Addresss Coverity warnings. [RT #46150]
4763. [contrib] Improve compatibility when building MySQL DLZ
diff --git a/bin/named/server.c b/bin/named/server.c
index aa13b27878..7baafe0441 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -152,6 +152,12 @@
#define EXCLBUFFERS 4096
#endif /* TUNE_LARGE */
+#ifdef WIN32
+#define DIR_PERM_OK W_OK
+#else
+#define DIR_PERM_OK W_OK|X_OK
+#endif
+
/*%
* Check an operation for failure. Assumes that the function
* using it has a 'result' variable and a 'cleanup' label.
@@ -893,6 +899,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
const cfg_obj_t *options = NULL;
const cfg_obj_t *obj = NULL;
const char *directory;
+ isc_boolean_t need_mkey_dir = ISC_FALSE;
int i = 0;
/* We don't need trust anchors for the _bind view */
@@ -1017,11 +1024,14 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
/*
* Add key zone for managed-keys.
*/
+ need_mkey_dir = ISC_TF(auto_root || view_managed_keys != NULL);
+
obj = NULL;
(void)ns_config_get(maps, "managed-keys-directory", &obj);
directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL);
- if (directory != NULL)
+ if (directory != NULL) {
result = isc_file_isdirectory(directory);
+ }
if (result != ISC_R_SUCCESS) {
isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
@@ -1029,7 +1039,37 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
directory, isc_result_totext(result));
goto cleanup;
+ } else if (need_mkey_dir && directory != NULL) {
+ if (access(directory, DIR_PERM_OK) != 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "managed-keys-directory '%s' "
+ "is not writable", directory);
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+ } else if (need_mkey_dir) {
+ char cwd[PATH_MAX];
+
+ if (getcwd(cwd, sizeof(cwd)) == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "unable to retrieve "
+ "current working directory");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (access(cwd, DIR_PERM_OK) != 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "working directory '%s' "
+ "is not writable", cwd);
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
}
+
CHECK(add_keydata_zone(view, directory, ns_g_mctx));
cleanup:
@@ -7995,7 +8035,7 @@ load_configuration(const char *filename, ns_server_t *server,
/*
* Check that the working directory is writable.
*/
- if (access(".", W_OK) != 0) {
+ if (access(".", DIR_PERM_OK) != 0) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"the working directory is not writable");
diff --git a/bin/tests/system/mkeys/README b/bin/tests/system/mkeys/README
index 43a88471ba..5b42f38f01 100644
--- a/bin/tests/system/mkeys/README
+++ b/bin/tests/system/mkeys/README
@@ -10,9 +10,9 @@ with RFC 5011 Automated Updates of DNSSEC Trust Anchors.
ns1 is the root server that offers new KSKs and hosts one record for
testing. The TTL for the zone's records is 2 seconds.
-ns2 is a validator uses managed-keys.
-"named -T rfc5011holddown=4" switch is used so it will attempt to do
-the automated updates frequently.
+ns2 is a validator that uses managed-keys. "-T mkeytimers=2/20/40"
+is used so it will attempt do automated updates frequently. "-T tat=1"
+is used so it will send TAT queries once per second.
ns3 is a validator with a broken key in managed-keys.
diff --git a/bin/tests/system/runtime/clean.sh b/bin/tests/system/runtime/clean.sh
index 5e0e33b0c3..48a7875cab 100644
--- a/bin/tests/system/runtime/clean.sh
+++ b/bin/tests/system/runtime/clean.sh
@@ -6,6 +6,12 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+rm -f ns2/named.conf
rm -f */named.memstats
rm -f */named*.run
rm -f ns*/named.lock ns*/named*.pid ns*/other.lock
+rm -f *.pid
+rm -f rndc.out*
+[ -d ns2/nope ] && chmod 755 ns2/nope
+rm -rf ns2/nope
+rm -f ns2/dir ns2/nopedir ns2/mkd ns2/nopemkd
diff --git a/bin/tests/system/runtime/ns2/named-alt1.conf b/bin/tests/system/runtime/ns2/named-alt1.conf
index 7a0095a541..568e95d516 100644
--- a/bin/tests/system/runtime/ns2/named-alt1.conf
+++ b/bin/tests/system/runtime/ns2/named-alt1.conf
@@ -21,3 +21,12 @@ options {
dnssec-enable no;
dnssec-validation no;
};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt2.conf b/bin/tests/system/runtime/ns2/named-alt2.conf
index 1ed96d4e0c..8d981dbe44 100644
--- a/bin/tests/system/runtime/ns2/named-alt2.conf
+++ b/bin/tests/system/runtime/ns2/named-alt2.conf
@@ -21,3 +21,12 @@ options {
dnssec-enable no;
dnssec-validation no;
};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt3.conf b/bin/tests/system/runtime/ns2/named-alt3.conf
index 77b3a421f0..e1a2c54eb3 100644
--- a/bin/tests/system/runtime/ns2/named-alt3.conf
+++ b/bin/tests/system/runtime/ns2/named-alt3.conf
@@ -22,3 +22,12 @@ options {
dnssec-enable no;
dnssec-validation no;
};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt4.conf b/bin/tests/system/runtime/ns2/named-alt4.conf
new file mode 100644
index 0000000000..8b3f83eb3a
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt4.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ include "dir";
+ include "nopemkd";
+ port 5300;
+ pid-file "../named4.pid";
+ listen-on { 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation auto;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt5.conf b/bin/tests/system/runtime/ns2/named-alt5.conf
new file mode 100644
index 0000000000..a9606d1e77
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt5.conf
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ include "nopedir";
+ port 5300;
+ pid-file "../named5.pid";
+ listen-on { 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation auto;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/ns2/named-alt6.conf b/bin/tests/system/runtime/ns2/named-alt6.conf
new file mode 100644
index 0000000000..7bb7db9024
--- /dev/null
+++ b/bin/tests/system/runtime/ns2/named-alt6.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+ include "../nopedir";
+ include "mkd";
+ port 5300;
+ pid-file "../named6.pid";
+ listen-on { 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ dnssec-validation auto;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/ns2/named.conf b/bin/tests/system/runtime/ns2/named1.conf
similarity index 79%
rename from bin/tests/system/runtime/ns2/named.conf
rename to bin/tests/system/runtime/ns2/named1.conf
index 635b9a9262..0d2ceae0c3 100644
--- a/bin/tests/system/runtime/ns2/named.conf
+++ b/bin/tests/system/runtime/ns2/named1.conf
@@ -21,3 +21,12 @@ options {
dnssec-enable no;
dnssec-validation no;
};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/runtime/setup.sh b/bin/tests/system/runtime/setup.sh
index 09791719ba..bbb5bc3ef4 100644
--- a/bin/tests/system/runtime/setup.sh
+++ b/bin/tests/system/runtime/setup.sh
@@ -10,3 +10,12 @@ SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
$SHELL clean.sh
+
+cp ns2/named1.conf ns2/named.conf
+
+mkdir ns2/nope
+chmod 555 ns2/nope
+echo "directory \"`pwd`/ns2\";" > ns2/dir
+echo "directory \"`pwd`/ns2/nope\";" > ns2/nopedir
+echo "managed-keys-directory \"`pwd`/ns2\";" > ns2/mkd
+echo "managed-keys-directory \"`pwd`/ns2/nope\";" > ns2/nopemkd
diff --git a/bin/tests/system/runtime/tests.sh b/bin/tests/system/runtime/tests.sh
index 36bbca9fc8..4365bb5e55 100644
--- a/bin/tests/system/runtime/tests.sh
+++ b/bin/tests/system/runtime/tests.sh
@@ -20,17 +20,15 @@ if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
if [ ! "$CYGWIN" ]; then
-
-n=`expr $n + 1`
-echo "I:verifying that named checks for conflicting listeners ($n)"
-ret=0
-(cd ns2; $NAMED -c named-alt1.conf -D ns2-extra-1 -X other.lock -m record,size,mctx -d 99 -g -U 4 >> named2.run 2>&1 & )
-sleep 2
-grep "unable to listen on any configured interface" ns2/named2.run > /dev/null || ret=1
-[ -s ns2/named2.pid ] && $KILL -15 `cat ns2/named2.pid`
-if [ $ret != 0 ]; then echo "I:failed"; fi
-status=`expr $status + $ret`
-
+ n=`expr $n + 1`
+ echo "I:verifying that named checks for conflicting listeners ($n)"
+ ret=0
+ (cd ns2; $NAMED -c named-alt1.conf -D ns2-extra-1 -X other.lock -m record,size,mctx -d 99 -g -U 4 >> named2.run 2>&1 & )
+ sleep 2
+ grep "unable to listen on any configured interface" ns2/named2.run > /dev/null || ret=1
+ [ -s ns2/named2.pid ] && $KILL -15 `cat ns2/named2.pid`
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
fi
n=`expr $n + 1`
@@ -53,6 +51,77 @@ grep "another named process" ns2/named4.run > /dev/null && ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+n=`expr $n + 1`
+echo "I: checking that named refuses to reconfigure if managed-keys-directory is set and not writable ($n)"
+ret=0
+cp -f ns2/named-alt4.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > rndc.out.$n 2>&1
+grep "failed: permission denied" rndc.out.$n > /dev/null 2>&1 || ret=1
+sleep 1
+grep "managed-keys-directory '.*' is not writable" ns2/named.run > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: checking that named refuses to reconfigure if managed-keys-directory is unset and working directory is not writable ($n)"
+ret=0
+cp -f ns2/named-alt5.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > rndc.out.$n 2>&1
+grep "failed: permission denied" rndc.out.$n > /dev/null 2>&1 || ret=1
+sleep 1
+grep "working directory '.*' is not writable" ns2/named.run > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: checking that named reconfigures if working directory is not writable but managed-keys-directory is ($n)"
+ret=0
+cp -f ns2/named-alt6.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reconfig > rndc.out.$n 2>&1
+grep "failed: permission denied" rndc.out.$n > /dev/null 2>&1 && ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: shutting down existing named"
+[ -s named4.pid ] && kill -15 `cat named4.pid` > /dev/null 2>&1
+[ -s named5.pid ] && kill -15 `cat named5.pid` > /dev/null 2>&1
+[ -s named6.pid ] && kill -15 `cat named6.pid` > /dev/null 2>&1
+
+n=`expr $n + 1`
+echo "I: checking that named refuses to start if managed-keys-directory is set and not writable ($n)"
+ret=0
+cd ns2
+$NAMED -c named-alt4.conf -d 99 -g > named4.run 2>&1 &
+sleep 2
+grep "exiting (due to fatal error)" named4.run > /dev/null || ret=1
+[ -s named4.pid ] && kill -15 `cat named4.pid` > /dev/null 2>&1
+cd ..
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: checking that named refuses to start if managed-keys-directory is unset and working directory is not writable ($n)"
+ret=0
+cd ns2
+$NAMED -c named-alt5.conf -d 99 -g > named5.run 2>&1 &
+sleep 2
+grep "exiting (due to fatal error)" named5.run > /dev/null || ret=1
+[ -s named5.pid ] && kill -15 `cat named5.pid` > /dev/null 2>&1
+cd ..
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I: checking that named starts if managed-keys-directory is writable and working directory is not writable ($n)"
+ret=0
+cd ns2
+$NAMED -c named-alt6.conf -d 99 -g > named6.run 2>&1 &
+sleep 2
+grep "exiting (due to fatal error)" named6.run > /dev/null || ret=1
+[ -s named6.pid ] && kill -15 `cat named6.pid` > /dev/null 2>&1
+cd ..
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
echo "I:exit status: $status"
[ $status -eq 0 ] || exit 1
diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
index e215bd532a..c10918c56c 100644
--- a/doc/arm/Bv9ARM-book.xml
+++ b/doc/arm/Bv9ARM-book.xml
@@ -4804,17 +4804,17 @@ badresp:1,adberr:0,findfail:0,valfail:0]
The working directory of the server.
- Any non-absolute pathnames in the configuration file will be
- taken
- as relative to this directory. The default location for most
- server
- output files (e.g. named.run)
- is this directory.
+ Any non-absolute pathnames in the configuration file will
+ be taken as relative to this directory. The default
+ location for most server output files
+ (e.g. named.run) is this directory.
If a directory is not specified, the working directory
defaults to `.', the directory from
- which the server
- was started. The directory specified should be an absolute
- path.
+ which the server was started. The directory specified
+ should be an absolute path. It is
+ strongly recommended
+ that the directory be writable by the effective user
+ ID of the named process.
@@ -5074,7 +5074,9 @@ badresp:1,adberr:0,findfail:0,valfail:0]
Specifies the directory in which to store the files that
track managed DNSSEC keys. By default, this is the working
- directory.
+ directory. The directory must
+ be writable by the effective user ID of the
+ named process.
If named is not configured to use views,
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 6cf553a630..47700a38b3 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -164,6 +164,17 @@
bind.keys. [RT #46155]
+
+
+ named will no longer start or accept
+ reconfiguration if managed-keys or
+ dnssec-validation auto are in use and
+ the managed-keys directory (specified by
+ managed-keys-directory, and defaulting
+ to the working directory if not specified),
+ is not writable by the effective user ID. [RT #46077]
+
+
Previously, update-policy local; accepted
diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c
index 1871046cd3..6d15e0c953 100644
--- a/lib/isccfg/parser.c
+++ b/lib/isccfg/parser.c
@@ -566,7 +566,8 @@ parse2(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
if (result != ISC_R_SUCCESS) {
/* Parsing failed but no errors have been logged. */
- cfg_parser_error(pctx, 0, "parsing failed");
+ cfg_parser_error(pctx, 0, "parsing failed: %s",
+ isc_result_totext(result));
goto cleanup;
}