Browse Source

Merge branch 'trac2759'

Mukund Sivaraman 12 years ago
parent
commit
d8991bf8ed

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

@@ -212,3 +212,13 @@ To make sure DDNS service is not interrupted, this problem is caught instead
 of reraised; The update is aborted, and a SERVFAIL is sent back to the client.
 This is most probably a bug in the DDNS code, but *could* be caused by
 the data source.
+
+% LIBDDNS_ZONE_INVALID_ERROR Newly received zone data %1/%2 fails validation: %3
+The zone data was received successfully, but the zone when updated with
+this zone data fails validation.
+
+% LIBDDNS_ZONE_INVALID_WARN Newly received zone data %1/%2 has a problem: %3
+The zone data was received successfully, but when checking the zone when
+updated with this zone data, it was discovered there's some issue with
+it. It might be correct, but it should be checked and possibly
+fixed. The problem does not stop the zone from being used.

+ 23 - 0
src/lib/python/isc/ddns/session.py

@@ -812,6 +812,20 @@ class UpdateSession:
         self.__diff.delete_data(old_soa)
         self.__diff.add_data(new_soa)
 
+    def __validate_error(self, reason):
+        '''
+        Used as error callback below.
+        '''
+        logger.error(LIBDDNS_ZONE_INVALID_ERROR, self.__zname, self.__zclass,
+                     reason)
+
+    def __validate_warning(self, reason):
+        '''
+        Used as warning callback below.
+        '''
+        logger.warn(LIBDDNS_ZONE_INVALID_WARN, self.__zname, self.__zclass,
+                    reason)
+
     def __do_update(self):
         '''Scan, check, and execute the Update section in the
            DDNS Update message.
@@ -849,8 +863,17 @@ class UpdateSession:
                 elif rrset.get_class() == RRClass.NONE:
                     self.__do_update_delete_rrs_from_rrset(rrset)
 
+            if not check_zone(self.__zname, self.__zclass,
+                              self.__diff.get_rrset_collection(),
+                              (self.__validate_error, self.__validate_warning)):
+                raise UpdateError('Validation of the new zone failed',
+                                  self.__zname, self.__zclass, Rcode.REFUSED)
             self.__diff.commit()
             return Rcode.NOERROR
+        except UpdateError:
+            # Propagate UpdateError exceptions (don't catch them in the
+            # blocks below)
+            raise
         except isc.datasrc.Error as dse:
             logger.info(LIBDDNS_UPDATE_DATASRC_COMMIT_FAILED, dse)
             return Rcode.SERVFAIL

+ 10 - 0
src/lib/python/isc/ddns/tests/session_tests.py

@@ -1481,6 +1481,16 @@ class SessionTest(SessionTestBase):
         self.assertEqual(Rcode.SERVFAIL.to_text(),
                          self._session._UpdateSession__do_update().to_text())
 
+    def test_check_zone_failure(self):
+        # ns3.example.org. is an NS and should not have a CNAME
+        # record. This would cause check_zone() to fail.
+        self.__initialize_update_rrsets()
+        new_cname = create_rrset("ns3.example.org", TEST_RRCLASS,
+                                 RRType.CNAME, 3600,
+                                 [ "cname.example.org." ])
+
+        self.check_full_handle_result(Rcode.REFUSED, [ new_cname ])
+
 class SessionACLTest(SessionTestBase):
     '''ACL related tests for update session.'''
     def test_update_acl_check(self):

+ 36 - 0
tests/lettuce/features/ddns_system.feature

@@ -118,6 +118,42 @@ Feature: DDNS System
         A query for new3.example.org should have rcode NOERROR
         The SOA serial for example.org should be 1236
 
+    Scenario: Zone validation check
+        Given I have bind10 running with configuration ddns/ddns.config
+        And wait for bind10 stderr message BIND10_STARTED_CC
+        And wait for bind10 stderr message AUTH_SERVER_STARTED
+        And wait for bind10 stderr message DDNS_STARTED
+
+        # Sanity check
+        A query for example.org type NS should have rcode NOERROR
+        The answer section of the last query response should be
+        """
+        example.org.                    3600    IN      NS      ns1.example.org.
+        example.org.                    3600    IN      NS      ns2.example.org.
+        example.org.                    3600    IN      NS      ns3.example.org.
+        """
+        The SOA serial for example.org should be 1234
+
+        # Test failed validation. Here, example.org has ns1.example.org
+        # configured as a name server. CNAME records cannot be added for
+        # ns1.example.org.
+        When I use DDNS to add a record ns1.example.org. 3600 IN CNAME ns3.example.org.
+        The DDNS response should be REFUSED
+        A query for ns1.example.org type CNAME should have rcode NXDOMAIN
+        The SOA serial for example.org should be 1234
+
+        # Test passed validation. Here, example.org does not have
+        # ns4.example.org configured as a name server. CNAME records can
+        # be added for ns4.example.org.
+        When I use DDNS to add a record ns4.example.org. 3600 IN CNAME ns3.example.org.
+        The DDNS response should be SUCCESS
+        A query for ns4.example.org type CNAME should have rcode NOERROR
+        The answer section of the last query response should be
+        """
+        ns4.example.org.                3600    IN      CNAME   ns3.example.org.
+        """
+        The SOA serial for example.org should be 1235
+
     #Scenario: DDNS and Xfrout
     ## Unfortunately, Xfrout can only notify to inzone slaves, and hence only
     ## to port 53, which we do not want to use for Lettuce tests (for various