+
+ if (c == ';' || c == '\0')
+ {
+ /* We must have both tag and value, and tags must be one char except
+ for the possibility of "bh". */
+
+ if ( cur_tag && cur_val
+ && (cur_tag->ptr == 1 || *cur_tag->s == 'b')
+ )
+ {
+ (void) string_from_gstring(cur_val);
+ pdkim_strtrim(cur_val);
+
+ DEBUG(D_acl) debug_printf(" %s=%s\n", cur_tag->s, cur_val->s);
+
+ switch (*cur_tag->s)
+ {
+ case 'b': /* sig-data or body-hash */
+ switch (cur_tag->s[1])
+ {
+ case '\0': pdkim_decode_base64(cur_val->s, &sig->sighash); break;
+ case 'h': if (cur_tag->ptr != 2) goto bad_tag;
+ pdkim_decode_base64(cur_val->s, &sig->bodyhash);
+ break;
+ default: goto bad_tag;
+ }
+ break;
+ case 'v': /* version */
+ /* We only support version 1, and that is currently the
+ only version there is. */
+ sig->version =
+ Ustrcmp(cur_val->s, PDKIM_SIGNATURE_VERSION) == 0 ? 1 : -1;
+ break;
+ case 'a': /* algorithm */
+ {
+ const uschar * list = cur_val->s;
+ int sep = '-';
+ uschar * elem;
+
+ if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
+ sig->keytype = pdkim_keyname_to_keytype(elem);
+ if ((elem = string_nextinlist(&list, &sep, NULL, 0)))
+ for (int i = 0; i < nelem(pdkim_hashes); i++)
+ if (Ustrcmp(elem, pdkim_hashes[i].dkim_hashname) == 0)
+ { sig->hashtype = i; break; }
+ }
+ break;
+
+ case 'c': /* canonicalization */
+ pdkim_cstring_to_canons(cur_val->s, 0,
+ &sig->canon_headers, &sig->canon_body);
+ break;
+ case 'q': /* Query method (for pubkey)*/
+ for (int i = 0; pdkim_querymethods[i]; i++)
+ if (Ustrcmp(cur_val->s, pdkim_querymethods[i]) == 0)
+ {
+ sig->querymethod = i; /* we never actually use this */
+ break;
+ }
+ break;
+ case 's': /* Selector */
+ sig->selector = string_copy_from_gstring(cur_val); break;
+ case 'd': /* SDID */
+ sig->domain = string_copy_from_gstring(cur_val); break;
+ case 'i': /* AUID */
+ sig->identity = pdkim_decode_qp(cur_val->s); break;
+ case 't': /* Timestamp */
+ sig->created = strtoul(CS cur_val->s, NULL, 10); break;
+ case 'x': /* Expiration */
+ sig->expires = strtoul(CS cur_val->s, NULL, 10); break;
+ case 'l': /* Body length count */
+ sig->bodylength = strtol(CS cur_val->s, NULL, 10); break;
+ case 'h': /* signed header fields */
+ sig->headernames = string_copy_from_gstring(cur_val); break;
+ case 'z': /* Copied headfields */
+ sig->copiedheaders = pdkim_decode_qp(cur_val->s); break;
+/*XXX draft-ietf-dcrup-dkim-crypto-05 would need 'p' tag support
+for rsafp signatures. But later discussion is dropping those. */
+ default:
+ goto bad_tag;
+ }
+ }
+ else
+bad_tag: DEBUG(D_acl) debug_printf(" Unknown tag encountered: %Y\n", cur_tag);
+
+ cur_tag = cur_val = NULL;
+ in_b_val = FALSE;
+ where = PDKIM_HDR_LIMBO;
+ }
+ else
+ cur_val = string_catn(cur_val, p, 1);