public static void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ClientSupportsEncryptionType clientSupportsEncryptionType)
        {
            Condition.IsTrue(state == ModelState.Initialized);
            Condition.IsNull(request);

            negotiateDialect = ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported, config.MaxSmbVersionSupported);

            Connection_ClientCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION = (clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption) ? true : false;

            if (ModelUtility.IsSmb3xFamily(negotiateDialect) && clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.4: The Capabilities field MUST be set to a combination of zero or more of the following bit values, as specified in section 2.2.4:");
                ModelHelper.Log(LogType.Requirement,
                                "\tSMB2_GLOBAL_CAP_ENCRYPTION if Connection.Dialect belongs to the SMB 3.x dialect family, the server supports encryption, " +
                                "and SMB2_GLOBAL_CAP_ENCRYPTION is set in the Capabilities field of the request.");

                // Encrpytion Model only applies to server that supports encryption.
                ModelHelper.Log(LogType.TestInfo,
                                "Connection.Dialect is {0}, the server supports encryption and SMB2_GLOBAL_CAP_ENCRYPTION is set. " +
                                "So SMB2_GLOBAL_CAP_ENCRYPTION bit is set in Capabilities field.", negotiateDialect);
                Connection_ServerCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION = true;
            }

            state = ModelState.Connected;
        }
        private void InitializeAlternativeChannel(
            Guid clientGuid,
            uint treeId,
            bool isClientSupportPersistent = true)
        {
            Site.Assume.IsNull(smb2ClientAlternativeChannel, "Expect smb2ClientAlternativeChannel is NULL.");

            testConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL);

            smb2ClientAlternativeChannel = new Smb2FunctionalClient(testConfig.Timeout, testConfig, Site);
            smb2ClientAlternativeChannel.Smb2Client.LeaseBreakNotificationReceived  += new Action <Packet_Header, LEASE_BREAK_Notification_Packet>(OnLeaseBreakNotificationReceived);
            smb2ClientAlternativeChannel.Smb2Client.OplockBreakNotificationReceived += new Action <Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived);
            smb2ClientAlternativeChannel.ConnectToServer(testConfig.UnderlyingTransport, serverNameMainChannel, serverIpMainChannel);
            uint status;

            #region Negotiate

            Capabilities_Values capability = isClientSupportPersistent ?
                                             Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU |
                                             Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES |
                                             Capabilities_Values.GLOBAL_CAP_ENCRYPTION :
                                             Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU |
                                             Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_ENCRYPTION;
            NEGOTIATE_Response?negotiateResponse = null;
            status = smb2ClientAlternativeChannel.Negotiate(
                new DialectRevision[] { dialectMainChannel },
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: ModelUtility.IsSmb3xFamily(dialectMainChannel) ? capability : Capabilities_Values.NONE,
                clientGuid: dialectMainChannel == DialectRevision.Smb2002 ? Guid.Empty : clientGuid,
                checker: (header, response) =>
            {
                Site.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

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

            #endregion

            #region SESSION_SETUP
            status = smb2ClientAlternativeChannel.AlternativeChannelSessionSetup(
                smb2ClientMainChannel,
                testConfig.DefaultSecurityPackage,
                principleNameMainChannel,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);

            Site.Log.Add(
                LogEntryKind.Debug,
                "Global encryption disabled");

            #endregion
        }
        public static void PrepareOpen(
            ModelDialectRevision clientDialect,
            AppInstanceIdType appInstanceIdType,
            CreateType createType)
        {
            Condition.IsTrue(State == ModelState.Initialized);

            // appInstanceIdType should not be Invalid or None when preparing.
            Condition.IsFalse(appInstanceIdType == AppInstanceIdType.InvalidAppInstanceId || appInstanceIdType == AppInstanceIdType.NoAppInstanceId);
            Condition.IsFalse(createType == CreateType.ReconnectDurable);

            Combination.Isolated(clientDialect == ModelDialectRevision.Smb2002);
            Combination.Isolated(clientDialect == ModelDialectRevision.Smb21);

            // If the server doesn't support Dialect 3.x family, then createdurablev2 will not work and CreateDurableThenDisconnect will result in Open is null.
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(MaxSmbVersionSupported), createType != CreateType.CreateDurableThenDisconnect);

            State = ModelState.Connected;
            Open  = new AppInstanceIdModelOpen();
            Open.CreateTypeWhenPrepare = createType;
            Open.AppInstanceId         = AppInstanceIdType.NoAppInstanceId;

            if (!ModelUtility.IsSmb3xFamily(MaxSmbVersionSupported))
            {
                ModelHelper.Log(LogType.TestInfo,
                                "Connection.Dialect does not belong to SMB 3.x dialect family. So Open.AppInstanceId is not set.");
                return;
            }

            // TDI: 72179
            ModelHelper.Log(LogType.Requirement,
                            "3.3.5.9: If Connection.Dialect belongs to the SMB 3.x dialect family, the server MUST initialize the following:");
            ModelHelper.Log(LogType.TestInfo, "Server supports dialect {0}.", MaxSmbVersionSupported);

            if (createType == CreateType.CreateDurable)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.9: Open.AppInstanceId MUST be set to AppInstanceId in the SMB2_CREATE_APP_INSTANCE_ID create context request " +
                                "if the create request includes the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 and SMB2_CREATE_APP_INSTANCE_ID create contexts.");
                Open.AppInstanceId = appInstanceIdType;
                ModelHelper.Log(LogType.TestInfo,
                                "The create request includes the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 and SMB2_CREATE_APP_INSTANCE_ID create contexts.");
            }
        }
        public static void ReadConfigReturn(SessionMgmtConfig c)
        {
            Condition.IsTrue(ConnectionList == null);
            Condition.IsNotNull(c);
            Condition.IsTrue(c.MaxSmbVersionSupported == ModelDialectRevision.Smb2002 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb21 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb30 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb302);

            if (!ModelUtility.IsSmb3xFamily(c.MaxSmbVersionSupported))
            {
                Condition.IsFalse(c.IsMultiChannelCapable);
            }

            ConnectionList     = new MapContainer <ModelConnectionId, ModelConnection>();
            GlobalSessionTable = new MapContainer <ModelSessionId, ModelSession>();

            config = c;
        }
        public static void SetupConnection(ModelDialectRevision clientMaxDialect)
        {
            Condition.IsTrue(state == ModelState.Initialized);
            Condition.IsNull(request);

            negotiateDialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, config.MaxSmbVersionSupported);

            if ((negotiateDialect == DialectRevision.Smb21 || ModelUtility.IsSmb3xFamily(negotiateDialect)) &&
                config.IsMultiCreditSupportedOnServer)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.4: If the common dialect is SMB 2.1 or 3.x dialect family and the underlying connection is either TCP port 445 or RDMA," +
                    "Connection.SupportsMultiCredit MUST be set to TRUE; otherwise, it MUST be set to FALSE.");
                ModelHelper.Log(
                    LogType.TestInfo,
                    "Common dialect is {0} and server implementation {1} multicredit", negotiateDialect,
                    config.IsMultiCreditSupportedOnServer ? "supports" : "does not support");

                isMultiCreditSupported = true;

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Connection.SupportsMultiCredit is set to TRUE");
            }
            else
            {
                isMultiCreditSupported = false;

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Connection.SupportsMultiCredit is set to FALSE");
            }

            state = ModelState.Connected;
        }
        public static void FileOperationToBreakLeaseRequestReturn(LeasingConfig c)
        {
            Condition.IsTrue(state == ModelState.Connected);

            ModelFileOperationRequest fileOperationRequest = ModelHelper.RetrieveOutstandingRequest <ModelFileOperationRequest>(ref request);

            Condition.IsFalse(negotiateDialect == DialectRevision.Smb2002);

            Condition.IsTrue(config.IsDirectoryLeasingSupported == c.IsDirectoryLeasingSupported);
            Condition.IsTrue(config.IsLeasingSupported == c.IsLeasingSupported);

            Condition.IsTrue(c.IsLeasingSupported || c.IsDirectoryLeasingSupported);
            Condition.IsTrue(config.MaxSmbVersionSupported == c.MaxSmbVersionSupported);

            // 3.3.1.4   Algorithm for Leasing in an Object Store
            smb2Lease.BreakToLeaseState = smb2Lease.LeaseState;

            if (fileOperationRequest.OptorType != OperatorType.SameClientId)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.1.4: READ caching permits the SMB2 client to cache data read from the object. Before processing one of the following operations from a client with a different ClientId, " +
                    "the object store MUST request that the server revoke READ caching. The object store is not required to wait for acknowledgment:");

                if ((smb2Lease.LeaseState & (uint)LeaseStateValues.SMB2_LEASE_READ_CACHING) != 0 &&
                    ((fileOperationRequest.Operation == FileOperation.OPEN_OVERWRITE) ||
                     (fileOperationRequest.Operation == FileOperation.WRITE_DATA) ||
                     (fileOperationRequest.Operation == FileOperation.SIZE_CHANGED) ||
                     (fileOperationRequest.Operation == FileOperation.RANGE_LOCK)))
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "READ caching on a file:");
                    ModelHelper.Log(LogType.Requirement,
                                    "\tThe file is opened in a manner that overwrites the existing file.");
                    ModelHelper.Log(LogType.Requirement,
                                    "\tData is written to the file.");
                    ModelHelper.Log(LogType.Requirement,
                                    "\tThe file size is changed.");
                    ModelHelper.Log(LogType.Requirement,
                                    "\tA byte range lock is requested for the file.");

                    ModelHelper.Log(LogType.TestInfo, "READ caching lease state is broken.");
                    smb2Lease.BreakToLeaseState &= ~(uint)LeaseStateValues.SMB2_LEASE_READ_CACHING;
                }
            }

            if (fileOperationRequest.OptorType != OperatorType.SameClientId)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "WRITE caching permits the SMB2 client to cache writes and byte-range locks on an object. " +
                    "Before processing one of the following operations, the underlying object store MUST request that the server revoke WRITE caching, " +
                    "and the object store MUST wait for acknowledgment from the server before proceeding with the operation:");

                if ((smb2Lease.LeaseState & (uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING) != 0 &&
                    fileOperationRequest.Operation != FileOperation.OPEN_SHARING_VIOLATION &&
                    fileOperationRequest.Operation != FileOperation.OPEN_SHARING_VIOLATION_WITH_OVERWRITE &&
                    fileOperationRequest.Operation != FileOperation.PARENT_DIR_RENAMED)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "The file is opened by a local application or via another protocol, " +
                        "or opened via SMB2 without providing the same ClientId, and requested access includes any flags other than FILE_READ_ATTRIBUTES, " +
                        "FILE_WRITE_ATTRIBUTES, and SYNCHRONIZE.");
                    ModelHelper.Log(
                        LogType.TestInfo, "WRITE caching lease state is broken.");
                    smb2Lease.BreakToLeaseState &= ~(uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING;
                }

                ModelHelper.Log(
                    LogType.Requirement,
                    "HANDLE caching permits one or more SMB2 clients to delay closing handles it holds open, " +
                    "or to defer sending opens. Before processing one of the following operations, " +
                    "the underlying object store MUST request that the server revoke HANDLE caching, " +
                    "and the object store MUST wait for acknowledgment before proceeding with the operation:");
                if ((smb2Lease.LeaseState & (uint)LeaseStateValues.SMB2_LEASE_HANDLE_CACHING) != 0 &&
                    (fileOperationRequest.Operation == FileOperation.OPEN_SHARING_VIOLATION ||
                     fileOperationRequest.Operation == FileOperation.OPEN_SHARING_VIOLATION_WITH_OVERWRITE ||
                     fileOperationRequest.Operation == FileOperation.RENAMEED || fileOperationRequest.Operation == FileOperation.DELETED ||
                     fileOperationRequest.Operation == FileOperation.PARENT_DIR_RENAMED))
                {
                    ModelHelper.Log(LogType.Requirement, "HANDLE caching on a file:");
                    ModelHelper.Log(
                        LogType.Requirement,
                        "\tA file is opened with an access or share mode incompatible with opens from different ClientIds " +
                        "or local applications as described in [MS-FSA] section 2.1.5.1.2.");
                    ModelHelper.Log(LogType.Requirement, "\tThe parent directory is being renamed.");

                    ModelHelper.Log(
                        LogType.TestInfo, "HANDLE caching lease state is broken.");
                    smb2Lease.BreakToLeaseState &= ~(uint)LeaseStateValues.SMB2_LEASE_HANDLE_CACHING;
                }
            }

            // HANDLE caching permits one or more SMB2 clients to delay closing handles it holds open, or to defer sending opens.
            // Before processing one of the following operations, the underlying object store MUST request that the server revoke HANDLE caching,
            // and the object store MUST wait for acknowledgment before proceeding with the operation:
            //      The parent directory is being renamed.
            if ((smb2Lease.LeaseState & (uint)LeaseStateValues.SMB2_LEASE_HANDLE_CACHING) != 0 &&
                fileOperationRequest.Operation == FileOperation.PARENT_DIR_RENAMED)
            {
                smb2Lease.BreakToLeaseState &= ~(uint)LeaseStateValues.SMB2_LEASE_HANDLE_CACHING;
            }

            if (smb2Lease.BreakToLeaseState != smb2Lease.LeaseState)
            {
                if (smb2Lease.LeaseState != (uint)LeaseStateValues.SMB2_LEASE_READ_CACHING)
                {
                    // 3.3.4.7   Object Store Indicates a Lease Break
                    // The server MUST set Lease.Breaking to TRUE
                    ModelHelper.Log(LogType.TestInfo, "Lease.Breaking is set to TRUE.");
                    smb2Lease.Breaking = true;
                }

                // 3.3.4.7   Object Store Indicates a Lease Break
                if (ModelUtility.IsSmb3xFamily(c.MaxSmbVersionSupported) && smb2Lease.Version == 2)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.4.7: If the server implements the SMB 3.x dialect family and Lease.Version is 2, the server MUST set NewEpoch to Lease.Epoch + 1. ");
                    ModelHelper.Log(LogType.TestInfo, "The server implements the SMB 3.x dialect family and Lease.Version is 2.");
                    smb2Lease.Epoch++;
                }

                // 3.3.1.4   Algorithm for Leasing in an Object Store
                // The algorithm SHOULD support the following combinations of caching flags on a file:
                // No caching, Read caching, Read + Write caching, Read + Handle caching, and Read + Write + Handle caching.
                if ((smb2Lease.BreakToLeaseState & (uint)LeaseStateValues.SMB2_LEASE_READ_CACHING) == 0)
                {
                    ModelHelper.Log(LogType.TestInfo, "Lease state is set to No caching.");
                    smb2Lease.BreakToLeaseState = 0;
                }
            }
        }
示例#7
0
        public static void RequestOplockAndOperateFileReturn(OplockLevel_Values grantedOplockLevel, OplockConfig c)
        {
            Condition.IsTrue(State == ModelState.Connected);
            Condition.IsNotNull(Request);

            ModelRequestOplockAndTriggerBreakRequest requestOplockAndTriggerBreakRequest = ModelHelper.RetrieveOutstandingRequest <ModelRequestOplockAndTriggerBreakRequest>(ref Request);

            Condition.IsTrue(Config.Platform == c.Platform);

            if (Share_ForceLevel2Oplock &&
                (requestOplockAndTriggerBreakRequest.RequestedOplockLevel == RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH ||
                 requestOplockAndTriggerBreakRequest.RequestedOplockLevel == RequestedOplockLevel_Values.OPLOCK_LEVEL_EXCLUSIVE))
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.9: If TreeConnect.Share.ForceLevel2Oplock is TRUE, " +
                                "and RequestedOplockLevel is SMB2_OPLOCK_LEVEL_BATCH or SMB2_OPLOCK_LEVEL_EXCLUSIVE, " +
                                "the server SHOULD<245> set RequestedOplockLevel to SMB2_OPLOCK_LEVEL_II.");
                if (Config.Platform != Platform.NonWindows)
                {
                    ModelHelper.Log(LogType.TestInfo, "The SUT platform is Windows.");
                    Condition.IsTrue(grantedOplockLevel == OplockLevel_Values.OPLOCK_LEVEL_II);

                    // Skip following WBN which is for pre-Win8
                    // <226> Section 3.3.5.9: Windows Vista and Windows Server 2008 do not support the SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK flag
                    // and ignore  the TreeConnect.Share.ForceLevel2Oplock value.
                }
            }

            if (ModelUtility.IsSmb3xFamily(Connection_Dialect) &&
                Share_Type_Include_STYPE_CLUSTER_SOFS &&
                requestOplockAndTriggerBreakRequest.RequestedOplockLevel == RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.9: If Connection.Dialect belongs to the SMB 3.x dialect family TreeConnect.Share.Type includes STYPE_CLUSTER_SOFS " +
                                "and the RequestedOplockLevel is SMB2_OPLOCK_LEVEL_BATCH, the server MUST set RequestedOplockLevel to SMB2_OPLOCK_LEVEL_II.");
                // The Oplock acquisition depends on underlying object store implemention specific
                // we may not garantee level2 would be always granted
                // Only assert it's not batch
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met.");
                Condition.IsTrue(grantedOplockLevel != OplockLevel_Values.OPLOCK_LEVEL_BATCH);
            }

            Open = new ModelOplockOpen();

            ModelHelper.Log(LogType.TestInfo, "Open.OplockLevel is set to SMB2_OPLOCK_LEVEL_NONE.");
            Open.OplockLevel = OplockLevel_Values.OPLOCK_LEVEL_NONE;

            ModelHelper.Log(LogType.TestInfo, "Open.OplockState is set to None.");
            Open.OplockState = OplockState.None;

            // Acquire Oplock from underlying object

            // If the underlying object store grants the oplock,
            // then Open.OplockState is set to Held and Open.OplockLevel is set to the level of the oplock acquired.
            if (grantedOplockLevel != OplockLevel_Values.OPLOCK_LEVEL_NONE)
            {
                ModelHelper.Log(LogType.TestInfo, "Open.OplockState is set to Held.");
                Open.OplockState = OplockState.Held;
                Open.OplockLevel = grantedOplockLevel;
            }
        }
示例#8
0
        public static void OpenRequest(
            ClientGuidType clientGuidType,
            PathNameType pathNameType,
            CreateType createType,
            ShareType shareType,
            AppInstanceIdType appInstanceIdType)
        {
            Condition.IsTrue(State == ModelState.Connected);
            Condition.IsNotNull(Open);

            // Isolate below params to limite the expanded test cases.
            Combination.Isolated(clientGuidType == ClientGuidType.SameClientGuid);
            Combination.Isolated(pathNameType == PathNameType.DifferentPathName);
            Combination.Isolated(shareType == ShareType.DifferentShareDifferentLocal);
            Combination.Isolated(shareType == ShareType.DifferentShareSameLocal);
            Combination.Isolated(appInstanceIdType == AppInstanceIdType.InvalidAppInstanceId);
            Combination.Isolated(appInstanceIdType == AppInstanceIdType.NoAppInstanceId);

            // "AppInstanceId is zero" is only applicable for the first Create Request.
            // For the second Create Request, only valid/notvalid/none make sense.
            Condition.IsFalse(appInstanceIdType == AppInstanceIdType.AppInstanceIdIsZero);

            // CreateDurableThenDisconnect is only applicable for the first Create Request.
            Condition.IsFalse(createType == CreateType.CreateDurableThenDisconnect);

            // If the client doesn't disconnect from the server after sending the first Create Request,
            // then the second Create Request does not need to contain reconnect context.
            // And vice versa.
            Condition.IfThen(Open.CreateTypeWhenPrepare != CreateType.CreateDurableThenDisconnect, createType != CreateType.ReconnectDurable);
            Condition.IfThen(Open.CreateTypeWhenPrepare == CreateType.CreateDurableThenDisconnect, createType == CreateType.ReconnectDurable);

            if (createType == CreateType.ReconnectDurable)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.9.13: If the create request also includes the SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 create context, " +
                                "the server MUST process the SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 create context as specified in section 3.3.5.9.12, " +
                                "and this section MUST be skipped.");
                ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 create context is included.");
                return;
            }

            if (!ModelUtility.IsSmb3xFamily(MaxSmbVersionSupported))
            {
                ModelHelper.Log(LogType.Requirement,
                                "2.2.13.2.13: The SMB2_CREATE_APP_INSTANCE_ID context is valid only for the SMB 3.x dialect family.");
                ModelHelper.Log(LogType.TestInfo, "The dialect version of the server is {0}.", MaxSmbVersionSupported);
                return;
            }

            if (appInstanceIdType == AppInstanceIdType.ValidAppInstanceId && Open.AppInstanceId != AppInstanceIdType.NoAppInstanceId &&
                pathNameType == PathNameType.SamePathName &&
                shareType == ShareType.SameShare &&
                clientGuidType == ClientGuidType.DifferentClientGuid)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.9.13: The server MUST attempt to locate an Open in GlobalOpenTable where:");
                ModelHelper.Log(LogType.Requirement,
                                "\tAppInstanceId in the request is equal to Open.AppInstanceId.");
                ModelHelper.Log(LogType.Requirement,
                                "\tTarget path name is equal to Open.PathName.");
                ModelHelper.Log(LogType.Requirement,
                                "\tOpen.TreeConnect.Share is equal to TreeConnect.Share.");
                ModelHelper.Log(LogType.Requirement,
                                "\tOpen.Session.Connection.ClientGuid is not equal to the current Connection.ClientGuid.");
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met.");

                ModelHelper.Log(LogType.Requirement,
                                "If an Open is found, the server MUST calculate the maximal access that the user, " +
                                "identified by Session.SecurityContext, has on the file being opened<277>. " +
                                "If the maximal access includes GENERIC_READ access, the server MUST close the open as specified in 3.3.4.17.");
                // The user used in this model is administrator, so maximal access always includes GENERIC_READ access.
                ModelHelper.Log(LogType.TestInfo, "The maximal access includes GENERIC_READ access. So open is closed.");

                // close open
                Open = null;
            }
            else
            {
                ModelHelper.Log(LogType.TestInfo, "appInstanceIdType is {0}.", appInstanceIdType.ToString());
                ModelHelper.Log(LogType.TestInfo, "pathNameType is {0}.", pathNameType.ToString());
                ModelHelper.Log(LogType.TestInfo, "shareType is {0}.", shareType.ToString());
                ModelHelper.Log(LogType.TestInfo, "clientGuidType is {0}.", clientGuidType.ToString());
                ModelHelper.Log(LogType.TestInfo, "All the above conditions do not match the requirement, so open will not be closed.");

                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
            }
        }
        private static void HandleGssApiAuth(ModelSmb2Status status, ModelSessionSetupRequest sessionSetupRequest)
        {
            ModelHelper.Log(LogType.Requirement, "3.3.5.5.3: 1. The status code in the SMB2 header of the response MUST be set to STATUS_SUCCESS. ");
            if (status != ModelSmb2Status.STATUS_SUCCESS)
            {
                return;
            }

            if (ModelUtility.IsSmb3xFamily(ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect))
            {
                ModelHelper.Log(LogType.Requirement, "If Connection.Dialect belongs to the SMB 3.x dialect family, the server MUST insert the Session into Connection.SessionTable. ");
                ModelHelper.Log(LogType.TestInfo, "Connection.Dialect is {0}", ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect);
                ConnectionList[sessionSetupRequest.connectionId].Session
                    = GlobalSessionTable[sessionSetupRequest.sessionId];
            }

            ModelHelper.Log(LogType.Requirement, "If Session.IsAnonymous is FALSE, the server MUST set Connection.ConstrainedConnection to FALSE.");
            ModelHelper.Log(LogType.TestInfo, "Session.IsAnonymous is FALSE, so set Connection.ConstrainedConnection to FALSE");
            ConnectionList[sessionSetupRequest.connectionId].ConstrainedConnection = false;

            /*
             * Assuming STATUS_SUCCESS indicates final message in the authentication exchange
             *
             * Skip following requirement according to assumption 6.
             * If the returned anon_state is TRUE, the server MUST set Session.IsAnonymous to TRUE and the server MAY set
             * the SMB2_SESSION_FLAG_IS_NULL flag in the SessionFlags field of the SMB2 SESSION_SETUP Response.
             * Otherwise, if the returned src_name corresponds to an implementation-specific guest user,<211>
             * the server MUST set the SMB2_SESSION_FLAG_IS_GUEST in the SessionFlags field of the SMB2 SESSION_SETUP Response
             * and MUST set Session.IsGuest to TRUE.
             */

            if (sessionSetupRequest.previousSessionId != ModelSessionId.ZeroSessionId)
            {
                ModelHelper.Log(LogType.Requirement, "12. If the PreviousSessionId field of the request is not equal to zero, the server MUST take the following actions:");
                ModelHelper.Log(LogType.TestInfo, "PreviousSessionId is not equal to zero.");

                ModelHelper.Log(LogType.Requirement, "1. The server MUST look up the old session in GlobalSessionTable, where Session.SessionId matches PreviousSessionId. ");
                if (GlobalSessionTable.ContainsKey(sessionSetupRequest.previousSessionId))
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "If a session is found with Session.SessionId equal to PreviousSessionId, " +
                                    "the server MUST determine if the old session and the newly established session are created by the same user " +
                                    "by comparing the user identifiers obtained from the Session.SecurityContext on the new and old session.");
                    ModelHelper.Log(LogType.TestInfo, "There is a session with Session.SessionId equal to PreviousSessionId.");

                    if (sessionSetupRequest.previousSessionId == sessionSetupRequest.sessionId)
                    {
                        ModelHelper.Log(LogType.Requirement, "1. If the PreviousSessionId and SessionId values in the SMB2 header of the request are equal, " +
                                        "the server SHOULD<230> ignore PreviousSessionId and no other processing is required.");
                        ModelHelper.Log(LogType.TestInfo, "PreviousSessionId is equal to SessionId.");
                        // Do nothing
                    }
                    else if (sessionSetupRequest.user == ModelUser.DefaultUser)
                    {
                        ModelHelper.Log(LogType.Requirement,
                                        "2.	Otherwise, if the server determines the authentications were for the same user, " +
                                        "the server MUST remove the old session from the GlobalSessionTable and also from the Connection.SessionTable, as specified in section 3.3.7.1.");
                        ModelHelper.Log(LogType.TestInfo, "The authentications were for the same user");
                        GlobalSessionTable.Remove(sessionSetupRequest.previousSessionId);
                    }
                }
            }

            ModelHelper.Log(LogType.Requirement, "13. Session.State MUST be set to Valid.");
            // Update both GlobalSessionTable and ConnectionList
            GlobalSessionTable[sessionSetupRequest.sessionId].State        = ModelSessionState.Valid;
            ConnectionList[sessionSetupRequest.connectionId].Session.State = ModelSessionState.Valid;
        }
        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);
        }
        private void InitializeMainChannel(
            ModelDialectRevision maxSmbVersionClientSupported,
            Guid clientGuid,
            ReplayModelShareType shareType,
            out uint treeId,
            bool isReconnect = false,
            bool isClientSupportPersistent = true)
        {
            Site.Assume.IsNull(smb2ClientMainChannel, "Expect smb2ClientMainChannel is NULL.");

            smb2ClientMainChannel = new Smb2FunctionalClient(testConfig.Timeout, testConfig, Site);
            smb2ClientMainChannel.Smb2Client.LeaseBreakNotificationReceived  += new Action <Packet_Header, LEASE_BREAK_Notification_Packet>(OnLeaseBreakNotificationReceived);
            smb2ClientMainChannel.Smb2Client.OplockBreakNotificationReceived += new Action <Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived);
            serverIpMainChannel   = (shareType == ReplayModelShareType.CAShare ? testConfig.CAShareServerIP : testConfig.SutIPAddress);
            serverNameMainChannel = (shareType == ReplayModelShareType.CAShare) ? testConfig.CAShareServerName : testConfig.SutComputerName;
            smb2ClientMainChannel.ConnectToServer(testConfig.UnderlyingTransport, serverNameMainChannel, serverIpMainChannel);

            DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported));
            uint status;

            #region Negotiate

            Capabilities_Values capability = isClientSupportPersistent ?
                                             Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU |
                                             Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES |
                                             Capabilities_Values.GLOBAL_CAP_ENCRYPTION :
                                             Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU |
                                             Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_ENCRYPTION;
            NEGOTIATE_Response?negotiateResponse = null;
            clientCapabilitiesMainChannel = ModelUtility.IsSmb3xFamily(maxSmbVersionClientSupported)? capability : Capabilities_Values.NONE;
            status = smb2ClientMainChannel.Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: clientCapabilitiesMainChannel,
                clientGuid: maxSmbVersionClientSupported == ModelDialectRevision.Smb2002 ? Guid.Empty : clientGuid,
                checker: (header, response) =>
            {
                Site.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

                negotiateResponse = response;
            });

            dialectMainChannel = negotiateResponse.Value.DialectRevision;
            #endregion

            #region SESSION_SETUP
            principleNameMainChannel = (shareType == ReplayModelShareType.CAShare ? testConfig.CAShareServerName : testConfig.SutComputerName);
            if (isReconnect)
            {
                status = smb2ClientMainChannel.ReconnectSessionSetup(
                    sessionIdMainChannel,
                    testConfig.DefaultSecurityPackage,
                    principleNameMainChannel,
                    testConfig.AccountCredential,
                    testConfig.UseServerGssToken);
                sessionIdMainChannel  = smb2ClientMainChannel.SessionId;
                sessionKeyMainChannel = smb2ClientMainChannel.SessionKey;
            }
            else
            {
                status = smb2ClientMainChannel.SessionSetup(
                    testConfig.DefaultSecurityPackage,
                    principleNameMainChannel,
                    testConfig.AccountCredential,
                    testConfig.UseServerGssToken);
                sessionIdMainChannel  = smb2ClientMainChannel.SessionId;
                sessionKeyMainChannel = smb2ClientMainChannel.SessionKey;
            }

            Site.Log.Add(
                LogEntryKind.Debug,
                "Global encryption disabled");

            #endregion

            #region TREE_CONNECT to share
            sharePathMainChannel = (shareType == ReplayModelShareType.CAShare ?
                                    Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName) : Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare));
            status = smb2ClientMainChannel.TreeConnect(
                sharePathMainChannel,
                out treeId);
            Site.Log.Add(
                LogEntryKind.Debug,
                "Establish main channel to connect share {0}", sharePathMainChannel);

            smb2ClientMainChannel.SetTreeEncryption(treeId, false);
            #endregion
        }
        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 static void SessionSetupResponse(ModelSmb2Status status, SessionEncryptDataType sessionEncryptDataType, EncryptionConfig c)
        {
            Condition.IsTrue(state == ModelState.Connected);

            Condition.IsTrue(config.IsGlobalEncryptDataEnabled == c.IsGlobalEncryptDataEnabled);
            Condition.IsTrue(config.IsGlobalRejectUnencryptedAccessEnabled == c.IsGlobalRejectUnencryptedAccessEnabled);

            if (ModelUtility.IsSmb3xFamily(config.MaxSmbVersionSupported) &&
                !Smb2Utility.IsSmb3xFamily(negotiateDialect) &&
                config.IsGlobalEncryptDataEnabled &&
                config.IsGlobalRejectUnencryptedAccessEnabled)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.5: 1. If the server implements the SMB 3.x dialect family, " +
                                "Connection.Dialect does not belong to the SMB 3.x dialect family, EncryptData is TRUE, " +
                                "and RejectUnencryptedAccess is TRUE, the server MUST fail the request with STATUS_ACCESS_DENIED.");
                ModelHelper.Log(LogType.TestInfo,
                                "The server implements {0}, Connection.Dialect is {1}, EncryptData is TRUE and RejectUnencryptedAccess is TRUE",
                                config.MaxSmbVersionSupported, negotiateDialect);

                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                Condition.IsTrue(status == ModelSmb2Status.STATUS_ACCESS_DENIED);
                return;
            }

            if (Smb2Utility.IsSmb3xFamily(negotiateDialect) &&
                config.IsGlobalEncryptDataEnabled &&
                config.IsGlobalRejectUnencryptedAccessEnabled &&
                !Connection_ClientCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.5: 2. If Connection.Dialect belongs to the SMB 3.x dialect family, " +
                                "EncryptData is TRUE, RejectUnencryptedAccess is TRUE, " +
                                "and Connection.ClientCapabilities does not include the SMB2_GLOBAL_CAP_ENCRYPTION bit, " +
                                "the server MUST fail the request with STATUS_ACCESS_DENIED.");
                ModelHelper.Log(LogType.TestInfo,
                                "Connection.Dialect is {0}, EncryptData is TRUE, RejectUnencryptedAccess is TRUE, " +
                                "and Connection.ClientCapabilities does not include the SMB2_GLOBAL_CAP_ENCRYPTION bit.", negotiateDialect);

                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                Condition.IsTrue(status == ModelSmb2Status.STATUS_ACCESS_DENIED);
                return;
            }

            if (Smb2Utility.IsSmb3xFamily(negotiateDialect) &&
                config.IsGlobalEncryptDataEnabled &&
                (Connection_ServerCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION ||
                 config.IsGlobalRejectUnencryptedAccessEnabled))
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.5.3: 10.	If global EncryptData is TRUE, the server MUST do the following: " +
                                "If Connection.ServerCapabilities includes SMB2_GLOBAL_CAP_ENCRYPTION or RejectUnencryptedAccess is TRUE,");
                Condition.IsTrue(sessionEncryptDataType == SessionEncryptDataType.SessionEncryptDataSet);
                Session_EncryptData = SessionEncryptDataType.SessionEncryptDataSet;
            }

            Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
            Session_IsExisted = true;
        }
示例#14
0
        public void SetupConnection(ModelDialectRevision clientMaxDialect)
        {
            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);
            testClient.RequestSent += new Action <Packet_Header>(PrintSequenceWindow);

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

            uint status;
            NEGOTIATE_Response?negotiateResponse = null;

            status = testClient.Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_LARGE_MTU,
                checker: (header, response) =>
            {
                Site.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

                // The server MUST grant the client at least 1 credit when responding to SMB2 NEGOTIATE.
                Site.Assert.IsTrue(
                    header.CreditRequestResponse >= 1,
                    "The server MUST grant the client at least 1 credit when responding to SMB2 NEGOTIATE");

                negotiateResponse = response;
            });

            Site.Log.Add(
                LogEntryKind.Debug,
                "The maximum size, in bytes, of Length in READ/WRITE that server will accept on the connection is {0}",
                testClient.MaxBufferSize);

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

            negotiateDialect = negotiateResponse.Value.DialectRevision;

            if ((negotiateDialect == DialectRevision.Smb21 || ModelUtility.IsSmb3xFamily(negotiateDialect))
                // In case server does not support multicredit even implement Smb21 or Smb30
                && testConfig.IsMultiCreditSupported)
            {
                isMultiCreditSupportedOnConnection = true;
            }
            else
            {
                isMultiCreditSupportedOnConnection = false;
            }

            status = testClient.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);

            status = testClient.TreeConnect(
                uncSharePath,
                out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            fileName = GetTestFileName(uncSharePath);
            status   = testClient.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);
        }
        public void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ModelShareFlag shareFlag, ModelShareType shareType)
        {
            IPAddress ip;

            if (shareType == ModelShareType.STYPE_CLUSTER_SOFS)
            {
                server = testConfig.ScaleOutFileServerName;
                ip     = Dns.GetHostEntry(server).AddressList[0];

                if (shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK)
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.ScaleOutFileServerName, testConfig.ShareWithForceLevel2AndSOFS);
                }
                else
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.ScaleOutFileServerName, testConfig.ShareWithoutForceLevel2WithSOFS);
                }
            }
            else
            {
                server = testConfig.SutComputerName;
                ip     = testConfig.SutIPAddress;
                if (shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK)
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.ShareWithForceLevel2WithoutSOFS);
                }
                else
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.ShareWithoutForceLevel2OrSOFS);
                }
            }

            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.Smb2Client.OplockBreakNotificationReceived += new Action <Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived);

            testClient.ConnectToServer(testConfig.UnderlyingTransport, server, ip, testConfig.ClientNic1IPAddress);

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

            NEGOTIATE_Response?negotiateResponse = null;

            testClient.Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                checker: (header, response) =>
            {
                Site.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

                negotiateResponse = response;
            });

            negotiatedDialect = negotiateResponse.Value.DialectRevision;

            testClient.SessionSetup(
                testConfig.DefaultSecurityPackage,
                server,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);

            testClient.TreeConnect(
                uncSharePath,
                out treeId,
                checker: (header, response) =>
            {
                Site.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

                Site.Assert.AreEqual(
                    shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK,
                    response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_FORCE_LEVELII_OPLOCK),
                    "SHAREFLAG_FORCE_LEVELII_OPLOCK is{0}expected to be set",
                    shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK ? " " : " not ");

                if (ModelUtility.IsSmb3xFamily(negotiateResponse.Value.DialectRevision))
                {
                    Site.Assert.AreEqual(
                        shareType == ModelShareType.STYPE_CLUSTER_SOFS,
                        response.Capabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_SCALEOUT),
                        "SHARE_CAP_SCALEOUT is{0}expected to be set",
                        shareType == ModelShareType.STYPE_CLUSTER_SOFS ? " " : " not ");
                }
            });
        }
        private static bool VerifyTreeConnect(ModelSmb2Status status, ModelRequestType modelRequestType, EncryptionConfig c)
        {
            ModelHelper.Log(LogType.Requirement, "3.3.5.2.11 Verifying the Tree Connect");

            if (Encryption_TreeId == EncryptionTreeId.NoTreeId)
            {
                ModelHelper.Log(LogType.Requirement,
                                "The server MUST look up the TreeConnect in Session.TreeConnectTable by using the TreeId in the SMB2 header of the request. " +
                                "If no tree connect is found, the request MUST be failed with STATUS_NETWORK_NAME_DELETED.");
                ModelHelper.Log(LogType.TestInfo, "No tree connect is found.");
                ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier);

                Condition.IsTrue(status == ModelSmb2Status.STATUS_NETWORK_NAME_DELETED);
                return(false);
            }

            if (ModelUtility.IsSmb3xFamily(config.MaxSmbVersionSupported))
            {
                ModelHelper.Log(LogType.Requirement,
                                "If the server implements the SMB 3.x dialect family, it MUST return STATUS_ACCESS_DENIED for the following cases:");
                ModelHelper.Log(LogType.TestInfo, "The server implements {0}.", config.MaxSmbVersionSupported);

                if (Encryption_TreeId == EncryptionTreeId.TreeIdToEncryptShare &&
                    config.IsGlobalRejectUnencryptedAccessEnabled &&
                    modelRequestType == ModelRequestType.UnEncryptedRequest)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "\tIf TreeConnect.Share.EncryptData is TRUE, RejectUnencryptedAccess is TRUE, and Request.IsEncrypted is FALSE.");
                    ModelHelper.Log(LogType.TestInfo, "The above conditions are met.");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                    Condition.IsTrue(status == ModelSmb2Status.STATUS_ACCESS_DENIED);
                    return(false);
                }
                else if (config.IsGlobalEncryptDataEnabled &&
                         config.IsGlobalRejectUnencryptedAccessEnabled &&
                         modelRequestType == ModelRequestType.UnEncryptedRequest)
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "\tIf EncryptData is TRUE, RejectUnencryptedAccess is TRUE, and Request.IsEncrypted is FALSE.");
                    ModelHelper.Log(LogType.TestInfo, "The above conditions are met.");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                    Condition.IsTrue(status == ModelSmb2Status.STATUS_ACCESS_DENIED);
                    return(false);
                }
            }

            if (ModelUtility.IsSmb3xFamily(config.MaxSmbVersionSupported) &&
                (config.IsGlobalEncryptDataEnabled ||
                 Encryption_TreeId == EncryptionTreeId.TreeIdToEncryptShare ||
                 modelRequestType == ModelRequestType.EncryptedRequest) &&
                config.IsGlobalRejectUnencryptedAccessEnabled &&
                !Connection_ServerCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION)
            {
                ModelHelper.Log(LogType.Requirement,
                                "If the server implements the SMB 3.x dialect family, EncryptData or TreeConnect.Share.EncryptData or Request.IsEncrypted is TRUE, " +
                                "RejectUnencryptedAccess is TRUE, and Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_ENCRYPTION, " +
                                "the server SHOULD fail the request with STATUS_ACCESS_DENIED.");

                Condition.IsTrue(config.Platform == c.Platform);
                ModelHelper.Log(LogType.TestInfo,
                                "The server implements {0}, EncryptData is {1}, TreeConnect.Share.EncryptData is {2}, " +
                                "Request.IsEncrypted is {3}, RejectUnencryptedAccess is TRUE, " +
                                "and Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_ENCRYPTION.",
                                config.MaxSmbVersionSupported,
                                config.IsGlobalEncryptDataEnabled,
                                Encryption_TreeId == EncryptionTreeId.TreeIdToEncryptShare ? "TRUE" : "FALSE",
                                modelRequestType == ModelRequestType.EncryptedRequest ? "TRUE" : "FALSE");
                ModelHelper.Log(LogType.TestInfo, "The SUT platform is {0}.", config.Platform);

                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                if (config.Platform == Platform.NonWindows)
                {
                    Condition.IsTrue(status != ModelSmb2Status.STATUS_SUCCESS);
                }
                else
                {
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_ACCESS_DENIED);
                }
                return(false);
            }

            return(true);
        }
示例#17
0
        public static void NegotiateResponse(ModelSmb2Status status, DialectRevision dialectRevision)
        {
            Condition.IsTrue(State == ModelState.Connected);
            Condition.IsTrue(Request is ModelComNegotiateRequest || Request is NegotiateRequest);

            // Avoid "Microsoft.SpecExplorer.Runtime.Testing.UnboundVariableException: Variable's value cannot be read before it is bound"
            Condition.IsTrue(dialectRevision == DialectRevision.Smb2002 || dialectRevision == DialectRevision.Smb21 ||
                             dialectRevision == DialectRevision.Smb30 || dialectRevision == DialectRevision.Smb302 ||
                             dialectRevision == DialectRevision.Smb2Wildcard ||
                             dialectRevision == DialectRevision.Smb2Unknown);

            if (Request is ModelComNegotiateRequest)
            {
                ModelComNegotiateRequest comNegotiateReq = ModelHelper.RetrieveOutstandingRequest <ModelComNegotiateRequest>(ref Request);

                if (Config.MaxSmbVersionSupported != DialectRevision.Smb21 && !ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported))
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.3.1: If the server does not implement the SMB 2.1 or 3.x dialect family, processing MUST continue as specified in 3.3.5.3.2.");

                    ComNegotiateHandleSmb2002InResponse(dialectRevision);
                }
                else
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.3.1: Otherwise, the server MUST scan the dialects provided for the dialect string \"SMB 2.???\".");

                    if (comNegotiateReq.Dialects.Contains(SMBDialects.SMB_2_X))
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.3.1: If the string is present, the server MUST respond with an SMB2 NEGOTIATE Response as specified in 2.2.4.");

                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.3.1: DialectRevision MUST be set to 0x02FF");

                        NegotiateDialect = DialectRevision.Smb2Wildcard;

                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.3.1: Connection.NegotiateDialect MUST be set to 0x02FF, and the response is sent to the client");

                        Condition.IsTrue(dialectRevision == DialectRevision.Smb2Wildcard);
                    }
                    else
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.3.1: If the string is not present, continue to section 3.3.5.3.2");

                        ComNegotiateHandleSmb2002InResponse(dialectRevision);
                    }
                }
            }
            else
            {
                NegotiateRequest negotiateReq = ModelHelper.RetrieveOutstandingRequest <NegotiateRequest>(ref Request);

                if (negotiateReq.Dialects.Count == 0)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.4: If the DialectCount of the SMB2 NEGOTIATE Request is 0, the server MUST fail the request with STATUS_INVALID_PARAMETER");
                    ModelHelper.Log(
                        LogType.TestInfo,
                        "DialectCount of the SMB2 NEGOTIATE Request is 0");
                    ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER);
                    return;
                }

                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.4: The server MUST select the greatest common dialect between the dialects it implements and the Dialects array of the SMB2 NEGOTIATE request");

                DialectRevision commonDialect = SelectCommonDialect(negotiateReq.Dialects);

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Common dialect is {0}", commonDialect);
                if (commonDialect == DialectRevision.Smb2Unknown)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.4: If a common dialect is not found, the server MUST fail the request with STATUS_NOT_SUPPORTED");
                    ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_NOT_SUPPORTED);
                    return;
                }

                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.4: If a common dialect is found, the server MUST set Connection.Dialect to \"2.002\", \"2.100\", \"3.000\", or \"3.002\"," +
                    " and Connection.NegotiateDialect to 0x0202, 0x0210, 0x0300, or 0x0302 accordingly, to reflect the dialect selected");

                NegotiateDialect = commonDialect;

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Connection.Dialect is set to {0}", NegotiateDialect);

                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.4: The server MUST then construct an SMB2 NEGOTIATE Response, as specified in section 2.2.4, with the following specific values, and return STATUS_SUCCESS to the client.");
                ModelHelper.Log(
                    LogType.Requirement,
                    "\tDialectRevision MUST be set to the common dialect");

                Condition.IsTrue(dialectRevision == commonDialect);
            }

            Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
        }
示例#18
0
        public static void ComNegotiateRequest(Sequence <string> dialects)
        {
            Condition.IsTrue(State == ModelState.Connected);
            Condition.IsNull(Request);

            Request = new ModelComNegotiateRequest(dialects);

            if (MessageId > 0)
            {
                // Negotiate request is always expected to be the first message in a connection
                State = ModelState.Disconnected;
                return;
            }

            ModelHelper.Log(
                LogType.Requirement,
                "3.3.5.3: This request is defined in [MS-SMB] section 2.2.4.5.1, with the SMB header defined in section 2.2.3.1." +
                " If the request matches the format described there, and Connection.NegotiateDialect is 0xFFFF, processing MUST continue as specified in 3.3.5.3.1.");

            if (NegotiateDialect != DialectRevision.Smb2Unknown)
            //|| (!dialects.Contains(SMBDialects.SMB_2_002) && !dialects.Contains(SMBDialects.SMB_2_X))) // TODO: more comments?
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.3: Otherwise, the server MUST disconnect the connection, as specified in section 3.3.7.1, without sending a response.");
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                State = ModelState.Disconnected;
                return;
            }

            if (!(Config.MaxSmbVersionSupported == DialectRevision.Smb21 || ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported)))
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.3.1: If the server does not implement the SMB 2.1 or 3.x dialect family, processing MUST continue as specified in 3.3.5.3.2.");

                ComNegotiateHandleSmb2002InRequest(dialects);
            }
            else
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.3.1: Otherwise, the server MUST scan the dialects provided for the dialect string \"SMB 2.???\".");

                if (!dialects.Contains(SMBDialects.SMB_2_X))
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.3.1: If the string is not present, continue to section 3.3.5.3.2.");

                    ComNegotiateHandleSmb2002InRequest(dialects);
                }
                else
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.3.1: If the string is present, the server MUST respond with an SMB2 NEGOTIATE Response as specified in 2.2.4");
                    ModelHelper.Log(
                        LogType.TestInfo,
                        "\"SMB 2.???\" is present in the dialects provided");
                }
            }

            // After every successful call, messageId MUST be incremented by 1.
            // But in this model it is set to 1 to avoid to generate duplicate cases which only have different messageId.
            MessageId = 1;
        }
        public static void TreeConnectResponse(
            ModelSmb2Status status,
            ShareEncryptDataType shareEncryptDataType,
            ModelResponseType modelResponseType,
            EncryptionConfig c)
        {
            Condition.IsTrue(state == ModelState.Connected);
            Condition.IsTrue(config.IsGlobalRejectUnencryptedAccessEnabled == c.IsGlobalRejectUnencryptedAccessEnabled);
            Condition.IsTrue(Session_IsExisted);

            ModelTreeConnectRequest treeConnectRequest = ModelHelper.RetrieveOutstandingRequest <ModelTreeConnectRequest>(ref request);

            if (!VerifySession(status, treeConnectRequest.modelRequestType, c))
            {
                return;
            }

            if (ModelUtility.IsSmb3xFamily(config.MaxSmbVersionSupported) &&
                (config.IsGlobalEncryptDataEnabled ||
                 treeConnectRequest.connectToShareType == ConnectToShareType.ConnectToEncryptedShare) &&
                config.IsGlobalRejectUnencryptedAccessEnabled &&
                !Connection_ServerCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.7: If the server implements the SMB 3.x dialect family, EncryptData or Share.EncryptData is TRUE, " +
                                "RejectUnencryptedAccess is TRUE, and Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_ENCRYPTION, " +
                                "the server MUST fail the request with STATUS_ACCESS_DENIED.");
                Condition.IsTrue(config.Platform == c.Platform);
                ModelHelper.Log(LogType.TestInfo,
                                "The server implements {0}, EncryptData is {1}, Share.EncryptData is {2}, RejectUnencryptedAccess is TRUE, " +
                                "Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_ENCRYPTION.",
                                config.MaxSmbVersionSupported,
                                config.IsGlobalEncryptDataEnabled,
                                treeConnectRequest.connectToShareType == ConnectToShareType.ConnectToEncryptedShare ? "TRUE" : "FALSE");
                ModelHelper.Log(LogType.TestInfo, "The SUT platform is {0}.", config.Platform);
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                Condition.IsTrue(status == ModelSmb2Status.STATUS_ACCESS_DENIED);

                return;
            }

            if (Smb2Utility.IsSmb3xFamily(negotiateDialect) &&
                treeConnectRequest.connectToShareType == ConnectToShareType.ConnectToEncryptedShare &&
                config.IsGlobalRejectUnencryptedAccessEnabled &&
                !Connection_ServerCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.7: If Connection.Dialect belongs to the SMB 3.x dialect family, " +
                                "Share.EncryptData is TRUE, RejectUnencryptedAccess is TRUE, " +
                                "and Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_ENCRYPTION, " +
                                "the server MUST fail the request with STATUS_ACCESS_DENIED.");
                ModelHelper.Log(LogType.Requirement,
                                "\tSet the SMB2_SHAREFLAG_ENCRYPT_DATA bit.");
                ModelHelper.Log(LogType.TestInfo, "Connection.Dialect is {0}, and Share.EncryptData is TRUE.", negotiateDialect);
                Condition.IsTrue(shareEncryptDataType == ShareEncryptDataType.ShareEncryptDataSet);
            }

            //TODO: To be implemented after TRANSFORM_HEADER added into Smb2FunctionalClient
            if (treeConnectRequest.modelRequestType == ModelRequestType.EncryptedRequest)
            {
                Condition.IsTrue(modelResponseType == ModelResponseType.EncryptedResponse);
            }
            else
            {
                Condition.IsTrue(modelResponseType == ModelResponseType.UnEncryptedResponse);
            }
            Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS);

            Encryption_TreeId = (treeConnectRequest.connectToShareType == ConnectToShareType.ConnectToEncryptedShare) ? EncryptionTreeId.TreeIdToEncryptShare : EncryptionTreeId.TreeIdToUnEncryptShare;
        }
        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,
                    "");
            }
        }