private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options) {
        if (serverInfo.ExtendedServerName == null) {
            string host = serverInfo.UserServerName;
            string protocol = serverInfo.UserProtocol;

            if (aliasLookup) { // We skip this for UserInstances...
                // Perform registry lookup to see if host is an alias.  It will appropriately set host and protocol, if an Alias.
                // Check if it was already resolved, during CR reconnection _currentSessionData values will be copied from
                // _reconnectSessonData of the previous connection
                if (_currentSessionData != null && !string.IsNullOrEmpty(host)) {
                    Tuple<string, string> hostPortPair;
                    if (_currentSessionData._resolvedAliases.TryGetValue(host, out hostPortPair)) {
                        host = hostPortPair.Item1;
                        protocol = hostPortPair.Item2;
                    }
                    else {
                        TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol);
                        _currentSessionData._resolvedAliases.Add(serverInfo.UserServerName, new Tuple<string, string>(host, protocol));
                    }
                }
                else {
                    TdsParserStaticMethods.AliasRegistryLookup(ref host, ref protocol);
                }

                //
                if (options.EnforceLocalHost) {
                    // verify LocalHost for |DataDirectory| usage
                    SqlConnectionString.VerifyLocalHostAndFixup(ref host, true, true /*fix-up to "."*/);
                }
            }

            serverInfo.SetDerivedNames(protocol, host);
        }
    }
    // Attempt to login to a host that does not have a failover partner
    //
    //  Will repeatedly attempt to connect, but back off between each attempt so as not to clog the network.
    //  Back off period increases for first few failures: 100ms, 200ms, 400ms, 800ms, then 1000ms for subsequent attempts
    //
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //  DEVNOTE: The logic in this method is paralleled by the logic in LoginWithFailover.
    //           Changes to either one should be examined to see if they need to be reflected in the other
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    private void LoginNoFailover(ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, bool redirectedUserInstance, 
                SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) {

        Debug.Assert(object.ReferenceEquals(connectionOptions, this.ConnectionOptions), "ConnectionOptions argument and property must be the same"); // consider removing the argument
        int routingAttempts = 0;
        ServerInfo originalServerInfo = serverInfo; // serverInfo may end up pointing to new object due to routing, original object is used to set CurrentDatasource

        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, host=%ls\n", ObjectID, serverInfo.UserServerName);
        }
        int  sleepInterval = 100;  //milliseconds to sleep (back off) between attempts.

        ResolveExtendedServerName(serverInfo, !redirectedUserInstance, connectionOptions);

        long timeoutUnitInterval = 0;
        Boolean isParallel = connectionOptions.MultiSubnetFailover || connectionOptions.TransparentNetworkIPResolution;

        if(isParallel) {
            // Determine unit interval
            if (timeout.IsInfinite) {
                timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * (1000L * ADP.DefaultConnectionTimeout)));
            }
            else {
                timeoutUnitInterval = checked((long)(ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining));
            }
        }
        // Only three ways out of this loop:
        //  1) Successfully connected
        //  2) Parser threw exception while main timer was expired
        //  3) Parser threw logon failure-related exception 
        //  4) Parser threw exception in post-initial connect code,
        //      such as pre-login handshake or during actual logon. (parser state != Closed)
        //
        //  Of these methods, only #1 exits normally. This preserves the call stack on the exception 
        //  back into the parser for the error cases.
        int attemptNumber = 0;
        TimeoutTimer intervalTimer = null;
        TimeoutTimer firstTransparentAttemptTimeout = TimeoutTimer.StartMillisecondsTimeout(ADP.FirstTransparentAttemptTimeout);
        TimeoutTimer attemptOneLoginTimeout = timeout;
        while(true) {

            if(isParallel) {
                attemptNumber++;
                // Set timeout for this attempt, but don't exceed original timer                
                long nextTimeoutInterval = checked(timeoutUnitInterval * attemptNumber);
                long milliseconds = timeout.MillisecondsRemaining;
                if (nextTimeoutInterval > milliseconds) {
                    nextTimeoutInterval = milliseconds;
                }
                intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval);
            }

            // Re-allocate parser each time to make sure state is known
            // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created
            if (_parser != null)
                _parser.Disconnect();
 
            _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous);
            Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext));

            try {
                // 


                Boolean isFirstTransparentAttempt =  connectionOptions.TransparentNetworkIPResolution && attemptNumber == 1;

                if(isFirstTransparentAttempt) {
                    attemptOneLoginTimeout = firstTransparentAttemptTimeout;
                }
                else {
                    if(isParallel) {
                        attemptOneLoginTimeout = intervalTimer;
                    }
                }
                
                AttemptOneLogin(    serverInfo, 
                                    newPassword,
                                    newSecurePassword,
                                    !isParallel,    // ignore timeout for SniOpen call unless MSF , and TNIR
                                    attemptOneLoginTimeout,
                                    isFirstTransparentAttempt:isFirstTransparentAttempt);
                
                if (connectionOptions.MultiSubnetFailover && null != ServerProvidedFailOverPartner) {
                    // connection succeeded: trigger exception if server sends failover partner and MultiSubnetFailover is used.
                    throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
                }

                if (_routingInfo != null) {
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover> Routed to %ls", serverInfo.ExtendedServerName);

                    if (routingAttempts > 0) {
                        throw SQL.ROR_RecursiveRoutingNotSupported(this);
                    }

                    if (timeout.IsExpired) {
                        throw SQL.ROR_TimeoutAfterRoutingInfo(this);
                    }                    

                    serverInfo = new ServerInfo(ConnectionOptions, _routingInfo, serverInfo.ResolvedServerName);
                    timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.RoutingDestination);
                    _originalClientConnectionId = _clientConnectionId;
                    _routingDestination = serverInfo.UserServerName;

                    // restore properties that could be changed by the environment tokens
                    _currentPacketSize = ConnectionOptions.PacketSize;
                    _currentLanguage = _originalLanguage = ConnectionOptions.CurrentLanguage;
                    CurrentDatabase = _originalDatabase = ConnectionOptions.InitialCatalog;
                    _currentFailoverPartner = null;
                    _instanceName = String.Empty;

                    routingAttempts++;

                    continue; // repeat the loop, but skip code reserved for failed connections (after the catch)
                }
                else {
                    break; // leave the while loop -- we've successfully connected
                }
            }
            catch (SqlException sqlex) {
                if (null == _parser
                    || TdsParserState.Closed != _parser.State
                    || IsDoNotRetryConnectError(sqlex)
                    || timeout.IsExpired) {       // no more time to try again
                    throw;  // Caller will call LoginFailure()
                }

                // Check sleep interval to make sure we won't exceed the timeout
                //  Do this in the catch block so we can re-throw the current exception
                if (timeout.MillisecondsRemaining <= sleepInterval) {
                    throw;
                }

                // 
            }

            // We only get here when we failed to connect, but are going to re-try

            // Switch to failover logic if the server provided a partner
            if (null != ServerProvidedFailOverPartner) {
                if (connectionOptions.MultiSubnetFailover) {
                    // connection failed: do not allow failover to server-provided failover partner if MultiSubnetFailover is set
                    throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner: true, internalConnection: this);
                }
                Debug.Assert(ConnectionOptions.ApplicationIntent != ApplicationIntent.ReadOnly, "FAILOVER+AppIntent=RO: Should already fail (at LOGSHIPNODE in OnEnvChange)");

                timeoutErrorInternal.ResetAndRestartPhase();
                timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
                timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario
                LoginWithFailover(
                            true,   // start by using failover partner, since we already failed to connect to the primary
                            serverInfo,
                            ServerProvidedFailOverPartner,
                            newPassword,
                            newSecurePassword,
                            redirectedUserInstance,
                            connectionOptions,
                            credential,
                            timeout);
                return; // LoginWithFailover successfully connected and handled entire connection setup
            }

            // Sleep for a bit to prevent clogging the network with requests, 
            //  then update sleep interval for next iteration (max 1 second interval)
            if (Bid.AdvancedOn) {
                Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval);
            }
            Thread.Sleep(sleepInterval);
            sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000;
        }

        if (null != PoolGroupProviderInfo) {
            // We must wait for CompleteLogin to finish for to have the
            // env change from the server to know its designated failover 
            // partner; save this information in _currentFailoverPartner.
            PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner);
        }
        CurrentDataSource = originalServerInfo.UserServerName;
    }
    // Attempt to login to a host that has a failover partner
    //
    // Connection & timeout sequence is
    //      First target, timeout = interval * 1
    //      second target, timeout = interval * 1
    //      sleep for 100ms
    //      First target, timeout = interval * 2
    //      Second target, timeout = interval * 2
    //      sleep for 200ms
    //      First Target, timeout = interval * 3
    //      etc.
    //
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    //  DEVNOTE: The logic in this method is paralleled by the logic in LoginNoFailover.
    //           Changes to either one should be examined to see if they need to be reflected in the other
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    private void LoginWithFailover(
            bool                useFailoverHost, 
            ServerInfo          primaryServerInfo, 
            string              failoverHost, 
            string              newPassword,
            SecureString        newSecurePassword,
            bool                redirectedUserInstance, 
            SqlConnectionString connectionOptions,
            SqlCredential       credential,
            TimeoutTimer        timeout
        ) {

        Debug.Assert(!connectionOptions.MultiSubnetFailover, "MultiSubnetFailover should not be set if failover partner is used");

        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", ObjectID, useFailoverHost);
            Bid.PutStr(primaryServerInfo.UserServerName);
            Bid.PutStr(", failover=");
            Bid.PutStr(failoverHost);
            Bid.PutStr("\n");
        }
        int  sleepInterval = 100;  //milliseconds to sleep (back off) between attempts.
        long timeoutUnitInterval;

        string     protocol = ConnectionOptions.NetworkLibrary;
        ServerInfo failoverServerInfo = new ServerInfo(connectionOptions, failoverHost);

        ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, connectionOptions);
        if (null == ServerProvidedFailOverPartner) {// No point in resolving the failover partner when we're going to override it below
            // Don't resolve aliases if failover == primary // 
            ResolveExtendedServerName(failoverServerInfo, !redirectedUserInstance && failoverHost != primaryServerInfo.UserServerName, connectionOptions);
        }

        // Determine unit interval
        if (timeout.IsInfinite) {
            timeoutUnitInterval = checked((long) ADP.FailoverTimeoutStep * ADP.TimerFromSeconds(ADP.DefaultConnectionTimeout));
        }
        else {
            timeoutUnitInterval = checked((long) (ADP.FailoverTimeoutStep * timeout.MillisecondsRemaining));
        }

        // Initialize loop variables
        bool failoverDemandDone = false; // have we demanded for partner information yet (as necessary)?
        int attemptNumber = 0;

        // Only three ways out of this loop:
        //  1) Successfully connected
        //  2) Parser threw exception while main timer was expired
        //  3) Parser threw logon failure-related exception (LOGON_FAILED, PASSWORD_EXPIRED, etc)
        //
        //  Of these methods, only #1 exits normally. This preserves the call stack on the exception 
        //  back into the parser for the error cases.
        while (true) {
            // Set timeout for this attempt, but don't exceed original timer
            long nextTimeoutInterval = checked(timeoutUnitInterval * ((attemptNumber / 2) + 1));
            long milliseconds = timeout.MillisecondsRemaining;
            if (nextTimeoutInterval > milliseconds) {
                nextTimeoutInterval = milliseconds;
            }

            TimeoutTimer intervalTimer = TimeoutTimer.StartMillisecondsTimeout(nextTimeoutInterval);

            // Re-allocate parser each time to make sure state is known
            // RFC 50002652 - if parser was created by previous attempt, dispose it to properly close the socket, if created
            if (_parser != null)
                _parser.Disconnect();

            _parser = new TdsParser(ConnectionOptions.MARS, ConnectionOptions.Asynchronous);
            Debug.Assert(SniContext.Undefined== Parser._physicalStateObj.SniContext, String.Format((IFormatProvider)null, "SniContext should be Undefined; actual Value: {0}", Parser._physicalStateObj.SniContext));

            ServerInfo currentServerInfo;
            if (useFailoverHost) {
                if (!failoverDemandDone) {
                    FailoverPermissionDemand();
                    failoverDemandDone = true;
                }

                // Primary server may give us a different failover partner than the connection string indicates.  Update it
                if (null != ServerProvidedFailOverPartner && failoverServerInfo.ResolvedServerName != ServerProvidedFailOverPartner) {
                    if (Bid.AdvancedOn) {
                        Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", ObjectID, ServerProvidedFailOverPartner);
                    }
                    failoverServerInfo.SetDerivedNames(protocol, ServerProvidedFailOverPartner);
                }
                currentServerInfo = failoverServerInfo;
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Failover);
            }
            else {
                currentServerInfo = primaryServerInfo;
                timeoutErrorInternal.SetInternalSourceType(SqlConnectionInternalSourceType.Principle);
            }

            try {
                // Attempt login.  Use timerInterval for attempt timeout unless infinite timeout was requested.
                AttemptOneLogin(
                        currentServerInfo,
                        newPassword,
                        newSecurePassword,
                        false,          // Use timeout in SniOpen
                        intervalTimer,
                        withFailover:true
                        );

                if (_routingInfo != null) {
                    // We are in login with failover scenation and server sent routing information
                    // If it is read-only routing - we did not supply AppIntent=RO (it should be checked before)
                    // If it is something else, not known yet (future server) - this client is not designed to support this.                    
                    // In any case, server should not have sent the routing info.
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", _routingInfo.ServerName);
                    throw SQL.ROR_UnexpectedRoutingInfo(this);
                }

                break; // leave the while loop -- we've successfully connected
            }
            catch (SqlException sqlex) {
                if (IsDoNotRetryConnectError(sqlex)
                        || timeout.IsExpired) 
                {       // no more time to try again
                    throw;  // Caller will call LoginFailure()
                }

                if (IsConnectionDoomed) {
                    throw;
                }

                if (1 == attemptNumber % 2) {
                    // Check sleep interval to make sure we won't exceed the original timeout
                    //  Do this in the catch block so we can re-throw the current exception
                    if (timeout.MillisecondsRemaining <= sleepInterval) {
                        throw;
                    }
                }

                // 
            }

            // We only get here when we failed to connect, but are going to re-try

            // After trying to connect to both servers fails, sleep for a bit to prevent clogging 
            //  the network with requests, then update sleep interval for next iteration (max 1 second interval)
            if (1 == attemptNumber % 2) {
                if (Bid.AdvancedOn) {
                    Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", ObjectID, sleepInterval);
                }
                Thread.Sleep(sleepInterval);
                sleepInterval = (sleepInterval < 500) ? sleepInterval * 2 : 1000;
            }

            // Update attempt number and target host
            attemptNumber++;
            useFailoverHost = !useFailoverHost;
        }

        // If we get here, connection/login succeeded!  Just a few more checks & record-keeping

        // if connected to failover host, but said host doesn't have DbMirroring set up, throw an error
        if (useFailoverHost && null == ServerProvidedFailOverPartner) {
            throw SQL.InvalidPartnerConfiguration(failoverHost, CurrentDatabase);
        }

        if (null != PoolGroupProviderInfo) {
            // We must wait for CompleteLogin to finish for to have the
            // env change from the server to know its designated failover 
            // partner; save this information in _currentFailoverPartner.
            PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner);
        }
        CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName);
    }
        private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword, SecureString newSecurePassword) {
            // create a new login record
            SqlLogin login = new SqlLogin();

            // gather all the settings the user set in the connection string or
            // properties and do the login
            CurrentDatabase   = server.ResolvedDatabaseName;
            _currentPacketSize = ConnectionOptions.PacketSize;
            _currentLanguage   = ConnectionOptions.CurrentLanguage;

            int timeoutInSeconds = 0;

            // If a timeout tick value is specified, compute the timeout based
            // upon the amount of time left in seconds.
            if (!timeout.IsInfinite)
            {
                long t = timeout.MillisecondsRemaining/1000;
                if ((long)Int32.MaxValue > t)
                {
                    timeoutInSeconds = (int)t;
                }
            }

            login.authentication = ConnectionOptions.Authentication;
            login.timeout = timeoutInSeconds;
            login.userInstance     = ConnectionOptions.UserInstance;
            login.hostName         = ConnectionOptions.ObtainWorkstationId();
            login.userName         = ConnectionOptions.UserID;
            login.password         = ConnectionOptions.Password;
            login.applicationName  = ConnectionOptions.ApplicationName;

            login.language         = _currentLanguage;
            if (!login.userInstance) { // Do not send attachdbfilename or database to SSE primary instance
                login.database         = CurrentDatabase;;
                login.attachDBFilename = ConnectionOptions.AttachDBFilename;
            }

            // VSTS#795621 - Ensure ServerName is Sent During TdsLogin To Enable Sql Azure Connectivity.
            // Using server.UserServerName (versus ConnectionOptions.DataSource) since TdsLogin requires 
            // serverName to always be non-null.
            login.serverName = server.UserServerName;

            login.useReplication   = ConnectionOptions.Replication;
            login.useSSPI          = ConnectionOptions.IntegratedSecurity 
                                     || (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated && !_fedAuthRequired);
            login.packetSize       = _currentPacketSize;
            login.newPassword      = newPassword;
            login.readOnlyIntent   = ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly;
            login.credential       = _credential;
            if (newSecurePassword != null) {
                login.newSecurePassword = newSecurePassword;
            }

            TdsEnums.FeatureExtension requestedFeatures = TdsEnums.FeatureExtension.None;
            if (ConnectionOptions.ConnectRetryCount>0) {
                requestedFeatures |= TdsEnums.FeatureExtension.SessionRecovery;
                _sessionRecoveryRequested = true;
            }

            // If the workflow being used is Active Directory Password or Active Directory Integrated and server's prelogin response
            // for FEDAUTHREQUIRED option indicates Federated Authentication is required, we have to insert FedAuth Feature Extension
            // in Login7, indicating the intent to use Active Directory Authentication Library for SQL Server.
            if (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryPassword
                || (ConnectionOptions.Authentication == SqlAuthenticationMethod.ActiveDirectoryIntegrated && _fedAuthRequired)) {
                requestedFeatures |= TdsEnums.FeatureExtension.FedAuth;
                _federatedAuthenticationInfoRequested = true;
                _fedAuthFeatureExtensionData = 
                    new FederatedAuthenticationFeatureExtensionData { 
                        libraryType = TdsEnums.FedAuthLibrary.ADAL,
                        authentication = ConnectionOptions.Authentication,
                        fedAuthRequiredPreLoginResponse = _fedAuthRequired
                    };
            }
            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;
            }

            // The TCE and GLOBALTRANSACTIONS feature are implicitly requested
            requestedFeatures |= TdsEnums.FeatureExtension.Tce | TdsEnums.FeatureExtension.GlobalTransactions;
            _parser.TdsLogin(login, requestedFeatures, _recoverySessionData, _fedAuthFeatureExtensionData);
        }
        private void OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential,
                    string newPassword, SecureString newSecurePassword, bool redirectedUserInstance) {
            bool useFailoverPartner; // should we use primary or secondary first
            ServerInfo dataSource = new ServerInfo(connectionOptions);
            string failoverPartner;

            if (null != PoolGroupProviderInfo) {
                useFailoverPartner = PoolGroupProviderInfo.UseFailoverPartner;
                failoverPartner = PoolGroupProviderInfo.FailoverPartner;
            }
            else {
                // Only ChangePassword or SSE User Instance comes through this code path.
                useFailoverPartner = false;
                failoverPartner = ConnectionOptions.FailoverPartner; 
            }

            timeoutErrorInternal.SetInternalSourceType(useFailoverPartner ? SqlConnectionInternalSourceType.Failover : SqlConnectionInternalSourceType.Principle);

            bool hasFailoverPartner = !ADP.IsEmpty(failoverPartner);

            // Open the connection and Login
            try {
                timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PreLoginBegin);
                if (hasFailoverPartner) {
                    timeoutErrorInternal.SetFailoverScenario(true); // this is a failover scenario
                    LoginWithFailover(
                                useFailoverPartner, 
                                dataSource, 
                                failoverPartner, 
                                newPassword,
                                newSecurePassword,
                                redirectedUserInstance, 
                                connectionOptions,
                                credential,
                                timeout);
                }
                else {
                    timeoutErrorInternal.SetFailoverScenario(false); // not a failover scenario
                    LoginNoFailover(dataSource, newPassword, newSecurePassword, redirectedUserInstance, 
                            connectionOptions, credential, timeout);
                }
                timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin);
            }
            catch (Exception e) {
                // 
                if (ADP.IsCatchableExceptionType(e)) {
                    LoginFailure();
                }
                throw;
            }
            timeoutErrorInternal.SetAllCompleteMarker();

#if DEBUG
            _parser._physicalStateObj.InvalidateDebugOnlyCopyOfSniContext();
#endif
        }
 private void AttemptOneLogin(ServerInfo serverInfo, string newPassword, bool ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject)
 {
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionTds.AttemptOneLogin|ADV> %d#, timout=%I64d{msec}, server=", base.ObjectID, timeout.MillisecondsRemaining);
         Bid.PutStr(serverInfo.ExtendedServerName);
         Bid.Trace("\n");
     }
     this._routingInfo = null;
     this._parser._physicalStateObj.SniContext = SniContext.Snix_Connect;
     this._parser.Connect(serverInfo, this, ignoreSniOpenTimeout, timeout.LegacyTimerExpire, base.ConnectionOptions.Encrypt, base.ConnectionOptions.TrustServerCertificate, base.ConnectionOptions.IntegratedSecurity);
     this._parser._physicalStateObj.SniContext = SniContext.Snix_Login;
     this.Login(serverInfo, timeout, newPassword);
     this.CompleteLogin(!base.ConnectionOptions.Pooling);
 }
        private void Login(ServerInfo server, TimeoutTimer timeout)
        {
            // create a new login record
            SqlLogin login = new SqlLogin();

            // gather all the settings the user set in the connection string or
            // properties and do the login
            CurrentDatabase = server.ResolvedDatabaseName;
            _currentPacketSize = ConnectionOptions.PacketSize;
            _currentLanguage = ConnectionOptions.CurrentLanguage;

            int timeoutInSeconds = 0;

            // If a timeout tick value is specified, compute the timeout based
            // upon the amount of time left in seconds.
            if (!timeout.IsInfinite)
            {
                long t = timeout.MillisecondsRemaining / 1000;
                if ((long)Int32.MaxValue > t)
                {
                    timeoutInSeconds = (int)t;
                }
            }

            login.timeout = timeoutInSeconds;
            login.userInstance = ConnectionOptions.UserInstance;
            login.hostName = ConnectionOptions.ObtainWorkstationId();
            login.userName = ConnectionOptions.UserID;
            login.password = ConnectionOptions.Password;
            login.applicationName = ConnectionOptions.ApplicationName;

            login.language = _currentLanguage;
            if (!login.userInstance)
            { // Do not send attachdbfilename or database to SSE primary instance
                login.database = CurrentDatabase; ;
                login.attachDBFilename = ConnectionOptions.AttachDBFilename;
            }

            // VSTS#795621 - Ensure ServerName is Sent During TdsLogin To Enable Sql Azure Connectivity.
            // Using server.UserServerName (versus ConnectionOptions.DataSource) since TdsLogin requires 
            // serverName to always be non-null.
            login.serverName = server.UserServerName;

            login.useReplication = ConnectionOptions.Replication;
            login.useSSPI = ConnectionOptions.IntegratedSecurity;
            login.packetSize = _currentPacketSize;
            login.readOnlyIntent = ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly;

            TdsEnums.FeatureExtension requestedFeatures = TdsEnums.FeatureExtension.None;
            if (ConnectionOptions.ConnectRetryCount > 0)
            {
                requestedFeatures |= TdsEnums.FeatureExtension.SessionRecovery;
                _sessionRecoveryRequested = true;
            }

            _parser.TdsLogin(login, requestedFeatures, _recoverySessionData);
        }
示例#8
0
        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;
        }
        private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnectionString options)
        {
            if (serverInfo.ExtendedServerName == null)
            {
                string host = serverInfo.UserServerName;
                string protocol = serverInfo.UserProtocol;


                serverInfo.SetDerivedNames(protocol, host);
            }
        }
 private void OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, string newPassword, bool redirectedUserInstance)
 {
     string failoverPartner;
     bool useFailoverPartner;
     ServerInfo primaryServerInfo = new ServerInfo(connectionOptions);
     if (this.PoolGroupProviderInfo != null)
     {
         useFailoverPartner = this.PoolGroupProviderInfo.UseFailoverPartner;
         failoverPartner = this.PoolGroupProviderInfo.FailoverPartner;
     }
     else
     {
         useFailoverPartner = false;
         failoverPartner = base.ConnectionOptions.FailoverPartner;
     }
     bool flag2 = !ADP.IsEmpty(failoverPartner);
     try
     {
         if (flag2)
         {
             this.LoginWithFailover(useFailoverPartner, primaryServerInfo, failoverPartner, newPassword, redirectedUserInstance, owningObject, connectionOptions, timeout);
         }
         else
         {
             this.LoginNoFailover(primaryServerInfo, newPassword, redirectedUserInstance, owningObject, connectionOptions, timeout);
         }
     }
     catch (Exception exception)
     {
         if (ADP.IsCatchableExceptionType(exception))
         {
             this.LoginFailure();
         }
         throw;
     }
 }
 private void ResolveExtendedServerName(ServerInfo serverInfo, bool aliasLookup, SqlConnection owningObject)
 {
     if (serverInfo.ExtendedServerName == null)
     {
         string userServerName = serverInfo.UserServerName;
         string userProtocol = serverInfo.UserProtocol;
         if (aliasLookup)
         {
             TdsParserStaticMethods.AliasRegistryLookup(ref userServerName, ref userProtocol);
             if ((owningObject != null) && ((SqlConnectionString) owningObject.UserConnectionOptions).EnforceLocalHost)
             {
                 SqlConnectionString.VerifyLocalHostAndFixup(ref userServerName, true, true);
             }
         }
         serverInfo.SetDerivedNames(userProtocol, userServerName);
     }
 }
 private void LoginWithFailover(bool useFailoverHost, ServerInfo primaryServerInfo, string failoverHost, string newPassword, bool redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
 {
     long num5;
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, useFailover=%d{bool}, primary=", base.ObjectID, useFailoverHost);
         Bid.PutStr(primaryServerInfo.UserServerName);
         Bid.PutStr(", failover=");
         Bid.PutStr(failoverHost);
         Bid.PutStr("\n");
     }
     int num = 100;
     string networkLibrary = base.ConnectionOptions.NetworkLibrary;
     ServerInfo serverInfo = new ServerInfo(connectionOptions, failoverHost);
     this.ResolveExtendedServerName(primaryServerInfo, !redirectedUserInstance, owningObject);
     if (this.ServerProvidedFailOverPartner == null)
     {
         this.ResolveExtendedServerName(serverInfo, !redirectedUserInstance && (failoverHost != primaryServerInfo.UserServerName), owningObject);
     }
     if (timeout.IsInfinite)
     {
         ADP.TimerFromSeconds(15);
         num5 = 0L;
     }
     else
     {
         num5 = (long) (0.08f * timeout.MillisecondsRemaining);
     }
     bool flag = false;
     int num2 = 0;
     while (true)
     {
         ServerInfo info2;
         long milliseconds = num5 * ((num2 / 2) + 1);
         long millisecondsRemaining = timeout.MillisecondsRemaining;
         if (milliseconds > millisecondsRemaining)
         {
             milliseconds = millisecondsRemaining;
         }
         TimeoutTimer timer = TimeoutTimer.StartMillisecondsTimeout(milliseconds);
         if (this._parser != null)
         {
             this._parser.Disconnect();
         }
         this._parser = new TdsParser(base.ConnectionOptions.MARS, base.ConnectionOptions.Asynchronous);
         if (useFailoverHost)
         {
             if (!flag)
             {
                 this.FailoverPermissionDemand();
                 flag = true;
             }
             if ((this.ServerProvidedFailOverPartner != null) && (serverInfo.ResolvedServerName != this.ServerProvidedFailOverPartner))
             {
                 if (Bid.AdvancedOn)
                 {
                     Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, new failover partner=%ls\n", base.ObjectID, this.ServerProvidedFailOverPartner);
                 }
                 serverInfo.SetDerivedNames(networkLibrary, this.ServerProvidedFailOverPartner);
             }
             info2 = serverInfo;
         }
         else
         {
             info2 = primaryServerInfo;
         }
         try
         {
             this.AttemptOneLogin(info2, newPassword, false, timer, owningObject);
             if (this._routingInfo != null)
             {
                 Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover> Routed to %ls", this._routingInfo.ServerName);
                 throw SQL.ROR_UnexpectedRoutingInfo();
             }
             break;
         }
         catch (SqlException exception)
         {
             if (this.IsDoNotRetryConnectError(exception) || timeout.IsExpired)
             {
                 throw;
             }
             if (base.IsConnectionDoomed)
             {
                 throw;
             }
             if ((1 == (num2 % 2)) && (timeout.MillisecondsRemaining <= num))
             {
                 throw;
             }
         }
         if (1 == (num2 % 2))
         {
             if (Bid.AdvancedOn)
             {
                 Bid.Trace("<sc.SqlInternalConnectionTds.LoginWithFailover|ADV> %d#, sleeping %d{milisec}\n", base.ObjectID, num);
             }
             Thread.Sleep(num);
             num = (num < 500) ? (num * 2) : 0x3e8;
         }
         num2++;
         useFailoverHost = !useFailoverHost;
     }
     if (useFailoverHost && (this.ServerProvidedFailOverPartner == null))
     {
         throw SQL.InvalidPartnerConfiguration(failoverHost, base.CurrentDatabase);
     }
     if (this.PoolGroupProviderInfo != null)
     {
         this.PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, this.ServerProvidedFailOverPartner);
     }
     base.CurrentDataSource = useFailoverHost ? failoverHost : primaryServerInfo.UserServerName;
 }
 private void LoginNoFailover(ServerInfo serverInfo, string newPassword, bool redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
 {
     int num2 = 0;
     ServerInfo info = serverInfo;
     if (Bid.AdvancedOn)
     {
         Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, host=%ls\n", base.ObjectID, serverInfo.UserServerName);
     }
     int num = 100;
     this.ResolveExtendedServerName(serverInfo, !redirectedUserInstance, owningObject);
 Label_0032:
     if (this._parser != null)
     {
         this._parser.Disconnect();
     }
     this._parser = new TdsParser(base.ConnectionOptions.MARS, base.ConnectionOptions.Asynchronous);
     try
     {
         this.AttemptOneLogin(serverInfo, newPassword, true, timeout, owningObject);
         if (connectionOptions.MultiSubnetFailover && (this.ServerProvidedFailOverPartner != null))
         {
             bool serverProvidedFailoverPartner = true;
             throw SQL.MultiSubnetFailoverWithFailoverPartner(serverProvidedFailoverPartner);
         }
         if (this._routingInfo == null)
         {
             if (this.PoolGroupProviderInfo != null)
             {
                 this.PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, this.ServerProvidedFailOverPartner);
             }
             base.CurrentDataSource = info.UserServerName;
             return;
         }
         Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover> Routed to %ls", serverInfo.ExtendedServerName);
         if (num2 > 0)
         {
             throw SQL.ROR_RecursiveRoutingNotSupported();
         }
         if (timeout.IsExpired)
         {
             throw SQL.ROR_TimeoutAfterRoutingInfo();
         }
         serverInfo = new ServerInfo(base.ConnectionOptions, this._routingInfo, serverInfo.ResolvedServerName);
         this._currentPacketSize = base.ConnectionOptions.PacketSize;
         this._currentLanguage = this._originalLanguage = base.ConnectionOptions.CurrentLanguage;
         base.CurrentDatabase = this._originalDatabase = base.ConnectionOptions.InitialCatalog;
         this._currentFailoverPartner = null;
         this._instanceName = string.Empty;
         num2++;
         goto Label_0032;
     }
     catch (SqlException exception)
     {
         if (((this._parser == null) || (this._parser.State != TdsParserState.Closed)) || (this.IsDoNotRetryConnectError(exception) || timeout.IsExpired))
         {
             throw;
         }
         if (timeout.MillisecondsRemaining <= num)
         {
             throw;
         }
     }
     if (this.ServerProvidedFailOverPartner != null)
     {
         if (connectionOptions.MultiSubnetFailover)
         {
             bool flag = true;
             throw SQL.MultiSubnetFailoverWithFailoverPartner(flag);
         }
         this.LoginWithFailover(true, serverInfo, this.ServerProvidedFailOverPartner, newPassword, redirectedUserInstance, owningObject, connectionOptions, timeout);
     }
     else
     {
         if (Bid.AdvancedOn)
         {
             Bid.Trace("<sc.SqlInternalConnectionTds.LoginNoFailover|ADV> %d#, sleeping %d{milisec}\n", base.ObjectID, num);
         }
         Thread.Sleep(num);
         num = (num < 500) ? (num * 2) : 0x3e8;
         goto Label_0032;
     }
 }
 private void Login(ServerInfo server, TimeoutTimer timeout, string newPassword)
 {
     SqlLogin rec = new SqlLogin();
     base.CurrentDatabase = server.ResolvedDatabaseName;
     this._currentPacketSize = base.ConnectionOptions.PacketSize;
     this._currentLanguage = base.ConnectionOptions.CurrentLanguage;
     int num2 = 0;
     if (!timeout.IsInfinite)
     {
         long num = timeout.MillisecondsRemaining / 0x3e8L;
         if (0x7fffffffL > num)
         {
             num2 = (int) num;
         }
     }
     rec.timeout = num2;
     rec.userInstance = base.ConnectionOptions.UserInstance;
     rec.hostName = base.ConnectionOptions.ObtainWorkstationId();
     rec.userName = base.ConnectionOptions.UserID;
     rec.password = base.ConnectionOptions.Password;
     rec.applicationName = base.ConnectionOptions.ApplicationName;
     rec.language = this._currentLanguage;
     if (!rec.userInstance)
     {
         rec.database = base.CurrentDatabase;
         rec.attachDBFilename = base.ConnectionOptions.AttachDBFilename;
     }
     rec.serverName = server.UserServerName;
     rec.useReplication = base.ConnectionOptions.Replication;
     rec.useSSPI = base.ConnectionOptions.IntegratedSecurity;
     rec.packetSize = this._currentPacketSize;
     rec.newPassword = newPassword;
     rec.readOnlyIntent = base.ConnectionOptions.ApplicationIntent == ApplicationIntent.ReadOnly;
     this._parser.TdsLogin(rec);
 }
    // Common code path for making one attempt to establish a connection and log in to server.
    private void AttemptOneLogin(ServerInfo serverInfo, string newPassword, SecureString newSecurePassword, bool ignoreSniOpenTimeout, TimeoutTimer timeout, bool withFailover = false, bool isFirstTransparentAttempt = true) {
        if (Bid.AdvancedOn) {
            Bid.Trace("<sc.SqlInternalConnectionTds.AttemptOneLogin|ADV> %d#, timout=%I64d{msec}, server=", ObjectID, timeout.MillisecondsRemaining);
            Bid.PutStr(serverInfo.ExtendedServerName);
            Bid.Trace("\n");
        }

        _routingInfo = null; // forget routing information 

        _parser._physicalStateObj.SniContext = SniContext.Snix_Connect;

        _parser.Connect(serverInfo,
                        this,
                        ignoreSniOpenTimeout,
                        timeout.LegacyTimerExpire,
                        ConnectionOptions.Encrypt,
                        ConnectionOptions.TrustServerCertificate,
                        ConnectionOptions.IntegratedSecurity,
                        withFailover,
                        isFirstTransparentAttempt,
                        ConnectionOptions.Authentication);

        timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);
        timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.LoginBegin);

        _parser._physicalStateObj.SniContext = SniContext.Snix_Login;
        this.Login(serverInfo, timeout, newPassword, newSecurePassword);

        timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth);
        timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PostLogin);

        CompleteLogin(!ConnectionOptions.Pooling);

        timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin);
    }
        // Common code path for making one attempt to establish a connection and log in to server.
        private void AttemptOneLogin(ServerInfo serverInfo,
                                bool ignoreSniOpenTimeout,
                                    TimeoutTimer timeout,
                                    bool withFailover = false)
        {
            _routingInfo = null; // forget routing information 

            _parser._physicalStateObj.SniContext = SniContext.Snix_Connect;

            _parser.Connect(serverInfo,
                            this,
                            ignoreSniOpenTimeout,
                            timeout.LegacyTimerExpire,
                            ConnectionOptions.Encrypt,
                            ConnectionOptions.TrustServerCertificate,
                            ConnectionOptions.IntegratedSecurity,
                            withFailover);

            _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ConsumePreLoginHandshake);
            _timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.LoginBegin);

            _parser._physicalStateObj.SniContext = SniContext.Snix_Login;
            this.Login(serverInfo, timeout);

            _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.ProcessConnectionAuth);
            _timeoutErrorInternal.SetAndBeginPhase(SqlConnectionTimeoutErrorPhase.PostLogin);

            CompleteLogin(!ConnectionOptions.Pooling);

            _timeoutErrorInternal.EndPhase(SqlConnectionTimeoutErrorPhase.PostLogin);
        }
示例#17
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;
                }
            }
        }