├── .gitignore ├── AdvancedConnectivityPolicyTests.ps1 ├── AzureSQLConnectivityChecker.ps1 ├── CODE_OF_CONDUCT.md ├── LICENSE ├── PRIVACY ├── README.md ├── ReducedSQLConnectivityChecker.ps1 ├── RunLocally.ps1 ├── SECURITY.md ├── TDSClient ├── TDSClient.UnitTests │ ├── Assets │ │ └── PacketData │ │ │ ├── Login7_Bytes.json │ │ │ ├── Login7_Object.json │ │ │ ├── LoginResponse_Bytes.json │ │ │ ├── LoginResponse_Object.json │ │ │ ├── PreLogin_Bytes.json │ │ │ └── PreLogin_Object.json │ ├── Settings.StyleCop │ ├── TDS │ │ ├── Comms │ │ │ └── TDSStreamTests.cs │ │ ├── Packets │ │ │ ├── Login7PacketTests.cs │ │ │ ├── LoginResponsePacketTests.cs │ │ │ └── PreLoginPacketTests.cs │ │ └── Utilities │ │ │ ├── BigEndianUtilitiesTests.cs │ │ │ └── LittleEndianUtilitiesTests.cs │ └── TDSClient.UnitTests.csproj ├── TDSClient.sln ├── TDSClient │ ├── AuthenticationProvider │ │ ├── ADALHelper.cs │ │ ├── AuthenticationProvider.cs │ │ └── MSALHelper.cs │ ├── TDS │ │ ├── Client │ │ │ ├── TDSClientTraceID.cs │ │ │ ├── TDSClientVersion.cs │ │ │ └── TDSSQLTestClient.cs │ │ ├── Comms │ │ │ ├── TDSCommunicator.cs │ │ │ ├── TDSCommunicatorState.cs │ │ │ ├── TDSStream.cs │ │ │ └── TDSTemporaryStream.cs │ │ ├── FedAuthMessage │ │ │ └── TDSFedAuthMessageToken.cs │ │ ├── Header │ │ │ ├── TDSMessageStatus.cs │ │ │ ├── TDSMessageType.cs │ │ │ └── TDSPacketHeader.cs │ │ ├── Interfaces │ │ │ ├── IPackageable.cs │ │ │ └── ITDSPacketData.cs │ │ ├── Login7 │ │ │ ├── Options │ │ │ │ ├── TDSLogin7Option.cs │ │ │ │ ├── TDSLogin7OptionFactory.cs │ │ │ │ ├── TDSLogin7PasswordOption.cs │ │ │ │ └── TDSLogin7TextOption.cs │ │ │ ├── TDSLogin7FeatureExt.cs │ │ │ ├── TDSLogin7FeatureOptionToken.cs │ │ │ ├── TDSLogin7FeatureOptionsToken.cs │ │ │ ├── TDSLogin7FedAuthOptionToken.cs │ │ │ ├── TDSLogin7GenericOptionToken.cs │ │ │ ├── TDSLogin7OptionFlags1.cs │ │ │ ├── TDSLogin7OptionFlags2.cs │ │ │ ├── TDSLogin7OptionFlags3.cs │ │ │ ├── TDSLogin7PacketData.cs │ │ │ ├── TDSLogin7TokenOffsetProperty.cs │ │ │ └── TDSLogin7TypeFlags.cs │ │ ├── PreLogin │ │ │ ├── TDSEncryptionOption.cs │ │ │ ├── TDSPreLoginAuthenticationType.cs │ │ │ ├── TDSPreLoginOptionToken.cs │ │ │ ├── TDSPreLoginOptionTokenType.cs │ │ │ └── TDSPreLoginPacketData.cs │ │ ├── Tokens │ │ │ ├── EnvChange │ │ │ │ ├── TDSEnvChangeToken.cs │ │ │ │ └── TDSEnvChangeType.cs │ │ │ ├── FedAuthInfoToken │ │ │ │ ├── TDSFedAuthInfoId.cs │ │ │ │ ├── TDSFedAuthInfoOption.cs │ │ │ │ ├── TDSFedAuthInfoOptionSPN.cs │ │ │ │ ├── TDSFedAuthInfoOptionSTSURL.cs │ │ │ │ └── TDSFedAuthInfoToken.cs │ │ │ ├── TDSDoneToken.cs │ │ │ ├── TDSErrorToken.cs │ │ │ ├── TDSInfoToken.cs │ │ │ ├── TDSLoginAckToken.cs │ │ │ ├── TDSToken.cs │ │ │ ├── TDSTokenFactory.cs │ │ │ ├── TDSTokenStreamPacketData.cs │ │ │ └── TDSTokenType.cs │ │ └── Utilities │ │ │ ├── BigEndianUtilities.cs │ │ │ ├── LittleEndianUtilities.cs │ │ │ └── LoggingUtilities.cs │ └── TDSClient.csproj └── TDSClientLiveTest │ ├── Program.cs │ └── TDSClientLiveTest.csproj ├── UserSettings.xml └── netstandard2.0 ├── Microsoft.Identity.Client.dll ├── Microsoft.IdentityModel.Abstractions.dll ├── Microsoft.IdentityModel.Clients.ActiveDirectory.dll └── TDSClient.dll /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /PRIVACY: -------------------------------------------------------------------------------- 1 | Data Collection. 2 | The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the repository. There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft's privacy statement. Our privacy statement is located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. 3 | 4 | You can avoid sending anonymous usage data by setting: 5 | SendAnonymousUsageData = $false -------------------------------------------------------------------------------- /RunLocally.ps1: -------------------------------------------------------------------------------- 1 | #Run locally parameters 2 | $LocalPath = [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Definition) 3 | $Path = Join-Path $LocalPath 'AzureSQLConnectivityChecker.ps1' 4 | 5 | # Script parameters 6 | $parameters = @{ 7 | Server = '.database.windows.net' 8 | Database = '' # Set the name of the database you wish to test, 'master' will be used by default if nothing is set 9 | User = '' # Set the login username you wish to use, 'AzSQLConnCheckerUser' will be used by default if nothing is set 10 | Password = '' # Set the login password you wish to use, 'AzSQLConnCheckerPassword' will be used by default if nothing is set 11 | 12 | ## Optional parameters (default values will be used if ommited) 13 | SendAnonymousUsageData = $true # Set as $true (default) or $false 14 | RunAdvancedConnectivityPolicyTests = $true # Set as $true (default) or $false, this will download the library needed for running advanced connectivity tests 15 | CollectNetworkTrace = $true # Set as $true (default) or $false 16 | ConnectionAttempts = 1 # Number of connection attempts while running advanced connectivity tests 17 | DelayBetweenConnections = 1 # Number of seconds to wait between connection attempts while running advanced connectivity tests 18 | #EncryptionProtocol = '' # Supported values: 'Tls 1.0', 'Tls 1.1', 'Tls 1.2'; Without this parameter operating system will choose the best protocol to use 19 | 20 | ## Run locally parameters 21 | Local = $true # Do Not Change 22 | LocalPath = $LocalPath # Do Not Change 23 | } 24 | 25 | Write-Host 'Please wait...' 26 | Write-Host '(The tests are being run inside a PowerShell job and output will be updated only once the job completes all the tests)' 27 | $ProgressPreference = "SilentlyContinue"; 28 | $job = Start-Job -ArgumentList $parameters -FilePath $Path 29 | Wait-Job $job | Out-Null 30 | Receive-Job -Job $job -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/Assets/PacketData/Login7_Bytes.json: -------------------------------------------------------------------------------- 1 | { 2 | "$type": "System.Byte[], System.Private.CoreLib", 3 | "$value": "iAAAAAIACXIAEAAAAAAABwABAAAAAAAA4AMAAOABAAAJBAAAXgAIAG4AAgByAAAAcgAHAIAAAACAAAAAgAAEAIgAAACIAAAAAFCL4rePiAAAAIgAAACIAAAAAAAAAHMAawBvAHMAdABvAHYAMQBzAGEATwBTAFEATAAtADMAMgBPAEQAQgBDAA==" 4 | } -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/Assets/PacketData/Login7_Object.json: -------------------------------------------------------------------------------- 1 | { 2 | "$type": "TDSClient.TDS.Login7.TDSLogin7PacketData, TDSClient", 3 | "Length": 136, 4 | "TDSVersion": 1913192450, 5 | "PacketSize": 4096, 6 | "ClientProgVer": 117440512, 7 | "ClientPID": 256, 8 | "ConnectionID": 0, 9 | "OptionFlags1": { 10 | "$type": "TDSClient.TDS.Login7.TDSLogin7OptionFlags1, TDSClient", 11 | "ByteOrder": 0, 12 | "Char": 0, 13 | "Float": 0, 14 | "DumpLoad": 0, 15 | "UseDB": 1, 16 | "Database": 1, 17 | "SetLang": 1 18 | }, 19 | "OptionFlags2": { 20 | "$type": "TDSClient.TDS.Login7.TDSLogin7OptionFlags2, TDSClient", 21 | "Language": 1, 22 | "ODBC": 1, 23 | "UserType": 0, 24 | "IntSecurity": 0 25 | }, 26 | "TypeFlags": { 27 | "$type": "TDSClient.TDS.Login7.TDSLogin7TypeFlags, TDSClient", 28 | "SQLType": 0, 29 | "OLEDB": 0, 30 | "ReadOnlyIntent": 0 31 | }, 32 | "OptionFlags3": { 33 | "$type": "TDSClient.TDS.Login7.TDSLogin7OptionFlags3, TDSClient", 34 | "ChangePassword": 0, 35 | "SendYukonBinaryXML": 0, 36 | "UserInstanceProcess": 0, 37 | "UnknownCollationHandling": 0, 38 | "Extension": 0 39 | }, 40 | "ClientTimeZone": 480, 41 | "ClientLCID": 1033, 42 | "ClientID": { 43 | "$type": "System.Byte[], System.Private.CoreLib", 44 | "$value": "AFCL4reP" 45 | }, 46 | "Options": { 47 | "$type": "System.Collections.Generic.List`1[[TDSClient.TDS.Login7.Options.TDSLogin7Option, TDSClient]], System.Private.CoreLib", 48 | "$values": [ 49 | { 50 | "$type": "TDSClient.TDS.Login7.Options.TDSLogin7TextOption, TDSClient", 51 | "Text": "skostov1", 52 | "Name": "HostName", 53 | "Position": 94, 54 | "Length": 8, 55 | "TrueLength": 16 56 | }, 57 | { 58 | "$type": "TDSClient.TDS.Login7.Options.TDSLogin7TextOption, TDSClient", 59 | "Text": "sa", 60 | "Name": "UserName", 61 | "Position": 110, 62 | "Length": 2, 63 | "TrueLength": 4 64 | }, 65 | { 66 | "$type": "TDSClient.TDS.Login7.Options.TDSLogin7TextOption, TDSClient", 67 | "Text": "OSQL-32", 68 | "Name": "AppName", 69 | "Position": 114, 70 | "Length": 7, 71 | "TrueLength": 14 72 | }, 73 | { 74 | "$type": "TDSClient.TDS.Login7.Options.TDSLogin7TextOption, TDSClient", 75 | "Text": "ODBC", 76 | "Name": "CltIntName", 77 | "Position": 128, 78 | "Length": 4, 79 | "TrueLength": 8 80 | } 81 | ] 82 | } 83 | } -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/Assets/PacketData/LoginResponse_Bytes.json: -------------------------------------------------------------------------------- 1 | { 2 | "$type": "System.Byte[], System.Private.CoreLib", 3 | "$value": "4xsAAQZtAGEAcwB0AGUAcgAGbQBhAHMAdABlAHIAq1gARRYAAAIAJQBDAGgAYQBuAGcAZQBkACAAZABhAHQAYQBiAGEAcwBlACAAYwBvAG4AdABlAHgAdAAgAHQAbwAgACcAbQBhAHMAdABlAHIAJwAuAAAAAAAAAOMIAAcFCQTQADQA4xcAAgp1AHMAXwBlAG4AZwBsAGkAcwBoAADjEwAEBDQAMAA5ADYABDQAMAA5ADYAq1wARxYAAAEAJwBDAGgAYQBuAGcAZQBkACAAbABhAG4AZwB1AGEAZwBlACAAcwBlAHQAdABpAG4AZwAgAHQAbwAgAHUAcwBfAGUAbgBnAGwAaQBzAGgALgAAAAAAAACtNgABcgkAAhZNAGkAYwByAG8AcwBvAGYAdAAgAFMAUQBMACAAUwBlAHIAdgBlAHIAAAAAAAAAAAD9AAAAAAAAAAAAAAAA" 4 | } -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/Assets/PacketData/LoginResponse_Object.json: -------------------------------------------------------------------------------- 1 | { 2 | "$type": "TDSClient.TDS.Tokens.TDSTokenStreamPacketData, TDSClient", 3 | "Tokens": { 4 | "$type": "System.Collections.Generic.List`1[[TDSClient.TDS.Tokens.TDSToken, TDSClient]], System.Private.CoreLib", 5 | "$values": [ 6 | { 7 | "$type": "TDSClient.TDS.Tokens.TDSEnvChangeToken, TDSClient", 8 | "Type": 1, 9 | "Values": { "$type": "System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.String, System.Private.CoreLib]], System.Private.CoreLib" } 10 | }, 11 | { 12 | "$type": "TDSClient.TDS.Tokens.TDSInfoToken, TDSClient", 13 | "Number": 5701, 14 | "State": 2, 15 | "Class": 0, 16 | "MsgText": "Changed database context to 'master'.", 17 | "ServerName": "", 18 | "ProcName": "", 19 | "LineNumber": 0 20 | }, 21 | { 22 | "$type": "TDSClient.TDS.Tokens.TDSEnvChangeToken, TDSClient", 23 | "Type": 7, 24 | "Values": { "$type": "System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.String, System.Private.CoreLib]], System.Private.CoreLib" } 25 | }, 26 | { 27 | "$type": "TDSClient.TDS.Tokens.TDSEnvChangeToken, TDSClient", 28 | "Type": 2, 29 | "Values": { "$type": "System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.String, System.Private.CoreLib]], System.Private.CoreLib" } 30 | }, 31 | { 32 | "$type": "TDSClient.TDS.Tokens.TDSEnvChangeToken, TDSClient", 33 | "Type": 4, 34 | "Values": { "$type": "System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.String, System.Private.CoreLib]], System.Private.CoreLib" } 35 | }, 36 | { 37 | "$type": "TDSClient.TDS.Tokens.TDSInfoToken, TDSClient", 38 | "Number": 5703, 39 | "State": 1, 40 | "Class": 0, 41 | "MsgText": "Changed language setting to us_english.", 42 | "ServerName": "", 43 | "ProcName": "", 44 | "LineNumber": 0 45 | } 46 | ] 47 | } 48 | } -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/Assets/PacketData/PreLogin_Bytes.json: -------------------------------------------------------------------------------- 1 | { 2 | "$type": "System.Byte[], System.Private.CoreLib", 3 | "$value": "AAAaAAYBACAAAQIAIQABAwAiAAQEACYAAf8JAAAAAAABALgNAAAB" 4 | } -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/Assets/PacketData/PreLogin_Object.json: -------------------------------------------------------------------------------- 1 | { 2 | "$type": "TDSClient.TDS.PreLogin.TDSPreLoginPacketData, TDSClient", 3 | "Options": { 4 | "$type": "System.Collections.Generic.List`1[[TDSClient.TDS.PreLogin.TDSPreLoginOptionToken, TDSClient]], System.Private.CoreLib", 5 | "$values": [ 6 | { 7 | "$type": "TDSClient.TDS.PreLogin.TDSPreLoginOptionToken, TDSClient", 8 | "Type": 0, 9 | "Offset": 26, 10 | "Length": 6 11 | }, 12 | { 13 | "$type": "TDSClient.TDS.PreLogin.TDSPreLoginOptionToken, TDSClient", 14 | "Type": 1, 15 | "Offset": 32, 16 | "Length": 1 17 | }, 18 | { 19 | "$type": "TDSClient.TDS.PreLogin.TDSPreLoginOptionToken, TDSClient", 20 | "Type": 2, 21 | "Offset": 33, 22 | "Length": 1 23 | }, 24 | { 25 | "$type": "TDSClient.TDS.PreLogin.TDSPreLoginOptionToken, TDSClient", 26 | "Type": 3, 27 | "Offset": 34, 28 | "Length": 4 29 | }, 30 | { 31 | "$type": "TDSClient.TDS.PreLogin.TDSPreLoginOptionToken, TDSClient", 32 | "Type": 4, 33 | "Offset": 38, 34 | "Length": 1 35 | }, 36 | { 37 | "$type": "TDSClient.TDS.PreLogin.TDSPreLoginOptionToken, TDSClient", 38 | "Type": 255, 39 | "Offset": 0, 40 | "Length": 0 41 | } 42 | ] 43 | }, 44 | "ClientVersion": { 45 | "$type": "TDSClient.TDS.Client.TDSClientVersion, TDSClient", 46 | "Major": 0, 47 | "Minor": 0, 48 | "BuildNumber": 2304, 49 | "SubBuildNumber": 0 50 | }, 51 | "Encryption": 1, 52 | "ThreadID": 3087859712, 53 | "MARS": true, 54 | "TraceID": null, 55 | "FedAuthRequired": false, 56 | "Nonce": null, 57 | "Instance": { 58 | "$type": "System.Byte[], System.Private.CoreLib", 59 | "$value": "AA==" 60 | }, 61 | "Terminated": true 62 | } -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/TDS/Comms/TDSStreamTests.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.UnitTests.TDS.Comms 8 | { 9 | using System; 10 | using System.IO; 11 | using Microsoft.VisualStudio.TestTools.UnitTesting; 12 | using TDSClient.TDS.Comms; 13 | 14 | [TestClass] 15 | public class TDSStreamTests 16 | { 17 | [TestMethod] 18 | public void ReadFromTDSStream_SinglePacket() 19 | { 20 | var innerStream = new MemoryStream(); 21 | 22 | innerStream.Write(new byte[] 23 | { 24 | 0x12, 0x01, 0x00, 0x2F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 25 | 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 26 | 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 27 | }); 28 | innerStream.Seek(0, SeekOrigin.Begin); 29 | 30 | var stream = new TDSStream(innerStream, new TimeSpan(0, 0, 30), 4096); 31 | byte[] resultBuffer = null; 32 | var curOffset = 0; 33 | 34 | do 35 | { 36 | Array.Resize(ref resultBuffer, curOffset + 4096); 37 | curOffset += stream.Read(resultBuffer, curOffset, 4096); 38 | } 39 | while (!stream.InboundMessageTerminated); 40 | 41 | Array.Resize(ref resultBuffer, curOffset); 42 | 43 | Console.WriteLine(string.Join(' ', resultBuffer)); 44 | 45 | CollectionAssert.AreEqual( 46 | new byte[] 47 | { 48 | 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 49 | 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 51 | }, 52 | resultBuffer); 53 | } 54 | 55 | [TestMethod] 56 | public void ReadFromTDSStream_MultiplePackets() 57 | { 58 | var innerStream = new MemoryStream(); 59 | 60 | innerStream.Write(new byte[] 61 | { 62 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 63 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 64 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 65 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 66 | 0x12, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 67 | }); 68 | innerStream.Seek(0, SeekOrigin.Begin); 69 | 70 | var stream = new TDSStream(innerStream, new TimeSpan(0, 0, 30), 16); 71 | byte[] resultBuffer = null; 72 | var curOffset = 0; 73 | 74 | do 75 | { 76 | Array.Resize(ref resultBuffer, curOffset + 2); 77 | curOffset += stream.Read(resultBuffer, curOffset, 2); 78 | } 79 | while (!stream.InboundMessageTerminated); 80 | 81 | Array.Resize(ref resultBuffer, curOffset); 82 | 83 | Console.WriteLine(string.Join(' ', resultBuffer)); 84 | 85 | CollectionAssert.AreEqual( 86 | new byte[] 87 | { 88 | 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 89 | 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 90 | 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 91 | }, 92 | resultBuffer); 93 | } 94 | 95 | [TestMethod] 96 | public void WriteToTDSStream_SinglePacket() 97 | { 98 | var innerStream = new MemoryStream(); 99 | var stream = new TDSStream(innerStream, new TimeSpan(0, 0, 30), 4096) 100 | { 101 | CurrentOutboundMessageType = TDSClient.TDS.Header.TDSMessageType.PreLogin 102 | }; 103 | 104 | stream.Write(new byte[] 105 | { 106 | 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 107 | 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 108 | 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 109 | }); 110 | 111 | CollectionAssert.AreEqual( 112 | new byte[] 113 | { 114 | 0x12, 0x01, 0x00, 0x2F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 115 | 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 116 | 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 117 | }, 118 | innerStream.ToArray()); 119 | } 120 | 121 | [TestMethod] 122 | public void WriteToTDSStream_MultiplePackets() 123 | { 124 | var innerStream = new MemoryStream(); 125 | var stream = new TDSStream(innerStream, new TimeSpan(0, 0, 30), 16) 126 | { 127 | CurrentOutboundMessageType = TDSClient.TDS.Header.TDSMessageType.PreLogin 128 | }; 129 | 130 | stream.Write(new byte[] 131 | { 132 | 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 133 | 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 134 | 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 135 | }); 136 | 137 | CollectionAssert.AreEqual( 138 | new byte[] 139 | { 140 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x06, 0x01, 0x00, 0x20, 141 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x21, 0x00, 0x01, 0x03, 142 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x22, 0x00, 0x04, 0x04, 0x00, 0x26, 0x00, 143 | 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x01, 0xFF, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 144 | 0x12, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0xB8, 0x0D, 0x00, 0x00, 0x01 145 | }, 146 | innerStream.ToArray()); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/TDS/Packets/Login7PacketTests.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.UnitTests.TDS.Packets 8 | { 9 | using System.IO; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using Newtonsoft.Json; 12 | using TDSClient.TDS.Login7; 13 | 14 | [TestClass] 15 | public class Login7PacketTests 16 | { 17 | [TestMethod] 18 | public void Login7Packing() 19 | { 20 | var bytesJSON = File.ReadAllText("./Assets/PacketData/Login7_Bytes.json"); 21 | var packetJSON = File.ReadAllText("./Assets/PacketData/Login7_Object.json"); 22 | 23 | JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 24 | var bytes = JsonConvert.DeserializeObject(bytesJSON, settings); 25 | var packet = JsonConvert.DeserializeObject(packetJSON, settings); 26 | 27 | var testArray = new byte[bytes.Length]; 28 | packet.Pack(new MemoryStream(testArray)); 29 | 30 | CollectionAssert.AreEqual(bytes, testArray); 31 | } 32 | 33 | [TestMethod] 34 | public void Login7Unpacking() 35 | { 36 | var bytesJSON = File.ReadAllText("./Assets/PacketData/Login7_Bytes.json"); 37 | var packetJSON = File.ReadAllText("./Assets/PacketData/Login7_Object.json"); 38 | 39 | JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 40 | var bytes = JsonConvert.DeserializeObject(bytesJSON, settings); 41 | var packet = JsonConvert.DeserializeObject(packetJSON, settings); 42 | 43 | var testPacket = new TDSLogin7PacketData("skostov1", "OSQL-32", "test-server", "test-database"); 44 | testPacket.Unpack(new MemoryStream(bytes)); 45 | var a = JsonConvert.SerializeObject(testPacket, settings); 46 | Assert.AreEqual(packet, testPacket); 47 | } 48 | 49 | [TestMethod] 50 | public void Login7PacketCreation() 51 | { 52 | // TODO: Add test. 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/TDS/Packets/LoginResponsePacketTests.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.UnitTests.TDS.Packets 8 | { 9 | using System.IO; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using Newtonsoft.Json; 12 | using TDSClient.TDS.Tokens; 13 | 14 | [TestClass] 15 | public class LoginResponsePacketTests 16 | { 17 | [TestMethod] 18 | public void LoginResponseUnpacking() 19 | { 20 | var bytesJSON = File.ReadAllText("./Assets/PacketData/LoginResponse_Bytes.json"); 21 | var packetJSON = File.ReadAllText("./Assets/PacketData/LoginResponse_Object.json"); 22 | 23 | JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 24 | var bytes = JsonConvert.DeserializeObject(bytesJSON, settings); 25 | var packet = JsonConvert.DeserializeObject(packetJSON, settings); 26 | 27 | var testPacket = new TDSTokenStreamPacketData(); 28 | testPacket.Unpack(new MemoryStream(bytes)); 29 | 30 | Assert.AreEqual(packet, testPacket); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/TDS/Packets/PreLoginPacketTests.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.UnitTests.TDS.Packets 8 | { 9 | using System.IO; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using Newtonsoft.Json; 12 | using TDSClient.TDS.PreLogin; 13 | 14 | [TestClass] 15 | public class PreLoginPacketTests 16 | { 17 | [TestMethod] 18 | public void PreLoginPacking() 19 | { 20 | var bytesJSON = File.ReadAllText("./Assets/PacketData/PreLogin_Bytes.json"); 21 | var packetJSON = File.ReadAllText("./Assets/PacketData/PreLogin_Object.json"); 22 | 23 | JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 24 | var bytes = JsonConvert.DeserializeObject(bytesJSON, settings); 25 | var packet = JsonConvert.DeserializeObject(packetJSON, settings); 26 | 27 | var testArray = new byte[bytes.Length]; 28 | packet.Pack(new MemoryStream(testArray)); 29 | 30 | CollectionAssert.AreEqual(bytes, testArray); 31 | } 32 | 33 | [TestMethod] 34 | public void PreLoginUnpacking() 35 | { 36 | var bytesJSON = File.ReadAllText("./Assets/PacketData/PreLogin_Bytes.json"); 37 | var packetJSON = File.ReadAllText("./Assets/PacketData/PreLogin_Object.json"); 38 | 39 | JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 40 | var bytes = JsonConvert.DeserializeObject(bytesJSON, settings); 41 | var packet = JsonConvert.DeserializeObject(packetJSON, settings); 42 | 43 | var testPacket = new TDSPreLoginPacketData(); 44 | testPacket.Unpack(new MemoryStream(bytes)); 45 | 46 | Assert.AreEqual(packet, testPacket); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/TDS/Utilities/BigEndianUtilitiesTests.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.UnitTests.TDS.Utilities 8 | { 9 | using System.IO; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using TDSClient.TDS.Utilities; 12 | 13 | [TestClass] 14 | public class BigEndianUtilitiesTests 15 | { 16 | [TestMethod] 17 | public void ReadUShortFromMemoryStream() 18 | { 19 | var stream = new MemoryStream(); 20 | stream.Write(new byte[] { 0x01, 0x23 }); 21 | stream.Seek(0, SeekOrigin.Begin); 22 | 23 | var res = BigEndianUtilities.ReadUShort(stream); 24 | 25 | Assert.AreEqual(0x0123, res); 26 | } 27 | 28 | [TestMethod] 29 | public void ReadUIntFromMemoryStream() 30 | { 31 | var stream = new MemoryStream(); 32 | stream.Write(new byte[] { 0x01, 0x23, 0x45, 0x67 }); 33 | stream.Seek(0, SeekOrigin.Begin); 34 | 35 | var res = BigEndianUtilities.ReadUInt(stream); 36 | 37 | Assert.AreEqual((uint)0x01234567, res); 38 | } 39 | 40 | [TestMethod] 41 | public void ReadULongFromMemoryStream() 42 | { 43 | var stream = new MemoryStream(); 44 | stream.Write(new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }); 45 | stream.Seek(0, SeekOrigin.Begin); 46 | 47 | var res = BigEndianUtilities.ReadULong(stream); 48 | 49 | Assert.AreEqual((ulong)0x0123456789abcdef, res); 50 | } 51 | 52 | [TestMethod] 53 | public void ReadByteArrayFromMemoryStream() 54 | { 55 | var stream = new MemoryStream(); 56 | stream.Write(new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }); 57 | stream.Seek(0, SeekOrigin.Begin); 58 | 59 | var res = BigEndianUtilities.ReadByteArray(stream, 8); 60 | 61 | CollectionAssert.AreEqual(new byte[] { 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01 }, res); 62 | } 63 | 64 | [TestMethod] 65 | public void WriteUShortToMemoryStream() 66 | { 67 | var stream = new MemoryStream(); 68 | 69 | BigEndianUtilities.WriteUShort(stream, 0x0123); 70 | 71 | CollectionAssert.AreEqual(new byte[] { 0x01, 0x23 }, stream.ToArray()); 72 | } 73 | 74 | [TestMethod] 75 | public void WriteUIntToMemoryStream() 76 | { 77 | var stream = new MemoryStream(); 78 | 79 | BigEndianUtilities.WriteUInt(stream, 0x01234567); 80 | 81 | CollectionAssert.AreEqual(new byte[] { 0x01, 0x23, 0x45, 0x67 }, stream.ToArray()); 82 | } 83 | 84 | [TestMethod] 85 | public void WriteULongToMemoryStream() 86 | { 87 | var stream = new MemoryStream(); 88 | 89 | BigEndianUtilities.WriteULong(stream, 0x0123456789abcdef); 90 | 91 | CollectionAssert.AreEqual(new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, stream.ToArray()); 92 | } 93 | 94 | [TestMethod] 95 | public void WriteByteArrayToMemoryStream() 96 | { 97 | var stream = new MemoryStream(); 98 | 99 | BigEndianUtilities.WriteByteArray(stream, new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }); 100 | 101 | CollectionAssert.AreEqual(new byte[] { 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01 }, stream.ToArray()); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/TDS/Utilities/LittleEndianUtilitiesTests.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.UnitTests.TDS.Utilities 8 | { 9 | using System.IO; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using TDSClient.TDS.Utilities; 12 | 13 | [TestClass] 14 | public class LittleEndianUtilitiesTests 15 | { 16 | [TestMethod] 17 | public void ReadUShortFromMemoryStream() 18 | { 19 | var stream = new MemoryStream(); 20 | stream.Write(new byte[] { 0x01, 0x23 }); 21 | stream.Seek(0, SeekOrigin.Begin); 22 | 23 | var res = LittleEndianUtilities.ReadUShort(stream); 24 | 25 | Assert.AreEqual(0x2301, res); 26 | } 27 | 28 | [TestMethod] 29 | public void ReadUIntFromMemoryStream() 30 | { 31 | var stream = new MemoryStream(); 32 | stream.Write(new byte[] { 0x01, 0x23, 0x45, 0x67 }); 33 | stream.Seek(0, SeekOrigin.Begin); 34 | 35 | var res = LittleEndianUtilities.ReadUInt(stream); 36 | 37 | Assert.AreEqual((uint)0x67452301, res); 38 | } 39 | 40 | [TestMethod] 41 | public void WriteUShortToMemoryStream() 42 | { 43 | var stream = new MemoryStream(); 44 | 45 | LittleEndianUtilities.WriteUShort(stream, 0x0123); 46 | 47 | CollectionAssert.AreEqual(new byte[] { 0x23, 0x01 }, stream.ToArray()); 48 | } 49 | 50 | [TestMethod] 51 | public void WriteUIntToMemoryStream() 52 | { 53 | var stream = new MemoryStream(); 54 | 55 | LittleEndianUtilities.WriteUInt(stream, 0x01234567); 56 | 57 | CollectionAssert.AreEqual(new byte[] { 0x67, 0x45, 0x23, 0x01 }, stream.ToArray()); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TDSClient/TDSClient.UnitTests/TDSClient.UnitTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Always 24 | 25 | 26 | Always 27 | 28 | 29 | PreserveNewest 30 | 31 | 32 | PreserveNewest 33 | 34 | 35 | Always 36 | 37 | 38 | Always 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /TDSClient/TDSClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29609.76 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TDSClient", "TDSClient\TDSClient.csproj", "{EC19F04A-D87D-46C7-9A84-9358D0858D13}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TDSClient.UnitTests", "TDSClient.UnitTests\TDSClient.UnitTests.csproj", "{7D3E4489-90B3-45D9-8317-771E2674988F}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TDSClientLiveTest", "TDSClientLiveTest\TDSClientLiveTest.csproj", "{9DD3A454-670F-4165-813E-324670E01538}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {EC19F04A-D87D-46C7-9A84-9358D0858D13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {EC19F04A-D87D-46C7-9A84-9358D0858D13}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {EC19F04A-D87D-46C7-9A84-9358D0858D13}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {EC19F04A-D87D-46C7-9A84-9358D0858D13}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {7D3E4489-90B3-45D9-8317-771E2674988F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {7D3E4489-90B3-45D9-8317-771E2674988F}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {7D3E4489-90B3-45D9-8317-771E2674988F}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {7D3E4489-90B3-45D9-8317-771E2674988F}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {9DD3A454-670F-4165-813E-324670E01538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {9DD3A454-670F-4165-813E-324670E01538}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {9DD3A454-670F-4165-813E-324670E01538}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {9DD3A454-670F-4165-813E-324670E01538}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {7774FE75-8B35-4EE6-92D3-D4636F4713B4} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/AuthenticationProvider/ADALHelper.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | using System; 8 | using System.Threading.Tasks; 9 | 10 | using Microsoft.IdentityModel.Clients.ActiveDirectory; 11 | using TDSClient.TDS.Utilities; 12 | 13 | namespace TDSClient.AuthenticationProvider 14 | { 15 | public class ADALHelper 16 | { 17 | private class AdalLoggerCallback : IAdalLogCallback 18 | { 19 | public void Log(LogLevel level, string message) 20 | { 21 | // Customize how you handle log messages here 22 | LoggingUtilities.WriteLog($"ADAL Log ({level}): {message}"); 23 | } 24 | } 25 | /// 26 | /// Gets JWT access token using ADAL with integrated authentication. 27 | /// 28 | /// 29 | /// 30 | /// 31 | public static async Task GetSQLAccessTokenFromADALUsingIntegratedAuth( 32 | string clientId, 33 | string authority, 34 | string resource) 35 | { 36 | try 37 | { 38 | var loggerCallback = new AdalLoggerCallback(); 39 | LoggerCallbackHandler.Callback = loggerCallback; 40 | 41 | UserCredential userCredentials = new UserCredential(); 42 | LoggingUtilities.WriteLog("Acquiring access token..."); 43 | AuthenticationContext authContext = new AuthenticationContext(authority); 44 | AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientId, userCredentials).ConfigureAwait(false); 45 | LoggingUtilities.WriteLog("Successfully acquired access token."); 46 | return result.AccessToken; 47 | } 48 | catch (Exception ex) 49 | { 50 | LogException(ex); 51 | throw; 52 | } 53 | } 54 | 55 | /// 56 | /// Logs possible ADAL exception message. 57 | /// 58 | /// Custom message 59 | private static void LogException(Exception ex) 60 | { 61 | if (ex is AdalException adalException) 62 | { 63 | LoggingUtilities.WriteLog($"Client exception occurred when trying to acquire a JWT token: {adalException.Message}"); 64 | LoggingUtilities.WriteLog($"Error code: {adalException.ErrorCode}"); 65 | } 66 | else if (ex is AdalServiceException serviceException) 67 | { 68 | LoggingUtilities.WriteLog($"Service exception occurred when trying to acquire a JWT token: {serviceException.Message}"); 69 | LoggingUtilities.WriteLog($"HTTP status code: {serviceException.StatusCode}"); 70 | } 71 | else 72 | { 73 | LoggingUtilities.WriteLog($"An unexpected error occurred when trying to acquire a JWT token: {ex.Message}"); 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/AuthenticationProvider/AuthenticationProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace TDSClient.AuthenticationProvider 6 | { 7 | public class AuthenticationProvider 8 | { 9 | /// 10 | /// Type of authentication. 11 | /// 12 | public enum TDSAuthenticationType 13 | { 14 | SQLServerAuthentication, 15 | ADPassword, 16 | ADIntegrated, 17 | ADInteractive, 18 | ADManagedIdentity 19 | } 20 | 21 | /// 22 | /// Type of authentication library. 23 | /// 24 | public enum TDSAuthenticationLibrary 25 | { 26 | ADAL, 27 | MSAL 28 | } 29 | 30 | /// 31 | /// Authentication type string to enum mapping. 32 | /// 33 | public static readonly Dictionary AuthTypeStringToEnum = new Dictionary 34 | { 35 | { "SQL Server Authentication", TDSAuthenticationType.SQLServerAuthentication }, 36 | { "Microsoft Entra Password", TDSAuthenticationType.ADPassword }, 37 | { "Microsoft Entra Integrated", TDSAuthenticationType.ADIntegrated }, 38 | { "Microsoft Entra Interactive", TDSAuthenticationType.ADInteractive }, 39 | { "Microsoft Entra Managed Identity", TDSAuthenticationType.ADManagedIdentity }, 40 | { "Microsoft Entra MSI", TDSAuthenticationType.ADManagedIdentity } 41 | }; 42 | 43 | /// 44 | /// Authentication type string to enum mapping. 45 | /// 46 | public static readonly Dictionary AuthLibStringToEnum = new Dictionary 47 | { 48 | { "ADAL", TDSAuthenticationLibrary.ADAL }, 49 | { "MSAL", TDSAuthenticationLibrary.MSAL } 50 | }; 51 | 52 | private readonly TDSAuthenticationLibrary AuthenticationLibrary; 53 | private readonly TDSAuthenticationType AuthenticationType; 54 | private readonly string UserID; 55 | private readonly string Password; 56 | private readonly string Authority; 57 | private readonly string Resource; 58 | private readonly string IdentityClientId; 59 | 60 | private readonly string AdoClientId = "2fd908ad-0664-4344-b9be-cd3e8b574c38"; 61 | private readonly string RedirectUri = "http://localhost"; 62 | 63 | /// 64 | /// AuthenticationProvider constructor. 65 | /// 66 | /// 67 | /// 68 | /// 69 | /// 70 | /// 71 | /// 72 | public AuthenticationProvider( 73 | TDSAuthenticationLibrary authenticationLibrary, 74 | TDSAuthenticationType authenticationType, 75 | string userId, 76 | string password, 77 | string aadAuthorityAudience, 78 | string resource, 79 | string identityClientId = null) 80 | { 81 | AuthenticationLibrary = authenticationLibrary; 82 | AuthenticationType = authenticationType; 83 | UserID = userId; 84 | Password = password; 85 | Authority = aadAuthorityAudience; 86 | Resource = resource; 87 | IdentityClientId = identityClientId; 88 | } 89 | 90 | /// 91 | /// Acquires JWT Access token. 92 | /// 93 | /// Access token as a string 94 | public async Task GetJWTAccessToken() 95 | { 96 | string accessToken = null; 97 | 98 | switch (AuthenticationType) 99 | { 100 | case TDSAuthenticationType.ADIntegrated: 101 | accessToken = await GetAccessTokenForIntegratedAuth(); 102 | break; 103 | case TDSAuthenticationType.ADInteractive: 104 | accessToken = await GetAccessTokenForInteractiveAuth(); 105 | break; 106 | case TDSAuthenticationType.ADPassword: 107 | accessToken = await GetAccessTokenForUsernamePassword(); 108 | break; 109 | case TDSAuthenticationType.ADManagedIdentity: 110 | accessToken = await GetAccessTokenForMSIAuth(); 111 | break; 112 | } 113 | 114 | return accessToken; 115 | } 116 | 117 | /// 118 | /// Acquires access token for AAD integrated authentication. 119 | /// 120 | /// Access token as a string 121 | private async Task GetAccessTokenForIntegratedAuth() 122 | { 123 | return AuthenticationLibrary == TDSAuthenticationLibrary.MSAL ? 124 | await MSALHelper.GetSQLAccessTokenFromMSALUsingIntegratedAuth(AdoClientId, Authority, Resource, UserID) : 125 | await ADALHelper.GetSQLAccessTokenFromADALUsingIntegratedAuth(AdoClientId, Authority, Resource); 126 | } 127 | 128 | /// 129 | /// Acquires access token for AAD username password authentication. 130 | /// 131 | /// 132 | private async Task GetAccessTokenForUsernamePassword() 133 | { 134 | return AuthenticationLibrary == TDSAuthenticationLibrary.MSAL ? 135 | await MSALHelper.GetSQLAccessTokenFromMSALUsingUsernamePassword(AdoClientId, Authority, Resource, UserID, Password) : 136 | throw new Exception("Username password authentication is not supported by ADAL."); 137 | } 138 | 139 | /// 140 | /// Acquires access token for AAD integrated authentication. 141 | /// 142 | /// 143 | private async Task GetAccessTokenForInteractiveAuth() 144 | { 145 | return await MSALHelper.GetSQLAccessTokenFromMSALInteractively(AdoClientId, Resource, Authority, RedirectUri); 146 | } 147 | 148 | /// 149 | /// Acquires access token for AAD integrated authentication. 150 | /// 151 | /// 152 | private async Task GetAccessTokenForMSIAuth() 153 | { 154 | return IdentityClientId != null ? 155 | await MSALHelper.GetSQLAccessTokenFromMSALUsingUserAssignedManagedIdentity(Authority, IdentityClientId) : 156 | await MSALHelper.GetSQLAccessTokenFromMSALUsingSystemAssignedManagedIdentity(Authority); 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Client/TDSClientTraceID.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Client 8 | { 9 | using System; 10 | using System.IO; 11 | using System.Linq; 12 | using TDSClient.TDS.Interfaces; 13 | using TDSClient.TDS.Utilities; 14 | 15 | /// 16 | /// Client Trace ID used in TDS PreLogin package. 17 | /// 18 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | public class TDSClientTraceID : IPackageable, IEquatable 20 | { 21 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 22 | /// 23 | /// Gets or sets the TDS Client Application Trace ID 24 | /// 25 | public byte[] TraceID { get; } 26 | 27 | /// 28 | /// Gets or sets the TDS Client Application Activity ID 29 | /// 30 | public byte[] ActivityID { get; } 31 | 32 | /// 33 | /// Gets or sets the TDS Client Application Activity Sequence 34 | /// 35 | public uint ActivitySequence { get; set; } 36 | 37 | /// 38 | /// Initializes a new instance of the class. 39 | /// 40 | public TDSClientTraceID() 41 | { 42 | } 43 | 44 | /// 45 | /// Initializes a new instance of the class. 46 | /// 47 | /// Trace ID 48 | /// Activity ID 49 | /// Activity Sequence 50 | public TDSClientTraceID(byte[] traceID, byte[] activityID, uint activitySequence) 51 | { 52 | TraceID = traceID ?? throw new ArgumentNullException(nameof(traceID)); 53 | ActivityID = activityID ?? throw new ArgumentNullException(nameof(activityID)); 54 | ActivitySequence = activitySequence; 55 | } 56 | 57 | /// 58 | /// Determines whether the specified object is equal to the current object. 59 | /// 60 | /// The object to compare with the current object. 61 | /// true if the specified object is equal to the current object; otherwise, false 62 | public override bool Equals(object obj) 63 | { 64 | return Equals(obj as TDSClientTraceID); 65 | } 66 | 67 | /// 68 | /// Determines whether the specified object is equal to the current object. 69 | /// 70 | /// The object to compare with the current object. 71 | /// true if the specified object is equal to the current object; otherwise, false 72 | 73 | public bool Equals(TDSClientTraceID other) 74 | { 75 | return other != null && 76 | TraceID.SequenceEqual(other.TraceID) && 77 | ActivityID.SequenceEqual(other.ActivityID) && 78 | ActivitySequence == other.ActivitySequence; 79 | } 80 | 81 | /// 82 | /// Used to pack IPackageable to a stream. 83 | /// 84 | /// MemoryStream in which IPackageable is packet into. 85 | public void Pack(MemoryStream stream) 86 | { 87 | stream.Write(TraceID, 0, TraceID.Length); 88 | stream.Write(ActivityID, 0, ActivityID.Length); 89 | LittleEndianUtilities.WriteUInt(stream, ActivitySequence); 90 | } 91 | 92 | /// 93 | /// Used to unpack IPackageable from a stream. 94 | /// 95 | /// MemoryStream from which to unpack IPackageable. 96 | /// Returns true if successful. 97 | public bool Unpack(MemoryStream stream) 98 | { 99 | stream.Read(TraceID, 0, 16); 100 | stream.Read(ActivityID, 0, 16); 101 | ActivitySequence = LittleEndianUtilities.ReadUInt(stream); 102 | 103 | return true; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Client/TDSClientVersion.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Client 8 | { 9 | using System; 10 | using System.IO; 11 | using TDSClient.TDS.Interfaces; 12 | using TDSClient.TDS.Utilities; 13 | 14 | /// 15 | /// Class describing TDS Client Version. 16 | /// 17 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 18 | public class TDSClientVersion : IPackageable, IEquatable 19 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 20 | { 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | public TDSClientVersion() 25 | { 26 | } 27 | 28 | /// 29 | /// Initializes a new instance of the class. 30 | /// 31 | /// Major version 32 | /// Minor version 33 | /// Build number 34 | /// SubBuild number 35 | public TDSClientVersion(byte major, byte minor, ushort buildNumber, ushort subBuildNumber) 36 | { 37 | Major = major; 38 | Minor = minor; 39 | BuildNumber = buildNumber; 40 | SubBuildNumber = subBuildNumber; 41 | } 42 | 43 | /// 44 | /// Gets or sets the Major version 45 | /// 46 | private byte Major; 47 | 48 | /// 49 | /// Gets or sets the Minor version 50 | /// 51 | private byte Minor; 52 | 53 | /// 54 | /// Gets or sets the Build number 55 | /// 56 | private ushort BuildNumber; 57 | 58 | /// 59 | /// Gets or sets the SubBuild number 60 | /// 61 | private ushort SubBuildNumber; 62 | 63 | /// 64 | /// Used to pack IPackageable to a stream. 65 | /// 66 | /// MemoryStream in which IPackageable is packet into. 67 | public void Pack(MemoryStream stream) 68 | { 69 | BigEndianUtilities.WriteUShort(stream, BuildNumber); 70 | stream.WriteByte(Minor); 71 | stream.WriteByte(Major); 72 | BigEndianUtilities.WriteUShort(stream, SubBuildNumber); 73 | } 74 | 75 | /// 76 | /// Used to unpack IPackageable from a stream. 77 | /// 78 | /// MemoryStream from which to unpack IPackageable. 79 | /// Returns true if successful. 80 | public bool Unpack(MemoryStream stream) 81 | { 82 | BuildNumber = BigEndianUtilities.ReadUShort(stream); 83 | Minor = Convert.ToByte(stream.ReadByte()); 84 | Major = Convert.ToByte(stream.ReadByte()); 85 | SubBuildNumber = BigEndianUtilities.ReadUShort(stream); 86 | 87 | return true; 88 | } 89 | 90 | /// 91 | /// Determines whether the specified object is equal to the current object. 92 | /// 93 | /// The object to compare with the current object. 94 | /// true if the specified object is equal to the current object; otherwise, false 95 | public override bool Equals(object obj) 96 | { 97 | return Equals(obj as TDSClientVersion); 98 | } 99 | 100 | /// 101 | /// Determines whether the specified object is equal to the current object. 102 | /// 103 | /// The object to compare with the current object. 104 | /// true if the specified object is equal to the current object; otherwise, false 105 | public bool Equals(TDSClientVersion other) 106 | { 107 | return other != null && 108 | Major == other.Major && 109 | Minor == other.Minor && 110 | BuildNumber == other.BuildNumber && 111 | SubBuildNumber == other.SubBuildNumber; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Comms/TDSCommunicatorState.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Comms 8 | { 9 | /// 10 | /// Enum describing TDS Communicator State 11 | /// 12 | public enum TDSCommunicatorState 13 | { 14 | /// 15 | /// Initial Communicator State 16 | /// 17 | Initial, 18 | 19 | /// 20 | /// SentInitialPreLogin Communicator State 21 | /// 22 | SentInitialPreLogin, 23 | 24 | /// 25 | /// SentLogin7RecordWithCompleteAuthenticationToken Communicator State 26 | /// 27 | SentLogin7RecordWithCompleteAuthenticationToken, 28 | 29 | /// 30 | /// SentLogin7RecordWithFederatedAuthenticationInformationRequest Communicator State 31 | /// 32 | SentLogin7RecordWithFederatedAuthenticationInformationRequest, 33 | 34 | /// 35 | /// LoggedIn Communicator State 36 | /// 37 | LoggedIn 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Comms/TDSTemporaryStream.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Comms 8 | { 9 | using System; 10 | using System.IO; 11 | 12 | /// 13 | /// Stream used for enabling TLS through TDS. 14 | /// 15 | public class TDSTemporaryStream : Stream, IDisposable 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// Inner stream used for communication 21 | public TDSTemporaryStream(Stream innerStream) 22 | { 23 | InnerStream = innerStream; 24 | } 25 | 26 | /// 27 | /// Gets or sets InnerStream. 28 | /// 29 | public Stream InnerStream { get; set; } 30 | 31 | /// 32 | /// Gets or sets a value indicating whether you can read from this stream. 33 | /// 34 | public override bool CanRead => InnerStream.CanRead; 35 | 36 | /// 37 | /// Gets or sets a value indicating whether you can seek throughout this stream. 38 | /// 39 | public override bool CanSeek => InnerStream.CanSeek; 40 | 41 | /// 42 | /// Gets or sets a value indicating whether you can write to this stream. 43 | /// 44 | public override bool CanWrite => InnerStream.CanWrite; 45 | 46 | /// 47 | /// Gets or sets the length of this stream, in bytes. 48 | /// 49 | public override long Length => InnerStream.Length; 50 | 51 | /// 52 | /// Gets or sets the current position within this stream. 53 | /// 54 | public override long Position { get => InnerStream.Position; set => InnerStream.Position = value; } 55 | 56 | /// 57 | /// Flush stream output. 58 | /// 59 | public override void Flush() 60 | { 61 | InnerStream.Flush(); 62 | } 63 | 64 | /// 65 | /// Read from inner stream. 66 | /// 67 | /// Buffer to store read data to. 68 | /// Offset within buffer. 69 | /// Number of bytes to read. 70 | /// Returns number of successfully read bytes. 71 | public override int Read(byte[] buffer, int offset, int count) 72 | { 73 | return InnerStream.Read(buffer, offset, count); 74 | } 75 | 76 | /// 77 | /// Seek within stream. 78 | /// 79 | /// Offset from origin. 80 | /// Origin to seek from. 81 | /// THe new position within current stream. 82 | public override long Seek(long offset, SeekOrigin origin) 83 | { 84 | return InnerStream.Seek(offset, origin); 85 | } 86 | 87 | /// 88 | /// Set stream length. 89 | /// 90 | /// New length. 91 | public override void SetLength(long value) 92 | { 93 | InnerStream.SetLength(value); 94 | } 95 | 96 | /// 97 | /// Write to stream. 98 | /// 99 | /// Buffer containing data that's being written. 100 | /// Offset within buffer. 101 | /// Number of bytes to write. 102 | public override void Write(byte[] buffer, int offset, int count) 103 | { 104 | InnerStream.Write(buffer, offset, count); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/FedAuthMessage/TDSFedAuthMessageToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.FedAuthMessage 8 | { 9 | using System.IO; 10 | using System.Text; 11 | using System.Linq; 12 | using System; 13 | 14 | using TDSClient.TDS.Utilities; 15 | using TDSClient.TDS.Interfaces; 16 | 17 | /// 18 | /// FedAuthToken Message definition. 19 | /// 20 | #pragma warning disable CS0659 21 | public class TDSFedAuthToken : ITDSPacketData 22 | #pragma warning restore CS0659 23 | { 24 | /// 25 | /// Federated Authentication Token 26 | /// 27 | public byte[] FedAuthToken { get; private set; } 28 | 29 | /// 30 | /// Nonce 31 | /// 32 | public byte[] Nonce { get; private set; } 33 | 34 | /// 35 | /// Default Constructor. 36 | /// 37 | public TDSFedAuthToken() 38 | { 39 | } 40 | 41 | /// 42 | /// Initialization constructor. 43 | /// 44 | /// Token 45 | public TDSFedAuthToken(string JWTAccessToken) : this() 46 | { 47 | if (JWTAccessToken == null) 48 | { 49 | throw new ArgumentNullException(nameof(JWTAccessToken)); 50 | } 51 | 52 | FedAuthToken = Encoding.Unicode.GetBytes(JWTAccessToken); 53 | } 54 | 55 | /// 56 | /// Unpacking constructor. 57 | /// 58 | /// 59 | public TDSFedAuthToken(MemoryStream source) : this() 60 | { 61 | Unpack(source); 62 | } 63 | 64 | /// 65 | /// Unpack the token 66 | /// NOTE: This operation is not continuable and assumes that the entire token is available in the stream 67 | /// 68 | /// Stream to unpack the token from. 69 | /// True in case of success, false otherwise. 70 | public bool Unpack(MemoryStream source) 71 | { 72 | uint totalLengthOfData = LittleEndianUtilities.ReadUInt(source); 73 | uint tokenLength = LittleEndianUtilities.ReadUInt(source); 74 | 75 | FedAuthToken = new byte[tokenLength]; 76 | source.Read(FedAuthToken, 0, (int)tokenLength); 77 | 78 | if (totalLengthOfData > tokenLength) 79 | { 80 | Nonce = new byte[totalLengthOfData - tokenLength]; 81 | source.Read(Nonce, 0, (int)(totalLengthOfData - tokenLength)); 82 | } 83 | else if (tokenLength > totalLengthOfData) 84 | { 85 | return false; 86 | } 87 | 88 | return true; 89 | } 90 | 91 | /// 92 | /// Pack the token. 93 | /// 94 | /// Stream to pack the token to. 95 | public void Pack(MemoryStream destination) 96 | { 97 | uint totalLengthOfData = sizeof(uint) + (uint)FedAuthToken.Length + (Nonce != null ? (uint)Nonce.Length : 0); 98 | 99 | LittleEndianUtilities.WriteUInt(destination, totalLengthOfData); 100 | 101 | LittleEndianUtilities.WriteUInt(destination, (uint)FedAuthToken.Length); 102 | 103 | destination.Write(FedAuthToken, 0, FedAuthToken.Length); 104 | 105 | if (Nonce != null) 106 | { 107 | destination.Write(Nonce, 0, Nonce.Length); 108 | } 109 | } 110 | 111 | /// 112 | /// Length of the Fed Auth Token message. 113 | /// 114 | /// 115 | public ushort Length() 116 | { 117 | return (ushort)(sizeof(uint) + sizeof(uint) + (uint)FedAuthToken.Length); 118 | } 119 | 120 | /// 121 | /// Compares. 122 | /// 123 | /// 124 | /// 125 | public override bool Equals(object obj) 126 | { 127 | if (obj == null || GetType() != obj.GetType()) 128 | { 129 | return false; 130 | } 131 | 132 | var otherToken = (TDSFedAuthToken)obj; 133 | return Length() == otherToken.Length() 134 | && FedAuthToken.SequenceEqual(otherToken.FedAuthToken) 135 | && Nonce.SequenceEqual(otherToken.Nonce); 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Header/TDSMessageStatus.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Header 8 | { 9 | /// 10 | /// Enum describing TDS Message Status 11 | /// 12 | public enum TDSMessageStatus : byte 13 | { 14 | /// 15 | /// Normal TDS Message Status 16 | /// 17 | Normal, 18 | 19 | /// 20 | /// TDS Message Terminator 21 | /// The packet is the last packet in the whole request. 22 | /// 23 | EndOfMessage, 24 | 25 | /// 26 | /// IgnoreEvent TDS Message Status 27 | /// Ignore this event (0x01 MUST also be set). 28 | /// 29 | IgnoreEvent, 30 | 31 | /// 32 | /// ResetConnection TDS Message Status 33 | /// Reset this connection before processing event. 34 | /// 35 | ResetConnection = 0x08, 36 | 37 | /// 38 | /// ResetConnectionSkipTran TDS Message Status 39 | /// Reset the connection before processing event but do not modify the transaction 40 | /// state (the state will remain the same before and after the reset). 41 | /// 42 | ResetConnectionSkipTran = 0x10 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Header/TDSMessageType.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Header 8 | { 9 | /// 10 | /// Enum describing TDS Message Type 11 | /// 12 | public enum TDSMessageType : byte 13 | { 14 | /// 15 | /// SQL Batch Message 16 | /// 17 | SQLBatch = 1, 18 | 19 | /// 20 | /// TDS7 Pre Login Message 21 | /// 22 | PreTDS7Login, 23 | 24 | /// 25 | /// RPC Message 26 | /// 27 | RPC, 28 | 29 | /// 30 | /// Tabular Result Message 31 | /// 32 | TabularResult, 33 | 34 | /// 35 | /// Attention Signal Message 36 | /// 37 | AttentionSignal = 6, 38 | 39 | /// 40 | /// Bulk Load Data Message 41 | /// 42 | BulkLoadData, 43 | 44 | /// 45 | /// Federated Authentication Token Message 46 | /// 47 | FedAuthToken, 48 | 49 | /// 50 | /// Transaction Manager Request Message 51 | /// 52 | TransactionManagerRequest = 14, 53 | 54 | /// 55 | /// TDS7 Login Message 56 | /// 57 | TDS7Login = 16, 58 | 59 | /// 60 | /// SSPI Message 61 | /// 62 | SSPI, 63 | 64 | /// 65 | /// PreLogin Message 66 | /// 67 | PreLogin 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Header/TDSPacketHeader.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Header 8 | { 9 | using System; 10 | using System.IO; 11 | using TDSClient.TDS.Interfaces; 12 | using TDSClient.TDS.Utilities; 13 | 14 | /// 15 | /// Class describing TDS Packet Header 16 | /// 17 | public class TDSPacketHeader : IPackageable 18 | { 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | public TDSPacketHeader() 23 | { 24 | } 25 | 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// 29 | /// TDS Message Type 30 | /// TDS Message Status 31 | /// SPID number 32 | /// Packet number 33 | /// Window number 34 | public TDSPacketHeader(TDSMessageType type, TDSMessageStatus status, ushort spid = 0x0000, byte packet = 0x00, byte window = 0x00) 35 | { 36 | Type = type; 37 | Status = status; 38 | SPID = spid; 39 | Packet = packet; 40 | Window = window; 41 | } 42 | 43 | /// 44 | /// Gets or sets TDS Message Type. 45 | /// 46 | public TDSMessageType Type { get; set; } 47 | 48 | /// 49 | /// Gets or sets TDS Message Status. 50 | /// 51 | public TDSMessageStatus Status { get; set; } 52 | 53 | /// 54 | /// Gets or sets TDS Message Length. 55 | /// 56 | public ushort Length { get; set; } 57 | 58 | /// 59 | /// Gets or sets SPID. 60 | /// 61 | public ushort SPID { get; set; } 62 | 63 | /// 64 | /// Gets or sets Packet Number. 65 | /// 66 | public byte Packet { get; set; } 67 | 68 | /// 69 | /// Gets or sets Window Number. 70 | /// 71 | public byte Window { get; set; } 72 | 73 | /// 74 | /// Gets converted (to int) Packet Length. 75 | /// 76 | public int ConvertedPacketLength => Convert.ToInt32(Length); 77 | 78 | /// 79 | /// Used to pack IPackageable to a stream. 80 | /// 81 | /// MemoryStream in which IPackageable is packet into. 82 | public void Pack(MemoryStream stream) 83 | { 84 | if (stream == null) 85 | { 86 | throw new ArgumentNullException(nameof(stream)); 87 | } 88 | 89 | stream.WriteByte((byte)Type); 90 | stream.WriteByte((byte)Status); 91 | BigEndianUtilities.WriteUShort(stream, Length); 92 | BigEndianUtilities.WriteUShort(stream, SPID); 93 | stream.WriteByte(Packet); 94 | stream.WriteByte(Window); 95 | } 96 | 97 | /// 98 | /// Used to unpack IPackageable from a stream. 99 | /// 100 | /// MemoryStream from which to unpack IPackageable. 101 | /// Returns true if successful. 102 | public bool Unpack(MemoryStream stream) 103 | { 104 | if (stream == null) 105 | { 106 | throw new ArgumentNullException(nameof(stream)); 107 | } 108 | 109 | Type = (TDSMessageType)stream.ReadByte(); 110 | Status = (TDSMessageStatus)stream.ReadByte(); 111 | Length = BigEndianUtilities.ReadUShort(stream); 112 | SPID = BigEndianUtilities.ReadUShort(stream); 113 | Packet = Convert.ToByte(stream.ReadByte()); 114 | Window = Convert.ToByte(stream.ReadByte()); 115 | 116 | return true; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Interfaces/IPackageable.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Interfaces 8 | { 9 | using System.IO; 10 | 11 | /// 12 | /// Interface used to describe all stream-packageable classes. 13 | /// 14 | public interface IPackageable 15 | { 16 | /// 17 | /// Used to pack IPackageable to a stream. 18 | /// 19 | /// MemoryStream in which IPackageable is packet into. 20 | void Pack(MemoryStream stream); 21 | 22 | /// 23 | /// Used to unpack IPackageable from a stream. 24 | /// 25 | /// MemoryStream from which to unpack IPackageable. 26 | /// Returns true if successful. 27 | bool Unpack(MemoryStream stream); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Interfaces/ITDSPacketData.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Interfaces 8 | { 9 | /// 10 | /// Interface used to describe TDS Packet Data. 11 | /// 12 | public interface ITDSPacketData : IPackageable 13 | { 14 | /// 15 | /// TDS Packet Data Length. 16 | /// 17 | /// Returns TDS Packet Data portion length. 18 | ushort Length(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/Options/TDSLogin7Option.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7.Options 8 | { 9 | using System; 10 | using System.IO; 11 | using TDSClient.TDS.Interfaces; 12 | 13 | /// 14 | /// TDS Login7 Packet Option 15 | /// 16 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 17 | public abstract class TDSLogin7Option : IPackageable, IEquatable 18 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | { 20 | /// 21 | /// Gets or sets option name 22 | /// 23 | public string Name { get; set; } 24 | 25 | /// 26 | /// Gets or sets option position within the packet 27 | /// 28 | public ushort Position { get; set; } 29 | 30 | /// 31 | /// Gets or sets option data length 32 | /// 33 | public ushort Length { get; set; } 34 | 35 | /// 36 | /// Gets or sets option true data length (in bytes) 37 | /// 38 | public ushort TrueLength { get; set; } 39 | 40 | /// 41 | /// Initializes a new instance of the class. 42 | /// 43 | public TDSLogin7Option() 44 | { 45 | } 46 | 47 | /// 48 | /// Initializes a new instance of the class. 49 | /// 50 | /// Option name 51 | /// Option position within the packet 52 | /// Option data length 53 | /// Option data length (in bytes) 54 | public TDSLogin7Option(string name, ushort position, ushort length, ushort trueLength) 55 | { 56 | Name = name; 57 | Position = position; 58 | Length = length; 59 | TrueLength = trueLength; 60 | } 61 | 62 | /// 63 | /// Determines whether the specified object is equal to the current object. 64 | /// 65 | /// The object to compare with the current object. 66 | /// true if the specified object is equal to the current object; otherwise, false 67 | public override bool Equals(object obj) 68 | { 69 | return Equals(obj as TDSLogin7Option); 70 | } 71 | 72 | /// 73 | /// Determines whether the specified object is equal to the current object. 74 | /// 75 | /// The object to compare with the current object. 76 | /// true if the specified object is equal to the current object; otherwise, false 77 | public bool Equals(TDSLogin7Option other) 78 | { 79 | if (other == null) 80 | { 81 | return false; 82 | } 83 | 84 | return Name == other.Name && 85 | Position == other.Position && 86 | Length == other.Length && 87 | TrueLength == other.TrueLength; 88 | } 89 | 90 | /// 91 | /// Used to pack IPackageable to a stream. 92 | /// 93 | /// MemoryStream in which IPackageable is packet into. 94 | public abstract void Pack(MemoryStream stream); 95 | 96 | /// 97 | /// Used to unpack IPackageable from a stream. 98 | /// 99 | /// MemoryStream from which to unpack IPackageable. 100 | /// Returns true if successful. 101 | public abstract bool Unpack(MemoryStream stream); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/Options/TDSLogin7PasswordOption.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7.Options 8 | { 9 | using System; 10 | using System.IO; 11 | using System.Text; 12 | 13 | /// 14 | /// TDS Login7 Password Option Type 15 | /// 16 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 17 | public class TDSLogin7PasswordOption : TDSLogin7Option, IEquatable 18 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public TDSLogin7PasswordOption() 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class. 29 | /// 30 | /// Option name 31 | /// Option position within the packet 32 | /// Option data length 33 | public TDSLogin7PasswordOption(string name, ushort position, ushort length) : base(name, position, length, (ushort)(length * 2)) 34 | { 35 | } 36 | 37 | /// 38 | /// Initializes a new instance of the class. 39 | /// 40 | /// Option name 41 | /// Option position within the packet 42 | /// Option data length 43 | /// Password in plain text 44 | public TDSLogin7PasswordOption(string name, ushort position, ushort length, string plainTextPassword) : base(name, position, length, (ushort)(length * 2)) 45 | { 46 | PlainTextPassword = plainTextPassword; 47 | } 48 | 49 | /// 50 | /// Gets or sets password in plain text 51 | /// 52 | public string PlainTextPassword { get; set; } 53 | 54 | /// 55 | /// Determines whether the specified object is equal to the current object. 56 | /// 57 | /// The object to compare with the current object. 58 | /// true if the specified object is equal to the current object; otherwise, false 59 | public override bool Equals(object obj) 60 | { 61 | return Equals(obj as TDSLogin7PasswordOption); 62 | } 63 | 64 | /// 65 | /// Determines whether the specified object is equal to the current object. 66 | /// 67 | /// The object to compare with the current object. 68 | /// true if the specified object is equal to the current object; otherwise, false 69 | public bool Equals(TDSLogin7PasswordOption other) 70 | { 71 | if (other == null) 72 | { 73 | return false; 74 | } 75 | 76 | return base.Equals(other) && 77 | PlainTextPassword == other.PlainTextPassword; 78 | } 79 | 80 | /// 81 | /// Used to pack IPackageable to a stream. 82 | /// 83 | /// MemoryStream in which IPackageable is packet into. 84 | public override void Pack(MemoryStream stream) 85 | { 86 | byte[] buffer = Encoding.Unicode.GetBytes(PlainTextPassword); 87 | buffer = GetScrambledPassword(buffer); 88 | stream.Write(buffer, 0, buffer.Length); 89 | } 90 | 91 | /// 92 | /// Used to unpack IPackageable from a stream. 93 | /// 94 | /// MemoryStream from which to unpack IPackageable. 95 | /// Returns true if successful. 96 | public override bool Unpack(MemoryStream stream) 97 | { 98 | var buffer = new byte[Length * 2]; 99 | stream.Read(buffer, 0, buffer.Length); 100 | buffer = GetUnscrambledPassword(buffer); 101 | PlainTextPassword = UnicodeEncoding.Unicode.GetString(buffer); 102 | 103 | return true; 104 | } 105 | 106 | /// 107 | /// Scrambles password bytes in a way described in TDS documentation 108 | /// 109 | /// Password bytes 110 | /// Scrambled password bytes 111 | private byte[] GetScrambledPassword(byte[] password) 112 | { 113 | for (int i = 0; i < password.Length; i++) 114 | { 115 | var piece0 = (byte)(password[i] >> 4); 116 | var piece1 = (byte)(password[i] & 0x0f); 117 | password[i] = (byte)((piece0 | (piece1 << 4)) ^ 0xA5); 118 | } 119 | 120 | return password; 121 | } 122 | 123 | /// 124 | /// Unscrambles password bytes in a way described in TDS documentation 125 | /// 126 | /// Scrambled password bytes 127 | /// Unscrambled password bytes 128 | private byte[] GetUnscrambledPassword(byte[] password) 129 | { 130 | for (int i = 0; i < password.Length; i++) 131 | { 132 | password[i] = (byte)(password[i] ^ 0xA5); 133 | password[i] = (byte)((password[i] >> 4) | (password[i] & 0x0f)); 134 | } 135 | 136 | return password; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/Options/TDSLogin7TextOption.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7.Options 8 | { 9 | using System; 10 | using System.IO; 11 | using System.Text; 12 | 13 | /// 14 | /// TDS Login7 Text Option Type 15 | /// 16 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 17 | public class TDSLogin7TextOption : TDSLogin7Option, IEquatable 18 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public TDSLogin7TextOption() 24 | { 25 | } 26 | 27 | /// 28 | /// Initializes a new instance of the class. 29 | /// 30 | /// Option name 31 | /// Option position within the packet 32 | /// Option data length 33 | public TDSLogin7TextOption(string name, ushort position, ushort length) : base(name, position, length, (ushort)(length * 2)) 34 | { 35 | } 36 | 37 | /// 38 | /// Initializes a new instance of the class. 39 | /// 40 | /// Option name 41 | /// Option position within the packet 42 | /// Option data length 43 | /// Text data 44 | public TDSLogin7TextOption(string name, ushort position, ushort length, string text) : base(name, position, length, (ushort)(length * 2)) 45 | { 46 | Text = text; 47 | } 48 | 49 | /// 50 | /// Gets or sets option text 51 | /// 52 | public string Text { get; set; } 53 | 54 | /// 55 | /// Determines whether the specified object is equal to the current object. 56 | /// 57 | /// The object to compare with the current object. 58 | /// true if the specified object is equal to the current object; otherwise, false 59 | public override bool Equals(object obj) 60 | { 61 | return Equals(obj as TDSLogin7TextOption); 62 | } 63 | 64 | /// 65 | /// Determines whether the specified object is equal to the current object. 66 | /// 67 | /// The object to compare with the current object. 68 | /// true if the specified object is equal to the current object; otherwise, false 69 | public bool Equals(TDSLogin7TextOption other) 70 | { 71 | if (other == null) 72 | { 73 | return false; 74 | } 75 | 76 | return base.Equals(other) && 77 | Text == other.Text; 78 | } 79 | 80 | /// 81 | /// Used to pack IPackageable to a stream. 82 | /// 83 | /// MemoryStream in which IPackageable is packet into. 84 | public override void Pack(MemoryStream stream) 85 | { 86 | byte[] buffer = Encoding.Unicode.GetBytes(Text); 87 | stream.Write(buffer, 0, buffer.Length); 88 | } 89 | 90 | /// 91 | /// Used to unpack IPackageable from a stream. 92 | /// 93 | /// MemoryStream from which to unpack IPackageable. 94 | /// Returns true if successful. 95 | public override bool Unpack(MemoryStream stream) 96 | { 97 | var buffer = new byte[Length * 2]; 98 | stream.Read(buffer, 0, buffer.Length); 99 | Text = UnicodeEncoding.Unicode.GetString(buffer); 100 | 101 | return true; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/TDSLogin7FeatureExt.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7 8 | { 9 | using System; 10 | using System.IO; 11 | 12 | using TDSClient.TDS.Interfaces; 13 | 14 | /// 15 | /// TDS feature identifier 16 | /// 17 | public enum TDSFeatureID : byte 18 | { 19 | /// 20 | /// Session recovery 21 | /// 22 | SessionRecovery = 0x01, 23 | 24 | /// 25 | /// Federated authentication 26 | /// 27 | FederatedAuthentication = 0x02, 28 | 29 | /// 30 | /// Column encryption 31 | /// 32 | ColumnEncryption = 0x04, 33 | 34 | /// 35 | /// Global transactions 36 | /// 37 | GlobalTransactions = 0x05, 38 | 39 | /// 40 | /// Azure SQL Support 41 | /// 42 | AzureSQLSupport = 0x08, 43 | 44 | /// 45 | /// Data Classification 46 | /// 47 | DataClassification = 0x09, 48 | 49 | /// 50 | /// UTF-8 encoding support 51 | /// 52 | SupportUTF8 = 0x0A, 53 | 54 | /// 57 | AzureSQLDNSCaching = 0x0B, 58 | 59 | /// 60 | /// End of the list 61 | /// 62 | Terminator = 0xFF 63 | } 64 | 65 | /// 66 | /// TDS Login7 Message Option Flags 3 67 | /// 68 | public abstract class TDSLogin7FeatureExt : IPackageable, IEquatable 69 | { 70 | 71 | /// 72 | /// Size of the data read during inflation operation. It is needed to properly parse the option stream. 73 | /// 74 | internal uint UnpackSize { get; set; } 75 | 76 | /// 77 | /// Feature type 78 | /// 79 | public virtual TDSFeatureID FeatureID { get; protected set; } 80 | 81 | public bool Equals(TDSLogin7FeatureExt other) 82 | { 83 | throw new NotImplementedException(); 84 | } 85 | 86 | /// 87 | /// Used to pack IPackageable to a stream. 88 | /// 89 | /// MemoryStream in which IPackageable is packet into. 90 | public abstract void Pack(MemoryStream stream); 91 | 92 | /// 93 | /// Used to unpack IPackageable from a stream. 94 | /// 95 | /// MemoryStream from which to unpack IPackageable. 96 | /// Returns true if successful. 97 | public abstract bool Unpack(MemoryStream stream); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/TDSLogin7FeatureOptionToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7 8 | { 9 | using System.IO; 10 | 11 | using TDSClient.TDS.Interfaces; 12 | 13 | /// 14 | /// Class that defines a feature option which is delivered in the login packet FeatureExt block 15 | /// 16 | public abstract class TDSLogin7FeatureOptionToken : IPackageable 17 | { 18 | /// 19 | /// Gets or sets the size of the data read during inflation operation. It is needed to properly parse the option stream. 20 | /// 21 | public uint Size { get; set; } 22 | 23 | /// 24 | /// Gets the feature ID. 25 | /// 26 | public virtual TDSFeatureID FeatureID { get; protected set; } 27 | 28 | /// 29 | /// Unpacks the Feature option from the given source stream. 30 | /// 31 | /// The source stream. 32 | /// True if the unpacking is successful; otherwise, false. 33 | public abstract bool Unpack(MemoryStream source); 34 | 35 | /// 36 | /// Packs the token into the given destination stream. 37 | /// 38 | /// The destination stream. 39 | public abstract void Pack(MemoryStream destination); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/TDSLogin7FeatureOptionsToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7 8 | { 9 | using System.IO; 10 | using System.Collections.Generic; 11 | 12 | /// 13 | /// Feature extension data delivered in the login packet 14 | /// 15 | public class TDSLogin7FeatureOptionsToken : List 16 | { 17 | /// 18 | /// Property used internally by unpack/ routine to tell caller how much data was read/written to the stream 19 | /// 20 | internal uint Size { get; set; } 21 | 22 | /// 23 | /// Unpack an object instance from the stream 24 | /// 25 | public bool Unpack(MemoryStream source) 26 | { 27 | TDSFeatureID featureID; 28 | do 29 | { 30 | featureID = (TDSFeatureID)source.ReadByte(); 31 | 32 | TDSLogin7FeatureOptionToken optionToken = null; 33 | 34 | switch (featureID) 35 | { 36 | case TDSFeatureID.FederatedAuthentication: 37 | optionToken = new TDSLogin7FedAuthOptionToken(); 38 | break; 39 | case TDSFeatureID.Terminator: 40 | break; 41 | default: 42 | optionToken = new TDSLogin7GenericOptionToken(featureID); 43 | break; 44 | } 45 | 46 | if (optionToken != null) 47 | { 48 | optionToken.Unpack(source); 49 | Add(optionToken); 50 | Size += optionToken.Size; 51 | } 52 | } 53 | while (TDSFeatureID.Terminator != featureID); 54 | 55 | return true; 56 | } 57 | 58 | /// 59 | /// Pack object into the stream 60 | /// 61 | public void Pack(MemoryStream destination) 62 | { 63 | foreach (TDSLogin7FeatureOptionToken option in this) 64 | { 65 | option.Pack(destination); 66 | } 67 | 68 | destination.WriteByte((byte)TDSFeatureID.Terminator); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/TDSLogin7GenericOptionToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7 8 | { 9 | using System.IO; 10 | 11 | using TDSClient.TDS.Utilities; 12 | 13 | /// 14 | /// Option token that can contain any data and doesn't have specialized inflation/deflation logic 15 | /// 16 | public class TDSLogin7GenericOptionToken : TDSLogin7FeatureOptionToken 17 | { 18 | /// 19 | /// Data that the token is carrying 20 | /// 21 | public byte[] Data { get; set; } 22 | 23 | /// 24 | /// Default constructor 25 | /// 26 | public TDSLogin7GenericOptionToken() 27 | { 28 | } 29 | 30 | /// 31 | /// Initialization constructor 32 | /// 33 | public TDSLogin7GenericOptionToken(TDSFeatureID featureID) 34 | { 35 | FeatureID = featureID; 36 | } 37 | 38 | /// 39 | /// Initialization constructor 40 | /// 41 | public TDSLogin7GenericOptionToken(TDSFeatureID featureID, byte[] data) : 42 | this(featureID) 43 | { 44 | Data = data; 45 | } 46 | 47 | /// 48 | /// Inflating constructor 49 | /// 50 | public TDSLogin7GenericOptionToken(MemoryStream source) : 51 | this() 52 | { 53 | Unpack(source); 54 | } 55 | 56 | 57 | /// 58 | /// Inflate the Feature option 59 | /// 60 | /// Stream to inflate the token from 61 | /// TRUE if inflation is complete 62 | public override bool Unpack(MemoryStream source) 63 | { 64 | Size = 0; 65 | int length = (int)BigEndianUtilities.ReadUInt(source); 66 | Size += sizeof(int); 67 | Data = new byte[length]; 68 | source.Read(Data, 0, Data.Length); 69 | Size += (uint)length; 70 | return true; 71 | } 72 | 73 | /// 74 | /// Deflate the token 75 | /// 76 | /// Stream the token to deflate to. 77 | public override void Pack(MemoryStream destination) 78 | { 79 | destination.WriteByte((byte)FeatureID); 80 | 81 | if (Data == null) 82 | { 83 | BigEndianUtilities.WriteUInt(destination, 0); 84 | } 85 | else 86 | { 87 | BigEndianUtilities.WriteUInt(destination, (uint)Data.Length); 88 | 89 | destination.Write(Data, 0, Data.Length); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/TDSLogin7OptionFlags2.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7 8 | { 9 | using System; 10 | using System.IO; 11 | 12 | using TDSClient.TDS.Interfaces; 13 | 14 | /// 15 | /// Enum describing Language flag 16 | /// Set if the change to initial language needs to succeed if the connect is to 17 | /// succeed. 18 | /// 19 | public enum TDSLogin7OptionFlags2Language : byte 20 | { 21 | /// 22 | /// Init Lang Flag Warning 23 | /// 24 | InitLangWarn, 25 | 26 | /// 27 | /// Init Lang FLag Fatal 28 | /// 29 | InitLangFatal 30 | } 31 | 32 | /// 33 | /// Enum describing ODBC flag 34 | /// Set if the client is the ODBC driver. This causes the server to set ANSI_DEFAULTS 35 | /// to ON, CURSOR_CLOSE_ON_COMMIT and IMPLICIT_TRANSACTIONS to OFF, TEXTSIZE to 36 | /// 0x7FFFFFFF (2GB) (TDS 7.2 and earlier), TEXTSIZE to infinite(introduced in TDS 7.3), and 37 | /// ROWCOUNT to infinite. 38 | /// 39 | public enum TDSLogin7OptionFlags2ODBC : byte 40 | { 41 | /// 42 | /// ODBC Flag Off 43 | /// 44 | OdbcOff, 45 | 46 | /// 47 | /// ODBC Flag On 48 | /// 49 | OdbcOn 50 | } 51 | 52 | /// 53 | /// The type of user connecting to the server. 54 | /// 55 | public enum TDSLogin7OptionFlags2UserType : byte 56 | { 57 | /// 58 | /// User Type Normal 59 | /// 60 | UserNormal, 61 | 62 | /// 63 | /// User Type Server 64 | /// 65 | UserServer, 66 | 67 | /// 68 | /// User Type Distributed Query User 69 | /// 70 | UserRemuser, 71 | 72 | /// 73 | /// User Type Replication User 74 | /// 75 | UserSQLRepl 76 | } 77 | 78 | /// 79 | /// The type of security required by the client. 80 | /// 81 | public enum TDSLogin7OptionFlags2IntSecurity : byte 82 | { 83 | /// 84 | /// Integrated Security Off 85 | /// 86 | IntegratedSecurityOff, 87 | 88 | /// 89 | /// Integrated Security On 90 | /// 91 | IntegratedSecurityOn 92 | } 93 | 94 | /// 95 | /// TDS Login7 Message Option Flags 2 96 | /// 97 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 98 | public class TDSLogin7OptionFlags2 : IPackageable, IEquatable 99 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 100 | { 101 | /// 102 | /// Gets or sets the Language Flag. 103 | /// Set if the change to initial language needs to succeed if the connect is to 104 | /// succeed. 105 | /// 106 | public TDSLogin7OptionFlags2Language Language { get; set; } 107 | 108 | /// 109 | /// Gets or sets the ODBC Flag. 110 | /// Set if the client is the ODBC driver 111 | /// 112 | public TDSLogin7OptionFlags2ODBC ODBC { get; set; } 113 | 114 | /// 115 | /// Gets or sets the UserType Flag. 116 | /// The type of user connecting to the server. 117 | /// 118 | public TDSLogin7OptionFlags2UserType UserType { get; set; } 119 | 120 | /// 121 | /// Gets or sets the IntSecurity Flag. 122 | /// The type of security required by the client. 123 | /// 124 | public TDSLogin7OptionFlags2IntSecurity IntSecurity { get; set; } 125 | 126 | /// 127 | /// Default construgtor 128 | /// 129 | public TDSLogin7OptionFlags2() 130 | { 131 | } 132 | 133 | /// 134 | /// Initialization constructor 135 | /// 136 | public TDSLogin7OptionFlags2(byte flags) 137 | { 138 | Language = (TDSLogin7OptionFlags2Language)(flags & 0x1); 139 | ODBC = (TDSLogin7OptionFlags2ODBC)((flags >> 1) & 0x1); 140 | // Skipping deprecated fTranBoundary and fCacheConnect 141 | UserType = (TDSLogin7OptionFlags2UserType)((flags >> 4) & 0x7); 142 | IntSecurity = (TDSLogin7OptionFlags2IntSecurity)((flags >> 7) & 0x1); 143 | } 144 | 145 | /// 146 | /// Determines whether the specified object is equal to the current object. 147 | /// 148 | /// The object to compare with the current object. 149 | /// true if the specified object is equal to the current object; otherwise, false 150 | public override bool Equals(object obj) 151 | { 152 | return Equals(obj as TDSLogin7OptionFlags2); 153 | } 154 | 155 | /// 156 | /// Determines whether the specified object is equal to the current object. 157 | /// 158 | /// The object to compare with the current object. 159 | /// true if the specified object is equal to the current object; otherwise, false 160 | public bool Equals(TDSLogin7OptionFlags2 other) 161 | { 162 | return other != null && 163 | Language == other.Language && 164 | ODBC == other.ODBC && 165 | UserType == other.UserType && 166 | IntSecurity == other.IntSecurity; 167 | } 168 | 169 | /// 170 | /// Used to pack IPackageable to a stream. 171 | /// 172 | /// MemoryStream in which IPackageable is packet into. 173 | public void Pack(MemoryStream stream) 174 | { 175 | byte packedByte = (byte)((byte)Language 176 | | ((byte)ODBC << 1) 177 | | ((byte)UserType << 4) 178 | | ((byte)IntSecurity << 7)); 179 | 180 | stream.WriteByte(packedByte); 181 | } 182 | 183 | /// 184 | /// Used to unpack IPackageable from a stream. 185 | /// 186 | /// MemoryStream from which to unpack IPackageable. 187 | /// Returns true if successful. 188 | public bool Unpack(MemoryStream stream) 189 | { 190 | byte flagByte = Convert.ToByte(stream.ReadByte()); 191 | Language = (TDSLogin7OptionFlags2Language)(flagByte & 0x01); 192 | ODBC = (TDSLogin7OptionFlags2ODBC)((flagByte >> 1) & 0x01); 193 | UserType = (TDSLogin7OptionFlags2UserType)((flagByte >> 4) & 0x07); 194 | IntSecurity = (TDSLogin7OptionFlags2IntSecurity)((flagByte >> 7) & 0x01); 195 | 196 | return true; 197 | } 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/TDSLogin7TokenOffsetProperty.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7 8 | { 9 | using System.Reflection; 10 | 11 | /// 12 | /// Helper class that takes care of setting property value 13 | /// 14 | public class TDSLogin7TokenOffsetProperty 15 | { 16 | /// 17 | /// Property which value is being set 18 | /// 19 | public PropertyInfo Property { get; set; } 20 | 21 | /// 22 | /// Position of the value in the data stream 23 | /// 24 | public uint Position { get; set; } 25 | 26 | /// 27 | /// Length of the property value in the data stream 28 | /// 29 | public uint Length { get; set; } 30 | 31 | /// 32 | /// This property is used to distinguish between "value" position in the stream and "offset of the value" position 33 | /// 34 | public bool IsOffsetOffset { get; set; } 35 | 36 | /// 37 | /// Initialization constructor 38 | /// 39 | public TDSLogin7TokenOffsetProperty(PropertyInfo property, ushort position, ushort length) 40 | { 41 | Property = property; 42 | Position = position; 43 | Length = length; 44 | } 45 | 46 | /// 47 | /// Initialization constructor 48 | /// 49 | public TDSLogin7TokenOffsetProperty(PropertyInfo property, ushort position, ushort length, bool isOffsetOffset) : 50 | this(property, position, length) 51 | { 52 | IsOffsetOffset = isOffsetOffset; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Login7/TDSLogin7TypeFlags.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Login7 8 | { 9 | using System; 10 | using System.IO; 11 | using TDSClient.TDS.Interfaces; 12 | 13 | /// 14 | /// The type of SQL the client sends to the server. 15 | /// 16 | public enum TDSLogin7TypeFlagsSQLType 17 | { 18 | /// 19 | /// Default SQL Type 20 | /// 21 | DFLT, 22 | 23 | /// 24 | /// Transact-SQL Type 25 | /// 26 | TSQL 27 | } 28 | 29 | /// 30 | /// Enum describing OLEDB flag 31 | /// Set if the client is the OLEDB driver. This causes the server to set 32 | /// ANSI_DEFAULTS to ON, CURSOR_CLOSE_ON_COMMIT and IMPLICIT_TRANSACTIONS to 33 | /// OFF, TEXTSIZE to 0x7FFFFFFF (2GB) (TDS 7.2 and earlier), TEXTSIZE to infinite 34 | /// (introduced in TDS 7.3), and ROWCOUNT to infinite. 35 | /// 36 | public enum TDSLogin7TypeFlagsOLEDB 37 | { 38 | /// 39 | /// OLEDB Flag Off 40 | /// 41 | Off, 42 | 43 | /// 44 | /// OLEDB Flag On 45 | /// 46 | On 47 | } 48 | 49 | /// 50 | /// Enum describing ReadOnlyIntent flag 51 | /// This bit was introduced in TDS 7.4; however, TDS 7.1, 7.2, and 7.3 52 | /// clients can also use this bit in LOGIN7 to specify that the application intent of the 53 | /// connection is read-only. 54 | /// 55 | public enum TDSLogin7TypeFlagsReadOnlyIntent 56 | { 57 | /// 58 | /// Read Only Intent Flag Off 59 | /// 60 | Off, 61 | 62 | /// 63 | /// Read Only Intent Flag On 64 | /// 65 | On 66 | } 67 | 68 | /// 69 | /// TDS Login7 Type Flags 70 | /// 71 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 72 | public class TDSLogin7TypeFlags : IPackageable, IEquatable 73 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 74 | { 75 | /// 76 | /// Gets or sets the type of SQL the client sends to the server. 77 | /// 78 | public TDSLogin7TypeFlagsSQLType SQLType { get; set; } 79 | 80 | /// 81 | /// Gets or sets the OLEDB Flag. 82 | /// Set if the client is the OLEDB driver. 83 | /// 84 | public TDSLogin7TypeFlagsOLEDB OLEDB { get; set; } 85 | 86 | /// 87 | /// Gets or sets the ReadOnlyIntent Flag. 88 | /// Specifies that the application intent of the 89 | /// connection is read-only. 90 | /// 91 | public TDSLogin7TypeFlagsReadOnlyIntent ReadOnlyIntent { get; set; } 92 | 93 | /// 94 | /// Default constructor 95 | /// 96 | public TDSLogin7TypeFlags() 97 | { 98 | } 99 | 100 | /// 101 | /// Initialization constructor 102 | /// 103 | public TDSLogin7TypeFlags(byte flags) 104 | { 105 | // Parse bytes as per TDS specification, section 2.2.6.3 LOGIN 7 106 | SQLType = (TDSLogin7TypeFlagsSQLType)(flags & 0xF); 107 | OLEDB = (TDSLogin7TypeFlagsOLEDB)((flags >> 4) & 0x1); 108 | ReadOnlyIntent = (TDSLogin7TypeFlagsReadOnlyIntent)((flags >> 5) & 0x1); 109 | } 110 | 111 | /// 112 | /// Determines whether the specified object is equal to the current object. 113 | /// 114 | /// The object to compare with the current object. 115 | /// true if the specified object is equal to the current object; otherwise, false 116 | public override bool Equals(object obj) 117 | { 118 | return Equals(obj as TDSLogin7TypeFlags); 119 | } 120 | 121 | /// 122 | /// Determines whether the specified object is equal to the current object. 123 | /// 124 | /// The object to compare with the current object. 125 | /// true if the specified object is equal to the current object; otherwise, false 126 | public bool Equals(TDSLogin7TypeFlags other) 127 | { 128 | return other != null && 129 | SQLType == other.SQLType && 130 | OLEDB == other.OLEDB && 131 | ReadOnlyIntent == other.ReadOnlyIntent; 132 | } 133 | 134 | /// 135 | /// Used to pack IPackageable to a stream. 136 | /// 137 | /// MemoryStream in which IPackageable is packet into. 138 | public void Pack(MemoryStream stream) 139 | { 140 | byte packedByte = (byte)((byte)SQLType 141 | | ((byte)OLEDB << 4) 142 | | ((byte)ReadOnlyIntent << 5)); 143 | stream.WriteByte(packedByte); 144 | } 145 | 146 | /// 147 | /// Used to unpack IPackageable from a stream. 148 | /// 149 | /// MemoryStream from which to unpack IPackageable. 150 | /// Returns true if successful. 151 | public bool Unpack(MemoryStream stream) 152 | { 153 | byte flagByte = Convert.ToByte(stream.ReadByte()); 154 | SQLType = (TDSLogin7TypeFlagsSQLType)(flagByte & 0x0F); 155 | OLEDB = (TDSLogin7TypeFlagsOLEDB)((flagByte >> 4) & 0x01); 156 | ReadOnlyIntent = (TDSLogin7TypeFlagsReadOnlyIntent)((flagByte >> 5) & 0x01); 157 | 158 | return true; 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/PreLogin/TDSEncryptionOption.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | // Depending upon whether the server has encryption available and enabled, the server responds with an ENCRYPTION value in the response according to the following table 8 | 9 | // +=============================+============================================================+===========================================================+================================================================+ 10 | // | Value sent by client | Value returned by server when server is set to ENCRYPT_OFF | Value returned by server when server is set to ENCRYPT_ON | Value returned by server when server is set to ENCRYPT_NOT_SUP | 11 | // +=============================+============================================================+===========================================================+================================================================+ 12 | // | ENCRYPT_OFF | ENCRYPT_OFF | ENCRYPT_REQ | ENCRYPT_NOT_SUP | 13 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 14 | // | ENCRYPT_ON | ENCRYPT_ON | ENCRYPT_ON | ENCRYPT_NOT_SUP (connection terminated) | 15 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 16 | // | ENCRYPT_NOT_SUP | ENCRYPT_NOT_SUP | ENCRYPT_REQ (connection terminated) | ENCRYPT_NOT_SUP | 17 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 18 | // | ENCRYPT_REQ | ENCRYPT_ON | ENCRYPT_ON | ENCRYPT_NOT_SUP (connection terminated) | 19 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 20 | // | ENCRYPT_CLIENT_CERT_OFF | ENCRYPT_OFF | ENCRYPT_REQ | ENCRYPT_NOT_SUP (connection terminated) | 21 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 22 | // | ENCRYPT_CLIENT_CERT_ON | ENCRYPT_ON | ENCRYPT_ON | ENCRYPT_NOT_SUP (connection terminated) | 23 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 24 | // | ENCRYPT_CLIENT_CERT_NOT_SUP | ENCRYPT_REQ (connection terminated) | ENCRYPT_REQ (connection terminated) | ENCRYPT_REQ (connection terminated) | 25 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 26 | // | ENCRYPT_CLIENT_CERT_REQ | ENCRYPT_ON | ENCRYPT_ON | ENCRYPT_NOT_SUP (connection terminated) | 27 | // +-----------------------------+------------------------------------------------------------+-----------------------------------------------------------+----------------------------------------------------------------+ 28 | 29 | // Assuming that the client is capable of encryption, the server requires the client to behave in the following manner. 30 | 31 | // +=============+===========================================+==========================================+===========================================+===============================================+ 32 | // | Client | Value returned from server is ENCRYPT_OFF | Value returned from server is ENCRYPT_ON | Value returned from server is ENCRYPT_REQ | Value returned from server is ENCRYPT_NOT_SUP | 33 | // +=============+===========================================+==========================================+===========================================+===============================================+ 34 | // | ENCRYPT_OFF | Encrypt login packet only | Encrypt entire connection | Encrypt entire connection | No encryption | 35 | // +-------------+-------------------------------------------+------------------------------------------+-------------------------------------------+-----------------------------------------------+ 36 | // | ENCRYPT_ON | Error (connection terminated) | Encrypt entire connection | Encrypt entire connection | Error (connection terminated) | 37 | // +-------------+-------------------------------------------+------------------------------------------+-------------------------------------------+-----------------------------------------------+ 38 | 39 | namespace TDSClient.TDS.Header 40 | { 41 | /// 42 | /// Enum describing TDSEncryptionOption 43 | /// 44 | public enum TDSEncryptionOption : byte 45 | { 46 | /// 47 | /// Encryption is available but off. 48 | /// 49 | EncryptOff = 0x00, 50 | 51 | /// 52 | /// Encryption is available and on. 53 | /// 54 | EncryptOn = 0x01, 55 | 56 | /// 57 | /// Encryption is not available. 58 | /// 59 | EncryptNotSup = 0x02, 60 | 61 | /// 62 | /// Encryption is required. 63 | /// 64 | EncryptReq = 0x03, 65 | 66 | /// 67 | /// Certificate-based authentication is requested by the client, encryption is off. 68 | /// 69 | EncryptClientCertOff = 0x80, 70 | 71 | /// 72 | /// Certificate-based authentication is requested by the client, encryption is on. 73 | /// 74 | EncryptClientCertOn = 0x81, 75 | 76 | /// 77 | /// Certificate-based authentication is requested by the client, encryption is required. 78 | /// 79 | EncryptClientCertReq = 0x83 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/PreLogin/TDSPreLoginAuthenticationType.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.PreLogin 8 | { 9 | /// 10 | /// FedAuthRequired option in the prelogin packet. 11 | /// 12 | public enum TdsPreLoginFedAuthRequiredOption : byte 13 | { 14 | /// 15 | /// FedAuthNotRequired. 16 | /// 17 | FedAuthNotRequired = 0x00, 18 | /// 19 | /// FedAuthRequired. 20 | /// 21 | FedAuthRequired = 0x01, 22 | /// 23 | /// Illegal. 24 | /// 25 | Illegal = 0x02 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/PreLogin/TDSPreLoginOptionToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.PreLogin 8 | { 9 | using System; 10 | using System.IO; 11 | 12 | using TDSClient.TDS.Interfaces; 13 | using TDSClient.TDS.Utilities; 14 | 15 | /// 16 | /// Class describing TDS PreLogin Option Token 17 | /// 18 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | public class TDSPreLoginOptionToken : IPackageable, IEquatable 20 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 21 | { 22 | /// 23 | /// Initializes a new instance of the class. 24 | /// 25 | public TDSPreLoginOptionToken() 26 | { 27 | } 28 | 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | /// PreLogin Option Token Type 33 | public TDSPreLoginOptionToken(TDSPreLoginOptionTokenType type) 34 | { 35 | Type = type; 36 | switch (Type) 37 | { 38 | case TDSPreLoginOptionTokenType.Encryption: 39 | { 40 | Length = 1; 41 | break; 42 | } 43 | 44 | case TDSPreLoginOptionTokenType.FedAuthRequired: 45 | { 46 | Length = 1; 47 | break; 48 | } 49 | 50 | case TDSPreLoginOptionTokenType.InstOpt: 51 | { 52 | throw new NotSupportedException(); 53 | } 54 | 55 | case TDSPreLoginOptionTokenType.MARS: 56 | { 57 | Length = 1; 58 | break; 59 | } 60 | 61 | case TDSPreLoginOptionTokenType.NonceOpt: 62 | { 63 | Length = 32; 64 | break; 65 | } 66 | 67 | case TDSPreLoginOptionTokenType.Terminator: 68 | { 69 | Length = 0; 70 | break; 71 | } 72 | 73 | case TDSPreLoginOptionTokenType.ThreadID: 74 | { 75 | Length = 4; 76 | break; 77 | } 78 | 79 | case TDSPreLoginOptionTokenType.TraceID: 80 | { 81 | Length = 36; 82 | break; 83 | } 84 | 85 | case TDSPreLoginOptionTokenType.Version: 86 | { 87 | Length = 6; 88 | break; 89 | } 90 | } 91 | } 92 | 93 | /// 94 | /// Gets or sets TDS PreLogin Option Token Type. 95 | /// 96 | public TDSPreLoginOptionTokenType Type { get; set; } 97 | 98 | /// 99 | /// Gets or sets Offset. 100 | /// 101 | public ushort Offset { get; set; } 102 | 103 | /// 104 | /// Gets or sets Length. 105 | /// 106 | public ushort Length { get; set; } 107 | 108 | /// 109 | /// Determines whether the specified object is equal to the current object. 110 | /// 111 | /// The object to compare with the current object. 112 | /// true if the specified object is equal to the current object; otherwise, false 113 | public override bool Equals(object obj) 114 | { 115 | return Equals(obj as TDSPreLoginOptionToken); 116 | } 117 | 118 | /// 119 | /// Determines whether the specified object is equal to the current object. 120 | /// 121 | /// The object to compare with the current object. 122 | /// true if the specified object is equal to the current object; otherwise, false 123 | public bool Equals(TDSPreLoginOptionToken other) 124 | { 125 | return other != null && 126 | Type == other.Type && 127 | Offset == other.Offset && 128 | Length == other.Length; 129 | } 130 | 131 | /// 132 | /// Used to pack IPackageable to a stream. 133 | /// 134 | /// MemoryStream in which IPackageable is packet into. 135 | public void Pack(MemoryStream stream) 136 | { 137 | stream.WriteByte((byte)Type); 138 | if (Type != TDSPreLoginOptionTokenType.Terminator) 139 | { 140 | BigEndianUtilities.WriteUShort(stream, Offset); 141 | BigEndianUtilities.WriteUShort(stream, Length); 142 | } 143 | } 144 | 145 | /// 146 | /// Used to unpack IPackageable from a stream. 147 | /// 148 | /// MemoryStream from which to unpack IPackageable. 149 | /// Returns true if successful. 150 | public bool Unpack(MemoryStream stream) 151 | { 152 | Type = (TDSPreLoginOptionTokenType)stream.ReadByte(); 153 | 154 | if (Type != TDSPreLoginOptionTokenType.Terminator) 155 | { 156 | Offset = BigEndianUtilities.ReadUShort(stream); 157 | Length = BigEndianUtilities.ReadUShort(stream); 158 | } 159 | 160 | return true; 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/PreLogin/TDSPreLoginOptionTokenType.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.PreLogin 8 | { 9 | // +-----------------+----------------------------------------------------------------------------------+ 10 | // | PL_OPTION_TOKEN | Description | 11 | // +-----------------+----------------------------------------------------------------------------------+ 12 | // | VERSION | PL_OPTION_DATA = UL_VERSION | 13 | // | | US_SUBBUILD | 14 | // | | UL_VERSION is composed of major version (1 byte), minor version (1 byte), | 15 | // | | and build number (2 bytes). It is represented in network byte order (bigendian). | 16 | // | | On x86 platforms, UL_VERSION is prepared as follows: | 17 | // | | US_BUILD = SwapBytes (VER_SQL_BUILD); | 18 | // | | UL_VERSION = ( (US_BUILD <16>) / (VER_SQL_MINOR <8>) / ( | 19 | // | | VER_SQL_MAJOR) ) | 20 | // | | SwapBytes is used to swap bytes. For example, SwapBytes(0x106A)= | 21 | // | | 0x6A10. | 22 | // +-----------------+----------------------------------------------------------------------------------+ 23 | // | ENCRYPTION | PL_OPTION_DATA = B_FENCRYPTION | 24 | // +-----------------+----------------------------------------------------------------------------------+ 25 | // | INSTOPT | PL_OPTION_DATA = B_INSTVALIDITY | 26 | // +-----------------+----------------------------------------------------------------------------------+ 27 | // | THREADID | PL_OPTION_DATA = UL_THREADID | 28 | // | | This value SHOULD be empty when being sent from the server to the client. | 29 | // +-----------------+----------------------------------------------------------------------------------+ 30 | // | MARS | PL_OPTION_DATA = B_MARS | 31 | // | |  0x00 = Off | 32 | // | |  0x01 = On | 33 | // +-----------------+----------------------------------------------------------------------------------+ 34 | // | TRACEID | PL_OPTION_DATA = GUID_CONNID | 35 | // | | ACTIVITY_GUID | 36 | // | | SEQUENCE_ID | 37 | // +-----------------+----------------------------------------------------------------------------------+ 38 | // | FEDAUTHREQUIRED | PL_OPTION_DATA = B_FEDAUTHREQUIRED | 39 | // | | Introduced in TDS 7.4. | 40 | // +-----------------+----------------------------------------------------------------------------------+ 41 | // | NONCEOPT | PL_OPTION_DATA = NONCE | 42 | // | | The client MUST send this option if it expects to be able to use federated | 43 | // | | authentication with Live ID Compact Token to authenticate to the server on | 44 | // | | this connection. | 45 | // | | If the server understands the NONCEOPT option and the client sends the | 46 | // | | option, the server MUST respond with its own NONCEOPT. | 47 | // +-----------------+----------------------------------------------------------------------------------+ 48 | // | TERMINATOR | Termination token. | 49 | // +-----------------+----------------------------------------------------------------------------------+ 50 | 51 | /// 52 | /// Enum describing TDS PreLogin Option Token type 53 | /// 54 | public enum TDSPreLoginOptionTokenType : byte 55 | { 56 | /// 57 | /// PreLogin Version Option Token. 58 | /// 59 | Version, 60 | 61 | /// 62 | /// PreLogin Encryption Option Token. 63 | /// 64 | Encryption, 65 | 66 | /// 67 | /// PreLogin Inst Option Token. 68 | /// 69 | InstOpt, 70 | 71 | /// 72 | /// PreLogin ThreadID Option Token. 73 | /// 74 | ThreadID, 75 | 76 | /// 77 | /// PreLogin MARS Option Token. 78 | /// 79 | MARS, 80 | 81 | /// 82 | /// PreLogin TraceID Option Token. 83 | /// 84 | TraceID, 85 | 86 | /// 87 | /// PreLogin FedAuth Option Token. 88 | /// 89 | FedAuthRequired, 90 | 91 | /// 92 | /// PreLogin Nonce Option Token. 93 | /// 94 | NonceOpt, 95 | 96 | /// 97 | /// PreLogin Token Terminator. 98 | /// 99 | Terminator = 0xFF 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/EnvChange/TDSEnvChangeToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | using System; 10 | using System.Collections.Generic; 11 | using System.IO; 12 | using System.Linq; 13 | using System.Text; 14 | 15 | using TDSClient.TDS.Tokens.EnvChange; 16 | using TDSClient.TDS.Utilities; 17 | 18 | /// 19 | /// Class describing TDS EnvChange Token 20 | /// 21 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 22 | public class TDSEnvChangeToken : TDSToken, IEquatable 23 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 24 | { 25 | /// 26 | /// Initializes a new instance of the class. 27 | /// 28 | public TDSEnvChangeToken() 29 | { 30 | Values = new Dictionary(); 31 | } 32 | 33 | /// 34 | /// Gets or sets TDS EnvChange Token Type 35 | /// 36 | public ushort TokenLength { get; set; } 37 | 38 | /// 39 | /// Gets or sets TDS EnvChange Token Type 40 | /// 41 | public TDSEnvChangeType Type { get; set; } 42 | 43 | /// 44 | /// Gets or sets TDS EnvChange Token values 45 | /// 46 | public Dictionary Values { get; set; } 47 | 48 | /// 49 | /// Determines whether the specified object is equal to the current object. 50 | /// 51 | /// The object to compare with the current object. 52 | /// true if the specified object is equal to the current object; otherwise, false 53 | public override bool Equals(object obj) 54 | { 55 | return Equals(obj as TDSEnvChangeToken); 56 | } 57 | 58 | /// 59 | /// Determines whether the specified object is equal to the current object. 60 | /// 61 | /// The object to compare with the current object. 62 | /// true if the specified object is equal to the current object; otherwise, false 63 | public bool Equals(TDSEnvChangeToken other) 64 | { 65 | return other != null && 66 | Type == other.Type && 67 | Values.Count == other.Values.Count && 68 | !Values.Except(other.Values).Any(); 69 | } 70 | 71 | /// 72 | /// EnvChange Token Length 73 | /// 74 | /// Returns EnvChange token length 75 | public override ushort Length() 76 | { 77 | throw new NotImplementedException(); 78 | } 79 | 80 | /// 81 | /// Used to pack IPackageable to a stream. 82 | /// 83 | /// Memory stream to pack the IPackageable to. 84 | public override void Pack(MemoryStream stream) 85 | { 86 | throw new NotImplementedException(); 87 | } 88 | 89 | public override void ProcessToken() 90 | { 91 | throw new NotImplementedException(); 92 | } 93 | 94 | /// 95 | /// Used to unpack IPackageable from a stream. 96 | /// 97 | /// MemoryStream containing the object that needs to be unpacked. 98 | /// Returns true if successful. 99 | public override bool Unpack(MemoryStream stream) 100 | { 101 | var length = LittleEndianUtilities.ReadUShort(stream); 102 | Type = (TDSEnvChangeType)stream.ReadByte(); 103 | switch (Type) 104 | { 105 | case TDSEnvChangeType.Routing: 106 | var routingDataValueLength = LittleEndianUtilities.ReadUShort(stream); 107 | if (routingDataValueLength == 0 || stream.ReadByte() != 0) 108 | { 109 | throw new InvalidOperationException(); 110 | } 111 | 112 | var protocolProperty = LittleEndianUtilities.ReadUShort(stream); 113 | if (protocolProperty == 0) 114 | { 115 | throw new InvalidOperationException(); 116 | } 117 | 118 | int strLength = LittleEndianUtilities.ReadUShort(stream) * 2; 119 | 120 | var temp = new byte[strLength]; 121 | stream.Read(temp, 0, strLength); 122 | 123 | Values["ProtocolProperty"] = string.Format("{0}", protocolProperty); 124 | Values["AlternateServer"] = Encoding.Unicode.GetString(temp); 125 | 126 | for (int i = 0; i < length - routingDataValueLength - sizeof(byte) - sizeof(ushort); i++) 127 | { 128 | // Ignore oldValue 129 | stream.ReadByte(); 130 | } 131 | 132 | break; 133 | default: 134 | { 135 | for (int i = 0; i < length - sizeof(byte); i++) 136 | { 137 | // Ignore unsupported types 138 | stream.ReadByte(); 139 | } 140 | 141 | return false; 142 | } 143 | } 144 | 145 | return true; 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/EnvChange/TDSEnvChangeType.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens.EnvChange 8 | { 9 | /// 10 | /// Enum describing ENcChange Token Type 11 | /// 12 | public enum TDSEnvChangeType : byte 13 | { 14 | /// 15 | /// EnvChange Database Token. 16 | /// 17 | Database = 1, 18 | 19 | /// 20 | /// EnvChange Language Token. 21 | /// 22 | Language, 23 | 24 | /// 25 | /// EnvChange CharacterSet Token. 26 | /// 27 | CharacterSet, 28 | 29 | /// 30 | /// EnvChange PacketSize Token. 31 | /// 32 | PacketSize, 33 | 34 | /// 35 | /// EnvChange Unicode Data Sorting Local ID Token. 36 | /// 37 | UnicodeDataSortingLocalID, 38 | 39 | /// 40 | /// EnvChange Unicode Data Sorting Comparison Flags Token. 41 | /// 42 | UnicodeDataSortingComparisonFlags, 43 | 44 | /// 45 | /// EnvChange SQLCollation Token. 46 | /// 47 | SQLCollation, 48 | 49 | /// 50 | /// EnvChange Begin Transaction Token. 51 | /// 52 | BeginTransaction, 53 | 54 | /// 55 | /// EnvChange Commit Transaction Token. 56 | /// 57 | CommitTransaction, 58 | 59 | /// 60 | /// EnvChange Rollback Transaction Token. 61 | /// 62 | RollbackTransaction, 63 | 64 | /// 65 | /// EnvChange Enlist DTC Transaction Token. 66 | /// 67 | EnlistDTCTransaction, 68 | 69 | /// 70 | /// EnvChange Defect Transaction Token. 71 | /// 72 | DefectTransaction, 73 | 74 | /// 75 | /// EnvChange Database Mirroring Partner Token. 76 | /// 77 | DatabaseMirroringPartner, 78 | 79 | /// 80 | /// EnvChange Promote Transaction Token. 81 | /// 82 | PromoteTransaction = 15, 83 | 84 | /// 85 | /// EnvChange Transaction Manager Address Token. 86 | /// 87 | TransactionManagerAddress, 88 | 89 | /// 90 | /// EnvChange Transaction Ended Token. 91 | /// 92 | TransactionEnded, 93 | 94 | /// 95 | /// EnvChange Reset Completion Ack Token. 96 | /// 97 | ResetCompletionAck, 98 | 99 | /// 100 | /// EnvChange Send Back User Info Token. 101 | /// 102 | SendBackUserInfo, 103 | 104 | /// 105 | /// EnvChange Routing Token. 106 | /// 107 | Routing 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/FedAuthInfoToken/TDSFedAuthInfoId.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens.FedAuthInfoToken 8 | { 9 | /// 10 | /// TDS Fed Auth Info Id. 11 | /// 12 | public enum TDSFedAuthInfoId 13 | { 14 | /// 15 | /// STS URL - A Unicode string that represents 16 | /// the token endpoint URL from which to 17 | /// acquire a Fed Auth Token 18 | /// 19 | STSURL = 0x01, 20 | 21 | /// 22 | /// Service Principal Name 23 | /// 24 | SPN = 0x02, 25 | 26 | /// 27 | /// Invalid InfoId 28 | /// 29 | Invalid = 0xEE 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/FedAuthInfoToken/TDSFedAuthInfoOption.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens.FedAuthInfoToken 8 | { 9 | using System.IO; 10 | 11 | using TDSClient.TDS.Interfaces; 12 | 13 | /// 14 | /// A single fedauth information option. 15 | /// 16 | public abstract class TDSFedAuthInfoOption : IPackageable 17 | { 18 | /// 19 | /// Information Data Length 20 | /// 21 | public uint InfoDataLength; 22 | 23 | /// 24 | /// FedAuth Info Identifier. 25 | /// 26 | public abstract TDSFedAuthInfoId FedAuthInfoId { get; } 27 | 28 | /// 29 | /// Initialization Constructor. 30 | /// 31 | public TDSFedAuthInfoOption() 32 | { 33 | } 34 | 35 | /// 36 | /// Unpack the token 37 | /// 38 | public abstract bool Unpack(MemoryStream source); 39 | 40 | /// 41 | /// Pack the token. 42 | /// 43 | public abstract void Pack(MemoryStream destination); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/FedAuthInfoToken/TDSFedAuthInfoOptionSPN.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens.FedAuthInfoToken 8 | { 9 | using System; 10 | using System.IO; 11 | using System.Text; 12 | 13 | /// 14 | /// TDS FedAuth Info Option for SPN 15 | /// 16 | public class TDSFedAuthInfoOptionSPN : TDSFedAuthInfoOption 17 | { 18 | /// 19 | /// Service Principal Name (SPN) 20 | /// 21 | public byte[] ServicePrincipalName { get; set; } 22 | 23 | /// 24 | /// Return the SPN as a unicode string. 25 | /// 26 | public string GetSPNString => ServicePrincipalName != null 27 | ? Encoding.Unicode.GetString(ServicePrincipalName) 28 | : null; 29 | 30 | /// 31 | /// Return the FedAuthInfo Id. 32 | /// 33 | public override TDSFedAuthInfoId FedAuthInfoId => TDSFedAuthInfoId.SPN; 34 | 35 | /// 36 | /// Default public contructor 37 | /// 38 | public TDSFedAuthInfoOptionSPN() 39 | { 40 | } 41 | 42 | /// 43 | /// Constructor 44 | /// 45 | /// Info Data Length 46 | public TDSFedAuthInfoOptionSPN(uint infoDataLength) 47 | : this() 48 | { 49 | InfoDataLength = infoDataLength; 50 | } 51 | 52 | /// 53 | /// Constructor 54 | /// 55 | /// SPN string 56 | public TDSFedAuthInfoOptionSPN(string spn) 57 | : this() 58 | { 59 | if (spn == null) 60 | { 61 | throw new ArgumentNullException(nameof(spn)); 62 | } 63 | 64 | ServicePrincipalName = Encoding.Unicode.GetBytes(spn); 65 | InfoDataLength = (uint)ServicePrincipalName.Length; 66 | } 67 | 68 | /// 69 | /// Unpack the data from the stream, when receiving this token. 70 | /// 71 | public override bool Unpack(MemoryStream source) 72 | { 73 | if (source == null) 74 | { 75 | throw new ArgumentNullException(nameof(source)); 76 | } 77 | 78 | if (InfoDataLength > 0) 79 | { 80 | ServicePrincipalName = new byte[InfoDataLength]; 81 | source.Read(ServicePrincipalName, 0, ServicePrincipalName.Length); 82 | } 83 | 84 | return true; 85 | } 86 | 87 | /// 88 | /// Pack the data to the stream, when writing this token. 89 | /// 90 | /// 91 | public override void Pack(MemoryStream source) 92 | { 93 | if (source == null) 94 | { 95 | throw new ArgumentNullException(nameof(source)); 96 | } 97 | 98 | if (InfoDataLength > 0) 99 | { 100 | source.Write(ServicePrincipalName, 0, ServicePrincipalName.Length); 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/FedAuthInfoToken/TDSFedAuthInfoOptionSTSURL.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens.FedAuthInfoToken 8 | { 9 | using System; 10 | using System.IO; 11 | using System.Text; 12 | 13 | /// 14 | /// TDS FedAuth Info Option for STS URL 15 | /// 16 | public class TDSFedAuthInfoOptionSTSURL : TDSFedAuthInfoOption 17 | { 18 | /// 19 | /// STS URL 20 | /// 21 | public byte[] StsUrl { get; set; } 22 | 23 | /// 24 | /// Return the FedAuthInfo Id. 25 | /// 26 | public override TDSFedAuthInfoId FedAuthInfoId => TDSFedAuthInfoId.STSURL; 27 | 28 | 29 | /// 30 | /// Return the STSURL as a unicode string. 31 | /// 32 | public string STSURL => StsUrl != null 33 | ? Encoding.Unicode.GetString(StsUrl) 34 | : null; 35 | 36 | /// 37 | /// Default public contructor 38 | /// 39 | public TDSFedAuthInfoOptionSTSURL() 40 | { 41 | } 42 | 43 | /// 44 | /// Constructor 45 | /// 46 | /// Info Data Length 47 | public TDSFedAuthInfoOptionSTSURL(uint infoDataLength) : this() 48 | { 49 | InfoDataLength = infoDataLength; 50 | } 51 | 52 | /// 53 | /// Constructor 54 | /// 55 | /// STSURL string 56 | public TDSFedAuthInfoOptionSTSURL(string stsurl) 57 | : this() 58 | { 59 | if (stsurl == null) 60 | { 61 | throw new ArgumentNullException(nameof(stsurl)); 62 | } 63 | 64 | StsUrl = Encoding.Unicode.GetBytes(stsurl); 65 | InfoDataLength = (uint)StsUrl.Length; 66 | } 67 | 68 | /// 69 | /// Unpack the data from the stream, when receiving this token. 70 | /// 71 | public override bool Unpack(MemoryStream source) 72 | { 73 | if (source == null) 74 | { 75 | throw new ArgumentNullException(nameof(source)); 76 | } 77 | 78 | if (InfoDataLength > 0) 79 | { 80 | StsUrl = new byte[InfoDataLength]; 81 | source.Read(StsUrl, 0, StsUrl.Length); 82 | } 83 | 84 | return true; 85 | } 86 | 87 | /// 88 | /// Pack the data to the stream, when writing this token. 89 | /// 90 | /// 91 | public override void Pack(MemoryStream source) 92 | { 93 | if (source == null) 94 | { 95 | throw new ArgumentNullException(nameof(source)); 96 | } 97 | 98 | if (InfoDataLength > 0) 99 | { 100 | source.Write(StsUrl, 0, StsUrl.Length); 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSDoneToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using TDSClient.TDS.Tokens; 6 | using TDSClient.TDS.Utilities; 7 | 8 | namespace TDSClient.TDS.Tokens 9 | { 10 | /// 11 | /// Status of the token 12 | /// 13 | public enum TDSDoneTokenStatusType : ushort 14 | { 15 | Final = 0x00, 16 | More = 0x01, 17 | Error = 0x02, 18 | TransactionInProgress = 0x04, 19 | Count = 0x10, 20 | Attention = 0x20, 21 | ServerError = 0x100 22 | } 23 | 24 | /// 25 | /// Completion Done token. 26 | /// 27 | public class TDSDoneToken : TDSToken 28 | { 29 | /// 30 | /// Status of the completion 31 | /// 32 | public TDSDoneTokenStatusType Status { get; set; } 33 | 34 | /// 35 | /// Token for which completion is indicated 36 | /// 37 | public ushort Command { get; set; } 38 | 39 | /// 40 | /// Amount of rows returned 41 | /// 42 | public ulong RowCount { get; set; } 43 | 44 | /// 45 | /// Default constructor 46 | /// 47 | public TDSDoneToken() 48 | { 49 | } 50 | 51 | /// 52 | /// Initialization constructor 53 | /// 54 | public TDSDoneToken(TDSDoneTokenStatusType status) 55 | { 56 | Status = status; 57 | } 58 | 59 | /// 60 | /// Inflate the token 61 | /// NOTE: This operation is not continuable and assumes that the entire token is available in the stream 62 | /// 63 | /// Stream to inflate the token from 64 | /// TRUE if inflation is complete 65 | public override bool Unpack(MemoryStream source) 66 | { 67 | Status = (TDSDoneTokenStatusType)LittleEndianUtilities.ReadUShort(source); 68 | Command = LittleEndianUtilities.ReadUShort(source); 69 | RowCount = LittleEndianUtilities.ReadULong(source); 70 | 71 | return true; 72 | } 73 | 74 | /// 75 | /// Deflate the token 76 | /// 77 | /// Stream to deflate token to 78 | public override void Pack(MemoryStream destination) 79 | { 80 | destination.WriteByte((byte)TDSTokenType.Done); 81 | LittleEndianUtilities.WriteUShort(destination, (ushort)Status); 82 | LittleEndianUtilities.WriteUShort(destination, (ushort)Command); 83 | LittleEndianUtilities.WriteULong(destination, RowCount); 84 | } 85 | 86 | public override ushort Length() 87 | { 88 | throw new NotImplementedException(); 89 | } 90 | 91 | public override bool Equals(object obj) 92 | { 93 | throw new NotImplementedException(); 94 | } 95 | 96 | public override void ProcessToken() 97 | { 98 | LoggingUtilities.WriteLog($" Processing Done token:"); 99 | LoggingUtilities.WriteLog($" Status: {Status}"); 100 | LoggingUtilities.WriteLog($" Current SQL statement command: {Command}"); 101 | LoggingUtilities.WriteLog($" Done Row Count: {RowCount}"); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSErrorToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | using System; 10 | using System.IO; 11 | using System.Text; 12 | 13 | using TDSClient.TDS.Utilities; 14 | 15 | /// 16 | /// Class describing TDS Error Token 17 | /// 18 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | public class TDSErrorToken : TDSToken, IEquatable 20 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 21 | { 22 | /// 23 | /// Gets or sets error number. 24 | /// 25 | public int Number { get; set; } 26 | 27 | /// 28 | /// Gets or sets error state. 29 | /// Used as a modifier to the error number. 30 | /// 31 | public byte State { get; set; } 32 | 33 | /// 34 | /// Gets or sets error class. 35 | /// The class (severity) of the error. A class of less than 10 indicates an informational message. 36 | /// 37 | public byte Class { get; set; } 38 | 39 | /// 40 | /// Gets or sets error message. 41 | /// 42 | public string MsgText { get; set; } 43 | 44 | /// 45 | /// Gets or sets server name. 46 | /// 47 | public string ServerName { get; set; } 48 | 49 | /// 50 | /// Gets or sets stored procedure name. 51 | /// 52 | public string ProcName { get; set; } 53 | 54 | /// 55 | /// Gets or sets line number. 56 | /// 57 | public uint LineNumber { get; set; } 58 | 59 | /// 60 | /// Determines whether the specified object is equal to the current object. 61 | /// 62 | /// The object to compare with the current object. 63 | /// true if the specified object is equal to the current object; otherwise, false 64 | public override bool Equals(object obj) 65 | { 66 | return Equals(obj as TDSErrorToken); 67 | } 68 | 69 | /// 70 | /// Determines whether the specified object is equal to the current object. 71 | /// 72 | /// The object to compare with the current object. 73 | /// true if the specified object is equal to the current object; otherwise, false 74 | public bool Equals(TDSErrorToken other) 75 | { 76 | return other != null && 77 | Number == other.Number && 78 | State == other.State && 79 | Class == other.Class && 80 | MsgText == other.MsgText && 81 | ServerName == other.ServerName && 82 | ProcName == other.ProcName && 83 | LineNumber == other.LineNumber; 84 | } 85 | 86 | /// 87 | /// TDS Error Token Length 88 | /// 89 | /// Returns TDS Error Token Length 90 | public override ushort Length() 91 | { 92 | throw new NotImplementedException(); 93 | } 94 | 95 | /// 96 | /// Used to pack IPackageable to a stream. 97 | /// 98 | /// MemoryStream in which IPackageable is packet into. 99 | public override void Pack(MemoryStream stream) 100 | { 101 | throw new NotImplementedException(); 102 | } 103 | 104 | /// 105 | /// Process token. 106 | /// 107 | /// 108 | public override void ProcessToken() 109 | { 110 | LoggingUtilities.WriteLog($" Client received Error token, Number: {Number}, State: {State}", writeToSummaryLog: true); 111 | LoggingUtilities.WriteLog($" MsgText: {MsgText}"); 112 | LoggingUtilities.WriteLog($" Class: {Class}"); 113 | LoggingUtilities.WriteLog($" ServerName: {ServerName}"); 114 | LoggingUtilities.WriteLog($" ProcName: {ProcName}"); 115 | LoggingUtilities.WriteLog($" LineNumber: {LineNumber}"); 116 | LoggingUtilities.WriteLog($" State: {State}"); 117 | 118 | if (Number == 18456) 119 | { 120 | throw new Exception("Login failure."); 121 | } 122 | } 123 | 124 | /// 125 | /// Used to unpack IPackageable from a stream. 126 | /// 127 | /// MemoryStream from which to unpack IPackageable. 128 | /// Returns true if successful. 129 | public override bool Unpack(MemoryStream stream) 130 | { 131 | LittleEndianUtilities.ReadUShort(stream); 132 | Number = (int)LittleEndianUtilities.ReadUInt(stream); 133 | State = Convert.ToByte(stream.ReadByte()); 134 | Class = Convert.ToByte(stream.ReadByte()); 135 | 136 | int length = LittleEndianUtilities.ReadUShort(stream) * 2; 137 | var buffer = new byte[length]; 138 | stream.Read(buffer, 0, length); 139 | MsgText = Encoding.Unicode.GetString(buffer); 140 | 141 | length = stream.ReadByte() * 2; 142 | buffer = new byte[length]; 143 | stream.Read(buffer, 0, length); 144 | ServerName = Encoding.Unicode.GetString(buffer); 145 | 146 | length = stream.ReadByte() * 2; 147 | buffer = new byte[length]; 148 | stream.Read(buffer, 0, length); 149 | ProcName = Encoding.Unicode.GetString(buffer); 150 | 151 | LineNumber = LittleEndianUtilities.ReadUInt(stream); 152 | 153 | return true; 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSInfoToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | using System; 10 | using System.IO; 11 | using System.Text; 12 | 13 | using TDSClient.TDS.Utilities; 14 | 15 | /// 16 | /// Class describing TDS Information Token 17 | /// 18 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | public class TDSInfoToken : TDSToken, IEquatable 20 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 21 | { 22 | /// 23 | /// Gets or sets information message number. 24 | /// 25 | public int Number { get; set; } 26 | 27 | /// 28 | /// Gets or sets information message state. 29 | /// 30 | public byte State { get; set; } 31 | 32 | /// 33 | /// Gets or sets information message class. 34 | /// 35 | public byte Class { get; set; } 36 | 37 | /// 38 | /// Gets or sets information message. 39 | /// 40 | public string MsgText { get; set; } 41 | 42 | /// 43 | /// Gets or sets server name. 44 | /// 45 | public string ServerName { get; set; } 46 | 47 | /// 48 | /// Gets or sets stored procedure name. 49 | /// 50 | public string ProcName { get; set; } 51 | 52 | /// 53 | /// Gets or sets line number. 54 | /// 55 | public uint LineNumber { get; set; } 56 | 57 | /// 58 | /// Determines whether the specified object is equal to the current object. 59 | /// 60 | /// The object to compare with the current object. 61 | /// true if the specified object is equal to the current object; otherwise, false 62 | public override bool Equals(object obj) 63 | { 64 | return Equals(obj as TDSInfoToken); 65 | } 66 | 67 | /// 68 | /// Determines whether the specified object is equal to the current object. 69 | /// 70 | /// The object to compare with the current object. 71 | /// true if the specified object is equal to the current object; otherwise, false 72 | public bool Equals(TDSInfoToken other) 73 | { 74 | return other != null && 75 | Number == other.Number && 76 | State == other.State && 77 | Class == other.Class && 78 | MsgText == other.MsgText && 79 | ServerName == other.ServerName && 80 | ProcName == other.ProcName && 81 | LineNumber == other.LineNumber; 82 | } 83 | 84 | /// 85 | /// TDS Info Token Length 86 | /// 87 | /// Returns TDS Info Token Length 88 | public override ushort Length() 89 | { 90 | throw new NotImplementedException(); 91 | } 92 | 93 | /// 94 | /// Used to pack IPackageable to a stream. 95 | /// 96 | /// MemoryStream in which IPackageable is packet into. 97 | public override void Pack(MemoryStream stream) 98 | { 99 | throw new NotImplementedException(); 100 | } 101 | 102 | /// 103 | /// Process Info token. 104 | /// 105 | public override void ProcessToken() 106 | { 107 | LoggingUtilities.WriteLog($" Processing Info token:"); 108 | LoggingUtilities.WriteLog($" Number: {Number}"); 109 | LoggingUtilities.WriteLog($" State: {State}"); 110 | LoggingUtilities.WriteLog($" Class: {Class}"); 111 | LoggingUtilities.WriteLog($" MsgText: {MsgText}"); 112 | LoggingUtilities.WriteLog($" ServerName: {ServerName}"); 113 | LoggingUtilities.WriteLog($" ProcName: {ProcName}"); 114 | LoggingUtilities.WriteLog($" LineNumber: {LineNumber}"); 115 | } 116 | 117 | /// 118 | /// Used to unpack IPackageable from a stream. 119 | /// 120 | /// MemoryStream from which to unpack IPackageable. 121 | /// Returns true if successful. 122 | public override bool Unpack(MemoryStream stream) 123 | { 124 | LittleEndianUtilities.ReadUShort(stream); 125 | Number = (int)LittleEndianUtilities.ReadUInt(stream); 126 | State = Convert.ToByte(stream.ReadByte()); 127 | Class = Convert.ToByte(stream.ReadByte()); 128 | 129 | int length = LittleEndianUtilities.ReadUShort(stream) * 2; 130 | var buffer = new byte[length]; 131 | stream.Read(buffer, 0, length); 132 | MsgText = Encoding.Unicode.GetString(buffer); 133 | 134 | length = stream.ReadByte() * 2; 135 | buffer = new byte[length]; 136 | stream.Read(buffer, 0, length); 137 | ServerName = Encoding.Unicode.GetString(buffer); 138 | 139 | length = stream.ReadByte() * 2; 140 | buffer = new byte[length]; 141 | stream.Read(buffer, 0, length); 142 | ProcName = Encoding.Unicode.GetString(buffer); 143 | 144 | LineNumber = LittleEndianUtilities.ReadUInt(stream); 145 | 146 | return true; 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSLoginAckToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | 5 | using TDSClient.TDS.Login7; 6 | using TDSClient.TDS.Utilities; 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | /// 10 | /// Login acknowledgement token. 11 | /// 12 | #pragma warning disable CS0659 13 | public class TDSLoginAckToken : TDSToken 14 | #pragma warning restore CS0659 15 | { 16 | /// 17 | /// The type of interface with which the server will accept client requests 18 | /// 19 | public ushort TokenLength { get; set; } 20 | 21 | /// 22 | /// The type of interface with which the server will accept client requests 23 | /// 24 | public TDSLogin7TypeFlagsSQLType Interface { get; set; } 25 | 26 | /// 27 | /// TDS Version used by the server 28 | /// 29 | public Version TDSVersion { get; set; } 30 | 31 | /// 32 | /// Name of the server (e.g. "Microsoft SQL Server") 33 | /// 34 | public string ProgName { get; set; } 35 | 36 | /// 37 | /// Server version 38 | /// 39 | public Version ServerVersion { get; set; } 40 | 41 | /// 42 | /// Default constructor 43 | /// 44 | public TDSLoginAckToken() 45 | { 46 | } 47 | 48 | /// 49 | /// Initialization constructor 50 | /// 51 | public TDSLoginAckToken(Version serverVersion) 52 | { 53 | ServerVersion = serverVersion; 54 | } 55 | 56 | /// 57 | /// Initialization constructor 58 | /// 59 | public TDSLoginAckToken(Version serverVersion, Version tdsVersion) : 60 | this(serverVersion) 61 | { 62 | TDSVersion = tdsVersion; 63 | } 64 | 65 | /// 66 | /// Initialization constructor 67 | /// 68 | public TDSLoginAckToken(Version serverVersion, Version tdsVersion, TDSLogin7TypeFlagsSQLType interfaceFlags) : 69 | this(serverVersion, tdsVersion) 70 | { 71 | Interface = interfaceFlags; 72 | } 73 | 74 | /// 75 | /// Initialization constructor 76 | /// 77 | public TDSLoginAckToken(Version serverVersion, Version tdsVersion, TDSLogin7TypeFlagsSQLType interfaceFlags, string serverName) : 78 | this(serverVersion, tdsVersion, interfaceFlags) 79 | { 80 | ProgName = serverName; 81 | } 82 | 83 | /// 84 | /// Unpack the token 85 | /// NOTE: This operation is not continuable and assumes that the entire token is available in the stream 86 | /// 87 | /// Stream to inflate the token from 88 | public override bool Unpack(MemoryStream source) 89 | { 90 | // We skip the token identifier because it is read by token factory 91 | 92 | TokenLength = (ushort)(source.ReadByte() + (source.ReadByte() << 8)); 93 | 94 | Interface = (TDSLogin7TypeFlagsSQLType)source.ReadByte(); 95 | 96 | string tdsVersion = string.Format("{0:X}", (uint)(source.ReadByte() << 24) 97 | + (uint)(source.ReadByte() << 16) 98 | + (uint)(source.ReadByte() << 8) 99 | + (uint)source.ReadByte()); 100 | 101 | // Consturct TDS version 102 | // See tds.h for TDSXX clarifications 103 | TDSVersion = new Version(int.Parse(tdsVersion.Substring(0, 1)), int.Parse(tdsVersion.Substring(1, 1)), Convert.ToInt32(tdsVersion.Substring(2, 2), 16), Convert.ToInt32(tdsVersion.Substring(4, 4), 16)); 104 | 105 | byte serverNameLength = (byte)source.ReadByte(); 106 | 107 | byte[] serverNameBytes = new byte[serverNameLength * 2]; 108 | 109 | source.Read(serverNameBytes, 0, serverNameBytes.Length); 110 | 111 | ProgName = Encoding.Unicode.GetString(serverNameBytes); 112 | 113 | ServerVersion = new Version(source.ReadByte(), source.ReadByte(), (source.ReadByte() << 8) + source.ReadByte()); 114 | 115 | return true; 116 | } 117 | 118 | /// 119 | /// Deflate the token 120 | /// 121 | /// Stream to deflate token to 122 | public override void Pack(MemoryStream destination) 123 | { 124 | destination.WriteByte((byte)TDSTokenType.LoginAck); 125 | 126 | // Calculate the length of the token 127 | // The total length, in bytes, of the following fields: Interface, TDSVersion, Progname, and ProgVersion. 128 | ushort tokenLength = (ushort)(sizeof(byte) + sizeof(uint) + sizeof(byte) + (string.IsNullOrEmpty(ProgName) ? 0 : ProgName.Length * 2) + sizeof(uint)); 129 | 130 | destination.WriteByte((byte)(tokenLength & 0xff)); 131 | destination.WriteByte((byte)((tokenLength >> 8) & 0xff)); 132 | 133 | destination.WriteByte((byte)Interface); 134 | 135 | uint tdsVersion = Convert.ToUInt32(string.Format("{0:X}", Math.Max(TDSVersion.Major, 0)) + string.Format("{0:X}", Math.Max(TDSVersion.Minor, 0)) + string.Format("{0:X2}", Math.Max(TDSVersion.Build, 0)) + string.Format("{0:X4}", Math.Max(TDSVersion.Revision, 0)), 16); 136 | 137 | destination.WriteByte((byte)((tdsVersion >> 24) & 0xff)); 138 | destination.WriteByte((byte)((tdsVersion >> 16) & 0xff)); 139 | destination.WriteByte((byte)((tdsVersion >> 8) & 0xff)); 140 | destination.WriteByte((byte)(tdsVersion & 0xff)); 141 | 142 | destination.WriteByte((byte)(string.IsNullOrEmpty(ProgName) ? 0 : ProgName.Length)); 143 | 144 | byte[] serverNameBytes = Encoding.Unicode.GetBytes(ProgName); 145 | 146 | destination.Write(serverNameBytes, 0, serverNameBytes.Length); 147 | 148 | destination.WriteByte((byte)(ServerVersion.Major & 0xff)); 149 | destination.WriteByte((byte)(ServerVersion.Minor & 0xff)); 150 | destination.WriteByte((byte)((ServerVersion.Build >> 8) & 0xff)); 151 | destination.WriteByte((byte)(ServerVersion.Build & 0xff)); 152 | } 153 | 154 | /// 155 | /// LoginAck token length 156 | /// 157 | /// Returns LoginAck length 158 | public override ushort Length() 159 | { 160 | return (ushort)(sizeof(byte) + sizeof(ushort) + TokenLength); 161 | } 162 | 163 | /// 164 | /// Compares. 165 | /// 166 | /// 167 | /// 168 | public override bool Equals(object obj) 169 | { 170 | return Equals(obj as TDSLoginAckToken); 171 | } 172 | 173 | /// 174 | /// Compares. 175 | /// 176 | /// 177 | /// 178 | public bool Equals(TDSLoginAckToken obj) 179 | { 180 | return Length() == obj.Length() 181 | && TokenLength == obj.TokenLength 182 | && Interface.Equals(obj.TokenLength) 183 | && TDSVersion.Equals(obj.TDSVersion) 184 | && ProgName.Equals(obj.ProgName); 185 | } 186 | 187 | /// 188 | /// Process login ack token. 189 | /// 190 | public override void ProcessToken() 191 | { 192 | LoggingUtilities.WriteLog($" Processing LoginAck token:"); 193 | LoggingUtilities.WriteLog($" Interface: {Interface}"); 194 | LoggingUtilities.WriteLog($" ProgName: {ProgName}"); 195 | LoggingUtilities.WriteLog($" ServerVersion: {ServerVersion}"); 196 | LoggingUtilities.WriteLog($" TDSVersion: {TDSVersion}"); 197 | LoggingUtilities.WriteLog($" Logged in successfully."); 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSToken.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | using System.IO; 10 | 11 | using TDSClient.TDS.Interfaces; 12 | 13 | /// 14 | /// Abstract class describing functionalities of a TDS Token 15 | /// 16 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 17 | public abstract class TDSToken : ITDSPacketData 18 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 19 | { 20 | /// 21 | /// TDS Token length 22 | /// 23 | /// Returns TDS Token length 24 | public abstract ushort Length(); 25 | 26 | /// 27 | /// Used to package TDS Token into a stream 28 | /// 29 | /// Stream to pack the TDS Token into 30 | public abstract void Pack(MemoryStream stream); 31 | 32 | /// 33 | /// Used to unpack a TDS Token from a given stream 34 | /// 35 | /// MemoryStream that contains the token to unpack 36 | /// Returns true if successful 37 | public abstract bool Unpack(MemoryStream stream); 38 | 39 | /// 40 | /// Determines whether the specified object is equal to the current object. 41 | /// 42 | /// The object to compare with the current object. 43 | /// true if the specified object is equal to the current object; otherwise, false 44 | public override abstract bool Equals(object obj); 45 | 46 | /// 47 | /// Processes a token. 48 | /// 49 | public abstract void ProcessToken(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSTokenFactory.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | using System; 10 | using System.IO; 11 | using TDSClient.TDS.Tokens.FedAuthInfoToken; 12 | using TDSClient.TDS.Utilities; 13 | 14 | /// 15 | /// Factory used to read different tokens from a stream 16 | /// 17 | public static class TDSTokenFactory 18 | { 19 | /// 20 | /// Reads a TDS Token from a given MemoryStream 21 | /// 22 | /// Stream that contains the token 23 | /// Returns read TDS Token 24 | public static TDSToken ReadTokenFromStream(MemoryStream stream) 25 | { 26 | var tokenType = (TDSTokenType)stream.ReadByte(); 27 | 28 | LoggingUtilities.WriteLog($" Received {tokenType} token in Login7 response."); 29 | switch (tokenType) 30 | { 31 | case TDSTokenType.Error: 32 | { 33 | var token = new TDSErrorToken(); 34 | token.Unpack(stream); 35 | 36 | return token; 37 | } 38 | 39 | case TDSTokenType.EnvChange: 40 | { 41 | var token = new TDSEnvChangeToken(); 42 | token.Unpack(stream); 43 | 44 | return token; 45 | } 46 | 47 | case TDSTokenType.Info: 48 | { 49 | var token = new TDSInfoToken(); 50 | token.Unpack(stream); 51 | 52 | return token; 53 | } 54 | 55 | case TDSTokenType.FedAuthInfo: 56 | { 57 | var token = new TDSFedAuthInfoToken(); 58 | token.Unpack(stream); 59 | 60 | return token; 61 | } 62 | 63 | case TDSTokenType.LoginAck: 64 | { 65 | var token = new TDSLoginAckToken(); 66 | token.Unpack(stream); 67 | 68 | return token; 69 | } 70 | 71 | case TDSTokenType.Done: 72 | { 73 | var token = new TDSDoneToken(); 74 | token.Unpack(stream); 75 | 76 | return token; 77 | } 78 | 79 | default: 80 | { 81 | IgnoreToken(tokenType, stream); 82 | 83 | return null; 84 | } 85 | } 86 | } 87 | 88 | /// 89 | /// Skips a token within a stream based on token type 90 | /// 91 | /// Type of the token to ignore 92 | /// Stream that contains the token 93 | private static void IgnoreToken(TDSTokenType tokenType, MemoryStream stream) 94 | { 95 | switch (((byte)tokenType >> 4) & 0x3) 96 | { 97 | // Variable count token 98 | case 0: 99 | { 100 | throw new NotSupportedException(); 101 | } 102 | 103 | // Zero length token 104 | case 1: 105 | { 106 | return; 107 | } 108 | 109 | // Variable length token 110 | case 2: 111 | { 112 | if (tokenType == TDSTokenType.DataClassification) 113 | { 114 | throw new NotSupportedException(); 115 | } 116 | 117 | ushort length = tokenType == TDSTokenType.FeatureExtAck ? (ushort)6 : LittleEndianUtilities.ReadUShort(stream); 118 | for (int i = 0; i < length; i++) 119 | { 120 | stream.ReadByte(); 121 | } 122 | 123 | return; 124 | } 125 | 126 | // Fixed length token 127 | case 3: 128 | { 129 | var bytesToRead = Math.Pow(2, ((byte)tokenType >> 2) & 0x3); 130 | 131 | if (tokenType == TDSTokenType.Done || tokenType == TDSTokenType.DoneInProc || tokenType == TDSTokenType.DoneProc) 132 | { 133 | bytesToRead = 12; // Untill support is added 134 | } 135 | 136 | for (int i = 0; i < bytesToRead; i++) 137 | { 138 | stream.ReadByte(); 139 | } 140 | 141 | return; 142 | } 143 | 144 | default: 145 | { 146 | throw new InvalidOperationException(); 147 | } 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSTokenStreamPacketData.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | using System; 10 | using System.Collections.Generic; 11 | using System.IO; 12 | using System.Linq; 13 | 14 | using TDSClient.TDS.Interfaces; 15 | using TDSClient.TDS.Utilities; 16 | 17 | /// 18 | /// Class describing data portion of a TDS Token Stream 19 | /// 20 | #pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 21 | public class TDSTokenStreamPacketData : ITDSPacketData, IEquatable 22 | #pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not override Object.GetHashCode() 23 | { 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | public TDSTokenStreamPacketData() 28 | { 29 | Tokens = new List(); 30 | } 31 | 32 | /// 33 | /// Gets or sets TDS Token Stream Token List 34 | /// 35 | public List Tokens { get; set; } 36 | 37 | /// 38 | /// Determines whether the specified object is equal to the current object. 39 | /// 40 | /// The object to compare with the current object. 41 | /// true if the specified object is equal to the current object; otherwise, false 42 | public override bool Equals(object obj) 43 | { 44 | return Equals(obj as TDSTokenStreamPacketData); 45 | } 46 | 47 | /// 48 | /// Determines whether the specified object is equal to the current object. 49 | /// 50 | /// The object to compare with the current object. 51 | /// true if the specified object is equal to the current object; otherwise, false 52 | public bool Equals(TDSTokenStreamPacketData other) 53 | { 54 | return other != null && 55 | Tokens.SequenceEqual(other.Tokens); 56 | } 57 | 58 | /// 59 | /// TDS Token Stream Packet Data Length 60 | /// 61 | /// Returns TDS Token Stream Packet data portion length 62 | public ushort Length() 63 | { 64 | throw new NotImplementedException(); 65 | } 66 | 67 | /// 68 | /// Used to pack IPackageable to a stream. 69 | /// 70 | /// MemoryStream in which IPackageable is packet into. 71 | public void Pack(MemoryStream stream) 72 | { 73 | throw new NotImplementedException(); 74 | } 75 | 76 | /// 77 | /// Used to unpack IPackageable from a stream. 78 | /// 79 | /// MemoryStream from which to unpack IPackageable. 80 | /// Returns true if successful. 81 | public bool Unpack(MemoryStream stream) 82 | { 83 | while (stream.Length > stream.Position) 84 | { 85 | TDSToken token = TDSTokenFactory.ReadTokenFromStream(stream); 86 | if (token != null) 87 | { 88 | Tokens.Add(token); 89 | } 90 | } 91 | 92 | return true; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Tokens/TDSTokenType.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Tokens 8 | { 9 | /// 10 | /// Enum describing TDS Token Type 11 | /// 12 | public enum TDSTokenType : byte 13 | { 14 | /// 15 | /// TDS Alt Metadata Token. 16 | /// 17 | AltMetadata = 0x88, 18 | 19 | /// 20 | /// TDS Alt Row Token. 21 | /// 22 | AltRow = 0xd3, 23 | 24 | /// 25 | /// TDS Col Info Token. 26 | /// 27 | ColInfo = 0xa5, 28 | 29 | /// 30 | /// TDS Col Metadata Token. 31 | /// 32 | ColMetadata = 0x81, 33 | 34 | /// 35 | /// TDS Data Classification Token. 36 | /// 37 | DataClassification = 0xa3, 38 | 39 | /// 40 | /// TDS Done Token. 41 | /// 42 | Done = 0xfd, 43 | 44 | /// 45 | /// TDS Done In Proc Token. 46 | /// 47 | DoneInProc = 0xff, 48 | 49 | /// 50 | /// TDS Done Proc Token. 51 | /// 52 | DoneProc = 0xfe, 53 | 54 | /// 55 | /// TDS EnvChange Token. 56 | /// 57 | EnvChange = 0xe3, 58 | 59 | /// 60 | /// TDS Error Token. 61 | /// 62 | Error = 0xaa, 63 | 64 | /// 65 | /// TDS Feature Ext Ack Token. 66 | /// 67 | FeatureExtAck = 0xae, 68 | 69 | /// 70 | /// TDS Fed Auth Info Token. 71 | /// 72 | FedAuthInfo = 0xee, 73 | 74 | /// 75 | /// TDS Info Token. 76 | /// 77 | Info = 0xab, 78 | 79 | /// 80 | /// TDS Login Ack Token. 81 | /// 82 | LoginAck = 0xad, 83 | 84 | /// 85 | /// TDS NBC Row Token. 86 | /// 87 | NbcRow = 0xd2, 88 | 89 | /// 90 | /// TDS Offset Token. 91 | /// 92 | Offset = 0x78, 93 | 94 | /// 95 | /// TDS Order Token. 96 | /// 97 | Order = 0xa9, 98 | 99 | /// 100 | /// TDS Return Status Token. 101 | /// 102 | ReturnStatus = 0x79, 103 | 104 | /// 105 | /// TDS Return Value Token. 106 | /// 107 | ReturnValue = 0xac, 108 | 109 | /// 110 | /// TDS Row Token. 111 | /// 112 | Row = 0xd1, 113 | 114 | /// 115 | /// TDS Session State Token. 116 | /// 117 | SessionState = 0xe4, 118 | 119 | /// 120 | /// TDS SSPI Token. 121 | /// 122 | SSPI = 0xed, 123 | 124 | /// 125 | /// TDS TVP Row Token. 126 | /// 127 | TvpRow = 0x01 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Utilities/BigEndianUtilities.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Utilities 8 | { 9 | using System; 10 | using System.IO; 11 | 12 | /// 13 | /// Utility class used for read and write operations on a stream containing data in big-endian byte order 14 | /// 15 | public static class BigEndianUtilities 16 | { 17 | /// 18 | /// Used to write value to stream in big endian order. 19 | /// 20 | /// MemoryStream to to write the value to. 21 | /// Value to write to MemoryStream. 22 | public static void WriteUShort(MemoryStream stream, ushort value) 23 | { 24 | stream.WriteByte((byte)(value >> 8)); 25 | stream.WriteByte((byte)value); 26 | } 27 | 28 | /// 29 | /// Used to write value to stream in big endian order. 30 | /// 31 | /// MemoryStream to to write the value to. 32 | /// Value to write to MemoryStream. 33 | public static void WriteUInt(MemoryStream stream, uint value) 34 | { 35 | stream.WriteByte((byte)(value >> 24)); 36 | stream.WriteByte((byte)(value >> 16)); 37 | stream.WriteByte((byte)(value >> 8)); 38 | stream.WriteByte((byte)value); 39 | } 40 | 41 | /// 42 | /// Used to write value to stream in big endian order. 43 | /// 44 | /// MemoryStream to to write the value to. 45 | /// Value to write to MemoryStream. 46 | public static void WriteULong(MemoryStream stream, ulong value) 47 | { 48 | stream.WriteByte((byte)(value >> 56)); 49 | stream.WriteByte((byte)(value >> 48)); 50 | stream.WriteByte((byte)(value >> 40)); 51 | stream.WriteByte((byte)(value >> 32)); 52 | stream.WriteByte((byte)(value >> 24)); 53 | stream.WriteByte((byte)(value >> 16)); 54 | stream.WriteByte((byte)(value >> 8)); 55 | stream.WriteByte((byte)value); 56 | } 57 | 58 | /// 59 | /// Used to write byte array to stream in big endian order. 60 | /// 61 | /// MemoryStream to to write the value to. 62 | /// Array to write to MemoryStream. 63 | public static void WriteByteArray(MemoryStream stream, byte[] array) 64 | { 65 | for (int i = array.Length - 1; i >= 0; i--) 66 | { 67 | stream.WriteByte(array[i]); 68 | } 69 | } 70 | 71 | /// 72 | /// Used to read a UShort value from stream in big endian order. 73 | /// 74 | /// MemoryStream from which to read the value. 75 | /// UShort value read from the stream. 76 | public static ushort ReadUShort(MemoryStream stream) 77 | { 78 | ushort result = 0; 79 | for (int i = 0; i < 2; i++) 80 | { 81 | result <<= 8; 82 | result |= Convert.ToByte(stream.ReadByte()); 83 | } 84 | 85 | return result; 86 | } 87 | 88 | /// 89 | /// Used to read a UInt value from stream in big endian order. 90 | /// 91 | /// MemoryStream from which to read the value. 92 | /// UInt value read from the stream. 93 | public static uint ReadUInt(MemoryStream stream) 94 | { 95 | uint result = 0; 96 | for (int i = 0; i < 4; i++) 97 | { 98 | result <<= 8; 99 | result |= Convert.ToByte(stream.ReadByte()); 100 | } 101 | 102 | return result; 103 | } 104 | 105 | /// 106 | /// Used to read a ULong value from stream in big endian order. 107 | /// 108 | /// MemoryStream from which to read the value. 109 | /// ULong value read from the stream. 110 | public static ulong ReadULong(MemoryStream stream) 111 | { 112 | ulong result = 0; 113 | for (int i = 0; i < 8; i++) 114 | { 115 | result <<= 8; 116 | result |= Convert.ToByte(stream.ReadByte()); 117 | } 118 | 119 | return result; 120 | } 121 | 122 | /// 123 | /// Used to read a byte array from stream in big endian order. 124 | /// 125 | /// MemoryStream from which to read the array. 126 | /// Length of the array to read. 127 | /// Byte Array read from the stream. 128 | public static byte[] ReadByteArray(MemoryStream stream, uint length) 129 | { 130 | byte[] result = new byte[length]; 131 | for (int i = 1; i <= length; i++) 132 | { 133 | result[length - i] = Convert.ToByte(stream.ReadByte()); 134 | } 135 | 136 | return result; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDS/Utilities/LittleEndianUtilities.cs: -------------------------------------------------------------------------------- 1 | // --------------------------------------------------------------------------- 2 | // 3 | // Copyright (c) Microsoft Corporation. All rights reserved. 4 | // 5 | // --------------------------------------------------------------------------- 6 | 7 | namespace TDSClient.TDS.Utilities 8 | { 9 | using System.IO; 10 | using System.Text; 11 | 12 | /// 13 | /// Utility class used for read and write operations on a stream containing data in little-endian byte order 14 | /// 15 | public static class LittleEndianUtilities 16 | { 17 | /// 18 | /// Used to write value to stream in little endian order. 19 | /// 20 | /// MemoryStream to to write the value to. 21 | /// Value to write to MemoryStream. 22 | public static void WriteUShort(MemoryStream stream, ushort value) 23 | { 24 | stream.WriteByte((byte)value); 25 | stream.WriteByte((byte)(value >> 8)); 26 | } 27 | 28 | /// 29 | /// Used to write value to stream in little endian order. 30 | /// 31 | /// MemoryStream to to write the value to. 32 | /// Value to write to MemoryStream. 33 | public static void WriteUInt(MemoryStream stream, uint value) 34 | { 35 | stream.WriteByte((byte)value); 36 | stream.WriteByte((byte)(value >> 8)); 37 | stream.WriteByte((byte)(value >> 16)); 38 | stream.WriteByte((byte)(value >> 24)); 39 | } 40 | 41 | /// 42 | /// Used to read a UShort value from stream in little endian order. 43 | /// 44 | /// MemoryStream from which to read the value. 45 | /// UShort value read from the stream. 46 | public static ushort ReadUShort(MemoryStream stream) 47 | { 48 | ushort result = 0; 49 | for (int i = 0; i < 2; i++) 50 | { 51 | result |= (ushort)(stream.ReadByte() << (8 * i)); 52 | } 53 | 54 | return result; 55 | } 56 | 57 | /// 58 | /// Used to read a UInt value from stream in little endian order. 59 | /// 60 | /// MemoryStream from which to read the value. 61 | /// UInt value read from the stream. 62 | public static uint ReadUInt(MemoryStream stream) 63 | { 64 | uint result = 0; 65 | for (int i = 0; i < 4; i++) 66 | { 67 | result |= (uint)(stream.ReadByte() << (8 * i)); 68 | } 69 | 70 | return result; 71 | } 72 | 73 | /// 74 | /// Read a password string and decrypt it 75 | /// 76 | internal static string ReadPasswordString(Stream source, ushort length) 77 | { 78 | byte[] byteString = new byte[length]; 79 | 80 | source.Read(byteString, 0, byteString.Length); 81 | 82 | // Perform password decryption 83 | for (int i = 0; i < byteString.Length; i++) 84 | { 85 | // XOR first 86 | byteString[i] ^= 0xA5; 87 | 88 | // Swap 4 high bits with 4 low bits 89 | byteString[i] = (byte)(((byteString[i] & 0xf0) >> 4) | ((byteString[i] & 0xf) << 4)); 90 | } 91 | 92 | // Convert 93 | return Encoding.Unicode.GetString(byteString, 0, byteString.Length); 94 | } 95 | 96 | /// 97 | /// Read string from the packet 98 | /// 99 | internal static string ReadString(Stream source, ushort length) 100 | { 101 | if (length == 0) 102 | { 103 | return null; 104 | } 105 | 106 | byte[] byteString = new byte[length]; 107 | 108 | source.Read(byteString, 0, byteString.Length); 109 | 110 | return Encoding.Unicode.GetString(byteString, 0, byteString.Length); 111 | } 112 | 113 | /// 114 | /// Write password string encrypted into the packet 115 | /// 116 | internal static void WritePasswordString(Stream destination, string value) 117 | { 118 | if (string.IsNullOrEmpty(value)) 119 | { 120 | return; 121 | } 122 | 123 | byte[] byteString = Encoding.Unicode.GetBytes(value); 124 | 125 | // Perform password decryption 126 | for (int i = 0; i < byteString.Length; i++) 127 | { 128 | // Swap 4 high bits with 4 low bits 129 | byteString[i] = (byte)(((byteString[i] & 0xf0) >> 4) | ((byteString[i] & 0xf) << 4)); 130 | 131 | // XOR 132 | byteString[i] ^= 0xA5; 133 | } 134 | 135 | destination.Write(byteString, 0, byteString.Length); 136 | } 137 | 138 | /// 139 | /// Write string from into the packet 140 | /// 141 | internal static void WriteString(Stream destination, string value) 142 | { 143 | if (string.IsNullOrEmpty(value)) 144 | { 145 | return; 146 | } 147 | 148 | byte[] byteString = Encoding.Unicode.GetBytes(value); 149 | 150 | destination.Write(byteString, 0, byteString.Length); 151 | } 152 | 153 | /// 154 | /// Read signed integer from the packet 155 | /// 156 | internal static int ReadInt(Stream source) 157 | { 158 | return source.ReadByte() 159 | + source.ReadByte() << 8 160 | + source.ReadByte() << 16 161 | + source.ReadByte() << 24; 162 | } 163 | 164 | /// 165 | /// Write signed integer into the stream 166 | /// 167 | internal static void WriteInt(Stream destination, int value) 168 | { 169 | destination.WriteByte((byte)value); 170 | destination.WriteByte((byte)(value >> 8)); 171 | destination.WriteByte((byte)(value >> 16)); 172 | destination.WriteByte((byte)(value >> 24)); 173 | } 174 | 175 | /// 176 | /// Read unsigned long from the stream 177 | /// 178 | internal static ulong ReadULong(Stream source) 179 | { 180 | return (ulong)(source.ReadByte() 181 | + (source.ReadByte() << 8) 182 | + (source.ReadByte() << 16) 183 | + (source.ReadByte() << 24) 184 | + (source.ReadByte() << 32) 185 | + (source.ReadByte() << 40) 186 | + (source.ReadByte() << 48) 187 | + (source.ReadByte() << 56)); 188 | } 189 | 190 | /// 191 | /// Write unsigned long into the stream 192 | /// 193 | internal static void WriteULong(Stream destination, ulong value) 194 | { 195 | destination.WriteByte((byte)(value & 0xff)); 196 | destination.WriteByte((byte)((value >> 8) & 0xff)); 197 | destination.WriteByte((byte)((value >> 16) & 0xff)); 198 | destination.WriteByte((byte)((value >> 24) & 0xff)); 199 | destination.WriteByte((byte)((value >> 32) & 0xff)); 200 | destination.WriteByte((byte)((value >> 40) & 0xff)); 201 | destination.WriteByte((byte)((value >> 48) & 0xff)); 202 | destination.WriteByte((byte)((value >> 56) & 0xff)); 203 | } 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /TDSClient/TDSClient/TDSClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8.0 5 | 6 | 7 | 8 | netstandard2.0 9 | false 10 | 11 | Copyright (c) Microsoft Corporation. 12 | 13 | 14 | 15 | .\..\.. 16 | Auto 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /TDSClient/TDSClientLiveTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using TDSClient.TDS.Client; 4 | 5 | namespace TDSClientLiveTest 6 | { 7 | class Program 8 | { 9 | public static string Server = ".database.windows.net"; 10 | public static string Database = ""; 11 | public static int Port = 1433; 12 | public static string Username = "AzSQLConnCheckerUser"; 13 | public static string Password = "AzSQLConnCheckerPassword"; 14 | public static string AuthenticationType = "SQL Server Authentication"; 15 | public static string AuthenticationLibrary = "MSAL"; 16 | 17 | static void Main(string[] args) 18 | { 19 | TDSSQLTestClient tdsClient = new TDSSQLTestClient(Server, Port, AuthenticationType, Username, Password, Database); 20 | TDSClient.TDS.Utilities.LoggingUtilities.SetVerboseLog(Console.Out); 21 | //TDSClient.TDS.Utilities.LoggingUtilities.SetSummaryLog(Console.Out); 22 | 23 | for (int i = 0; i < 1; i++) 24 | { 25 | tdsClient.Connect(); 26 | tdsClient.Disconnect(); 27 | Console.WriteLine(); 28 | Thread.Sleep(1000); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TDSClient/TDSClientLiveTest/TDSClientLiveTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net8.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /UserSettings.xml: -------------------------------------------------------------------------------- 1 | 20200304013445 2 | -------------------------------------------------------------------------------- /netstandard2.0/Microsoft.Identity.Client.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/SQL-Connectivity-Checker/30476b732056364ebef6f3bd5edbb9d7f3711101/netstandard2.0/Microsoft.Identity.Client.dll -------------------------------------------------------------------------------- /netstandard2.0/Microsoft.IdentityModel.Abstractions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/SQL-Connectivity-Checker/30476b732056364ebef6f3bd5edbb9d7f3711101/netstandard2.0/Microsoft.IdentityModel.Abstractions.dll -------------------------------------------------------------------------------- /netstandard2.0/Microsoft.IdentityModel.Clients.ActiveDirectory.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/SQL-Connectivity-Checker/30476b732056364ebef6f3bd5edbb9d7f3711101/netstandard2.0/Microsoft.IdentityModel.Clients.ActiveDirectory.dll -------------------------------------------------------------------------------- /netstandard2.0/TDSClient.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/SQL-Connectivity-Checker/30476b732056364ebef6f3bd5edbb9d7f3711101/netstandard2.0/TDSClient.dll --------------------------------------------------------------------------------