Back to index

opendkim  2.6.2
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-2011 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_done = FALSE;
00904        new->canon_blankline = TRUE;
00905        new->canon_blanks = 0;
00906        new->canon_bodystate = 0;
00907        new->canon_wrote = 0;
00908        new->canon_hashbuflen = 0;
00909        new->canon_hashbufsize = 0;
00910        new->canon_hashbuf = NULL;
00911        new->canon_lastchar = '\0';
00912 
00913        if (dkim->dkim_canonhead == NULL)
00914        {
00915               dkim->dkim_canontail = new;
00916               dkim->dkim_canonhead = new;
00917        }
00918        else
00919        {
00920               dkim->dkim_canontail->canon_next = new;
00921               dkim->dkim_canontail = new;
00922        }
00923 
00924        if (cout != NULL)
00925               *cout = new;
00926 
00927        return DKIM_STAT_OK;
00928 }
00929 
00930 /*
00931 **  DKIM_CANON_SELECTHDRS -- choose headers to be included in canonicalization
00932 **
00933 **  Parameters:
00934 **     dkim -- DKIM context in which this is performed
00935 **     hdrlist -- string containing headers that should be marked, separated
00936 **                by the ":" character
00937 **     ptrs -- array of header pointers (modified)
00938 **     nptr -- number of pointers available at "ptrs"
00939 **
00940 **  Return value:
00941 **     Count of headers added to "ptrs", or -1 on error.
00942 **
00943 **  Notes:
00944 **     Selects headers to be passed to canonicalization and the order in
00945 **     which this is done.  "ptrs" is populated by pointers to headers
00946 **     in the order in which they should be fed to canonicalization.
00947 **
00948 **     If any of the returned pointers is NULL, then a header named by
00949 **     "hdrlist" was not found.
00950 */
00951 
00952 int
00953 dkim_canon_selecthdrs(DKIM *dkim, u_char *hdrlist, struct dkim_header **ptrs,
00954                       int nptrs)
00955 {
00956        int c;
00957        int n;
00958        int m;
00959        int shcnt;
00960        size_t len;
00961        char *bar;
00962        char *ctx;
00963        u_char *colon;
00964        struct dkim_header *hdr;
00965        struct dkim_header **lhdrs;
00966        u_char **hdrs;
00967 
00968        assert(dkim != NULL);
00969        assert(ptrs != NULL);
00970        assert(nptrs != 0);
00971 
00972        /* if there are no headers named, use them all */
00973        if (hdrlist == NULL)
00974        {
00975               n = 0;
00976 
00977               for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next)
00978               {
00979                      if (n >= nptrs)
00980                      {
00981                             dkim_error(dkim, "too many headers (max %d)",
00982                                        nptrs);
00983                             return -1;
00984                      }
00985                      ptrs[n] = hdr;
00986                      n++;
00987               }
00988 
00989               return n;
00990        }
00991 
00992        if (dkim->dkim_hdrlist == NULL)
00993        {
00994               dkim->dkim_hdrlist = dkim_malloc(dkim->dkim_libhandle,
00995                                                dkim->dkim_closure,
00996                                                DKIM_MAXHEADER);
00997               if (dkim->dkim_hdrlist == NULL)
00998               {
00999                      dkim_error(dkim, "unable to allocate %d bytes(s)",
01000                                 DKIM_MAXHEADER);
01001 
01002                      return -1;
01003               }
01004        }
01005 
01006        strlcpy((char *) dkim->dkim_hdrlist, (char *) hdrlist, DKIM_MAXHEADER);
01007 
01008        /* mark all headers as not used */
01009        for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next)
01010               hdr->hdr_flags &= ~DKIM_HDR_SIGNED;
01011 
01012        n = dkim->dkim_hdrcnt * sizeof(struct dkim_header *);
01013        lhdrs = DKIM_MALLOC(dkim, n);
01014        if (lhdrs == NULL)
01015               return -1;
01016        memset(lhdrs, '\0', n);
01017 
01018        shcnt = 1;
01019        for (colon = dkim->dkim_hdrlist; *colon != '\0'; colon++)
01020        {
01021               if (*colon == ':')
01022                      shcnt++;
01023        }
01024        n = sizeof(u_char *) * shcnt;
01025        hdrs = DKIM_MALLOC(dkim, n);
01026        if (hdrs == NULL)
01027        {
01028               (void) DKIM_FREE(dkim, lhdrs);
01029               return -1;
01030        }
01031        memset(hdrs, '\0', n);
01032 
01033        n = 0;
01034 
01035        /* make a split-out copy of hdrlist */
01036        for (bar = strtok_r((char *) dkim->dkim_hdrlist, ":", &ctx);
01037             bar != NULL;
01038             bar = strtok_r(NULL, ":", &ctx))
01039        {
01040               hdrs[n] = (u_char *) bar;
01041               n++;
01042        }
01043 
01044        /* for each named header, find the last unused one and use it up */
01045        shcnt = 0;
01046        for (c = 0; c < n; c++)
01047        {
01048               lhdrs[shcnt] = NULL;
01049 
01050               len = MIN(DKIM_MAXHEADER, strlen((char *) hdrs[c]));
01051               while (len > 0 &&
01052                      isascii(hdrs[c][len - 1]) &&
01053                      isspace(hdrs[c][len - 1]))
01054                      len--;
01055 
01056               for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next)
01057               {
01058                      if (hdr->hdr_flags & DKIM_HDR_SIGNED)
01059                             continue;
01060 
01061                      if (len == hdr->hdr_namelen &&
01062                          strncasecmp((char *) hdr->hdr_text,
01063                                      (char *) hdrs[c], len) == 0)
01064                             lhdrs[shcnt] = hdr;
01065               }
01066 
01067               if (lhdrs[shcnt] != NULL)
01068               {
01069                      lhdrs[shcnt]->hdr_flags |= DKIM_HDR_SIGNED;
01070                      shcnt++;
01071               }
01072        }
01073 
01074        /* bounds check */
01075        if (shcnt > nptrs)
01076        {
01077               dkim_error(dkim, "too many headers (found %d, max %d)", shcnt,
01078                          nptrs);
01079 
01080               DKIM_FREE(dkim, lhdrs);
01081               DKIM_FREE(dkim, hdrs);
01082 
01083               return -1;
01084        }
01085 
01086        /* copy to the caller's buffers */
01087        m = 0;
01088        for (c = 0; c < shcnt; c++)
01089        {
01090               if (lhdrs[c] != NULL)
01091               {
01092                      ptrs[m] = lhdrs[c];
01093                      m++;
01094               }
01095        }
01096 
01097        DKIM_FREE(dkim, lhdrs);
01098        DKIM_FREE(dkim, hdrs);
01099 
01100        return m;
01101 }
01102 
01103 /*
01104 **  DKIM_CANON_RUNHEADERS -- run the headers through all header
01105 **                           canonicalizations
01106 **
01107 **  Parameters:
01108 **     dkim -- DKIM handle
01109 **
01110 **  Return value:
01111 **     A DKIM_STAT_* constant.
01112 **
01113 **  Note:
01114 **     Header canonicalizations are finalized by this function when
01115 **     verifying.  In signing mode, header canonicalizations are finalized
01116 **     by a subsequent call to dkim_canon_signature().
01117 */
01118 
01119 DKIM_STAT
01120 dkim_canon_runheaders(DKIM *dkim)
01121 {
01122        _Bool signing;
01123        u_char savechar;
01124        int c;
01125        int n;
01126        int in;
01127        int nhdrs = 0;
01128        int last = '\0';
01129        DKIM_STAT status;
01130        u_char *tmp;
01131        u_char *end;
01132        DKIM_CANON *cur;
01133        u_char *p;
01134        struct dkim_header *hdr;
01135        struct dkim_header **hdrset;
01136        struct dkim_header tmphdr;
01137        u_char tmpbuf[BUFRSZ];
01138 
01139        assert(dkim != NULL);
01140 
01141        tmp = tmpbuf;
01142        end = tmpbuf + sizeof tmpbuf - 1;
01143 
01144        n = dkim->dkim_hdrcnt * sizeof(struct dkim_header *);
01145        hdrset = DKIM_MALLOC(dkim, n);
01146        if (hdrset == NULL)
01147               return DKIM_STAT_NORESOURCE;
01148 
01149        if (dkim->dkim_hdrbuf == NULL)
01150        {
01151               dkim->dkim_hdrbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ);
01152               if (dkim->dkim_hdrbuf == NULL)
01153               {
01154                      DKIM_FREE(dkim, hdrset);
01155                      return DKIM_STAT_NORESOURCE;
01156               }
01157        }
01158        else
01159        {
01160               dkim_dstring_blank(dkim->dkim_hdrbuf);
01161        }
01162 
01163        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01164        {
01165               /* skip done hashes and those which are of the wrong type */
01166               if (cur->canon_done || !cur->canon_hdr)
01167                      continue;
01168 
01169               signing = (cur->canon_sigheader == NULL);
01170 
01171               /* clear header selection flags if verifying */
01172               if (!signing)
01173               {
01174                      if (cur->canon_hdrlist == NULL)
01175                      {
01176                             for (hdr = dkim->dkim_hhead;
01177                                  hdr != NULL;
01178                                  hdr = hdr->hdr_next)
01179                                    hdr->hdr_flags |= DKIM_HDR_SIGNED;
01180                      }
01181                      else
01182                      {
01183                             for (hdr = dkim->dkim_hhead;
01184                                  hdr != NULL;
01185                                  hdr = hdr->hdr_next)
01186                                    hdr->hdr_flags &= ~DKIM_HDR_SIGNED;
01187 
01188                             memset(hdrset, '\0', n);
01189 
01190                             /* do header selection */
01191                             nhdrs = dkim_canon_selecthdrs(dkim,
01192                                                           cur->canon_hdrlist,
01193                                                           hdrset,
01194                                                           dkim->dkim_hdrcnt);
01195 
01196                             if (nhdrs == -1)
01197                             {
01198                                    dkim_error(dkim,
01199                                               "dkim_canon_selecthdrs() failed during canonicalization");
01200                                    DKIM_FREE(dkim, hdrset);
01201                                    return DKIM_STAT_INTERNAL;
01202                             }
01203                      }
01204               }
01205               else
01206               {
01207                      DKIM_LIB *lib;
01208 
01209                      lib = dkim->dkim_libhandle;
01210 
01211                      memset(hdrset, '\0', sizeof hdrset);
01212                      nhdrs = 0;
01213 
01214                      /* tag headers to be signed */
01215                      for (hdr = dkim->dkim_hhead;
01216                           hdr != NULL;
01217                           hdr = hdr->hdr_next)
01218                      {
01219                             if (!lib->dkiml_signre)
01220                             {
01221                                    tmp = dkim_dstring_get(dkim->dkim_hdrbuf);
01222 
01223                                    if (tmp[0] != '\0')
01224                                    {
01225                                           dkim_dstring_cat1(dkim->dkim_hdrbuf,
01226                                                            ':');
01227                                    }
01228 
01229                                    dkim_dstring_catn(dkim->dkim_hdrbuf,
01230                                                      hdr->hdr_text,
01231                                                      hdr->hdr_namelen);
01232                                    continue;
01233                             }
01234 
01235                             /* could be space, could be colon ... */
01236                             savechar = hdr->hdr_text[hdr->hdr_namelen];
01237 
01238                             /* terminate the header field name and test */
01239                             hdr->hdr_text[hdr->hdr_namelen] = '\0';
01240                             status = regexec(&lib->dkiml_hdrre,
01241                                              (char *) hdr->hdr_text,
01242                                              0, NULL, 0);
01243 
01244                             /* restore the character */
01245                             hdr->hdr_text[hdr->hdr_namelen] = savechar;
01246 
01247                             if (status == 0)
01248                             {
01249                                    tmp = dkim_dstring_get(dkim->dkim_hdrbuf);
01250 
01251                                    if (tmp[0] != '\0')
01252                                    {
01253                                           dkim_dstring_cat1(dkim->dkim_hdrbuf,
01254                                                            ':');
01255                                    }
01256 
01257                                    dkim_dstring_catn(dkim->dkim_hdrbuf,
01258                                                      hdr->hdr_text,
01259                                                    hdr->hdr_namelen);
01260                             }
01261                             else
01262                             {
01263                                    assert(status == REG_NOMATCH);
01264                             }
01265                      }
01266 
01267                      memset(hdrset, '\0', n);
01268 
01269                      /* do header selection */
01270                      nhdrs = dkim_canon_selecthdrs(dkim,
01271                                                    dkim_dstring_get(dkim->dkim_hdrbuf),
01272                                                    hdrset,
01273                                                    dkim->dkim_hdrcnt);
01274 
01275                      if (nhdrs == -1)
01276                      {
01277                             dkim_error(dkim,
01278                                        "dkim_canon_selecthdrs() failed during canonicalization");
01279                             DKIM_FREE(dkim, hdrset);
01280                             return DKIM_STAT_INTERNAL;
01281                      }
01282               }
01283 
01284               /* canonicalize each marked header */
01285               for (c = 0; c < nhdrs; c++)
01286               {
01287                      if (hdrset[c] != NULL &&
01288                          (hdrset[c]->hdr_flags & DKIM_HDR_SIGNED) != 0)
01289                      {
01290                             status = dkim_canon_header(dkim, cur,
01291                                                        hdrset[c], TRUE);
01292                             if (status != DKIM_STAT_OK)
01293                             {
01294                                    DKIM_FREE(dkim, hdrset);
01295                                    return status;
01296                             }
01297                      }
01298               }
01299 
01300               /* if signing, we can't do the rest of this yet */
01301               if (cur->canon_sigheader == NULL)
01302                      continue;
01303 
01304               /*
01305               **  We need to copy the DKIM-Signature: header being verified,
01306               **  minus the contents of the "b=" part, and include it in the
01307               **  canonicalization.  However, skip this if no hashing was
01308               **  done.
01309               */
01310 
01311               dkim_dstring_blank(dkim->dkim_hdrbuf);
01312 
01313               tmp = tmpbuf;
01314 
01315               n = 0;
01316               in = '\0';
01317               for (p = cur->canon_sigheader->hdr_text; *p != '\0'; p++)
01318               {
01319                      if (*p == ';')
01320                             in = '\0';
01321 
01322                      if (in == 'b')
01323                      {
01324                             last = *p;
01325                             continue;
01326                      }
01327 
01328                      if (in == '\0' && *p == '=')
01329                             in = last;
01330 
01331                      *tmp++ = *p;
01332 
01333                      /* flush buffer? */
01334                      if (tmp == end)
01335                      {
01336                             *tmp = '\0';
01337 
01338                             if (!dkim_dstring_catn(dkim->dkim_hdrbuf,
01339                                                    tmpbuf, tmp - tmpbuf))
01340                             {
01341                                    DKIM_FREE(dkim, hdrset);
01342 
01343                                    return DKIM_STAT_NORESOURCE;
01344                             }
01345 
01346                             tmp = tmpbuf;
01347                      }
01348 
01349                      last = *p;
01350               }
01351 
01352               /* flush anything cached */
01353               if (tmp != tmpbuf)
01354               {
01355                      *tmp = '\0';
01356 
01357                      if (!dkim_dstring_catn(dkim->dkim_hdrbuf,
01358                                             tmpbuf, tmp - tmpbuf))
01359                      {
01360                             DKIM_FREE(dkim, hdrset);
01361 
01362                             return DKIM_STAT_NORESOURCE;
01363                      }
01364               }
01365 
01366               /* canonicalize */
01367               tmphdr.hdr_text = dkim_dstring_get(dkim->dkim_hdrbuf);
01368               tmphdr.hdr_namelen = cur->canon_sigheader->hdr_namelen;
01369               tmphdr.hdr_colon = tmphdr.hdr_text + (cur->canon_sigheader->hdr_colon - cur->canon_sigheader->hdr_text);
01370               tmphdr.hdr_textlen = dkim_dstring_len(dkim->dkim_hdrbuf);
01371               tmphdr.hdr_flags = 0;
01372               tmphdr.hdr_next = NULL;
01373 
01374               if (cur->canon_canon == DKIM_CANON_RELAXED)
01375                      dkim_lowerhdr(tmphdr.hdr_text);
01376               (void) dkim_canon_header(dkim, cur, &tmphdr, FALSE);
01377               dkim_canon_buffer(cur, NULL, 0);
01378 
01379               /* finalize */
01380               switch (cur->canon_hashtype)
01381               {
01382 #ifdef USE_GNUTLS
01383                 case DKIM_HASHTYPE_SHA1:
01384                 case DKIM_HASHTYPE_SHA256:
01385                 {
01386                      int alg;
01387                      struct dkim_sha *sha;
01388 
01389                      sha = (struct dkim_sha *) cur->canon_hash;
01390 
01391                      if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1)
01392                             alg = GNUTLS_DIG_SHA1;
01393                      else
01394                             alg = GNUTLS_DIG_SHA256;
01395 
01396                      sha->sha_outlen = gnutls_hash_get_len(alg);
01397 
01398                      sha->sha_out = DKIM_MALLOC(dkim, sha->sha_outlen);
01399                      if (sha->sha_out == NULL)
01400                      {
01401                             dkim_error(dkim, "unable to allocate %u bytes",
01402                                        sha->sha_outlen);
01403                             return DKIM_STAT_NORESOURCE;
01404                      }
01405 
01406                      gnutls_hash_output(sha->sha_hd, sha->sha_out);
01407 
01408                      break;
01409                 }
01410 
01411 #else /* USE_GNUTLS */
01412                 case DKIM_HASHTYPE_SHA1:
01413                 {
01414                      struct dkim_sha1 *sha1;
01415 
01416                      sha1 = (struct dkim_sha1 *) cur->canon_hash;
01417                      SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx);
01418 
01419                      if (sha1->sha1_tmpbio != NULL)
01420                             (void) BIO_flush(sha1->sha1_tmpbio);
01421 
01422                      break;
01423                 }
01424 
01425 # ifdef HAVE_SHA256
01426                 case DKIM_HASHTYPE_SHA256:
01427                 {
01428                      struct dkim_sha256 *sha256;
01429 
01430                      sha256 = (struct dkim_sha256 *) cur->canon_hash;
01431                      SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx);
01432 
01433                      if (sha256->sha256_tmpbio != NULL)
01434                             (void) BIO_flush(sha256->sha256_tmpbio);
01435 
01436                      break;
01437                 }
01438 # endif /* HAVE_SHA256 */
01439 #endif /* USE_GNUTLS */
01440 
01441                 default:
01442                      assert(0);
01443                      /* NOTREACHED */
01444               }
01445 
01446               cur->canon_done = TRUE;
01447        }
01448 
01449        DKIM_FREE(dkim, hdrset);
01450 
01451        return DKIM_STAT_OK;
01452 }
01453 
01454 /*
01455 **  DKIM_CANON_SIGNATURE -- append a signature header when signing
01456 **
01457 **  Parameters:
01458 **     dkim -- DKIM handle
01459 **     hdr -- header
01460 **
01461 **  Return value:
01462 **     A DKIM_STAT_* constant.
01463 **
01464 **  Notes:
01465 **     Header canonicalizations are finalized by this function.
01466 */
01467 
01468 DKIM_STAT
01469 dkim_canon_signature(DKIM *dkim, struct dkim_header *hdr)
01470 {
01471        DKIM_STAT status;
01472        DKIM_CANON *cur;
01473        struct dkim_header tmphdr;
01474 
01475        assert(dkim != NULL);
01476        assert(hdr != NULL);
01477 
01478        if (dkim->dkim_hdrbuf == NULL)
01479        {
01480               dkim->dkim_hdrbuf = dkim_dstring_new(dkim, DKIM_MAXHEADER, 0);
01481               if (dkim->dkim_hdrbuf == NULL)
01482                      return DKIM_STAT_NORESOURCE;
01483        }
01484        else
01485        {
01486               dkim_dstring_blank(dkim->dkim_hdrbuf);
01487        }
01488 
01489        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01490        {
01491               /* skip done hashes and those which are of the wrong type */
01492               if (cur->canon_done || !cur->canon_hdr)
01493                      continue;
01494 
01495               /* prepare the data */
01496               dkim_dstring_copy(dkim->dkim_hdrbuf, hdr->hdr_text);
01497               tmphdr.hdr_text = dkim_dstring_get(dkim->dkim_hdrbuf);
01498               tmphdr.hdr_namelen = hdr->hdr_namelen;
01499               tmphdr.hdr_colon = tmphdr.hdr_text + (hdr->hdr_colon - hdr->hdr_text);
01500               tmphdr.hdr_textlen = dkim_dstring_len(dkim->dkim_hdrbuf);
01501               tmphdr.hdr_flags = 0;
01502               tmphdr.hdr_next = NULL;
01503               if (cur->canon_canon == DKIM_CANON_RELAXED)
01504                      dkim_lowerhdr(tmphdr.hdr_text);
01505               
01506               /* canonicalize the signature */
01507               status = dkim_canon_header(dkim, cur, &tmphdr, FALSE);
01508               if (status != DKIM_STAT_OK)
01509                      return status;
01510               dkim_canon_buffer(cur, NULL, 0);
01511 
01512               /* now close it */
01513               switch (cur->canon_hashtype)
01514               {
01515 #ifdef USE_GNUTLS
01516                 case DKIM_HASHTYPE_SHA1:
01517                 case DKIM_HASHTYPE_SHA256:
01518                 {
01519                      int alg;
01520                      struct dkim_sha *sha;
01521 
01522                      sha = (struct dkim_sha *) cur->canon_hash;
01523 
01524                      if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1)
01525                             alg = GNUTLS_DIG_SHA1;
01526                      else
01527                             alg = GNUTLS_DIG_SHA256;
01528 
01529                      sha->sha_outlen = gnutls_hash_get_len(alg);
01530 
01531                      sha->sha_out = DKIM_MALLOC(dkim, sha->sha_outlen);
01532                      if (sha->sha_out == NULL)
01533                      {
01534                             dkim_error(dkim, "unable to allocate %u bytes",
01535                                        sha->sha_outlen);
01536                             return DKIM_STAT_NORESOURCE;
01537                      }
01538 
01539                      gnutls_hash_output(sha->sha_hd, sha->sha_out);
01540 
01541                      if (sha->sha_tmpfd != -1)
01542                      {
01543                             close(sha->sha_tmpfd);
01544                             sha->sha_tmpfd = -1;
01545                      }
01546 
01547                      break;
01548                 }
01549 #else /* USE_GNUTLS */
01550                 case DKIM_HASHTYPE_SHA1:
01551                 {
01552                      struct dkim_sha1 *sha1;
01553 
01554                      sha1 = (struct dkim_sha1 *) cur->canon_hash;
01555                      SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx);
01556 
01557                      if (sha1->sha1_tmpbio != NULL)
01558                             (void) BIO_flush(sha1->sha1_tmpbio);
01559 
01560                      break;
01561                 }
01562 
01563 # ifdef HAVE_SHA256
01564                 case DKIM_HASHTYPE_SHA256:
01565                 {
01566                      struct dkim_sha256 *sha256;
01567 
01568                      sha256 = (struct dkim_sha256 *) cur->canon_hash;
01569                      SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx);
01570 
01571                      if (sha256->sha256_tmpbio != NULL)
01572                             (void) BIO_flush(sha256->sha256_tmpbio);
01573 
01574                      break;
01575                 }
01576 # endif /* HAVE_SHA256 */
01577 #endif /* USE_GNUTLS */
01578 
01579                 default:
01580                      assert(0);
01581                      /* NOTREACHED */
01582               }
01583 
01584               cur->canon_done = TRUE;
01585        }
01586 
01587        return DKIM_STAT_OK;
01588 }
01589 
01590 /*
01591 **  DKIM_CANON_MINBODY -- return number of bytes required to satisfy all
01592 **                        canonicalizations
01593 **
01594 **  Parameters:
01595 **     dkim -- DKIM handle
01596 **
01597 **  Return value:
01598 **     0 -- all canonicalizations satisfied
01599 **     ULONG_MAX -- at least one canonicalization wants the whole message
01600 **     other -- bytes required to satisfy all canonicalizations
01601 */
01602 
01603 u_long
01604 dkim_canon_minbody(DKIM *dkim)
01605 {
01606        u_long minbody = 0;
01607        DKIM_CANON *cur;
01608 
01609        assert(dkim != NULL);
01610 
01611        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01612        {
01613               /* skip done hashes and those which are of the wrong type */
01614               if (cur->canon_done || cur->canon_hdr)
01615                      continue;
01616 
01617               /* if this one wants the whole message, short-circuit */
01618               if (cur->canon_remain == (ssize_t) -1)
01619                      return ULONG_MAX;
01620 
01621               /* compare to current minimum */
01622               minbody = MAX(minbody, (u_long) cur->canon_remain);
01623        }
01624 
01625        return minbody;
01626 }
01627 
01628 /*
01629 **  DKIM_CANON_BODYCHUNK -- run a body chunk through all body
01630 **                          canonicalizations
01631 **
01632 **  Parameters:
01633 **     dkim -- DKIM handle
01634 **     buf -- pointer to bytes to canonicalize
01635 **     buflen -- number of bytes to canonicalize
01636 **
01637 **  Return value:
01638 **     A DKIM_STAT_* constant.
01639 */
01640 
01641 DKIM_STAT
01642 dkim_canon_bodychunk(DKIM *dkim, u_char *buf, size_t buflen)
01643 {
01644        _Bool fixcrlf;
01645        DKIM_STAT status;
01646        u_int wlen;
01647        DKIM_CANON *cur;
01648        size_t plen;
01649        u_char *p;
01650        u_char *wrote;
01651        u_char *eob;
01652        u_char *start;
01653 
01654        assert(dkim != NULL);
01655 
01656        dkim->dkim_bodylen += buflen;
01657 
01658        fixcrlf = (dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_FIXCRLF);
01659 
01660        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01661        {
01662               /* skip done hashes and those which are of the wrong type */
01663               if (cur->canon_done || cur->canon_hdr)
01664                      continue;
01665 
01666               start = buf;
01667               plen = buflen;
01668 
01669               if (fixcrlf)
01670               {
01671                      status = dkim_canon_fixcrlf(dkim, cur, buf, buflen);
01672                      if (status != DKIM_STAT_OK)
01673                             return status;
01674 
01675                      start = dkim_dstring_get(dkim->dkim_canonbuf);
01676                      plen = dkim_dstring_len(dkim->dkim_canonbuf);
01677               }
01678 
01679               eob = start + plen - 1;
01680               wrote = start;
01681               wlen = 0;
01682 
01683               switch (cur->canon_canon)
01684               {
01685                 case DKIM_CANON_SIMPLE:
01686                      for (p = start; p <= eob; p++)
01687                      {
01688                             if (*p == '\n')
01689                             {
01690                                    if (cur->canon_lastchar == '\r')
01691                                    {
01692                                           if (cur->canon_blankline)
01693                                           {
01694                                                  cur->canon_blanks++;
01695                                           }
01696                                           else if (wlen == 1 ||
01697                                                    p == start)
01698                                           {
01699                                                  dkim_canon_buffer(cur,
01700                                                                    CRLF,
01701                                                                    2);
01702                                           }
01703                                           else
01704                                           {
01705                                                  dkim_canon_buffer(cur,
01706                                                                    wrote,
01707                                                                    wlen + 1);
01708                                           }
01709 
01710                                           wrote = p + 1;
01711                                           wlen = 0;
01712                                           cur->canon_blankline = TRUE;
01713                                    }
01714                             }
01715                             else
01716                             {
01717                                    if (p == start &&
01718                                        cur->canon_lastchar == '\r')
01719                                    {
01720                                           if (fixcrlf)
01721                                           {
01722                                                  dkim_canon_buffer(cur,
01723                                                                    CRLF,
01724                                                                    2);
01725                                                  cur->canon_lastchar = '\n';
01726                                                  cur->canon_blankline = TRUE;
01727                                           }
01728                                           else
01729                                           {
01730                                                  dkim_canon_buffer(cur,
01731                                                                    (u_char *) "\r",
01732                                                                    1);
01733                                           }
01734                                    }
01735 
01736                                    if (*p != '\r')
01737                                    {
01738                                           if (cur->canon_blanks > 0)
01739                                                  dkim_canon_flushblanks(cur);
01740                                           cur->canon_blankline = FALSE;
01741                                    }
01742 
01743                                    wlen++;
01744                             }
01745 
01746                             cur->canon_lastchar = *p;
01747                      }
01748 
01749                      if (wlen > 0 && wrote[wlen - 1] == '\r')
01750                             wlen--;
01751 
01752                      dkim_canon_buffer(cur, wrote, wlen);
01753 
01754                      break;
01755 
01756                 case DKIM_CANON_RELAXED:
01757                      for (p = start; p <= eob; p++)
01758                      {
01759                             switch (cur->canon_bodystate)
01760                             {
01761                               case 0:
01762                                    if (DKIM_ISLWSP(*p))
01763                                    {
01764                                           cur->canon_bodystate = 1;
01765                                    }
01766                                    else if (*p == '\r')
01767                                    {
01768                                           cur->canon_bodystate = 2;
01769                                    }
01770                                    else
01771                                    {
01772                                           cur->canon_blankline = FALSE;
01773                                           dkim_dstring_cat1(cur->canon_buf,
01774                                                             *p);
01775                                           cur->canon_bodystate = 3;
01776                                    }
01777                                    break;
01778 
01779                               case 1:
01780                                    if (DKIM_ISLWSP(*p))
01781                                    {
01782                                           break;
01783                                    }
01784                                    else if (*p == '\r')
01785                                    {
01786                                           cur->canon_bodystate = 2;
01787                                    }
01788                                    else
01789                                    {
01790                                           dkim_canon_flushblanks(cur);
01791                                           dkim_canon_buffer(cur, SP, 1);
01792                                           cur->canon_blankline = FALSE;
01793                                           dkim_dstring_cat1(cur->canon_buf,
01794                                                             *p);
01795                                           cur->canon_bodystate = 3;
01796                                    }
01797                                    break;
01798 
01799                               case 2:
01800                                    if (fixcrlf || *p == '\n')
01801                                    {
01802                                           if (cur->canon_blankline)
01803                                           {
01804                                                  cur->canon_blanks++;
01805                                                  cur->canon_bodystate = 0;
01806                                           }
01807                                           else
01808                                           {
01809                                                  dkim_canon_flushblanks(cur);
01810                                                  dkim_canon_buffer(cur,
01811                                                                    dkim_dstring_get(cur->canon_buf),
01812                                                                    dkim_dstring_len(cur->canon_buf));
01813                                                  dkim_canon_buffer(cur,
01814                                                                    CRLF,
01815                                                                    2);
01816                                                  dkim_dstring_blank(cur->canon_buf);
01817 
01818                                                  if (*p == '\n')
01819                                                  {
01820                                                         cur->canon_blankline = TRUE;
01821                                                         cur->canon_bodystate = 0;
01822                                                  }
01823                                                  else if (*p == '\r')
01824                                                  {
01825                                                         cur->canon_blankline = TRUE;
01826                                                  }
01827                                                  else
01828                                                  {
01829                                                         if (DKIM_ISLWSP(*p))
01830                                                         {
01831                                                                cur->canon_bodystate = 1;
01832                                                         }
01833                                                         else
01834                                                         {
01835                                                                dkim_dstring_cat1(cur->canon_buf,
01836                                                                                  *p);
01837                                                                cur->canon_bodystate = 3;
01838                                                         }
01839                                                  }
01840                                           }
01841                                    }
01842                                    else if (*p == '\r')
01843                                    {
01844                                           cur->canon_blankline = FALSE;
01845                                           dkim_dstring_cat1(cur->canon_buf,
01846                                                             *p);
01847                                    }
01848                                    else if (DKIM_ISLWSP(*p))
01849                                    {
01850                                           dkim_canon_flushblanks(cur);
01851                                           dkim_canon_buffer(cur,
01852                                                             dkim_dstring_get(cur->canon_buf),
01853                                                             dkim_dstring_len(cur->canon_buf));
01854                                           dkim_dstring_blank(cur->canon_buf);
01855                                           cur->canon_bodystate = 1;
01856                                    }
01857                                    else
01858                                    {
01859                                           cur->canon_blankline = FALSE;
01860                                           dkim_dstring_cat1(cur->canon_buf,
01861                                                             *p);
01862                                           cur->canon_bodystate = 3;
01863                                    }
01864                                    break;
01865 
01866                               case 3:
01867                                    if (DKIM_ISLWSP(*p))
01868                                    {
01869                                           dkim_canon_flushblanks(cur);
01870                                           dkim_canon_buffer(cur,
01871                                                             dkim_dstring_get(cur->canon_buf),
01872                                                             dkim_dstring_len(cur->canon_buf));
01873                                           dkim_dstring_blank(cur->canon_buf);
01874                                           cur->canon_bodystate = 1;
01875                                    }
01876                                    else if (*p == '\r')
01877                                    {
01878                                           cur->canon_bodystate = 2;
01879                                    }
01880                                    else
01881                                    {
01882                                           dkim_dstring_cat1(cur->canon_buf,
01883                                                             *p);
01884                                    }
01885                                    break;
01886                             }
01887 
01888                             cur->canon_lastchar = *p;
01889                      }
01890 
01891                      dkim_canon_buffer(cur, NULL, 0);
01892 
01893                      break;
01894 
01895                 default:
01896                      assert(0);
01897                      /* NOTREACHED */
01898               }
01899        }
01900 
01901        return DKIM_STAT_OK;
01902 }
01903 
01904 /*
01905 **  DKIM_CANON_CLOSEBODY -- close all body canonicalizations
01906 **
01907 **  Parameters:
01908 **     dkim -- DKIM handle
01909 **
01910 **  Return value:
01911 **     A DKIM_STAT_* constant.
01912 */
01913 
01914 DKIM_STAT
01915 dkim_canon_closebody(DKIM *dkim)
01916 {
01917        DKIM_CANON *cur;
01918 
01919        assert(dkim != NULL);
01920 
01921        for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next)
01922        {
01923               /* skip done hashes or header canonicalizations */
01924               if (cur->canon_done || cur->canon_hdr)
01925                      continue;
01926 
01927               /* "simple" canonicalization must include at least a CRLF */
01928               if (cur->canon_canon == DKIM_CANON_SIMPLE &&
01929                   cur->canon_wrote == 0)
01930                      dkim_canon_buffer(cur, CRLF, 2);
01931 
01932               dkim_canon_buffer(cur, NULL, 0);
01933 
01934               /* finalize */
01935               switch (cur->canon_hashtype)
01936               {
01937 #ifdef USE_GNUTLS
01938                 case DKIM_HASHTYPE_SHA1:
01939                 case DKIM_HASHTYPE_SHA256:
01940                 {
01941                      int alg;
01942                      u_int diglen;
01943                      struct dkim_sha *sha;
01944 
01945                      sha = (struct dkim_sha *) cur->canon_hash;
01946 
01947                      if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1)
01948                             alg = GNUTLS_DIG_SHA1;
01949                      else
01950                             alg = GNUTLS_DIG_SHA256;
01951 
01952                      diglen = gnutls_hash_get_len(alg);
01953 
01954                      sha->sha_out = DKIM_MALLOC(dkim, diglen);
01955                      if (sha->sha_out == NULL)
01956                      {
01957                             dkim_error(dkim, "unable to allocate %u bytes",
01958                                        diglen);
01959                             return DKIM_STAT_NORESOURCE;
01960                      }
01961 
01962                      gnutls_hash_output(sha->sha_hd, sha->sha_out);
01963                      sha->sha_outlen = diglen;
01964 
01965                      break;
01966                 }
01967 #else /* USE_GNUTLS */
01968                 case DKIM_HASHTYPE_SHA1:
01969                 {
01970                      struct dkim_sha1 *sha1;
01971 
01972                      sha1 = (struct dkim_sha1 *) cur->canon_hash;
01973                      SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx);
01974 
01975                      if (sha1->sha1_tmpbio != NULL)
01976                             (void) BIO_flush(sha1->sha1_tmpbio);
01977 
01978                      break;
01979                 }
01980 
01981 # ifdef HAVE_SHA256
01982                 case DKIM_HASHTYPE_SHA256:
01983                 {
01984                      struct dkim_sha256 *sha256;
01985 
01986                      sha256 = (struct dkim_sha256 *) cur->canon_hash;
01987                      SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx);
01988 
01989                      if (sha256->sha256_tmpbio != NULL)
01990                             (void) BIO_flush(sha256->sha256_tmpbio);
01991 
01992                      break;
01993                 }
01994 # endif /* HAVE_SHA256 */
01995 #endif /* USE_GNUTLS */
01996 
01997                 default:
01998                      assert(0);
01999                      /* NOTREACHED */
02000               }
02001 
02002               cur->canon_done = TRUE;
02003        }
02004 
02005        return DKIM_STAT_OK;
02006 }
02007 
02008 /*
02009 **  DKIM_CANON_GETFINAL -- retrieve final digest
02010 **
02011 **  Parameters:
02012 **     canon -- DKIM_CANON handle
02013 **     digest -- pointer to the digest (returned)
02014 **     dlen -- digest length (returned)
02015 **
02016 **  Return value:
02017 **     A DKIM_STAT_* constant.
02018 */
02019 
02020 DKIM_STAT
02021 dkim_canon_getfinal(DKIM_CANON *canon, u_char **digest, size_t *dlen)
02022 {
02023        assert(canon != NULL);
02024        assert(digest != NULL);
02025        assert(dlen != NULL);
02026 
02027        if (!canon->canon_done)
02028               return DKIM_STAT_INVALID;
02029 
02030        switch (canon->canon_hashtype)
02031        {
02032 #ifdef USE_GNUTLS
02033          case DKIM_HASHTYPE_SHA1:
02034          case DKIM_HASHTYPE_SHA256:
02035          {
02036               struct dkim_sha *sha;
02037 
02038               sha = (struct dkim_sha *) canon->canon_hash;
02039               *digest = sha->sha_out;
02040               *dlen = sha->sha_outlen;
02041 
02042               return DKIM_STAT_OK;
02043          }
02044 #else /* USE_GNUTLS */
02045          case DKIM_HASHTYPE_SHA1:
02046          {
02047               struct dkim_sha1 *sha1;
02048 
02049               sha1 = (struct dkim_sha1 *) canon->canon_hash;
02050               *digest = sha1->sha1_out;
02051               *dlen = sizeof sha1->sha1_out;
02052 
02053               return DKIM_STAT_OK;
02054          }
02055 
02056 # ifdef HAVE_SHA256
02057          case DKIM_HASHTYPE_SHA256:
02058          {
02059               struct dkim_sha256 *sha256;
02060 
02061               sha256 = (struct dkim_sha256 *) canon->canon_hash;
02062               *digest = sha256->sha256_out;
02063               *dlen = sizeof sha256->sha256_out;
02064 
02065               return DKIM_STAT_OK;
02066          }
02067 # endif /* HAVE_SHA256 */
02068 #endif /* USE_GNUTLS */
02069 
02070          default:
02071               assert(0);
02072               /* NOTREACHED */
02073               return DKIM_STAT_INTERNAL;
02074        }
02075 }
02076 
02077 /*
02078 **  DKIM_CANON_GETHASHES -- retrieve hashes
02079 **
02080 **  Parameters:
02081 **     sig -- signature from which to get completed hashes
02082 **     hh -- pointer to header hash buffer (returned)
02083 **     hhlen -- bytes used at hh (returned)
02084 **     bh -- pointer to body hash buffer (returned)
02085 **     bhlen -- bytes used at bh (returned)
02086 **
02087 **  Return value:
02088 **     DKIM_STAT_OK -- successful completion
02089 **     DKIM_STAT_INVALID -- hashing hasn't been completed
02090 */
02091 
02092 DKIM_STAT
02093 dkim_canon_gethashes(DKIM_SIGINFO *sig, void **hh, size_t *hhlen,
02094                      void **bh, size_t *bhlen)
02095 {
02096        DKIM_STAT status;
02097        struct dkim_canon *hdc;
02098        struct dkim_canon *bdc;
02099        u_char *hd;
02100        u_char *bd;
02101        size_t hdlen;
02102        size_t bdlen;
02103 
02104        hdc = sig->sig_hdrcanon;
02105        bdc = sig->sig_bodycanon;
02106 
02107        status = dkim_canon_getfinal(hdc, &hd, &hdlen);
02108        if (status != DKIM_STAT_OK)
02109               return status;
02110 
02111        status = dkim_canon_getfinal(bdc, &bd, &bdlen);
02112        if (status != DKIM_STAT_OK)
02113               return status;
02114 
02115        *hh = hd;
02116        *hhlen = hdlen;
02117        *bh = bd;
02118        *bhlen = bdlen;
02119 
02120        return DKIM_STAT_OK;
02121 }