def test_transfer(self): """ An attempt is made to transfer the zone for the domain the L{SecondaryAuthority} was constructed with from the server address it was constructed with when L{SecondaryAuthority.transfer} is called. """ secondary = SecondaryAuthority.fromServerAddressAndDomain( ('192.168.1.2', 1234), 'example.com') secondary._reactor = reactor = MemoryReactorClock() secondary.transfer() # Verify a connection attempt to the server address above host, port, factory, timeout, bindAddress = reactor.tcpClients.pop(0) self.assertEqual(host, '192.168.1.2') self.assertEqual(port, 1234) # See if a zone transfer query is issued. proto = factory.buildProtocol((host, port)) transport = StringTransport() proto.makeConnection(transport) msg = Message() # DNSProtocol.writeMessage length encodes the message by prepending a # 2 byte message length to the buffered value. msg.decode(StringIO(transport.value()[2:])) self.assertEqual( [dns.Query('example.com', dns.AXFR, dns.IN)], msg.queries)
def queryTCP(queries): self.assertEqual(queries, m.queries) response = Message() response.answers = ['answer'] response.authority = ['authority'] response.additional = ['additional'] return succeed(response)
def test_transfer(self): """ An attempt is made to transfer the zone for the domain the L{SecondaryAuthority} was constructed with from the server address it was constructed with when L{SecondaryAuthority.transfer} is called. """ secondary = SecondaryAuthority.fromServerAddressAndDomain( ('192.168.1.2', 1234), 'example.com') secondary._reactor = reactor = MemoryReactorClock() secondary.transfer() # Verify a connection attempt to the server address above host, port, factory, timeout, bindAddress = reactor.tcpClients.pop(0) self.assertEqual(host, '192.168.1.2') self.assertEqual(port, 1234) # See if a zone transfer query is issued. proto = factory.buildProtocol((host, port)) transport = StringTransport() proto.makeConnection(transport) msg = Message() # DNSProtocol.writeMessage length encodes the message by prepending a # 2 byte message length to the buffered value. msg.decode(StringIO(transport.value()[2:])) self.assertEqual([dns.Query('example.com', dns.AXFR, dns.IN)], msg.queries)
def buildResponse(inMessage): outMessage = Message(id=inMessage.id, answer=1, opCode=inMessage.opCode, recDes=1, recAv=1, auth=1, authenticData=1) outMessage.queries = inMessage.queries rcode = NOERROR querytlds = [] for query in inMessage.queries: tld = query.name.name.decode("utf-8").lower().split(".")[-1] if not tld in tlds: if rcode != SERVFAIL: rcode = REFUSED if not tld in querytlds: # SOA even if wrong type querytlds.append(tld) if not (query.type == 28 or query.type == 255): # AAAA or ALL continue # NOERROR without record try: error, queryRRH = doQuery(query) if error: print("error", query.name.name.decode("utf-8"), error) if len(inMessage.queries) < 2: rcode = error elif error == NOERROR: # Don't change for NOERROR pass elif error == SERVFAIL or rcode == SERVFAIL: # SERVFAIL replaces all rcode = SERVFAIL elif error == REFUSED or rcode == REFUSED: # Refused replaces all but SERVFAIL rcode = REFUSED elif error == NXDOMAIN or rcode == NXDOMAIN: # NXDOMAIN rcode = NXDOMAIN else: print("Unexpected error from doQuery:", error) rcode = SERVFAIL except Exception as e: rcode = SERVFAIL print("oops", query, traceback.format_exc()) outMessage.answers = [] querytlds = [] break if queryRRH != None: outMessage.answers.append(queryRRH) for tld in querytlds: outMessage.authority.append(RRHeader( name=tld, type=6, # SOA cls=query.cls, ttl=ttl, payload=Record_SOA( mname=tld, rname="", serial=int(time()/ttl), refresh=ttl, retry=ttl, expire=ttl, minimum=ttl), auth=True)) outMessage.rCode = rcode return(outMessage)
def _respond(self, answers=[], authority=[], additional=[], rCode=OK): """ Create a L{Message} suitable for use as a response to a query. @param answers: A C{list} of two-tuples giving data for the answers section of the message. The first element of each tuple is a name for the L{RRHeader}. The second element is the payload. @param authority: A C{list} like C{answers}, but for the authority section of the response. @param additional: A C{list} like C{answers}, but for the additional section of the response. @param rCode: The response code the message will be created with. @return: A new L{Message} initialized with the given values. """ response = Message(rCode=rCode) for (section, data) in [ (response.answers, answers), (response.authority, authority), (response.additional, additional), ]: section.extend([ RRHeader(name, record.TYPE, getattr(record, "CLASS", IN), payload=record) for (name, record) in data ]) return response
def test_notifyMessageReceived(self): """ L{DNSServerFactory.messageReceived} passes messages with an opcode of C{OP_NOTIFY} on to L{DNSServerFactory.handleNotify}. """ # RFC 1996, section 4.5 opCode = 4 self._messageReceivedTest('handleNotify', Message(opCode=opCode))
def test_lookupAddress(self): """ L{SecondaryAuthority.lookupAddress} returns a L{Deferred} that fires with the I{A} records the authority has cached from the primary. """ secondary = SecondaryAuthority.fromServerAddressAndDomain( (b'192.168.1.2', 1234), b'example.com') secondary._reactor = reactor = MemoryReactorClock() secondary.transfer() host, port, factory, timeout, bindAddress = reactor.tcpClients.pop(0) proto = factory.buildProtocol((host, port)) transport = StringTransport() proto.makeConnection(transport) query = Message(answer=1, auth=1) query.decode(StringIO(transport.value()[2:])) # Generate a response with some data we can check. soa = Record_SOA( mname=b'ns1.example.com', rname='admin.example.com', serial=123456, refresh=3600, minimum=4800, expire=7200, retry=9600, ttl=12000, ) a = Record_A(b'192.168.1.2', ttl=0) answer = Message(id=query.id, answer=1, auth=1) answer.answers.extend([ RRHeader(b'example.com', type=SOA, payload=soa), RRHeader(b'example.com', payload=a), RRHeader(b'example.com', type=SOA, payload=soa), ]) data = answer.toStr() proto.dataReceived(pack('!H', len(data)) + data) result = self.successResultOf(secondary.lookupAddress('example.com')) self.assertEqual(( [RRHeader(b'example.com', payload=a, auth=True)], [], []), result)
def test_updateMessageReceived(self): """ L{DNSServerFactory.messageReceived} passes messages with an opcode of C{OP_UPDATE} on to L{DNSServerFactory.handleOther}. This may change if the implementation ever covers update messages. """ # RFC 2136, section 1.3 opCode = 5 self._messageReceivedTest('handleOther', Message(opCode=opCode))
def _queryTest(self, filter): """ Invoke L{Resolver._query} and verify that it sends the correct DNS query. Deliver a canned response to the query and return whatever the L{Deferred} returned by L{Resolver._query} fires with. @param filter: The value to pass for the C{filter} parameter to L{Resolver._query}. """ reactor = MemoryReactor() resolver = Resolver([], reactor=reactor) d = resolver._query( Query(b'foo.example.com', A, IN), [('1.1.2.3', 1053)], (30,), filter) # A UDP port should have been started. portNumber, transport = reactor.udpPorts.popitem() # And a DNS packet sent. [(packet, address)] = transport._sentPackets message = Message() message.fromStr(packet) # It should be a query with the parameters used above. self.assertEqual(message.queries, [Query(b'foo.example.com', A, IN)]) self.assertEqual(message.answers, []) self.assertEqual(message.authority, []) self.assertEqual(message.additional, []) response = [] d.addCallback(response.append) self.assertEqual(response, []) # Once a reply is received, the Deferred should fire. del message.queries[:] message.answer = 1 message.answers.append(RRHeader( b'foo.example.com', payload=Record_A('5.8.13.21'))) transport._protocol.datagramReceived( message.toStr(), ('1.1.2.3', 1053)) return response[0]
def test_truncatedMessage(self): """ Test that a truncated message results in an equivalent request made via TCP. """ m = Message(trunc=True) m.addQuery('example.com') def queryTCP(queries): self.assertEqual(queries, m.queries) response = Message() response.answers = ['answer'] response.authority = ['authority'] response.additional = ['additional'] return succeed(response) self.resolver.queryTCP = queryTCP d = self.resolver.filterAnswers(m) d.addCallback( self.assertEqual, (['answer'], ['authority'], ['additional'])) return d
def datagramReceived(self, data, addr): m = Message() try: m.fromStr(data) except EOFError: log.msg("Truncated packet (%d bytes) from %s" % (len(data), addr)) return except: log.err(failure.Failure(), "Unexpected decoding error") return if m.id in self.liveMessages: d, canceller = self.liveMessages[m.id] del self.liveMessages[m.id] canceller.cancel() try: d.callback(m) except: log.err() else: if m.id not in self.resends: self.controller.messageReceived(m, self)
def _queryTest(self, filter): """ Invoke L{Resolver._query} and verify that it sends the correct DNS query. Deliver a canned response to the query and return whatever the L{Deferred} returned by L{Resolver._query} fires with. @param filter: The value to pass for the C{filter} parameter to L{Resolver._query}. """ reactor = MemoryReactor() resolver = Resolver([], reactor=reactor) d = resolver._query(Query(b'foo.example.com', A, IN), [('1.1.2.3', 1053)], (30, ), filter) # A UDP port should have been started. portNumber, transport = reactor.udpPorts.popitem() # And a DNS packet sent. [(packet, address)] = transport._sentPackets msg = Message() msg.fromStr(packet) # It should be a query with the parameters used above. self.assertEqual(msg.queries, [Query(b'foo.example.com', A, IN)]) self.assertEqual(msg.answers, []) self.assertEqual(msg.authority, []) self.assertEqual(msg.additional, []) response = [] d.addCallback(response.append) self.assertEqual(response, []) # Once a reply is received, the Deferred should fire. del msg.queries[:] msg.answer = 1 msg.answers.append( RRHeader(b'foo.example.com', payload=Record_A('5.8.13.21'))) transport._protocol.datagramReceived(msg.toStr(), ('1.1.2.3', 1053)) return response[0]
def test_extractAuthorityDeprecated(self): """ Calling L{root.extractAuthority} produces a deprecation warning. """ extractAuthority(Message(), {}) warnings = self.flushWarnings([self.test_extractAuthorityDeprecated]) self.assertEqual(warnings[0]['category'], DeprecationWarning) self.assertEqual( warnings[0]['message'], 'twisted.names.root.extractAuthority is deprecated since Twisted ' '10.0. Please inspect the Message object directly.') self.assertEqual(len(warnings), 1)
def dataReceived(self, data): self.buffer += data while self.buffer: if self.length is None and len(self.buffer) >= 2: self.length = struct.unpack('!H', self.buffer[:2])[0] self.buffer = self.buffer[2:] if len(self.buffer) >= self.length: myChunk = self.buffer[:self.length] m = Message() m.fromStr(myChunk) try: d, canceller = self.liveMessages[m.id] except KeyError: self.controller.messageReceived(m, self) else: del self.liveMessages[m.id] canceller.cancel() try: if self.factory.controller is not None: d, self.factory.controller = self.factory.controller, None message = Message() strio = StringIO.StringIO(myChunk) message.encode(strio) back = strio.getvalue() b = m.toStr() d.callback(b) # d.callback(back) # print 'dir(self.factory):',dir(self.factory.ip) # d.callback(m.toStr()) except: log.err() self.buffer = self.buffer[self.length:] self.length = None else: break
def test_lookupAddress(self): """ L{SecondaryAuthority.lookupAddress} returns a L{Deferred} that fires with the I{A} records the authority has cached from the primary. """ secondary = SecondaryAuthority.fromServerAddressAndDomain( ("192.168.1.2", 1234), b"example.com") secondary._reactor = reactor = MemoryReactorClock() secondary.transfer() host, port, factory, timeout, bindAddress = reactor.tcpClients.pop(0) proto = factory.buildProtocol((host, port)) transport = StringTransport() proto.makeConnection(transport) query = Message(answer=1, auth=1) query.decode(BytesIO(transport.value()[2:])) # Generate a response with some data we can check. soa = Record_SOA( mname=b"ns1.example.com", rname="admin.example.com", serial=123456, refresh=3600, minimum=4800, expire=7200, retry=9600, ttl=12000, ) a = Record_A(b"192.168.1.2", ttl=0) answer = Message(id=query.id, answer=1, auth=1) answer.answers.extend([ RRHeader(b"example.com", type=SOA, payload=soa), RRHeader(b"example.com", payload=a), RRHeader(b"example.com", type=SOA, payload=soa), ]) data = answer.toStr() proto.dataReceived(pack("!H", len(data)) + data) result = self.successResultOf(secondary.lookupAddress("example.com")) self.assertEqual( ([RRHeader(b"example.com", payload=a, auth=True)], [], []), result)
def buildResponseBytes(data): inMessage = Message() inMessage.fromStr(data) return(buildResponse(inMessage).toStr())
def _rcodeTest(self, rcode, exc): m = Message(rCode=rcode) err = self.resolver.filterAnswers(m) err.trap(exc)