@@ -111,71 +111,80 @@ Function Get-SqlServerTlsCertificate {
111111 $StrictEncrypt
112112 )
113113
114- class TdsTlsStream : System.IO.Stream {
115- [System.IO.Stream ]$InnerStream
116- [int ]$PayloadLength = 0
114+ if (-not ([System.Management.Automation.PSTypeName ]" TdsTlsStream" ).Type) {
115+ Add-Type - TypeDefinition @"
116+ using System;
117+ using System.IO;
117118
118- TdsTlsStream([ System.IO. Stream] $InnerStream ) {
119- $this .InnerStream = $InnerStream
120- }
119+ public class TdsTlsStream : Stream {
120+ private Stream _innerStream;
121+ private int _payloadLength = 0;
121122
122- [bool ] get_CanRead() { return $this.InnerStream.CanRead }
123- [bool ] get_CanWrite() { return $this.InnerStream.CanWrite }
124- [bool ] get_CanSeek() { return $this.InnerStream.CanSeek }
125- [Int64 ] get_Length() { return $this.InnerStream.Length }
126- [Int64 ] get_Position() { return $this.InnerStream.Position }
127- [void ] set_Position([Int64 ]$Value ) { $this.InnerStream.Position = $Value }
128- [int ] get_ReadTimeout() { return $this.InnerStream.ReadTimeout }
129- [int ] get_WriteTimeout() { return $this.InnerStream.WriteTimeout }
130-
131- [void ] Flush() { $this.InnerStream.Flush () }
132- [Int64 ] Seek([Int64 ]$Offset , [System.IO.SeekOrigin ]$Origin ) { return $this.InnerStream.Seek ($Offset , $Origin ) }
133- [void ] SetLength([Int64 ]$Value ) { $this.InnerStream.SetLength ($Value ) }
134-
135- [int ] Read([byte []]$Buffer , [int ]$Offset , [int ]$Count ) {
136- # We need to strip off the TDS header before setting the Buffer
137- if ($this.PayloadLength -eq 0 ) {
138- $header = [byte []]::new(8 )
139- $read = 0
140- while ($read -lt 8 ) {
141- $read += $this.InnerStream.Read ($header , 0 , 8 )
142- }
123+ public TdsTlsStream(Stream innerStream) {
124+ _innerStream = innerStream;
125+ }
143126
144- $lengthBeforeHeader = [System.BitConverter ]::ToUInt16([byte []]@ ($header [3 ], $header [2 ]), 0 )
145- $lengthBeforeHeader -= 8
146- $this.PayloadLength = $lengthBeforeHeader
127+ public override bool CanRead { get { return _innerStream.CanRead; } }
128+ public override bool CanWrite { get { return _innerStream.CanWrite; } }
129+ public override bool CanSeek { get { return _innerStream.CanSeek; } }
130+ public override long Length { get { return _innerStream.Length; } }
131+ public override long Position {
132+ get { return _innerStream.Position; }
133+ set { _innerStream.Position = value; }
134+ }
135+ public override int ReadTimeout { get { return _innerStream.ReadTimeout; } }
136+ public override int WriteTimeout { get { return _innerStream.WriteTimeout; } }
137+
138+ public override void Flush() { _innerStream.Flush(); }
139+ public override long Seek(long offset, SeekOrigin origin) { return _innerStream.Seek(offset, origin); }
140+ public override void SetLength(long value) { _innerStream.SetLength(value); }
141+
142+ public override int Read(byte[] buffer, int offset, int count) {
143+ // We need to strip off the TDS header before setting the Buffer
144+ if (_payloadLength == 0) {
145+ byte[] header = new byte[8];
146+ int read = 0;
147+ while (read < 8) {
148+ read += _innerStream.Read(header, 0, 8);
147149 }
148150
149- if ($Count -gt $this.PayloadLength ) {
150- $Count = $this.PayloadLength
151- }
152- $read = $this.InnerStream.Read ($Buffer , $Offset , $Count )
153- $this.PayloadLength -= $read
154- return $read
151+ int lengthBeforeHeader = (int)BitConverter.ToUInt16(new byte[] { header[3], header[2] }, 0);
152+ lengthBeforeHeader -= 8;
153+ _payloadLength = lengthBeforeHeader;
155154 }
156155
157- [void ] Write([byte []]$Buffer , [int ]$Offset , [int ]$Count ) {
158- $newPayload = $this.GenerateTdsHeader ($Buffer , $Offset , $Count )
159- $this.InnerStream.Write ($newPayload , 0 , $newPayload.Length )
156+ if (count > _payloadLength) {
157+ count = _payloadLength;
160158 }
159+ int bytesRead = _innerStream.Read(buffer, offset, count);
160+ _payloadLength -= bytesRead;
161+ return bytesRead;
162+ }
161163
162- [byte []] GenerateTdsHeader([byte []]$Payload , [int ]$Offset , [int ]$Count ) {
163- # The length is big endian encoded so it is inserted in reverse order
164- $lengthBytes = [System.BitConverter ]::GetBytes([uint16 ]($Count + 8 ))
165-
166- $newPayload = [byte []]::new(8 + $Count )
167- $newPayload [0 ] = 0x12 # Type - Pre-Login
168- $newPayload [1 ] = 0x01 # Status - End of message (EOM)
169- $newPayload [2 ] = $lengthBytes [1 ]
170- $newPayload [3 ] = $lengthBytes [0 ]
171- $newPayload [4 ] = 0 # SPID
172- $newPayload [5 ] = 0 # SPID
173- $newPayload [6 ] = 0 # PacketID
174- $newPayload [7 ] = 0 # Window
175- [System.Array ]::Copy($Payload , $Offset , $newPayload , 8 , $Count )
176-
177- return $newPayload
178- }
164+ public override void Write(byte[] buffer, int offset, int count) {
165+ byte[] newPayload = GenerateTdsHeader(buffer, offset, count);
166+ _innerStream.Write(newPayload, 0, newPayload.Length);
167+ }
168+
169+ private byte[] GenerateTdsHeader(byte[] payload, int offset, int count) {
170+ // The length is big endian encoded so it is inserted in reverse order
171+ byte[] lengthBytes = BitConverter.GetBytes((ushort)(count + 8));
172+
173+ byte[] newPayload = new byte[8 + count];
174+ newPayload[0] = 0x12; // Type - Pre-Login
175+ newPayload[1] = 0x01; // Status - End of message (EOM)
176+ newPayload[2] = lengthBytes[1];
177+ newPayload[3] = lengthBytes[0];
178+ newPayload[4] = 0; // SPID
179+ newPayload[5] = 0; // SPID
180+ newPayload[6] = 0; // PacketID
181+ newPayload[7] = 0; // Window
182+ Array.Copy(payload, offset, newPayload, 8, count);
183+
184+ return newPayload;
185+ }
186+ }
187+ "@
179188 }
180189
181190 $udpClient = $socket = $targetStream = $sslStream = $null
@@ -190,7 +199,7 @@ Function Get-SqlServerTlsCertificate {
190199 if ($ConnectionType -eq " SQLBrowser" ) {
191200 # Use the SQLBrowser
192201 # https://learn.microsoft.com/en-us/openspecs/windows_protocols/mc-sqlr/2e1560c9-5097-4023-9f5e-72b9ff1ec3b1
193- $udpClient = [ System.Net.Sockets.UdpClient ]::new ($ComputerName , 1434 )
202+ $udpClient = New-Object - TypeName System.Net.Sockets.UdpClient - ArgumentList @ ($ComputerName , 1434 )
194203 $udpClient.Client.SendTimeout = $ConnectTimeout
195204 $udpClient.Client.ReceiveTimeout = $ConnectTimeout
196205 $null = $udpClient.Send ([byte []]@ (0x03 ), 1 ) # CLNT_UCAST_EX
@@ -239,18 +248,17 @@ Function Get-SqlServerTlsCertificate {
239248 if ($ConnectionType -eq " TCP" ) {
240249 Write-Verbose - Message " Connecting to TCP/IP endpoint $ ( $ComputerName ) :$Port "
241250
242- $socket = [ System.Net.Sockets.TcpClient ]::new()
251+ $socket = New-Object - TypeName System.Net.Sockets.TcpClient
243252 $connectTask = $socket.ConnectAsync ($ComputerName , $Port )
244253 if (-not $connectTask.Wait ($ConnectTimeout )) {
245254 throw " Timed out connecting to TCP/IP endpoint $ ( $ComputerName ) :$Port "
246255 }
247256
248- $null = $connectTask.GetAwaiter ().GetResult()
249257 $targetStream = $socket.GetStream ()
250258 }
251259 else {
252260 Write-Verbose - Message " Connecting to Named Pipe endpoint \\$ ( $ComputerName ) \pipe\$pipeName "
253- $targetStream = [ System.IO.Pipes.NamedPipeClientStream ]::new (
261+ $targetStream = New-Object - TypeName System.IO.Pipes.NamedPipeClientStream - ArgumentList @ (
254262 $ComputerName ,
255263 $pipeName ,
256264 [System.IO.Pipes.PipeDirection ]::InOut)
@@ -281,7 +289,7 @@ Function Get-SqlServerTlsCertificate {
281289 )
282290 $targetStream.Write ($tdsPreLogin , 0 , $tdsPreLogin.Count )
283291
284- $headerBytes = [ byte []]::new( 8 )
292+ $headerBytes = New-Object byte[] 8
285293 $read = 0
286294 while ($read -ne $headerBytes.Length ) {
287295 $read += $targetStream.Read ($headerBytes , $read , $headerBytes.Length - $read )
@@ -292,7 +300,7 @@ Function Get-SqlServerTlsCertificate {
292300 $payloadLength = [System.BitConverter ]::ToUInt16([byte []]@ ($headerBytes [3 ], $headerBytes [2 ]), 0 )
293301 $payloadLength -= 8
294302
295- $tdsPreLoginResp = [ byte []]::new( $payloadLength )
303+ $tdsPreLoginResp = New-Object byte[] $payloadLength
296304 $read = 0
297305 while ($read -ne $tdsPreLoginResp.Length ) {
298306 $read += $targetStream.Read ($tdsPreLoginResp , $read , $tdsPreLoginResp.Length - $read )
@@ -337,21 +345,22 @@ Function Get-SqlServerTlsCertificate {
337345 # there is a note that TDS 7.1 or earlier (SQL Server 2000 or earlier)
338346 # should use the table response type (0x04) instead. As this is so old
339347 # I'm not going to implement that.
340- $streamToWrap = [ TdsTlsStream ]::new( $targetStream )
348+ $streamToWrap = New-Object - TypeName TdsTlsStream - ArgumentList $targetStream
341349 }
342350
343351 # Create the SslStream with a disable certificate verification callback.
344352 # This allows it to connect to a self signed or cert with different
345353 # hostname. The callback will also capture more information about the peer
346354 # Allows us to emit warnings if it was going to fail.
347355 $certState = @ {}
348- $sslStream = [System.Net.Security.SslStream ]::new( $streamToWrap , $false , {
349- param ($Sender , $Certificate , $Chain , $SslPolicyErrors )
356+ $sslValidationCallback = [System.Net.Security.RemoteCertificateValidationCallback ] {
357+ param ($Sender , $Certificate , $Chain , $SslPolicyErrors )
350358
351- $certState.Chain = $chain
352- $certState.SslPolicyErrors = $SslPolicyErrors
353- $true
354- })
359+ $certState.Chain = $Chain
360+ $certState.SslPolicyErrors = $SslPolicyErrors
361+ $true
362+ }
363+ $sslStream = New-Object - TypeName System.Net.Security.SslStream - ArgumentList @ ($streamToWrap , $false , $sslValidationCallback )
355364 Write-Verbose - Message " Starting TLS Handshake"
356365 $sslStream.AuthenticateAsClient ($ComputerName )
357366 Write-Verbose - Message " TLS result: $ ( $certState.SslPolicyErrors ) "
@@ -364,7 +373,7 @@ Function Get-SqlServerTlsCertificate {
364373 Write-Warning - Message $msg.TrimEnd ()
365374 }
366375
367- $cert = [ System.Security.Cryptography.X509Certificates.X509Certificate2 ]::new( $sslStream.RemoteCertificate )
376+ $cert = New-Object - TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 - ArgumentList $sslStream.RemoteCertificate
368377 Write-Verbose - Message " Found cert for $ ( $cert.Subject ) , Expires: $ ( $cert.NotAfter ) , SANs: $ ( $cert.DnsNameList -join " , " ) "
369378
370379 $cert
@@ -378,4 +387,4 @@ Function Get-SqlServerTlsCertificate {
378387 if ($targetStream ) { $targetStream.Dispose () }
379388 if ($socket ) { $socket.Dispose () }
380389 }
381- }
390+ }
0 commit comments