Example #1
0
    def test_resource_record_equal(self):
        """
        Test case for comparing two equal resource records.
        """

        record1: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "1.2.3.4")
        record2: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "1.2.3.4")

        self.assertTrue(record1 == record2)
Example #2
0
    def test_resource_record_not_equal_rdata(self):
        """
        Test case for comparing two resource records with different rdata.
        """

        record1: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "1.2.3.4")
        record2: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "6.5.3.1")

        self.assertTrue(record1 != record2)
Example #3
0
    def test_resource_record_not_equal_name(self):
        """
        Test case for comparing two resource records with different names.
        """

        record1: ResourceRecord = ResourceRecord("name1", 1, 1, 600, 4, "1.2.3.4")
        record2: ResourceRecord = ResourceRecord("name2", 1, 1, 600, 4, "1.2.3.4")

        self.assertTrue(record1 != record2)
Example #4
0
    def test_main_helper_two_answers_returned(self):
        """
        Test case for when the resolver returns two answers
        """
        mock_resolver: Mock = Mock(**{'ask.return_value': [ResourceRecord("www.ubc.cs.ca", 1, 1, 600, 4, "1.2.3.4"),
                                                           ResourceRecord("www.ubc.cs.ca", 28, 1, 2000, 4, "5.6.7.8")]})

        with redirect_stdout(self.buffer):
            main_helper(mock_resolver, "www.cs.ubc.ca", "1.2.3.4", False, False)

        self.assertEqual(self.buffer.getvalue(), "\nAnswers:"
                                                 "\n  www.cs.ubc.ca 600   A 1.2.3.4"
                                                 "\n  www.cs.ubc.ca 2000   AAAA 5.6.7.8\n")
Example #5
0
    def test_parse_type_ns_type(self):
        """
        Test case to parse a type of value 2 (NS type).
        """

        a_type: str = ResourceRecord.parse_type(self.ns_type)
        self.assertEqual(a_type, 'NS')
Example #6
0
    def test_parse_type_cn_type(self):
        """
        Test case to parse a type of value 5 (CN type).
        """

        a_type: str = ResourceRecord.parse_type(self.cn_type)
        self.assertEqual(a_type, 'CN')
Example #7
0
    def test_parse_type_unsupported_type(self):
        """
        Test case to parse a type of value 3, which is unsupported by dns_shark.
        """

        a_type: str = ResourceRecord.parse_type(self.unsupported_type)
        self.assertEqual(a_type, '3')
Example #8
0
    def test_parse_type_aaaa_type(self):
        """
        Test case to parse a type of value 28 (AAAA type).
        """

        a_type: str = ResourceRecord.parse_type(self.aaaa_type)
        self.assertEqual(a_type, 'AAAA')
Example #9
0
 def test_decode_rdata_unsupported_type(self):
     """
     Test case to decode rdata of an unsupported type.
     """
     rdata: BytesIO = BytesIO(self.ipv6_address_data)
     copy: BytesIO = BytesIO(self.ipv6_address_data)
     ipv6_address: str = ResourceRecord._decode_rdata(rdata, copy, self.unsupported_type)
     self.assertEqual(ipv6_address, 'UNSUPPORTED RESOURCE RECORD TYPE')
Example #10
0
 def test_decode_rdata_aaaa_type(self):
     """
     Test case to decode rdata of type aaaa (ipv6).
     """
     rdata: BytesIO = BytesIO(self.ipv6_address_data)
     copy: BytesIO = BytesIO(self.ipv6_address_data)
     ipv6_address: str = ResourceRecord._decode_rdata(rdata, copy, self.aaaa_type)
     self.assertEqual(ipv6_address, '1008:2002:1008:2002:1008:2002:1008:2002')
Example #11
0
    def test_resource_record_not_equal_different_object_type(self):
        """
        Test case for comparing two resource records with different rdata.
        """

        record1: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "1.2.3.4")

        self.assertTrue(record1 != "string value")
Example #12
0
 def test_decode_rdata_a_type(self):
     """
     Test case to decode rdata of type a (ipv4).
     """
     rdata: BytesIO = BytesIO(self.ipv4_address_data)
     copy: BytesIO = BytesIO(self.ipv4_address_data)
     ipv4_address: str = ResourceRecord._decode_rdata(rdata, copy, self.a_type)
     self.assertEqual(ipv4_address, '16.8.32.2')
Example #13
0
 def test_decode_rdata_cn_type(self):
     """
     Test case to decode rdata of type cn (name server).
     """
     rdata: BytesIO = BytesIO(self.simple_domain_name_encoded)
     copy: BytesIO = BytesIO(self.simple_domain_name_encoded)
     decoded_domain_name: str = ResourceRecord._decode_rdata(rdata, copy, self.cn_type)
     self.assertEqual(decoded_domain_name, self.simple_domain_name)
    def test_name_resolution(self):
        """
        Test case for when name resolution requires performing a name resolution.

        This is also a case where the name resolution returns multiple answers.
        """

        resolver: ResolverCore = ResolverCore(self.mock_socket, False,
                                              "1.2.3.4", self.mock_random)

        answers: List[ResourceRecord] = resolver.resolve_domain_name(
            "www.stanford.edu", "1.2.3.4", 1)
        expected_answer: List[ResourceRecord] = [
            ResourceRecord('www.stanford.edu', 1, 1, 60, 4, '54.218.91.228'),
            ResourceRecord('www.stanford.edu', 1, 1, 60, 4, '52.27.175.139'),
            ResourceRecord('www.stanford.edu', 1, 1, 60, 4, '52.10.247.217')
        ]

        self.assertEqual(answers, expected_answer)
    def test_cname_resolution(self):
        """
        Test case for when name resolution requires performing a cname resolution.
        """

        resolver: ResolverCore = ResolverCore(self.mock_socket, False, "1.2.3.4", self.mock_random)

        answers: List[ResourceRecord] = resolver.resolve_domain_name("prep.ai.mit.edu", "1.2.3.4", 1)
        expected_answer: List[ResourceRecord] = [ResourceRecord('ftp.gnu.org', 1, 1, 300, 4, '208.118.235.20')]

        self.assertEqual(answers, expected_answer)
    def test_matching_authoritative_response(self):
        """
        Test case for when the first response given by the queried dns name server is an authoritative response with
        a matching resource record type.
        """

        resolver: ResolverCore = ResolverCore(self.mock_socket, False, "1.2.3.4", self.mock_random)

        answers: List[ResourceRecord] = resolver.resolve_domain_name("www.cs.ubc.ca", "1.2.3.4", 1)
        expected_answer: List[ResourceRecord] = [ResourceRecord('www.cs.ubc.ca', 1, 1, 3600, 4, '142.103.6.5')]

        self.assertEqual(answers, expected_answer)
    def test_incorrect_query_id(self):
        """
        Test case for when a response is received that does not match the query id of the previously sent message. Thus,
        the resolver discards the packet and waits for another packet with the correct query id.
        """

        resolver: ResolverCore = ResolverCore(self.mock_socket, False, "1.2.3.4", self.mock_random)

        answers: List[ResourceRecord] = resolver.resolve_domain_name("www.cs.ubc.ca", "1.2.3.4", 1)
        expected_answer: List[ResourceRecord] = [ResourceRecord('www.cs.ubc.ca', 1, 1, 3600, 4, '142.103.6.5')]

        self.assertEqual(answers, expected_answer)
Example #18
0
    def test_print_dns_response(self):
        """
        Test case for printing dns responses to stdout.
        """

        message: DNSMessage = DNSMessage(
            1, True, 1, True, True, True, True, 1, 1, 1, 2, 3,
            [DNSQuestion("question", 1, 1)],
            [ResourceRecord("record1", 10, 11, 12, 4, "1.2.3.4")], [
                ResourceRecord("record1", 10, 11, 12, 4, "1.2.3.4"),
                ResourceRecord("record2", 15, 16, 17, 4, "5.6.7.8")
            ], [
                ResourceRecord("record1", 10, 11, 12, 4, "1.2.3.4"),
                ResourceRecord("record2", 15, 16, 17, 4, "5.6.7.8"),
                ResourceRecord("record3", 18, 19, 20, 4, "9.10.11.12")
            ])

        buffer: StringIO = StringIO()

        with redirect_stdout(buffer):
            message.print_dns_response()

        self.assertEqual(
            buffer.getvalue(), "Response ID: 1 Authoritative = True\n"
            "  Answers (1)\n"
            "      record1                        12         10   1.2.3.4\n"
            "  Name Servers (2)\n"
            "      record1                        12         10   1.2.3.4\n"
            "      record2                        17         15   5.6.7.8\n"
            "  Additional Information (3)\n"
            "      record1                        12         10   1.2.3.4\n"
            "      record2                        17         15   5.6.7.8\n"
            "      record3                        20         18   9.10.11.12\n"
        )
Example #19
0
    def test_decode_resource_record(self):
        """
        Test case to decode a resource record.
        """
        resource_record: ResourceRecord = ResourceRecord.decode_resource_record(BytesIO(self.resource_record_encoded),
                                                                                BytesIO(self.resource_record_encoded))

        self.assertEqual(resource_record.name, 'ca')
        self.assertEqual(resource_record.type, self.ns_type)
        self.assertEqual(resource_record.response_class, 1)
        self.assertEqual(resource_record.ttl, 150873)
        self.assertEqual(resource_record.rdlength, 14)
        self.assertEqual(resource_record.rdata, 'x.ca-servers')
Example #20
0
    def test_print_record_for_trace(self):
        """
        Test case for printing resource records for the tracing
        """

        record: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "1.2.3.4")

        buffer: StringIO = StringIO()

        with redirect_stdout(buffer):
            record.print_record_for_trace()

        self.assertEqual(buffer.getvalue(), "      record                         600        A    1.2.3.4\n")
Example #21
0
    def print_dns_query(self, dns_server_ip: str) -> None:
        """
        Print a dns query message.

        This includes printing the query id, domain name being asked for by the dns query,
        the type of record being asked for, and the dns server that is being queried.

        :param dns_server_ip: ip address of the dns server the domain name resolution request was sent to.
        :return: None
        """
        print('Query ID:    ' + str(self.query_id) + ' ' +
              self.dns_questions[0].name + '  ' +
              ResourceRecord.parse_type(self.dns_questions[0].type) + ' --> ' +
              dns_server_ip)
Example #22
0
    def test_get_name_server_ip_address_helper_no_additional_records(self):
        """
        Test case to retrieve the ip address for a name server for which there is additional record whose
        name matches the name server name.
        """

        name_server_record: ResourceRecord = ResourceRecord(
            "ca", 2, 1, 172800, 8, "no-match")

        name_server_ip: Optional[
            str] = DNSMessage.get_name_server_ip_address_helper(
                name_server_record, [])

        self.assertEqual(name_server_ip, None)
Example #23
0
    def test_get_name_server_ip_address_helper_no_type_match(self):
        """
        Test case to retrieve the ip address for a name server for which there is an additional record whose
        name is the name server name, but is of the incorrect type.
        """

        name_server_record: ResourceRecord = ResourceRecord(
            "ca", 2, 1, 172800, 8, "y.ubc.ca")

        name_server_ip: Optional[
            str] = DNSMessage.get_name_server_ip_address_helper(
                name_server_record, self.additional_records)

        self.assertEqual(name_server_ip, None)
Example #24
0
    def test_get_name_server_ip_address_helper_only_one_match(self):
        """
        Test case to retrieve the ip address of a name server for which there is a match of the correct type
        and there is only one match in the additional records.
        """

        name_server_record: ResourceRecord = ResourceRecord(
            "ca", 2, 1, 172800, 8, "x.ubc.ca")

        name_server_ip: Optional[
            str] = DNSMessage.get_name_server_ip_address_helper(
                name_server_record, self.additional_records)

        self.assertEqual(name_server_ip, "1.2.3.4")
Example #25
0
    def test_resource_record_print(self):
        """
        Test case for printing a resource record using print(), which calls __repr__().
        """

        record: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "1.2.3.4")

        buffer: StringIO = StringIO()

        with redirect_stdout(buffer):
            print(record)

        self.assertEqual(buffer.getvalue(), "ResourceRecord(name: record, type: 1, class: 1, "
                                            "ttl: 600, rdlength: 4, rdata: 1.2.3.4)\n")
Example #26
0
    def test_name_server_response_then_authoritative_ipv6(self):
        """
        Test case for when the first two responses non-authoritative responses and the final one is authoritative and
        contains a matching resource record.

        The first two responses both contain the ip address a name server, so we do
        not need to do a separate lookup for the ip address of the name server.
        """

        resolver: ResolverCore = ResolverCore(self.mock_socket, False, "1.2.3.4", self.mock_random)

        answers: List[ResourceRecord] = resolver.resolve_domain_name("www.google.com", "1.2.3.4", 28)
        expected_answer: List[ResourceRecord] = [ResourceRecord('www.google.com', 28, 1, 300, 16, '2607:f8b0:400a:803::2004')]

        self.assertEqual(answers, expected_answer)
Example #27
0
    def test_print_record_with_supplied_domain_name(self):
        """
        Test case for printing resource records with a supplied domain name to be included in the message. (Used when
        printing the answers of the resolver. We supply the original domain name that was searched for to clearly
        indicate to the user that the records we have found are for the domain name they initially searched for.)
        """

        record: ResourceRecord = ResourceRecord("record", 1, 1, 600, 4, "1.2.3.4")

        buffer: StringIO = StringIO()

        with redirect_stdout(buffer):
            record.print_record_with_supplied_domain_name("the original domain name")

        self.assertEqual(buffer.getvalue(), "  the original domain name 600   A 1.2.3.4\n")
Example #28
0
    def test_get_name_server_ip_address_helper_multiple_matches(self):
        """
        Test case to retrieve the ip address of a name server for which there is a match of the correct type
        and there are multiple matching records in the additional records. The first match's ip address should be
        returned.
        """

        name_server_record: ResourceRecord = ResourceRecord(
            "ca", 2, 1, 172800, 8, "z.ubc.ca")

        name_server_ip: Optional[
            str] = DNSMessage.get_name_server_ip_address_helper(
                name_server_record, self.additional_records)

        self.assertEqual(name_server_ip, "3.4.5.6")
Example #29
0
    def test_cname_resolution(self):
        """
        Test case for when two different cname resolutions and one name server resolution
        needs to be performed before finding an authoritative response.
        """

        resolver: ResolverCore = ResolverCore(self.mock_socket, False,
                                              "1.2.3.4", self.mock_random)

        answers: List[ResourceRecord] = resolver.resolve_domain_name(
            "finance.google.ca", "1.2.3.4", 1)
        expected_answer: List[ResourceRecord] = [
            ResourceRecord('www3.l.google.com', 1, 1, 300, 4, '216.58.193.78')
        ]

        self.assertEqual(answers, expected_answer)
Example #30
0
    def _read_resource_records(data: BytesIO, copy_of_message: BytesIO,
                               num_of_records: int) -> List[ResourceRecord]:
        """
        Read the resource records from the remaining dns message data.

        :param data: the remaining data of the dns message to be processed
        :param copy_of_message: a copy of the entire dns message, used for handling pointers in domain names
        :param num_of_records: number of records to decode
        :return: list of the resource records decoded
        """
        list_of_records = []
        for _ in range(num_of_records):
            list_of_records.append(
                ResourceRecord.decode_resource_record(data, copy_of_message))

        return list_of_records