1 /* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.1.2.4 2009/02/26 16:07:36 tom Exp $ */
13 /* -------------------------------------------------------------------------- */
14 /* A bunch of list constants */
15 char *pdkim_querymethods[] = {
19 char *pdkim_algos[] = {
24 char *pdkim_canons[] = {
30 typedef struct pdkim_combined_canon_entry {
34 } pdkim_combined_canon_entry;
35 pdkim_combined_canon_entry pdkim_combined_canons[] = {
36 { "simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
37 { "simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
38 { "relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
39 { "relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
40 { "simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
41 { "relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
46 /* -------------------------------------------------------------------------- */
47 /* Various debugging functions */
49 void pdkim_quoteprint(FILE *stream, char *data, int len, int lf) {
51 unsigned char *p = (unsigned char *)data;
56 case ' ' : fprintf(stream,"{SP}"); break;
57 case '\t': fprintf(stream,"{TB}"); break;
58 case '\r': fprintf(stream,"{CR}"); break;
59 case '\n': fprintf(stream,"{LF}"); break;
60 case '{' : fprintf(stream,"{BO}"); break;
61 case '}' : fprintf(stream,"{BC}"); break;
63 if ( (c < 32) || (c > 127) )
64 fprintf(stream,"{%02x}",c);
76 /* -------------------------------------------------------------------------- */
77 /* Simple string list implementation for convinience */
78 pdkim_stringlist *pdkim_append_stringlist(pdkim_stringlist *base, char *str) {
79 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
80 if (new_entry == NULL) return NULL;
81 memset(new_entry,0,sizeof(pdkim_stringlist));
82 new_entry->value = malloc(strlen(str)+1);
83 if (new_entry->value == NULL) return NULL;
84 strcpy(new_entry->value,str);
86 pdkim_stringlist *last = base;
87 while (last->next != NULL) { last = last->next; };
88 last->next = new_entry;
91 else return new_entry;
95 /* -------------------------------------------------------------------------- */
96 /* A small "growing string" implementation to escape malloc/realloc hell */
97 pdkim_str *pdkim_strnew (char *cstr) {
98 unsigned int len = cstr?strlen(cstr):0;
99 pdkim_str *p = malloc(sizeof(pdkim_str));
100 if (p == NULL) return NULL;
101 memset(p,0,sizeof(pdkim_str));
102 p->str = malloc(len+1);
103 if (p->str == NULL) {
107 p->allocated=(len+1);
109 if (cstr) strcpy(p->str,cstr);
112 char *pdkim_strcat(pdkim_str *str, char *cstr) {
113 return pdkim_strncat(str, cstr, strlen(cstr));
115 char *pdkim_strncat(pdkim_str *str, char *data, int len) {
116 if ((str->allocated - str->len) < (len+1)) {
117 /* Extend the buffer */
118 int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
119 char *n = realloc(str->str,
120 (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
121 if (n == NULL) return NULL;
123 str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
125 strncpy(&(str->str[str->len]),data,len);
127 str->str[str->len] = '\0';
130 char *pdkim_numcat(pdkim_str *str, unsigned long num) {
132 snprintf(minibuf,20,"%lu",num);
133 return pdkim_strcat(str,minibuf);
135 char *pdkim_strtrim(pdkim_str *str) {
138 while ( (*p != '\0') && ((*p == '\t') || (*p == ' ')) ) p++;
139 while (*p != '\0') {*q = *p; q++; p++;};
141 while ( (q != str->str) && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) ) {
145 str->len = strlen(str->str);
148 char *pdkim_strclear(pdkim_str *str) {
153 void pdkim_strfree(pdkim_str *str) {
154 if (str == NULL) return;
155 if (str->str != NULL) free(str->str);
160 /* -------------------------------------------------------------------------- */
161 /* Matches the name of the passed raw "header" against
162 the passed colon-separated "list". Case-insensitive.
163 Returns '0' for a match. */
164 int header_name_match(char *header,
171 char *hcolon = strchr(header,':');
172 if (hcolon == NULL) return rc; /* This isn't a header */
173 hname = malloc((hcolon-header)+1);
174 if (hname == NULL) return PDKIM_ERR_OOM;
175 memset(hname,0,(hcolon-header)+1);
176 strncpy(hname,header,(hcolon-header));
177 lcopy = malloc(strlen(list)+1);
180 return PDKIM_ERR_OOM;
187 if (strcasecmp(p,hname) == 0) {
194 if (strcasecmp(p,hname) == 0) rc = PDKIM_OK;
202 /* -------------------------------------------------------------------------- */
203 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
205 char *pdkim_relax_header (char *header, int crlf) {
206 int past_field_name = 0;
210 char *relaxed = malloc(strlen(header));
211 if (relaxed == NULL) return NULL;
216 if ( (c == '\r') || (c == '\n') ) {
220 if ( (c == '\t') || (c == ' ') ) {
221 c = ' '; /* Turns WSP into SP */
229 if ( (!past_field_name) && (c == ':') ) {
230 if (seen_wsp) q--; /* This removes WSP before the colon */
231 seen_wsp = 1; /* This removes WSP after the colon */
236 /* Lowercase header name */
237 if (!past_field_name) c = tolower(c);
243 if (crlf) strcat(relaxed,"\r\n");
248 /* -------------------------------------------------------------------------- */
249 #define PDKIM_QP_ERROR_DECODE -1
250 char *pdkim_decode_qp_char(char *qp_p, int *c) {
251 char *initial_pos = qp_p;
253 /* Advance one char */
256 /* Check for two hex digits and decode them */
257 if (isxdigit(*qp_p) && isxdigit(qp_p[1])) {
258 /* Do hex conversion */
259 if (isdigit(*qp_p)) {*c = *qp_p - '0';}
260 else {*c = toupper(*qp_p) - 'A' + 10;};
262 if (isdigit(qp_p[1])) {*c |= qp_p[1] - '0';}
263 else {*c |= toupper(qp_p[1]) - 'A' + 10;};
267 /* Illegal char here */
268 *c = PDKIM_QP_ERROR_DECODE;
273 /* -------------------------------------------------------------------------- */
274 char *pdkim_decode_qp(char *str) {
278 char *n = malloc(strlen(p)+1);
279 if (n == NULL) return NULL;
284 p = pdkim_decode_qp_char(p,&nchar);
301 /* -------------------------------------------------------------------------- */
302 char *pdkim_decode_base64(char *str) {
306 base64_decode(NULL, &dlen, str, strlen(str));
307 res = malloc(dlen+1);
308 if (res == NULL) return NULL;
309 if (base64_decode(res,&dlen,str,strlen(str)) != 0) {
317 /* -------------------------------------------------------------------------- */
318 #define PDKIM_HDR_LIMBO 0
319 #define PDKIM_HDR_TAG 1
320 #define PDKIM_HDR_VALUE 2
321 pdkim_signature *pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr) {
322 pdkim_signature *sig ;
323 char *rawsig_no_b_val;
325 pdkim_str *cur_tag = NULL;
326 pdkim_str *cur_val = NULL;
329 int where = PDKIM_HDR_LIMBO;
332 sig = malloc(sizeof(pdkim_signature));
333 if (sig == NULL) return NULL;
334 memset(sig,0,sizeof(pdkim_signature));
336 sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1);
337 if (sig->rawsig_no_b_val == NULL) {
343 q = sig->rawsig_no_b_val;
348 if ( (*p == '\r') || (*p == '\n') )
351 /* Fast-forward through header name */
353 if (*p == ':') past_hname = 1;
357 if (where == PDKIM_HDR_LIMBO) {
358 /* In limbo, just wait for a tag-char to appear */
359 if (!((*p >= 'a') && (*p <= 'z')))
362 where = PDKIM_HDR_TAG;
365 if (where == PDKIM_HDR_TAG) {
367 cur_tag = pdkim_strnew(NULL);
369 if ((*p >= 'a') && (*p <= 'z'))
370 pdkim_strncat(cur_tag,p,1);
373 if (strcmp(cur_tag->str,"b") == 0) {
377 where = PDKIM_HDR_VALUE;
382 if (where == PDKIM_HDR_VALUE) {
384 cur_val = pdkim_strnew(NULL);
386 if ( (*p == '\r') || (*p == '\n') )
390 if (cur_tag->len > 0) {
391 pdkim_strtrim(cur_val);
393 if (ctx->debug_stream)
394 fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str);
396 switch (cur_tag->str[0]) {
398 switch (cur_tag->str[1]) {
400 sig->bodyhash = pdkim_decode_base64(cur_val->str);
403 sig->sigdata = pdkim_decode_base64(cur_val->str);
408 if (strcmp(cur_val->str,PDKIM_SIGNATURE_VERSION) == 0) {
409 /* We only support version 1, and that is currently the
410 only version there is. */
416 while (pdkim_algos[i] != NULL) {
417 if (strcmp(cur_val->str,pdkim_algos[i]) == 0 ) {
426 while (pdkim_combined_canons[i].str != NULL) {
427 if (strcmp(cur_val->str,pdkim_combined_canons[i].str) == 0 ) {
428 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
429 sig->canon_body = pdkim_combined_canons[i].canon_body;
437 while (pdkim_querymethods[i] != NULL) {
438 if (strcmp(cur_val->str,pdkim_querymethods[i]) == 0 ) {
439 sig->querymethod = i;
446 sig->selector = malloc(strlen(cur_val->str)+1);
447 if (sig->selector == NULL) break;
448 strcpy(sig->selector, cur_val->str);
451 sig->domain = malloc(strlen(cur_val->str)+1);
452 if (sig->domain == NULL) break;
453 strcpy(sig->domain, cur_val->str);
456 sig->identity = pdkim_decode_qp(cur_val->str);
459 sig->created = strtoul(cur_val->str,NULL,10);
462 sig->expires = strtoul(cur_val->str,NULL,10);
465 sig->bodylength = strtoul(cur_val->str,NULL,10);
468 sig->headernames = malloc(strlen(cur_val->str)+1);
469 if (sig->headernames == NULL) break;
470 strcpy(sig->headernames, cur_val->str);
473 sig->copiedheaders = pdkim_decode_qp(cur_val->str);
477 if (ctx->debug_stream)
478 fprintf(ctx->debug_stream, "Unknown tag encountered\n");
483 pdkim_strclear(cur_tag);
484 pdkim_strclear(cur_val);
486 where = PDKIM_HDR_LIMBO;
489 else pdkim_strncat(cur_val,p,1);
501 /* Make sure the most important bits are there. */
502 if (!(sig->domain && (*(sig->domain) != '\0') &&
503 sig->selector && (*(sig->selector) != '\0') &&
504 sig->headernames && (*(sig->headernames) != '\0') &&
506 pdkim_free_signature(sig);
512 if (ctx->debug_stream) {
513 fprintf(ctx->debug_stream,
514 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
515 pdkim_quoteprint(ctx->debug_stream,
516 sig->rawsig_no_b_val,
517 strlen(sig->rawsig_no_b_val), 1);
518 fprintf(ctx->debug_stream,
519 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
527 /* -------------------------------------------------------------------------- */
528 int pdkim_update_bodyhash(pdkim_ctx *ctx, char *data, int len) {
529 pdkim_signature *sig = ctx->sig;
530 /* Cache relaxed version of data */
531 char *relaxed_data = NULL;
534 /* Traverse all signatures, updating their hashes. */
535 while (sig != NULL) {
536 /* Defaults to simple canon (no further treatment necessary) */
537 char *canon_data = data;
540 if (sig->canon_body == PDKIM_CANON_RELAXED) {
541 /* Relax the line if not done already */
542 if (relaxed_data == NULL) {
546 relaxed_data = malloc(len+1);
547 if (relaxed_data == NULL) return PDKIM_ERR_OOM;
550 if ( (c == '\t') || (c == ' ') ) {
551 c = ' '; /* Turns WSP into SP */
559 relaxed_data[q++] = c;
562 relaxed_data[q] = '\0';
565 canon_data = relaxed_data;
566 canon_len = relaxed_len;
569 /* Make sure we don't exceed the to-be-signed body length */
570 if (sig->bodylength &&
571 ((sig->signed_body_bytes+(unsigned long)canon_len) > sig->bodylength))
572 canon_len = (sig->bodylength - sig->signed_body_bytes);
575 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
576 sha1_update(&(sig->sha1_body),(unsigned char *)canon_data,canon_len);
578 sha2_update(&(sig->sha2_body),(unsigned char *)canon_data,canon_len);
579 sig->signed_body_bytes += canon_len;
581 if (ctx->debug_stream!=NULL)
582 pdkim_quoteprint(ctx->debug_stream,canon_data,canon_len,0);
589 if (relaxed_data != NULL) free(relaxed_data);
594 /* -------------------------------------------------------------------------- */
595 int pdkim_finish_bodyhash(pdkim_ctx *ctx) {
596 pdkim_signature *sig = ctx->sig;
598 /* Traverse all signatures */
599 while (sig != NULL) {
602 if (ctx->debug_stream)
603 fprintf(ctx->debug_stream, "PDKIM [%s] Body bytes hashed: %lu\n",
604 sig->domain, sig->signed_body_bytes);
608 unsigned char bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
609 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
610 sha1_finish(&(sig->sha1_body),bh);
612 sha2_finish(&(sig->sha2_body),bh);
614 /* SIGNING -------------------------------------------------------------- */
615 if (ctx->mode == PDKIM_MODE_SIGN) {
617 /* Build base64 version of body hash and place it in the sig struct */
618 int slen = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
620 base64_encode(NULL,&dlen,bh,slen); /* Puts needed length in dlen */
621 sig->bodyhash = malloc(dlen+1);
622 if (sig->bodyhash == NULL) return PDKIM_ERR_OOM;
623 if (base64_encode((unsigned char *)sig->bodyhash,&dlen,bh,slen) == 0) {
624 sig->bodyhash[dlen] = '\0';
626 if (ctx->debug_stream)
627 fprintf(ctx->debug_stream, "PDKIM [%s] body hash: %s\n",
628 sig->domain, sig->bodyhash);
633 /* If bodylength limit is set, and we have received less bytes
634 than the requested amount, effectively remove the limit tag. */
635 if (sig->signed_body_bytes < sig->bodylength) sig->bodylength = 0;
637 /* VERIFICATION --------------------------------------------------------- */
651 /* -------------------------------------------------------------------------- */
652 /* Callback from pdkim_feed below for processing complete body lines */
653 int pdkim_bodyline_complete(pdkim_ctx *ctx) {
654 char *p = ctx->linebuf;
655 int n = ctx->linebuf_offset;
657 /* Ignore extra data if we've seen the end-of-data marker */
658 if (ctx->seen_eod) goto BAIL;
660 /* We've always got one extra byte to stuff a zero ... */
661 ctx->linebuf[(ctx->linebuf_offset)] = '\0';
663 if (ctx->input_mode == PDKIM_INPUT_SMTP) {
664 /* Terminate on EOD marker */
665 if (memcmp(p,".\r\n",3) == 0) {
670 if (memcmp(p,"..",2) == 0) {
676 /* Empty lines need to be buffered until we find a non-empty line */
677 if (memcmp(p,"\r\n",2) == 0) {
678 ctx->num_buffered_crlf++;
682 /* At this point, we have a non-empty line, so release the buffered ones. */
683 while (ctx->num_buffered_crlf) {
684 pdkim_update_bodyhash(ctx,"\r\n",2);
685 ctx->num_buffered_crlf--;
688 pdkim_update_bodyhash(ctx,p,n);
691 ctx->linebuf_offset = 0;
696 /* -------------------------------------------------------------------------- */
697 /* Callback from pdkim_feed below for processing complete headers */
698 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
699 int pdkim_header_complete(pdkim_ctx *ctx) {
700 pdkim_signature *sig = ctx->sig;
702 /* Special case: The last header can have an extra \r appended */
703 if ( (ctx->cur_header->len > 1) &&
704 (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') ) {
705 ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
706 ctx->cur_header->len--;
709 /* Traverse all signatures */
710 while (sig != NULL) {
712 /* SIGNING -------------------------------------------------------------- */
713 if (ctx->mode == PDKIM_MODE_SIGN) {
714 if (header_name_match(ctx->cur_header->str,
715 sig->sign_headers?sig->sign_headers
716 :PDKIM_DEFAULT_SIGN_HEADERS) == 0) {
717 pdkim_stringlist *list = pdkim_append_stringlist(sig->headers,
718 ctx->cur_header->str);
719 if (list == NULL) return PDKIM_ERR_OOM;
723 /* VERIFICATION --------------------------------------------------------- */
731 /* DKIM-Signature: headers are added to the verification list */
732 if ( (ctx->mode == PDKIM_MODE_VERIFY) &&
733 (strncasecmp(ctx->cur_header->str,
734 DKIM_SIGNATURE_HEADERNAME,
735 strlen(DKIM_SIGNATURE_HEADERNAME)) == 0) ) {
736 /* Create and chain new signature block */
738 if (ctx->debug_stream)
739 fprintf(ctx->debug_stream,
740 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
742 pdkim_signature *new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str);
743 if (new_sig != NULL) {
744 pdkim_signature *last_sig = ctx->sig;
745 if (last_sig == NULL) {
749 while (last_sig->next != NULL) { last_sig = last_sig->next; };
750 last_sig->next = new_sig;
755 if (ctx->debug_stream) {
756 fprintf(ctx->debug_stream,"Error while parsing signature header\n");
757 fprintf(ctx->debug_stream,
758 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
764 pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
770 /* -------------------------------------------------------------------------- */
771 #define HEADER_BUFFER_FRAG_SIZE 256
772 int pdkim_feed (pdkim_ctx *ctx,
776 for (p=0;p<len;p++) {
778 if (ctx->past_headers) {
779 /* Processing body byte */
780 ctx->linebuf[(ctx->linebuf_offset)++] = c;
782 int rc = pdkim_bodyline_complete(ctx); /* End of line */
783 if (rc != PDKIM_OK) return rc;
785 if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
786 return PDKIM_ERR_LONG_LINE;
789 /* Processing header byte */
793 int rc = pdkim_header_complete(ctx); /* Seen last header line */
794 if (rc != PDKIM_OK) return rc;
795 ctx->past_headers = 1;
798 if (ctx->debug_stream)
799 fprintf(ctx->debug_stream,
800 "PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
804 else ctx->seen_lf = 1;
806 else if (ctx->seen_lf) {
807 if (! ((c == '\t') || (c == ' '))) {
808 int rc = pdkim_header_complete(ctx); /* End of header */
809 if (rc != PDKIM_OK) return rc;
814 if (ctx->cur_header == NULL) {
815 ctx->cur_header = pdkim_strnew(NULL);
816 if (ctx->cur_header == NULL) return PDKIM_ERR_OOM;
818 if (pdkim_strncat(ctx->cur_header,&data[p],1) == NULL)
819 return PDKIM_ERR_OOM;
826 /* -------------------------------------------------------------------------- */
827 pdkim_str *pdkim_create_header(pdkim_signature *sig, int final) {
829 pdkim_str *hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
830 if (hdr == NULL) return NULL;
831 /* Required and static bits */
833 pdkim_strcat(hdr,"; a=") &&
834 pdkim_strcat(hdr,pdkim_algos[sig->algo]) &&
835 pdkim_strcat(hdr,"; q=") &&
836 pdkim_strcat(hdr,pdkim_querymethods[sig->querymethod]) &&
837 pdkim_strcat(hdr,"; c=") &&
838 pdkim_strcat(hdr,pdkim_canons[sig->canon_headers]) &&
839 pdkim_strcat(hdr,"/") &&
840 pdkim_strcat(hdr,pdkim_canons[sig->canon_body]) &&
841 pdkim_strcat(hdr,"; d=") &&
842 pdkim_strcat(hdr,sig->domain) &&
843 pdkim_strcat(hdr,"; s=") &&
844 pdkim_strcat(hdr,sig->selector) &&
845 pdkim_strcat(hdr,";\r\n\th=") &&
846 pdkim_strcat(hdr,sig->headernames) &&
847 pdkim_strcat(hdr,"; bh=") &&
848 pdkim_strcat(hdr,sig->bodyhash) &&
849 pdkim_strcat(hdr,";\r\n\t")
852 if (sig->identity != NULL) {
853 if (!( pdkim_strcat(hdr,"i=") &&
854 pdkim_strcat(hdr,sig->identity) &&
855 pdkim_strcat(hdr,";") ) ) {
859 if (sig->created > 0) {
860 if (!( pdkim_strcat(hdr,"t=") &&
861 pdkim_numcat(hdr,sig->created) &&
862 pdkim_strcat(hdr,";") ) ) {
866 if (sig->expires > 0) {
867 if (!( pdkim_strcat(hdr,"x=") &&
868 pdkim_numcat(hdr,sig->expires) &&
869 pdkim_strcat(hdr,";") ) ) {
873 if (sig->bodylength > 0) {
874 if (!( pdkim_strcat(hdr,"l=") &&
875 pdkim_numcat(hdr,sig->bodylength) &&
876 pdkim_strcat(hdr,";") ) ) {
880 /* Extra linebreak */
881 if (hdr->str[(hdr->len)-1] == ';') {
882 if (!pdkim_strcat(hdr," \r\n\t")) return NULL;
884 /* Preliminary or final version? */
887 pdkim_strcat(hdr,"b=") &&
888 pdkim_strcat(hdr,sig->sigdata) &&
889 pdkim_strcat(hdr,";")
893 if (pdkim_strcat(hdr,"b=;")) return hdr;
900 /* -------------------------------------------------------------------------- */
901 int pdkim_feed_finish(pdkim_ctx *ctx, char **signature) {
903 /* Check if we must still flush a (partial) header. If that is the
904 case, the message has no body, and we must compute a body hash
906 if (ctx->cur_header->len) {
907 int rc = pdkim_header_complete(ctx);
908 if (rc != PDKIM_OK) return rc;
909 pdkim_update_bodyhash(ctx,"\r\n",2);
912 /* For non-smtp input, check if there's an unfinished line in the
913 body line buffer. If that is the case, we must add a CRLF to the
914 hash to properly terminate the message. */
915 if ((ctx->input_mode == PDKIM_INPUT_NORMAL) && ctx->linebuf_offset) {
916 pdkim_update_bodyhash(ctx, ctx->linebuf, ctx->linebuf_offset);
917 pdkim_update_bodyhash(ctx,"\r\n",2);
920 if (ctx->debug_stream)
921 fprintf(ctx->debug_stream,
922 "\nPDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
926 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK) return PDKIM_ERR_OOM;
928 /* SIGNING ---------------------------------------------------------------- */
929 if (ctx->mode == PDKIM_MODE_SIGN) {
931 pdkim_str *headernames;
933 char *canon_signature;
934 unsigned char headerhash[32];
935 char *headerhash_base64;
938 sha1_context sha1_headers;
939 sha2_context sha2_headers;
941 if (ctx->sig->algo == PDKIM_ALGO_RSA_SHA1) sha1_starts(&sha1_headers);
942 else sha2_starts(&sha2_headers,0);
943 /* Run through the accumulated list of to-be-signed headers */
945 if (ctx->debug_stream)
946 fprintf(ctx->debug_stream,
947 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
949 headernames = pdkim_strnew(NULL);
950 p = ctx->sig->headers;
953 /* Collect header names (Note: colon presence is guaranteed here) */
954 char *q = strchr(p->value,':');
955 if (pdkim_strncat(headernames, p->value,
956 (q-(p->value))+((p->next==NULL)?0:1)) == NULL)
957 return PDKIM_ERR_OOM;
958 /* Cook the header if using relaxed canon */
959 if (ctx->sig->canon_body == PDKIM_CANON_RELAXED) {
960 rh = pdkim_relax_header(p->value,1);
961 if (rh == NULL) return PDKIM_ERR_OOM;
963 /* Feed header to the hash algorithm */
964 if (ctx->sig->algo == PDKIM_ALGO_RSA_SHA1)
965 sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh));
967 sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh));
969 if (ctx->debug_stream)
970 pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
976 if (ctx->debug_stream)
977 fprintf(ctx->debug_stream,
978 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
981 /* Copy headernames to signature struct */
982 ctx->sig->headernames = malloc((headernames->len)+1);
983 if (ctx->sig->headernames == NULL) return PDKIM_ERR_OOM;
984 strcpy(ctx->sig->headernames, headernames->str);
985 pdkim_strfree(headernames);
987 /* Create signature header with b= omitted */
988 hdr = pdkim_create_header(ctx->sig,0);
989 if (hdr == NULL) return PDKIM_ERR_OOM;
991 /* If necessary, perform relaxed canon */
992 canon_signature = hdr->str;
993 if (ctx->sig->canon_headers == PDKIM_CANON_RELAXED) {
994 canon_signature = pdkim_relax_header(canon_signature,0);
995 if (canon_signature == NULL) return PDKIM_ERR_OOM;
999 if (ctx->debug_stream) {
1000 fprintf(ctx->debug_stream,
1001 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1002 pdkim_quoteprint(ctx->debug_stream, canon_signature, strlen(canon_signature), 1);
1003 fprintf(ctx->debug_stream,
1004 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1008 /* Feed preliminary signature header to the hash algorithm */
1009 if (ctx->sig->algo == PDKIM_ALGO_RSA_SHA1) {
1011 sha1_update(&(sha1_headers),(unsigned char *)canon_signature,strlen(canon_signature));
1012 sha1_finish(&(sha1_headers),headerhash);
1013 base64_encode(NULL,&dlen,headerhash,20);
1014 headerhash_base64 = malloc(dlen+1);
1015 if (headerhash == NULL) return PDKIM_ERR_OOM;
1016 base64_encode((unsigned char *)headerhash_base64,&dlen,headerhash,20);
1017 headerhash_base64[dlen] = '\0';
1019 if (ctx->debug_stream)
1020 fprintf(ctx->debug_stream,
1021 "PDKIM SHA1 header hash: %s\n",headerhash_base64);
1026 sha2_update(&(sha2_headers),(unsigned char *)canon_signature,strlen(canon_signature));
1027 sha2_finish(&(sha2_headers),headerhash);
1028 base64_encode(NULL,&dlen,headerhash,32);
1029 headerhash_base64 = malloc(dlen+1);
1030 if (headerhash == NULL) return PDKIM_ERR_OOM;
1031 base64_encode((unsigned char *)headerhash_base64,&dlen,headerhash,32);
1032 headerhash_base64[dlen] = '\0';
1034 if (ctx->debug_stream)
1035 fprintf(ctx->debug_stream,
1036 "PDKIM SHA256 header hash: %s\n",headerhash_base64);
1040 if (rsa_parse_key(&rsa, (unsigned char *)ctx->sig->rsa_privkey,
1041 strlen(ctx->sig->rsa_privkey), NULL, 0) != 0) {
1042 return PDKIM_ERR_RSA_PRIVKEY;
1045 rsa_sig = malloc(mpi_size(&(rsa.N)));
1046 if (rsa_sig == NULL) return PDKIM_ERR_OOM;
1048 if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
1049 ((ctx->sig->algo == PDKIM_ALGO_RSA_SHA1)?
1054 0, headerhash, (unsigned char *)rsa_sig ) != 0) {
1055 return PDKIM_ERR_RSA_SIGNING;
1058 base64_encode(NULL,&sigdata_len,(unsigned char *)rsa_sig,mpi_size(&(rsa.N)));
1059 ctx->sig->sigdata = malloc(sigdata_len+1);
1060 if (ctx->sig->sigdata == NULL) return PDKIM_ERR_OOM;
1061 base64_encode((unsigned char *)ctx->sig->sigdata,
1063 (unsigned char *)rsa_sig,
1064 mpi_size(&(rsa.N)));
1065 ctx->sig->sigdata[sigdata_len] = '\0';
1068 if (ctx->debug_stream)
1069 fprintf(ctx->debug_stream,
1070 "PDKIM RSA-signed hash: %s\n",ctx->sig->sigdata);
1073 /* Recreate signature header with b= included */
1075 hdr = pdkim_create_header(ctx->sig,1);
1076 if (hdr == NULL) return PDKIM_ERR_OOM;
1079 if (ctx->debug_stream) {
1080 fprintf(ctx->debug_stream,
1081 "PDKIM >> Final DKIM-Signature header >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1082 pdkim_quoteprint(ctx->debug_stream, hdr->str, hdr->len, 1);
1083 fprintf(ctx->debug_stream,
1084 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1088 if (signature != NULL) {
1089 *signature = hdr->str;
1099 /* -------------------------------------------------------------------------- */
1100 pdkim_ctx *pdkim_init_verify(void) {
1101 pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
1102 if (ctx == NULL) return NULL;
1103 memset(ctx,0,sizeof(pdkim_ctx));
1104 ctx->mode = PDKIM_MODE_VERIFY;
1109 /* -------------------------------------------------------------------------- */
1110 pdkim_ctx *pdkim_init_sign(char *domain,
1112 char *rsa_privkey) {
1115 if (!domain || !selector || !rsa_privkey) return NULL;
1117 ctx = malloc(sizeof(pdkim_ctx));
1118 if (ctx == NULL) return NULL;
1119 memset(ctx,0,sizeof(pdkim_ctx));
1120 pdkim_signature *sig = malloc(sizeof(pdkim_signature));
1125 memset(sig,0,sizeof(pdkim_signature));
1127 ctx->mode = PDKIM_MODE_SIGN;
1130 ctx->sig->domain = malloc(strlen(domain)+1);
1131 ctx->sig->selector = malloc(strlen(selector)+1);
1132 ctx->sig->rsa_privkey = malloc(strlen(rsa_privkey)+1);
1134 if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey) {
1135 pdkim_free_ctx(ctx);
1139 strcpy(ctx->sig->domain, domain);
1140 strcpy(ctx->sig->selector, selector);
1141 strcpy(ctx->sig->rsa_privkey, rsa_privkey);
1143 sha1_starts(&(ctx->sig->sha1_body));
1144 sha2_starts(&(ctx->sig->sha2_body),0);
1150 /* -------------------------------------------------------------------------- */
1151 void pdkim_set_debug_stream(pdkim_ctx *ctx,
1152 FILE *debug_stream) {
1153 ctx->debug_stream = debug_stream;
1157 /* -------------------------------------------------------------------------- */
1158 int pdkim_set_optional(pdkim_ctx *ctx,
1164 unsigned long bodylength,
1166 unsigned long created,
1167 unsigned long expires) {
1169 if (identity != NULL) {
1170 ctx->sig->identity = malloc(strlen(identity)+1);
1171 if (!ctx->sig->identity) {
1172 return PDKIM_ERR_OOM;
1174 strcpy(ctx->sig->identity, identity);
1177 if (sign_headers != NULL) {
1178 ctx->sig->sign_headers = malloc(strlen(sign_headers)+1);
1179 if (!ctx->sig->sign_headers) {
1180 return PDKIM_ERR_OOM;
1182 strcpy(ctx->sig->sign_headers, sign_headers);
1185 ctx->input_mode = input_mode;
1186 ctx->sig->canon_headers = canon_headers;
1187 ctx->sig->canon_body = canon_body;
1188 ctx->sig->bodylength = bodylength;
1189 ctx->sig->algo = algo;
1190 ctx->sig->created = created;
1191 ctx->sig->expires = expires;
1199 /* -------------------------------------------------------------------------- */
1200 void pdkim_free_sig(pdkim_signature *sig) {
1202 pdkim_signature *next = (pdkim_signature *)sig->next;
1204 pdkim_stringlist *e = sig->headers;
1206 pdkim_stringlist *c = e;
1207 if (e->value != NULL) free(e->value);
1212 if (sig->sigdata != NULL) free(sig->sigdata);
1213 if (sig->bodyhash != NULL) free(sig->bodyhash);
1214 if (sig->selector != NULL) free(sig->selector);
1215 if (sig->domain != NULL) free(sig->domain);
1216 if (sig->identity != NULL) free(sig->identity);
1217 if (sig->headernames != NULL) free(sig->headernames);
1218 if (sig->copiedheaders != NULL) free(sig->copiedheaders);
1219 if (sig->rsa_privkey != NULL) free(sig->rsa_privkey);
1220 if (sig->sign_headers != NULL) free(sig->sign_headers);
1223 if (next != NULL) pdkim_free_sig(next);
1228 /* -------------------------------------------------------------------------- */
1229 void pdkim_free_ctx(pdkim_ctx *ctx) {
1231 pdkim_free_sig(ctx->sig);
1232 pdkim_strfree(ctx->cur_header);