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 8.1KB

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