1 /* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.1.2.5 2009/02/27 17:04:20 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);
73 void pdkim_hexprint(FILE *stream, char *data, int len, int lf) {
75 unsigned char *p = (unsigned char *)data;
79 fprintf(stream,"%02x ",c);
87 /* -------------------------------------------------------------------------- */
88 /* Simple string list implementation for convinience */
89 pdkim_stringlist *pdkim_append_stringlist(pdkim_stringlist *base, char *str) {
90 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
91 if (new_entry == NULL) return NULL;
92 memset(new_entry,0,sizeof(pdkim_stringlist));
93 new_entry->value = malloc(strlen(str)+1);
94 if (new_entry->value == NULL) return NULL;
95 strcpy(new_entry->value,str);
97 pdkim_stringlist *last = base;
98 while (last->next != NULL) { last = last->next; };
99 last->next = new_entry;
102 else return new_entry;
106 /* -------------------------------------------------------------------------- */
107 /* A small "growing string" implementation to escape malloc/realloc hell */
108 pdkim_str *pdkim_strnew (char *cstr) {
109 unsigned int len = cstr?strlen(cstr):0;
110 pdkim_str *p = malloc(sizeof(pdkim_str));
111 if (p == NULL) return NULL;
112 memset(p,0,sizeof(pdkim_str));
113 p->str = malloc(len+1);
114 if (p->str == NULL) {
118 p->allocated=(len+1);
120 if (cstr) strcpy(p->str,cstr);
123 char *pdkim_strcat(pdkim_str *str, char *cstr) {
124 return pdkim_strncat(str, cstr, strlen(cstr));
126 char *pdkim_strncat(pdkim_str *str, char *data, int len) {
127 if ((str->allocated - str->len) < (len+1)) {
128 /* Extend the buffer */
129 int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
130 char *n = realloc(str->str,
131 (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
132 if (n == NULL) return NULL;
134 str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
136 strncpy(&(str->str[str->len]),data,len);
138 str->str[str->len] = '\0';
141 char *pdkim_numcat(pdkim_str *str, unsigned long num) {
143 snprintf(minibuf,20,"%lu",num);
144 return pdkim_strcat(str,minibuf);
146 char *pdkim_strtrim(pdkim_str *str) {
149 while ( (*p != '\0') && ((*p == '\t') || (*p == ' ')) ) p++;
150 while (*p != '\0') {*q = *p; q++; p++;};
152 while ( (q != str->str) && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) ) {
156 str->len = strlen(str->str);
159 char *pdkim_strclear(pdkim_str *str) {
164 void pdkim_strfree(pdkim_str *str) {
165 if (str == NULL) return;
166 if (str->str != NULL) free(str->str);
171 /* -------------------------------------------------------------------------- */
172 /* Matches the name of the passed raw "header" against
173 the passed colon-separated "list", starting at entry
174 "start". Returns the position of the header name in
176 int header_name_match(char *header,
185 char *hcolon = strchr(header,':');
186 if (hcolon == NULL) return rc; /* This isn't a header */
187 hname = malloc((hcolon-header)+1);
188 if (hname == NULL) return PDKIM_ERR_OOM;
189 memset(hname,0,(hcolon-header)+1);
190 strncpy(hname,header,(hcolon-header));
191 lcopy = malloc(strlen(list)+1);
194 return PDKIM_ERR_OOM;
202 if (strcasecmp(p,hname) == 0) {
212 if (strcasecmp(p,hname) == 0)
222 /* -------------------------------------------------------------------------- */
223 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
225 char *pdkim_relax_header (char *header, int crlf) {
226 int past_field_name = 0;
230 char *relaxed = malloc(strlen(header));
231 if (relaxed == NULL) return NULL;
236 if ( (c == '\r') || (c == '\n') ) {
240 if ( (c == '\t') || (c == ' ') ) {
241 c = ' '; /* Turns WSP into SP */
249 if ( (!past_field_name) && (c == ':') ) {
250 if (seen_wsp) q--; /* This removes WSP before the colon */
251 seen_wsp = 1; /* This removes WSP after the colon */
256 /* Lowercase header name */
257 if (!past_field_name) c = tolower(c);
263 if (crlf) strcat(relaxed,"\r\n");
268 /* -------------------------------------------------------------------------- */
269 #define PDKIM_QP_ERROR_DECODE -1
270 char *pdkim_decode_qp_char(char *qp_p, int *c) {
271 char *initial_pos = qp_p;
273 /* Advance one char */
276 /* Check for two hex digits and decode them */
277 if (isxdigit(*qp_p) && isxdigit(qp_p[1])) {
278 /* Do hex conversion */
279 if (isdigit(*qp_p)) {*c = *qp_p - '0';}
280 else {*c = toupper(*qp_p) - 'A' + 10;};
282 if (isdigit(qp_p[1])) {*c |= qp_p[1] - '0';}
283 else {*c |= toupper(qp_p[1]) - 'A' + 10;};
287 /* Illegal char here */
288 *c = PDKIM_QP_ERROR_DECODE;
293 /* -------------------------------------------------------------------------- */
294 char *pdkim_decode_qp(char *str) {
298 char *n = malloc(strlen(p)+1);
299 if (n == NULL) return NULL;
304 p = pdkim_decode_qp_char(p,&nchar);
321 /* -------------------------------------------------------------------------- */
322 char *pdkim_decode_base64(char *str, int *num_decoded) {
326 base64_decode(NULL, &dlen, (unsigned char *)str, strlen(str));
327 res = malloc(dlen+1);
328 if (res == NULL) return NULL;
329 if (base64_decode((unsigned char *)res,&dlen,(unsigned char *)str,strlen(str)) != 0) {
333 if (num_decoded != NULL) *num_decoded = dlen;
337 /* -------------------------------------------------------------------------- */
338 char *pdkim_encode_base64(char *str, int num) {
342 base64_encode(NULL, &dlen, (unsigned char *)str, num);
343 res = malloc(dlen+1);
344 if (res == NULL) return NULL;
345 if (base64_encode((unsigned char *)res,&dlen,(unsigned char *)str,num) != 0) {
353 /* -------------------------------------------------------------------------- */
354 #define PDKIM_HDR_LIMBO 0
355 #define PDKIM_HDR_TAG 1
356 #define PDKIM_HDR_VALUE 2
357 pdkim_signature *pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr) {
358 pdkim_signature *sig ;
360 pdkim_str *cur_tag = NULL;
361 pdkim_str *cur_val = NULL;
364 int where = PDKIM_HDR_LIMBO;
367 sig = malloc(sizeof(pdkim_signature));
368 if (sig == NULL) return NULL;
369 memset(sig,0,sizeof(pdkim_signature));
371 sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1);
372 if (sig->rawsig_no_b_val == NULL) {
378 q = sig->rawsig_no_b_val;
383 if ( (*p == '\r') || (*p == '\n') )
386 /* Fast-forward through header name */
388 if (*p == ':') past_hname = 1;
392 if (where == PDKIM_HDR_LIMBO) {
393 /* In limbo, just wait for a tag-char to appear */
394 if (!((*p >= 'a') && (*p <= 'z')))
397 where = PDKIM_HDR_TAG;
400 if (where == PDKIM_HDR_TAG) {
402 cur_tag = pdkim_strnew(NULL);
404 if ((*p >= 'a') && (*p <= 'z'))
405 pdkim_strncat(cur_tag,p,1);
408 if (strcmp(cur_tag->str,"b") == 0) {
412 where = PDKIM_HDR_VALUE;
417 if (where == PDKIM_HDR_VALUE) {
419 cur_val = pdkim_strnew(NULL);
421 if ( (*p == '\r') || (*p == '\n') )
425 if (cur_tag->len > 0) {
426 pdkim_strtrim(cur_val);
428 if (ctx->debug_stream)
429 fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str);
431 switch (cur_tag->str[0]) {
433 switch (cur_tag->str[1]) {
435 sig->bodyhash = pdkim_decode_base64(cur_val->str,&(sig->bodyhash_len));
438 sig->sigdata = pdkim_decode_base64(cur_val->str,&(sig->sigdata_len));
443 if (strcmp(cur_val->str,PDKIM_SIGNATURE_VERSION) == 0) {
444 /* We only support version 1, and that is currently the
445 only version there is. */
451 while (pdkim_algos[i] != NULL) {
452 if (strcmp(cur_val->str,pdkim_algos[i]) == 0 ) {
461 while (pdkim_combined_canons[i].str != NULL) {
462 if (strcmp(cur_val->str,pdkim_combined_canons[i].str) == 0 ) {
463 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
464 sig->canon_body = pdkim_combined_canons[i].canon_body;
472 while (pdkim_querymethods[i] != NULL) {
473 if (strcmp(cur_val->str,pdkim_querymethods[i]) == 0 ) {
474 sig->querymethod = i;
481 sig->selector = malloc(strlen(cur_val->str)+1);
482 if (sig->selector == NULL) break;
483 strcpy(sig->selector, cur_val->str);
486 sig->domain = malloc(strlen(cur_val->str)+1);
487 if (sig->domain == NULL) break;
488 strcpy(sig->domain, cur_val->str);
491 sig->identity = pdkim_decode_qp(cur_val->str);
494 sig->created = strtoul(cur_val->str,NULL,10);
497 sig->expires = strtoul(cur_val->str,NULL,10);
500 sig->bodylength = strtoul(cur_val->str,NULL,10);
503 sig->headernames = malloc(strlen(cur_val->str)+1);
504 if (sig->headernames == NULL) break;
505 strcpy(sig->headernames, cur_val->str);
508 sig->copiedheaders = pdkim_decode_qp(cur_val->str);
512 if (ctx->debug_stream)
513 fprintf(ctx->debug_stream, "Unknown tag encountered\n");
518 pdkim_strclear(cur_tag);
519 pdkim_strclear(cur_val);
521 where = PDKIM_HDR_LIMBO;
524 else pdkim_strncat(cur_val,p,1);
536 /* Make sure the most important bits are there. */
537 if (!(sig->domain && (*(sig->domain) != '\0') &&
538 sig->selector && (*(sig->selector) != '\0') &&
539 sig->headernames && (*(sig->headernames) != '\0') &&
540 sig->bodyhash && (*(sig->bodyhash) != '\0') &&
541 sig->sigdata && (*(sig->sigdata) != '\0') &&
549 if (ctx->debug_stream) {
550 fprintf(ctx->debug_stream,
551 "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
552 pdkim_quoteprint(ctx->debug_stream,
553 sig->rawsig_no_b_val,
554 strlen(sig->rawsig_no_b_val), 1);
555 fprintf(ctx->debug_stream,
556 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
560 sha1_starts(&(sig->sha1_body));
561 sha2_starts(&(sig->sha2_body),0);
568 /* -------------------------------------------------------------------------- */
569 int pdkim_update_bodyhash(pdkim_ctx *ctx, char *data, int len) {
570 pdkim_signature *sig = ctx->sig;
571 /* Cache relaxed version of data */
572 char *relaxed_data = NULL;
575 /* Traverse all signatures, updating their hashes. */
576 while (sig != NULL) {
577 /* Defaults to simple canon (no further treatment necessary) */
578 char *canon_data = data;
581 if (sig->canon_body == PDKIM_CANON_RELAXED) {
582 /* Relax the line if not done already */
583 if (relaxed_data == NULL) {
587 relaxed_data = malloc(len+1);
588 if (relaxed_data == NULL) return PDKIM_ERR_OOM;
591 if ( (c == '\t') || (c == ' ') ) {
592 c = ' '; /* Turns WSP into SP */
600 relaxed_data[q++] = c;
603 relaxed_data[q] = '\0';
606 canon_data = relaxed_data;
607 canon_len = relaxed_len;
610 /* Make sure we don't exceed the to-be-signed body length */
611 if (sig->bodylength &&
612 ((sig->signed_body_bytes+(unsigned long)canon_len) > sig->bodylength))
613 canon_len = (sig->bodylength - sig->signed_body_bytes);
616 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
617 sha1_update(&(sig->sha1_body),(unsigned char *)canon_data,canon_len);
619 sha2_update(&(sig->sha2_body),(unsigned char *)canon_data,canon_len);
620 sig->signed_body_bytes += canon_len;
622 if (ctx->debug_stream!=NULL)
623 pdkim_quoteprint(ctx->debug_stream,canon_data,canon_len,0);
630 if (relaxed_data != NULL) free(relaxed_data);
635 /* -------------------------------------------------------------------------- */
636 int pdkim_finish_bodyhash(pdkim_ctx *ctx) {
637 pdkim_signature *sig = ctx->sig;
639 /* Traverse all signatures */
640 while (sig != NULL) {
643 unsigned char bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
644 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
645 sha1_finish(&(sig->sha1_body),bh);
647 sha2_finish(&(sig->sha2_body),bh);
650 if (ctx->debug_stream) {
651 fprintf(ctx->debug_stream, "PDKIM [%s] Body bytes hashed: %lu\n",
652 sig->domain, sig->signed_body_bytes);
653 fprintf(ctx->debug_stream, "PDKIM [%s] bh computed: ", sig->domain);
654 pdkim_hexprint(ctx->debug_stream, (char *)bh,
655 (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
659 /* SIGNING -------------------------------------------------------------- */
660 if (ctx->mode == PDKIM_MODE_SIGN) {
661 sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
662 sig->bodyhash = malloc(sig->bodyhash_len);
663 if (sig->bodyhash == NULL) return PDKIM_ERR_OOM;
664 memcpy(sig->bodyhash,bh,sig->bodyhash_len);
666 /* If bodylength limit is set, and we have received less bytes
667 than the requested amount, effectively remove the limit tag. */
668 if (sig->signed_body_bytes < sig->bodylength) sig->bodylength = 0;
670 /* VERIFICATION --------------------------------------------------------- */
672 /* Compare bodyhash */
673 if (memcmp(bh,sig->bodyhash,
674 (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0) {
676 if (ctx->debug_stream)
677 fprintf(ctx->debug_stream, "PDKIM [%s] Body hash verified OK\n",
683 if (ctx->debug_stream) {
684 fprintf(ctx->debug_stream, "PDKIM [%s] Body hash did NOT verify\n",
686 fprintf(ctx->debug_stream, "PDKIM [%s] bh signature: ", sig->domain);
687 pdkim_hexprint(ctx->debug_stream, sig->bodyhash,
688 (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
691 sig->verify_status = PDKIM_VERIFY_FAIL;
692 sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
704 /* -------------------------------------------------------------------------- */
705 /* Callback from pdkim_feed below for processing complete body lines */
706 int pdkim_bodyline_complete(pdkim_ctx *ctx) {
707 char *p = ctx->linebuf;
708 int n = ctx->linebuf_offset;
710 /* Ignore extra data if we've seen the end-of-data marker */
711 if (ctx->seen_eod) goto BAIL;
713 /* We've always got one extra byte to stuff a zero ... */
714 ctx->linebuf[(ctx->linebuf_offset)] = '\0';
716 if (ctx->input_mode == PDKIM_INPUT_SMTP) {
717 /* Terminate on EOD marker */
718 if (memcmp(p,".\r\n",3) == 0) {
723 if (memcmp(p,"..",2) == 0) {
729 /* Empty lines need to be buffered until we find a non-empty line */
730 if (memcmp(p,"\r\n",2) == 0) {
731 ctx->num_buffered_crlf++;
735 /* At this point, we have a non-empty line, so release the buffered ones. */
736 while (ctx->num_buffered_crlf) {
737 pdkim_update_bodyhash(ctx,"\r\n",2);
738 ctx->num_buffered_crlf--;
741 pdkim_update_bodyhash(ctx,p,n);
744 ctx->linebuf_offset = 0;
749 /* -------------------------------------------------------------------------- */
750 /* Callback from pdkim_feed below for processing complete headers */
751 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
752 int pdkim_header_complete(pdkim_ctx *ctx) {
753 pdkim_signature *sig = ctx->sig;
755 /* Special case: The last header can have an extra \r appended */
756 if ( (ctx->cur_header->len > 1) &&
757 (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') ) {
758 ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
759 ctx->cur_header->len--;
762 /* Traverse all signatures */
763 while (sig != NULL) {
765 /* SIGNING -------------------------------------------------------------- */
766 if (ctx->mode == PDKIM_MODE_SIGN) {
767 if (header_name_match(ctx->cur_header->str,
770 PDKIM_DEFAULT_SIGN_HEADERS, 0) < 0) goto NEXT_SIG;
772 /* VERIFICATION --------------------------------------------------------- */
774 int rc = header_name_match(ctx->cur_header->str,
776 sig->headernames_pos);
777 /* Header is not included or out-of-sequence */
778 if (rc < 0) goto NEXT_SIG;
779 sig->headernames_pos = rc;
782 /* Add header to the signed headers list */
783 pdkim_stringlist *list = pdkim_append_stringlist(sig->headers,
784 ctx->cur_header->str);
785 if (list == NULL) return PDKIM_ERR_OOM;
792 /* DKIM-Signature: headers are added to the verification list */
793 if ( (ctx->mode == PDKIM_MODE_VERIFY) &&
794 (strncasecmp(ctx->cur_header->str,
795 DKIM_SIGNATURE_HEADERNAME,
796 strlen(DKIM_SIGNATURE_HEADERNAME)) == 0) ) {
797 /* Create and chain new signature block */
799 if (ctx->debug_stream)
800 fprintf(ctx->debug_stream,
801 "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
803 pdkim_signature *new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str);
804 if (new_sig != NULL) {
805 pdkim_signature *last_sig = ctx->sig;
806 if (last_sig == NULL) {
810 while (last_sig->next != NULL) { last_sig = last_sig->next; };
811 last_sig->next = new_sig;
816 if (ctx->debug_stream) {
817 fprintf(ctx->debug_stream,"Error while parsing signature header\n");
818 fprintf(ctx->debug_stream,
819 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
825 pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
831 /* -------------------------------------------------------------------------- */
832 #define HEADER_BUFFER_FRAG_SIZE 256
833 int pdkim_feed (pdkim_ctx *ctx,
837 for (p=0;p<len;p++) {
839 if (ctx->past_headers) {
840 /* Processing body byte */
841 ctx->linebuf[(ctx->linebuf_offset)++] = c;
843 int rc = pdkim_bodyline_complete(ctx); /* End of line */
844 if (rc != PDKIM_OK) return rc;
846 if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
847 return PDKIM_ERR_LONG_LINE;
850 /* Processing header byte */
854 int rc = pdkim_header_complete(ctx); /* Seen last header line */
855 if (rc != PDKIM_OK) return rc;
856 ctx->past_headers = 1;
859 if (ctx->debug_stream)
860 fprintf(ctx->debug_stream,
861 "PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
865 else ctx->seen_lf = 1;
867 else if (ctx->seen_lf) {
868 if (! ((c == '\t') || (c == ' '))) {
869 int rc = pdkim_header_complete(ctx); /* End of header */
870 if (rc != PDKIM_OK) return rc;
875 if (ctx->cur_header == NULL) {
876 ctx->cur_header = pdkim_strnew(NULL);
877 if (ctx->cur_header == NULL) return PDKIM_ERR_OOM;
879 if (pdkim_strncat(ctx->cur_header,&data[p],1) == NULL)
880 return PDKIM_ERR_OOM;
887 /* -------------------------------------------------------------------------- */
888 char *pdkim_create_header(pdkim_signature *sig, int final) {
890 char *base64_bh = NULL;
891 char *base64_b = NULL;
892 pdkim_str *hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
893 if (hdr == NULL) return NULL;
895 base64_bh = pdkim_encode_base64(sig->bodyhash, sig->bodyhash_len);
896 if (base64_bh == NULL) goto BAIL;
898 /* Required and static bits */
900 pdkim_strcat(hdr,"; a=") &&
901 pdkim_strcat(hdr,pdkim_algos[sig->algo]) &&
902 pdkim_strcat(hdr,"; q=") &&
903 pdkim_strcat(hdr,pdkim_querymethods[sig->querymethod]) &&
904 pdkim_strcat(hdr,"; c=") &&
905 pdkim_strcat(hdr,pdkim_canons[sig->canon_headers]) &&
906 pdkim_strcat(hdr,"/") &&
907 pdkim_strcat(hdr,pdkim_canons[sig->canon_body]) &&
908 pdkim_strcat(hdr,"; d=") &&
909 pdkim_strcat(hdr,sig->domain) &&
910 pdkim_strcat(hdr,"; s=") &&
911 pdkim_strcat(hdr,sig->selector) &&
912 pdkim_strcat(hdr,";\r\n\th=") &&
913 pdkim_strcat(hdr,sig->headernames) &&
914 pdkim_strcat(hdr,"; bh=") &&
915 pdkim_strcat(hdr,base64_bh) &&
916 pdkim_strcat(hdr,";\r\n\t")
919 if (sig->identity != NULL) {
920 if (!( pdkim_strcat(hdr,"i=") &&
921 pdkim_strcat(hdr,sig->identity) &&
922 pdkim_strcat(hdr,";") ) ) {
926 if (sig->created > 0) {
927 if (!( pdkim_strcat(hdr,"t=") &&
928 pdkim_numcat(hdr,sig->created) &&
929 pdkim_strcat(hdr,";") ) ) {
933 if (sig->expires > 0) {
934 if (!( pdkim_strcat(hdr,"x=") &&
935 pdkim_numcat(hdr,sig->expires) &&
936 pdkim_strcat(hdr,";") ) ) {
940 if (sig->bodylength > 0) {
941 if (!( pdkim_strcat(hdr,"l=") &&
942 pdkim_numcat(hdr,sig->bodylength) &&
943 pdkim_strcat(hdr,";") ) ) {
947 /* Extra linebreak */
948 if (hdr->str[(hdr->len)-1] == ';') {
949 if (!pdkim_strcat(hdr," \r\n\t")) goto BAIL;
951 /* Preliminary or final version? */
953 base64_b = pdkim_encode_base64(sig->sigdata, sig->sigdata_len);
954 if (base64_b == NULL) goto BAIL;
956 pdkim_strcat(hdr,"b=") &&
957 pdkim_strcat(hdr,base64_b) &&
958 pdkim_strcat(hdr,";")
962 if (pdkim_strcat(hdr,"b=;")) goto DONE;
969 rc = strdup(hdr->str);
973 if (base64_bh != NULL) free(base64_bh);
974 if (base64_b != NULL) free(base64_b);
979 /* -------------------------------------------------------------------------- */
980 int pdkim_feed_finish(pdkim_ctx *ctx, char **signature) {
981 pdkim_signature *sig = ctx->sig;
982 pdkim_str *headernames = NULL; /* Collected signed header names */
984 /* Check if we must still flush a (partial) header. If that is the
985 case, the message has no body, and we must compute a body hash
987 if (ctx->cur_header->len) {
988 int rc = pdkim_header_complete(ctx);
989 if (rc != PDKIM_OK) return rc;
990 pdkim_update_bodyhash(ctx,"\r\n",2);
993 /* For non-smtp input, check if there's an unfinished line in the
994 body line buffer. If that is the case, we must add a CRLF to the
995 hash to properly terminate the message. */
996 if ((ctx->input_mode == PDKIM_INPUT_NORMAL) && ctx->linebuf_offset) {
997 pdkim_update_bodyhash(ctx, ctx->linebuf, ctx->linebuf_offset);
998 pdkim_update_bodyhash(ctx,"\r\n",2);
1001 if (ctx->debug_stream)
1002 fprintf(ctx->debug_stream,
1003 "\nPDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1007 /* Build (and/or evaluate) body hash */
1008 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK) return PDKIM_ERR_OOM;
1010 /* SIGNING -------------------------------------------------------------- */
1011 if (ctx->mode == PDKIM_MODE_SIGN) {
1012 headernames = pdkim_strnew(NULL);
1013 if (headernames == NULL) return PDKIM_ERR_OOM;
1015 /* ---------------------------------------------------------------------- */
1017 while (sig != NULL) {
1018 sha1_context sha1_headers;
1019 sha2_context sha2_headers;
1020 pdkim_stringlist *p = sig->headers;
1022 char headerhash[32];
1024 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1025 sha1_starts(&sha1_headers);
1027 sha2_starts(&sha2_headers,0);
1030 if (ctx->debug_stream)
1031 fprintf(ctx->debug_stream,
1032 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1038 /* SIGNING -------------------------------------------------------------- */
1039 if (ctx->mode == PDKIM_MODE_SIGN) {
1040 /* Collect header names (Note: colon presence is guaranteed here) */
1041 char *q = strchr(p->value,':');
1042 if (pdkim_strncat(headernames, p->value,
1043 (q-(p->value))+((p->next==NULL)?0:1)) == NULL)
1044 return PDKIM_ERR_OOM;
1046 /* ---------------------------------------------------------------------- */
1048 if (sig->canon_body == PDKIM_CANON_RELAXED)
1049 rh = pdkim_relax_header(p->value,1); /* cook header for relaxed canon */
1051 rh = strdup(p->value); /* just copy it for simple canon */
1053 if (rh == NULL) return PDKIM_ERR_OOM;
1055 /* Feed header to the hash algorithm */
1056 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1057 sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh));
1059 sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh));
1061 if (ctx->debug_stream)
1062 pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
1069 if (ctx->debug_stream)
1070 fprintf(ctx->debug_stream,
1071 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1075 /* SIGNING ---------------------------------------------------------------- */
1076 if (ctx->mode == PDKIM_MODE_SIGN) {
1077 /* Copy headernames to signature struct */
1078 sig->headernames = strdup(headernames->str);
1079 pdkim_strfree(headernames);
1081 /* Create signature header with b= omitted */
1082 sig_hdr = pdkim_create_header(ctx->sig,0);
1084 /* VERIFICATION ----------------------------------------------------------- */
1086 sig_hdr = strdup(sig->rawsig_no_b_val);
1088 /* ------------------------------------------------------------------------ */
1090 if (sig_hdr == NULL) return PDKIM_ERR_OOM;
1092 /* Relax header if necessary */
1093 if (sig->canon_headers == PDKIM_CANON_RELAXED) {
1094 char *relaxed_hdr = pdkim_relax_header(sig_hdr,0);
1096 if (relaxed_hdr == NULL) return PDKIM_ERR_OOM;
1097 sig_hdr = relaxed_hdr;
1101 if (ctx->debug_stream) {
1102 fprintf(ctx->debug_stream,
1103 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1104 pdkim_quoteprint(ctx->debug_stream, sig_hdr, strlen(sig_hdr), 1);
1105 fprintf(ctx->debug_stream,
1106 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1110 /* Finalize header hash */
1111 if (sig->algo == PDKIM_ALGO_RSA_SHA1) {
1112 sha1_update(&(sha1_headers),(unsigned char *)sig_hdr,strlen(sig_hdr));
1113 sha1_finish(&(sha1_headers),(unsigned char *)headerhash);
1116 sha2_update(&(sha2_headers),(unsigned char *)sig_hdr,strlen(sig_hdr));
1117 sha2_finish(&(sha2_headers),(unsigned char *)headerhash);
1122 /* SIGNING ---------------------------------------------------------------- */
1123 if (ctx->mode == PDKIM_MODE_SIGN) {
1126 /* Perform private key operation */
1127 if (rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
1128 strlen(sig->rsa_privkey), NULL, 0) != 0) {
1129 return PDKIM_ERR_RSA_PRIVKEY;
1132 sig->sigdata_len = mpi_size(&(rsa.N));
1133 sig->sigdata = malloc(sig->sigdata_len);
1134 if (sig->sigdata == NULL) return PDKIM_ERR_OOM;
1136 if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
1137 ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
1138 RSA_SHA1:RSA_SHA256),
1140 (unsigned char *)headerhash,
1141 (unsigned char *)sig->sigdata ) != 0) {
1142 return PDKIM_ERR_RSA_SIGNING;
1148 if (ctx->debug_stream) {
1149 fprintf(ctx->debug_stream, "PDKIM [%s] b computed: ",
1151 pdkim_hexprint(ctx->debug_stream, sig->sigdata, sig->sigdata_len, 1);
1155 /* Recreate signature header with b= included, return it to the caller */
1156 if (signature != NULL) {
1157 *signature = pdkim_create_header(ctx->sig,1);
1158 if (*signature == NULL) return PDKIM_ERR_OOM;
1161 /* VERIFICATION ----------------------------------------------------------- */
1173 /* -------------------------------------------------------------------------- */
1174 pdkim_ctx *pdkim_init_verify(void) {
1175 pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
1176 if (ctx == NULL) return NULL;
1177 memset(ctx,0,sizeof(pdkim_ctx));
1178 ctx->mode = PDKIM_MODE_VERIFY;
1183 /* -------------------------------------------------------------------------- */
1184 pdkim_ctx *pdkim_init_sign(char *domain,
1186 char *rsa_privkey) {
1189 if (!domain || !selector || !rsa_privkey) return NULL;
1191 ctx = malloc(sizeof(pdkim_ctx));
1192 if (ctx == NULL) return NULL;
1193 memset(ctx,0,sizeof(pdkim_ctx));
1194 pdkim_signature *sig = malloc(sizeof(pdkim_signature));
1199 memset(sig,0,sizeof(pdkim_signature));
1201 ctx->mode = PDKIM_MODE_SIGN;
1204 ctx->sig->domain = malloc(strlen(domain)+1);
1205 ctx->sig->selector = malloc(strlen(selector)+1);
1206 ctx->sig->rsa_privkey = malloc(strlen(rsa_privkey)+1);
1208 if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey) {
1209 pdkim_free_ctx(ctx);
1213 strcpy(ctx->sig->domain, domain);
1214 strcpy(ctx->sig->selector, selector);
1215 strcpy(ctx->sig->rsa_privkey, rsa_privkey);
1217 sha1_starts(&(ctx->sig->sha1_body));
1218 sha2_starts(&(ctx->sig->sha2_body),0);
1224 /* -------------------------------------------------------------------------- */
1225 void pdkim_set_debug_stream(pdkim_ctx *ctx,
1226 FILE *debug_stream) {
1227 ctx->debug_stream = debug_stream;
1231 /* -------------------------------------------------------------------------- */
1232 int pdkim_set_optional(pdkim_ctx *ctx,
1238 unsigned long bodylength,
1240 unsigned long created,
1241 unsigned long expires) {
1243 if (identity != NULL) {
1244 ctx->sig->identity = malloc(strlen(identity)+1);
1245 if (!ctx->sig->identity) {
1246 return PDKIM_ERR_OOM;
1248 strcpy(ctx->sig->identity, identity);
1251 if (sign_headers != NULL) {
1252 ctx->sig->sign_headers = malloc(strlen(sign_headers)+1);
1253 if (!ctx->sig->sign_headers) {
1254 return PDKIM_ERR_OOM;
1256 strcpy(ctx->sig->sign_headers, sign_headers);
1259 ctx->input_mode = input_mode;
1260 ctx->sig->canon_headers = canon_headers;
1261 ctx->sig->canon_body = canon_body;
1262 ctx->sig->bodylength = bodylength;
1263 ctx->sig->algo = algo;
1264 ctx->sig->created = created;
1265 ctx->sig->expires = expires;
1273 /* -------------------------------------------------------------------------- */
1274 void pdkim_free_sig(pdkim_signature *sig) {
1276 pdkim_signature *next = (pdkim_signature *)sig->next;
1278 pdkim_stringlist *e = sig->headers;
1280 pdkim_stringlist *c = e;
1281 if (e->value != NULL) free(e->value);
1286 if (sig->sigdata != NULL) free(sig->sigdata);
1287 if (sig->bodyhash != NULL) free(sig->bodyhash);
1288 if (sig->selector != NULL) free(sig->selector);
1289 if (sig->domain != NULL) free(sig->domain);
1290 if (sig->identity != NULL) free(sig->identity);
1291 if (sig->headernames != NULL) free(sig->headernames);
1292 if (sig->copiedheaders != NULL) free(sig->copiedheaders);
1293 if (sig->rsa_privkey != NULL) free(sig->rsa_privkey);
1294 if (sig->sign_headers != NULL) free(sig->sign_headers);
1297 if (next != NULL) pdkim_free_sig(next);
1302 /* -------------------------------------------------------------------------- */
1303 void pdkim_free_ctx(pdkim_ctx *ctx) {
1305 pdkim_free_sig(ctx->sig);
1306 pdkim_strfree(ctx->cur_header);