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