Skip to content

ArgumentException: The specified value is not valid in the 'NativeProtocols' enumeration. #3120

Closed

Description

@austinw-fineart

Describe the bug

SqlClient throws an exception when opening the connection.

System.ArgumentException
  HResult=0x80070057
  Message=The specified value is not valid in the 'NativeProtocols' enumeration.
Parameter name: NativeProtocols
  Source=Microsoft.Data.SqlClient
  StackTrace:
   at Microsoft.Data.SqlClient.SslProtocolsHelper.ToFriendlyName(SslProtocols protocol) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserHelperClasses.cs:line 809
   at Microsoft.Data.SqlClient.SslProtocolsHelper.GetProtocolWarning(SslProtocols protocol) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserHelperClasses.cs:line 837
   at Microsoft.Data.SqlClient.TdsParser.EnableSsl(UInt32 info, SqlConnectionEncryptOption encrypt, Boolean integratedSecurity, String serverCertificate) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs:line 1250
   at Microsoft.Data.SqlClient.TdsParser.ConsumePreLoginHandshake(SqlAuthenticationMethod authType, SqlConnectionEncryptOption encrypt, Boolean trustServerCert, Boolean integratedSecurity, Boolean& marsCapable, Boolean& fedAuthRequired, Boolean tlsFirst, String serverCertificateFilename) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs:line 1513
   at Microsoft.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, TimeoutTimer timeout, SqlConnectionString connectionOptions, Boolean withFailover, Boolean isFirstTransparentAttempt, Boolean disableTnir) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs:line 723
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, TimeoutTimer timeout, Boolean withFailover, Boolean isFirstTransparentAttempt, Boolean disableTnir) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs:line 2309
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs:line 1863
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs:line 1729
   at Microsoft.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken, Boolean applyTransientFaultHandling, Func`3 accessTokenCallback) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs:line 534
   at Microsoft.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionFactory.cs:line 147
   at Microsoft.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs:line 153
   at Microsoft.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs:line 906
   at Microsoft.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs:line 1975
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs:line 1369
   at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionPool.cs:line 1261
   at Microsoft.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionFactory.cs:line 306
   at Microsoft.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionInternal.cs:line 972
   at Microsoft.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) in /_/src/Microsoft.Data.SqlClient/src/Microsoft/Data/ProviderBase/DbConnectionClosed.cs:line 43
   at Microsoft.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs:line 2160
   at Microsoft.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry, SqlConnectionOverrides overrides) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs:line 2129
   at Microsoft.Data.SqlClient.SqlConnection.Open(SqlConnectionOverrides overrides) in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs:line 1674
   at Microsoft.Data.SqlClient.SqlConnection.Open() in /_/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs:line 1644

Stepping into the code, the value of protocol is 128 which indeed doesn't match any of the SslProtocols

To reproduce

using var connection = new SqlConnection("data source=10.1.1.69;encrypt=optional;initial catalog=TEST");
connection.Open();

Expected behavior

It just works.

Further technical details

Microsoft.Data.SqlClient version: 6.0.0
.NET target: .NET Framework 4.8
SQL Server version: SQL Server 2012
Operating system: Windows Server 2012

Additional context
Microsoft.EntityFramework.SqlServer version: 6.5.1

Activity

  1. ErikEJ commented on Jan 17, 2025

    @ErikEJ
    Contributor

    Wonder if support for SQL Server 2012 is broken - have you tried with a newer server version?

  2. cheenamalhotra commented on Jan 17, 2025

    @cheenamalhotra
    Member

    Can you also check if this is a recent issue or also occurs with MDS 5.2.2?

  3. austinw-fineart commented on Jan 17, 2025

    @austinw-fineart
    Author

    No such problem on SQL Server 2022. No idea on other versions. A production server was running 2012 which is why I had to rollback to 5.2.2, no issues on that version. I went through the changelog but nothing indicates such a change. I looked through the file history in question and I believe #2376 is what broke it. The old code has a NativeProtocols enum and my 128 would have represented SP_PROT_TLS1_0_CLIENT. The new code only uses SslProtocols which appears to combine flags instead so it doesn't get matched.

    // protocol versions from native sni
    [Flags]
    private enum NativeProtocols
    {
    SP_PROT_SSL2_SERVER = 0x00000004,
    SP_PROT_SSL2_CLIENT = 0x00000008,
    SP_PROT_SSL3_SERVER = 0x00000010,
    SP_PROT_SSL3_CLIENT = 0x00000020,
    SP_PROT_TLS1_0_SERVER = 0x00000040,
    SP_PROT_TLS1_0_CLIENT = 0x00000080,
    SP_PROT_TLS1_1_SERVER = 0x00000100,
    SP_PROT_TLS1_1_CLIENT = 0x00000200,
    SP_PROT_TLS1_2_SERVER = 0x00000400,
    SP_PROT_TLS1_2_CLIENT = 0x00000800,
    SP_PROT_TLS1_3_SERVER = 0x00001000,
    SP_PROT_TLS1_3_CLIENT = 0x00002000,
    SP_PROT_SSL2 = SP_PROT_SSL2_SERVER | SP_PROT_SSL2_CLIENT,
    SP_PROT_SSL3 = SP_PROT_SSL3_SERVER | SP_PROT_SSL3_CLIENT,
    SP_PROT_TLS1_0 = SP_PROT_TLS1_0_SERVER | SP_PROT_TLS1_0_CLIENT,
    SP_PROT_TLS1_1 = SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_CLIENT,
    SP_PROT_TLS1_2 = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_CLIENT,
    SP_PROT_TLS1_3 = SP_PROT_TLS1_3_SERVER | SP_PROT_TLS1_3_CLIENT,
    SP_PROT_NONE = 0x0
    }
    private static string ToFriendlyName(this NativeProtocols protocol)
    {
    string name;
    if (protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_3_CLIENT) || protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_3_SERVER))
    {
    name = "TLS 1.3";
    }
    else if (protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_2_CLIENT) || protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_2_SERVER))
    {
    name = "TLS 1.2";
    }
    else if (protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_1_CLIENT) || protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_1_SERVER))
    {
    name = "TLS 1.1";
    }
    else if (protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_0_CLIENT) || protocol.HasFlag(NativeProtocols.SP_PROT_TLS1_0_SERVER))
    {
    name = "TLS 1.0";
    }
    else if (protocol.HasFlag(NativeProtocols.SP_PROT_SSL3_CLIENT) || protocol.HasFlag(NativeProtocols.SP_PROT_SSL3_SERVER))
    {
    name = "SSL 3.0";
    }
    else if (protocol.HasFlag(NativeProtocols.SP_PROT_SSL2_CLIENT) || protocol.HasFlag(NativeProtocols.SP_PROT_SSL2_SERVER))
    {
    name = "SSL 2.0";
    }
    else if (protocol.HasFlag(NativeProtocols.SP_PROT_NONE))
    {
    name = "None";
    }
    else
    {
    throw new ArgumentException(StringsHelper.GetString(StringsHelper.net_invalid_enum, nameof(NativeProtocols)), nameof(NativeProtocols));
    }
    return name;
    }

    private static string ToFriendlyName(this SslProtocols protocol)
    {
    string name;
    /* The SslProtocols.Tls13 is supported by netcoreapp3.1 and later
    * This driver does not support this version yet!
    if ((protocol & SslProtocols.Tls13) == SslProtocols.Tls13)
    {
    name = "TLS 1.3";
    }*/
    #pragma warning disable CA5398 // Avoid hardcoded SslProtocols values
    if ((protocol & SslProtocols.Tls12) == SslProtocols.Tls12)
    {
    name = "TLS 1.2";
    }
    #if NET
    #pragma warning disable SYSLIB0039 // Type or member is obsolete: TLS 1.0 & 1.1 are deprecated
    #endif
    else if ((protocol & SslProtocols.Tls11) == SslProtocols.Tls11)
    {
    name = "TLS 1.1";
    }
    else if ((protocol & SslProtocols.Tls) == SslProtocols.Tls)
    {
    name = "TLS 1.0";
    }
    #if NET
    #pragma warning restore SYSLIB0039 // Type or member is obsolete: SSL and TLS 1.0 & 1.1 is deprecated
    #endif
    #pragma warning disable CS0618 // Type or member is obsolete: SSL is deprecated
    else if ((protocol & SslProtocols.Ssl3) == SslProtocols.Ssl3)
    {
    name = "SSL 3.0";
    }
    else if ((protocol & SslProtocols.Ssl2) == SslProtocols.Ssl2)
    #pragma warning restore CS0618 // Type or member is obsolete: SSL and TLS 1.0 & 1.1 is deprecated
    {
    name = "SSL 2.0";
    }
    #pragma warning restore CA5398 // Avoid hardcoded SslProtocols values
    else
    {
    #if !NETFRAMEWORK
    name = protocol.ToString();
    #else
    throw new ArgumentException(StringsHelper.GetString(StringsHelper.net_invalid_enum, "NativeProtocols"), "NativeProtocols");
    #endif
    }
    return name;
    }

  4. edwardneal commented on Jan 17, 2025

    @edwardneal
    Contributor

    Thanks for the pointer - you're correct, #2376 introduced the problem. This only occurs when using .NET Framework to connect to a SQL Server instance using an encryption protocol other than TLS 1.2. Enabling TLS 1.2 resolves this - the most recent CU for SQL Server 2008 upwards introduces support.

    This only occurs on .NET Framework because it looks like the SSL protocol values are reported differently between the native and the managed SNIs, and I didn't pick up on that difference. This should probably have been tested by the CertificateTestWithTdsServer class, but the TDS server we use for testing always uses TLS 1.2. Sorry for the gap here.

    I'll submit a PR shortly which fixes and tests this.

  5. added this to the 6.0.0 milestone on Jan 18, 2025
  6. edwardneal commented on Jan 24, 2025

    @edwardneal
    Contributor

    @austinw-fineart SqlClient 6.0.1 was released earlier today, and it should contain the bugfix. Can you re-test with this version please?

  7. cheenamalhotra commented on Jan 26, 2025

    @cheenamalhotra
    Member

    Closing as issue has been addressed in 6.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Regression 💥Issues that are regressions introduced from earlier PRs.

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions