Esempio n. 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapLiteral"/> class.
        /// </summary>
        /// <remarks>
        /// Creates a new <see cref="MailKit.Net.Imap.ImapLiteral"/>.
        /// </remarks>
        /// <param name="options">The formatting options.</param>
        /// <param name="literal">The literal.</param>
        /// <param name="action">The progress update action.</param>
        public ImapLiteral(FormatOptions options, object literal, Action <int> action = null)
        {
            format = options.Clone();
            format.NewLineFormat = NewLineFormat.Dos;

            update = action;

            if (literal is MimeMessage)
            {
                Type = ImapLiteralType.MimeMessage;
            }
            else if (literal is Stream)
            {
                Type = ImapLiteralType.Stream;
            }
            else if (literal is string)
            {
                literal = Encoding.UTF8.GetBytes((string)literal);
                Type    = ImapLiteralType.String;
            }
            else if (literal is byte[])
            {
                Type = ImapLiteralType.String;
            }
            else
            {
                throw new ArgumentException("Unknown literal type");
            }

            Literal = literal;
        }
Esempio n. 2
0
        async Task ArcSignAsync(FormatOptions options, MimeMessage message, IList <string> headers, bool doAsync, CancellationToken cancellationToken)
        {
            ArcVerifier.GetArcHeaderSets(message, true, out ArcHeaderSet[] sets, out int count, out var errors);
            AuthenticationResults authres;
            int    instance = count + 1;
            string cv;

            // do not sign if there is already a failed/invalid ARC-Seal.
            if (count > 0 && (errors & ArcValidationErrors.InvalidArcSealChainValidationValue) != 0)
            {
                return;
            }

            options = options.Clone();
            options.NewLineFormat = NewLineFormat.Dos;
            options.EnsureNewLine = true;

            if (doAsync)
            {
                authres = await GenerateArcAuthenticationResultsAsync(options, message, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                authres = GenerateArcAuthenticationResults(options, message, cancellationToken);
            }

            if (authres == null)
            {
                return;
            }

            authres.Instance = instance;

            var aar = new Header(HeaderId.ArcAuthenticationResults, authres.ToString());

            cv = "none";

            if (count > 0)
            {
                cv = "pass";

                foreach (var method in authres.Results)
                {
                    if (method.Method.Equals("arc", StringComparison.OrdinalIgnoreCase))
                    {
                        cv = method.Result;
                        break;
                    }
                }
            }

            var t    = GetTimestamp();
            var ams  = GenerateArcMessageSignature(options, message, instance, t, headers);
            var seal = GenerateArcSeal(options, instance, cv, t, sets, count, aar, ams);

            message.Headers.Insert(0, aar);
            message.Headers.Insert(0, ams);
            message.Headers.Insert(0, seal);
        }
Esempio n. 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapLiteral"/> class.
        /// </summary>
        /// <remarks>
        /// Creates a new <see cref="MailKit.Net.Imap.ImapLiteral"/>.
        /// </remarks>
        /// <param name="options">The formatting options.</param>
        /// <param name="literal">The literal.</param>
        public ImapLiteral(FormatOptions options, byte[] literal)
        {
            format = options.Clone();
            format.NewLineFormat = NewLineFormat.Dos;

            Type    = ImapLiteralType.String;
            Literal = literal;
        }
Esempio n. 4
0
        async Task <bool> VerifyArcSealAsync(FormatOptions options, ArcHeaderSet[] sets, int i, bool doAsync, CancellationToken cancellationToken)
        {
            DkimSignatureAlgorithm algorithm;
            AsymmetricKeyParameter key;
            string d, s, q, b;

            ValidateArcSealParameters(sets[i].ArcSealParameters, out algorithm, out d, out s, out q, out b);

            if (!IsEnabled(algorithm))
            {
                return(false);
            }

            if (doAsync)
            {
                key = await PublicKeyLocator.LocatePublicKeyAsync(q, d, s, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                key = PublicKeyLocator.LocatePublicKey(q, d, s, cancellationToken);
            }

            if ((key is RsaKeyParameters rsa) && rsa.Modulus.BitLength < MinimumRsaKeyLength)
            {
                return(false);
            }

            options = options.Clone();
            options.NewLineFormat = NewLineFormat.Dos;

            using (var stream = new DkimSignatureStream(CreateVerifyContext(algorithm, key))) {
                using (var filtered = new FilteredStream(stream)) {
                    filtered.Add(options.CreateNewLineFilter());

                    for (int j = 0; j < i; j++)
                    {
                        WriteHeaderRelaxed(options, filtered, sets[j].ArcAuthenticationResult, false);
                        WriteHeaderRelaxed(options, filtered, sets[j].ArcMessageSignature, false);
                        WriteHeaderRelaxed(options, filtered, sets[j].ArcSeal, false);
                    }

                    WriteHeaderRelaxed(options, filtered, sets[i].ArcAuthenticationResult, false);
                    WriteHeaderRelaxed(options, filtered, sets[i].ArcMessageSignature, false);

                    // now include the ARC-Seal header that we are verifying,
                    // but only after removing the "b=" signature value.
                    var seal = GetSignedSignatureHeader(sets[i].ArcSeal);

                    WriteHeaderRelaxed(options, filtered, seal, true);

                    filtered.Flush();
                }

                return(stream.VerifySignature(b));
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MailKit.Net.Imap.ImapLiteral"/> class.
        /// </summary>
        /// <remarks>
        /// Creates a new <see cref="MailKit.Net.Imap.ImapLiteral"/>.
        /// </remarks>
        /// <param name="options">The formatting options.</param>
        /// <param name="literal">The literal.</param>
        /// <param name="action">The progress update action.</param>
        public ImapLiteral(FormatOptions options, MimeMessage literal, Action <int> action = null)
        {
            format = options.Clone();
            format.NewLineFormat = NewLineFormat.Dos;

            update = action;

            Type    = ImapLiteralType.MimeMessage;
            Literal = literal;
        }
Esempio n. 6
0
        async Task <bool> VerifyArcMessageSignatureAsync(FormatOptions options, MimeMessage message, Header arcSignature, Dictionary <string, string> parameters, bool doAsync, CancellationToken cancellationToken)
        {
            DkimCanonicalizationAlgorithm headerAlgorithm, bodyAlgorithm;
            DkimSignatureAlgorithm        signatureAlgorithm;
            AsymmetricKeyParameter        key;
            string d, s, q, bh, b;

            string[] headers;
            int      maxLength;

            ValidateArcMessageSignatureParameters(parameters, out signatureAlgorithm, out headerAlgorithm, out bodyAlgorithm,
                                                  out d, out s, out q, out headers, out bh, out b, out maxLength);

            if (!IsEnabled(signatureAlgorithm))
            {
                return(false);
            }

            options = options.Clone();
            options.NewLineFormat = NewLineFormat.Dos;

            // first check the body hash (if that's invalid, then the entire signature is invalid)
            if (!VerifyBodyHash(options, message, signatureAlgorithm, bodyAlgorithm, maxLength, bh))
            {
                return(false);
            }

            if (doAsync)
            {
                key = await PublicKeyLocator.LocatePublicKeyAsync(q, d, s, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                key = PublicKeyLocator.LocatePublicKey(q, d, s, cancellationToken);
            }

            if ((key is RsaKeyParameters rsa) && rsa.Modulus.BitLength < MinimumRsaKeyLength)
            {
                return(false);
            }

            return(VerifySignature(options, message, arcSignature, signatureAlgorithm, key, headers, headerAlgorithm, b));
        }
Esempio n. 7
0
        async Task <bool> VerifyAsync(FormatOptions options, MimeMessage message, Header dkimSignature, bool doAsync, CancellationToken cancellationToken)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (dkimSignature == null)
            {
                throw new ArgumentNullException(nameof(dkimSignature));
            }

            if (dkimSignature.Id != HeaderId.DkimSignature)
            {
                throw new ArgumentException("The signature parameter MUST be a DKIM-Signature header.", nameof(dkimSignature));
            }

            var parameters = ParseParameterTags(dkimSignature.Id, dkimSignature.Value);
            DkimCanonicalizationAlgorithm headerAlgorithm, bodyAlgorithm;
            DkimSignatureAlgorithm        signatureAlgorithm;
            AsymmetricKeyParameter        key;
            string d, s, q, bh, b;

            string[] headers;
            int      maxLength;

            ValidateDkimSignatureParameters(parameters, out signatureAlgorithm, out headerAlgorithm, out bodyAlgorithm,
                                            out d, out s, out q, out headers, out bh, out b, out maxLength);

            if (!IsEnabled(signatureAlgorithm))
            {
                return(false);
            }

            if (doAsync)
            {
                key = await PublicKeyLocator.LocatePublicKeyAsync(q, d, s, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                key = PublicKeyLocator.LocatePublicKey(q, d, s, cancellationToken);
            }

            if ((key is RsaKeyParameters rsa) && rsa.Modulus.BitLength < MinimumRsaKeyLength)
            {
                return(false);
            }

            options = options.Clone();
            options.NewLineFormat = NewLineFormat.Dos;

            // first check the body hash (if that's invalid, then the entire signature is invalid)
            var hash = Convert.ToBase64String(message.HashBody(options, signatureAlgorithm, bodyAlgorithm, maxLength));

            if (hash != bh)
            {
                return(false);
            }

            using (var stream = new DkimSignatureStream(CreateVerifyContext(signatureAlgorithm, key))) {
                using (var filtered = new FilteredStream(stream)) {
                    filtered.Add(options.CreateNewLineFilter());

                    WriteHeaders(options, message, headers, headerAlgorithm, filtered);

                    // now include the DKIM-Signature header that we are verifying,
                    // but only after removing the "b=" signature value.
                    var header = GetSignedSignatureHeader(dkimSignature);

                    switch (headerAlgorithm)
                    {
                    case DkimCanonicalizationAlgorithm.Relaxed:
                        WriteHeaderRelaxed(options, filtered, header, true);
                        break;

                    default:
                        WriteHeaderSimple(options, filtered, header, true);
                        break;
                    }

                    filtered.Flush();
                }

                return(stream.VerifySignature(b));
            }
        }
Esempio n. 8
0
        void DkimSign(FormatOptions options, MimeMessage message, IList <string> headers)
        {
            var value = new StringBuilder("v=1");
            var t     = GetTimestamp();

            byte[] signature, hash;
            Header dkim;

            options = options.Clone();
            options.NewLineFormat = NewLineFormat.Dos;
            options.EnsureNewLine = true;

            switch (SignatureAlgorithm)
            {
            case DkimSignatureAlgorithm.Ed25519Sha256:
                value.Append("; a=ed25519-sha256");
                break;

            case DkimSignatureAlgorithm.RsaSha256:
                value.Append("; a=rsa-sha256");
                break;

            default:
                value.Append("; a=rsa-sha1");
                break;
            }

            value.AppendFormat("; d={0}; s={1}", Domain, Selector);
            value.AppendFormat("; c={0}/{1}",
                               HeaderCanonicalizationAlgorithm.ToString().ToLowerInvariant(),
                               BodyCanonicalizationAlgorithm.ToString().ToLowerInvariant());
            if (!string.IsNullOrEmpty(QueryMethod))
            {
                value.AppendFormat("; q={0}", QueryMethod);
            }
            if (!string.IsNullOrEmpty(AgentOrUserIdentifier))
            {
                value.AppendFormat("; i={0}", AgentOrUserIdentifier);
            }
            value.AppendFormat("; t={0}", t);

            using (var stream = new DkimSignatureStream(CreateSigningContext())) {
                using (var filtered = new FilteredStream(stream)) {
                    filtered.Add(options.CreateNewLineFilter());

                    // write the specified message headers
                    DkimVerifierBase.WriteHeaders(options, message, headers, HeaderCanonicalizationAlgorithm, filtered);

                    value.AppendFormat("; h={0}", string.Join(":", headers.ToArray()));

                    hash = message.HashBody(options, SignatureAlgorithm, BodyCanonicalizationAlgorithm, -1);
                    value.AppendFormat("; bh={0}", Convert.ToBase64String(hash));
                    value.Append("; b=");

                    dkim = new Header(HeaderId.DkimSignature, value.ToString());
                    message.Headers.Insert(0, dkim);

                    switch (HeaderCanonicalizationAlgorithm)
                    {
                    case DkimCanonicalizationAlgorithm.Relaxed:
                        DkimVerifierBase.WriteHeaderRelaxed(options, filtered, dkim, true);
                        break;

                    default:
                        DkimVerifierBase.WriteHeaderSimple(options, filtered, dkim, true);
                        break;
                    }

                    filtered.Flush();
                }

                signature = stream.GenerateSignature();

                dkim.Value += Convert.ToBase64String(signature);
            }
        }
Esempio n. 9
0
        async Task <bool> VerifyAsync(FormatOptions options, MimeMessage message, Header dkimSignature, bool doAsync, CancellationToken cancellationToken)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (dkimSignature == null)
            {
                throw new ArgumentNullException(nameof(dkimSignature));
            }

            if (dkimSignature.Id != HeaderId.DkimSignature)
            {
                throw new ArgumentException("The signature parameter MUST be a DKIM-Signature header.", nameof(dkimSignature));
            }

            var parameters = ParseParameterTags(dkimSignature.Id, dkimSignature.Value);
            DkimCanonicalizationAlgorithm headerAlgorithm, bodyAlgorithm;
            DkimSignatureAlgorithm        signatureAlgorithm;
            AsymmetricKeyParameter        key;
            string d, s, q, bh, b;

            string[] headers;
            int      maxLength;

            ValidateDkimSignatureParameters(parameters, out signatureAlgorithm, out headerAlgorithm, out bodyAlgorithm,
                                            out d, out s, out q, out headers, out bh, out b, out maxLength);

            if (!IsEnabled(signatureAlgorithm))
            {
                return(false);
            }

            options = options.Clone();
            options.NewLineFormat = NewLineFormat.Dos;

            // first check the body hash (if that's invalid, then the entire signature is invalid)
            if (!VerifyBodyHash(options, message, signatureAlgorithm, bodyAlgorithm, maxLength, bh))
            {
                return(false);
            }

            if (doAsync)
            {
                key = await PublicKeyLocator.LocatePublicKeyAsync(q, d, s, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                key = PublicKeyLocator.LocatePublicKey(q, d, s, cancellationToken);
            }

            if ((key is RsaKeyParameters rsa) && rsa.Modulus.BitLength < MinimumRsaKeyLength)
            {
                return(false);
            }

            return(VerifySignature(options, message, dkimSignature, signatureAlgorithm, key, headers, headerAlgorithm, b));
        }