1936 lines · 76.3 KB · C#
RawDownload
//******************************************************************************************************//  TlsClient.cs - Gbtc////  Copyright © 2012, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://www.opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  07/12/2012 - Stephen C. Wills//       Generated original version of source code.//  12/13/2012 - Starlynn Danyelle Gilliam//       Modified Header.////****************************************************************************************************** using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.ComponentModel;using System.Diagnostics;using System.IO;using System.Net;using System.Net.Security;using System.Net.Sockets;using System.Security;using System.Security.Authentication;using System.Security.Cryptography.X509Certificates;using System.Text.RegularExpressions;using System.Threading;using GSF.Configuration;using GSF.IO;using GSF.Net.Security;using GSF.Threading; namespace GSF.Communication{    /// <summary>    /// Represents a TCP-based communication client with SSL authentication and encryption.    /// </summary>    /// <seealso cref="TcpClient"/>    public class TlsClient : ClientBase    {        #region [ Members ]         // Nested Types        private sealed class ConnectState : IDisposable        {            public Socket Socket;            public NetworkStream NetworkStream;            public SslStream SslStream;            public NegotiateStream NegotiateStream;             public SocketAsyncEventArgs ConnectArgs = new SocketAsyncEventArgs();            public int ConnectionAttempts;             public CancellationToken Token = new CancellationToken();             public void Dispose()            {                Dispose(ConnectArgs);                 Dispose(Socket);                Dispose(NetworkStream);                Dispose(SslStream);                Dispose(NegotiateStream);            }             private static void Dispose(IDisposable obj)            {                if ((object)obj != null)                    obj.Dispose();            }        }         private sealed class ReceiveState : IDisposable        {            public Socket Socket;            public NetworkStream NetworkStream;            public SslStream SslStream;             public byte[] Buffer;            public int Offset;            public int PayloadLength = -1;             public CancellationToken Token;             public void Dispose()            {                Dispose(Socket);                Dispose(NetworkStream);                Dispose(SslStream);            }             private static void Dispose(IDisposable obj)            {                if ((object)obj != null)                    obj.Dispose();            }        }         private sealed class SendState : IDisposable        {            public Socket Socket;            public NetworkStream NetworkStream;            public SslStream SslStream;             public ConcurrentQueue<TlsClientPayload> SendQueue = new ConcurrentQueue<TlsClientPayload>();            public TlsClientPayload Payload;            public int Sending;             public CancellationToken Token;             public void Dispose()            {                TlsClientPayload payload;                 Dispose(Socket);                Dispose(NetworkStream);                Dispose(SslStream);                 while (SendQueue.TryDequeue(out payload))                {                    payload.WaitHandle.Set();                    payload.WaitHandle.Dispose();                }            }             private static void Dispose(IDisposable obj)            {                if ((object)obj != null)                    obj.Dispose();            }        }         private class TlsClientPayload        {            public byte[] Data;            public int Offset;            public int Length;            public ManualResetEvent WaitHandle;        }         private class CancellationToken        {            private int m_cancelled;             public bool Cancelled            {                get                {                    return Interlocked.CompareExchange(ref m_cancelled, 0, 0) != 0;                }            }             public bool Cancel()            {                return Interlocked.Exchange(ref m_cancelled, 1) != 0;            }        }         // Constants         /// <summary>        /// Specifies the default value for the <see cref="TrustedCertificatesPath"/> property.        /// </summary>        public readonly string DefaultTrustedCertificatesPath = FilePath.GetAbsolutePath(@"Certs\Remotes");         /// <summary>        /// Specifies the default value for the <see cref="PayloadAware"/> property.        /// </summary>        public const bool DefaultPayloadAware = false;         /// <summary>        /// Specifies the default value for the <see cref="IntegratedSecurity"/> property.        /// </summary>        public const bool DefaultIntegratedSecurity = false;         /// <summary>        /// Specifies the default value for the <see cref="IgnoreInvalidCredentials"/> property.        /// </summary>        public const bool DefaultIgnoreInvalidCredentials = false;         /// <summary>        /// Specifies the default value for the <see cref="AllowDualStackSocket"/> property.        /// </summary>        public const bool DefaultAllowDualStackSocket = true;         /// <summary>        /// Specifies the default value for the <see cref="MaxSendQueueSize"/> property.        /// </summary>        public const int DefaultMaxSendQueueSize = 500000;         /// <summary>        /// Specifies the default value for the <see cref="ClientBase.ConnectionString"/> property.        /// </summary>        public const string DefaultConnectionString = "Server=localhost:8888";         // Fields        private readonly SimpleCertificateChecker m_defaultCertificateChecker;        private ICertificateChecker m_certificateChecker;        private RemoteCertificateValidationCallback m_remoteCertificateValidationCallback;        private LocalCertificateSelectionCallback m_localCertificateSelectionCallback;        private readonly X509Certificate2Collection m_clientCertificates;        private SslProtocols m_enabledSslProtocols;        private bool m_checkCertificateRevocation;        private string m_trustedCertificatesPath;        private string m_certificateFile;        private X509Certificate m_certificate;         private bool m_payloadAware;        private byte[] m_payloadMarker;        private bool m_integratedSecurity;        private bool m_ignoreInvalidCredentials;        private IPStack m_ipStack;        private bool m_allowDualStackSocket;        private int m_maxSendQueueSize;        private ShortSynchronizedOperation m_dumpPayloadsOperation;        private Dictionary<string, string> m_connectData;        private ManualResetEvent m_connectWaitHandle;        private NetworkCredential m_networkCredential;         private ConnectState m_connectState;        private ReceiveState m_receiveState;        private SendState m_sendState;         private bool m_disposed;         #endregion         #region [ Constructors ]         /// <summary>        /// Initializes a new instance of the <see cref="TlsClient"/> class.        /// </summary>        public TlsClient()            : this(DefaultConnectionString)        {        }         /// <summary>        /// Initializes a new instance of the <see cref="TlsClient"/> class.        /// </summary>        /// <param name="connectString">Connect string of the <see cref="TlsClient"/>. See <see cref="DefaultConnectionString"/> for format.</param>        public TlsClient(string connectString)            : base(TransportProtocol.Tcp, connectString)        {            m_defaultCertificateChecker = new SimpleCertificateChecker();            m_localCertificateSelectionCallback = DefaultLocalCertificateSelectionCallback;            m_clientCertificates = new X509Certificate2Collection();#if MONO            // Tls12 is not supported under Mono as of v3.8.0            m_enabledSslProtocols = SslProtocols.Tls;#else            m_enabledSslProtocols = SslProtocols.Tls12;#endif            m_checkCertificateRevocation = true;             m_trustedCertificatesPath = DefaultTrustedCertificatesPath;            m_payloadAware = DefaultPayloadAware;            m_payloadMarker = Payload.DefaultMarker;            m_integratedSecurity = DefaultIntegratedSecurity;            m_ignoreInvalidCredentials = DefaultIgnoreInvalidCredentials;            m_allowDualStackSocket = DefaultAllowDualStackSocket;            m_maxSendQueueSize = DefaultMaxSendQueueSize;            m_dumpPayloadsOperation = new ShortSynchronizedOperation(DumpPayloads, OnSendDataException);        }         /// <summary>        /// Initializes a new instance of the <see cref="TlsClient"/> class.        /// </summary>        /// <param name="container"><see cref="IContainer"/> object that contains the <see cref="TlsClient"/>.</param>        public TlsClient(IContainer container)            : this()        {            if (container != null)                container.Add(this);        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets or sets a boolean value that indicates whether the payload boundaries are to be preserved during transmission.        /// </summary>        [Category("Data"),        DefaultValue(DefaultPayloadAware),        Description("Indicates whether the payload boundaries are to be preserved during transmission.")]        public bool PayloadAware        {            get            {                return m_payloadAware;            }            set            {                m_payloadAware = value;            }        }         /// <summary>        /// Gets or sets the byte sequence used to mark the beginning of a payload in a <see cref="PayloadAware"/> transmission.        /// </summary>        /// <exception cref="ArgumentNullException">The value being assigned is null or empty buffer.</exception>        [Browsable(false),        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]        public byte[] PayloadMarker        {            get            {                return m_payloadMarker;            }            set            {                if ((object)value == null || value.Length == 0)                    throw new ArgumentNullException("value");                 m_payloadMarker = value;            }        }         /// <summary>        /// Gets or sets a boolean value that indicates whether the current Windows account credentials are used for authentication.        /// </summary>        /// <remarks>           /// This option is ignored under Mono deployments.        /// </remarks>        [Category("Security"),        DefaultValue(DefaultIntegratedSecurity),        Description("Indicates whether the current Windows account credentials are used for authentication.")]        public bool IntegratedSecurity        {            get            {                return m_integratedSecurity;            }            set            {#if MONO                if (value)                    throw new NotImplementedException("Not supported under Mono.");#else                m_integratedSecurity = value;#endif            }        }         /// <summary>        /// Gets or sets a boolean value that indicates whether the server        /// should ignore errors when the client's credentials are invalid.        /// </summary>        /// <remarks>        /// This property should only be set to true if there is an alternative by which        /// to authenticate the client when integrated security fails.        /// </remarks>        [Category("Security"),        DefaultValue(DefaultIgnoreInvalidCredentials),        Description("Indicates whether the client Windows account credentials are validated during authentication.")]        public bool IgnoreInvalidCredentials        {            get            {                return m_ignoreInvalidCredentials;            }            set            {                m_ignoreInvalidCredentials = value;            }        }         /// <summary>        /// Gets or sets a boolean value that determines if dual-mode socket is allowed when endpoint address is IPv6.        /// </summary>        [Category("Settings"),        DefaultValue(DefaultAllowDualStackSocket),        Description("Determines if dual-mode socket is allowed when endpoint address is IPv6.")]        public bool AllowDualStackSocket        {            get            {                return m_allowDualStackSocket;            }            set            {                m_allowDualStackSocket = value;            }        }         /// <summary>        /// Gets or sets the maximum size for the send queue before payloads are dumped from the queue.        /// </summary>        [Category("Settings"),        DefaultValue(DefaultMaxSendQueueSize),        Description("The maximum size for the send queue before payloads are dumped from the queue.")]        public int MaxSendQueueSize        {            get            {                return m_maxSendQueueSize;            }            set            {                m_maxSendQueueSize = value;            }        }         /// <summary>        /// Gets the <see cref="Socket"/> object for the <see cref="TlsClient"/>.        /// </summary>        [Browsable(false)]        public Socket Client        {            get            {                ConnectState connectState = m_connectState;                 if ((object)connectState != null)                    return connectState.Socket;                 return null;            }        }         /// <summary>        /// Gets the server URI of the <see cref="TlsClient"/>.        /// </summary>        [Browsable(false)]        public override string ServerUri        {            get            {                return string.Format("{0}://{1}", TransportProtocol, m_connectData["server"]).ToLower();            }        }         /// <summary>        /// Gets or sets network credential that is used when        /// <see cref="IntegratedSecurity"/> is set to <c>true</c>.        /// </summary>        [Browsable(false),        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]        public NetworkCredential NetworkCredential        {            get            {                return m_networkCredential;            }            set            {                m_networkCredential = value;            }        }         /// <summary>        /// Gets or sets the certificate checker used to validate remote certificates.        /// </summary>        /// <remarks>        /// The certificate checker will only be used to validate certificates if        /// the <see cref="RemoteCertificateValidationCallback"/> is set to null.        /// </remarks>        [Browsable(false),        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]        public ICertificateChecker CertificateChecker        {            get            {                return m_certificateChecker ?? m_defaultCertificateChecker;            }            set            {                m_certificateChecker = value;            }        }         /// <summary>        /// Gets or sets the callback used to verify remote certificates.        /// </summary>        /// <remarks>        /// Setting this property overrides the validation        /// callback in the <see cref="CertificateChecker"/>.        /// </remarks>        [Browsable(false),        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]        public RemoteCertificateValidationCallback RemoteCertificateValidationCallback        {            get            {                return m_remoteCertificateValidationCallback;            }            set

Lines 1–500 of 1936.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t