Skip to content

Commit

Permalink
Merged PR 4072: [2.1.7]
Browse files Browse the repository at this point in the history
  • Loading branch information
David-Engel committed Oct 18, 2023
1 parent acfdeca commit 2463cb8
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake(bool encrypt, bool trus
int payloadOffset = 0;
int payloadLength = 0;
int option = payload[offset++];
bool serverSupportsEncryption = false;

while (option != (byte)PreLoginOptions.LASTOPT)
{
Expand Down Expand Up @@ -900,18 +901,11 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake(bool encrypt, bool trus
LOGIN
} */

// Any response other than NOT_SUP means the server supports encryption.
serverSupportsEncryption = serverOption != EncryptionOptions.NOT_SUP;

switch (_encryptionOption)
{
case (EncryptionOptions.ON):
if (serverOption == EncryptionOptions.NOT_SUP)
{
_physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0));
_physicalStateObj.Dispose();
ThrowExceptionAndWarning(_physicalStateObj);
}

break;

case (EncryptionOptions.OFF):
if (serverOption == EncryptionOptions.OFF)
{
Expand All @@ -929,6 +923,7 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake(bool encrypt, bool trus
case (EncryptionOptions.NOT_SUP):
if (serverOption == EncryptionOptions.REQ)
{
// Server requires encryption, but client does not support it.
_physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByClient(), "", 0));
_physicalStateObj.Dispose();
ThrowExceptionAndWarning(_physicalStateObj);
Expand All @@ -937,49 +932,15 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake(bool encrypt, bool trus
break;

default:
Debug.Fail("Invalid client encryption option detected");
break;
}

if (_encryptionOption == EncryptionOptions.ON ||
_encryptionOption == EncryptionOptions.LOGIN)
{
uint error = 0;

// Validate Certificate if Trust Server Certificate=false and Encryption forced (EncryptionOptions.ON) from Server.
bool shouldValidateServerCert = (_encryptionOption == EncryptionOptions.ON && !trustServerCert) || (_connHandler._accessTokenInBytes != null && !trustServerCert);
uint info = (shouldValidateServerCert ? TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE : 0)
| (isYukonOrLater ? TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE : 0);

if (encrypt && !integratedSecurity)
{
// optimization: in case of SQL Authentication and encryption, set SNI_SSL_IGNORE_CHANNEL_BINDINGS to let SNI
// know that it does not need to allocate/retrieve the Channel Bindings from the SSL context.
// This applies to Native SNI
info |= TdsEnums.SNI_SSL_IGNORE_CHANNEL_BINDINGS;
}

error = _physicalStateObj.EnableSsl(ref info);

if (error != TdsEnums.SNI_SUCCESS)
{
_physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
ThrowExceptionAndWarning(_physicalStateObj);
}

int protocolVersion = 0;
WaitForSSLHandShakeToComplete(ref error, ref protocolVersion);

SslProtocols protocol = (SslProtocols)protocolVersion;
string warningMessage = protocol.GetProtocolWarning();
if (!string.IsNullOrEmpty(warningMessage))
{
// This logs console warning of insecure protocol in use.
_logger.LogWarning(_typeName, MethodBase.GetCurrentMethod().Name, warningMessage);
}
// Any other client option needs encryption
if (serverOption == EncryptionOptions.NOT_SUP)
{
_physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0));
_physicalStateObj.Dispose();
ThrowExceptionAndWarning(_physicalStateObj);
}

// create a new packet encryption changes the internal packet size
_physicalStateObj.ClearAllWritePackets();
break;
}

break;
Expand Down Expand Up @@ -1062,6 +1023,54 @@ private PreLoginHandshakeStatus ConsumePreLoginHandshake(bool encrypt, bool trus
}
}

if (_encryptionOption == EncryptionOptions.ON ||
_encryptionOption == EncryptionOptions.LOGIN)
{
if (!serverSupportsEncryption)
{
_physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0));
_physicalStateObj.Dispose();
ThrowExceptionAndWarning(_physicalStateObj);
}

uint error = 0;

// Validate Certificate if Trust Server Certificate=false and Encryption forced (EncryptionOptions.ON) from Server.
bool shouldValidateServerCert = (_encryptionOption == EncryptionOptions.ON && !trustServerCert) || (_connHandler._accessTokenInBytes != null && !trustServerCert);
uint info = (shouldValidateServerCert ? TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE : 0)
| (isYukonOrLater ? TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE : 0);

if (encrypt && !integratedSecurity)
{
// optimization: in case of SQL Authentication and encryption, set SNI_SSL_IGNORE_CHANNEL_BINDINGS to let SNI
// know that it does not need to allocate/retrieve the Channel Bindings from the SSL context.
// This applies to Native SNI
info |= TdsEnums.SNI_SSL_IGNORE_CHANNEL_BINDINGS;
}

error = _physicalStateObj.EnableSsl(ref info);

if (error != TdsEnums.SNI_SUCCESS)
{
_physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
ThrowExceptionAndWarning(_physicalStateObj);
}

int protocolVersion = 0;
WaitForSSLHandShakeToComplete(ref error, ref protocolVersion);

SslProtocols protocol = (SslProtocols)protocolVersion;
string warningMessage = protocol.GetProtocolWarning();
if (!string.IsNullOrEmpty(warningMessage))
{
// This logs console warning of insecure protocol in use.
_logger.LogWarning(_typeName, MethodBase.GetCurrentMethod().Name, warningMessage);
}

// create a new packet encryption changes the internal packet size
_physicalStateObj.ClearAllWritePackets();
}

return PreLoginHandshakeStatus.Successful;
}

Expand Down
Loading

0 comments on commit 2463cb8

Please sign in to comment.