static void ValidateDkimSignatureParameters (IDictionary<string, string> parameters, out DkimSignatureAlgorithm algorithm, out DkimCanonicalizationAlgorithm headerAlgorithm,
out DkimCanonicalizationAlgorithm bodyAlgorithm, out string d, out string s, out string q, out string[] headers, out string bh, out string b, out int maxLength)
{
bool containsFrom = false;
string v, a, c, h, l, id;
if (!parameters.TryGetValue ("v", out v))
throw new FormatException ("Malformed DKIM-Signature header: no version parameter detected.");
if (v != "1")
throw new FormatException (string.Format ("Unrecognized DKIM-Signature version: v={0}", v));
if (!parameters.TryGetValue ("a", out a))
throw new FormatException ("Malformed DKIM-Signature header: no signature algorithm parameter detected.");
switch (a.ToLowerInvariant ()) {
case "rsa-sha256": algorithm = DkimSignatureAlgorithm.RsaSha256; break;
case "rsa-sha1": algorithm = DkimSignatureAlgorithm.RsaSha1; break;
default: throw new FormatException (string.Format ("Unrecognized DKIM-Signature algorithm parameter: a={0}", a));
}
if (!parameters.TryGetValue ("d", out d))
throw new FormatException ("Malformed DKIM-Signature header: no domain parameter detected.");
if (parameters.TryGetValue ("i", out id)) {
string ident;
int at;
if ((at = id.LastIndexOf ('@')) == -1)
throw new FormatException ("Malformed DKIM-Signature header: no @ in the AUID value.");
ident = id.Substring (at + 1);
if (!ident.Equals (d, StringComparison.OrdinalIgnoreCase) && !ident.EndsWith ("." + d, StringComparison.OrdinalIgnoreCase))
throw new FormatException ("Invalid DKIM-Signature header: the domain in the AUID does not match the domain parameter.");
}
if (!parameters.TryGetValue ("s", out s))
throw new FormatException ("Malformed DKIM-Signature header: no selector parameter detected.");
if (!parameters.TryGetValue ("q", out q))
q = "dns/txt";
if (parameters.TryGetValue ("l", out l)) {
if (!int.TryParse (l, out maxLength))
throw new FormatException (string.Format ("Malformed DKIM-Signature header: invalid length parameter: l={0}", l));
} else {
maxLength = -1;
}
if (parameters.TryGetValue ("c", out c)) {
var tokens = c.ToLowerInvariant ().Split ('/');
if (tokens.Length == 0 || tokens.Length > 2)
throw new FormatException (string.Format ("Malformed DKIM-Signature header: invalid canonicalization parameter: c={0}", c));
switch (tokens[0]) {
case "relaxed": headerAlgorithm = DkimCanonicalizationAlgorithm.Relaxed; break;
case "simple": headerAlgorithm = DkimCanonicalizationAlgorithm.Simple; break;
default: throw new FormatException (string.Format ("Malformed DKIM-Signature header: invalid canonicalization parameter: c={0}", c));
}
if (tokens.Length == 2) {
switch (tokens[1]) {
case "relaxed": bodyAlgorithm = DkimCanonicalizationAlgorithm.Relaxed; break;
case "simple": bodyAlgorithm = DkimCanonicalizationAlgorithm.Simple; break;
default: throw new FormatException (string.Format ("Malformed DKIM-Signature header: invalid canonicalization parameter: c={0}", c));
}
} else {
bodyAlgorithm = DkimCanonicalizationAlgorithm.Simple;
}
} else {
headerAlgorithm = DkimCanonicalizationAlgorithm.Simple;
bodyAlgorithm = DkimCanonicalizationAlgorithm.Simple;
}
if (!parameters.TryGetValue ("h", out h))
throw new FormatException ("Malformed DKIM-Signature header: no signed header parameter detected.");
headers = h.Split (':');
for (int i = 0; i < headers.Length; i++) {
if (headers[i].Equals ("from", StringComparison.OrdinalIgnoreCase)) {
containsFrom = true;
break;
}
}
if (!containsFrom)
throw new FormatException (string.Format ("Malformed DKIM-Signature header: From header not signed."));
if (!parameters.TryGetValue ("bh", out bh))
throw new FormatException ("Malformed DKIM-Signature header: no body hash parameter detected.");
if (!parameters.TryGetValue ("b", out b))
throw new FormatException ("Malformed DKIM-Signature header: no signature parameter detected.");
}