BIND 10 master, updated. d185c72f14dab4b4ca10dd01e6ea9b7aeb42b2df Changelog
BIND 10 source code commits
bind10-changes at lists.isc.org
Sat Jul 16 08:24:54 UTC 2011
The branch, master has been updated
via d185c72f14dab4b4ca10dd01e6ea9b7aeb42b2df (commit)
via 50070c824270d5da1db0b716db73b726d458e9f7 (commit)
via 66ebc54e863f58b86c3ae65ca9f4764906c9a348 (commit)
via 3912ef9b24104abea0e9344ff24deeed700712e3 (commit)
via 5471e816ab36a6182b2223dea461fc8d086ed9e7 (commit)
via 686ed44b82c009ddb63ed064d46ce44fcade5fbe (commit)
via f551799e8c3de59be0a6a7c5168194b93987e876 (commit)
via bb1028fd4f52135f4a2c8175d9bf1b90043df1cc (commit)
via 582348ce86ac20e0bb92079e5f15ba9b05f60a66 (commit)
via 92bf1032800f3365a5d8eb5052a2a045495ca646 (commit)
via ebc15cde7e0fa14a61127be51267a5ad0c430f90 (commit)
via df79b8d3306394ae123fb4c558f7239146e9f0d6 (commit)
via 6d784213ea929dfa06099d7d85ed87709a7f408e (commit)
via e77575c3c85c7e219137b2c616ad104e5b28eb20 (commit)
via 49f1d2d2e7f75432465ddd4acae2579c018aab33 (commit)
via ed9c17ed1627872d701c76336aff407d3ad5c44e (commit)
via b0e38303e79e2a487e37a9dcadd5f1730cdeae9e (commit)
via 93145c09728dbfb7fe5bd77b5a3671e911c41deb (commit)
via 1c1bd99f0add79535b62f6723d7e942661007653 (commit)
via 1d03e4212cffa7fcf57d0f3a4fcdc1920c959e40 (commit)
from 7d85a63f7bd3ef5926b92dd8f7d9c1588cf6e286 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d185c72f14dab4b4ca10dd01e6ea9b7aeb42b2df
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Sat Jul 16 10:23:47 2011 +0200
Changelog
commit 50070c824270d5da1db0b716db73b726d458e9f7
Merge: 7d85a63f7bd3ef5926b92dd8f7d9c1588cf6e286 66ebc54e863f58b86c3ae65ca9f4764906c9a348
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Sat Jul 16 10:14:08 2011 +0200
Merge branch 'work/xfroutacl'
Conflicts:
src/bin/xfrout/tests/xfrout_test.py.in
commit 66ebc54e863f58b86c3ae65ca9f4764906c9a348
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Sat Jul 16 10:12:47 2011 +0200
[772] Small cleanups
commit 3912ef9b24104abea0e9344ff24deeed700712e3
Merge: 5471e816ab36a6182b2223dea461fc8d086ed9e7 686ed44b82c009ddb63ed064d46ce44fcade5fbe
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri Jul 15 21:10:30 2011 +0200
Merge branch 'trac772' of git+ssh://git.bind10.isc.org/var/bind10/git/bind10 into work/xfroutacl
commit 5471e816ab36a6182b2223dea461fc8d086ed9e7
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri Jul 15 21:07:57 2011 +0200
[trac772] More review comments
commit 686ed44b82c009ddb63ed064d46ce44fcade5fbe
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Fri Jul 15 11:23:13 2011 -0700
[trac772] minor editorial fix.
commit f551799e8c3de59be0a6a7c5168194b93987e876
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri Jul 15 12:06:13 2011 +0200
[trac772] Comment update
commit bb1028fd4f52135f4a2c8175d9bf1b90043df1cc
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Fri Jul 15 11:51:52 2011 +0200
[trac772] Address review comments
commit 582348ce86ac20e0bb92079e5f15ba9b05f60a66
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Thu Jul 14 15:08:40 2011 -0700
[trac772] some more trivial editorial fixes
commit 92bf1032800f3365a5d8eb5052a2a045495ca646
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Thu Jul 14 14:32:39 2011 -0700
[trac772] trivial editorial cleanup
commit ebc15cde7e0fa14a61127be51267a5ad0c430f90
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Thu Jul 14 12:55:34 2011 -0700
[trac772] fix usual MacOS build failure: add lib/acl/.libs to
LIBRARY_PATH_PLACEHOLDER
commit df79b8d3306394ae123fb4c558f7239146e9f0d6
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jul 13 13:07:05 2011 +0200
[trac772] Logging
commit 6d784213ea929dfa06099d7d85ed87709a7f408e
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jul 13 13:06:30 2011 +0200
[trac772] Send the response based on ACL
commit e77575c3c85c7e219137b2c616ad104e5b28eb20
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jul 13 12:49:48 2011 +0200
[trac772] Perform the ACL check
commit 49f1d2d2e7f75432465ddd4acae2579c018aab33
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jul 13 12:08:54 2011 +0200
[trac772] Propagate the ACL as well
commit ed9c17ed1627872d701c76336aff407d3ad5c44e
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Wed Jul 13 11:55:04 2011 +0200
[trac772] Propagate the remote endpoint to XfrOut session
commit b0e38303e79e2a487e37a9dcadd5f1730cdeae9e
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jul 11 14:55:26 2011 +0200
[trac772] Loading of ACL from configuration
commit 93145c09728dbfb7fe5bd77b5a3671e911c41deb
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jul 11 14:39:50 2011 +0200
[trac772] Default ACL
commit 1c1bd99f0add79535b62f6723d7e942661007653
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jul 11 13:57:24 2011 +0200
[trac772] Add ACL to spec file
commit 1d03e4212cffa7fcf57d0f3a4fcdc1920c959e40
Author: Michal 'vorner' Vaner <michal.vaner at nic.cz>
Date: Mon Jul 11 13:46:54 2011 +0200
[trac772] Comment cleanup
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 6 ++
src/bin/xfrout/tests/Makefile.am | 2 +-
src/bin/xfrout/tests/xfrout_test.py.in | 115 ++++++++++++++++++++++++++------
src/bin/xfrout/xfrout.py.in | 98 +++++++++++++++++++--------
src/bin/xfrout/xfrout.spec.pre.in | 26 +++++--
src/bin/xfrout/xfrout_messages.mes | 11 +++
6 files changed, 200 insertions(+), 58 deletions(-)
-----------------------------------------------------------------------
diff --git a/ChangeLog b/ChangeLog
index fc9e8b4..9c1926a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+273. [func] vorner
+ It is possible to specify ACL for the xfrout module. It is in the ACL
+ configuration key and has the usual ACL syntax. It currently supports
+ only the source address currently. Default ACL accepts everything.
+ (Trac #772, git 50070c824270d5da1db0b716db73b726d458e9f7)
+
272. [func] jinmei
libdns++/pydnspp: TSIG signing now handles truncated DNS messages
(i.e. with TC bit on) with TSIG correctly.
diff --git a/src/bin/xfrout/tests/Makefile.am b/src/bin/xfrout/tests/Makefile.am
index 6ca2b42..99f4843 100644
--- a/src/bin/xfrout/tests/Makefile.am
+++ b/src/bin/xfrout/tests/Makefile.am
@@ -6,7 +6,7 @@ EXTRA_DIST = $(PYTESTS)
# required by loadable python modules.
LIBRARY_PATH_PLACEHOLDER =
if SET_ENV_LIBRARY_PATH
-LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
+LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/acl/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs:$(abs_top_builddir)/src/lib/util/io/.libs:$$$(ENV_LIBRARY_PATH)
endif
# test using command-line arguments, so use check-local target instead of TESTS
diff --git a/src/bin/xfrout/tests/xfrout_test.py.in b/src/bin/xfrout/tests/xfrout_test.py.in
index 7ab4a58..a41e0ed 100644
--- a/src/bin/xfrout/tests/xfrout_test.py.in
+++ b/src/bin/xfrout/tests/xfrout_test.py.in
@@ -24,6 +24,7 @@ from pydnspp import *
from xfrout import *
import xfrout
import isc.log
+import isc.acl.dns
TSIG_KEY = TSIGKey("example.com:SFuWd/q99SzF8Yzd1QbB9g==")
@@ -117,8 +118,11 @@ class TestXfroutSession(unittest.TestCase):
def setUp(self):
self.sock = MySocket(socket.AF_INET,socket.SOCK_STREAM)
- #self.log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False )
- self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(), TSIGKeyRing())
+ self.xfrsess = MyXfroutSession(self.sock, None, Dbserver(),
+ TSIGKeyRing(), ('127.0.0.1', 12345),
+ # When not testing ACLs, simply accept
+ isc.acl.dns.REQUEST_LOADER.load(
+ [{"action": "ACCEPT"}]))
self.mdata = bytes(b'\xd6=\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\xfc\x00\x01')
self.soa_record = (4, 3, 'example.com.', 'com.example.', 3600, 'SOA', None, 'master.example.com. admin.example.com. 1234 3600 1800 2419200 7200')
@@ -138,6 +142,36 @@ class TestXfroutSession(unittest.TestCase):
self.assertEqual(rcode.to_text(), "NOERROR")
self.assertTrue(self.xfrsess._tsig_ctx is not None)
+ # ACL checks, put some ACL inside
+ self.xfrsess._acl = isc.acl.dns.REQUEST_LOADER.load([
+ {
+ "from": "127.0.0.1",
+ "action": "ACCEPT"
+ },
+ {
+ "from": "192.0.2.1",
+ "action": "DROP"
+ }
+ ])
+ # Localhost (the default in this test) is accepted
+ rcode, msg = self.xfrsess._parse_query_message(self.mdata)
+ self.assertEqual(rcode.to_text(), "NOERROR")
+ # This should be dropped completely, therefore returning None
+ self.xfrsess._remote = ('192.0.2.1', 12345)
+ rcode, msg = self.xfrsess._parse_query_message(self.mdata)
+ self.assertEqual(None, rcode)
+ # This should be refused, therefore REFUSED
+ self.xfrsess._remote = ('192.0.2.2', 12345)
+ rcode, msg = self.xfrsess._parse_query_message(self.mdata)
+ self.assertEqual(rcode.to_text(), "REFUSED")
+ # If the TSIG check fails, it should not check ACL
+ # (If it checked ACL as well, it would just drop the request)
+ self.xfrsess._remote = ('192.0.2.1', 12345)
+ self.xfrsess._tsig_key_ring = TSIGKeyRing()
+ rcode, msg = self.xfrsess._parse_query_message(request_data)
+ self.assertEqual(rcode.to_text(), "NOTAUTH")
+ self.assertTrue(self.xfrsess._tsig_ctx is not None)
+
def test_get_query_zone_name(self):
msg = self.getmsg()
self.assertEqual(self.xfrsess._get_query_zone_name(msg), "example.com.")
@@ -196,20 +230,6 @@ class TestXfroutSession(unittest.TestCase):
self.assertEqual(msg.get_rcode(), rcode)
self.assertTrue(msg.get_header_flag(Message.HEADERFLAG_AA))
- def test_reply_query_with_format_error(self):
- msg = self.getmsg()
- self.xfrsess._reply_query_with_format_error(msg, self.sock)
- get_msg = self.sock.read_msg()
- self.assertEqual(get_msg.get_rcode().to_text(), "FORMERR")
-
- # tsig signed message
- msg = self.getmsg()
- self.xfrsess._tsig_ctx = self.create_mock_tsig_ctx(TSIGError.NOERROR)
- self.xfrsess._reply_query_with_format_error(msg, self.sock)
- get_msg = self.sock.read_msg()
- self.assertEqual(get_msg.get_rcode().to_text(), "FORMERR")
- self.assertTrue(self.message_has_tsig(get_msg))
-
def test_create_rrset_from_db_record(self):
rrset = self.xfrsess._create_rrset_from_db_record(self.soa_record)
self.assertEqual(rrset.get_name().to_text(), "example.com.")
@@ -516,18 +536,42 @@ class MyCCSession():
class MyUnixSockServer(UnixSockServer):
def __init__(self):
- self._lock = threading.Lock()
- self._transfers_counter = 0
self._shutdown_event = threading.Event()
self._max_transfers_out = 10
self._cc = MyCCSession()
- #self._log = isc.log.NSLogger('xfrout', '', severity = 'critical', log_to_console = False )
+ self._common_init()
class TestUnixSockServer(unittest.TestCase):
def setUp(self):
self.write_sock, self.read_sock = socket.socketpair()
self.unix = MyUnixSockServer()
+ def test_guess_remote(self):
+ """Test we can guess the remote endpoint when we have only the
+ file descriptor. This is needed, because we get only that one
+ from auth."""
+ # We test with UDP, as it can be "connected" without other
+ # endpoint
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ sock.connect(('127.0.0.1', 12345))
+ self.assertEqual(('127.0.0.1', 12345),
+ self.unix._guess_remote(sock.fileno()))
+ if socket.has_ipv6:
+ # Don't check IPv6 address on hosts not supporting them
+ sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+ sock.connect(('::1', 12345))
+ self.assertEqual(('::1', 12345, 0, 0),
+ self.unix._guess_remote(sock.fileno()))
+ # Try when pretending there's no IPv6 support
+ # (No need to pretend when there's really no IPv6)
+ xfrout.socket.has_ipv6 = False
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ sock.connect(('127.0.0.1', 12345))
+ self.assertEqual(('127.0.0.1', 12345),
+ self.unix._guess_remote(sock.fileno()))
+ # Return it back
+ xfrout.socket.has_ipv6 = True
+
def test_receive_query_message(self):
send_msg = b"\xd6=\x00\x00\x00\x01\x00"
msg_len = struct.pack('H', socket.htons(len(send_msg)))
@@ -536,15 +580,34 @@ class TestUnixSockServer(unittest.TestCase):
recv_msg = self.unix._receive_query_message(self.read_sock)
self.assertEqual(recv_msg, send_msg)
- def test_updata_config_data(self):
+ def check_default_ACL(self):
+ context = isc.acl.dns.RequestContext(socket.getaddrinfo("127.0.0.1",
+ 1234, 0, 0, 0,
+ socket.AI_NUMERICHOST)[0][4])
+ self.assertEqual(isc.acl.acl.ACCEPT, self.unix._acl.execute(context))
+
+ def check_loaded_ACL(self):
+ context = isc.acl.dns.RequestContext(socket.getaddrinfo("127.0.0.1",
+ 1234, 0, 0, 0,
+ socket.AI_NUMERICHOST)[0][4])
+ self.assertEqual(isc.acl.acl.ACCEPT, self.unix._acl.execute(context))
+ context = isc.acl.dns.RequestContext(socket.getaddrinfo("192.0.2.1",
+ 1234, 0, 0, 0,
+ socket.AI_NUMERICHOST)[0][4])
+ self.assertEqual(isc.acl.acl.REJECT, self.unix._acl.execute(context))
+
+ def test_update_config_data(self):
+ self.check_default_ACL()
tsig_key_str = 'example.com:SFuWd/q99SzF8Yzd1QbB9g=='
tsig_key_list = [tsig_key_str]
bad_key_list = ['bad..example.com:SFuWd/q99SzF8Yzd1QbB9g==']
self.unix.update_config_data({'transfers_out':10 })
self.assertEqual(self.unix._max_transfers_out, 10)
self.assertTrue(self.unix.tsig_key_ring is not None)
+ self.check_default_ACL()
- self.unix.update_config_data({'transfers_out':9, 'tsig_key_ring':tsig_key_list})
+ self.unix.update_config_data({'transfers_out':9,
+ 'tsig_key_ring':tsig_key_list})
self.assertEqual(self.unix._max_transfers_out, 9)
self.assertEqual(self.unix.tsig_key_ring.size(), 1)
self.unix.tsig_key_ring.remove(Name("example.com."))
@@ -555,6 +618,16 @@ class TestUnixSockServer(unittest.TestCase):
self.assertRaises(None, self.unix.update_config_data(config_data))
self.assertEqual(self.unix.tsig_key_ring.size(), 0)
+ # Load the ACL
+ self.unix.update_config_data({'query_acl': [{'from': '127.0.0.1',
+ 'action': 'ACCEPT'}]})
+ self.check_loaded_ACL()
+ # Pass a wrong data there and check it does not replace the old one
+ self.assertRaises(isc.acl.acl.LoaderError,
+ self.unix.update_config_data,
+ {'query_acl': ['Something bad']})
+ self.check_loaded_ACL()
+
def test_get_db_file(self):
self.assertEqual(self.unix.get_db_file(), "initdb.file")
diff --git a/src/bin/xfrout/xfrout.py.in b/src/bin/xfrout/xfrout.py.in
index b44b099..2e94369 100755
--- a/src/bin/xfrout/xfrout.py.in
+++ b/src/bin/xfrout/xfrout.py.in
@@ -48,6 +48,9 @@ except ImportError as e:
# must keep running, so we warn about it and move forward.
log.error(XFROUT_IMPORT, str(e))
+from isc.acl.acl import ACCEPT, REJECT, DROP
+from isc.acl.dns import REQUEST_LOADER
+
isc.util.process.rename()
def init_paths():
@@ -92,16 +95,16 @@ def get_rrset_len(rrset):
class XfroutSession():
- def __init__(self, sock_fd, request_data, server, tsig_key_ring):
- # The initializer for the superclass may call functions
- # that need _log to be set, so we set it first
+ def __init__(self, sock_fd, request_data, server, tsig_key_ring, remote,
+ acl):
self._sock_fd = sock_fd
self._request_data = request_data
self._server = server
- #self._log = log
self._tsig_key_ring = tsig_key_ring
self._tsig_ctx = None
self._tsig_len = 0
+ self._remote = remote
+ self._acl = acl
self.handle()
def create_tsig_ctx(self, tsig_record, tsig_key_ring):
@@ -114,7 +117,7 @@ class XfroutSession():
self.dns_xfrout_start(self._sock_fd, self._request_data)
#TODO, avoid catching all exceptions
except Exception as e:
- logger.error(XFROUT_HANDLE_QUERY_ERROR, str(e))
+ logger.error(XFROUT_HANDLE_QUERY_ERROR, e)
pass
os.close(self._sock_fd)
@@ -141,8 +144,25 @@ class XfroutSession():
# TSIG related checks
rcode = self._check_request_tsig(msg, mdata)
+ if rcode == Rcode.NOERROR():
+ # ACL checks
+ acl_result = self._acl.execute(
+ isc.acl.dns.RequestContext(self._remote))
+ if acl_result == DROP:
+ logger.info(XFROUT_QUERY_DROPPED,
+ self._get_query_zone_name(msg),
+ self._get_query_zone_class(msg),
+ self._remote[0], self._remote[1])
+ return None, None
+ elif acl_result == REJECT:
+ logger.info(XFROUT_QUERY_REJECTED,
+ self._get_query_zone_name(msg),
+ self._get_query_zone_class(msg),
+ self._remote[0], self._remote[1])
+ return Rcode.REFUSED(), msg
+
except Exception as err:
- logger.error(XFROUT_PARSE_QUERY_ERROR, str(err))
+ logger.error(XFROUT_PARSE_QUERY_ERROR, err)
return Rcode.FORMERR(), None
return rcode, msg
@@ -183,18 +203,11 @@ class XfroutSession():
def _reply_query_with_error_rcode(self, msg, sock_fd, rcode_):
- msg.make_response()
- msg.set_rcode(rcode_)
- self._send_message(sock_fd, msg, self._tsig_ctx)
-
-
- def _reply_query_with_format_error(self, msg, sock_fd):
- '''query message format isn't legal.'''
if not msg:
return # query message is invalid. send nothing back.
msg.make_response()
- msg.set_rcode(Rcode.FORMERR())
+ msg.set_rcode(rcode_)
self._send_message(sock_fd, msg, self._tsig_ctx)
def _zone_has_soa(self, zone):
@@ -244,10 +257,13 @@ class XfroutSession():
def dns_xfrout_start(self, sock_fd, msg_query):
rcode_, msg = self._parse_query_message(msg_query)
#TODO. create query message and parse header
- if rcode_ == Rcode.NOTAUTH():
+ if rcode_ is None: # Dropped by ACL
+ return
+ elif rcode_ == Rcode.NOTAUTH() or rcode_ == Rcode.REFUSED():
return self._reply_query_with_error_rcode(msg, sock_fd, rcode_)
elif rcode_ != Rcode.NOERROR():
- return self._reply_query_with_format_error(msg, sock_fd)
+ return self._reply_query_with_error_rcode(msg, sock_fd,
+ Rcode.FORMERR())
zone_name = self._get_query_zone_name(msg)
zone_class_str = self._get_query_zone_class(msg)
@@ -257,7 +273,7 @@ class XfroutSession():
if rcode_ != Rcode.NOERROR():
logger.info(XFROUT_AXFR_TRANSFER_FAILED, zone_name,
zone_class_str, rcode_.to_text())
- return self. _reply_query_with_error_rcode(msg, sock_fd, rcode_)
+ return self._reply_query_with_error_rcode(msg, sock_fd, rcode_)
try:
logger.info(XFROUT_AXFR_TRANSFER_STARTED, zone_name, zone_class_str)
@@ -375,14 +391,20 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
self._sock_file = sock_file
socketserver_mixin.NoPollMixIn.__init__(self)
ThreadingUnixStreamServer.__init__(self, sock_file, handle_class)
- self._lock = threading.Lock()
- self._transfers_counter = 0
self._shutdown_event = shutdown_event
self._write_sock, self._read_sock = socket.socketpair()
- #self._log = log
+ self._common_init()
self.update_config_data(config_data)
self._cc = cc
+ def _common_init(self):
+ self._lock = threading.Lock()
+ self._transfers_counter = 0
+ # This default value will probably get overwritten by the (same)
+ # default value from the spec file. This is here just to make
+ # sure and to make the default value in tests consistent.
+ self._acl = REQUEST_LOADER.load('[{"action": "ACCEPT"}]')
+
def _receive_query_message(self, sock):
''' receive request message from sock'''
# receive data length
@@ -465,10 +487,28 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
t.daemon = True
t.start()
+ def _guess_remote(self, sock_fd):
+ """
+ Guess remote address and port of the socket. The sock_fd must be a
+ socket
+ """
+ # This uses a trick. If the socket is IPv4 in reality and we pretend
+ # it to be IPv6, it returns IPv4 address anyway. This doesn't seem
+ # to care about the SOCK_STREAM parameter at all (which it really is,
+ # except for testing)
+ if socket.has_ipv6:
+ sock = socket.fromfd(sock_fd, socket.AF_INET6, socket.SOCK_STREAM)
+ else:
+ # To make it work even on hosts without IPv6 support
+ # (Any idea how to simulate this in test?)
+ sock = socket.fromfd(sock_fd, socket.AF_INET, socket.SOCK_STREAM)
+ return sock.getpeername()
def finish_request(self, sock_fd, request_data):
'''Finish one request by instantiating RequestHandlerClass.'''
- self.RequestHandlerClass(sock_fd, request_data, self, self.tsig_key_ring)
+ self.RequestHandlerClass(sock_fd, request_data, self,
+ self.tsig_key_ring,
+ self._guess_remote(sock_fd), self._acl)
def _remove_unused_sock_file(self, sock_file):
'''Try to remove the socket file. If the file is being used
@@ -512,6 +552,8 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
def update_config_data(self, new_config):
'''Apply the new config setting of xfrout module. '''
logger.info(XFROUT_NEW_CONFIG)
+ if 'query_acl' in new_config:
+ self._acl = REQUEST_LOADER.load(new_config['query_acl'])
self._lock.acquire()
self._max_transfers_out = new_config.get('transfers_out')
self.set_tsig_key_ring(new_config.get('tsig_key_ring'))
@@ -563,16 +605,12 @@ class UnixSockServer(socketserver_mixin.NoPollMixIn, ThreadingUnixStreamServer):
class XfroutServer:
def __init__(self):
self._unix_socket_server = None
- #self._log = None
self._listen_sock_file = UNIX_SOCKET_FILE
self._shutdown_event = threading.Event()
self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION, self.config_handler, self.command_handler)
self._config_data = self._cc.get_full_config()
self._cc.start()
self._cc.add_remote_config(AUTH_SPECFILE_LOCATION);
- #self._log = isc.log.NSLogger(self._config_data.get('log_name'), self._config_data.get('log_file'),
- # self._config_data.get('log_severity'), self._config_data.get('log_versions'),
- # self._config_data.get('log_max_bytes'), True)
self._start_xfr_query_listener()
self._start_notifier()
@@ -601,11 +639,13 @@ class XfroutServer:
continue
self._config_data[key] = new_config[key]
- #if self._log:
- # self._log.update_config(new_config)
-
if self._unix_socket_server:
- self._unix_socket_server.update_config_data(self._config_data)
+ try:
+ self._unix_socket_server.update_config_data(self._config_data)
+ except Exception as e:
+ answer = create_answer(1,
+ "Failed to handle new configuration: " +
+ str(e))
return answer
diff --git a/src/bin/xfrout/xfrout.spec.pre.in b/src/bin/xfrout/xfrout.spec.pre.in
index 2efa3d7..8ecbb0b 100644
--- a/src/bin/xfrout/xfrout.spec.pre.in
+++ b/src/bin/xfrout/xfrout.spec.pre.in
@@ -16,27 +16,27 @@
},
{
"item_name": "log_file",
- "item_type": "string",
+ "item_type": "string",
"item_optional": false,
"item_default": "@@LOCALSTATEDIR@@/@PACKAGE@/log/Xfrout.log"
},
{
"item_name": "log_severity",
- "item_type": "string",
+ "item_type": "string",
"item_optional": false,
- "item_default": "debug"
+ "item_default": "debug"
},
{
"item_name": "log_versions",
- "item_type": "integer",
+ "item_type": "integer",
"item_optional": false,
- "item_default": 5
+ "item_default": 5
},
{
"item_name": "log_max_bytes",
- "item_type": "integer",
+ "item_type": "integer",
"item_optional": false,
- "item_default": 1048576
+ "item_default": 1048576
},
{
"item_name": "tsig_key_ring",
@@ -49,6 +49,18 @@
"item_type": "string",
"item_optional": true
}
+ },
+ {
+ "item_name": "query_acl",
+ "item_type": "list",
+ "item_optional": false,
+ "item_default": [{"action": "ACCEPT"}],
+ "list_item_spec":
+ {
+ "item_name": "acl_element",
+ "item_type": "any",
+ "item_optional": true
+ }
}
],
"commands": [
diff --git a/src/bin/xfrout/xfrout_messages.mes b/src/bin/xfrout/xfrout_messages.mes
index 2dada54..19b104e 100644
--- a/src/bin/xfrout/xfrout_messages.mes
+++ b/src/bin/xfrout/xfrout_messages.mes
@@ -95,6 +95,17 @@ in the log message, but at this point no specific information other
than that could be given. This points to incomplete exception handling
in the code.
+% XFROUT_QUERY_DROPPED request to transfer %1/%2 to [%3]:%4 dropped
+The xfrout process silently dropped a request to transfer zone to given host.
+This is required by the ACLs. The %1 and %2 represent the zone name and class,
+the %3 and %4 the IP address and port of the peer requesting the transfer.
+
+% XFROUT_QUERY_REJECTED request to transfer %1/%2 to [%3]:%4 rejected
+The xfrout process rejected (by REFUSED rcode) a request to transfer zone to
+given host. This is because of ACLs. The %1 and %2 represent the zone name and
+class, the %3 and %4 the IP address and port of the peer requesting the
+transfer.
+
% XFROUT_RECEIVE_FILE_DESCRIPTOR_ERROR error receiving the file descriptor for an XFR connection
There was an error receiving the file descriptor for the transfer
request. Normally, the request is received by b10-auth, and passed on
More information about the bind10-changes
mailing list