1 /* This file is part of Mailfromd.
2    Copyright (C) 2020-2021 Sergey Poznyakoff
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <nettle/sha2.h>
25 #include <nettle/buffer.h>
26 #include <nettle/rsa.h>
27 #include <nettle/base64.h>
28 #include <nettle/asn1.h>
29 #include "mailfromd.h"
30 #include <mailutils/imaputil.h>
31 #include "dkim.h"
32 
33 /*
34  * Read public and private rsa keys from file.
35  * Matching code derived from pkcs1-conv.c in Nettle.
36  */
37 
38 static const uint8_t pem_start_pattern[] = "-----BEGIN ";
39 static int pem_start_pattern_length = sizeof(pem_start_pattern) - 1;
40 static const uint8_t pem_end_pattern[] = "-----END ";
41 static int pem_end_pattern_length = sizeof(pem_end_pattern) - 1;
42 static const uint8_t pem_trailer_pattern[] = "-----";
43 static int pem_trailer_pattern_length = sizeof(pem_trailer_pattern) - 1;
44 
45 enum {
46 	READ_PEM_OK,
47 	READ_PEM_ERROR,
48 	READ_PEM_EOF
49 };
50 
51 /* Returns READ_PEM_OK on match. */
52 static int
match_pem_start(size_t length,const uint8_t * line,size_t * marker_start,size_t * marker_length)53 match_pem_start(size_t length, const uint8_t *line,
54 		size_t *marker_start,
55 		size_t *marker_length)
56 {
57 	while (length > 0 && mu_isspace(line[length - 1]))
58 		length--;
59 
60 	if (length > (pem_start_pattern_length + pem_trailer_pattern_length)
61 	    && memcmp(line, pem_start_pattern, pem_start_pattern_length) == 0
62 	    && memcmp(line + length - pem_trailer_pattern_length,
63 		      pem_trailer_pattern, pem_trailer_pattern_length) == 0) {
64 		*marker_start = pem_start_pattern_length;
65 		*marker_length = length -
66 			(pem_start_pattern_length + pem_trailer_pattern_length);
67 		return READ_PEM_OK;
68 	}
69 	return READ_PEM_ERROR;
70 }
71 
72 /* Returns READ_PEM_OK on match, READ_PEM_EOF if the line is of the right
73    form except for the marker, otherwise READ_PEM_ERROR. */
74 static int
match_pem_end(size_t length,const uint8_t * line,size_t marker_length,const uint8_t * marker)75 match_pem_end(size_t length, const uint8_t *line,
76 	      size_t marker_length,
77 	      const uint8_t *marker)
78 {
79 	while (length > 0 && mu_isspace(line[length - 1]))
80 		length--;
81 
82 	if (length > (pem_end_pattern_length + pem_trailer_pattern_length)
83 	    && memcmp(line, pem_end_pattern, pem_end_pattern_length) == 0
84 	    && memcmp(line + length - pem_trailer_pattern_length,
85 		      pem_trailer_pattern, pem_trailer_pattern_length) == 0) {
86 		if (length == marker_length +
87 		    (pem_end_pattern_length + pem_trailer_pattern_length)
88 		    && memcmp(line + pem_end_pattern_length, marker,
89 			      marker_length) == 0)
90 			return READ_PEM_OK;
91 		else
92 			return READ_PEM_EOF;
93 	}
94 
95 	return READ_PEM_ERROR;
96 }
97 
98 struct pem_info {
99 	size_t marker_start;
100 	size_t marker_length;
101 	size_t data_start;
102 	size_t data_length;
103 };
104 
105 /* Read a single line from file into buffer. */
106 static int
read_line(FILE * fp,struct nettle_buffer * buffer)107 read_line(FILE *fp, struct nettle_buffer *buffer)
108 {
109 	int c;
110 
111 	while ((c = getc(fp)) != EOF) {
112 		if (!NETTLE_BUFFER_PUTC(buffer, c))
113 			return READ_PEM_ERROR;
114 
115 		if (c == '\n')
116 			return READ_PEM_OK;
117 	}
118 	if (ferror(fp))
119 		return READ_PEM_ERROR;
120 
121 	return READ_PEM_EOF;
122 }
123 
124 /* Read PEM file into buffer and parse it.  Arguments:
125  *
126  * fp          input file.
127  * buffer      buffer to read PEM into.
128  * info        fill this structure with information about PEM structure.
129  */
130 static int
read_pem(FILE * fp,struct nettle_buffer * buffer,struct pem_info * info)131 read_pem(FILE *fp, struct nettle_buffer *buffer, struct pem_info *info)
132 {
133 	int rc;
134 
135 	/* Find start line */
136 	for (;;) {
137 		nettle_buffer_reset(buffer);
138 		rc = read_line(fp, buffer);
139 		if (rc != READ_PEM_OK)
140 			return rc;
141 
142 		if (match_pem_start(buffer->size, buffer->contents,
143 				    &info->marker_start,
144 				    &info->marker_length) == READ_PEM_OK)
145 			break;
146 	}
147 
148 	buffer->contents[info->marker_start + info->marker_length] = 0;
149 
150 	info->data_start = buffer->size;
151 
152 	for (;;) {
153 		size_t line_start = buffer->size;
154 
155 		if ((rc = read_line(fp, buffer)) != READ_PEM_OK)
156 			return rc;
157 
158 		switch (match_pem_end(buffer->size - line_start,
159 				      buffer->contents + line_start,
160 				      info->marker_length,
161 				      buffer->contents + info->marker_start)) {
162 		case READ_PEM_OK:
163 			info->data_length = line_start - info->data_start;
164 			return READ_PEM_OK;
165 		case READ_PEM_ERROR:
166 			break;
167 		case READ_PEM_EOF:
168 			return READ_PEM_EOF;
169 		}
170 	}
171 	return READ_PEM_ERROR;
172 }
173 
174 static inline int
base64_decode_in_place(struct base64_decode_ctx * ctx,size_t * dst_length,size_t length,uint8_t * data)175 base64_decode_in_place (struct base64_decode_ctx *ctx, size_t *dst_length,
176 			size_t length, uint8_t *data)
177 {
178 	return base64_decode_update(ctx, dst_length,
179 				    data, length,
180 				    (const uint8_t *) data);
181 }
182 
183 static int
decode_base64(struct nettle_buffer * buffer,size_t start,size_t * length)184 decode_base64(struct nettle_buffer *buffer, size_t start, size_t *length)
185 {
186 	struct base64_decode_ctx ctx;
187 
188 	base64_decode_init(&ctx);
189 
190 	/* Decode in place */
191 	if (base64_decode_in_place(&ctx, length, *length,
192 				   buffer->contents + start)
193 	    && base64_decode_final(&ctx))
194 		return READ_PEM_OK;
195 	return READ_PEM_ERROR;
196 }
197 
198 static int
convert_rsa_private_key(uint8_t * buffer,size_t size,struct rsa_public_key * pub,struct rsa_private_key * priv)199 convert_rsa_private_key(uint8_t *buffer, size_t size,
200 			struct rsa_public_key *pub,
201 			struct rsa_private_key *priv)
202 {
203 	rsa_public_key_init(pub);
204 	rsa_private_key_init(priv);
205 	return rsa_keypair_from_der(pub, priv, 0, size, buffer)
206 		? READ_PEM_OK : READ_PEM_ERROR;
207 }
208 
209 /* Read a private key PEM file and return RSA key pair. */
210 static int
read_keys(FILE * fp,struct rsa_public_key * pub,struct rsa_private_key * priv)211 read_keys(FILE *fp, struct rsa_public_key *pub, struct rsa_private_key *priv)
212 {
213 	struct nettle_buffer buffer;
214 	struct pem_info info;
215 	static char privkey_marker[] = "RSA PRIVATE KEY";
216 	static size_t privkey_marker_length = sizeof(privkey_marker) - 1;
217 	int rc;
218 
219 	nettle_buffer_init_realloc(&buffer, NULL, nettle_xrealloc);//FIXME
220 	rc = read_pem(fp, &buffer, &info);
221 	if (info.marker_length == privkey_marker_length
222 	    && memcmp(buffer.contents + info.marker_start, privkey_marker,
223 		      privkey_marker_length) == 0
224 	    && decode_base64(&buffer, info.data_start,
225 			     &info.data_length) == READ_PEM_OK
226 	    && convert_rsa_private_key(buffer.contents + info.data_start,
227 				       info.data_length,
228 				       pub, priv) == READ_PEM_OK)
229 		rc = READ_PEM_OK;
230 	else
231 		rc = READ_PEM_ERROR;
232 	nettle_buffer_clear(&buffer);
233 
234 	return rc;
235 }
236 
237 static int
pubkey_from_base64(struct rsa_public_key * pub,const char * str)238 pubkey_from_base64(struct rsa_public_key *pub, const char *str)
239 {
240 	struct nettle_buffer buffer;
241 	size_t length = strlen(str);
242 	struct asn1_der_iterator i, j;
243 	int result = READ_PEM_ERROR;
244 
245 	nettle_buffer_init_realloc(&buffer, NULL, nettle_xrealloc);
246 	nettle_buffer_write(&buffer, strlen(str), (const uint8_t*) str);
247 	if (decode_base64(&buffer, 0, &length) == READ_PEM_OK
248 
249 	/* SubjectPublicKeyInfo ::= SEQUENCE {
250 	       algorithm		AlgorithmIdentifier,
251 	       subjectPublicKey 	BIT STRING
252 	   }
253 
254 	   AlgorithmIdentifier ::= SEQUENCE {
255 	       algorithm  	OBJECT IDENTIFIER,
256 	       parameters 	OPTIONAL
257 	   }
258 	*/
259 
260 	    && asn1_der_iterator_first(&i, length, buffer.contents) == ASN1_ITERATOR_CONSTRUCTED
261 	    && i.type == ASN1_SEQUENCE
262 	    && asn1_der_decode_constructed_last(&i) == ASN1_ITERATOR_CONSTRUCTED
263 	    && i.type == ASN1_SEQUENCE
264 
265 	    /* Use the j iterator to parse the algorithm identifier */
266 	    && asn1_der_decode_constructed(&i, &j) == ASN1_ITERATOR_PRIMITIVE
267 	    && j.type == ASN1_IDENTIFIER
268 	    && asn1_der_iterator_next(&i) == ASN1_ITERATOR_PRIMITIVE
269 	    && i.type == ASN1_BITSTRING
270 
271 	    /* Use i to parse the object wrapped in the bit string.*/
272 	    && asn1_der_decode_bitstring_last(&i)) {
273 		/* pkcs-1 {
274 		       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
275 		       pkcs-1(1) modules(0) pkcs-1(1)
276 		   }
277 
278 		   --
279 		   -- When rsaEncryption is used in an AlgorithmIdentifier the
280 		   -- parameters MUST be present and MUST be NULL.
281 		   --
282 		   rsaEncryption    OBJECT IDENTIFIER ::= { pkcs-1 1 }
283 		*/
284 		static const uint8_t id_rsaEncryption[9] =
285 			{ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
286 
287 		if (j.length == sizeof(id_rsaEncryption)
288 		    && memcmp(j.data, id_rsaEncryption,
289 			      sizeof(id_rsaEncryption)) == 0
290 		    && asn1_der_iterator_next(&j) == ASN1_ITERATOR_PRIMITIVE
291 		    && j.type == ASN1_NULL
292 		    && j.length == 0
293 		    && asn1_der_iterator_next(&j) == ASN1_ITERATOR_END) {
294 			rsa_public_key_init(pub);
295 
296 			if (rsa_public_key_from_der_iterator(pub, 0, &i))
297 				result = READ_PEM_OK;
298 		}
299 	}
300 	nettle_buffer_clear(&buffer);
301 	return result;
302 }
303 
304 /* State of iteratiom over a colon-separated list of headers. */
305 struct h_list_buf {
306 	char const *ptr;  /* Current position in the header list. */
307 	char *base;       /* Return memory pointer. */
308 	size_t size;      /* Size of memory allocated for base. */
309 };
310 
311 /*
312  * dkim_header_list_next(SAVE)
313  * ---------------------------
314  * Free the state buffer allocated by dkim_header_list_first.
315  */
316 void
dkim_header_list_end(void * save)317 dkim_header_list_end(void *save)
318 {
319 	struct h_list_buf *hbuf = save;
320 	free(hbuf->base);
321 	free(hbuf);
322 }
323 
324 /*
325  * Return next header from the header list, or NULL if the list is exhausted.
326  * SAVE is the iteration state pointer returned by dkim_header_list_first.
327  */
328 static char *
dkim_header_list_next(void * save)329 dkim_header_list_next(void *save)
330 {
331 	struct h_list_buf *hbuf = save;
332 	char const *hp = hbuf->ptr;
333 
334 	while (*hp && (*hp == ' ' || *hp == '\t' || *hp == ':'))
335 		hp++;
336 	if (*hp) {
337 		size_t len = strcspn(hp, " \t:");
338 		if (len + 1 > hbuf->size) {
339 			hbuf->base = mu_realloc(hbuf->base, len + 1);
340 			hbuf->size = len + 1;
341 		}
342 		memcpy(hbuf->base, hp, len);
343 		hbuf->base[len] = 0;
344 		hbuf->ptr = hp + len;
345 	} else {
346 		hbuf->ptr = hp;
347 		return NULL;
348 	}
349 	return hbuf->base;
350 }
351 
352 /*
353  * Start iteration over a list of header names (H_LIST), delimited by
354  * colons with optional whitespace around them.  Return first header
355  * name and save the state in the memory location pointed to by SAVE.
356  * No matter the return value, dkim_header_list_end must be called to
357  * reclaim the allocated memory.
358  */
359 char *
dkim_header_list_first(char const * h_list,void * save)360 dkim_header_list_first(char const *h_list, void *save)
361 {
362 	struct h_list_buf *hbuf, **hbuf_ptr = save;
363 
364 	hbuf = mu_alloc(sizeof(hbuf[0]));
365 	hbuf->ptr = h_list;
366 	hbuf->base = NULL;
367 	hbuf->size = 0;
368 	*hbuf_ptr = hbuf;
369 	return dkim_header_list_next(hbuf);
370 }
371 
372 int
dkim_header_list_match(char const * h_list,char const * h)373 dkim_header_list_match(char const *h_list, char const *h)
374 {
375 	size_t len = strlen (h);
376 	while (*h_list) {
377 		size_t n;
378 
379 		while (*h_list && (*h_list == ' ' || *h_list == '\t'))
380 			h_list++;
381 		if (*h_list == 0)
382 			break;
383 
384 		n = strcspn(h_list, " \t:");
385 		if (n == len && mu_c_strncasecmp (h_list, h, len) == 0)
386 			return 1;
387 		h_list += n;
388 
389 		while (*h_list && (*h_list == ' ' || *h_list == '\t'))
390 			h_list++;
391 		if (*h_list != ':')
392 			break;
393 		++h_list;
394 	}
395 	return 0;
396 }
397 
398 /*
399  * SHA256 hashing functions.
400  */
401 
402 #define BUF_SIZE 1024
403 
404 /* Hash the contents read from the mailutils stream STR starting from
405  * the current position and up to the end of file.
406  */
407 static int
hash_stream(mu_stream_t str,struct sha256_ctx * ctx)408 hash_stream(mu_stream_t str, struct sha256_ctx *ctx)
409 {
410 	uint8_t buffer[BUF_SIZE];
411 	size_t count;
412 	int rc;
413 
414 	while ((rc = mu_stream_read(str, buffer, sizeof(buffer), &count)) == 0
415 	       && count > 0) {
416 //		mu_error("READ %*.*s", (int)count, (int)count, buffer);
417 		sha256_update(ctx, count, buffer);
418 	}
419 
420 	if (rc) {
421 		mu_diag_funcall(MU_DIAG_ERROR, "mu_stream_read", NULL, rc);
422 		return -1;
423 	}
424 
425 	return 0;
426 }
427 
428 /* Hash LEN bytes from the current position in stream STR. */
429 static int
hash_stream_segment(mu_stream_t str,size_t len,struct sha256_ctx * ctx)430 hash_stream_segment(mu_stream_t str, size_t len, struct sha256_ctx *ctx)
431 {
432 	while (len) {
433 		uint8_t buffer[BUF_SIZE];
434 		int rc;
435 		size_t n = sizeof(buffer), count;
436 		if (n > len)
437 			n = len;
438 		rc = mu_stream_read(str, buffer, n, &count);
439 		//printf("HASH %*.*s\n",(int)count,(int)count,buffer);
440 		if (rc) {
441 			mu_diag_funcall(MU_DIAG_ERROR, "mu_stream_read", NULL,
442 					rc);
443 			return -1;
444 		}
445 		if (count == 0) {
446 			mu_error(_("unexpected end of file in canonical stream"));
447 			return -1;
448 		}
449 		sha256_update(ctx, count, buffer);
450 		len -= count;
451 	}
452 
453 	return 0;
454 }
455 
456 /* Hash the remaining content of the stream from the current position
457  * and store a nul-terminated base64 encoded result in outbuf.
458  * Outbuf must have at least BASE64_ENCODE_RAW_LENGTH(SHA256_DIGEST_SIZE) + 1
459  * bytes of capacity,
460  */
461 static int
dkim_body_hash(mu_stream_t str,size_t len,uint8_t * outbuf)462 dkim_body_hash(mu_stream_t str, size_t len, uint8_t *outbuf)
463 {
464 	struct sha256_ctx ctx;
465 	uint8_t body_digest[SHA256_DIGEST_SIZE];
466 
467 	sha256_init(&ctx);
468 	if (len == DKIM_LENGTH_ALL)
469 		hash_stream(str, &ctx);
470 	else
471 		hash_stream_segment(str, len, &ctx);
472 	sha256_digest(&ctx, sizeof(body_digest), body_digest);
473 	base64_encode_raw(outbuf, sizeof(body_digest), body_digest);
474 
475 	return 0;
476 }
477 
478 /*
479  * RSA SHA256 digest.
480  */
481 
482 /* Given the RSA private key and a pointer to SHA256 context, create the
483  * RSA digest in base64.  Return value is stored in RET_B64 (malloced).
484  */
485 int
dkim_rsa_sha256_sign(struct rsa_private_key * priv,struct sha256_ctx * ctx,uint8_t ** ret_b64)486 dkim_rsa_sha256_sign(struct rsa_private_key *priv, struct sha256_ctx *ctx,
487 		     uint8_t **ret_b64)
488 {
489 	int rc;
490 	mpz_t sig;
491 	size_t i;
492 	struct nettle_buffer buffer;
493 	uint8_t *outbuf;
494 
495 	mpz_init(sig);
496 	rc = rsa_sha256_sign(priv, ctx, sig);
497 	if (!rc)
498 		return -1;
499 
500 	nettle_buffer_init_realloc(&buffer, NULL, nettle_xrealloc);//FIXME
501 	for (i = mpz_size(sig); i > 0; i--) {
502 		mp_limb_t limb = mpz_getlimbn(sig, i - 1);
503 		size_t j;
504 		uint8_t *p = nettle_buffer_space(&buffer, sizeof(mp_limb_t))
505 			     + sizeof(mp_limb_t) - 1;
506 		for (j = 0; j < sizeof(mp_limb_t); j++) {
507 			*p-- = limb & 0xff;
508 			limb >>= 8;
509 		}
510 	}
511 	mpz_clear(sig);
512 
513 	outbuf = malloc(BASE64_ENCODE_RAW_LENGTH(buffer.size) + 1);
514 	if (!outbuf) {
515 		nettle_buffer_clear(&buffer);
516 		return -1;
517 	}
518 
519 	base64_encode_raw(outbuf, buffer.size, buffer.contents);
520 	outbuf[BASE64_ENCODE_RAW_LENGTH(buffer.size)] = 0;
521 	nettle_buffer_clear(&buffer);
522 
523 	*ret_b64 = outbuf;
524 
525 	return 0;
526 }
527 
528 /*
529  * Canonicalization names
530  * re. "DKIM-Signature Canonicalization Header" IANA registry.
531  */
532 static char const *dkim_canon_string[] = { "simple", "relaxed", NULL };
533 #define DKIM_CANON_STRING_MAX (sizeof(dkim_canon_string[DKIM_CANON_RELAXED])-1)
534 /*
535  * Convert STR to a DKIM_CANON_* constant (return DKIM_CANON_ERR on error).
536  * If ENDP is NULL, STR must be one of the strings from dkim_canon_string.
537  * Otherwise, STR may be followed by '\0' or '/'.  The pointer to that
538  * character will be returned in the memory location pointed to by ENDP.
539  */
540 int
dkim_str_to_canon_type(char const * str,char ** endp)541 dkim_str_to_canon_type(char const *str, char **endp)
542 {
543 	int i;
544 	size_t len = strcspn(str, "/");
545 	if (endp || str[len] == 0) {
546 		for (i = 0; dkim_canon_string[i]; i++)
547 			if (len == strlen(dkim_canon_string[i]) &&
548 			    memcmp(str, dkim_canon_string[i], len) == 0) {
549 				if (endp)
550 					*endp = (char*)(str + len);
551 				return i;
552 			}
553 	}
554 	return DKIM_CANON_ERR;
555 }
556 
557 /* Format a struct dkim_signature as a DKIM-Signature header. */
558 
559 #define MAX_LINE_LEN 78
560 
561 struct dkim_format_buf {
562 	mu_stream_t str;
563 	mu_stream_stat_buffer stat;
564 	int crlf;
565 };
566 
567 static inline void
dkim_format_nl(struct dkim_format_buf * fb)568 dkim_format_nl(struct dkim_format_buf *fb)
569 {
570 	if (fb->crlf)
571 		mu_stream_write(fb->str, "\r\n ", 3, NULL);
572 	else
573 		mu_stream_write(fb->str, "\n ", 2, NULL);
574 	fb->stat[MU_STREAM_STAT_OUT] = 0;
575 }
576 
577 static inline int
dkim_format_wrap(struct dkim_format_buf * fb,size_t len)578 dkim_format_wrap(struct dkim_format_buf *fb, size_t len)
579 {
580 	if (fb->stat[MU_STREAM_STAT_OUT]
581 	    && fb->stat[MU_STREAM_STAT_OUT] + len > MAX_LINE_LEN) {
582 		dkim_format_nl(fb);
583 		return 1;
584 	}
585 	return 0;
586 }
587 
588 static void
dkim_format_tag(struct dkim_format_buf * fb,char const * tag,char const * val)589 dkim_format_tag(struct dkim_format_buf *fb, char const *tag, char const *val)
590 {
591 	if (!val)
592 		return;
593 	if (!dkim_format_wrap(fb, strlen(tag) + strlen(val) + 2))
594 		dkim_format_wrap(fb, strlen(tag) + 1);
595 	mu_stream_write(fb->str, tag, strlen(tag), NULL);
596 	mu_stream_write(fb->str, "=", 1, NULL);
597 	dkim_format_wrap(fb, strlen(val) + 1);
598 	mu_stream_write(fb->str, val, strlen(val), NULL);
599 	mu_stream_write(fb->str, ";", 1, NULL);
600 }
601 
602 static void
dkim_format_tag_base64(struct dkim_format_buf * fb,char const * tag,char const * val)603 dkim_format_tag_base64(struct dkim_format_buf *fb, char const *tag,
604 		       char const *val)
605 {
606 	size_t len = strlen(val);
607 
608 	if (!dkim_format_wrap(fb, strlen(tag) + strlen(val) + 2))
609 		dkim_format_wrap(fb, strlen(tag) + 1);
610 	mu_stream_write(fb->str, tag, strlen(tag), NULL);
611 	mu_stream_write(fb->str, "=", 1, NULL);
612 
613 	while (len > 0) {
614 		size_t n = MAX_LINE_LEN - fb->stat[MU_STREAM_STAT_OUT];
615 		if (len < n)
616 			n = len;
617 		mu_stream_write(fb->str, val, n, NULL);
618 		dkim_format_wrap(fb, 1);
619 		val += n;
620 		len -= n;
621 	}
622 	mu_stream_write(fb->str, ";", 1, NULL);
623 }
624 
625 void
dkim_signature_free(struct dkim_signature * sig)626 dkim_signature_free(struct dkim_signature *sig)
627 {
628 	free(sig->a);
629 	free(sig->b);
630 	free(sig->bh);
631 	free(sig->d);
632 	free(sig->s);
633 	free(sig->h);
634 	free(sig->i);
635 	free(sig->q);
636 	free(sig->v);
637 }
638 
639 /*
640  * Auxiliary functions for parsing and formatting dkim_signature fields.
641  *
642  * Each parser is declared as
643  *   int P(char const *value, void *data)
644  * Its arguments are:
645  *   value  -  actual tag value obtained from the header.
646  *   data   -  pointer to the member of struct dkim_signature.
647  * The parser returns 0 on success and non-zero on error.  It is not supposed
648  * to emit any diagnostic messages.
649  *
650  * Each formatter is declared as
651  *   int F(struct dkim_format_buf *fb, char const *tag, void *data)
652  * Its arguments are:
653  *   fb     -  formatting buffer,
654  *   tag    -  the tag name,
655  *   value  -  pointer to the member of struct dkim_signature.
656  */
657 
658 /* General purpose parser for char* (or uint8_t*) fields */
659 static int
dkim_tag_char_parser(char const * value,void * data)660 dkim_tag_char_parser(char const *value, void *data)
661 {
662 	char **cptr = data;
663 	*cptr = mu_strdup(value);
664 	return 0;
665 }
666 
667 /* General purpose formatter for char* (or uint8_t*) fields */
668 static void
dkim_tag_char_formatter(struct dkim_format_buf * fb,char const * tag,void * data)669 dkim_tag_char_formatter(struct dkim_format_buf *fb,
670 			char const *tag,
671 			void *data)
672 {
673 	char **cptr = data;
674 	dkim_format_tag(fb, tag, *cptr);
675 }
676 
677 /* Formatter for the a= tag */
678 static void
dkim_tag_a_formatter(struct dkim_format_buf * fb,char const * tag,void * data)679 dkim_tag_a_formatter(struct dkim_format_buf *fb,
680 		     char const *tag,
681 		     void *data)
682 {
683 	char **cptr = data;
684 	dkim_format_tag(fb, tag, *cptr ? *cptr : DKIM_ALGORITHM);
685 }
686 
687 /* Formatter for the q= tag */
688 static void
dkim_tag_q_formatter(struct dkim_format_buf * fb,char const * tag,void * data)689 dkim_tag_q_formatter(struct dkim_format_buf *fb,
690 		     char const *tag,
691 		     void *data)
692 {
693 	char **cptr = data;
694 	dkim_format_tag(fb, tag, *cptr ? *cptr : DKIM_QUERY_METHOD);
695 }
696 
697 /* Special formatter for the h= tag, that ensures proper wrapping. */
698 static void
dkim_tag_h_formatter(struct dkim_format_buf * fb,char const * tag,void * data)699 dkim_tag_h_formatter(struct dkim_format_buf *fb,
700 		     char const *tag,
701 		     void *data)
702 {
703 	char **cptr = data;
704 	void *save;
705 	char const *hval;
706 
707 	if (!dkim_format_wrap(fb, 2))
708 		dkim_format_wrap(fb, strlen(*cptr) + 3);
709 
710 	mu_stream_write(fb->str, "h=", 2, NULL);
711 
712 	if ((hval = dkim_header_list_first(*cptr, &save)) != NULL) {
713 		dkim_format_wrap(fb, strlen(hval));
714 		mu_stream_write(fb->str, hval, strlen(hval), NULL);
715 		while ((hval = dkim_header_list_next(save)) != NULL) {
716 			dkim_format_wrap(fb, strlen(hval) + 1);
717 			mu_stream_write(fb->str, ":", 1, NULL);
718 			mu_stream_write(fb->str, hval, strlen(hval), NULL);
719 		}
720 	}
721 	dkim_header_list_end(save);
722 	dkim_format_wrap(fb, 1);
723 	mu_stream_write(fb->str, ";", 1, NULL);
724 }
725 
726 /* Parser and formatter for the c= tag. */
727 static int
dkim_tag_c_parser(char const * value,void * data)728 dkim_tag_c_parser(char const *value, void *data)
729 {
730 	int *canon = data;
731 	char *s;
732 
733 	if ((canon[0] = dkim_str_to_canon_type(value, &s)) == DKIM_CANON_ERR)
734 		return -1;
735 	if (*s == 0)
736 		canon[1] = canon[0];
737 	else if (*s != '/' ||
738 		 (canon[1] = dkim_str_to_canon_type(s + 1, NULL)) == DKIM_CANON_ERR)
739 		return -1;
740 	return 0;
741 }
742 
743 static void
dkim_tag_c_formatter(struct dkim_format_buf * fb,char const * tag,void * data)744 dkim_tag_c_formatter(struct dkim_format_buf *fb,
745 		     char const *tag,
746 		     void *data)
747 {
748 	int *canon = data;
749 	char v[(DKIM_CANON_STRING_MAX+1)*2];
750 	strcpy(v, dkim_canon_string[canon[0]]);
751 	strcat(v, "/");
752 	strcat(v, dkim_canon_string[canon[1]]);
753 	dkim_format_tag(fb, tag, v);
754 }
755 
756 /* General-purpose parser and formatter for time_t members (t and x) */
757 static int
dkim_tag_time_parser(char const * value,void * data)758 dkim_tag_time_parser(char const *value, void *data)
759 {
760 	time_t *tptr = data;
761 	unsigned long n;
762 	char *p;
763 	errno = 0;
764 	n = strtoul(value, &p, 10);
765 	if (errno || *p)
766 		return -1;
767 	*tptr = n;
768 	return 0;
769 }
770 
771 static void
dkim_tag_time_formatter(struct dkim_format_buf * fb,char const * tag,void * data)772 dkim_tag_time_formatter(struct dkim_format_buf *fb,
773 			char const *tag,
774 			void *data)
775 {
776 	time_t *tptr = data;
777 
778 	if (*tptr) {
779 		char tbuf[80];
780 		snprintf(tbuf, sizeof(tbuf), "%lu", (long unsigned) *tptr);
781 		dkim_format_tag(fb, tag, tbuf);
782 	}
783 }
784 
785 /* Parser and formatter for the l= tag */
786 static int
dkim_tag_l_parser(char const * value,void * data)787 dkim_tag_l_parser(char const *value, void *data)
788 {
789 	size_t *sptr = data;
790 	unsigned long n;
791 	char *endp;
792 	errno = 0;
793 	n = strtoul(value, &endp, 10);
794 	if (errno || *endp)
795 		return -1;
796 	*sptr = n;
797 	return 0;
798 }
799 
800 static void
dkim_tag_l_formatter(struct dkim_format_buf * fb,char const * tag,void * data)801 dkim_tag_l_formatter(struct dkim_format_buf *fb,
802 		     char const *tag,
803 		     void *data)
804 {
805 	size_t *sptr = data;
806 	char tbuf[80];
807 	if (*sptr != DKIM_LENGTH_ALL) {
808 		snprintf(tbuf, sizeof(tbuf), "%zu", *sptr);
809 		dkim_format_tag(fb, tag, tbuf);
810 	}
811 }
812 
813 /* Formatter for the bh= tag. */
814 static void
dkim_tag_bh_formatter(struct dkim_format_buf * fb,char const * tag,void * data)815 dkim_tag_bh_formatter(struct dkim_format_buf *fb,
816 		      char const *tag,
817 		      void *data)
818 {
819 	char **sptr = data;
820 	dkim_format_tag_base64(fb, tag, *sptr);
821 }
822 
823 /* Formatter for the b= tag. */
824 static void
dkim_tag_b_formatter(struct dkim_format_buf * fb,char const * tag,void * data)825 dkim_tag_b_formatter(struct dkim_format_buf *fb,
826 		     char const *tag,
827 		      void *data)
828 {
829 	char **sptr = data;
830 	dkim_format_nl(fb);
831 	dkim_format_tag_base64(fb, tag, *sptr ? *sptr : "");
832 }
833 
834 /* Tag definition structure */
835 struct dkim_tag_descr {
836 	char *tag;       /* Tag name. */
837 	size_t off;      /* Field offset in struct dkim_signature. */
838 	int (*parser)(char const *, void *);
839        	                 /* Parser function. */
840 	void (*formatter)(struct dkim_format_buf *, char const *, void *);
841 	                 /* Formatter function. */
842 };
843 
844 /* Order of entries in this array defines the order in which tags are
845    formatted.
846 */
847 static struct dkim_tag_descr tag_descr[] = {
848 	{
849 		"v",
850 		offsetof(struct dkim_signature, v),
851 		dkim_tag_char_parser,
852 		dkim_tag_char_formatter,
853 	},
854 	{
855 		"a",
856 		offsetof(struct dkim_signature, a),
857 		dkim_tag_char_parser,
858 		dkim_tag_a_formatter
859 	},
860 	{
861 		"d",
862 		offsetof(struct dkim_signature, d),
863 		dkim_tag_char_parser,
864 		dkim_tag_char_formatter,
865 	},
866 	{
867 		"s",
868 		offsetof(struct dkim_signature, s),
869 		dkim_tag_char_parser,
870 		dkim_tag_char_formatter,
871 	},
872 	{
873 		"c",
874 		offsetof(struct dkim_signature, canon),
875 		dkim_tag_c_parser,
876 		dkim_tag_c_formatter
877 	},
878 	{
879 		"q",
880 		offsetof(struct dkim_signature, q),
881 		dkim_tag_char_parser,
882 		dkim_tag_q_formatter
883 	},
884 	{
885 		"h",
886 		offsetof(struct dkim_signature, h),
887 		dkim_tag_char_parser,
888 		dkim_tag_h_formatter,
889 	},
890 	{
891 		"i",
892 		offsetof(struct dkim_signature, i),
893 		dkim_tag_char_parser,
894 		dkim_tag_char_formatter,
895 	},
896 	{
897 		"l",
898 		offsetof(struct dkim_signature, l),
899 		dkim_tag_l_parser,
900 		dkim_tag_l_formatter
901 	},
902 	{
903 		"t",
904 		offsetof(struct dkim_signature, t),
905 		dkim_tag_time_parser,
906 		dkim_tag_time_formatter
907 	},
908 	{
909 		"x",
910 		offsetof(struct dkim_signature, x),
911 		dkim_tag_time_parser,
912 		dkim_tag_time_formatter
913 	},
914 	{
915 		"bh",
916 		offsetof(struct dkim_signature, bh),
917 		dkim_tag_char_parser,
918 		dkim_tag_bh_formatter
919 	},
920 	{
921 		"b",
922 		offsetof(struct dkim_signature, b),
923 		dkim_tag_char_parser,
924 		dkim_tag_b_formatter
925 	},
926 	{ NULL }
927 };
928 
929 /* Table-driven DKIM-Signature parser. */
930 int
dkim_signature_parse(char * str,struct dkim_signature * ret_sig)931 dkim_signature_parse(char *str, struct dkim_signature *ret_sig)
932 {
933 	struct mu_wordsplit ws;
934 	int i;
935 	int rc = 0;
936 	struct dkim_signature sig;
937 
938 	/*
939 	 * tag-list  =  tag-spec *( ";" tag-spec ) [ ";" ]
940 	 * tag-spec  =  [FWS] tag-name [FWS] "=" [FWS] tag-value [FWS]
941 	 *
942 	 * The mu_wordsplit call splits the value on ';' and removes
943 	 * whitespace at both sides of each token.  Internal FWS (around
944 	 * the equals sign) is removed later.
945 	 */
946 	ws.ws_delim = ";";
947 	rc = mu_wordsplit(str,
948 			  &ws,
949 			  MU_WRDSF_DELIM |
950 			  MU_WRDSF_NOVAR |
951 			  MU_WRDSF_WS |
952 			  MU_WRDSF_NOCMD);
953 	if (rc) {
954 		mu_wordsplit_free(&ws);
955 		return rc;
956 	}
957 
958 	memset(&sig, 0, sizeof(sig));
959 	sig.canon[0] = sig.canon[1] = DKIM_CANON_SIMPLE;
960 	sig.l = DKIM_LENGTH_ALL;
961 	for (i = 0; i < ws.ws_wordc; i++) {
962 		struct dkim_tag_descr *tg;
963 		char *k = ws.ws_wordv[i];
964 		char *p = strchr(k, '=');
965 		if (!p) {
966 			rc = -1;
967 			goto end;
968 		}
969 		*p++ = 0;
970 		/* Remove internal FWS */
971 		mu_rtrim_class(k, MU_CTYPE_BLANK);
972 		mu_ltrim_class(p, MU_CTYPE_BLANK);
973 		/* Handle known tags */
974 		for (tg = tag_descr; tg->tag; tg++) {
975 			if (strcmp(k, tg->tag) == 0) {
976 				rc = tg->parser(p, (char*)&sig + tg->off);
977 				if (rc)
978 					goto end;
979 				break;
980 			}
981 		}
982 	}
983 end:
984 	mu_wordsplit_free(&ws);
985 	if (rc)
986 		dkim_signature_free(&sig);
987 	else
988 		*ret_sig = sig;
989 	return rc;
990 }
991 
992 /*
993  * Table-driven DKIM-Signature formatter.
994  * The CRLF parameter defines what delimiter to use for wrapping.
995  */
996 int
dkim_signature_format(struct dkim_signature * sig,int crlf,char ** result)997 dkim_signature_format(struct dkim_signature *sig, int crlf, char **result)
998 {
999 	struct dkim_format_buf fb;
1000 	int rc;
1001 	static char header_field[] = DKIM_SIGNATURE_HEADER ": ";
1002 	mu_off_t off;
1003 	size_t size;
1004 	char *text;
1005 	struct dkim_tag_descr *tg;
1006 
1007 	/* Initialize format buffer */
1008 	fb.crlf = crlf;
1009 	rc = mu_memory_stream_create(&fb.str, MU_STREAM_RDWR);
1010 	if (rc) {
1011 		mu_diag_funcall(MU_DIAG_ERROR,
1012 				"mu_memory_stream_create",
1013 				NULL, rc);
1014 		return rc;
1015 	}
1016 	mu_stream_set_stat(fb.str,
1017 			   MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT),
1018 			   fb.stat);
1019 	mu_stream_write(fb.str, header_field, strlen(header_field), NULL);
1020 	for (tg = tag_descr; tg->tag; tg++) {
1021 		tg->formatter(&fb, tg->tag, ((char*)sig + tg->off));
1022 	}
1023 
1024 	if (mu_stream_err(fb.str)) {
1025 		rc = mu_stream_last_error(fb.str);
1026 		mu_diag_funcall(MU_DIAG_ERROR,
1027 				"dkim_signature_format", NULL, rc);
1028 	} else {
1029 		rc = 0;
1030 		mu_stream_seek(fb.str, 0, MU_SEEK_CUR, &off);
1031 
1032 		//FIXME: assert(size < (size_t)~0)
1033 		size = off;
1034 		text = mu_alloc(size + 1);
1035 
1036 		mu_stream_seek(fb.str, 0, MU_SEEK_SET, NULL);
1037 
1038 		mu_stream_read(fb.str, text, size, NULL);
1039 		text[size] = 0;
1040 		*result = text;
1041 	}
1042 	mu_stream_destroy(&fb.str);
1043 
1044 	return rc;
1045 }
1046 
1047 /* Canonicalize the message into a stream.
1048  * Arguments:
1049  *
1050  * msg          input message.
1051  * canon        canonicalization algorithms for header and body.
1052  * canon_str    output stream.
1053  */
1054 int
canonicalize(mu_message_t msg,int canon[2],mu_stream_t * canon_str)1055 canonicalize(mu_message_t msg, int canon[2], mu_stream_t *canon_str)
1056 {
1057 	mu_stream_t mstr, flt, in;
1058 	int rc;
1059 
1060 	rc = mu_temp_file_stream_create(&mstr, NULL, 0);
1061 	if (rc) {
1062 		mu_diag_funcall(MU_DIAG_ERROR,
1063 				"mu_temp_file_stream_create",
1064 				NULL, rc);
1065 		return -1;
1066 	}
1067 
1068 	rc = mu_message_get_streamref(msg, &in);
1069 	if (rc) {
1070 		mu_diag_funcall(MU_DIAG_ERROR,
1071 				"mu_message_get_streamref",
1072 				NULL, rc);
1073 		mu_stream_destroy(&mstr);
1074 		return -1;
1075 	}
1076 
1077 	rc = dkim_canonicalizer_create(&flt, in,
1078 				       canon[0],
1079 				       canon[1],
1080 				       MU_STREAM_READ);
1081 	mu_stream_unref(in);
1082 	if (rc) {
1083 		mu_error("dkim_canonicalizer_create: %s",
1084 			 mu_strerror(rc));
1085 		mu_stream_destroy(&mstr);
1086 		return -1;
1087 	}
1088 
1089 	in = flt;
1090 	rc = mu_filter_create(&flt, in, "CRLF",
1091 			      MU_FILTER_ENCODE, MU_STREAM_READ);
1092 	mu_stream_unref(in);
1093 	if (rc) {
1094 		mu_error("mu_filter_stream_create: %s", mu_strerror(rc));
1095 		mu_stream_destroy(&mstr);
1096 		return -1;
1097 	}
1098 
1099 	rc = mu_stream_copy(mstr, flt, 0, NULL);
1100 	mu_stream_unref(flt);
1101 	if (rc) {
1102 		mu_error("mu_stream_copy: %s", mu_strerror(rc));
1103 		mu_stream_destroy(&mstr);
1104 		return -1;
1105 	}
1106 	mu_stream_seek(mstr, 0, MU_SEEK_SET, NULL);
1107 	*canon_str = mstr;
1108 	return 0;
1109 }
1110 
1111 /*
1112  * Header maps.
1113  *
1114  * Message headers form a doubly-linked list of struct header_map
1115  * pointers.  The list itself is referenced by its head structure,
1116  * which is a regular header_map where only prev and next pointers
1117  * are valid.  In a header, next points to the first and prev to the
1118  * last element in the list.
1119  */
1120 struct header_map {
1121 	struct header_map *prev, *next;  /* List of elements */
1122 	char *header;         /* Header name */
1123 	mu_off_t start;       /* Header start offset */
1124 	mu_off_t end;         /* Header end offset (points past the
1125 				 final CRLF) */
1126 };
1127 
1128 /* Header_map is initialized using this macro. */
1129 #define HEADER_MAP_INITIALIZER(h) { &(h), &(h) }
1130 
1131 /* Remove the header_map from the list */
1132 static inline void
header_map_remove(struct header_map * hp)1133 header_map_remove(struct header_map *hp)
1134 {
1135 	hp->prev->next = hp->next;
1136 	hp->next->prev = hp->prev;
1137 }
1138 
1139 /* Insert header_map B to the list after A. */
1140 static inline void
header_map_insert_after(struct header_map * a,struct header_map * b)1141 header_map_insert_after(struct header_map *a, struct header_map *b)
1142 {
1143 	a->next->prev = b;
1144 	b->next = a->next;
1145 	a->next = b;
1146 	b->prev = a;
1147 }
1148 
1149 /* Append header_map to the end of the list. */
1150 static inline void
header_map_append(struct header_map * link,struct header_map * hp)1151 header_map_append(struct header_map *link, struct header_map *hp)
1152 {
1153 	header_map_insert_after(link->prev, hp);
1154 }
1155 
1156 /* Free the list.  List head is not freed. */
1157 static inline void
header_map_free(struct header_map * link)1158 header_map_free(struct header_map *link)
1159 {
1160 	struct header_map *hmap = link->next;
1161 	while (hmap != link) {
1162 		header_map_remove(hmap);
1163 		free(hmap);
1164 		hmap = link->next;
1165 	}
1166 }
1167 
1168 /*
1169  * Two iterators.
1170  *
1171  * Arguments:
1172  * link     the head element of the list.
1173  * h        iteration variable
1174  */
1175 
1176 /* Iterate over the list in natural direction. */
1177 #define HEADER_MAP_FOREACH(h,link) \
1178 	for (h = (link)->next; h != (link); h = (h)->next)
1179 /* Iterate over the list in reverse direction. */
1180 #define HEADER_MAP_FOREACH_REV(h,link)				\
1181 	for (h = (link)->prev; h != (link); h = (h)->prev)
1182 
1183 /* Return true if a message can have multiple instances of the named header.
1184  *
1185  * RFC 6376 mandates that such headers be processed in reverse order.
1186  * Refer to subsection 5.4.2.  "Signatures Involving Multiple Instances of
1187  * a Field" on page 41 for details.
1188  */
1189 static int
is_rev_header(char const * name)1190 is_rev_header(char const *name)
1191 {
1192 	static char *rev_headers[] = {
1193 		"Received",
1194 		DKIM_SIGNATURE_HEADER,
1195 		"Resent-*",
1196 		NULL
1197 	};
1198 	int i;
1199 
1200 	for (i = 0; rev_headers[i]; i++) {
1201 		if (mu_imap_wildmatch_ci(rev_headers[i], name, ':') == 0)
1202 			return 1;
1203 	}
1204 	return 0;
1205 }
1206 
1207 static int
dkim_tag_find(char const * sigstr,char const * tag,size_t * ret_len)1208 dkim_tag_find(char const *sigstr, char const *tag, size_t *ret_len)
1209 {
1210 	int i;
1211 	size_t tag_len = strlen(tag);
1212 	size_t sig_len = strlen(sigstr);
1213 
1214 	for (i = 0; i + tag_len + 1 < sig_len; i++) {
1215 		if (!(sigstr[i] == ' ' || sigstr[i] == '\t' ||
1216 		      sigstr[i] == '\r' || sigstr[i] == '\n')) {
1217 			size_t n = strcspn(sigstr + i, ";");
1218 			if (memcmp(sigstr + i, tag, tag_len) == 0 &&
1219 			    sigstr[i + tag_len] == '=') {
1220 				*ret_len = n - tag_len - 1;
1221 				return i;
1222 			}
1223 			i += n;
1224 		}
1225 	}
1226 	return -1;
1227 }
1228 
1229 enum {
1230 	DKIM_HASH_ERR = -1,
1231 	DKIM_HASH_OK,
1232 	DKIM_HASH_DIFF
1233 };
1234 
1235 #define BH_SIZE (BASE64_ENCODE_RAW_LENGTH(SHA256_DIGEST_SIZE))
1236 
1237 /*
1238  * dkim_hash(MSG, SIG, SIGSTR, CTX)
1239  * --------------------------------
1240  * Compute a message hash of MSG as per RFC 6376 section 3.7.
1241  *
1242  * Parameters:
1243  *  MSG    - (input) message
1244  *  SIG    - (input/output) parsed out DKIM signature
1245  *  SIGSTR - (input) original value of the DKIM signature header.
1246  *  CTX    - (output) SHA256 context to leave the hash in.
1247  *
1248  * The function is used both for message signing and verification.
1249  *
1250  * When signing, SIGSTR is NULL.  Before return, the malloced copy
1251  * of the computed body hash is left in SIG->bh.  The caller is
1252  * responsible for freeing it when no longer needed.  In this mode,
1253  * the function returns DKIM_HASH_OK on success and DKIM_HASH_ERR
1254  * on error.
1255  *
1256  * When verifying, SIGSTR is not NULL and SIG is the validated broken
1257  * out DKIM signature obtained from SIGSTR.  In this case, the function
1258  * does not modify SIG in any way.  Instead, it checks whether the computed
1259  * body hash matches SIG->bh and returns DKIM_HASH_DIFF if it does not.
1260  */
1261 static int
dkim_hash(mu_message_t msg,struct dkim_signature * sig,char const * sigstr,struct sha256_ctx * ctx)1262 dkim_hash(mu_message_t msg, struct dkim_signature *sig, char const *sigstr,
1263 	  struct sha256_ctx *ctx)
1264 {
1265 	mu_stream_t canon_stream = NULL;
1266 	char *hp;
1267 	void *hstate;
1268 	struct header_map h_all = HEADER_MAP_INITIALIZER(h_all);
1269 	struct header_map h_sel = HEADER_MAP_INITIALIZER(h_sel);
1270 	struct header_map *hmap;
1271 	uint8_t bh[BH_SIZE];
1272 	mu_opool_t op = NULL;
1273 	char c;
1274 	int rc;
1275 	int result = DKIM_HASH_ERR;
1276 	size_t count;
1277 	enum { H_INIT, H_HEADER, H_CR1, H_CR2, H_NL } state = H_INIT;
1278 	mu_stream_t sigcanon, str;
1279 	char *sig_str_buf;
1280 
1281 	/* Create a canonical representation of the message */
1282 	if (canonicalize(msg, sig->canon, &canon_stream))
1283 		goto err;
1284 
1285 	/*
1286 	 * Scan the header part of the canonicalized stream and record
1287 	 * the headers in the h_all list.
1288 	 *
1289 	 * Header names its elements refer to are stored in the object
1290 	 * pool.
1291 	 */
1292 	mu_opool_create(&op, MU_OPOOL_DEFAULT);
1293 	hmap = NULL;
1294 
1295 	while ((rc = mu_stream_read(canon_stream, &c, 1, &count)) == 0 &&
1296 	       count == 1) {
1297 		switch (state) {
1298 		case H_INIT:
1299 			if (c == ':') {
1300 				c = 0;
1301 				mu_opool_append(op, &c, 1);
1302 				hmap = calloc(1, sizeof(hmap[0]));
1303 				hmap->header = mu_opool_finish(op, NULL);
1304 				mu_strlower(hmap->header);
1305 				mu_stream_seek(canon_stream, 0, MU_SEEK_CUR,
1306 					       &hmap->start);
1307 				hmap->start -= strlen(hmap->header) + 1;
1308 				header_map_append(&h_all, hmap);
1309 				state = H_HEADER;
1310 			} else
1311 				mu_opool_append(op, &c, 1);
1312 			break;
1313 
1314 		case H_HEADER:
1315 			if (c == '\r')
1316 				state = H_CR1;
1317 			break;
1318 
1319 		case H_CR1:
1320 			if (c == '\n')
1321 				state = H_NL;
1322 			break;
1323 
1324 		case H_NL:
1325 			if (mu_isblank(c))
1326 				state = H_HEADER;
1327 			else {
1328 				mu_stream_seek(canon_stream, 0, MU_SEEK_CUR,
1329 					       &hmap->end);
1330 				hmap->end--;
1331 				if (c == '\r')
1332 					state = H_CR2;
1333 				else {
1334 					state = H_INIT;
1335 					mu_opool_append(op, &c, 1);
1336 				}
1337 			}
1338 			break;
1339 
1340 		case H_CR2:
1341 			if (c != '\n') {
1342 				goto badstream;
1343 			}
1344 			goto end;
1345 		}
1346 	}
1347 
1348 	/* Error exit from the above loop */
1349 	if (rc)
1350 		mu_diag_funcall(MU_DIAG_ERROR, "mu_stream_read", NULL, rc);
1351 badstream:
1352 	mu_error(_("malformed canonical stream"));
1353 	goto err;
1354 
1355 end:
1356 	/*
1357 	 * Scanning terminated successfully.  Current position in the
1358 	 * canon_stream is left at the start of the body, which will come
1359 	 * handy later.
1360 	 *
1361 	 * Select headers to hash according to the h= tag.  Selected headers
1362 	 * are removed from the h_all and added to the h_sel list.
1363 	 */
1364 	for (hp = dkim_header_list_first(sig->h, &hstate); hp;
1365 	     hp = dkim_header_list_next(hstate)) {
1366 		if (is_rev_header(hp)) {
1367 			HEADER_MAP_FOREACH_REV(hmap, &h_all) {
1368 				if (mu_c_strcasecmp(hmap->header, hp) == 0) {
1369 					header_map_remove(hmap);
1370 					header_map_append(&h_sel, hmap);
1371 					break;
1372 				}
1373 			}
1374 		} else {
1375 			HEADER_MAP_FOREACH(hmap, &h_all) {
1376 				if (mu_c_strcasecmp(hmap->header, hp) == 0) {
1377 					header_map_remove(hmap);
1378 					header_map_append(&h_sel, hmap);
1379 					break;
1380 				}
1381 			}
1382 		}
1383 	}
1384 	dkim_header_list_end(hstate);
1385 
1386 	/* Hash the body */
1387 	if (dkim_body_hash(canon_stream, sig->l, bh))
1388 		goto err;
1389 	if (sig->bh) {
1390 		if (memcmp(sig->bh, bh, BH_SIZE)) {
1391 			result = DKIM_HASH_DIFF;
1392 			goto err;
1393 		}
1394 	} else {
1395 		sig->bh = malloc(BH_SIZE + 1);
1396 		if (!sig->bh)
1397 			goto err;
1398 		memcpy(sig->bh, bh, BH_SIZE);
1399 		sig->bh[BH_SIZE] = 0;
1400 	}
1401 
1402 	/* Hash the selected headers */
1403 	HEADER_MAP_FOREACH(hmap, &h_sel) {
1404 		mu_stream_seek(canon_stream, hmap->start, MU_SEEK_SET, NULL);
1405 		hash_stream_segment(canon_stream, hmap->end - hmap->start,
1406 				    ctx);
1407 	}
1408 
1409 	/* Add to the hash the DKIM-Signature header with empty b= tag. */
1410 	if (sigstr) {
1411 		size_t len, blen;
1412 		char *vp;
1413 		int n = dkim_tag_find(sigstr, "b", &blen);
1414 		if (n == -1)
1415 			goto err;
1416 		len = strlen(sigstr);
1417 		sig_str_buf = malloc(sizeof(DKIM_SIGNATURE_HEADER) + 1
1418 				     + len - blen + 1);
1419 		if (!sig_str_buf)
1420 			goto err;
1421 		strcpy(sig_str_buf, DKIM_SIGNATURE_HEADER ": ");
1422 		vp = sig_str_buf + sizeof(DKIM_SIGNATURE_HEADER) + 1;
1423 		memcpy(vp, sigstr, n);
1424 		memcpy(vp + n, "b=", 2);
1425 		strcpy(vp + n + 2, sigstr + n + 2 + blen);
1426 	} else {
1427 		dkim_signature_format(sig, 0, &sig_str_buf);
1428 	}
1429 	mu_fixed_memory_stream_create(&str, sig_str_buf, strlen(sig_str_buf),
1430 				      MU_STREAM_RDWR|MU_STREAM_SEEK);
1431 	rc = dkim_canonicalizer_create(&sigcanon, str,
1432 				       sig->canon[0], sig->canon[1],
1433 				       MU_STREAM_READ);
1434 	mu_stream_unref(str);
1435 	if (rc) {
1436 		mu_error("dkim_canonicalizer_create: %s", mu_strerror(rc));
1437 		goto err;
1438 	}
1439 
1440 	rc = mu_filter_create(&str, sigcanon, "CRLF", MU_FILTER_ENCODE,
1441 			      MU_STREAM_READ);
1442 	mu_stream_unref(sigcanon);
1443 	if (rc) {
1444 		mu_diag_funcall(MU_DIAG_ERROR,
1445 				"mu_filter_stream_create", NULL, c);
1446 		goto err;
1447 	}
1448 	sigcanon = str;
1449 
1450 	hash_stream(sigcanon, ctx);
1451 	mu_stream_unref(sigcanon);
1452 	free(sig_str_buf);
1453 	result = DKIM_HASH_OK;
1454 err:
1455 	/* Reclaim the allocated memory. */
1456 	mu_opool_destroy(&op);
1457 	header_map_free(&h_all);
1458 	header_map_free(&h_sel);
1459 	mu_stream_destroy(&canon_stream);
1460 	return result;
1461 }
1462 
1463 
1464 /* Sign the message.  Arguments:
1465  *
1466  * msg          message to sign.
1467  * sig          initialized struct dkim_signature.
1468  * priv_file    name of a disk file with the RSA private key in PEM format.
1469  * ret_sighdr   return pointer.
1470  *
1471  * On success, a malloced copy of DKIM-Signature header line will be stored
1472  * in ret_sighdr and 0 will be returned.
1473  *
1474  * Side effects: sig->bh is filled with SHA256 digest of the message body.
1475  */
1476 int
mfd_dkim_sign(mu_message_t msg,struct dkim_signature * sig,char * priv_file,char ** ret_sighdr)1477 mfd_dkim_sign(mu_message_t msg, struct dkim_signature *sig,
1478 	      char *priv_file,
1479 	      char **ret_sighdr)
1480 {
1481 	int rc;
1482 	struct rsa_private_key priv;
1483 	struct rsa_public_key pub;
1484 	FILE *fp;
1485 	struct sha256_ctx ctx;
1486 	int result = -1;
1487 
1488 	fp = fopen(priv_file, "r");
1489 	if (!fp) {
1490 		mu_error(_("can't open %s: %s"), priv_file, strerror(errno));
1491 		return -1;
1492 	}
1493 
1494 	rc = read_keys(fp, &pub, &priv);
1495 	fclose(fp);
1496 	if (rc != READ_PEM_OK) {
1497 		mu_error(_("can't read private key from %s: %s"),
1498 			 priv_file, strerror(errno));
1499 		return -1;
1500 	}
1501 	rsa_public_key_clear(&pub);
1502 
1503 	sha256_init(&ctx);
1504 	if (dkim_hash(msg, sig, NULL, &ctx) == DKIM_HASH_OK) {
1505 	    /* Create the RSA-SHA256 signature in b */
1506 	    dkim_rsa_sha256_sign(&priv, &ctx, &sig->b);
1507 
1508 	    /* Create the header */
1509 	    dkim_signature_format(sig, 1, ret_sighdr);
1510 	    result = 0;
1511 	}
1512 	/* Reclaim the allocated memory. */
1513 	free(sig->b);
1514 	sig->b = NULL;
1515 	free(sig->bh);
1516 	sig->bh = NULL;
1517 	rsa_private_key_clear(&priv);
1518 	return result;
1519 }
1520 
1521 char const *dkim_explanation_str[] = {
1522 	[DKIM_EXPL_OK] = "DKIM verification passed",
1523 	[DKIM_EXPL_NO_SIG] = "No DKIM signature",
1524 	[DKIM_EXPL_INTERNAL_ERROR] = "internal error",
1525 	[DKIM_EXPL_SIG_SYNTAX] = "signature syntax error",
1526 	[DKIM_EXPL_SIG_MISS] = "signature is missing required tag",
1527 	[DKIM_EXPL_DOMAIN_MISMATCH] = "domain mismatch",
1528 	[DKIM_EXPL_BAD_VERSION] = "incompatible version",
1529 	[DKIM_EXPL_BAD_ALGORITHM] = "unsupported algorithm",
1530 	[DKIM_EXPL_BAD_QUERY] = "unsupported query method",
1531 	[DKIM_EXPL_FROM] = "From field not signed",
1532 	[DKIM_EXPL_EXPIRED] = "signature expired",
1533 	[DKIM_EXPL_DNS_UNAVAIL] = "public key unavailable",
1534 	[DKIM_EXPL_DNS_NOTFOUND] = "public key not found",
1535 	[DKIM_EXPL_KEY_SYNTAX] = "key syntax error",
1536 	[DKIM_EXPL_KEY_REVOKED] = "key revoked",
1537 	[DKIM_EXPL_BAD_BODY] = "body hash did not verify",
1538 	[DKIM_EXPL_BAD_BASE64] = "can't decode b= tag",
1539 	[DKIM_EXPL_BAD_SIG] = "signature did not verify",
1540 };
1541 
1542 int dkim_result_trans[] = {
1543 	[DKIM_EXPL_OK] =		DKIM_VERIFY_OK,
1544 	[DKIM_EXPL_BAD_ALGORITHM] =	DKIM_VERIFY_PERMFAIL,
1545 	[DKIM_EXPL_BAD_BASE64] =	DKIM_VERIFY_PERMFAIL,
1546 	[DKIM_EXPL_BAD_BODY] =		DKIM_VERIFY_PERMFAIL,
1547 	[DKIM_EXPL_BAD_SIG] =		DKIM_VERIFY_PERMFAIL,
1548 	[DKIM_EXPL_BAD_QUERY] =		DKIM_VERIFY_PERMFAIL,
1549 	[DKIM_EXPL_BAD_VERSION] =	DKIM_VERIFY_PERMFAIL,
1550 	[DKIM_EXPL_DNS_NOTFOUND] =	DKIM_VERIFY_PERMFAIL,
1551 	[DKIM_EXPL_DOMAIN_MISMATCH] =	DKIM_VERIFY_PERMFAIL,
1552 	[DKIM_EXPL_EXPIRED] =		DKIM_VERIFY_PERMFAIL,
1553 	[DKIM_EXPL_FROM] =		DKIM_VERIFY_PERMFAIL,
1554 	[DKIM_EXPL_KEY_REVOKED] =	DKIM_VERIFY_PERMFAIL,
1555 	[DKIM_EXPL_KEY_SYNTAX] =	DKIM_VERIFY_PERMFAIL,
1556 	[DKIM_EXPL_SIG_MISS] =		DKIM_VERIFY_PERMFAIL,
1557 	[DKIM_EXPL_SIG_SYNTAX] =	DKIM_VERIFY_PERMFAIL,
1558 	[DKIM_EXPL_NO_SIG] =            DKIM_VERIFY_TEMPFAIL,
1559 	[DKIM_EXPL_DNS_UNAVAIL] =	DKIM_VERIFY_TEMPFAIL,
1560 	[DKIM_EXPL_INTERNAL_ERROR] =	DKIM_VERIFY_TEMPFAIL,
1561 };
1562 
1563 static int
dkim_sig_validate(struct dkim_signature * sig)1564 dkim_sig_validate(struct dkim_signature *sig)
1565 {
1566 	if (!sig->a
1567 	    || !sig->b
1568 	    || !sig->bh
1569 	    || !sig->d
1570 	    || !sig->h
1571 	    || !sig->s
1572 	    || !sig->v) {
1573 		return DKIM_EXPL_SIG_MISS;
1574 	}
1575 
1576 	if (strcmp(sig->v, DKIM_VERSION))
1577 		return DKIM_EXPL_BAD_VERSION;
1578 
1579 	if (strcmp(sig->a, DKIM_ALGORITHM))
1580 		return DKIM_EXPL_BAD_ALGORITHM;
1581 
1582         if (!sig->q)
1583 		sig->q = mu_strdup(DKIM_QUERY_METHOD);
1584 	else if (strcmp(sig->q, DKIM_QUERY_METHOD))
1585 		return DKIM_EXPL_BAD_QUERY;
1586 
1587 	if (sig->i) {
1588 		char *p = strchr(sig->i, '@');
1589 		size_t ilen, dlen;
1590 		if (!p)
1591 			return DKIM_EXPL_SIG_SYNTAX;
1592 		p++;
1593 		ilen = strlen(p);
1594 		dlen = strlen(sig->d);
1595 		if (!(dlen <= ilen &&
1596 		      mu_c_strcasecmp(sig->d, p + ilen - dlen) == 0 &&
1597 		      (p[ilen - dlen - 1] == '.' || p[ilen - dlen - 1] == '@')))
1598 			return DKIM_EXPL_DOMAIN_MISMATCH;
1599 	}
1600 
1601 	if (!dkim_header_list_match(sig->h, MU_HEADER_FROM))
1602 		return DKIM_EXPL_FROM;
1603 
1604 	if (sig->x && time(NULL) > sig->x)
1605 		return DKIM_EXPL_EXPIRED;
1606 
1607 	return DKIM_EXPL_OK;
1608 }
1609 
1610 static int
dnsrec_parse(char * rec,mu_assoc_t * pa)1611 dnsrec_parse(char *rec, mu_assoc_t *pa)
1612 {
1613 	mu_assoc_t a;
1614 	struct mu_wordsplit ws;
1615 	int result;
1616 
1617 	if (mu_assoc_create (&a, 0))
1618 		mu_alloc_die ();
1619 	mu_assoc_set_destroy_item (a, mu_list_free_item);
1620 
1621 	ws.ws_delim = ";";
1622 	if (mu_wordsplit(rec,
1623 			 &ws,
1624 			 MU_WRDSF_DELIM |
1625 			 MU_WRDSF_NOVAR |
1626 			 MU_WRDSF_WS |
1627 			 MU_WRDSF_NOCMD)) {
1628 		result = 1;
1629 	} else {
1630 		size_t i;
1631 
1632 		for (i = 0; i < ws.ws_wordc; i++) {
1633 			char *p = strchr(ws.ws_wordv[i], '=');
1634 			char **slot;
1635 			int rc;
1636 
1637 			if (!p) {
1638 				result = 1;
1639 				break;
1640 			}
1641 			*p++ = 0;
1642 			mu_rtrim_class(ws.ws_wordv[i], MU_CTYPE_BLANK);
1643 			mu_ltrim_class(p, MU_CTYPE_BLANK);
1644 
1645 			rc = mu_assoc_install_ref(a, ws.ws_wordv[i], &slot);
1646 			if (rc == ENOMEM)
1647 				mu_alloc_die ();
1648 			else if (rc) {
1649 				result = 1;
1650 				break;
1651 			} else
1652 				result = 0;
1653 			*slot = mu_strdup(p);
1654 		}
1655 	}
1656 
1657 	mu_wordsplit_free(&ws);
1658 	if (result)
1659 		mu_assoc_destroy (&a);
1660 	else
1661 		*pa = a;
1662 	return result;
1663 }
1664 
1665 static int
pubkey_validate(mu_assoc_t a,struct dkim_signature const * sig)1666 pubkey_validate(mu_assoc_t a, struct dkim_signature const *sig)
1667 {
1668 	char *s;
1669 	size_t n;
1670 
1671 	if ((s = mu_assoc_get(a, "v")) != NULL &&
1672 	    strcmp(s, DKIM_KEYRECORD_VERSION))
1673 		return DKIM_EXPL_KEY_SYNTAX;
1674 
1675 	if ((s = mu_assoc_get(a, "p")) == NULL)
1676 		return DKIM_EXPL_KEY_SYNTAX;
1677 
1678 	if (s[0] == 0)
1679 		return DKIM_EXPL_KEY_REVOKED;
1680 
1681 	n = strcspn(sig->a, "-");
1682 	if ((s = mu_assoc_get(a, "k")) != NULL &&
1683 	    !(n == strlen(s) && memcmp(s, sig->a, n) == 0))
1684 		return DKIM_EXPL_BAD_ALGORITHM;
1685 
1686 	if ((s = mu_assoc_get(a, "h")) != NULL &&
1687 	    !dkim_header_list_match(s, sig->a + n + 1))
1688 		return DKIM_EXPL_BAD_ALGORITHM;
1689 	return DKIM_EXPL_OK;
1690 }
1691 
1692 static int
dkim_sig_key_verify(mu_message_t msg,struct dkim_signature * sig,struct rsa_public_key * pub)1693 dkim_sig_key_verify(mu_message_t msg, struct dkim_signature *sig,
1694 		    struct rsa_public_key *pub)
1695 {
1696 	struct sha256_ctx ctx;
1697 	mpz_t bs;
1698 	int rc;
1699 	struct nettle_buffer buffer;
1700 	size_t length;
1701 	mu_header_t hdr;
1702 	char const *sigstr;
1703 
1704 	rc = mu_message_get_header(msg, &hdr);
1705 	if (rc) {
1706 		mu_diag_funcall(MU_DIAG_ERROR,
1707 				"mu_message_get_header", NULL, rc);
1708 		return DKIM_EXPL_INTERNAL_ERROR;
1709 	}
1710 	rc = mu_header_sget_value(hdr, DKIM_SIGNATURE_HEADER, &sigstr);
1711 	if (rc) {
1712 		mu_diag_funcall(MU_DIAG_ERROR,
1713 				"mu_header_sget_value",
1714 				DKIM_SIGNATURE_HEADER, rc);
1715 		return DKIM_EXPL_INTERNAL_ERROR;
1716 	}
1717 
1718 	sha256_init(&ctx);
1719 	switch (dkim_hash(msg, sig, sigstr, &ctx)) {
1720 	case DKIM_HASH_OK:
1721 		break;
1722 
1723 	case DKIM_HASH_DIFF:
1724 		return DKIM_EXPL_BAD_BODY;
1725 
1726 	case DKIM_HASH_ERR:
1727 		return DKIM_EXPL_INTERNAL_ERROR;
1728 	}
1729 
1730 	length = strlen((char*)sig->b);
1731 	nettle_buffer_init_realloc(&buffer, NULL, nettle_xrealloc);
1732 	nettle_buffer_write(&buffer, length, sig->b);
1733 	if (decode_base64(&buffer, 0, &length) != READ_PEM_OK)
1734 		return DKIM_EXPL_BAD_BASE64;
1735 
1736 	nettle_mpz_init_set_str_256_u(bs, length, buffer.contents);
1737 	rc = rsa_sha256_verify (pub, &ctx, bs);
1738 	nettle_buffer_clear(&buffer);
1739 	mpz_clear(bs);
1740 
1741 	return rc ? DKIM_EXPL_OK : DKIM_EXPL_BAD_SIG;
1742 }
1743 
1744 static int
dkim_sig_verify(mu_message_t msg,struct dkim_signature * sig)1745 dkim_sig_verify(mu_message_t msg, struct dkim_signature *sig)
1746 {
1747 	char **dnsrec;
1748 	int i;
1749 	int result;
1750 
1751 	/* Get the DKIM DNS record */
1752 	switch (dkim_lookup(sig->d, sig->s, &dnsrec)) {
1753 	case dns_success:
1754 		break;
1755 
1756 	case dns_not_found:
1757 		return DKIM_EXPL_DNS_NOTFOUND;
1758 
1759 	default:
1760 		return DKIM_EXPL_DNS_UNAVAIL;
1761 	}
1762 
1763 	for (i = 0; dnsrec[i]; i++) {
1764 		mu_assoc_t a;
1765 		struct rsa_public_key pub;
1766 		int rc;
1767 
1768 		if (dnsrec_parse(dnsrec[i], &a))
1769 			continue;
1770 
1771 		if ((rc = pubkey_validate(a, sig)) != DKIM_EXPL_OK) {
1772 			result = rc;
1773 		} else if (pubkey_from_base64(&pub, mu_assoc_get(a, "p"))
1774 			   != READ_PEM_OK) {
1775 			result = DKIM_EXPL_KEY_SYNTAX;
1776 		} else {
1777 			result = dkim_sig_key_verify(msg, sig, &pub);
1778 			rsa_public_key_clear(&pub);
1779 		}
1780 		mu_assoc_destroy(&a);
1781 
1782 		if (result == DKIM_EXPL_OK)
1783 			break;
1784 	}
1785 
1786 	for (i = 0; dnsrec[i]; i++)
1787 		free(dnsrec[i]);
1788 	free(dnsrec);
1789 
1790 	return result;
1791 }
1792 
1793 static void
wselim(char * s)1794 wselim(char *s)
1795 {
1796 	char *p = s; /* current destination pointer */
1797 	char *q = s; /* q - current source pointer */
1798 	while (*q) {
1799 		size_t len = strcspn(q, " \t");
1800 		if (p != q)
1801 			memmove(p, q, len);
1802 		p += len;
1803 		q += len;
1804 		q += strspn(q, " \t");
1805 	}
1806 	*p = 0;
1807 }
1808 
1809 int
mfd_dkim_verify(mu_message_t msg,char ** ret_sig)1810 mfd_dkim_verify(mu_message_t msg, char **ret_sig)
1811 {
1812 	mu_header_t hdr;
1813 	int rc;
1814 	int result = DKIM_EXPL_NO_SIG;
1815 	size_t i;
1816 
1817 	/* Get the DKIM-Signature header from the message */
1818 	rc = mu_message_get_header(msg, &hdr);
1819 	if (rc) {
1820 		mu_diag_funcall(MU_DIAG_ERROR,
1821 				"mu_message_get_header", NULL, rc);
1822 		return DKIM_EXPL_INTERNAL_ERROR;
1823 	}
1824 
1825 	for (i = 1; result != DKIM_EXPL_OK; i++) {
1826 		struct dkim_signature sig;
1827 		char *sig_str;
1828 
1829 		rc = mu_header_aget_value_unfold_n(hdr,
1830 						   DKIM_SIGNATURE_HEADER,
1831 						   i,
1832 						   &sig_str);
1833 		if (rc == MU_ERR_NOENT)
1834 			break;
1835 		else if (rc) {
1836 			mu_diag_funcall(MU_DIAG_ERROR,
1837 					"mu_header_aget_value_unfold",
1838 					NULL, rc);
1839 			result = DKIM_EXPL_INTERNAL_ERROR;
1840 			break;
1841 		}
1842 		wselim(sig_str);
1843 
1844 		/* Parse the DKIM signature */
1845 		if (dkim_signature_parse(sig_str, &sig)) {
1846 			result = DKIM_EXPL_SIG_SYNTAX;
1847 		} else {
1848 			/* Validate the signature */
1849 			result = dkim_sig_validate(&sig);
1850 			if (result == DKIM_EXPL_OK)
1851 				result = dkim_sig_verify(msg, &sig);
1852 			if (result == DKIM_EXPL_OK && ret_sig) {
1853 				*ret_sig = sig_str;
1854 				sig_str = NULL;
1855 			}
1856 			dkim_signature_free(&sig);
1857 		}
1858 		free(sig_str);
1859 	}
1860 	return result;
1861 }
1862 
1863