Merge branch 'master' of https://github.com/dotnet/corefx into utf8-feature-extension
authorKeerat Singh <v-kesin@microsoft.com>
Tue, 3 Jul 2018 21:28:48 +0000 (14:28 -0700)
committerKeerat Singh <v-kesin@microsoft.com>
Tue, 3 Jul 2018 21:28:48 +0000 (14:28 -0700)
Commit migrated from https://github.com/dotnet/corefx/commit/3d5e4abe5f1cb5166919e2d7feba67e4e52b64e3

1  2 
src/libraries/System.Data.SqlClient/src/System/Data/SqlClient/SqlInternalConnectionTds.cs
src/libraries/System.Data.SqlClient/src/System/Data/SqlClient/TdsEnums.cs
src/libraries/System.Data.SqlClient/src/System/Data/SqlClient/TdsParser.cs

@@@ -1125,9 -1144,22 +1144,22 @@@ namespace System.Data.SqlClien
                  _sessionRecoveryRequested = true;
              }
  
 -            // The GLOBALTRANSACTIONS feature is implicitly requested
 -            requestedFeatures |= TdsEnums.FeatureExtension.GlobalTransactions;
+             if (_accessTokenInBytes != null)
+             {
+                 requestedFeatures |= TdsEnums.FeatureExtension.FedAuth;
+                 _fedAuthFeatureExtensionData = new FederatedAuthenticationFeatureExtensionData
+                 {
+                     libraryType = TdsEnums.FedAuthLibrary.SecurityToken,
+                     fedAuthRequiredPreLoginResponse = _fedAuthRequired,
+                     accessToken = _accessTokenInBytes
+                 };
+                 // No need any further info from the server for token based authentication. So set _federatedAuthenticationRequested to true
+                 _federatedAuthenticationRequested = true;
+             }
-             requestedFeatures |= TdsEnums.FeatureExtension.GlobalTransactions | TdsEnums.FeatureExtension.UTF8Support ;
-             _parser.TdsLogin(login, requestedFeatures, _recoverySessionData);
 +            // The GLOBALTRANSACTIONS and UTF8 support features are implicitly requested
++            requestedFeatures |= TdsEnums.FeatureExtension.GlobalTransactions | TdsEnums.FeatureExtension.UTF8Support;
+             _parser.TdsLogin(login, requestedFeatures, _recoverySessionData, _fedAuthFeatureExtensionData);
          }
  
          private void LoginFailure()
                          }
                          break;
                      }
+                 case TdsEnums.FEATUREEXT_FEDAUTH:
+                     {
+                         if (!_federatedAuthenticationRequested)
+                         {
+                             throw SQL.ParsingErrorFeatureId(ParsingErrorState.UnrequestedFeatureAckReceived, featureId);
+                         }
+                         Debug.Assert(_fedAuthFeatureExtensionData != null, "_fedAuthFeatureExtensionData must not be null when _federatedAuthenticatonRequested == true");
+                         switch (_fedAuthFeatureExtensionData.Value.libraryType)
+                         {
+                             case TdsEnums.FedAuthLibrary.SecurityToken:
+                                 // The server shouldn't have sent any additional data with the ack (like a nonce)
+                                 if (data.Length != 0)
+                                 {
+                                     throw SQL.ParsingError(ParsingErrorState.FedAuthFeatureAckContainsExtraData);
+                                 }
+                                 break;
+                             default:
+                                 Debug.Assert(false, "Unknown _fedAuthLibrary type");
+                                 throw SQL.ParsingErrorLibraryType(ParsingErrorState.FedAuthFeatureAckUnknownLibraryType, (int)_fedAuthFeatureExtensionData.Value.libraryType);
+                         }
+                         _federatedAuthenticationAcknowledged = true;
+                         break;
+                     }
  
 +                case TdsEnums.FEATUREEXT_UTF8SUPPORT:
 +                    {
 +                        if (data.Length < 1)
 +                        {
 +                            throw SQL.ParsingError();
 +                        }
 +                        break;
 +                    }
                  default:
                      {
                          // Unknown feature ack 
@@@ -201,19 -201,31 +201,35 @@@ namespace System.Data.SqlClien
          // Feature Extension
          public const byte FEATUREEXT_TERMINATOR = 0xFF;
          public const byte FEATUREEXT_SRECOVERY = 0x01;
 -        public const byte FEATUREEXT_GLOBALTRANSACTIONS = 0x05;
+         public const byte FEATUREEXT_FEDAUTH = 0x02;
 +        public const byte FEATUREEXT_GLOBALTRANSACTIONS = 0x05;
 +        public const byte FEATUREEXT_UTF8SUPPORT = 0x0A;
 +
          [Flags]
          public enum FeatureExtension : uint
          {
              None = 0,
              SessionRecovery = 1,
 -            GlobalTransactions = 8,
+             FedAuth = 2,
 +            GlobalTransactions = 16,
 +            UTF8Support = 512,
          }
 +        public const uint UTF8_IN_TDSCOLLATION = 0x4000000;
  
+         public const byte FEDAUTHLIB_LIVEID = 0X00;
+         public const byte FEDAUTHLIB_SECURITYTOKEN = 0x01;
+         public const byte FEDAUTHLIB_ADAL = 0x02;
+         public const byte FEDAUTHLIB_RESERVED = 0X7F;
+         public enum FedAuthLibrary : byte
+         {
+             LiveId = FEDAUTHLIB_LIVEID,
+             SecurityToken = FEDAUTHLIB_SECURITYTOKEN,
+             ADAL = FEDAUTHLIB_ADAL, // For later support
+             Default = FEDAUTHLIB_RESERVED
+         }
          //    Loginrec defines
          public const byte MAX_LOG_NAME = 30;              // TDS 4.2 login rec max name length
          public const byte MAX_PROG_NAME = 10;              // max length of loginrec program name
@@@ -5999,21 -6067,8 +6090,21 @@@ namespace System.Data.SqlClien
  
              return len;
          }
 +        internal int WriteUTF8SupportFeatureRequest(bool write /* if false just calculates the length */)
 +        {
 +            int len = 5; // 1byte = featureID, 4bytes = featureData length, sizeof(DWORD)
 +
 +            if (write)
 +            {
 +                // Write Feature ID
 +                _physicalStateObj.WriteByte(TdsEnums.FEATUREEXT_UTF8SUPPORT);
 +                WriteInt(0, _physicalStateObj); // we don't send any data
 +            }
 +
 +            return len;
 +        }
  
-         internal void TdsLogin(SqlLogin rec, TdsEnums.FeatureExtension requestedFeatures, SessionData recoverySessionData)
+         internal void TdsLogin(SqlLogin rec, TdsEnums.FeatureExtension requestedFeatures, SessionData recoverySessionData, FederatedAuthenticationFeatureExtensionData? fedAuthFeatureExtensionData)
          {
              _physicalStateObj.SetTimeoutSeconds(rec.timeout);
  
                  {
                      length += WriteSessionRecoveryFeatureRequest(recoverySessionData, false);
                  }
++                if ((requestedFeatures & TdsEnums.FeatureExtension.FedAuth) != 0)
++                {
++                    Debug.Assert(fedAuthFeatureExtensionData != null, "fedAuthFeatureExtensionData should not null.");
++                    length += WriteFedAuthFeatureRequest(fedAuthFeatureExtensionData.Value, write: false);
++                }
                  if ((requestedFeatures & TdsEnums.FeatureExtension.GlobalTransactions) != 0)
                  {
                      length += WriteGlobalTransactionsFeatureRequest(false);
                  }
 -                if ((requestedFeatures & TdsEnums.FeatureExtension.FedAuth) != 0)
 +                if ((requestedFeatures & TdsEnums.FeatureExtension.UTF8Support) != 0)
                  {
 -                    Debug.Assert(fedAuthFeatureExtensionData != null, "fedAuthFeatureExtensionData should not null.");
 -                    length += WriteFedAuthFeatureRequest(fedAuthFeatureExtensionData.Value, write: false);
 +                    length += WriteUTF8SupportFeatureRequest(false);
                  }
++
                  length++; // for terminator
              }
  
                      {
                          length += WriteSessionRecoveryFeatureRequest(recoverySessionData, true);
                      }
++                    if ((requestedFeatures & TdsEnums.FeatureExtension.FedAuth) != 0)
++                    {
++                        Debug.Assert(fedAuthFeatureExtensionData != null, "fedAuthFeatureExtensionData should not null.");
++                        WriteFedAuthFeatureRequest(fedAuthFeatureExtensionData.Value, write: true);
++                    }
                      if ((requestedFeatures & TdsEnums.FeatureExtension.GlobalTransactions) != 0)
                      {
                          WriteGlobalTransactionsFeatureRequest(true);
                      }
 -                    if ((requestedFeatures & TdsEnums.FeatureExtension.FedAuth) != 0)
 +                    if ((requestedFeatures & TdsEnums.FeatureExtension.UTF8Support) != 0)
                      {
 -                        Debug.Assert(fedAuthFeatureExtensionData != null, "fedAuthFeatureExtensionData should not null.");
 -                        WriteFedAuthFeatureRequest(fedAuthFeatureExtensionData.Value, write: true);
 -                    };
 +                        WriteUTF8SupportFeatureRequest(true);
 +                    }
++
                      _physicalStateObj.WriteByte(0xFF); // terminator
                  }
              }