968a9f6c7ff6b28d6911ff018ed8bcbeb98213d8
[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.10 2009/04/09 14:47:50 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 (1) {
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') || (*p == ' ') || (*p == '\t') )
543         goto NEXT_CHAR;
544
545       if ( (*p == ';') || (*p == '\0') ) {
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     if (*p == '\0') break;
644
645     if (!in_b_val) {
646       *q = *p;
647       q++;
648     }
649     p++;
650   }
651
652   /* Make sure the most important bits are there. */
653   if (!(sig->domain      && (*(sig->domain)      != '\0') &&
654         sig->selector    && (*(sig->selector)    != '\0') &&
655         sig->headernames && (*(sig->headernames) != '\0') &&
656         sig->bodyhash    &&
657         sig->sigdata     &&
658         sig->version)) {
659     pdkim_free_sig(sig);
660     return NULL;
661   }
662
663   *q = '\0';
664   /* Chomp raw header. The final newline must not be added to the signature. */
665   q--;
666   while( (q > sig->rawsig_no_b_val) && ((*q == '\r') || (*q == '\n')) ) {
667     *q = '\0'; q--;
668   }
669
670   #ifdef PDKIM_DEBUG
671   if (ctx->debug_stream) {
672     fprintf(ctx->debug_stream,
673             "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
674     pdkim_quoteprint(ctx->debug_stream,
675                      sig->rawsig_no_b_val,
676                      strlen(sig->rawsig_no_b_val), 1);
677     fprintf(ctx->debug_stream,
678             "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
679   }
680   #endif
681
682   sig->sha1_body = malloc(sizeof(sha1_context));
683   if (sig->sha1_body == NULL) {
684     pdkim_free_sig(sig);
685     return NULL;
686   }
687   sig->sha2_body = malloc(sizeof(sha2_context));
688   if (sig->sha2_body == NULL) {
689     pdkim_free_sig(sig);
690     return NULL;
691   }
692
693   sha1_starts(sig->sha1_body);
694   sha2_starts(sig->sha2_body,0);
695
696   return sig;
697 }
698
699
700 /* -------------------------------------------------------------------------- */
701 pdkim_pubkey *pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record) {
702   pdkim_pubkey *pub ;
703   char *p;
704   pdkim_str *cur_tag = NULL;
705   pdkim_str *cur_val = NULL;
706   int where = PDKIM_HDR_LIMBO;
707
708   pub = malloc(sizeof(pdkim_pubkey));
709   if (pub == NULL) return NULL;
710   memset(pub,0,sizeof(pdkim_pubkey));
711
712   p = raw_record;
713
714   while (1) {
715
716     /* Ignore FWS */
717     if ( (*p == '\r') || (*p == '\n') )
718       goto NEXT_CHAR;
719
720     if (where == PDKIM_HDR_LIMBO) {
721       /* In limbo, just wait for a tag-char to appear */
722       if (!((*p >= 'a') && (*p <= 'z')))
723         goto NEXT_CHAR;
724
725       where = PDKIM_HDR_TAG;
726     }
727
728     if (where == PDKIM_HDR_TAG) {
729       if (cur_tag == NULL)
730         cur_tag = pdkim_strnew(NULL);
731
732       if ((*p >= 'a') && (*p <= 'z'))
733         pdkim_strncat(cur_tag,p,1);
734
735       if (*p == '=') {
736         where = PDKIM_HDR_VALUE;
737         goto NEXT_CHAR;
738       }
739     }
740
741     if (where == PDKIM_HDR_VALUE) {
742       if (cur_val == NULL)
743         cur_val = pdkim_strnew(NULL);
744
745       if ( (*p == '\r') || (*p == '\n') )
746         goto NEXT_CHAR;
747
748       if ( (*p == ';') || (*p == '\0') ) {
749         if (cur_tag->len > 0) {
750           pdkim_strtrim(cur_val);
751           #ifdef PDKIM_DEBUG
752           if (ctx->debug_stream)
753             fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str);
754           #endif
755           switch (cur_tag->str[0]) {
756             case 'v':
757               /* This tag isn't evaluated because:
758                  - We only support version DKIM1.
759                  - Which is the default for this value (set below)
760                  - Other versions are currently not specified.      */
761             break;
762             case 'h':
763               pub->hashes = strdup(cur_val->str);
764             break;
765             case 'g':
766               pub->granularity = strdup(cur_val->str);
767             break;
768             case 'n':
769               pub->notes = pdkim_decode_qp(cur_val->str);
770             break;
771             case 'p':
772               pub->key = pdkim_decode_base64(cur_val->str,&(pub->key_len));
773             break;
774             case 'k':
775               pub->hashes = strdup(cur_val->str);
776             break;
777             case 's':
778               pub->srvtype = strdup(cur_val->str);
779             break;
780             case 't':
781               if (strchr(cur_val->str,'t') != NULL) pub->testing = 1;
782               if (strchr(cur_val->str,'s') != NULL) pub->no_subdomaining = 1;
783             break;
784             default:
785               #ifdef PDKIM_DEBUG
786               if (ctx->debug_stream)
787                 fprintf(ctx->debug_stream, "Unknown tag encountered\n");
788               #endif
789             break;
790           }
791         }
792         pdkim_strclear(cur_tag);
793         pdkim_strclear(cur_val);
794         where = PDKIM_HDR_LIMBO;
795         goto NEXT_CHAR;
796       }
797       else pdkim_strncat(cur_val,p,1);
798     }
799
800     NEXT_CHAR:
801     if (*p == '\0') break;
802     p++;
803   }
804
805   /* Set fallback defaults */
806   if (pub->version     == NULL) pub->version     = strdup(PDKIM_PUB_RECORD_VERSION);
807   if (pub->granularity == NULL) pub->granularity = strdup("*");
808   if (pub->keytype     == NULL) pub->keytype     = strdup("rsa");
809   if (pub->srvtype     == NULL) pub->srvtype     = strdup("*");
810
811   /* p= is required */
812   if (pub->key == NULL) {
813     pdkim_free_pubkey(pub);
814     return NULL;
815   }
816
817   return pub;
818 }
819
820
821 /* -------------------------------------------------------------------------- */
822 int pdkim_update_bodyhash(pdkim_ctx *ctx, char *data, int len) {
823   pdkim_signature *sig = ctx->sig;
824   /* Cache relaxed version of data */
825   char *relaxed_data = NULL;
826   int   relaxed_len  = 0;
827
828   /* Traverse all signatures, updating their hashes. */
829   while (sig != NULL) {
830     /* Defaults to simple canon (no further treatment necessary) */
831     char *canon_data = data;
832     int   canon_len = len;
833
834     if (sig->canon_body == PDKIM_CANON_RELAXED) {
835       /* Relax the line if not done already */
836       if (relaxed_data == NULL) {
837         int seen_wsp = 0;
838         char *p = data;
839         int q = 0;
840         relaxed_data = malloc(len+1);
841         if (relaxed_data == NULL) return PDKIM_ERR_OOM;
842         while (*p != '\0') {
843           char c = *p;
844           if ( (c == '\t') || (c == ' ') ) {
845             c = ' '; /* Turns WSP into SP */
846             if (seen_wsp) {
847               p++;
848               continue;
849             }
850             else seen_wsp = 1;
851           }
852           else seen_wsp = 0;
853           relaxed_data[q++] = c;
854           p++;
855         }
856         relaxed_data[q] = '\0';
857         relaxed_len = q;
858       }
859       canon_data = relaxed_data;
860       canon_len  = relaxed_len;
861     }
862
863     /* Make sure we don't exceed the to-be-signed body length */
864     if ((sig->bodylength >= 0) &&
865         ((sig->signed_body_bytes+(unsigned long)canon_len) > sig->bodylength))
866       canon_len = (sig->bodylength - sig->signed_body_bytes);
867
868     if (canon_len > 0) {
869       if (sig->algo == PDKIM_ALGO_RSA_SHA1)
870         sha1_update(sig->sha1_body,(unsigned char *)canon_data,canon_len);
871       else
872         sha2_update(sig->sha2_body,(unsigned char *)canon_data,canon_len);
873       sig->signed_body_bytes += canon_len;
874 #ifdef PDKIM_DEBUG
875       if (ctx->debug_stream!=NULL)
876         pdkim_quoteprint(ctx->debug_stream,canon_data,canon_len,0);
877 #endif
878     }
879
880     sig = sig->next;
881   }
882
883   if (relaxed_data != NULL) free(relaxed_data);
884   return PDKIM_OK;
885 };
886
887
888 /* -------------------------------------------------------------------------- */
889 int pdkim_finish_bodyhash(pdkim_ctx *ctx) {
890   pdkim_signature *sig = ctx->sig;
891
892   /* Traverse all signatures */
893   while (sig != NULL) {
894
895     /* Finish hashes */
896     unsigned char bh[32]; /* SHA-256 = 32 Bytes,  SHA-1 = 20 Bytes */
897     if (sig->algo == PDKIM_ALGO_RSA_SHA1)
898       sha1_finish(sig->sha1_body,bh);
899     else
900       sha2_finish(sig->sha2_body,bh);
901
902     #ifdef PDKIM_DEBUG
903     if (ctx->debug_stream) {
904       fprintf(ctx->debug_stream, "PDKIM [%s] Body bytes hashed: %lu\n",
905         sig->domain, sig->signed_body_bytes);
906       fprintf(ctx->debug_stream, "PDKIM [%s] bh  computed: ", sig->domain);
907       pdkim_hexprint(ctx->debug_stream, (char *)bh,
908                      (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
909     }
910     #endif
911
912     /* SIGNING -------------------------------------------------------------- */
913     if (ctx->mode == PDKIM_MODE_SIGN) {
914       sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
915       sig->bodyhash = malloc(sig->bodyhash_len);
916       if (sig->bodyhash == NULL) return PDKIM_ERR_OOM;
917       memcpy(sig->bodyhash,bh,sig->bodyhash_len);
918
919       /* If bodylength limit is set, and we have received less bytes
920          than the requested amount, effectively remove the limit tag. */
921       if (sig->signed_body_bytes < sig->bodylength) sig->bodylength = -1;
922     }
923     /* VERIFICATION --------------------------------------------------------- */
924     else {
925       /* Compare bodyhash */
926       if (memcmp(bh,sig->bodyhash,
927                  (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0) {
928         #ifdef PDKIM_DEBUG
929         if (ctx->debug_stream)
930           fprintf(ctx->debug_stream, "PDKIM [%s] Body hash verified OK\n",
931                   sig->domain);
932         #endif
933       }
934       else {
935         #ifdef PDKIM_DEBUG
936         if (ctx->debug_stream) {
937           fprintf(ctx->debug_stream, "PDKIM [%s] Body hash did NOT verify\n",
938                   sig->domain);
939           fprintf(ctx->debug_stream, "PDKIM [%s] bh signature: ", sig->domain);
940           pdkim_hexprint(ctx->debug_stream, sig->bodyhash,
941                            (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
942         }
943         #endif
944         sig->verify_status     = PDKIM_VERIFY_FAIL;
945         sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
946       }
947     }
948
949     sig = sig->next;
950   }
951
952   return PDKIM_OK;
953 };
954
955
956
957 /* -------------------------------------------------------------------------- */
958 /* Callback from pdkim_feed below for processing complete body lines */
959 int pdkim_bodyline_complete(pdkim_ctx *ctx) {
960   char *p = ctx->linebuf;
961   int   n = ctx->linebuf_offset;
962
963   /* Ignore extra data if we've seen the end-of-data marker */
964   if (ctx->seen_eod) goto BAIL;
965
966   /* We've always got one extra byte to stuff a zero ... */
967   ctx->linebuf[(ctx->linebuf_offset)] = '\0';
968
969   if (ctx->input_mode == PDKIM_INPUT_SMTP) {
970     /* Terminate on EOD marker */
971     if (memcmp(p,".\r\n",3) == 0) {
972       ctx->seen_eod = 1;
973       goto BAIL;
974     }
975     /* Unstuff dots */
976     if (memcmp(p,"..",2) == 0) {
977       p++;
978       n--;
979     }
980   }
981
982   /* Empty lines need to be buffered until we find a non-empty line */
983   if (memcmp(p,"\r\n",2) == 0) {
984     ctx->num_buffered_crlf++;
985     goto BAIL;
986   }
987
988   /* At this point, we have a non-empty line, so release the buffered ones. */
989   while (ctx->num_buffered_crlf) {
990     pdkim_update_bodyhash(ctx,"\r\n",2);
991     ctx->num_buffered_crlf--;
992   }
993
994   pdkim_update_bodyhash(ctx,p,n);
995
996   BAIL:
997   ctx->linebuf_offset = 0;
998   return PDKIM_OK;
999 }
1000
1001
1002 /* -------------------------------------------------------------------------- */
1003 /* Callback from pdkim_feed below for processing complete headers */
1004 #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
1005 int pdkim_header_complete(pdkim_ctx *ctx) {
1006   pdkim_signature *sig = ctx->sig;
1007
1008   /* Special case: The last header can have an extra \r appended */
1009   if ( (ctx->cur_header->len > 1) &&
1010        (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') ) {
1011     ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
1012     ctx->cur_header->len--;
1013   }
1014
1015   ctx->num_headers++;
1016   if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
1017
1018   /* Traverse all signatures */
1019   while (sig != NULL) {
1020     pdkim_stringlist *list;
1021
1022     /* SIGNING -------------------------------------------------------------- */
1023     if (ctx->mode == PDKIM_MODE_SIGN) {
1024       if (header_name_match(ctx->cur_header->str,
1025                             sig->sign_headers?
1026                               sig->sign_headers:
1027                               PDKIM_DEFAULT_SIGN_HEADERS, 0) < 0) goto NEXT_SIG;
1028     }
1029     /* VERIFICATION --------------------------------------------------------- */
1030     else {
1031       int rc = header_name_match(ctx->cur_header->str,
1032                                  sig->headernames,
1033                                  sig->headernames_pos);
1034       /* Header is not included or out-of-sequence */
1035       if (rc < 0) goto NEXT_SIG;
1036       sig->headernames_pos = rc;
1037     }
1038
1039     /* Add header to the signed headers list */
1040     list = pdkim_append_stringlist(sig->headers,
1041                                    ctx->cur_header->str);
1042     if (list == NULL) return PDKIM_ERR_OOM;
1043     sig->headers = list;
1044
1045     NEXT_SIG:
1046     sig = sig->next;
1047   }
1048
1049   /* DKIM-Signature: headers are added to the verification list */
1050   if ( (ctx->mode == PDKIM_MODE_VERIFY) &&
1051        (strncasecmp(ctx->cur_header->str,
1052                     DKIM_SIGNATURE_HEADERNAME,
1053                     strlen(DKIM_SIGNATURE_HEADERNAME)) == 0) ) {
1054      pdkim_signature *new_sig;
1055     /* Create and chain new signature block */
1056     #ifdef PDKIM_DEBUG
1057     if (ctx->debug_stream)
1058       fprintf(ctx->debug_stream,
1059         "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1060     #endif
1061     new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str);
1062     if (new_sig != NULL) {
1063       pdkim_signature *last_sig = ctx->sig;
1064       if (last_sig == NULL) {
1065         ctx->sig = new_sig;
1066       }
1067       else {
1068         while (last_sig->next != NULL) { last_sig = last_sig->next; };
1069         last_sig->next = new_sig;
1070       }
1071     }
1072     else {
1073       #ifdef PDKIM_DEBUG
1074       if (ctx->debug_stream) {
1075         fprintf(ctx->debug_stream,"Error while parsing signature header\n");
1076         fprintf(ctx->debug_stream,
1077           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1078       }
1079       #endif
1080     }
1081   }
1082
1083   BAIL:
1084   pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
1085   return PDKIM_OK;
1086 };
1087
1088
1089
1090 /* -------------------------------------------------------------------------- */
1091 #define HEADER_BUFFER_FRAG_SIZE 256
1092 DLLEXPORT int pdkim_feed (pdkim_ctx *ctx,
1093                 char *data,
1094                 int   len) {
1095   int p;
1096   for (p=0;p<len;p++) {
1097     char c = data[p];
1098     if (ctx->past_headers) {
1099       /* Processing body byte */
1100       ctx->linebuf[(ctx->linebuf_offset)++] = c;
1101       if (c == '\n') {
1102         int rc = pdkim_bodyline_complete(ctx); /* End of line */
1103         if (rc != PDKIM_OK) return rc;
1104       }
1105       if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
1106         return PDKIM_ERR_LONG_LINE;
1107     }
1108     else {
1109       /* Processing header byte */
1110       if (c != '\r') {
1111         if (c == '\n') {
1112           if (ctx->seen_lf) {
1113             int rc = pdkim_header_complete(ctx); /* Seen last header line */
1114             if (rc != PDKIM_OK) return rc;
1115             ctx->past_headers = 1;
1116             ctx->seen_lf = 0;
1117 #ifdef PDKIM_DEBUG
1118             if (ctx->debug_stream)
1119               fprintf(ctx->debug_stream,
1120                 "PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1121 #endif
1122             continue;
1123           }
1124           else ctx->seen_lf = 1;
1125         }
1126         else if (ctx->seen_lf) {
1127           if (! ((c == '\t') || (c == ' '))) {
1128             int rc = pdkim_header_complete(ctx); /* End of header */
1129             if (rc != PDKIM_OK) return rc;
1130           }
1131           ctx->seen_lf = 0;
1132         }
1133       }
1134       if (ctx->cur_header == NULL) {
1135         ctx->cur_header = pdkim_strnew(NULL);
1136         if (ctx->cur_header == NULL) return PDKIM_ERR_OOM;
1137       }
1138       if (ctx->cur_header->len < PDKIM_MAX_HEADER_LEN)
1139         if (pdkim_strncat(ctx->cur_header,&data[p],1) == NULL)
1140           return PDKIM_ERR_OOM;
1141     }
1142   }
1143   return PDKIM_OK;
1144 };
1145
1146
1147 /* -------------------------------------------------------------------------- */
1148 char *pdkim_create_header(pdkim_signature *sig, int final) {
1149   char *rc = NULL;
1150   char *base64_bh = NULL;
1151   char *base64_b  = NULL;
1152   pdkim_str *hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
1153   if (hdr == NULL) return NULL;
1154
1155   base64_bh = pdkim_encode_base64(sig->bodyhash, sig->bodyhash_len);
1156   if (base64_bh == NULL) goto BAIL;
1157
1158   /* Required and static bits */
1159   if (
1160         pdkim_strcat(hdr,"; a=")                                &&
1161         pdkim_strcat(hdr,pdkim_algos[sig->algo])                &&
1162         pdkim_strcat(hdr,"; q=")                                &&
1163         pdkim_strcat(hdr,pdkim_querymethods[sig->querymethod])  &&
1164         pdkim_strcat(hdr,"; c=")                                &&
1165         pdkim_strcat(hdr,pdkim_canons[sig->canon_headers])      &&
1166         pdkim_strcat(hdr,"/")                                   &&
1167         pdkim_strcat(hdr,pdkim_canons[sig->canon_body])         &&
1168         pdkim_strcat(hdr,"; d=")                                &&
1169         pdkim_strcat(hdr,sig->domain)                           &&
1170         pdkim_strcat(hdr,"; s=")                                &&
1171         pdkim_strcat(hdr,sig->selector)                         &&
1172         pdkim_strcat(hdr,";\r\n\th=")                           &&
1173         pdkim_strcat(hdr,sig->headernames)                      &&
1174         pdkim_strcat(hdr,"; bh=")                               &&
1175         pdkim_strcat(hdr,base64_bh)                             &&
1176         pdkim_strcat(hdr,";\r\n\t")
1177      ) {
1178     /* Optional bits */
1179     if (sig->identity != NULL) {
1180       if (!( pdkim_strcat(hdr,"i=")                             &&
1181              pdkim_strcat(hdr,sig->identity)                    &&
1182              pdkim_strcat(hdr,";") ) ) {
1183         goto BAIL;
1184       }
1185     }
1186     if (sig->created > 0) {
1187       if (!( pdkim_strcat(hdr,"t=")                             &&
1188              pdkim_numcat(hdr,sig->created)                     &&
1189              pdkim_strcat(hdr,";") ) ) {
1190         goto BAIL;
1191       }
1192     }
1193     if (sig->expires > 0) {
1194       if (!( pdkim_strcat(hdr,"x=")                             &&
1195              pdkim_numcat(hdr,sig->expires)                     &&
1196              pdkim_strcat(hdr,";") ) ) {
1197         goto BAIL;
1198       }
1199     }
1200     if (sig->bodylength >= 0) {
1201       if (!( pdkim_strcat(hdr,"l=")                             &&
1202              pdkim_numcat(hdr,sig->bodylength)                  &&
1203              pdkim_strcat(hdr,";") ) ) {
1204         goto BAIL;
1205       }
1206     }
1207     /* Extra linebreak */
1208     if (hdr->str[(hdr->len)-1] == ';') {
1209       if (!pdkim_strcat(hdr," \r\n\t")) goto BAIL;
1210     }
1211     /* Preliminary or final version? */
1212     if (final) {
1213       base64_b = pdkim_encode_base64(sig->sigdata, sig->sigdata_len);
1214       if (base64_b == NULL) goto BAIL;
1215       if (
1216             pdkim_strcat(hdr,"b=")                              &&
1217             pdkim_strcat(hdr,base64_b)                          &&
1218             pdkim_strcat(hdr,";")
1219          ) goto DONE;
1220     }
1221     else {
1222       if (pdkim_strcat(hdr,"b=;")) goto DONE;
1223     }
1224
1225     goto BAIL;
1226   }
1227
1228   DONE:
1229   rc = strdup(hdr->str);
1230
1231   BAIL:
1232   pdkim_strfree(hdr);
1233   if (base64_bh != NULL) free(base64_bh);
1234   if (base64_b  != NULL) free(base64_b);
1235   return rc;
1236 }
1237
1238
1239 /* -------------------------------------------------------------------------- */
1240 DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures) {
1241   pdkim_signature *sig = ctx->sig;
1242   pdkim_str *headernames = NULL;             /* Collected signed header names */
1243
1244   /* Check if we must still flush a (partial) header. If that is the
1245      case, the message has no body, and we must compute a body hash
1246      out of '<CR><LF>' */
1247   if (ctx->cur_header->len) {
1248     int rc = pdkim_header_complete(ctx);
1249     if (rc != PDKIM_OK) return rc;
1250     pdkim_update_bodyhash(ctx,"\r\n",2);
1251   }
1252   else {
1253     /* For non-smtp input, check if there's an unfinished line in the
1254        body line buffer. If that is the case, we must add a CRLF to the
1255        hash to properly terminate the message. */
1256     if ((ctx->input_mode == PDKIM_INPUT_NORMAL) && ctx->linebuf_offset) {
1257       pdkim_update_bodyhash(ctx, ctx->linebuf, ctx->linebuf_offset);
1258       pdkim_update_bodyhash(ctx,"\r\n",2);
1259     }
1260     #ifdef PDKIM_DEBUG
1261     if (ctx->debug_stream)
1262       fprintf(ctx->debug_stream,
1263         "\nPDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1264     #endif
1265   }
1266
1267   /* Build (and/or evaluate) body hash */
1268   if (pdkim_finish_bodyhash(ctx) != PDKIM_OK) return PDKIM_ERR_OOM;
1269
1270   /* SIGNING -------------------------------------------------------------- */
1271   if (ctx->mode == PDKIM_MODE_SIGN) {
1272     headernames = pdkim_strnew(NULL);
1273     if (headernames == NULL) return PDKIM_ERR_OOM;
1274   }
1275   /* ---------------------------------------------------------------------- */
1276
1277   while (sig != NULL) {
1278     sha1_context sha1_headers;
1279     sha2_context sha2_headers;
1280     pdkim_stringlist *p = sig->headers;
1281     char *sig_hdr;
1282     char headerhash[32];
1283
1284     if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1285       sha1_starts(&sha1_headers);
1286     else
1287       sha2_starts(&sha2_headers,0);
1288
1289     #ifdef PDKIM_DEBUG
1290     if (ctx->debug_stream)
1291       fprintf(ctx->debug_stream,
1292               "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
1293     #endif
1294
1295     while (p != NULL) {
1296       char *rh;
1297
1298       /* SIGNING -------------------------------------------------------------- */
1299       if (ctx->mode == PDKIM_MODE_SIGN) {
1300         /* Collect header names (Note: colon presence is guaranteed here) */
1301         char *q = strchr(p->value,':');
1302         if (pdkim_strncat(headernames, p->value,
1303                           (q-(p->value))+((p->next==NULL)?0:1)) == NULL)
1304           return PDKIM_ERR_OOM;
1305       }
1306       /* ---------------------------------------------------------------------- */
1307
1308       if (sig->canon_body == PDKIM_CANON_RELAXED)
1309         rh = pdkim_relax_header(p->value,1); /* cook header for relaxed canon */
1310       else
1311         rh = strdup(p->value);               /* just copy it for simple canon */
1312
1313       if (rh == NULL) return PDKIM_ERR_OOM;
1314
1315       /* Feed header to the hash algorithm */
1316       if (sig->algo == PDKIM_ALGO_RSA_SHA1)
1317         sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh));
1318       else
1319         sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh));
1320       #ifdef PDKIM_DEBUG
1321       if (ctx->debug_stream)
1322         pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
1323       #endif
1324       free(rh);
1325       p = p->next;
1326     }
1327
1328     #ifdef PDKIM_DEBUG
1329     if (ctx->debug_stream)
1330       fprintf(ctx->debug_stream,
1331               "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1332     #endif
1333
1334
1335     /* SIGNING ---------------------------------------------------------------- */
1336     if (ctx->mode == PDKIM_MODE_SIGN) {
1337       /* Copy headernames to signature struct */
1338       sig->headernames = strdup(headernames->str);
1339       pdkim_strfree(headernames);
1340
1341       /* Create signature header with b= omitted */
1342       sig_hdr = pdkim_create_header(ctx->sig,0);
1343     }
1344     /* VERIFICATION ----------------------------------------------------------- */
1345     else {
1346       sig_hdr = strdup(sig->rawsig_no_b_val);
1347     }
1348     /* ------------------------------------------------------------------------ */
1349
1350     if (sig_hdr == NULL) return PDKIM_ERR_OOM;
1351
1352     /* Relax header if necessary */
1353     if (sig->canon_headers == PDKIM_CANON_RELAXED) {
1354       char *relaxed_hdr = pdkim_relax_header(sig_hdr,0);
1355       free(sig_hdr);
1356       if (relaxed_hdr == NULL) return PDKIM_ERR_OOM;
1357       sig_hdr = relaxed_hdr;
1358     }
1359
1360     #ifdef PDKIM_DEBUG
1361     if (ctx->debug_stream) {
1362       fprintf(ctx->debug_stream,
1363               "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
1364       pdkim_quoteprint(ctx->debug_stream, sig_hdr, strlen(sig_hdr), 1);
1365       fprintf(ctx->debug_stream,
1366               "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1367     }
1368     #endif
1369
1370     /* Finalize header hash */
1371     if (sig->algo == PDKIM_ALGO_RSA_SHA1) {
1372       sha1_update(&(sha1_headers),(unsigned char *)sig_hdr,strlen(sig_hdr));
1373       sha1_finish(&(sha1_headers),(unsigned char *)headerhash);
1374       fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
1375       pdkim_hexprint(ctx->debug_stream, headerhash, 20, 1);
1376     }
1377     else {
1378       sha2_update(&(sha2_headers),(unsigned char *)sig_hdr,strlen(sig_hdr));
1379       sha2_finish(&(sha2_headers),(unsigned char *)headerhash);
1380       fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
1381       pdkim_hexprint(ctx->debug_stream, headerhash, 32, 1);
1382     }
1383
1384     free(sig_hdr);
1385
1386     /* SIGNING ---------------------------------------------------------------- */
1387     if (ctx->mode == PDKIM_MODE_SIGN) {
1388       rsa_context rsa;
1389
1390       rsa_init(&rsa,RSA_PKCS_V15,0,NULL,NULL);
1391
1392       /* Perform private key operation */
1393       if (rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
1394                         strlen(sig->rsa_privkey), NULL, 0) != 0) {
1395         return PDKIM_ERR_RSA_PRIVKEY;
1396       }
1397
1398       sig->sigdata_len = mpi_size(&(rsa.N));
1399       sig->sigdata = malloc(sig->sigdata_len);
1400       if (sig->sigdata == NULL) return PDKIM_ERR_OOM;
1401
1402       if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
1403                           ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
1404                              RSA_SHA1:RSA_SHA256),
1405                           0,
1406                           (unsigned char *)headerhash,
1407                           (unsigned char *)sig->sigdata ) != 0) {
1408         return PDKIM_ERR_RSA_SIGNING;
1409       }
1410
1411       rsa_free(&rsa);
1412
1413       #ifdef PDKIM_DEBUG
1414       if (ctx->debug_stream) {
1415         fprintf(ctx->debug_stream, "PDKIM [%s] b computed: ",
1416                 sig->domain);
1417         pdkim_hexprint(ctx->debug_stream, sig->sigdata, sig->sigdata_len, 1);
1418       }
1419       #endif
1420
1421       sig->signature_header = pdkim_create_header(ctx->sig,1);
1422       if (sig->signature_header == NULL) return PDKIM_ERR_OOM;
1423     }
1424     /* VERIFICATION ----------------------------------------------------------- */
1425     else {
1426       rsa_context rsa;
1427       char *dns_txt_name, *dns_txt_reply;
1428
1429       rsa_init(&rsa,RSA_PKCS_V15,0,NULL,NULL);
1430
1431       dns_txt_name  = malloc(PDKIM_DNS_TXT_MAX_NAMELEN);
1432       if (dns_txt_name == NULL) return PDKIM_ERR_OOM;
1433       dns_txt_reply = malloc(PDKIM_DNS_TXT_MAX_RECLEN);
1434       if (dns_txt_reply == NULL) {
1435         free(dns_txt_name);
1436         return PDKIM_ERR_OOM;
1437       }
1438       memset(dns_txt_reply,0,PDKIM_DNS_TXT_MAX_RECLEN);
1439       memset(dns_txt_name ,0,PDKIM_DNS_TXT_MAX_NAMELEN);
1440
1441       if (snprintf(dns_txt_name,PDKIM_DNS_TXT_MAX_NAMELEN,
1442                    "%s._domainkey.%s.",
1443                    sig->selector,sig->domain) >= PDKIM_DNS_TXT_MAX_NAMELEN) {
1444         sig->verify_status =      PDKIM_VERIFY_INVALID;
1445         sig->verify_ext_status =  PDKIM_VERIFY_INVALID_BUFFER_SIZE;
1446         goto NEXT_VERIFY;
1447       };
1448
1449       if ((ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK) ||
1450           (dns_txt_reply[0] == '\0')) {
1451         sig->verify_status =      PDKIM_VERIFY_INVALID;
1452         sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
1453         goto NEXT_VERIFY;
1454       }
1455
1456       #ifdef PDKIM_DEBUG
1457       if (ctx->debug_stream) {
1458         fprintf(ctx->debug_stream,
1459                 "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
1460         fprintf(ctx->debug_stream,"Raw record: ");
1461         pdkim_quoteprint(ctx->debug_stream, dns_txt_reply, strlen(dns_txt_reply), 1);
1462       }
1463       #endif
1464
1465       sig->pubkey = pdkim_parse_pubkey_record(ctx,dns_txt_reply);
1466       if (sig->pubkey == NULL) {
1467         sig->verify_status =      PDKIM_VERIFY_INVALID;
1468         sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
1469         #ifdef PDKIM_DEBUG
1470         if (ctx->debug_stream) {
1471           fprintf(ctx->debug_stream,"Error while parsing public key record\n");
1472           fprintf(ctx->debug_stream,
1473             "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1474         }
1475         #endif
1476         goto NEXT_VERIFY;
1477       }
1478
1479       #ifdef PDKIM_DEBUG
1480       if (ctx->debug_stream) {
1481         fprintf(ctx->debug_stream,
1482           "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
1483       }
1484       #endif
1485
1486       if (rsa_parse_public_key(&rsa,
1487                               (unsigned char *)sig->pubkey->key,
1488                                sig->pubkey->key_len) != 0) {
1489         sig->verify_status =      PDKIM_VERIFY_INVALID;
1490         sig->verify_ext_status =  PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
1491         goto NEXT_VERIFY;
1492       }
1493
1494       /* Check the signature */
1495       if (rsa_pkcs1_verify(&rsa,
1496                         RSA_PUBLIC,
1497                         ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
1498                              RSA_SHA1:RSA_SHA256),
1499                         0,
1500                         (unsigned char *)headerhash,
1501                         (unsigned char *)sig->sigdata) != 0) {
1502         sig->verify_status =      PDKIM_VERIFY_FAIL;
1503         sig->verify_ext_status =  PDKIM_VERIFY_FAIL_MESSAGE;
1504         #ifdef PDKIM_DEBUG
1505         if (ctx->debug_stream) {
1506           fprintf(ctx->debug_stream, "PDKIM [%s] signature did NOT verify OK\n",
1507                   sig->domain);
1508         }
1509         #endif
1510         goto NEXT_VERIFY;
1511       }
1512
1513       /* We have a winner! */
1514       sig->verify_status = PDKIM_VERIFY_PASS;
1515
1516       #ifdef PDKIM_DEBUG
1517       if (ctx->debug_stream) {
1518         fprintf(ctx->debug_stream, "PDKIM [%s] signature verified OK\n",
1519                 sig->domain);
1520       }
1521       #endif
1522
1523       NEXT_VERIFY:
1524       rsa_free(&rsa);
1525       free(dns_txt_name);
1526       free(dns_txt_reply);
1527     }
1528
1529     sig = sig->next;
1530   }
1531
1532   /* If requested, set return pointer to signature(s) */
1533   if (return_signatures != NULL) {
1534     *return_signatures = ctx->sig;
1535   }
1536
1537   return PDKIM_OK;
1538 }
1539
1540
1541 /* -------------------------------------------------------------------------- */
1542 DLLEXPORT pdkim_ctx *pdkim_init_verify(int input_mode,
1543                              int(*dns_txt_callback)(char *, char *)
1544                              ) {
1545   pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
1546   if (ctx == NULL) return NULL;
1547   memset(ctx,0,sizeof(pdkim_ctx));
1548
1549   ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN);
1550   if (ctx->linebuf == NULL) {
1551     free(ctx);
1552     return NULL;
1553   }
1554
1555   ctx->mode = PDKIM_MODE_VERIFY;
1556   ctx->input_mode = input_mode;
1557   ctx->dns_txt_callback = dns_txt_callback;
1558
1559   return ctx;
1560 }
1561
1562
1563 /* -------------------------------------------------------------------------- */
1564 DLLEXPORT pdkim_ctx *pdkim_init_sign(int input_mode,
1565                            char *domain,
1566                            char *selector,
1567                            char *rsa_privkey) {
1568   pdkim_ctx *ctx;
1569   pdkim_signature *sig;
1570
1571   if (!domain || !selector || !rsa_privkey) return NULL;
1572
1573   ctx = malloc(sizeof(pdkim_ctx));
1574   if (ctx == NULL) return NULL;
1575   memset(ctx,0,sizeof(pdkim_ctx));
1576
1577   ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN);
1578   if (ctx->linebuf == NULL) {
1579     free(ctx);
1580     return NULL;
1581   }
1582
1583   sig = malloc(sizeof(pdkim_signature));
1584   if (sig == NULL) {
1585     free(ctx->linebuf);
1586     free(ctx);
1587     return NULL;
1588   }
1589   memset(sig,0,sizeof(pdkim_signature));
1590   sig->bodylength = -1;
1591
1592   ctx->mode = PDKIM_MODE_SIGN;
1593   ctx->input_mode = input_mode;
1594   ctx->sig = sig;
1595
1596   ctx->sig->domain = strdup(domain);
1597   ctx->sig->selector = strdup(selector);
1598   ctx->sig->rsa_privkey = strdup(rsa_privkey);
1599
1600   if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey) {
1601     pdkim_free_ctx(ctx);
1602     return NULL;
1603   }
1604
1605   ctx->sig->sha1_body = malloc(sizeof(sha1_context));
1606   if (ctx->sig->sha1_body == NULL) {
1607     pdkim_free_ctx(ctx);
1608     return NULL;
1609   }
1610   sha1_starts(ctx->sig->sha1_body);
1611
1612   ctx->sig->sha2_body = malloc(sizeof(sha2_context));
1613   if (ctx->sig->sha2_body == NULL) {
1614     pdkim_free_ctx(ctx);
1615     return NULL;
1616   }
1617   sha2_starts(ctx->sig->sha2_body,0);
1618
1619   return ctx;
1620 };
1621
1622 #ifdef PDKIM_DEBUG
1623 /* -------------------------------------------------------------------------- */
1624 DLLEXPORT void pdkim_set_debug_stream(pdkim_ctx *ctx,
1625                             FILE *debug_stream) {
1626   ctx->debug_stream = debug_stream;
1627 };
1628 #endif
1629
1630 /* -------------------------------------------------------------------------- */
1631 DLLEXPORT int pdkim_set_optional(pdkim_ctx *ctx,
1632                        char *sign_headers,
1633                        char *identity,
1634                        int canon_headers,
1635                        int canon_body,
1636                        long bodylength,
1637                        int algo,
1638                        unsigned long created,
1639                        unsigned long expires) {
1640
1641   if (identity != NULL) {
1642     ctx->sig->identity = strdup(identity);
1643     if (ctx->sig->identity == NULL) return PDKIM_ERR_OOM;
1644   }
1645
1646   if (sign_headers != NULL) {
1647     ctx->sig->sign_headers = strdup(sign_headers);
1648     if (ctx->sig->sign_headers == NULL) return PDKIM_ERR_OOM;
1649   }
1650
1651   ctx->sig->canon_headers = canon_headers;
1652   ctx->sig->canon_body = canon_body;
1653   ctx->sig->bodylength = bodylength;
1654   ctx->sig->algo = algo;
1655   ctx->sig->created = created;
1656   ctx->sig->expires = expires;
1657
1658   return PDKIM_OK;
1659 };