Docs: clean for next release
[exim.git] / src / src / pdkim / pdkim.c
CommitLineData
80a47a2c
TK
1/*
2 * PDKIM - a RFC4871 (DKIM) implementation
3 *
f444c2c7 4 * Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
f9ba5e22 5 * Copyright (C) 2016 - 2018 Jeremy Harris <jgh@exim.org>
80a47a2c
TK
6 *
7 * http://duncanthrax.net/pdkim/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
0d04a285 24#include "../exim.h"
80a47a2c 25
f444c2c7
JH
26
27#ifndef DISABLE_DKIM /* entire file */
28
29#ifndef SUPPORT_TLS
30# error Need SUPPORT_TLS for DKIM
31#endif
32
cb224393 33#include "crypt_ver.h"
f444c2c7 34
d73e45df 35#ifdef SIGN_OPENSSL
cb224393
JH
36# include <openssl/rsa.h>
37# include <openssl/ssl.h>
38# include <openssl/err.h>
d73e45df 39#elif defined(SIGN_GNUTLS)
f444c2c7
JH
40# include <gnutls/gnutls.h>
41# include <gnutls/x509.h>
f444c2c7
JH
42#endif
43
44#include "pdkim.h"
9b2583c4 45#include "signing.h"
80a47a2c
TK
46
47#define PDKIM_SIGNATURE_VERSION "1"
e2e3255a 48#define PDKIM_PUB_RECORD_VERSION US "DKIM1"
80a47a2c
TK
49
50#define PDKIM_MAX_HEADER_LEN 65536
51#define PDKIM_MAX_HEADERS 512
52#define PDKIM_MAX_BODY_LINE_LEN 16384
53#define PDKIM_DNS_TXT_MAX_NAMELEN 1024
80a47a2c
TK
54
55/* -------------------------------------------------------------------------- */
56struct pdkim_stringlist {
e2e3255a
JH
57 uschar * value;
58 int tag;
59 void * next;
80a47a2c
TK
60};
61
80a47a2c
TK
62/* -------------------------------------------------------------------------- */
63/* A bunch of list constants */
e2e3255a
JH
64const uschar * pdkim_querymethods[] = {
65 US"dns/txt",
80a47a2c
TK
66 NULL
67};
e2e3255a
JH
68const uschar * pdkim_canons[] = {
69 US"simple",
70 US"relaxed",
80a47a2c
TK
71 NULL
72};
d73e45df 73
617d3932 74const pdkim_hashtype pdkim_hashes[] = {
d73e45df
JH
75 { US"sha1", HASH_SHA1 },
76 { US"sha256", HASH_SHA2_256 },
77 { US"sha512", HASH_SHA2_512 }
80a47a2c 78};
d73e45df 79
e2e3255a 80const uschar * pdkim_keytypes[] = {
286b9d5f
JH
81 [KEYTYPE_RSA] = US"rsa",
82#ifdef SIGN_HAVE_ED25519
321ef002 83 [KEYTYPE_ED25519] = US"ed25519", /* Works for 3.6.0 GnuTLS, OpenSSL 1.1.1 */
286b9d5f
JH
84#endif
85
86#ifdef notyet_EC_dkim_extensions /* https://tools.ietf.org/html/draft-srose-dkim-ecc-00 */
87 US"eccp256",
88 US"eccp348",
89 US"ed448",
90#endif
80a47a2c
TK
91};
92
93typedef struct pdkim_combined_canon_entry {
286b9d5f
JH
94 const uschar * str;
95 int canon_headers;
96 int canon_body;
80a47a2c 97} pdkim_combined_canon_entry;
f444c2c7 98
80a47a2c 99pdkim_combined_canon_entry pdkim_combined_canons[] = {
e2e3255a
JH
100 { US"simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
101 { US"simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
102 { US"relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
103 { US"relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
104 { US"simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
105 { US"relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
106 { NULL, 0, 0 }
80a47a2c
TK
107};
108
109
9e70917d
JH
110static blob lineending = {.data = US"\r\n", .len = 2};
111
f444c2c7 112/* -------------------------------------------------------------------------- */
d73e45df 113uschar *
9e70917d 114dkim_sig_to_a_tag(const pdkim_signature * sig)
d73e45df
JH
115{
116if ( sig->keytype < 0 || sig->keytype > nelem(pdkim_keytypes)
117 || sig->hashtype < 0 || sig->hashtype > nelem(pdkim_hashes))
118 return US"err";
119return string_sprintf("%s-%s",
120 pdkim_keytypes[sig->keytype], pdkim_hashes[sig->hashtype].dkim_hashname);
121}
122
123
617d3932
JH
124int
125pdkim_hashname_to_hashtype(const uschar * s, unsigned len)
126{
127int i;
128if (!len) len = Ustrlen(s);
129for (i = 0; i < nelem(pdkim_hashes); i++)
130 if (Ustrncmp(s, pdkim_hashes[i].dkim_hashname, len) == 0)
131 return i;
132return -1;
133}
134
135void
136pdkim_cstring_to_canons(const uschar * s, unsigned len,
137 int * canon_head, int * canon_body)
138{
139int i;
140if (!len) len = Ustrlen(s);
141for (i = 0; pdkim_combined_canons[i].str; i++)
142 if ( Ustrncmp(s, pdkim_combined_canons[i].str, len) == 0
143 && len == Ustrlen(pdkim_combined_canons[i].str))
144 {
145 *canon_head = pdkim_combined_canons[i].canon_headers;
146 *canon_body = pdkim_combined_canons[i].canon_body;
147 break;
148 }
149}
150
151
f444c2c7
JH
152
153const char *
154pdkim_verify_status_str(int status)
155{
f7302073
JH
156switch(status)
157 {
158 case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
159 case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
160 case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
161 case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
162 default: return "PDKIM_VERIFY_UNKNOWN";
ff7ddfd7
TK
163 }
164}
f444c2c7
JH
165
166const char *
167pdkim_verify_ext_status_str(int ext_status)
168{
f7302073
JH
169switch(ext_status)
170 {
171 case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
172 case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
135e9496 173 case PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH: return "PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH";
f7302073
JH
174 case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
175 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
176 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
177 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
178 case PDKIM_VERIFY_INVALID_SIGNATURE_ERROR: return "PDKIM_VERIFY_INVALID_SIGNATURE_ERROR";
179 case PDKIM_VERIFY_INVALID_DKIM_VERSION: return "PDKIM_VERIFY_INVALID_DKIM_VERSION";
180 default: return "PDKIM_VERIFY_UNKNOWN";
181 }
182}
183
b9df1829 184const uschar *
f7302073
JH
185pdkim_errstr(int status)
186{
187switch(status)
188 {
b9df1829
JH
189 case PDKIM_OK: return US"OK";
190 case PDKIM_FAIL: return US"FAIL";
286b9d5f
JH
191 case PDKIM_ERR_RSA_PRIVKEY: return US"PRIVKEY";
192 case PDKIM_ERR_RSA_SIGNING: return US"SIGNING";
193 case PDKIM_ERR_LONG_LINE: return US"LONG_LINE";
b9df1829 194 case PDKIM_ERR_BUFFER_TOO_SMALL: return US"BUFFER_TOO_SMALL";
64b67b65 195 case PDKIM_ERR_EXCESS_SIGS: return US"EXCESS_SIGS";
b9df1829
JH
196 case PDKIM_SIGN_PRIVKEY_WRAP: return US"PRIVKEY_WRAP";
197 case PDKIM_SIGN_PRIVKEY_B64D: return US"PRIVKEY_B64D";
ef698bf6 198 default: return US"(unknown)";
ff7ddfd7
TK
199 }
200}
201
202
80a47a2c
TK
203/* -------------------------------------------------------------------------- */
204/* Print debugging functions */
617d3932 205void
b78006ac 206pdkim_quoteprint(const uschar *data, int len)
3045f050
JH
207{
208int i;
0d04a285 209for (i = 0; i < len; i++)
3045f050 210 {
b78006ac 211 const int c = data[i];
3045f050
JH
212 switch (c)
213 {
0d04a285
JH
214 case ' ' : debug_printf("{SP}"); break;
215 case '\t': debug_printf("{TB}"); break;
216 case '\r': debug_printf("{CR}"); break;
217 case '\n': debug_printf("{LF}"); break;
218 case '{' : debug_printf("{BO}"); break;
219 case '}' : debug_printf("{BC}"); break;
3045f050
JH
220 default:
221 if ( (c < 32) || (c > 127) )
0d04a285 222 debug_printf("{%02x}", c);
3045f050 223 else
0d04a285 224 debug_printf("%c", c);
80a47a2c
TK
225 break;
226 }
227 }
2592e6c0 228debug_printf("\n");
80a47a2c 229}
80a47a2c 230
617d3932 231void
b78006ac 232pdkim_hexprint(const uschar *data, int len)
3045f050
JH
233{
234int i;
02c4f8fb
JH
235if (data) for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
236else debug_printf("<NULL>");
2592e6c0 237debug_printf("\n");
80a47a2c 238}
80a47a2c
TK
239
240
f444c2c7 241
f444c2c7 242static pdkim_stringlist *
ca9cb170 243pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str)
3045f050 244{
ca9cb170 245pdkim_stringlist * new_entry = store_get(sizeof(pdkim_stringlist));
3045f050 246
abe1010c 247memset(new_entry, 0, sizeof(pdkim_stringlist));
ca9cb170 248new_entry->value = string_copy(str);
ab9152ff
JH
249if (base) new_entry->next = base;
250return new_entry;
6ab02e3f 251}
80a47a2c
TK
252
253
8ef02a06
JH
254
255/* Trim whitespace fore & aft */
256
ca9cb170 257static void
acec9514 258pdkim_strtrim(gstring * str)
3045f050 259{
acec9514 260uschar * p = str->s;
b2bcdd35 261uschar * q;
acec9514
JH
262
263while (*p == '\t' || *p == ' ') /* dump the leading whitespace */
264 { str->size--; str->ptr--; str->s++; }
265
266while ( str->ptr > 0
81147e20 267 && ((q = str->s + str->ptr - 1), (*q == '\t' || *q == ' '))
acec9514
JH
268 )
269 str->ptr--; /* dump trailing whitespace */
270
271(void) string_from_gstring(str);
8ef02a06
JH
272}
273
274
80a47a2c 275
80a47a2c 276/* -------------------------------------------------------------------------- */
3045f050
JH
277
278DLLEXPORT void
279pdkim_free_ctx(pdkim_ctx *ctx)
280{
6ab02e3f 281}
80a47a2c
TK
282
283
284/* -------------------------------------------------------------------------- */
285/* Matches the name of the passed raw "header" against
8ef02a06 286 the passed colon-separated "tick", and invalidates
484cc1a9
JH
287 the entry in tick. Entries can be prefixed for multi- or over-signing,
288 in which case do not invalidate.
289
290 Returns OK for a match, or fail-code
291*/
3045f050 292
f444c2c7 293static int
e2e3255a 294header_name_match(const uschar * header, uschar * tick)
3045f050 295{
484cc1a9
JH
296const uschar * ticklist = tick;
297int sep = ':';
298BOOL multisign;
299uschar * hname, * p, * ele;
ca9cb170 300uschar * hcolon = Ustrchr(header, ':'); /* Get header name */
3045f050 301
ca9cb170
JH
302if (!hcolon)
303 return PDKIM_FAIL; /* This isn't a header */
3045f050 304
ca9cb170
JH
305/* if we had strncmpic() we wouldn't need this copy */
306hname = string_copyn(header, hcolon-header);
3045f050 307
484cc1a9 308while (p = US ticklist, ele = string_nextinlist(&ticklist, &sep, NULL, 0))
3045f050 309 {
484cc1a9
JH
310 switch (*ele)
311 {
312 case '=': case '+': multisign = TRUE; ele++; break;
313 default: multisign = FALSE; break;
80a47a2c
TK
314 }
315
484cc1a9
JH
316 if (strcmpic(ele, hname) == 0)
317 {
318 if (!multisign)
319 *p = '_'; /* Invalidate this header name instance in tick-off list */
320 return PDKIM_OK;
321 }
322 }
ca9cb170 323return PDKIM_FAIL;
80a47a2c
TK
324}
325
326
327/* -------------------------------------------------------------------------- */
ca9cb170 328/* Performs "relaxed" canonicalization of a header. */
3045f050 329
617d3932
JH
330uschar *
331pdkim_relax_header_n(const uschar * header, int len, BOOL append_crlf)
3045f050
JH
332{
333BOOL past_field_name = FALSE;
334BOOL seen_wsp = FALSE;
ca9cb170 335const uschar * p;
617d3932 336uschar * relaxed = store_get(len+3);
ca9cb170 337uschar * q = relaxed;
3045f050 338
617d3932 339for (p = header; p - header < len; p++)
3045f050 340 {
ca9cb170 341 uschar c = *p;
ea18931d
JH
342
343 if (c == '\r' || c == '\n') /* Ignore CR & LF */
3045f050
JH
344 continue;
345 if (c == '\t' || c == ' ')
346 {
347 if (seen_wsp)
80a47a2c 348 continue;
3045f050
JH
349 c = ' '; /* Turns WSP into SP */
350 seen_wsp = TRUE;
80a47a2c 351 }
3045f050
JH
352 else
353 if (!past_field_name && c == ':')
354 {
ea18931d
JH
355 if (seen_wsp) q--; /* This removes WSP immediately before the colon */
356 seen_wsp = TRUE; /* This removes WSP immediately after the colon */
3045f050 357 past_field_name = TRUE;
80a47a2c 358 }
3045f050
JH
359 else
360 seen_wsp = FALSE;
361
362 /* Lowercase header name */
363 if (!past_field_name) c = tolower(c);
364 *q++ = c;
80a47a2c 365 }
3045f050
JH
366
367if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
3045f050 368
ea18931d 369if (append_crlf) { *q++ = '\r'; *q++ = '\n'; }
ca9cb170 370*q = '\0';
3045f050 371return relaxed;
6ab02e3f 372}
80a47a2c
TK
373
374
617d3932
JH
375uschar *
376pdkim_relax_header(const uschar * header, BOOL append_crlf)
377{
378return pdkim_relax_header_n(header, Ustrlen(header), append_crlf);
379}
380
381
80a47a2c
TK
382/* -------------------------------------------------------------------------- */
383#define PDKIM_QP_ERROR_DECODE -1
3045f050 384
35cf75e9
JH
385static const uschar *
386pdkim_decode_qp_char(const uschar *qp_p, int *c)
3045f050 387{
35cf75e9 388const uschar *initial_pos = qp_p;
3045f050
JH
389
390/* Advance one char */
391qp_p++;
392
393/* Check for two hex digits and decode them */
394if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
395 {
396 /* Do hex conversion */
397 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
a5840e10 398 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
3045f050 399 return qp_p + 2;
6ab02e3f 400 }
80a47a2c 401
3045f050
JH
402/* Illegal char here */
403*c = PDKIM_QP_ERROR_DECODE;
404return initial_pos;
80a47a2c
TK
405}
406
407
408/* -------------------------------------------------------------------------- */
3045f050 409
e2e3255a 410static uschar *
35cf75e9 411pdkim_decode_qp(const uschar * str)
3045f050
JH
412{
413int nchar = 0;
ca9cb170 414uschar * q;
35cf75e9 415const uschar * p = str;
ca9cb170 416uschar * n = store_get(Ustrlen(str)+1);
3045f050
JH
417
418*n = '\0';
419q = n;
ca9cb170 420while (*p)
3045f050
JH
421 {
422 if (*p == '=')
423 {
424 p = pdkim_decode_qp_char(p, &nchar);
425 if (nchar >= 0)
426 {
427 *q++ = nchar;
428 continue;
80a47a2c
TK
429 }
430 }
3045f050
JH
431 else
432 *q++ = *p;
433 p++;
80a47a2c 434 }
3045f050
JH
435*q = '\0';
436return n;
80a47a2c
TK
437}
438
439
440/* -------------------------------------------------------------------------- */
3045f050 441
617d3932 442void
35cf75e9 443pdkim_decode_base64(const uschar * str, blob * b)
3045f050 444{
617d3932 445int dlen = b64decode(str, &b->data);
2592e6c0
JH
446if (dlen < 0) b->data = NULL;
447b->len = dlen;
80a47a2c
TK
448}
449
617d3932 450uschar *
2592e6c0 451pdkim_encode_base64(blob * b)
3045f050 452{
ca9cb170 453return b64encode(b->data, b->len);
80a47a2c
TK
454}
455
456
457/* -------------------------------------------------------------------------- */
458#define PDKIM_HDR_LIMBO 0
459#define PDKIM_HDR_TAG 1
460#define PDKIM_HDR_VALUE 2
3045f050 461
f444c2c7 462static pdkim_signature *
9e70917d 463pdkim_parse_sig_header(pdkim_ctx * ctx, uschar * raw_hdr)
3045f050 464{
2c0f3ea1 465pdkim_signature * sig;
ca9cb170 466uschar *p, *q;
acec9514
JH
467gstring * cur_tag = NULL;
468gstring * cur_val = NULL;
3045f050
JH
469BOOL past_hname = FALSE;
470BOOL in_b_val = FALSE;
471int where = PDKIM_HDR_LIMBO;
472int i;
473
ca9cb170 474sig = store_get(sizeof(pdkim_signature));
abe1010c 475memset(sig, 0, sizeof(pdkim_signature));
3045f050
JH
476sig->bodylength = -1;
477
07eeb4df 478/* Set so invalid/missing data error display is accurate */
07eeb4df 479sig->version = 0;
d73e45df
JH
480sig->keytype = -1;
481sig->hashtype = -1;
07eeb4df 482
ca9cb170 483q = sig->rawsig_no_b_val = store_get(Ustrlen(raw_hdr)+1);
80a47a2c 484
3045f050
JH
485for (p = raw_hdr; ; p++)
486 {
487 char c = *p;
80a47a2c 488
3045f050
JH
489 /* Ignore FWS */
490 if (c == '\r' || c == '\n')
491 goto NEXT_CHAR;
80a47a2c 492
3045f050
JH
493 /* Fast-forward through header name */
494 if (!past_hname)
495 {
496 if (c == ':') past_hname = TRUE;
497 goto NEXT_CHAR;
80a47a2c
TK
498 }
499
3045f050
JH
500 if (where == PDKIM_HDR_LIMBO)
501 {
502 /* In limbo, just wait for a tag-char to appear */
503 if (!(c >= 'a' && c <= 'z'))
504 goto NEXT_CHAR;
80a47a2c 505
3045f050 506 where = PDKIM_HDR_TAG;
80a47a2c
TK
507 }
508
3045f050
JH
509 if (where == PDKIM_HDR_TAG)
510 {
3045f050 511 if (c >= 'a' && c <= 'z')
acec9514 512 cur_tag = string_catn(cur_tag, p, 1);
80a47a2c 513
3045f050
JH
514 if (c == '=')
515 {
acec9514 516 if (Ustrcmp(string_from_gstring(cur_tag), "b") == 0)
3045f050 517 {
ca9cb170 518 *q++ = '=';
3045f050
JH
519 in_b_val = TRUE;
520 }
521 where = PDKIM_HDR_VALUE;
522 goto NEXT_CHAR;
80a47a2c
TK
523 }
524 }
525
3045f050
JH
526 if (where == PDKIM_HDR_VALUE)
527 {
3045f050
JH
528 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
529 goto NEXT_CHAR;
530
531 if (c == ';' || c == '\0')
532 {
a05d3e34
JH
533 /* We must have both tag and value, and tags must be one char except
534 for the possibility of "bh". */
535
536 if ( cur_tag && cur_val
537 && (cur_tag->ptr == 1 || *cur_tag->s == 'b')
538 )
3045f050 539 {
acec9514 540 (void) string_from_gstring(cur_val);
3045f050
JH
541 pdkim_strtrim(cur_val);
542
acec9514 543 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->s, cur_val->s);
3045f050 544
acec9514 545 switch (*cur_tag->s)
3045f050 546 {
286b9d5f 547 case 'b': /* sig-data or body-hash */
a05d3e34
JH
548 switch (cur_tag->s[1])
549 {
550 case '\0': pdkim_decode_base64(cur_val->s, &sig->sighash); break;
551 case 'h': if (cur_tag->ptr == 2)
552 pdkim_decode_base64(cur_val->s, &sig->bodyhash);
553 break;
554 default: break;
555 }
3045f050 556 break;
286b9d5f 557 case 'v': /* version */
3045f050
JH
558 /* We only support version 1, and that is currently the
559 only version there is. */
07eeb4df 560 sig->version =
acec9514 561 Ustrcmp(cur_val->s, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
3045f050 562 break;
286b9d5f 563 case 'a': /* algorithm */
d73e45df 564 {
e220ba1d
JH
565 const uschar * list = cur_val->s;
566 int sep = '-';
567 uschar * elem;
568
569 if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
570 for(i = 0; i < nelem(pdkim_keytypes); i++)
571 if (Ustrcmp(elem, pdkim_keytypes[i]) == 0)
572 { sig->keytype = i; break; }
573 if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
574 for (i = 0; i < nelem(pdkim_hashes); i++)
575 if (Ustrcmp(elem, pdkim_hashes[i].dkim_hashname) == 0)
576 { sig->hashtype = i; break; }
d73e45df
JH
577 }
578
286b9d5f 579 case 'c': /* canonicalization */
617d3932
JH
580 pdkim_cstring_to_canons(cur_val->s, 0,
581 &sig->canon_headers, &sig->canon_body);
3045f050 582 break;
286b9d5f 583 case 'q': /* Query method (for pubkey)*/
3045f050 584 for (i = 0; pdkim_querymethods[i]; i++)
acec9514 585 if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
3045f050 586 {
286b9d5f 587 sig->querymethod = i; /* we never actually use this */
3045f050
JH
588 break;
589 }
590 break;
286b9d5f 591 case 's': /* Selector */
acec9514 592 sig->selector = string_copyn(cur_val->s, cur_val->ptr); break;
286b9d5f 593 case 'd': /* SDID */
acec9514 594 sig->domain = string_copyn(cur_val->s, cur_val->ptr); break;
286b9d5f 595 case 'i': /* AUID */
acec9514 596 sig->identity = pdkim_decode_qp(cur_val->s); break;
286b9d5f 597 case 't': /* Timestamp */
acec9514 598 sig->created = strtoul(CS cur_val->s, NULL, 10); break;
286b9d5f 599 case 'x': /* Expiration */
acec9514 600 sig->expires = strtoul(CS cur_val->s, NULL, 10); break;
286b9d5f 601 case 'l': /* Body length count */
acec9514 602 sig->bodylength = strtol(CS cur_val->s, NULL, 10); break;
286b9d5f 603 case 'h': /* signed header fields */
acec9514 604 sig->headernames = string_copyn(cur_val->s, cur_val->ptr); break;
286b9d5f 605 case 'z': /* Copied headfields */
acec9514 606 sig->copiedheaders = pdkim_decode_qp(cur_val->s); break;
286b9d5f
JH
607/*XXX draft-ietf-dcrup-dkim-crypto-05 would need 'p' tag support
608for rsafp signatures. But later discussion is dropping those. */
3045f050 609 default:
0d04a285 610 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
3045f050
JH
611 break;
612 }
613 }
acec9514 614 cur_tag = cur_val = NULL;
3045f050
JH
615 in_b_val = FALSE;
616 where = PDKIM_HDR_LIMBO;
80a47a2c 617 }
3045f050 618 else
acec9514 619 cur_val = string_catn(cur_val, p, 1);
80a47a2c
TK
620 }
621
3045f050
JH
622NEXT_CHAR:
623 if (c == '\0')
624 break;
80a47a2c 625
3045f050
JH
626 if (!in_b_val)
627 *q++ = c;
80a47a2c
TK
628 }
629
286b9d5f
JH
630if (sig->keytype < 0 || sig->hashtype < 0) /* Cannot verify this signature */
631 return NULL;
632
3045f050
JH
633*q = '\0';
634/* Chomp raw header. The final newline must not be added to the signature. */
37f3dc43
JH
635while (--q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
636 *q = '\0';
80a47a2c 637
0d04a285 638DEBUG(D_acl)
3045f050 639 {
0d04a285 640 debug_printf(
3045f050 641 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
e2e3255a 642 pdkim_quoteprint(US sig->rawsig_no_b_val, Ustrlen(sig->rawsig_no_b_val));
0d04a285 643 debug_printf(
dcd03763 644 "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sighash.len*8);
0d04a285 645 debug_printf(
3045f050 646 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
80a47a2c 647 }
80a47a2c 648
617d3932 649if (!pdkim_set_sig_bodyhash(ctx, sig))
7b83389d 650 return NULL;
cf1cce5e 651
3045f050 652return sig;
80a47a2c
TK
653}
654
655
656/* -------------------------------------------------------------------------- */
80a47a2c 657
617d3932
JH
658pdkim_pubkey *
659pdkim_parse_pubkey_record(const uschar *raw_record)
3045f050 660{
35cf75e9
JH
661const uschar * ele;
662int sep = ';';
663pdkim_pubkey * pub;
80a47a2c 664
ca9cb170 665pub = store_get(sizeof(pdkim_pubkey));
abe1010c 666memset(pub, 0, sizeof(pdkim_pubkey));
80a47a2c 667
35cf75e9
JH
668while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
669 {
670 const uschar * val;
671
672 if ((val = Ustrchr(ele, '=')))
3045f050 673 {
35cf75e9 674 int taglen = val++ - ele;
80a47a2c 675
35cf75e9
JH
676 DEBUG(D_acl) debug_printf(" %.*s=%s\n", taglen, ele, val);
677 switch (ele[0])
3045f050 678 {
35cf75e9
JH
679 case 'v': pub->version = val; break;
680 case 'h': pub->hashes = val; break;
286b9d5f 681 case 'k': pub->keytype = val; break;
35cf75e9
JH
682 case 'g': pub->granularity = val; break;
683 case 'n': pub->notes = pdkim_decode_qp(val); break;
684 case 'p': pdkim_decode_base64(val, &pub->key); break;
685 case 's': pub->srvtype = val; break;
686 case 't': if (Ustrchr(val, 'y')) pub->testing = 1;
687 if (Ustrchr(val, 's')) pub->no_subdomaining = 1;
e21a4d00 688 break;
35cf75e9 689 default: DEBUG(D_acl) debug_printf(" Unknown tag encountered\n"); break;
80a47a2c 690 }
e21a4d00 691 }
35cf75e9 692 }
80a47a2c 693
3045f050 694/* Set fallback defaults */
fc6fb551
JH
695if (!pub->version)
696 pub->version = string_copy(PDKIM_PUB_RECORD_VERSION);
135e9496
JH
697else if (Ustrcmp(pub->version, PDKIM_PUB_RECORD_VERSION) != 0)
698 {
699 DEBUG(D_acl) debug_printf(" Bad v= field\n");
700 return NULL;
701 }
e21a4d00 702
35cf75e9 703if (!pub->granularity) pub->granularity = US"*";
35cf75e9 704if (!pub->keytype ) pub->keytype = US"rsa";
35cf75e9 705if (!pub->srvtype ) pub->srvtype = US"*";
80a47a2c 706
3045f050 707/* p= is required */
2592e6c0 708if (pub->key.data)
80a47a2c 709 return pub;
3045f050 710
135e9496 711DEBUG(D_acl) debug_printf(" Missing p= field\n");
3045f050 712return NULL;
80a47a2c
TK
713}
714
715
716/* -------------------------------------------------------------------------- */
3045f050 717
cf1cce5e 718/* Update one bodyhash with some additional data.
9e70917d
JH
719If we have to relax the data for this sig, return our copy of it. */
720
9e70917d 721static blob *
cf1cce5e 722pdkim_update_ctx_bodyhash(pdkim_bodyhash * b, blob * orig_data, blob * relaxed_data)
3045f050 723{
9e70917d
JH
724blob * canon_data = orig_data;
725/* Defaults to simple canon (no further treatment necessary) */
3045f050 726
cf1cce5e 727if (b->canon_method == PDKIM_CANON_RELAXED)
3045f050 728 {
9e70917d
JH
729 /* Relax the line if not done already */
730 if (!relaxed_data)
3045f050 731 {
9e70917d 732 BOOL seen_wsp = FALSE;
744976d4 733 const uschar * p, * r;
9e70917d 734 int q = 0;
3045f050 735
9e70917d
JH
736 /* We want to be able to free this else we allocate
737 for the entire message which could be many MB. Since
738 we don't know what allocations the SHA routines might
739 do, not safe to use store_get()/store_reset(). */
d5bccfc8 740
9e70917d
JH
741 relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
742 relaxed_data->data = US (relaxed_data+1);
3045f050 743
744976d4 744 for (p = orig_data->data, r = p + orig_data->len; p < r; p++)
9e70917d
JH
745 {
746 char c = *p;
747 if (c == '\r')
748 {
749 if (q > 0 && relaxed_data->data[q-1] == ' ')
750 q--;
751 }
752 else if (c == '\t' || c == ' ')
753 {
754 c = ' '; /* Turns WSP into SP */
755 if (seen_wsp)
756 continue;
757 seen_wsp = TRUE;
3045f050 758 }
9e70917d
JH
759 else
760 seen_wsp = FALSE;
761 relaxed_data->data[q++] = c;
80a47a2c 762 }
9e70917d
JH
763 relaxed_data->data[q] = '\0';
764 relaxed_data->len = q;
80a47a2c 765 }
9e70917d
JH
766 canon_data = relaxed_data;
767 }
80a47a2c 768
9e70917d 769/* Make sure we don't exceed the to-be-signed body length */
cf1cce5e
JH
770if ( b->bodylength >= 0
771 && b->signed_body_bytes + (unsigned long)canon_data->len > b->bodylength
9e70917d 772 )
cf1cce5e 773 canon_data->len = b->bodylength - b->signed_body_bytes;
80a47a2c 774
9e70917d
JH
775if (canon_data->len > 0)
776 {
cf1cce5e
JH
777 exim_sha_update(&b->body_hash_ctx, CUS canon_data->data, canon_data->len);
778 b->signed_body_bytes += canon_data->len;
9e70917d 779 DEBUG(D_acl) pdkim_quoteprint(canon_data->data, canon_data->len);
80a47a2c
TK
780 }
781
9e70917d 782return relaxed_data;
6ab02e3f 783}
80a47a2c
TK
784
785
786/* -------------------------------------------------------------------------- */
80a47a2c 787
ca9cb170 788static void
9e70917d 789pdkim_finish_bodyhash(pdkim_ctx * ctx)
3045f050 790{
cf1cce5e 791pdkim_bodyhash * b;
9e70917d 792pdkim_signature * sig;
80a47a2c 793
cf1cce5e 794for (b = ctx->bodyhash; b; b = b->next) /* Finish hashes */
617d3932 795 {
46682a67 796 DEBUG(D_acl) debug_printf("PDKIM: finish bodyhash %d/%d/%ld len %ld\n",
617d3932 797 b->hashtype, b->canon_method, b->bodylength, b->signed_body_bytes);
cf1cce5e 798 exim_sha_finish(&b->body_hash_ctx, &b->bh);
617d3932 799 }
cf1cce5e 800
3045f050 801/* Traverse all signatures */
f4d091fb 802for (sig = ctx->sig; sig; sig = sig->next)
cf1cce5e
JH
803 {
804 b = sig->calc_body_hash;
3045f050 805
0d04a285 806 DEBUG(D_acl)
3045f050 807 {
4ff848b5 808 debug_printf("PDKIM [%s] Body bytes (%s) hashed: %lu\n"
9e70917d 809 "PDKIM [%s] Body %s computed: ",
4ff848b5
JH
810 sig->domain, pdkim_canons[b->canon_method], b->signed_body_bytes,
811 sig->domain, pdkim_hashes[b->hashtype].dkim_hashname);
cf1cce5e 812 pdkim_hexprint(CUS b->bh.data, b->bh.len);
80a47a2c 813 }
3045f050
JH
814
815 /* SIGNING -------------------------------------------------------------- */
e983e85a 816 if (ctx->flags & PDKIM_MODE_SIGN)
3045f050 817 {
3045f050
JH
818 /* If bodylength limit is set, and we have received less bytes
819 than the requested amount, effectively remove the limit tag. */
cf1cce5e 820 if (b->signed_body_bytes < sig->bodylength)
3045f050 821 sig->bodylength = -1;
80a47a2c 822 }
3045f050 823
3045f050 824 else
02c4f8fb
JH
825 /* VERIFICATION --------------------------------------------------------- */
826 /* Be careful that the header sig included a bodyash */
827
cf1cce5e
JH
828 if ( sig->bodyhash.data
829 && memcmp(b->bh.data, sig->bodyhash.data, b->bh.len) == 0)
3045f050 830 {
4ff848b5 831 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash compared OK\n", sig->domain);
80a47a2c 832 }
3045f050
JH
833 else
834 {
0d04a285 835 DEBUG(D_acl)
3045f050 836 {
e21a4d00 837 debug_printf("PDKIM [%s] Body hash signature from headers: ", sig->domain);
dcd03763 838 pdkim_hexprint(sig->bodyhash.data, sig->bodyhash.len);
0d04a285 839 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
3045f050 840 }
3045f050
JH
841 sig->verify_status = PDKIM_VERIFY_FAIL;
842 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
80a47a2c 843 }
80a47a2c 844 }
6ab02e3f 845}
80a47a2c
TK
846
847
848
9e70917d 849static void
e983e85a
JH
850pdkim_body_complete(pdkim_ctx * ctx)
851{
cf1cce5e 852pdkim_bodyhash * b;
e983e85a
JH
853
854/* In simple body mode, if any empty lines were buffered,
855replace with one. rfc 4871 3.4.3 */
856/*XXX checking the signed-body-bytes is a gross hack; I think
857it indicates that all linebreaks should be buffered, including
858the one terminating a text line */
859
cf1cce5e
JH
860for (b = ctx->bodyhash; b; b = b->next)
861 if ( b->canon_method == PDKIM_CANON_SIMPLE
862 && b->signed_body_bytes == 0
863 && b->num_buffered_blanklines > 0
9e70917d 864 )
cf1cce5e 865 (void) pdkim_update_ctx_bodyhash(b, &lineending, NULL);
e983e85a
JH
866
867ctx->flags |= PDKIM_SEEN_EOD;
868ctx->linebuf_offset = 0;
e983e85a
JH
869}
870
871
872
80a47a2c 873/* -------------------------------------------------------------------------- */
e983e85a 874/* Call from pdkim_feed below for processing complete body lines */
744976d4 875/* NOTE: the line is not NUL-terminated; but we have a count */
3045f050 876
9e70917d
JH
877static void
878pdkim_bodyline_complete(pdkim_ctx * ctx)
3045f050 879{
9e70917d 880blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
cf1cce5e 881pdkim_bodyhash * b;
9e70917d
JH
882blob * rnl = NULL;
883blob * rline = NULL;
3045f050
JH
884
885/* Ignore extra data if we've seen the end-of-data marker */
9e70917d 886if (ctx->flags & PDKIM_SEEN_EOD) goto all_skip;
3045f050
JH
887
888/* We've always got one extra byte to stuff a zero ... */
9e70917d 889ctx->linebuf[line.len] = '\0';
3045f050 890
0d04a285 891/* Terminate on EOD marker */
e983e85a 892if (ctx->flags & PDKIM_DOT_TERM)
3045f050 893 {
9e70917d
JH
894 if (memcmp(line.data, ".\r\n", 3) == 0)
895 { pdkim_body_complete(ctx); return; }
0d04a285 896
e983e85a 897 /* Unstuff dots */
9e70917d
JH
898 if (memcmp(line.data, "..", 2) == 0)
899 { line.data++; line.len--; }
80a47a2c
TK
900 }
901
3045f050 902/* Empty lines need to be buffered until we find a non-empty line */
9e70917d 903if (memcmp(line.data, "\r\n", 2) == 0)
3045f050 904 {
cf1cce5e 905 for (b = ctx->bodyhash; b; b = b->next) b->num_buffered_blanklines++;
9e70917d 906 goto all_skip;
80a47a2c
TK
907 }
908
cf1cce5e
JH
909/* Process line for each bodyhash separately */
910for (b = ctx->bodyhash; b; b = b->next)
3045f050 911 {
cf1cce5e 912 if (b->canon_method == PDKIM_CANON_RELAXED)
3045f050 913 {
9e70917d 914 /* Lines with just spaces need to be buffered too */
7845dbb3 915 uschar * cp = line.data;
9e70917d 916 char c;
6a11a9e6 917
9e70917d
JH
918 while ((c = *cp))
919 {
920 if (c == '\r' && cp[1] == '\n') break;
cf1cce5e 921 if (c != ' ' && c != '\t') goto hash_process;
9e70917d
JH
922 cp++;
923 }
924
cf1cce5e
JH
925 b->num_buffered_blanklines++;
926 goto hash_skip;
6a11a9e6
JH
927 }
928
cf1cce5e 929hash_process:
9e70917d 930 /* At this point, we have a non-empty line, so release the buffered ones. */
6a11a9e6 931
cf1cce5e 932 while (b->num_buffered_blanklines)
9e70917d 933 {
cf1cce5e
JH
934 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
935 b->num_buffered_blanklines--;
9e70917d
JH
936 }
937
cf1cce5e
JH
938 rline = pdkim_update_ctx_bodyhash(b, &line, rline);
939hash_skip: ;
80a47a2c
TK
940 }
941
9e70917d
JH
942if (rnl) store_free(rnl);
943if (rline) store_free(rline);
944
945all_skip:
80a47a2c 946
3045f050 947ctx->linebuf_offset = 0;
9e70917d 948return;
80a47a2c
TK
949}
950
951
952/* -------------------------------------------------------------------------- */
953/* Callback from pdkim_feed below for processing complete headers */
954#define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
3045f050 955
f444c2c7 956static int
2c0f3ea1 957pdkim_header_complete(pdkim_ctx * ctx)
3045f050 958{
2c0f3ea1
JH
959pdkim_signature * sig, * last_sig;
960
3045f050 961/* Special case: The last header can have an extra \r appended */
acec9514
JH
962if ( (ctx->cur_header->ptr > 1) &&
963 (ctx->cur_header->s[ctx->cur_header->ptr-1] == '\r') )
964 --ctx->cur_header->ptr;
965(void) string_from_gstring(ctx->cur_header);
80a47a2c 966
617d3932
JH
967#ifdef EXPERIMENTAL_ARC
968/* Feed the header line to ARC processing */
969(void) arc_header_feed(ctx->cur_header, !(ctx->flags & PDKIM_MODE_SIGN));
970#endif
971
2c0f3ea1 972if (++ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
80a47a2c 973
3045f050 974/* SIGNING -------------------------------------------------------------- */
e983e85a 975if (ctx->flags & PDKIM_MODE_SIGN)
0d04a285 976 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
80a47a2c 977
ab9152ff 978 /* Add header to the signed headers list (in reverse order) */
acec9514 979 sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
94431adb 980
0d04a285 981/* VERIFICATION ----------------------------------------------------------- */
3045f050 982/* DKIM-Signature: headers are added to the verification list */
e983e85a 983else
3045f050 984 {
f6ee24a2 985#ifdef notdef
bd8fbe36
JH
986 DEBUG(D_acl)
987 {
988 debug_printf("PDKIM >> raw hdr: ");
acec9514 989 pdkim_quoteprint(CUS ctx->cur_header->s, ctx->cur_header->ptr);
bd8fbe36 990 }
f6ee24a2 991#endif
acec9514 992 if (strncasecmp(CCS ctx->cur_header->s,
3045f050 993 DKIM_SIGNATURE_HEADERNAME,
e2e3255a 994 Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
3045f050 995 {
02c4f8fb
JH
996 /* Create and chain new signature block. We could error-check for all
997 required tags here, but prefer to create the internal sig and expicitly
998 fail verification of it later. */
80a47a2c 999
0d04a285 1000 DEBUG(D_acl) debug_printf(
3045f050 1001 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
3045f050 1002
acec9514 1003 sig = pdkim_parse_sig_header(ctx, ctx->cur_header->s);
02c4f8fb
JH
1004
1005 if (!(last_sig = ctx->sig))
2c0f3ea1 1006 ctx->sig = sig;
02c4f8fb 1007 else
3045f050 1008 {
02c4f8fb 1009 while (last_sig->next) last_sig = last_sig->next;
2c0f3ea1 1010 last_sig->next = sig;
80a47a2c 1011 }
64b67b65
JH
1012
1013 if (--dkim_collect_input == 0)
1014 {
1015 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
1016 ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0';
1017 return PDKIM_ERR_EXCESS_SIGS;
1018 }
80a47a2c 1019 }
37f8b554 1020
eea19017 1021 /* all headers are stored for signature verification */
acec9514 1022 ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
80a47a2c
TK
1023 }
1024
3045f050 1025BAIL:
acec9514 1026ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0'; /* leave buffer for reuse */
3045f050 1027return PDKIM_OK;
6ab02e3f 1028}
80a47a2c
TK
1029
1030
1031
1032/* -------------------------------------------------------------------------- */
1033#define HEADER_BUFFER_FRAG_SIZE 256
3045f050
JH
1034
1035DLLEXPORT int
ef698bf6 1036pdkim_feed(pdkim_ctx * ctx, uschar * data, int len)
3045f050 1037{
02c4f8fb 1038int p, rc;
3045f050 1039
e983e85a
JH
1040/* Alternate EOD signal, used in non-dotstuffing mode */
1041if (!data)
1042 pdkim_body_complete(ctx);
1043
64b67b65 1044else for (p = 0; p < len; p++)
3045f050 1045 {
ca9cb170 1046 uschar c = data[p];
3045f050 1047
e983e85a 1048 if (ctx->flags & PDKIM_PAST_HDRS)
3045f050 1049 {
b895f4b2
JH
1050 if (c == '\n' && !(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
1051 {
1052 ctx->linebuf[ctx->linebuf_offset++] = '\r';
1053 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
1054 return PDKIM_ERR_LONG_LINE;
1055 }
1056
3045f050 1057 /* Processing body byte */
0d04a285 1058 ctx->linebuf[ctx->linebuf_offset++] = c;
b895f4b2
JH
1059 if (c == '\r')
1060 ctx->flags |= PDKIM_SEEN_CR;
1061 else if (c == '\n')
3045f050 1062 {
b895f4b2 1063 ctx->flags &= ~PDKIM_SEEN_CR;
9e70917d 1064 pdkim_bodyline_complete(ctx);
80a47a2c 1065 }
b895f4b2
JH
1066
1067 if (ctx->linebuf_offset == PDKIM_MAX_BODY_LINE_LEN-1)
3045f050 1068 return PDKIM_ERR_LONG_LINE;
80a47a2c 1069 }
3045f050
JH
1070 else
1071 {
1072 /* Processing header byte */
b895f4b2
JH
1073 if (c == '\r')
1074 ctx->flags |= PDKIM_SEEN_CR;
1075 else if (c == '\n')
3045f050 1076 {
b895f4b2 1077 if (!(ctx->flags & PDKIM_SEEN_CR)) /* emulate the CR */
acec9514 1078 ctx->cur_header = string_catn(ctx->cur_header, CUS "\r", 1);
b895f4b2 1079
02c4f8fb 1080 if (ctx->flags & PDKIM_SEEN_LF) /* Seen last header line */
b895f4b2 1081 {
02c4f8fb
JH
1082 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1083 return rc;
b895f4b2 1084
863bd541 1085 ctx->flags = (ctx->flags & ~(PDKIM_SEEN_LF|PDKIM_SEEN_CR)) | PDKIM_PAST_HDRS;
b895f4b2 1086 DEBUG(D_acl) debug_printf(
02c4f8fb 1087 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
b895f4b2 1088 continue;
3045f050 1089 }
b895f4b2 1090 else
863bd541 1091 ctx->flags = (ctx->flags & ~PDKIM_SEEN_CR) | PDKIM_SEEN_LF;
b895f4b2
JH
1092 }
1093 else if (ctx->flags & PDKIM_SEEN_LF)
1094 {
02c4f8fb
JH
1095 if (!(c == '\t' || c == ' ')) /* End of header */
1096 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1097 return rc;
b895f4b2 1098 ctx->flags &= ~PDKIM_SEEN_LF;
80a47a2c 1099 }
3045f050 1100
acec9514
JH
1101 if (!ctx->cur_header || ctx->cur_header->ptr < PDKIM_MAX_HEADER_LEN)
1102 ctx->cur_header = string_catn(ctx->cur_header, CUS &data[p], 1);
80a47a2c
TK
1103 }
1104 }
3045f050 1105return PDKIM_OK;
6ab02e3f 1106}
80a47a2c 1107
ca9cb170
JH
1108
1109
acec9514
JH
1110/* Extend a growing header with a continuation-linebreak */
1111static gstring *
1112pdkim_hdr_cont(gstring * str, int * col)
ca9cb170
JH
1113{
1114*col = 1;
acec9514 1115return string_catn(str, US"\r\n\t", 3);
ca9cb170
JH
1116}
1117
1118
1119
05b7d6de
JB
1120/*
1121 * RFC 5322 specifies that header line length SHOULD be no more than 78
1122 * lets make it so!
1123 * pdkim_headcat
ca9cb170
JH
1124 *
1125 * returns uschar * (not nul-terminated)
05b7d6de
JB
1126 *
1127 * col: this int holds and receives column number (octets since last '\n')
1128 * str: partial string to append to
94431adb 1129 * pad: padding, split line or space after before or after eg: ";"
05b7d6de
JB
1130 * intro: - must join to payload eg "h=", usually the tag name
1131 * payload: eg base64 data - long data can be split arbitrarily.
1132 *
1133 * this code doesn't fold the header in some of the places that RFC4871
1134 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1135 * pairs and inside long values. it also always spaces or breaks after the
94431adb 1136 * "pad"
05b7d6de
JB
1137 *
1138 * no guarantees are made for output given out-of range input. like tag
f444c2c7 1139 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
05b7d6de
JB
1140 */
1141
acec9514
JH
1142static gstring *
1143pdkim_headcat(int * col, gstring * str,
ca9cb170 1144 const uschar * pad, const uschar * intro, const uschar * payload)
3045f050
JH
1145{
1146size_t l;
1147
1148if (pad)
05b7d6de 1149 {
ca9cb170 1150 l = Ustrlen(pad);
3045f050 1151 if (*col + l > 78)
acec9514
JH
1152 str = pdkim_hdr_cont(str, col);
1153 str = string_catn(str, pad, l);
3045f050 1154 *col += l;
05b7d6de
JB
1155 }
1156
ca9cb170 1157l = (pad?1:0) + (intro?Ustrlen(intro):0);
05b7d6de 1158
3045f050 1159if (*col + l > 78)
05b7d6de 1160 { /*can't fit intro - start a new line to make room.*/
acec9514 1161 str = pdkim_hdr_cont(str, col);
ca9cb170 1162 l = intro?Ustrlen(intro):0;
05b7d6de
JB
1163 }
1164
ca9cb170 1165l += payload ? Ustrlen(payload):0 ;
05b7d6de 1166
3045f050 1167while (l>77)
05b7d6de 1168 { /* this fragment will not fit on a single line */
3045f050 1169 if (pad)
05b7d6de 1170 {
acec9514 1171 str = string_catn(str, US" ", 1);
3045f050
JH
1172 *col += 1;
1173 pad = NULL; /* only want this once */
1174 l--;
05b7d6de 1175 }
3045f050
JH
1176
1177 if (intro)
05b7d6de 1178 {
ca9cb170 1179 size_t sl = Ustrlen(intro);
3045f050 1180
acec9514 1181 str = string_catn(str, intro, sl);
3045f050
JH
1182 *col += sl;
1183 l -= sl;
1184 intro = NULL; /* only want this once */
05b7d6de 1185 }
3045f050
JH
1186
1187 if (payload)
05b7d6de 1188 {
ca9cb170 1189 size_t sl = Ustrlen(payload);
3045f050
JH
1190 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1191
acec9514 1192 str = string_catn(str, payload, chomp);
3045f050
JH
1193 *col += chomp;
1194 payload += chomp;
1195 l -= chomp-1;
05b7d6de 1196 }
3045f050
JH
1197
1198 /* the while precondition tells us it didn't fit. */
acec9514 1199 str = pdkim_hdr_cont(str, col);
05b7d6de 1200 }
3045f050
JH
1201
1202if (*col + l > 78)
05b7d6de 1203 {
acec9514 1204 str = pdkim_hdr_cont(str, col);
3045f050 1205 pad = NULL;
05b7d6de
JB
1206 }
1207
3045f050 1208if (pad)
05b7d6de 1209 {
acec9514 1210 str = string_catn(str, US" ", 1);
3045f050
JH
1211 *col += 1;
1212 pad = NULL;
05b7d6de
JB
1213 }
1214
3045f050 1215if (intro)
05b7d6de 1216 {
ca9cb170 1217 size_t sl = Ustrlen(intro);
3045f050 1218
acec9514 1219 str = string_catn(str, intro, sl);
3045f050
JH
1220 *col += sl;
1221 l -= sl;
1222 intro = NULL;
05b7d6de 1223 }
3045f050
JH
1224
1225if (payload)
05b7d6de 1226 {
ca9cb170 1227 size_t sl = Ustrlen(payload);
3045f050 1228
acec9514 1229 str = string_catn(str, payload, sl);
3045f050 1230 *col += sl;
05b7d6de
JB
1231 }
1232
ca9cb170 1233return str;
05b7d6de 1234}
80a47a2c 1235
3045f050 1236
80a47a2c 1237/* -------------------------------------------------------------------------- */
3045f050 1238
cf1cce5e
JH
1239/* Signing: create signature header
1240*/
ca9cb170 1241static uschar *
9e70917d 1242pdkim_create_header(pdkim_signature * sig, BOOL final)
3045f050 1243{
ca9cb170
JH
1244uschar * base64_bh;
1245uschar * base64_b;
3045f050 1246int col = 0;
acec9514
JH
1247gstring * hdr;
1248gstring * canon_all;
3045f050 1249
acec9514
JH
1250canon_all = string_cat (NULL, pdkim_canons[sig->canon_headers]);
1251canon_all = string_catn(canon_all, US"/", 1);
1252canon_all = string_cat (canon_all, pdkim_canons[sig->canon_body]);
1253(void) string_from_gstring(canon_all);
3045f050 1254
acec9514
JH
1255hdr = string_cat(NULL, US"DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1256col = hdr->ptr;
3045f050
JH
1257
1258/* Required and static bits */
acec9514
JH
1259hdr = pdkim_headcat(&col, hdr, US";", US"a=", dkim_sig_to_a_tag(sig));
1260hdr = pdkim_headcat(&col, hdr, US";", US"q=", pdkim_querymethods[sig->querymethod]);
1261hdr = pdkim_headcat(&col, hdr, US";", US"c=", canon_all->s);
1262hdr = pdkim_headcat(&col, hdr, US";", US"d=", sig->domain);
1263hdr = pdkim_headcat(&col, hdr, US";", US"s=", sig->selector);
ca9cb170
JH
1264
1265/* list of header names can be split between items. */
3045f050 1266 {
e2e3255a 1267 uschar * n = string_copy(sig->headernames);
ca9cb170
JH
1268 uschar * i = US"h=";
1269 uschar * s = US";";
1270
1271 while (*n)
05b7d6de 1272 {
ca9cb170 1273 uschar * c = Ustrchr(n, ':');
3045f050 1274
ca9cb170 1275 if (c) *c ='\0';
05b7d6de 1276
ca9cb170 1277 if (!i)
acec9514 1278 hdr = pdkim_headcat(&col, hdr, NULL, NULL, US":");
05b7d6de 1279
acec9514 1280 hdr = pdkim_headcat(&col, hdr, s, i, n);
3045f050 1281
ca9cb170
JH
1282 if (!c)
1283 break;
3045f050 1284
ca9cb170
JH
1285 n = c+1;
1286 s = NULL;
1287 i = NULL;
80a47a2c 1288 }
ca9cb170 1289 }
05b7d6de 1290
cf1cce5e 1291base64_bh = pdkim_encode_base64(&sig->calc_body_hash->bh);
acec9514 1292hdr = pdkim_headcat(&col, hdr, US";", US"bh=", base64_bh);
3045f050 1293
ca9cb170
JH
1294/* Optional bits */
1295if (sig->identity)
acec9514 1296 hdr = pdkim_headcat(&col, hdr, US";", US"i=", sig->identity);
3045f050 1297
ca9cb170
JH
1298if (sig->created > 0)
1299 {
e2e3255a 1300 uschar minibuf[20];
3045f050 1301
e2e3255a 1302 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->created);
acec9514 1303 hdr = pdkim_headcat(&col, hdr, US";", US"t=", minibuf);
ca9cb170 1304}
3045f050 1305
ca9cb170
JH
1306if (sig->expires > 0)
1307 {
e2e3255a 1308 uschar minibuf[20];
3045f050 1309
e2e3255a 1310 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->expires);
acec9514 1311 hdr = pdkim_headcat(&col, hdr, US";", US"x=", minibuf);
ca9cb170 1312 }
3045f050 1313
ca9cb170
JH
1314if (sig->bodylength >= 0)
1315 {
e2e3255a 1316 uschar minibuf[20];
80a47a2c 1317
e2e3255a 1318 snprintf(CS minibuf, sizeof(minibuf), "%lu", sig->bodylength);
acec9514 1319 hdr = pdkim_headcat(&col, hdr, US";", US"l=", minibuf);
3045f050 1320 }
05b7d6de 1321
ca9cb170 1322/* Preliminary or final version? */
ea18931d
JH
1323if (final)
1324 {
1325 base64_b = pdkim_encode_base64(&sig->sighash);
acec9514 1326 hdr = pdkim_headcat(&col, hdr, US";", US"b=", base64_b);
80a47a2c 1327
ea18931d 1328 /* add trailing semicolon: I'm not sure if this is actually needed */
acec9514 1329 hdr = pdkim_headcat(&col, hdr, NULL, US";", US"");
ea18931d
JH
1330 }
1331else
1332 {
1333 /* To satisfy the rule "all surrounding whitespace [...] deleted"
1334 ( RFC 6376 section 3.7 ) we ensure there is no whitespace here. Otherwise
1335 the headcat routine could insert a linebreak which the relaxer would reduce
1336 to a single space preceding the terminating semicolon, resulting in an
1337 incorrect header-hash. */
acec9514 1338 hdr = pdkim_headcat(&col, hdr, US";", US"b=;", US"");
ea18931d 1339 }
80a47a2c 1340
acec9514 1341return string_from_gstring(hdr);
80a47a2c
TK
1342}
1343
1344
cd1a5fe0
JH
1345/* -------------------------------------------------------------------------- */
1346
321ef002
JH
1347/* According to draft-ietf-dcrup-dkim-crypto-07 "keys are 256 bits" (referring
1348to DNS, hence the pubkey). Check for more than 32 bytes; if so assume the
1349alternate possible representation (still) being discussed: a
1350SubjectPublickeyInfo wrapped key - and drop all but the trailing 32-bytes (it
1351should be a DER, with exactly 12 leading bytes - but we could accept a BER also,
1352which could be any size). We still rely on the crypto library for checking for
1353undersize.
1354
1355When the RFC is published this should be re-addressed. */
1356
1357static void
1358check_bare_ed25519_pubkey(pdkim_pubkey * p)
1359{
1360int excess = p->key.len - 32;
1361if (excess > 0)
1362 {
1363 DEBUG(D_acl) debug_printf("PDKIM: unexpected pubkey len %lu\n", p->key.len);
1364 p->key.data += excess; p->key.len = 32;
1365 }
1366}
1367
1368
cd1a5fe0 1369static pdkim_pubkey *
b9df1829
JH
1370pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
1371 const uschar ** errstr)
cd1a5fe0
JH
1372{
1373uschar * dns_txt_name, * dns_txt_reply;
1374pdkim_pubkey * p;
cd1a5fe0
JH
1375
1376/* Fetch public key for signing domain, from DNS */
1377
1378dns_txt_name = string_sprintf("%s._domainkey.%s.", sig->selector, sig->domain);
1379
617d3932 1380if ( !(dns_txt_reply = ctx->dns_txt_callback(dns_txt_name))
cd1a5fe0
JH
1381 || dns_txt_reply[0] == '\0'
1382 )
1383 {
1384 sig->verify_status = PDKIM_VERIFY_INVALID;
1385 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1386 return NULL;
1387 }
1388
1389DEBUG(D_acl)
1390 {
1391 debug_printf(
1392 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
9e70917d
JH
1393 " %s\n"
1394 " Raw record: ",
1395 dns_txt_name);
cd1a5fe0
JH
1396 pdkim_quoteprint(CUS dns_txt_reply, Ustrlen(dns_txt_reply));
1397 }
1398
617d3932 1399if ( !(p = pdkim_parse_pubkey_record(CUS dns_txt_reply))
cd1a5fe0
JH
1400 || (Ustrcmp(p->srvtype, "*") != 0 && Ustrcmp(p->srvtype, "email") != 0)
1401 )
1402 {
1403 sig->verify_status = PDKIM_VERIFY_INVALID;
1404 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1405
1406 DEBUG(D_acl)
1407 {
1408 if (p)
1409 debug_printf(" Invalid public key service type '%s'\n", p->srvtype);
1410 else
1411 debug_printf(" Error while parsing public key record\n");
1412 debug_printf(
1413 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1414 }
1415 return NULL;
1416 }
1417
1418DEBUG(D_acl) debug_printf(
1419 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1420
1421/* Import public key */
286b9d5f 1422
cb78c1a8
JH
1423/* Normally we use the signature a= tag to tell us the pubkey format.
1424When signing under debug we do a test-import of the pubkey, and at that
1425time we do not have a signature so we must interpret the pubkey k= tag
1426instead. Assume writing on the sig is ok in that case. */
1427
1428if (sig->keytype < 0)
1429 {
1430 int i;
1431 for(i = 0; i < nelem(pdkim_keytypes); i++)
1432 if (Ustrcmp(p->keytype, pdkim_keytypes[i]) == 0)
1433 { sig->keytype = i; goto k_ok; }
1434 DEBUG(D_acl) debug_printf("verify_init: unhandled keytype %s\n", p->keytype);
1435 sig->verify_status = PDKIM_VERIFY_INVALID;
1436 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1437 return NULL;
1438 }
1439k_ok:
1440
321ef002
JH
1441if (sig->keytype == KEYTYPE_ED25519)
1442 check_bare_ed25519_pubkey(p);
1443
286b9d5f
JH
1444if ((*errstr = exim_dkim_verify_init(&p->key,
1445 sig->keytype == KEYTYPE_ED25519 ? KEYFMT_ED25519_BARE : KEYFMT_DER,
1446 vctx)))
cd1a5fe0 1447 {
b9df1829 1448 DEBUG(D_acl) debug_printf("verify_init: %s\n", *errstr);
cd1a5fe0
JH
1449 sig->verify_status = PDKIM_VERIFY_INVALID;
1450 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1451 return NULL;
1452 }
1453
286b9d5f 1454vctx->keytype = sig->keytype;
cd1a5fe0
JH
1455return p;
1456}
1457
1458
80a47a2c 1459/* -------------------------------------------------------------------------- */
3045f050
JH
1460
1461DLLEXPORT int
b9df1829
JH
1462pdkim_feed_finish(pdkim_ctx * ctx, pdkim_signature ** return_signatures,
1463 const uschar ** err)
3045f050 1464{
cf1cce5e 1465pdkim_bodyhash * b;
9e70917d 1466pdkim_signature * sig;
286b9d5f 1467BOOL verify_pass = FALSE;
3045f050
JH
1468
1469/* Check if we must still flush a (partial) header. If that is the
1470 case, the message has no body, and we must compute a body hash
1471 out of '<CR><LF>' */
acec9514 1472if (ctx->cur_header && ctx->cur_header->ptr > 0)
3045f050 1473 {
9e70917d
JH
1474 blob * rnl = NULL;
1475 int rc;
1476
1477 if ((rc = pdkim_header_complete(ctx)) != PDKIM_OK)
1478 return rc;
1479
cf1cce5e
JH
1480 for (b = ctx->bodyhash; b; b = b->next)
1481 rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
9e70917d 1482 if (rnl) store_free(rnl);
80a47a2c 1483 }
3045f050 1484else
0d04a285 1485 DEBUG(D_acl) debug_printf(
3045f050 1486 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
80a47a2c 1487
617d3932
JH
1488/* Build (and/or evaluate) body hash. Do this even if no DKIM sigs, in case we
1489have a hash to do for ARC. */
1490
1491pdkim_finish_bodyhash(ctx);
1492
286b9d5f
JH
1493if (!ctx->sig)
1494 {
1495 DEBUG(D_acl) debug_printf("PDKIM: no signatures\n");
617d3932 1496 *return_signatures = NULL;
286b9d5f
JH
1497 return PDKIM_OK;
1498 }
1499
9e70917d 1500for (sig = ctx->sig; sig; sig = sig->next)
3045f050 1501 {
2592e6c0 1502 hctx hhash_ctx;
ad6f5499 1503 uschar * sig_hdr = US"";
2592e6c0 1504 blob hhash;
acec9514 1505 gstring * hdata = NULL;
286b9d5f
JH
1506 es_ctx sctx;
1507
617d3932
JH
1508 if ( !(ctx->flags & PDKIM_MODE_SIGN)
1509 && sig->verify_status == PDKIM_VERIFY_FAIL)
1510 {
1511 DEBUG(D_acl)
1512 debug_printf("PDKIM: [%s] abandoning this signature\n", sig->domain);
1513 continue;
1514 }
1515
286b9d5f
JH
1516 /*XXX The hash of the headers is needed for GCrypt (for which we can do RSA
1517 suging only, as it happens) and for either GnuTLS and OpenSSL when we are
1518 signing with EC (specifically, Ed25519). The former is because the GCrypt
1519 signing operation is pure (does not do its own hash) so we must hash. The
1520 latter is because we (stupidly, but this is what the IETF draft is saying)
1521 must hash with the declared hash method, then pass the result to the library
1522 hash-and-sign routine (because that's all the libraries are providing. And
1523 we're stuck with whatever that hidden hash method is, too). We may as well
1524 do this hash incrementally.
1525 We don't need the hash we're calculating here for the GnuTLS and OpenSSL
1526 cases of RSA signing, since those library routines can do hash-and-sign.
1527
1528 Some time in the future we could easily avoid doing the hash here for those
1529 cases (which will be common for a long while. We could also change from
1530 the current copy-all-the-headers-into-one-block, then call the hash-and-sign
1531 implementation - to a proper incremental one. Unfortunately, GnuTLS just
1532 cannot do incremental - either signing or verification. Unsure about GCrypt.
1533 */
1534
1535 /*XXX The header hash is also used (so far) by the verify operation */
2592e6c0 1536
d73e45df 1537 if (!exim_sha_init(&hhash_ctx, pdkim_hashes[sig->hashtype].exim_hashmethod))
7b83389d 1538 {
286b9d5f
JH
1539 log_write(0, LOG_MAIN|LOG_PANIC,
1540 "PDKIM: hash setup error, possibly nonhandled hashtype");
7b83389d
JH
1541 break;
1542 }
80a47a2c 1543
9e70917d
JH
1544 if (ctx->flags & PDKIM_MODE_SIGN)
1545 DEBUG(D_acl) debug_printf(
1546 "PDKIM >> Headers to be signed: >>>>>>>>>>>>\n"
1547 " %s\n",
1548 sig->sign_headers);
1549
0d04a285 1550 DEBUG(D_acl) debug_printf(
4ff848b5
JH
1551 "PDKIM >> Header data for hash, canonicalized (%-7s), in sequence >>\n",
1552 pdkim_canons[sig->canon_headers]);
3045f050 1553
9e70917d 1554
3045f050
JH
1555 /* SIGNING ---------------------------------------------------------------- */
1556 /* When signing, walk through our header list and add them to the hash. As we
8ef02a06
JH
1557 go, construct a list of the header's names to use for the h= parameter.
1558 Then append to that list any remaining header names for which there was no
1559 header to sign. */
3045f050 1560
e983e85a 1561 if (ctx->flags & PDKIM_MODE_SIGN)
3045f050 1562 {
acec9514 1563 gstring * g = NULL;
3045f050 1564 pdkim_stringlist *p;
8ef02a06
JH
1565 const uschar * l;
1566 uschar * s;
1567 int sep = 0;
3045f050 1568
286b9d5f
JH
1569 /* Import private key, including the keytype which we need for building
1570 the signature header */
1571
1572/*XXX extend for non-RSA algos */
617d3932 1573 if ((*err = exim_dkim_signing_init(CUS sig->privkey, &sctx)))
286b9d5f
JH
1574 {
1575 log_write(0, LOG_MAIN|LOG_PANIC, "signing_init: %s", *err);
1576 return PDKIM_ERR_RSA_PRIVKEY;
1577 }
1578 sig->keytype = sctx.keytype;
9e70917d 1579
286b9d5f
JH
1580 for (sig->headernames = NULL, /* Collected signed header names */
1581 p = sig->headers; p; p = p->next)
9e70917d
JH
1582 {
1583 uschar * rh = p->value;
1584
1585 if (header_name_match(rh, sig->sign_headers) == PDKIM_OK)
ab9152ff 1586 {
ab9152ff 1587 /* Collect header names (Note: colon presence is guaranteed here) */
acec9514 1588 g = string_append_listele_n(g, ':', rh, Ustrchr(rh, ':') - rh);
3045f050 1589
9e70917d
JH
1590 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1591 rh = pdkim_relax_header(rh, TRUE); /* cook header for relaxed canon */
3045f050 1592
ab9152ff 1593 /* Feed header to the hash algorithm */
e2e3255a 1594 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
f444c2c7 1595
ab9152ff 1596 /* Remember headers block for signing (when the library cannot do incremental) */
286b9d5f 1597 /*XXX we could avoid doing this for all but the GnuTLS/RSA case */
acec9514 1598 hdata = exim_dkim_data_append(hdata, rh);
3045f050 1599
ab9152ff
JH
1600 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1601 }
9e70917d 1602 }
8ef02a06 1603
484cc1a9
JH
1604 /* Any headers we wanted to sign but were not present must also be listed.
1605 Ignore elements that have been ticked-off or are marked as never-oversign. */
1606
ca9cb170 1607 l = sig->sign_headers;
8ef02a06 1608 while((s = string_nextinlist(&l, &sep, NULL, 0)))
484cc1a9
JH
1609 {
1610 if (*s == '+') /* skip oversigning marker */
1611 s++;
1612 if (*s != '_' && *s != '=')
acec9514 1613 g = string_append_listele(g, ':', s);
484cc1a9 1614 }
acec9514 1615 sig->headernames = string_from_gstring(g);
ca9cb170
JH
1616
1617 /* Create signature header with b= omitted */
1618 sig_hdr = pdkim_create_header(sig, FALSE);
80a47a2c 1619 }
37f8b554 1620
3045f050
JH
1621 /* VERIFICATION ----------------------------------------------------------- */
1622 /* When verifying, walk through the header name list in the h= parameter and
1623 add the headers to the hash in that order. */
1624 else
1625 {
10c50704 1626 uschar * p = sig->headernames;
2592e6c0
JH
1627 uschar * q;
1628 pdkim_stringlist * hdrs;
3045f050 1629
10c50704 1630 if (p)
3045f050 1631 {
10c50704 1632 /* clear tags */
3045f050 1633 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
10c50704 1634 hdrs->tag = 0;
3045f050 1635
10c50704
JH
1636 p = string_copy(p);
1637 while(1)
1638 {
1639 if ((q = Ustrchr(p, ':')))
1640 *q = '\0';
1641
1642 /*XXX walk the list of headers in same order as received. */
1643 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1644 if ( hdrs->tag == 0
4dc2379a 1645 && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
10c50704
JH
1646 && (hdrs->value)[Ustrlen(p)] == ':'
1647 )
1648 {
1649 /* cook header for relaxed canon, or just copy it for simple */
1650
1651 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
ea18931d 1652 ? pdkim_relax_header(hdrs->value, TRUE)
10c50704
JH
1653 : string_copy(CUS hdrs->value);
1654
1655 /* Feed header to the hash algorithm */
1656 exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
1657
1658 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1659 hdrs->tag = 1;
1660 break;
1661 }
3045f050 1662
10c50704
JH
1663 if (!q) break;
1664 p = q+1;
1665 }
3045f050 1666
10c50704 1667 sig_hdr = string_copy(sig->rawsig_no_b_val);
80a47a2c 1668 }
80a47a2c
TK
1669 }
1670
0d04a285 1671 DEBUG(D_acl) debug_printf(
3045f050 1672 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
80a47a2c 1673
9e70917d
JH
1674 DEBUG(D_acl)
1675 {
1676 debug_printf(
1677 "PDKIM >> Signed DKIM-Signature header, pre-canonicalized >>>>>>>>>>>>>\n");
1678 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
1679 debug_printf(
1680 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1681 }
1682
3045f050
JH
1683 /* Relax header if necessary */
1684 if (sig->canon_headers == PDKIM_CANON_RELAXED)
ea18931d 1685 sig_hdr = pdkim_relax_header(sig_hdr, FALSE);
80a47a2c 1686
0d04a285 1687 DEBUG(D_acl)
3045f050 1688 {
4ff848b5
JH
1689 debug_printf("PDKIM >> Signed DKIM-Signature header, canonicalized (%-7s) >>>>>>>\n",
1690 pdkim_canons[sig->canon_headers]);
e2e3255a 1691 pdkim_quoteprint(CUS sig_hdr, Ustrlen(sig_hdr));
0d04a285 1692 debug_printf(
3045f050 1693 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
80a47a2c 1694 }
3045f050
JH
1695
1696 /* Finalize header hash */
e2e3255a 1697 exim_sha_update(&hhash_ctx, CUS sig_hdr, Ustrlen(sig_hdr));
2592e6c0 1698 exim_sha_finish(&hhash_ctx, &hhash);
3045f050 1699
f444c2c7
JH
1700 DEBUG(D_acl)
1701 {
9e70917d
JH
1702 debug_printf("PDKIM [%s] Header %s computed: ",
1703 sig->domain, pdkim_hashes[sig->hashtype].dkim_hashname);
2592e6c0 1704 pdkim_hexprint(hhash.data, hhash.len);
80a47a2c
TK
1705 }
1706
9e70917d
JH
1707 /* Remember headers block for signing (when the signing library cannot do
1708 incremental) */
e983e85a 1709 if (ctx->flags & PDKIM_MODE_SIGN)
acec9514 1710 hdata = exim_dkim_data_append(hdata, US sig_hdr);
f444c2c7 1711
3045f050 1712 /* SIGNING ---------------------------------------------------------------- */
e983e85a 1713 if (ctx->flags & PDKIM_MODE_SIGN)
3045f050 1714 {
286b9d5f 1715 hashmethod hm = sig->keytype == KEYTYPE_ED25519
cb78c1a8
JH
1716#if defined(SIGN_OPENSSL)
1717 ? HASH_NULL
1718#else
1719 ? HASH_SHA2_512
1720#endif
1721 : pdkim_hashes[sig->hashtype].exim_hashmethod;
f444c2c7 1722
286b9d5f
JH
1723#ifdef SIGN_HAVE_ED25519
1724 /* For GCrypt, and for EC, we pass the hash-of-headers to the signing
1725 routine. For anything else we just pass the headers. */
f444c2c7 1726
286b9d5f 1727 if (sig->keytype != KEYTYPE_ED25519)
f444c2c7 1728#endif
286b9d5f
JH
1729 {
1730 hhash.data = hdata->s;
1731 hhash.len = hdata->ptr;
1732 }
f444c2c7 1733
286b9d5f 1734 if ((*err = exim_dkim_sign(&sctx, hm, &hhash, &sig->sighash)))
f444c2c7 1735 {
286b9d5f 1736 log_write(0, LOG_MAIN|LOG_PANIC, "signing: %s", *err);
f444c2c7
JH
1737 return PDKIM_ERR_RSA_SIGNING;
1738 }
80a47a2c 1739
0d04a285 1740 DEBUG(D_acl)
3045f050 1741 {
0d04a285 1742 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
dcd03763 1743 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
80a47a2c 1744 }
80a47a2c 1745
ca9cb170 1746 sig->signature_header = pdkim_create_header(sig, TRUE);
80a47a2c 1747 }
80a47a2c 1748
3045f050
JH
1749 /* VERIFICATION ----------------------------------------------------------- */
1750 else
1751 {
2592e6c0 1752 ev_ctx vctx;
cb78c1a8 1753 hashmethod hm;
3045f050 1754
07eeb4df 1755 /* Make sure we have all required signature tags */
1756 if (!( sig->domain && *sig->domain
1757 && sig->selector && *sig->selector
1758 && sig->headernames && *sig->headernames
1759 && sig->bodyhash.data
dcd03763 1760 && sig->sighash.data
d73e45df
JH
1761 && sig->keytype >= 0
1762 && sig->hashtype >= 0
07eeb4df 1763 && sig->version
1764 ) )
1765 {
1766 sig->verify_status = PDKIM_VERIFY_INVALID;
1767 sig->verify_ext_status = PDKIM_VERIFY_INVALID_SIGNATURE_ERROR;
1768
1769 DEBUG(D_acl) debug_printf(
d9604f37
JH
1770 " Error in DKIM-Signature header: tags missing or invalid (%s)\n"
1771 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
1772 !(sig->domain && *sig->domain) ? "d="
1773 : !(sig->selector && *sig->selector) ? "s="
1774 : !(sig->headernames && *sig->headernames) ? "h="
1775 : !sig->bodyhash.data ? "bh="
1776 : !sig->sighash.data ? "b="
1777 : sig->keytype < 0 || sig->hashtype < 0 ? "a="
1778 : "v="
1779 );
07eeb4df 1780 goto NEXT_VERIFY;
1781 }
d9604f37 1782
07eeb4df 1783 /* Make sure sig uses supported DKIM version (only v1) */
1784 if (sig->version != 1)
1785 {
1786 sig->verify_status = PDKIM_VERIFY_INVALID;
1787 sig->verify_ext_status = PDKIM_VERIFY_INVALID_DKIM_VERSION;
1788
1789 DEBUG(D_acl) debug_printf(
1790 " Error in DKIM-Signature header: unsupported DKIM version\n"
1791 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1792 goto NEXT_VERIFY;
1793 }
1794
9e70917d
JH
1795 DEBUG(D_acl)
1796 {
1797 debug_printf( "PDKIM [%s] b from mail: ", sig->domain);
1798 pdkim_hexprint(sig->sighash.data, sig->sighash.len);
1799 }
1800
b9df1829 1801 if (!(sig->pubkey = pdkim_key_from_dns(ctx, sig, &vctx, err)))
286b9d5f
JH
1802 {
1803 log_write(0, LOG_MAIN, "PDKIM: %s%s %s%s [failed key import]",
1804 sig->domain ? "d=" : "", sig->domain ? sig->domain : US"",
1805 sig->selector ? "s=" : "", sig->selector ? sig->selector : US"");
3045f050 1806 goto NEXT_VERIFY;
286b9d5f 1807 }
80a47a2c 1808
135e9496
JH
1809 /* If the pubkey limits to a list of specific hashes, ignore sigs that
1810 do not have the hash part of the sig algorithm matching */
1811
1812 if (sig->pubkey->hashes)
1813 {
1814 const uschar * list = sig->pubkey->hashes, * ele;
1815 int sep = ':';
1816 while ((ele = string_nextinlist(&list, &sep, NULL, 0)))
d73e45df 1817 if (Ustrcmp(ele, pdkim_hashes[sig->hashtype].dkim_hashname) == 0) break;
135e9496
JH
1818 if (!ele)
1819 {
d73e45df
JH
1820 DEBUG(D_acl) debug_printf("pubkey h=%s vs. sig a=%s_%s\n",
1821 sig->pubkey->hashes,
1822 pdkim_keytypes[sig->keytype],
1823 pdkim_hashes[sig->hashtype].dkim_hashname);
135e9496
JH
1824 sig->verify_status = PDKIM_VERIFY_FAIL;
1825 sig->verify_ext_status = PDKIM_VERIFY_FAIL_SIG_ALGO_MISMATCH;
1826 goto NEXT_VERIFY;
1827 }
1828 }
1829
cb78c1a8
JH
1830 hm = sig->keytype == KEYTYPE_ED25519
1831#if defined(SIGN_OPENSSL)
1832 ? HASH_NULL
1833#else
1834 ? HASH_SHA2_512
1835#endif
1836 : pdkim_hashes[sig->hashtype].exim_hashmethod;
1837
3045f050 1838 /* Check the signature */
cb78c1a8
JH
1839
1840 if ((*err = exim_dkim_verify(&vctx, hm, &hhash, &sig->sighash)))
3045f050 1841 {
b9df1829 1842 DEBUG(D_acl) debug_printf("headers verify: %s\n", *err);
3045f050
JH
1843 sig->verify_status = PDKIM_VERIFY_FAIL;
1844 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1845 goto NEXT_VERIFY;
ff7ddfd7
TK
1846 }
1847
2592e6c0 1848
4c04137d 1849 /* We have a winner! (if bodyhash was correct earlier) */
3045f050 1850 if (sig->verify_status == PDKIM_VERIFY_NONE)
286b9d5f 1851 {
3045f050 1852 sig->verify_status = PDKIM_VERIFY_PASS;
286b9d5f
JH
1853 verify_pass = TRUE;
1854 }
3045f050
JH
1855
1856NEXT_VERIFY:
1857
0d04a285 1858 DEBUG(D_acl)
3045f050 1859 {
286b9d5f
JH
1860 debug_printf("PDKIM [%s] %s signature status: %s",
1861 sig->domain, dkim_sig_to_a_tag(sig),
1862 pdkim_verify_status_str(sig->verify_status));
3045f050 1863 if (sig->verify_ext_status > 0)
0d04a285 1864 debug_printf(" (%s)\n",
3045f050
JH
1865 pdkim_verify_ext_status_str(sig->verify_ext_status));
1866 else
0d04a285 1867 debug_printf("\n");
80a47a2c 1868 }
80a47a2c 1869 }
80a47a2c
TK
1870 }
1871
3045f050
JH
1872/* If requested, set return pointer to signature(s) */
1873if (return_signatures)
1874 *return_signatures = ctx->sig;
80a47a2c 1875
286b9d5f
JH
1876return ctx->flags & PDKIM_MODE_SIGN || verify_pass
1877 ? PDKIM_OK : PDKIM_FAIL;
80a47a2c
TK
1878}
1879
1880
1881/* -------------------------------------------------------------------------- */
3045f050
JH
1882
1883DLLEXPORT pdkim_ctx *
617d3932 1884pdkim_init_verify(uschar * (*dns_txt_callback)(uschar *), BOOL dot_stuffing)
3045f050 1885{
ca9cb170 1886pdkim_ctx * ctx;
3045f050 1887
ca9cb170 1888ctx = store_get(sizeof(pdkim_ctx));
abe1010c 1889memset(ctx, 0, sizeof(pdkim_ctx));
3045f050 1890
e983e85a 1891if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
ca9cb170 1892ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
3045f050 1893ctx->dns_txt_callback = dns_txt_callback;
80a47a2c 1894
3045f050 1895return ctx;
80a47a2c
TK
1896}
1897
1898
1899/* -------------------------------------------------------------------------- */
80a47a2c 1900
9e70917d
JH
1901DLLEXPORT pdkim_signature *
1902pdkim_init_sign(pdkim_ctx * ctx,
1903 uschar * domain, uschar * selector, uschar * privkey,
1904 uschar * hashname, const uschar ** errstr)
3045f050 1905{
d73e45df 1906int hashtype;
cd1a5fe0 1907pdkim_signature * sig;
80a47a2c 1908
d73e45df 1909if (!domain || !selector || !privkey)
3045f050 1910 return NULL;
80a47a2c 1911
9e70917d 1912/* Allocate & init one signature struct */
80a47a2c 1913
9e70917d 1914sig = store_get(sizeof(pdkim_signature));
abe1010c 1915memset(sig, 0, sizeof(pdkim_signature));
80a47a2c 1916
3045f050 1917sig->bodylength = -1;
80a47a2c 1918
e2e3255a
JH
1919sig->domain = string_copy(US domain);
1920sig->selector = string_copy(US selector);
d73e45df 1921sig->privkey = string_copy(US privkey);
286b9d5f 1922sig->keytype = -1;
cb224393 1923
d73e45df
JH
1924for (hashtype = 0; hashtype < nelem(pdkim_hashes); hashtype++)
1925 if (Ustrcmp(hashname, pdkim_hashes[hashtype].dkim_hashname) == 0)
1926 { sig->hashtype = hashtype; break; }
1927if (hashtype >= nelem(pdkim_hashes))
7b83389d 1928 {
286b9d5f
JH
1929 log_write(0, LOG_MAIN|LOG_PANIC,
1930 "PDKIM: unrecognised hashname '%s'", hashname);
d73e45df
JH
1931 return NULL;
1932 }
1933
cd1a5fe0
JH
1934DEBUG(D_acl)
1935 {
1936 pdkim_signature s = *sig;
1937 ev_ctx vctx;
1938
328c5688 1939 debug_printf("PDKIM (checking verify key)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
b9df1829 1940 if (!pdkim_key_from_dns(ctx, &s, &vctx, errstr))
cd1a5fe0 1941 debug_printf("WARNING: bad dkim key in dns\n");
328c5688 1942 debug_printf("PDKIM (finished checking verify key)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
cd1a5fe0 1943 }
9e70917d 1944return sig;
6ab02e3f 1945}
80a47a2c 1946
f444c2c7 1947
80a47a2c 1948/* -------------------------------------------------------------------------- */
3045f050 1949
9e70917d
JH
1950DLLEXPORT void
1951pdkim_set_optional(pdkim_signature * sig,
1952 char * sign_headers,
1953 char * identity,
80a47a2c
TK
1954 int canon_headers,
1955 int canon_body,
1956 long bodylength,
80a47a2c 1957 unsigned long created,
3045f050
JH
1958 unsigned long expires)
1959{
3045f050 1960if (identity)
e2e3255a 1961 sig->identity = string_copy(US identity);
80a47a2c 1962
ca9cb170
JH
1963sig->sign_headers = string_copy(sign_headers
1964 ? US sign_headers : US PDKIM_DEFAULT_SIGN_HEADERS);
80a47a2c 1965
8ef02a06
JH
1966sig->canon_headers = canon_headers;
1967sig->canon_body = canon_body;
1968sig->bodylength = bodylength;
1969sig->created = created;
1970sig->expires = expires;
80a47a2c 1971
9e70917d
JH
1972return;
1973}
1974
1975
1976
cf1cce5e 1977/* Set up a blob for calculating the bodyhash according to the
617d3932 1978given needs. Use an existing one if possible, or create a new one.
cf1cce5e 1979
617d3932 1980Return: hashblob pointer, or NULL on error
cf1cce5e
JH
1981*/
1982pdkim_bodyhash *
617d3932
JH
1983pdkim_set_bodyhash(pdkim_ctx * ctx, int hashtype, int canon_method,
1984 long bodylength)
cf1cce5e
JH
1985{
1986pdkim_bodyhash * b;
1987
1988for (b = ctx->bodyhash; b; b = b->next)
617d3932
JH
1989 if ( hashtype == b->hashtype
1990 && canon_method == b->canon_method
1991 && bodylength == b->bodylength)
1992 {
0ae2cff6 1993 DEBUG(D_receive) debug_printf("PDKIM: using existing bodyhash %d/%d/%ld\n",
617d3932
JH
1994 hashtype, canon_method, bodylength);
1995 return b;
1996 }
cf1cce5e 1997
0ae2cff6 1998DEBUG(D_receive) debug_printf("PDKIM: new bodyhash %d/%d/%ld\n",
617d3932 1999 hashtype, canon_method, bodylength);
cf1cce5e
JH
2000b = store_get(sizeof(pdkim_bodyhash));
2001b->next = ctx->bodyhash;
617d3932
JH
2002b->hashtype = hashtype;
2003b->canon_method = canon_method;
2004b->bodylength = bodylength;
cf1cce5e 2005if (!exim_sha_init(&b->body_hash_ctx, /*XXX hash method: extend for sha512 */
617d3932 2006 pdkim_hashes[hashtype].exim_hashmethod))
cf1cce5e
JH
2007 {
2008 DEBUG(D_acl)
2009 debug_printf("PDKIM: hash init error, possibly nonhandled hashtype\n");
2010 return NULL;
2011 }
2012b->signed_body_bytes = 0;
2013b->num_buffered_blanklines = 0;
2014ctx->bodyhash = b;
617d3932
JH
2015return b;
2016}
2017
cf1cce5e 2018
617d3932
JH
2019/* Set up a blob for calculating the bodyhash according to the
2020needs of this signature. Use an existing one if possible, or
2021create a new one.
2022
2023Return: hashblob pointer, or NULL on error (only used as a boolean).
2024*/
2025pdkim_bodyhash *
2026pdkim_set_sig_bodyhash(pdkim_ctx * ctx, pdkim_signature * sig)
2027{
2028pdkim_bodyhash * b = pdkim_set_bodyhash(ctx,
2029 sig->hashtype, sig->canon_body, sig->bodylength);
cf1cce5e
JH
2030sig->calc_body_hash = b;
2031return b;
2032}
2033
2034
2035/* -------------------------------------------------------------------------- */
2036
2037
9e70917d
JH
2038void
2039pdkim_init_context(pdkim_ctx * ctx, BOOL dot_stuffed,
617d3932 2040 uschar * (*dns_txt_callback)(uschar *))
9e70917d
JH
2041{
2042memset(ctx, 0, sizeof(pdkim_ctx));
2043ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
2044ctx->linebuf = store_get(PDKIM_MAX_BODY_LINE_LEN);
2045DEBUG(D_acl) ctx->dns_txt_callback = dns_txt_callback;
6ab02e3f 2046}
3045f050 2047
3045f050 2048
2592e6c0
JH
2049void
2050pdkim_init(void)
2051{
9b2583c4 2052exim_dkim_init();
2592e6c0
JH
2053}
2054
2055
2056
f444c2c7 2057#endif /*DISABLE_DKIM*/