pdkim_cstring_to_canons(const uschar * s, unsigned len,
int * canon_head, int * canon_body)
{
pdkim_cstring_to_canons(const uschar * s, unsigned len,
int * canon_head, int * canon_body)
{
if ( Ustrncmp(s, pdkim_combined_canons[i].str, len) == 0
&& len == Ustrlen(pdkim_combined_canons[i].str))
{
if ( Ustrncmp(s, pdkim_combined_canons[i].str, len) == 0
&& len == Ustrlen(pdkim_combined_canons[i].str))
{
case PDKIM_ERR_RSA_SIGNING: return US"SIGNING";
case PDKIM_ERR_LONG_LINE: return US"LONG_LINE";
case PDKIM_ERR_BUFFER_TOO_SMALL: return US"BUFFER_TOO_SMALL";
case PDKIM_ERR_RSA_SIGNING: return US"SIGNING";
case PDKIM_ERR_LONG_LINE: return US"LONG_LINE";
case PDKIM_ERR_BUFFER_TOO_SMALL: return US"BUFFER_TOO_SMALL";
case PDKIM_SIGN_PRIVKEY_WRAP: return US"PRIVKEY_WRAP";
case PDKIM_SIGN_PRIVKEY_B64D: return US"PRIVKEY_B64D";
default: return US"(unknown)";
case PDKIM_SIGN_PRIVKEY_WRAP: return US"PRIVKEY_WRAP";
case PDKIM_SIGN_PRIVKEY_B64D: return US"PRIVKEY_B64D";
default: return US"(unknown)";
static pdkim_stringlist *
pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str)
{
static pdkim_stringlist *
pdkim_prepend_stringlist(pdkim_stringlist * base, const uschar * str)
{
memset(new_entry, 0, sizeof(pdkim_stringlist));
new_entry->value = string_copy(str);
memset(new_entry, 0, sizeof(pdkim_stringlist));
new_entry->value = string_copy(str);
gstring * cur_tag = NULL;
gstring * cur_val = NULL;
BOOL past_hname = FALSE;
BOOL in_b_val = FALSE;
int where = PDKIM_HDR_LIMBO;
gstring * cur_tag = NULL;
gstring * cur_val = NULL;
BOOL past_hname = FALSE;
BOOL in_b_val = FALSE;
int where = PDKIM_HDR_LIMBO;
uschar * elem;
if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
uschar * elem;
if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
if (Ustrcmp(elem, pdkim_keytypes[i]) == 0)
{ sig->keytype = i; break; }
if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
if (Ustrcmp(elem, pdkim_keytypes[i]) == 0)
{ sig->keytype = i; break; }
if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
if (Ustrcmp(elem, pdkim_hashes[i].dkim_hashname) == 0)
{ sig->hashtype = i; break; }
}
if (Ustrcmp(elem, pdkim_hashes[i].dkim_hashname) == 0)
{ sig->hashtype = i; break; }
}
&sig->canon_headers, &sig->canon_body);
break;
case 'q': /* Query method (for pubkey)*/
&sig->canon_headers, &sig->canon_body);
break;
case 'q': /* Query method (for pubkey)*/
if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
{
sig->querymethod = i; /* we never actually use this */
if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
{
sig->querymethod = i; /* we never actually use this */
memset(pub, 0, sizeof(pdkim_pubkey));
while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
memset(pub, 0, sizeof(pdkim_pubkey));
while ((ele = string_nextinlist(&raw_record, &sep, NULL, 0)))
relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
relaxed_data->data = US (relaxed_data+1);
relaxed_data = store_malloc(sizeof(blob) + orig_data->len+1);
relaxed_data->data = US (relaxed_data+1);
{
DEBUG(D_acl) debug_printf("PDKIM: finish bodyhash %d/%d/%ld len %ld\n",
b->hashtype, b->canon_method, b->bodylength, b->signed_body_bytes);
{
DEBUG(D_acl) debug_printf("PDKIM: finish bodyhash %d/%d/%ld len %ld\n",
b->hashtype, b->canon_method, b->bodylength, b->signed_body_bytes);
/* In simple body mode, if any empty lines were buffered,
replace with one. rfc 4871 3.4.3 */
/*XXX checking the signed-body-bytes is a gross hack; I think
it indicates that all linebreaks should be buffered, including
the one terminating a text line */
/* In simple body mode, if any empty lines were buffered,
replace with one. rfc 4871 3.4.3 */
/*XXX checking the signed-body-bytes is a gross hack; I think
it indicates that all linebreaks should be buffered, including
the one terminating a text line */
if ( b->canon_method == PDKIM_CANON_SIMPLE
&& b->signed_body_bytes == 0
&& b->num_buffered_blanklines > 0
if ( b->canon_method == PDKIM_CANON_SIMPLE
&& b->signed_body_bytes == 0
&& b->num_buffered_blanklines > 0
pdkim_bodyline_complete(pdkim_ctx * ctx)
{
blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
pdkim_bodyline_complete(pdkim_ctx * ctx)
{
blob line = {.data = ctx->linebuf, .len = ctx->linebuf_offset};
/* Empty lines need to be buffered until we find a non-empty line */
if (memcmp(line.data, "\r\n", 2) == 0)
{
/* Empty lines need to be buffered until we find a non-empty line */
if (memcmp(line.data, "\r\n", 2) == 0)
{
/* SIGNING -------------------------------------------------------------- */
if (ctx->flags & PDKIM_MODE_SIGN)
/* SIGNING -------------------------------------------------------------- */
if (ctx->flags & PDKIM_MODE_SIGN)
/* Add header to the signed headers list (in reverse order) */
sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
/* Add header to the signed headers list (in reverse order) */
sig->headers = pdkim_prepend_stringlist(sig->headers, ctx->cur_header->s);
DKIM_SIGNATURE_HEADERNAME,
Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
{
DKIM_SIGNATURE_HEADERNAME,
Ustrlen(DKIM_SIGNATURE_HEADERNAME)) == 0)
{
/* Create and chain new signature block. We could error-check for all
required tags here, but prefer to create the internal sig and expicitly
fail verification of it later. */
/* Create and chain new signature block. We could error-check for all
required tags here, but prefer to create the internal sig and expicitly
fail verification of it later. */
+
+ if (--dkim_collect_input == 0)
+ {
+ ctx->headers = pdkim_prepend_stringlist(ctx->headers, ctx->cur_header->s);
+ ctx->cur_header->s[ctx->cur_header->ptr = 0] = '\0';
+ return PDKIM_ERR_EXCESS_SIGS;
+ }
/* Alternate EOD signal, used in non-dotstuffing mode */
if (!data)
pdkim_body_complete(ctx);
/* Alternate EOD signal, used in non-dotstuffing mode */
if (!data)
pdkim_body_complete(ctx);
if (Ustrcmp(p->keytype, pdkim_keytypes[i]) == 0)
{ sig->keytype = i; goto k_ok; }
DEBUG(D_acl) debug_printf("verify_init: unhandled keytype %s\n", p->keytype);
if (Ustrcmp(p->keytype, pdkim_keytypes[i]) == 0)
{ sig->keytype = i; goto k_ok; }
DEBUG(D_acl) debug_printf("verify_init: unhandled keytype %s\n", p->keytype);
rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
if (rnl) store_free(rnl);
}
rnl = pdkim_update_ctx_bodyhash(b, &lineending, rnl);
if (rnl) store_free(rnl);
}
- for (sig->headernames = NULL, /* Collected signed header names */
- p = sig->headers; p; p = p->next)
+ sig->headernames = NULL; /* Collected signed header names */
+ for (pdkim_stringlist * p = sig->headers; p; p = p->next)
if ( hdrs->tag == 0
&& strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
&& (hdrs->value)[Ustrlen(p)] == ':'
if ( hdrs->tag == 0
&& strncasecmp(CCS hdrs->value, CCS p, Ustrlen(p)) == 0
&& (hdrs->value)[Ustrlen(p)] == ':'
memset(ctx, 0, sizeof(pdkim_ctx));
if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
memset(ctx, 0, sizeof(pdkim_ctx));
if (dot_stuffing) ctx->flags = PDKIM_DOT_TERM;
DEBUG(D_receive) debug_printf("PDKIM: new bodyhash %d/%d/%ld\n",
hashtype, canon_method, bodylength);
DEBUG(D_receive) debug_printf("PDKIM: new bodyhash %d/%d/%ld\n",
hashtype, canon_method, bodylength);
{
memset(ctx, 0, sizeof(pdkim_ctx));
ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;
{
memset(ctx, 0, sizeof(pdkim_ctx));
ctx->flags = dot_stuffed ? PDKIM_MODE_SIGN | PDKIM_DOT_TERM : PDKIM_MODE_SIGN;