Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[.NET Core] Event Source traces revision - Part 3 #897

Merged
merged 13 commits into from
Feb 25, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Microsoft.Data.SqlClient.SNI
internal sealed class LocalDB
{
private static readonly LocalDB Instance = new LocalDB();
private const string s_className = nameof(LocalDB);

//HKEY_LOCAL_MACHINE
private const string LocalDBInstalledVersionRegistryKey = "SOFTWARE\\Microsoft\\Microsoft SQL Server Local DB\\Installed Versions\\";
Expand All @@ -26,7 +27,7 @@ internal sealed class LocalDB
private IntPtr _startInstanceHandle = IntPtr.Zero;

// Local Db api doc https://msdn.microsoft.com/en-us/library/hh217143.aspx
// HRESULT LocalDBStartInstance( [Input ] PCWSTR pInstanceName, [Input ] DWORD dwFlags,[Output] LPWSTR wszSqlConnection,[Input/Output] LPDWORD lpcchSqlConnection);
// HRESULT LocalDBStartInstance( [Input ] PCWSTR pInstanceName, [Input ] DWORD dwFlags,[Output] LPWSTR wszSqlConnection,[Input/Output] LPDWORD lpcchSqlConnection);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate int LocalDBStartInstance(
[In] [MarshalAs(UnmanagedType.LPWStr)] string localDBInstanceName,
Expand Down Expand Up @@ -64,26 +65,16 @@ internal static uint MapLocalDBErrorStateToCode(LocalDBErrorState errorState)
switch (errorState)
{
case LocalDBErrorState.NO_INSTALLATION:
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.MapLocalDBErrorStateToCode |SNI|ERR > LocalDB is not installed. Error State ={0}", errorState);
return SNICommon.LocalDBNoInstallation;

case LocalDBErrorState.INVALID_CONFIG:
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.MapLocalDBErrorStateToCode |SNI|ERR > Invalid configuration. Error State ={0}", errorState);
return SNICommon.LocalDBInvalidConfig;

case LocalDBErrorState.NO_SQLUSERINSTANCEDLL_PATH:
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.MapLocalDBErrorStateToCode |SNI|ERR > No SQL user instance path. Error State ={0}", errorState);
return SNICommon.LocalDBNoSqlUserInstanceDllPath;

case LocalDBErrorState.INVALID_SQLUSERINSTANCEDLL_PATH:
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.MapLocalDBErrorStateToCode |SNI|ERR > Invalid SQL user instance path. Error State ={0}", errorState);
return SNICommon.LocalDBInvalidSqlUserInstanceDllPath;

case LocalDBErrorState.NONE:
return 0;

default:
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.MapLocalDBErrorStateToCode |SNI|ERR > Invalid configuration. Error State ={0}", errorState);
return SNICommon.LocalDBInvalidConfig;
}
}
Expand Down Expand Up @@ -112,7 +103,7 @@ internal static string MapLocalDBErrorStateToErrorMessage(LocalDBErrorState erro
/// </summary>
private bool LoadUserInstanceDll()
{
long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI>");
long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);
try
{
// Check in a non thread-safe way if the handle is already set for performance.
Expand All @@ -137,15 +128,15 @@ private bool LoadUserInstanceDll()
if (dllPath == null)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, MapLocalDBErrorStateToCode(registryQueryErrorState), MapLocalDBErrorStateToErrorMessage(registryQueryErrorState));
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR >User instance DLL path is null.");
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "User instance DLL path is null.");
return false;
}

// In case the registry had an empty path for dll
if (string.IsNullOrWhiteSpace(dllPath))
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBInvalidSqlUserInstanceDllPath, Strings.SNI_ERROR_55);
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR > User instance DLL path is invalid. DLL path ={0}", dllPath);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "User instance DLL path is invalid. DLL path = {0}", dllPath);
return false;
}

Expand All @@ -155,7 +146,7 @@ private bool LoadUserInstanceDll()
if (libraryHandle.IsInvalid)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBFailedToLoadDll, Strings.SNI_ERROR_56);
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR > Library Handle is invalid. Could not load the dll.");
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Library Handle is invalid. Could not load the dll.");
libraryHandle.Dispose();
return false;
}
Expand All @@ -166,7 +157,7 @@ private bool LoadUserInstanceDll()
if (_startInstanceHandle == IntPtr.Zero)
{
SNILoadHandle.SingletonInstance.LastError = new SNIError(SNIProviders.INVALID_PROV, 0, SNICommon.LocalDBBadRuntime, Strings.SNI_ERROR_57);
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|ERR > Was not able to load the PROC from DLL. Bad Runtime.");
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Was not able to load the PROC from DLL. Bad Runtime.");
libraryHandle.Dispose();
return false;
}
Expand All @@ -183,7 +174,7 @@ private bool LoadUserInstanceDll()
}

_sqlUserInstanceLibraryHandle = libraryHandle;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.LoadUserInstanceDll |SNI|INFO > User Instance DLL was loaded successfully.");
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "User Instance DLL was loaded successfully.");
return true;
}
}
Expand All @@ -200,7 +191,7 @@ private bool LoadUserInstanceDll()
/// <returns></returns>
private string GetUserInstanceDllPath(out LocalDBErrorState errorState)
{
long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.LocalDB.Windows.GetUserInstanceDllPath |SNI|SCOPE|INFO > GetUserInstanceDllPath");
long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent(s_className);
try
{
string dllPath = null;
Expand All @@ -209,7 +200,7 @@ private string GetUserInstanceDllPath(out LocalDBErrorState errorState)
if (key == null)
{
errorState = LocalDBErrorState.NO_INSTALLATION;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.GetUserInstanceDllPath |SNI|ERR > not installed. Error state ={0}.", errorState);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "No installation found.");
return null;
}

Expand All @@ -224,7 +215,7 @@ private string GetUserInstanceDllPath(out LocalDBErrorState errorState)
if (!Version.TryParse(subKey, out currentKeyVersion))
{
errorState = LocalDBErrorState.INVALID_CONFIG;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.GetUserInstanceDllPath |SNI|ERR > Invalid Configuration. state ={0}.", errorState);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Invalid Configuration.");
return null;
}

Expand All @@ -238,7 +229,7 @@ private string GetUserInstanceDllPath(out LocalDBErrorState errorState)
if (latestVersion.Equals(zeroVersion))
{
errorState = LocalDBErrorState.INVALID_CONFIG;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.GetUserInstanceDllPath |SNI|ERR > Invalid Configuration. state ={0}.", errorState);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Invalid Configuration.");
return null;
}

Expand All @@ -251,7 +242,7 @@ private string GetUserInstanceDllPath(out LocalDBErrorState errorState)
if (instanceAPIPathRegistryObject == null)
{
errorState = LocalDBErrorState.NO_SQLUSERINSTANCEDLL_PATH;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.GetUserInstanceDllPath |SNI|ERR > No SQL user instance DLL. Instance API Path Registry Object Error. state ={0}.", errorState);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "No SQL user instance DLL. Instance API Path Registry Object Error.");
return null;
}

Expand All @@ -260,7 +251,7 @@ private string GetUserInstanceDllPath(out LocalDBErrorState errorState)
if (valueKind != RegistryValueKind.String)
{
errorState = LocalDBErrorState.INVALID_SQLUSERINSTANCEDLL_PATH;
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.LocalDB.Windows.GetUserInstanceDllPath |SNI|ERR > No SQL user instance DLL. state ={0}. Registry value kind error.", errorState);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Invalid SQL user instance DLL path. Registry value kind mismatch.");
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ internal enum SNISMUXFlags

internal class SNICommon
{
private const string s_className = nameof(SNICommon);

// Each error number maps to SNI_ERROR_* in String.resx
internal const int ConnTerminatedError = 2;
internal const int InvalidParameterError = 5;
Expand All @@ -126,47 +128,49 @@ internal class SNICommon
internal const int LocalDBBadRuntime = 57;

/// <summary>
/// Validate server certificate callback for SSL
/// We only validate Server name in Certificate to match with "targetServerName".
/// Certificate validation and chain trust validations are done by SSLStream class [System.Net.Security.SecureChannel.VerifyRemoteCertificate method]
/// This method is called as a result of callback for SSL Stream Certificate validation.
/// </summary>
/// <param name="targetServerName">Server that client is expecting to connect to</param>
/// <param name="sender">Sender object</param>
/// <param name="cert">X.509 certificate</param>
/// <param name="chain">X.509 chain</param>
/// <param name="policyErrors">Policy errors</param>
/// <returns>True if certificate is valid</returns>
internal static bool ValidateSslServerCertificate(string targetServerName, object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
internal static bool ValidateSslServerCertificate(string targetServerName, X509Certificate cert, SslPolicyErrors policyErrors)
{
long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("<sc.SNI.SNICommon.ValidateSslServerCertificate |SNI|SCOPE|INFO >");
long scopeID = SqlClientEventSource.Log.TrySNIScopeEnterEvent("SNICommon.ValidateSslServerCertificate | SNI | SCOPE | INFO | Entering Scope {0} ");
try
{
if (policyErrors == SslPolicyErrors.None)
{
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNICommon.ValidateSslServerCertificate |SNI|INFO > SSL Server certificate validated.");
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "targetServerName {0}, SSL Server certificate not validated as PolicyErrors set to None.", args0: targetServerName);
return true;
}

if ((policyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) != 0)
{
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNICommon.ValidateSslServerCertificate |SNI|ERR > SSL Remote certificate name mismatched.");
string certServerName = cert.Subject.Substring(cert.Subject.IndexOf('=') + 1);

// Verify that target server name matches subject in the certificate
if (targetServerName.Length > certServerName.Length)
{
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "targetServerName {0}, Target Server name is of greater length than Subject in Certificate.", args0: targetServerName);
return false;
}
else if (targetServerName.Length == certServerName.Length)
{
// Both strings have the same length, so targetServerName must be a FQDN
if (!targetServerName.Equals(certServerName, StringComparison.OrdinalIgnoreCase))
{
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "targetServerName {0}, Target Server name does not match Subject in Certificate.", args0: targetServerName);
return false;
}
}
else
{
if (string.Compare(targetServerName, 0, certServerName, 0, targetServerName.Length, StringComparison.OrdinalIgnoreCase) != 0)
{
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "targetServerName {0}, Target Server name does not match Subject in Certificate.", args0: targetServerName);
return false;
}

Expand All @@ -176,15 +180,18 @@ internal static bool ValidateSslServerCertificate(string targetServerName, objec
// (Names have different lengths, so the target server can't be a FQDN.)
if (certServerName[targetServerName.Length] != '.')
{
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "targetServerName {0}, Target Server name does not match Subject in Certificate.", args0: targetServerName);
return false;
}
}
}
else
{
// Fail all other SslPolicy cases besides RemoteCertificateNameMismatch
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "targetServerName {0}, SslPolicyError {1}, SSL Policy invalidated certificate.", args0: targetServerName, args1: policyErrors);
return false;
}
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.INFO, "targetServerName {0}, Client certificate validated successfully.", args0: targetServerName);
return true;
}
finally
Expand All @@ -203,7 +210,7 @@ internal static bool ValidateSslServerCertificate(string targetServerName, objec
/// <returns></returns>
internal static uint ReportSNIError(SNIProviders provider, uint nativeError, uint sniError, string errorMessage)
{
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNICommon. ReportSNIError |SNI|ERR > Provider ={0}, native Error ={1}, SNI Error ={2}, Error Message ={3}", provider, nativeError, sniError, errorMessage);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Provider = {0}, native Error = {1}, SNI Error = {2}, Error Message = {3}", args0: provider, args1: nativeError, args2: sniError, args3: errorMessage);
return ReportSNIError(new SNIError(provider, nativeError, sniError, errorMessage));
}

Expand All @@ -216,7 +223,7 @@ internal static uint ReportSNIError(SNIProviders provider, uint nativeError, uin
/// <returns></returns>
internal static uint ReportSNIError(SNIProviders provider, uint sniError, Exception sniException)
{
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNICommon. ReportSNIError |SNI|ERR > Provider ={0}, SNI Error ={1}, Exception ={2}", provider, sniError, sniException.Message);
SqlClientEventSource.Log.TrySNITraceEvent(s_className, EventType.ERR, "Provider = {0}, SNI Error = {1}, Exception = {2}", args0: provider, args1: sniError, args2: sniException?.Message);
return ReportSNIError(new SNIError(provider, sniError, sniException));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public SNIError LastError

set
{
SqlClientEventSource.Log.TrySNITraceEvent("<sc.SNI.SNILoadHandle.LastError |SNI|INFO|SETTER > Last Error Value = {0}", value);
_lastError.Value = value;
}
}
Expand Down
Loading