From: JINMEI Tatuya Date: Wed, 16 May 2012 02:42:07 +0000 (-0700) Subject: [1512] an initial validation: check the # of zone in the zone section. X-Git-Tag: trac2351_base~226^2~82^2~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2025f34658956271cf1850bba7c9fa15fe690a3b;p=thirdparty%2Fkea.git [1512] an initial validation: check the # of zone in the zone section. --- diff --git a/src/lib/python/isc/ddns/session.py b/src/lib/python/isc/ddns/session.py index 5ab5881055..19459d1d85 100644 --- a/src/lib/python/isc/ddns/session.py +++ b/src/lib/python/isc/ddns/session.py @@ -13,20 +13,47 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +import isc.dns + +# Result codes for UpdateSession.handle() +UPDATE_DONE = 0 # handled completely, and the response is ready +UPDATE_DROP = 1 # critical error happened, no response should be sent + +# Convenient aliases of update-specific section names +SECTION_ZONE = isc.dns.Message.SECTION_QUESTION +SECTION_PREREQUISITE = isc.dns.Message.SECTION_ANSWER +SECTION_UPDATE = isc.dns.Message.SECTION_AUTHORITY + class UpdateSession: '''Protocol handling for a single dynamic update request. TBD ''' - def __init__(self, request, datasrc_client): - pass + def __init__(self, req_message, req_data, client_addr, datasrc_client): + self.__message = req_message + + def get_message(self): + '''Return the update message. + + After handle() is called, it's generally transformed to the response + to be returned to the client; otherwise it would be identical to + the request message passed on construction. + + ''' + return self.__message def handle(self): - '''Handle the update request in more detail. + '''Handle the update request according to RFC2136. Return: the result code of the session, indicating the next action to be taken. ''' - pass + # 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 + return UPDATE_DONE diff --git a/src/lib/python/isc/ddns/tests/session_tests.py b/src/lib/python/isc/ddns/tests/session_tests.py index 68f4779c39..f558aa9490 100644 --- a/src/lib/python/isc/ddns/tests/session_tests.py +++ b/src/lib/python/isc/ddns/tests/session_tests.py @@ -14,9 +14,62 @@ # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import isc.log +import unittest +from isc.dns import * +from isc.ddns.session import * + +# Some common test parameters +TEST_ZONE = Name('example.com') +UPDATE_RRTYPE = RRType.SOA() +TEST_RRCLASS = RRClass.IN() + +def create_update_msg(zone_name=TEST_ZONE): + 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)) + + renderer = MessageRenderer() + msg.to_wire(renderer) + + # re-read the created data in the parse mode + msg.clear(Message.PARSE) + msg.from_wire(renderer.get_data()) + + return renderer.get_data(), msg class SessionTest(unittest.TestCase): - pass + '''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.__session = UpdateSession(self.__update_msg, + self.__update_msgdata, + self.__client_addr, None) + + def check_response(self, msg, expected_rcode): + '''Perform common checks on update resposne message.''' + self.assertTrue(msg.get_header_flag(Message.HEADERFLAG_QR)) + self.assertEqual(Opcode.UPDATE().to_text(), msg.get_opcode().to_text()) + self.assertEqual(expected_rcode.to_text(), msg.get_rcode().to_text()) + # All sections should be cleared + self.assertEqual(0, msg.get_rr_count(SECTION_ZONE)) + self.assertEqual(0, msg.get_rr_count(SECTION_PREREQUISITE)) + self.assertEqual(0, msg.get_rr_count(SECTION_UPDATE)) + self.assertEqual(0, msg.get_rr_count(Message.SECTION_ADDITIONAL)) + + def test_broken_request(self): + # Zone section is empty + msg_data, msg = create_update_msg(zone_name=None) + session = UpdateSession(msg, msg_data, None, None) + self.assertEqual(UPDATE_DONE, session.handle()) + self.check_response(session.get_message(), Rcode.FORMERR()) + + def test_handle(self): + self.assertEqual(UPDATE_DONE, self.__session.handle()) + self.assertNotEqual(UPDATE_DROP, self.__session.handle()) if __name__ == "__main__": isc.log.init("bind10")