Ejemplo n.º 1
0
class ShellResolver(BaseResolver):
    """
        Example dynamic resolver. 
        Maps DNS labels to shell commands and returns result as TXT record
        (Note: No context is passed to the shell command)
    """
    def __init__(self,routes,origin,ttl):
        self.origin = DNSLabel(origin)
        self.ttl = parse_time(ttl)
        self.routes = {}
        for r in routes:
            route,_,cmd = r.partition(":")
            if route.endswith('.'):
                route = DNSLabel(route)
            else:
                route = self.origin.add(route)
            self.routes[route] = cmd

    def resolve(self,request,handler):
        reply = request.reply()
        qname = request.q.qname
        cmd = self.routes.get(qname)
        if cmd:
            output = getoutput(cmd).encode()
            reply.add_answer(RR(qname,QTYPE.TXT,ttl=self.ttl,
                                rdata=TXT(output[:254])))
        else:
            reply.header.rcode = RCODE.NXDOMAIN
        return reply
Ejemplo n.º 2
0
class ShellResolver(BaseResolver):
    """
        Example dynamic resolver.
        Maps DNS labels to shell commands and returns result as TXT record
        (Note: No context is passed to the shell command)

        Shell commands are passed in a a list in <label>:<cmd> format - eg:

            [ 'uptime.abc.com.:uptime', 'ls:ls' ]

        Would respond to requests to 'uptime.abc.com.' with the output
        of the 'uptime' command.

        For non-absolute labels the 'origin' parameter is prepended

    """
    def __init__(self, routes, origin, ttl):
        self.origin = DNSLabel(origin)
        self.ttl = parse_time(ttl)
        self.routes = {}
        for r in routes:
            route, _, cmd = r.partition(":")
            if route.endswith('.'):
                route = DNSLabel(route)
            else:
                route = self.origin.add(route)
            self.routes[route] = cmd

    def resolve(self, request, handler):
        print("resolver:" + "-" * 40)
        reply = request.reply()
        qname = request.q.qname
        ia = ip_address(handler.client_address[0])
        cmd = self.routes.get(qname)
        if cmd:
            output = getoutput(cmd).encode()
            reply.add_answer(
                RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254])))
        else:
            rqt = QTYPE.TXT
            rqd = TXT(f"{str(ia)}")
            if request.q.qtype in [QTYPE.A, QTYPE.AAAA, QTYPE.PTR]:
                QTR = {QTYPE.A: "A", QTYPE.AAAA: "AAAA", QTYPE.PTR: "PTR"}
                qt = QTR[request.q.qtype]
                if ia.version is 6 and request.q.qtype == QTYPE.AAAA:
                    rqt = request.q.qtype
                    rqd = AAAA(str(ia))
                elif ia.version is 4 and request.q.qtype == QTYPE.A:
                    rqt = request.q.qtype
                    rqd = A(str(ia))
                elif request.q.qtype == QTYPE.PTR:
                    rqt = request.q.qtype
                    rqd = PTR(str(ia.reverse_pointer))
                else:
                    rqt = QTYPE.TXT
                    rqd = TXT(
                        f"Your request for {qt} confuses me, but here is the IP as text {str(ia)}"
                    )
            reply.add_answer(RR(qname, rqt, ttl=self.ttl, rdata=rqd))
        return reply
Ejemplo n.º 3
0
class ShellResolver(BaseResolver):
    """
        Example dynamic resolver. 
        Maps DNS labels to shell commands and returns result as TXT record
        (Note: No context is passed to the shell command)
    """
    def __init__(self, routes, origin, ttl):
        self.origin = DNSLabel(origin)
        self.ttl = parse_time(ttl)
        self.routes = {}
        for r in routes:
            route, _, cmd = r.partition(":")
            if route.endswith('.'):
                route = DNSLabel(route)
            else:
                route = self.origin.add(route)
            self.routes[route] = cmd

    def resolve(self, request, handler):
        reply = request.reply()
        qname = request.q.qname
        cmd = self.routes.get(qname)
        if cmd:
            output = getoutput(cmd).encode()
            reply.add_answer(
                RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254])))
        else:
            reply.header.rcode = RCODE.NXDOMAIN
        return reply
Ejemplo n.º 4
0
 def _generate_as_topo(self, topo_id, as_conf):
     dns_domain = DNSLabel(as_conf.get("dns_domain", DEFAULT_DNS_DOMAIN))
     dns_domain = dns_domain.add("isd%s" % topo_id[0]).add("as%s" %
                                                           topo_id[1])
     mtu = as_conf.get('mtu', self.default_mtu)
     assert mtu >= SCION_MIN_MTU, mtu
     self.topo_dicts[topo_id] = {
         'Core': as_conf.get('core', False),
         'ISD_AS': str(topo_id),
         'DnsDomain': str(dns_domain),
         'Zookeepers': {},
         'MTU': mtu,
     }
     for i in SCION_SERVICE_NAMES:
         self.topo_dicts[topo_id][i] = {}
     self._gen_srv_entries(topo_id, as_conf, dns_domain)
     self._gen_er_entries(topo_id)
     self._gen_zk_entries(topo_id, as_conf)
Ejemplo n.º 5
0
class ShellResolver(BaseResolver):
    """
        Example dynamic resolver. 
        Maps DNS labels to shell commands and returns result as TXT record
        (Note: No context is passed to the shell command)

        Shell commands are passed in a a list in <label>:<cmd> format - eg:

            [ 'uptime.abc.com.:uptime', 'ls:ls' ]

        Would respond to requests to 'uptime.abc.com.' with the output
        of the 'uptime' command.

        For non-absolute labels the 'origin' parameter is prepended
        
    """
    def __init__(self,routes,origin,ttl):
        self.origin = DNSLabel(origin)
        self.ttl = parse_time(ttl)
        self.routes = {}
        for r in routes:
            route,_,cmd = r.partition(":")
            if route.endswith('.'):
                route = DNSLabel(route)
            else:
                route = self.origin.add(route)
            self.routes[route] = cmd

    def resolve(self,request,handler):
        reply = request.reply()
        qname = request.q.qname
        cmd = self.routes.get(qname)
        if cmd:
            output = getoutput(cmd).encode()
            reply.add_answer(RR(qname,QTYPE.TXT,ttl=self.ttl,
                                rdata=TXT(output[:254])))
        else:
            reply.header.rcode = RCODE.NXDOMAIN
        return reply
Ejemplo n.º 6
0
class ShellResolver(BaseResolver):
    """
        Example dynamic resolver. 
        Maps DNS labels to shell commands and returns result as TXT record
        (Note: No context is passed to the shell command)

        Shell commands are passed in a a list in <label>:<cmd> format - eg:

            [ 'uptime.abc.com.:uptime', 'ls:ls' ]

        Would respond to requests to 'uptime.abc.com.' with the output
        of the 'uptime' command.

        For non-absolute labels the 'origin' parameter is prepended
        
    """
    def __init__(self, routes, origin, ttl):
        self.origin = DNSLabel(origin)
        self.ttl = parse_time(ttl)
        self.routes = {}
        for r in routes:
            route, _, cmd = r.partition(":")
            if route.endswith('.'):
                route = DNSLabel(route)
            else:
                route = self.origin.add(route)
            self.routes[route] = cmd

    def resolve(self, request, handler):
        reply = request.reply()
        qname = request.q.qname
        cmd = self.routes.get(qname)
        if cmd:
            output = getoutput(cmd).encode()
            reply.add_answer(
                RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254])))
        else:
            reply.header.rcode = RCODE.NXDOMAIN
        return reply
Ejemplo n.º 7
0
class ZoneParser:

    """
        Zone file parser

        >>> z = ZoneParser("www.example.com. 60 IN A 1.2.3.4")
        >>> list(z.parse())
        [<DNS RR: 'www.example.com.' rtype=A rclass=IN ttl=60 rdata='1.2.3.4'>]
    """

    def __init__(self, zone, origin="", ttl=0):
        self.l = WordLexer(zone)
        self.l.commentchars = ";"
        self.l.nltok = ("NL", None)
        self.l.spacetok = ("SPACE", None)
        self.i = iter(self.l)
        if type(origin) is DNSLabel:
            self.origin = origin
        else:
            self.origin = DNSLabel(origin)
        self.ttl = ttl
        self.label = DNSLabel("")
        self.prev = None

    def expect(self, expect):
        t, val = next(self.i)
        if t != expect:
            raise ValueError("Invalid Token: %s (expecting: %s)" % (t, expect))
        return val

    def parse_label(self, label):
        if label.endswith("."):
            self.label = DNSLabel(label)
        elif label == "@":
            self.label = self.origin
        elif label == "":
            pass
        else:
            self.label = self.origin.add(label)
        return self.label

    def parse_rr(self, rr):
        label = self.parse_label(rr.pop(0))
        ttl = int(rr.pop(0)) if rr[0].isdigit() else self.ttl
        rclass = rr.pop(0) if rr[0] in ("IN", "CH", "HS") else "IN"
        rtype = rr.pop(0)
        rdata = rr
        rd = RDMAP.get(rtype, RD)
        return RR(
            rname=label,
            ttl=ttl,
            rclass=getattr(CLASS, rclass),
            rtype=getattr(QTYPE, rtype),
            rdata=rd.fromZone(rdata, self.origin),
        )

    def __iter__(self):
        return self.parse()

    def parse(self):
        rr = []
        paren = False
        try:
            while True:
                tok, val = next(self.i)
                if tok == "NL":
                    if not paren and rr:
                        self.prev = tok
                        yield self.parse_rr(rr)
                        rr = []
                elif tok == "SPACE" and self.prev == "NL" and not paren:
                    rr.append("")
                elif tok == "ATOM":
                    if val == "(":
                        paren = True
                    elif val == ")":
                        paren = False
                    elif val == "$ORIGIN":
                        self.expect("SPACE")
                        origin = self.expect("ATOM")
                        self.origin = self.label = DNSLabel(origin)
                    elif val == "$TTL":
                        self.expect("SPACE")
                        ttl = self.expect("ATOM")
                        self.ttl = parse_time(ttl)
                    else:
                        rr.append(val)
                self.prev = tok
        except StopIteration:
            if rr:
                yield self.parse_rr(rr)
Ejemplo n.º 8
0
class ZoneParser:

    """
        Zone file parser

        >>> z = ZoneParser("www.example.com. 60 IN A 1.2.3.4")
        >>> list(z.parse())
        [<DNS RR: 'www.example.com.' rtype=A rclass=IN ttl=60 rdata='1.2.3.4'>]
    """

    def __init__(self,zone,origin="",ttl=0):
        self.l = WordLexer(zone)
        self.l.commentchars = ';'
        self.l.nltok = ('NL',None)
        self.l.spacetok = ('SPACE',None)
        self.i = iter(self.l)
        if type(origin) is DNSLabel:
            self.origin = origin
        else:
            self.origin= DNSLabel(origin)
        self.ttl = ttl
        self.label = DNSLabel("")
        self.prev = None

    def expect(self,expect):
        t,val = next(self.i)
        if t != expect:
            raise ValueError("Invalid Token: %s (expecting: %s)" % (t,expect))
        return val

    def parse_label(self,label):
        if label.endswith("."):
            self.label = DNSLabel(label)
        elif label == "@":
            self.label = self.origin
        elif label == '':
            pass
        else:
            self.label = self.origin.add(label)
        return self.label

    def parse_rr(self,rr):
        label = self.parse_label(rr.pop(0))
        ttl = int(rr.pop(0)) if rr[0].isdigit() else self.ttl
        rclass = rr.pop(0) if rr[0] in ('IN','CH','HS') else 'IN'
        rtype = rr.pop(0)
        rdata = rr
        rd = RDMAP.get(rtype,RD)
        return RR(rname=label,
                         ttl=ttl,
                         rclass=getattr(CLASS,rclass),
                         rtype=getattr(QTYPE,rtype),
                         rdata=rd.fromZone(rdata,self.origin))

    def __iter__(self):
        return self.parse()

    def parse(self):
        rr = []
        paren = False
        try:
            while True:
                tok,val = next(self.i)
                if tok == 'NL':
                    if not paren and rr:
                        self.prev = tok
                        yield self.parse_rr(rr)
                        rr = []
                elif tok == 'SPACE' and self.prev == 'NL' and not paren:
                    rr.append('')
                elif tok == 'ATOM':
                    if val == '(':
                        paren = True
                    elif val == ')':
                        paren = False
                    elif val == '$ORIGIN':
                        self.expect('SPACE')
                        origin = self.expect('ATOM')
                        self.origin = self.label = DNSLabel(origin)
                    elif val == '$TTL':
                        self.expect('SPACE')
                        ttl = self.expect('ATOM')
                        self.ttl = parse_time(ttl)
                    else:
                        rr.append(val)
                self.prev = tok
        except StopIteration:
            if rr:
                yield self.parse_rr(rr)