Example #1
0
        /// <summary>
        /// Connect to the server.
        /// </summary>
        public void Connect()
        {
            LoggingUtilities.WriteLog($" Connect initiated.");
            do
            {
                this.reconnect       = false;
                this.Client          = new TcpClient(this.Server, this.Port);
                this.TdsCommunicator = new TDSCommunicator(this.Client.GetStream(), 4096, this.TrustServerCertificate);
                this.SendPreLogin();
                this.ReceivePreLoginResponse();
                this.SendLogin7();
                if (flag == TDSEncryptionOption.EncryptOff)
                {
                    this.TdsCommunicator = new TDSCommunicator(this.Client.GetStream(), 4096, this.TrustServerCertificate);
                }
                this.ReceiveLogin7Response();

                if (this.reconnect)
                {
                    this.Disconnect();
                    LoggingUtilities.WriteLog($" Routing to: {this.Server}:{this.Port}.");
                }
            }while (this.reconnect);

            LoggingUtilities.WriteLog($" Connect done.");
        }
Example #2
0
        /// <summary>
        /// Receive PreLogin response from the server.
        /// </summary>
        public void ReceivePreLoginResponse()
        {
            LoggingUtilities.WriteLog($" ReceivePreLoginResponse initiated.");

            if (this.TdsCommunicator.ReceiveTDSMessage() is TDSPreLoginPacketData response)
            {
                if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.Encryption) && response.Encryption == TDSEncryptionOption.EncryptReq)
                {
                    LoggingUtilities.WriteLog($" Server requires encryption, enabling encryption.");
                    this.TdsCommunicator.EnableEncryption(this.Server, this.EncryptionProtocol);
                    LoggingUtilities.WriteLog($" Encryption enabled.");
                }

                if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.FedAuthRequired) && response.FedAuthRequired == true)
                {
                    throw new NotSupportedException("FedAuth is being requested but the client doesn't support FedAuth.");
                }
            }
            else
            {
                throw new InvalidOperationException();
            }

            LoggingUtilities.WriteLog($" ReceivePreLoginResponse done.");
        }
Example #3
0
        /// <summary>
        /// Receive Login7 response from the server.
        /// </summary>
        public void ReceiveLogin7Response()
        {
            LoggingUtilities.WriteLog($" ReceiveLogin7Response initiated.");

            if (this.TdsCommunicator.ReceiveTDSMessage() is TDSTokenStreamPacketData response)
            {
                foreach (var token in response.Tokens)
                {
                    if (token is TDSEnvChangeToken)
                    {
                        var envChangeToken = token as TDSEnvChangeToken;
                        if (envChangeToken.Type == Tokens.EnvChange.TDSEnvChangeType.Routing)
                        {
                            LoggingUtilities.WriteLog($" Client received EnvChange routing token, client is being routed.");
                            this.Server     = envChangeToken.Values["AlternateServer"];
                            this.ServerName = this.Server;
                            this.Port       = int.Parse(envChangeToken.Values["ProtocolProperty"]);
                            this.reconnect  = true;
                        }
                    }
                    else if (token is TDSErrorToken)
                    {
                        var errorToken = token as TDSErrorToken;
                        LoggingUtilities.WriteLog($" Client received Error token:");

                        LoggingUtilities.WriteLog($"     Number: {errorToken.Number}");
                        LoggingUtilities.WriteLog($"     State: {errorToken.State}");
                        LoggingUtilities.WriteLog($"     Class: {errorToken.Class}");
                        LoggingUtilities.WriteLog($"     MsgText: {errorToken.MsgText}");
                        LoggingUtilities.WriteLog($"     ServerName: {errorToken.ServerName}");
                        LoggingUtilities.WriteLog($"     ProcName: {errorToken.ProcName}");
                        LoggingUtilities.WriteLog($"     LineNumber: {errorToken.LineNumber}");

                        if (errorToken.Number == 18456)
                        {
                            throw new Exception("Login failure.");
                        }
                    }
                    else if (token is TDSInfoToken)
                    {
                        var infoToken = token as TDSInfoToken;
                        LoggingUtilities.WriteLog($" Client received Info token:");

                        LoggingUtilities.WriteLog($"     Number: {infoToken.Number}");
                        LoggingUtilities.WriteLog($"     State: {infoToken.State}");
                        LoggingUtilities.WriteLog($"     Class: {infoToken.Class}");
                        LoggingUtilities.WriteLog($"     MsgText: {infoToken.MsgText}");
                        LoggingUtilities.WriteLog($"     ServerName: {infoToken.ServerName}");
                        LoggingUtilities.WriteLog($"     ProcName: {infoToken.ProcName}");
                        LoggingUtilities.WriteLog($"     LineNumber: {infoToken.LineNumber}");
                    }
                }
            }
            else
            {
                throw new InvalidOperationException();
            }

            LoggingUtilities.WriteLog($" ReceiveLogin7Response done.");
        }
        /// <summary>
        /// Terminate TDS PreLogin Packet.
        /// </summary>
        public void Terminate()
        {
            this.Terminated = true;
            this.Options.Add(new TDSPreLoginOptionToken(TDSPreLoginOptionTokenType.Terminator));

            LoggingUtilities.WriteLog($"  Adding PreLogin message terminator.");
        }
Example #5
0
 /// <summary>
 /// Disconnect from the server.
 /// </summary>
 public void Disconnect()
 {
     LoggingUtilities.WriteLog($" Disconnect initiated.");
     this.Client.Close();
     this.Client = null;
     LoggingUtilities.WriteLog($" Disconnect done.");
 }
Example #6
0
        /// <summary>
        /// Add TDS Login7 Option.
        /// </summary>
        /// <param name="optionName">Option Name</param>
        /// <param name="data">Option Data</param>
        public void AddOption(string optionName, string data)
        {
            if (optionName == null || data == null)
            {
                throw new ArgumentNullException();
            }

            if (this.Options.Where(opt => opt.Name == optionName).Any())
            {
                throw new Exception("Login7 option already set!");
            }

            if (optionName != "Password" && optionName != "ChangePassword")
            {
                LoggingUtilities.WriteLog($"  Adding Login7 option {optionName} [{data}].");
            }
            else
            {
                LoggingUtilities.WriteLog($"  Adding Login7 option {optionName}.");
            }

            var option = TDSLogin7OptionFactory.CreateOption(optionName, data);

            this.Options.Add(option);
        }
        /// <summary>
        /// Validate Server Certificate
        /// </summary>
        /// <param name="sender">Sender object</param>
        /// <param name="certificate">X509 Certificate</param>
        /// <param name="chain">X509 Chain</param>
        /// <param name="sslPolicyErrors">SSL Policy Errors</param>
        /// <returns>Returns true if no errors occurred.</returns>
        public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
            {
                return(true);
            }

            LoggingUtilities.WriteLog($"Certificate error: {sslPolicyErrors}");

            return(false);
        }
        public void SendPreLogin()
        {
            LoggingUtilities.WriteLog($" SendPreLogin initiated.");
            var tdsMessageBody = new TDSPreLoginPacketData(Version);

            tdsMessageBody.AddOption(TDSPreLoginOptionTokenType.Encryption, TDSEncryptionOption.EncryptOff);
            tdsMessageBody.Terminate();

            TdsCommunicator.SendTDSMessage(tdsMessageBody);
            LoggingUtilities.WriteLog($" SendPreLogin done.");
        }
Example #9
0
        /// <summary>
        /// Sends PreLogin message to the server.
        /// </summary>
        public void SendPreLogin()
        {
            LoggingUtilities.WriteLog($" SendPreLogin initiated.");
            var tdsMessageBody = new TDSPreLoginPacketData(this.Version);

            tdsMessageBody.AddOption(TDSPreLoginOptionTokenType.Encryption, TDSEncryptionOption.EncryptOff);
            tdsMessageBody.AddOption(TDSPreLoginOptionTokenType.TraceID, new TDSClientTraceID(Guid.NewGuid().ToByteArray(), Guid.NewGuid().ToByteArray(), 0));
            tdsMessageBody.Terminate();

            this.TdsCommunicator.SendTDSMessage(tdsMessageBody);
            LoggingUtilities.WriteLog($" SendPreLogin done.");
        }
        /// <summary>
        /// Connect to the server.
        /// </summary>
        public void Connect()
        {
            DateTime connectStartTime = DateTime.UtcNow;
            bool     preLoginDone     = false;

            LoggingUtilities.WriteLog($" Connect initiated.");

            try
            {
                do
                {
                    preLoginDone         = false;
                    this.reconnect       = false;
                    this.Client          = new TcpClient(this.Server, this.Port);
                    this.TdsCommunicator = new TDSCommunicator(this.Client.GetStream(), 4096);
                    this.SendPreLogin();
                    this.ReceivePreLoginResponse();
                    preLoginDone = true;
                    LoggingUtilities.WriteLog($" PreLogin phase took {(int)(DateTime.UtcNow - connectStartTime).TotalMilliseconds} milliseconds.");
                    this.SendLogin7();
                    this.ReceiveLogin7Response();

                    if (this.reconnect)
                    {
                        this.Disconnect();
                        LoggingUtilities.WriteLog($" Routing to: {this.Server}:{this.Port}.");
                    }
                }while (this.reconnect);

                LoggingUtilities.WriteLog($" Connect done.");
            }
            catch (SocketException socketException)
            {
                LoggingUtilities.WriteLog($" Networking error {socketException.NativeErrorCode} while trying to connect to {this.Server}:{this.Port}.");
            }
            catch (Exception ex)
            {
                if (!preLoginDone && DateTime.UtcNow >= connectStartTime.AddSeconds(5))
                {
                    LoggingUtilities.WriteLog($" Possible SNI timeout");
                }
                LoggingUtilities.WriteLog($"Exception:");
                LoggingUtilities.WriteLog($"{ex.Message}");
                if (ex.InnerException != null)
                {
                    LoggingUtilities.WriteLog($"InnerException: {ex.InnerException.Message}");
                }
                throw ex;
            }
        }
        /// <summary>
        /// Enable Transport Layer Security over TDS
        /// </summary>
        /// <param name="server">Server FQDN</param>
        /// <param name="encryptionProtocol">Encryption Protocol</param>
        public void EnableEncryption(string server, SslProtocols encryptionProtocol)
        {
            var tempStream0 = new TDSTemporaryStream(this.innerTdsStream);
            var tempStream1 = new SslStream(tempStream0, true, ValidateServerCertificate);

            //var tempStream1 = new SslStream(tempStream0, true);


            tempStream1.AuthenticateAsClient(server, new X509CertificateCollection(), encryptionProtocol, true);

            tempStream0.InnerStream         = this.innerTdsStream.InnerStream;
            this.innerTdsStream.InnerStream = tempStream1;

            LoggingUtilities.WriteLog($"  Cipher: {tempStream1.CipherAlgorithm} strength {tempStream1.CipherStrength}");
            LoggingUtilities.WriteLog($"  Hash: {tempStream1.HashAlgorithm} strength {tempStream1.HashStrength}");
            LoggingUtilities.WriteLog($"  Key exchange: {tempStream1.KeyExchangeAlgorithm} strength {tempStream1.KeyExchangeStrength}");
            LoggingUtilities.WriteLog($"  Protocol: {tempStream1.SslProtocol}");

            LoggingUtilities.WriteLog($"  Is authenticated: {tempStream1.IsAuthenticated}");
            LoggingUtilities.WriteLog($"  IsSigned: {tempStream1.IsSigned}");
            LoggingUtilities.WriteLog($"  Is Encrypted: {tempStream1.IsEncrypted}");

            X509Certificate localCertificate = tempStream1.LocalCertificate;

            if (tempStream1.LocalCertificate != null)
            {
                LoggingUtilities.WriteLog($"  Local cert was issued to {localCertificate.Subject} and is valid from {localCertificate.GetEffectiveDateString()} until {localCertificate.GetExpirationDateString()}.");
            }
            else
            {
                LoggingUtilities.WriteLog("  Local certificate is null.");
            }

            X509Certificate remoteCertificate = tempStream1.RemoteCertificate;

            if (tempStream1.RemoteCertificate != null)
            {
                LoggingUtilities.WriteLog($"  Remote cert was issued to {remoteCertificate.Subject} and is valid from {remoteCertificate.GetEffectiveDateString()} until {remoteCertificate.GetExpirationDateString()}.");
            }
            else
            {
                LoggingUtilities.WriteLog("  Remote certificate is null.");
            }
        }
 private void MeasureDNSResolutionTime()
 {
     try
     {
         var stopwatch = Stopwatch.StartNew();
         var addresses = Dns.GetHostAddresses(this.Server);
         stopwatch.Stop();
         var addressListString = string.Join(",", addresses.AsEnumerable());
         LoggingUtilities.WriteLog($"  DNS resolution took {stopwatch.ElapsedMilliseconds} ms, ({addressListString})", writeToSummaryLog: true);
     }
     catch (SocketException socketException)
     {
         LoggingUtilities.WriteLog($" DNS resolution failed with \"{socketException.Message}\", error {socketException.NativeErrorCode} for address {this.Server}", writeToSummaryLog: true);
     }
     catch (Exception ex)
     {
         LoggingUtilities.WriteLog($" DNS resolution failed with \"{ex.Message}\", for address {this.Server}", writeToSummaryLog: true);
     }
 }
Example #13
0
        /// <summary>
        /// Sends Login7 message to the server
        /// </summary>
        public void SendLogin7()
        {
            LoggingUtilities.WriteLog($" SendLogin7 initiated.");

            var tdsMessageBody = new TDSLogin7PacketData();

            tdsMessageBody.AddOption("HostName", Environment.MachineName);
            tdsMessageBody.AddOption("UserName", this.UserID);
            tdsMessageBody.AddOption("ServerName", this.ServerName);
            tdsMessageBody.AddOption("Password", this.Password);
            tdsMessageBody.AddOption("Database", this.Database);
            tdsMessageBody.AddOption("CltIntName", "TDSSQLTestClient");

            tdsMessageBody.OptionFlags1.Char      = TDSLogin7OptionFlags1Char.CharsetASCII;
            tdsMessageBody.OptionFlags1.Database  = TDSLogin7OptionFlags1Database.InitDBFatal;
            tdsMessageBody.OptionFlags1.DumpLoad  = TDSLogin7OptionFlags1DumpLoad.DumploadOn;
            tdsMessageBody.OptionFlags1.Float     = TDSLogin7OptionFlags1Float.FloatIEEE754;
            tdsMessageBody.OptionFlags1.SetLang   = TDSLogin7OptionFlags1SetLang.SetLangOn;
            tdsMessageBody.OptionFlags1.ByteOrder = TDSLogin7OptionFlags1ByteOrder.OrderX86;
            tdsMessageBody.OptionFlags1.UseDB     = TDSLogin7OptionFlags1UseDB.UseDBOff;

            tdsMessageBody.OptionFlags2.Language = TDSLogin7OptionFlags2Language.InitLangFatal;
            tdsMessageBody.OptionFlags2.ODBC     = TDSLogin7OptionFlags2ODBC.OdbcOn;
            tdsMessageBody.OptionFlags2.UserType = TDSLogin7OptionFlags2UserType.UserNormal;
            //Row below added
            //tdsMessageBody.OptionFlags2.IntSecurity = TDSLogin7OptionFlags2IntSecurity.IntegratedSecurityOn;

            tdsMessageBody.OptionFlags3.ChangePassword           = TDSLogin7OptionFlags3ChangePassword.NoChangeRequest;
            tdsMessageBody.OptionFlags3.UserInstanceProcess      = TDSLogin7OptionFlags3UserInstanceProcess.DontRequestSeparateProcess;
            tdsMessageBody.OptionFlags3.UnknownCollationHandling = TDSLogin7OptionFlags3UnknownCollationHandling.On;
            tdsMessageBody.OptionFlags3.Extension = TDSLogin7OptionFlags3Extension.DoesntExist;

            tdsMessageBody.TypeFlags.OLEDB          = TDSLogin7TypeFlagsOLEDB.On;
            tdsMessageBody.TypeFlags.SQLType        = TDSLogin7TypeFlagsSQLType.DFLT;
            tdsMessageBody.TypeFlags.ReadOnlyIntent = TDSLogin7TypeFlagsReadOnlyIntent.On;

            this.TdsCommunicator.SendTDSMessage(tdsMessageBody);

            LoggingUtilities.WriteLog($" SendLogin7 done.");
        }
Example #14
0
        /// <summary>
        /// Reads a TDS Token from a given MemoryStream
        /// </summary>
        /// <param name="stream">Stream that contains the token</param>
        /// <returns>Returns read TDS Token</returns>
        public static TDSToken ReadTokenFromStream(MemoryStream stream)
        {
            var tokenType = (TDSTokenType)stream.ReadByte();

            LoggingUtilities.WriteLog($"  Received {tokenType} token in Login7 response.");
            switch (tokenType)
            {
            case TDSTokenType.Error:
            {
                var token = new TDSErrorToken();
                token.Unpack(stream);

                return(token);
            }

            case TDSTokenType.EnvChange:
            {
                var token = new TDSEnvChangeToken();
                token.Unpack(stream);

                return(token);
            }

            case TDSTokenType.Info:
            {
                var token = new TDSInfoToken();
                token.Unpack(stream);

                return(token);
            }

            default:
            {
                IgnoreToken(tokenType, stream);

                return(null);
            }
            }
        }
        public void Connect()
        {
            LoggingUtilities.WriteLog($" Connect initiated.");
            do
            {
                Reconnect       = false;
                Client          = new TcpClient(Server, Port);
                TdsCommunicator = new TDSCommunicator(Client.GetStream(), 4096);
                SendPreLogin();
                ReceivePreLoginResponse();
                SendLogin7();
                ReceiveLogin7Response();

                if (Reconnect)
                {
                    Disconnect();
                    LoggingUtilities.WriteLog($" Routing to: {Server}:{Port}.");
                }
            }while (Reconnect);

            LoggingUtilities.WriteLog($" Connect done.");
        }
Example #16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TDSSQLTestClient"/> class.
        /// </summary>
        /// <param name="server">Server to connect to</param>
        /// <param name="port">Port to connect to</param>
        /// <param name="userID">Used ID</param>
        /// <param name="password">User password</param>
        /// <param name="database">Database to connect to</param>
        /// <param name="encryptionProtocol">Encryption Protocol</param>
        public TDSSQLTestClient(string server, int port, string userID, string password, string database, SslProtocols encryptionProtocol = SslProtocols.Tls12)
        {
            if (string.IsNullOrEmpty(server) || string.IsNullOrEmpty(userID) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(database))
            {
                throw new ArgumentNullException();
            }

            this.Client             = null;
            this.Version            = new TDSClientVersion(1, 0, 0, 0);
            this.Server             = server;
            this.ServerName         = server;
            this.Port               = port;
            this.UserID             = userID;
            this.Password           = password;
            this.Database           = database;
            this.EncryptionProtocol = encryptionProtocol;

            LoggingUtilities.WriteLog($" Instantiating TDSSQLTestClient with the following parameters:");

            LoggingUtilities.WriteLog($"     Server: {server}.");
            LoggingUtilities.WriteLog($"     Port: {port}.");
            LoggingUtilities.WriteLog($"     UserID: {userID}.");
            LoggingUtilities.WriteLog($"     Database: {database}.");
        }
        /// <summary>
        /// Adds PreLogin option to the PreLogin packet
        /// </summary>
        /// <param name="type">Option type</param>
        /// <param name="data">Option data</param>
        public void AddOption(TDSPreLoginOptionTokenType type, object data)
        {
            if (this.Terminated)
            {
                throw new InvalidOperationException();
            }

            switch (type)
            {
            case TDSPreLoginOptionTokenType.Version:
            {
                if (data is TDSClientVersion && this.ClientVersion == null)
                {
                    this.ClientVersion = (TDSClientVersion)data;
                    //LoggingUtilities.WriteLog($"    Adding PreLogin option {type}.");
                }
                else
                {
                    throw new ArgumentException();
                }

                break;
            }

            case TDSPreLoginOptionTokenType.Encryption:
            {
                if (data is TDSEncryptionOption)
                {
                    this.Encryption = (TDSEncryptionOption)data;

                    LoggingUtilities.WriteLog($"  Adding PreLogin option {type} [{this.Encryption}].");
                }
                else
                {
                    throw new ArgumentException();
                }

                break;
            }

            case TDSPreLoginOptionTokenType.FedAuthRequired:
            {
                if (data is bool)
                {
                    this.FedAuthRequired = (bool)data;

                    LoggingUtilities.WriteLog($"  Adding PreLogin option {type} [{(bool)data}].");
                }
                else
                {
                    throw new ArgumentException();
                }

                break;
            }

            case TDSPreLoginOptionTokenType.MARS:
            {
                if (data is bool)
                {
                    this.MARS = (bool)data;

                    LoggingUtilities.WriteLog($"  Adding PreLogin option {type} [{(bool)data}].");
                }
                else
                {
                    throw new ArgumentException();
                }

                break;
            }

            case TDSPreLoginOptionTokenType.ThreadID:
            {
                if (data is uint)
                {
                    this.ThreadID = (uint)data;

                    LoggingUtilities.WriteLog($"  Adding PreLogin option {type} [{this.ThreadID}].");
                }
                else
                {
                    throw new ArgumentException();
                }

                break;
            }

            case TDSPreLoginOptionTokenType.TraceID:
            {
                if (data is TDSClientTraceID)
                {
                    this.TraceID = (TDSClientTraceID)data;

                    LoggingUtilities.WriteLog($"  Adding PreLogin option {type}");
                    LoggingUtilities.WriteLog($"   ConnectionID: {new Guid(this.TraceID.TraceID).ToString().ToUpper()}", writeToSummaryLog: true);
                    LoggingUtilities.WriteLog($"   ActivityID: {new Guid(this.TraceID.ActivityID).ToString().ToUpper()}");
                    LoggingUtilities.WriteLog($"   ActivitySequence: {this.TraceID.ActivitySequence}");
                }
                else
                {
                    throw new ArgumentException();
                }

                break;
            }

            case TDSPreLoginOptionTokenType.NonceOpt:
            {
                if (data is byte[])
                {
                    this.Nonce = (byte[])data;

                    LoggingUtilities.WriteLog($"  Adding PreLogin option {type}.");
                }
                else
                {
                    throw new ArgumentException();
                }

                break;
            }

            default:
            {
                throw new NotSupportedException();
            }
            }

            this.Options.Add(new TDSPreLoginOptionToken(type));
        }
Example #18
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TDSSQLTestClient"/> class.
        /// </summary>
        /// <param name="server">Server to connect to</param>
        /// <param name="port">Port to connect to</param>
        /// <param name="userID">Used ID</param>
        /// <param name="password">User password</param>
        /// <param name="database">Database to connect to</param>
        /// <param name="encryptionProtocol">Encryption Protocol</param>
        public TDSSQLTestClient(string server, int port, string userID, string password, string database, Boolean TrustServerCertficate, string EncryptionOption, SslProtocols encryptionProtocol = SslProtocols.Tls12)
        {
            if (string.IsNullOrEmpty(server) || string.IsNullOrEmpty(userID) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(database))
            {
                throw new ArgumentNullException();
            }
            LoggingUtilities.WriteLog($"Nije sa githuba");
            this.Client                 = null;
            this.Version                = new TDSClientVersion(1, 0, 0, 0);
            this.Server                 = server;
            this.ServerName             = server;
            this.Port                   = port;
            this.UserID                 = userID;
            this.Password               = password;
            this.Database               = database;
            this.EncryptionProtocol     = encryptionProtocol;
            this.TrustServerCertificate = TrustServerCertficate;
            LoggingUtilities.WriteLog(EncryptionOption);

            switch (EncryptionOption)
            {
            case "EncryptOn":
            {
                this.EncryptionOption = TDSEncryptionOption.EncryptOn;
                break;
            }

            case "EncryptOff":
            {
                this.EncryptionOption = TDSEncryptionOption.EncryptOff;
                break;
            }

            case "EncryptReq":
            {
                this.EncryptionOption = TDSEncryptionOption.EncryptReq;
                break;
            }

            case "EncryptNotSup":
            {
                this.EncryptionOption = TDSEncryptionOption.EncryptNotSup;
                break;
            }

            case "EncryptClientCertOn":
            {
                this.EncryptionOption = TDSEncryptionOption.EncryptClientCertOn;
                break;
            }

            case "EncryptClientCertOff":
            {
                this.EncryptionOption = TDSEncryptionOption.EncryptClientCertOff;
                break;
            }

            case "EncryptClientCertReq":
            {
                this.EncryptionOption = TDSEncryptionOption.EncryptClientCertReq;
                break;
            }

            default:
            {
                throw new InvalidOperationException();
            }
            }

            LoggingUtilities.WriteLog($" Instantiating TDSSQLTestClient with the following parameters:");

            LoggingUtilities.WriteLog($"     Server: {server}.");
            LoggingUtilities.WriteLog($"     Port: {port}.");
            LoggingUtilities.WriteLog($"     UserID: {userID}.");
            LoggingUtilities.WriteLog($"     Database: {database}.");
            LoggingUtilities.WriteLog($"     TrustServerCertificate: {TrustServerCertificate}.");
            LoggingUtilities.WriteLog($"     EncryptionOption: {EncryptionOption}.");
        }
        /// <summary>
        /// Connect to the server.
        /// </summary>
        public void Connect()
        {
            DateTime connectStartTime   = DateTime.UtcNow;
            bool     preLoginDone       = false;
            var      originalServerName = this.Server;
            var      originalPort       = this.Port;

            LoggingUtilities.WriteLog($"Connect initiated (attempt # {++connectionAttempt}).", writeToSummaryLog: true);

            try
            {
                do
                {
                    preLoginDone   = false;
                    this.reconnect = false;

                    MeasureDNSResolutionTime();
                    this.Client          = new TcpClient(this.Server, this.Port);
                    this.TdsCommunicator = new TDSCommunicator(this.Client.GetStream(), 4096);
                    LoggingUtilities.WriteLog($"  TCP connection open between local {this.Client.Client.LocalEndPoint} and remote {this.Client.Client.RemoteEndPoint}", writeToVerboseLog: false, writeToSummaryLog: true);
                    LoggingUtilities.WriteLog($"  TCP connection open");
                    LoggingUtilities.WriteLog($"   Local endpoint is {this.Client.Client.LocalEndPoint}");
                    LoggingUtilities.WriteLog($"   Remote endpoint is {this.Client.Client.RemoteEndPoint}");
                    connectStartTime = DateTime.UtcNow;
                    this.SendPreLogin();
                    this.ReceivePreLoginResponse();
                    preLoginDone = true;
                    LoggingUtilities.WriteLog($" PreLogin phase took {(int)(DateTime.UtcNow - connectStartTime).TotalMilliseconds} milliseconds.");
                    this.SendLogin7();
                    this.ReceiveLogin7Response();

                    if (this.reconnect)
                    {
                        this.Disconnect();
                        LoggingUtilities.AddEmptyLine();
                        LoggingUtilities.WriteLog($" Routing to: {this.Server}:{this.Port}.");
                    }
                }while (this.reconnect);

                LoggingUtilities.WriteLog($" Connect done.", writeToSummaryLog: true);
            }
            catch (SocketException socketException)
            {
                LoggingUtilities.WriteLog($" Networking error {socketException.NativeErrorCode} while trying to connect to {this.Server}:{this.Port}.", writeToSummaryLog: true);
            }
            catch (Exception ex)
            {
                if (!preLoginDone && DateTime.UtcNow >= connectStartTime.AddSeconds(5))
                {
                    LoggingUtilities.WriteLog($" SNI timeout detected, PreLogin phase was not complete after {(int)(DateTime.UtcNow - connectStartTime).TotalMilliseconds} milliseconds.", writeToSummaryLog: true);
                }
                LoggingUtilities.WriteLog($"Exception:");
                LoggingUtilities.WriteLog($"{ex.Message}");
                if (ex.InnerException != null)
                {
                    LoggingUtilities.WriteLog($"InnerException: {ex.InnerException.Message}");
                }
                //throw ex;
            }
            finally
            {
                this.Server = originalServerName;
                this.Port   = originalPort;
            }
        }