1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
/* Copyright (c) 2010-2011, Vsevolod Stakhov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DKIM_H_
#define DKIM_H_
#include "config.h"
#include "event.h"
#include "dns.h"
#ifdef HAVE_OPENSSL
#include <openssl/rsa.h>
#include <openssl/engine.h>
#endif
/* Main types and definitions */
#define DKIM_SIGNHEADER "DKIM-Signature"
/* DKIM signature header */
/* special DNS tokens */
#define DKIM_DNSKEYNAME "_domainkey"
/* reserved DNS sub-zone */
#define DKIM_DNSPOLICYNAME "_adsp" /* reserved DNS sub-zone */
/* Canonization methods */
#define DKIM_CANON_UNKNOWN (-1) /* unknown method */
#define DKIM_CANON_SIMPLE 0 /* as specified in DKIM spec */
#define DKIM_CANON_RELAXED 1 /* as specified in DKIM spec */
#define DKIM_CANON_DEFAULT DKIM_CANON_SIMPLE
/* Signature methods */
#define DKIM_SIGN_UNKNOWN (-2) /* unknown method */
#define DKIM_SIGN_DEFAULT (-1) /* use internal default */
#define DKIM_SIGN_RSASHA1 0 /* an RSA-signed SHA1 digest */
#define DKIM_SIGN_RSASHA256 1 /* an RSA-signed SHA256 digest */
/* Params */
#define DKIM_PARAM_UNKNOWN (-1) /* unknown */
#define DKIM_PARAM_SIGNATURE 0 /* b */
#define DKIM_PARAM_SIGNALG 1 /* a */
#define DKIM_PARAM_DOMAIN 2 /* d */
#define DKIM_PARAM_CANONALG 3 /* c */
#define DKIM_PARAM_QUERYMETHOD 4 /* q */
#define DKIM_PARAM_SELECTOR 5 /* s */
#define DKIM_PARAM_HDRLIST 6 /* h */
#define DKIM_PARAM_VERSION 7 /* v */
#define DKIM_PARAM_IDENTITY 8 /* i */
#define DKIM_PARAM_TIMESTAMP 9 /* t */
#define DKIM_PARAM_EXPIRATION 10 /* x */
#define DKIM_PARAM_COPIEDHDRS 11 /* z */
#define DKIM_PARAM_BODYHASH 12 /* bh */
#define DKIM_PARAM_BODYLENGTH 13 /* l */
/* Errors (from OpenDKIM) */
#define DKIM_SIGERROR_UNKNOWN (-1) /* unknown error */
#define DKIM_SIGERROR_OK 0 /* no error */
#define DKIM_SIGERROR_VERSION 1 /* unsupported version */
#define DKIM_SIGERROR_DOMAIN 2 /* invalid domain (d=/i=) */
#define DKIM_SIGERROR_EXPIRED 3 /* signature expired */
#define DKIM_SIGERROR_FUTURE 4 /* signature in the future */
#define DKIM_SIGERROR_TIMESTAMPS 5 /* x= < t= */
#define DKIM_SIGERROR_UNUSED 6 /* OBSOLETE */
#define DKIM_SIGERROR_INVALID_HC 7 /* c= invalid (header) */
#define DKIM_SIGERROR_INVALID_BC 8 /* c= invalid (body) */
#define DKIM_SIGERROR_MISSING_A 9 /* a= missing */
#define DKIM_SIGERROR_INVALID_A 10 /* a= invalid */
#define DKIM_SIGERROR_MISSING_H 11 /* h= missing */
#define DKIM_SIGERROR_INVALID_L 12 /* l= invalid */
#define DKIM_SIGERROR_INVALID_Q 13 /* q= invalid */
#define DKIM_SIGERROR_INVALID_QO 14 /* q= option invalid */
#define DKIM_SIGERROR_MISSING_D 15 /* d= missing */
#define DKIM_SIGERROR_EMPTY_D 16 /* d= empty */
#define DKIM_SIGERROR_MISSING_S 17 /* s= missing */
#define DKIM_SIGERROR_EMPTY_S 18 /* s= empty */
#define DKIM_SIGERROR_MISSING_B 19 /* b= missing */
#define DKIM_SIGERROR_EMPTY_B 20 /* b= empty */
#define DKIM_SIGERROR_CORRUPT_B 21 /* b= corrupt */
#define DKIM_SIGERROR_NOKEY 22 /* no key found in DNS */
#define DKIM_SIGERROR_DNSSYNTAX 23 /* DNS reply corrupt */
#define DKIM_SIGERROR_KEYFAIL 24 /* DNS query failed */
#define DKIM_SIGERROR_MISSING_BH 25 /* bh= missing */
#define DKIM_SIGERROR_EMPTY_BH 26 /* bh= empty */
#define DKIM_SIGERROR_CORRUPT_BH 27 /* bh= corrupt */
#define DKIM_SIGERROR_BADSIG 28 /* signature mismatch */
#define DKIM_SIGERROR_SUBDOMAIN 29 /* unauthorized subdomain */
#define DKIM_SIGERROR_MULTIREPLY 30 /* multiple records returned */
#define DKIM_SIGERROR_EMPTY_H 31 /* h= empty */
#define DKIM_SIGERROR_INVALID_H 32 /* h= missing req'd entries */
#define DKIM_SIGERROR_TOOLARGE_L 33 /* l= value exceeds body size */
#define DKIM_SIGERROR_MBSFAILED 34 /* "must be signed" failure */
#define DKIM_SIGERROR_KEYVERSION 35 /* unknown key version */
#define DKIM_SIGERROR_KEYUNKNOWNHASH 36 /* unknown key hash */
#define DKIM_SIGERROR_KEYHASHMISMATCH 37 /* sig-key hash mismatch */
#define DKIM_SIGERROR_NOTEMAILKEY 38 /* not an e-mail key */
#define DKIM_SIGERROR_UNUSED2 39 /* OBSOLETE */
#define DKIM_SIGERROR_KEYTYPEMISSING 40 /* key type missing */
#define DKIM_SIGERROR_KEYTYPEUNKNOWN 41 /* key type unknown */
#define DKIM_SIGERROR_KEYREVOKED 42 /* key revoked */
#define DKIM_SIGERROR_KEYDECODE 43 /* key couldn't be decoded */
#define DKIM_SIGERROR_MISSING_V 44 /* v= tag missing */
#define DKIM_SIGERROR_EMPTY_V 45 /* v= tag empty */
/* Check results */
#define DKIM_CONTINUE 0 /* continue */
#define DKIM_REJECT 1 /* reject */
#define DKIM_TRYAGAIN 2 /* try again later */
#define DKIM_NOTFOUND 3 /* requested record not found */
#define DKIM_RECORD_ERROR 4 /* error requesting record */
typedef struct rspamd_dkim_context_s {
rspamd_mempool_t *pool;
gint sig_alg;
gint header_canon_type;
gint body_canon_type;
gsize len;
gchar *domain;
gchar *selector;
time_t timestamp;
time_t expiration;
gint8 *b;
gint8 *bh;
guint bhlen;
guint blen;
GPtrArray *hlist;
guint ver;
gchar *dns_key;
GChecksum *headers_hash;
GChecksum *body_hash;
} rspamd_dkim_context_t;
typedef struct rspamd_dkim_key_s {
guint8 *keydata;
guint keylen;
gsize decoded_len;
guint ttl;
#ifdef HAVE_OPENSSL
RSA *key_rsa;
BIO *key_bio;
EVP_PKEY *key_evp;
#endif
}
rspamd_dkim_key_t;
struct rspamd_task;
/* Err MUST be freed if it is not NULL, key is allocated by slice allocator */
typedef void (*dkim_key_handler_f)(rspamd_dkim_key_t *key, gsize keylen,
rspamd_dkim_context_t *ctx, gpointer ud, GError *err);
/**
* Create new dkim context from signature
* @param sig message's signature
* @param pool pool to allocate memory from
* @param time_jitter jitter in seconds to allow time diff while checking
* @param err pointer to error object
* @return new context or NULL
*/
rspamd_dkim_context_t * rspamd_create_dkim_context (const gchar *sig,
rspamd_mempool_t *pool,
guint time_jitter,
GError **err);
/**
* Make DNS request for specified context and obtain and parse key
* @param ctx dkim context from signature
* @param resolver dns resolver object
* @param s async session to make request
* @return
*/
gboolean rspamd_get_dkim_key (rspamd_dkim_context_t *ctx,
struct rspamd_dns_resolver *resolver,
struct rspamd_async_session *s,
dkim_key_handler_f handler,
gpointer ud);
/**
* Check task for dkim context using dkim key
* @param ctx dkim verify context
* @param key dkim key (from cache or from dns request)
* @param task task to check
* @return
*/
gint rspamd_dkim_check (rspamd_dkim_context_t *ctx,
rspamd_dkim_key_t *key,
struct rspamd_task *task);
/**
* Free DKIM key
* @param key
*/
void rspamd_dkim_key_free (rspamd_dkim_key_t *key);
#endif /* DKIM_H_ */
|