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