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