├── .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
--------------------------------------------------------------------------------