Exemple #1
0
class SRV(RD):

    priority = H('priority')
    weight = H('weight')
    port = H('port')

    @classmethod
    def parse(cls, buffer, length):
        try:
            priority, weight, port = buffer.unpack("!HHH")
            target = buffer.decode_name()
            return cls(priority, weight, port, target)
        except (BufferError, BimapError) as e:
            raise DNSError("Error unpacking SRV [offset=%d]: %s" %
                           (buffer.offset, e))

    @classmethod
    def fromZone(cls, rd, origin=None):
        return cls(int(rd[0]), int(rd[1]), int(rd[2]), rd[3])

    def __init__(self, priority=0, weight=0, port=0, target=None):
        self.priority = priority
        self.weight = weight
        self.port = port
        self.target = target

    def set_target(self, target):
        if isinstance(target, DNSLabel):
            self._target = target
        else:
            self._target = DNSLabel(target)

    def get_target(self):
        return self._target

    target = property(get_target, set_target)

    def pack(self, buffer):
        buffer.pack("!HHH", self.priority, self.weight, self.port)
        buffer.encode_name(self.target)

    def __repr__(self):
        return "%d %d %d %s" % (self.priority, self.weight, self.port,
                                self.target)

    attrs = ('priority', 'weight', 'port', 'target')
Exemple #2
0
class MX(RD):

    preference = H('preference')

    @classmethod
    def parse(cls,buffer,length):
        try:
            (preference,) = buffer.unpack("!H")
            mx = buffer.decode_name()
            return cls(mx,preference)
        except (BufferError,BimapError) as e:
            raise DNSError("Error unpacking MX [offset=%d]: %s" %
                                        (buffer.offset,e))

    @classmethod
    def fromZone(cls,rd,origin=None):
        return cls(label(rd[1],origin),int(rd[0]))

    def __init__(self,label=None,preference=10):
        self.label = label
        self.preference = preference

    def set_label(self,label):
        if isinstance(label,DNSLabel):
            self._label = label
        else:
            self._label = DNSLabel(label)

    def get_label(self):
        return self._label

    label = property(get_label,set_label)

    def pack(self,buffer):
        buffer.pack("!H",self.preference)
        buffer.encode_name(self.label)

    def __repr__(self):
        return "%d %s" % (self.preference,self.label)

    attrs = ('preference','label')
Exemple #3
0
class DNSKEY(RD):

    flags = H('flags')
    protocol = B('protocol')
    algorithm = B('algorithm')

    @classmethod
    def parse(cls,buffer,length):
        try:
            (flags,protocol,algorithm) = buffer.unpack("!HBB")
            key = buffer.get(length - 4)
            return cls(flags,protocol,algorithm,key)
        except (BufferError,BimapError) as e:
            raise DNSError("Error unpacking DNSKEY [offset=%d]: %s" %
                                        (buffer.offset,e))

    @classmethod
    def fromZone(cls,rd,origin=None):
        return cls(int(rd[0]),int(rd[1]),int(rd[2]),
                   base64.b64decode(("".join(rd[3:])).encode('ascii')))

    def __init__(self,flags,protocol,algorithm,key):
        self.flags = flags
        self.protocol = protocol
        self.algorithm = algorithm
        self.key = key

    def pack(self,buffer):
        buffer.pack("!HBB",self.flags,self.protocol,self.algorithm)
        buffer.append(self.key)

    def __repr__(self):
        return "%d %d %d %s" % (self.flags,self.protocol,self.algorithm,
                                base64.b64encode(self.key).decode())

    attrs = ('flags','protocol','algorithm','key')
Exemple #4
0
class RR(object):

    """
        DNS Resource Record
        Contains RR header and RD (resource data) instance
    """

    rtype = H('rtype')
    rclass = H('rclass')
    ttl = I('ttl')
    rdlength = H('rdlength')

    @classmethod
    def parse(cls,buffer):
        try:
            rname = buffer.decode_name()
            rtype,rclass,ttl,rdlength = buffer.unpack("!HHIH")
            if rtype == QTYPE.OPT:
                options = []
                option_buffer = Buffer(buffer.get(rdlength))
                while option_buffer.remaining() > 4:
                    code,length = option_buffer.unpack("!HH")
                    data = option_buffer.get(length)
                    options.append(EDNSOption(code,data))
                rdata = options
            else:
                if rdlength:
                    rdata = RDMAP.get(QTYPE.get(rtype),RD).parse(
                                            buffer,rdlength)
                else:
                    rdata = ''
            return cls(rname,rtype,rclass,ttl,rdata)
        except (BufferError,BimapError) as e:
            raise DNSError("Error unpacking RR [offset=%d]: %s" % (
                                buffer.offset,e))

    @classmethod
    def fromZone(cls,zone,origin="",ttl=0):
        """
            Parse RR data from zone file and return list of RRs
        """
        return list(ZoneParser(zone,origin=origin,ttl=ttl))

    def __init__(self,rname=None,rtype=1,rclass=1,ttl=0,rdata=None):
        self.rname = rname
        self.rtype = rtype
        self.rclass = rclass
        self.ttl = ttl
        self.rdata = rdata
        # TODO Add property getters/setters
        if self.rtype == QTYPE.OPT:
            self.edns_len = self.rclass
            self.edns_do = get_bits(self.ttl,15)
            self.edns_ver = get_bits(self.ttl,16,8)
            self.edns_rcode = get_bits(self.ttl,24,8)

    def set_rname(self,rname):
        if isinstance(rname,DNSLabel):
            self._rname = rname
        else:
            self._rname = DNSLabel(rname)

    def get_rname(self):
        return self._rname

    rname = property(get_rname,set_rname)

    def pack(self,buffer):
        buffer.encode_name(self.rname)
        buffer.pack("!HHI",self.rtype,self.rclass,self.ttl)
        rdlength_ptr = buffer.offset
        buffer.pack("!H",0)
        start = buffer.offset
        if self.rtype == QTYPE.OPT:
            for opt in self.rdata:
                opt.pack(buffer)
        else:
            self.rdata.pack(buffer)
        end = buffer.offset
        buffer.update(rdlength_ptr,"!H",end-start)

    def __repr__(self):
        if self.rtype == QTYPE.OPT:
            s = ["<DNS OPT: edns_ver=%d do=%d ext_rcode=%d udp_len=%d>" % (
                        self.edns_ver,self.edns_do,self.edns_rcode,self.edns_len)]
            s.extend([repr(opt) for opt in self.rdata])
            return "\n".join(s)
        else:
            return "<DNS RR: '%s' rtype=%s rclass=%s ttl=%d rdata='%s'>" % (
                    self.rname, QTYPE.get(self.rtype), CLASS.get(self.rclass),
                    self.ttl, self.rdata)

    def toZone(self):
        if self.rtype == QTYPE.OPT:
            edns = [ ";OPT PSEUDOSECTION",
                     ";EDNS: version: %d, flags: %s; udp: %d" % (
                             self.edns_ver,
                             "do" if self.edns_do else "",
                             self.edns_len)
                    ]
            edns.extend([str(opt) for opt in self.rdata])
            return "\n".join(edns)
        else:
            return '%-23s %-7s %-7s %-7s %s' % (self.rname,self.ttl,
                                                CLASS.get(self.rclass),
                                                QTYPE.get(self.rtype),
                                                self.rdata.toZone())

    def __str__(self):
        return self.toZone()

    def __ne__(self,other):
        return not(self.__eq__(other))

    def __eq__(self,other):
        if type(other) != type(self):
            return False
        else:
            # List of attributes to compare when diffing (ignore ttl)
            attrs = ('rname','rclass','rtype','rdata')
            return all([getattr(self,x) == getattr(other,x) for x in attrs])
Exemple #5
0
class DNSHeader(object):

    """
        DNSHeader section
    """

    # Ensure attribute values match packet
    id = H('id')
    bitmap = H('bitmap')
    q = H('q')
    a = H('a')
    auth = H('auth')
    ar = H('ar')

    @classmethod
    def parse(cls,buffer):
        """
            Implements parse interface
        """
        try:
            (id,bitmap,q,a,auth,ar) = buffer.unpack("!HHHHHH")
            return cls(id,bitmap,q,a,auth,ar)
        except (BufferError,BimapError) as e:
            raise DNSError("Error unpacking DNSHeader [offset=%d]: %s" % (
                                buffer.offset,e))

    def __init__(self,id=None,bitmap=None,q=0,a=0,auth=0,ar=0,**args):
        if id is None:
            self.id = random.randint(0,65535)
        else:
            self.id = id
        if bitmap is None:
            self.bitmap = 0
            self.rd = 1
        else:
            self.bitmap = bitmap
        self.q = q
        self.a = a
        self.auth = auth
        self.ar = ar
        for k,v in list(args.items()):
            if k.lower() == "qr":
                self.qr = v
            elif k.lower() == "opcode":
                self.opcode = v
            elif k.lower() == "aa":
                self.aa = v
            elif k.lower() == "tc":
                self.tc = v
            elif k.lower() == "rd":
                self.rd = v
            elif k.lower() == "ra":
                self.ra = v
            elif k.lower() == "rcode":
                self.rcode = v

    # Accessors for header properties (automatically pack/unpack
    # into bitmap)
    def get_qr(self):
        return get_bits(self.bitmap,15)

    def set_qr(self,val):
        self.bitmap = set_bits(self.bitmap,val,15)

    qr = property(get_qr,set_qr)

    def get_opcode(self):
        return get_bits(self.bitmap,11,4)

    def set_opcode(self,val):
        self.bitmap = set_bits(self.bitmap,val,11,4)

    opcode = property(get_opcode,set_opcode)

    def get_aa(self):
        return get_bits(self.bitmap,10)

    def set_aa(self,val):
        self.bitmap = set_bits(self.bitmap,val,10)

    aa = property(get_aa,set_aa)

    def get_tc(self):
        return get_bits(self.bitmap,9)

    def set_tc(self,val):
        self.bitmap = set_bits(self.bitmap,val,9)

    tc = property(get_tc,set_tc)

    def get_rd(self):
        return get_bits(self.bitmap,8)

    def set_rd(self,val):
        self.bitmap = set_bits(self.bitmap,val,8)

    rd = property(get_rd,set_rd)

    def get_ra(self):
        return get_bits(self.bitmap,7)

    def set_ra(self,val):
        self.bitmap = set_bits(self.bitmap,val,7)

    ra = property(get_ra,set_ra)

    def get_rcode(self):
        return get_bits(self.bitmap,0,4)

    def set_rcode(self,val):
        self.bitmap = set_bits(self.bitmap,val,0,4)

    rcode = property(get_rcode,set_rcode)

    def pack(self,buffer):
        buffer.pack("!HHHHHH",self.id,self.bitmap,
                              self.q,self.a,self.auth,self.ar)

    def __repr__(self):
        f = [ self.aa and 'AA',
              self.tc and 'TC',
              self.rd and 'RD',
              self.ra and 'RA' ]
        if OPCODE.get(self.opcode) == 'UPDATE':
            f1='zo'
            f2='pr'
            f3='up'
            f4='ad'
        else:
            f1='q'
            f2='a'
            f3='ns'
            f4='ar'
        return "<DNS Header: id=0x%x type=%s opcode=%s flags=%s " \
                            "rcode='%s' %s=%d %s=%d %s=%d %s=%d>" % (
                    self.id,
                    QR.get(self.qr),
                    OPCODE.get(self.opcode),
                    ",".join([_f for _f in f if _f]),
                    RCODE.get(self.rcode),
                    f1, self.q, f2, self.a, f3, self.auth, f4, self.ar )

    def toZone(self):
        f = [ self.qr and 'qr',
              self.aa and 'aa',
              self.tc and 'tc',
              self.rd and 'rd',
              self.ra and 'ra' ]
        z1 = ';; ->>HEADER<<- opcode: %s, status: %s, id: %d' % (
                    OPCODE.get(self.opcode),RCODE.get(self.rcode),self.id)
        z2 = ';; flags: %s; QUERY: %d, ANSWER: %d, AUTHORITY: %d, ADDITIONAL: %d' % (
                      " ".join([_f for _f in f if _f]),
                      self.q,self.a,self.auth,self.ar)
        return z1 + "\n" + z2

    def __str__(self):
        return self.toZone()

    def __ne__(self,other):
        return not(self.__eq__(other))

    def __eq__(self,other):
        if type(other) != type(self):
            return False
        else:
            # Ignore id
            attrs = ('qr','aa','tc','rd','ra','opcode','rcode')
            return all([getattr(self,x) == getattr(other,x) for x in attrs])
Exemple #6
0
class RRSIG(RD):

    covered = H('covered')
    algorithm = B('algorithm')
    labels = B('labels')
    orig_ttl = I('orig_ttl')
    sig_exp = I('sig_exp')
    sig_inc = I('sig_inc')
    key_tag = H('key_tag')

    @classmethod
    def parse(cls,buffer,length):
        try:
            start = buffer.offset
            (covered,algorithm,labels,
                orig_ttl,sig_exp,sig_inc,key_tag) = buffer.unpack("!HBBIIIH")
            name = buffer.decode_name()
            sig = buffer.get(length - (buffer.offset - start))
            return cls(covered,algorithm,labels,orig_ttl,sig_exp,sig_inc,key_tag,
                            name,sig)
        except (BufferError,BimapError) as e:
            raise DNSError("Error unpacking DNSKEY [offset=%d]: %s" %
                                        (buffer.offset,e))

    @classmethod
    def fromZone(cls,rd,origin=None):
        return cls(getattr(QTYPE,rd[0]),int(rd[1]),int(rd[2]),int(rd[3]),
                        int(time.mktime(time.strptime(rd[4]+'GMT',"%Y%m%d%H%M%S%Z"))),
                        int(time.mktime(time.strptime(rd[5]+'GMT',"%Y%m%d%H%M%S%Z"))),
                        int(rd[6]),rd[7],
                        base64.b64decode(("".join(rd[8:])).encode('ascii')))

    def __init__(self,covered,algorithm,labels,orig_ttl,
                      sig_exp,sig_inc,key_tag,name,sig):
        self.covered = covered
        self.algorithm = algorithm
        self.labels = labels
        self.orig_ttl = orig_ttl
        self.sig_exp = sig_exp
        self.sig_inc = sig_inc
        self.key_tag = key_tag
        self.name = DNSLabel(name)
        self.sig = sig

    def pack(self,buffer):
        buffer.pack("!HBBIIIH",self.covered,self.algorithm,self.labels,
                               self.orig_ttl,self.sig_exp,self.sig_inc,
                               self.key_tag)
        buffer.encode_name_nocompress(self.name)
        buffer.append(self.sig)

    def __repr__(self):
        return "%s %d %d %d %s %s %d %s %s" % (
                        QTYPE.get(self.covered),
                        self.algorithm,
                        self.labels,
                        self.orig_ttl,
                        time.strftime("%Y%m%d%H%M%S",time.gmtime(self.sig_exp)),
                        time.strftime("%Y%m%d%H%M%S",time.gmtime(self.sig_inc)),
                        self.key_tag,
                        self.name,
                        base64.b64encode(self.sig).decode())

    attrs = ('covered','algorithm','labels','orig_ttl','sig_exp','sig_inc',
             'key_tag','name','sig')
Exemple #7
0
class NAPTR(RD):

    order = H('order')
    preference = H('preference')

    @classmethod
    def parse(cls, buffer, length):
        try:
            order, preference = buffer.unpack('!HH')
            (length,) = buffer.unpack('!B')
            flags = buffer.get(length)
            (length,) = buffer.unpack('!B')
            service = buffer.get(length)
            (length,) = buffer.unpack('!B')
            regexp = buffer.get(length)
            replacement = buffer.decode_name()
            return cls(order, preference, flags, service, regexp, replacement)
        except (BufferError,BimapError) as e:
            raise DNSError("Error unpacking NAPTR [offset=%d]: %s" %
                                    (buffer.offset,e))

    @classmethod
    def fromZone(cls,rd,origin=None):
        encode = lambda s : s.encode()
        _label = lambda s : label(s,origin)
        m = (int,int,encode,encode,encode,_label)
        return cls(*[ f(v) for f,v in zip(m,rd)])

    def __init__(self,order,preference,flags,service,regexp,replacement=None):
        self.order = order
        self.preference = preference
        self.flags = flags
        self.service = service
        self.regexp = regexp
        self.replacement = replacement

    def set_replacement(self,replacement):
        if isinstance(replacement,DNSLabel):
            self._replacement = replacement
        else:
            self._replacement = DNSLabel(replacement)

    def get_replacement(self):
        return self._replacement

    replacement = property(get_replacement,set_replacement)

    def pack(self, buffer):
        buffer.pack('!HH', self.order, self.preference)
        buffer.pack('!B', len(self.flags))
        buffer.append(self.flags)
        buffer.pack('!B', len(self.service))
        buffer.append(self.service)
        buffer.pack('!B', len(self.regexp))
        buffer.append(self.regexp)
        buffer.encode_name(self.replacement)

    def __repr__(self):
        return '%d %d "%s" "%s" "%s" %s' %(
            self.order,self.preference,self.flags.decode(),
            self.service.decode(),
            self.regexp.decode().replace('\\','\\\\'),
            self.replacement or '.'
        )

    attrs = ('order','preference','flags','service','regexp','replacement')