]> source.dussan.org Git - rspamd.git/commitdiff
DMARC: check for subdomain policy 266/head
authorAndrew Lewis <nerf@judo.za.org>
Fri, 17 Apr 2015 23:02:16 +0000 (01:02 +0200)
committerAndrew Lewis <nerf@judo.za.org>
Fri, 17 Apr 2015 23:02:16 +0000 (01:02 +0200)
src/plugins/lua/dmarc.lua

index 25f8d03f38d111f8216fe47c820a914f6a892aea..ec3d88e2d17a18fc15f136eed93d029493d61fef 100644 (file)
@@ -76,6 +76,17 @@ local function dmarc_callback(task)
   end
   
   local function dmarc_dns_cb(resolver, to_resolve, results, err, key)
+
+    local lookup_domain = string.sub(to_resolve, 8)
+    if not results then
+      if lookup_domain ~= dmarc_domain then
+        task:get_resolver():resolve_txt(task:get_session(),
+        task:get_mempool(), '_dmarc.' .. dmarc_domain, dmarc_dns_cb)
+        return
+      else
+        return
+    end
+
     local strict_spf = false
     local strict_dkim = false
     local strict_policy = false
@@ -84,9 +95,6 @@ local function dmarc_callback(task)
     local failed_policy = false
     local rua
     
-    if not results then
-      return
-    end
     for _,r in ipairs(results) do
       if failed_policy then break end
       (function()
@@ -135,18 +143,18 @@ local function dmarc_callback(task)
               end
             end
             subdomain_policy = string.match(e, '^sp=(.+)$')
-            if subdomain_policy then
+            if subdomain_policy and lookup_domain == dmarc_domain then
               if (subdomain_policy == 'reject') then
-                if url_from:get_tld() ~= from[1]['domain'] then
+                if dmarc_domain ~= from[1]['domain'] then
                   strict_policy = true
                 end
               elseif (subdomain_policy == 'quarantine') then
-                if url_from:get_tld() ~= from[1]['domain'] then
+                if dmarc_domain ~= from[1]['domain'] then
                   strict_policy = true
                   quarantine_policy = true
                 end
               elseif (subdomain_policy == 'none') then
-                if url_from:get_tld() ~= from[1]['domain'] then
+                if dmarc_domain ~= from[1]['domain'] then
                   strict_policy = false
                   quarantine_policy = false
                 end
@@ -168,7 +176,15 @@ local function dmarc_callback(task)
       end)()
     end
 
-    if not found_policy or failed_policy then return end
+    if not found_policy then
+      if lookup_domain ~= dmarc_domain then
+        task:get_resolver():resolve_txt(task:get_session(),
+        task:get_mempool(), '_dmarc.' .. dmarc_domain, dmarc_dns_cb)
+        return
+      else
+        return
+    end
+    if failed_policy then return end
 
     -- Check dkim and spf symbols
     local spf_ok = false
@@ -180,8 +196,8 @@ local function dmarc_callback(task)
             spf_ok = true
           elseif not strict_spf then
             if string.sub(efrom[1]['domain'],
-              -string.len('.' .. dmarc_domain))
-              == '.' .. dmarc_domain then
+              -string.len('.' .. lookup_domain))
+              == '.' .. lookup_domain then
                 spf_ok = true
             end
           end
@@ -193,8 +209,8 @@ local function dmarc_callback(task)
         dkim_ok = true
       elseif not strict_dkim then
         if string.sub(das[1]['options'][0],
-          -string.len('.' .. dmarc_domain))
-          == '.' .. dmarc_domain then
+          -string.len('.' .. lookup_domain))
+          == '.' .. lookup_domain then
             dkim_ok = true
         end
       end
@@ -205,17 +221,17 @@ local function dmarc_callback(task)
       res = 1.0
       if quarantine_policy then
         if not pct or pct == 100 or (math.random(100) <= pct) then
-          task:insert_result('DMARC_POLICY_QUARANTINE', res, dmarc_domain)
+          task:insert_result('DMARC_POLICY_QUARANTINE', res, lookup_domain)
         end
       elseif strict_policy then
         if not pct or pct == 100 or (math.random(100) <= pct) then
-          task:insert_result('DMARC_POLICY_REJECT', res, dmarc_domain)
+          task:insert_result('DMARC_POLICY_REJECT', res, lookup_domain)
         end
       else
-        task:insert_result('DMARC_POLICY_SOFTFAIL', res, dmarc_domain)
+        task:insert_result('DMARC_POLICY_SOFTFAIL', res, lookup_domain)
       end
     else
-      task:insert_result('DMARC_POLICY_ALLOW', res, dmarc_domain)
+      task:insert_result('DMARC_POLICY_ALLOW', res, lookup_domain)
     end
     
     if rua and not(spf_ok or dkim_ok) and upstreams then
@@ -234,13 +250,12 @@ local function dmarc_callback(task)
     -- XXX: handle rua and push data to redis
   end
 
-  -- XXX: Check for DMARC policy record at subdomain
   if from and from[1]['domain'] and not from[2] then
     local url_from = rspamd_url.create(task:get_mempool(), from[1]['domain'])
     if url_from then
       dmarc_domain = url_from:get_tld()
       task:get_resolver():resolve_txt(task:get_session(), task:get_mempool(),
-        '_dmarc.' .. dmarc_domain, dmarc_dns_cb)
+        '_dmarc.' .. from[1]['domain'], dmarc_dns_cb)
     end
   end
 end