예제 #1
0
    def read_master_file(self, filename):
        """Read the zone from a master file

        See section 5 of RFC 1035.

        Args:
            filename (str): the filename of the master file
        """
        records = re.finditer(
            Zone.record_re, open(filename, "r").read(), flags=re.MULTILINE
        )
        for r in records:
            domain, ttl, class_, type_, rdata = r.groups()
            domain = domain or self.last_domain
            self.last_domain = domain
            record = ResourceRecord(
                name=Name(domain),
                type_=Type[type_],
                class_=Class[class_],
                ttl=int(ttl) if ttl is not None else Zone.default_ttl,
                rdata=RecordData.create_from_str(Type[type_], rdata)
            )
            if domain in self.records:
                self.records[domain].append(record)
            else:
                self.records[domain] = [record]
예제 #2
0
    def load_and_parse(self, content):
        content = re.sub(re.compile(";.*?\n"), "\n", content)  #Remove comments
        content = re.sub(re.compile("\n\n*\n"), "\n",
                         content)  #Remove whitespaces
        content = re.sub(re.compile("  * "), " ",
                         content)  #Remove multiple spaces between words
        content = re.sub(re.compile("\t\t*\t"), " ",
                         content)  #Remove tabs between words
        content = re.sub(re.compile("\n *"), "\n",
                         content)  #Remove spaces at start of line
        content = re.sub(re.compile("\n\t*"), "\n",
                         content)  #Remove tabs at start of line
        content = re.compile(r'\(.*?\)', re.DOTALL)\
            .sub(lambda x: x.group().replace('\n', ''), content) #Remove newlines between ()
        content = re.sub(re.compile("\t+"), " ",
                         content)  #Remove tabs between words
        default_ttl = None
        origin = None

        recordSet = []

        for line in content.split('\n'):
            if line[:4] == "$TTL":
                prev_ttl = self.time_to_seconds(line[4:].strip())
            elif line[:7] == "$ORIGIN":
                origin = line[7:].strip()
            elif "SOA" not in line:
                parts = line.split(' ')
                rr_name = parts[0]

                rr_ttl = self.time_to_seconds(parts[1])
                offset = int(rr_ttl == 0)
                if offset:
                    rr_ttl = prev_ttl

                rr_class = Class[parts[1 + offset]]
                rr_type = parts[2 + offset]
                if Type[rr_type] == Type.CNAME or Type[rr_type] == Type.NS:
                    rr_data = RecordData.create(
                        Type[rr_type], Name(parts[3 + offset].rstrip('.')))
                else:
                    rr_data = RecordData.create(Type[rr_type],
                                                parts[3 + offset].rstrip('.'))
                self.add_node(
                    rr_name,
                    ResourceRecord(Name(rr_name), Type[rr_type], rr_class,
                                   rr_ttl, rr_data))
    def setUp(self):
        # put invalid record in cache file
        record_data = RecordData.create(Type.A, "192.168.123.456")
        self.rr = ResourceRecord("invalid.invalid", Type.A, Class.IN, 3, record_data)

        cache = RecordCache()
        cache.add_record(self.rr)
        cache.write_cache_file()
 def test_cache_lookup(self):
     """
     Add a record to the cache and look it up
     """
     rr = ResourceRecord("wiki.nl", Type.A, Class.IN, self.ttl, RecordData.create(Type.A, "192.168.123.456"))
     cache = RecordCache()
     cache.add_record(rr)
     lookup_vals = cache.lookup("wiki.nl", Type.A, Class.IN)
     self.assertEqual([rr], lookup_vals)
    def setUp(self):
        # put invalid record in cache file
        record_data = RecordData.create(Type.A, "192.168.123.456")
        self.rr = ResourceRecord("invalid.invalid", Type.A, Class.IN, 3,
                                 record_data)

        cache = RecordCache()
        cache.add_record(self.rr)
        cache.write_cache_file()
 def test_cache_lookup(self):
     """
     Add a record to the cache and look it up
     """
     rr = ResourceRecord("wiki.nl", Type.A, Class.IN, self.ttl,
                         RecordData.create(Type.A, "192.168.123.456"))
     cache = RecordCache()
     cache.add_record(rr)
     lookup_vals = cache.lookup("wiki.nl", Type.A, Class.IN)
     self.assertEqual([rr], lookup_vals)
    def test_TTL_expiration(self):
        """
        cache a record, wait till ttl expires, see if record is removed from cache
        """
        rr = ResourceRecord("wiki.nl", Type.A, Class.IN, self.ttl, RecordData.create(Type.A, "192.168.123.456"))
        cache = RecordCache()
        cache.add_record(rr)

        time.sleep(rr.ttl)

        lookup_vals = cache.lookup("wiki.nl", Type.A, Class.IN)
        self.assertFalse(lookup_vals)
예제 #8
0
def resource_from_json(dct):
    """ Convert JSON object to ResourceRecord
    
    Usage:
        records = json.loads(string, object_hook=resource_from_json)
    """
    name = dct["name"]
    type_ = Type.from_string(dct["type"])
    class_ = Class.from_string(dct["class"])
    ttl = dct["ttl"]
    rdata = RecordData.create(type_, dct["rdata"])
    return ResourceRecord(name, type_, class_, ttl, rdata)
    def test_TTL_expiration(self):
        """
        cache a record, wait till ttl expires, see if record is removed from cache
        """
        rr = ResourceRecord("wiki.nl", Type.A, Class.IN, self.ttl,
                            RecordData.create(Type.A, "192.168.123.456"))
        cache = RecordCache()
        cache.add_record(rr)

        time.sleep(rr.ttl)

        lookup_vals = cache.lookup("wiki.nl", Type.A, Class.IN)
        self.assertFalse(lookup_vals)
예제 #10
0
    def resource_from_json(dct):
        """ Convert JSON object to ResourceRecord

        Usage:
            records = json.loads(string, object_hook=resource_from_json)
        """
        name = dct["name"]
        type_ = Type.from_string(dct["type"])
        class_ = Class.from_string(dct["class"])
        ttl = dct["ttl"]
        rdata = RecordData.create(type_, dct["rdata"])
        t = dct["time"]
        return ResourceRecord(name, type_, class_, ttl, rdata, t)
예제 #11
0
    def test_cache_disk_io(self):
        """
        Add a record to the cache, write to disk, read from disk, do a lookup
        """
        rr = ResourceRecord("wiki.nl", Type.A, Class.IN, self.ttl, RecordData.create(Type.A, "192.168.123.456"))
        cache = RecordCache()
        cache.write_cache_file() # overwrite the current cache file

        # add rr to cache and write to disk
        cache.add_record(rr)
        cache.write_cache_file()

        # read from disk again
        new_cache = RecordCache()
        new_cache.read_cache_file()
        lookup_vals = new_cache.lookup("wiki.nl", Type.A, Class.IN)
        self.assertEqual([rr], lookup_vals)
    def test_cache_disk_io(self):
        """
        Add a record to the cache, write to disk, read from disk, do a lookup
        """
        rr = ResourceRecord("wiki.nl", Type.A, Class.IN, self.ttl,
                            RecordData.create(Type.A, "192.168.123.456"))
        cache = RecordCache()
        cache.write_cache_file()  # overwrite the current cache file

        # add rr to cache and write to disk
        cache.add_record(rr)
        cache.write_cache_file()

        # read from disk again
        new_cache = RecordCache()
        new_cache.read_cache_file()
        lookup_vals = new_cache.lookup("wiki.nl", Type.A, Class.IN)
        self.assertEqual([rr], lookup_vals)
예제 #13
0
 def setUpClass(cls):
     cls.ttl = 3
     rr = ResourceRecord("wiki.nl", Type.A, Class.IN, cls.ttl, RecordData.create(Type.A, "192.168.123.456"))
 def setUpClass(cls):
     cls.ttl = 3
     rr = ResourceRecord("wiki.nl", Type.A, Class.IN, cls.ttl,
                         RecordData.create(Type.A, "192.168.123.456"))
예제 #15
0
    def handle_request(self):
        """ Attempts to answer the received query """
        #Check this next to the given algorithm

        #print("Catalog:",self.catalog.zones)
        #for zone in self.catalog.zones:
        #    print("Records:",self.catalog.zones[zone].records)

        if self.message.header.opcode != 0:  #Send a not implemented error, we don't need to support those kinds of queries
            print("[-] - Received a nonstandard query. This is unsupported.")
            header = Header(ident, 0, 1, 0, 0, 0)
            header.qr = 1
            header.rd = self.message.header.rd
            header.ra = 1
            header.rcode = 4
            self.sendResponse(Message(header, self.message.questions, []))
            return

        #print("[*] - Handling request.")
        if len(self.message.questions) != 1:  #Send a format error response
            print("[-] - Invalid request.")
            header = Header(ident, 0, 1, 0, 0, 0)
            header.qr = 1
            header.rd = self.message.header.rd
            header.ra = 1
            header.rcode = 1
            self.sendResponse(Message(header, self.message.questions, []))
            return
        #print("MSG:",self.message)
        #print("RECEIVED QUESTION",self.message.questions[0])
        hname = str(self.message.questions[0].qname)
        #print("Solving",hname,type(hname))
        ident = self.message.header.ident
        #print("Checking zone")
        answer, authority, found = self.check_zone(hname)
        #print("Wat we in de zone hebben gevonden")
        #print("ANS:",answer,"AUTH:",authority,"FOUND:",found)
        #found = False
        if found:
            print("Found in zone")
            header = Header(ident, 0, 1, len(answer), len(authority), 0)
            header.qr = 1
            header.aa = 1
            header.rd = self.message.header.rd
            header.ra = 1

            self.sendResponse(
                Message(header, self.message.questions, answer, authority))

        elif self.message.header.rd == 1:
            h, al, ad = self.resolver.gethostbyname(hname)

            #Make and send th appropriate response
            header = Header(ident, 0, 1, len(al) + len(ad), 0, 0)
            header.qr = 1
            header.rd = self.message.header.rd
            header.ra = 1

            aliases = [
                ResourceRecord(Name(h), Type.CNAME, Class.IN, self.ttl,
                               RecordData.create(Type.CNAME, Name(alias)))
                for alias in al
            ]
            addresses = [
                ResourceRecord(Name(h), Type.A, Class.IN, self.ttl,
                               RecordData.create(Type.A, address))
                for address in ad
            ]

            self.sendResponse(
                Message(header, self.message.questions, aliases + addresses))
        else:  #Send an empty response
            header = Header(ident, 0, 1, 0, 0, 0)
            header.qr = 1
            header.rd = self.message.header.rd
            header.ra = 1
            header.rcode = 0
            self.sendResponse(Message(header, self.message.questions, []))