//******************************************************************************************************// 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 GSF.Configuration;using GSF.Diagnostics;using GSF.IO;using GSF.Net.Security;using GSF.Threading;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.ComponentModel;using System.Diagnostics;using System.IO;using System.Linq;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;using System.Text.RegularExpressions;using System.Threading; // ReSharper disable AccessToDisposedClosure// ReSharper disable ArrangeAccessorOwnerBodynamespace 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 readonly SocketAsyncEventArgs ConnectArgs = new SocketAsyncEventArgs(); public int ConnectionAttempts; public readonly CancellationToken Token = new CancellationToken(); public ICancellationToken TimeoutToken; public void Dispose() { ConnectArgs.Dispose(); Socket?.Dispose(); NetworkStream?.Dispose(); SslStream?.Dispose(); NegotiateStream?.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) => obj?.Dispose(); } private sealed class SendState : IDisposable { public Socket Socket; public NetworkStream NetworkStream; public SslStream SslStream; public readonly ConcurrentQueue<TlsClientPayload> SendQueue = new ConcurrentQueue<TlsClientPayload>(); public TlsClientPayload Payload; public int Sending; public CancellationToken Token; public void Dispose() { Dispose(Socket); Dispose(NetworkStream); Dispose(SslStream); while (SendQueue.TryDequeue(out TlsClientPayload payload)) { payload.WaitHandle.Set(); payload.WaitHandle.Dispose(); } } private static void Dispose(IDisposable obj) => 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 => Interlocked.CompareExchange(ref m_cancelled, 0, 0) != 0; public bool Cancel() => 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="NoDelay"/> property. /// </summary> public const bool DefaultNoDelay = false; /// <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 readonly X509Certificate2Collection m_clientCertificates; private SslProtocols m_enabledSslProtocols; private string m_certificateFile; private byte[] m_payloadMarker; private EndianOrder m_payloadEndianOrder; private IPStack m_ipStack; private readonly ShortSynchronizedOperation m_dumpPayloadsOperation; private string[] m_serverList; private Dictionary<string, string> m_connectData; private ManualResetEvent m_connectWaitHandle; 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(); LocalCertificateSelectionCallback = DefaultLocalCertificateSelectionCallback; m_clientCertificates = new X509Certificate2Collection(); m_enabledSslProtocols = SslProtocols.Tls12; CheckCertificateRevocation = true; TrustedCertificatesPath = DefaultTrustedCertificatesPath; PayloadAware = DefaultPayloadAware; m_payloadMarker = Payload.DefaultMarker; m_payloadEndianOrder = EndianOrder.LittleEndian; IntegratedSecurity = DefaultIntegratedSecurity; IgnoreInvalidCredentials = DefaultIgnoreInvalidCredentials; AllowDualStackSocket = DefaultAllowDualStackSocket; MaxSendQueueSize = DefaultMaxSendQueueSize; NoDelay = DefaultNoDelay; 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() => 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; set; } /// <summary> /// Gets or sets the byte sequence used to mark the beginning of a payload in a <see cref="PayloadAware"/> transmission. /// </summary> /// <remarks> /// Setting property to <c>null</c> will create a zero-length payload marker. /// </remarks> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public byte[] PayloadMarker { get => m_payloadMarker; set => m_payloadMarker = value ?? Array.Empty<byte>(); } /// <summary> /// Gets or sets the endian order to apply for encoding and decoding payload size in a <see cref="PayloadAware"/> transmission. /// </summary> /// <remarks> /// Setting property to <c>null</c> will force use of little-endian encoding. /// </remarks> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public EndianOrder PayloadEndianOrder { get => m_payloadEndianOrder; set => m_payloadEndianOrder = value ?? EndianOrder.LittleEndian; } /// <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; set; } /// <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; set; } /// <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; set; } /// <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; set; } /// <summary> /// Gets or sets a boolean value that determines if small packets are delivered to the remote host without delay. /// </summary> [Category("Settings")] [DefaultValue(DefaultNoDelay)] [Description("Determines if small packets are delivered to the remote host without delay.")] public bool NoDelay { get; set; } /// <summary> /// Gets the <see cref="Socket"/> object for the <see cref="TlsClient"/>. /// </summary> [Browsable(false)] public Socket Client => m_connectState?.Socket; /// <summary> /// Gets the <see cref="SslStream"/> object for the <see cref="TlsClient"/>. /// </summary> [Browsable(false)] public SslStream SslStream => m_connectState?.SslStream; /// <summary> /// Gets the server URI of the <see cref="TlsClient"/>. /// </summary> [Browsable(false)] public override string ServerUri => $"{TransportProtocol}://{ServerList[ServerIndex]}".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; set; } /// <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 => 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; set; } /// <summary> /// Gets or sets the callback used to select a local certificate. /// </summary> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public LocalCertificateSelectionCallback LocalCertificateSelectionCallback { get; set; } /// <summary> /// Gets the collection of X509 certificates for this client. /// </summary> [Browsable(false)] public X509CertificateCollection ClientCertificates => m_clientCertificates; /// <summary> /// Gets or sets a set of flags which determine the enabled <see cref="SslProtocols"/>. /// </summary> /// <exception cref="SecurityException">Failed to write event log entry for security warning about use of less secure TLS/SSL protocols.</exception> [Category("Settings")] [DefaultValue(SslProtocols.Tls12)] [Description("The set of SSL protocols that are enabled for this client.")] public SslProtocols EnabledSslProtocols { get => m_enabledSslProtocols; set { m_enabledSslProtocols = value; // As of July 2014, Tls12 is the latest and most secure TLS protocol - all other protocols // represent a security risk when used, as such we log a security message when any of the // older protocols are being used. if (m_enabledSslProtocols >= SslProtocols.Tls12) return; try { string applicationName; // Get application name try { // Attempt to retrieve application name as defined in common security settings - this name // is typically preconfigured as the desired event source for event log entries ConfigurationFile config = ConfigurationFile.Current; CategorizedSettingsElementCollection settings = config.Settings["SecurityProvider"]; applicationName = settings["ApplicationName"].Value; } catch { applicationName = null; } // Fall back on running executable name if (string.IsNullOrWhiteSpace(applicationName)) applicationName = FilePath.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName); string message = $"One or more less secure TLS/SSL protocols \"{m_enabledSslProtocols}\" are being used by an instance of the TlsClient in {applicationName}"; EventLog.WriteEntry(applicationName, message, EventLogEntryType.Warning, 1); } catch (Exception ex) { throw new SecurityException($"Failed to write event log entry for security warning about use of less secure TLS/SSL protocols \"{m_enabledSslProtocols}\": {ex.Message}", ex); } } } /// <summary> /// Gets or sets a boolean value that determines whether the certificate revocation list is checked during authentication. /// </summary> [Category("Settings")] [DefaultValue(true)] [Description("True if the certificate revocation list is to be checked during authentication, otherwise False.")] public bool CheckCertificateRevocation { get; set; } /// <summary> /// Gets or sets the path to the certificate used for authentication. /// </summary> [Category("Settings")] [DefaultValue(null)] [Description("Path to the certificate used by this client for authentication.")] public string CertificateFile { get => m_certificateFile; set { if (string.IsNullOrWhiteSpace(value)) { m_certificateFile = null; Certificate = null; } else { m_certificateFile = FilePath.GetAbsolutePath(value); if (File.Exists(m_certificateFile)) Certificate = new X509Certificate2(m_certificateFile); } } } /// <summary> /// Gets or sets the local certificate selected by the default <see cref="LocalCertificateSelectionCallback"/>. /// </summary> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public X509Certificate Certificate { get; set; } /// <summary> /// Gets or sets the path to the directory containing the trusted certificates. /// </summary>Lines 1–500 of 1850. Load more
//****************************************************************************************************** // 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 GSF.Configuration; using GSF.Diagnostics; using GSF.IO; using GSF.Net.Security; using GSF.Threading; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; 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; using System.Text.RegularExpressions; using System.Threading; // ReSharper disable AccessToDisposedClosure // ReSharper disable ArrangeAccessorOwnerBody 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 readonly SocketAsyncEventArgs ConnectArgs = new SocketAsyncEventArgs(); public int ConnectionAttempts; public readonly CancellationToken Token = new CancellationToken(); public ICancellationToken TimeoutToken; public void Dispose() { ConnectArgs.Dispose(); Socket?.Dispose(); NetworkStream?.Dispose(); SslStream?.Dispose(); NegotiateStream?.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) => obj?.Dispose(); } private sealed class SendState : IDisposable { public Socket Socket; public NetworkStream NetworkStream; public SslStream SslStream; public readonly ConcurrentQueue<TlsClientPayload> SendQueue = new ConcurrentQueue<TlsClientPayload>(); public TlsClientPayload Payload; public int Sending; public CancellationToken Token; public void Dispose() { Dispose(Socket); Dispose(NetworkStream); Dispose(SslStream); while (SendQueue.TryDequeue(out TlsClientPayload payload)) { payload.WaitHandle.Set(); payload.WaitHandle.Dispose(); } } private static void Dispose(IDisposable obj) => 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 => Interlocked.CompareExchange(ref m_cancelled, 0, 0) != 0; public bool Cancel() => 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="NoDelay"/> property. /// </summary> public const bool DefaultNoDelay = false; /// <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 readonly X509Certificate2Collection m_clientCertificates; private SslProtocols m_enabledSslProtocols; private string m_certificateFile; private byte[] m_payloadMarker; private EndianOrder m_payloadEndianOrder; private IPStack m_ipStack; private readonly ShortSynchronizedOperation m_dumpPayloadsOperation; private string[] m_serverList; private Dictionary<string, string> m_connectData; private ManualResetEvent m_connectWaitHandle; 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(); LocalCertificateSelectionCallback = DefaultLocalCertificateSelectionCallback; m_clientCertificates = new X509Certificate2Collection(); m_enabledSslProtocols = SslProtocols.Tls12; CheckCertificateRevocation = true; TrustedCertificatesPath = DefaultTrustedCertificatesPath; PayloadAware = DefaultPayloadAware; m_payloadMarker = Payload.DefaultMarker; m_payloadEndianOrder = EndianOrder.LittleEndian; IntegratedSecurity = DefaultIntegratedSecurity; IgnoreInvalidCredentials = DefaultIgnoreInvalidCredentials; AllowDualStackSocket = DefaultAllowDualStackSocket; MaxSendQueueSize = DefaultMaxSendQueueSize; NoDelay = DefaultNoDelay; 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() => 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; set; } /// <summary> /// Gets or sets the byte sequence used to mark the beginning of a payload in a <see cref="PayloadAware"/> transmission. /// </summary> /// <remarks> /// Setting property to <c>null</c> will create a zero-length payload marker. /// </remarks> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public byte[] PayloadMarker { get => m_payloadMarker; set => m_payloadMarker = value ?? Array.Empty<byte>(); } /// <summary> /// Gets or sets the endian order to apply for encoding and decoding payload size in a <see cref="PayloadAware"/> transmission. /// </summary> /// <remarks> /// Setting property to <c>null</c> will force use of little-endian encoding. /// </remarks> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public EndianOrder PayloadEndianOrder { get => m_payloadEndianOrder; set => m_payloadEndianOrder = value ?? EndianOrder.LittleEndian; } /// <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; set; } /// <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; set; } /// <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; set; } /// <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; set; } /// <summary> /// Gets or sets a boolean value that determines if small packets are delivered to the remote host without delay. /// </summary> [Category("Settings")] [DefaultValue(DefaultNoDelay)] [Description("Determines if small packets are delivered to the remote host without delay.")] public bool NoDelay { get; set; } /// <summary> /// Gets the <see cref="Socket"/> object for the <see cref="TlsClient"/>. /// </summary> [Browsable(false)] public Socket Client => m_connectState?.Socket; /// <summary> /// Gets the <see cref="SslStream"/> object for the <see cref="TlsClient"/>. /// </summary> [Browsable(false)] public SslStream SslStream => m_connectState?.SslStream; /// <summary> /// Gets the server URI of the <see cref="TlsClient"/>. /// </summary> [Browsable(false)] public override string ServerUri => $"{TransportProtocol}://{ServerList[ServerIndex]}".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; set; } /// <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 => 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; set; } /// <summary> /// Gets or sets the callback used to select a local certificate. /// </summary> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public LocalCertificateSelectionCallback LocalCertificateSelectionCallback { get; set; } /// <summary> /// Gets the collection of X509 certificates for this client. /// </summary> [Browsable(false)] public X509CertificateCollection ClientCertificates => m_clientCertificates; /// <summary> /// Gets or sets a set of flags which determine the enabled <see cref="SslProtocols"/>. /// </summary> /// <exception cref="SecurityException">Failed to write event log entry for security warning about use of less secure TLS/SSL protocols.</exception> [Category("Settings")] [DefaultValue(SslProtocols.Tls12)] [Description("The set of SSL protocols that are enabled for this client.")] public SslProtocols EnabledSslProtocols { get => m_enabledSslProtocols; set { m_enabledSslProtocols = value; // As of July 2014, Tls12 is the latest and most secure TLS protocol - all other protocols // represent a security risk when used, as such we log a security message when any of the // older protocols are being used. if (m_enabledSslProtocols >= SslProtocols.Tls12) return; try { string applicationName; // Get application name try { // Attempt to retrieve application name as defined in common security settings - this name // is typically preconfigured as the desired event source for event log entries ConfigurationFile config = ConfigurationFile.Current; CategorizedSettingsElementCollection settings = config.Settings["SecurityProvider"]; applicationName = settings["ApplicationName"].Value; } catch { applicationName = null; } // Fall back on running executable name if (string.IsNullOrWhiteSpace(applicationName)) applicationName = FilePath.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName); string message = $"One or more less secure TLS/SSL protocols \"{m_enabledSslProtocols}\" are being used by an instance of the TlsClient in {applicationName}"; EventLog.WriteEntry(applicationName, message, EventLogEntryType.Warning, 1); } catch (Exception ex) { throw new SecurityException($"Failed to write event log entry for security warning about use of less secure TLS/SSL protocols \"{m_enabledSslProtocols}\": {ex.Message}", ex); } } } /// <summary> /// Gets or sets a boolean value that determines whether the certificate revocation list is checked during authentication. /// </summary> [Category("Settings")] [DefaultValue(true)] [Description("True if the certificate revocation list is to be checked during authentication, otherwise False.")] public bool CheckCertificateRevocation { get; set; } /// <summary> /// Gets or sets the path to the certificate used for authentication. /// </summary> [Category("Settings")] [DefaultValue(null)] [Description("Path to the certificate used by this client for authentication.")] public string CertificateFile { get => m_certificateFile; set { if (string.IsNullOrWhiteSpace(value)) { m_certificateFile = null; Certificate = null; } else { m_certificateFile = FilePath.GetAbsolutePath(value); if (File.Exists(m_certificateFile)) Certificate = new X509Certificate2(m_certificateFile); } } } /// <summary> /// Gets or sets the local certificate selected by the default <see cref="LocalCertificateSelectionCallback"/>. /// </summary> [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public X509Certificate Certificate { get; set; } /// <summary> /// Gets or sets the path to the directory containing the trusted certificates. /// </summary>