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