Esempio n. 1
0
    def _handle_create(self, request):
        response = dns.message.make_response(request)

        question = request.question[0]
        requester = request.environ['addr'][0]
        zone_name = question.name.to_text()

        if not self._allowed(request, requester, "CREATE", zone_name):
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        serial = self.backend.find_zone_serial(zone_name)

        if serial is not None:
            LOG.warn(_LW("Not creating %(name)s, zone already exists") %
                 {'name': zone_name})
            # Provide an authoritative answer
            response.flags |= dns.flags.AA
            return response

        LOG.debug("Received %(verb)s for %(name)s from %(host)s" %
                 {'verb': "CREATE", 'name': zone_name, 'host': requester})

        try:
            zone = dnsutils.do_axfr(zone_name, self.masters,
                source=self.transfer_source)
            self.backend.create_zone(zone)
        except Exception:
            response.set_rcode(dns.rcode.from_text("SERVFAIL"))
            return response

        # Provide an authoritative answer
        response.flags |= dns.flags.AA

        return response
Esempio n. 2
0
    def _handle_create(self, request):
        response = dns.message.make_response(request)

        question = request.question[0]
        requester = request.environ['addr'][0]
        zone_name = question.name.to_text()

        if not self._allowed(request, requester, "CREATE", zone_name):
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        serial = self.backend.find_zone_serial(zone_name)

        if serial is not None:
            LOG.warning(_LW("Not creating %(name)s, zone already exists") %
                 {'name': zone_name})
            # Provide an authoritative answer
            response.flags |= dns.flags.AA
            return response

        LOG.debug("Received %(verb)s for %(name)s from %(host)s",
                  {'verb': "CREATE", 'name': zone_name, 'host': requester})

        try:
            zone = dnsutils.do_axfr(zone_name, self.masters,
                source=self.transfer_source)
            self.backend.create_zone(zone)
        except Exception:
            response.set_rcode(dns.rcode.from_text("SERVFAIL"))
            return response

        # Provide an authoritative answer
        response.flags |= dns.flags.AA

        return response
Esempio n. 3
0
    def _handle_notify(self, request):
        """
        Constructs the response to a NOTIFY and acts accordingly on it.

        * Decodes the NOTIFY
        * Checks if the master sending the NOTIFY is allowed to notify
        * Does a serial check to see if further action needs to be taken
        * Kicks off an AXFR and returns a valid response
        """
        response = dns.message.make_response(request)

        question = request.question[0]
        requester = request.environ['addr'][0]
        zone_name = question.name.to_text().decode('utf-8')

        if not self._allowed(request, requester, "NOTIFY", zone_name):
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        serial = self.backend.find_zone_serial(zone_name)

        if serial is None:
            LOG.warning(
                _LW("Refusing NOTIFY for %(name)s, doesn't exist") %
                {'name': zone_name})
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        LOG.debug("Received %(verb)s for %(name)s from %(host)s", {
            'verb': "NOTIFY",
            'name': zone_name,
            'host': requester
        })

        # According to RFC we should query the server that sent the NOTIFY
        # TODO(Tim): Reenable this when it makes more sense
        # resolver = dns.resolver.Resolver()
        # resolver.nameservers = [requester]
        # This assumes that the Master is running on port 53
        # soa_answer = resolver.query(zone_name, 'SOA')
        # Check that the serial is < serial above

        try:
            zone = dnsutils.do_axfr(zone_name,
                                    self.masters,
                                    source=self.transfer_source)
            self.backend.update_zone(zone)
        except Exception:
            response.set_rcode(dns.rcode.from_text("SERVFAIL"))
            return response

        # Provide an authoritative answer
        response.flags |= dns.flags.AA

        return response
Esempio n. 4
0
    def _handle_notify(self, request):
        """
        Constructs the response to a NOTIFY and acts accordingly on it.

        * Decodes the NOTIFY
        * Checks if the master sending the NOTIFY is allowed to notify
        * Does a serial check to see if further action needs to be taken
        * Kicks off an AXFR and returns a valid response
        """
        response = dns.message.make_response(request)

        question = request.question[0]
        requester = request.environ['addr'][0]
        zone_name = question.name.to_text()
        if six.PY3 and isinstance(zone_name, bytes):
            zone_name = zone_name.decode('utf-8')

        if not self._allowed(request, requester, "NOTIFY", zone_name):
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        serial = self.backend.find_zone_serial(zone_name)

        if serial is None:
            LOG.warning("Refusing NOTIFY for %(name)s, doesn't exist",
                        {'name': zone_name})
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        LOG.debug("Received %(verb)s for %(name)s from %(host)s",
                  {'verb': "NOTIFY", 'name': zone_name, 'host': requester})

        # According to RFC we should query the server that sent the NOTIFY
        # TODO(Tim): Reenable this when it makes more sense
        # resolver = dns.resolver.Resolver()
        # resolver.nameservers = [requester]
        # This assumes that the Master is running on port 53
        # soa_answer = resolver.query(zone_name, 'SOA')
        # Check that the serial is < serial above

        try:
            zone = dnsutils.do_axfr(zone_name, self.masters,
                source=self.transfer_source)
            self.backend.update_zone(zone)
        except Exception:
            response.set_rcode(dns.rcode.from_text("SERVFAIL"))
            return response

        # Provide an authoritative answer
        response.flags |= dns.flags.AA

        return response
Esempio n. 5
0
    def _handle_create(self, request):
        response = dns.message.make_response(request)

        question = request.question[0]
        requester = request.environ['addr'][0]
        zone_name = question.name.to_text().decode('utf-8')

        if not self._allowed(request, requester, "CREATE", zone_name):
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        serial = self.backend.find_zone_serial(zone_name)

        if serial is not None:
            # Does this warrant a warning?
            # There is a race condition between checking if the zone exists
            # and creating it.
            LOG.warning(_LW("Not creating %(name)s, zone already exists"),
                        {'name': zone_name})
            # Provide an authoritative answer
            response.flags |= dns.flags.AA
            return response

        LOG.debug("Received %(verb)s for %(name)s from %(host)s", {
            'verb': "CREATE",
            'name': zone_name,
            'host': requester
        })

        try:
            # Receive an AXFR from MiniDNS to populate the zone
            zone = dnsutils.do_axfr(zone_name,
                                    self.masters,
                                    source=self.transfer_source)
            self.backend.create_zone(zone)
        except Exception as e:
            # TODO(Federico) unknown exceptions should be logged with a full
            # traceback. Same in the other methods.
            LOG.error(_LE("Exception while creating zone %r"), e)
            response.set_rcode(dns.rcode.from_text("SERVFAIL"))
            return response

        # Provide an authoritative answer
        response.flags |= dns.flags.AA

        return response
Esempio n. 6
0
    def zone_sync(self, context, zone, servers=None):
        servers = servers or zone.masters
        servers = servers.to_list()

        timeout = cfg.CONF["service:mdns"].xfr_timeout
        try:
            dnspython_zone = dnsutils.do_axfr(zone.name, servers,
                                              timeout=timeout)
        except exceptions.XFRFailure as e:
            LOG.warning(e)
            return

        zone.update(dnsutils.from_dnspython_zone(dnspython_zone))

        zone.transferred_at = timeutils.utcnow()

        self.central_api.update_zone(context, zone, increment_serial=False)
Esempio n. 7
0
    def domain_sync(self, context, domain, servers=None):
        servers = servers or domain.masters
        servers = dnsutils.expand_servers(servers)

        timeout = cfg.CONF["service:mdns"].xfr_timeout
        try:
            dnspython_zone = dnsutils.do_axfr(domain.name, servers,
                                              timeout=timeout)
        except exceptions.XFRFailure as e:
            LOG.warning(e.message)
            return

        zone = dnsutils.from_dnspython_zone(dnspython_zone)
        domain.update(zone)

        domain.transferred_at = timeutils.utcnow()

        self.central_api.update_domain(context, domain, increment_serial=False)
Esempio n. 8
0
    def _handle_create(self, request):
        response = dns.message.make_response(request)

        question = request.question[0]
        requester = request.environ['addr'][0]
        zone_name = question.name.to_text()
        if six.PY3 and isinstance(zone_name, bytes):
            zone_name = zone_name.decode('utf-8')

        if not self._allowed(request, requester, "CREATE", zone_name):
            response.set_rcode(dns.rcode.from_text("REFUSED"))
            return response

        serial = self.backend.find_zone_serial(zone_name)

        if serial is not None:
            # Does this warrant a warning?
            # There is a race condition between checking if the zone exists
            # and creating it.
            LOG.warning("Not creating %(name)s, zone already exists",
                        {'name': zone_name})
            # Provide an authoritative answer
            response.flags |= dns.flags.AA
            return response

        LOG.debug("Received %(verb)s for %(name)s from %(host)s",
                  {'verb': "CREATE", 'name': zone_name, 'host': requester})

        try:
            # Receive an AXFR from MiniDNS to populate the zone
            zone = dnsutils.do_axfr(zone_name, self.masters,
                                    source=self.transfer_source)
            self.backend.create_zone(zone)
        except Exception as e:
            # TODO(Federico) unknown exceptions should be logged with a full
            # traceback. Same in the other methods.
            LOG.error("Exception while creating zone %r", e)
            response.set_rcode(dns.rcode.from_text("SERVFAIL"))
            return response

        # Provide an authoritative answer
        response.flags |= dns.flags.AA

        return response
Esempio n. 9
0
    def domain_sync(self, context, domain, servers=None):
        servers = servers or domain.masters
        servers = dnsutils.expand_servers(servers)

        timeout = cfg.CONF["service:mdns"].xfr_timeout
        try:
            dnspython_zone = dnsutils.do_axfr(domain.name,
                                              servers,
                                              timeout=timeout)
        except exceptions.XFRFailure as e:
            LOG.warning(e.message)
            return

        zone = dnsutils.from_dnspython_zone(dnspython_zone)
        domain.update(zone)

        domain.transferred_at = timeutils.utcnow()

        self.central_api.update_domain(context, domain, increment_serial=False)
Esempio n. 10
0
    def test_do_afxr(self, mock_from_xfr_impl, mock_xfr):
        mock_from_xfr = mock.MagicMock()
        mock_from_xfr_impl.return_value = mock_from_xfr

        mock_from_xfr.origin.to_text.return_value = 'raw_zone'
        mock_from_xfr.return_value = 'raw_zone'

        masters = [
            {
                'host': '192.168.0.1',
                'port': 53
            },
            {
                'host': '192.168.0.2',
                'port': 53
            },
        ]

        self.assertEqual(mock_from_xfr,
                         dnsutils.do_axfr('example.com', masters))

        self.assertTrue(mock_xfr.called)
        self.assertTrue(mock_from_xfr_impl.called)
Esempio n. 11
0
    def zone_sync(self, context, zone, servers=None):
        start_time = time.time()
        try:
            servers = servers or zone.masters
            servers = servers.to_list()

            timeout = cfg.CONF["service:mdns"].xfr_timeout
            try:
                dnspython_zone = dnsutils.do_axfr(zone.name,
                                                  servers,
                                                  timeout=timeout)
            except exceptions.XFRFailure as e:
                LOG.warning(e)
                return

            zone.update(dnsutils.from_dnspython_zone(dnspython_zone))

            zone.transferred_at = timeutils.utcnow()

            zone.obj_reset_changes(["name"])
            self.central_api.update_zone(context, zone, increment_serial=False)
        finally:
            metrics.timing('mdns.xfr.zone_sync', time.time() - start_time)