You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

auth_results.lua 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. --[[
  2. Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
  3. Copyright (c) 2017, Vsevolod Stakhov <vsevolod@highsecure.ru>
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. ]]--
  14. local global = require "global_functions"
  15. local default_settings = {
  16. spf_symbols = {
  17. pass = 'R_SPF_ALLOW',
  18. fail = 'R_SPF_FAIL',
  19. softfail = 'R_SPF_SOFTFAIL',
  20. neutral = 'R_SPF_NEUTRAL',
  21. temperror = 'R_SPF_DNSFAIL',
  22. none = 'R_SPF_NA',
  23. permerror = 'R_SPF_PERMFAIL',
  24. },
  25. dkim_symbols = {
  26. pass = 'R_DKIM_ALLOW',
  27. fail = 'R_DKIM_REJECT',
  28. temperror = 'R_DKIM_TEMPFAIL',
  29. none = 'R_DKIM_NA',
  30. permerror = 'R_DKIM_PERMFAIL',
  31. },
  32. dmarc_symbols = {
  33. pass = 'DMARC_POLICY_ALLOW',
  34. permerror = 'DMARC_BAD_POLICY',
  35. temperror = 'DMARC_DNSFAIL',
  36. none = 'DMARC_NA',
  37. reject = 'DMARC_POLICY_REJECT',
  38. softfail = 'DMARC_POLICY_SOFTFAIL',
  39. quarantine = 'DMARC_POLICY_QUARANTINE',
  40. },
  41. arc_symbols = {
  42. pass = 'ARC_ALLOW',
  43. permerror = 'ARC_INVALID',
  44. temperror = 'ARC_DNSFAIL',
  45. none = 'ARC_NA',
  46. reject = 'ARC_REJECT',
  47. },
  48. }
  49. local exports = {}
  50. local function gen_auth_results(task, settings)
  51. local table = table
  52. local pairs = pairs
  53. local ipairs = ipairs
  54. local auth_results, hdr_parts = {}, {}
  55. if not settings then
  56. settings = default_settings
  57. end
  58. local auth_types = {
  59. dkim = settings.dkim_symbols,
  60. dmarc = settings.dmarc_symbols,
  61. spf = settings.spf_symbols,
  62. arc = settings.arc_symbols,
  63. }
  64. local common = {
  65. symbols = {}
  66. }
  67. local received = task:get_received_headers() or {}
  68. local mxname = (received[1] or {}).by_hostname
  69. if mxname then
  70. table.insert(hdr_parts, mxname)
  71. end
  72. for auth_type, symbols in pairs(auth_types) do
  73. for key, sym in pairs(symbols) do
  74. if not common.symbols.sym then
  75. local s = task:get_symbol(sym)
  76. if not s then
  77. common.symbols[sym] = false
  78. else
  79. common.symbols[sym] = s
  80. if not auth_results[auth_type] then
  81. auth_results[auth_type] = {key}
  82. else
  83. table.insert(auth_results[auth_type], key)
  84. end
  85. if auth_type ~= 'dkim' then
  86. break
  87. end
  88. end
  89. end
  90. end
  91. end
  92. for auth_type, keys in pairs(auth_results) do
  93. for _, key in ipairs(keys) do
  94. local hdr = ''
  95. if auth_type == 'dmarc' and key ~= 'none' then
  96. local opts = common.symbols[auth_types['dmarc'][key]][1]['options'] or {}
  97. hdr = hdr .. 'dmarc='
  98. if key == 'reject' or key == 'quarantine' or key == 'softfail' then
  99. hdr = hdr .. 'fail'
  100. else
  101. hdr = hdr .. key
  102. end
  103. if key == 'pass' then
  104. hdr = hdr .. ' policy=' .. opts[2]
  105. hdr = hdr .. ' header.from=' .. opts[1]
  106. elseif key ~= 'none' then
  107. local t = global.rspamd_str_split(opts[1], ' : ')
  108. local dom = t[1]
  109. local rsn = t[2]
  110. if rsn then
  111. hdr = hdr .. ' reason="' .. rsn .. '"'
  112. end
  113. hdr = hdr .. ' header.from=' .. dom
  114. if key == 'softfail' then
  115. hdr = hdr .. ' policy=none'
  116. else
  117. hdr = hdr .. ' policy=' .. key
  118. end
  119. end
  120. table.insert(hdr_parts, hdr)
  121. elseif auth_type == 'dkim' and key ~= 'none' then
  122. if common.symbols[auth_types['dkim'][key]][1] then
  123. local opts = common.symbols[auth_types['dkim'][key]][1]['options']
  124. for _, v in ipairs(opts) do
  125. hdr = hdr .. auth_type .. '=' .. key .. ' header.d=' .. v
  126. table.insert(hdr_parts, hdr)
  127. end
  128. end
  129. elseif auth_type == 'arc' and key ~= 'none' then
  130. if common.symbols[auth_types['arc'][key]][1] then
  131. local opts = common.symbols[auth_types['arc'][key]][1]['options'] or {}
  132. for _, v in ipairs(opts) do
  133. hdr = hdr .. auth_type .. '=' .. key .. ' (' .. v .. ')'
  134. table.insert(hdr_parts, hdr)
  135. end
  136. end
  137. elseif auth_type == 'spf' and key ~= 'none' then
  138. hdr = hdr .. auth_type .. '=' .. key
  139. local smtp_from = task:get_from('smtp')
  140. if smtp_from['addr'] ~= '' and smtp_from['addr'] ~= nil then
  141. hdr = hdr .. ' smtp.mailfrom=' .. smtp_from['addr']
  142. else
  143. local helo = task:get_helo()
  144. if helo then
  145. hdr = hdr .. ' smtp.helo=' .. task:get_helo()
  146. end
  147. end
  148. table.insert(hdr_parts, hdr)
  149. end
  150. end
  151. end
  152. local u = task:get_user()
  153. local smtp_from = task:get_from('smtp')
  154. if u and smtp_from then
  155. local hdr
  156. if #smtp_from[1]['addr'] > 0 then
  157. hdr = string.format('auth=pass smtp.auth=%s smtp.mailfrom=%s',
  158. u, smtp_from[1]['addr'])
  159. else
  160. hdr = string.format('auth=pass smtp.auth=%s', u)
  161. end
  162. table.insert(hdr_parts, hdr)
  163. end
  164. if #hdr_parts > 0 then
  165. return table.concat(hdr_parts, '; ')
  166. end
  167. return nil
  168. end
  169. exports.gen_auth_results = gen_auth_results
  170. return exports