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