2 * PDKIM - a RFC4871 (DKIM) implementation
4 * Copyright (C) 2009 - 2015 Tom Kistner <tom@duncanthrax.net>
6 * http://duncanthrax.net/pdkim/
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "pdkim-rsa.h"
27 #include "polarssl/sha1.h"
28 #include "polarssl/sha2.h"
29 #include "polarssl/rsa.h"
30 #include "polarssl/base64.h"
32 #define PDKIM_SIGNATURE_VERSION "1"
33 #define PDKIM_PUB_RECORD_VERSION "DKIM1"
35 #define PDKIM_MAX_HEADER_LEN 65536
36 #define PDKIM_MAX_HEADERS 512
37 #define PDKIM_MAX_BODY_LINE_LEN 16384
38 #define PDKIM_DNS_TXT_MAX_NAMELEN 1024
39 #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
40 "Message-ID:To:Cc:MIME-Version:Content-Type:"\
41 "Content-Transfer-Encoding:Content-ID:"\
42 "Content-Description:Resent-Date:Resent-From:"\
43 "Resent-Sender:Resent-To:Resent-Cc:"\
44 "Resent-Message-ID:In-Reply-To:References:"\
45 "List-Id:List-Help:List-Unsubscribe:"\
46 "List-Subscribe:List-Post:List-Owner:List-Archive"
48 /* -------------------------------------------------------------------------- */
49 struct pdkim_stringlist {
55 #define PDKIM_STR_ALLOC_FRAG 256
59 unsigned int allocated;
62 /* -------------------------------------------------------------------------- */
63 /* A bunch of list constants */
64 const char *pdkim_querymethods[] = {
68 const char *pdkim_algos[] = {
73 const char *pdkim_canons[] = {
78 const char *pdkim_hashes[] = {
83 const char *pdkim_keytypes[] = {
88 typedef struct pdkim_combined_canon_entry {
92 } pdkim_combined_canon_entry;
93 pdkim_combined_canon_entry pdkim_combined_canons[] = {
94 { "simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
95 { "simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
96 { "relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
97 { "relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
98 { "simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
99 { "relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
104 const char *pdkim_verify_status_str(int status) {
106 case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
107 case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
108 case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
109 case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
110 default: return "PDKIM_VERIFY_UNKNOWN";
113 const char *pdkim_verify_ext_status_str(int ext_status) {
115 case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
116 case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
117 case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
118 case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
119 case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: return "PDKIM_VERIFY_INVALID_PUBKEY_PARSING";
120 default: return "PDKIM_VERIFY_UNKNOWN";
125 /* -------------------------------------------------------------------------- */
126 /* Print debugging functions */
128 pdkim_quoteprint(const char *data, int len, int lf)
131 const unsigned char *p = (const unsigned char *)data;
133 for (i = 0; i < len; i++)
138 case ' ' : debug_printf("{SP}"); break;
139 case '\t': debug_printf("{TB}"); break;
140 case '\r': debug_printf("{CR}"); break;
141 case '\n': debug_printf("{LF}"); break;
142 case '{' : debug_printf("{BO}"); break;
143 case '}' : debug_printf("{BC}"); break;
145 if ( (c < 32) || (c > 127) )
146 debug_printf("{%02x}", c);
148 debug_printf("%c", c);
157 pdkim_hexprint(const char *data, int len, int lf)
160 const unsigned char *p = (const unsigned char *)data;
162 for (i = 0 ; i < len; i++)
163 debug_printf("%02x", p[i]);
169 /* -------------------------------------------------------------------------- */
170 /* Simple string list implementation for convinience */
172 pdkim_append_stringlist(pdkim_stringlist *base, char *str)
174 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
176 if (!new_entry) return NULL;
177 memset(new_entry, 0, sizeof(pdkim_stringlist));
178 if (!(new_entry->value = strdup(str))) return NULL;
181 pdkim_stringlist *last = base;
182 while (last->next != NULL) { last = last->next; }
183 last->next = new_entry;
191 pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
193 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
195 if (!new_entry) return NULL;
196 memset(new_entry, 0, sizeof(pdkim_stringlist));
197 if (!(new_entry->value = strdup(str))) return NULL;
199 new_entry->next = base;
204 /* -------------------------------------------------------------------------- */
205 /* A small "growing string" implementation to escape malloc/realloc hell */
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';
230 pdkim_strncat(pdkim_str *str, const char *data, int len)
232 if ((str->allocated - str->len) < (len+1))
234 /* Extend the buffer */
235 int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
236 char *n = realloc(str->str,
237 (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
238 if (n == NULL) return NULL;
240 str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
242 strncpy(&(str->str[str->len]), data, len);
244 str->str[str->len] = '\0';
249 pdkim_strcat(pdkim_str *str, const char *cstr)
251 return pdkim_strncat(str, cstr, strlen(cstr));
255 pdkim_numcat(pdkim_str *str, unsigned long num)
258 snprintf(minibuf, 20, "%lu", num);
259 return pdkim_strcat(str, minibuf);
263 pdkim_strtrim(pdkim_str *str)
267 while ( (*p != '\0') && ((*p == '\t') || (*p == ' ')) ) p++;
268 while (*p != '\0') {*q = *p; q++; p++;}
270 while ( (q != str->str) && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) )
275 str->len = strlen(str->str);
280 pdkim_strclear(pdkim_str *str)
288 pdkim_strfree(pdkim_str *str)
291 if (str->str) free(str->str);
297 /* -------------------------------------------------------------------------- */
300 pdkim_free_pubkey(pdkim_pubkey *pub)
304 if (pub->version ) free(pub->version);
305 if (pub->granularity) free(pub->granularity);
306 if (pub->hashes ) free(pub->hashes);
307 if (pub->keytype ) free(pub->keytype);
308 if (pub->srvtype ) free(pub->srvtype);
309 if (pub->notes ) free(pub->notes);
310 if (pub->key ) free(pub->key);
316 /* -------------------------------------------------------------------------- */
319 pdkim_free_sig(pdkim_signature *sig)
323 pdkim_signature *next = (pdkim_signature *)sig->next;
325 pdkim_stringlist *e = sig->headers;
328 pdkim_stringlist *c = e;
329 if (e->value) free(e->value);
334 if (sig->sigdata ) free(sig->sigdata);
335 if (sig->bodyhash ) free(sig->bodyhash);
336 if (sig->selector ) free(sig->selector);
337 if (sig->domain ) free(sig->domain);
338 if (sig->identity ) free(sig->identity);
339 if (sig->headernames ) free(sig->headernames);
340 if (sig->copiedheaders ) free(sig->copiedheaders);
341 if (sig->rsa_privkey ) free(sig->rsa_privkey);
342 if (sig->sign_headers ) free(sig->sign_headers);
343 if (sig->signature_header) free(sig->signature_header);
344 if (sig->sha1_body ) free(sig->sha1_body);
345 if (sig->sha2_body ) free(sig->sha2_body);
347 if (sig->pubkey) pdkim_free_pubkey(sig->pubkey);
350 if (next) pdkim_free_sig(next);
355 /* -------------------------------------------------------------------------- */
358 pdkim_free_ctx(pdkim_ctx *ctx)
362 pdkim_stringlist *e = ctx->headers;
365 pdkim_stringlist *c = e;
366 if (e->value) free(e->value);
370 pdkim_free_sig(ctx->sig);
371 pdkim_strfree(ctx->cur_header);
377 /* -------------------------------------------------------------------------- */
378 /* Matches the name of the passed raw "header" against
379 the passed colon-separated "list", starting at entry
380 "start". Returns the position of the header name in
384 header_name_match(const char *header,
394 /* Get header name */
395 char *hcolon = strchr(header, ':');
397 if (!hcolon) return rc; /* This isn't a header */
399 if (!(hname = malloc((hcolon-header)+1)))
400 return PDKIM_ERR_OOM;
401 memset(hname, 0, (hcolon-header)+1);
402 strncpy(hname, header, (hcolon-header));
404 /* Copy tick-off list locally, so we can punch zeroes into it */
405 if (!(lcopy = strdup(tick)))
408 return PDKIM_ERR_OOM;
416 if (strcasecmp(p, hname) == 0)
419 /* Invalidate header name instance in tick-off list */
420 if (do_tick) tick[p-lcopy] = '_';
428 if (strcasecmp(p, hname) == 0)
431 /* Invalidate header name instance in tick-off list */
432 if (do_tick) tick[p-lcopy] = '_';
442 /* -------------------------------------------------------------------------- */
443 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
447 pdkim_relax_header (char *header, int crlf)
449 BOOL past_field_name = FALSE;
450 BOOL seen_wsp = FALSE;
453 char *relaxed = malloc(strlen(header)+3);
455 if (!relaxed) return NULL;
458 for (p = header; *p != '\0'; p++)
462 if (c == '\r' || c == '\n')
464 if (c == '\t' || c == ' ')
468 c = ' '; /* Turns WSP into SP */
472 if (!past_field_name && c == ':')
474 if (seen_wsp) q--; /* This removes WSP before the colon */
475 seen_wsp = TRUE; /* This removes WSP after the colon */
476 past_field_name = TRUE;
481 /* Lowercase header name */
482 if (!past_field_name) c = tolower(c);
486 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
489 if (crlf) strcat(relaxed, "\r\n");
494 /* -------------------------------------------------------------------------- */
495 #define PDKIM_QP_ERROR_DECODE -1
498 pdkim_decode_qp_char(char *qp_p, int *c)
500 char *initial_pos = qp_p;
502 /* Advance one char */
505 /* Check for two hex digits and decode them */
506 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
508 /* Do hex conversion */
509 *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
510 *c |= isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
514 /* Illegal char here */
515 *c = PDKIM_QP_ERROR_DECODE;
520 /* -------------------------------------------------------------------------- */
523 pdkim_decode_qp(char *str)
528 char *n = malloc(strlen(p)+1);
538 p = pdkim_decode_qp_char(p, &nchar);
554 /* -------------------------------------------------------------------------- */
557 pdkim_decode_base64(char *str, int *num_decoded)
562 base64_decode(NULL, &dlen, (unsigned char *)str, strlen(str));
564 if (!(res = malloc(dlen+1)))
566 if (base64_decode((unsigned char *)res, &dlen, (unsigned char *)str, strlen(str)) != 0)
572 if (num_decoded) *num_decoded = dlen;
577 /* -------------------------------------------------------------------------- */
580 pdkim_encode_base64(char *str, int num)
585 base64_encode(NULL, &dlen, (unsigned char *)str, num);
587 if (!(res = malloc(dlen+1)))
589 if (base64_encode((unsigned char *)res, &dlen, (unsigned char *)str, num) != 0)
598 /* -------------------------------------------------------------------------- */
599 #define PDKIM_HDR_LIMBO 0
600 #define PDKIM_HDR_TAG 1
601 #define PDKIM_HDR_VALUE 2
604 pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
606 pdkim_signature *sig ;
608 pdkim_str *cur_tag = NULL;
609 pdkim_str *cur_val = NULL;
610 BOOL past_hname = FALSE;
611 BOOL in_b_val = FALSE;
612 int where = PDKIM_HDR_LIMBO;
615 if (!(sig = malloc(sizeof(pdkim_signature)))) return NULL;
616 memset(sig, 0, sizeof(pdkim_signature));
617 sig->bodylength = -1;
619 if (!(sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1)))
625 q = sig->rawsig_no_b_val;
627 for (p = raw_hdr; ; p++)
632 if (c == '\r' || c == '\n')
635 /* Fast-forward through header name */
638 if (c == ':') past_hname = TRUE;
642 if (where == PDKIM_HDR_LIMBO)
644 /* In limbo, just wait for a tag-char to appear */
645 if (!(c >= 'a' && c <= 'z'))
648 where = PDKIM_HDR_TAG;
651 if (where == PDKIM_HDR_TAG)
654 cur_tag = pdkim_strnew(NULL);
656 if (c >= 'a' && c <= 'z')
657 pdkim_strncat(cur_tag, p, 1);
661 if (strcmp(cur_tag->str, "b") == 0)
666 where = PDKIM_HDR_VALUE;
671 if (where == PDKIM_HDR_VALUE)
674 cur_val = pdkim_strnew(NULL);
676 if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
679 if (c == ';' || c == '\0')
681 if (cur_tag->len > 0)
683 pdkim_strtrim(cur_val);
685 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
687 switch (cur_tag->str[0])
690 if (cur_tag->str[1] == 'h')
691 sig->bodyhash = pdkim_decode_base64(cur_val->str,
694 sig->sigdata = pdkim_decode_base64(cur_val->str,
698 /* We only support version 1, and that is currently the
699 only version there is. */
700 if (strcmp(cur_val->str, PDKIM_SIGNATURE_VERSION) == 0)
704 for (i = 0; pdkim_algos[i]; i++)
705 if (strcmp(cur_val->str, pdkim_algos[i]) == 0)
712 for (i = 0; pdkim_combined_canons[i].str; i++)
713 if (strcmp(cur_val->str, pdkim_combined_canons[i].str) == 0)
715 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
716 sig->canon_body = pdkim_combined_canons[i].canon_body;
721 for (i = 0; pdkim_querymethods[i]; i++)
722 if (strcmp(cur_val->str, pdkim_querymethods[i]) == 0)
724 sig->querymethod = i;
729 sig->selector = strdup(cur_val->str); break;
731 sig->domain = strdup(cur_val->str); break;
733 sig->identity = pdkim_decode_qp(cur_val->str); break;
735 sig->created = strtoul(cur_val->str, NULL, 10); break;
737 sig->expires = strtoul(cur_val->str, NULL, 10); break;
739 sig->bodylength = strtol(cur_val->str, NULL, 10); break;
741 sig->headernames = strdup(cur_val->str); break;
743 sig->copiedheaders = pdkim_decode_qp(cur_val->str); break;
745 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
749 pdkim_strclear(cur_tag);
750 pdkim_strclear(cur_val);
752 where = PDKIM_HDR_LIMBO;
755 pdkim_strncat(cur_val, p, 1);
766 /* Make sure the most important bits are there. */
767 if (!(sig->domain && (*(sig->domain) != '\0') &&
768 sig->selector && (*(sig->selector) != '\0') &&
769 sig->headernames && (*(sig->headernames) != '\0') &&
779 /* Chomp raw header. The final newline must not be added to the signature. */
781 while (q > sig->rawsig_no_b_val && (*q == '\r' || *q == '\n'))
782 *q = '\0'; q--; /*XXX questionable code layout; possible bug */
787 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
788 pdkim_quoteprint(sig->rawsig_no_b_val, strlen(sig->rawsig_no_b_val), 1);
790 "PDKIM >> Sig size: %4d bits\n", sig->sigdata_len*8);
792 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
795 if ( !(sig->sha1_body = malloc(sizeof(sha1_context)))
796 || !(sig->sha2_body = malloc(sizeof(sha2_context)))
803 sha1_starts(sig->sha1_body);
804 sha2_starts(sig->sha2_body, 0);
810 /* -------------------------------------------------------------------------- */
813 pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
817 pdkim_str *cur_tag = NULL;
818 pdkim_str *cur_val = NULL;
819 int where = PDKIM_HDR_LIMBO;
821 if (!(pub = malloc(sizeof(pdkim_pubkey)))) return NULL;
822 memset(pub, 0, sizeof(pdkim_pubkey));
824 for (p = raw_record; ; p++)
829 if (c == '\r' || c == '\n')
832 if (where == PDKIM_HDR_LIMBO)
834 /* In limbo, just wait for a tag-char to appear */
835 if (!(c >= 'a' && c <= 'z'))
838 where = PDKIM_HDR_TAG;
841 if (where == PDKIM_HDR_TAG)
844 cur_tag = pdkim_strnew(NULL);
846 if (c >= 'a' && c <= 'z')
847 pdkim_strncat(cur_tag, p, 1);
851 where = PDKIM_HDR_VALUE;
856 if (where == PDKIM_HDR_VALUE)
859 cur_val = pdkim_strnew(NULL);
861 if (c == '\r' || c == '\n')
864 if (c == ';' || c == '\0')
866 if (cur_tag->len > 0)
868 pdkim_strtrim(cur_val);
869 DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->str, cur_val->str);
871 switch (cur_tag->str[0])
874 /* This tag isn't evaluated because:
875 - We only support version DKIM1.
876 - Which is the default for this value (set below)
877 - Other versions are currently not specified. */
880 pub->hashes = strdup(cur_val->str); break;
882 pub->granularity = strdup(cur_val->str); break;
884 pub->notes = pdkim_decode_qp(cur_val->str); break;
886 pub->key = pdkim_decode_base64(cur_val->str, &(pub->key_len)); break;
888 pub->hashes = strdup(cur_val->str); break;
890 pub->srvtype = strdup(cur_val->str); break;
892 if (strchr(cur_val->str, 'y') != NULL) pub->testing = 1;
893 if (strchr(cur_val->str, 's') != NULL) pub->no_subdomaining = 1;
896 DEBUG(D_acl) debug_printf(" Unknown tag encountered\n");
900 pdkim_strclear(cur_tag);
901 pdkim_strclear(cur_val);
902 where = PDKIM_HDR_LIMBO;
905 pdkim_strncat(cur_val, p, 1);
909 if (c == '\0') break;
912 /* Set fallback defaults */
913 if (!pub->version ) pub->version = strdup(PDKIM_PUB_RECORD_VERSION);
914 if (!pub->granularity) pub->granularity = strdup("*");
915 if (!pub->keytype ) pub->keytype = strdup("rsa");
916 if (!pub->srvtype ) pub->srvtype = strdup("*");
922 pdkim_free_pubkey(pub);
927 /* -------------------------------------------------------------------------- */
930 pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
932 pdkim_signature *sig = ctx->sig;
933 /* Cache relaxed version of data */
934 char *relaxed_data = NULL;
937 /* Traverse all signatures, updating their hashes. */
940 /* Defaults to simple canon (no further treatment necessary) */
941 const char *canon_data = data;
944 if (sig->canon_body == PDKIM_CANON_RELAXED)
946 /* Relax the line if not done already */
949 BOOL seen_wsp = FALSE;
953 if (!(relaxed_data = malloc(len+1)))
954 return PDKIM_ERR_OOM;
956 for (p = data; *p; p++)
961 if (q > 0 && relaxed_data[q-1] == ' ')
964 else if (c == '\t' || c == ' ')
966 c = ' '; /* Turns WSP into SP */
973 relaxed_data[q++] = c;
975 relaxed_data[q] = '\0';
978 canon_data = relaxed_data;
979 canon_len = relaxed_len;
982 /* Make sure we don't exceed the to-be-signed body length */
983 if ( sig->bodylength >= 0
984 && sig->signed_body_bytes + (unsigned long)canon_len > sig->bodylength
986 canon_len = sig->bodylength - sig->signed_body_bytes;
990 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
991 sha1_update(sig->sha1_body, (unsigned char *)canon_data, canon_len);
993 sha2_update(sig->sha2_body, (unsigned char *)canon_data, canon_len);
995 sig->signed_body_bytes += canon_len;
996 DEBUG(D_acl) pdkim_quoteprint(canon_data, canon_len, 1);
1002 if (relaxed_data) free(relaxed_data);
1007 /* -------------------------------------------------------------------------- */
1010 pdkim_finish_bodyhash(pdkim_ctx *ctx)
1012 pdkim_signature *sig = ctx->sig;
1014 /* Traverse all signatures */
1016 { /* Finish hashes */
1017 unsigned char bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
1019 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1020 sha1_finish(sig->sha1_body, bh);
1022 sha2_finish(sig->sha2_body, bh);
1026 debug_printf("PDKIM [%s] Body bytes hashed: %lu\n"
1027 "PDKIM [%s] bh computed: ",
1028 sig->domain, sig->signed_body_bytes, sig->domain);
1029 pdkim_hexprint((char *)bh, sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32, 1);
1032 /* SIGNING -------------------------------------------------------------- */
1033 if (ctx->mode == PDKIM_MODE_SIGN)
1035 sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
1037 if (!(sig->bodyhash = malloc(sig->bodyhash_len)))
1038 return PDKIM_ERR_OOM;
1039 memcpy(sig->bodyhash, bh, sig->bodyhash_len);
1041 /* If bodylength limit is set, and we have received less bytes
1042 than the requested amount, effectively remove the limit tag. */
1043 if (sig->signed_body_bytes < sig->bodylength)
1044 sig->bodylength = -1;
1047 /* VERIFICATION --------------------------------------------------------- */
1050 /* Compare bodyhash */
1051 if (memcmp(bh, sig->bodyhash,
1052 (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0)
1054 DEBUG(D_acl) debug_printf("PDKIM [%s] Body hash verified OK\n", sig->domain);
1060 debug_printf("PDKIM [%s] bh signature: ", sig->domain);
1061 pdkim_hexprint(sig->bodyhash,
1062 sig->algo == PDKIM_ALGO_RSA_SHA1 ? 20 : 32, 1);
1063 debug_printf("PDKIM [%s] Body hash did NOT verify\n", sig->domain);
1065 sig->verify_status = PDKIM_VERIFY_FAIL;
1066 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
1078 /* -------------------------------------------------------------------------- */
1079 /* Callback from pdkim_feed below for processing complete body lines */
1082 pdkim_bodyline_complete(pdkim_ctx *ctx)
1084 char *p = ctx->linebuf;
1085 int n = ctx->linebuf_offset;
1086 pdkim_signature *sig = ctx->sig; /*XXX assumes only one sig */
1088 /* Ignore extra data if we've seen the end-of-data marker */
1089 if (ctx->seen_eod) goto BAIL;
1091 /* We've always got one extra byte to stuff a zero ... */
1092 ctx->linebuf[ctx->linebuf_offset] = '\0';
1094 /* Terminate on EOD marker */
1095 if (memcmp(p, ".\r\n", 3) == 0)
1097 /* In simple body mode, if any empty lines were buffered,
1098 replace with one. rfc 4871 3.4.3 */
1099 /*XXX checking the signed-body-bytes is a gross hack; I think
1100 it indicates that all linebreaks should be buffered, including
1101 the one terminating a text line */
1102 if ( sig && sig->canon_body == PDKIM_CANON_SIMPLE
1103 && sig->signed_body_bytes == 0
1104 && ctx->num_buffered_crlf > 0
1106 pdkim_update_bodyhash(ctx, "\r\n", 2);
1108 ctx->seen_eod = TRUE;
1112 if (memcmp(p, "..", 2) == 0)
1118 /* Empty lines need to be buffered until we find a non-empty line */
1119 if (memcmp(p, "\r\n", 2) == 0)
1121 ctx->num_buffered_crlf++;
1125 if (sig && sig->canon_body == PDKIM_CANON_RELAXED)
1127 /* Lines with just spaces need to be buffered too */
1129 while (memcmp(check, "\r\n", 2) != 0)
1133 if (c != '\t' && c != ' ')
1138 ctx->num_buffered_crlf++;
1143 /* At this point, we have a non-empty line, so release the buffered ones. */
1144 while (ctx->num_buffered_crlf)
1146 pdkim_update_bodyhash(ctx, "\r\n", 2);
1147 ctx->num_buffered_crlf--;
1150 pdkim_update_bodyhash(ctx, p, n);
1153 ctx->linebuf_offset = 0;
1158 /* -------------------------------------------------------------------------- */
1159 /* Callback from pdkim_feed below for processing complete headers */
1160 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
1163 pdkim_header_complete(pdkim_ctx *ctx)
1165 /* Special case: The last header can have an extra \r appended */
1166 if ( (ctx->cur_header->len > 1) &&
1167 (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') )
1169 ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
1170 ctx->cur_header->len--;
1174 if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
1176 /* SIGNING -------------------------------------------------------------- */
1177 if (ctx->mode == PDKIM_MODE_SIGN)
1179 pdkim_signature *sig;
1181 for (sig = ctx->sig; sig; sig = sig->next) /* Traverse all signatures */
1182 if (header_name_match(ctx->cur_header->str,
1185 PDKIM_DEFAULT_SIGN_HEADERS, 0) == PDKIM_OK)
1187 pdkim_stringlist *list;
1189 /* Add header to the signed headers list (in reverse order) */
1190 if (!(list = pdkim_prepend_stringlist(sig->headers,
1191 ctx->cur_header->str)))
1192 return PDKIM_ERR_OOM;
1193 sig->headers = list;
1197 /* VERIFICATION ----------------------------------------------------------- */
1198 /* DKIM-Signature: headers are added to the verification list */
1199 if (ctx->mode == PDKIM_MODE_VERIFY)
1201 if (strncasecmp(ctx->cur_header->str,
1202 DKIM_SIGNATURE_HEADERNAME,
1203 strlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
1205 pdkim_signature *new_sig;
1207 /* Create and chain new signature block */
1208 DEBUG(D_acl) debug_printf(
1209 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1211 if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str)))
1213 pdkim_signature *last_sig = ctx->sig;
1218 while (last_sig->next) last_sig = last_sig->next;
1219 last_sig->next = new_sig;
1223 DEBUG(D_acl) debug_printf(
1224 "Error while parsing signature header\n"
1225 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1228 /* every other header is stored for signature verification */
1231 pdkim_stringlist *list;
1233 if (!(list = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->str)))
1234 return PDKIM_ERR_OOM;
1235 ctx->headers = list;
1240 pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
1246 /* -------------------------------------------------------------------------- */
1247 #define HEADER_BUFFER_FRAG_SIZE 256
1250 pdkim_feed (pdkim_ctx *ctx, char *data, int len)
1254 for (p = 0; p<len; p++)
1258 if (ctx->past_headers)
1260 /* Processing body byte */
1261 ctx->linebuf[ctx->linebuf_offset++] = c;
1264 int rc = pdkim_bodyline_complete(ctx); /* End of line */
1265 if (rc != PDKIM_OK) return rc;
1267 if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
1268 return PDKIM_ERR_LONG_LINE;
1272 /* Processing header byte */
1279 int rc = pdkim_header_complete(ctx); /* Seen last header line */
1280 if (rc != PDKIM_OK) return rc;
1282 ctx->past_headers = TRUE;
1284 DEBUG(D_acl) debug_printf(
1285 "PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1289 ctx->seen_lf = TRUE;
1291 else if (ctx->seen_lf)
1293 if (!(c == '\t' || c == ' '))
1295 int rc = pdkim_header_complete(ctx); /* End of header */
1296 if (rc != PDKIM_OK) return rc;
1298 ctx->seen_lf = FALSE;
1302 if (!ctx->cur_header)
1303 if (!(ctx->cur_header = pdkim_strnew(NULL)))
1304 return PDKIM_ERR_OOM;
1306 if (ctx->cur_header->len < PDKIM_MAX_HEADER_LEN)
1307 if (!pdkim_strncat(ctx->cur_header, &data[p], 1))
1308 return PDKIM_ERR_OOM;
1315 * RFC 5322 specifies that header line length SHOULD be no more than 78
1320 * col: this int holds and receives column number (octets since last '\n')
1321 * str: partial string to append to
1322 * pad: padding, split line or space after before or after eg: ";"
1323 * intro: - must join to payload eg "h=", usually the tag name
1324 * payload: eg base64 data - long data can be split arbitrarily.
1326 * this code doesn't fold the header in some of the places that RFC4871
1327 * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1328 * pairs and inside long values. it also always spaces or breaks after the
1331 * no guarantees are made for output given out-of range input. like tag
1332 * names loinger than 78, or bogus col. Input is assumed to be free of line breaks.
1336 pdkim_headcat(int *col, pdkim_str *str, const char * pad,
1337 const char *intro, const char *payload)
1346 pdkim_strcat(str, "\r\n\t");
1349 pdkim_strncat(str, pad, l);
1353 l = (pad?1:0) + (intro?strlen(intro):0);
1356 { /*can't fit intro - start a new line to make room.*/
1357 pdkim_strcat(str, "\r\n\t");
1359 l = intro?strlen(intro):0;
1362 l += payload ? strlen(payload):0 ;
1365 { /* this fragment will not fit on a single line */
1368 pdkim_strcat(str, " ");
1370 pad = NULL; /* only want this once */
1376 size_t sl = strlen(intro);
1378 pdkim_strncat(str, intro, sl);
1381 intro = NULL; /* only want this once */
1386 size_t sl = strlen(payload);
1387 size_t chomp = *col+sl < 77 ? sl : 78-*col;
1389 pdkim_strncat(str, payload, chomp);
1395 /* the while precondition tells us it didn't fit. */
1396 pdkim_strcat(str, "\r\n\t");
1402 pdkim_strcat(str, "\r\n\t");
1409 pdkim_strcat(str, " ");
1416 size_t sl = strlen(intro);
1418 pdkim_strncat(str, intro, sl);
1426 size_t sl = strlen(payload);
1428 pdkim_strncat(str, payload, sl);
1436 /* -------------------------------------------------------------------------- */
1439 pdkim_create_header(pdkim_signature *sig, int final)
1442 char *base64_bh = NULL;
1443 char *base64_b = NULL;
1446 pdkim_str *canon_all;
1448 if (!(hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION)))
1451 if (!(canon_all = pdkim_strnew(pdkim_canons[sig->canon_headers])))
1454 if (!(base64_bh = pdkim_encode_base64(sig->bodyhash, sig->bodyhash_len)))
1457 col = strlen(hdr->str);
1459 /* Required and static bits */
1460 if ( pdkim_headcat(&col, hdr, ";", "a=", pdkim_algos[sig->algo])
1461 && pdkim_headcat(&col, hdr, ";", "q=", pdkim_querymethods[sig->querymethod])
1462 && pdkim_strcat(canon_all, "/")
1463 && pdkim_strcat(canon_all, pdkim_canons[sig->canon_body])
1464 && pdkim_headcat(&col, hdr, ";", "c=", canon_all->str)
1465 && pdkim_headcat(&col, hdr, ";", "d=", sig->domain)
1466 && pdkim_headcat(&col, hdr, ";", "s=", sig->selector)
1469 /* list of eader names can be split between items. */
1471 char *n = strdup(sig->headernames);
1479 char *c = strchr(n, ':');
1484 if (!pdkim_headcat(&col, hdr, NULL, NULL, ":"))
1490 if (!pdkim_headcat(&col, hdr, s, i, n))
1506 if(!pdkim_headcat(&col, hdr, ";", "bh=", base64_bh))
1511 if(!pdkim_headcat(&col, hdr, ";", "i=", sig->identity))
1514 if (sig->created > 0)
1518 snprintf(minibuf, 20, "%lu", sig->created);
1519 if(!pdkim_headcat(&col, hdr, ";", "t=", minibuf))
1523 if (sig->expires > 0)
1527 snprintf(minibuf, 20, "%lu", sig->expires);
1528 if(!pdkim_headcat(&col, hdr, ";", "x=", minibuf))
1532 if (sig->bodylength >= 0)
1536 snprintf(minibuf, 20, "%lu", sig->bodylength);
1537 if(!pdkim_headcat(&col, hdr, ";", "l=", minibuf))
1541 /* Preliminary or final version? */
1544 if (!(base64_b = pdkim_encode_base64(sig->sigdata, sig->sigdata_len)))
1546 if (!pdkim_headcat(&col, hdr, ";", "b=", base64_b))
1550 if(!pdkim_headcat(&col, hdr, ";", "b=", ""))
1553 /* add trailing semicolon: I'm not sure if this is actually needed */
1554 if (!pdkim_headcat(&col, hdr, NULL, ";", ""))
1558 rc = strdup(hdr->str);
1562 if (canon_all) pdkim_strfree(canon_all);
1563 if (base64_bh) free(base64_bh);
1564 if (base64_b ) free(base64_b);
1569 /* -------------------------------------------------------------------------- */
1572 pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
1574 pdkim_signature *sig = ctx->sig;
1575 pdkim_str *headernames = NULL; /* Collected signed header names */
1577 /* Check if we must still flush a (partial) header. If that is the
1578 case, the message has no body, and we must compute a body hash
1579 out of '<CR><LF>' */
1580 if (ctx->cur_header && ctx->cur_header->len)
1582 int rc = pdkim_header_complete(ctx);
1583 if (rc != PDKIM_OK) return rc;
1584 pdkim_update_bodyhash(ctx, "\r\n", 2);
1587 DEBUG(D_acl) debug_printf(
1588 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1590 /* Build (and/or evaluate) body hash */
1591 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK)
1592 return PDKIM_ERR_OOM;
1594 /* SIGNING -------------------------------------------------------------- */
1595 if (ctx->mode == PDKIM_MODE_SIGN)
1596 if (!(headernames = pdkim_strnew(NULL)))
1597 return PDKIM_ERR_OOM;
1598 /* ---------------------------------------------------------------------- */
1602 sha1_context sha1_headers;
1603 sha2_context sha2_headers;
1605 char headerhash[32];
1607 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1608 sha1_starts(&sha1_headers);
1610 sha2_starts(&sha2_headers, 0);
1612 DEBUG(D_acl) debug_printf(
1613 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1615 /* SIGNING ---------------------------------------------------------------- */
1616 /* When signing, walk through our header list and add them to the hash. As we
1617 go, construct a list of the header's names to use for the h= parameter. */
1619 if (ctx->mode == PDKIM_MODE_SIGN)
1621 pdkim_stringlist *p;
1623 for (p = sig->headers; p; p = p->next)
1626 /* Collect header names (Note: colon presence is guaranteed here) */
1627 char *q = strchr(p->value, ':');
1629 if (!(pdkim_strncat(headernames, p->value,
1630 (q-(p->value)) + (p->next ? 1 : 0))))
1631 return PDKIM_ERR_OOM;
1633 rh = sig->canon_headers == PDKIM_CANON_RELAXED
1634 ? pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
1635 : strdup(p->value); /* just copy it for simple canon */
1637 return PDKIM_ERR_OOM;
1639 /* Feed header to the hash algorithm */
1640 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1641 sha1_update(&(sha1_headers), (unsigned char *)rh, strlen(rh));
1643 sha2_update(&(sha2_headers), (unsigned char *)rh, strlen(rh));
1645 DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
1650 /* VERIFICATION ----------------------------------------------------------- */
1651 /* When verifying, walk through the header name list in the h= parameter and
1652 add the headers to the hash in that order. */
1655 char *b = strdup(sig->headernames);
1658 pdkim_stringlist *hdrs;
1660 if (!b) return PDKIM_ERR_OOM;
1663 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1668 if ((q = strchr(p, ':')))
1671 for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1673 && strncasecmp(hdrs->value, p, strlen(p)) == 0
1674 && (hdrs->value)[strlen(p)] == ':'
1679 rh = sig->canon_headers == PDKIM_CANON_RELAXED
1680 ? pdkim_relax_header(hdrs->value, 1) /* cook header for relaxed canon */
1681 : strdup(hdrs->value); /* just copy it for simple canon */
1683 return PDKIM_ERR_OOM;
1685 /* Feed header to the hash algorithm */
1686 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1687 sha1_update(&sha1_headers, (unsigned char *)rh, strlen(rh));
1689 sha2_update(&sha2_headers, (unsigned char *)rh, strlen(rh));
1691 DEBUG(D_acl) pdkim_quoteprint(rh, strlen(rh), 1);
1703 DEBUG(D_acl) debug_printf(
1704 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1706 /* SIGNING ---------------------------------------------------------------- */
1707 if (ctx->mode == PDKIM_MODE_SIGN)
1709 /* Copy headernames to signature struct */
1710 sig->headernames = strdup(headernames->str);
1711 pdkim_strfree(headernames);
1713 /* Create signature header with b= omitted */
1714 sig_hdr = pdkim_create_header(ctx->sig, 0);
1717 /* VERIFICATION ----------------------------------------------------------- */
1719 sig_hdr = strdup(sig->rawsig_no_b_val);
1720 /* ------------------------------------------------------------------------ */
1723 return PDKIM_ERR_OOM;
1725 /* Relax header if necessary */
1726 if (sig->canon_headers == PDKIM_CANON_RELAXED)
1728 char *relaxed_hdr = pdkim_relax_header(sig_hdr, 0);
1732 return PDKIM_ERR_OOM;
1733 sig_hdr = relaxed_hdr;
1739 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1740 pdkim_quoteprint(sig_hdr, strlen(sig_hdr), 1);
1742 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1745 /* Finalize header hash */
1746 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1748 sha1_update(&sha1_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
1749 sha1_finish(&sha1_headers, (unsigned char *)headerhash);
1753 debug_printf( "PDKIM [%s] hh computed: ", sig->domain);
1754 pdkim_hexprint(headerhash, 20, 1);
1759 sha2_update(&sha2_headers, (unsigned char *)sig_hdr, strlen(sig_hdr));
1760 sha2_finish(&sha2_headers, (unsigned char *)headerhash);
1764 debug_printf("PDKIM [%s] hh computed: ", sig->domain);
1765 pdkim_hexprint(headerhash, 32, 1);
1771 /* SIGNING ---------------------------------------------------------------- */
1772 if (ctx->mode == PDKIM_MODE_SIGN)
1776 rsa_init(&rsa, RSA_PKCS_V15, 0);
1778 /* Perform private key operation */
1779 if (rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
1780 strlen(sig->rsa_privkey), NULL, 0) != 0)
1781 return PDKIM_ERR_RSA_PRIVKEY;
1783 sig->sigdata_len = mpi_size(&(rsa.N));
1784 if (!(sig->sigdata = malloc(sig->sigdata_len)))
1785 return PDKIM_ERR_OOM;
1787 if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
1788 ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
1789 SIG_RSA_SHA1:SIG_RSA_SHA256),
1791 (unsigned char *)headerhash,
1792 (unsigned char *)sig->sigdata ) != 0)
1793 return PDKIM_ERR_RSA_SIGNING;
1799 debug_printf( "PDKIM [%s] b computed: ", sig->domain);
1800 pdkim_hexprint(sig->sigdata, sig->sigdata_len, 1);
1803 if (!(sig->signature_header = pdkim_create_header(ctx->sig, 1)))
1804 return PDKIM_ERR_OOM;
1807 /* VERIFICATION ----------------------------------------------------------- */
1811 char *dns_txt_name, *dns_txt_reply;
1813 rsa_init(&rsa, RSA_PKCS_V15, 0);
1815 if (!(dns_txt_name = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
1816 return PDKIM_ERR_OOM;
1818 if (!(dns_txt_reply = malloc(PDKIM_DNS_TXT_MAX_RECLEN)))
1821 return PDKIM_ERR_OOM;
1824 memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1825 memset(dns_txt_name , 0, PDKIM_DNS_TXT_MAX_NAMELEN);
1827 if (snprintf(dns_txt_name, PDKIM_DNS_TXT_MAX_NAMELEN,
1828 "%s._domainkey.%s.",
1829 sig->selector, sig->domain) >= PDKIM_DNS_TXT_MAX_NAMELEN)
1831 sig->verify_status = PDKIM_VERIFY_INVALID;
1832 sig->verify_ext_status = PDKIM_VERIFY_INVALID_BUFFER_SIZE;
1836 if ( ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK
1837 || dns_txt_reply[0] == '\0')
1839 sig->verify_status = PDKIM_VERIFY_INVALID;
1840 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1847 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
1849 pdkim_quoteprint(dns_txt_reply, strlen(dns_txt_reply), 1);
1852 if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx, dns_txt_reply)))
1854 sig->verify_status = PDKIM_VERIFY_INVALID;
1855 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
1857 DEBUG(D_acl) debug_printf(
1858 " Error while parsing public key record\n"
1859 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1863 DEBUG(D_acl) debug_printf(
1864 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1866 if (rsa_parse_public_key(&rsa,
1867 (unsigned char *)sig->pubkey->key,
1868 sig->pubkey->key_len) != 0)
1870 sig->verify_status = PDKIM_VERIFY_INVALID;
1871 sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
1875 /* Check the signature */
1876 if (rsa_pkcs1_verify(&rsa,
1878 ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
1879 SIG_RSA_SHA1:SIG_RSA_SHA256),
1881 (unsigned char *)headerhash,
1882 (unsigned char *)sig->sigdata) != 0)
1884 sig->verify_status = PDKIM_VERIFY_FAIL;
1885 sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
1889 /* We have a winner! (if bodydhash was correct earlier) */
1890 if (sig->verify_status == PDKIM_VERIFY_NONE)
1891 sig->verify_status = PDKIM_VERIFY_PASS;
1897 debug_printf("PDKIM [%s] signature status: %s",
1898 sig->domain, pdkim_verify_status_str(sig->verify_status));
1899 if (sig->verify_ext_status > 0)
1900 debug_printf(" (%s)\n",
1901 pdkim_verify_ext_status_str(sig->verify_ext_status));
1908 free(dns_txt_reply);
1914 /* If requested, set return pointer to signature(s) */
1915 if (return_signatures)
1916 *return_signatures = ctx->sig;
1922 /* -------------------------------------------------------------------------- */
1924 DLLEXPORT pdkim_ctx *
1925 pdkim_init_verify(int(*dns_txt_callback)(char *, char *))
1927 pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
1931 memset(ctx, 0, sizeof(pdkim_ctx));
1933 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1939 ctx->mode = PDKIM_MODE_VERIFY;
1940 ctx->dns_txt_callback = dns_txt_callback;
1946 /* -------------------------------------------------------------------------- */
1948 DLLEXPORT pdkim_ctx *
1949 pdkim_init_sign(char *domain, char *selector, char *rsa_privkey)
1952 pdkim_signature *sig;
1954 if (!domain || !selector || !rsa_privkey)
1957 if (!(ctx = malloc(sizeof(pdkim_ctx))))
1959 memset(ctx, 0, sizeof(pdkim_ctx));
1961 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
1967 if (!(sig = malloc(sizeof(pdkim_signature))))
1973 memset(sig, 0, sizeof(pdkim_signature));
1975 sig->bodylength = -1;
1977 ctx->mode = PDKIM_MODE_SIGN;
1980 ctx->sig->domain = strdup(domain);
1981 ctx->sig->selector = strdup(selector);
1982 ctx->sig->rsa_privkey = strdup(rsa_privkey);
1984 if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey)
1987 if (!(ctx->sig->sha1_body = malloc(sizeof(sha1_context))))
1989 sha1_starts(ctx->sig->sha1_body);
1991 if (!(ctx->sig->sha2_body = malloc(sizeof(sha2_context))))
1993 sha2_starts(ctx->sig->sha2_body, 0);
1998 pdkim_free_ctx(ctx);
2002 /* -------------------------------------------------------------------------- */
2005 pdkim_set_optional(pdkim_ctx *ctx,
2012 unsigned long created,
2013 unsigned long expires)
2017 if (!(ctx->sig->identity = strdup(identity)))
2018 return PDKIM_ERR_OOM;
2021 if (!(ctx->sig->sign_headers = strdup(sign_headers)))
2022 return PDKIM_ERR_OOM;
2024 ctx->sig->canon_headers = canon_headers;
2025 ctx->sig->canon_body = canon_body;
2026 ctx->sig->bodylength = bodylength;
2027 ctx->sig->algo = algo;
2028 ctx->sig->created = created;
2029 ctx->sig->expires = expires;