Back to index

opendkim  2.6.6
dkim-canon.c
Go to the documentation of this file.
00001 /*
00002 **  Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers.
00003 **    All rights reserved.
00004 **
00005 **  Copyright (c) 2009-2012, The OpenDKIM Project.  All rights reserved.
00006 */
00007 
00008 #ifndef lint
00009 static char dkim_canon_c_id[] = "@(#)$Id: dkim-canon.c,v 1.21.10.1 2010/10/27 21:43:08 cm-msk Exp $";
00010 #endif /* !lint */
00011 
00012 #include "build-config.h"
00013 
00014 /* for Solaris */
00015 #ifndef _REENTRANT
00016 # define _REENTRANT
00017 #endif /* _REENTRANT */
00018 
00019 /* system includes */
00020 #include <sys/param.h>
00021 #include <sys/types.h>
00022 #ifdef HAVE_STDBOOL_H
00023 # include <stdbool.h>
00024 #endif /* HAVE_STDBOOL_H */
00025 #include <assert.h>
00026 #include <string.h>
00027 #include <ctype.h>
00028 #include <unistd.h>
00029 #include <limits.h>
00030 #ifdef USE_TRE
00031 # ifdef TRE_PRE_080
00032 #  include <tre/regex.h>
00033 # else /* TRE_PRE_080 */
00034 #  include <tre/tre.h>
00035 #  ifndef TRE_USE_SYSTEM_REGEX_H
00036 #   define regcomp   tre_regcomp
00037 #   define regexec   tre_regexec
00038 #   define regfree   tre_regfree
00039 #  endif /* TRE_USE_SYSTEM_REGEX_H */
00040 # endif /* TRE_PRE_080 */
00041 #else /* USE_TRE */
00042 # include <regex.h>
00043 #endif /* USE_TRE */
00044 
00045 /* libopendkim includes */
00046 #include "dkim-internal.h"
00047 #include "dkim-types.h"
00048 #include "dkim-canon.h"
00049 #include "dkim-util.h"
00050 #include "dkim-strl.h"
00051 #include "util.h"
00052 
00053 /* definitions */
00054 #define       CRLF   (u_char *) "\r\n"
00055 #define       SP     (u_char *) " "
00056 
00057 /* macros */
00058 #define       DKIM_ISLWSP(x)       ((x) == 011 || (x) == 013 || (x) == 014 || (x) == 040)
00059 
00060 /* prototypes */
00061 extern void dkim_error __P((DKIM *, const char *, ...));
00062 
00063 /* ========================= PRIVATE SECTION ========================= */
00064 
00065 /*
00066 **  DKIM_CANON_FREE -- destroy a canonicalization
00067 **
00068 **  Parameters:
00069 **     dkim -- DKIM handle
00070 **     canon -- canonicalization to destroy
00071 **
00072 **  Return value:
00073 **     None.
00074 */
00075 
00076 static void
00077 dkim_canon_free(DKIM *dkim, DKIM_CANON *canon)
00078 {
00079        assert(dkim != NULL);
00080        assert(canon != NULL);
00081 
00082        if (canon->canon_hash != NULL)
00083        {
00084               switch (canon->canon_hashtype)
00085               {
00086 #ifdef USE_GNUTLS
00087                 case DKIM_HASHTYPE_SHA1:
00088                 case DKIM_HASHTYPE_SHA256:
00089                 {
00090                      struct dkim_sha *sha;
00091 
00092                      sha = (struct dkim_sha *) canon->canon_hash;
00093 
00094                      if (sha->sha_tmpfd != -1)
00095                      {
00096                             close(sha->sha_tmpfd);
00097                             sha->sha_tmpfd = -1;
00098                      }
00099 
00100                      gnutls_hash_deinit(sha->sha_hd, NULL);
00101 
00102                      if (sha->sha_out != NULL)
00103                      {
00104                             DKIM_FREE(dkim, sha->sha_out);
00105                             sha->sha_out = NULL;
00106                      }
00107 
00108                      break;
00109                 }
00110 
00111 #else /* USE_GNUTLS */
00112                 case DKIM_HASHTYPE_SHA1:
00113                 {
00114                      struct dkim_sha1 *sha1;
00115 
00116                      sha1 = (struct dkim_sha1 *) canon->canon_hash;
00117 
00118                      if (sha1->sha1_tmpbio != NULL)
00119                      {
00120                             BIO_free(sha1->sha1_tmpbio);
00121                             sha1->sha1_tmpfd = -1;
00122                             sha1->sha1_tmpbio = NULL;
00123                      }
00124 
00125                      break;
00126                 }
00127 
00128 # ifdef HAVE_SHA256
00129                 case DKIM_HASHTYPE_SHA256:
00130                 {
00131                      struct dkim_sha256 *sha256;
00132 
00133                      sha256 = (struct dkim_sha256 *) canon->canon_hash;
00134 
00135                      if (sha256->sha256_tmpbio != NULL)
00136                      {
00137                             BIO_free(sha256->sha256_tmpbio);
00138                             sha256->sha256_tmpfd = -1;
00139                             sha256->sha256_tmpbio = NULL;
00140                      }
00141 
00142                      break;
00143                 }
00144 # endif /* HAVE_SHA256 */
00145 #endif /* USE_GNUTLS */
00146 
00147                 default:
00148                      assert(0);
00149                      /* NOTREACHED */
00150               }
00151 
00152               dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure,
00153                          canon->canon_hash);
00154        }
00155 
00156        if (canon->canon_hashbuf != NULL)
00157        {
00158               dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure,
00159                          canon->canon_hashbuf);
00160        }
00161 
00162        if (canon->canon_buf != NULL)
00163               dkim_dstring_free(canon->canon_buf);
00164 
00165        dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure, canon);
00166 }
00167 
00168 /*
00169 **  DKIM_CANON_WRITE -- write data to canonicalization stream(s)
00170 **
00171 **  Parameters:
00172 **     canon -- DKIM_CANON handle
00173 **     buf -- buffer containing canonicalized data
00174 **     buflen -- number of bytes to consume
00175 **
00176 **  Return value:
00177 **     None.
00178 */
00179 
00180 static void
00181 dkim_canon_write(DKIM_CANON *canon, u_char *buf, size_t buflen)
00182 {
00183        assert(canon != NULL);
00184 
00185        if (canon->canon_remain != (ssize_t) -1)
00186               buflen = MIN(buflen, canon->canon_remain);
00187 
00188        canon->canon_wrote += buflen;
00189 
00190        if (buf == NULL || buflen == 0)
00191               return;
00192 
00193        assert(canon->canon_hash != NULL);
00194 
00195        switch (canon->canon_hashtype)
00196        {
00197 #ifdef USE_GNUTLS
00198          case DKIM_HASHTYPE_SHA1:
00199          case DKIM_HASHTYPE_SHA256:
00200          {
00201               struct dkim_sha *sha;
00202 
00203               sha = (struct dkim_sha *) canon->canon_hash;
00204 
00205               gnutls_hash(sha->sha_hd, buf, buflen);
00206 
00207               if (sha->sha_tmpfd != -1)
00208                      (void) write(sha->sha_tmpfd, buf, buflen);
00209 
00210               break;
00211          }
00212 #else /* USE_GNUTLS */
00213          case DKIM_HASHTYPE_SHA1:
00214          {
00215               struct dkim_sha1 *sha1;
00216 
00217               sha1 = (struct dkim_sha1 *) canon->canon_hash;
00218               SHA1_Update(&sha1->sha1_ctx, buf, buflen);
00219 
00220               if (sha1->sha1_tmpbio != NULL)
00221                      BIO_write(sha1->sha1_tmpbio, buf, buflen);
00222 
00223               break;
00224          }
00225 
00226 # ifdef HAVE_SHA256
00227          case DKIM_HASHTYPE_SHA256:
00228          {
00229               struct dkim_sha256 *sha256;
00230 
00231               sha256 = (struct dkim_sha256 *) canon->canon_hash;
00232               SHA256_Update(&sha256->sha256_ctx, buf, buflen);
00233 
00234               if (sha256->sha256_tmpbio != NULL)
00235                      BIO_write(sha256->sha256_tmpbio, buf, buflen);
00236 
00237               break;
00238          }
00239 # endif /* HAVE_SHA256 */
00240 #endif /* USE_GNUTLS */
00241        }
00242 
00243        if (canon->canon_remain != (ssize_t) -1)
00244               canon->canon_remain -= buflen;
00245 }
00246 
00247 /*
00248 **  DKIM_CANON_BUFFER -- buffer for dkim_canon_write()
00249 **
00250 **  Parameters:
00251 **     canon -- DKIM_CANON handle
00252 **     buf -- buffer containing canonicalized data
00253 **     buflen -- number of bytes to consume
00254 **
00255 **  Return value:
00256 **     None.
00257 */
00258 
00259 static void
00260 dkim_canon_buffer(DKIM_CANON *canon, u_char *buf, size_t buflen)
00261 {
00262        assert(canon != NULL);
00263 
00264        /* NULL buffer or 0 length means flush */
00265        if (buf == NULL || buflen == 0)
00266        {
00267               if (canon->canon_hashbuflen > 0)
00268               {
00269                      dkim_canon_write(canon, canon->canon_hashbuf,
00270                                       canon->canon_hashbuflen);
00271                      canon->canon_hashbuflen = 0;
00272               }
00273               return;
00274        }
00275 
00276        /* not enough buffer space; write the buffer out */
00277        if (canon->canon_hashbuflen + buflen > canon->canon_hashbufsize)
00278        {
00279               dkim_canon_write(canon, canon->canon_hashbuf,
00280                                canon->canon_hashbuflen);
00281               canon->canon_hashbuflen = 0;
00282        }
00283 
00284        /*
00285        **  Now, if the input is bigger than the buffer, write it too;
00286        **  otherwise cache it.
00287        */
00288 
00289        if (buflen >= canon->canon_hashbufsize)
00290        {
00291               dkim_canon_write(canon, buf, buflen);
00292        }
00293        else
00294        {
00295               memcpy(&canon->canon_hashbuf[canon->canon_hashbuflen],
00296                      buf, buflen);
00297               canon->canon_hashbuflen += buflen;
00298        }
00299 }
00300 
00301 /*
00302 **  DKIM_CANON_HEADER_STRING -- canonicalize a header field
00303 **
00304 **  Parameters:
00305 **     dstr -- dkim_dstring to use for output
00306 **     canon -- canonicalization mode to apply
00307 **     hdr -- header field input
00308 **     hdrlen -- bytes to process at "hdr"
00309 **     crlf -- write a CRLF at the end?
00310 **
00311 **  Return value:
00312 **     A DKIM_STAT constant.
00313 */
00314 
00315 DKIM_STAT
00316 dkim_canon_header_string(struct dkim_dstring *dstr, dkim_canon_t canon,
00317                          unsigned char *hdr, size_t hdrlen, _Bool crlf)
00318 {
00319        _Bool space;
00320        u_char *p;
00321        u_char *tmp;
00322        u_char *end;
00323        u_char tmpbuf[BUFRSZ];
00324 
00325        assert(dstr != NULL);
00326        assert(hdr != NULL);
00327 
00328        tmp = tmpbuf;
00329        end = tmpbuf + sizeof tmpbuf - 1;
00330 
00331        switch (canon)
00332        {
00333          case DKIM_CANON_SIMPLE:
00334               if (!dkim_dstring_catn(dstr, hdr, hdrlen) ||
00335                   (crlf && !dkim_dstring_catn(dstr, CRLF, 2)))
00336                      return DKIM_STAT_NORESOURCE;
00337               break;
00338 
00339          case DKIM_CANON_RELAXED:
00340               /* process header field name (before colon) first */
00341               for (p = hdr; p < hdr + hdrlen; p++)
00342               {
00343                      /*
00344                      **  Discard spaces before the colon or before the end
00345                      **  of the first word.
00346                      */
00347 
00348                      if (isascii(*p))
00349                      {
00350                             /* discard spaces */
00351                             if (isspace(*p))
00352                                    continue;
00353 
00354                             /* convert to lowercase */
00355                             if (isupper(*p))
00356                                    *tmp++ = tolower(*p);
00357                             else
00358                                    *tmp++ = *p;
00359                      }
00360                      else
00361                      {
00362                             *tmp++ = *p;
00363                      }
00364 
00365                      /* reaching the end of the cache buffer, flush it */
00366                      if (tmp == end)
00367                      {
00368                             *tmp = '\0';
00369 
00370                             if (!dkim_dstring_catn(dstr,
00371                                                    tmpbuf, tmp - tmpbuf))
00372                                    return DKIM_STAT_NORESOURCE;
00373 
00374                             tmp = tmpbuf;
00375                      }
00376                      
00377                      if (*p == ':')
00378                      {
00379                             p++;
00380                             break;
00381                      }
00382               }
00383 
00384               /* skip all spaces before first word */
00385               while (*p != '\0' && isascii(*p) && isspace(*p))
00386                      p++;
00387 
00388               space = FALSE;                            /* just saw a space */
00389 
00390               for ( ; *p != '\0'; p++)
00391               {
00392                      if (isascii(*p) && isspace(*p))
00393                      {
00394                             /* mark that there was a space and continue */
00395                             space = TRUE;
00396 
00397                             continue;
00398                      }
00399 
00400                      /*
00401                      **  Any non-space marks the beginning of a word.
00402                      **  If there's a stored space, use it up.
00403                      */
00404 
00405                      if (space)
00406                      {
00407                             *tmp++ = ' ';
00408 
00409                             /* flush buffer? */
00410                             if (tmp == end)
00411                             {
00412                                    *tmp = '\0';
00413 
00414                                    if (!dkim_dstring_catn(dstr,
00415                                                           tmpbuf,
00416                                                           tmp - tmpbuf))
00417                                           return DKIM_STAT_NORESOURCE;
00418 
00419                                    tmp = tmpbuf;
00420                             }
00421 
00422                             space = FALSE;
00423                      }
00424 
00425                      /* copy the byte */
00426                      *tmp++ = *p;
00427 
00428                      /* flush buffer? */
00429                      if (tmp == end)
00430                      {
00431                             *tmp = '\0';
00432 
00433                             if (!dkim_dstring_catn(dstr,
00434                                                    tmpbuf, tmp - tmpbuf))
00435                                    return DKIM_STAT_NORESOURCE;
00436 
00437                             tmp = tmpbuf;
00438                      }
00439               }
00440 
00441               /* flush any cached data */
00442               if (tmp != tmpbuf)
00443               {
00444                      *tmp = '\0';
00445 
00446                      if (!dkim_dstring_catn(dstr,
00447                                             tmpbuf, tmp - tmpbuf))
00448                             return DKIM_STAT_NORESOURCE;
00449               }
00450 
00451               if (crlf && !dkim_dstring_catn(dstr, CRLF, 2))
00452                      return DKIM_STAT_NORESOURCE;
00453 
00454               break;
00455        }
00456 
00457        return DKIM_STAT_OK;
00458 }
00459 
00460 /*
00461 **  DKIM_CANON_HEADER -- canonicalize a header and write it
00462 **
00463 **  Parameters:
00464 **     dkim -- DKIM handle
00465 **     canon -- DKIM_CANON handle
00466 **     hdr -- header handle
00467 **     crlf -- write a CRLF at the end?
00468 **
00469 **  Return value:
00470 **     A DKIM_STAT constant.
00471 */
00472 
00473 static DKIM_STAT
00474 dkim_canon_header(DKIM *dkim, DKIM_CANON *canon, struct dkim_header *hdr,
00475                   _Bool crlf)
00476 {
00477        DKIM_STAT status;
00478 
00479        assert(dkim != NULL);
00480        assert(canon != NULL);
00481        assert(hdr != NULL);
00482 
00483        if (dkim->dkim_canonbuf == NULL)
00484        {
00485               dkim->dkim_canonbuf = dkim_dstring_new(dkim, hdr->hdr_textlen,
00486                                                      0);
00487               if (dkim->dkim_canonbuf == NULL)
00488                      return DKIM_STAT_NORESOURCE;
00489        }
00490        else
00491        {
00492               dkim_dstring_blank(dkim->dkim_canonbuf);
00493        }
00494 
00495        dkim_canon_buffer(canon, NULL, 0);
00496 
00497        status = dkim_canon_header_string(dkim->dkim_canonbuf,
00498                                          canon->canon_canon,
00499                                          hdr->hdr_text, hdr->hdr_textlen,
00500                                          crlf);
00501        if (status != DKIM_STAT_OK)
00502               return status;
00503 
00504        dkim_canon_buffer(canon, dkim_dstring_get(dkim->dkim_canonbuf),
00505                          dkim_dstring_len(dkim->dkim_canonbuf));
00506 
00507        return DKIM_STAT_OK;
00508 }
00509 
00510 /*
00511 **  DKIM_CANON_FLUSHBLANKS -- use accumulated blank lines in canonicalization
00512 **
00513 **  Parameters:
00514 **     canon -- DKIM_CANON handle
00515 **
00516 **  Return value:
00517 **     None.
00518 */
00519 
00520 static void
00521 dkim_canon_flushblanks(DKIM_CANON *canon)
00522 {
00523        int c;
00524 
00525        assert(canon != NULL);
00526 
00527        for (c = 0; c < canon->canon_blanks; c++)
00528               dkim_canon_buffer(canon, CRLF, 2);
00529        canon->canon_blanks = 0;
00530 }
00531 
00532 /*
00533 **  DKIM_CANON_FIXCRLF -- rebuffer a body chunk, fixing "naked" CRs and LFs
00534 **
00535 **  Parameters:
00536 **     dkim -- DKIM handle
00537 **     canon -- canonicalization being handled
00538 **     buf -- buffer to be fixed
00539 **     buflen -- number of bytes at "buf"
00540 **
00541 **  Return value:
00542 **     A DKIM_STAT_* constant.
00543 **
00544 **  Side effects:
00545 **     dkim->dkim_canonbuf will be initialized and used.
00546 */
00547 
00548 static DKIM_STAT
00549 dkim_canon_fixcrlf(DKIM *dkim, DKIM_CANON *canon, u_char *buf, size_t buflen)
00550 {
00551        u_char prev;
00552        u_char *p;
00553        u_char *eob;
00554 
00555        assert(dkim != NULL);
00556        assert(canon != NULL);
00557        assert(buf != NULL);
00558 
00559        if (dkim->dkim_canonbuf == NULL)
00560        {
00561               dkim->dkim_canonbuf = dkim_dstring_new(dkim, buflen, 0);
00562               if (dkim->dkim_canonbuf == NULL)
00563                      return DKIM_STAT_NORESOURCE;
00564        }
00565        else
00566        {
00567               dkim_dstring_blank(dkim->dkim_canonbuf);
00568        }
00569 
00570        eob = buf + buflen - 1;
00571 
00572        prev = canon->canon_lastchar;
00573 
00574        for (p = buf; p <= eob; p++)
00575        {
00576               if (*p == '\n' && prev != '\r')
00577               {
00578                      /* fix a solitary LF */
00579                      dkim_dstring_catn(dkim->dkim_canonbuf, CRLF, 2);
00580               }
00581               else if (*p == '\r')
00582               {
00583                      if (p < eob && *(p + 1) != '\n')
00584                             /* fix a solitary CR */
00585                             dkim_dstring_catn(dkim->dkim_canonbuf, CRLF, 2);
00586                      else
00587                             /* CR at EOL, or CR followed by a LF */
00588                             dkim_dstring_cat1(dkim->dkim_canonbuf, *p);
00589               }
00590               else
00591               {
00592                      /* something else */
00593                      dkim_dstring_cat1(dkim->dkim_canonbuf, *p);
00594               }
00595 
00596               prev = *p;
00597        }
00598 
00599        return DKIM_STAT_OK;
00600 }
00601 
00602 /* ========================= PUBLIC SECTION ========================= */
00603 
00604 /*
00605 **  DKIM_CANON_INIT -- initialize all canonicalizations
00606 **
00607 **  Parameters:
00608 **     dkim -- DKIM handle
00609 **     tmp -- make temp files?
00610 **     keep -- keep temp files?
00611 **
00612 **  Return value:
00613 **     A DKIM_STAT_* constant.
00614 */
00615 
00616 DKIM_STAT
00617 dkim_canon_init(DKIM *dkim, _Bool tmp, _Bool keep)
00618 {
00619        int fd;
00620        DKIM_STAT status;
00621        DKIM_CANON *cur;
00622 
00623        assert(dkim != NULL);
00624 
00625        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
00626        {
00627               cur->canon_hashbuf = DKIM_MALLOC(dkim, DKIM_HASHBUFSIZE);
00628               if (cur->canon_hashbuf == NULL)
00629               {
00630                      dkim_error(dkim, "unable to allocate %d byte(s)",
00631                                 DKIM_HASHBUFSIZE);
00632                      return DKIM_STAT_NORESOURCE;
00633               }
00634               cur->canon_hashbufsize = DKIM_HASHBUFSIZE;
00635               cur->canon_hashbuflen = 0;
00636               cur->canon_buf = dkim_dstring_new(dkim, BUFRSZ, BUFRSZ);
00637               if (cur->canon_buf == NULL)
00638                      return DKIM_STAT_NORESOURCE;
00639 
00640               switch (cur->canon_hashtype)
00641               {
00642 #ifdef USE_GNUTLS
00643                 case DKIM_HASHTYPE_SHA1:
00644                 case DKIM_HASHTYPE_SHA256:
00645                 {
00646                      struct dkim_sha *sha;
00647 
00648                      sha = (struct dkim_sha *) DKIM_MALLOC(dkim,
00649                                                            sizeof(struct dkim_sha));
00650                      if (sha == NULL)
00651                      {
00652                             dkim_error(dkim,
00653                                        "unable to allocate %d byte(s)",
00654                                        sizeof(struct dkim_sha));
00655                             return DKIM_STAT_NORESOURCE;
00656                      }
00657 
00658                      memset(sha, '\0', sizeof(struct dkim_sha));
00659                      sha->sha_tmpfd = -1;
00660 
00661                      /* XXX -- test for errors */
00662                      if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1)
00663                      {
00664                             (void) gnutls_hash_init(&sha->sha_hd,
00665                                                     GNUTLS_DIG_SHA1);
00666                      }
00667                      else
00668                      {
00669                             (void) gnutls_hash_init(&sha->sha_hd,
00670                                                     GNUTLS_DIG_SHA256);
00671                      }
00672 
00673                      if (sha->sha_hd == NULL)
00674                      {
00675                             DKIM_FREE(dkim, sha);
00676                             return DKIM_STAT_INTERNAL;
00677                      }
00678                             
00679                      if (tmp)
00680                      {
00681                             status = dkim_tmpfile(dkim, &fd, keep);
00682                             if (status != DKIM_STAT_OK)
00683                             {
00684                                    DKIM_FREE(dkim, sha);
00685                                    return status;
00686                             }
00687 
00688                             sha->sha_tmpfd = fd;
00689                      }
00690 
00691                      cur->canon_hash = sha;
00692 
00693                      break;
00694                 }
00695 #else /* USE_GNUTLS */
00696                 case DKIM_HASHTYPE_SHA1:
00697                 {
00698                      struct dkim_sha1 *sha1;
00699 
00700                      sha1 = (struct dkim_sha1 *) DKIM_MALLOC(dkim,
00701                                                              sizeof(struct dkim_sha1));
00702                      if (sha1 == NULL)
00703                      {
00704                             dkim_error(dkim,
00705                                        "unable to allocate %d byte(s)",
00706                                        sizeof(struct dkim_sha1));
00707                             return DKIM_STAT_NORESOURCE;
00708                      }
00709 
00710                      memset(sha1, '\0', sizeof(struct dkim_sha1));
00711                      SHA1_Init(&sha1->sha1_ctx);
00712 
00713                      if (tmp)
00714                      {
00715                             status = dkim_tmpfile(dkim, &fd, keep);
00716                             if (status != DKIM_STAT_OK)
00717                             {
00718                                    DKIM_FREE(dkim, sha1);
00719                                    return status;
00720                             }
00721 
00722                             sha1->sha1_tmpfd = fd;
00723                             sha1->sha1_tmpbio = BIO_new_fd(fd, 1);
00724                      }
00725 
00726                      cur->canon_hash = sha1;
00727 
00728                      break;
00729                 }
00730 
00731 # ifdef HAVE_SHA256
00732                 case DKIM_HASHTYPE_SHA256:
00733                 {
00734                      struct dkim_sha256 *sha256;
00735 
00736                      sha256 = (struct dkim_sha256 *) DKIM_MALLOC(dkim,
00737                                                                  sizeof(struct dkim_sha256));
00738                      if (sha256 == NULL)
00739                      {
00740                             dkim_error(dkim,
00741                                        "unable to allocate %d byte(s)",
00742                                        sizeof(struct dkim_sha256));
00743                             return DKIM_STAT_NORESOURCE;
00744                      }
00745 
00746                      memset(sha256, '\0', sizeof(struct dkim_sha256));
00747                      SHA256_Init(&sha256->sha256_ctx);
00748 
00749                      if (tmp)
00750                      {
00751                             status = dkim_tmpfile(dkim, &fd, keep);
00752                             if (status != DKIM_STAT_OK)
00753                             {
00754                                    DKIM_FREE(dkim, sha256);
00755                                    return status;
00756                             }
00757 
00758                             sha256->sha256_tmpfd = fd;
00759                             sha256->sha256_tmpbio = BIO_new_fd(fd, 1);
00760                      }
00761 
00762                      cur->canon_hash = sha256;
00763 
00764                      break;
00765                 }
00766 # endif /* HAVE_SHA256 */
00767 #endif /* USE_GNUTLS */
00768 
00769                 default:
00770                      assert(0);
00771               }
00772        }
00773 
00774        return DKIM_STAT_OK;
00775 }
00776 
00777 /*
00778 **  DKIM_CANON_CLEANUP -- discard canonicalizations
00779 **
00780 **  Parameters:
00781 **     dkim -- DKIM handle
00782 **
00783 **  Return value:
00784 **     None.
00785 */
00786 
00787 void
00788 dkim_canon_cleanup(DKIM *dkim)
00789 {
00790        DKIM_CANON *cur;
00791        DKIM_CANON *next;
00792 
00793        assert(dkim != NULL);
00794 
00795 #ifdef _FFR_RESIGN
00796        if (dkim->dkim_resign != NULL && dkim->dkim_hdrbind)
00797               return;
00798 #endif /* _FFR_RESIGN */
00799 
00800        cur = dkim->dkim_canonhead;
00801        while (cur != NULL)
00802        {
00803               next = cur->canon_next;
00804 
00805 #ifdef _FFR_RESIGN
00806               /* skip if resigning and body */
00807               if (dkim->dkim_resign == NULL || cur->canon_hdr)
00808                      dkim_canon_free(dkim, cur);
00809 #else /* _FFR_RESIGN */
00810               dkim_canon_free(dkim, cur);
00811 #endif /* _FFR_RESIGN */
00812 
00813               cur = next;
00814        }
00815 
00816        dkim->dkim_canonhead = NULL;
00817 }
00818 
00819 /*
00820 **  DKIM_ADD_CANON -- add a new canonicalization handle if needed
00821 **
00822 **  Parameters:
00823 **     dkim -- verification handle
00824 **     hdr -- TRUE iff this is specifying a header canonicalization
00825 **     canon -- canonicalization mode
00826 **     hashtype -- hash type
00827 **     hdrlist -- for header canonicalization, the header list
00828 **     sighdr -- pointer to header being verified (NULL for signing)
00829 **     length -- for body canonicalization, the length limit (-1 == all)
00830 **     cout -- DKIM_CANON handle (returned)
00831 **
00832 **  Return value:
00833 **     A DKIM_STAT_* constant.
00834 */
00835 
00836 DKIM_STAT
00837 dkim_add_canon(DKIM *dkim, _Bool hdr, dkim_canon_t canon, int hashtype,
00838                u_char *hdrlist, struct dkim_header *sighdr,
00839                ssize_t length, DKIM_CANON **cout)
00840 {
00841        DKIM_CANON *cur;
00842        DKIM_CANON *new;
00843 
00844        assert(dkim != NULL);
00845        assert(canon == DKIM_CANON_SIMPLE || canon == DKIM_CANON_RELAXED);
00846        if (dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256))
00847        {
00848               assert(hashtype == DKIM_HASHTYPE_SHA1 ||
00849                      hashtype == DKIM_HASHTYPE_SHA256);
00850        }
00851        else
00852        {
00853               assert(hashtype == DKIM_HASHTYPE_SHA1);
00854        }
00855 
00856        if (!hdr)
00857        {
00858               for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
00859               {
00860                      if (cur->canon_hdr ||
00861                          cur->canon_hashtype != hashtype ||
00862                          cur->canon_canon != canon)
00863                             continue;
00864 
00865                      if (length != cur->canon_length)
00866                             continue;
00867 
00868                      if (cout != NULL)
00869                             *cout = cur;
00870 
00871                      return DKIM_STAT_OK;
00872               }
00873        }
00874 
00875        new = (DKIM_CANON *) dkim_malloc(dkim->dkim_libhandle,
00876                                         dkim->dkim_closure, sizeof *new);
00877        if (new == NULL)
00878        {
00879               dkim_error(dkim, "unable to allocate %d byte(s)", sizeof *new);
00880               return DKIM_STAT_NORESOURCE;
00881        }
00882 
00883        new->canon_done = FALSE;
00884        new->canon_hdr = hdr;
00885        new->canon_canon = canon;
00886        new->canon_hashtype = hashtype;
00887        new->canon_hash = NULL;
00888        new->canon_wrote = 0;
00889        if (hdr)
00890        {
00891               new->canon_length = (ssize_t) -1;
00892               new->canon_remain = (ssize_t) -1;
00893        }
00894        else
00895        {
00896               new->canon_length = length;
00897               new->canon_remain = length;
00898        }
00899        new->canon_sigheader = sighdr;
00900        new->canon_hdrlist = hdrlist;
00901        new->canon_buf = NULL;
00902        new->canon_next = NULL;
00903        new->canon_blankline = TRUE;
00904        new->canon_blanks = 0;
00905        new->canon_bodystate = 0;
00906        new->canon_hashbuflen = 0;
00907        new->canon_hashbufsize = 0;
00908        new->canon_hashbuf = NULL;
00909        new->canon_lastchar = '\0';
00910 
00911        if (dkim->dkim_canonhead == NULL)
00912        {
00913               dkim->dkim_canontail = new;
00914               dkim->dkim_canonhead = new;
00915        }
00916        else
00917        {
00918               dkim->dkim_canontail->canon_next = new;
00919               dkim->dkim_canontail = new;
00920        }
00921 
00922        if (cout != NULL)
00923               *cout = new;
00924 
00925        return DKIM_STAT_OK;
00926 }
00927 
00928 /*
00929 **  DKIM_CANON_SELECTHDRS -- choose headers to be included in canonicalization
00930 **
00931 **  Parameters:
00932 **     dkim -- DKIM context in which this is performed
00933 **     hdrlist -- string containing headers that should be marked, separated
00934 **                by the ":" character
00935 **     ptrs -- array of header pointers (modified)
00936 **     nptr -- number of pointers available at "ptrs"
00937 **
00938 **  Return value:
00939 **     Count of headers added to "ptrs", or -1 on error.
00940 **
00941 **  Notes:
00942 **     Selects headers to be passed to canonicalization and the order in
00943 **     which this is done.  "ptrs" is populated by pointers to headers
00944 **     in the order in which they should be fed to canonicalization.
00945 **
00946 **     If any of the returned pointers is NULL, then a header named by
00947 **     "hdrlist" was not found.
00948 */
00949 
00950 int
00951 dkim_canon_selecthdrs(DKIM *dkim, u_char *hdrlist, struct dkim_header **ptrs,
00952                       int nptrs)
00953 {
00954        int c;
00955        int n;
00956        int m;
00957        int shcnt;
00958        size_t len;
00959        char *bar;
00960        char *ctx;
00961        u_char *colon;
00962        struct dkim_header *hdr;
00963        struct dkim_header **lhdrs;
00964        u_char **hdrs;
00965 
00966        assert(dkim != NULL);
00967        assert(ptrs != NULL);
00968        assert(nptrs != 0);
00969 
00970        /* if there are no headers named, use them all */
00971        if (hdrlist == NULL)
00972        {
00973               n = 0;
00974 
00975               for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next)
00976               {
00977                      if (n >= nptrs)
00978                      {
00979                             dkim_error(dkim, "too many headers (max %d)",
00980                                        nptrs);
00981                             return -1;
00982                      }
00983                      ptrs[n] = hdr;
00984                      n++;
00985               }
00986 
00987               return n;
00988        }
00989 
00990        if (dkim->dkim_hdrlist == NULL)
00991        {
00992               dkim->dkim_hdrlist = dkim_malloc(dkim->dkim_libhandle,
00993                                                dkim->dkim_closure,
00994                                                DKIM_MAXHEADER);
00995               if (dkim->dkim_hdrlist == NULL)
00996               {
00997                      dkim_error(dkim, "unable to allocate %d bytes(s)",
00998                                 DKIM_MAXHEADER);
00999 
01000                      return -1;
01001               }
01002        }
01003 
01004        strlcpy((char *) dkim->dkim_hdrlist, (char *) hdrlist, DKIM_MAXHEADER);
01005 
01006        /* mark all headers as not used */
01007        for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next)
01008               hdr->hdr_flags &= ~DKIM_HDR_SIGNED;
01009 
01010        n = dkim->dkim_hdrcnt * sizeof(struct dkim_header *);
01011        lhdrs = DKIM_MALLOC(dkim, n);
01012        if (lhdrs == NULL)
01013               return -1;
01014        memset(lhdrs, '\0', n);
01015 
01016        shcnt = 1;
01017        for (colon = dkim->dkim_hdrlist; *colon != '\0'; colon++)
01018        {
01019               if (*colon == ':')
01020                      shcnt++;
01021        }
01022        n = sizeof(u_char *) * shcnt;
01023        hdrs = DKIM_MALLOC(dkim, n);
01024        if (hdrs == NULL)
01025        {
01026               (void) DKIM_FREE(dkim, lhdrs);
01027               return -1;
01028        }
01029        memset(hdrs, '\0', n);
01030 
01031        n = 0;
01032 
01033        /* make a split-out copy of hdrlist */
01034        for (bar = strtok_r((char *) dkim->dkim_hdrlist, ":", &ctx);
01035             bar != NULL;
01036             bar = strtok_r(NULL, ":", &ctx))
01037        {
01038               hdrs[n] = (u_char *) bar;
01039               n++;
01040        }
01041 
01042        /* for each named header, find the last unused one and use it up */
01043        shcnt = 0;
01044        for (c = 0; c < n; c++)
01045        {
01046               lhdrs[shcnt] = NULL;
01047 
01048               len = MIN(DKIM_MAXHEADER, strlen((char *) hdrs[c]));
01049               while (len > 0 &&
01050                      isascii(hdrs[c][len - 1]) &&
01051                      isspace(hdrs[c][len - 1]))
01052                      len--;
01053 
01054               for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next)
01055               {
01056                      if (hdr->hdr_flags & DKIM_HDR_SIGNED)
01057                             continue;
01058 
01059                      if (len == hdr->hdr_namelen &&
01060                          strncasecmp((char *) hdr->hdr_text,
01061                                      (char *) hdrs[c], len) == 0)
01062                             lhdrs[shcnt] = hdr;
01063               }
01064 
01065               if (lhdrs[shcnt] != NULL)
01066               {
01067                      lhdrs[shcnt]->hdr_flags |= DKIM_HDR_SIGNED;
01068                      shcnt++;
01069               }
01070        }
01071 
01072        /* bounds check */
01073        if (shcnt > nptrs)
01074        {
01075               dkim_error(dkim, "too many headers (found %d, max %d)", shcnt,
01076                          nptrs);
01077 
01078               DKIM_FREE(dkim, lhdrs);
01079               DKIM_FREE(dkim, hdrs);
01080 
01081               return -1;
01082        }
01083 
01084        /* copy to the caller's buffers */
01085        m = 0;
01086        for (c = 0; c < shcnt; c++)
01087        {
01088               if (lhdrs[c] != NULL)
01089               {
01090                      ptrs[m] = lhdrs[c];
01091                      m++;
01092               }
01093        }
01094 
01095        DKIM_FREE(dkim, lhdrs);
01096        DKIM_FREE(dkim, hdrs);
01097 
01098        return m;
01099 }
01100 
01101 /*
01102 **  DKIM_CANON_RUNHEADERS -- run the headers through all header
01103 **                           canonicalizations
01104 **
01105 **  Parameters:
01106 **     dkim -- DKIM handle
01107 **
01108 **  Return value:
01109 **     A DKIM_STAT_* constant.
01110 **
01111 **  Note:
01112 **     Header canonicalizations are finalized by this function when
01113 **     verifying.  In signing mode, header canonicalizations are finalized
01114 **     by a subsequent call to dkim_canon_signature().
01115 */
01116 
01117 DKIM_STAT
01118 dkim_canon_runheaders(DKIM *dkim)
01119 {
01120        _Bool signing;
01121        u_char savechar;
01122        int c;
01123        int n;
01124        int in;
01125        int nhdrs = 0;
01126        int last = '\0';
01127        DKIM_STAT status;
01128        u_char *tmp;
01129        u_char *end;
01130        DKIM_CANON *cur;
01131        u_char *p;
01132        struct dkim_header *hdr;
01133        struct dkim_header **hdrset;
01134        struct dkim_header tmphdr;
01135        u_char tmpbuf[BUFRSZ];
01136 
01137        assert(dkim != NULL);
01138 
01139        tmp = tmpbuf;
01140        end = tmpbuf + sizeof tmpbuf - 1;
01141 
01142        n = dkim->dkim_hdrcnt * sizeof(struct dkim_header *);
01143        hdrset = DKIM_MALLOC(dkim, n);
01144        if (hdrset == NULL)
01145               return DKIM_STAT_NORESOURCE;
01146 
01147        if (dkim->dkim_hdrbuf == NULL)
01148        {
01149               dkim->dkim_hdrbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ);
01150               if (dkim->dkim_hdrbuf == NULL)
01151               {
01152                      DKIM_FREE(dkim, hdrset);
01153                      return DKIM_STAT_NORESOURCE;
01154               }
01155        }
01156        else
01157        {
01158               dkim_dstring_blank(dkim->dkim_hdrbuf);
01159        }
01160 
01161        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01162        {
01163               /* skip done hashes and those which are of the wrong type */
01164               if (cur->canon_done || !cur->canon_hdr)
01165                      continue;
01166 
01167               signing = (cur->canon_sigheader == NULL);
01168 
01169               /* clear header selection flags if verifying */
01170               if (!signing)
01171               {
01172                      if (cur->canon_hdrlist == NULL)
01173                      {
01174                             for (hdr = dkim->dkim_hhead;
01175                                  hdr != NULL;
01176                                  hdr = hdr->hdr_next)
01177                                    hdr->hdr_flags |= DKIM_HDR_SIGNED;
01178                      }
01179                      else
01180                      {
01181                             for (hdr = dkim->dkim_hhead;
01182                                  hdr != NULL;
01183                                  hdr = hdr->hdr_next)
01184                                    hdr->hdr_flags &= ~DKIM_HDR_SIGNED;
01185 
01186                             memset(hdrset, '\0', n);
01187 
01188                             /* do header selection */
01189                             nhdrs = dkim_canon_selecthdrs(dkim,
01190                                                           cur->canon_hdrlist,
01191                                                           hdrset,
01192                                                           dkim->dkim_hdrcnt);
01193 
01194                             if (nhdrs == -1)
01195                             {
01196                                    dkim_error(dkim,
01197                                               "dkim_canon_selecthdrs() failed during canonicalization");
01198                                    DKIM_FREE(dkim, hdrset);
01199                                    return DKIM_STAT_INTERNAL;
01200                             }
01201                      }
01202               }
01203               else
01204               {
01205                      DKIM_LIB *lib;
01206 
01207                      lib = dkim->dkim_libhandle;
01208 
01209                      memset(hdrset, '\0', sizeof hdrset);
01210                      nhdrs = 0;
01211 
01212                      /* tag headers to be signed */
01213                      for (hdr = dkim->dkim_hhead;
01214                           hdr != NULL;
01215                           hdr = hdr->hdr_next)
01216                      {
01217                             if (!lib->dkiml_signre)
01218                             {
01219                                    tmp = dkim_dstring_get(dkim->dkim_hdrbuf);
01220 
01221                                    if (tmp[0] != '\0')
01222                                    {
01223                                           dkim_dstring_cat1(dkim->dkim_hdrbuf,
01224                                                            ':');
01225                                    }
01226 
01227                                    dkim_dstring_catn(dkim->dkim_hdrbuf,
01228                                                      hdr->hdr_text,
01229                                                      hdr->hdr_namelen);
01230                                    continue;
01231                             }
01232 
01233                             /* could be space, could be colon ... */
01234                             savechar = hdr->hdr_text[hdr->hdr_namelen];
01235 
01236                             /* terminate the header field name and test */
01237                             hdr->hdr_text[hdr->hdr_namelen] = '\0';
01238                             status = regexec(&lib->dkiml_hdrre,
01239                                              (char *) hdr->hdr_text,
01240                                              0, NULL, 0);
01241 
01242                             /* restore the character */
01243                             hdr->hdr_text[hdr->hdr_namelen] = savechar;
01244 
01245                             if (status == 0)
01246                             {
01247                                    tmp = dkim_dstring_get(dkim->dkim_hdrbuf);
01248 
01249                                    if (tmp[0] != '\0')
01250                                    {
01251                                           dkim_dstring_cat1(dkim->dkim_hdrbuf,
01252                                                            ':');
01253                                    }
01254 
01255                                    dkim_dstring_catn(dkim->dkim_hdrbuf,
01256                                                      hdr->hdr_text,
01257                                                    hdr->hdr_namelen);
01258                             }
01259                             else
01260                             {
01261                                    assert(status == REG_NOMATCH);
01262                             }
01263                      }
01264 
01265                      memset(hdrset, '\0', n);
01266 
01267                      /* do header selection */
01268                      nhdrs = dkim_canon_selecthdrs(dkim,
01269                                                    dkim_dstring_get(dkim->dkim_hdrbuf),
01270                                                    hdrset,
01271                                                    dkim->dkim_hdrcnt);
01272 
01273                      if (nhdrs == -1)
01274                      {
01275                             dkim_error(dkim,
01276                                        "dkim_canon_selecthdrs() failed during canonicalization");
01277                             DKIM_FREE(dkim, hdrset);
01278                             return DKIM_STAT_INTERNAL;
01279                      }
01280               }
01281 
01282               /* canonicalize each marked header */
01283               for (c = 0; c < nhdrs; c++)
01284               {
01285                      if (hdrset[c] != NULL &&
01286                          (hdrset[c]->hdr_flags & DKIM_HDR_SIGNED) != 0)
01287                      {
01288                             status = dkim_canon_header(dkim, cur,
01289                                                        hdrset[c], TRUE);
01290                             if (status != DKIM_STAT_OK)
01291                             {
01292                                    DKIM_FREE(dkim, hdrset);
01293                                    return status;
01294                             }
01295                      }
01296               }
01297 
01298               /* if signing, we can't do the rest of this yet */
01299               if (cur->canon_sigheader == NULL)
01300                      continue;
01301 
01302               /*
01303               **  We need to copy the DKIM-Signature: header being verified,
01304               **  minus the contents of the "b=" part, and include it in the
01305               **  canonicalization.  However, skip this if no hashing was
01306               **  done.
01307               */
01308 
01309               dkim_dstring_blank(dkim->dkim_hdrbuf);
01310 
01311               tmp = tmpbuf;
01312 
01313               n = 0;
01314               in = '\0';
01315               for (p = cur->canon_sigheader->hdr_text; *p != '\0'; p++)
01316               {
01317                      if (*p == ';')
01318                             in = '\0';
01319 
01320                      if (in == 'b')
01321                      {
01322                             last = *p;
01323                             continue;
01324                      }
01325 
01326                      if (in == '\0' && *p == '=')
01327                             in = last;
01328 
01329                      *tmp++ = *p;
01330 
01331                      /* flush buffer? */
01332                      if (tmp == end)
01333                      {
01334                             *tmp = '\0';
01335 
01336                             if (!dkim_dstring_catn(dkim->dkim_hdrbuf,
01337                                                    tmpbuf, tmp - tmpbuf))
01338                             {
01339                                    DKIM_FREE(dkim, hdrset);
01340 
01341                                    return DKIM_STAT_NORESOURCE;
01342                             }
01343 
01344                             tmp = tmpbuf;
01345                      }
01346 
01347                      last = *p;
01348               }
01349 
01350               /* flush anything cached */
01351               if (tmp != tmpbuf)
01352               {
01353                      *tmp = '\0';
01354 
01355                      if (!dkim_dstring_catn(dkim->dkim_hdrbuf,
01356                                             tmpbuf, tmp - tmpbuf))
01357                      {
01358                             DKIM_FREE(dkim, hdrset);
01359 
01360                             return DKIM_STAT_NORESOURCE;
01361                      }
01362               }
01363 
01364               /* canonicalize */
01365               tmphdr.hdr_text = dkim_dstring_get(dkim->dkim_hdrbuf);
01366               tmphdr.hdr_namelen = cur->canon_sigheader->hdr_namelen;
01367               tmphdr.hdr_colon = tmphdr.hdr_text + (cur->canon_sigheader->hdr_colon - cur->canon_sigheader->hdr_text);
01368               tmphdr.hdr_textlen = dkim_dstring_len(dkim->dkim_hdrbuf);
01369               tmphdr.hdr_flags = 0;
01370               tmphdr.hdr_next = NULL;
01371 
01372               if (cur->canon_canon == DKIM_CANON_RELAXED)
01373                      dkim_lowerhdr(tmphdr.hdr_text);
01374               (void) dkim_canon_header(dkim, cur, &tmphdr, FALSE);
01375               dkim_canon_buffer(cur, NULL, 0);
01376 
01377               /* finalize */
01378               switch (cur->canon_hashtype)
01379               {
01380 #ifdef USE_GNUTLS
01381                 case DKIM_HASHTYPE_SHA1:
01382                 case DKIM_HASHTYPE_SHA256:
01383                 {
01384                      int alg;
01385                      struct dkim_sha *sha;
01386 
01387                      sha = (struct dkim_sha *) cur->canon_hash;
01388 
01389                      if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1)
01390                             alg = GNUTLS_DIG_SHA1;
01391                      else
01392                             alg = GNUTLS_DIG_SHA256;
01393 
01394                      sha->sha_outlen = gnutls_hash_get_len(alg);
01395 
01396                      sha->sha_out = DKIM_MALLOC(dkim, sha->sha_outlen);
01397                      if (sha->sha_out == NULL)
01398                      {
01399                             dkim_error(dkim, "unable to allocate %u bytes",
01400                                        sha->sha_outlen);
01401                             return DKIM_STAT_NORESOURCE;
01402                      }
01403 
01404                      gnutls_hash_output(sha->sha_hd, sha->sha_out);
01405 
01406                      break;
01407                 }
01408 
01409 #else /* USE_GNUTLS */
01410                 case DKIM_HASHTYPE_SHA1:
01411                 {
01412                      struct dkim_sha1 *sha1;
01413 
01414                      sha1 = (struct dkim_sha1 *) cur->canon_hash;
01415                      SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx);
01416 
01417                      if (sha1->sha1_tmpbio != NULL)
01418                             (void) BIO_flush(sha1->sha1_tmpbio);
01419 
01420                      break;
01421                 }
01422 
01423 # ifdef HAVE_SHA256
01424                 case DKIM_HASHTYPE_SHA256:
01425                 {
01426                      struct dkim_sha256 *sha256;
01427 
01428                      sha256 = (struct dkim_sha256 *) cur->canon_hash;
01429                      SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx);
01430 
01431                      if (sha256->sha256_tmpbio != NULL)
01432                             (void) BIO_flush(sha256->sha256_tmpbio);
01433 
01434                      break;
01435                 }
01436 # endif /* HAVE_SHA256 */
01437 #endif /* USE_GNUTLS */
01438 
01439                 default:
01440                      assert(0);
01441                      /* NOTREACHED */
01442               }
01443 
01444               cur->canon_done = TRUE;
01445        }
01446 
01447        DKIM_FREE(dkim, hdrset);
01448 
01449        return DKIM_STAT_OK;
01450 }
01451 
01452 /*
01453 **  DKIM_CANON_SIGNATURE -- append a signature header when signing
01454 **
01455 **  Parameters:
01456 **     dkim -- DKIM handle
01457 **     hdr -- header
01458 **
01459 **  Return value:
01460 **     A DKIM_STAT_* constant.
01461 **
01462 **  Notes:
01463 **     Header canonicalizations are finalized by this function.
01464 */
01465 
01466 DKIM_STAT
01467 dkim_canon_signature(DKIM *dkim, struct dkim_header *hdr)
01468 {
01469        DKIM_STAT status;
01470        DKIM_CANON *cur;
01471        struct dkim_header tmphdr;
01472 
01473        assert(dkim != NULL);
01474        assert(hdr != NULL);
01475 
01476        if (dkim->dkim_hdrbuf == NULL)
01477        {
01478               dkim->dkim_hdrbuf = dkim_dstring_new(dkim, DKIM_MAXHEADER, 0);
01479               if (dkim->dkim_hdrbuf == NULL)
01480                      return DKIM_STAT_NORESOURCE;
01481        }
01482        else
01483        {
01484               dkim_dstring_blank(dkim->dkim_hdrbuf);
01485        }
01486 
01487        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01488        {
01489               /* skip done hashes and those which are of the wrong type */
01490               if (cur->canon_done || !cur->canon_hdr)
01491                      continue;
01492 
01493               /* prepare the data */
01494               dkim_dstring_copy(dkim->dkim_hdrbuf, hdr->hdr_text);
01495               tmphdr.hdr_text = dkim_dstring_get(dkim->dkim_hdrbuf);
01496               tmphdr.hdr_namelen = hdr->hdr_namelen;
01497               tmphdr.hdr_colon = tmphdr.hdr_text + (hdr->hdr_colon - hdr->hdr_text);
01498               tmphdr.hdr_textlen = dkim_dstring_len(dkim->dkim_hdrbuf);
01499               tmphdr.hdr_flags = 0;
01500               tmphdr.hdr_next = NULL;
01501               if (cur->canon_canon == DKIM_CANON_RELAXED)
01502                      dkim_lowerhdr(tmphdr.hdr_text);
01503               
01504               /* canonicalize the signature */
01505               status = dkim_canon_header(dkim, cur, &tmphdr, FALSE);
01506               if (status != DKIM_STAT_OK)
01507                      return status;
01508               dkim_canon_buffer(cur, NULL, 0);
01509 
01510               /* now close it */
01511               switch (cur->canon_hashtype)
01512               {
01513 #ifdef USE_GNUTLS
01514                 case DKIM_HASHTYPE_SHA1:
01515                 case DKIM_HASHTYPE_SHA256:
01516                 {
01517                      int alg;
01518                      struct dkim_sha *sha;
01519 
01520                      sha = (struct dkim_sha *) cur->canon_hash;
01521 
01522                      if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1)
01523                             alg = GNUTLS_DIG_SHA1;
01524                      else
01525                             alg = GNUTLS_DIG_SHA256;
01526 
01527                      sha->sha_outlen = gnutls_hash_get_len(alg);
01528 
01529                      sha->sha_out = DKIM_MALLOC(dkim, sha->sha_outlen);
01530                      if (sha->sha_out == NULL)
01531                      {
01532                             dkim_error(dkim, "unable to allocate %u bytes",
01533                                        sha->sha_outlen);
01534                             return DKIM_STAT_NORESOURCE;
01535                      }
01536 
01537                      gnutls_hash_output(sha->sha_hd, sha->sha_out);
01538 
01539                      if (sha->sha_tmpfd != -1)
01540                      {
01541                             close(sha->sha_tmpfd);
01542                             sha->sha_tmpfd = -1;
01543                      }
01544 
01545                      break;
01546                 }
01547 #else /* USE_GNUTLS */
01548                 case DKIM_HASHTYPE_SHA1:
01549                 {
01550                      struct dkim_sha1 *sha1;
01551 
01552                      sha1 = (struct dkim_sha1 *) cur->canon_hash;
01553                      SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx);
01554 
01555                      if (sha1->sha1_tmpbio != NULL)
01556                             (void) BIO_flush(sha1->sha1_tmpbio);
01557 
01558                      break;
01559                 }
01560 
01561 # ifdef HAVE_SHA256
01562                 case DKIM_HASHTYPE_SHA256:
01563                 {
01564                      struct dkim_sha256 *sha256;
01565 
01566                      sha256 = (struct dkim_sha256 *) cur->canon_hash;
01567                      SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx);
01568 
01569                      if (sha256->sha256_tmpbio != NULL)
01570                             (void) BIO_flush(sha256->sha256_tmpbio);
01571 
01572                      break;
01573                 }
01574 # endif /* HAVE_SHA256 */
01575 #endif /* USE_GNUTLS */
01576 
01577                 default:
01578                      assert(0);
01579                      /* NOTREACHED */
01580               }
01581 
01582               cur->canon_done = TRUE;
01583        }
01584 
01585        return DKIM_STAT_OK;
01586 }
01587 
01588 /*
01589 **  DKIM_CANON_MINBODY -- return number of bytes required to satisfy all
01590 **                        canonicalizations
01591 **
01592 **  Parameters:
01593 **     dkim -- DKIM handle
01594 **
01595 **  Return value:
01596 **     0 -- all canonicalizations satisfied
01597 **     ULONG_MAX -- at least one canonicalization wants the whole message
01598 **     other -- bytes required to satisfy all canonicalizations
01599 */
01600 
01601 u_long
01602 dkim_canon_minbody(DKIM *dkim)
01603 {
01604        u_long minbody = 0;
01605        DKIM_CANON *cur;
01606 
01607        assert(dkim != NULL);
01608 
01609        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01610        {
01611               /* skip done hashes and those which are of the wrong type */
01612               if (cur->canon_done || cur->canon_hdr)
01613                      continue;
01614 
01615               /* if this one wants the whole message, short-circuit */
01616               if (cur->canon_remain == (ssize_t) -1)
01617                      return ULONG_MAX;
01618 
01619               /* compare to current minimum */
01620               minbody = MAX(minbody, (u_long) cur->canon_remain);
01621        }
01622 
01623        return minbody;
01624 }
01625 
01626 /*
01627 **  DKIM_CANON_BODYCHUNK -- run a body chunk through all body
01628 **                          canonicalizations
01629 **
01630 **  Parameters:
01631 **     dkim -- DKIM handle
01632 **     buf -- pointer to bytes to canonicalize
01633 **     buflen -- number of bytes to canonicalize
01634 **
01635 **  Return value:
01636 **     A DKIM_STAT_* constant.
01637 */
01638 
01639 DKIM_STAT
01640 dkim_canon_bodychunk(DKIM *dkim, u_char *buf, size_t buflen)
01641 {
01642        _Bool fixcrlf;
01643        DKIM_STAT status;
01644        u_int wlen;
01645        DKIM_CANON *cur;
01646        size_t plen;
01647        u_char *p;
01648        u_char *wrote;
01649        u_char *eob;
01650        u_char *start;
01651 
01652        assert(dkim != NULL);
01653 
01654        dkim->dkim_bodylen += buflen;
01655 
01656        fixcrlf = (dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_FIXCRLF);
01657 
01658        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01659        {
01660               /* skip done hashes and those which are of the wrong type */
01661               if (cur->canon_done || cur->canon_hdr)
01662                      continue;
01663 
01664               start = buf;
01665               plen = buflen;
01666 
01667               if (fixcrlf)
01668               {
01669                      status = dkim_canon_fixcrlf(dkim, cur, buf, buflen);
01670                      if (status != DKIM_STAT_OK)
01671                             return status;
01672 
01673                      start = dkim_dstring_get(dkim->dkim_canonbuf);
01674                      plen = dkim_dstring_len(dkim->dkim_canonbuf);
01675               }
01676 
01677               eob = start + plen - 1;
01678               wrote = start;
01679               wlen = 0;
01680 
01681               switch (cur->canon_canon)
01682               {
01683                 case DKIM_CANON_SIMPLE:
01684                      for (p = start; p <= eob; p++)
01685                      {
01686                             if (*p == '\n')
01687                             {
01688                                    if (cur->canon_lastchar == '\r')
01689                                    {
01690                                           if (cur->canon_blankline)
01691                                           {
01692                                                  cur->canon_blanks++;
01693                                           }
01694                                           else if (wlen == 1 ||
01695                                                    p == start)
01696                                           {
01697                                                  dkim_canon_buffer(cur,
01698                                                                    CRLF,
01699                                                                    2);
01700                                           }
01701                                           else
01702                                           {
01703                                                  dkim_canon_buffer(cur,
01704                                                                    wrote,
01705                                                                    wlen + 1);
01706                                           }
01707 
01708                                           wrote = p + 1;
01709                                           wlen = 0;
01710                                           cur->canon_blankline = TRUE;
01711                                    }
01712                             }
01713                             else
01714                             {
01715                                    if (p == start &&
01716                                        cur->canon_lastchar == '\r')
01717                                    {
01718                                           if (fixcrlf)
01719                                           {
01720                                                  dkim_canon_buffer(cur,
01721                                                                    CRLF,
01722                                                                    2);
01723                                                  cur->canon_lastchar = '\n';
01724                                                  cur->canon_blankline = TRUE;
01725                                           }
01726                                           else
01727                                           {
01728                                                  dkim_canon_buffer(cur,
01729                                                                    (u_char *) "\r",
01730                                                                    1);
01731                                           }
01732                                    }
01733 
01734                                    if (*p != '\r')
01735                                    {
01736                                           if (cur->canon_blanks > 0)
01737                                                  dkim_canon_flushblanks(cur);
01738                                           cur->canon_blankline = FALSE;
01739                                    }
01740 
01741                                    wlen++;
01742                             }
01743 
01744                             cur->canon_lastchar = *p;
01745                      }
01746 
01747                      if (wlen > 0 && wrote[wlen - 1] == '\r')
01748                             wlen--;
01749 
01750                      dkim_canon_buffer(cur, wrote, wlen);
01751 
01752                      break;
01753 
01754                 case DKIM_CANON_RELAXED:
01755                      for (p = start; p <= eob; p++)
01756                      {
01757                             switch (cur->canon_bodystate)
01758                             {
01759                               case 0:
01760                                    if (DKIM_ISLWSP(*p))
01761                                    {
01762                                           cur->canon_bodystate = 1;
01763                                    }
01764                                    else if (*p == '\r')
01765                                    {
01766                                           cur->canon_bodystate = 2;
01767                                    }
01768                                    else
01769                                    {
01770                                           cur->canon_blankline = FALSE;
01771                                           dkim_dstring_cat1(cur->canon_buf,
01772                                                             *p);
01773                                           cur->canon_bodystate = 3;
01774                                    }
01775                                    break;
01776 
01777                               case 1:
01778                                    if (DKIM_ISLWSP(*p))
01779                                    {
01780                                           break;
01781                                    }
01782                                    else if (*p == '\r')
01783                                    {
01784                                           cur->canon_bodystate = 2;
01785                                    }
01786                                    else
01787                                    {
01788                                           dkim_canon_flushblanks(cur);
01789                                           dkim_canon_buffer(cur, SP, 1);
01790                                           cur->canon_blankline = FALSE;
01791                                           dkim_dstring_cat1(cur->canon_buf,
01792                                                             *p);
01793                                           cur->canon_bodystate = 3;
01794                                    }
01795                                    break;
01796 
01797                               case 2:
01798                                    if (fixcrlf || *p == '\n')
01799                                    {
01800                                           if (cur->canon_blankline)
01801                                           {
01802                                                  cur->canon_blanks++;
01803                                                  cur->canon_bodystate = 0;
01804                                           }
01805                                           else
01806                                           {
01807                                                  dkim_canon_flushblanks(cur);
01808                                                  dkim_canon_buffer(cur,
01809                                                                    dkim_dstring_get(cur->canon_buf),
01810                                                                    dkim_dstring_len(cur->canon_buf));
01811                                                  dkim_canon_buffer(cur,
01812                                                                    CRLF,
01813                                                                    2);
01814                                                  dkim_dstring_blank(cur->canon_buf);
01815 
01816                                                  if (*p == '\n')
01817                                                  {
01818                                                         cur->canon_blankline = TRUE;
01819                                                         cur->canon_bodystate = 0;
01820                                                  }
01821                                                  else if (*p == '\r')
01822                                                  {
01823                                                         cur->canon_blankline = TRUE;
01824                                                  }
01825                                                  else
01826                                                  {
01827                                                         if (DKIM_ISLWSP(*p))
01828                                                         {
01829                                                                cur->canon_bodystate = 1;
01830                                                         }
01831                                                         else
01832                                                         {
01833                                                                dkim_dstring_cat1(cur->canon_buf,
01834                                                                                  *p);
01835                                                                cur->canon_bodystate = 3;
01836                                                         }
01837                                                  }
01838                                           }
01839                                    }
01840                                    else if (*p == '\r')
01841                                    {
01842                                           cur->canon_blankline = FALSE;
01843                                           dkim_dstring_cat1(cur->canon_buf,
01844                                                             *p);
01845                                    }
01846                                    else if (DKIM_ISLWSP(*p))
01847                                    {
01848                                           dkim_canon_flushblanks(cur);
01849                                           dkim_canon_buffer(cur,
01850                                                             dkim_dstring_get(cur->canon_buf),
01851                                                             dkim_dstring_len(cur->canon_buf));
01852                                           dkim_dstring_blank(cur->canon_buf);
01853                                           cur->canon_bodystate = 1;
01854                                    }
01855                                    else
01856                                    {
01857                                           cur->canon_blankline = FALSE;
01858                                           dkim_dstring_cat1(cur->canon_buf,
01859                                                             *p);
01860                                           cur->canon_bodystate = 3;
01861                                    }
01862                                    break;
01863 
01864                               case 3:
01865                                    if (DKIM_ISLWSP(*p))
01866                                    {
01867                                           dkim_canon_flushblanks(cur);
01868                                           dkim_canon_buffer(cur,
01869                                                             dkim_dstring_get(cur->canon_buf),
01870                                                             dkim_dstring_len(cur->canon_buf));
01871                                           dkim_dstring_blank(cur->canon_buf);
01872                                           cur->canon_bodystate = 1;
01873                                    }
01874                                    else if (*p == '\r')
01875                                    {
01876                                           cur->canon_bodystate = 2;
01877                                    }
01878                                    else
01879                                    {
01880                                           dkim_dstring_cat1(cur->canon_buf,
01881                                                             *p);
01882                                    }
01883                                    break;
01884                             }
01885 
01886                             cur->canon_lastchar = *p;
01887                      }
01888 
01889                      dkim_canon_buffer(cur, NULL, 0);
01890 
01891                      break;
01892 
01893                 default:
01894                      assert(0);
01895                      /* NOTREACHED */
01896               }
01897        }
01898 
01899        return DKIM_STAT_OK;
01900 }
01901 
01902 /*
01903 **  DKIM_CANON_CLOSEBODY -- close all body canonicalizations
01904 **
01905 **  Parameters:
01906 **     dkim -- DKIM handle
01907 **
01908 **  Return value:
01909 **     A DKIM_STAT_* constant.
01910 */
01911 
01912 DKIM_STAT
01913 dkim_canon_closebody(DKIM *dkim)
01914 {
01915        DKIM_CANON *cur;
01916 
01917        assert(dkim != NULL);
01918 
01919        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01920        {
01921               /* skip done hashes or header canonicalizations */
01922               if (cur->canon_done || cur->canon_hdr)
01923                      continue;
01924 
01925               /* handle unprocessed content */
01926               if (dkim_dstring_len(cur->canon_buf) > 0)
01927               {
01928                      if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_FIXCRLF) != 0)
01929                      {
01930                             dkim_canon_buffer(cur,
01931                                               dkim_dstring_get(cur->canon_buf),
01932                                               dkim_dstring_len(cur->canon_buf));
01933                             dkim_canon_buffer(cur, CRLF, 2);
01934                      }
01935                      else
01936                      {
01937                             dkim_error(dkim, "CRLF at end of body missing");
01938                             return DKIM_STAT_SYNTAX;
01939                      }
01940               }
01941 
01942               /* "simple" canonicalization must include at least a CRLF */
01943               if (cur->canon_canon == DKIM_CANON_SIMPLE &&
01944                   cur->canon_wrote == 0)
01945                      dkim_canon_buffer(cur, CRLF, 2);
01946 
01947               dkim_canon_buffer(cur, NULL, 0);
01948 
01949               /* finalize */
01950               switch (cur->canon_hashtype)
01951               {
01952 #ifdef USE_GNUTLS
01953                 case DKIM_HASHTYPE_SHA1:
01954                 case DKIM_HASHTYPE_SHA256:
01955                 {
01956                      int alg;
01957                      u_int diglen;
01958                      struct dkim_sha *sha;
01959 
01960                      sha = (struct dkim_sha *) cur->canon_hash;
01961 
01962                      if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1)
01963                             alg = GNUTLS_DIG_SHA1;
01964                      else
01965                             alg = GNUTLS_DIG_SHA256;
01966 
01967                      diglen = gnutls_hash_get_len(alg);
01968 
01969                      sha->sha_out = DKIM_MALLOC(dkim, diglen);
01970                      if (sha->sha_out == NULL)
01971                      {
01972                             dkim_error(dkim, "unable to allocate %u bytes",
01973                                        diglen);
01974                             return DKIM_STAT_NORESOURCE;
01975                      }
01976 
01977                      gnutls_hash_output(sha->sha_hd, sha->sha_out);
01978                      sha->sha_outlen = diglen;
01979 
01980                      break;
01981                 }
01982 #else /* USE_GNUTLS */
01983                 case DKIM_HASHTYPE_SHA1:
01984                 {
01985                      struct dkim_sha1 *sha1;
01986 
01987                      sha1 = (struct dkim_sha1 *) cur->canon_hash;
01988                      SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx);
01989 
01990                      if (sha1->sha1_tmpbio != NULL)
01991                             (void) BIO_flush(sha1->sha1_tmpbio);
01992 
01993                      break;
01994                 }
01995 
01996 # ifdef HAVE_SHA256
01997                 case DKIM_HASHTYPE_SHA256:
01998                 {
01999                      struct dkim_sha256 *sha256;
02000 
02001                      sha256 = (struct dkim_sha256 *) cur->canon_hash;
02002                      SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx);
02003 
02004                      if (sha256->sha256_tmpbio != NULL)
02005                             (void) BIO_flush(sha256->sha256_tmpbio);
02006 
02007                      break;
02008                 }
02009 # endif /* HAVE_SHA256 */
02010 #endif /* USE_GNUTLS */
02011 
02012                 default:
02013                      assert(0);
02014                      /* NOTREACHED */
02015               }
02016 
02017               cur->canon_done = TRUE;
02018        }
02019 
02020        return DKIM_STAT_OK;
02021 }
02022 
02023 /*
02024 **  DKIM_CANON_GETFINAL -- retrieve final digest
02025 **
02026 **  Parameters:
02027 **     canon -- DKIM_CANON handle
02028 **     digest -- pointer to the digest (returned)
02029 **     dlen -- digest length (returned)
02030 **
02031 **  Return value:
02032 **     A DKIM_STAT_* constant.
02033 */
02034 
02035 DKIM_STAT
02036 dkim_canon_getfinal(DKIM_CANON *canon, u_char **digest, size_t *dlen)
02037 {
02038        assert(canon != NULL);
02039        assert(digest != NULL);
02040        assert(dlen != NULL);
02041 
02042        if (!canon->canon_done)
02043               return DKIM_STAT_INVALID;
02044 
02045        switch (canon->canon_hashtype)
02046        {
02047 #ifdef USE_GNUTLS
02048          case DKIM_HASHTYPE_SHA1:
02049          case DKIM_HASHTYPE_SHA256:
02050          {
02051               struct dkim_sha *sha;
02052 
02053               sha = (struct dkim_sha *) canon->canon_hash;
02054               *digest = sha->sha_out;
02055               *dlen = sha->sha_outlen;
02056 
02057               return DKIM_STAT_OK;
02058          }
02059 #else /* USE_GNUTLS */
02060          case DKIM_HASHTYPE_SHA1:
02061          {
02062               struct dkim_sha1 *sha1;
02063 
02064               sha1 = (struct dkim_sha1 *) canon->canon_hash;
02065               *digest = sha1->sha1_out;
02066               *dlen = sizeof sha1->sha1_out;
02067 
02068               return DKIM_STAT_OK;
02069          }
02070 
02071 # ifdef HAVE_SHA256
02072          case DKIM_HASHTYPE_SHA256:
02073          {
02074               struct dkim_sha256 *sha256;
02075 
02076               sha256 = (struct dkim_sha256 *) canon->canon_hash;
02077               *digest = sha256->sha256_out;
02078               *dlen = sizeof sha256->sha256_out;
02079 
02080               return DKIM_STAT_OK;
02081          }
02082 # endif /* HAVE_SHA256 */
02083 #endif /* USE_GNUTLS */
02084 
02085          default:
02086               assert(0);
02087               /* NOTREACHED */
02088               return DKIM_STAT_INTERNAL;
02089        }
02090 }
02091 
02092 /*
02093 **  DKIM_CANON_GETHASHES -- retrieve hashes
02094 **
02095 **  Parameters:
02096 **     sig -- signature from which to get completed hashes
02097 **     hh -- pointer to header hash buffer (returned)
02098 **     hhlen -- bytes used at hh (returned)
02099 **     bh -- pointer to body hash buffer (returned)
02100 **     bhlen -- bytes used at bh (returned)
02101 **
02102 **  Return value:
02103 **     DKIM_STAT_OK -- successful completion
02104 **     DKIM_STAT_INVALID -- hashing hasn't been completed
02105 */
02106 
02107 DKIM_STAT
02108 dkim_canon_gethashes(DKIM_SIGINFO *sig, void **hh, size_t *hhlen,
02109                      void **bh, size_t *bhlen)
02110 {
02111        DKIM_STAT status;
02112        struct dkim_canon *hdc;
02113        struct dkim_canon *bdc;
02114        u_char *hd;
02115        u_char *bd;
02116        size_t hdlen;
02117        size_t bdlen;
02118 
02119        hdc = sig->sig_hdrcanon;
02120        bdc = sig->sig_bodycanon;
02121 
02122        status = dkim_canon_getfinal(hdc, &hd, &hdlen);
02123        if (status != DKIM_STAT_OK)
02124               return status;
02125 
02126        status = dkim_canon_getfinal(bdc, &bd, &bdlen);
02127        if (status != DKIM_STAT_OK)
02128               return status;
02129 
02130        *hh = hd;
02131        *hhlen = hdlen;
02132        *bh = bd;
02133        *bhlen = bdlen;
02134 
02135        return DKIM_STAT_OK;
02136 }