/// <summary>
        /// It is called when SQL batch request arrives
        /// </summary>
        public virtual TDSMessageCollection OnSQLBatchRequest(ITDSServerSession session, TDSMessage message)
        {
            // Delegate to the query engine
            TDSMessageCollection responseMessage = Engine.ExecuteBatch(session, message);

            // Check if session packet size is different than the engine packet size
            if (session.PacketSize != Arguments.PacketSize)
            {
                // Get the first message
                TDSMessage firstMessage = responseMessage[0];

                // Find DONE token in it
                int indexOfDone = firstMessage.IndexOf(firstMessage.Where(t => t is TDSDoneToken).First());

                // Create new packet size environment change token
                TDSEnvChangeToken envChange = new TDSEnvChangeToken(TDSEnvChangeTokenType.PacketSize, Arguments.PacketSize.ToString(), session.PacketSize.ToString());

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", envChange);

                // Insert env change before done token
                firstMessage.Insert(indexOfDone, envChange);

                // Update session with the new packet size
                session.PacketSize = (uint)Arguments.PacketSize;
            }

            return(responseMessage);
        }
        /// <summary>
        /// Handler for pre-login request
        /// </summary>
        public override TDSMessageCollection OnPreLoginRequest(ITDSServerSession session, TDSMessage request)
        {
            // Delegate to the base class
            TDSMessageCollection response = base.OnPreLoginRequest(session, request);

            // Check if arguments are of the routing server
            if (Arguments is RoutingTDSServerArguments)
            {
                // Cast to routing server arguments
                RoutingTDSServerArguments serverArguments = Arguments as RoutingTDSServerArguments;

                // Check if routing is configured during login
                if (serverArguments.RouteOnPacket == TDSMessageType.TDS7Login)
                {
                    // Check if pre-login response is contained inside the first message
                    if (response.Count > 0 && response[0].Any(t => t is TDSPreLoginToken))
                    {
                        // Find the first prelogin token
                        TDSPreLoginToken preLoginResponse = (TDSPreLoginToken)response[0].Where(t => t is TDSPreLoginToken).First();

                        // Inflate pre-login request from the message
                        TDSPreLoginToken preLoginRequest = request[0] as TDSPreLoginToken;

                        // Update MARS with the requested value
                        preLoginResponse.IsMARS = preLoginRequest.IsMARS;
                    }
                }
            }

            return(response);
        }
        /// <summary>
        /// Handler for login request
        /// </summary>
        public override TDSMessageCollection OnLogin7Request(ITDSServerSession session, TDSMessage request)
        {
            // Get the collection from the normal behavior On Login7 Request
            TDSMessageCollection login7Collection = base.OnLogin7Request(session, request);

            // Check if arguments are of the Federated Authentication server
            if (Arguments is FederatedAuthenticationNegativeTDSServerArguments)
            {
                // Cast to federated authentication server arguments
                FederatedAuthenticationNegativeTDSServerArguments ServerArguments = Arguments as FederatedAuthenticationNegativeTDSServerArguments;

                // Get the Federated Authentication ExtAck from Login 7
                TDSFeatureExtAckFederatedAuthenticationOption fedAutExtAct = GetFeatureExtAckFederatedAuthenticationOptionFromLogin7(login7Collection);

                // If not found, return the base collection intact
                if (fedAutExtAct != null)
                {
                    switch (ServerArguments.Scenario)
                    {
                    case FederatedAuthenticationNegativeTDSScenarioType.NonceMissingInFedAuthFEATUREXTACK:
                    {
                        // Delete the nonce from the Token
                        fedAutExtAct.ClientNonce = null;

                        break;
                    }

                    case FederatedAuthenticationNegativeTDSScenarioType.FedAuthMissingInFEATUREEXTACK:
                    {
                        // Remove the Fed Auth Ext Ack from the options list in the FeatureExtAckToken
                        GetFeatureExtAckTokenFromLogin7(login7Collection).Options.Remove(fedAutExtAct);

                        break;
                    }

                    case FederatedAuthenticationNegativeTDSScenarioType.SignatureMissingInFedAuthFEATUREXTACK:
                    {
                        // Delete the signature from the Token
                        fedAutExtAct.Signature = null;

                        break;
                    }
                    }
                }
            }

            // Return the collection
            return(login7Collection);
        }
        /// <summary>
        /// It is called when SQL batch request arrives
        /// </summary>
        /// <param name="message">TDS message recieved</param>
        /// <returns>TDS message to respond with</returns>
        public override TDSMessageCollection OnSQLBatchRequest(ITDSServerSession session, TDSMessage request)
        {
            // Delegate to the base class to produce the response first
            TDSMessageCollection batchResponse = base.OnSQLBatchRequest(session, request);

            // Check if arguments are of routing server
            if (Arguments is RoutingTDSServerArguments)
            {
                // Cast to routing server arguments
                RoutingTDSServerArguments ServerArguments = Arguments as RoutingTDSServerArguments;

                // Check routing condition
                if (ServerArguments.RouteOnPacket == TDSMessageType.SQLBatch)
                {
                    // Construct routing token
                    TDSPacketToken routingToken = CreateRoutingToken();

                    // Log response
                    TDSUtilities.Log(Arguments.Log, "Response", routingToken);

                    // Insert the routing token at the beginning of the response
                    batchResponse[0].Insert(0, routingToken);
                }
                else
                {
                    // Get the first response message
                    TDSMessage responseMessage = batchResponse[0];

                    // Reset the content of the first message
                    responseMessage.Clear();

                    // Prepare ERROR token with the denial details
                    responseMessage.Add(new TDSErrorToken(11111, 1, 14, "Client should have been routed by now", Arguments.ServerName));

                    // Log response
                    TDSUtilities.Log(Arguments.Log, "Response", responseMessage[0]);

                    // Prepare DONE token
                    responseMessage.Add(new TDSDoneToken(TDSDoneTokenStatusType.Final | TDSDoneTokenStatusType.Error));

                    // Log response
                    TDSUtilities.Log(Arguments.Log, "Response", responseMessage[1]);
                }
            }

            // Register only one message with the collection
            return(batchResponse);
        }
        /// <summary>
        /// Handler for login request
        /// </summary>
        public override TDSMessageCollection OnPreLoginRequest(ITDSServerSession session, TDSMessage request)
        {
            // Get the collection from a valid On PreLogin Request
            TDSMessageCollection preLoginCollection = base.OnPreLoginRequest(session, request);

            // Check if arguments are of the Federated Authentication server
            if (Arguments is FederatedAuthenticationNegativeTDSServerArguments)
            {
                // Cast to federated authentication server arguments
                FederatedAuthenticationNegativeTDSServerArguments ServerArguments = Arguments as FederatedAuthenticationNegativeTDSServerArguments;

                // Find the is token carrying on TDSPreLoginToken
                TDSPreLoginToken preLoginToken = preLoginCollection.Find(message => message.Exists(packetToken => packetToken is TDSPreLoginToken)).
                                                 Find(packetToken => packetToken is TDSPreLoginToken) as TDSPreLoginToken;

                switch (ServerArguments.Scenario)
                {
                case FederatedAuthenticationNegativeTDSScenarioType.NonceMissingInFedAuthPreLogin:
                {
                    // If we have the prelogin token
                    if (preLoginToken != null && preLoginToken.Nonce != null)
                    {
                        // Nullify the nonce from the Token
                        preLoginToken.Nonce = null;
                    }

                    break;
                }

                case FederatedAuthenticationNegativeTDSScenarioType.InvalidB_FEDAUTHREQUIREDResponse:
                {
                    // If we have the prelogin token
                    if (preLoginToken != null)
                    {
                        // Set an illegal value for B_FEDAUTHREQURED
                        preLoginToken.FedAuthRequired = TdsPreLoginFedAuthRequiredOption.Illegal;
                    }

                    break;
                }
                }
            }

            // Return the collection
            return(preLoginCollection);
        }
        /// <summary>
        /// Complete login sequence
        /// </summary>
        protected override TDSMessageCollection OnAuthenticationCompleted(ITDSServerSession session)
        {
            // Delegate to the base class
            TDSMessageCollection responseMessageCollection = base.OnAuthenticationCompleted(session);

            // Check if arguments are of routing server
            if (Arguments is RoutingTDSServerArguments)
            {
                // Cast to routing server arguments
                RoutingTDSServerArguments serverArguments = Arguments as RoutingTDSServerArguments;

                // Check routing condition
                if (serverArguments.RouteOnPacket == TDSMessageType.TDS7Login)
                {
                    // Construct routing token
                    TDSPacketToken routingToken = CreateRoutingToken();

                    // Log response
                    TDSUtilities.Log(Arguments.Log, "Response", routingToken);

                    // Get the first message
                    TDSMessage targetMessage = responseMessageCollection[0];

                    // Index at which to insert the routing token
                    int insertIndex = targetMessage.Count - 1;

                    // VSTS# 1021027 - Read-Only Routing yields TDS protocol error
                    // Resolution: Send TDS FeatureExtAct token before TDS ENVCHANGE token with routing information
                    TDSPacketToken featureExtAckToken = targetMessage.Find(t => t is TDSFeatureExtAckToken);

                    // Check if found
                    if (featureExtAckToken != null)
                    {
                        // Find token position
                        insertIndex = targetMessage.IndexOf(featureExtAckToken);
                    }

                    // Insert right before the done token
                    targetMessage.Insert(insertIndex, routingToken);
                }
            }

            return(responseMessageCollection);
        }
        /// <summary>
        /// Complete the Federated Login
        /// </summary>
        /// <param name="session">Server session</param>
        /// <returns>Federated Login message collection</returns>
        protected virtual TDSMessageCollection OnFederatedAuthenticationCompleted(ITDSServerSession session, byte[] ticket)
        {
            // Delegate to successful authentication routine
            TDSMessageCollection responseMessageCollection = OnAuthenticationCompleted(session);

            // Get the last message
            TDSMessage targetMessage = responseMessageCollection.Last();

            IFederatedAuthenticationTicket decryptedTicket = null;

            try
            {
                // Get the Federated Authentication ticket using RPS
                decryptedTicket = FederatedAuthenticationTicketService.DecryptTicket((session as GenericTDSServerSession).FederatedAuthenticationLibrary, ticket);

                if (decryptedTicket is RpsTicket)
                {
                    TDSUtilities.Log(Arguments.Log, "RPS ticket session key: ", (decryptedTicket as RpsTicket).sessionKey);
                }
                else if (decryptedTicket is JwtTicket)
                {
                    TDSUtilities.Log(Arguments.Log, "JWT Ticket Received", null);
                }
            }
            catch (Exception ex)
            {
                // Prepare ERROR token
                TDSErrorToken errorToken = new TDSErrorToken(54879, 1, 20, "Authentication error in Federated Authentication Ticket Service: " + ex.Message, Arguments.ServerName);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", errorToken);

                // Create DONE token
                TDSDoneToken doneToken = new TDSDoneToken(TDSDoneTokenStatusType.Final | TDSDoneTokenStatusType.Error);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", doneToken);

                // Return the message and stop processing request
                return(new TDSMessageCollection(new TDSMessage(TDSMessageType.Response, errorToken, doneToken)));
            }

            // Create federated authentication extension option
            TDSFeatureExtAckFederatedAuthenticationOption federatedAuthenticationOption;

            if ((session as GenericTDSServerSession).FederatedAuthenticationLibrary == TDSFedAuthLibraryType.MSAL)
            {
                // For the time being, fake fedauth tokens are used for ADAL, so decryptedTicket is null.
                federatedAuthenticationOption =
                    new TDSFeatureExtAckFederatedAuthenticationOption((session as GenericTDSServerSession).ClientNonce, null);
            }
            else
            {
                federatedAuthenticationOption =
                    new TDSFeatureExtAckFederatedAuthenticationOption((session as GenericTDSServerSession).ClientNonce,
                                                                      decryptedTicket.GetSignature((session as GenericTDSServerSession).ClientNonce));
            }

            // Look for feature extension token
            TDSFeatureExtAckToken featureExtActToken = (TDSFeatureExtAckToken)targetMessage.Where(t => t is TDSFeatureExtAckToken).FirstOrDefault();

            // Check if response already contains federated authentication
            if (featureExtActToken == null)
            {
                // Create Feature extension Ack token
                featureExtActToken = new TDSFeatureExtAckToken(federatedAuthenticationOption);

                // Serialize feature extension token into the response
                // The last token is Done token, so we should put feautureextack token before done token
                targetMessage.Insert(targetMessage.Count - 1, featureExtActToken);
            }
            else
            {
                // Update
                featureExtActToken.Options.Add(federatedAuthenticationOption);
            }

            // Log response
            TDSUtilities.Log(Arguments.Log, "Response", federatedAuthenticationOption);

            // Wrap a message with a collection
            return(responseMessageCollection);
        }
        /// <summary>
        /// Advances one step in SSPI authentication sequence
        /// </summary>
        protected virtual TDSMessageCollection ContinueSSPIAuthentication(ITDSServerSession session, byte[] payload)
        {
            // Response to send to the client
            SSPIResponse response;

            try
            {
                // Check if we have an SSPI context
                if (session.NTUserAuthenticationContext == null)
                {
                    // This is the first step so we need to create a server context and initialize it
                    session.NTUserAuthenticationContext = SSPIContext.CreateServer();

                    // Run the first step of authentication
                    response = session.NTUserAuthenticationContext.StartServerAuthentication(payload);
                }
                else
                {
                    // Process SSPI request from the client
                    response = session.NTUserAuthenticationContext.ContinueServerAuthentication(payload);
                }
            }
            catch (Exception e)
            {
                // Prepare ERROR token with the reason
                TDSErrorToken errorToken = new TDSErrorToken(12345, 1, 15, "Failed to accept security SSPI context", Arguments.ServerName);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", errorToken);

                // Serialize the error token into the response packet
                TDSMessage responseErrorMessage = new TDSMessage(TDSMessageType.Response, errorToken);

                // Prepare ERROR token with the final errorToken
                errorToken = new TDSErrorToken(12345, 1, 15, e.Message, Arguments.ServerName);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", errorToken);

                // Serialize the error token into the response packet
                responseErrorMessage.Add(errorToken);

                // Create DONE token
                TDSDoneToken doneToken = new TDSDoneToken(TDSDoneTokenStatusType.Final | TDSDoneTokenStatusType.Error);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", doneToken);

                // Serialize DONE token into the response packet
                responseErrorMessage.Add(doneToken);

                // Respond with a single message
                return(new TDSMessageCollection(responseErrorMessage));
            }

            // Message collection to respond with
            TDSMessageCollection responseMessages = new TDSMessageCollection();

            // Check if there's a response
            if (response != null)
            {
                // Check if there's a payload
                if (response.Payload != null)
                {
                    // Create SSPI token
                    TDSSSPIToken sspiToken = new TDSSSPIToken(response.Payload);

                    // Log response
                    TDSUtilities.Log(Arguments.Log, "Response", sspiToken);

                    // Prepare response message with a single response token
                    responseMessages.Add(new TDSMessage(TDSMessageType.Response, sspiToken));

                    // Check if we can complete login
                    if (!response.IsFinal)
                    {
                        // Send the message to the client
                        return(responseMessages);
                    }
                }
            }

            // Reset SQL user identifier since we're using NT authentication
            session.SQLUserID = null;

            // Append successfully authentication response
            responseMessages.AddRange(OnAuthenticationCompleted(session));

            // Return the message with SSPI token
            return(responseMessages);
        }
        /// <summary>
        /// Handler for login request
        /// </summary>
        public virtual TDSMessageCollection OnLogin7Request(ITDSServerSession session, TDSMessage request)
        {
            // Inflate login7 request from the message
            TDSLogin7Token loginRequest = request[0] as TDSLogin7Token;

            // Log request
            TDSUtilities.Log(Arguments.Log, "Request", loginRequest);

            // Update server context
            session.Database = string.IsNullOrEmpty(loginRequest.Database) ? "master" : loginRequest.Database;

            // Resolve TDS version
            session.TDSVersion = TDSVersion.Resolve(TDSVersion.GetTDSVersion(Arguments.ServerVersion), loginRequest.TDSVersion);

            // Check for the TDS version
            TDSMessageCollection collection = CheckTDSVersion(session);

            // Check if any errors are posted
            if (collection != null)
            {
                // Version check needs to send own message hence we can't proceed
                return(collection);
            }

            // Indicates federated authentication
            bool bIsFedAuthConnection = false;

            // Federated authentication option to be used later
            TDSLogin7FedAuthOptionToken federatedAuthenticationOption = null;

            // Check if feature extension block is available
            if (loginRequest.FeatureExt != null)
            {
                // Go over the feature extension data
                foreach (TDSLogin7FeatureOptionToken option in loginRequest.FeatureExt)
                {
                    // Check option type
                    switch (option.FeatureID)
                    {
                    case TDSFeatureID.SessionRecovery:
                    {
                        // Enable session recovery
                        session.IsSessionRecoveryEnabled = true;

                        // Cast to session state options
                        TDSLogin7SessionRecoveryOptionToken sessionStateOption = option as TDSLogin7SessionRecoveryOptionToken;

                        // Inflate session state
                        (session as GenericTDSServerSession).Inflate(sessionStateOption.Initial, sessionStateOption.Current);

                        break;
                    }

                    case TDSFeatureID.FederatedAuthentication:
                    {
                        // Cast to federated authentication option
                        federatedAuthenticationOption = option as TDSLogin7FedAuthOptionToken;

                        // Mark authentication as federated
                        bIsFedAuthConnection = true;

                        // Validate federated authentication option
                        collection = CheckFederatedAuthenticationOption(session, option as TDSLogin7FedAuthOptionToken);

                        if (collection != null)
                        {
                            // Version error happened.
                            return(collection);
                        }

                        // Save the fed auth library to be used
                        (session as GenericTDSServerSession).FederatedAuthenticationLibrary = federatedAuthenticationOption.Library;

                        break;
                    }

                    default:
                    {
                        // Do nothing
                        break;
                    }
                    }
                }
            }

            // Check if SSPI authentication is requested
            if (loginRequest.OptionalFlags2.IntegratedSecurity == TDSLogin7OptionalFlags2IntSecurity.On)
            {
                // Delegate to SSPI authentication
                return(ContinueSSPIAuthentication(session, loginRequest.SSPI));
            }

            // If it is not a FedAuth connection or the server has been started up as not supporting FedAuth, just ignore the FeatureExtension
            // Yes unfortunately for the fake server, supporting FedAuth = Requiring FedAuth
            if (!bIsFedAuthConnection ||
                Arguments.FedAuthRequiredPreLoginOption == TdsPreLoginFedAuthRequiredOption.FedAuthNotRequired)
            {
                // We use SQL authentication
                session.SQLUserID = loginRequest.UserID;

                // Process with the SQL login.
                return(OnSqlAuthenticationCompleted(session));
            }
            else
            {
                // Fedauth feature extension is present and server has been started up as Requiring (or Supporting) FedAuth
                if (federatedAuthenticationOption.IsRequestingAuthenticationInfo)
                {
                    // Must provide client with more info before completing authentication
                    return(OnFederatedAuthenticationInfoRequest(session));
                }
                else
                {
                    return(OnFederatedAuthenticationCompleted(session, federatedAuthenticationOption.Token));
                }
            }
        }
 private TDSFeatureExtAckFederatedAuthenticationOption GetFeatureExtAckFederatedAuthenticationOptionFromLogin7(TDSMessageCollection login7Collection)
 {
     // Get the Fed Auth Ext Ack from the list of options in the feature ExtAck
     return(GetFeatureExtAckTokenFromLogin7(login7Collection).Options.
            Where(o => o is TDSFeatureExtAckFederatedAuthenticationOption).FirstOrDefault() as TDSFeatureExtAckFederatedAuthenticationOption);
 }
 private TDSFeatureExtAckToken GetFeatureExtAckTokenFromLogin7(TDSMessageCollection login7Collection)
 {
     // Find the is token carrying on TDSFeatureExtAckToken
     return(login7Collection.Find(m => m.Exists(p => p is TDSFeatureExtAckToken)).
            Find(t => t is TDSFeatureExtAckToken) as TDSFeatureExtAckToken);
 }
        /// <summary>
        /// Run one cycle of the parser to process incoming stream of data or dispatch outgoing data
        /// </summary>
        public void Run()
        {
            // Check if there's a message being inflated
            if (MessageBeingReceived == null)
            {
                // Create a new message
                MessageBeingReceived = new TDSMessage();
            }

            // Inflate the message using incoming stream
            // This call will use only as much data is it needs and leave everything else on the stream
            if (MessageBeingReceived.InflateClientRequest(Transport))
            {
                // Call into the server logics to process the message and generate the response
                TDSMessageCollection responseMessages = null;

                // Check the type of the packet
                switch (MessageBeingReceived.MessageType)
                {
                case TDSMessageType.PreLogin:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnPreLoginRequest(Session, MessageBeingReceived);
                    break;
                }

                case TDSMessageType.TDS7Login:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnLogin7Request(Session, MessageBeingReceived);

                    // Check if encryption needs to be turned off
                    if (Session.Encryption == TDSEncryptionType.LoginOnly)
                    {
                        // Disable transport encryption
                        DisableTransportEncryption();
                    }

                    break;
                }

                case TDSMessageType.SSPI:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnSSPIRequest(Session, MessageBeingReceived);
                    break;
                }

                case TDSMessageType.SQLBatch:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnSQLBatchRequest(Session, MessageBeingReceived);
                    break;
                }

                case TDSMessageType.Attention:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnAttention(Session, MessageBeingReceived);
                    break;
                }

                case TDSMessageType.FederatedAuthenticationToken:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnFederatedAuthenticationTokenMessage(Session, MessageBeingReceived);
                    break;
                }

                case TDSMessageType.RPC:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnRPCRequest(Session, MessageBeingReceived);
                    break;
                }

                case TDSMessageType.TransactionManager:
                {
                    // Call into the subscriber to process the packet
                    responseMessages = Server.OnTransactionManagerRequest(Session, MessageBeingReceived);
                    break;
                }

                default:
                {
                    // New code is needed to process this message
                    throw new NotImplementedException(string.Format("Handler of TDS message \"{0}\" is not implemented", MessageBeingReceived.MessageType));
                }
                }

                // Check if TDS packet size changed
                if (Session.PacketSize != Transport.PacketSize)
                {
                    // Update packet size
                    Transport.PacketSize = Session.PacketSize;
                }

                // Send all messages to the client
                responseMessages.Deflate(Transport);

                // Check the type of message just sent
                if (MessageBeingReceived.MessageType == TDSMessageType.PreLogin)
                {
                    // Check encryption settings on the session
                    if (Session.Encryption == TDSEncryptionType.LoginOnly || Session.Encryption == TDSEncryptionType.Full)
                    {
                        // Enable server side encryption
                        EnableServerTransportEncryption(Session.EncryptionCertificate);
                    }
                }

                // Reset the current message because it's complete
                // It would also trigger creation of the next message during the next cycle
                MessageBeingReceived = null;
            }
        }
Example #13
0
        /// <summary>
        /// Advances one step in SSPI authentication sequence
        /// </summary>
        protected virtual TDSMessageCollection ContinueSSPIAuthentication(ITDSServerSession session, byte[] payload)
        {
            // Response to send to the client
            SSPIResponse response;

            try
            {
                // Check if we have an SSPI context
                if (session.NTUserAuthenticationContext == null)
                {
                    // This is the first step so we need to create a server context and initialize it
                    session.NTUserAuthenticationContext = SSPIContext.CreateServer();

                    // Run the first step of authentication
                    response = session.NTUserAuthenticationContext.StartServerAuthentication(payload);
                }
                else
                {
                    // Process SSPI request from the client
                    response = session.NTUserAuthenticationContext.ContinueServerAuthentication(payload);
                }
            }
            catch (Exception e)
            {
                // Prepare ERROR token with the reason
                TDSErrorToken errorToken = new TDSErrorToken(12345, 1, 15, "Failed to accept security SSPI context", Arguments.ServerName);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", errorToken);

                // Serialize the error token into the response packet
                TDSMessage responseErrorMessage = new TDSMessage(TDSMessageType.Response, errorToken);

                // Prepare ERROR token with the final errorToken
                errorToken = new TDSErrorToken(12345, 1, 15, e.Message, Arguments.ServerName);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", errorToken);

                // Serialize the error token into the response packet
                responseErrorMessage.Add(errorToken);

                // Create DONE token
                TDSDoneToken doneToken = new TDSDoneToken(TDSDoneTokenStatusType.Final | TDSDoneTokenStatusType.Error);

                // Log response
                TDSUtilities.Log(Arguments.Log, "Response", doneToken);

                // Serialize DONE token into the response packet
                responseErrorMessage.Add(doneToken);

                // Respond with a single message
                return new TDSMessageCollection(responseErrorMessage);
            }

            // Message collection to respond with
            TDSMessageCollection responseMessages = new TDSMessageCollection();

            // Check if there's a response
            if (response != null)
            {
                // Check if there's a payload
                if (response.Payload != null)
                {
                    // Create SSPI token
                    TDSSSPIToken sspiToken = new TDSSSPIToken(response.Payload);

                    // Log response
                    TDSUtilities.Log(Arguments.Log, "Response", sspiToken);

                    // Prepare response message with a single response token
                    responseMessages.Add(new TDSMessage(TDSMessageType.Response, sspiToken));

                    // Check if we can complete login
                    if (!response.IsFinal)
                    {
                        // Send the message to the client
                        return responseMessages;
                    }
                }
            }

            // Reset SQL user identifier since we're using NT authentication
            session.SQLUserID = null;

            // Append successfully authentication response
            responseMessages.AddRange(OnAuthenticationCompleted(session));

            // Return the message with SSPI token
            return responseMessages;
        }
 private TDSFeatureExtAckFederatedAuthenticationOption GetFeatureExtAckFederatedAuthenticationOptionFromLogin7(TDSMessageCollection login7Collection)
 {
     // Get the Fed Auth Ext Ack from the list of options in the feature ExtAck
     return GetFeatureExtAckTokenFromLogin7(login7Collection).Options.
         Where(o => o is TDSFeatureExtAckFederatedAuthenticationOption).FirstOrDefault() as TDSFeatureExtAckFederatedAuthenticationOption;
 }
 private TDSFeatureExtAckToken GetFeatureExtAckTokenFromLogin7(TDSMessageCollection login7Collection)
 {
     // Find the is token carrying on TDSFeatureExtAckToken
     return login7Collection.Find(m => m.Exists(p => p is TDSFeatureExtAckToken)).
         Find(t => t is TDSFeatureExtAckToken) as TDSFeatureExtAckToken;
 }