1 /* $Cambridge: exim/src/src/pdkim/pdkim.h,v 1.1.2.5 2009/03/17 12:57:37 tom Exp $ */
9 #define PDKIM_SIGNATURE_VERSION "1"
10 #define PDKIM_PUB_RECORD_VERSION "DKIM1"
12 #define PDKIM_MAX_HEADER_LEN 65536
13 #define PDKIM_MAX_HEADERS 512
14 #define PDKIM_MAX_BODY_LINE_LEN 1024
15 #define PDKIM_DNS_TXT_MAX_NAMELEN 1024
16 #define PDKIM_DNS_TXT_MAX_RECLEN 4096
18 #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
19 "Message-ID:To:Cc:MIME-Version:Content-Type:"\
20 "Content-Transfer-Encoding:Content-ID:"\
21 "Content-Description:Resent-Date:Resent-From:"\
22 "Resent-Sender:Resent-To:Resent-Cc:"\
23 "Resent-Message-ID:In-Reply-To:References:"\
24 "List-Id:List-Help:List-Unsubscribe:"\
25 "List-Subscribe:List-Post:List-Owner:List-Archive"
28 /* Function success / error codes */
31 #define PDKIM_ERR_OOM -100
32 #define PDKIM_ERR_RSA_PRIVKEY -101
33 #define PDKIM_ERR_RSA_SIGNING -102
34 #define PDKIM_ERR_LONG_LINE -103
35 #define PDKIM_ERR_BUFFER_TOO_SMALL -104
37 /* Main verification status */
38 #define PDKIM_VERIFY_NONE 0
39 #define PDKIM_VERIFY_INVALID 1
40 #define PDKIM_VERIFY_FAIL 2
41 #define PDKIM_VERIFY_PASS 3
43 /* Extended verification status */
44 #define PDKIM_VERIFY_FAIL_BODY 1
45 #define PDKIM_VERIFY_FAIL_MESSAGE 2
47 #define PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE 3
48 #define PDKIM_VERIFY_INVALID_BUFFER_SIZE 4
49 #define PDKIM_VERIFY_INVALID_PUBKEY_PARSING 5
53 void pdkim_quoteprint(FILE *, char *, int, int);
56 typedef struct pdkim_stringlist {
60 pdkim_stringlist *pdkim_append_stringlist(pdkim_stringlist *, char *);
63 #define PDKIM_STR_ALLOC_FRAG 256
64 typedef struct pdkim_str {
67 unsigned int allocated;
69 pdkim_str *pdkim_strnew (char *);
70 char *pdkim_strcat (pdkim_str *, char *);
71 char *pdkim_strncat(pdkim_str *, char *, int);
72 void pdkim_strfree(pdkim_str *);
74 #define PDKIM_QUERYMETHOD_DNS_TXT 0
76 #define PDKIM_ALGO_RSA_SHA256 0
77 #define PDKIM_ALGO_RSA_SHA1 1
79 #define PDKIM_CANON_SIMPLE 0
80 #define PDKIM_CANON_RELAXED 1
82 #define PDKIM_HASH_SHA256 0
83 #define PDKIM_HASH_SHA1 1
85 #define PDKIM_KEYTYPE_RSA 0
88 /* -------------------------------------------------------------------------- */
89 /* Public key as (usually) fetched from DNS */
90 typedef struct pdkim_pubkey {
91 char *version; /* v= */
92 char *granularity; /* g= */
94 char *hashes; /* h= */
95 char *keytype; /* k= */
96 char *srvtype; /* s= */
102 int testing; /* t=y */
103 int no_subdomaining; /* t=s */
106 /* -------------------------------------------------------------------------- */
107 /* Signature as it appears in a DKIM-Signature header */
108 typedef struct pdkim_signature {
110 /* Bits stored in a DKIM signature header --------------------------- */
112 /* (v=) The version, as an integer. Currently, always "1" */
115 /* (a=) The signature algorithm. Either PDKIM_ALGO_RSA_SHA256
116 or PDKIM_ALGO_RSA_SHA1 */
119 /* (c=x/) Header canonicalization method. Either PDKIM_CANON_SIMPLE
120 or PDKIM_CANON_RELAXED */
123 /* (c=/x) Body canonicalization method. Either PDKIM_CANON_SIMPLE
124 or PDKIM_CANON_RELAXED */
127 /* (q=) Query Method. Currently, only PDKIM_QUERYMETHOD_DNS_TXT
131 /* (s=) The selector string as given in the signature */
134 /* (d=) The domain as given in the signature */
137 /* (i=) The identity as given in the signature */
140 /* (t=) Timestamp of signature creation */
141 unsigned long created;
143 /* (x=) Timestamp of expiry of signature */
144 unsigned long expires;
146 /* (l=) Amount of hashed body bytes (after canonicalization) */
147 unsigned long bodylength;
149 /* (h=) Colon-separated list of header names that are included in the
156 /* (b=) Decoded raw signature data, along with its length in bytes */
160 /* (bh=) Decoded raw body hash data, along with its length in bytes */
164 /* The main verification status. One of:
166 PDKIM_VERIFY_NONE Verification was not attempted. This status
169 PDKIM_VERIFY_INVALID There was an error while trying to verify
170 the signature. A more precise description
171 is available in verify_ext_status.
173 PDKIM_VERIFY_FAIL Verification failed because either the body
174 hash did not match, or the signature verification
175 failed. This probably means the message was
176 modified. Check verify_ext_status for the
179 PDKIM_VERIFY_PASS Verification succeeded.
184 /* Extended verification status. Depending on the value of verify_status,
187 For verify_status == PDKIM_VERIFY_INVALID:
189 PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE
190 Unable to retrieve a public key container.
192 PDKIM_VERIFY_INVALID_BUFFER_SIZE
193 Either the DNS name constructed to retrieve the public key record
194 does not fit into PDKIM_DNS_TXT_MAX_NAMELEN bytes, or the retrieved
195 record is longer than PDKIM_DNS_TXT_MAX_RECLEN bytes.
197 PDKIM_VERIFY_INVALID_PUBKEY_PARSING
198 (Syntax) error while parsing the retrieved public key record.
201 For verify_status == PDKIM_VERIFY_FAIL:
203 PDKIM_VERIFY_FAIL_BODY
204 PDKIM_VERIFY_FAIL_MESSAGE
208 int verify_ext_status;
212 pdkim_pubkey *pubkey; /* Public key used to verify this signature. */
213 void *next; /* Pointer to next signature in list. */
215 /* Per-signature helper variables ----------------------------------- */
216 sha1_context sha1_body;
217 sha2_context sha2_body;
218 unsigned long signed_body_bytes;
219 pdkim_stringlist *headers;
220 /* Signing specific ------------------------------------------------- */
221 char *rsa_privkey; /* Private RSA key */
222 char *sign_headers; /* To-be-signed header names */
223 /* Verification specific -------------------------------------------- */
224 int headernames_pos; /* Current position in header name list */
225 char *rawsig_no_b_val; /* Original signature header w/o b= tag value. */
229 /* -------------------------------------------------------------------------- */
230 /* Context to keep state between all operations */
232 #define PDKIM_MODE_SIGN 0
233 #define PDKIM_MODE_VERIFY 1
234 #define PDKIM_INPUT_NORMAL 0
235 #define PDKIM_INPUT_SMTP 1
237 typedef struct pdkim_ctx {
239 /* PDKIM_MODE_VERIFY or PDKIM_MODE_SIGN */
242 /* PDKIM_INPUT_SMTP or PDKIM_INPUT_NORMAL */
245 /* One (signing) or several chained (verification) signatures */
246 pdkim_signature *sig;
248 /* Callback for dns/txt query method (verification only) */
249 int(*dns_txt_callback)(char *, char *);
251 /* Coder's little helpers */
252 pdkim_str *cur_header;
253 char linebuf[PDKIM_MAX_BODY_LINE_LEN];
258 int num_buffered_crlf;
262 /* A FILE pointer. When not NULL, debug output will be generated
263 and sent to this stream */
270 int header_name_match (char *, char *, int);
271 char *pdkim_relax_header (char *, int);
273 int pdkim_update_bodyhash (pdkim_ctx *, char *, int);
274 int pdkim_finish_bodyhash (pdkim_ctx *);
276 int pdkim_bodyline_complete (pdkim_ctx *);
277 int pdkim_header_complete (pdkim_ctx *);
279 int pdkim_feed (pdkim_ctx *, char *, int);
280 int pdkim_feed_finish (pdkim_ctx *, char **);
282 char *pdkim_create_header (pdkim_signature *, int);
285 *pdkim_init_sign (int, char *, char *, char *);
288 *pdkim_init_verify (int, int(*dns_txt_callback)(char *, char *));
290 int pdkim_set_optional (pdkim_ctx *,
297 void pdkim_free_pubkey (pdkim_pubkey *);
298 void pdkim_free_sig (pdkim_signature *);
299 void pdkim_free_ctx (pdkim_ctx *);
303 void pdkim_set_debug_stream (pdkim_ctx *, FILE *);