示例#1
0
class RBLProviderBase(object):

    """Baseclass for all rbl providers"""

    def __init__(self, rbldomain, timeout=3, lifetime=10):
        self.replycodes = {}
        self.rbldomain = rbldomain
        self.logger = logging.getLogger('%s.rbllookup.%s' % (__package__, self.rbldomain))
        self.resolver = DNSLookup(timeout=timeout, lifetime=lifetime)
        self.descriptiontemplate = "${input} is listed on ${rbldomain} (${identifier})"
        self.lifetime = lifetime

    def add_replycode(self, mask, identifier=None):
        """add a replycode/bitmask. identifier is any object which will be returned if a dns result matches this replycode
        if identifier is not passed, the lookup domain will be used"""

        if identifier is None:
            identifier = self.rbldomain

        self.replycodes[mask] = identifier

    def _listed_identifiers(self, input, transform, dnsresult):
        listings = []
        for code, identifier in self.replycodes.items():
            if dnsresult == "%s" % code or dnsresult == "127.0.0.%s" % code:
                listings.append(
                    (identifier,
                     self.make_description(input=input,
                                           dnsresult=dnsresult,
                                           transform=transform,
                                           identifier=identifier,
                                           replycode=code)))
        return listings

    def make_description(self, **values):
        """create a human readable listing explanation"""
        template = Template(self.descriptiontemplate)
        values['rbldomain'] = self.rbldomain
        return template.safe_substitute(values)

    def accept_input(self, value):
        return re.match("^[a-zA-Z0-9.-]{2,256}$", value) is not None

    def transform_input(self, value):
        """transform input, eg, look up records or make md5 hashes here or whatever is needed for your specific provider and return a list of transformed values"""
        return [value, ]

    def make_lookup(self, transform):
        """some bls require additional modifications, even after input transformation, eg. ips must be reversed...
        by default we just fix trailing dots
        """
        return add_trailing_dot(transform) + self.rbldomain

    def listed(self, input, parallel=False):
        listings = []
        if not self.accept_input(input):
            return []
        transforms = self.transform_input(input)

        if parallel:
            lookup_to_trans = {}
            for transform in transforms:
                lookup_to_trans[self.make_lookup(transform)] = transform

            logging.debug("lookup_to_trans=%s" % lookup_to_trans)

            multidnsresult = self.resolver.lookup_multi(lookup_to_trans.keys())

            for lookup, arecordlist in multidnsresult.items():
                if lookup not in lookup_to_trans:
                    self.logger.error(
                        "dns error: I asked for %s but got '%s' ?!" %
                        (lookup_to_trans.keys(), lookup))
                    continue

                for ipresult in arecordlist:
                    listings.extend(
                        self._listed_identifiers(input,
                                                 lookup_to_trans[lookup],
                                                 ipresult.content))
        else:
            loopstarttime = time.time()
            for transform in transforms:
                lookup = self.make_lookup(transform)
                arecordlist = self.resolver.lookup(lookup.encode('utf-8', 'ignore'))
                for ipresult in arecordlist:
                    listings.extend(
                        self._listed_identifiers(
                            input,
                            transform,
                            ipresult.content))
                
                runtime = time.time() - loopstarttime
                if runtime > self.lifetime:
                    self.logger.debug('rbl lookup aborted due to timeout after %ss' % runtime)
                    break

        return listings

    def __str__(self):
        return "<%s d=%s codes=%s>" % (self.__class__.__name__, self.rbldomain, self.replycodes)

    def __repr__(self):
        return str(self)
示例#2
0
class RBLProviderBase(object):
    """Baseclass for all rbl providers"""
    def __init__(self, rbldomain, timeout=3, lifetime=10):
        self.replycodes = {}
        self.rbldomain = rbldomain
        self.logger = logging.getLogger('%s.rbllookup.%s' %
                                        (__package__, self.rbldomain))
        self.resolver = DNSLookup(timeout=timeout, lifetime=lifetime)
        self.descriptiontemplate = "${input} is listed on ${rbldomain} (${identifier})"
        self.lifetime = lifetime

    def add_replycode(self, mask, identifier=None):
        """add a replycode/bitmask. identifier is any object which will be returned if a dns result matches this replycode
        if identifier is not passed, the lookup domain will be used"""

        if identifier is None:
            identifier = self.rbldomain

        self.replycodes[mask] = identifier

    def _listed_identifiers(self, input, transform, dnsresult):
        listings = []
        for code, identifier in self.replycodes.items():
            if dnsresult == "%s" % code or dnsresult == "127.0.0.%s" % code:
                listings.append((identifier,
                                 self.make_description(input=input,
                                                       dnsresult=dnsresult,
                                                       transform=transform,
                                                       identifier=identifier,
                                                       replycode=code)))
        return listings

    def make_description(self, **values):
        """create a human readable listing explanation"""
        template = Template(self.descriptiontemplate)
        values['rbldomain'] = self.rbldomain
        return template.safe_substitute(values)

    def accept_input(self, value):
        return re.match("^[a-zA-Z0-9.-]{2,256}$", value) is not None

    def transform_input(self, value):
        """transform input, eg, look up records or make md5 hashes here or whatever is needed for your specific provider and return a list of transformed values"""
        return [
            value,
        ]

    def make_lookup(self, transform):
        """some bls require additional modifications, even after input transformation, eg. ips must be reversed...
        by default we just fix trailing dots
        """
        return add_trailing_dot(transform) + self.rbldomain

    def listed(self, input, parallel=False):
        listings = []
        if not self.accept_input(input):
            return []
        transforms = self.transform_input(input)

        if parallel:
            lookup_to_trans = {}
            for transform in transforms:
                lookup_to_trans[self.make_lookup(transform)] = transform

            logging.debug("lookup_to_trans=%s" % lookup_to_trans)

            multidnsresult = self.resolver.lookup_multi(lookup_to_trans.keys())

            for lookup, arecordlist in multidnsresult.items():
                if lookup not in lookup_to_trans:
                    self.logger.error(
                        "dns error: I asked for %s but got '%s' ?!" %
                        (lookup_to_trans.keys(), lookup))
                    continue

                for ipresult in arecordlist:
                    listings.extend(
                        self._listed_identifiers(input,
                                                 lookup_to_trans[lookup],
                                                 ipresult.content))
        else:
            loopstarttime = time.time()
            for transform in transforms:
                lookup = self.make_lookup(transform)
                arecordlist = self.resolver.lookup(
                    lookup.encode('utf-8', 'ignore'))
                for ipresult in arecordlist:
                    listings.extend(
                        self._listed_identifiers(input, transform,
                                                 ipresult.content))

                runtime = time.time() - loopstarttime
                if runtime > self.lifetime:
                    self.logger.debug(
                        'rbl lookup aborted due to timeout after %ss' %
                        runtime)
                    break

        return listings

    def __str__(self):
        return "<%s d=%s codes=%s>" % (self.__class__.__name__, self.rbldomain,
                                       self.replycodes)

    def __repr__(self):
        return str(self)