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