public static void LogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId)
        {
            VerifyConnection(connectionId);
            Condition.IsNull(ConnectionList[connectionId].Request);

            // Reduce states
            Combination.NWise(1, connectionId, sessionId);

            // If no session exists before, then any session id is invalid
            Condition.IfThen(ConnectionList[connectionId].Session == null, sessionId == ModelSessionId.InvalidSessionId);

            // If the session id in LogOff request is different from the existing one, then the id is invalid.
            Condition.IfThen(ConnectionList[connectionId].Session != null && ConnectionList[connectionId].Session.SessionId != sessionId,
                             sessionId == ModelSessionId.InvalidSessionId);

            if (ConnectionList[connectionId].Session == null &&
                ConnectionList[connectionId].ConstrainedConnection)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.2.9: The server MUST look up the Session in Connection.SessionTable by using the SessionId in the SMB2 header of the request. " +
                                "If Connection.SessionTable is empty and Connection.ConstrainedConnection is TRUE, the server SHOULD<210> disconnect the connection. ");
                ModelHelper.Log(LogType.TestInfo, "Connection.SessionTable is empty and Connection.ConstrainedConnection is TRUE");
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                // server SHOULD disconnect the connection
                ConnectionList[connectionId].ConnectionState = ModelState.Disconnected;
                return;
            }

            ConnectionList[connectionId].Request = new ModelLogOffRequest(connectionId, sessionId);
        }
        private static bool VerifyFootnote(ModelConnectionId connectionId, SessionMgmtConfig c, ModelSmb2Status?status)
        {
            Condition.IsTrue(config.Platform == c.Platform);

            if ((config.Platform == Platform.WindowsServer2008 || config.Platform == Platform.WindowsServer2008R2) &&
                ConnectionList.ContainsKey(connectionId) && ConnectionList[connectionId].Session == null)
            {
                ModelHelper.Log(LogType.Requirement,
                                "<210> Section 3.3.5.2.9: Windows Vista, Windows Server 2008, Windows 7, and Windows Server 2008 R2 fail the request with STATUS_USER_SESSION_DELETED. " +
                                "If Connection.ConstrainedConnection is FALSE and Connection.SessionTable is empty, then server MUST fail any request with STATUS_USER_SESSION_DELETED. ");
                // No matter Connection.ConstrainedConnection is FALSE or TRUE, Windows Server 2008 and 2008 R2 will fail the Log off request.
                ModelHelper.Log(LogType.TestInfo,
                                "The SUT platform is {0}, Connection.ConstrainedConnection is {1}, and Connection.SessionTable is empty",
                                config.Platform, ConnectionList[connectionId].ConstrainedConnection);
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                if (status == null)
                {
                    // null means SUT terminates the connection.
                    // but SUT should return STATUS_USER_SESSION_DELETED
                    Condition.IsTrue(false);
                }
                else
                {
                    Condition.IsTrue(status.Value == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                }
                // Return true stands for this function handles the message, no more actions needed.
                return(true);
            }
            // Go on processing message.
            return(false);
        }
        public static void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            VerifyConnection(connectionId);
            Condition.IsNull(ConnectionList[connectionId].Request);

            #region Combinations

            Combination.NWise(1, connectionId, sessionId, previousSessionId, signed, flags, user);
            #endregion

            #region Other contraints

            // Do not estabilish 2nd session if no session exist yet
            Condition.IfThen(GlobalSessionTable.Count == 0,
                             sessionId != ModelSessionId.AlternativeSessionId &&
                             user == ModelUser.DefaultUser);

            // Do not establish new session if there's one in the requested connection
            Condition.IfThen(ConnectionList[connectionId].Session != null, sessionId != ModelSessionId.ZeroSessionId);

            // Do not establish new session if 2 sessions exist
            Condition.IfThen(GlobalSessionTable.Count == 2, sessionId != ModelSessionId.ZeroSessionId);

            // Do not set previousSessionId to session1 if currently establish session1
            Condition.IfThen(GlobalSessionTable.Count == 0 &&
                             sessionId == ModelSessionId.ZeroSessionId,
                             previousSessionId != ModelSessionId.MainSessionId);

            // If session id is zero, it's the same that the binding flag is set or not.
            Condition.IfThen(sessionId == ModelSessionId.ZeroSessionId, flags == ModelFlags.NotBinding);

            // Restrict the condition to no session exist yet as we only simulate one session in this Model
            Condition.IsNull(ConnectionList[connectionId].Session);

            // If we need to skip SessionSetup when it's re-auth an existing one
            if (ReAuthentication == ModelAllowReauthentication.NotAllowReauthentication)
            {
                Condition.IsTrue(ConnectionList[connectionId].Session == null ||
                                 ConnectionList[connectionId].Session.State != ModelSessionState.Valid);
            }

            #endregion

            ConnectionList[connectionId].Request = new ModelSessionSetupRequest(
                connectionId,
                sessionId,
                previousSessionId,
                signed == ModelSigned.SignFlagSet,
                flags,
                user);
        }
        private static T RetrieveOutstandingRequest <T>(ModelConnectionId connectionId) where T : ModelSMB2Request
        {
            ModelSMB2Request request = ConnectionList[connectionId].Request;

            ConnectionList[connectionId].Request = null;

            Condition.IsTrue(request is T);
            return(request as T);
        }
        public void LogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId)
        {
            ulong adapterSessionId;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            #endregion

            PrintCurrentSessionTable("Before LogOff Request");

            #region Send Request
            try
            {
                uint status;
                // Use desired explored sessionId
                ulong oldSessionId = connectionList[connectionId].SessionId;
                connectionList[connectionId].SessionId = adapterSessionId;
                status = connectionList[connectionId].LogOff(
                    (header, response) =>
                {
                    // do nothing, avoid exception when status != status_success
                });
                // Restore original sessionId
                connectionList[connectionId].SessionId = oldSessionId;

                if (status == Smb2Status.STATUS_SUCCESS)
                {
                    sessionTable.Remove(sessionId);
                }

                PrintCurrentSessionTable("After LogOff Request");

                LogOffResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
                return;
            }
            catch
            {
            }

            Site.Assert.IsTrue(connectionList[connectionId].Smb2Client.IsServerDisconnected, "Logoff failure should be caused by transport connection termination");

            ExpectDisconnect(connectionId, sessionMgmtConfig);
            sessionTable.Remove(sessionId);
            connectionList.Remove(connectionId);

            #endregion
        }
        public void LogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId)
        {
            ulong adapterSessionId;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            #endregion

            PrintCurrentSessionTable("Before LogOff Request");

            #region Send Request
            try
            {
                uint status;
                // Use desired explored sessionId
                ulong oldSessionId = connectionList[connectionId].SessionId;
                connectionList[connectionId].SessionId = adapterSessionId;
                status = connectionList[connectionId].LogOff(
                    (header, response) =>
                    {
                        // do nothing, avoid exception when status != status_success
                    });
                // Restore original sessionId
                connectionList[connectionId].SessionId = oldSessionId;

                if (status == Smb2Status.STATUS_SUCCESS)
                {
                    sessionTable.Remove(sessionId);
                }

                PrintCurrentSessionTable("After LogOff Request");

                LogOffResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
                return;
            }
            catch
            {
            }

            Site.Assert.IsTrue(connectionList[connectionId].Smb2Client.IsServerDisconnected, "Logoff failure should be caused by transport connection termination");

            ExpectDisconnect(connectionId, sessionMgmtConfig);
            sessionTable.Remove(sessionId);
            connectionList.Remove(connectionId);

            #endregion
        }
 private Guid GetClientGuid(ModelConnectionId connectionId, DialectRevision[] dialects)
 {
     if (dialects.Length == 1 && dialects[0] == DialectRevision.Smb2002)
     {
         return(Guid.Empty);
     }
     else if (connectionId == ModelConnectionId.MainConnection)
     {
         this.clientGuid = Guid.NewGuid();
         return(this.clientGuid);
     }
     else
     {
         return(this.clientGuid);
     }
 }
Exemple #8
0
 public ModelSessionSetupRequest(
     ModelConnectionId connectionId,
     ModelSessionId sessionId,
     ModelSessionId previousSessionId,
     bool isSigned,
     ModelFlags flags,
     ModelUser user
     )
     : base(0)
 {
     this.connectionId      = connectionId;
     this.sessionId         = sessionId;
     this.previousSessionId = previousSessionId;
     this.isSigned          = isSigned;
     this.flags             = flags;
     this.user = user;
 }
        public static void TerminateConnection(ModelConnectionId connectionId)
        {
            VerifyConnection(connectionId);

            if (ConnectionList[connectionId].Session != null)
            {
                ModelHelper.Log(LogType.Requirement, "3.3.7.1: the Session MUST be removed from GlobalSessionTable and freed. ");
                GlobalSessionTable.Remove(ConnectionList[connectionId].Session.SessionId);
            }

            // Disconnect and remove the connection
            ConnectionList[connectionId].ConnectionState = ModelState.Disconnected;

            ModelHelper.Log(LogType.Requirement, "3.3.7.1: The connection MUST be removed from ConnectionList and MUST be freed.");
            ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
            ConnectionList.Remove(connectionId);
        }
        public static void SetupConnection(ModelConnectionId connectionId, ModelDialectRevision clientMaxDialect)
        {
            // Restrict model contains 2 connections at most
            Condition.IsTrue(!ConnectionList.ContainsKey(connectionId));

            // Reduce states
            Combination.NWise(1, connectionId, clientMaxDialect);

            DialectRevision dialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, config.MaxSmbVersionSupported);

            // Establish new connection
            ConnectionList.Add(
                connectionId,
                new ModelConnection(dialect));

            ConnectionList[connectionId].ConnectionState = ModelState.Connected;

            ModelHelper.Log(LogType.Requirement, "3.3.5.1: Connection.ConstrainedConnection is set to TRUE.");
            ConnectionList[connectionId].ConstrainedConnection = true;
        }
        public static void ExpectDisconnect(ModelConnectionId connectionId, SessionMgmtConfig c)
        {
            if (VerifyFootnote(connectionId, c, null))
            {
                return;
            }

            Condition.IsTrue(ConnectionList.ContainsKey(connectionId));
            Condition.IsTrue(ConnectionList[connectionId].ConnectionState == ModelState.Disconnected);

            if (ConnectionList[connectionId].Session != null)
            {
                ModelHelper.Log(LogType.Requirement, "3.3.7.1: the Session MUST be removed from GlobalSessionTable and freed. ");
                GlobalSessionTable.Remove(ConnectionList[connectionId].Session.SessionId);
            }

            ModelHelper.Log(LogType.Requirement, "3.3.7.1: The connection MUST be removed from ConnectionList and MUST be freed.");
            ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
            ConnectionList.Remove(connectionId);
        }
Exemple #12
0
 public ModelLogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId)
     : base(0)
 {
     this.connectionId = connectionId;
     this.sessionId    = sessionId;
 }
 public void TerminateConnection(ModelConnectionId connectionId)
 {
     connectionList[connectionId].Disconnect();
     sessionTable.Remove(ModelSessionId.MainSessionId);
     connectionList.Remove(connectionId);
 }
        public void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            ulong adapterSessionId;
            ulong adapterPreviousSessionId;
            Packet_Header_Flags_Values headerFlags;
            SESSION_SETUP_Request_Flags sessionSetupFlags;
            AccountCredential credential;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];

                // For sessionId is 0 which indicates session creation
                // assign a new one
                if (sessionId == ModelSessionId.ZeroSessionId)
                {
                    if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId))
                    {
                        sessionId = ModelSessionId.MainSessionId;
                    }
                    else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId))
                    {
                        sessionId = ModelSessionId.AlternativeSessionId;
                    }
                }
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}",
                sessionId, adapterSessionId);

            #endregion

            #region previousSessionId
            if (sessionTable.ContainsKey(previousSessionId))
            {
                adapterPreviousSessionId = sessionTable[previousSessionId];
            }
            else
            {
                Random r = new Random();
                adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}",
                sessionId, adapterPreviousSessionId);

            #endregion

            #region isSigned

            headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            #endregion

            #region flags

            switch (flags)
            {
                case ModelFlags.Binding:
                    {
                        sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING;
                        break;
                    }
                case ModelFlags.NotBinding:
                    {
                        sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE;
                        break;
                    }
                default:
                    throw new ArgumentException("flags");
            }

            #endregion

            #region user

            switch (user)
            {
                case ModelUser.DefaultUser:
                    {
                        credential = testConfig.AccountCredential;
                        break;
                    }
                case ModelUser.DiffUser:
                    {
                        credential = testConfig.NonAdminAccountCredential;
                        break;
                    }
                default:
                    throw new ArgumentException("user");
            }

            #endregion

            #region MultipleChannel
            // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family
            bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect);
            #endregion

            PrintCurrentSessionTable("Before SessionSetup Request");

            #region Send Request

            uint status;
            SESSION_SETUP_Response? sessionSetupResponse = null;
            string serverName = testConfig.SutComputerName;
            SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage;
            bool useServerGssToken = testConfig.UseServerGssToken;

            // Use desired explored sessionId
            ulong oldSessionId = connectionList[connectionId].SessionId;
            connectionList[connectionId].SessionId = adapterSessionId;

            // alternative connection and never session setup
            if (connectionId == ModelConnectionId.AlternativeConnection
                && sessionId == ModelSessionId.MainSessionId
                && connectionList[connectionId].SessionKey == null
                && connectionList.ContainsKey(ModelConnectionId.MainConnection))
            {
                connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true);
            }

            status = connectionList[connectionId].SessionSetup(
                headerFlags,
                sessionSetupFlags,
                adapterPreviousSessionId,
                securityPackageType,
                serverName,
                credential,
                useServerGssToken,
                isMultipleChannelSupported,
                (header, response) =>
                {
                    sessionSetupResponse = response;
                });

            if (status != Smb2Status.STATUS_SUCCESS
                && status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)
            {
                // Restore original sessionId if request failed
                connectionList[connectionId].SessionId = oldSessionId;
            }

            #endregion

            // Insert session to session table
            if (!sessionTable.ContainsKey(sessionId)
                && (status == Smb2Status.STATUS_SUCCESS
                || status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED))
            {
                sessionTable.Add(sessionId, connectionList[connectionId].SessionId);
            }

            PrintCurrentSessionTable("After SessionSetup Request");

            SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
        }
 private static void VerifyConnection(ModelConnectionId connectionId)
 {
     // Ensure connection exist and connected
     Condition.IsTrue(ConnectionList.ContainsKey(connectionId));
     Condition.IsTrue(ConnectionList[connectionId].ConnectionState == ModelState.Connected);
 }
        public static void LogOffResponse(ModelSmb2Status status, ModelConnectionId connectionId, SessionMgmtConfig c)
        {
            Condition.IsTrue(config.Platform == c.Platform);
            if (config.Platform == Platform.NonWindows &&
                ConnectionList.ContainsKey(connectionId) &&
                ConnectionList[connectionId].Session == null &&
                ConnectionList[connectionId].ConstrainedConnection)
            {
                // The TD statements are logged in LogOffRequest
                ModelHelper.Log(LogType.TestInfo, "SUT platform is NonWindows, so server could return an error code instead of disconnect the connection.");
                Condition.IsTrue(status != ModelSmb2Status.STATUS_SUCCESS);
                return;
            }

            if (VerifyFootnote(connectionId, c, status))
            {
                return;
            }

            VerifyConnection(connectionId);
            Condition.IsNotNull(ConnectionList[connectionId].Request);

            ModelLogOffRequest logOffRequest = RetrieveOutstandingRequest <ModelLogOffRequest>(connectionId);

            if (ConnectionList[connectionId].Session != null && ConnectionList[connectionId].Session.SessionId != logOffRequest.sessionId)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.2.9: If Connection.SessionTable is not empty and SessionId is not found in Connection.SessionTable, " +
                                "the server MUST fail the request with STATUS_USER_SESSION_DELETED.");
                ModelHelper.Log(LogType.TestInfo, "Connection.SessionTable is not empty and SessionId of Logoff Request is not found in Connection.SessionTable");
                ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier);
                Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                return;
            }

            if (!ConnectionList[connectionId].ConstrainedConnection && ConnectionList[connectionId].Session == null)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.2.9: If Connection.ConstrainedConnection is FALSE and Connection.SessionTable is empty, then the server MUST fail any request with STATUS_USER_SESSION_DELETED.");
                ModelHelper.Log(LogType.TestInfo, "Connection.ConstrainedConnection is FALSE and Connection.SessionTable is empty.");
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                return;
            }

            if (GlobalSessionTable.ContainsKey(logOffRequest.sessionId))
            {
                if (GlobalSessionTable[logOffRequest.sessionId].State == ModelSessionState.InProgress)
                {
                    ModelHelper.Log(LogType.Requirement, "3.3.5.2.9: If Session.State is InProgress, the server MUST continue to process the SMB2 LOGOFF, SMB2 CLOSE, and SMB2 LOCK commands. ");
                    ModelHelper.Log(LogType.TestInfo, "Session.State is InProgress");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    // Do nothing for LOGOFF and continue
                }

                ModelHelper.Log(LogType.Requirement, "3.3.5.6: The server MUST remove this session from the GlobalSessionTable and also from the Connection.SessionTable");
                GlobalSessionTable.Remove(logOffRequest.sessionId);
                ConnectionList[logOffRequest.connectionId].Session = null;
            }

            ModelHelper.Log(LogType.TestInfo, "Verifying the Session succeeds.");
            Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS);
        }
        public void SetupConnection(ModelConnectionId connectionId, ModelDialectRevision clientMaxDialect)
        {
            connectionList.Add(connectionId, new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site));

            if (connectionId == ModelConnectionId.MainConnection)
            {
                connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic1IPAddress);
            }
            else
            {
                connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic2IPAddress);
            }

            DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect));

            uint status;
            NEGOTIATE_Response? negotiateResponse = null;
            status = connectionList[connectionId].Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL,
                clientGuid: GetClientGuid(connectionId, dialects),
                checker: (header, response) =>
                {
                    Site.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should succeed", header.Command);

                    negotiateResponse = response;
                });

            DialectRevision expectedDialect;
            if (clientMaxDialect < sessionMgmtConfig.MaxSmbVersionSupported)
            {
                expectedDialect = ModelUtility.GetDialectRevision(clientMaxDialect);
            }
            else
            {
                expectedDialect = ModelUtility.GetDialectRevision(sessionMgmtConfig.MaxSmbVersionSupported);
            }

            Site.Assert.AreEqual(
                expectedDialect,
                negotiateResponse.Value.DialectRevision,
                "DialectRevision {0} is expected", expectedDialect);

            if (ModelUtility.IsSmb3xFamily(negotiateResponse.Value.DialectRevision) && sessionMgmtConfig.IsMultiChannelCapable)
            {
                // SMB2_GLOBAL_CAP_MULTI_CHANNEL if Connection.Dialect belongs to the SMB 3.x dialect family,
                // IsMultiChannelCapable is TRUE, and SMB2_GLOBAL_CAP_MULTI_CHANNEL is set in the Capabilities field of the request.
                Site.Assert.AreEqual(
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL,
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities,
                    "");
            }
            else
            {
                Site.Assert.AreNotEqual(
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL,
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities,
                    "");
            }
        }
 public void TerminateConnection(ModelConnectionId connectionId)
 {
     connectionList[connectionId].Disconnect();
     sessionTable.Remove(ModelSessionId.MainSessionId);
     connectionList.Remove(connectionId);
 }
        public static void SessionSetupResponse(ModelSmb2Status status, ModelConnectionId connectionId, SessionMgmtConfig c)
        {
            VerifyConnection(connectionId);
            Condition.IsNotNull(ConnectionList[connectionId].Request);

            Condition.IsTrue(config.Platform == c.Platform);
            Condition.IsTrue(config.IsMultiChannelCapable == c.IsMultiChannelCapable);

            ModelSessionSetupRequest sessionSetupRequest = RetrieveOutstandingRequest <ModelSessionSetupRequest>(connectionId);

            if (sessionSetupRequest.isSigned)
            {
                ModelHelper.Log(LogType.Requirement, "3.3.5.2.4: If the SMB2 header of the request has SMB2_FLAGS_SIGNED set in the Flags field, the server MUST verify the signature.");
                ModelHelper.Log(LogType.TestInfo, "SMB2_FLAGS_SIGNED is set in the SMB2 header of the SessionSetup Request.");

                // If server does not support Multiple channel then whether binding is set is meaningless.
                if (config.IsMultiChannelCapable && sessionSetupRequest.flags == ModelFlags.Binding)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "If the request is for binding the session, the server MUST look up the session in the GlobalSessionTable using the SessionId in the SMB2 header of the request. ");
                    ModelHelper.Log(LogType.TestInfo, "SMB2_SESSION_FLAG_BINDING bit is set.");

                    if (!GlobalSessionTable.ContainsKey(sessionSetupRequest.sessionId))
                    {
                        ModelHelper.Log(LogType.Requirement,
                                        "If the session is not found, the request MUST be failed, as specified in section Sending an Error Response (section 3.3.4.4), " +
                                        "with the error code STATUS_USER_SESSION_DELETED. ");
                        ModelHelper.Log(LogType.TestInfo, "The session is not found in GlobalSessionTable.");
                        ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier);
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                        return;
                    }
                }
                else
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "For all other requests, the server MUST look up the session in the Connection.SessionTable using the SessionId in the SMB2 header of the request.");
                    ModelHelper.Log(LogType.TestInfo, "SMB2_SESSION_FLAG_BINDING bit is not set.");

                    if (ConnectionList[connectionId].Session == null || ConnectionList[connectionId].Session.SessionId != sessionSetupRequest.sessionId)
                    {
                        ModelHelper.Log(LogType.Requirement,
                                        "If the session is not found, the request MUST be failed, as specified in section Sending an Error Response (section 3.3.4.4), " +
                                        "with the error code STATUS_USER_SESSION_DELETED. ");
                        ModelHelper.Log(LogType.TestInfo, "The session is not found in Connection.SessionTable.");
                        ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier);
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                        return;
                    }
                }
            }

            if (sessionSetupRequest.sessionId == ModelSessionId.ZeroSessionId)
            {
                ModelHelper.Log(LogType.Requirement, "3.3.5.5: 3. If SessionId in the SMB2 header of the request is zero, the server MUST process the authentication request as specified in section 3.3.5.5.1.");
                ModelHelper.Log(LogType.TestInfo, "The SessionId of the SessionSetup Request is zero");

                AuthNewSession(status, sessionSetupRequest);
                Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS || status == ModelSmb2Status.STATUS_MORE_PROCESSING_REQUIRED);
                return;
            }

            if (ModelUtility.IsSmb3xFamily(ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect) &&
                config.IsMultiChannelCapable &&
                sessionSetupRequest.flags == ModelFlags.Binding)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.5: 4. If Connection.Dialect belongs to the SMB 3.x dialect family, IsMultiChannelCapable is TRUE," +
                                "and the SMB2_SESSION_FLAG_BINDING bit is set in the Flags field of the request, the server MUST perform the following:" +
                                "The server MUST look up the session in GlobalSessionTable using the SessionId from the SMB2 header.");
                ModelHelper.Log(LogType.TestInfo,
                                "Connection.Dialect is {0}, IsMultiChannelCapable is TRUE, and the SMB2_SESSION_FLAG_BINDING bit is set",
                                ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect);

                if (!GlobalSessionTable.ContainsKey(sessionSetupRequest.sessionId))
                {
                    ModelHelper.Log(LogType.Requirement, "If the session is not found, the server MUST fail the session setup request with STATUS_USER_SESSION_DELETED.");
                    ModelHelper.Log(LogType.TestInfo, "The SessionId cannot be found in GlobalSessionTable");
                    ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                    return;
                }

                ModelHelper.Log(LogType.Requirement, "If a session is found, the server MUST do the following:");
                if (ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect != GlobalSessionTable[sessionSetupRequest.sessionId].Dialect)
                {
                    ModelHelper.Log(LogType.Requirement, "If Connection.Dialect is not the same as Session.Connection.Dialect, the server MUST fail the request with STATUS_INVALID_PARAMETER.");
                    ModelHelper.Log(LogType.TestInfo,
                                    "The Connection.Dialect is {0}, Session.Connection.Dialect is {1}",
                                    ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect,
                                    GlobalSessionTable[sessionSetupRequest.sessionId].Dialect);
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER);
                    return;
                }

                if (!sessionSetupRequest.isSigned)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "If the SMB2_FLAGS_SIGNED bit is not set in the Flags field in the header, the server MUST fail the request with error STATUS_INVALID_PARAMETER.");
                    ModelHelper.Log(LogType.TestInfo, "The SMB2_FLAGS_SIGNED bit is not set in the SessionSetup Request");
                    ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER);
                    return;
                }

                if (GlobalSessionTable[sessionSetupRequest.sessionId].State == ModelSessionState.InProgress)
                {
                    ModelHelper.Log(LogType.Requirement, "If Session.State is InProgress, the server MUST fail the request with STATUS_REQUEST_NOT_ACCEPTED.");
                    ModelHelper.Log(LogType.TestInfo, "Session.State is InProgress");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED);
                    return;
                }

                // If Session.IsAnonymousor Session.IsGuestis TRUE, the server MUST fail the request with STATUS_NOT_SUPPORTED.
                // Skip above requirement according to assumption 6.

                if (ConnectionList[sessionSetupRequest.connectionId].Session != null &&
                    ConnectionList[sessionSetupRequest.connectionId].Session.SessionId == sessionSetupRequest.sessionId)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "If there is a session in Connection.SessionTable identified by the SessionId in the request, the server MUST fail the request with STATUS_REQUEST_NOT_ACCEPTED.");
                    ModelHelper.Log(LogType.TestInfo, "There is a session in Connection.SessionTable which has a same SessionId in the request");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED);
                    return;
                }

                // The server MUST verify the signature as specified in section 3.3.5.2.4, using the Session.SessionKey.
                // Skip above requirement as it is verified in signing model

                if (sessionSetupRequest.user == ModelUser.DiffUser)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "The server MUST obtain the security context from the GSS authentication subsystem, " +
                                    "and it MUST invoke the GSS_Inquire_context call as specified in [RFC2743] section 2.2.6, " +
                                    "passing the security context as the input parameter." +
                                    "If the returned \"src_name\" does not match with the Session.Username, the server MUST fail the request with error code STATUS_NOT_SUPPORTED.");
                    ModelHelper.Log(LogType.TestInfo, "A different user is used when binding to an existing session");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_NOT_SUPPORTED);
                    return;
                }
            }
            else
            {
                if (config.Platform == Platform.WindowsServer2012 &&
                    sessionSetupRequest.flags == ModelFlags.Binding)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "<232> Section 3.3.5.5: Windows 8 and Windows Server 2012 look up the session in GlobalSessionTable using the SessionId from the SMB2 header " +
                                    "if the SMB2_SESSION_FLAG_BINDING bit is set in the Flags field of the request. ");
                    ModelHelper.Log(LogType.TestInfo, "The SUT platform is {0}. The SMB2_SESSION_FLAG_BINDING bit is set.", config.Platform);
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                    if (GlobalSessionTable.ContainsKey(sessionSetupRequest.sessionId))
                    {
                        ModelHelper.Log(LogType.Requirement, "If the session is found, the server fails the request with STATUS_REQUEST_NOT_ACCEPTED. ");
                        ModelHelper.Log(LogType.TestInfo, "The session is found");
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED);
                        return;
                    }
                    else
                    {
                        ModelHelper.Log(LogType.Requirement, "If the session is not found, the server fails the request with STATUS_USER_SESSION_DELETED.");
                        ModelHelper.Log(LogType.TestInfo, "The session is not found");
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                        return;
                    }
                }
                if (ModelUtility.IsSmb3xFamily(config.MaxSmbVersionSupported) &&
                    ((ModelUtility.IsSmb2Family(ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect) || !config.IsMultiChannelCapable)) &&
                    sessionSetupRequest.flags == ModelFlags.Binding)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "3.3.5.5: Otherwise, if the server implements the SMB 3.x dialect family, " +
                                    "and Connection.Dialect is equal to \"2.002\" or \"2.100\" or IsMultiChannelCapable is FALSE, " +
                                    "and SMB2_SESSION_FLAG_BINDING bit is set in the Flags field of the request, " +
                                    "the server SHOULD<225> fail the session setup request with STATUS_REQUEST_NOT_ACCEPTED.");
                    ModelHelper.Log(LogType.TestInfo,
                                    "Connection.Dialect is {0}, IsMultiChannelCapable is {1}, SUT platform is {2}, Max Smb version supported is {3} and SMB2_SESSION_FLAG_BINDING bit is set.",
                                    ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect,
                                    config.IsMultiChannelCapable,
                                    config.Platform,
                                    config.MaxSmbVersionSupported);
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                    if (config.Platform != Platform.NonWindows)
                    {
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED);
                    }
                    else
                    {
                        ModelHelper.Log(LogType.TestInfo, "The SUT platform is NonWindows, so the server could fail the request with other error code.");
                        Condition.IsTrue(status != ModelSmb2Status.STATUS_SUCCESS);
                    }
                    return;
                }
                else
                {
                    if (ConnectionList[sessionSetupRequest.connectionId].Session == null ||
                        ConnectionList[sessionSetupRequest.connectionId].Session.SessionId != sessionSetupRequest.sessionId)
                    {
                        ModelHelper.Log(LogType.Requirement,
                                        "3.3.5.5: Otherwise, the server MUST look up the session in Connection.SessionTable using the SessionId from the SMB2 header." +
                                        "If the session is not found, the server MUST fail the session setup request with STATUS_USER_SESSION_DELETED. ");
                        ModelHelper.Log(LogType.TestInfo, "The session is not found using the SessionId of the request");
                        ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED);
                        return;
                    }
                }
            }
            if (GlobalSessionTable[sessionSetupRequest.sessionId].State == ModelSessionState.Valid)
            {
                ModelHelper.Log(LogType.Requirement, "3.3.5.5: 6. If Session.State is Valid, the server SHOULD process the session setup request as specified in section 3.3.5.5.2.");
                ModelHelper.Log(LogType.TestInfo, "Session.State is Valid");
                if (config.Platform == Platform.WindowsServer2008)
                {
                    ModelHelper.Log(LogType.Requirement, "Footnote: Windows Vista SP1 and Windows Server 2008 servers fail the session setup request with STATUS_REQUEST_NOT_ACCEPTED.");
                    ModelHelper.Log(LogType.TestInfo, "The SUT platform is Windows Server 2008");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED);
                    return;
                }

                if (config.Platform != Platform.NonWindows)
                {
                    ModelHelper.Log(LogType.TestInfo, "The SUT platform is Windows");
                    ReAuthentication(status, sessionSetupRequest);

                    Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS || status == ModelSmb2Status.STATUS_MORE_PROCESSING_REQUIRED);
                    return;
                }
            }

            ModelHelper.Log(LogType.Requirement, "3.3.5.5: 7. The server MUST continue processing the request as specified in section 3.3.5.5.3.");
            HandleGssApiAuth(status, sessionSetupRequest);
            ModelHelper.Log(LogType.TestInfo, "The authentication should succeed.");
            Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS || status == ModelSmb2Status.STATUS_MORE_PROCESSING_REQUIRED);
        }
        public void SessionSetupRequest(
            ModelConnectionId connectionId,
            ModelSessionId sessionId,
            ModelSessionId previousSessionId,
            ModelSigned signed,
            ModelFlags flags,
            ModelUser user,
            ModelAllowReauthentication ReAuthentication)
        {
            ulong adapterSessionId;
            ulong adapterPreviousSessionId;
            Packet_Header_Flags_Values  headerFlags;
            SESSION_SETUP_Request_Flags sessionSetupFlags;
            AccountCredential           credential;

            #region sessionId
            if (sessionTable.ContainsKey(sessionId))
            {
                adapterSessionId = sessionTable[sessionId];

                // For sessionId is 0 which indicates session creation
                // assign a new one
                if (sessionId == ModelSessionId.ZeroSessionId)
                {
                    if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId))
                    {
                        sessionId = ModelSessionId.MainSessionId;
                    }
                    else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId))
                    {
                        sessionId = ModelSessionId.AlternativeSessionId;
                    }
                }
            }
            else
            {
                Random r = new Random();
                adapterSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}",
                sessionId, adapterSessionId);

            #endregion

            #region previousSessionId
            if (sessionTable.ContainsKey(previousSessionId))
            {
                adapterPreviousSessionId = sessionTable[previousSessionId];
            }
            else
            {
                Random r = new Random();
                adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue);
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}",
                sessionId, adapterPreviousSessionId);

            #endregion

            #region isSigned

            headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            #endregion

            #region flags

            switch (flags)
            {
            case ModelFlags.Binding:
            {
                sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING;
                break;
            }

            case ModelFlags.NotBinding:
            {
                sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE;
                break;
            }

            default:
                throw new ArgumentException("flags");
            }

            #endregion

            #region user

            switch (user)
            {
            case ModelUser.DefaultUser:
            {
                credential = testConfig.AccountCredential;
                break;
            }

            case ModelUser.DiffUser:
            {
                credential = testConfig.NonAdminAccountCredential;
                break;
            }

            default:
                throw new ArgumentException("user");
            }

            #endregion

            #region MultipleChannel
            // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family
            bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect);
            #endregion

            PrintCurrentSessionTable("Before SessionSetup Request");

            #region Send Request

            uint status;
            SESSION_SETUP_Response?sessionSetupResponse = null;
            string serverName = testConfig.SutComputerName;
            SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage;
            bool useServerGssToken = testConfig.UseServerGssToken;

            // Use desired explored sessionId
            ulong oldSessionId = connectionList[connectionId].SessionId;
            connectionList[connectionId].SessionId = adapterSessionId;

            // alternative connection and never session setup
            if (connectionId == ModelConnectionId.AlternativeConnection &&
                sessionId == ModelSessionId.MainSessionId &&
                connectionList[connectionId].SessionKey == null &&
                connectionList.ContainsKey(ModelConnectionId.MainConnection))
            {
                connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true);
            }

            status = connectionList[connectionId].SessionSetup(
                headerFlags,
                sessionSetupFlags,
                adapterPreviousSessionId,
                securityPackageType,
                serverName,
                credential,
                useServerGssToken,
                isMultipleChannelSupported,
                (header, response) =>
            {
                sessionSetupResponse = response;
            });

            if (status != Smb2Status.STATUS_SUCCESS &&
                status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)
            {
                // Restore original sessionId if request failed
                connectionList[connectionId].SessionId = oldSessionId;
            }

            #endregion

            // Insert session to session table
            if (!sessionTable.ContainsKey(sessionId) &&
                (status == Smb2Status.STATUS_SUCCESS ||
                 status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED))
            {
                sessionTable.Add(sessionId, connectionList[connectionId].SessionId);
            }

            PrintCurrentSessionTable("After SessionSetup Request");

            SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig);
        }
 public ModelLogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId)
     : base(0)
 {
     this.connectionId = connectionId;
     this.sessionId = sessionId;
 }
 private Guid GetClientGuid(ModelConnectionId connectionId, DialectRevision[] dialects)
 {
     if (dialects.Length == 1 && dialects[0] == DialectRevision.Smb2002)
     {
         return Guid.Empty;
     }
     else if (connectionId == ModelConnectionId.MainConnection)
     {
         this.clientGuid = Guid.NewGuid();
         return this.clientGuid;
     }
     else
     {
         return this.clientGuid;
     }
 }
 public ModelSessionSetupRequest(
     ModelConnectionId connectionId,
     ModelSessionId sessionId,
     ModelSessionId previousSessionId,
     bool isSigned,
     ModelFlags flags,
     ModelUser user
     )
     : base(0)
 {
     this.connectionId = connectionId;
     this.sessionId = sessionId;
     this.previousSessionId = previousSessionId;
     this.isSigned = isSigned;
     this.flags = flags;
     this.user = user;
 }
        public void SetupConnection(ModelConnectionId connectionId, ModelDialectRevision clientMaxDialect)
        {
            connectionList.Add(connectionId, new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site));

            if (connectionId == ModelConnectionId.MainConnection)
            {
                connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic1IPAddress);
            }
            else
            {
                connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic2IPAddress);
            }

            DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect));

            uint status;
            NEGOTIATE_Response?negotiateResponse = null;

            status = connectionList[connectionId].Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL,
                clientGuid: GetClientGuid(connectionId, dialects),
                checker: (header, response) =>
            {
                Site.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

                negotiateResponse = response;
            });

            DialectRevision expectedDialect;

            if (clientMaxDialect < sessionMgmtConfig.MaxSmbVersionSupported)
            {
                expectedDialect = ModelUtility.GetDialectRevision(clientMaxDialect);
            }
            else
            {
                expectedDialect = ModelUtility.GetDialectRevision(sessionMgmtConfig.MaxSmbVersionSupported);
            }

            Site.Assert.AreEqual(
                expectedDialect,
                negotiateResponse.Value.DialectRevision,
                "DialectRevision {0} is expected", expectedDialect);

            if (ModelUtility.IsSmb3xFamily(negotiateResponse.Value.DialectRevision) && sessionMgmtConfig.IsMultiChannelCapable)
            {
                // SMB2_GLOBAL_CAP_MULTI_CHANNEL if Connection.Dialect belongs to the SMB 3.x dialect family,
                // IsMultiChannelCapable is TRUE, and SMB2_GLOBAL_CAP_MULTI_CHANNEL is set in the Capabilities field of the request.
                Site.Assert.AreEqual(
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL,
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities,
                    "");
            }
            else
            {
                Site.Assert.AreNotEqual(
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL,
                    Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities,
                    "");
            }
        }