internal void Connect(ServerInfo serverInfo,
                              SqlInternalConnectionTds connHandler,
                              bool ignoreSniOpenTimeout,
                              long timerExpire,
                              bool encrypt,
                              bool trustServerCert,
                              bool integratedSecurity,
                              bool withFailover,
                              bool isFirstTransparentAttempt,
                              SqlAuthenticationMethod authType) {
            if (_state != TdsParserState.Closed) {
                Debug.Assert(false, "TdsParser.Connect called on non-closed connection!");
                return;
            }

            _connHandler = connHandler;
            _loginWithFailover = withFailover;

            UInt32 sniStatus = SNILoadHandle.SingletonInstance.SNIStatus;
            if (sniStatus != TdsEnums.SNI_SUCCESS) {
                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
                _physicalStateObj.Dispose();
                ThrowExceptionAndWarning(_physicalStateObj);
                Debug.Assert(false, "SNI returned status != success, but no error thrown?");
            }

            //Create LocalDB instance if necessary             
            if (connHandler.ConnectionOptions.LocalDBInstance != null)
                LocalDBAPI.CreateLocalDBInstance(connHandler.ConnectionOptions.LocalDBInstance);

            if (integratedSecurity || authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated) {
                LoadSSPILibrary();
                // now allocate proper length of buffer
                _sniSpnBuffer = new byte[SNINativeMethodWrapper.SniMaxComposedSpnLength];
                Bid.Trace("<sc.TdsParser.Connect|SEC> SSPI or Active Directory Authentication Library for SQL Server based integrated authentication\n");
            }
            else {
                _sniSpnBuffer = null;
                if (authType == SqlAuthenticationMethod.ActiveDirectoryPassword) {
                    Bid.Trace("<sc.TdsParser.Connect|SEC> Active Directory Password authentication\n");
                }
                else if (authType == SqlAuthenticationMethod.SqlPassword) {
                    Bid.Trace("<sc.TdsParser.Connect|SEC> SQL Password authentication\n");
                }
                else{
                    Bid.Trace("<sc.TdsParser.Connect|SEC> SQL authentication\n");
                }
            }

            byte[] instanceName = null;

            Debug.Assert(_connHandler != null, "SqlConnectionInternalTds handler can not be null at this point.");
            _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
            _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.InitializeConnection);

            bool fParallel = _connHandler.ConnectionOptions.MultiSubnetFailover;

            TransparentNetworkResolutionState transparentNetworkResolutionState;
            if(_connHandler.ConnectionOptions.TransparentNetworkIPResolution)
            {
                if(isFirstTransparentAttempt)
                    transparentNetworkResolutionState = TransparentNetworkResolutionState.SequentialMode;
                else
                    transparentNetworkResolutionState = TransparentNetworkResolutionState.ParallelMode;
            }
            else 
                transparentNetworkResolutionState = TransparentNetworkResolutionState.DisabledMode;

            int  totalTimeout = _connHandler.ConnectionOptions.ConnectTimeout;

            _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire,
                        out instanceName, _sniSpnBuffer, false, true, fParallel, transparentNetworkResolutionState, totalTimeout);

            if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status) {
                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));

                // Since connect failed, free the unmanaged connection memory.
                // HOWEVER - only free this after the netlib error was processed - if you
                // don't, the memory for the connection object might not be accurate and thus
                // a bad error could be returned (as it was when it was freed to early for me).
                _physicalStateObj.Dispose();
                Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n");
                ThrowExceptionAndWarning(_physicalStateObj);
                Debug.Assert(false, "SNI returned status != success, but no error thrown?");
            }

            _server = serverInfo.ResolvedServerName;

            if (null != connHandler.PoolGroupProviderInfo) {
                // If we are pooling, check to see if we were processing an
                // alias which has changed, which means we need to clean out
                // the pool. See Webdata 104293.
                // This should not apply to routing, as it is not an alias change, routed connection 
                // should still use VNN of AlwaysOn cluster as server for pooling purposes.
                connHandler.PoolGroupProviderInfo.AliasCheck(serverInfo.PreRoutingServerName==null ?
                    serverInfo.ResolvedServerName: serverInfo.PreRoutingServerName);
            }
            _state = TdsParserState.OpenNotLoggedIn;
            _physicalStateObj.SniContext = SniContext.Snix_PreLoginBeforeSuccessfullWrite; // SQL BU DT 376766
            _physicalStateObj.TimeoutTime = timerExpire;

            bool marsCapable = false;

            _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.InitializeConnection);
            _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);

            UInt32 result = SNINativeMethodWrapper.SniGetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);
            Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId");

            // 
            Bid.Trace("<sc.TdsParser.Connect|SEC> Sending prelogin handshake\n");
            SendPreLoginHandshake(instanceName, encrypt);

            _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);
            _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);

            _physicalStateObj.SniContext = SniContext.Snix_PreLogin;

            Bid.Trace("<sc.TdsParser.Connect|SEC> Consuming prelogin handshake\n");
            PreLoginHandshakeStatus status = ConsumePreLoginHandshake(authType, encrypt, trustServerCert, integratedSecurity, out marsCapable,
                                                                      out _connHandler._fedAuthRequired);

            if (status == PreLoginHandshakeStatus.InstanceFailure) {
                Bid.Trace("<sc.TdsParser.Connect|SEC> Prelogin handshake unsuccessful. Reattempting prelogin handshake\n");
                _physicalStateObj.Dispose(); // Close previous connection

                // On Instance failure re-connect and flush SNI named instance cache.
                _physicalStateObj.SniContext=SniContext.Snix_Connect;
                _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, _sniSpnBuffer, true, true, fParallel, transparentNetworkResolutionState, totalTimeout);

                if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status) {
                    _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
                    Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n");
                    ThrowExceptionAndWarning(_physicalStateObj);
                }

                UInt32 retCode = SNINativeMethodWrapper.SniGetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);
                Debug.Assert(retCode == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId");
                
                Bid.Trace("<sc.TdsParser.Connect|SEC> Sending prelogin handshake\n");
                SendPreLoginHandshake(instanceName, encrypt);
                status = ConsumePreLoginHandshake(authType, encrypt, trustServerCert, integratedSecurity, out marsCapable,
                                                  out _connHandler._fedAuthRequired);

                // Don't need to check for Sphinx failure, since we've already consumed
                // one pre-login packet and know we are connecting to Shiloh.
                if (status == PreLoginHandshakeStatus.InstanceFailure) {
                    Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Prelogin handshake unsuccessful. Login failure\n");
                    throw SQL.InstanceFailure();
                }
            }
            Bid.Trace("<sc.TdsParser.Connect|SEC> Prelogin handshake successful\n");

            if (_fMARS && marsCapable) {
                // if user explictly disables mars or mars not supported, don't create the session pool
                _sessionPool = new TdsParserSessionPool(this);
            }
            else {
                _fMARS = false;
            }

            if (authType == SqlAuthenticationMethod.ActiveDirectoryPassword || (authType == SqlAuthenticationMethod.ActiveDirectoryIntegrated && _connHandler._fedAuthRequired)) {
                Debug.Assert(!integratedSecurity, "The legacy Integrated Security connection string option cannot be true when using Active Directory Authentication Library for SQL Server Based workflows.");

                LoadADALLibrary();
                if (Bid.AdvancedOn) {
                    Bid.Trace("<sc.TdsParser.Connect|SEC> Active directory authentication.Loaded Active Directory Authentication Library for SQL Server\n");
                }
            }

            return;
        }
Exemple #2
0
        internal void Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, bool ignoreSniOpenTimeout, long timerExpire, bool encrypt, bool trustServerCert, bool integratedSecurity, bool withFailover)
        {
            if (_state != TdsParserState.Closed)
            {
                Debug.Assert(false, "TdsParser.Connect called on non-closed connection!");
                return;
            }

            _connHandler = connHandler;
            _loginWithFailover = withFailover;

            UInt32 sniStatus = SNILoadHandle.SingletonInstance.SNIStatus;

            if (sniStatus != TdsEnums.SNI_SUCCESS)
            {
                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
                _physicalStateObj.Dispose();
                ThrowExceptionAndWarning(_physicalStateObj);
                Debug.Assert(false, "SNI returned status != success, but no error thrown?");
            }

            if (integratedSecurity)
            {
                LoadSSPILibrary();
                // now allocate proper length of buffer
                _sniSpnBuffer = new byte[SNINativeMethodWrapper.SniMaxComposedSpnLength];
            }
            else
            {
                _sniSpnBuffer = null;
            }

            byte[] instanceName = null;

            Debug.Assert(_connHandler != null, "SqlConnectionInternalTds handler can not be null at this point.");
            _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
            _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.InitializeConnection);

            bool fParallel = _connHandler.ConnectionOptions.MultiSubnetFailover;

            _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire,
                        out instanceName, _sniSpnBuffer, false, true, fParallel);

            if (TdsEnums.SNI_SUCCESS != _physicalStateObj.Status)
            {
                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));

                // Since connect failed, free the unmanaged connection memory.
                // HOWEVER - only free this after the netlib error was processed - if you
                // don't, the memory for the connection object might not be accurate and thus
                // a bad error could be returned (as it was when it was freed to early for me).
                _physicalStateObj.Dispose();
                ThrowExceptionAndWarning(_physicalStateObj);
                Debug.Assert(false, "SNI returned status != success, but no error thrown?");
            }

            _server = serverInfo.ResolvedServerName;

            if (null != connHandler.PoolGroupProviderInfo)
            {
                // If we are pooling, check to see if we were processing an
                // alias which has changed, which means we need to clean out
                // the pool. See Webdata 104293.
                // This should not apply to routing, as it is not an alias change, routed connection 
                // should still use VNN of AlwaysOn cluster as server for pooling purposes.
                connHandler.PoolGroupProviderInfo.AliasCheck(serverInfo.PreRoutingServerName == null ?
                    serverInfo.ResolvedServerName : serverInfo.PreRoutingServerName);
            }
            _state = TdsParserState.OpenNotLoggedIn;
            _physicalStateObj.SniContext = SniContext.Snix_PreLoginBeforeSuccessfullWrite;
            _physicalStateObj.TimeoutTime = timerExpire;

            bool marsCapable = false;

            _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.InitializeConnection);
            _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);

            UInt32 result = SNINativeMethodWrapper.SniGetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);

            Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId");

            SendPreLoginHandshake(instanceName, encrypt);

            _connHandler.TimeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.SendPreLoginHandshake);
            _connHandler.TimeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);

            _physicalStateObj.SniContext = SniContext.Snix_PreLogin;

            PreLoginHandshakeStatus status = ConsumePreLoginHandshake(encrypt, trustServerCert, integratedSecurity, out marsCapable);

            if (status == PreLoginHandshakeStatus.InstanceFailure)
            {
                _physicalStateObj.Dispose(); // Close previous connection

                // On Instance failure re-connect and flush SNI named instance cache.
                _physicalStateObj.SniContext = SniContext.Snix_Connect;
                _physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, _sniSpnBuffer, true, true, fParallel);

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

                UInt32 retCode = SNINativeMethodWrapper.SniGetConnectionId(_physicalStateObj.Handle, ref _connHandler._clientConnectionId);

                Debug.Assert(retCode == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SniGetConnectionId");

                SendPreLoginHandshake(instanceName, encrypt);
                status = ConsumePreLoginHandshake(encrypt, trustServerCert, integratedSecurity, out marsCapable);

                // Don't need to check for Sphinx failure, since we've already consumed
                // one pre-login packet and know we are connecting to Shiloh.
                if (status == PreLoginHandshakeStatus.InstanceFailure)
                {
                    throw SQL.InstanceFailure();
                }
            }

            if (_fMARS && marsCapable)
            {
                // if user explictly disables mars or mars not supported, don't create the session pool
                _sessionPool = new TdsParserSessionPool(this);
            }
            else
            {
                _fMARS = false;
            }
            return;
        }
        internal void Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, bool ignoreSniOpenTimeout, long timerExpire, bool encrypt, bool trustServerCert, bool integratedSecurity)
        {
            if (this._state == TdsParserState.Closed)
            {
                this._connHandler = connHandler;
                if (SNILoadHandle.SingletonInstance.SNIStatus != 0)
                {
                    this.Errors.Add(this.ProcessSNIError(this._physicalStateObj));
                    this._physicalStateObj.Dispose();
                    this.ThrowExceptionAndWarning();
                }
                if (connHandler.ConnectionOptions.LocalDBInstance != null)
                {
                    LocalDBAPI.CreateLocalDBInstance(connHandler.ConnectionOptions.LocalDBInstance);
                }
                if (integratedSecurity)
                {
                    this.LoadSSPILibrary();
                    this._sniSpnBuffer = new byte[SNINativeMethodWrapper.SniMaxComposedSpnLength];
                    Bid.Trace("<sc.TdsParser.Connect|SEC> SSPI authentication\n");
                }
                else
                {
                    this._sniSpnBuffer = null;
                    Bid.Trace("<sc.TdsParser.Connect|SEC> SQL authentication\n");
                }
                byte[] instanceName = null;
                bool multiSubnetFailover = this._connHandler.ConnectionOptions.MultiSubnetFailover;
                this._physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, this._sniSpnBuffer, false, this._fAsync, multiSubnetFailover);
                if (this._physicalStateObj.Status != 0)
                {
                    this.Errors.Add(this.ProcessSNIError(this._physicalStateObj));
                    this._physicalStateObj.Dispose();
                    Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n");
                    this.ThrowExceptionAndWarning();
                }
                this._server = serverInfo.ResolvedServerName;
                if (connHandler.PoolGroupProviderInfo != null)
                {
                    connHandler.PoolGroupProviderInfo.AliasCheck((serverInfo.PreRoutingServerName == null) ? serverInfo.ResolvedServerName : serverInfo.PreRoutingServerName);
                }
                this._state = TdsParserState.OpenNotLoggedIn;
                this._physicalStateObj.SniContext = SniContext.Snix_PreLoginBeforeSuccessfullWrite;
                this._physicalStateObj.TimeoutTime = timerExpire;
                bool marsCapable = false;
                this.SendPreLoginHandshake(instanceName, encrypt);
                this._physicalStateObj.SniContext = SniContext.Snix_PreLogin;
                switch (this.ConsumePreLoginHandshake(encrypt, trustServerCert, out marsCapable))
                {
                    case PreLoginHandshakeStatus.SphinxFailure:
                        this._fMARS = false;
                        this._physicalStateObj._sniPacket = null;
                        this._physicalStateObj.SniContext = SniContext.Snix_Connect;
                        this._physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, this._sniSpnBuffer, false, this._fAsync, multiSubnetFailover);
                        if (this._physicalStateObj.Status != 0)
                        {
                            this.Errors.Add(this.ProcessSNIError(this._physicalStateObj));
                            Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n");
                            this.ThrowExceptionAndWarning();
                        }
                        break;

                    case PreLoginHandshakeStatus.InstanceFailure:
                        this._physicalStateObj.Dispose();
                        this._physicalStateObj.SniContext = SniContext.Snix_Connect;
                        this._physicalStateObj.CreatePhysicalSNIHandle(serverInfo.ExtendedServerName, ignoreSniOpenTimeout, timerExpire, out instanceName, this._sniSpnBuffer, true, this._fAsync, multiSubnetFailover);
                        if (this._physicalStateObj.Status != 0)
                        {
                            this.Errors.Add(this.ProcessSNIError(this._physicalStateObj));
                            Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n");
                            this.ThrowExceptionAndWarning();
                        }
                        this.SendPreLoginHandshake(instanceName, encrypt);
                        if (this.ConsumePreLoginHandshake(encrypt, trustServerCert, out marsCapable) == PreLoginHandshakeStatus.InstanceFailure)
                        {
                            Bid.Trace("<sc.TdsParser.Connect|ERR|SEC> Login failure\n");
                            throw SQL.InstanceFailure();
                        }
                        break;
                }
                if (this._fMARS && marsCapable)
                {
                    this._sessionPool = new TdsParserSessionPool(this);
                }
                else
                {
                    this._fMARS = false;
                }
            }
        }