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