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.

пре 8 година
пре 12 година
пре 8 година
пре 12 година
пре 8 година
пре 12 година
пре 12 година
пре 8 година
пре 12 година
пре 12 година
пре 12 година
пре 9 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 9 година
пре 12 година
пре 12 година
пре 12 година
пре 10 година
пре 12 година
пре 12 година
пре 12 година
пре 10 година
пре 12 година
пре 12 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 8 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 4 година
пре 12 година
пре 10 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 4 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 12 година
пре 5 година
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  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. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /***MODULE:dkim
  17. * rspamd module that checks dkim records of incoming email
  18. *
  19. * Allowed options:
  20. * - symbol_allow (string): symbol to insert in case of allow (default: 'R_DKIM_ALLOW')
  21. * - symbol_reject (string): symbol to insert (default: 'R_DKIM_REJECT')
  22. * - symbol_tempfail (string): symbol to insert in case of temporary fail (default: 'R_DKIM_TEMPFAIL')
  23. * - symbol_permfail (string): symbol to insert in case of permanent failure (default: 'R_DKIM_PERMFAIL')
  24. * - symbol_na (string): symbol to insert in case of no signing (default: 'R_DKIM_NA')
  25. * - whitelist (map): map of whitelisted networks
  26. * - domains (map): map of domains to check
  27. * - strict_multiplier (number): multiplier for strict domains
  28. * - time_jitter (number): jitter in seconds to allow time diff while checking
  29. * - trusted_only (flag): check signatures only for domains in 'domains' map
  30. */
  31. #include "config.h"
  32. #include "libmime/message.h"
  33. #include "libserver/dkim.h"
  34. #include "libutil/hash.h"
  35. #include "libserver/maps/map.h"
  36. #include "libserver/maps/map_helpers.h"
  37. #include "rspamd.h"
  38. #include "utlist.h"
  39. #include "unix-std.h"
  40. #include "lua/lua_common.h"
  41. #include "libserver/mempool_vars_internal.h"
  42. #define DEFAULT_SYMBOL_REJECT "R_DKIM_REJECT"
  43. #define DEFAULT_SYMBOL_TEMPFAIL "R_DKIM_TEMPFAIL"
  44. #define DEFAULT_SYMBOL_ALLOW "R_DKIM_ALLOW"
  45. #define DEFAULT_SYMBOL_NA "R_DKIM_NA"
  46. #define DEFAULT_SYMBOL_PERMFAIL "R_DKIM_PERMFAIL"
  47. #define DEFAULT_CACHE_SIZE 2048
  48. #define DEFAULT_TIME_JITTER 60
  49. #define DEFAULT_MAX_SIGS 5
  50. static const gchar *M = "rspamd dkim plugin";
  51. static const gchar default_sign_headers[] = ""
  52. "(o)from:(x)sender:(o)reply-to:(o)subject:(x)date:(x)message-id:"
  53. "(o)to:(o)cc:(x)mime-version:(x)content-type:(x)content-transfer-encoding:"
  54. "resent-to:resent-cc:resent-from:resent-sender:resent-message-id:"
  55. "(x)in-reply-to:(x)references:list-id:list-help:list-owner:list-unsubscribe:"
  56. "list-subscribe:list-post:(x)openpgp:(x)autocrypt";
  57. static const gchar default_arc_sign_headers[] = ""
  58. "(o)from:(x)sender:(o)reply-to:(o)subject:(x)date:(x)message-id:"
  59. "(o)to:(o)cc:(x)mime-version:(x)content-type:(x)content-transfer-encoding:"
  60. "resent-to:resent-cc:resent-from:resent-sender:resent-message-id:"
  61. "(x)in-reply-to:(x)references:list-id:list-help:list-owner:list-unsubscribe:"
  62. "list-subscribe:list-post:dkim-signature:(x)openpgp:(x)autocrypt";
  63. struct dkim_ctx {
  64. struct module_ctx ctx;
  65. const gchar *symbol_reject;
  66. const gchar *symbol_tempfail;
  67. const gchar *symbol_allow;
  68. const gchar *symbol_na;
  69. const gchar *symbol_permfail;
  70. struct rspamd_radix_map_helper *whitelist_ip;
  71. struct rspamd_hash_map_helper *dkim_domains;
  72. guint strict_multiplier;
  73. guint time_jitter;
  74. rspamd_lru_hash_t *dkim_hash;
  75. rspamd_lru_hash_t *dkim_sign_hash;
  76. const gchar *sign_headers;
  77. const gchar *arc_sign_headers;
  78. guint max_sigs;
  79. gboolean trusted_only;
  80. gboolean check_local;
  81. gboolean check_authed;
  82. };
  83. struct dkim_check_result {
  84. rspamd_dkim_context_t *ctx;
  85. rspamd_dkim_key_t *key;
  86. struct rspamd_task *task;
  87. struct rspamd_dkim_check_result *res;
  88. gdouble mult_allow;
  89. gdouble mult_deny;
  90. struct rspamd_symcache_item *item;
  91. struct dkim_check_result *next, *prev, *first;
  92. };
  93. static void dkim_symbol_callback (struct rspamd_task *task,
  94. struct rspamd_symcache_item *item,
  95. void *unused);
  96. static void dkim_sign_callback (struct rspamd_task *task,
  97. struct rspamd_symcache_item *item,
  98. void *unused);
  99. static gint lua_dkim_sign_handler (lua_State *L);
  100. static gint lua_dkim_verify_handler (lua_State *L);
  101. static gint lua_dkim_canonicalize_handler (lua_State *L);
  102. /* Initialization */
  103. gint dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx);
  104. gint dkim_module_config (struct rspamd_config *cfg);
  105. gint dkim_module_reconfig (struct rspamd_config *cfg);
  106. module_t dkim_module = {
  107. "dkim",
  108. dkim_module_init,
  109. dkim_module_config,
  110. dkim_module_reconfig,
  111. NULL,
  112. RSPAMD_MODULE_VER,
  113. (guint)-1,
  114. };
  115. static inline struct dkim_ctx *
  116. dkim_get_context (struct rspamd_config *cfg)
  117. {
  118. return (struct dkim_ctx *)g_ptr_array_index (cfg->c_modules,
  119. dkim_module.ctx_offset);
  120. }
  121. static void
  122. dkim_module_key_dtor (gpointer k)
  123. {
  124. rspamd_dkim_key_t *key = k;
  125. rspamd_dkim_key_unref (key);
  126. }
  127. static void
  128. dkim_module_free_list (gpointer k)
  129. {
  130. g_list_free_full ((GList *)k, rspamd_gstring_free_hard);
  131. }
  132. gint
  133. dkim_module_init (struct rspamd_config *cfg, struct module_ctx **ctx)
  134. {
  135. struct dkim_ctx *dkim_module_ctx;
  136. dkim_module_ctx = rspamd_mempool_alloc0 (cfg->cfg_pool,
  137. sizeof (*dkim_module_ctx));
  138. dkim_module_ctx->sign_headers = default_sign_headers;
  139. dkim_module_ctx->arc_sign_headers = default_arc_sign_headers;
  140. dkim_module_ctx->max_sigs = DEFAULT_MAX_SIGS;
  141. *ctx = (struct module_ctx *)dkim_module_ctx;
  142. rspamd_rcl_add_doc_by_path (cfg,
  143. NULL,
  144. "DKIM check plugin",
  145. "dkim",
  146. UCL_OBJECT,
  147. NULL,
  148. 0,
  149. NULL,
  150. 0);
  151. rspamd_rcl_add_doc_by_path (cfg,
  152. "dkim",
  153. "Map of IP addresses that should be excluded from DKIM checks",
  154. "whitelist",
  155. UCL_STRING,
  156. NULL,
  157. 0,
  158. NULL,
  159. 0);
  160. rspamd_rcl_add_doc_by_path (cfg,
  161. "dkim",
  162. "Symbol that is added if DKIM check is successful",
  163. "symbol_allow",
  164. UCL_STRING,
  165. NULL,
  166. 0,
  167. DEFAULT_SYMBOL_ALLOW,
  168. 0);
  169. rspamd_rcl_add_doc_by_path (cfg,
  170. "dkim",
  171. "Symbol that is added if DKIM check is unsuccessful",
  172. "symbol_reject",
  173. UCL_STRING,
  174. NULL,
  175. 0,
  176. DEFAULT_SYMBOL_REJECT,
  177. 0);
  178. rspamd_rcl_add_doc_by_path (cfg,
  179. "dkim",
  180. "Symbol that is added if DKIM check can't be completed (e.g. DNS failure)",
  181. "symbol_tempfail",
  182. UCL_STRING,
  183. NULL,
  184. 0,
  185. DEFAULT_SYMBOL_TEMPFAIL,
  186. 0);
  187. rspamd_rcl_add_doc_by_path (cfg,
  188. "dkim",
  189. "Symbol that is added if mail is not signed",
  190. "symbol_na",
  191. UCL_STRING,
  192. NULL,
  193. 0,
  194. DEFAULT_SYMBOL_NA,
  195. 0);
  196. rspamd_rcl_add_doc_by_path (cfg,
  197. "dkim",
  198. "Symbol that is added if permanent failure encountered",
  199. "symbol_permfail",
  200. UCL_STRING,
  201. NULL,
  202. 0,
  203. DEFAULT_SYMBOL_PERMFAIL,
  204. 0);
  205. rspamd_rcl_add_doc_by_path (cfg,
  206. "dkim",
  207. "Size of DKIM keys cache",
  208. "dkim_cache_size",
  209. UCL_INT,
  210. NULL,
  211. 0,
  212. G_STRINGIFY (DEFAULT_CACHE_SIZE),
  213. 0);
  214. rspamd_rcl_add_doc_by_path (cfg,
  215. "dkim",
  216. "Allow this time difference when checking DKIM signature time validity",
  217. "time_jitter",
  218. UCL_TIME,
  219. NULL,
  220. 0,
  221. G_STRINGIFY (DEFAULT_TIME_JITTER),
  222. 0);
  223. rspamd_rcl_add_doc_by_path (cfg,
  224. "dkim",
  225. "Domains to check DKIM for (check all domains if this option is empty)",
  226. "domains",
  227. UCL_STRING,
  228. NULL,
  229. 0,
  230. "empty",
  231. 0);
  232. rspamd_rcl_add_doc_by_path (cfg,
  233. "dkim",
  234. "Map of domains that are treated as 'trusted' meaning that DKIM policy failure has more significant score",
  235. "trusted_domains",
  236. UCL_STRING,
  237. NULL,
  238. 0,
  239. "empty",
  240. 0);
  241. rspamd_rcl_add_doc_by_path (cfg,
  242. "dkim",
  243. "Multiply dkim score by this factor for trusted domains",
  244. "strict_multiplier",
  245. UCL_FLOAT,
  246. NULL,
  247. 0,
  248. NULL,
  249. 0);
  250. rspamd_rcl_add_doc_by_path (cfg,
  251. "dkim",
  252. "Check DKIM policies merely for `trusted_domains`",
  253. "trusted_only",
  254. UCL_BOOLEAN,
  255. NULL,
  256. 0,
  257. "false",
  258. 0);
  259. rspamd_rcl_add_doc_by_path (cfg,
  260. "dkim",
  261. "Lua script that tells if a message should be signed and with what params (obsoleted)",
  262. "sign_condition",
  263. UCL_STRING,
  264. NULL,
  265. 0,
  266. "empty",
  267. 0);
  268. rspamd_rcl_add_doc_by_path (cfg,
  269. "dkim",
  270. "Obsoleted: maximum number of DKIM signatures to check",
  271. "max_sigs",
  272. UCL_INT,
  273. NULL,
  274. 0,
  275. "n/a",
  276. 0);
  277. rspamd_rcl_add_doc_by_path (cfg,
  278. "dkim",
  279. "Headers used in signing",
  280. "sign_headers",
  281. UCL_STRING,
  282. NULL,
  283. 0,
  284. default_sign_headers,
  285. 0);
  286. return 0;
  287. }
  288. gint
  289. dkim_module_config (struct rspamd_config *cfg)
  290. {
  291. const ucl_object_t *value;
  292. gint res = TRUE, cb_id = -1;
  293. guint cache_size, sign_cache_size;
  294. gboolean got_trusted = FALSE;
  295. struct dkim_ctx *dkim_module_ctx = dkim_get_context (cfg);
  296. /* Register global methods */
  297. lua_getglobal (cfg->lua_state, "rspamd_plugins");
  298. if (lua_type (cfg->lua_state, -1) == LUA_TTABLE) {
  299. lua_pushstring (cfg->lua_state, "dkim");
  300. lua_createtable (cfg->lua_state, 0, 1);
  301. /* Set methods */
  302. lua_pushstring (cfg->lua_state, "sign");
  303. lua_pushcfunction (cfg->lua_state, lua_dkim_sign_handler);
  304. lua_settable (cfg->lua_state, -3);
  305. lua_pushstring (cfg->lua_state, "verify");
  306. lua_pushcfunction (cfg->lua_state, lua_dkim_verify_handler);
  307. lua_settable (cfg->lua_state, -3);
  308. lua_pushstring (cfg->lua_state, "canon_header_relaxed");
  309. lua_pushcfunction (cfg->lua_state, lua_dkim_canonicalize_handler);
  310. lua_settable (cfg->lua_state, -3);
  311. /* Finish dkim key */
  312. lua_settable (cfg->lua_state, -3);
  313. }
  314. lua_pop (cfg->lua_state, 1); /* Remove global function */
  315. dkim_module_ctx->whitelist_ip = NULL;
  316. value = rspamd_config_get_module_opt (cfg, "dkim", "check_local");
  317. if (value == NULL) {
  318. rspamd_config_get_module_opt (cfg, "options", "check_local");
  319. }
  320. if (value != NULL) {
  321. dkim_module_ctx->check_local = ucl_object_toboolean (value);
  322. }
  323. else {
  324. dkim_module_ctx->check_local = FALSE;
  325. }
  326. value = rspamd_config_get_module_opt (cfg, "dkim", "check_authed");
  327. if (value == NULL) {
  328. rspamd_config_get_module_opt (cfg, "options", "check_authed");
  329. }
  330. if (value != NULL) {
  331. dkim_module_ctx->check_authed = ucl_object_toboolean (value);
  332. }
  333. else {
  334. dkim_module_ctx->check_authed = FALSE;
  335. }
  336. if ((value =
  337. rspamd_config_get_module_opt (cfg, "dkim", "symbol_reject")) != NULL) {
  338. dkim_module_ctx->symbol_reject = ucl_object_tostring (value);
  339. }
  340. else {
  341. dkim_module_ctx->symbol_reject = DEFAULT_SYMBOL_REJECT;
  342. }
  343. if ((value =
  344. rspamd_config_get_module_opt (cfg, "dkim",
  345. "symbol_tempfail")) != NULL) {
  346. dkim_module_ctx->symbol_tempfail = ucl_object_tostring (value);
  347. }
  348. else {
  349. dkim_module_ctx->symbol_tempfail = DEFAULT_SYMBOL_TEMPFAIL;
  350. }
  351. if ((value =
  352. rspamd_config_get_module_opt (cfg, "dkim", "symbol_allow")) != NULL) {
  353. dkim_module_ctx->symbol_allow = ucl_object_tostring (value);
  354. }
  355. else {
  356. dkim_module_ctx->symbol_allow = DEFAULT_SYMBOL_ALLOW;
  357. }
  358. if ((value =
  359. rspamd_config_get_module_opt (cfg, "dkim", "symbol_na")) != NULL) {
  360. dkim_module_ctx->symbol_na = ucl_object_tostring (value);
  361. }
  362. else {
  363. dkim_module_ctx->symbol_na = DEFAULT_SYMBOL_NA;
  364. }
  365. if ((value =
  366. rspamd_config_get_module_opt (cfg, "dkim", "symbol_permfail")) != NULL) {
  367. dkim_module_ctx->symbol_permfail = ucl_object_tostring (value);
  368. }
  369. else {
  370. dkim_module_ctx->symbol_permfail = DEFAULT_SYMBOL_PERMFAIL;
  371. }
  372. if ((value =
  373. rspamd_config_get_module_opt (cfg, "dkim",
  374. "dkim_cache_size")) != NULL) {
  375. cache_size = ucl_object_toint (value);
  376. }
  377. else {
  378. cache_size = DEFAULT_CACHE_SIZE;
  379. }
  380. if ((value =
  381. rspamd_config_get_module_opt (cfg, "dkim",
  382. "sign_cache_size")) != NULL) {
  383. sign_cache_size = ucl_object_toint (value);
  384. }
  385. else {
  386. sign_cache_size = 128;
  387. }
  388. if ((value =
  389. rspamd_config_get_module_opt (cfg, "dkim", "time_jitter")) != NULL) {
  390. dkim_module_ctx->time_jitter = ucl_object_todouble (value);
  391. }
  392. else {
  393. dkim_module_ctx->time_jitter = DEFAULT_TIME_JITTER;
  394. }
  395. if ((value =
  396. rspamd_config_get_module_opt (cfg, "dkim", "max_sigs")) != NULL) {
  397. dkim_module_ctx->max_sigs = ucl_object_toint (value);
  398. }
  399. if ((value =
  400. rspamd_config_get_module_opt (cfg, "dkim", "whitelist")) != NULL) {
  401. rspamd_config_radix_from_ucl (cfg, value, "DKIM whitelist",
  402. &dkim_module_ctx->whitelist_ip, NULL, NULL);
  403. }
  404. if ((value =
  405. rspamd_config_get_module_opt (cfg, "dkim", "domains")) != NULL) {
  406. if (!rspamd_map_add_from_ucl (cfg, value,
  407. "DKIM domains",
  408. rspamd_kv_list_read,
  409. rspamd_kv_list_fin,
  410. rspamd_kv_list_dtor,
  411. (void **)&dkim_module_ctx->dkim_domains,
  412. NULL)) {
  413. msg_warn_config ("cannot load dkim domains list from %s",
  414. ucl_object_tostring (value));
  415. }
  416. else {
  417. got_trusted = TRUE;
  418. }
  419. }
  420. if (!got_trusted && (value =
  421. rspamd_config_get_module_opt (cfg, "dkim", "trusted_domains")) != NULL) {
  422. if (!rspamd_map_add_from_ucl (cfg, value,
  423. "DKIM domains",
  424. rspamd_kv_list_read,
  425. rspamd_kv_list_fin,
  426. rspamd_kv_list_dtor,
  427. (void **)&dkim_module_ctx->dkim_domains,
  428. NULL)) {
  429. msg_warn_config ("cannot load dkim domains list from %s",
  430. ucl_object_tostring (value));
  431. }
  432. else {
  433. got_trusted = TRUE;
  434. }
  435. }
  436. if ((value =
  437. rspamd_config_get_module_opt (cfg, "dkim",
  438. "strict_multiplier")) != NULL) {
  439. dkim_module_ctx->strict_multiplier = ucl_object_toint (value);
  440. }
  441. else {
  442. dkim_module_ctx->strict_multiplier = 1;
  443. }
  444. if ((value =
  445. rspamd_config_get_module_opt (cfg, "dkim", "trusted_only")) != NULL) {
  446. dkim_module_ctx->trusted_only = ucl_object_toboolean (value);
  447. }
  448. else {
  449. dkim_module_ctx->trusted_only = FALSE;
  450. }
  451. if ((value =
  452. rspamd_config_get_module_opt (cfg, "dkim", "sign_headers")) != NULL) {
  453. dkim_module_ctx->sign_headers = ucl_object_tostring (value);
  454. }
  455. if ((value =
  456. rspamd_config_get_module_opt (cfg, "arc", "sign_headers")) != NULL) {
  457. dkim_module_ctx->arc_sign_headers = ucl_object_tostring (value);
  458. }
  459. if (cache_size > 0) {
  460. dkim_module_ctx->dkim_hash = rspamd_lru_hash_new (
  461. cache_size,
  462. g_free,
  463. dkim_module_key_dtor);
  464. rspamd_mempool_add_destructor (cfg->cfg_pool,
  465. (rspamd_mempool_destruct_t)rspamd_lru_hash_destroy,
  466. dkim_module_ctx->dkim_hash);
  467. }
  468. if (sign_cache_size > 0) {
  469. dkim_module_ctx->dkim_sign_hash = rspamd_lru_hash_new (
  470. sign_cache_size,
  471. g_free,
  472. (GDestroyNotify) rspamd_dkim_sign_key_unref);
  473. rspamd_mempool_add_destructor (cfg->cfg_pool,
  474. (rspamd_mempool_destruct_t)rspamd_lru_hash_destroy,
  475. dkim_module_ctx->dkim_sign_hash);
  476. }
  477. if (dkim_module_ctx->trusted_only && !got_trusted) {
  478. msg_err_config (
  479. "trusted_only option is set and no trusted domains are defined; disabling dkim module completely as it is useless in this case");
  480. }
  481. else {
  482. if (!rspamd_config_is_module_enabled (cfg, "dkim")) {
  483. return TRUE;
  484. }
  485. cb_id = rspamd_symcache_add_symbol (cfg->cache,
  486. "DKIM_CHECK",
  487. 0,
  488. dkim_symbol_callback,
  489. NULL,
  490. SYMBOL_TYPE_CALLBACK,
  491. -1);
  492. rspamd_config_add_symbol (cfg,
  493. "DKIM_CHECK",
  494. 0.0,
  495. "DKIM check callback",
  496. "policies",
  497. RSPAMD_SYMBOL_FLAG_IGNORE_METRIC,
  498. 1,
  499. 1);
  500. rspamd_config_add_symbol_group (cfg, "DKIM_CHECK", "dkim");
  501. rspamd_symcache_add_symbol (cfg->cache,
  502. dkim_module_ctx->symbol_reject,
  503. 0,
  504. NULL,
  505. NULL,
  506. SYMBOL_TYPE_VIRTUAL | SYMBOL_TYPE_FINE,
  507. cb_id);
  508. rspamd_symcache_add_symbol (cfg->cache,
  509. dkim_module_ctx->symbol_na,
  510. 0,
  511. NULL, NULL,
  512. SYMBOL_TYPE_VIRTUAL | SYMBOL_TYPE_FINE,
  513. cb_id);
  514. rspamd_symcache_add_symbol (cfg->cache,
  515. dkim_module_ctx->symbol_permfail,
  516. 0,
  517. NULL, NULL,
  518. SYMBOL_TYPE_VIRTUAL | SYMBOL_TYPE_FINE,
  519. cb_id);
  520. rspamd_symcache_add_symbol (cfg->cache,
  521. dkim_module_ctx->symbol_tempfail,
  522. 0,
  523. NULL, NULL,
  524. SYMBOL_TYPE_VIRTUAL | SYMBOL_TYPE_FINE,
  525. cb_id);
  526. rspamd_symcache_add_symbol (cfg->cache,
  527. dkim_module_ctx->symbol_allow,
  528. 0,
  529. NULL, NULL,
  530. SYMBOL_TYPE_VIRTUAL | SYMBOL_TYPE_FINE,
  531. cb_id);
  532. rspamd_symcache_add_symbol (cfg->cache,
  533. "DKIM_TRACE",
  534. 0,
  535. NULL, NULL,
  536. SYMBOL_TYPE_VIRTUAL | SYMBOL_TYPE_NOSTAT,
  537. cb_id);
  538. rspamd_config_add_symbol (cfg,
  539. "DKIM_TRACE",
  540. 0.0,
  541. "DKIM trace symbol",
  542. "policies",
  543. RSPAMD_SYMBOL_FLAG_IGNORE_METRIC,
  544. 1,
  545. 1);
  546. rspamd_config_add_symbol_group (cfg, "DKIM_TRACE", "dkim");
  547. msg_info_config ("init internal dkim module");
  548. #ifndef HAVE_OPENSSL
  549. msg_warn_config (
  550. "openssl is not found so dkim rsa check is disabled, only check body hash, it is NOT safe to trust these results");
  551. #endif
  552. }
  553. return res;
  554. }
  555. /**
  556. * Grab a private key from the cache
  557. * or from the key content provided
  558. */
  559. rspamd_dkim_sign_key_t *
  560. dkim_module_load_key_format (struct rspamd_task *task,
  561. struct dkim_ctx *dkim_module_ctx,
  562. const gchar *key, gsize keylen,
  563. enum rspamd_dkim_key_format key_format)
  564. {
  565. guchar h[rspamd_cryptobox_HASHBYTES],
  566. hex_hash[rspamd_cryptobox_HASHBYTES * 2 + 1];
  567. rspamd_dkim_sign_key_t *ret = NULL;
  568. GError *err = NULL;
  569. struct stat st;
  570. memset (hex_hash, 0, sizeof (hex_hash));
  571. rspamd_cryptobox_hash (h, key, keylen, NULL, 0);
  572. rspamd_encode_hex_buf (h, sizeof (h), hex_hash, sizeof (hex_hash));
  573. if (dkim_module_ctx->dkim_sign_hash) {
  574. ret = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_sign_hash,
  575. hex_hash, time (NULL));
  576. }
  577. /*
  578. * This fails for paths that are also valid base64.
  579. * Maybe the caller should have specified a format.
  580. */
  581. if (key_format == RSPAMD_DKIM_KEY_UNKNOWN) {
  582. if (key[0] == '.' || key[0] == '/') {
  583. if (!rspamd_cryptobox_base64_is_valid (key, keylen)) {
  584. key_format = RSPAMD_DKIM_KEY_FILE;
  585. }
  586. }
  587. else if (rspamd_cryptobox_base64_is_valid (key, keylen)) {
  588. key_format = RSPAMD_DKIM_KEY_BASE64;
  589. }
  590. }
  591. if (ret != NULL && key_format == RSPAMD_DKIM_KEY_FILE) {
  592. msg_debug_task("checking for stale file key");
  593. if (stat (key, &st) != 0) {
  594. msg_err_task("cannot stat key file: %s", strerror (errno));
  595. return NULL;
  596. }
  597. if (rspamd_dkim_sign_key_maybe_invalidate (ret, st.st_mtime)) {
  598. msg_debug_task("removing stale file key");
  599. /*
  600. * Invalidate DKIM key
  601. * removal from lru cache also cleanup the key and value
  602. */
  603. if (dkim_module_ctx->dkim_sign_hash) {
  604. rspamd_lru_hash_remove (dkim_module_ctx->dkim_sign_hash,
  605. hex_hash);
  606. }
  607. ret = NULL;
  608. }
  609. }
  610. /* found key; done */
  611. if (ret != NULL) {
  612. return ret;
  613. }
  614. ret = rspamd_dkim_sign_key_load (key, keylen, key_format, &err);
  615. if (ret == NULL) {
  616. msg_err_task ("cannot load dkim key %s: %e",
  617. key, err);
  618. g_error_free (err);
  619. }
  620. else if (dkim_module_ctx->dkim_sign_hash) {
  621. rspamd_lru_hash_insert (dkim_module_ctx->dkim_sign_hash,
  622. g_strdup (hex_hash), ret, time (NULL), 0);
  623. }
  624. return ret;
  625. }
  626. static gint
  627. lua_dkim_sign_handler (lua_State *L)
  628. {
  629. struct rspamd_task *task = lua_check_task (L, 1);
  630. gint64 arc_idx = 0, expire = 0;
  631. enum rspamd_dkim_type sign_type = RSPAMD_DKIM_NORMAL;
  632. GError *err = NULL;
  633. GString *hdr;
  634. GList *sigs = NULL;
  635. const gchar *selector = NULL, *domain = NULL, *key = NULL, *rawkey = NULL,
  636. *headers = NULL, *sign_type_str = NULL, *arc_cv = NULL,
  637. *pubkey = NULL;
  638. rspamd_dkim_sign_context_t *ctx;
  639. rspamd_dkim_sign_key_t *dkim_key;
  640. gsize rawlen = 0, keylen = 0;
  641. gboolean no_cache = FALSE, strict_pubkey_check = FALSE;
  642. struct dkim_ctx *dkim_module_ctx;
  643. luaL_argcheck (L, lua_type (L, 2) == LUA_TTABLE, 2, "'table' expected");
  644. /*
  645. * Get the following elements:
  646. * - selector
  647. * - domain
  648. * - key
  649. */
  650. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  651. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  652. "key=V;rawkey=V;*domain=S;*selector=S;no_cache=B;headers=S;"
  653. "sign_type=S;arc_idx=I;arc_cv=S;expire=I;pubkey=S;"
  654. "strict_pubkey_check=B",
  655. &keylen, &key, &rawlen, &rawkey, &domain,
  656. &selector, &no_cache, &headers,
  657. &sign_type_str, &arc_idx, &arc_cv, &expire, &pubkey,
  658. &strict_pubkey_check)) {
  659. msg_err_task ("cannot parse table arguments: %e",
  660. err);
  661. g_error_free (err);
  662. lua_pushboolean (L, FALSE);
  663. return 1;
  664. }
  665. dkim_module_ctx = dkim_get_context (task->cfg);
  666. if (key) {
  667. dkim_key = dkim_module_load_key_format (task, dkim_module_ctx, key,
  668. keylen, RSPAMD_DKIM_KEY_UNKNOWN);
  669. }
  670. else if (rawkey) {
  671. dkim_key = dkim_module_load_key_format (task, dkim_module_ctx, rawkey,
  672. rawlen, RSPAMD_DKIM_KEY_UNKNOWN);
  673. }
  674. else {
  675. msg_err_task ("neither key nor rawkey are specified");
  676. lua_pushboolean (L, FALSE);
  677. return 1;
  678. }
  679. if (dkim_key == NULL) {
  680. lua_pushboolean (L, FALSE);
  681. return 1;
  682. }
  683. if (sign_type_str) {
  684. if (strcmp (sign_type_str, "dkim") == 0) {
  685. sign_type = RSPAMD_DKIM_NORMAL;
  686. if (headers == NULL) {
  687. headers = dkim_module_ctx->sign_headers;
  688. }
  689. }
  690. else if (strcmp (sign_type_str, "arc-sign") == 0) {
  691. sign_type = RSPAMD_DKIM_ARC_SIG;
  692. if (headers == NULL) {
  693. headers = dkim_module_ctx->arc_sign_headers;
  694. }
  695. if (arc_idx == 0) {
  696. lua_settop (L, 0);
  697. return luaL_error (L, "no arc idx specified");
  698. }
  699. }
  700. else if (strcmp (sign_type_str, "arc-seal") == 0) {
  701. sign_type = RSPAMD_DKIM_ARC_SEAL;
  702. if (arc_cv == NULL) {
  703. lua_settop (L, 0);
  704. return luaL_error (L, "no arc cv specified");
  705. }
  706. if (arc_idx == 0) {
  707. lua_settop (L, 0);
  708. return luaL_error (L, "no arc idx specified");
  709. }
  710. }
  711. else {
  712. lua_settop (L, 0);
  713. return luaL_error (L, "unknown sign type: %s",
  714. sign_type_str);
  715. }
  716. }
  717. else {
  718. /* Unspecified sign type, assume plain dkim */
  719. if (headers == NULL) {
  720. headers = dkim_module_ctx->sign_headers;
  721. }
  722. }
  723. if (pubkey != NULL) {
  724. /* Also check if private and public keys match */
  725. rspamd_dkim_key_t *pk;
  726. keylen = strlen (pubkey);
  727. pk = rspamd_dkim_parse_key (pubkey, &keylen, NULL);
  728. if (pk == NULL) {
  729. if (strict_pubkey_check) {
  730. msg_err_task ("cannot parse pubkey from string: %s, skip signing",
  731. pubkey);
  732. lua_pushboolean (L, FALSE);
  733. return 1;
  734. }
  735. else {
  736. msg_warn_task ("cannot parse pubkey from string: %s",
  737. pubkey);
  738. }
  739. }
  740. else {
  741. GError *te = NULL;
  742. /* We have parsed the key, so try to check keys */
  743. if (!rspamd_dkim_match_keys (pk, dkim_key, &te)) {
  744. if (strict_pubkey_check) {
  745. msg_err_task ("public key for %s/%s does not match private "
  746. "key: %e, skip signing",
  747. domain, selector, te);
  748. g_error_free (te);
  749. lua_pushboolean (L, FALSE);
  750. rspamd_dkim_key_unref (pk);
  751. return 1;
  752. }
  753. else {
  754. msg_warn_task ("public key for %s/%s does not match private "
  755. "key: %e",
  756. domain, selector, te);
  757. g_error_free (te);
  758. }
  759. }
  760. rspamd_dkim_key_unref (pk);
  761. }
  762. }
  763. ctx = rspamd_create_dkim_sign_context (task, dkim_key,
  764. DKIM_CANON_RELAXED, DKIM_CANON_RELAXED,
  765. headers, sign_type, &err);
  766. if (ctx == NULL) {
  767. msg_err_task ("cannot create sign context: %e",
  768. err);
  769. g_error_free (err);
  770. lua_pushboolean (L, FALSE);
  771. return 1;
  772. }
  773. hdr = rspamd_dkim_sign (task, selector, domain, 0,
  774. expire, arc_idx, arc_cv, ctx);
  775. if (hdr) {
  776. if (!no_cache) {
  777. sigs = rspamd_mempool_get_variable (task->task_pool, "dkim-signature");
  778. if (sigs == NULL) {
  779. sigs = g_list_append (sigs, hdr);
  780. rspamd_mempool_set_variable (task->task_pool, "dkim-signature",
  781. sigs, dkim_module_free_list);
  782. } else {
  783. sigs = g_list_append (sigs, hdr);
  784. (void)sigs;
  785. }
  786. }
  787. lua_pushboolean (L, TRUE);
  788. lua_pushlstring (L, hdr->str, hdr->len);
  789. if (no_cache) {
  790. g_string_free (hdr, TRUE);
  791. }
  792. return 2;
  793. }
  794. lua_pushboolean (L, FALSE);
  795. lua_pushnil (L);
  796. return 2;
  797. }
  798. gint
  799. dkim_module_reconfig (struct rspamd_config *cfg)
  800. {
  801. return dkim_module_config (cfg);
  802. }
  803. /*
  804. * Parse strict value for domain in format: 'reject_multiplier:deny_multiplier'
  805. */
  806. static gboolean
  807. dkim_module_parse_strict (const gchar *value, gdouble *allow, gdouble *deny)
  808. {
  809. const gchar *colon;
  810. gchar *err = NULL;
  811. gdouble val;
  812. gchar numbuf[64];
  813. colon = strchr (value, ':');
  814. if (colon) {
  815. rspamd_strlcpy (numbuf, value,
  816. MIN (sizeof (numbuf), (colon - value) + 1));
  817. val = strtod (numbuf, &err);
  818. if (err == NULL || *err == '\0') {
  819. *deny = val;
  820. colon++;
  821. rspamd_strlcpy (numbuf, colon, sizeof (numbuf));
  822. err = NULL;
  823. val = strtod (numbuf, &err);
  824. if (err == NULL || *err == '\0') {
  825. *allow = val;
  826. return TRUE;
  827. }
  828. }
  829. }
  830. return FALSE;
  831. }
  832. static void
  833. dkim_module_check (struct dkim_check_result *res)
  834. {
  835. gboolean all_done = TRUE;
  836. const gchar *strict_value;
  837. struct dkim_check_result *first, *cur = NULL;
  838. struct dkim_ctx *dkim_module_ctx = dkim_get_context (res->task->cfg);
  839. struct rspamd_task *task = res->task;
  840. first = res->first;
  841. DL_FOREACH (first, cur) {
  842. if (cur->ctx == NULL) {
  843. continue;
  844. }
  845. if (cur->key != NULL && cur->res == NULL) {
  846. cur->res = rspamd_dkim_check (cur->ctx, cur->key, task);
  847. if (dkim_module_ctx->dkim_domains != NULL) {
  848. /* Perform strict check */
  849. if ((strict_value =
  850. rspamd_match_hash_map (dkim_module_ctx->dkim_domains,
  851. rspamd_dkim_get_domain (cur->ctx))) != NULL) {
  852. if (!dkim_module_parse_strict (strict_value, &cur->mult_allow,
  853. &cur->mult_deny)) {
  854. cur->mult_allow = dkim_module_ctx->strict_multiplier;
  855. cur->mult_deny = dkim_module_ctx->strict_multiplier;
  856. }
  857. }
  858. }
  859. }
  860. }
  861. DL_FOREACH (first, cur) {
  862. if (cur->ctx == NULL) {
  863. continue;
  864. }
  865. if (cur->res == NULL) {
  866. /* Still need a key */
  867. all_done = FALSE;
  868. }
  869. }
  870. if (all_done) {
  871. /* Create zero terminated array of results */
  872. struct rspamd_dkim_check_result **pres;
  873. guint nres = 0, i = 0;
  874. DL_FOREACH (first, cur) {
  875. if (cur->ctx == NULL || cur->res == NULL) {
  876. continue;
  877. }
  878. nres ++;
  879. }
  880. pres = rspamd_mempool_alloc (task->task_pool, sizeof (*pres) * (nres + 1));
  881. pres[nres] = NULL;
  882. DL_FOREACH (first, cur) {
  883. const gchar *symbol = NULL, *trace = NULL;
  884. gdouble symbol_weight = 1.0;
  885. if (cur->ctx == NULL || cur->res == NULL) {
  886. continue;
  887. }
  888. pres[i++] = cur->res;
  889. if (cur->res->rcode == DKIM_REJECT) {
  890. symbol = dkim_module_ctx->symbol_reject;
  891. trace = "-";
  892. symbol_weight = cur->mult_deny * 1.0;
  893. }
  894. else if (cur->res->rcode == DKIM_CONTINUE) {
  895. symbol = dkim_module_ctx->symbol_allow;
  896. trace = "+";
  897. symbol_weight = cur->mult_allow * 1.0;
  898. }
  899. else if (cur->res->rcode == DKIM_PERM_ERROR) {
  900. trace = "~";
  901. symbol = dkim_module_ctx->symbol_permfail;
  902. }
  903. else if (cur->res->rcode == DKIM_TRYAGAIN) {
  904. trace = "?";
  905. symbol = dkim_module_ctx->symbol_tempfail;
  906. }
  907. if (symbol != NULL) {
  908. const gchar *domain = rspamd_dkim_get_domain (cur->ctx);
  909. const gchar *selector = rspamd_dkim_get_selector (cur->ctx);
  910. gsize tracelen;
  911. gchar *tracebuf;
  912. tracelen = strlen (domain) + strlen (selector) + 4;
  913. tracebuf = rspamd_mempool_alloc (task->task_pool,
  914. tracelen);
  915. rspamd_snprintf (tracebuf, tracelen, "%s:%s", domain, trace);
  916. rspamd_task_insert_result (cur->task,
  917. "DKIM_TRACE",
  918. 0.0,
  919. tracebuf);
  920. rspamd_snprintf (tracebuf, tracelen, "%s:s=%s", domain, selector);
  921. rspamd_task_insert_result (task,
  922. symbol,
  923. symbol_weight,
  924. tracebuf);
  925. }
  926. }
  927. rspamd_mempool_set_variable (task->task_pool,
  928. RSPAMD_MEMPOOL_DKIM_CHECK_RESULTS,
  929. pres, NULL);
  930. }
  931. }
  932. static void
  933. dkim_module_key_handler (rspamd_dkim_key_t *key,
  934. gsize keylen,
  935. rspamd_dkim_context_t *ctx,
  936. gpointer ud,
  937. GError *err)
  938. {
  939. struct dkim_check_result *res = ud;
  940. struct rspamd_task *task;
  941. struct dkim_ctx *dkim_module_ctx;
  942. task = res->task;
  943. dkim_module_ctx = dkim_get_context (task->cfg);
  944. if (key != NULL) {
  945. /* Another ref belongs to the check context */
  946. res->key = rspamd_dkim_key_ref (key);
  947. /*
  948. * We actually receive key with refcount = 1, so we just assume that
  949. * lru hash owns this object now
  950. */
  951. /* Release key when task is processed */
  952. rspamd_mempool_add_destructor (res->task->task_pool,
  953. dkim_module_key_dtor, res->key);
  954. if (dkim_module_ctx->dkim_hash) {
  955. rspamd_lru_hash_insert (dkim_module_ctx->dkim_hash,
  956. g_strdup (rspamd_dkim_get_dns_key (ctx)),
  957. key, res->task->task_timestamp, rspamd_dkim_key_get_ttl (key));
  958. msg_info_task ("stored DKIM key for %s in LRU cache for %d seconds, "
  959. "%d/%d elements in the cache",
  960. rspamd_dkim_get_dns_key (ctx),
  961. rspamd_dkim_key_get_ttl (key),
  962. rspamd_lru_hash_size (dkim_module_ctx->dkim_hash),
  963. rspamd_lru_hash_capacity (dkim_module_ctx->dkim_hash));
  964. }
  965. }
  966. else {
  967. /* Insert tempfail symbol */
  968. msg_info_task ("cannot get key for domain %s: %e",
  969. rspamd_dkim_get_dns_key (ctx), err);
  970. if (err != NULL) {
  971. if (err->code == DKIM_SIGERROR_NOKEY) {
  972. res->res = rspamd_dkim_create_result (ctx, DKIM_TRYAGAIN, task);
  973. res->res->fail_reason = "DNS error when getting key";
  974. }
  975. else {
  976. res->res = rspamd_dkim_create_result (ctx, DKIM_PERM_ERROR, task);
  977. res->res->fail_reason = "invalid DKIM record";
  978. }
  979. }
  980. }
  981. if (err) {
  982. g_error_free (err);
  983. }
  984. dkim_module_check (res);
  985. }
  986. static void
  987. dkim_symbol_callback (struct rspamd_task *task,
  988. struct rspamd_symcache_item *item,
  989. void *unused)
  990. {
  991. rspamd_dkim_context_t *ctx;
  992. rspamd_dkim_key_t *key;
  993. GError *err = NULL;
  994. struct rspamd_mime_header *rh, *rh_cur;
  995. struct dkim_check_result *res = NULL, *cur;
  996. guint checked = 0;
  997. gdouble *dmarc_checks;
  998. struct dkim_ctx *dkim_module_ctx = dkim_get_context (task->cfg);
  999. /* Allow dmarc */
  1000. dmarc_checks = rspamd_mempool_get_variable (task->task_pool,
  1001. RSPAMD_MEMPOOL_DMARC_CHECKS);
  1002. if (dmarc_checks) {
  1003. (*dmarc_checks) ++;
  1004. }
  1005. else {
  1006. dmarc_checks = rspamd_mempool_alloc (task->task_pool,
  1007. sizeof (*dmarc_checks));
  1008. *dmarc_checks = 1;
  1009. rspamd_mempool_set_variable (task->task_pool,
  1010. RSPAMD_MEMPOOL_DMARC_CHECKS,
  1011. dmarc_checks, NULL);
  1012. }
  1013. /* First check if plugin should be enabled */
  1014. if ((!dkim_module_ctx->check_authed && task->user != NULL)
  1015. || (!dkim_module_ctx->check_local &&
  1016. rspamd_inet_address_is_local (task->from_addr, TRUE))) {
  1017. msg_info_task ("skip DKIM checks for local networks and authorized users");
  1018. rspamd_symcache_finalize_item (task, item);
  1019. return;
  1020. }
  1021. /* Check whitelist */
  1022. if (rspamd_match_radix_map_addr (dkim_module_ctx->whitelist_ip,
  1023. task->from_addr) != NULL) {
  1024. msg_info_task ("skip DKIM checks for whitelisted address");
  1025. rspamd_symcache_finalize_item (task, item);
  1026. return;
  1027. }
  1028. rspamd_symcache_item_async_inc (task, item, M);
  1029. /* Now check if a message has its signature */
  1030. rh = rspamd_message_get_header_array (task, RSPAMD_DKIM_SIGNHEADER);
  1031. if (rh) {
  1032. msg_debug_task ("dkim signature found");
  1033. DL_FOREACH (rh, rh_cur) {
  1034. if (rh_cur->decoded == NULL || rh_cur->decoded[0] == '\0') {
  1035. msg_info_task ("cannot load empty DKIM signature");
  1036. continue;
  1037. }
  1038. cur = rspamd_mempool_alloc0 (task->task_pool, sizeof (*cur));
  1039. cur->first = res;
  1040. cur->res = NULL;
  1041. cur->task = task;
  1042. cur->mult_allow = 1.0;
  1043. cur->mult_deny = 1.0;
  1044. cur->item = item;
  1045. ctx = rspamd_create_dkim_context (rh_cur->decoded,
  1046. task->task_pool,
  1047. dkim_module_ctx->time_jitter,
  1048. RSPAMD_DKIM_NORMAL,
  1049. &err);
  1050. if (res == NULL) {
  1051. res = cur;
  1052. res->first = res;
  1053. res->prev = res;
  1054. }
  1055. else {
  1056. DL_APPEND (res, cur);
  1057. }
  1058. if (ctx == NULL) {
  1059. if (err != NULL) {
  1060. msg_info_task ("cannot parse DKIM signature: %e",
  1061. err);
  1062. g_error_free (err);
  1063. err = NULL;
  1064. }
  1065. else {
  1066. msg_info_task ("cannot parse DKIM signature: "
  1067. "unknown error");
  1068. }
  1069. continue;
  1070. }
  1071. else {
  1072. /* Get key */
  1073. cur->ctx = ctx;
  1074. if (dkim_module_ctx->trusted_only &&
  1075. (dkim_module_ctx->dkim_domains == NULL ||
  1076. rspamd_match_hash_map (dkim_module_ctx->dkim_domains,
  1077. rspamd_dkim_get_domain (ctx)) == NULL)) {
  1078. msg_debug_task ("skip dkim check for %s domain",
  1079. rspamd_dkim_get_domain (ctx));
  1080. continue;
  1081. }
  1082. if (dkim_module_ctx->dkim_hash) {
  1083. key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash,
  1084. rspamd_dkim_get_dns_key (ctx),
  1085. task->task_timestamp);
  1086. }
  1087. else {
  1088. key = NULL;
  1089. }
  1090. if (key != NULL) {
  1091. cur->key = rspamd_dkim_key_ref (key);
  1092. /* Release key when task is processed */
  1093. rspamd_mempool_add_destructor (task->task_pool,
  1094. dkim_module_key_dtor, cur->key);
  1095. }
  1096. else {
  1097. if (!rspamd_get_dkim_key (ctx,
  1098. task,
  1099. dkim_module_key_handler,
  1100. cur)) {
  1101. continue;
  1102. }
  1103. }
  1104. }
  1105. checked ++;
  1106. if (checked > dkim_module_ctx->max_sigs) {
  1107. msg_info_task ("message has multiple signatures but we"
  1108. " stopped after %d checked signatures as limit"
  1109. " is reached", checked);
  1110. break;
  1111. }
  1112. }
  1113. }
  1114. else {
  1115. rspamd_task_insert_result (task,
  1116. dkim_module_ctx->symbol_na,
  1117. 1.0,
  1118. NULL);
  1119. }
  1120. if (res != NULL) {
  1121. dkim_module_check (res);
  1122. }
  1123. rspamd_symcache_item_async_dec_check (task, item, M);
  1124. }
  1125. struct rspamd_dkim_lua_verify_cbdata {
  1126. rspamd_dkim_context_t *ctx;
  1127. struct rspamd_task *task;
  1128. lua_State *L;
  1129. rspamd_dkim_key_t *key;
  1130. gint cbref;
  1131. };
  1132. static void
  1133. dkim_module_lua_push_verify_result (struct rspamd_dkim_lua_verify_cbdata *cbd,
  1134. struct rspamd_dkim_check_result *res, GError *err)
  1135. {
  1136. struct rspamd_task **ptask, *task;
  1137. const gchar *error_str = "unknown error";
  1138. gboolean success = FALSE;
  1139. task = cbd->task;
  1140. switch (res->rcode) {
  1141. case DKIM_CONTINUE:
  1142. error_str = NULL;
  1143. success = TRUE;
  1144. break;
  1145. case DKIM_REJECT:
  1146. if (err) {
  1147. error_str = err->message;
  1148. }
  1149. else {
  1150. error_str = "reject";
  1151. }
  1152. break;
  1153. case DKIM_TRYAGAIN:
  1154. if (err) {
  1155. error_str = err->message;
  1156. }
  1157. else {
  1158. error_str = "tempfail";
  1159. }
  1160. break;
  1161. case DKIM_NOTFOUND:
  1162. if (err) {
  1163. error_str = err->message;
  1164. }
  1165. else {
  1166. error_str = "not found";
  1167. }
  1168. break;
  1169. case DKIM_RECORD_ERROR:
  1170. if (err) {
  1171. error_str = err->message;
  1172. }
  1173. else {
  1174. error_str = "bad record";
  1175. }
  1176. break;
  1177. case DKIM_PERM_ERROR:
  1178. if (err) {
  1179. error_str = err->message;
  1180. }
  1181. else {
  1182. error_str = "permanent error";
  1183. }
  1184. break;
  1185. default:
  1186. break;
  1187. }
  1188. lua_rawgeti (cbd->L, LUA_REGISTRYINDEX, cbd->cbref);
  1189. ptask = lua_newuserdata (cbd->L, sizeof (*ptask));
  1190. *ptask = task;
  1191. lua_pushboolean (cbd->L, success);
  1192. if (error_str) {
  1193. lua_pushstring (cbd->L, error_str);
  1194. }
  1195. else {
  1196. lua_pushnil (cbd->L);
  1197. }
  1198. if (cbd->ctx) {
  1199. if (res->domain) {
  1200. lua_pushstring (cbd->L, res->domain);
  1201. }
  1202. else {
  1203. lua_pushnil (cbd->L);
  1204. }
  1205. if (res->selector) {
  1206. lua_pushstring (cbd->L, res->selector);
  1207. }
  1208. else {
  1209. lua_pushnil (cbd->L);
  1210. }
  1211. if (res->short_b) {
  1212. lua_pushstring (cbd->L, res->short_b);
  1213. }
  1214. else {
  1215. lua_pushnil (cbd->L);
  1216. }
  1217. if (res->fail_reason) {
  1218. lua_pushstring (cbd->L, res->fail_reason);
  1219. }
  1220. else {
  1221. lua_pushnil (cbd->L);
  1222. }
  1223. }
  1224. else {
  1225. lua_pushnil (cbd->L);
  1226. lua_pushnil (cbd->L);
  1227. lua_pushnil (cbd->L);
  1228. lua_pushnil (cbd->L);
  1229. }
  1230. if (lua_pcall (cbd->L, 7, 0, 0) != 0) {
  1231. msg_err_task ("call to verify callback failed: %s",
  1232. lua_tostring (cbd->L, -1));
  1233. lua_pop (cbd->L, 1);
  1234. }
  1235. luaL_unref (cbd->L, LUA_REGISTRYINDEX, cbd->cbref);
  1236. }
  1237. static void
  1238. dkim_module_lua_on_key (rspamd_dkim_key_t *key,
  1239. gsize keylen,
  1240. rspamd_dkim_context_t *ctx,
  1241. gpointer ud,
  1242. GError *err)
  1243. {
  1244. struct rspamd_dkim_lua_verify_cbdata *cbd = ud;
  1245. struct rspamd_task *task;
  1246. struct rspamd_dkim_check_result *res;
  1247. struct dkim_ctx *dkim_module_ctx;
  1248. task = cbd->task;
  1249. dkim_module_ctx = dkim_get_context (task->cfg);
  1250. if (key != NULL) {
  1251. /* Another ref belongs to the check context */
  1252. cbd->key = rspamd_dkim_key_ref (key);
  1253. /*
  1254. * We actually receive key with refcount = 1, so we just assume that
  1255. * lru hash owns this object now
  1256. */
  1257. if (dkim_module_ctx->dkim_hash) {
  1258. rspamd_lru_hash_insert (dkim_module_ctx->dkim_hash,
  1259. g_strdup (rspamd_dkim_get_dns_key (ctx)),
  1260. key, cbd->task->task_timestamp, rspamd_dkim_key_get_ttl (key));
  1261. }
  1262. /* Release key when task is processed */
  1263. rspamd_mempool_add_destructor (cbd->task->task_pool,
  1264. dkim_module_key_dtor, cbd->key);
  1265. }
  1266. else {
  1267. /* Insert tempfail symbol */
  1268. msg_info_task ("cannot get key for domain %s: %e",
  1269. rspamd_dkim_get_dns_key (ctx), err);
  1270. if (err != NULL) {
  1271. if (err->code == DKIM_SIGERROR_NOKEY) {
  1272. res = rspamd_dkim_create_result (ctx, DKIM_TRYAGAIN, task);
  1273. res->fail_reason = "DNS error when getting key";
  1274. }
  1275. else {
  1276. res = rspamd_dkim_create_result (ctx, DKIM_PERM_ERROR, task);
  1277. res->fail_reason = "invalid DKIM record";
  1278. }
  1279. }
  1280. else {
  1281. res = rspamd_dkim_create_result (ctx, DKIM_TRYAGAIN, task);
  1282. res->fail_reason = "DNS error when getting key";
  1283. }
  1284. dkim_module_lua_push_verify_result (cbd, res, err);
  1285. if (err) {
  1286. g_error_free (err);
  1287. }
  1288. return;
  1289. }
  1290. res = rspamd_dkim_check (cbd->ctx, cbd->key, cbd->task);
  1291. dkim_module_lua_push_verify_result (cbd, res, NULL);
  1292. }
  1293. static gint
  1294. lua_dkim_verify_handler (lua_State *L)
  1295. {
  1296. struct rspamd_task *task = lua_check_task (L, 1);
  1297. const gchar *sig = luaL_checkstring (L, 2);
  1298. rspamd_dkim_context_t *ctx;
  1299. struct rspamd_dkim_lua_verify_cbdata *cbd;
  1300. rspamd_dkim_key_t *key;
  1301. struct rspamd_dkim_check_result *ret;
  1302. GError *err = NULL;
  1303. const gchar *type_str = NULL;
  1304. enum rspamd_dkim_type type = RSPAMD_DKIM_NORMAL;
  1305. struct dkim_ctx *dkim_module_ctx;
  1306. if (task && sig && lua_isfunction (L, 3)) {
  1307. if (lua_isstring (L, 4)) {
  1308. type_str = lua_tostring (L, 4);
  1309. if (type_str) {
  1310. if (strcmp (type_str, "dkim") == 0) {
  1311. type = RSPAMD_DKIM_NORMAL;
  1312. }
  1313. else if (strcmp (type_str, "arc-sign") == 0) {
  1314. type = RSPAMD_DKIM_ARC_SIG;
  1315. }
  1316. else if (strcmp (type_str, "arc-seal") == 0) {
  1317. type = RSPAMD_DKIM_ARC_SEAL;
  1318. }
  1319. else {
  1320. lua_settop (L, 0);
  1321. return luaL_error (L, "unknown sign type: %s",
  1322. type_str);
  1323. }
  1324. }
  1325. }
  1326. dkim_module_ctx = dkim_get_context (task->cfg);
  1327. ctx = rspamd_create_dkim_context (sig,
  1328. task->task_pool,
  1329. dkim_module_ctx->time_jitter,
  1330. type,
  1331. &err);
  1332. if (ctx == NULL) {
  1333. lua_pushboolean (L, false);
  1334. if (err) {
  1335. lua_pushstring (L, err->message);
  1336. g_error_free (err);
  1337. }
  1338. else {
  1339. lua_pushstring (L, "unknown error");
  1340. }
  1341. return 2;
  1342. }
  1343. cbd = rspamd_mempool_alloc (task->task_pool, sizeof (*cbd));
  1344. cbd->L = L;
  1345. cbd->task = task;
  1346. lua_pushvalue (L, 3);
  1347. cbd->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
  1348. cbd->ctx = ctx;
  1349. cbd->key = NULL;
  1350. if (dkim_module_ctx->dkim_hash) {
  1351. key = rspamd_lru_hash_lookup (dkim_module_ctx->dkim_hash,
  1352. rspamd_dkim_get_dns_key (ctx),
  1353. task->task_timestamp);
  1354. }
  1355. else {
  1356. key = NULL;
  1357. }
  1358. if (key != NULL) {
  1359. cbd->key = rspamd_dkim_key_ref (key);
  1360. /* Release key when task is processed */
  1361. rspamd_mempool_add_destructor (task->task_pool,
  1362. dkim_module_key_dtor, cbd->key);
  1363. ret = rspamd_dkim_check (cbd->ctx, cbd->key, cbd->task);
  1364. dkim_module_lua_push_verify_result (cbd, ret, NULL);
  1365. }
  1366. else {
  1367. rspamd_get_dkim_key (ctx,
  1368. task,
  1369. dkim_module_lua_on_key,
  1370. cbd);
  1371. }
  1372. }
  1373. else {
  1374. return luaL_error (L, "invalid arguments");
  1375. }
  1376. lua_pushboolean (L, TRUE);
  1377. lua_pushnil (L);
  1378. return 2;
  1379. }
  1380. static gint
  1381. lua_dkim_canonicalize_handler (lua_State *L)
  1382. {
  1383. gsize nlen, vlen;
  1384. const gchar *hname = luaL_checklstring (L, 1, &nlen),
  1385. *hvalue = luaL_checklstring (L, 2, &vlen);
  1386. static gchar st_buf[8192];
  1387. gchar *buf;
  1388. guint inlen;
  1389. gboolean allocated = FALSE;
  1390. goffset r;
  1391. if (hname && hvalue && nlen > 0) {
  1392. inlen = nlen + vlen + sizeof (":" CRLF);
  1393. if (inlen > sizeof (st_buf)) {
  1394. buf = g_malloc (inlen);
  1395. allocated = TRUE;
  1396. }
  1397. else {
  1398. /* Faster */
  1399. buf = st_buf;
  1400. }
  1401. r = rspamd_dkim_canonize_header_relaxed_str (hname, hvalue, buf, inlen);
  1402. if (r == -1) {
  1403. lua_pushnil (L);
  1404. }
  1405. else {
  1406. lua_pushlstring (L, buf, r);
  1407. }
  1408. if (allocated) {
  1409. g_free (buf);
  1410. }
  1411. }
  1412. else {
  1413. return luaL_error (L, "invalid arguments");
  1414. }
  1415. return 1;
  1416. }