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