Browse Source

[1458] handle the case of ACL action being DROP.

JINMEI Tatuya 13 years ago
parent
commit
b14e2801e5

+ 3 - 0
src/lib/python/isc/ddns/libddns_messages.mes

@@ -42,3 +42,6 @@ of NOTAUTH.
 
 % LIBDDNS_UPDATE_REFUSED update client %1 for zone %2 denied
 TBD
+
+% LIBDDNS_UPDATE_DROPPED update client %1 for zone %2 dropped
+TBD

+ 20 - 6
src/lib/python/isc/ddns/session.py

@@ -45,7 +45,8 @@ class UpdateError(Exception):
     - msg (string) A string explaining the error.
     - zname (isc.dns.Name) The zone name.  Can be None when not identified.
     - zclass (isc.dns.RRClass) The zone class.  Like zname, can be None.
-    - rcode (isc.dns.RCode) The RCODE to be set in the response message.
+    - rcode (isc.dns.RCode or None) The RCODE to be set in the response
+      message; this can be None if the response is not expected to be sent.
     - nolog (bool) If True, it indicates there's no more need for logging.
 
     '''
@@ -97,8 +98,10 @@ class UpdateSession:
         '''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.
+        to be returned to the client.  If the request has been dropped,
+        this method returns None.  If this method is called before handle()
+        the return value would be identical to the request message passed on
+        construction, although it's of no practical use.
 
         '''
         return self.__message
@@ -114,7 +117,8 @@ class UpdateSession:
           UPDATE_DROP Error happened and no response should be sent.
           Except the case of UPDATE_DROP, the UpdateSession object will have
           created a response that is to be returned to the request client,
-          which can be retrieved by get_message().
+          which can be retrieved by get_message().  If it's UPDATE_DROP,
+          subsequent call to get_message() returns None.
         - The name of the updated zone (isc.dns.Name object) in case of
           UPDATE_SUCCESS; otherwise None.
         - The RR class of the updated zone (isc.dns.RRClass object) in case
@@ -134,8 +138,13 @@ class UpdateSession:
                 logger.debug(logger.DBGLVL_TRACE_BASIC, LIBDDNS_UPDATE_ERROR,
                              ClientFormatter(self.__client_addr),
                              ZoneFormatter(e.zname, e.zclass), e)
-            self.__make_response(e.rcode)
-            return UPDATE_ERROR, None, None
+            # If RCODE is specified, create a corresponding resonse and return
+            # ERROR; otherwise clear the message and return DROP.
+            if e.rcode is not None:
+                self.__make_response(e.rcode)
+                return UPDATE_ERROR, None, None
+            self.__message = None
+            return UPDATE_DROP, None, None
 
     def __get_update_zone(self):
         '''Parse the zone section and find the zone to be updated.
@@ -187,6 +196,11 @@ class UpdateSession:
                         ClientFormatter(self.__client_addr),
                         ZoneFormatter(zname, zclass))
             raise UpdateError('rejected', zname, zclass, Rcode.REFUSED(), True)
+        if action == DROP:
+            logger.info(LIBDDNS_UPDATE_DROPPED,
+                        ClientFormatter(self.__client_addr),
+                        ZoneFormatter(zname, zclass))
+            raise UpdateError('rejected', zname, zclass, None, True)
 
     def __make_response(self, rcode):
         '''Transform the internal message to the update response.

+ 13 - 4
src/lib/python/isc/ddns/tests/session_tests.py

@@ -170,10 +170,19 @@ class SessionACLTest(SesseionTestBase):
                                 TEST_CLIENT4, ZoneConfig([], TEST_RRCLASS,
                                                          self._datasrc_client))
         # then the request should be rejected.
-        result, zname, zclass = session.handle()
-        self.assertEqual(UPDATE_ERROR, result)
-        self.assertEqual(None, zname)
-        self.assertEqual(None, zclass)
+        self.assertEqual((UPDATE_ERROR, None, None), session.handle())
+
+        # recreate the request message, and test with an ACL that would result
+        # in 'DROP'.  get_message() should return None.
+        msgdata, msg = create_update_msg()
+        acl_map = {(TEST_ZONE_NAME, TEST_RRCLASS):
+                       REQUEST_LOADER.load([{"action": "DROP", "from":
+                                                 TEST_CLIENT4[0]}])}
+        session = UpdateSession(msg, msgdata, TEST_CLIENT4,
+                                ZoneConfig([], TEST_RRCLASS,
+                                           self._datasrc_client, acl_map))
+        self.assertEqual((UPDATE_DROP, None, None), session.handle())
+        self.assertEqual(None, session.get_message())
 
 if __name__ == "__main__":
     isc.log.init("bind10")