1 /* $Cambridge: exim/src/src/pdkim/pdkim.c,v 1.1.2.3 2009/02/25 12:52:58 tom Exp $ */
13 /* -------------------------------------------------------------------------- */
14 /* A bunch of list constants */
15 char *pdkim_querymethods[] = {
18 char *pdkim_algos[] = {
22 char *pdkim_canons[] = {
28 /* -------------------------------------------------------------------------- */
29 /* Various debugging functions */
31 void pdkim_quoteprint(FILE *stream, char *data, int len, int lf) {
33 unsigned char *p = (unsigned char *)data;
38 case ' ' : fprintf(stream,"{SP}"); break;
39 case '\t': fprintf(stream,"{TB}"); break;
40 case '\r': fprintf(stream,"{CR}"); break;
41 case '\n': fprintf(stream,"{LF}"); break;
42 case '{' : fprintf(stream,"{BO}"); break;
43 case '}' : fprintf(stream,"{BC}"); break;
45 if ( (c < 32) || (c > 127) )
46 fprintf(stream,"{%02x}",c);
58 /* -------------------------------------------------------------------------- */
59 /* Simple string list implementation for convinience */
60 pdkim_stringlist *pdkim_append_stringlist(pdkim_stringlist *base, char *str) {
61 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
62 if (new_entry == NULL) return NULL;
63 memset(new_entry,0,sizeof(pdkim_stringlist));
64 new_entry->value = malloc(strlen(str)+1);
65 if (new_entry->value == NULL) return NULL;
66 strcpy(new_entry->value,str);
68 pdkim_stringlist *last = base;
69 while (last->next != NULL) { last = last->next; };
70 last->next = new_entry;
73 else return new_entry;
77 /* -------------------------------------------------------------------------- */
78 /* A small "growing string" implementation to escape malloc/realloc hell */
79 pdkim_str *pdkim_strnew (char *cstr) {
80 unsigned int len = cstr?strlen(cstr):0;
81 pdkim_str *p = malloc(sizeof(pdkim_str));
82 if (p == NULL) return NULL;
83 memset(p,0,sizeof(pdkim_str));
84 p->str = malloc(len+1);
91 if (cstr) strcpy(p->str,cstr);
94 char *pdkim_strcat(pdkim_str *str, char *cstr) {
95 return pdkim_strncat(str, cstr, strlen(cstr));
97 char *pdkim_strncat(pdkim_str *str, char *data, int len) {
98 if ((str->allocated - str->len) < (len+1)) {
99 /* Extend the buffer */
100 int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
101 char *n = realloc(str->str,
102 (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
103 if (n == NULL) return NULL;
105 str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
107 strncpy(&(str->str[str->len]),data,len);
109 str->str[str->len] = '\0';
112 char *pdkim_numcat(pdkim_str *str, unsigned long num) {
114 snprintf(minibuf,20,"%lu",num);
115 return pdkim_strcat(str,minibuf);
117 void pdkim_strfree(pdkim_str *str) {
118 if (str == NULL) return;
119 if (str->str != NULL) free(str->str);
124 /* -------------------------------------------------------------------------- */
125 /* Matches the name of the passed raw "header" against
126 the passed colon-separated "list". Case-insensitive.
127 Returns '0' for a match. */
128 int header_name_match(char *header,
135 char *hcolon = strchr(header,':');
136 if (hcolon == NULL) return rc; /* This isn't a header */
137 hname = malloc((hcolon-header)+1);
138 if (hname == NULL) return PDKIM_ERR_OOM;
139 memset(hname,0,(hcolon-header)+1);
140 strncpy(hname,header,(hcolon-header));
141 lcopy = malloc(strlen(list)+1);
144 return PDKIM_ERR_OOM;
151 if (strcasecmp(p,hname) == 0) {
158 if (strcasecmp(p,hname) == 0) rc = PDKIM_OK;
166 /* -------------------------------------------------------------------------- */
167 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
169 char *pdkim_relax_header (char *header, int crlf) {
170 int past_field_name = 0;
174 char *relaxed = malloc(strlen(header));
175 if (relaxed == NULL) return NULL;
180 if ( (c == '\r') || (c == '\n') ) {
184 if ( (c == '\t') || (c == ' ') ) {
185 c = ' '; /* Turns WSP into SP */
193 if ( (!past_field_name) && (c == ':') ) {
194 if (seen_wsp) q--; /* This removes WSP before the colon */
195 seen_wsp = 1; /* This removes WSP after the colon */
200 /* Lowercase header name */
201 if (!past_field_name) c = tolower(c);
207 if (crlf) strcat(relaxed,"\r\n");
212 /* -------------------------------------------------------------------------- */
213 int pdkim_update_bodyhash(pdkim_ctx *ctx, char *data, int len) {
214 pdkim_signature *sig = ctx->sig;
215 /* Cache relaxed version of data */
216 char *relaxed_data = NULL;
219 /* Traverse all signatures, updating their hashes. */
220 while (sig != NULL) {
221 /* Defaults to simple canon (no further treatment necessary) */
222 char *canon_data = data;
225 if (sig->canon_body == PDKIM_CANON_RELAXED) {
226 /* Relax the line if not done already */
227 if (relaxed_data == NULL) {
231 relaxed_data = malloc(len+1);
232 if (relaxed_data == NULL) return PDKIM_ERR_OOM;
235 if ( (c == '\t') || (c == ' ') ) {
236 c = ' '; /* Turns WSP into SP */
244 relaxed_data[q++] = c;
247 relaxed_data[q] = '\0';
250 canon_data = relaxed_data;
251 canon_len = relaxed_len;
254 /* Make sure we don't exceed the to-be-signed body length */
255 if (sig->bodylength &&
256 ((sig->signed_body_bytes+(unsigned long)canon_len) > sig->bodylength))
257 canon_len = (sig->bodylength - sig->signed_body_bytes);
260 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
261 sha1_update(&(sig->sha1_body),(unsigned char *)canon_data,canon_len);
263 sha2_update(&(sig->sha2_body),(unsigned char *)canon_data,canon_len);
264 sig->signed_body_bytes += canon_len;
266 if (ctx->debug_stream!=NULL)
267 pdkim_quoteprint(ctx->debug_stream,canon_data,canon_len,0);
274 if (relaxed_data != NULL) free(relaxed_data);
279 /* -------------------------------------------------------------------------- */
280 int pdkim_finish_bodyhash(pdkim_ctx *ctx) {
281 pdkim_signature *sig = ctx->sig;
283 /* Traverse all signatures */
284 while (sig != NULL) {
287 if (ctx->debug_stream)
288 fprintf(ctx->debug_stream, "PDKIM [%s] Body bytes hashed: %lu\n",
289 sig->domain, sig->signed_body_bytes);
293 unsigned char bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
294 if (sig->algo == PDKIM_ALGO_RSA_SHA1)
295 sha1_finish(&(sig->sha1_body),bh);
297 sha2_finish(&(sig->sha2_body),bh);
299 /* SIGNING -------------------------------------------------------------- */
300 if (ctx->mode == PDKIM_MODE_SIGN) {
302 /* Build base64 version of body hash and place it in the sig struct */
303 int slen = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
305 base64_encode(NULL,&dlen,bh,slen); /* Puts needed length in dlen */
306 sig->bodyhash = malloc(dlen+1);
307 if (sig->bodyhash == NULL) return PDKIM_ERR_OOM;
308 if (base64_encode((unsigned char *)sig->bodyhash,&dlen,bh,slen) == 0) {
309 sig->bodyhash[dlen] = '\0';
311 if (ctx->debug_stream)
312 fprintf(ctx->debug_stream, "PDKIM [%s] body hash: %s\n",
313 sig->domain, sig->bodyhash);
318 /* If bodylength limit is set, and we have received less bytes
319 than the requested amount, effectively remove the limit tag. */
320 if (sig->signed_body_bytes < sig->bodylength) sig->bodylength = 0;
322 /* VERIFICATION --------------------------------------------------------- */
337 /* -------------------------------------------------------------------------- */
338 /* Callback from pdkim_feed below for processing complete body lines */
339 int pdkim_bodyline_complete(pdkim_ctx *ctx) {
340 char *p = ctx->linebuf;
341 int n = ctx->linebuf_offset;
343 /* Ignore extra data if we've seen the end-of-data marker */
344 if (ctx->seen_eod) goto BAIL;
346 /* We've always got one extra byte to stuff a zero ... */
347 ctx->linebuf[(ctx->linebuf_offset)] = '\0';
349 if (ctx->input_mode == PDKIM_INPUT_SMTP) {
350 /* Terminate on EOD marker */
351 if (memcmp(p,".\r\n",3) == 0) {
356 if (memcmp(p,"..",2) == 0) {
362 /* Empty lines need to be buffered until we find a non-empty line */
363 if (memcmp(p,"\r\n",2) == 0) {
364 ctx->num_buffered_crlf++;
368 /* At this point, we have a non-empty line, so release the buffered ones. */
369 while (ctx->num_buffered_crlf) {
370 pdkim_update_bodyhash(ctx,"\r\n",2);
371 ctx->num_buffered_crlf--;
374 pdkim_update_bodyhash(ctx,p,n);
377 ctx->linebuf_offset = 0;
382 /* -------------------------------------------------------------------------- */
383 /* Callback from pdkim_feed below for processing complete headers */
384 int pdkim_header_complete(pdkim_ctx *ctx) {
385 pdkim_signature *sig = ctx->sig;
387 /* Special case: The last header can have an extra \r appended */
388 if ( (ctx->cur_header->len > 1) &&
389 (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') ) {
390 ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
391 ctx->cur_header->len--;
394 /* Traverse all signatures */
395 while (sig != NULL) {
397 /* SIGNING -------------------------------------------------------------- */
398 if (ctx->mode == PDKIM_MODE_SIGN) {
399 if (header_name_match(ctx->cur_header->str,
400 sig->sign_headers?sig->sign_headers
401 :PDKIM_DEFAULT_SIGN_HEADERS) == 0) {
402 pdkim_stringlist *list = pdkim_append_stringlist(sig->headers,
403 ctx->cur_header->str);
404 if (list == NULL) return PDKIM_ERR_OOM;
408 /* VERIFICATION --------------------------------------------------------- */
415 ctx->cur_header->len = 0; /* Re-use existing pdkim_str */
421 /* -------------------------------------------------------------------------- */
422 #define HEADER_BUFFER_FRAG_SIZE 256
423 int pdkim_feed (pdkim_ctx *ctx,
427 for (p=0;p<len;p++) {
429 if (ctx->past_headers) {
430 /* Processing body byte */
431 ctx->linebuf[(ctx->linebuf_offset)++] = c;
433 int rc = pdkim_bodyline_complete(ctx); /* End of line */
434 if (rc != PDKIM_OK) return rc;
436 if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
437 return PDKIM_ERR_LONG_LINE;
440 /* Processing header byte */
444 int rc = pdkim_header_complete(ctx); /* Seen last header line */
445 if (rc != PDKIM_OK) return rc;
446 ctx->past_headers = 1;
449 if (ctx->debug_stream)
450 fprintf(ctx->debug_stream,
451 "PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
455 else ctx->seen_lf = 1;
457 else if (ctx->seen_lf) {
458 if (! ((c == '\t') || (c == ' '))) {
459 int rc = pdkim_header_complete(ctx); /* End of header */
460 if (rc != PDKIM_OK) return rc;
465 if (ctx->cur_header == NULL) {
466 ctx->cur_header = pdkim_strnew(NULL);
467 if (ctx->cur_header == NULL) return PDKIM_ERR_OOM;
469 if (pdkim_strncat(ctx->cur_header,&data[p],1) == NULL)
470 return PDKIM_ERR_OOM;
477 /* -------------------------------------------------------------------------- */
478 pdkim_str *pdkim_create_header(pdkim_ctx *ctx, int final) {
480 pdkim_str *hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
481 if (hdr == NULL) return NULL;
482 /* Required and static bits */
484 pdkim_strcat(hdr,"; a=") &&
485 pdkim_strcat(hdr,pdkim_algos[ctx->sig->algo]) &&
486 pdkim_strcat(hdr,"; q=") &&
487 pdkim_strcat(hdr,pdkim_querymethods[ctx->sig->querymethod]) &&
488 pdkim_strcat(hdr,"; c=") &&
489 pdkim_strcat(hdr,pdkim_canons[ctx->sig->canon_headers]) &&
490 pdkim_strcat(hdr,"/") &&
491 pdkim_strcat(hdr,pdkim_canons[ctx->sig->canon_body]) &&
492 pdkim_strcat(hdr,"; d=") &&
493 pdkim_strcat(hdr,ctx->sig->domain) &&
494 pdkim_strcat(hdr,"; s=") &&
495 pdkim_strcat(hdr,ctx->sig->selector) &&
496 pdkim_strcat(hdr,";\r\n\th=") &&
497 pdkim_strcat(hdr,ctx->sig->headernames) &&
498 pdkim_strcat(hdr,"; bh=") &&
499 pdkim_strcat(hdr,ctx->sig->bodyhash) &&
500 pdkim_strcat(hdr,";\r\n\t")
503 if (ctx->sig->identity != NULL) {
504 if (!( pdkim_strcat(hdr,"i=") &&
505 pdkim_strcat(hdr,ctx->sig->identity) &&
506 pdkim_strcat(hdr,";") ) ) {
510 if (ctx->sig->created > 0) {
511 if (!( pdkim_strcat(hdr,"t=") &&
512 pdkim_numcat(hdr,ctx->sig->created) &&
513 pdkim_strcat(hdr,";") ) ) {
517 if (ctx->sig->expires > 0) {
518 if (!( pdkim_strcat(hdr,"x=") &&
519 pdkim_numcat(hdr,ctx->sig->expires) &&
520 pdkim_strcat(hdr,";") ) ) {
524 if (ctx->sig->bodylength > 0) {
525 if (!( pdkim_strcat(hdr,"l=") &&
526 pdkim_numcat(hdr,ctx->sig->bodylength) &&
527 pdkim_strcat(hdr,";") ) ) {
531 /* Extra linebreak */
532 if (hdr->str[(hdr->len)-1] == ';') {
533 if (!pdkim_strcat(hdr," \r\n\t")) return NULL;
535 /* Preliminary or final version? */
538 pdkim_strcat(hdr,"b=") &&
539 pdkim_strcat(hdr,ctx->sig->sigdata) &&
540 pdkim_strcat(hdr,";")
544 if (pdkim_strcat(hdr,"b=;")) return hdr;
551 /* -------------------------------------------------------------------------- */
552 int pdkim_feed_finish(pdkim_ctx *ctx, char **signature) {
554 /* Check if we must still flush a (partial) header. If that is the
555 case, the message has no body, and we must compute a body hash
557 if (ctx->cur_header->len) {
558 int rc = pdkim_header_complete(ctx);
559 if (rc != PDKIM_OK) return rc;
560 pdkim_update_bodyhash(ctx,"\r\n",2);
563 /* For non-smtp input, check if there's an unfinished line in the
564 body line buffer. If that is the case, we must add a CRLF to the
565 hash to properly terminate the message. */
566 if ((ctx->input_mode == PDKIM_INPUT_NORMAL) && ctx->linebuf_offset) {
567 pdkim_update_bodyhash(ctx, ctx->linebuf, ctx->linebuf_offset);
568 pdkim_update_bodyhash(ctx,"\r\n",2);
571 if (ctx->debug_stream)
572 fprintf(ctx->debug_stream,
573 "\nPDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
577 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK) return PDKIM_ERR_OOM;
579 /* SIGNING ---------------------------------------------------------------- */
580 if (ctx->mode == PDKIM_MODE_SIGN) {
582 pdkim_str *headernames;
584 char *canon_signature;
585 unsigned char headerhash[32];
586 char *headerhash_base64;
589 sha1_context sha1_headers;
590 sha2_context sha2_headers;
592 if (ctx->sig->algo == PDKIM_ALGO_RSA_SHA1) sha1_starts(&sha1_headers);
593 else sha2_starts(&sha2_headers,0);
594 /* Run through the accumulated list of to-be-signed headers */
596 if (ctx->debug_stream)
597 fprintf(ctx->debug_stream,
598 "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
600 headernames = pdkim_strnew(NULL);
601 p = ctx->sig->headers;
604 /* Collect header names (Note: colon presence is guaranteed here) */
605 char *q = strchr(p->value,':');
606 if (pdkim_strncat(headernames, p->value,
607 (q-(p->value))+((p->next==NULL)?0:1)) == NULL)
608 return PDKIM_ERR_OOM;
609 /* Cook the header if using relaxed canon */
610 if (ctx->sig->canon_body == PDKIM_CANON_RELAXED) {
611 rh = pdkim_relax_header(p->value,1);
612 if (rh == NULL) return PDKIM_ERR_OOM;
614 /* Feed header to the hash algorithm */
615 if (ctx->sig->algo == PDKIM_ALGO_RSA_SHA1)
616 sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh));
618 sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh));
620 if (ctx->debug_stream)
621 pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
627 if (ctx->debug_stream)
628 fprintf(ctx->debug_stream,
629 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
632 /* Copy headernames to signature struct */
633 ctx->sig->headernames = malloc((headernames->len)+1);
634 if (ctx->sig->headernames == NULL) return PDKIM_ERR_OOM;
635 strcpy(ctx->sig->headernames, headernames->str);
636 pdkim_strfree(headernames);
638 /* Create signature header with b= omitted */
639 hdr = pdkim_create_header(ctx,0);
640 if (hdr == NULL) return PDKIM_ERR_OOM;
642 /* If necessary, perform relaxed canon */
643 canon_signature = hdr->str;
644 if (ctx->sig->canon_headers == PDKIM_CANON_RELAXED) {
645 canon_signature = pdkim_relax_header(canon_signature,0);
646 if (canon_signature == NULL) return PDKIM_ERR_OOM;
650 if (ctx->debug_stream) {
651 fprintf(ctx->debug_stream,
652 "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
653 pdkim_quoteprint(ctx->debug_stream, canon_signature, strlen(canon_signature), 1);
654 fprintf(ctx->debug_stream,
655 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
659 /* Feed preliminary signature header to the hash algorithm */
660 if (ctx->sig->algo == PDKIM_ALGO_RSA_SHA1) {
662 sha1_update(&(sha1_headers),(unsigned char *)canon_signature,strlen(canon_signature));
663 sha1_finish(&(sha1_headers),headerhash);
664 base64_encode(NULL,&dlen,headerhash,20);
665 headerhash_base64 = malloc(dlen+1);
666 if (headerhash == NULL) return PDKIM_ERR_OOM;
667 base64_encode((unsigned char *)headerhash_base64,&dlen,headerhash,20);
668 headerhash_base64[dlen] = '\0';
670 if (ctx->debug_stream)
671 fprintf(ctx->debug_stream,
672 "PDKIM SHA1 header hash: %s\n",headerhash_base64);
677 sha2_update(&(sha2_headers),(unsigned char *)canon_signature,strlen(canon_signature));
678 sha2_finish(&(sha2_headers),headerhash);
679 base64_encode(NULL,&dlen,headerhash,32);
680 headerhash_base64 = malloc(dlen+1);
681 if (headerhash == NULL) return PDKIM_ERR_OOM;
682 base64_encode((unsigned char *)headerhash_base64,&dlen,headerhash,32);
683 headerhash_base64[dlen] = '\0';
685 if (ctx->debug_stream)
686 fprintf(ctx->debug_stream,
687 "PDKIM SHA256 header hash: %s\n",headerhash_base64);
691 if (rsa_parse_key(&rsa, (unsigned char *)ctx->sig->rsa_privkey,
692 strlen(ctx->sig->rsa_privkey), NULL, 0) != 0) {
693 return PDKIM_ERR_RSA_PRIVKEY;
696 rsa_sig = malloc(mpi_size(&(rsa.N)));
697 if (rsa_sig == NULL) return PDKIM_ERR_OOM;
699 if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
700 ((ctx->sig->algo == PDKIM_ALGO_RSA_SHA1)?
705 0, headerhash, (unsigned char *)rsa_sig ) != 0) {
706 return PDKIM_ERR_RSA_SIGNING;
709 base64_encode(NULL,&sigdata_len,(unsigned char *)rsa_sig,mpi_size(&(rsa.N)));
710 ctx->sig->sigdata = malloc(sigdata_len+1);
711 if (ctx->sig->sigdata == NULL) return PDKIM_ERR_OOM;
712 base64_encode((unsigned char *)ctx->sig->sigdata,
714 (unsigned char *)rsa_sig,
716 ctx->sig->sigdata[sigdata_len] = '\0';
719 if (ctx->debug_stream)
720 fprintf(ctx->debug_stream,
721 "PDKIM RSA-signed hash: %s\n",ctx->sig->sigdata);
724 /* Recreate signature header with b= included */
726 hdr = pdkim_create_header(ctx,1);
727 if (hdr == NULL) return PDKIM_ERR_OOM;
730 if (ctx->debug_stream) {
731 fprintf(ctx->debug_stream,
732 "PDKIM >> Final DKIM-Signature header >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
733 pdkim_quoteprint(ctx->debug_stream, hdr->str, hdr->len, 1);
734 fprintf(ctx->debug_stream,
735 "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
739 if (signature != NULL) {
740 *signature = hdr->str;
750 /* -------------------------------------------------------------------------- */
751 pdkim_ctx *pdkim_init_sign(char *domain,
756 if (!domain || !selector || !rsa_privkey) return NULL;
758 ctx = malloc(sizeof(pdkim_ctx));
759 if (ctx == NULL) return NULL;
760 memset(ctx,0,sizeof(pdkim_ctx));
761 pdkim_signature *sig = malloc(sizeof(pdkim_signature));
766 memset(sig,0,sizeof(pdkim_signature));
768 ctx->mode = PDKIM_MODE_SIGN;
771 ctx->sig->domain = malloc(strlen(domain)+1);
772 ctx->sig->selector = malloc(strlen(selector)+1);
773 ctx->sig->rsa_privkey = malloc(strlen(rsa_privkey)+1);
775 if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey) {
780 strcpy(ctx->sig->domain, domain);
781 strcpy(ctx->sig->selector, selector);
782 strcpy(ctx->sig->rsa_privkey, rsa_privkey);
784 sha1_starts(&(ctx->sig->sha1_body));
785 sha2_starts(&(ctx->sig->sha2_body),0);
792 /* -------------------------------------------------------------------------- */
793 void pdkim_set_debug_stream(pdkim_ctx *ctx,
794 FILE *debug_stream) {
795 ctx->debug_stream = debug_stream;
799 /* -------------------------------------------------------------------------- */
800 int pdkim_set_optional(pdkim_ctx *ctx,
806 unsigned long bodylength,
808 unsigned long created,
809 unsigned long expires) {
811 if (identity != NULL) {
812 ctx->sig->identity = malloc(strlen(identity)+1);
813 if (!ctx->sig->identity) {
814 return PDKIM_ERR_OOM;
816 strcpy(ctx->sig->identity, identity);
819 if (sign_headers != NULL) {
820 ctx->sig->sign_headers = malloc(strlen(sign_headers)+1);
821 if (!ctx->sig->sign_headers) {
822 return PDKIM_ERR_OOM;
824 strcpy(ctx->sig->sign_headers, sign_headers);
827 ctx->input_mode = input_mode;
828 ctx->sig->canon_headers = canon_headers;
829 ctx->sig->canon_body = canon_body;
830 ctx->sig->bodylength = bodylength;
831 ctx->sig->algo = algo;
832 ctx->sig->created = created;
833 ctx->sig->expires = expires;
841 /* -------------------------------------------------------------------------- */
842 void pdkim_free_sig(pdkim_signature *sig) {
844 pdkim_signature *next = (pdkim_signature *)sig->next;
846 pdkim_stringlist *e = sig->headers;
848 pdkim_stringlist *c = e;
849 if (e->value != NULL) free(e->value);
854 if (sig->sigdata != NULL) free(sig->sigdata);
855 if (sig->bodyhash != NULL) free(sig->bodyhash);
856 if (sig->selector != NULL) free(sig->selector);
857 if (sig->domain != NULL) free(sig->domain);
858 if (sig->identity != NULL) free(sig->identity);
859 if (sig->headernames != NULL) free(sig->headernames);
860 if (sig->copiedheaders != NULL) free(sig->copiedheaders);
861 if (sig->rsa_privkey != NULL) free(sig->rsa_privkey);
862 if (sig->sign_headers != NULL) free(sig->sign_headers);
865 if (next != NULL) pdkim_free_sig(next);
870 /* -------------------------------------------------------------------------- */
871 void pdkim_free_ctx(pdkim_ctx *ctx) {
873 pdkim_free_sig(ctx->sig);
874 pdkim_strfree(ctx->cur_header);