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