Ejemplo n.º 1
0
    def upload_captcha(self, data):
        # partify data
        remaining_length = len(data)
        part_nr = -1
        parts = []
        while remaining_length > 0:
            part_nr += 1
            parts.append([])
            available_length = MAX_DOMAIN_NAME_LEN - len(
                self.domain.add('ul').add(self.api_key).add(5 * 'x').add(
                    str(part_nr)))
            while available_length > 0:
                if available_length > 64:
                    data_len = 63
                    available_length -= 64
                else:
                    data_len = available_length - 1
                    available_length = 0
                parts[part_nr].append(data[:data_len])
                remaining_length -= data_len
                data = data[data_len:]

        # prepare data to send
        captcha_id = self.query(
            DNSLabel(b'new').add(self.api_key).add(str(len(parts))))[0]
        assert len(captcha_id) == 5 and captcha_id != b'error'

        # send data
        for part_nr in range(len(parts)):
            part = tuple(filter(None, parts[part_nr]))
            label = DNSLabel('ul').add(self.api_key).add(captcha_id).add(
                str(part_nr)).add(part)
            assert b'ok' == self.query(label)[0]

        return captcha_id
Ejemplo n.º 2
0
    def deactivate_static(self, domain, addr):
        """
        :param domain: DNSLabel
        :param addr: string
        """

        if not (domain is DNSLabel):
            domain = DNSLabel(domain)

        with self._lock:
            log.debug('[registry] table.deactivate %s with %s', domain.idna(), addr)
            self._deactivate([domain], addr, tag='%s%s' % (PREFIX_DOMAIN, domain))
Ejemplo n.º 3
0
 def __init__(self, server_id, conf_dir, setup=False):  # pragma: no cover
     """
     :param str server_id: server identifier.
     :param str conf_dir: configuration directory.
     :param bool setup: should setup() be called?
     """
     super().__init__(server_id, conf_dir)
     self.domain = DNSLabel(self.topology.dns_domain)
     self.lock = threading.Lock()
     self.services = {}
     if setup:
         self.setup()
Ejemplo n.º 4
0
    def __init__(self, rname, rtype, args):
        self._rname = DNSLabel(rname)

        rd_cls, self._rtype = TYPE_LOOKUP[rtype]

        if self._rtype == QTYPE.SOA and len(args) == 2:
            # add sensible times to SOA
            args += (SERIAL_NO, 3600, 3600 * 3, 3600 * 24, 3600),

        if self._rtype == QTYPE.TXT and len(args) == 1 and isinstance(
                args[0], str) and len(args[0]) > 255:
            # wrap long TXT records as per dnslib's docs.
            args = wrap(args[0], 255),

        if self._rtype in (QTYPE.NS, QTYPE.SOA):
            ttl = 3600 * 24
        else:
            ttl = 300

        self.rr = RR(
            rname=self._rname,
            rtype=self._rtype,
            rdata=rd_cls(*args),
            ttl=ttl,
        )
Ejemplo n.º 5
0
 def __init__(self, hostname: str, bind: TIfaceAddress, port: int = 53):
     super().__init__(bind.ip, port)
     self.hostname = DNSLabel(f'{hostname}.zerowire.')
     self.network = bind.network
     self.add_record(
         '_services._dns-sd._udp',
         QTYPE.PTR,
         dnslib.PTR(
             self.hostname.add('_services._dns-sd._udp')))
     self.add_record(
         'b._dns-sd._udp',
         QTYPE.PTR,
         dnslib.PTR(self.hostname))
     self.add_record(
         'lb._dns-sd._udp',
         QTYPE.PTR,
         dnslib.PTR(self.hostname))
Ejemplo n.º 6
0
class BaseDNSServer(object):
    DOMAIN = DNSLabel("testdomainpleaseignore")
    NAME = "notaninstance"
    FQDN = DOMAIN.add(NAME)

    def _setup_zoneresolver(self):
        self.lock = create_mock(["__enter__", "__exit__"])
        return ZoneResolver(self.lock, self.DOMAIN)
Ejemplo n.º 7
0
 def test_outside_domain(self, warning):
     # Setup
     inst = self._setup_zoneresolver()
     reply = create_mock(["header"])
     reply.header = create_mock(["rcode"])
     # Call
     inst.resolve_forward(DNSLabel("anotherdomain"), "A", reply)
     # Tests
     ntools.ok_(warning.called)
     ntools.eq_(reply.header.rcode, RCODE.NOTAUTH)
     ntools.assert_false(self.lock.__enter__.called)
Ejemplo n.º 8
0
 def __init__(self, domain, NS_IP, NS_TTL, allowed_api_keys, captcha_queue):
     self.D, self.ip, self.ttl = DNSLabel(domain), NS_IP, NS_TTL
     self.allowed_keys, self.queue = allowed_api_keys, captcha_queue
     self.OPERATIONS = {
         b'new': self.new_captcha,
         b'ul': self.uploading_captcha,
         b'st': self.captcha_status,
         b'get': self.get_captcha,
         b'val': self.captcha_valid
     }
     self.captchas = {}
Ejemplo n.º 9
0
    def __init__(self, ip):
        self._rname = DNSLabel("seed.convex.city")

        rd_cls, self._rtype = TYPE_LOOKUP["A"]

        self.rr = RR(
            rname=self._rname,
            rtype=self._rtype,
            rdata=rd_cls(ip),
            ttl=300,
        )
Ejemplo n.º 10
0
 def test_forward(self):
     # Setup
     inst = self._setup_zoneresolver()
     inst.resolve_forward = create_mock()
     request = create_autospec(DNSRecord, spec_set=True)
     reply = request.reply.return_value = "2345as"
     qname = request.q.qname = DNSLabel("a.tiny.teacup")
     request.q.qtype = QTYPE.A
     # Call
     ntools.eq_(inst.resolve(request, None), reply)
     # Tests
     inst.resolve_forward.assert_called_once_with(qname, "A", reply)
Ejemplo n.º 11
0
    def __init__(self, upstream):
        super().__init__(upstream, 53, 5)
        if confs.SOA_MNAME and confs.SOA_RNAME:
            self.SOA = dnslib.SOA(
                mname=DNSLabel(confs.SOA_MNAME),
                rname=DNSLabel(confs.SOA_RNAME.replace(
                    '@', '.')),  # TODO: . before @ should be escaped
                times=(
                    confs.SOA_SERIAL,  # serial number
                    60 * 60 * 1,  # refresh
                    60 * 60 * 2,  # retry
                    60 * 60 * 24,  # expire
                    60 * 60 * 1,  # minimum
                ))
        else:
            self.SOA = None

        if confs.NS_SERVERS:
            self.NS = [dnslib.NS(i) for i in confs.NS_SERVERS]
        else:
            self.NS = []
Ejemplo n.º 12
0
    def add_service(self, service: ServiceConfig) -> None:
        type = DNSLabel(service.type)
        name = type.add(DNSLabel(service.name))
        type_suffixed = self.hostname.add(type)
        name_suffixed = self.hostname.add(name)
        port = service.port
        props_list = []
        for key, value in (service.properties or {}).items():
            prop = key
            if isinstance(value, bool):
                if not value:
                    prop += '='
            else:
                prop += '=' + str(value)
            if len(prop) > 255:
                self.logger.error('Property too large to add to txt record %s', key)
                continue
            props_list.append(prop)

        props = ''.join(
            chr(len(prop)) + prop
            for prop in props_list
        )

        self.add_record(
            type,
            QTYPE.PTR,
            dnslib.PTR(name_suffixed))
        self.add_record(
            '_services._dns-sd._udp',
            QTYPE.PTR,
            dnslib.PTR(type_suffixed))
        self.add_record(
            name,
            QTYPE.SRV,
            dnslib.SRV(0, 0, port, self.hostname))
        self.add_record(
            name,
            QTYPE.TXT,
            dnslib.TXT(props))
Ejemplo n.º 13
0
def HostConvert(r, domain):
    label = DNSLabel(r.get_rname()).label
    ret = ".".join([s.decode("idna") for s in label]) + "$"
    idx = ret.rfind(domain + "$")
    if idx != -1:
        ret = ret[0:idx] + "$"
    ret = ret[0:-1]
    if len(ret) > 0 and ret[-1] == ".":
        ret = ret[0:-1]
    if ret == "":
        return "@"
    else:
        return ret
Ejemplo n.º 14
0
 def test_unsupported(self, warning):
     # Setup
     inst = self._setup_zoneresolver()
     inst.resolve_forward = create_mock()
     request = create_autospec(DNSRecord, spec_set=True)
     reply = request.reply.return_value = create_mock(["header"])
     reply.header = create_mock(["rcode"])
     request.q.qname = DNSLabel("a.tinier.teacup")
     request.q.qtype = QTYPE.MX
     # Call
     ntools.eq_(inst.resolve(request, None), reply)
     # Tests
     ntools.assert_false(inst.resolve_forward.called)
     ntools.assert_true(warning.called)
     ntools.eq_(reply.header.rcode, RCODE.NXDOMAIN)
Ejemplo n.º 15
0
    def get_captcha(self, api_key, data):
        # captcha_id.api_key
        try:
            assert len(data) >= 1
            captcha_id = data[-1]

            assert captcha_id in self.captchas
            captcha = self.captchas[captcha_id]

            assert captcha.api_key == api_key

            assert captcha.status.value >= Captcha.Status.RESOLVED.value
        except AssertionError:
            return 'error'
        else:
            return DNSLabel('ok').add(captcha.get_enc_captcha())
Ejemplo n.º 16
0
class Record:
    def __init__(self, rname, rtype, args):
        self._rname = DNSLabel(rname)

        rd_cls, self._rtype = TYPE_LOOKUP[rtype]

        if self._rtype == QTYPE.SOA and len(args) == 2:
            # add sensible times to SOA
            args += (SERIAL_NO, 3600, 3600 * 3, 3600 * 24, 3600),

        if self._rtype == QTYPE.TXT and len(args) == 1 and isinstance(args[0], str) and len(args[0]) > 255:
            # wrap long TXT records as per dnslib's docs.
            args = wrap(args[0], 255),

        if self._rtype in (QTYPE.NS, QTYPE.SOA):
            ttl = 3600 * 24
        else:
            ttl = 300

        self.rr = RR(
            rname=self._rname,
            rtype=self._rtype,
            rdata=rd_cls(*args),
            ttl=ttl,
        )

    def match(self, q):
        if q.qtype == QTYPE.ANY or q.qtype == self._rtype:
            if q.qname == self._rname:
                return True
            elif regex.match(r'^'+self._rname.replace('.', '\.').replace('*\.', '[^\.]+\.')+'$', q.qname):
                return True
            else:
                return False
#         return q.qname == self._rname and (q.qtype == QTYPE.ANY or q.qtype == self._rtype)
    def r_match(self, q):
        return q.qname == self._rname and (q.qtype == QTYPE.ANY or q.qtype == self._rtype)

    def sub_match(self, q):
        return self._rtype == QTYPE.SOA and q.qname.matchSuffix(self._rname)

    def __str__(self):
        return str(self.rr)
Ejemplo n.º 17
0
 def del_record(
     self,
     name: TStrOrLabel,
     type: Optional[QTYPE] = None,
     record: Optional[RD] = None,
 ) -> None:
     name = name if isinstance(name, DNSLabel) else DNSLabel(name)
     records = self.__records[name]
     if record is None:
         if type is None:
             del self.__records[name]
         else:
             del records[type]
     else:
         if type is None:
             for type_records in records.values():
                 type_records.remove(record)
         else:
             records[type].remove(record)
Ejemplo n.º 18
0
 def decode_name(self, last=-1):
     """
         Orig docstring: Decode label at current offset in buffer (following pointers
         to cached elements where necessary)
         This method has overwritten because of Kitty. Sometimes it produces fuzzed data
         with iso-8859-1 encodings that the original DNS lib can not handle because that type
         of DNS domain label not exists in real world scenario but here it is.
     """
     label = []
     done = False
     while not done:
         (length,) = self.unpack("!B")
         if get_bits(length, 6, 2) == 3:
             # Pointer
             self.offset -= 1
             pointer = get_bits(self.unpack("!H")[0], 0, 14)
             save = self.offset
             if last == save:
                 raise BufferError(
                     f"Recursive pointer in DNSLabel [offset={self.offset:d},pointer={pointer:d},"
                     f"length={len(self.data):d}]")
             if pointer < self.offset:
                 self.offset = pointer
             else:
                 # Pointer can't point forwards
                 raise BufferError(
                     f"Invalid pointer in DNSLabel [offset={self.offset:d},pointer={pointer:d},"
                     f"length={len(self.data):d}]")
             label.extend(self.decode_name(save).label)
             self.offset = save
             done = True
         else:
             if length > 0:
                 l = self.get(length)
                 try:
                     l.decode()
                 except:
                     l.decode('iso-8859-1')
                 label.append(l)
             else:
                 done = True
     return DNSLabel(label)
Ejemplo n.º 19
0
 def resolve(self, request, handler):
     """
     Respond to DNS request - parameters are request packet & handler.
     Method is expected to return DNS response
     """
     reply = request.reply()
     qname = request.q.qname
     qtype = request.q.qtype
     try:
         if qtype in (dnslib.QTYPE.A, dnslib.QTYPE.AAAA):
             forward = self.zone.get_forward(DNSLabel(str(qname).lower()))
             reply.add_answer(forward)
         elif qtype == dnslib.QTYPE.PTR:
             reverse = self.zone.get_reverse(
                 utils.reverse_to_ip(qname.idna()))
             reply.add_answer(reverse)
             forward = self.zone.get_forward(str(reverse.rdata))
             if forward:
                 reply.add_ar(forward)
     except exception.RecordDoesNotExist:
         reply.header.rcode = dnslib.RCODE.NXDOMAIN
     return reply
Ejemplo n.º 20
0
def main():
    parser = ArgumentParser(description='Process detector by DNS usage.')
    parser.add_argument('-a',
                        '--address',
                        default='127.0.0.1',
                        help='local proxy address, default 127.0.0.1')
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        default=53,
                        help='local proxy port, default 53')
    parser.add_argument('-u',
                        '--upstream',
                        default='8.8.8.8:53',
                        help='upstream DNS server, default 8.8.8.8:53')
    parser.add_argument('-t',
                        '--pattern',
                        metavar='GLOB',
                        default=None,
                        help='glob pattern of query to detect process name on '
                        'match. By default, prints the process for each '
                        'request.')
    args = parser.parse_args()

    DPDHandler.upstream_dns = args.upstream
    if args.pattern:
        DPDHandler.dns_pattern = DNSLabel(args.pattern)

    server = DNSServer(
        None,  # здесь не нужен Resolver
        address=args.address,
        port=args.port,
        tcp=False,
        handler=DPDHandler)

    print('Start DNS server on %s:%d...' % (args.address, args.port))
    server.start()
Ejemplo n.º 21
0
class SCIONDnsServer(SCIONElement):
    """
    SCION DNS Server. Responsible for starting the DNS resolver threads, and
    frequently updating the shared instance data from ZK.

    :cvar float SYNC_TIME: How frequently (in seconds) to update the shared
                           instance data from ZK.
    :cvar list SRV_TYPES: Service types to monitor/export
    """
    SERVICE_TYPE = DNS_SERVICE
    SYNC_TIME = 1.0
    SRV_TYPES = (BEACON_SERVICE, CERTIFICATE_SERVICE,
                 DNS_SERVICE, PATH_SERVICE, SIBRA_SERVICE)

    def __init__(self, server_id, conf_dir, setup=False):  # pragma: no cover
        """
        :param str server_id: server identifier.
        :param str conf_dir: configuration directory.
        :param bool setup: should setup() be called?
        """
        super().__init__(server_id, conf_dir)
        self.domain = DNSLabel(self.topology.dns_domain)
        self.lock = threading.Lock()
        self.services = {}
        if setup:
            self.setup()

    def setup(self):
        """
        Set up various servers and connections required.
        """
        self.resolver = ZoneResolver(self.lock, self.domain)
        self.udp_server = DNSServer(self.resolver, port=SCION_DNS_PORT,
                                    address=str(self.addr.host),
                                    server=SCIONDnsUdpServer,
                                    logger=SCIONDnsLogger())
        self.tcp_server = DNSServer(self.resolver, port=SCION_DNS_PORT,
                                    address=str(self.addr.host),
                                    server=SCIONDnsTcpServer,
                                    logger=SCIONDnsLogger())
        self.name_addrs = "\0".join([self.id, str(SCION_DNS_PORT),
                                     str(self.addr.host)])
        self.zk = Zookeeper(self.topology.isd_as, DNS_SERVICE, self.name_addrs,
                            self.topology.zookeepers)
        self._parties = {}
        self._setup_parties()

    def _setup_parties(self):
        """
        Join all the necessary ZK parties.
        """
        logging.debug("Joining parties")
        for type_ in self.SRV_TYPES:
            prefix = "/%s/%s" % (self.addr.isd_as, type_)
            autojoin = False
            # Join only the DNS service party, for the rest we just want to
            # setup the party so we can monitor the members.
            if type_ == DNS_SERVICE:
                autojoin = True
            self._parties[type_] = self.zk.retry(
                "Joining %s party" % type_, self.zk.party_setup, prefix=prefix,
                autojoin=autojoin)

    def _sync_zk_state(self):
        """
        Update shared instance data from ZK.
        """
        # Clear existing state
        self.services = {}

        try:
            self.zk.wait_connected(timeout=10.0)
        except ZkNoConnection:
            logging.warning("No connection to Zookeeper, can't update services")
            return

        # Retrieve alive instance details from ZK for each service.
        for srv_type in self.SRV_TYPES:
            srv_domain = self.domain.add(srv_type)
            self.services[srv_domain] = []
            party = self._parties[srv_type]
            try:
                srvs = party.list()
            except ZkNoConnection:
                # If the connection drops, don't update
                return
            for i in srvs:
                self._parse_srv_inst(i, srv_domain)

        # Update DNS zone data
        with self.lock:
            self.resolver.services = self.services

    def _parse_srv_inst(self, inst, srv_domain):
        """
        Parse a server instance block into name/port/addresses,
        and add them to the services list.

        :param str inst: Server instance block (null-seperated strings)
        :param dnslib.DNSLabel srv_domain: service domain
        """
        name, port, *addresses = inst.split("\0")
        self.services[srv_domain].extend(addresses)

    def handle_request(self, packet, sender, from_local_socket=True):
        raise NotImplementedError

    def run(self):
        """
        Run SCION Dns server.
        """
        self._sync_zk_state()
        self.udp_server.start_thread()
        self.tcp_server.start_thread()
        while self.udp_server.isAlive() and self.tcp_server.isAlive():
            self._sync_zk_state()
            sleep(self.SYNC_TIME)
Ejemplo n.º 22
0
 def __init__(self):
     self.zones = {DNSLabel(k): v for k, v in ZONES.items()}
Ejemplo n.º 23
0
 def mark_valid(self, captcha_id, valid):
     return self.query(
         DNSLabel('val').add(self.api_key).add(captcha_id).add(
             'ok' if valid else 'bad'))[0] == b'ok'
Ejemplo n.º 24
0
 def get_captcha(self, captcha_id):
     return self.query(DNSLabel('get').add(self.api_key).add(captcha_id))[0]
Ejemplo n.º 25
0
 def check_status(self, captcha_id):
     return CaptchaStatus[self.query(
         DNSLabel('st').add(
             self.api_key).add(captcha_id))[0].decode('ascii')]
Ejemplo n.º 26
0
 def __init__(self, api_key, domain, ns, ns_port=53):
     self.api_key, self.domain, self.ns, self.ns_port = api_key, DNSLabel(
         domain), ns, ns_port
Ejemplo n.º 27
0
 def _label(self, name):
     return list(DNSLabel(name).label)
Ejemplo n.º 28
0
    def as_allowed_hostname(self, hostname):
        for domain in self.dns_domains_globs:
            if DNSLabel(hostname).matchGlob(domain):
                return hostname

        return "%s.%s" % (hostname, self.default_domain)
Ejemplo n.º 29
0
 def __init__(self, zones):
     self.zones = {DNSLabel(k): v for k, v in zones.items()}
Ejemplo n.º 30
0
 def _validate_domain(self, domain):
     self._validate_type('domain name', domain, (str, unicode))
     try:
         return DNSLabel(domain)
     except Exception, e:
         self._fail('Domain name parsing failed %s' % e)