Example #1
0
    def _check_rbl(self, msg, rbl_server, qtype="A", subtest=None):
        """Checks all the IPs of this message on the specified
        list.

        :param msg: The message that we perform the check on.
        :param rbl_server: The RBL list to check
        :param qtype: The DNS record type to check
        :param subtest: If specified then an additional check
          is done on the result of the DNS lookup by matching
          this regular expression against the result.
        :return: True if there is a match and the subtest
          passes and False otherwise.
        """
        if self.ctxt.skip_rbl_checks:
            return False

        if subtest is not None:
            try:
                subtest = Regex(subtest)
            except re.error as e:
                self.ctxt.err("Invalid regex %s: %s", subtest, e)
                return False

        for ip in msg.get_untrusted_ips():
            rev = self.ctxt.dns.reverse_ip(ip)
            results = self.ctxt.dns.query("%s.%s" % (rev, rbl_server), qtype)

            if results and not subtest:
                return True

            for result in results:
                if subtest.match(str(result)):
                    return True
        return False
Example #2
0
 def _check_for_forged_received(self, msg):
     mismatch_from = 0
     mismatch_ip_helo = 0
     hostname_re = Regex(r"^\w+(?:[\w.-]+\.)+\w+$")
     ip_re = Regex(r"^(\d+\.\d+)\.\d+\.\d+")
     for index, relay in enumerate(msg.untrusted_relays):
         from_ip = relay.get("ip")
         from_host = self.hostname_to_domain(relay.get("rdns"))
         by_host = self.hostname_to_domain(relay.get("by"))
         helo_host = self.hostname_to_domain(relay.get("helo"))
         if not by_host or not hostname_re.match(by_host):
             continue
         if from_host and from_ip == '127.0.0.1':
                 from_host = "undef"
         self.ctxt.log.debug("eval: forged-HELO: from=%s helo=%s by=%s" % (
             from_host if from_host else "(undef)",
             helo_host if helo_host else "(undef)",
             by_host if by_host else "(undef)"
         ))
         try:
             ip_netmask_16 = ipaddress.IPv4Network(from_ip).supernet(16)
         except ValueError:
             ip_netmask_16 = ""
         try:
             helo_netmask_16 = ipaddress.IPv4Network(helo_host).supernet(16)
         except ValueError:
             helo_netmask_16 = ""
         if ip_netmask_16 and helo_netmask_16 and from_ip != helo_host:
             if (ip_netmask_16 != helo_netmask_16 and
                     not IP_PRIVATE.match(helo_host)):
                 self.ctxt.log.debug("eval: forged-HELO: massive mismatch "
                                     "on IP-addr HELO: %s != %s" %
                                     (helo_host, from_ip))
                 mismatch_ip_helo += 1
         prev = msg.untrusted_relays[index - 1]
         if prev and index > 0:
             prev_from_host = prev.get("rdns")
             if (hostname_re.match(prev_from_host)
                 and by_host != prev_from_host
                 and not self._helo_forgery_whitelisted(by_host,
                                                        prev_from_host)):
                 self.ctxt.log.debug("eval: forged-HELO: mismatch on from: "
                                     "%s != %s" % (prev_from_host, by_host))
                 mismatch_from += 1
     self.set_global("mismatch_from", mismatch_from)
     self.set_global("mismatch_ip_helo", mismatch_ip_helo)
Example #3
0
 def check_for_forged_gw05_received_headers(self, msg, target=None):
     gw05_re = Regex(r"from\s(\S+)\sby\s(\S+)\swith\sESMTP\;\s+\S\S\S,"
                     r"\s+\d+\s+\S\S\S\s+\d{4}\s+\d\d:\d\d:\d\d\s+[-+]*"
                     r"\d{4}", re.X | re.I)
     for rcv in msg.get_decoded_header("Received"):
         h1 = ""
         h2 = ""
         try:
             match = gw05_re.match(rcv)
             if match:
                 h1, h2 = match.groups()
             if h1 and h2 and h2 != ".":
                 return True
         except IndexError:
             continue
     return False
Example #4
0
 def check_for_no_rdns_dotcom_helo(self, msg, option=None, target=None):
     """Check untrusted relays and verify if latest relay it has helo from
     a big email provider like lycos, hotmail, excite, caramail, cs, aol,
     msn, yahoo, drizzle"""
     no_rdns_dotcom_helo = False
     for relay in msg.untrusted_relays:
         if IP_PRIVATE.match(relay.get("ip")):
             continue
         from_host = relay.get("rdns")
         helo_host = relay.get("helo")
         if not helo_host:
             continue
         no_rdns_dotcom_helo = False
         big_isp_re = Regex(
             r".*(?:\.|^)(lycos\.com|lycos\.co\.uk|hotmail\.com"
             r"|localhost\.com|excite\.com|caramail\.com|"
             r"cs\.com|aol\.com|msn\.com|yahoo\.com|"
             r"drizzle\.com)$")
         if big_isp_re.match(helo_host):
             if not from_host:
                 no_rdns_dotcom_helo = True
     return no_rdns_dotcom_helo
Example #5
0
    def _check_rbl_addr(self, addresses, rbl_server, subtest=None):
        """Checks the specified addresses on the specified list.

        :param addresses: A list of addresses to check
        :param rbl_server: The RBL list to check
        :param subtest: If specified then an additional check
          is done on the result of the DNS lookup by matching
          this regular expression against the result.
        :return: True if there is a match and the subtest
          passes and False otherwise.
        """

        if self.ctxt.skip_rbl_checks:
            return False

        if subtest is not None:
            try:
                subtest = Regex(subtest)
            except re.error as e:
                self.ctxt.err("Invalid regex %s: %s", subtest, e)
                return False

        for addr in addresses:
            if "@" in addr:
                domain = addr.rsplit("@", 1)[1].strip()
            else:
                domain = addr.strip()
            results = self.ctxt.dns.query("%s.%s" % (domain, rbl_server), "A")

            if results and not subtest:
                return True

            for result in results:
                if subtest.match(str(result)):
                    return True
        return False