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