From: JINMEI Tatuya Date: Wed, 16 May 2012 03:58:41 +0000 (-0700) Subject: [1512] covered some more invalid zone section cases. X-Git-Tag: trac2351_base~226^2~82^2~27 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=75fa2da75c4222f430efc01a3becbdbf9cff100d;p=thirdparty%2Fkea.git [1512] covered some more invalid zone section cases. also bit refactored the code to reduce duplicates. --- diff --git a/src/lib/python/isc/ddns/session.py b/src/lib/python/isc/ddns/session.py index 19459d1d85..d3da51a439 100644 --- a/src/lib/python/isc/ddns/session.py +++ b/src/lib/python/isc/ddns/session.py @@ -24,6 +24,11 @@ SECTION_ZONE = isc.dns.Message.SECTION_QUESTION SECTION_PREREQUISITE = isc.dns.Message.SECTION_ANSWER SECTION_UPDATE = isc.dns.Message.SECTION_AUTHORITY +class ZoneError(Exception): + def __init__(self, msg, rcode): + Exception(msg) + self.rcode = rcode + class UpdateSession: '''Protocol handling for a single dynamic update request. @@ -50,10 +55,35 @@ class UpdateSession: to be taken. ''' - # Interpret the zone section. It must contain exactly one - # "question", and it must be of type SOA. - if self.__message.get_rr_count(SECTION_ZONE) == 0: - self.__message.make_response() - self.__message.set_rcode(isc.dns.Rcode.FORMERR()) - return UPDATE_DONE + try: + zone_record = self.__get_update_zone() + except ZoneError as e: + self.__make_response(e.rcode) return UPDATE_DONE + + def __get_update_zone(self): + '''Interpret the zone section and return it as a Question object. + + It must contain exactly one question, and it must be of type SOA. + + ''' + if self.__message.get_rr_count(SECTION_ZONE) != 1: + raise ZoneError('Invalid number of records in zone section: ' + + str(1), isc.dns.Rcode.FORMERR()) + zone_record = self.__message.get_question()[0] + if zone_record.get_type() != isc.dns.RRType.SOA(): + raise ZoneError('update zone section contains non-SOA', + isc.dns.Rcode.FORMERR()) + return zone_record + + def __make_response(self, rcode): + '''Transform the internal message to the update response. + + According RFC2136 Section 3.8, the zone section will be cleared + as well as other sections. The response Rcode will be set to the + given value. + + ''' + self.__message.make_response() + self.__message.clear_section(SECTION_ZONE) + self.__message.set_rcode(rcode) diff --git a/src/lib/python/isc/ddns/tests/session_tests.py b/src/lib/python/isc/ddns/tests/session_tests.py index f558aa9490..0be93c91b5 100644 --- a/src/lib/python/isc/ddns/tests/session_tests.py +++ b/src/lib/python/isc/ddns/tests/session_tests.py @@ -19,17 +19,18 @@ from isc.dns import * from isc.ddns.session import * # Some common test parameters -TEST_ZONE = Name('example.com') +TEST_ZONE_NAME = Name('example.com') UPDATE_RRTYPE = RRType.SOA() TEST_RRCLASS = RRClass.IN() +TEST_ZONE_RECORD = Question(TEST_ZONE_NAME, TEST_RRCLASS, UPDATE_RRTYPE) -def create_update_msg(zone_name=TEST_ZONE): +def create_update_msg(zones=[TEST_ZONE_RECORD]): msg = Message(Message.RENDER) msg.set_qid(5353) # arbitrary chosen msg.set_opcode(Opcode.UPDATE()) msg.set_rcode(Rcode.NOERROR()) - if zone_name is not None: - msg.add_question(Question(zone_name, TEST_RRCLASS, UPDATE_RRTYPE)) + for z in zones: + msg.add_question(z) renderer = MessageRenderer() msg.to_wire(renderer) @@ -44,7 +45,7 @@ class SessionTest(unittest.TestCase): '''Session tests''' def setUp(self): self.__client_addr = ('192.0.2.1', 53) - self.__update_msgdata, self.__update_msg = create_update_msg(TEST_ZONE) + self.__update_msgdata, self.__update_msg = create_update_msg() self.__session = UpdateSession(self.__update_msg, self.__update_msgdata, self.__client_addr, None) @@ -62,7 +63,22 @@ class SessionTest(unittest.TestCase): def test_broken_request(self): # Zone section is empty - msg_data, msg = create_update_msg(zone_name=None) + msg_data, msg = create_update_msg(zones=[]) + session = UpdateSession(msg, msg_data, None, None) + self.assertEqual(UPDATE_DONE, session.handle()) + self.check_response(session.get_message(), Rcode.FORMERR()) + + # Zone section contains multiple records + msg_data, msg = create_update_msg(zones=[TEST_ZONE_RECORD, + TEST_ZONE_RECORD]) + session = UpdateSession(msg, msg_data, None, None) + self.assertEqual(UPDATE_DONE, session.handle()) + self.check_response(session.get_message(), Rcode.FORMERR()) + + # Zone section's type is not SOA + msg_data, msg = create_update_msg(zones=[Question(TEST_ZONE_NAME, + TEST_RRCLASS, + RRType.A())]) session = UpdateSession(msg, msg_data, None, None) self.assertEqual(UPDATE_DONE, session.handle()) self.check_response(session.get_message(), Rcode.FORMERR())