2 * PDKIM - a RFC4871 (DKIM) implementation
4 * Copyright (C) 2009 - 2016 Tom Kistner <tom@duncanthrax.net>
5 * Copyright (C) 2016 Jeremy Harris <jgh@exim.org>
7 * http://duncanthrax.net/pdkim/
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.
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.
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.
27 #ifndef DISABLE_DKIM /* entire file */
30 # error Need SUPPORT_TLS for DKIM
33 #include "crypt_ver.h"
36 # include <openssl/rsa.h>
37 # include <openssl/ssl.h>
38 # include <openssl/err.h>
39 #elif defined(RSA_GNUTLS)
40 # include <gnutls/gnutls.h>
41 # include <gnutls/x509.h>
47 #define PDKIM_SIGNATURE_VERSION "1"
48 #define PDKIM_PUB_RECORD_VERSION "DKIM1"
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
54 #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
55 "Message-ID:To:Cc:MIME-Version:Content-Type:"\
56 "Content-Transfer-Encoding:Content-ID:"\
57 "Content-Description:Resent-Date:Resent-From:"\
58 "Resent-Sender:Resent-To:Resent-Cc:"\
59 "Resent-Message-ID:In-Reply-To:References:"\
60 "List-Id:List-Help:List-Unsubscribe:"\
61 "List-Subscribe:List-Post:List-Owner:List-Archive"
63 /* -------------------------------------------------------------------------- */
64 struct pdkim_stringlist {
70 #define PDKIM_STR_ALLOC_FRAG 256
74 unsigned int allocated;
77 /* -------------------------------------------------------------------------- */
78 /* A bunch of list constants */
79 const char *pdkim_querymethods[] = {
83 const char *pdkim_algos[] = {
88 const char *pdkim_canons[] = {
93 const char *pdkim_hashes[] = {
98 const char *pdkim_keytypes[] = {
103 typedef struct pdkim_combined_canon_entry {
107 } pdkim_combined_canon_entry;
109 pdkim_combined_canon_entry pdkim_combined_canons[] = {
110 { "simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
111 { "simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
112 { "relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
113 { "relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
114 { "simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
115 { "relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
120 /* -------------------------------------------------------------------------- */
123 pdkim_verify_status_str(int status)
126 case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
127 case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
128 case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
129 case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
130 default: return "PDKIM_VERIFY_UNKNOWN";
135 pdkim_verify_ext_status_str(int ext_status)
138 case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
139 case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
140 case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
141 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
142 case PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD: return "PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD";
143 case PDKIM_VERIFY_INVALID_PUBKEY_IMPORT: return "PDKIM_VERIFY_INVALID_PUBKEY_IMPORT";
144 default: return "PDKIM_VERIFY_UNKNOWN";
149 /* -------------------------------------------------------------------------- */
150 /* Print debugging functions */
152 pdkim_quoteprint(const uschar *data, int len)
155 for (i = 0; i < len; i++)
157 const int c = data[i];
160 case ' ' : debug_printf("{SP}"); break;
161 case '\t': debug_printf("{TB}"); break;
162 case '\r': debug_printf("{CR}"); break;
163 case '\n': debug_printf("{LF}"); break;
164 case '{' : debug_printf("{BO}"); break;
165 case '}' : debug_printf("{BC}"); break;
167 if ( (c < 32) || (c > 127) )
168 debug_printf("{%02x}", c);
170 debug_printf("%c", c);
178 pdkim_hexprint(const uschar *data, int len)
181 for (i = 0 ; i < len; i++) debug_printf("%02x", data[i]);
187 /* SSS probably want to keep the "stringlist" notion */
189 static pdkim_stringlist *
190 pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
192 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
194 if (!new_entry) return NULL;
195 memset(new_entry, 0, sizeof(pdkim_stringlist));
196 if (!(new_entry->value = strdup(str))) return NULL;
197 if (base) new_entry->next = base;
202 /* -------------------------------------------------------------------------- */
203 /* A small "growing string" implementation to escape malloc/realloc hell */
204 /* String package: should be replaced by Exim standard ones */
208 pdkim_strnew (const char *cstr)
210 unsigned int len = cstr ? strlen(cstr) : 0;
211 pdkim_str *p = malloc(sizeof(pdkim_str));
214 memset(p, 0, sizeof(pdkim_str));
215 if (!(p->str = malloc(len+1)))
220 p->allocated = len+1;
223 strcpy(p->str, cstr);
225 p->str[p->len] = '\0';
233 pdkim_strncat(pdkim_str *str, const char *data, int len)
235 if ((str->allocated - str->len) < (len+1))
237 /* Extend the buffer */
238 int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
239 char *n = realloc(str->str,
240 (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
241 if (n == NULL) return NULL;
243 str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
245 strncpy(&(str->str[str->len]), data, len);
247 str->str[str->len] = '\0';
255 pdkim_strcat(pdkim_str *str, const char *cstr)
257 return pdkim_strncat(str, cstr, strlen(cstr));
262 /* Trim whitespace fore & aft */
265 pdkim_strtrim(pdkim_str *str)
269 while (*p == '\t' || *p == ' ') p++; /* skip whitespace */
270 while (*p) {*q = *p; q++; p++;} /* dump the leading whitespace */
272 while (q != str->str && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) )
273 { /* dump trailing whitespace */
277 str->len = strlen(str->str);
284 pdkim_strclear(pdkim_str *str)
294 pdkim_strfree(pdkim_str *str)
297 if (str->str) free(str->str);
303 pdkim_stringlist_free(pdkim_stringlist * e)
307 pdkim_stringlist * c = e;
308 if (e->value) free(e->value);
316 /* -------------------------------------------------------------------------- */
319 pdkim_free_pubkey(pdkim_pubkey *pub)
323 if (pub->version ) free(pub->version);
324 if (pub->granularity) free(pub->granularity);
325 if (pub->hashes ) free(pub->hashes);
326 if (pub->keytype ) free(pub->keytype);
327 if (pub->srvtype ) free(pub->srvtype);
328 if (pub->notes ) free(pub->notes);
334 /* -------------------------------------------------------------------------- */
337 pdkim_free_sig(pdkim_signature *sig)
341 pdkim_signature *next = (pdkim_signature *)sig->next;
343 pdkim_stringlist_free(sig->headers);
344 if (sig->selector ) free(sig->selector);
345 if (sig->domain ) free(sig->domain);
346 if (sig->identity ) free(sig->identity);
347 if (sig->copiedheaders ) free(sig->copiedheaders);
348 if (sig->rsa_privkey ) free(sig->rsa_privkey);
349 if (sig->sign_headers ) free(sig->sign_headers);
350 if (sig->signature_header) free(sig->signature_header);
352 if (sig->pubkey) pdkim_free_pubkey(sig->pubkey);
355 if (next) pdkim_free_sig(next);
360 /* -------------------------------------------------------------------------- */
363 pdkim_free_ctx(pdkim_ctx *ctx)
367 pdkim_stringlist_free(ctx->headers);
368 pdkim_free_sig(ctx->sig);
369 pdkim_strfree(ctx->cur_header);
375 /* -------------------------------------------------------------------------- */
376 /* Matches the name of the passed raw "header" against
377 the passed colon-separated "tick", and invalidates
378 the entry in tick. Returns OK or fail-code */
379 /*XXX might be safer done using a pdkim_stringlist for "tick" */
382 header_name_match(const char * header, char * tick)
390 /* Get header name */
391 char *hcolon = strchr(header, ':');
393 if (!hcolon) return rc; /* This isn't a header */
395 if (!(hname = malloc((hcolon-header)+1)))
396 return PDKIM_ERR_OOM;
397 memset(hname, 0, (hcolon-header)+1);
398 strncpy(hname, header, (hcolon-header));
400 /* Copy tick-off list locally, so we can punch zeroes into it */
401 if (!(lcopy = strdup(tick)))
404 return PDKIM_ERR_OOM;
412 if (strcasecmp(p, hname) == 0)
415 /* Invalidate header name instance in tick-off list */
424 if (strcasecmp(p, hname) == 0)
427 /* Invalidate header name instance in tick-off list */
438 /* -------------------------------------------------------------------------- */
439 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
443 pdkim_relax_header (char *header, int crlf)
445 BOOL past_field_name = FALSE;
446 BOOL seen_wsp = FALSE;
449 char *relaxed = malloc(strlen(header)+3);
451 if (!relaxed) return NULL;
454 for (p = header; *p != '\0'; p++)
458 if (c == '\r' || c == '\n')
460 if (c == '\t' || c == ' ')
464 c = ' '; /* Turns WSP into SP */
468 if (!past_field_name && c == ':')
470 if (seen_wsp) q--; /* This removes WSP before the colon */
471 seen_wsp = TRUE; /* This removes WSP after the colon */
472 past_field_name = TRUE;
477 /* Lowercase header name */
478 if (!past_field_name) c = tolower(c);
482 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
485 if (crlf) strcat(relaxed, "\r\n");
490 /* -------------------------------------------------------------------------- */
491 #define PDKIM_QP_ERROR_DECODE -1
494 pdkim_decode_qp_char(char *qp_p, int *c)
496 char *initial_pos = qp_p;
498 /* Advance one char */
501 /* Check for two hex digits and decode them */
502 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
504 /* Do hex conversion */
505 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
506 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
510 /* Illegal char here */
511 *c = PDKIM_QP_ERROR_DECODE;
516 /* -------------------------------------------------------------------------- */
519 pdkim_decode_qp(char *str)
524 char *n = malloc(strlen(p)+1);
534 p = pdkim_decode_qp_char(p, &nchar);
550 /* -------------------------------------------------------------------------- */
553 pdkim_decode_base64(uschar *str, blob * b)
556 dlen = b64decode(str, &b->data);
557 if (dlen < 0) b->data = NULL;
561 /* -------------------------------------------------------------------------- */
564 pdkim_encode_base64(blob * b)
567 int old_pool = store_pool;
569 store_pool = POOL_PERM;
570 ret = CS b64encode(b->data, b->len);
571 store_pool = old_pool;
576 /* -------------------------------------------------------------------------- */
577 #define PDKIM_HDR_LIMBO 0
578 #define PDKIM_HDR_TAG 1
579 #define PDKIM_HDR_VALUE 2
581 static pdkim_signature *
582 pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
584 pdkim_signature *sig ;
586 pdkim_str *cur_tag = NULL;
587 pdkim_str *cur_val = NULL;
588 BOOL past_hname = FALSE;
589 BOOL in_b_val = FALSE;
590 int where = PDKIM_HDR_LIMBO;
592 int old_pool = store_pool;
594 /* There is a store-reset between header & body reception
595 so cannot use the main pool. Any allocs done by Exim
596 memory-handling must use the perm pool. */
598 store_pool = POOL_PERM;
600 if (!(sig = malloc(sizeof(pdkim_signature)))) return NULL;
601 memset(sig, 0, sizeof(pdkim_signature));
602 sig->bodylength = -1;
604 if (!(sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1)))
610 q = sig->rawsig_no_b_val;
612 for (p = raw_hdr; ; p++)
617 if (c == '\r' || c == '\n')
620 /* Fast-forward through header name */
623 if (c == ':') past_hname = TRUE;
627 if (where == PDKIM_HDR_LIMBO)
629 /* In limbo, just wait for a tag-char to appear */
630 if (!(c >= 'a' && c <= 'z'))
633 where = PDKIM_HDR_TAG;
636 if (where == PDKIM_HDR_TAG)
639 cur_tag = pdkim_strnew(NULL);
641 if (c >= 'a' && c <= 'z')
642 pdkim_strncat(cur_tag, p, 1);
646 if (strcmp(cur_tag->str, "b") == 0)
651 where = PDKIM_HDR_VALUE;
656 if (where == PDKIM_HDR_VALUE)
659 cur_val = pdkim_strnew(NULL);
661 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
664 if (c == ';' || c == '\0')
666 if (cur_tag->len > 0)
668 pdkim_strtrim(cur_val);
670 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
672 switch (cur_tag->str[0])
675 if (cur_tag->str[1] == 'h')
676 pdkim_decode_base64(US cur_val->str, &sig->bodyhash);
678 pdkim_decode_base64(US cur_val->str, &sig->sigdata);
681 /* We only support version 1, and that is currently the
682 only version there is. */
683 if (strcmp(cur_val->str, PDKIM_SIGNATURE_VERSION) == 0)
687 for (i = 0; pdkim_algos[i]; i++)
688 if (strcmp(cur_val->str, pdkim_algos[i]) == 0)
695 for (i = 0; pdkim_combined_canons[i].str; i++)
696 if (strcmp(cur_val->str, pdkim_combined_canons[i].str) == 0)
698 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
699 sig->canon_body = pdkim_combined_canons[i].canon_body;
704 for (i = 0; pdkim_querymethods[i]; i++)
705 if (strcmp(cur_val->str, pdkim_querymethods[i]) == 0)
707 sig->querymethod = i;
712 sig->selector = strdup(cur_val->str); break;
714 sig->domain = strdup(cur_val->str); break;
716 sig->identity = pdkim_decode_qp(cur_val->str); break;
718 sig->created = strtoul(cur_val->str, NULL, 10); break;
720 sig->expires = strtoul(cur_val->str, NULL, 10); break;
722 sig->bodylength = strtol(cur_val->str, NULL, 10); break;
724 sig->headernames = string_copy(US cur_val->str); break;
726 sig->copiedheaders = pdkim_decode_qp(cur_val->str); break;
728 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
732 pdkim_strclear(cur_tag);
733 pdkim_strclear(cur_val);
735 where = PDKIM_HDR_LIMBO;
738 pdkim_strncat(cur_val, p, 1);
749 store_pool = old_pool;
751 /* Make sure the most important bits are there. */
752 if (!(sig->domain && (*(sig->domain) != '\0') &&
753 sig->selector && (*(sig->selector) != '\0') &&
754 sig->headernames && (*(sig->headernames) != '\0') &&
762 /* Chomp raw header. The final newline must not be added to the signature. */
764 while (q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
765 *q = '\0'; q--; /*XXX questionable code layout; possible bug */
770 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
771 pdkim_quoteprint(US sig->rawsig_no_b_val, strlen(sig->rawsig_no_b_val));
773 "PDKIM >> Sig size: %4u bits\n", (unsigned) sig->sigdata.len*8);
775 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
778 exim_sha_init(&sig->body_hash, sig->algo == PDKIM_ALGO_RSA_SHA1);
783 /* -------------------------------------------------------------------------- */
785 static pdkim_pubkey *
786 pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
790 pdkim_str *cur_tag = NULL;
791 pdkim_str *cur_val = NULL;
792 int where = PDKIM_HDR_LIMBO;
794 if (!(pub = malloc(sizeof(pdkim_pubkey)))) return NULL;
795 memset(pub, 0, sizeof(pdkim_pubkey));
797 for (p = raw_record; ; p++)
802 if (c == '\r' || c == '\n')
805 if (where == PDKIM_HDR_LIMBO)
807 /* In limbo, just wait for a tag-char to appear */
808 if (!(c >= 'a' && c <= 'z'))
811 where = PDKIM_HDR_TAG;
814 if (where == PDKIM_HDR_TAG)
817 cur_tag = pdkim_strnew(NULL);
819 if (c >= 'a' && c <= 'z')
820 pdkim_strncat(cur_tag, p, 1);
824 where = PDKIM_HDR_VALUE;
829 if (where == PDKIM_HDR_VALUE)
832 cur_val = pdkim_strnew(NULL);
834 if (c == '\r' || c == '\n')
837 if (c == ';' || c == '\0')
839 if (cur_tag->len > 0)
841 pdkim_strtrim(cur_val);
842 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
844 switch (cur_tag->str[0])
847 /* This tag isn't evaluated because:
848 - We only support version DKIM1.
849 - Which is the default for this value (set below)
850 - Other versions are currently not specified. */
853 pub->hashes = strdup(cur_val->str); break;
855 pub->granularity = strdup(cur_val->str); break;
857 pub->notes = pdkim_decode_qp(cur_val->str); break;
859 pdkim_decode_base64(US cur_val->str, &pub->key);
862 pub->hashes = strdup(cur_val->str); break;
864 pub->srvtype = strdup(cur_val->str); break;
866 if (strchr(cur_val->str, 'y') != NULL) pub->testing = 1;
867 if (strchr(cur_val->str, 's') != NULL) pub->no_subdomaining = 1;
870 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
874 pdkim_strclear(cur_tag);
875 pdkim_strclear(cur_val);
876 where = PDKIM_HDR_LIMBO;
879 pdkim_strncat(cur_val, p, 1);
883 if (c == '\0') break;
886 /* Set fallback defaults */
887 if (!pub->version ) pub->version = strdup(PDKIM_PUB_RECORD_VERSION);
888 if (!pub->granularity) pub->granularity = strdup("*");
889 if (!pub->keytype ) pub->keytype = strdup("rsa");
890 if (!pub->srvtype ) pub->srvtype = strdup("*");
896 pdkim_free_pubkey(pub);
901 /* -------------------------------------------------------------------------- */
904 pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
906 pdkim_signature *sig = ctx->sig;
907 /* Cache relaxed version of data */
908 uschar *relaxed_data = NULL;
911 /* Traverse all signatures, updating their hashes. */
914 /* Defaults to simple canon (no further treatment necessary) */
915 const uschar *canon_data = CUS data;
918 if (sig->canon_body == PDKIM_CANON_RELAXED)
920 /* Relax the line if not done already */
923 BOOL seen_wsp = FALSE;
927 if (!(relaxed_data = malloc(len+1)))
928 return PDKIM_ERR_OOM;
930 for (p = data; *p; p++)
935 if (q > 0 && relaxed_data[q-1] == ' ')
938 else if (c == '\t' || c == ' ')
940 c = ' '; /* Turns WSP into SP */
947 relaxed_data[q++] = c;
949 relaxed_data[q] = '\0';
952 canon_data = relaxed_data;
953 canon_len = relaxed_len;
956 /* Make sure we don't exceed the to-be-signed body length */
957 if ( sig->bodylength >= 0
958 && sig->signed_body_bytes + (unsigned long)canon_len > sig->bodylength
960 canon_len = sig->bodylength - sig->signed_body_bytes;
964 exim_sha_update(&sig->body_hash, CCS canon_data, canon_len);
965 sig->signed_body_bytes += canon_len;
966 DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len);
972 if (relaxed_data) free(relaxed_data);
977 /* -------------------------------------------------------------------------- */
980 pdkim_finish_bodyhash(pdkim_ctx *ctx)
982 pdkim_signature *sig;
984 /* Traverse all signatures */
985 for (sig = ctx->sig; sig; sig = sig->next)
986 { /* Finish hashes */
989 exim_sha_finish(&sig->body_hash, &bh);
993 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
994 "PDKIM [%s] bh computed: ",
995 sig->domain, sig->signed_body_bytes, sig->domain);
996 pdkim_hexprint(CUS bh.data, bh.len);
999 /* SIGNING -------------------------------------------------------------- */
1000 if (ctx->mode == PDKIM_MODE_SIGN)
1004 /* If bodylength limit is set, and we have received less bytes
1005 than the requested amount, effectively remove the limit tag. */
1006 if (sig->signed_body_bytes < sig->bodylength)
1007 sig->bodylength = -1;
1010 /* VERIFICATION --------------------------------------------------------- */
1013 /* Compare bodyhash */
1014 if (memcmp(bh.data, sig->bodyhash.data, bh.len) == 0)
1016 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
1022 debug_printf("PDKIM [%s] bh signature: ", sig->domain);
1023 pdkim_hexprint(sig->bodyhash.data,
1024 exim_sha_hashlen(&sig->body_hash));
1025 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
1027 sig->verify_status = PDKIM_VERIFY_FAIL;
1028 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
1038 /* -------------------------------------------------------------------------- */
1039 /* Callback from pdkim_feed below for processing complete body lines */
1042 pdkim_bodyline_complete(pdkim_ctx *ctx)
1044 char *p = ctx->linebuf;
1045 int n = ctx->linebuf_offset;
1046 pdkim_signature *sig = ctx->sig; /*XXX assumes only one sig */
1048 /* Ignore extra data if we've seen the end-of-data marker */
1049 if (ctx->seen_eod) goto BAIL;
1051 /* We've always got one extra byte to stuff a zero ... */
1052 ctx->linebuf[ctx->linebuf_offset] = '\0';
1054 /* Terminate on EOD marker */
1055 if (memcmp(p, ".\r\n", 3) == 0)
1057 /* In simple body mode, if any empty lines were buffered,
1058 replace with one. rfc 4871 3.4.3 */
1059 /*XXX checking the signed-body-bytes is a gross hack; I think
1060 it indicates that all linebreaks should be buffered, including
1061 the one terminating a text line */
1062 if ( sig && sig->canon_body == PDKIM_CANON_SIMPLE
1063 && sig->signed_body_bytes == 0
1064 && ctx->num_buffered_crlf > 0
1066 pdkim_update_bodyhash(ctx, "\r\n", 2);
1068 ctx->seen_eod = TRUE;
1072 if (memcmp(p, "..", 2) == 0)
1078 /* Empty lines need to be buffered until we find a non-empty line */
1079 if (memcmp(p, "\r\n", 2) == 0)
1081 ctx->num_buffered_crlf++;
1085 if (sig && sig->canon_body == PDKIM_CANON_RELAXED)
1087 /* Lines with just spaces need to be buffered too */
1089 while (memcmp(check, "\r\n", 2) != 0)
1093 if (c != '\t' && c != ' ')
1098 ctx->num_buffered_crlf++;
1103 /* At this point, we have a non-empty line, so release the buffered ones. */
1104 while (ctx->num_buffered_crlf)
1106 pdkim_update_bodyhash(ctx, "\r\n", 2);
1107 ctx->num_buffered_crlf--;
1110 pdkim_update_bodyhash(ctx, p, n);
1113 ctx->linebuf_offset = 0;
1118 /* -------------------------------------------------------------------------- */
1119 /* Callback from pdkim_feed below for processing complete headers */
1120 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
1123 pdkim_header_complete(pdkim_ctx *ctx)
1125 /* Special case: The last header can have an extra \r appended */
1126 if ( (ctx->cur_header->len > 1) &&
1127 (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') )
1129 ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
1130 ctx->cur_header->len--;
1134 if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
1136 /* SIGNING -------------------------------------------------------------- */
1137 if (ctx->mode == PDKIM_MODE_SIGN)
1139 pdkim_signature *sig;
1141 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
1143 pdkim_stringlist *list;
1145 /* Add header to the signed headers list (in reverse order) */
1146 if (!(list = pdkim_prepend_stringlist(sig->headers,
1147 ctx->cur_header->str)))
1148 return PDKIM_ERR_OOM;
1149 sig->headers = list;
1153 /* VERIFICATION ----------------------------------------------------------- */
1154 /* DKIM-Signature: headers are added to the verification list */
1155 if (ctx->mode == PDKIM_MODE_VERIFY)
1157 if (strncasecmp(ctx->cur_header->str,
1158 DKIM_SIGNATURE_HEADERNAME,
1159 strlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
1161 pdkim_signature *new_sig;
1163 /* Create and chain new signature block */
1164 DEBUG(D_acl) debug_printf(
1165 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1167 if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str)))
1169 pdkim_signature *last_sig = ctx->sig;
1174 while (last_sig->next) last_sig = last_sig->next;
1175 last_sig->next = new_sig;
1179 DEBUG(D_acl) debug_printf(
1180 "Error while parsing signature header\n"
1181 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1184 /* every other header is stored for signature verification */
1187 pdkim_stringlist *list;
1189 if (!(list = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->str)))
1190 return PDKIM_ERR_OOM;
1191 ctx->headers = list;
1196 pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
1202 /* -------------------------------------------------------------------------- */
1203 #define HEADER_BUFFER_FRAG_SIZE 256
1206 pdkim_feed (pdkim_ctx *ctx, char *data, int len)
1210 for (p = 0; p<len; p++)
1214 if (ctx->past_headers)
1216 /* Processing body byte */
1217 ctx->linebuf[ctx->linebuf_offset++] = c;
1220 int rc = pdkim_bodyline_complete(ctx); /* End of line */
1221 if (rc != PDKIM_OK) return rc;
1223 if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
1224 return PDKIM_ERR_LONG_LINE;
1228 /* Processing header byte */
1235 int rc = pdkim_header_complete(ctx); /* Seen last header line */
1236 if (rc != PDKIM_OK) return rc;
1238 ctx->past_headers = TRUE;
1240 DEBUG(D_acl) debug_printf(
1241 "PDKIM >> Body data for hash, canonicalized >>>>>>>>>>>>>>>>>>>>>>\n");
1245 ctx->seen_lf = TRUE;
1247 else if (ctx->seen_lf)
1249 if (!(c == '\t' || c == ' '))
1251 int rc = pdkim_header_complete(ctx); /* End of header */
1252 if (rc != PDKIM_OK) return rc;
1254 ctx->seen_lf = FALSE;
1258 if (!ctx->cur_header)
1259 if (!(ctx->cur_header = pdkim_strnew(NULL)))
1260 return PDKIM_ERR_OOM;
1262 if (ctx->cur_header->len < PDKIM_MAX_HEADER_LEN)
1263 if (!pdkim_strncat(ctx->cur_header, &data[p], 1))
1264 return PDKIM_ERR_OOM;
1271 * RFC 5322 specifies that header line length SHOULD be no more than 78
1276 * col: this int holds and receives column number (octets since last '\n')
1277 * str: partial string to append to
1278 * pad: padding, split line or space after before or after eg: ";"
1279 * intro: - must join to payload eg "h=", usually the tag name
1280 * payload: eg base64 data - long data can be split arbitrarily.
1282 * this code doesn't fold the header in some of the places that RFC4871
1283 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1284 * pairs and inside long values. it also always spaces or breaks after the
1287 * no guarantees are made for output given out-of range input. like tag
1288 * names longer than 78, or bogus col. Input is assumed to be free of line breaks.
1292 pdkim_headcat(int *col, pdkim_str *str, const char * pad,
1293 const char *intro, const char *payload)
1302 pdkim_strcat(str, "\r\n\t");
1305 pdkim_strncat(str, pad, l);
1309 l = (pad?1:0) + (intro?strlen(intro):0);
1312 { /*can't fit intro - start a new line to make room.*/
1313 pdkim_strcat(str, "\r\n\t");
1315 l = intro?strlen(intro):0;
1318 l += payload ? strlen(payload):0 ;
1321 { /* this fragment will not fit on a single line */
1324 pdkim_strcat(str, " ");
1326 pad = NULL; /* only want this once */
1332 size_t sl = strlen(intro);
1334 pdkim_strncat(str, intro, sl);
1337 intro = NULL; /* only want this once */
1342 size_t sl = strlen(payload);
1343 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1345 pdkim_strncat(str, payload, chomp);
1351 /* the while precondition tells us it didn't fit. */
1352 pdkim_strcat(str, "\r\n\t");
1358 pdkim_strcat(str, "\r\n\t");
1365 pdkim_strcat(str, " ");
1372 size_t sl = strlen(intro);
1374 pdkim_strncat(str, intro, sl);
1382 size_t sl = strlen(payload);
1384 pdkim_strncat(str, payload, sl);
1392 /* -------------------------------------------------------------------------- */
1395 pdkim_create_header(pdkim_signature *sig, BOOL final)
1398 char *base64_bh = NULL;
1399 char *base64_b = NULL;
1402 pdkim_str *canon_all;
1404 if (!(hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION)))
1407 if (!(canon_all = pdkim_strnew(pdkim_canons[sig->canon_headers])))
1410 if (!(base64_bh = pdkim_encode_base64(&sig->bodyhash)))
1413 col = strlen(hdr->str);
1415 /* Required and static bits */
1416 if ( pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
1417 && pdkim_headcat(&col, hdr, ";", "q=", pdkim_querymethods[sig->querymethod])
1418 && pdkim_strcat(canon_all, "/")
1419 && pdkim_strcat(canon_all, pdkim_canons[sig->canon_body])
1420 && pdkim_headcat(&col, hdr, ";", "c=", canon_all->str)
1421 && pdkim_headcat(&col, hdr, ";", "d=", sig->domain)
1422 && pdkim_headcat(&col, hdr, ";", "s=", sig->selector)
1425 /* list of header names can be split between items. */
1427 char *n = CS string_copy(sig->headernames);
1434 char *c = strchr(n, ':');
1439 if (!pdkim_headcat(&col, hdr, NULL, NULL, ":"))
1444 if (!pdkim_headcat(&col, hdr, s, i, n))
1458 if(!pdkim_headcat(&col, hdr, ";", "bh=", base64_bh))
1463 if(!pdkim_headcat(&col, hdr, ";", "i=", sig->identity))
1466 if (sig->created > 0)
1470 snprintf(minibuf, 20, "%lu", sig->created);
1471 if(!pdkim_headcat(&col, hdr, ";", "t=", minibuf))
1475 if (sig->expires > 0)
1479 snprintf(minibuf, 20, "%lu", sig->expires);
1480 if(!pdkim_headcat(&col, hdr, ";", "x=", minibuf))
1484 if (sig->bodylength >= 0)
1488 snprintf(minibuf, 20, "%lu", sig->bodylength);
1489 if(!pdkim_headcat(&col, hdr, ";", "l=", minibuf))
1493 /* Preliminary or final version? */
1496 if (!(base64_b = pdkim_encode_base64(&sig->sigdata)))
1498 if (!pdkim_headcat(&col, hdr, ";", "b=", base64_b))
1502 if(!pdkim_headcat(&col, hdr, ";", "b=", ""))
1505 /* add trailing semicolon: I'm not sure if this is actually needed */
1506 if (!pdkim_headcat(&col, hdr, NULL, ";", ""))
1510 rc = strdup(hdr->str);
1514 if (canon_all) pdkim_strfree(canon_all);
1519 /* -------------------------------------------------------------------------- */
1522 pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
1524 pdkim_signature *sig = ctx->sig;
1525 pdkim_str *headernames = NULL; /* Collected signed header names */
1527 /* Check if we must still flush a (partial) header. If that is the
1528 case, the message has no body, and we must compute a body hash
1529 out of '<CR><LF>' */
1530 if (ctx->cur_header && ctx->cur_header->len)
1532 int rc = pdkim_header_complete(ctx);
1533 if (rc != PDKIM_OK) return rc;
1534 pdkim_update_bodyhash(ctx, "\r\n", 2);
1537 DEBUG(D_acl) debug_printf(
1538 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1540 /* Build (and/or evaluate) body hash */
1541 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK)
1542 return PDKIM_ERR_OOM;
1544 /* SIGNING -------------------------------------------------------------- */
1545 if (ctx->mode == PDKIM_MODE_SIGN)
1546 if (!(headernames = pdkim_strnew(NULL)))
1547 return PDKIM_ERR_OOM;
1548 /* ---------------------------------------------------------------------- */
1552 BOOL is_sha1 = sig->algo == PDKIM_ALGO_RSA_SHA1;
1557 int hdata_alloc = 0;
1562 exim_sha_init(&hhash_ctx, is_sha1);
1564 DEBUG(D_acl) debug_printf(
1565 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1567 /* SIGNING ---------------------------------------------------------------- */
1568 /* When signing, walk through our header list and add them to the hash. As we
1569 go, construct a list of the header's names to use for the h= parameter.
1570 Then append to that list any remaining header names for which there was no
1573 if (ctx->mode == PDKIM_MODE_SIGN)
1575 pdkim_stringlist *p;
1580 for (p = sig->headers; p; p = p->next)
1581 if (header_name_match(p->value, sig->sign_headers) == PDKIM_OK)
1584 /* Collect header names (Note: colon presence is guaranteed here) */
1585 uschar * q = Ustrchr(p->value, ':');
1587 if (!(pdkim_strncat(headernames, p->value,
1588 (q - US p->value) + (p->next ? 1 : 0))))
1589 return PDKIM_ERR_OOM;
1591 rh = sig->canon_headers == PDKIM_CANON_RELAXED
1592 ? US pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
1593 : string_copy(CUS p->value); /* just copy it for simple canon */
1595 return PDKIM_ERR_OOM;
1597 /* Feed header to the hash algorithm */
1598 exim_sha_update(&hhash_ctx, CCS rh, Ustrlen(rh));
1600 /* Remember headers block for signing (when the library cannot do incremental) */
1601 (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh);
1603 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1606 l = US sig->sign_headers;
1607 while((s = string_nextinlist(&l, &sep, NULL, 0)))
1609 { /*SSS string_append_listele() */
1610 if (headernames->len > 0 && headernames->str[headernames->len-1] != ':')
1611 if (!(pdkim_strncat(headernames, ":", 1)))
1612 return PDKIM_ERR_OOM;
1613 if (!(pdkim_strncat(headernames, CS s, Ustrlen(s))))
1614 return PDKIM_ERR_OOM;
1618 /* VERIFICATION ----------------------------------------------------------- */
1619 /* When verifying, walk through the header name list in the h= parameter and
1620 add the headers to the hash in that order. */
1623 uschar * b = string_copy(sig->headernames);
1626 pdkim_stringlist * hdrs;
1628 if (!b) return PDKIM_ERR_OOM;
1631 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1636 if ((q = Ustrchr(p, ':')))
1639 /*XXX walk the list of headers in same order as received. */
1640 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1642 && strncasecmp(hdrs->value, CS p, Ustrlen(p)) == 0
1643 && (hdrs->value)[Ustrlen(p)] == ':'
1646 uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
1647 ? US pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
1648 : string_copy(CUS hdrs->value); /* just copy it for simple canon */
1650 return PDKIM_ERR_OOM;
1652 /* Feed header to the hash algorithm */
1653 exim_sha_update(&hhash_ctx, CCS rh, Ustrlen(rh));
1655 DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
1665 DEBUG(D_acl) debug_printf(
1666 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1668 /* SIGNING ---------------------------------------------------------------- */
1669 if (ctx->mode == PDKIM_MODE_SIGN)
1671 /* Copy headernames to signature struct */
1672 sig->headernames = string_copy(US headernames->str);
1673 pdkim_strfree(headernames);
1675 /* Create signature header with b= omitted */
1676 sig_hdr = pdkim_create_header(sig, FALSE);
1679 /* VERIFICATION ----------------------------------------------------------- */
1681 sig_hdr = strdup(sig->rawsig_no_b_val);
1682 /* ------------------------------------------------------------------------ */
1685 return PDKIM_ERR_OOM;
1687 /* Relax header if necessary */
1688 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1690 char *relaxed_hdr = pdkim_relax_header(sig_hdr, 0);
1694 return PDKIM_ERR_OOM;
1695 sig_hdr = relaxed_hdr;
1701 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1702 pdkim_quoteprint(CUS sig_hdr, strlen(sig_hdr));
1704 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1707 /* Finalize header hash */
1708 exim_sha_update(&hhash_ctx, sig_hdr, strlen(sig_hdr));
1709 exim_sha_finish(&hhash_ctx, &hhash);
1713 debug_printf("PDKIM [%s] hh computed: ", sig->domain);
1714 pdkim_hexprint(hhash.data, hhash.len);
1717 /* Remember headers block for signing (when the library cannot do incremental) */
1718 if (ctx->mode == PDKIM_MODE_SIGN)
1719 (void) exim_rsa_data_append(&hdata, &hdata_alloc, US sig_hdr);
1723 /* SIGNING ---------------------------------------------------------------- */
1724 if (ctx->mode == PDKIM_MODE_SIGN)
1727 const uschar * errstr;
1729 /* Import private key */
1730 if ((errstr = exim_rsa_signing_init(US sig->rsa_privkey, &sctx)))
1732 DEBUG(D_acl) debug_printf("signing_init: %s\n", errstr);
1733 return PDKIM_ERR_RSA_PRIVKEY;
1736 /* Do signing. With OpenSSL we are signing the hash of headers just
1737 calculated, with GnuTLS we have to sign an entire block of headers
1738 (due to available interfaces) and it recalculates the hash internally. */
1740 #if defined(RSA_OPENSSL) || defined(RSA_GCRYPT)
1744 if ((errstr = exim_rsa_sign(&sctx, is_sha1, &hdata, &sig->sigdata)))
1746 DEBUG(D_acl) debug_printf("signing: %s\n", errstr);
1747 return PDKIM_ERR_RSA_SIGNING;
1752 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1753 pdkim_hexprint(sig->sigdata.data, sig->sigdata.len);
1756 if (!(sig->signature_header = pdkim_create_header(sig, TRUE)))
1757 return PDKIM_ERR_OOM;
1760 /* VERIFICATION ----------------------------------------------------------- */
1764 const uschar * errstr;
1766 char *dns_txt_name, *dns_txt_reply;
1768 /* Fetch public key for signing domain, from DNS */
1770 if (!(dns_txt_name = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
1771 return PDKIM_ERR_OOM;
1773 if (!(dns_txt_reply = malloc(PDKIM_DNS_TXT_MAX_RECLEN)))
1776 return PDKIM_ERR_OOM;
1779 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1780 memset(dns_txt_name , 0, PDKIM_DNS_TXT_MAX_NAMELEN);
1782 if (snprintf(dns_txt_name, PDKIM_DNS_TXT_MAX_NAMELEN,
1783 "%s._domainkey.%s.",
1784 sig->selector, sig->domain) >= PDKIM_DNS_TXT_MAX_NAMELEN)
1786 sig->verify_status = PDKIM_VERIFY_INVALID;
1787 sig->verify_ext_status = PDKIM_VERIFY_INVALID_BUFFER_SIZE;
1791 if ( ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK
1792 || dns_txt_reply[0] == '\0')
1794 sig->verify_status = PDKIM_VERIFY_INVALID;
1795 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1802 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1804 pdkim_quoteprint(CUS dns_txt_reply, strlen(dns_txt_reply));
1807 if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, dns_txt_reply)))
1809 sig->verify_status = PDKIM_VERIFY_INVALID;
1810 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_DNSRECORD;
1812 DEBUG(D_acl) debug_printf(
1813 " Error while parsing public key record\n"
1814 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1818 DEBUG(D_acl) debug_printf(
1819 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1821 /* Import public key */
1822 if ((errstr = exim_rsa_verify_init(&sig->pubkey->key, &vctx)))
1824 DEBUG(D_acl) debug_printf("verify_init: %s\n", errstr);
1825 sig->verify_status = PDKIM_VERIFY_INVALID;
1826 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_IMPORT;
1830 /* Check the signature */
1831 if ((errstr = exim_rsa_verify(&vctx, is_sha1, &hhash, &sig->sigdata)))
1833 DEBUG(D_acl) debug_printf("headers verify: %s\n", errstr);
1834 sig->verify_status = PDKIM_VERIFY_FAIL;
1835 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1840 /* We have a winner! (if bodydhash was correct earlier) */
1841 if (sig->verify_status == PDKIM_VERIFY_NONE)
1842 sig->verify_status = PDKIM_VERIFY_PASS;
1848 debug_printf("PDKIM [%s] signature status: %s",
1849 sig->domain, pdkim_verify_status_str(sig->verify_status));
1850 if (sig->verify_ext_status > 0)
1851 debug_printf(" (%s)\n",
1852 pdkim_verify_ext_status_str(sig->verify_ext_status));
1858 free(dns_txt_reply);
1864 /* If requested, set return pointer to signature(s) */
1865 if (return_signatures)
1866 *return_signatures = ctx->sig;
1872 /* -------------------------------------------------------------------------- */
1874 DLLEXPORT pdkim_ctx *
1875 pdkim_init_verify(int(*dns_txt_callback)(char *, char *))
1877 pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
1881 memset(ctx, 0, sizeof(pdkim_ctx));
1883 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1889 ctx->mode = PDKIM_MODE_VERIFY;
1890 ctx->dns_txt_callback = dns_txt_callback;
1896 /* -------------------------------------------------------------------------- */
1898 DLLEXPORT pdkim_ctx *
1899 pdkim_init_sign(char *domain, char *selector, char *rsa_privkey, int algo)
1902 pdkim_signature *sig;
1904 if (!domain || !selector || !rsa_privkey)
1907 if (!(ctx = malloc(sizeof(pdkim_ctx))))
1909 memset(ctx, 0, sizeof(pdkim_ctx));
1911 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1917 if (!(sig = malloc(sizeof(pdkim_signature))))
1923 memset(sig, 0, sizeof(pdkim_signature));
1925 sig->bodylength = -1;
1927 ctx->mode = PDKIM_MODE_SIGN;
1930 sig->domain = strdup(domain);
1931 sig->selector = strdup(selector);
1932 sig->rsa_privkey = strdup(rsa_privkey);
1935 if (!sig->domain || !sig->selector || !sig->rsa_privkey)
1938 exim_sha_init(&sig->body_hash, algo == PDKIM_ALGO_RSA_SHA1);
1942 pdkim_free_ctx(ctx);
1947 /* -------------------------------------------------------------------------- */
1950 pdkim_set_optional(pdkim_ctx *ctx,
1956 unsigned long created,
1957 unsigned long expires)
1959 pdkim_signature * sig = ctx->sig;
1962 if (!(sig->identity = strdup(identity)))
1963 return PDKIM_ERR_OOM;
1965 if (!(sig->sign_headers = strdup(sign_headers
1966 ? sign_headers : PDKIM_DEFAULT_SIGN_HEADERS)))
1967 return PDKIM_ERR_OOM;
1969 sig->canon_headers = canon_headers;
1970 sig->canon_body = canon_body;
1971 sig->bodylength = bodylength;
1972 sig->created = created;
1973 sig->expires = expires;
1987 #endif /*DISABLE_DKIM*/