1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Diagnostics; 6 using System.Data.SqlClient.SNI; 7 8 namespace System.Data.SqlClient 9 { 10 internal sealed partial class TdsParser 11 { 12 private static volatile bool s_fSSPILoaded = false; // bool to indicate whether library has been loaded 13 PostReadAsyncForMars()14 internal void PostReadAsyncForMars() 15 { 16 if (TdsParserStateObjectFactory.UseManagedSNI) 17 return; 18 19 // HACK HACK HACK - for Async only 20 // Have to post read to initialize MARS - will get callback on this when connection goes 21 // down or is closed. 22 23 IntPtr temp = IntPtr.Zero; 24 uint error = TdsEnums.SNI_SUCCESS; 25 26 _pMarsPhysicalConObj.IncrementPendingCallbacks(); 27 object handle = _pMarsPhysicalConObj.SessionHandle; 28 temp = (IntPtr)_pMarsPhysicalConObj.ReadAsync(out error, ref handle); 29 30 if (temp != IntPtr.Zero) 31 { 32 // Be sure to release packet, otherwise it will be leaked by native. 33 _pMarsPhysicalConObj.ReleasePacket(temp); 34 } 35 36 Debug.Assert(IntPtr.Zero == temp, "unexpected syncReadPacket without corresponding SNIPacketRelease"); 37 if (TdsEnums.SNI_SUCCESS_IO_PENDING != error) 38 { 39 Debug.Assert(TdsEnums.SNI_SUCCESS != error, "Unexpected successful read async on physical connection before enabling MARS!"); 40 _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj)); 41 ThrowExceptionAndWarning(_physicalStateObj); 42 } 43 } 44 LoadSSPILibrary()45 private void LoadSSPILibrary() 46 { 47 if (TdsParserStateObjectFactory.UseManagedSNI) 48 return; 49 // Outer check so we don't acquire lock once it's loaded. 50 if (!s_fSSPILoaded) 51 { 52 lock (s_tdsParserLock) 53 { 54 // re-check inside lock 55 if (!s_fSSPILoaded) 56 { 57 // use local for ref param to defer setting s_maxSSPILength until we know the call succeeded. 58 UInt32 maxLength = 0; 59 60 if (0 != SNINativeMethodWrapper.SNISecInitPackage(ref maxLength)) 61 SSPIError(SQLMessage.SSPIInitializeError(), TdsEnums.INIT_SSPI_PACKAGE); 62 63 s_maxSSPILength = maxLength; 64 s_fSSPILoaded = true; 65 } 66 } 67 } 68 69 if (s_maxSSPILength > Int32.MaxValue) 70 { 71 throw SQL.InvalidSSPIPacketSize(); // SqlBu 332503 72 } 73 } 74 WaitForSSLHandShakeToComplete(ref uint error)75 private void WaitForSSLHandShakeToComplete(ref uint error) 76 { 77 if (TdsParserStateObjectFactory.UseManagedSNI) 78 return; 79 // in the case where an async connection is made, encryption is used and Windows Authentication is used, 80 // wait for SSL handshake to complete, so that the SSL context is fully negotiated before we try to use its 81 // Channel Bindings as part of the Windows Authentication context build (SSL handshake must complete 82 // before calling SNISecGenClientContext). 83 error = _physicalStateObj.WaitForSSLHandShakeToComplete(); 84 if (error != TdsEnums.SNI_SUCCESS) 85 { 86 _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj)); 87 ThrowExceptionAndWarning(_physicalStateObj); 88 } 89 } 90 GetSniErrorDetails()91 private SNIErrorDetails GetSniErrorDetails() 92 { 93 SNIErrorDetails details = new SNIErrorDetails(); 94 95 if (TdsParserStateObjectFactory.UseManagedSNI) 96 { 97 SNIError sniError = SNIProxy.Singleton.GetLastError(); 98 details.sniErrorNumber = sniError.sniError; 99 details.errorMessage = sniError.errorMessage; 100 details.nativeError = sniError.nativeError; 101 details.provider = (int)sniError.provider; 102 details.lineNumber = sniError.lineNumber; 103 details.function = sniError.function; 104 details.exception = sniError.exception; 105 } 106 else 107 { 108 SNINativeMethodWrapper.SNI_Error sniError; 109 SNINativeMethodWrapper.SNIGetLastError(out sniError); 110 details.sniErrorNumber = sniError.sniError; 111 details.errorMessage = sniError.errorMessage; 112 details.nativeError = sniError.nativeError; 113 details.provider = (int)sniError.provider; 114 details.lineNumber = sniError.lineNumber; 115 details.function = sniError.function; 116 } 117 return details; 118 } 119 120 } // tdsparser 121 }//namespace