/// <summary> /// Ensure that federated authentication option is valid /// </summary> protected virtual TDSMessageCollection CheckFederatedAuthenticationOption(ITDSServerSession session, TDSLogin7FedAuthOptionToken federatedAuthenticationOption) { // Check if server's prelogin response for FedAuthRequired prelogin option is echoed back correctly in FedAuth Feature Extenion Echo if (federatedAuthenticationOption.Echo != (session as GenericTDSServerSession).FedAuthRequiredPreLoginServerResponse) { // Create Error message string message = string.Format("FEDAUTHREQUIRED option in the prelogin response is not echoed back correctly: in prelogin response, it is {0} and in login, it is {1}: ", (session as GenericTDSServerSession).FedAuthRequiredPreLoginServerResponse, federatedAuthenticationOption.Echo); // Create errorToken token TDSErrorToken errorToken = new TDSErrorToken(3456, 34, 23, message); // 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); // Build a collection with a single message of two tokens return(new TDSMessageCollection(new TDSMessage(TDSMessageType.Response, errorToken, doneToken))); } // Check if the nonce exists if ((federatedAuthenticationOption.Nonce == null && federatedAuthenticationOption.Library == TDSFedAuthLibraryType.IDCRL) || !AreEqual((session as GenericTDSServerSession).ServerNonce, federatedAuthenticationOption.Nonce)) { // Error message string message = string.Format("Unexpected NONCEOPT specified in the Federated authentication feature extension"); // Create errorToken token TDSErrorToken errorToken = new TDSErrorToken(5672, 32, 87, message); // 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); // Build a collection with a single message of two tokens return(new TDSMessageCollection(new TDSMessage(TDSMessageType.Response, errorToken, doneToken))); } // We're good return(null); }
/// <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)); } } }