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