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.

dkim_signing.lua 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. --[[
  2. Copyright (c) 2016, Andrew Lewis <nerf@judo.za.org>
  3. Copyright (c) 2016, 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 lua_util = require "lua_util"
  15. local rspamd_logger = require "rspamd_logger"
  16. local dkim_sign_tools = require "lua_dkim_tools"
  17. local lua_redis = require "lua_redis"
  18. local lua_maps = require "lua_maps"
  19. if confighelp then
  20. return
  21. end
  22. local settings = {
  23. allow_envfrom_empty = true,
  24. allow_hdrfrom_mismatch = false,
  25. allow_hdrfrom_mismatch_local = false,
  26. allow_hdrfrom_mismatch_sign_networks = false,
  27. allow_hdrfrom_multiple = false,
  28. allow_username_mismatch = false,
  29. allow_pubkey_mismatch = true,
  30. auth_only = true,
  31. check_pubkey = false,
  32. domain = {},
  33. path = string.format('%s/%s/%s', rspamd_paths['DBDIR'], 'dkim', '$domain.$selector.key'),
  34. sign_local = true,
  35. selector = 'dkim',
  36. symbol = 'DKIM_SIGNED',
  37. try_fallback = true,
  38. use_domain = 'header',
  39. use_esld = true,
  40. use_redis = false,
  41. key_prefix = 'dkim_keys', -- default hash name
  42. }
  43. local N = 'dkim_signing'
  44. local redis_params
  45. local sign_func = rspamd_plugins.dkim.sign
  46. local function do_sign(task, p)
  47. if settings.check_pubkey then
  48. local resolve_name = p.selector .. "._domainkey." .. p.domain
  49. task:get_resolver():resolve_txt({
  50. task = task,
  51. name = resolve_name,
  52. callback = function(_, _, results, err)
  53. if not err and results and results[1] then
  54. p.pubkey = results[1]
  55. p.strict_pubkey_check = not settings.allow_pubkey_mismatch
  56. elseif not settings.allow_pubkey_mismatch then
  57. rspamd_logger.errx('public key for domain %s/%s is not found: %s, skip signing',
  58. p.domain, p.selector, err)
  59. return
  60. else
  61. rspamd_logger.infox('public key for domain %s/%s is not found: %s',
  62. p.domain, p.selector, err)
  63. end
  64. local sret, _ = sign_func(task, p)
  65. if sret then
  66. task:insert_result(settings.symbol, 1.0)
  67. end
  68. end,
  69. forced = true
  70. })
  71. else
  72. local sret, _ = sign_func(task, p)
  73. if sret then
  74. task:insert_result(settings.symbol, 1.0)
  75. end
  76. end
  77. end
  78. local function sign_error(task, msg)
  79. rspamd_logger.errx(task, 'signing failure: %s', msg)
  80. end
  81. local function dkim_signing_cb(task)
  82. local ret,selectors = dkim_sign_tools.prepare_dkim_signing(N, task, settings)
  83. if not ret then
  84. return
  85. end
  86. if settings.use_redis then
  87. dkim_sign_tools.sign_using_redis(N, task, settings, selectors, do_sign, sign_error)
  88. else
  89. if selectors.vault then
  90. dkim_sign_tools.sign_using_vault(N, task, settings, selectors, do_sign, sign_error)
  91. else
  92. if #selectors > 0 then
  93. for _, k in ipairs(selectors) do
  94. -- templates
  95. if k.key then
  96. k.key = lua_util.template(k.key, {
  97. domain = k.domain,
  98. selector = k.selector
  99. })
  100. lua_util.debugm(N, task, 'using key "%s", use selector "%s" for domain "%s"',
  101. k.key, k.selector, k.domain)
  102. end
  103. do_sign(task, k)
  104. end
  105. else
  106. rspamd_logger.infox(task, 'key path or dkim selector unconfigured; no signing')
  107. return false
  108. end
  109. end
  110. end
  111. end
  112. local opts = rspamd_config:get_all_opt('dkim_signing')
  113. if not opts then return end
  114. dkim_sign_tools.process_signing_settings(N, settings, opts)
  115. if not dkim_sign_tools.validate_signing_settings(settings) then
  116. rspamd_logger.infox(rspamd_config, 'mandatory parameters missing, disable dkim signing')
  117. lua_util.disable_module(N, "config")
  118. return
  119. end
  120. if settings.use_redis then
  121. redis_params = lua_redis.parse_redis_server('dkim_signing')
  122. if not redis_params then
  123. rspamd_logger.errx(rspamd_config,
  124. 'no servers are specified, but module is configured to load keys from redis, disable dkim signing')
  125. lua_util.disable_module(N, "redis")
  126. return
  127. end
  128. settings.redis_params = redis_params
  129. end
  130. rspamd_config:register_symbol({
  131. name = settings['symbol'],
  132. callback = dkim_signing_cb,
  133. groups = {"policies", "dkim"},
  134. score = 0.0,
  135. })
  136. -- Add dependency on DKIM checks
  137. rspamd_config:register_dependency(settings['symbol'], 'DKIM_CHECK')