- if (sig->algo == PDKIM_ALGO_RSA_SHA1)
- sha1_starts(&sha1_headers);
- else
- sha2_starts(&sha2_headers,0);
-
- #ifdef PDKIM_DEBUG
- if (ctx->debug_stream)
- fprintf(ctx->debug_stream,
- "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
- #endif
-
- /* 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. */
- if (ctx->mode == PDKIM_MODE_SIGN) {
- pdkim_stringlist *p = sig->headers;
- while (p != NULL) {
- char *rh = NULL;
- /* Collect header names (Note: colon presence is guaranteed here) */
- char *q = strchr(p->value,':');
- if (pdkim_strncat(headernames, p->value,
- (q-(p->value))+((p->next==NULL)?0:1)) == NULL)
- return PDKIM_ERR_OOM;
-
- if (sig->canon_headers == PDKIM_CANON_RELAXED)
- rh = pdkim_relax_header(p->value,1); /* cook header for relaxed canon */
- else
- rh = strdup(p->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);
- p = p->next;
- }
+/* SIGNING -------------------------------------------------------------- */
+if (ctx->mode == PDKIM_MODE_SIGN)
+ if (!(headernames = pdkim_strnew(NULL)))
+ return PDKIM_ERR_OOM;
+/* ---------------------------------------------------------------------- */
+
+while (sig)
+ {
+ BOOL is_sha1 = sig->algo == PDKIM_ALGO_RSA_SHA1;
+ hctx hhash_ctx;
+ char * sig_hdr;
+ blob hhash;
+ blob hdata;
+ int hdata_alloc = 0;
+
+ hdata.data = NULL;
+ hdata.len = 0;
+
+ exim_sha_init(&hhash_ctx, is_sha1);
+
+ DEBUG(D_acl) debug_printf(
+ "PDKIM >> Hashed header data, 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->mode == PDKIM_MODE_SIGN)
+ {
+ 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, ':');
+
+ if (!(pdkim_strncat(headernames, p->value,
+ (q - US p->value) + (p->next ? 1 : 0))))
+ return PDKIM_ERR_OOM;
+
+ rh = sig->canon_headers == PDKIM_CANON_RELAXED
+ ? US pdkim_relax_header(p->value, 1) /* cook header for relaxed canon */
+ : string_copy(CUS p->value); /* just copy it for simple canon */
+ if (!rh)
+ return PDKIM_ERR_OOM;
+
+ /* Feed header to the hash algorithm */
+ exim_sha_update(&hhash_ctx, CCS rh, Ustrlen(rh));
+
+ /* Remember headers block for signing (when the library cannot do incremental) */
+ (void) exim_rsa_data_append(&hdata, &hdata_alloc, rh);
+
+ DEBUG(D_acl) pdkim_quoteprint(rh, Ustrlen(rh));
+ }
+
+ l = US sig->sign_headers;
+ while((s = string_nextinlist(&l, &sep, NULL, 0)))
+ if (*s != '_')
+ { /*SSS string_append_listele() */
+ if (headernames->len > 0 && headernames->str[headernames->len-1] != ':')
+ if (!(pdkim_strncat(headernames, ":", 1)))
+ return PDKIM_ERR_OOM;
+ if (!(pdkim_strncat(headernames, CS s, Ustrlen(s))))
+ return PDKIM_ERR_OOM;
+ }