Пример #1
0
        internal static ArcSignatureValidationResult GetArcHeaderSets(MimeMessage message, bool throwOnError, out ArcHeaderSet[] sets, out int count)
        {
            ArcHeaderSet set;

            sets  = new ArcHeaderSet[50];
            count = 0;

            for (int i = 0; i < message.Headers.Count; i++)
            {
                Dictionary <string, string> parameters = null;
                var    header = message.Headers[i];
                int    instance;
                string value;

                switch (header.Id)
                {
                case HeaderId.ArcAuthenticationResults:
                    if (!AuthenticationResults.TryParse(header.RawValue, out AuthenticationResults authres))
                    {
                        if (throwOnError)
                        {
                            throw new FormatException("Invalid ARC-Authentication-Results header.");
                        }

                        return(ArcSignatureValidationResult.Fail);
                    }

                    if (!authres.Instance.HasValue)
                    {
                        if (throwOnError)
                        {
                            throw new FormatException("Missing instance tag in ARC-Authentication-Results header.");
                        }

                        return(ArcSignatureValidationResult.Fail);
                    }

                    instance = authres.Instance.Value;

                    if (instance < 1 || instance > 50)
                    {
                        if (throwOnError)
                        {
                            throw new FormatException(string.Format("Invalid instance tag in ARC-Authentication-Results header: i={0}", instance));
                        }

                        return(ArcSignatureValidationResult.Fail);
                    }
                    break;

                case HeaderId.ArcMessageSignature:
                case HeaderId.ArcSeal:
                    try {
                        parameters = ParseParameterTags(header.Id, header.Value);
                    } catch {
                        if (throwOnError)
                        {
                            throw;
                        }

                        return(ArcSignatureValidationResult.Fail);
                    }

                    if (!parameters.TryGetValue("i", out value))
                    {
                        if (throwOnError)
                        {
                            throw new FormatException(string.Format("Missing instance tag in {0} header.", header.Id.ToHeaderName()));
                        }

                        return(ArcSignatureValidationResult.Fail);
                    }

                    if (!int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out instance) || instance < 1 || instance > 50)
                    {
                        if (throwOnError)
                        {
                            throw new FormatException(string.Format("Invalid instance tag in {0} header: i={1}", header.Id.ToHeaderName(), value));
                        }

                        return(ArcSignatureValidationResult.Fail);
                    }
                    break;

                default:
                    instance = 0;
                    break;
                }

                if (instance == 0)
                {
                    continue;
                }

                set = sets[instance - 1];
                if (set == null)
                {
                    sets[instance - 1] = set = new ArcHeaderSet();
                }

                if (!set.Add(header, parameters))
                {
                    return(ArcSignatureValidationResult.Fail);
                }

                if (instance > count)
                {
                    count = instance;
                }
            }

            if (count == 0)
            {
                // there are no ARC sets
                return(ArcSignatureValidationResult.None);
            }

            // verify that all ARC sets are complete
            for (int i = 0; i < count; i++)
            {
                set = sets[i];

                if (set == null)
                {
                    if (throwOnError)
                    {
                        throw new FormatException(string.Format("Missing ARC headers for i={0}", i + 1));
                    }

                    return(ArcSignatureValidationResult.Fail);
                }

                if (set.ArcAuthenticationResult == null)
                {
                    if (throwOnError)
                    {
                        throw new FormatException(string.Format("Missing ARC-Authentication-Results header for i={0}", i + 1));
                    }

                    return(ArcSignatureValidationResult.Fail);
                }

                if (set.ArcMessageSignature == null)
                {
                    if (throwOnError)
                    {
                        throw new FormatException(string.Format("Missing ARC-Message-Signature header for i={0}", i + 1));
                    }

                    return(ArcSignatureValidationResult.Fail);
                }

                if (set.ArcSeal == null)
                {
                    if (throwOnError)
                    {
                        throw new FormatException(string.Format("Missing ARC-Seal header for i={0}", i + 1));
                    }

                    return(ArcSignatureValidationResult.Fail);
                }

                if (!set.ArcSealParameters.TryGetValue("cv", out string cv))
                {
                    if (throwOnError)
                    {
                        throw new FormatException(string.Format("Missing chain validation tag in ARC-Seal header for i={0}.", i + 1));
                    }

                    return(ArcSignatureValidationResult.Fail);
                }

                // The "cv" value for all ARC-Seal header fields MUST NOT be
                // "fail". For ARC Sets with instance values > 1, the values
                // MUST be "pass". For the ARC Set with instance value = 1, the
                // value MUST be "none".
                if (!cv.Equals(i == 0 ? "none" : "pass", StringComparison.Ordinal))
                {
                    return(ArcSignatureValidationResult.Fail);
                }
            }

            return(ArcSignatureValidationResult.Pass);
        }