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.h 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. #ifndef DKIM_H_
  17. #define DKIM_H_
  18. #include "config.h"
  19. #include "contrib/libev/ev.h"
  20. #include "dns.h"
  21. #include "ref.h"
  22. /* Main types and definitions */
  23. #define RSPAMD_DKIM_SIGNHEADER "DKIM-Signature"
  24. #define RSPAMD_DKIM_ARC_SIGNHEADER "ARC-Message-Signature"
  25. #define RSPAMD_DKIM_ARC_AUTHHEADER "ARC-Authentication-Results"
  26. #define RSPAMD_DKIM_ARC_SEALHEADER "ARC-Seal"
  27. /* DKIM signature header */
  28. /* Errors (from OpenDKIM) */
  29. #define DKIM_SIGERROR_UNKNOWN (-1) /* unknown error */
  30. #define DKIM_SIGERROR_OK 0 /* no error */
  31. #define DKIM_SIGERROR_VERSION 1 /* unsupported version */
  32. #define DKIM_SIGERROR_DOMAIN 2 /* invalid domain (d=/i=) */
  33. #define DKIM_SIGERROR_EXPIRED 3 /* signature expired */
  34. #define DKIM_SIGERROR_FUTURE 4 /* signature in the future */
  35. #define DKIM_SIGERROR_TIMESTAMPS 5 /* x= < t= */
  36. #define DKIM_SIGERROR_NOREC 6 /* No record */
  37. #define DKIM_SIGERROR_INVALID_HC 7 /* c= invalid (header) */
  38. #define DKIM_SIGERROR_INVALID_BC 8 /* c= invalid (body) */
  39. #define DKIM_SIGERROR_MISSING_A 9 /* a= missing */
  40. #define DKIM_SIGERROR_INVALID_A 10 /* a= invalid */
  41. #define DKIM_SIGERROR_MISSING_H 11 /* h= missing */
  42. #define DKIM_SIGERROR_INVALID_L 12 /* l= invalid */
  43. #define DKIM_SIGERROR_INVALID_Q 13 /* q= invalid */
  44. #define DKIM_SIGERROR_INVALID_QO 14 /* q= option invalid */
  45. #define DKIM_SIGERROR_MISSING_D 15 /* d= missing */
  46. #define DKIM_SIGERROR_EMPTY_D 16 /* d= empty */
  47. #define DKIM_SIGERROR_MISSING_S 17 /* s= missing */
  48. #define DKIM_SIGERROR_EMPTY_S 18 /* s= empty */
  49. #define DKIM_SIGERROR_MISSING_B 19 /* b= missing */
  50. #define DKIM_SIGERROR_EMPTY_B 20 /* b= empty */
  51. #define DKIM_SIGERROR_CORRUPT_B 21 /* b= corrupt */
  52. #define DKIM_SIGERROR_NOKEY 22 /* no key found in DNS */
  53. #define DKIM_SIGERROR_DNSSYNTAX 23 /* DNS reply corrupt */
  54. #define DKIM_SIGERROR_KEYFAIL 24 /* DNS query failed */
  55. #define DKIM_SIGERROR_MISSING_BH 25 /* bh= missing */
  56. #define DKIM_SIGERROR_EMPTY_BH 26 /* bh= empty */
  57. #define DKIM_SIGERROR_CORRUPT_BH 27 /* bh= corrupt */
  58. #define DKIM_SIGERROR_BADSIG 28 /* signature mismatch */
  59. #define DKIM_SIGERROR_SUBDOMAIN 29 /* unauthorized subdomain */
  60. #define DKIM_SIGERROR_MULTIREPLY 30 /* multiple records returned */
  61. #define DKIM_SIGERROR_EMPTY_H 31 /* h= empty */
  62. #define DKIM_SIGERROR_INVALID_H 32 /* h= missing req'd entries */
  63. #define DKIM_SIGERROR_TOOLARGE_L 33 /* l= value exceeds body size */
  64. #define DKIM_SIGERROR_MBSFAILED 34 /* "must be signed" failure */
  65. #define DKIM_SIGERROR_KEYVERSION 35 /* unknown key version */
  66. #define DKIM_SIGERROR_KEYUNKNOWNHASH 36 /* unknown key hash */
  67. #define DKIM_SIGERROR_KEYHASHMISMATCH 37 /* sig-key hash mismatch */
  68. #define DKIM_SIGERROR_NOTEMAILKEY 38 /* not an e-mail key */
  69. #define DKIM_SIGERROR_UNUSED2 39 /* OBSOLETE */
  70. #define DKIM_SIGERROR_KEYTYPEMISSING 40 /* key type missing */
  71. #define DKIM_SIGERROR_KEYTYPEUNKNOWN 41 /* key type unknown */
  72. #define DKIM_SIGERROR_KEYREVOKED 42 /* key revoked */
  73. #define DKIM_SIGERROR_KEYDECODE 43 /* key couldn't be decoded */
  74. #define DKIM_SIGERROR_MISSING_V 44 /* v= tag missing */
  75. #define DKIM_SIGERROR_EMPTY_V 45 /* v= tag empty */
  76. #ifdef __cplusplus
  77. extern "C" {
  78. #endif
  79. /* Check results */
  80. enum rspamd_dkim_check_rcode {
  81. DKIM_CONTINUE = 0,
  82. DKIM_REJECT,
  83. DKIM_TRYAGAIN,
  84. DKIM_NOTFOUND,
  85. DKIM_RECORD_ERROR,
  86. DKIM_PERM_ERROR,
  87. };
  88. #define DKIM_CANON_SIMPLE 0 /* as specified in DKIM spec */
  89. #define DKIM_CANON_RELAXED 1 /* as specified in DKIM spec */
  90. struct rspamd_dkim_context_s;
  91. typedef struct rspamd_dkim_context_s rspamd_dkim_context_t;
  92. struct rspamd_dkim_sign_context_s;
  93. typedef struct rspamd_dkim_sign_context_s rspamd_dkim_sign_context_t;
  94. struct rspamd_dkim_key_s;
  95. typedef struct rspamd_dkim_key_s rspamd_dkim_key_t;
  96. typedef struct rspamd_dkim_key_s rspamd_dkim_sign_key_t;
  97. struct rspamd_task;
  98. enum rspamd_dkim_key_format {
  99. RSPAMD_DKIM_KEY_FILE = 0,
  100. RSPAMD_DKIM_KEY_PEM,
  101. RSPAMD_DKIM_KEY_BASE64,
  102. RSPAMD_DKIM_KEY_RAW,
  103. RSPAMD_DKIM_KEY_UNKNOWN
  104. };
  105. enum rspamd_dkim_type {
  106. RSPAMD_DKIM_NORMAL,
  107. RSPAMD_DKIM_ARC_SIG,
  108. RSPAMD_DKIM_ARC_SEAL
  109. };
  110. /* Signature methods */
  111. enum rspamd_sign_type {
  112. DKIM_SIGN_UNKNOWN = -2,
  113. DKIM_SIGN_RSASHA1 = 0,
  114. DKIM_SIGN_RSASHA256,
  115. DKIM_SIGN_RSASHA512,
  116. DKIM_SIGN_ECDSASHA256,
  117. DKIM_SIGN_ECDSASHA512,
  118. DKIM_SIGN_EDDSASHA256,
  119. };
  120. enum rspamd_dkim_key_type {
  121. RSPAMD_DKIM_KEY_RSA = 0,
  122. RSPAMD_DKIM_KEY_ECDSA,
  123. RSPAMD_DKIM_KEY_EDDSA
  124. };
  125. struct rspamd_dkim_check_result {
  126. enum rspamd_dkim_check_rcode rcode;
  127. rspamd_dkim_context_t *ctx;
  128. /* Processed parts */
  129. const gchar *selector;
  130. const gchar *domain;
  131. const gchar *short_b;
  132. const gchar *fail_reason;
  133. };
  134. /* Err MUST be freed if it is not NULL, key is allocated by slice allocator */
  135. typedef void (*dkim_key_handler_f) (rspamd_dkim_key_t *key, gsize keylen,
  136. rspamd_dkim_context_t *ctx, gpointer ud, GError *err);
  137. /**
  138. * Create new dkim context from signature
  139. * @param sig message's signature
  140. * @param pool pool to allocate memory from
  141. * @param time_jitter jitter in seconds to allow time diff while checking
  142. * @param err pointer to error object
  143. * @return new context or NULL
  144. */
  145. rspamd_dkim_context_t *rspamd_create_dkim_context (const gchar *sig,
  146. rspamd_mempool_t *pool,
  147. struct rspamd_dns_resolver *resolver,
  148. guint time_jitter,
  149. enum rspamd_dkim_type type,
  150. GError **err);
  151. /**
  152. * Create new dkim context for making a signature
  153. * @param task
  154. * @param priv_key
  155. * @param err
  156. * @return
  157. */
  158. rspamd_dkim_sign_context_t *rspamd_create_dkim_sign_context (struct rspamd_task *task,
  159. rspamd_dkim_sign_key_t *priv_key,
  160. gint headers_canon,
  161. gint body_canon,
  162. const gchar *dkim_headers,
  163. enum rspamd_dkim_type type,
  164. GError **err);
  165. /**
  166. * Load dkim key
  167. * @param path
  168. * @param err
  169. * @return
  170. */
  171. rspamd_dkim_sign_key_t *rspamd_dkim_sign_key_load (const gchar *what, gsize len,
  172. enum rspamd_dkim_key_format type,
  173. GError **err);
  174. /**
  175. * Invalidate modified sign key
  176. * @param key
  177. * @return
  178. */
  179. gboolean rspamd_dkim_sign_key_maybe_invalidate (rspamd_dkim_sign_key_t *key,
  180. time_t mtime);
  181. /**
  182. * Make DNS request for specified context and obtain and parse key
  183. * @param ctx dkim context from signature
  184. * @param resolver dns resolver object
  185. * @param s async session to make request
  186. * @return
  187. */
  188. gboolean rspamd_get_dkim_key (rspamd_dkim_context_t *ctx,
  189. struct rspamd_task *task,
  190. dkim_key_handler_f handler,
  191. gpointer ud);
  192. /**
  193. * Check task for dkim context using dkim key
  194. * @param ctx dkim verify context
  195. * @param key dkim key (from cache or from dns request)
  196. * @param task task to check
  197. * @return
  198. */
  199. struct rspamd_dkim_check_result *rspamd_dkim_check (rspamd_dkim_context_t *ctx,
  200. rspamd_dkim_key_t *key,
  201. struct rspamd_task *task);
  202. struct rspamd_dkim_check_result *
  203. rspamd_dkim_create_result (rspamd_dkim_context_t *ctx,
  204. enum rspamd_dkim_check_rcode rcode,
  205. struct rspamd_task *task);
  206. GString *rspamd_dkim_sign (struct rspamd_task *task,
  207. const gchar *selector,
  208. const gchar *domain,
  209. time_t expire,
  210. gsize len,
  211. guint idx,
  212. const gchar *arc_cv,
  213. rspamd_dkim_sign_context_t *ctx);
  214. rspamd_dkim_key_t *rspamd_dkim_key_ref (rspamd_dkim_key_t *k);
  215. void rspamd_dkim_key_unref (rspamd_dkim_key_t *k);
  216. rspamd_dkim_sign_key_t *rspamd_dkim_sign_key_ref (rspamd_dkim_sign_key_t *k);
  217. void rspamd_dkim_sign_key_unref (rspamd_dkim_sign_key_t *k);
  218. const gchar *rspamd_dkim_get_domain (rspamd_dkim_context_t *ctx);
  219. const gchar *rspamd_dkim_get_selector (rspamd_dkim_context_t *ctx);
  220. const gchar *rspamd_dkim_get_dns_key (rspamd_dkim_context_t *ctx);
  221. guint rspamd_dkim_key_get_ttl (rspamd_dkim_key_t *k);
  222. /**
  223. * Create DKIM public key from a raw data
  224. * @param keydata
  225. * @param keylen
  226. * @param type
  227. * @param err
  228. * @return
  229. */
  230. rspamd_dkim_key_t *rspamd_dkim_make_key (const gchar *keydata, guint keylen,
  231. enum rspamd_dkim_key_type type,
  232. GError **err);
  233. #define RSPAMD_DKIM_KEY_ID_LEN 16
  234. /**
  235. * Returns key id for dkim key (raw md5 of RSPAMD_DKIM_KEY_ID_LEN)
  236. * NOT ZERO TERMINATED, use RSPAMD_DKIM_KEY_ID_LEN for length
  237. * @param key
  238. * @return
  239. */
  240. const guchar *rspamd_dkim_key_id (rspamd_dkim_key_t *key);
  241. /**
  242. * Parse DKIM public key from a TXT record
  243. * @param txt
  244. * @param keylen
  245. * @param err
  246. * @return
  247. */
  248. rspamd_dkim_key_t *rspamd_dkim_parse_key (const gchar *txt, gsize *keylen,
  249. GError **err);
  250. /**
  251. * Canonocalise header using relaxed algorithm
  252. * @param hname
  253. * @param hvalue
  254. * @param out
  255. * @param outlen
  256. * @return
  257. */
  258. goffset rspamd_dkim_canonize_header_relaxed_str (const gchar *hname,
  259. const gchar *hvalue,
  260. gchar *out,
  261. gsize outlen);
  262. /**
  263. * Checks public and private keys for match
  264. * @param pk
  265. * @param sk
  266. * @param err
  267. * @return
  268. */
  269. gboolean rspamd_dkim_match_keys (rspamd_dkim_key_t *pk,
  270. rspamd_dkim_sign_key_t *sk,
  271. GError **err);
  272. /**
  273. * Free DKIM key
  274. * @param key
  275. */
  276. void rspamd_dkim_key_free (rspamd_dkim_key_t *key);
  277. #ifdef __cplusplus
  278. }
  279. #endif
  280. #endif /* DKIM_H_ */