- /* VERIFICATION ----------------------------------------------------------- */
- /* When verifying, walk through the header name list in the h= parameter and
- add the headers to the hash in that order. */
- else {
- char *b = strdup(sig->headernames);
- char *p = b;
- char *q = NULL;
- if (b == NULL) return PDKIM_ERR_OOM;
-
- while(1) {
- pdkim_stringlist *hdrs = sig->headers;
- q = strchr(p,':');
- if (q != NULL) *q = '\0';
- while (hdrs != NULL) {
- if ( (strncasecmp(hdrs->value,p,strlen(p)) == 0) &&
- ((hdrs->value)[strlen(p)] == ':') ) {
- char *rh = NULL;
- if (sig->canon_headers == PDKIM_CANON_RELAXED)
- rh = pdkim_relax_header(hdrs->value,1); /* cook header for relaxed canon */
- else
- rh = strdup(hdrs->value); /* just copy it for simple canon */
- if (rh == NULL) return PDKIM_ERR_OOM;
- /* Feed header to the hash algorithm */
- if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh));
- else
- sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh));
- #ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
- #endif
- free(rh);
- (hdrs->value)[0] = '_';
- break;
- }
- hdrs = hdrs->next;
- }
- if (q == NULL) break;
- p = q+1;
+
+ DEBUG(D_acl) debug_printf(
+ "PDKIM >> Header data for hash, canonicalized, in sequence >>>>>>>>>>>>\n");
+
+ /* SIGNING ---------------------------------------------------------------- */
+ /* When signing, walk through our header list and add them to the hash. As we
+ go, construct a list of the header's names to use for the h= parameter.
+ Then append to that list any remaining header names for which there was no
+ header to sign. */
+
+ if (ctx->flags & PDKIM_MODE_SIGN)
+ {
+ uschar * headernames = NULL; /* Collected signed header names */
+ int hs = 0, hl = 0;
+ pdkim_stringlist *p;
+ const uschar * l;
+ uschar * s;
+ int sep = 0;
+
+ for (p = sig->headers; p; p = p->next)
+ if (header_name_match(p->value, sig->sign_headers) == PDKIM_OK)
+ {
+ uschar * rh;
+ /* Collect header names (Note: colon presence is guaranteed here) */
+ uschar * q = Ustrchr(p->value, ':');
+
+ headernames = string_catn(headernames, &hs, &hl,
+ p->value, (q - US p->value) + (p->next ? 1 : 0));
+
+ rh = sig->canon_headers == PDKIM_CANON_RELAXED
+ ? pdkim_relax_header(p->value, TRUE) /* cook header for relaxed canon */
+ : string_copy(CUS p->value); /* just copy it for simple canon */
+
+ /* Feed header to the hash algorithm */
+ exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
+
+ /* Remember headers block for signing (when the library cannot do incremental) */
+ (void) exim_dkim_data_append(&hdata, &hdata_alloc, rh);
+
+ DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
+ }
+
+ l = sig->sign_headers;
+ while((s = string_nextinlist(&l, &sep, NULL, 0)))
+ if (*s != '_')
+ { /*SSS string_append_listele() */
+ if (hl > 0 && headernames[hl-1] != ':')
+ headernames = string_catn(headernames, &hs, &hl, US":", 1);
+
+ headernames = string_cat(headernames, &hs, &hl, s);
+ }
+ headernames[hl] = '\0';
+
+ /* Copy headernames to signature struct */
+ sig->headernames = headernames;
+
+ /* Create signature header with b= omitted */
+ sig_hdr = pdkim_create_header(sig, FALSE);
+ }
+
+ /* VERIFICATION ----------------------------------------------------------- */
+ /* When verifying, walk through the header name list in the h= parameter and
+ add the headers to the hash in that order. */
+ else
+ {
+ uschar * p = sig->headernames;
+ uschar * q;
+ pdkim_stringlist * hdrs;
+
+ if (p)
+ {
+ /* clear tags */
+ for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
+ hdrs->tag = 0;
+
+ p = string_copy(p);
+ while(1)
+ {
+ if ((q = Ustrchr(p, ':')))
+ *q = '\0';
+
+ /*XXX walk the list of headers in same order as received. */
+ for (hdrs = ctx->headers; hdrs; hdrs = hdrs->next)
+ if ( hdrs->tag == 0
+ && strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
+ && (hdrs->value)[Ustrlen(p)] == ':'
+ )
+ {
+ /* cook header for relaxed canon, or just copy it for simple */
+
+ uschar * rh = sig->canon_headers == PDKIM_CANON_RELAXED
+ ? pdkim_relax_header(hdrs->value, TRUE)
+ : string_copy(CUS hdrs->value);
+
+ /* Feed header to the hash algorithm */
+ exim_sha_update(&hhash_ctx, CUS rh, Ustrlen(rh));
+
+ DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
+ hdrs->tag = 1;
+ break;
+ }
+
+ if (!q) break;
+ p = q+1;
+ }
+
+ sig_hdr = string_copy(sig->rawsig_no_b_val);