commit c826412d86123fb2346635710aabec82f8e33946 from: Martijn van Duren date: Thu May 2 10:58:08 2019 UTC Add support for the z mail header. -z adds the mail headers used in the signature -Z adds all the mail headers commit - e974922c653d65bd532e1dc385cf9e479aa4f38f commit + c826412d86123fb2346635710aabec82f8e33946 blob - 28d8ba5bf82eb2649a65a0eac8506ad50819861c blob + 114ca8bc90f950566cfe35bb43c14ae1b58834c9 --- filter-dkim.1 +++ filter-dkim.1 @@ -27,6 +27,8 @@ .Op Fl h Ar headers .Op Fl t .Op Fl x Ar seconds +.Op Fl z +.Op Fl Z .Fl d Ar domain .Fl k Ar file .Fl s Ar selector @@ -67,6 +69,12 @@ Add the time of signing to the dkim header. Add the amount of .Ar seconds the signature is valid to the dkim header. +.It Fl z +Add the mail headers used in the dkim signature to the dkim header. +Useful for debugging purposes. +.It Fl Z +Add all the mail headers to the dkim header. +Useful for debugging purposes. .El .Sh SEE ALSO .Xr smtpd 8 blob - 3cea23ed9ce4523d9d36321b860f6531d5554eec blob + be71a9bd0e73e19d1841154579e31e506362fa4e --- main.c +++ main.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -92,6 +93,7 @@ static int canonbody = CANON_SIMPLE; static int addtime = 0; static long long addexpire = 0; +static int addheaders = 0; static char *domain = NULL; static char *selector = NULL; @@ -116,6 +118,7 @@ int dkim_session_cmp(struct dkim_session *, struct dki void dkim_parse_header(struct dkim_session *, char *, int); void dkim_parse_body(struct dkim_session *, char *); void dkim_sign(struct dkim_session *); +int dkim_signature_printheader(struct dkim_session *, char *); int dkim_signature_printf(struct dkim_session *, char *, ...) __attribute__((__format__ (printf, 2, 3))); int dkim_signature_normalize(struct dkim_session *); @@ -131,7 +134,7 @@ main(int argc, char *argv[]) FILE *keyfile; const char *errstr; - while ((ch = getopt(argc, argv, "a:c:Dd:h:k:s:tx:")) != -1) { + while ((ch = getopt(argc, argv, "a:c:Dd:h:k:s:tx:zZ")) != -1) { switch (ch) { case 'a': if (strncmp(optarg, "rsa-", 4) != 0) @@ -186,6 +189,12 @@ main(int argc, char *argv[]) if (addexpire == 0) errx(1, "Expire offset is %s", errstr); break; + case 'z': + addheaders = 1; + break; + case 'Z': + addheaders = 2; + break; case 'D': debug = 1; break; @@ -257,6 +266,8 @@ dkim_dataline(char *type, int version, struct timespec line++; dkim_parse_header(session, line, 0); } else if (linelen == 0 && session->parsing_headers) { + if (addheaders > 0 && !dkim_signature_printf(session, "; ")) + return; session->parsing_headers = 0; } else { if (line[0] == '.') @@ -319,6 +330,8 @@ dkim_session_new(uint64_t reqid) canonbody == CANON_SIMPLE ? "simple" : "relaxed", domain, selector)) return NULL; + if (addheaders > 0 && !dkim_signature_printf(session, "z=")) + return NULL; if ((session->b = EVP_MD_CTX_new()) == NULL || (session->bh = EVP_MD_CTX_new()) == NULL) { @@ -424,6 +437,10 @@ dkim_parse_header(struct dkim_session *session, char * char *htmp; char *tmp; + if (addheaders == 2 && !force && + !dkim_signature_printheader(session, line)) + return; + if ((line[0] == ' ' || line[0] == '\t') && !session->lastheader) return; if ((line[0] != ' ' && line[0] != '\t')) { @@ -442,6 +459,10 @@ dkim_parse_header(struct dkim_session *session, char * return; } + if (addheaders == 1 && !force && + !dkim_signature_printheader(session, line)) + return; + if (canonheader == CANON_RELAXED) { if (!session->lastheader) fieldname = 1; @@ -724,11 +745,13 @@ dkim_signature_normalize(struct dkim_session *session) switch (tag) { case 'B': case 'b': + case 'z': checkpoint = i; break; case 'h': if (sig[i] == ':') checkpoint = i; + break; } if (tag == '\0' && sig[i] != ' ' && sig[i] != '\t') { if ((tag = sig[i]) == 'b' && sig[i + 1] == 'h' && @@ -744,6 +767,51 @@ dkim_signature_normalize(struct dkim_session *session) } int +dkim_signature_printheader(struct dkim_session *session, char *header) +{ + size_t i, j, len; + static char *fmtheader = NULL; + char *tmp; + static size_t size = 0; + int first; + + len = strlen(header); + if ((len + 3) * 3 < len) { + errno = EOVERFLOW; + dkim_err(session, "Can't add z-component to header"); + return 0; + } + if ((len + 3) * 3 > size) { + if ((tmp = reallocarray(fmtheader, 3, len + 3)) == NULL) { + dkim_err(session, "Can't add z-component to header"); + return 0; + } + fmtheader = tmp; + size = (len + 1) * 3; + } + + first = session->signature.signature[session->signature.len - 1] == '='; + for (j = i = 0; header[i] != '\0'; i++, j++) { + if (i == 0 && header[i] != ' ' && header[i] != '\t' && !first) + fmtheader[j++] = '|'; + if ((header[i] >= 0x21 && header[i] <= 0x3A) || + header[i] == 0x3C || + (header[i] >= 0x3E && header[i] <= 0x7B) || + (header[i] >= 0x7D && header[i] <= 0x7E)) + fmtheader[j] = header[i]; + else { + fmtheader[j++] = '='; + (void) sprintf(fmtheader + j, "%02hhX", header[i]); + j++; + } + } + (void) sprintf(fmtheader + j, "=%02hhX=%02hhX", (unsigned char) '\r', + (unsigned char) '\n'); + + return dkim_signature_printf(session, "%s", fmtheader); +} + +int dkim_signature_printf(struct dkim_session *session, char *fmt, ...) { struct dkim_signature *sig = &(session->signature);