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.

http_headers.lua 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. --[[
  2. Copyright (c) 2015, Vsevolod Stakhov <vsevolod@highsecure.ru>
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ]]--
  13. local logger = require "rspamd_logger"
  14. local ucl = require "ucl"
  15. local spf_symbols = {
  16. symbol_allow = 'R_SPF_ALLOW',
  17. symbol_deny = 'R_SPF_FAIL',
  18. symbol_softfail = 'R_SPF_SOFTFAIL',
  19. symbol_neutral = 'R_SPF_NEUTRAL',
  20. symbol_tempfail = 'R_SPF_DNSFAIL',
  21. symbol_na = 'R_SPF_NA',
  22. symbol_permfail = 'R_SPF_PERMFAIL',
  23. }
  24. local dkim_symbols = {
  25. symbol_allow = 'R_DKIM_ALLOW',
  26. symbol_deny = 'R_DKIM_REJECT',
  27. symbol_tempfail = 'R_DKIM_TEMPFAIL',
  28. symbol_na = 'R_DKIM_NA',
  29. symbol_permfail = 'R_DKIM_PERMFAIL',
  30. }
  31. local dmarc_symbols = {
  32. allow = 'DMARC_POLICY_ALLOW',
  33. badpolicy = 'DMARC_BAD_POLICY',
  34. dnsfail = 'DMARC_DNSFAIL',
  35. na = 'DMARC_NA',
  36. reject = 'DMARC_POLICY_REJECT',
  37. softfail = 'DMARC_POLICY_SOFTFAIL',
  38. quarantine = 'DMARC_POLICY_QUARANTINE',
  39. }
  40. local opts = rspamd_config:get_all_opt('dmarc')
  41. if opts and opts['symbols'] then
  42. for k,_ in pairs(dmarc_symbols) do
  43. if opts['symbols'][k] then
  44. dmarc_symbols[k] = opts['symbols'][k]
  45. end
  46. end
  47. end
  48. opts = rspamd_config:get_all_opt('dkim')
  49. if opts then
  50. for k,_ in pairs(dkim_symbols) do
  51. if opts[k] then
  52. dkim_symbols[k] = opts[k]
  53. end
  54. end
  55. end
  56. opts = rspamd_config:get_all_opt('spf')
  57. if opts then
  58. for k,_ in pairs(spf_symbols) do
  59. if opts[k] then
  60. spf_symbols[k] = opts[k]
  61. end
  62. end
  63. end
  64. -- Disable DKIM checks if passed via HTTP headers
  65. rspamd_config:add_condition("R_DKIM_ALLOW", function(task)
  66. local hdr = task:get_request_header('DKIM')
  67. if hdr then
  68. local parser = ucl.parser()
  69. local res, err = parser:parse_string(tostring(hdr))
  70. if not res then
  71. logger.infox(task, "cannot parse DKIM header: %1", err)
  72. return true
  73. end
  74. local obj = parser:get_object()
  75. if obj['result'] then
  76. if obj['result'] == 'pass' or obj['result'] == 'allow' then
  77. task:insert_result(dkim_symbols['symbol_allow'], 1.0, 'http header')
  78. elseif obj['result'] == 'fail' or obj['result'] == 'reject' then
  79. task:insert_result(dkim_symbols['symbol_deny'], 1.0, 'http header')
  80. elseif obj['result'] == 'tempfail' or obj['result'] == 'softfail' then
  81. task:insert_result(dkim_symbols['symbol_tempfail'], 1.0, 'http header')
  82. elseif obj['result'] == 'permfail' then
  83. task:insert_result(dkim_symbols['symbol_permfail'], 1.0, 'http header')
  84. elseif obj['result'] == 'na' then
  85. task:insert_result(dkim_symbols['symbol_na'], 1.0, 'http header')
  86. end
  87. return false
  88. end
  89. end
  90. return true
  91. end)
  92. -- Disable SPF checks if passed via HTTP headers
  93. rspamd_config:add_condition("R_SPF_ALLOW", function(task)
  94. local hdr = task:get_request_header('SPF')
  95. if hdr then
  96. local parser = ucl.parser()
  97. local res, err = parser:parse_string(tostring(hdr))
  98. if not res then
  99. logger.infox(task, "cannot parse SPF header: %1", err)
  100. return true
  101. end
  102. local obj = parser:get_object()
  103. if obj['result'] then
  104. if obj['result'] == 'pass' or obj['result'] == 'allow' then
  105. task:insert_result(spf_symbols['symbol_allow'], 1.0, 'http header')
  106. elseif obj['result'] == 'fail' or obj['result'] == 'reject' then
  107. task:insert_result(spf_symbols['symbol_deny'], 1.0, 'http header')
  108. elseif obj['result'] == 'neutral' then
  109. task:insert_result(spf_symbols['symbol_neutral'], 1.0, 'http header')
  110. elseif obj['result'] == 'softfail' then
  111. task:insert_result(spf_symbols['symbol_softfail'], 1.0, 'http header')
  112. elseif obj['result'] == 'permfail' then
  113. task:insert_result(spf_symbols['symbol_permfail'], 1.0, 'http header')
  114. elseif obj['result'] == 'na' then
  115. task:insert_result(spf_symbols['symbol_na'], 1.0, 'http header')
  116. end
  117. return false
  118. end
  119. end
  120. return true
  121. end)
  122. rspamd_config:add_condition("DMARC_POLICY_ALLOW", function(task)
  123. local hdr = task:get_request_header('DMARC')
  124. if hdr then
  125. local parser = ucl.parser()
  126. local res, err = parser:parse_string(tostring(hdr))
  127. if not res then
  128. logger.infox(task, "cannot parse DMARC header: %1", err)
  129. return true
  130. end
  131. local obj = parser:get_object()
  132. if obj['result'] then
  133. if obj['result'] == 'pass' or obj['result'] == 'allow' then
  134. task:insert_result(dmarc_symbols['allow'], 1.0, 'http header')
  135. elseif obj['result'] == 'fail' or obj['result'] == 'reject' then
  136. task:insert_result(dmarc_symbols['reject'], 1.0, 'http header')
  137. elseif obj['result'] == 'quarantine' then
  138. task:insert_result(dmarc_symbols['quarantine'], 1.0, 'http header')
  139. elseif obj['result'] == 'tempfail' then
  140. task:insert_result(dmarc_symbols['dnsfail'], 1.0, 'http header')
  141. elseif obj['result'] == 'softfail' or obj['result'] == 'none' then
  142. task:insert_result(dmarc_symbols['softfail'], 1.0, 'http header')
  143. elseif obj['result'] == 'permfail' or obj['result'] == 'badpolicy' then
  144. task:insert_result(dmarc_symbols['badpolicy'], 1.0, 'http header')
  145. elseif obj['result'] == 'na' then
  146. task:insert_result(dmarc_symbols['na'], 1.0, 'http header')
  147. end
  148. return false
  149. end
  150. end
  151. return true
  152. end)