/// <summary>
 /// Initializes a new instance of the <see cref="SendOperation"/> class.
 /// </summary>
 /// <param name="stage">The pipeline stage.</param>
 public SendOperation(ElasticsearchPipelineStage stage)
 {
     mStage                = stage;
     mContentStream        = new MemoryBlockStream(ArrayPool <byte> .Shared);
     mRequestContentWriter = new Utf8JsonWriter(mContentStream, mJsonWriterOptions);
     IsFull                = false;
 }
 /// <summary>
 /// Resets the content stream and the <see cref="IsFull"/> property.
 /// </summary>
 private void ResetContentStream()
 {
     mContentStream?.Dispose();                 // returns buffers back to the pool
     mContentStream        = new MemoryBlockStream(ArrayPool <byte> .Shared);
     mRequestContentWriter = new Utf8JsonWriter(mContentStream, mJsonWriterOptions);
     IsFull = false;
 }
Example #3
0
        static void LoadContent(MimePart attachment, Stream stream)
        {
            var content = new MemoryBlockStream();

            if (attachment.ContentType.IsMimeType("text", "*"))
            {
                var filter = new BestEncodingFilter();
                var buf = new byte[4096];
                int index, length;
                int nread;

                while ((nread = stream.Read(buf, 0, buf.Length)) > 0)
                {
                    filter.Filter(buf, 0, nread, out index, out length);
                    content.Write(buf, 0, nread);
                }

                filter.Flush(buf, 0, 0, out index, out length);

                attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
            }
            else
            {
                attachment.ContentTransferEncoding = ContentEncoding.Base64;
                stream.CopyTo(content, 4096);
            }

            content.Position = 0;

            attachment.Content = new MimeContent(content);
        }
        void LoadContent(MimePart attachment, string fileName)
        {
            var content = new MemoryBlockStream();
            var filter  = new BestEncodingFilter();

            using (var stream = File.OpenRead(fileName)) {
                var buf = new byte[4096];
                int index, length;
                int nread;

                while ((nread = stream.Read(buf, 0, buf.Length)) > 0)
                {
                    filter.Filter(buf, 0, nread, out index, out length);
                    content.Write(buf, 0, nread);
                }

                filter.Flush(buf, 0, 0, out index, out length);
            }

            content.Position = 0;

            if (linked)
            {
                attachment.ContentLocation = new Uri(Path.GetFileName(fileName), UriKind.Relative);
            }

            attachment.ContentTransferEncoding = filter.GetBestEncoding(EncodingConstraint.SevenBit);
            attachment.ContentObject           = new ContentObject(content, ContentEncoding.Default);
        }
Example #5
0
        /// <summary>
        /// Cryptographically signs the specified entity.
        /// </summary>
        /// <remarks>
        /// <para>Signs the entity using the supplied signer and <see cref="SecureMimeContext"/>.</para>
        /// <para>For better interoperability with other mail clients, you should use
        /// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/>
        /// instead as the multipart/signed format is supported among a much larger
        /// subset of mail client software.</para>
        /// </remarks>
        /// <returns>The signed entity.</returns>
        /// <param name="ctx">The S/MIME context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="entity">The entity.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static ApplicationPkcs7Mime Sign(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

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

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

            using (var memory = new MemoryBlockStream()) {
                var options = FormatOptions.CloneDefault();
                options.NewLineFormat = NewLineFormat.Dos;

                entity.WriteTo(options, memory);
                memory.Position = 0;

                return(ctx.EncapsulatedSign(signer, memory));
            }
        }
Example #6
0
        async Task ConstructMimePartAsync(MimePart part, CancellationToken cancellationToken)
        {
            Stream content;
            bool   isEmpty;

            if (persistent)
            {
                long begin = GetOffset(inputIndex);
                long end;

                using (var measured = new MeasuringStream()) {
                    isEmpty = await ScanContentAsync(measured, true, cancellationToken).ConfigureAwait(false);

                    end = begin + measured.Length;
                }

                content = new BoundStream(stream, begin, end, true);
            }
            else
            {
                content = new MemoryBlockStream();
                isEmpty = await ScanContentAsync(content, true, cancellationToken).ConfigureAwait(false);

                content.Seek(0, SeekOrigin.Begin);
            }

            if (!isEmpty)
            {
                part.Content = new MimeContent(content, part.ContentTransferEncoding);
            }
            else
            {
                content.Dispose();
            }
        }
Example #7
0
        public ImapReplayCommand(string tag, string command, string resource, bool compressed = false)
        {
            CommandBuffer = Latin1.GetBytes(command);
            Compressed    = compressed;
            Command       = command;

            using (var stream = GetType().Assembly.GetManifestResourceStream("UnitTests.Net.Imap.Resources." + resource)) {
                using (var memory = new MemoryBlockStream()) {
                    using (Stream compress = new CompressedStream(memory)) {
                        using (var filtered = new FilteredStream(compressed ? compress : memory)) {
                            filtered.Add(new ImapReplayFilter("A########", tag));
                            filtered.Add(new Unix2DosFilter());
                            stream.CopyTo(filtered, 4096);
                            filtered.Flush();
                        }

                        Response = memory.ToArray();
                    }
                }
            }

            if (compressed)
            {
                using (var memory = new MemoryStream()) {
                    using (var compress = new CompressedStream(memory)) {
                        compress.Write(CommandBuffer, 0, CommandBuffer.Length);
                        compress.Flush();

                        CommandBuffer = memory.ToArray();
                    }
                }
            }
        }
Example #8
0
        private static void ParseImplementation(Node node, MimeEntity entity)
        {
            var tmp = new Node("entity", entity.ContentType.MimeType);

            ProcessHeaders(tmp, entity);

            if (entity is MultipartSigned signed)
            {
                // Multipart content.
                var signatures = new Node("signatures");
                foreach (var idx in signed.Verify())
                {
                    if (!idx.Verify())
                    {
                        throw new SecurityException("Signature of MIME message was not valid");
                    }
                    signatures.Add(new Node("fingerprint", idx.SignerCertificate.Fingerprint.ToLower()));
                }
                tmp.Add(signatures);

                // Then traversing content of multipart/signed message.
                foreach (var idx in signed)
                {
                    ParseImplementation(tmp, idx);
                }
            }
            else if (entity is MultipartEncrypted)
            {
                throw new ArgumentException("Magic currently does not support decrypting MIME messages");
            }
            else if (entity is Multipart multi)
            {
                // Multipart content.
                foreach (var idx in multi)
                {
                    ParseImplementation(tmp, idx);
                }
            }
            else if (entity is TextPart text)
            {
                // Singular content type.
                // Notice! We don't really care about the encoding the text was encoded with.
                tmp.Add(new Node("content", text.GetText(out var encoding)));
            }
            else if (entity is MimePart part)
            {
                using (var stream = new MemoryBlockStream())
                {
                    // Decoding content to memory.
                    part.Content.DecodeTo(stream);

                    // Resetting position and setting up a buffer object to hold content.
                    stream.Position = 0;

                    // Putting content into return node for MimeEntity.
                    tmp.Add(new Node("content", stream.ToArray()));
                }
            }
            node.Add(tmp);
        }
Example #9
0
        /// <summary>
        /// Encrypts the specified entity.
        /// </summary>
        /// <remarks>
        /// Encrypts the entity to the specified recipients using the supplied <see cref="SecureMimeContext"/>.
        /// </remarks>
        /// <returns>The encrypted entity.</returns>
        /// <param name="ctx">The S/MIME context to use for encrypting.</param>
        /// <param name="recipients">The recipients.</param>
        /// <param name="entity">The entity.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="recipients"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static ApplicationPkcs7Mime Encrypt(SecureMimeContext ctx, CmsRecipientCollection recipients, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

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

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

            using (var memory = new MemoryBlockStream()) {
                var options = FormatOptions.CloneDefault();
                options.NewLineFormat = NewLineFormat.Dos;

                entity.WriteTo(options, memory);
                memory.Position = 0;

                return(ctx.Encrypt(recipients, memory));
            }
        }
Example #10
0
        /// <summary>
        /// Creates a new <see cref="MultipartSigned"/>.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs the entity using the supplied signer in order
        /// to generate a detached signature and then adds the entity along with
        /// the detached signature data to a new multipart/signed part.
        /// </remarks>
        /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
        /// <param name="ctx">The S/MIME context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="entity">The entity to sign.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static MultipartSigned Create(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

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

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

            using (var memory = new MemoryBlockStream()) {
                var prepared = Prepare(entity, memory);

                memory.Position = 0;

                // sign the cleartext content
                var signature = ctx.Sign(signer, memory);

                return(Create(ctx, signer.DigestAlgorithm, prepared, signature));
            }
        }
Example #11
0
        /// <summary>
        /// Cryptographically signs the specified entity.
        /// </summary>
        /// <remarks>
        /// <para>Signs the entity using the supplied signer, digest algorithm and <see cref="SecureMimeContext"/>.</para>
        /// <para>For better interoperability with other mail clients, you should use
        /// <see cref="MultipartSigned.Create(SecureMimeContext, CmsSigner, MimeEntity)"/>
        /// instead as the multipart/signed format is supported among a much larger
        /// subset of mail client software.</para>
        /// </remarks>
        /// <returns>The signed entity.</returns>
        /// <param name="ctx">The S/MIME context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="digestAlgo">The digest algorithm to use for signing.</param>
        /// <param name="entity">The entity.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="CertificateNotFoundException">
        /// A signing certificate could not be found for <paramref name="signer"/>.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static ApplicationPkcs7Mime Sign(SecureMimeContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }

            if (signer == null)
            {
                throw new ArgumentNullException("signer");
            }

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            using (var memory = new MemoryBlockStream()) {
                var options = FormatOptions.CloneDefault();
                options.NewLineFormat = NewLineFormat.Dos;

                entity.WriteTo(options, memory);
                memory.Position = 0;

                return(ctx.EncapsulatedSign(signer, digestAlgo, memory));
            }
        }
Example #12
0
        /// <summary>
        /// Encrypts the specified entity.
        /// </summary>
        /// <remarks>
        /// Encrypts the entity to the specified recipients using the supplied <see cref="SecureMimeContext"/>.
        /// </remarks>
        /// <returns>The encrypted entity.</returns>
        /// <param name="ctx">The S/MIME context to use for encrypting.</param>
        /// <param name="recipients">The recipients.</param>
        /// <param name="entity">The entity.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="recipients"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// Valid certificates could not be found for one or more of the <paramref name="recipients"/>.
        /// </exception>
        /// <exception cref="CertificateNotFoundException">
        /// A certificate could not be found for one or more of the <paramref name="recipients"/>.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static ApplicationPkcs7Mime Encrypt(SecureMimeContext ctx, IEnumerable <MailboxAddress> recipients, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }

            if (recipients == null)
            {
                throw new ArgumentNullException("recipients");
            }

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            using (var memory = new MemoryBlockStream()) {
                var options = FormatOptions.CloneDefault();
                options.NewLineFormat = NewLineFormat.Dos;

                entity.WriteTo(options, memory);
                memory.Position = 0;

                return((ApplicationPkcs7Mime)ctx.Encrypt(recipients, memory));
            }
        }
        public void Setup()
        {
            var bytes    = new byte[9 * 1024];
            int position = 0;

            random = new Random();
            random.NextBytes(bytes);

            // this is our master stream, all operations on the chained stream
            // should match the results on this stream
            master = new MemoryStream(bytes);
            mbuf   = new byte[4096];
            buf    = new byte[4096];

            // write the content into the memory block stream in random chunks
            blocks = new MemoryBlockStream();

            Assert.IsTrue(blocks.CanRead, "Expected to be able to read from the memory block stream.");
            Assert.IsTrue(blocks.CanWrite, "Expected to be able to write to the memory block stream.");
            Assert.IsTrue(blocks.CanSeek, "Expected to be able to seek in the memory block stream.");
            Assert.IsFalse(blocks.CanTimeout, "Did not expect to be able to set timeouts in the memory block stream.");

            while (position < bytes.Length)
            {
                int n = Math.Min(bytes.Length - position, random.Next() % 4096);
                blocks.Write(bytes, position, n);
                position += n;
            }

            blocks.Seek(0, SeekOrigin.Begin);
        }
Example #14
0
        public void TestStreamArguments()
        {
            using (var stream = new MeasuringStream())
                AssertStreamArguments(stream);

            using (var stream = new MemoryBlockStream())
                AssertStreamArguments(stream);

            using (var memory = new MemoryStream()) {
                Assert.Throws <ArgumentNullException> (() => new FilteredStream(null));

                using (var stream = new FilteredStream(memory))
                    AssertStreamArguments(stream);
            }

            using (var memory = new MemoryStream()) {
                Assert.Throws <ArgumentNullException> (() => new BoundStream(null, 0, 10, true));
                Assert.Throws <ArgumentOutOfRangeException> (() => new BoundStream(memory, -1, 10, true));
                Assert.Throws <ArgumentOutOfRangeException> (() => new BoundStream(memory, 5, 1, true));

                using (var stream = new BoundStream(memory, 0, -1, true))
                    AssertStreamArguments(stream);
            }

            using (var memory = new MemoryStream()) {
                using (var stream = new ChainedStream()) {
                    stream.Add(memory);

                    Assert.Throws <ArgumentNullException> (() => stream.Add(null));

                    AssertStreamArguments(stream);
                }
            }
        }
Example #15
0
        public ImapReplayCommand(string command, string resource)
        {
            string tag = null;

            Command = command;

            if (command.StartsWith("A00000", StringComparison.Ordinal))
            {
                tag = command.Substring(0, 9);
            }

            using (var stream = GetType().Assembly.GetManifestResourceStream("UnitTests.Net.Imap.Resources." + resource)) {
                using (var memory = new MemoryBlockStream()) {
                    using (var filtered = new FilteredStream(memory)) {
                        if (tag != null)
                        {
                            filtered.Add(new ImapReplayFilter("A########", tag));
                        }

                        filtered.Add(new Unix2DosFilter());
                        stream.CopyTo(filtered, 4096);
                        filtered.Flush();
                    }

                    Response = memory.ToArray();
                }
            }
        }
Example #16
0
        /// <summary>
        /// Parses a MimeEntity and returns as lambda to caller.
        /// </summary>
        /// <param name="node">Node containing the MIME message as value,
        /// and also where the lambda structure representing the parsed message will be placed.</param>
        /// <param name="entity">MimeEntity to parse.</param>
        public static void Parse(Node node, MimeEntity entity)
        {
            node.Value = entity.ContentType.MimeType;
            ProcessHeaders(node, entity);

            if (entity is Multipart multi)
            {
                // Multipart content.
                foreach (var idx in multi)
                {
                    var idxNode = new Node("entity");
                    Parse(idxNode, idx);
                    node.Add(idxNode);
                }
            }
            else if (entity is TextPart text)
            {
                // Test type of entity.
                node.Add(new Node("content", text.GetText(out var _)));
            }
            else if (entity is MimePart part)
            {
                using (var stream = new MemoryBlockStream())
                {
                    // Decoding content to memory.
                    part.Content.DecodeTo(stream);

                    // Resetting position and setting up a buffer object to hold content.
                    stream.Position = 0;

                    // Putting content into return node for MimeEntity.
                    node.Add(new Node("content", stream.ToArray()));
                }
            }
        }
Example #17
0
        public void TestStreamArguments()
        {
            using (var stream = new MeasuringStream())
                AssertStreamArguments(stream);

            using (var stream = new MemoryBlockStream())
                AssertStreamArguments(stream);

            using (var memory = new MemoryStream()) {
                using (var stream = new FilteredStream(memory))
                    AssertStreamArguments(stream);
            }

            using (var memory = new MemoryStream()) {
                using (var stream = new BoundStream(memory, 0, -1, true))
                    AssertStreamArguments(stream);
            }

            using (var memory = new MemoryStream()) {
                using (var stream = new ChainedStream()) {
                    stream.Add(memory);

                    AssertStreamArguments(stream);
                }
            }
        }
Example #18
0
        /// <summary>
        /// Creates a new <see cref="MultipartSigned"/>.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs the entity using the supplied signer and digest algorithm in
        /// order to generate a detached signature and then adds the entity along with the
        /// detached signature data to a new multipart/signed part.
        /// </remarks>
        /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
        /// <param name="ctx">The cryptography context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="digestAlgo">The digest algorithm to use for signing.</param>
        /// <param name="entity">The entity to sign.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="System.ArgumentOutOfRangeException">
        /// The <paramref name="digestAlgo"/> was out of range.
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// The <paramref name="digestAlgo"/> is not supported.
        /// </exception>
        /// <exception cref="CertificateNotFoundException">
        /// A signing certificate could not be found for <paramref name="signer"/>.
        /// </exception>
        /// <exception cref="PrivateKeyNotFoundException">
        /// The private key could not be found for <paramref name="signer"/>.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static MultipartSigned Create(CryptographyContext ctx, MailboxAddress signer, DigestAlgorithm digestAlgo, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

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

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

            using (var memory = new MemoryBlockStream()) {
                var prepared = Prepare(entity, memory);

                memory.Position = 0;

                // sign the cleartext content
                var signature = ctx.Sign(signer, digestAlgo, memory);

                return(Create(ctx, digestAlgo, prepared, signature));
            }
        }
Example #19
0
        async Task <BoundaryType> ConstructMimePartAsync(MimePart part, CancellationToken cancellationToken)
        {
            ScanContentResults results;
            Stream             content;

            if (persistent)
            {
                long begin = GetOffset(inputIndex);
                long end;

                using (var measured = new MeasuringStream()) {
                    results = await ScanContentAsync(measured, true, cancellationToken).ConfigureAwait(false);

                    end = begin + measured.Length;
                }

                content = new BoundStream(stream, begin, end, true);
            }
            else
            {
                content = new MemoryBlockStream();
                results = await ScanContentAsync(content, true, cancellationToken).ConfigureAwait(false);

                content.Seek(0, SeekOrigin.Begin);
            }

            if (!results.IsEmpty)
            {
                part.ContentObject = new ContentObject(content, part.ContentTransferEncoding);
            }

            return(results.Boundary);
        }
        private static MimePart GetMimePart(AttachmentBase item)
        {
            var      mimeType    = item.ContentType.ToString();
            var      contentType = ContentType.Parse(mimeType);
            var      attachment  = item as Attachment;
            MimePart part;

            if (contentType.MediaType.Equals("text", StringComparison.OrdinalIgnoreCase))
            {
                // Original: part = new TextPart(contentType);
                // Due to constructor of TextPart(ContentType contentType) being internal,
                // mimic the instantiation by using MimePart(ContentType contentType)
                part = new MimePart(contentType);
            }
            else
            {
                part = new MimePart(contentType);
            }

            if (attachment != null)
            {
                var disposition = attachment.ContentDisposition.ToString();
                part.ContentDisposition = ContentDisposition.Parse(disposition);
            }

            switch (item.TransferEncoding)
            {
            case System.Net.Mime.TransferEncoding.QuotedPrintable:
                part.ContentTransferEncoding = ContentEncoding.QuotedPrintable;
                break;

            case System.Net.Mime.TransferEncoding.Base64:
                part.ContentTransferEncoding = ContentEncoding.Base64;
                break;

            case System.Net.Mime.TransferEncoding.SevenBit:
                part.ContentTransferEncoding = ContentEncoding.SevenBit;
                break;

            case System.Net.Mime.TransferEncoding.EightBit:
                part.ContentTransferEncoding = ContentEncoding.EightBit;
                break;
            }

            if (item.ContentId != null)
            {
                part.ContentId = item.ContentId;
            }

            var stream = new MemoryBlockStream();

            item.ContentStream.CopyTo(stream);
            stream.Position = 0;

#pragma warning disable CS0618 // Type or member is obsolete, this line will be removed once the ContentObject property is fully removed
            part.ContentObject = new ContentObject(stream);
#pragma warning restore CS0618 // Type or member is obsolete, this line will be removed once the ContentObject property is fully removed

            return(part);
        }
Example #21
0
        public MemoryBlockStreamTests()
        {
            var bytes    = new byte[9 * 1024];
            int position = 0;

            random = new Random();
            random.NextBytes(bytes);

            // this is our master stream, all operations on the chained stream
            // should match the results on this stream
            master = new MemoryStream(bytes);
            mbuf   = new byte[4096];
            buf    = new byte[4096];

            // write the content into the memory block stream in random chunks
            blocks = new MemoryBlockStream();

            while (position < bytes.Length)
            {
                int n = Math.Min(bytes.Length - position, random.Next() % 4096);
                blocks.Write(bytes, position, n);
                position += n;
            }

            blocks.Seek(0, SeekOrigin.Begin);
        }
Example #22
0
        /// <summary>
        /// Creates a new <see cref="MultipartSigned"/>.
        /// </summary>
        /// <remarks>
        /// Cryptographically signs the entity using the supplied signer in order
        /// to generate a detached signature and then adds the entity along with
        /// the detached signature data to a new multipart/signed part.
        /// </remarks>
        /// <returns>A new <see cref="MultipartSigned"/> instance.</returns>
        /// <param name="ctx">The S/MIME context to use for signing.</param>
        /// <param name="signer">The signer.</param>
        /// <param name="entity">The entity to sign.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <para><paramref name="ctx"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="signer"/> is <c>null</c>.</para>
        /// <para>-or-</para>
        /// <para><paramref name="entity"/> is <c>null</c>.</para>
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public static MultipartSigned Create(SecureMimeContext ctx, CmsSigner signer, MimeEntity entity)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }

            if (signer == null)
            {
                throw new ArgumentNullException("signer");
            }

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            entity.Prepare(EncodingConstraint.SevenBit, 78);

            using (var memory = new MemoryBlockStream()) {
                using (var filtered = new FilteredStream(memory)) {
                    // Note: see rfc3156, section 3 - second note
                    filtered.Add(new ArmoredFromFilter());

                    // Note: see rfc3156, section 5.4 (this is the main difference between rfc2015 and rfc3156)
                    filtered.Add(new TrailingWhitespaceFilter());

                    // Note: see rfc2015 or rfc3156, section 5.1
                    filtered.Add(new Unix2DosFilter());

                    entity.WriteTo(filtered);
                    filtered.Flush();
                }

                memory.Position = 0;

                // Note: we need to parse the modified entity structure to preserve any modifications
                var parser = new MimeParser(memory, MimeFormat.Entity);
                var parsed = parser.ParseEntity();
                memory.Position = 0;

                // sign the cleartext content
                var micalg    = ctx.GetDigestAlgorithmName(signer.DigestAlgorithm);
                var signature = ctx.Sign(signer, memory);
                var signed    = new MultipartSigned();

                // set the protocol and micalg Content-Type parameters
                signed.ContentType.Parameters["protocol"] = ctx.SignatureProtocol;
                signed.ContentType.Parameters["micalg"]   = micalg;

                // add the modified/parsed entity as our first part
                signed.Add(parsed);

                // add the detached signature as the second part
                signed.Add(signature);

                return(signed);
            }
        }
        /// <summary>
        /// Decrypts the <see cref="MultipartEncrypted"/> part.
        /// </summary>
        /// <remarks>
        /// Decrypts the <see cref="MultipartEncrypted"/> and extracts any digital signatures in cases
        /// where the content was also signed.
        /// </remarks>
        /// <returns>The decrypted entity.</returns>
        /// <param name="ctx">The OpenPGP cryptography context to use for decrypting.</param>
        /// <param name="signatures">A list of digital signatures if the data was both signed and encrypted.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="ctx"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.FormatException">
        /// <para>The <c>protocol</c> parameter was not specified.</para>
        /// <para>-or-</para>
        /// <para>The multipart is malformed in some way.</para>
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// The provided <see cref="OpenPgpContext"/> does not support the protocol parameter.
        /// </exception>
        /// <exception cref="PrivateKeyNotFoundException">
        /// The private key could not be found to decrypt the encrypted data.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The user chose to cancel the password prompt.
        /// </exception>
        /// <exception cref="System.UnauthorizedAccessException">
        /// 3 bad attempts were made to unlock the secret key.
        /// </exception>
        public MimeEntity Decrypt(OpenPgpContext ctx, out DigitalSignatureCollection signatures)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }

            var protocol = ContentType.Parameters["protocol"];

            if (string.IsNullOrEmpty(protocol))
            {
                throw new FormatException();
            }

            protocol = protocol.Trim().ToLowerInvariant();
            if (!ctx.Supports(protocol))
            {
                throw new NotSupportedException();
            }

            if (Count < 2)
            {
                throw new FormatException();
            }

            var version = this[0] as MimePart;

            if (version == null)
            {
                throw new FormatException();
            }

            var ctype = version.ContentType;
            var value = string.Format("{0}/{1}", ctype.MediaType, ctype.MediaSubtype);

            if (value.ToLowerInvariant() != protocol)
            {
                throw new FormatException();
            }

            var encrypted = this[1] as MimePart;

            if (encrypted == null || encrypted.ContentObject == null)
            {
                throw new FormatException();
            }

            if (!encrypted.ContentType.Matches("application", "octet-stream"))
            {
                throw new FormatException();
            }

            using (var memory = new MemoryBlockStream()) {
                encrypted.ContentObject.DecodeTo(memory);
                memory.Position = 0;

                return(ctx.Decrypt(memory, out signatures));
            }
        }
Example #24
0
        static void AssertJwzMboxResults(string actual, Stream output)
        {
            var summary = File.ReadAllText(Path.Combine(MboxDataDir, "jwz-summary.txt")).Replace("\r\n", "\n");
            var original = new MemoryBlockStream();
            var expected = new byte[4096];
            var buffer = new byte[4096];
            int nx, n;

            // WORKAROUND: Mono's iso-2022-jp decoder breaks on this input in versions <= 3.2.3 but is fixed in 3.2.4+
            string iso2022jp = Encoding.GetEncoding("iso-2022-jp").GetString(Convert.FromBase64String("GyRAOjRGI0stGyhK"));

            if (iso2022jp != "佐藤豊")
            {
                actual = actual.Replace(iso2022jp, "佐藤豊");
            }

            Assert.AreEqual(summary, actual, "Summaries do not match for jwz.mbox");

            using (var stream = File.OpenRead(Path.Combine(MboxDataDir, "jwz.mbox.txt"))) {
                using (var filtered = new FilteredStream(original)) {
                    filtered.Add(new Dos2UnixFilter());
                    stream.CopyTo(filtered);
                    filtered.Flush();
                }
            }

            original.Position = 0;
            output.Position   = 0;

            Assert.AreEqual(original.Length, output.Length, "The length of the mbox did not match.");

            do
            {
                var position = original.Position;

                nx = original.Read(expected, 0, expected.Length);
                n  = output.Read(buffer, 0, buffer.Length);

                if (nx == 0)
                {
                    break;
                }

                for (int i = 0; i < nx; i++)
                {
                    if (buffer[i] == expected[i])
                    {
                        continue;
                    }

                    var strExpected = CharsetUtils.Latin1.GetString(expected, 0, nx);
                    var strActual   = CharsetUtils.Latin1.GetString(buffer, 0, n);

                    Assert.AreEqual(strExpected, strActual, "The mbox differs at position {0}", position + i);
                }
            } while (true);
        }
        private static MimePart GetMimePart(AttachmentBase item)
        {
            var mimeType    = item.ContentType.ToString();
            var contentType = ContentType.Parse(mimeType);
            var attachment  = item as Attachment;
            var part        = new MimePart(contentType);

            //
            if (attachment != null)
            {
                var disposition = attachment.ContentDisposition.ToString();
                part.ContentDisposition = ContentDisposition.Parse(disposition);
            }

            // Adjust the transfer encoding
            switch (item.TransferEncoding)
            {
            case TransferEncoding.QuotedPrintable:
                part.ContentTransferEncoding = ContentEncoding.QuotedPrintable;
                break;

            case TransferEncoding.Base64:
                part.ContentTransferEncoding = ContentEncoding.Base64;
                break;

            case TransferEncoding.SevenBit:
                part.ContentTransferEncoding = ContentEncoding.SevenBit;
                break;

            case TransferEncoding.EightBit:
                part.ContentTransferEncoding = ContentEncoding.EightBit;
                break;

            case TransferEncoding.Unknown:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            // Adjust the attachment content identifier
            if (item.ContentId != null)
            {
                part.ContentId = item.ContentId;
            }

            // Copy the content of the attachment
            var stream = new MemoryBlockStream();

            item.ContentStream.CopyTo(stream);
            stream.Position = 0;

            part.Content = new MimeContent(stream);

            // Done
            return(part);
        }
Example #26
0
        /// <summary>
        /// Verify the multipart/signed part.
        /// </summary>
        /// <remarks>
        /// Verifies the multipart/signed part using the supplied cryptography context.
        /// </remarks>
        /// <returns>A signer info collection.</returns>
        /// <param name="ctx">The cryptography context to use for verifying the signature.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="ctx"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.FormatException">
        /// The multipart is malformed in some way.
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// <paramref name="ctx"/> does not support verifying the signature part.
        /// </exception>
        /// <exception cref="System.OperationCanceledException">
        /// The operation was cancelled via the cancellation token.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public async Task <DigitalSignatureCollection> VerifyAsync(CryptographyContext ctx, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }

            var protocol = ContentType.Parameters["protocol"]?.Trim();

            if (string.IsNullOrEmpty(protocol))
            {
                throw new FormatException("The multipart/signed part did not specify a protocol.");
            }

            if (!ctx.Supports(protocol))
            {
                throw new NotSupportedException("The specified cryptography context does not support the signature protocol.");
            }

            if (Count < 2)
            {
                throw new FormatException("The multipart/signed part did not contain the expected children.");
            }

            var signature = this[1] as MimePart;

            if (signature == null || signature.Content == null)
            {
                throw new FormatException("The signature part could not be found.");
            }

            var ctype = signature.ContentType;
            var value = string.Format("{0}/{1}", ctype.MediaType, ctype.MediaSubtype);

            if (!ctx.Supports(value))
            {
                throw new NotSupportedException(string.Format("The specified cryptography context does not support '{0}'.", value));
            }

            using (var signatureData = new MemoryBlockStream()) {
                await signature.Content.DecodeToAsync(signatureData, cancellationToken).ConfigureAwait(false);

                signatureData.Position = 0;

                using (var cleartext = new MemoryBlockStream()) {
                    // Note: see rfc2015 or rfc3156, section 5.1
                    var options = FormatOptions.CloneDefault();
                    options.NewLineFormat      = NewLineFormat.Dos;
                    options.VerifyingSignature = true;

                    await this[0].WriteToAsync(options, cleartext, cancellationToken);
                    cleartext.Position = 0;

                    return(await ctx.VerifyAsync(cleartext, signatureData, cancellationToken).ConfigureAwait(false));
                }
            }
        }
Example #27
0
        private void CompareState(MemoryStream ms, MemoryBlockStream ms2)
        {
            // Compare byte content.
            byte[] buff1 = ms.ToArray();
            byte[] buff2 = ms2.ToArray();

            // Compare read/write position.
            Assert.Equal(buff1, buff2);
            Assert.Equal(ms.Position, ms2.Position);
        }
        void OnFieldsChanged(object sender, HeaderListChangedEventArgs e)
        {
            var stream  = new MemoryBlockStream();
            var options = FormatOptions.Default;

            fields.WriteTo(options, stream);
            stream.Position = 0;

            ContentObject = new ContentObject(stream);
        }
Example #29
0
        public void TestGetSetTimeouts()
        {
            using (var block = new MemoryBlockStream()) {
                Assert.Throws <InvalidOperationException> (() => { int x = block.ReadTimeout; });
                Assert.Throws <InvalidOperationException> (() => { int x = block.WriteTimeout; });

                Assert.Throws <InvalidOperationException> (() => block.ReadTimeout  = 5);
                Assert.Throws <InvalidOperationException> (() => block.WriteTimeout = 5);
            }
        }
Example #30
0
        /// <summary>
        /// Verifies the multipart/signed part.
        /// </summary>
        /// <remarks>
        /// Verifies the multipart/signed part using the supplied cryptography context.
        /// </remarks>
        /// <returns>A signer info collection.</returns>
        /// <param name="ctx">The cryptography context to use for verifying the signature.</param>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="ctx"/> is <c>null</c>.
        /// </exception>
        /// <exception cref="System.FormatException">
        /// The multipart is malformed in some way.
        /// </exception>
        /// <exception cref="System.NotSupportedException">
        /// <paramref name="ctx"/> does not support verifying the signature part.
        /// </exception>
        /// <exception cref="Org.BouncyCastle.Cms.CmsException">
        /// An error occurred in the cryptographic message syntax subsystem.
        /// </exception>
        public DigitalSignatureCollection Verify(CryptographyContext ctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }

            var protocol = ContentType.Parameters["protocol"];

            if (string.IsNullOrEmpty(protocol))
            {
                throw new FormatException("The multipart/signed part did not specify a protocol.");
            }

            if (!ctx.Supports(protocol.Trim()))
            {
                throw new NotSupportedException("The specified cryptography context does not support the signature protocol.");
            }

            if (Count < 2)
            {
                throw new FormatException("The multipart/signed part did not contain the expected children.");
            }

            var signature = this[1] as MimePart;

            if (signature == null || signature.ContentObject == null)
            {
                throw new FormatException("The signature part could not be found.");
            }

            var ctype = signature.ContentType;
            var value = string.Format("{0}/{1}", ctype.MediaType, ctype.MediaSubtype);

            if (!ctx.Supports(value))
            {
                throw new NotSupportedException(string.Format("The specified cryptography context does not support '{0}'.", value));
            }

            using (var signatureData = new MemoryBlockStream()) {
                signature.ContentObject.DecodeTo(signatureData);
                signatureData.Position = 0;

                using (var cleartext = new MemoryBlockStream()) {
                    // Note: see rfc2015 or rfc3156, section 5.1
                    var options = FormatOptions.CloneDefault();
                    options.NewLineFormat = NewLineFormat.Dos;

                    this[0].WriteTo(options, cleartext);
                    cleartext.Position = 0;

                    return(ctx.Verify(cleartext, signatureData));
                }
            }
        }