From 0d418f440781e865dd444461ce2197ce21344d92 Mon Sep 17 00:00:00 2001 From: v-nmarko Date: Thu, 23 Jul 2020 10:25:42 +0200 Subject: [PATCH 1/2] Added support for unencrypted connections --- .../TDSClient.UnitTests.csproj | 2 +- .../TDSClient/TDS/Client/TDSClientVersion.cs | 2 +- .../TDSClient/TDS/Client/TDSSQLTestClient.cs | 33 ++++++++++++-- .../TDSClient/TDS/Comms/TDSCommunicator.cs | 43 ++++++++++++++++--- TDSClient/TDSClient/TDS/Comms/TDSStream.cs | 3 ++ TDSClient/TDSClient/TDSClient.csproj | 4 ++ TDSClient/TDSClientLiveTest/Program.cs | 18 ++++---- .../TDSClientLiveTest.csproj | 2 +- 8 files changed, 85 insertions(+), 22 deletions(-) diff --git a/TDSClient/TDSClient.UnitTests/TDSClient.UnitTests.csproj b/TDSClient/TDSClient.UnitTests/TDSClient.UnitTests.csproj index 981ab35..88056de 100644 --- a/TDSClient/TDSClient.UnitTests/TDSClient.UnitTests.csproj +++ b/TDSClient/TDSClient.UnitTests/TDSClient.UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp2.1 false diff --git a/TDSClient/TDSClient/TDS/Client/TDSClientVersion.cs b/TDSClient/TDSClient/TDS/Client/TDSClientVersion.cs index 51577b2..caa6aea 100644 --- a/TDSClient/TDSClient/TDS/Client/TDSClientVersion.cs +++ b/TDSClient/TDSClient/TDS/Client/TDSClientVersion.cs @@ -111,4 +111,4 @@ public bool Equals(TDSClientVersion other) this.SubBuildNumber == other.SubBuildNumber; } } -} +} \ No newline at end of file diff --git a/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs b/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs index 8715521..1132643 100644 --- a/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs +++ b/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs @@ -35,7 +35,7 @@ public class TDSSQLTestClient /// User password /// Database to connect to /// Encryption Protocol - public TDSSQLTestClient(string server, int port, string userID, string password, string database, SslProtocols encryptionProtocol = SslProtocols.Tls12) + public TDSSQLTestClient(string server, int port, string userID, string password, string database, Boolean TrustServerCertficate, TDSEncryptionOption EncryptionOption, SslProtocols encryptionProtocol = SslProtocols.Tls12) { if (string.IsNullOrEmpty(server) || string.IsNullOrEmpty(userID) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(database)) { @@ -51,6 +51,8 @@ public TDSSQLTestClient(string server, int port, string userID, string password, this.Password = password; this.Database = database; this.EncryptionProtocol = encryptionProtocol; + this.TrustServerCertificate = TrustServerCertficate; + this.EncryptionOption = EncryptionOption; LoggingUtilities.WriteLog($" Instantiating TDSSQLTestClient with the following parameters:"); @@ -60,10 +62,24 @@ public TDSSQLTestClient(string server, int port, string userID, string password, LoggingUtilities.WriteLog($" Database: {database}."); } + /// + /// Gets or sets the Encryption Option + /// + public TDSEncryptionOption EncryptionOption { get; set; } + + /// + /// Gets or sets TrustServerCertificate. + /// + public Boolean TrustServerCertificate { get; set; } + /// /// Gets or sets the Server. /// public string Server { get; set; } + /// + /// Server Encryption Reply sent in PreLoginResponse package. + /// + public static TDSEncryptionOption flag = TDSEncryptionOption.EncryptOn; /// /// Gets or sets the Server Name. @@ -118,7 +134,8 @@ public void SendPreLogin() LoggingUtilities.WriteLog($" SendPreLogin initiated."); var tdsMessageBody = new TDSPreLoginPacketData(this.Version); - tdsMessageBody.AddOption(TDSPreLoginOptionTokenType.Encryption, TDSEncryptionOption.EncryptOff); + //tdsMessageBody.AddOption(TDSPreLoginOptionTokenType.Encryption, TDSEncryptionOption.EncryptOn); + tdsMessageBody.AddOption(TDSPreLoginOptionTokenType.Encryption, this.EncryptionOption); tdsMessageBody.AddOption(TDSPreLoginOptionTokenType.TraceID, new TDSClientTraceID(Guid.NewGuid().ToByteArray(), Guid.NewGuid().ToByteArray(), 0)); tdsMessageBody.Terminate(); @@ -153,6 +170,8 @@ public void SendLogin7() 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; @@ -177,8 +196,10 @@ public void ReceivePreLoginResponse() if (this.TdsCommunicator.ReceiveTDSMessage() is TDSPreLoginPacketData response) { - if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.Encryption) && response.Encryption == TDSEncryptionOption.EncryptReq) + //if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.Encryption) && response.Encryption == TDSEncryptionOption.EncryptReq) + if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.Encryption) && (response.Encryption == TDSEncryptionOption.EncryptReq || response.Encryption == TDSEncryptionOption.EncryptOn || response.Encryption == TDSEncryptionOption.EncryptOff)) { + flag = response.Encryption; LoggingUtilities.WriteLog($" Server requires encryption, enabling encryption."); this.TdsCommunicator.EnableEncryption(this.Server, this.EncryptionProtocol); LoggingUtilities.WriteLog($" Encryption enabled."); @@ -271,10 +292,14 @@ public void Connect() { this.reconnect = false; this.Client = new TcpClient(this.Server, this.Port); - this.TdsCommunicator = new TDSCommunicator(this.Client.GetStream(), 4096); + 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) diff --git a/TDSClient/TDSClient/TDS/Comms/TDSCommunicator.cs b/TDSClient/TDSClient/TDS/Comms/TDSCommunicator.cs index 136c9de..6bf9b3e 100644 --- a/TDSClient/TDSClient/TDS/Comms/TDSCommunicator.cs +++ b/TDSClient/TDSClient/TDS/Comms/TDSCommunicator.cs @@ -12,6 +12,7 @@ namespace TDSClient.TDS.Comms using System.Net.Sockets; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; + using TDSClient.TDS.Client; using TDSClient.TDS.Header; using TDSClient.TDS.Interfaces; using TDSClient.TDS.Login7; @@ -39,6 +40,11 @@ public class TDSCommunicator /// private readonly ushort packetSize; + /// + /// TrustServerCertificate + /// + private static Boolean TrustServerCertificate; + /// /// Current TDS Communicator State /// @@ -49,11 +55,12 @@ public class TDSCommunicator /// /// NetworkStream used for communication /// TDS packet size - public TDSCommunicator(Stream stream, ushort packetSize) + public TDSCommunicator(Stream stream, ushort packetSize, Boolean TrustServerCertificate) { this.packetSize = packetSize; this.innerTdsStream = new TDSStream(stream, new TimeSpan(0, 0, 30), packetSize); this.innerStream = this.innerTdsStream; + TDSCommunicator.TrustServerCertificate = TrustServerCertificate; } /// @@ -66,15 +73,26 @@ public TDSCommunicator(Stream stream, ushort packetSize) /// Returns true if no errors occurred. public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { - if (sslPolicyErrors == SslPolicyErrors.None) + if(TrustServerCertificate == false) + { + if (sslPolicyErrors == SslPolicyErrors.None) + { + return true; + } + + LoggingUtilities.WriteLog($"Certificate error: {sslPolicyErrors}"); + + return false; + } + else { return true; } + + } - LoggingUtilities.WriteLog($"Certificate error: {sslPolicyErrors}"); - return false; - } + /// /// Enable Transport Layer Security over TDS @@ -85,9 +103,11 @@ 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; @@ -121,15 +141,24 @@ public void EnableEncryption(string server, SslProtocols encryptionProtocol) } } + /// /// Receive TDS Message from the server. /// /// Returns received TDS Message. public ITDSPacketData ReceiveTDSMessage() { + if(TDSSQLTestClient.flag == TDSEncryptionOption.EncryptOff && this.communicatorState == TDSCommunicatorState.Initial) + { + this.communicatorState = TDSCommunicatorState.SentLogin7RecordWithCompleteAuthToken; + } + TDSSQLTestClient.flag = TDSEncryptionOption.EncryptOn; byte[] resultBuffer = null; var curOffset = 0; - + if(this.communicatorState == TDSCommunicatorState.SentLogin7RecordWithCompleteAuthToken) + { + + } do { Array.Resize(ref resultBuffer, curOffset + this.packetSize); diff --git a/TDSClient/TDSClient/TDS/Comms/TDSStream.cs b/TDSClient/TDSClient/TDS/Comms/TDSStream.cs index 0563106..877d545 100644 --- a/TDSClient/TDSClient/TDS/Comms/TDSStream.cs +++ b/TDSClient/TDSClient/TDS/Comms/TDSStream.cs @@ -9,6 +9,8 @@ namespace TDSClient.TDS.Comms using System; using System.IO; using TDSClient.TDS.Header; + using TDSClient.TDS.Utilities; + using System.Text; /// /// Stream used to pass TDS messages. @@ -133,6 +135,7 @@ public override int Read(byte[] buffer, int offset, int count) do { curPos += this.InnerStream.Read(headerBuffer, curPos, 8 - curPos); + //LoggingUtilities.WriteLog(Encoding.UTF8.GetString(headerBuffer, 0, 8)); if (curPos == 0) { diff --git a/TDSClient/TDSClient/TDSClient.csproj b/TDSClient/TDSClient/TDSClient.csproj index 8967eb1..ed704fa 100644 --- a/TDSClient/TDSClient/TDSClient.csproj +++ b/TDSClient/TDSClient/TDSClient.csproj @@ -5,6 +5,10 @@ false Copyright (c) Microsoft Corporation. + + Library + + diff --git a/TDSClient/TDSClientLiveTest/Program.cs b/TDSClient/TDSClientLiveTest/Program.cs index cc61e45..5dba9e2 100644 --- a/TDSClient/TDSClientLiveTest/Program.cs +++ b/TDSClient/TDSClientLiveTest/Program.cs @@ -1,23 +1,25 @@ using System; using TDSClient.TDS.Client; +using TDSClient.TDS.Header; namespace TDSClientLiveTest { class Program { - public static string Server = ""; + public static string Server = "localhost"; public static int Port = 1433; - public static string Username = ""; - public static string Password = ""; - public static string Database = ""; - - + public static string Username = "admin"; + public static string Password = "admin"; + public static string Database = "master"; + public static bool TrustServerCertificate = true; + public static TDSEncryptionOption EncryptionOption = TDSEncryptionOption.EncryptOn; + static void Main(string[] args) { - TDSSQLTestClient tdsClient = new TDSSQLTestClient(Server, Port, Username, Password, Database); + TDSSQLTestClient tdsClient = new TDSSQLTestClient(Server, Port, Username, Password, Database, TrustServerCertificate, EncryptionOption); TDSClient.TDS.Utilities.LoggingUtilities.SetVerboseLog(Console.Out); tdsClient.Connect(); tdsClient.Disconnect(); } } -} +} \ No newline at end of file diff --git a/TDSClient/TDSClientLiveTest/TDSClientLiveTest.csproj b/TDSClient/TDSClientLiveTest/TDSClientLiveTest.csproj index b223a2c..c60a6b6 100644 --- a/TDSClient/TDSClientLiveTest/TDSClientLiveTest.csproj +++ b/TDSClient/TDSClientLiveTest/TDSClientLiveTest.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + netcoreapp2.1 From 97f0b667fb58786bcd7c4ff65ce15daaecbac8c9 Mon Sep 17 00:00:00 2001 From: v-nmarko Date: Thu, 30 Jul 2020 10:24:37 +0200 Subject: [PATCH 2/2] Added support for all encryption options --- AdvancedConnectivityPolicyTests.ps1 | 6 +- AzureSQLConnectivityChecker.ps1 | 121 +++++++++++++++--- README.md | 12 +- ReducedSQLConnectivityChecker.ps1 | 26 ++-- RunLocally.ps1 | 14 +- .../TDSClient/TDS/Client/TDSSQLTestClient.cs | 60 ++++++++- TDSClient/TDSClientLiveTest/Program.cs | 2 +- netstandard2.0/TDSClient.dll | Bin 52736 -> 57344 bytes 8 files changed, 196 insertions(+), 45 deletions(-) diff --git a/AdvancedConnectivityPolicyTests.ps1 b/AdvancedConnectivityPolicyTests.ps1 index fee642e..64c7a08 100644 --- a/AdvancedConnectivityPolicyTests.ps1 +++ b/AdvancedConnectivityPolicyTests.ps1 @@ -137,6 +137,9 @@ $EncryptionProtocol = $parameters['EncryptionProtocol'] $RepositoryBranch = $parameters['RepositoryBranch'] $Local = $parameters['Local'] $LocalPath = $parameters['LocalPath'] +$TrustServerCertificate = $parameters['TrustServerCertificate'] +$EncryptionOption = $parameters['EncryptionOption'] + if ([string]::IsNullOrEmpty($env:TEMP)) { @@ -153,6 +156,7 @@ try { else { $path = $env:TEMP + "/AzureSQLConnectivityChecker/TDSClient.dll" Invoke-WebRequest -Uri $('https://github.com/Azure/SQL-Connectivity-Checker/raw/' + $RepositoryBranch + '/netstandard2.0/TDSClient.dll') -OutFile $path -UseBasicParsing + } $path = $env:TEMP + "/AzureSQLConnectivityChecker/TDSClient.dll" @@ -185,7 +189,7 @@ try { $encryption = [System.Security.Authentication.SslProtocols]::Tls12 -bor [System.Security.Authentication.SslProtocols]::Tls11 -bor [System.Security.Authentication.SslProtocols]::Default } } - $tdsClient = [TDSClient.TDS.Client.TDSSQLTestClient]::new($Server, $Port, $User, $Password, $Database, $encryption) + $tdsClient = [TDSClient.TDS.Client.TDSSQLTestClient]::new($Server, $Port, $User, $Password, $Database, $TrustServerCertificate, $EncryptionOption, $encryption) $tdsClient.Connect() $tdsClient.Disconnect() } diff --git a/AzureSQLConnectivityChecker.ps1 b/AzureSQLConnectivityChecker.ps1 index 421df96..56f28a8 100644 --- a/AzureSQLConnectivityChecker.ps1 +++ b/AzureSQLConnectivityChecker.ps1 @@ -57,6 +57,14 @@ if ($null -ne $parameters) { if ($null -ne $parameters['RepositoryBranch']) { $RepositoryBranch = $parameters['RepositoryBranch'] } + if($null -ne $parameters['TrustServerCertificate']){ + $TrustServerCertificate = $parameters['TrustServerCertificate'] + } + write-host $TrustServerCertificate + if($null -ne $parameters['EncryptionOption']){ + $EncryptionOption = $parameters['EncryptionOption'] + } + write-host $EncryptionOption } $Server = $Server.Trim() @@ -65,6 +73,8 @@ $Server = $Server.Replace(',1433', '') $Server = $Server.Replace(',3342', '') $Server = $Server.Replace(';', '') +$flag = $false + if ($null -eq $User -or '' -eq $User) { $User = 'AzSQLConnCheckerUser' } @@ -224,7 +234,50 @@ function PrintDNSResults($dnsResult, [string] $dnsSource) { } } -function ValidateDNS([String] $Server) { +function ValidateDnsHelper([string] $Server1){ + $flag = ValidateDNS $Server + if($flag -eq $false){ + $flag = ValidateDNS ($Server1 + '.database.windows.net') + if($flag -eq $true){ + $Server1 = ($Server + '.database.windows.net') + } + } + if($flag -eq $false){ + $flag = ValidateDNS $Server1 + '.database.cloudapi.de' + if($flag -eq $true){ + $Server1 = ($Server + '.database.cloudapi.de') + } + } + if($flag -eq $false){ + $flag = ValidateDNS ($Server1 + '.database.chinacloudapi.cn') + if($flag -eq $true){ + $Server1 = ($Server + '.database.chinacloudapi.cn') + } + } + if($flag -eq $false){ + $flag = ValidateDNS ($Server1 + '.database.usgovcloudapi.net') + if($flag -eq $true){ + $Server1 = ($Server + '.database.usgovcloudapi.net') + } + } + if($flag -eq $false){ + $flag = ValidateDNS ($Server1 + '.sql.azuresynapse.net') + if($flag -eq $true){ + $Server1 = ($Server + '.sql.azuresynapse.net') + } + } + if($flag -eq $true){ + $Server = $Server1 + Write-Host $Server + return [bool]($flag), $Server1 + }else{ + Write-Host "Error at ValidateDNS" -Foreground Red + Write-Host "Server cant be Validated" -Foreground Red + $host.exit() + } +} + +function ValidateDNS([string] $Server) { Try { Write-Host 'Validating DNS record for' $Server -ForegroundColor Green @@ -239,6 +292,8 @@ function ValidateDNS([String] $Server) { $DNSfromAzureDNS = Resolve-DnsName -Name $Server -DnsOnly -Server 208.67.222.222 -ErrorAction SilentlyContinue PrintDNSResults $DNSfromAzureDNS 'Open DNS' + + return [bool]($DNSfromAzureDNS -or $DNSfromCache -or $DNSfromCustomerServer -or $DNSfromHosts) } Catch { Write-Host "Error at ValidateDNS" -Foreground Red @@ -246,6 +301,14 @@ function ValidateDNS([String] $Server) { } } +function CheckIfIpAddress([string] $Server){ + if($Server -match "\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"){ + return $true + }else{ + return $false + } +} + function IsManagedInstance([String] $Server) { return [bool]((($Server.ToCharArray() | Where-Object { $_ -eq '.' } | Measure-Object).Count) -ge 4) } @@ -476,7 +539,7 @@ function RunSqlDBConnectivityTests($resolvedAddress) { } $gateway = $SQLDBGateways | Where-Object { $_.Gateways -eq $resolvedAddress } - if (!$gateway) { + if (!$gateway -and !($resolvedAddress -eq '127.0.0.1') -and !($resolvedAddress -eq '::1')) { Write-Host ' ERROR:' $resolvedAddress 'is not a valid gateway address' -ForegroundColor Red Write-Host ' Please review your DNS configuration, it should resolve to a valid gateway address' -ForegroundColor Red Write-Host ' See the valid gateway addresses at https://docs.microsoft.com/en-us/azure/sql-database/sql-database-connectivity-architecture#azure-sql-database-gateway-ip-addresses' -ForegroundColor Red @@ -574,6 +637,8 @@ function RunConnectivityPolicyTests($port) { RepositoryBranch = $RepositoryBranch Local = $Local LocalPath = $LocalPath + TrustServerCertificate = $TrustServerCertificate + EncryptionOption = $EncryptionOption } if (Test-Path "$env:TEMP\AzureSQLConnectivityChecker\") { @@ -584,6 +649,7 @@ function RunConnectivityPolicyTests($port) { if ($Local) { Copy-Item -Path $($LocalPath + './AdvancedConnectivityPolicyTests.ps1') -Destination "$env:TEMP\AzureSQLConnectivityChecker\AdvancedConnectivityPolicyTests.ps1" + } else { Invoke-WebRequest -Uri $('https://raw.githubusercontent.com/Azure/SQL-Connectivity-Checker/' + $RepositoryBranch + '/AdvancedConnectivityPolicyTests.ps1') -OutFile "$env:TEMP\AzureSQLConnectivityChecker\AdvancedConnectivityPolicyTests.ps1" -UseBasicParsing @@ -694,13 +760,13 @@ try { throw } - if (!$Server.EndsWith('.database.windows.net') ` - -and !$Server.EndsWith('.database.cloudapi.de') ` - -and !$Server.EndsWith('.database.chinacloudapi.cn') ` - -and !$Server.EndsWith('.database.usgovcloudapi.net') ` - -and !$Server.EndsWith('.sql.azuresynapse.net')) { - $Server = $Server + '.database.windows.net' - } + #if (!$Server.EndsWith('.database.windows.net') ` + # -and !$Server.EndsWith('.database.cloudapi.de') ` + # -and !$Server.EndsWith('.database.chinacloudapi.cn') ` + # -and !$Server.EndsWith('.database.usgovcloudapi.net') ` + # -and !$Server.EndsWith('.sql.azuresynapse.net')) { + # $Server = $Server + '.database.windows.net' + #} #Print local network configuration PrintLocalNetworkConfiguration @@ -718,20 +784,33 @@ try { } } - ValidateDNS $Server + $checkIP = CheckIfIpAddress $Server - try { - $dnsResult = [System.Net.DNS]::GetHostEntry($Server) - } - catch { - Write-Host ' ERROR: Name resolution of' $Server 'failed' -ForegroundColor Red - Write-Host ' Please make sure the server name FQDN is correct and that your machine can resolve it.' -ForegroundColor Red - Write-Host ' Failure to resolve domain name for your logical server is almost always the result of specifying an invalid/misspelled server name,' -ForegroundColor Red - Write-Host ' or a client-side networking issue that you will need to pursue with your local network administrator.' -ForegroundColor Red - Write-Error '' -ErrorAction Stop + if($checkIP -eq $false){ + $return = ValidateDnsHelper $Server + $Server = $return[1] + $success = $return[0] + + + try { + $dnsResult = [System.Net.DNS]::GetHostEntry($Server) + } + + catch { + Write-Host ' ERROR: Name resolution of' $Server 'failed' -ForegroundColor Red + Write-Host ' Please make sure the server name FQDN is correct and that your machine can resolve it.' -ForegroundColor Red + Write-Host ' Failure to resolve domain name for your logical server is almost always the result of specifying an invalid/misspelled server name,' -ForegroundColor Red + Write-Host ' or a client-side networking issue that you will need to pursue with your local network administrator.' -ForegroundColor Red + Write-Error '' -ErrorAction Stop } - $resolvedAddress = $dnsResult.AddressList[0].IPAddressToString - $dbPort = 1433 + $resolvedAddress = $dnsResult.AddressList[0].IPAddressToString + $dbPort = 1433 + }else{ + $resolvedAddress = $Server + $dbPort = 1433 + } + + write-host $resolvedAddress #Run connectivity tests Write-Host diff --git a/README.md b/README.md index 4f9a28c..bb54ee8 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,16 @@ $parameters = @{ # Supports Single, Elastic Pools and Managed Instance (please provide FQDN, MI public endpoint is supported) # Supports Azure Synapse / Azure SQL Data Warehouse (*.sql.azuresynapse.net / *.database.windows.net) # Supports Public Cloud (*.database.windows.net), Azure China (*.database.chinacloudapi.cn), Azure Germany (*.database.cloudapi.de) and Azure Government (*.database.usgovcloudapi.net) - Server = '.database.windows.net' # or any other supported FQDN - Database = '' # Set the name of the database you wish to test, 'master' will be used by default if nothing is set - User = '' # Set the login username you wish to use, 'AzSQLConnCheckerUser' will be used by default if nothing is set - Password = '' # Set the login password you wish to use, 'AzSQLConnCheckerPassword' will be used by default if nothing is set + Server = 'localhost' # or any other supported FQDN + Database = 'master' # Set the name of the database you wish to test, 'master' will be used by default if nothing is set + User = 'admin' # Set the login username you wish to use, 'AzSQLConnCheckerUser' will be used by default if nothing is set + Password = 'admin' # Set the login password you wish to use, 'AzSQLConnCheckerPassword' will be used by default if nothing is set + TrustServerCertificate = '' #Boolean value, 'true' will be used by default if nothing is set + EncryptionOption = '' # TDS Encryption option sent by the client, can be: 'EncryptOn', 'EncryptOff', 'EncryptNotSup', 'EncryptReq', 'EncryptClientCertOff', 'EncryptClientCertOn', 'EncryptClientCertReq', 'EncryptOn' will be used by default if nothing is set ## Optional parameters (default values will be used if omitted) SendAnonymousUsageData = $true # Set as $true (default) or $false - RunAdvancedConnectivityPolicyTests = $true # Set as $true (default) or $false, this will load the library from Microsoft's GitHub repository needed for running advanced connectivity tests + RunAdvancedConnectivityPolicyTests = $false # Set as $true (default) or $false, this will load the library from Microsoft's GitHub repository needed for running advanced connectivity tests CollectNetworkTrace = $true # Set as $true (default) or $false #EncryptionProtocol = '' # Supported values: 'Tls 1.0', 'Tls 1.1', 'Tls 1.2'; Without this parameter operating system will choose the best protocol to use } diff --git a/ReducedSQLConnectivityChecker.ps1 b/ReducedSQLConnectivityChecker.ps1 index 0506439..7bae41f 100644 --- a/ReducedSQLConnectivityChecker.ps1 +++ b/ReducedSQLConnectivityChecker.ps1 @@ -9,6 +9,8 @@ if ($null -ne $parameters) { if ($null -ne $parameters['RepositoryBranch']) { $RepositoryBranch = $parameters['RepositoryBranch'] } + $TrustServerCertificate = $parameters['TrustServerCertificate'] + $EncryptionOption = $parameters['EncryptionOption'] } $Server = $Server.Trim() @@ -35,6 +37,14 @@ if ($null -eq $Local) { if ($null -eq $RepositoryBranch) { $RepositoryBranch = 'master' +} + +if ($null -eq $TrustServerCertificate -or '' -eq $TrustServerCertificate){ + $TrustServerCertificate = $true +} + +if ($null -eq $EncryptionOption -or '' -eq $EncryptionOption){ + $EncryptionOption = 'EncryptOn' } # PowerShell Container Image Support Start @@ -223,13 +233,13 @@ try { throw } - if (!$Server.EndsWith('.database.windows.net') ` - -and !$Server.EndsWith('.database.cloudapi.de') ` - -and !$Server.EndsWith('.database.chinacloudapi.cn') ` - -and !$Server.EndsWith('.sql.azuresynapse.net')) { - $Server = $Server + '.database.windows.net' - } - + # if (!$Server.EndsWith('.database.windows.net') ` + # -and !$Server.EndsWith('.database.cloudapi.de') ` + # -and !$Server.EndsWith('.database.chinacloudapi.cn') ` + # -and !$Server.EndsWith('.sql.azuresynapse.net')) { + # $Server = $Server + '.database.windows.net' + # } + if ($SendAnonymousUsageData) { SendAnonymousUsageData } @@ -281,7 +291,7 @@ try { $Port = 3342 } - $tdsClient = [TDSClient.TDS.Client.TDSSQLTestClient]::new($Server, $Port, $User, $Password, $Database, $encryption) + $tdsClient = [TDSClient.TDS.Client.TDSSQLTestClient]::new($Server, $Port, $User, $Password, $Database, $encryption, $TrustServerCertificate, $EncryptionOption) $tdsClient.Connect() $tdsClient.Disconnect() } diff --git a/RunLocally.ps1 b/RunLocally.ps1 index 3692295..0fff80f 100644 --- a/RunLocally.ps1 +++ b/RunLocally.ps1 @@ -3,16 +3,20 @@ $LocalPath = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definiti # Script parameters $parameters = @{ - Server = '.database.windows.net' - Database = '' # Set the name of the database you wish to test, 'master' will be used by default if nothing is set - User = '' # Set the login username you wish to use, 'AzSQLConnCheckerUser' will be used by default if nothing is set - Password = '' # Set the login password you wish to use, 'AzSQLConnCheckerPassword' will be used by default if nothing is set + Server = 'localhost' + Database = 'master' # Set the name of the database you wish to test, 'master' will be used by default if nothing is set + User = 'admin' # Set the login username you wish to use, 'AzSQLConnCheckerUser' will be used by default if nothing is set + Password = 'admin' # Set the login password you wish to use, 'AzSQLConnCheckerPassword' will be used by default if nothing is set + TrustServerCertificate = 'true' #Boolean value, 'true' will be used by default if nothing is set + EncryptionOption = 'EncryptNotSup' # TDS Encryption option sent by the client, can be: 'EncryptOn', 'EncryptOff', 'EncryptNotSup', 'EncryptReq', 'EncryptClientCertOff', 'EncryptClientCertOn', 'EncryptClientCertReq', 'EncryptOn' will be used by default if nothing is set + + ## Optional parameters (default values will be used if ommited) SendAnonymousUsageData = $true # Set as $true (default) or $false RunAdvancedConnectivityPolicyTests = $true # Set as $true (default) or $false, this will download the library needed for running advanced connectivity tests CollectNetworkTrace = $true # Set as $true (default) or $false - #EncryptionProtocol = '' # Supported values: 'Tls 1.0', 'Tls 1.1', 'Tls 1.2'; Without this parameter operating system will choose the best protocol to use + EncryptionProtocol = 'Tls 1.2' # Supported values: 'Tls 1.0', 'Tls 1.1', 'Tls 1.2'; Without this parameter operating system will choose the best protocol to use ## Run locally parameters Local = $true # Do Not Change diff --git a/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs b/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs index 1132643..24fe080 100644 --- a/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs +++ b/TDSClient/TDSClient/TDS/Client/TDSSQLTestClient.cs @@ -35,13 +35,13 @@ public class TDSSQLTestClient /// User password /// Database to connect to /// Encryption Protocol - public TDSSQLTestClient(string server, int port, string userID, string password, string database, Boolean TrustServerCertficate, TDSEncryptionOption EncryptionOption, SslProtocols encryptionProtocol = SslProtocols.Tls12) + 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; @@ -52,7 +52,51 @@ public TDSSQLTestClient(string server, int port, string userID, string password, this.Database = database; this.EncryptionProtocol = encryptionProtocol; this.TrustServerCertificate = TrustServerCertficate; - this.EncryptionOption = EncryptionOption; + 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:"); @@ -60,6 +104,8 @@ public TDSSQLTestClient(string server, int port, string userID, string password, LoggingUtilities.WriteLog($" Port: {port}."); LoggingUtilities.WriteLog($" UserID: {userID}."); LoggingUtilities.WriteLog($" Database: {database}."); + LoggingUtilities.WriteLog($" TrustServerCertificate: {TrustServerCertificate}."); + LoggingUtilities.WriteLog($" EncryptionOption: {EncryptionOption}."); } /// @@ -196,7 +242,11 @@ public void ReceivePreLoginResponse() if (this.TdsCommunicator.ReceiveTDSMessage() is TDSPreLoginPacketData response) { - //if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.Encryption) && response.Encryption == TDSEncryptionOption.EncryptReq) + if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.Encryption) && (response.Encryption == TDSEncryptionOption.EncryptReq && this.EncryptionOption == TDSEncryptionOption.EncryptNotSup)) + { + throw new NotSupportedException("Server requires encryption and has closed the connection"); + } + if (response.Options.Exists(opt => opt.Type == TDSPreLoginOptionTokenType.Encryption) && (response.Encryption == TDSEncryptionOption.EncryptReq || response.Encryption == TDSEncryptionOption.EncryptOn || response.Encryption == TDSEncryptionOption.EncryptOff)) { flag = response.Encryption; @@ -209,6 +259,8 @@ public void ReceivePreLoginResponse() { throw new NotSupportedException("FedAuth is being requested but the client doesn't support FedAuth."); } + + } else { diff --git a/TDSClient/TDSClientLiveTest/Program.cs b/TDSClient/TDSClientLiveTest/Program.cs index 5dba9e2..e219b26 100644 --- a/TDSClient/TDSClientLiveTest/Program.cs +++ b/TDSClient/TDSClientLiveTest/Program.cs @@ -12,7 +12,7 @@ class Program public static string Password = "admin"; public static string Database = "master"; public static bool TrustServerCertificate = true; - public static TDSEncryptionOption EncryptionOption = TDSEncryptionOption.EncryptOn; + public static string EncryptionOption = "EncryptOff"; static void Main(string[] args) { diff --git a/netstandard2.0/TDSClient.dll b/netstandard2.0/TDSClient.dll index 51713b2fbc60afcdfd4ee934331191282221dfe8..5a6f72c4a28322195695ddff0a83973ed0bead64 100644 GIT binary patch literal 57344 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 literal 52736 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 Qo{5-kP1g^v|2qx*2Nnl$@Bjb+