4b48664df1da3558268548ce2b5ead9f244e0a1d
[users/heiko/exim.git] / src / src / pdkim / pdkim.c
1 /*
2  *  PDKIM - a RFC4871 (DKIM) implementation
3  *
4  *  Copyright (C) 2009 - 2015  Tom Kistner <tom@duncanthrax.net>
5  *
6  *  http://duncanthrax.net/pdkim/
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
27
28 #include "../mytypes.h"
29 #include "pdkim.h"
30 #include "pdkim-rsa.h"
31
32 #include "polarssl/sha1.h"
33 #include "polarssl/sha2.h"
34 #include "polarssl/rsa.h"
35 #include "polarssl/base64.h"
36
37 #define PDKIM_SIGNATURE_VERSION     "1"
38 #define PDKIM_PUB_RECORD_VERSION    "DKIM1"
39
40 #define PDKIM_MAX_HEADER_LEN        65536
41 #define PDKIM_MAX_HEADERS           512
42 #define PDKIM_MAX_BODY_LINE_LEN     16384
43 #define PDKIM_DNS_TXT_MAX_NAMELEN   1024
44 #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
45                              "Message-ID:To:Cc:MIME-Version:Content-Type:"\
46                              "Content-Transfer-Encoding:Content-ID:"\
47                              "Content-Description:Resent-Date:Resent-From:"\
48                              "Resent-Sender:Resent-To:Resent-Cc:"\
49                              "Resent-Message-ID:In-Reply-To:References:"\
50                              "List-Id:List-Help:List-Unsubscribe:"\
51                              "List-Subscribe:List-Post:List-Owner:List-Archive"
52
53 /* -------------------------------------------------------------------------- */
54 struct pdkim_stringlist {
55   char *value;
56   int  tag;
57   void *next;
58 };
59
60 #define PDKIM_STR_ALLOC_FRAG 256
61 struct pdkim_str {
62   char         *str;
63   unsigned int  len;
64   unsigned int  allocated;
65 };
66
67 /* -------------------------------------------------------------------------- */
68 /* A bunch of list constants */
69 const char *pdkim_querymethods[] = {
70   "dns/txt",
71   NULL
72 };
73 const char *pdkim_algos[] = {
74   "rsa-sha256",
75   "rsa-sha1",
76   NULL
77 };
78 const char *pdkim_canons[] = {
79   "simple",
80   "relaxed",
81   NULL
82 };
83 const char *pdkim_hashes[] = {
84   "sha256",
85   "sha1",
86   NULL
87 };
88 const char *pdkim_keytypes[] = {
89   "rsa",
90   NULL
91 };
92
93 typedef struct pdkim_combined_canon_entry {
94   const char *str;
95   int canon_headers;
96   int canon_body;
97 } pdkim_combined_canon_entry;
98 pdkim_combined_canon_entry pdkim_combined_canons[] = {
99   { "simple/simple",    PDKIM_CANON_SIMPLE,   PDKIM_CANON_SIMPLE },
100   { "simple/relaxed",   PDKIM_CANON_SIMPLE,   PDKIM_CANON_RELAXED },
101   { "relaxed/simple",   PDKIM_CANON_RELAXED,  PDKIM_CANON_SIMPLE },
102   { "relaxed/relaxed",  PDKIM_CANON_RELAXED,  PDKIM_CANON_RELAXED },
103   { "simple",           PDKIM_CANON_SIMPLE,   PDKIM_CANON_SIMPLE },
104   { "relaxed",          PDKIM_CANON_RELAXED,  PDKIM_CANON_SIMPLE },
105   { NULL,               0,                    0 }
106 };
107
108
109 const char *pdkim_verify_status_str(int status) {
110   switch(status) {
111     case PDKIM_VERIFY_NONE:    return "PDKIM_VERIFY_NONE";
112     case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
113     case PDKIM_VERIFY_FAIL:    return "PDKIM_VERIFY_FAIL";
114     case PDKIM_VERIFY_PASS:    return "PDKIM_VERIFY_PASS";
115     default:                   return "PDKIM_VERIFY_UNKNOWN";
116   }
117 }
118 const char *pdkim_verify_ext_status_str(int ext_status) {
119   switch(ext_status) {
120     case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
121     case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
122     case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
123     case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
124     case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: return "PDKIM_VERIFY_INVALID_PUBKEY_PARSING";
125     default: return "PDKIM_VERIFY_UNKNOWN";
126   }
127 }
128
129
130 /* -------------------------------------------------------------------------- */
131 /* Print debugging functions */
132 #ifdef PDKIM_DEBUG
133 void
134 pdkim_quoteprint(FILE *stream, const char *data, int len, int lf)
135 {
136 int i;
137 const unsigned char *p = (const unsigned char *)data;
138
139 for (i = 0; i<len; i++)
140   {
141   const int c = p[i];
142   switch (c)
143     {
144     case ' ' : fprintf(stream,"{SP}"); break;
145     case '\t': fprintf(stream,"{TB}"); break;
146     case '\r': fprintf(stream,"{CR}"); break;
147     case '\n': fprintf(stream,"{LF}"); break;
148     case '{' : fprintf(stream,"{BO}"); break;
149     case '}' : fprintf(stream,"{BC}"); break;
150     default:
151       if ( (c < 32) || (c > 127) )
152         fprintf(stream,"{%02x}",c);
153       else
154         fputc(c,stream);
155       break;
156     }
157   }
158 if (lf)
159   fputc('\n',stream);
160 }
161
162 void
163 pdkim_hexprint(FILE *stream, const char *data, int len, int lf)
164 {
165 int i;
166 const unsigned char *p = (const unsigned char *)data;
167
168 for (i =0 ; i<len; i++)
169   {
170   const int c = p[i];
171   fprintf(stream,"%02x",c);
172   }
173 if (lf)
174   fputc('\n',stream);
175 }
176 #endif
177
178
179 /* -------------------------------------------------------------------------- */
180 /* Simple string list implementation for convinience */
181 pdkim_stringlist *
182 pdkim_append_stringlist(pdkim_stringlist *base, char *str)
183 {
184 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
185
186 if (!new_entry) return NULL;
187 memset(new_entry,0,sizeof(pdkim_stringlist));
188 if (!(new_entry->value = strdup(str))) return NULL;
189 if (base)
190   {
191   pdkim_stringlist *last = base;
192   while (last->next != NULL) { last = last->next; }
193   last->next = new_entry;
194   return base;
195   }
196 else
197   return new_entry;
198 }
199
200 pdkim_stringlist *
201 pdkim_prepend_stringlist(pdkim_stringlist *base, char *str)
202 {
203 pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
204
205 if (!new_entry) return NULL;
206 memset(new_entry,0,sizeof(pdkim_stringlist));
207 if (!(new_entry->value = strdup(str))) return NULL;
208 if (base)
209   new_entry->next = base;
210 return new_entry;
211 }
212
213
214 /* -------------------------------------------------------------------------- */
215 /* A small "growing string" implementation to escape malloc/realloc hell */
216
217 pdkim_str *
218 pdkim_strnew (const char *cstr)
219 {
220 unsigned int len = cstr ? strlen(cstr) : 0;
221 pdkim_str *p = malloc(sizeof(pdkim_str));
222
223 if (!p) return NULL;
224 memset(p,0,sizeof(pdkim_str));
225 if (!(p->str = malloc(len+1)))
226   {
227   free(p);
228   return NULL;
229   }
230 p->allocated = len+1;
231 p->len = len;
232 if (cstr)
233   strcpy(p->str,cstr);
234 else
235   p->str[p->len] = '\0';
236 return p;
237 }
238
239 char *
240 pdkim_strncat(pdkim_str *str, const char *data, int len)
241 {
242 if ((str->allocated - str->len) < (len+1))
243   {
244   /* Extend the buffer */
245   int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
246   char *n = realloc(str->str,
247                     (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
248   if (n == NULL) return NULL;
249   str->str = n;
250   str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
251   }
252 strncpy(&(str->str[str->len]), data, len);
253 str->len += len;
254 str->str[str->len] = '\0';
255 return str->str;
256 }
257
258 char *
259 pdkim_strcat(pdkim_str *str, const char *cstr)
260 {
261 return pdkim_strncat(str, cstr, strlen(cstr));
262 }
263
264 char *
265 pdkim_numcat(pdkim_str *str, unsigned long num)
266 {
267 char minibuf[20];
268 snprintf(minibuf,20,"%lu",num);
269 return pdkim_strcat(str,minibuf);
270 }
271
272 char *
273 pdkim_strtrim(pdkim_str *str)
274 {
275 char *p = str->str;
276 char *q = str->str;
277 while ( (*p != '\0') && ((*p == '\t') || (*p == ' ')) ) p++;
278 while (*p != '\0') {*q = *p; q++; p++;}
279 *q = '\0';
280 while ( (q != str->str) && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) )
281   {
282   *q = '\0';
283   q--;
284   }
285 str->len = strlen(str->str);
286 return str->str;
287 }
288
289 char *
290 pdkim_strclear(pdkim_str *str)
291 {
292 str->str[0] = '\0';
293 str->len = 0;
294 return str->str;
295 }
296
297 void
298 pdkim_strfree(pdkim_str *str)
299 {
300 if (!str) return;
301 if (str->str) free(str->str);
302 free(str);
303 }
304
305
306
307 /* -------------------------------------------------------------------------- */
308
309 void
310 pdkim_free_pubkey(pdkim_pubkey *pub)
311 {
312 if (pub)
313   {
314   if (pub->version    ) free(pub->version);
315   if (pub->granularity) free(pub->granularity);
316   if (pub->hashes     ) free(pub->hashes);
317   if (pub->keytype    ) free(pub->keytype);
318   if (pub->srvtype    ) free(pub->srvtype);
319   if (pub->notes      ) free(pub->notes);
320   if (pub->key        ) free(pub->key);
321   free(pub);
322   }
323 }
324
325
326 /* -------------------------------------------------------------------------- */
327
328 void
329 pdkim_free_sig(pdkim_signature *sig)
330 {
331 if (sig)
332   {
333   pdkim_signature *next = (pdkim_signature *)sig->next;
334
335   pdkim_stringlist *e = sig->headers;
336   while(e)
337     {
338     pdkim_stringlist *c = e;
339     if (e->value) free(e->value);
340     e = e->next;
341     free(c);
342     }
343
344   if (sig->sigdata         ) free(sig->sigdata);
345   if (sig->bodyhash        ) free(sig->bodyhash);
346   if (sig->selector        ) free(sig->selector);
347   if (sig->domain          ) free(sig->domain);
348   if (sig->identity        ) free(sig->identity);
349   if (sig->headernames     ) free(sig->headernames);
350   if (sig->copiedheaders   ) free(sig->copiedheaders);
351   if (sig->rsa_privkey     ) free(sig->rsa_privkey);
352   if (sig->sign_headers    ) free(sig->sign_headers);
353   if (sig->signature_header) free(sig->signature_header);
354   if (sig->sha1_body       ) free(sig->sha1_body);
355   if (sig->sha2_body       ) free(sig->sha2_body);
356
357   if (sig->pubkey) pdkim_free_pubkey(sig->pubkey);
358
359   free(sig);
360   if (next) pdkim_free_sig(next);
361   }
362 }
363
364
365 /* -------------------------------------------------------------------------- */
366
367 DLLEXPORT void
368 pdkim_free_ctx(pdkim_ctx *ctx)
369 {
370 if (ctx)
371   {
372   pdkim_stringlist *e = ctx->headers;
373   while(e)
374     {
375     pdkim_stringlist *c = e;
376     if (e->value) free(e->value);
377     e = e->next;
378     free(c);
379     }
380   pdkim_free_sig(ctx->sig);
381   pdkim_strfree(ctx->cur_header);
382   free(ctx);
383   }
384 }
385
386
387 /* -------------------------------------------------------------------------- */
388 /* Matches the name of the passed raw "header" against
389    the passed colon-separated "list", starting at entry
390    "start". Returns the position of the header name in
391    the list. */
392
393 int
394 header_name_match(const char *header,
395                       char       *tick,
396                       int         do_tick)
397 {
398 char *hname;
399 char *lcopy;
400 char *p;
401 char *q;
402 int rc = PDKIM_FAIL;
403
404 /* Get header name */
405 char *hcolon = strchr(header,':');
406
407 if (!hcolon) return rc; /* This isn't a header */
408
409 if (!(hname = malloc((hcolon-header)+1)))
410   return PDKIM_ERR_OOM;
411 memset(hname,0,(hcolon-header)+1);
412 strncpy(hname,header,(hcolon-header));
413
414 /* Copy tick-off list locally, so we can punch zeroes into it */
415 if (!(lcopy = strdup(tick)))
416   {
417   free(hname);
418   return PDKIM_ERR_OOM;
419   }
420 p = lcopy;
421 q = strchr(p,':');
422 while (q)
423   {
424   *q = '\0';
425
426   if (strcasecmp(p,hname) == 0)
427     {
428     rc = PDKIM_OK;
429     /* Invalidate header name instance in tick-off list */
430     if (do_tick) tick[p-lcopy] = '_';
431     goto BAIL;
432     }
433
434   p = q+1;
435   q = strchr(p,':');
436   }
437
438 if (strcasecmp(p,hname) == 0)
439   {
440   rc = PDKIM_OK;
441   /* Invalidate header name instance in tick-off list */
442   if (do_tick) tick[p-lcopy] = '_';
443   }
444
445 BAIL:
446 free(hname);
447 free(lcopy);
448 return rc;
449 }
450
451
452 /* -------------------------------------------------------------------------- */
453 /* Performs "relaxed" canonicalization of a header. The returned pointer needs
454    to be free()d. */
455
456 char *
457 pdkim_relax_header (char *header, int crlf)
458 {
459 BOOL past_field_name = FALSE;
460 BOOL seen_wsp = FALSE;
461 char *p;
462 char *q;
463 char *relaxed = malloc(strlen(header)+3);
464
465 if (!relaxed) return NULL;
466
467 q = relaxed;
468 for (p = header; *p != '\0'; p++)
469   {
470   int c = *p;
471   /* Ignore CR & LF */
472   if (c == '\r' || c == '\n')
473     continue;
474   if (c == '\t' || c == ' ')
475     {
476     if (seen_wsp)
477       continue;
478     c = ' ';                    /* Turns WSP into SP */
479     seen_wsp = TRUE;
480     }
481   else
482     if (!past_field_name && c == ':')
483       {
484       if (seen_wsp) q--;        /* This removes WSP before the colon */
485       seen_wsp = TRUE;          /* This removes WSP after the colon */
486       past_field_name = TRUE;
487       }
488     else
489       seen_wsp = FALSE;
490
491   /* Lowercase header name */
492   if (!past_field_name) c = tolower(c);
493   *q++ = c;
494   }
495
496 if (q > relaxed && q[-1] == ' ') q--; /* Squash eventual trailing SP */
497 *q = '\0';
498
499 if (crlf) strcat(relaxed,"\r\n");
500 return relaxed;
501 }
502
503
504 /* -------------------------------------------------------------------------- */
505 #define PDKIM_QP_ERROR_DECODE -1
506
507 char *
508 pdkim_decode_qp_char(char *qp_p, int *c)
509 {
510 char *initial_pos = qp_p;
511
512 /* Advance one char */
513 qp_p++;
514
515 /* Check for two hex digits and decode them */
516 if (isxdigit(*qp_p) && isxdigit(qp_p[1]))
517   {
518   /* Do hex conversion */
519   *c = (isdigit(*qp_p) ? *qp_p - '0' : toupper(*qp_p) - 'A' + 10) << 4;
520   *c != isdigit(qp_p[1]) ? qp_p[1] - '0' : toupper(qp_p[1]) - 'A' + 10;
521   return qp_p + 2;
522   }
523
524 /* Illegal char here */
525 *c = PDKIM_QP_ERROR_DECODE;
526 return initial_pos;
527 }
528
529
530 /* -------------------------------------------------------------------------- */
531
532 char *
533 pdkim_decode_qp(char *str)
534 {
535 int nchar = 0;
536 char *q;
537 char *p = str;
538 char *n = malloc(strlen(p)+1);
539
540 if (!n) return NULL;
541
542 *n = '\0';
543 q = n;
544 while (*p != '\0')
545   {
546   if (*p == '=')
547     {
548     p = pdkim_decode_qp_char(p, &nchar);
549     if (nchar >= 0)
550       {
551       *q++ = nchar;
552       continue;
553       }
554     }
555   else
556     *q++ = *p;
557   p++;
558   }
559 *q = '\0';
560 return n;
561 }
562
563
564 /* -------------------------------------------------------------------------- */
565
566 char *
567 pdkim_decode_base64(char *str, int *num_decoded)
568 {
569 int dlen = 0;
570 char *res;
571
572 base64_decode(NULL, &dlen, (unsigned char *)str, strlen(str));
573
574 if (!(res = malloc(dlen+1)))
575    return NULL;
576 if (base64_decode((unsigned char *)res, &dlen, (unsigned char *)str, strlen(str)) != 0)
577   {
578   free(res);
579   return NULL;
580   }
581
582 if (num_decoded) *num_decoded = dlen;
583 return res;
584 }
585
586
587 /* -------------------------------------------------------------------------- */
588
589 char *
590 pdkim_encode_base64(char *str, int num)
591 {
592 int dlen = 0;
593 char *res;
594
595 base64_encode(NULL, &dlen, (unsigned char *)str, num);
596
597 if (!(res = malloc(dlen+1)))
598   return NULL;
599 if (base64_encode((unsigned char *)res, &dlen, (unsigned char *)str, num) != 0)
600   {
601   free(res);
602   return NULL;
603   }
604 return res;
605 }
606
607
608 /* -------------------------------------------------------------------------- */
609 #define PDKIM_HDR_LIMBO 0
610 #define PDKIM_HDR_TAG   1
611 #define PDKIM_HDR_VALUE 2
612
613 pdkim_signature *
614 pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr)
615 {
616 pdkim_signature *sig ;
617 char *p,*q;
618 pdkim_str *cur_tag = NULL;
619 pdkim_str *cur_val = NULL;
620 BOOL past_hname = FALSE;
621 BOOL in_b_val = FALSE;
622 int where = PDKIM_HDR_LIMBO;
623 int i;
624
625 if (!(sig = malloc(sizeof(pdkim_signature)))) return NULL;
626 memset(sig,0,sizeof(pdkim_signature));
627 sig->bodylength = -1;
628
629 if (!(sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1)))
630   {
631   free(sig);
632   return NULL;
633   }
634
635 q = sig->rawsig_no_b_val;
636
637 for (p = raw_hdr; ; p++)
638   {
639   char c = *p;
640
641   /* Ignore FWS */
642   if (c == '\r' || c == '\n')
643     goto NEXT_CHAR;
644
645   /* Fast-forward through header name */
646   if (!past_hname)
647     {
648     if (c == ':') past_hname = TRUE;
649     goto NEXT_CHAR;
650     }
651
652   if (where == PDKIM_HDR_LIMBO)
653     {
654     /* In limbo, just wait for a tag-char to appear */
655     if (!(c >= 'a' && c <= 'z'))
656       goto NEXT_CHAR;
657
658     where = PDKIM_HDR_TAG;
659     }
660
661   if (where == PDKIM_HDR_TAG)
662     {
663     if (!cur_tag)
664       cur_tag = pdkim_strnew(NULL);
665
666     if (c >= 'a' && c <= 'z')
667       pdkim_strncat(cur_tag, p, 1);
668
669     if (c == '=')
670       {
671       if (strcmp(cur_tag->str, "b") == 0)
672         {
673         *q = '='; q++;
674         in_b_val = TRUE;
675         }
676       where = PDKIM_HDR_VALUE;
677       goto NEXT_CHAR;
678       }
679     }
680
681   if (where == PDKIM_HDR_VALUE)
682     {
683     if (!cur_val)
684       cur_val = pdkim_strnew(NULL);
685
686     if (c == '\r' || c == '\n' || c == ' ' || c == '\t')
687       goto NEXT_CHAR;
688
689     if (c == ';' || c == '\0')
690       {
691       if (cur_tag->len > 0)
692         {
693         pdkim_strtrim(cur_val);
694
695 #ifdef PDKIM_DEBUG
696         if (ctx->debug_stream)
697           fprintf(ctx->debug_stream, " %s=%s\n", cur_tag->str, cur_val->str);
698 #endif
699
700         switch (cur_tag->str[0])
701           {
702           case 'b':
703             if (cur_tag->str[1] == 'h')
704               sig->bodyhash = pdkim_decode_base64(cur_val->str,
705                   &sig->bodyhash_len);
706             else
707               sig->sigdata = pdkim_decode_base64(cur_val->str,
708                   &sig->sigdata_len);
709             break;
710           case 'v':
711               /* We only support version 1, and that is currently the
712                  only version there is. */
713             if (strcmp(cur_val->str, PDKIM_SIGNATURE_VERSION) == 0)
714               sig->version = 1;
715             break;
716           case 'a':
717             for (i = 0; pdkim_algos[i]; i++)
718               if (strcmp(cur_val->str, pdkim_algos[i]) == 0)
719                 {
720                 sig->algo = i;
721                 break;
722                 }
723             break;
724           case 'c':
725             for (i = 0; pdkim_combined_canons[i].str; i++)
726               if (strcmp(cur_val->str, pdkim_combined_canons[i].str) == 0)
727                 {
728                 sig->canon_headers = pdkim_combined_canons[i].canon_headers;
729                 sig->canon_body    = pdkim_combined_canons[i].canon_body;
730                 break;
731                 }
732             break;
733           case 'q':
734             for (i = 0; pdkim_querymethods[i]; i++)
735               if (strcmp(cur_val->str, pdkim_querymethods[i]) == 0)
736                 {
737                 sig->querymethod = i;
738                 break;
739                 }
740             break;
741           case 's':
742             sig->selector = strdup(cur_val->str); break;
743           case 'd':
744             sig->domain = strdup(cur_val->str); break;
745           case 'i':
746             sig->identity = pdkim_decode_qp(cur_val->str); break;
747           case 't':
748             sig->created = strtoul(cur_val->str, NULL, 10); break;
749           case 'x':
750             sig->expires = strtoul(cur_val->str, NULL, 10); break;
751           case 'l':
752             sig->bodylength = strtol(cur_val->str, NULL, 10); break;
753           case 'h':
754             sig->headernames = strdup(cur_val->str); break;
755           case 'z':
756             sig->copiedheaders = pdkim_decode_qp(cur_val->str); break;
757           default:
758 #ifdef PDKIM_DEBUG
759             if (ctx->debug_stream)
760               fprintf(ctx->debug_stream, " Unknown tag encountered\n");
761 #endif
762             break;
763           }
764         }
765       pdkim_strclear(cur_tag);
766       pdkim_strclear(cur_val);
767       in_b_val = FALSE;
768       where = PDKIM_HDR_LIMBO;
769       }
770     else
771       pdkim_strncat(cur_val, p, 1);
772     }
773
774 NEXT_CHAR:
775   if (c == '\0')
776     break;
777
778   if (!in_b_val)
779     *q++ = c;
780   }
781
782 /* Make sure the most important bits are there. */
783 if (!(sig->domain      && (*(sig->domain)      != '\0') &&
784       sig->selector    && (*(sig->selector)    != '\0') &&
785       sig->headernames && (*(sig->headernames) != '\0') &&
786       sig->bodyhash    &&
787       sig->sigdata     &&
788       sig->version))
789   {
790   pdkim_free_sig(sig);
791   return NULL;
792   }
793
794 *q = '\0';
795 /* Chomp raw header. The final newline must not be added to the signature. */
796 q--;
797 while (q > sig->rawsig_no_b_val  && (*q == '\r' || *q == '\n'))
798   *q = '\0'; q--;       /*XXX questionable code layout; possible bug */
799
800 #ifdef PDKIM_DEBUG
801 if (ctx->debug_stream)
802   {
803   fprintf(ctx->debug_stream,
804           "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
805   pdkim_quoteprint(ctx->debug_stream,
806                    sig->rawsig_no_b_val,
807                    strlen(sig->rawsig_no_b_val), 1);
808   fprintf(ctx->debug_stream,
809           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
810   }
811 #endif
812
813 if (  !(sig->sha1_body = malloc(sizeof(sha1_context)))
814    || !(sig->sha2_body = malloc(sizeof(sha2_context)))
815    )
816   {
817   pdkim_free_sig(sig);
818   return NULL;
819   }
820
821 sha1_starts(sig->sha1_body);
822 sha2_starts(sig->sha2_body, 0);
823
824 return sig;
825 }
826
827
828 /* -------------------------------------------------------------------------- */
829
830 pdkim_pubkey *
831 pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record)
832 {
833 pdkim_pubkey *pub;
834 char *p;
835 pdkim_str *cur_tag = NULL;
836 pdkim_str *cur_val = NULL;
837 int where = PDKIM_HDR_LIMBO;
838
839 if (!(pub = malloc(sizeof(pdkim_pubkey)))) return NULL;
840 memset(pub,0,sizeof(pdkim_pubkey));
841
842 for (p = raw_record; ; p++)
843   {
844   char c = *p;
845
846   /* Ignore FWS */
847   if (c == '\r' || c == '\n')
848     goto NEXT_CHAR;
849
850   if (where == PDKIM_HDR_LIMBO)
851     {
852     /* In limbo, just wait for a tag-char to appear */
853     if (!(c >= 'a' && c <= 'z'))
854       goto NEXT_CHAR;
855
856     where = PDKIM_HDR_TAG;
857     }
858
859   if (where == PDKIM_HDR_TAG)
860     {
861     if (!cur_tag)
862       cur_tag = pdkim_strnew(NULL);
863
864     if (c >= 'a' && c <= 'z')
865       pdkim_strncat(cur_tag, p, 1);
866
867     if (c == '=')
868       {
869       where = PDKIM_HDR_VALUE;
870       goto NEXT_CHAR;
871       }
872     }
873
874   if (where == PDKIM_HDR_VALUE)
875     {
876     if (!cur_val)
877       cur_val = pdkim_strnew(NULL);
878
879     if (c == '\r' || c == '\n')
880       goto NEXT_CHAR;
881
882     if (c == ';' || c == '\0')
883       {
884       if (cur_tag->len > 0)
885         {
886         pdkim_strtrim(cur_val);
887 #ifdef PDKIM_DEBUG
888         if (ctx->debug_stream)
889           fprintf(ctx->debug_stream, " %s=%s\n", cur_tag->str, cur_val->str);
890 #endif
891
892         switch (cur_tag->str[0])
893           {
894           case 'v':
895             /* This tag isn't evaluated because:
896                - We only support version DKIM1.
897                - Which is the default for this value (set below)
898                - Other versions are currently not specified.      */
899             break;
900           case 'h':
901             pub->hashes = strdup(cur_val->str); break;
902           case 'g':
903             pub->granularity = strdup(cur_val->str); break;
904           case 'n':
905             pub->notes = pdkim_decode_qp(cur_val->str); break;
906           case 'p':
907             pub->key = pdkim_decode_base64(cur_val->str, &(pub->key_len)); break;
908           case 'k':
909             pub->hashes = strdup(cur_val->str); break;
910           case 's':
911             pub->srvtype = strdup(cur_val->str); break;
912           case 't':
913             if (strchr(cur_val->str,'y') != NULL) pub->testing = 1;
914             if (strchr(cur_val->str,'s') != NULL) pub->no_subdomaining = 1;
915             break;
916           default:
917 #ifdef PDKIM_DEBUG
918             if (ctx->debug_stream)
919               fprintf(ctx->debug_stream, " Unknown tag encountered\n");
920 #endif
921             break;
922           }
923         }
924       pdkim_strclear(cur_tag);
925       pdkim_strclear(cur_val);
926       where = PDKIM_HDR_LIMBO;
927       }
928     else
929       pdkim_strncat(cur_val, p, 1);
930     }
931
932 NEXT_CHAR:
933   if (c == '\0') break;
934   }
935
936 /* Set fallback defaults */
937 if (!pub->version    ) pub->version     = strdup(PDKIM_PUB_RECORD_VERSION);
938 if (!pub->granularity) pub->granularity = strdup("*");
939 if (!pub->keytype    ) pub->keytype     = strdup("rsa");
940 if (!pub->srvtype    ) pub->srvtype     = strdup("*");
941
942 /* p= is required */
943 if (pub->key)
944   return pub;
945
946 pdkim_free_pubkey(pub);
947 return NULL;
948 }
949
950
951 /* -------------------------------------------------------------------------- */
952
953 int
954 pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len)
955 {
956 pdkim_signature *sig = ctx->sig;
957 /* Cache relaxed version of data */
958 char *relaxed_data = NULL;
959 int   relaxed_len  = 0;
960
961 /* Traverse all signatures, updating their hashes. */
962 while (sig)
963   {
964   /* Defaults to simple canon (no further treatment necessary) */
965   const char *canon_data = data;
966   int         canon_len = len;
967
968   if (sig->canon_body == PDKIM_CANON_RELAXED)
969     {
970     /* Relax the line if not done already */
971     if (!relaxed_data)
972       {
973       BOOL seen_wsp = FALSE;
974       const char *p;
975       int q = 0;
976
977       if (!(relaxed_data = malloc(len+1)))
978         return PDKIM_ERR_OOM;
979
980       for (p = data; *p; p++)
981         {
982         char c = *p;
983         if (c == '\r')
984           {
985           if (q > 0 && relaxed_data[q-1] == ' ')
986             q--;
987           }
988         else if (c == '\t' || c == ' ')
989           {
990           c = ' '; /* Turns WSP into SP */
991           if (seen_wsp)
992             continue;
993           seen_wsp = TRUE;
994           }
995         else
996           seen_wsp = FALSE;
997         relaxed_data[q++] = c;
998         }
999       relaxed_data[q] = '\0';
1000       relaxed_len = q;
1001       }
1002     canon_data = relaxed_data;
1003     canon_len  = relaxed_len;
1004     }
1005
1006   /* Make sure we don't exceed the to-be-signed body length */
1007   if (  sig->bodylength >= 0
1008      && sig->signed_body_bytes + (unsigned long)canon_len > sig->bodylength
1009      )
1010     canon_len = sig->bodylength - sig->signed_body_bytes;
1011
1012   if (canon_len > 0)
1013     {
1014     if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1015       sha1_update(sig->sha1_body,(unsigned char *)canon_data,canon_len);
1016     else
1017       sha2_update(sig->sha2_body,(unsigned char *)canon_data,canon_len);
1018
1019     sig->signed_body_bytes += canon_len;
1020 #ifdef PDKIM_DEBUG
1021     if (ctx->debug_stream)
1022       pdkim_quoteprint(ctx->debug_stream, canon_data, canon_len, 1);
1023 #endif
1024     }
1025
1026   sig = sig->next;
1027   }
1028
1029 if (relaxed_data) free(relaxed_data);
1030 return PDKIM_OK;
1031 }
1032
1033
1034 /* -------------------------------------------------------------------------- */
1035
1036 int
1037 pdkim_finish_bodyhash(pdkim_ctx *ctx)
1038 {
1039 pdkim_signature *sig = ctx->sig;
1040
1041 /* Traverse all signatures */
1042 while (sig)
1043   {                                     /* Finish hashes */
1044   unsigned char bh[32]; /* SHA-256 = 32 Bytes,  SHA-1 = 20 Bytes */
1045
1046   if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1047     sha1_finish(sig->sha1_body,bh);
1048   else
1049     sha2_finish(sig->sha2_body,bh);
1050
1051 #ifdef PDKIM_DEBUG
1052   if (ctx->debug_stream)
1053     {
1054     fprintf(ctx->debug_stream, "PDKIM [%s] Body bytes hashed: %lu\n",
1055       sig->domain, sig->signed_body_bytes);
1056     fprintf(ctx->debug_stream, "PDKIM [%s] bh  computed: ", sig->domain);
1057     pdkim_hexprint(ctx->debug_stream, (char *)bh,
1058                    (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
1059     }
1060 #endif
1061
1062   /* SIGNING -------------------------------------------------------------- */
1063   if (ctx->mode == PDKIM_MODE_SIGN)
1064     {
1065     sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
1066
1067     if (!(sig->bodyhash = malloc(sig->bodyhash_len)))
1068       return PDKIM_ERR_OOM;
1069     memcpy(sig->bodyhash, bh, sig->bodyhash_len);
1070
1071     /* If bodylength limit is set, and we have received less bytes
1072        than the requested amount, effectively remove the limit tag. */
1073     if (sig->signed_body_bytes < sig->bodylength)
1074       sig->bodylength = -1;
1075     }
1076
1077   /* VERIFICATION --------------------------------------------------------- */
1078   else
1079     {
1080     /* Compare bodyhash */
1081     if (memcmp(bh, sig->bodyhash,
1082                (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0)
1083       {
1084 #ifdef PDKIM_DEBUG
1085       if (ctx->debug_stream)
1086         fprintf(ctx->debug_stream, "PDKIM [%s] Body hash verified OK\n",
1087                 sig->domain);
1088 #endif
1089       }
1090     else
1091       {
1092 #ifdef PDKIM_DEBUG
1093       if (ctx->debug_stream)
1094         {
1095         fprintf(ctx->debug_stream, "PDKIM [%s] bh signature: ", sig->domain);
1096         pdkim_hexprint(ctx->debug_stream, sig->bodyhash,
1097                          (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
1098         fprintf(ctx->debug_stream, "PDKIM [%s] Body hash did NOT verify\n",
1099                 sig->domain);
1100         }
1101 #endif
1102       sig->verify_status     = PDKIM_VERIFY_FAIL;
1103       sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
1104       }
1105     }
1106
1107   sig = sig->next;
1108   }
1109
1110 return PDKIM_OK;
1111 }
1112
1113
1114
1115 /* -------------------------------------------------------------------------- */
1116 /* Callback from pdkim_feed below for processing complete body lines */
1117
1118 int
1119 pdkim_bodyline_complete(pdkim_ctx *ctx)
1120 {
1121 char *p = ctx->linebuf;
1122 int   n = ctx->linebuf_offset;
1123
1124 /* Ignore extra data if we've seen the end-of-data marker */
1125 if (ctx->seen_eod) goto BAIL;
1126
1127 /* We've always got one extra byte to stuff a zero ... */
1128 ctx->linebuf[(ctx->linebuf_offset)] = '\0';
1129
1130 if (ctx->input_mode == PDKIM_INPUT_SMTP)
1131   {
1132   /* Terminate on EOD marker */
1133   if (memcmp(p, ".\r\n", 3) == 0)
1134     {
1135     /* In simple body mode, if any empty lines were buffered,
1136     replace with one. rfc 4871 3.4.3 */
1137     if (  ctx->sig && ctx->sig->canon_body == PDKIM_CANON_SIMPLE
1138        && ctx->num_buffered_crlf > 0
1139        )
1140       pdkim_update_bodyhash(ctx, "\r\n",2);
1141
1142     ctx->seen_eod = 1;
1143     goto BAIL;
1144     }
1145   /* Unstuff dots */
1146   if (memcmp(p, "..", 2) == 0)
1147     {
1148     p++;
1149     n--;
1150     }
1151   }
1152
1153 /* Empty lines need to be buffered until we find a non-empty line */
1154 if (memcmp(p, "\r\n", 2) == 0)
1155   {
1156   ctx->num_buffered_crlf++;
1157   goto BAIL;
1158   }
1159
1160 if (  ctx->sig
1161    && ctx->sig->canon_body == PDKIM_CANON_RELAXED
1162    )
1163   {
1164   /* Lines with just spaces need to be buffered too */
1165   char *check = p;
1166   while (memcmp(check, "\r\n", 2) != 0)
1167     {
1168     char c = *check;
1169
1170     if (c != '\t' && c != ' ')
1171       goto PROCESS;
1172     check++;
1173     }
1174
1175   ctx->num_buffered_crlf++;
1176   goto BAIL;
1177 }
1178
1179 PROCESS:
1180 /* At this point, we have a non-empty line, so release the buffered ones. */
1181 while (ctx->num_buffered_crlf)
1182   {
1183   pdkim_update_bodyhash(ctx, "\r\n", 2);
1184   ctx->num_buffered_crlf--;
1185   }
1186
1187 pdkim_update_bodyhash(ctx, p, n);
1188
1189 BAIL:
1190 ctx->linebuf_offset = 0;
1191 return PDKIM_OK;
1192 }
1193
1194
1195 /* -------------------------------------------------------------------------- */
1196 /* Callback from pdkim_feed below for processing complete headers */
1197 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
1198
1199 int
1200 pdkim_header_complete(pdkim_ctx *ctx)
1201 {
1202 pdkim_signature *sig = ctx->sig;
1203
1204 /* Special case: The last header can have an extra \r appended */
1205 if ( (ctx->cur_header->len > 1) &&
1206      (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') )
1207   {
1208   ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
1209   ctx->cur_header->len--;
1210   }
1211
1212 ctx->num_headers++;
1213 if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
1214
1215 /* SIGNING -------------------------------------------------------------- */
1216 if (ctx->mode == PDKIM_MODE_SIGN)
1217   for ( ; sig; sig = sig->next)                 /* Traverse all signatures */
1218     if (header_name_match(ctx->cur_header->str,
1219                           sig->sign_headers?
1220                             sig->sign_headers:
1221                             PDKIM_DEFAULT_SIGN_HEADERS, 0) == PDKIM_OK)
1222       {
1223       pdkim_stringlist *list;
1224
1225       /* Add header to the signed headers list (in reverse order) */
1226       if (!(list = pdkim_prepend_stringlist(sig->headers,
1227                                     ctx->cur_header->str)))
1228         return PDKIM_ERR_OOM;
1229       sig->headers = list;
1230       }
1231
1232 /* DKIM-Signature: headers are added to the verification list */
1233 if (ctx->mode == PDKIM_MODE_VERIFY)
1234   {
1235   if (strncasecmp(ctx->cur_header->str,
1236                   DKIM_SIGNATURE_HEADERNAME,
1237                   strlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
1238     {
1239     pdkim_signature *new_sig;
1240
1241     /* Create and chain new signature block */
1242 #ifdef PDKIM_DEBUG
1243     if (ctx->debug_stream)
1244       fprintf(ctx->debug_stream,
1245         "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1246 #endif
1247
1248     if ((new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str)))
1249       {
1250       pdkim_signature *last_sig = ctx->sig;
1251       if (!last_sig)
1252         ctx->sig = new_sig;
1253       else
1254         {
1255         while (last_sig->next) last_sig = last_sig->next;
1256         last_sig->next = new_sig;
1257         }
1258       }
1259     else
1260 #ifdef PDKIM_DEBUG
1261       if (ctx->debug_stream)
1262         {
1263         fprintf(ctx->debug_stream,"Error while parsing signature header\n");
1264         fprintf(ctx->debug_stream,
1265           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1266         }
1267 #endif
1268     }
1269
1270   /* every other header is stored for signature verification */
1271   else
1272     {
1273     pdkim_stringlist *list;
1274
1275     if (!(list = pdkim_prepend_stringlist(ctx->headers,
1276                                     ctx->cur_header->str)))
1277       return PDKIM_ERR_OOM;
1278     ctx->headers = list;
1279     }
1280   }
1281
1282 BAIL:
1283 pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
1284 return PDKIM_OK;
1285 }
1286
1287
1288
1289 /* -------------------------------------------------------------------------- */
1290 #define HEADER_BUFFER_FRAG_SIZE 256
1291
1292 DLLEXPORT int
1293 pdkim_feed (pdkim_ctx *ctx, char *data, int len)
1294 {
1295 int p;
1296
1297 for (p = 0; p<len; p++)
1298   {
1299   char c = data[p];
1300
1301   if (ctx->past_headers)
1302     {
1303     /* Processing body byte */
1304     ctx->linebuf[(ctx->linebuf_offset)++] = c;
1305     if (c == '\n')
1306       {
1307       int rc = pdkim_bodyline_complete(ctx); /* End of line */
1308       if (rc != PDKIM_OK) return rc;
1309       }
1310     if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
1311       return PDKIM_ERR_LONG_LINE;
1312     }
1313   else
1314     {
1315     /* Processing header byte */
1316     if (c != '\r')
1317       {
1318       if (c == '\n')
1319         {
1320         if (ctx->seen_lf)
1321           {
1322           int rc = pdkim_header_complete(ctx); /* Seen last header line */
1323           if (rc != PDKIM_OK) return rc;
1324
1325           ctx->past_headers = 1;
1326           ctx->seen_lf = 0;
1327 #ifdef PDKIM_DEBUG
1328           if (ctx->debug_stream)
1329             fprintf(ctx->debug_stream,
1330               "PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1331 #endif
1332           continue;
1333           }
1334         else
1335           ctx->seen_lf = 1;
1336         }
1337       else if (ctx->seen_lf)
1338         {
1339         if (!(c == '\t' || c == ' '))
1340           {
1341           int rc = pdkim_header_complete(ctx); /* End of header */
1342           if (rc != PDKIM_OK) return rc;
1343           }
1344         ctx->seen_lf = 0;
1345         }
1346       }
1347
1348     if (!ctx->cur_header)
1349       if (!(ctx->cur_header = pdkim_strnew(NULL)))
1350         return PDKIM_ERR_OOM;
1351
1352     if (ctx->cur_header->len < PDKIM_MAX_HEADER_LEN)
1353       if (!pdkim_strncat(ctx->cur_header, &data[p], 1))
1354         return PDKIM_ERR_OOM;
1355     }
1356   }
1357 return PDKIM_OK;
1358 }
1359
1360 /*
1361  * RFC 5322 specifies that header line length SHOULD be no more than 78
1362  * lets make it so!
1363  *  pdkim_headcat
1364  * returns char*
1365  *
1366  * col: this int holds and receives column number (octets since last '\n')
1367  * str: partial string to append to
1368  * pad: padding, split line or space after before or after eg: ";"
1369  * intro: - must join to payload eg "h=", usually the tag name
1370  * payload: eg base64 data - long data can be split arbitrarily.
1371  *
1372  * this code doesn't fold the header in some of the places that RFC4871
1373  * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
1374  * pairs and inside long values. it also always spaces or breaks after the
1375  * "pad"
1376  *
1377  * no guarantees are made for output given out-of range input. like tag
1378  * names loinger than 78, or bogus col. Input is assumed to be free of line breaks.
1379  */
1380
1381 static char *
1382 pdkim_headcat(int *col, pdkim_str *str, const char * pad,
1383   const char *intro, const char *payload)
1384 {
1385 size_t l;
1386
1387 if (pad)
1388   {
1389   l = strlen(pad);
1390   if (*col + l > 78)
1391     {
1392     pdkim_strcat(str, "\r\n\t");
1393     *col = 1;
1394     }
1395   pdkim_strncat(str, pad, l);
1396   *col += l;
1397   }
1398
1399 l = (pad?1:0) + (intro?strlen(intro):0);
1400
1401 if (*col + l > 78)
1402   { /*can't fit intro - start a new line to make room.*/
1403   pdkim_strcat(str, "\r\n\t");
1404   *col = 1;
1405   l = intro?strlen(intro):0;
1406   }
1407
1408 l += payload ? strlen(payload):0 ;
1409
1410 while (l>77)
1411   { /* this fragment will not fit on a single line */
1412   if (pad)
1413     {
1414     pdkim_strcat(str, " ");
1415     *col += 1;
1416     pad = NULL; /* only want this once */
1417     l--;
1418     }
1419
1420   if (intro)
1421     {
1422     size_t sl = strlen(intro);
1423
1424     pdkim_strncat(str, intro,sl);
1425     *col += sl;
1426     l -= sl;
1427     intro = NULL; /* only want this once */
1428     }
1429
1430   if (payload)
1431     {
1432     size_t sl = strlen(payload);
1433     size_t chomp = *col+sl < 77 ? sl : 78-*col;
1434
1435     pdkim_strncat(str, payload,chomp);
1436     *col += chomp;
1437     payload += chomp;
1438     l -= chomp-1;
1439     }
1440
1441   /* the while precondition tells us it didn't fit. */
1442   pdkim_strcat(str, "\r\n\t");
1443   *col = 1;
1444   }
1445
1446 if (*col + l > 78)
1447   {
1448   pdkim_strcat(str, "\r\n\t");
1449   *col = 1;
1450   pad = NULL;
1451   }
1452
1453 if (pad)
1454   {
1455   pdkim_strcat(str, " ");
1456   *col += 1;
1457   pad = NULL;
1458   }
1459
1460 if (intro)
1461   {
1462   size_t sl = strlen(intro);
1463
1464   pdkim_strncat(str, intro, sl);
1465   *col += sl;
1466   l -= sl;
1467   intro = NULL;
1468   }
1469
1470 if (payload)
1471   {
1472   size_t sl = strlen(payload);
1473
1474   pdkim_strncat(str, payload, sl);
1475   *col += sl;
1476   }
1477
1478 return str->str;
1479 }
1480
1481
1482 /* -------------------------------------------------------------------------- */
1483
1484 char *
1485 pdkim_create_header(pdkim_signature *sig, int final)
1486 {
1487 char *rc = NULL;
1488 char *base64_bh = NULL;
1489 char *base64_b  = NULL;
1490 int col = 0;
1491 pdkim_str *hdr;
1492 pdkim_str *canon_all;
1493
1494 if (!(hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION)))
1495   return NULL;
1496
1497 if (!(canon_all = pdkim_strnew(pdkim_canons[sig->canon_headers])))
1498   goto BAIL;
1499
1500 if (!(base64_bh = pdkim_encode_base64(sig->bodyhash, sig->bodyhash_len)))
1501   goto BAIL;
1502
1503 col = strlen(hdr->str);
1504
1505 /* Required and static bits */
1506 if (
1507       pdkim_headcat(&col,hdr,";","a=",pdkim_algos[sig->algo]) &&
1508       pdkim_headcat(&col,hdr,";","q=",pdkim_querymethods[sig->querymethod])  &&
1509         pdkim_strcat(canon_all,"/")                           &&
1510         pdkim_strcat(canon_all,pdkim_canons[sig->canon_body]) &&
1511       pdkim_headcat(&col,hdr,";","c=",canon_all->str)         &&
1512       pdkim_headcat(&col,hdr,";","d=",sig->domain)            &&
1513       pdkim_headcat(&col,hdr,";","s=",sig->selector)
1514    )
1515   {
1516   /* list of eader names can be split between items. */
1517     {
1518     char *n = strdup(sig->headernames);
1519     char *f = n;
1520     char *i = "h=";
1521     char *s = ";";
1522
1523     if (!n) goto BAIL;
1524     while (*n)
1525       {
1526       char *c = strchr(n,':');
1527
1528       if (c) *c ='\0';
1529
1530       if (!i)
1531         if (!pdkim_headcat(&col,hdr,NULL,NULL,":"))
1532           {
1533           free(f);
1534           goto BAIL;
1535           }
1536
1537       if (!pdkim_headcat(&col,hdr,s,i,n))
1538         {
1539         free(f);
1540         goto BAIL;
1541         }
1542
1543       if (!c)
1544         break;
1545
1546       n = c+1;
1547       s = NULL;
1548       i = NULL;
1549       }
1550     free(f);
1551     }
1552
1553   if(!pdkim_headcat(&col, hdr, ";", "bh=", base64_bh))
1554     goto BAIL;
1555
1556   /* Optional bits */
1557   if (sig->identity)
1558     if(!pdkim_headcat(&col, hdr, ";", "i=", sig->identity))
1559       goto BAIL;
1560
1561   if (sig->created > 0)
1562     {
1563     char minibuf[20];
1564
1565     snprintf(minibuf,20,"%lu",sig->created);
1566     if(!pdkim_headcat(&col, hdr, ";", "t=", minibuf))
1567       goto BAIL;
1568   }
1569
1570   if (sig->expires > 0)
1571     {
1572     char minibuf[20];
1573
1574     snprintf(minibuf,20,"%lu",sig->expires);
1575     if(!pdkim_headcat(&col, hdr, ";", "x=", minibuf))
1576       goto BAIL;
1577     }
1578
1579   if (sig->bodylength >= 0)
1580     {
1581     char minibuf[20];
1582
1583     snprintf(minibuf,20,"%lu",sig->bodylength);
1584     if(!pdkim_headcat(&col, hdr, ";", "l=", minibuf))
1585       goto BAIL;
1586     }
1587
1588   /* Preliminary or final version? */
1589   if (final)
1590     {
1591     if (!(base64_b = pdkim_encode_base64(sig->sigdata, sig->sigdata_len)))
1592       goto BAIL;
1593     if (!pdkim_headcat(&col, hdr, ";", "b=", base64_b))
1594       goto BAIL;
1595   }
1596   else 
1597     if(!pdkim_headcat(&col, hdr, ";", "b=", ""))
1598       goto BAIL;
1599
1600   /* add trailing semicolon: I'm not sure if this is actually needed */
1601   if (!pdkim_headcat(&col,hdr,NULL,";",""))
1602     goto BAIL;
1603   }
1604
1605 rc = strdup(hdr->str);
1606
1607 BAIL:
1608 pdkim_strfree(hdr);
1609 if (canon_all) pdkim_strfree(canon_all);
1610 if (base64_bh) free(base64_bh);
1611 if (base64_b ) free(base64_b);
1612 return rc;
1613 }
1614
1615
1616 /* -------------------------------------------------------------------------- */
1617
1618 DLLEXPORT int
1619 pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures)
1620 {
1621 pdkim_signature *sig = ctx->sig;
1622 pdkim_str *headernames = NULL;             /* Collected signed header names */
1623
1624 /* Check if we must still flush a (partial) header. If that is the
1625    case, the message has no body, and we must compute a body hash
1626    out of '<CR><LF>' */
1627 if (ctx->cur_header && ctx->cur_header->len)
1628   {
1629   int rc = pdkim_header_complete(ctx);
1630   if (rc != PDKIM_OK) return rc;
1631   pdkim_update_bodyhash(ctx, "\r\n", 2);
1632   }
1633 else
1634   {
1635   /* For non-smtp input, check if there's an unfinished line in the
1636      body line buffer. If that is the case, we must add a CRLF to the
1637      hash to properly terminate the message. */
1638   if ((ctx->input_mode == PDKIM_INPUT_NORMAL) && ctx->linebuf_offset)
1639     {
1640     pdkim_update_bodyhash(ctx, ctx->linebuf, ctx->linebuf_offset);
1641     pdkim_update_bodyhash(ctx, "\r\n", 2);
1642     }
1643 #ifdef PDKIM_DEBUG
1644   if (ctx->debug_stream)
1645     fprintf(ctx->debug_stream,
1646       "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1647 #endif
1648   }
1649
1650 /* Build (and/or evaluate) body hash */
1651 if (pdkim_finish_bodyhash(ctx) != PDKIM_OK)
1652   return PDKIM_ERR_OOM;
1653
1654 /* SIGNING -------------------------------------------------------------- */
1655 if (ctx->mode == PDKIM_MODE_SIGN)
1656   if (!(headernames = pdkim_strnew(NULL)))
1657     return PDKIM_ERR_OOM;
1658 /* ---------------------------------------------------------------------- */
1659
1660 while (sig)
1661   {
1662   sha1_context sha1_headers;
1663   sha2_context sha2_headers;
1664   char *sig_hdr;
1665   char headerhash[32];
1666
1667   if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1668     sha1_starts(&sha1_headers);
1669   else
1670     sha2_starts(&sha2_headers,0);
1671
1672 #ifdef PDKIM_DEBUG
1673   if (ctx->debug_stream)
1674     fprintf(ctx->debug_stream,
1675             "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1676 #endif
1677
1678   /* SIGNING ---------------------------------------------------------------- */
1679   /* When signing, walk through our header list and add them to the hash. As we
1680      go, construct a list of the header's names to use for the h= parameter. */
1681
1682   if (ctx->mode == PDKIM_MODE_SIGN)
1683     {
1684     pdkim_stringlist *p;
1685
1686     for (p = sig->headers; p; p = p->next)
1687       {
1688       char *rh = NULL;
1689       /* Collect header names (Note: colon presence is guaranteed here) */
1690       char *q = strchr(p->value,':');
1691
1692       if (!(pdkim_strncat(headernames, p->value,
1693                         (q-(p->value)) + (p->next ? 1 : 0))))
1694         return PDKIM_ERR_OOM;
1695
1696       rh = sig->canon_headers == PDKIM_CANON_RELAXED
1697         ? pdkim_relax_header(p->value,1) /* cook header for relaxed canon */
1698         : strdup(p->value);              /* just copy it for simple canon */
1699       if (!rh)
1700         return PDKIM_ERR_OOM;
1701
1702       /* Feed header to the hash algorithm */
1703       if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1704         sha1_update(&(sha1_headers), (unsigned char *)rh, strlen(rh));
1705       else
1706         sha2_update(&(sha2_headers), (unsigned char *)rh, strlen(rh));
1707
1708 #ifdef PDKIM_DEBUG
1709       if (ctx->debug_stream)
1710         pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
1711 #endif
1712       free(rh);
1713       }
1714     }
1715
1716   /* VERIFICATION ----------------------------------------------------------- */
1717   /* When verifying, walk through the header name list in the h= parameter and
1718      add the headers to the hash in that order. */
1719   else
1720     {
1721     char *b = strdup(sig->headernames);
1722     char *p = b;
1723     char *q = NULL;
1724     pdkim_stringlist *hdrs;
1725
1726     if (!b) return PDKIM_ERR_OOM;
1727
1728     /* clear tags */
1729     for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1730       hdrs->tag = 0;
1731
1732     while(1)
1733       {
1734       if ((q = strchr(p,':')))
1735         *q = '\0';
1736
1737       for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
1738         if (  hdrs->tag == 0
1739            && strncasecmp(hdrs->value,p,strlen(p)) == 0
1740            && (hdrs->value)[strlen(p)] == ':'
1741            )
1742           {
1743           char *rh;
1744
1745           rh = sig->canon_headers == PDKIM_CANON_RELAXED
1746             ? pdkim_relax_header(hdrs->value,1)  /* cook header for relaxed canon */
1747             : strdup(hdrs->value);               /* just copy it for simple canon */
1748           if (!rh)
1749             return PDKIM_ERR_OOM;
1750
1751           /* Feed header to the hash algorithm */
1752           if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1753             sha1_update(&(sha1_headers), (unsigned char *)rh, strlen(rh));
1754           else
1755             sha2_update(&(sha2_headers), (unsigned char *)rh, strlen(rh));
1756
1757 #ifdef PDKIM_DEBUG
1758           if (ctx->debug_stream)
1759             pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
1760 #endif
1761           free(rh);
1762           hdrs->tag = 1;
1763           break;
1764           }
1765
1766       if (!q) break;
1767       p = q+1;
1768       }
1769     free(b);
1770     }
1771
1772 #ifdef PDKIM_DEBUG
1773   if (ctx->debug_stream)
1774     fprintf(ctx->debug_stream,
1775             "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1776 #endif
1777
1778   /* SIGNING ---------------------------------------------------------------- */
1779   if (ctx->mode == PDKIM_MODE_SIGN)
1780     {
1781     /* Copy headernames to signature struct */
1782     sig->headernames = strdup(headernames->str);
1783     pdkim_strfree(headernames);
1784
1785     /* Create signature header with b= omitted */
1786     sig_hdr = pdkim_create_header(ctx->sig, 0);
1787     }
1788
1789   /* VERIFICATION ----------------------------------------------------------- */
1790   else
1791     sig_hdr = strdup(sig->rawsig_no_b_val);
1792   /* ------------------------------------------------------------------------ */
1793
1794   if (!sig_hdr)
1795     return PDKIM_ERR_OOM;
1796
1797   /* Relax header if necessary */
1798   if (sig->canon_headers == PDKIM_CANON_RELAXED)
1799     {
1800     char *relaxed_hdr = pdkim_relax_header(sig_hdr, 0);
1801
1802     free(sig_hdr);
1803     if (!relaxed_hdr)
1804       return PDKIM_ERR_OOM;
1805     sig_hdr = relaxed_hdr;
1806     }
1807
1808 #ifdef PDKIM_DEBUG
1809   if (ctx->debug_stream)
1810     {
1811     fprintf(ctx->debug_stream,
1812             "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1813     pdkim_quoteprint(ctx->debug_stream, sig_hdr, strlen(sig_hdr), 1);
1814     fprintf(ctx->debug_stream,
1815             "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1816     }
1817 #endif
1818
1819   /* Finalize header hash */
1820   if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1821     {
1822     sha1_update(&(sha1_headers), (unsigned char *)sig_hdr, strlen(sig_hdr));
1823     sha1_finish(&(sha1_headers), (unsigned char *)headerhash);
1824
1825 #ifdef PDKIM_DEBUG
1826     if (ctx->debug_stream)
1827       {
1828       fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
1829       pdkim_hexprint(ctx->debug_stream, headerhash, 20, 1);
1830       }
1831 #endif
1832     }
1833   else
1834     {
1835     sha2_update(&(sha2_headers), (unsigned char *)sig_hdr, strlen(sig_hdr));
1836     sha2_finish(&(sha2_headers), (unsigned char *)headerhash);
1837
1838 #ifdef PDKIM_DEBUG
1839     if (ctx->debug_stream)
1840       {
1841       fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
1842       pdkim_hexprint(ctx->debug_stream, headerhash, 32, 1);
1843       }
1844 #endif
1845     }
1846
1847   free(sig_hdr);
1848
1849   /* SIGNING ---------------------------------------------------------------- */
1850   if (ctx->mode == PDKIM_MODE_SIGN)
1851     {
1852     rsa_context rsa;
1853
1854     rsa_init(&rsa, RSA_PKCS_V15, 0);
1855
1856     /* Perform private key operation */
1857     if (rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
1858                       strlen(sig->rsa_privkey), NULL, 0) != 0)
1859       return PDKIM_ERR_RSA_PRIVKEY;
1860
1861     sig->sigdata_len = mpi_size(&(rsa.N));
1862     if (!(sig->sigdata = malloc(sig->sigdata_len)))
1863       return PDKIM_ERR_OOM;
1864
1865     if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
1866                         ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
1867                            SIG_RSA_SHA1:SIG_RSA_SHA256),
1868                         0,
1869                         (unsigned char *)headerhash,
1870                         (unsigned char *)sig->sigdata ) != 0)
1871       return PDKIM_ERR_RSA_SIGNING;
1872
1873     rsa_free(&rsa);
1874
1875 #ifdef PDKIM_DEBUG
1876     if (ctx->debug_stream)
1877       {
1878       fprintf(ctx->debug_stream, "PDKIM [%s] b computed: ", sig->domain);
1879       pdkim_hexprint(ctx->debug_stream, sig->sigdata, sig->sigdata_len, 1);
1880       }
1881 #endif
1882
1883     if (!(sig->signature_header = pdkim_create_header(ctx->sig,1)))
1884       return PDKIM_ERR_OOM;
1885     }
1886
1887   /* VERIFICATION ----------------------------------------------------------- */
1888   else
1889     {
1890     rsa_context rsa;
1891     char *dns_txt_name, *dns_txt_reply;
1892
1893     rsa_init(&rsa, RSA_PKCS_V15, 0);
1894
1895     if (!(dns_txt_name  = malloc(PDKIM_DNS_TXT_MAX_NAMELEN)))
1896       return PDKIM_ERR_OOM;
1897
1898     if (!(dns_txt_reply = malloc(PDKIM_DNS_TXT_MAX_RECLEN)))
1899       {
1900       free(dns_txt_name);
1901       return PDKIM_ERR_OOM;
1902       }
1903
1904     memset(dns_txt_reply, 0, PDKIM_DNS_TXT_MAX_RECLEN);
1905     memset(dns_txt_name , 0, PDKIM_DNS_TXT_MAX_NAMELEN);
1906
1907     if (snprintf(dns_txt_name,PDKIM_DNS_TXT_MAX_NAMELEN,
1908                  "%s._domainkey.%s.",
1909                  sig->selector,sig->domain) >= PDKIM_DNS_TXT_MAX_NAMELEN)
1910       {
1911       sig->verify_status =      PDKIM_VERIFY_INVALID;
1912       sig->verify_ext_status =  PDKIM_VERIFY_INVALID_BUFFER_SIZE;
1913       goto NEXT_VERIFY;
1914       }
1915
1916     if (  ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK 
1917        || dns_txt_reply[0] == '\0')
1918       {
1919       sig->verify_status =      PDKIM_VERIFY_INVALID;
1920       sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1921       goto NEXT_VERIFY;
1922       }
1923
1924 #ifdef PDKIM_DEBUG
1925     if (ctx->debug_stream)
1926       {
1927       fprintf(ctx->debug_stream,
1928               "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1929       fprintf(ctx->debug_stream," Raw record: ");
1930       pdkim_quoteprint(ctx->debug_stream, dns_txt_reply, strlen(dns_txt_reply), 1);
1931       }
1932 #endif
1933
1934     if (!(sig->pubkey = pdkim_parse_pubkey_record(ctx,dns_txt_reply)))
1935       {
1936       sig->verify_status =      PDKIM_VERIFY_INVALID;
1937       sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
1938
1939 #ifdef PDKIM_DEBUG
1940       if (ctx->debug_stream)
1941         {
1942         fprintf(ctx->debug_stream," Error while parsing public key record\n");
1943         fprintf(ctx->debug_stream,
1944           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1945         }
1946 #endif
1947       goto NEXT_VERIFY;
1948       }
1949
1950 #ifdef PDKIM_DEBUG
1951     if (ctx->debug_stream)
1952       fprintf(ctx->debug_stream,
1953         "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1954 #endif
1955
1956     if (rsa_parse_public_key(&rsa,
1957                             (unsigned char *)sig->pubkey->key,
1958                              sig->pubkey->key_len) != 0)
1959       {
1960       sig->verify_status =      PDKIM_VERIFY_INVALID;
1961       sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
1962       goto NEXT_VERIFY;
1963       }
1964
1965     /* Check the signature */
1966     if (rsa_pkcs1_verify(&rsa,
1967                       RSA_PUBLIC,
1968                       ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
1969                            SIG_RSA_SHA1:SIG_RSA_SHA256),
1970                       0,
1971                       (unsigned char *)headerhash,
1972                       (unsigned char *)sig->sigdata) != 0)
1973       {
1974       sig->verify_status =      PDKIM_VERIFY_FAIL;
1975       sig->verify_ext_status =  PDKIM_VERIFY_FAIL_MESSAGE;
1976       goto NEXT_VERIFY;
1977       }
1978
1979     /* We have a winner! (if bodydhash was correct earlier) */
1980     if (sig->verify_status == PDKIM_VERIFY_NONE)
1981       sig->verify_status = PDKIM_VERIFY_PASS;
1982
1983 NEXT_VERIFY:
1984
1985 #ifdef PDKIM_DEBUG
1986     if (ctx->debug_stream)
1987       {
1988       fprintf(ctx->debug_stream, "PDKIM [%s] signature status: %s",
1989               sig->domain, pdkim_verify_status_str(sig->verify_status));
1990       if (sig->verify_ext_status > 0)
1991         fprintf(ctx->debug_stream, " (%s)\n",
1992                 pdkim_verify_ext_status_str(sig->verify_ext_status));
1993       else
1994         fprintf(ctx->debug_stream, "\n");
1995       }
1996 #endif
1997
1998     rsa_free(&rsa);
1999     free(dns_txt_name);
2000     free(dns_txt_reply);
2001     }
2002
2003   sig = sig->next;
2004   }
2005
2006 /* If requested, set return pointer to signature(s) */
2007 if (return_signatures)
2008   *return_signatures = ctx->sig;
2009
2010 return PDKIM_OK;
2011 }
2012
2013
2014 /* -------------------------------------------------------------------------- */
2015
2016 DLLEXPORT pdkim_ctx *
2017 pdkim_init_verify(int input_mode, int(*dns_txt_callback)(char *, char *))
2018 {
2019 pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
2020
2021 if (!ctx)
2022   return NULL;
2023 memset(ctx,0,sizeof(pdkim_ctx));
2024
2025 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
2026   {
2027   free(ctx);
2028   return NULL;
2029   }
2030
2031 ctx->mode = PDKIM_MODE_VERIFY;
2032 ctx->input_mode = input_mode;
2033 ctx->dns_txt_callback = dns_txt_callback;
2034
2035 return ctx;
2036 }
2037
2038
2039 /* -------------------------------------------------------------------------- */
2040
2041 DLLEXPORT pdkim_ctx *
2042 pdkim_init_sign(int input_mode, char *domain, char *selector, char *rsa_privkey)
2043 {
2044 pdkim_ctx *ctx;
2045 pdkim_signature *sig;
2046
2047 if (!domain || !selector || !rsa_privkey)
2048   return NULL;
2049
2050 if (!(ctx = malloc(sizeof(pdkim_ctx))))
2051   return NULL;
2052 memset(ctx,0,sizeof(pdkim_ctx));
2053
2054 if (!(ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN)))
2055   {
2056   free(ctx);
2057   return NULL;
2058   }
2059
2060 if (!(sig = malloc(sizeof(pdkim_signature))))
2061   {
2062   free(ctx->linebuf);
2063   free(ctx);
2064   return NULL;
2065   }
2066 memset(sig,0,sizeof(pdkim_signature));
2067
2068 sig->bodylength = -1;
2069
2070 ctx->mode = PDKIM_MODE_SIGN;
2071 ctx->input_mode = input_mode;
2072 ctx->sig = sig;
2073
2074 ctx->sig->domain = strdup(domain);
2075 ctx->sig->selector = strdup(selector);
2076 ctx->sig->rsa_privkey = strdup(rsa_privkey);
2077
2078 if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey)
2079   goto BAIL;
2080
2081 if (!(ctx->sig->sha1_body = malloc(sizeof(sha1_context))))
2082   goto BAIL;
2083 sha1_starts(ctx->sig->sha1_body);
2084
2085 if (!(ctx->sig->sha2_body = malloc(sizeof(sha2_context))))
2086   goto BAIL;
2087 sha2_starts(ctx->sig->sha2_body,0);
2088
2089 return ctx;
2090
2091 BAIL:
2092   pdkim_free_ctx(ctx);
2093   return NULL;
2094 }
2095
2096 /* -------------------------------------------------------------------------- */
2097
2098 DLLEXPORT int
2099 pdkim_set_optional(pdkim_ctx *ctx,
2100                        char *sign_headers,
2101                        char *identity,
2102                        int canon_headers,
2103                        int canon_body,
2104                        long bodylength,
2105                        int algo,
2106                        unsigned long created,
2107                        unsigned long expires)
2108 {
2109
2110 if (identity)
2111   if (!(ctx->sig->identity = strdup(identity)))
2112     return PDKIM_ERR_OOM;
2113
2114 if (sign_headers)
2115   if (!(ctx->sig->sign_headers = strdup(sign_headers)))
2116     return PDKIM_ERR_OOM;
2117
2118 ctx->sig->canon_headers = canon_headers;
2119 ctx->sig->canon_body = canon_body;
2120 ctx->sig->bodylength = bodylength;
2121 ctx->sig->algo = algo;
2122 ctx->sig->created = created;
2123 ctx->sig->expires = expires;
2124
2125 return PDKIM_OK;
2126 }
2127
2128 /* -------------------------------------------------------------------------- */
2129
2130 #ifdef PDKIM_DEBUG
2131 DLLEXPORT void
2132 pdkim_set_debug_stream(pdkim_ctx *ctx, FILE *debug_stream)
2133 {
2134 ctx->debug_stream = debug_stream;
2135 }
2136 #endif
2137