Exemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the DefaultLeaseResponseChecker class with specified TestSite, LeaseKey and LeaseState.
 /// </summary>
 /// <param name="TestSite">The TestSite used to provide logging, assertions, and SUT adapters.</param>
 /// <param name="leaseKey">The expected LeaseKey value in the response.</param>
 /// <param name="leaseState">The expected LeaseState value in the response.</param>
 /// <param name="leaseFlag">The expected LeaseFlag value in the response.</param>
 public DefaultLeaseResponseChecker(ITestSite TestSite, Guid leaseKey, LeaseStateValues leaseState, LeaseFlagsValues leaseFlag)
     : base(TestSite, typeof(Smb2CreateResponseLease))
 {
     this.leaseKey   = leaseKey;
     this.leaseState = leaseState;
     this.leaseFlag  = leaseFlag;
 }
Exemplo n.º 2
0
 /// <summary>
 /// Initializes a new instance of the DefaultLeaseV2ResponseChecker class with specified TestSite, LeaseKey, LeaseState and ParentLeaseKey.
 /// </summary>
 /// <param name="TestSite">The TestSite used to provide logging, assertions, and SUT adapters.</param>
 /// <param name="leaseKey">The expected LeaseKey value in the response.</param>
 /// <param name="leaseState">The expected LeaseState value in the response.</param>
 /// <param name="leaseFlag">The expected LeaseFlag value in the response.</param>
 /// <param name="parentLeaseKey">The expected ParentLeaseKey value in the response. Default value indicates not checking this field.</param>
 public DefaultLeaseV2ResponseChecker(ITestSite TestSite, Guid leaseKey, LeaseStateValues leaseState, LeaseFlagsValues leaseFlag, Guid parentLeaseKey = default(Guid))
     : base(TestSite, typeof(Smb2CreateResponseLeaseV2))
 {
     this.leaseKey       = leaseKey;
     this.leaseState     = leaseState;
     this.leaseFlag      = leaseFlag;
     this.parentLeaseKey = parentLeaseKey;
 }
        public static void CreateRequest(ConnectTargetType connectTargetType, LeaseContextType leaseContextType,
                                         LeaseKeyType leaseKey, uint leaseState, LeaseFlagsValues leaseFlags, ParentLeaseKeyType parentLeaseKey)
        {
            Condition.IsTrue(state == ModelState.Connected);
            Condition.IsNull(request);

            // Limit these three less important paramters to reduce test case numbers.
            Combination.NWise(1, connectTargetType, leaseKey, leaseState);

            // Current leasing only supports to test leasing on the file. So limit the exploration.
            Condition.In(parentLeaseKey, ParentLeaseKeyType.EmptyParentLeaseKey, ParentLeaseKeyType.ValidParentLeaseKey);
            Combination.Pairwise(leaseFlags, parentLeaseKey);

            // If Conenction.Dialect is Smb2.002 or Smb2.1, then do not test Lease V2.
            Condition.IfThen(
                negotiateDialect == DialectRevision.Smb21 || negotiateDialect == DialectRevision.Smb2002,
                leaseContextType == LeaseContextType.LeaseV1);

            if (leaseContextType == LeaseContextType.LeaseV1)
            {
                request = new ModelCreateLeaseRequest(
                    (connectTargetType == ConnectTargetType.ConnectToDirectory) ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                    new ModelCreateRequestLease
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                    LeaseFlags = leaseFlags
                },
                    leaseContextType);
            }
            else
            {
                request = new ModelCreateLeaseRequest(
                    (connectTargetType == ConnectTargetType.ConnectToDirectory) ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                    new ModelCreateRequestLeaseV2
                {
                    LeaseKey       = leaseKey,
                    LeaseState     = leaseState,
                    LeaseFlags     = leaseFlags,
                    ParentLeaseKey = parentLeaseKey
                },
                    leaseContextType);
            }
        }
        public static void CreateRequest(ConnectTargetType connectTargetType, LeaseContextType leaseContextType,
            LeaseKeyType leaseKey, uint leaseState, LeaseFlagsValues leaseFlags, ParentLeaseKeyType parentLeaseKey)
        {
            Condition.IsTrue(state == ModelState.Connected);
            Condition.IsNull(request);

            // Limit these three less important paramters to reduce test case numbers.
            Combination.NWise(1, connectTargetType, leaseKey, leaseState);

            // Current leasing only supports to test leasing on the file. So limit the exploration.
            Condition.In(parentLeaseKey, ParentLeaseKeyType.EmptyParentLeaseKey, ParentLeaseKeyType.ValidParentLeaseKey);
            Combination.Pairwise(leaseFlags, parentLeaseKey);

            // If Conenction.Dialect is Smb2.002 or Smb2.1, then do not test Lease V2.
            Condition.IfThen(
                negotiateDialect == DialectRevision.Smb21 || negotiateDialect == DialectRevision.Smb2002,
                leaseContextType == LeaseContextType.LeaseV1);

            if (leaseContextType == LeaseContextType.LeaseV1)
            {
                request = new ModelCreateLeaseRequest(
                    (connectTargetType == ConnectTargetType.ConnectToDirectory) ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                    new ModelCreateRequestLease
                    {
                        LeaseKey = leaseKey,
                        LeaseState = leaseState,
                        LeaseFlags = leaseFlags
                    },
                    leaseContextType);
            }
            else
            {
                request = new ModelCreateLeaseRequest(
                    (connectTargetType == ConnectTargetType.ConnectToDirectory) ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                    new ModelCreateRequestLeaseV2
                    {
                        LeaseKey = leaseKey,
                        LeaseState = leaseState,
                        LeaseFlags = leaseFlags,
                        ParentLeaseKey = parentLeaseKey
                    },
                    leaseContextType);
            }
        }
        public void CreateRequest(ConnectTargetType connectTargetType, LeaseContextType leaseContextType,
            LeaseKeyType leaseKey, uint leaseState, LeaseFlagsValues leaseFlags,
            ParentLeaseKeyType parentLeaseKey)
        {
            ValidateLeaseState(leaseState);

            uint status = 0;
            #region Fill Contexts
            LeaseKey = (leaseKey == LeaseKeyType.ValidLeaseKey ? Guid.NewGuid() : Guid.Empty);
            ParentLeaseKey = (parentLeaseKey == ParentLeaseKeyType.EmptyParentLeaseKey ? Guid.Empty : Guid.NewGuid());
            originalClient.IsDirectory = connectTargetType == ConnectTargetType.ConnectToDirectory;

            switch (leaseContextType)
            {
                case LeaseContextType.LeaseV1:
                    testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE);

                    originalClient.CreateContexts = new Smb2CreateContextRequest[]
                    {
                        new Smb2CreateRequestLease
                        {
                            LeaseKey = LeaseKey,
                            LeaseState = (LeaseStateValues)leaseState,
                            LeaseFlags = (uint)leaseFlags,
                        }
                    };
                    break;
                case LeaseContextType.LeaseV2:
                    testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2);

                    originalClient.CreateContexts = new Smb2CreateContextRequest[]
                    {
                        new Smb2CreateRequestLeaseV2
                        {
                            LeaseKey = LeaseKey,
                            LeaseState = (LeaseStateValues)leaseState,
                            LeaseFlags = (uint)leaseFlags,
                            ParentLeaseKey = ParentLeaseKey,
                        }
                    };
                    break;
                default:
                    Site.Assume.Fail("Unexpected type: {0}", leaseContextType);
                    break;
            }
            #endregion

            Packet_Header header;
            CREATE_Response createResponse;
            Smb2CreateContextResponse[] serverCreateContexts;

            status = originalClient.Client.Create(1, 64, originalClient.Flags, originalClient.MessageId++, originalClient.SessionId, originalClient.TreeId, originalClient.File,
                AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE,
                ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE,
                (connectTargetType == ConnectTargetType.ConnectToDirectory) ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                CreateDisposition_Values.FILE_OPEN_IF,
                File_Attributes.NONE,
                ImpersonationLevel_Values.Impersonation,
                SecurityFlags_Values.NONE,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                originalClient.CreateContexts,
                out originalClient.FileId,
                out serverCreateContexts,
                out header,
                out createResponse);

            #region Handle Create Response

            // 3.3.5.9.11   Handling the SMB2_CREATE_REQUEST_LEASE_V2 Create Context
            // If Connection.Dialect does not belong to the SMB 3.x dialect family or if RequestedOplockLevel is not SMB2_OPLOCK_LEVEL_LEASE, the server SHOULD<270> ignore the SMB2_CREATE_REQUEST_LEASE_V2 Create Context request.
            // <270> Section 3.3.5.9.11: Windows 8, Windows Server 2012, Windows 8.1,
            // and Windows Server 2012 R2 servers do not ignore the SMB2_CREATE_REQUEST_LEASE_V2 create context when Connection.Dialect is equal to "2.100" or if RequestedOplockLevel is not equal to SMB2_OPLOCK_LEVEL_LEASE.
            if (!Smb2Utility.IsSmb3xFamily(originalClient.Dialect) && leaseContextType == LeaseContextType.LeaseV2)
            {
                Smb2CreateResponseLeaseV2 leaseContext = null;
                if (serverCreateContexts != null)
                {
                    foreach (var context in serverCreateContexts)
                    {
                        if (context is Smb2CreateResponseLeaseV2)
                        {
                            leaseContext = context as Smb2CreateResponseLeaseV2;
                            break;
                        }
                    }
                }
                if (testConfig.Platform == Platform.NonWindows)
                {
                    Site.Assert.IsNull(leaseContext, "Create response should not include SMB2_CREATE_RESPONSE_LEASE_V2.");
                }
                else
                {
                    if (originalClient.Dialect == DialectRevision.Smb21
                        && (testConfig.Platform == Platform.WindowsServer2012
                            || testConfig.Platform == Platform.WindowsServer2012R2))
                    {
                        Site.Assert.IsNotNull(leaseContext, "Create response should include SMB2_CREATE_RESPONSE_LEASE_V2 when platform is Windows 8, Windows 2012 and Windows 2012R2 and dialect is equal to \"2.100\".");
                    }
                    else
                    {
                        Site.Assert.IsNull(leaseContext, "Create response should not include SMB2_CREATE_RESPONSE_LEASE_V2.");
                    }
                }
                // Bypass the situation to avoid Windows issues.
                this.CreateResponse(ModelSmb2Status.STATUS_SUCCESS, ReturnLeaseContextType.ReturnLeaseContextNotIncluded,
                    (uint)LeaseStateValues.SMB2_LEASE_NONE, LeaseFlagsValues.NONE, leasingConfig);
            }
            else if (status == Smb2Status.STATUS_SUCCESS)
            {
                if (leaseContextType == LeaseContextType.LeaseV1)
                {
                    if (serverCreateContexts != null)
                    {
                        Smb2CreateResponseLease leaseContext = null;
                        foreach (var context in serverCreateContexts)
                        {
                            if (context is Smb2CreateResponseLease)
                            {
                                leaseContext = context as Smb2CreateResponseLease;
                                break;
                            }
                        }
                        Site.Assert.IsNotNull(leaseContext, "Create response MUST include SMB2_CREATE_RESPONSE_LEASE.");

                        Site.Assert.AreEqual<Guid>(LeaseKey, leaseContext.LeaseKey, "Expect the LeaseKey in the response equals the LeaseKey in the request.");
                        Site.Assert.AreEqual<LeaseFlagsValues>(LeaseFlagsValues.NONE, leaseContext.LeaseFlags, "Expect the lease is not in breaking.");
                        Site.CaptureRequirementIfAreEqual<ulong>(0, leaseContext.LeaseDuration,
                            RequirementCategory.MUST_BE_ZERO.Id,
                            RequirementCategory.MUST_BE_ZERO.Description);

                        originalClient.LeaseState = leaseContext.LeaseState;
                        this.CreateResponse((ModelSmb2Status)status, ReturnLeaseContextType.ReturnLeaseContextIncluded,
                            (uint)leaseContext.LeaseState, leaseContext.LeaseFlags, leasingConfig);
                    }
                    else
                    {
                        this.CreateResponse((ModelSmb2Status)status, ReturnLeaseContextType.ReturnLeaseContextNotIncluded,
                            (uint)LeaseStateValues.SMB2_LEASE_NONE, LeaseFlagsValues.NONE,  leasingConfig);
                    }
                }
                else if (leaseContextType == LeaseContextType.LeaseV2)
                {
                    if (serverCreateContexts != null)
                    {
                        Smb2CreateResponseLeaseV2 leaseContext = null;
                        foreach (var context in serverCreateContexts)
                        {
                            if (context is Smb2CreateResponseLeaseV2)
                            {
                                leaseContext = context as Smb2CreateResponseLeaseV2;
                                break;
                            }
                        }
                        Site.Assert.IsNotNull(leaseContext, "Create response MUST include SMB2_CREATE_RESPONSE_LEASE_V2.");

                        Site.Assert.AreEqual<Guid>(LeaseKey, leaseContext.LeaseKey, "Expect the LeaseKey in the response equals the LeaseKey in the request.");
                        Site.Assert.IsTrue((leaseContext.Flags & LeaseFlagsValues.LEASE_FLAG_BREAK_IN_PROGRESS) == 0, "Expect the lease is not in breaking.");
                        Site.CaptureRequirementIfAreEqual<ulong>(0, leaseContext.LeaseDuration,
                            RequirementCategory.MUST_BE_ZERO.Id,
                            RequirementCategory.MUST_BE_ZERO.Description);
                        if ((leaseContext.Flags & LeaseFlagsValues.SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET) != 0)
                        {
                            Site.Assert.AreEqual<Guid>(ParentLeaseKey, leaseContext.ParentLeaseKey, "Expect the ParentLeaseKey in the response equals the ParentLeaseKey in the request.");
                        }
                        else
                        {
                            Site.Assert.AreEqual<Guid>(Guid.Empty, leaseContext.ParentLeaseKey, "Expect the ParentLeaseKey in the response is empty.");
                        }
                        // Epoch (2 bytes): A 16-bit unsigned integer incremented by the server on a lease state change.
                        Site.Assert.AreEqual<ulong>(1, leaseContext.Epoch, "Expect the Epoch in the response equals 1.");
                        if (testConfig.Platform == Platform.NonWindows)
                        {
                            // Reserved (2 bytes): This field MUST NOT be used and MUST be reserved. The server SHOULD<52> set this to 0, and the client MUST ignore it on receipt.
                            // <52> Section 2.2.14.2.11: Windows 8, Windows Server 2012, Windows 8.1, and Windows Server 2012 R2 set this field to an arbitrary value.
                            Site.CaptureRequirementIfAreEqual<ulong>(0, leaseContext.Reserved,
                                RequirementCategory.MUST_BE_ZERO.Id,
                                RequirementCategory.MUST_BE_ZERO.Description);
                        }

                        originalClient.LeaseState = leaseContext.LeaseState;
                        this.CreateResponse((ModelSmb2Status)status, ReturnLeaseContextType.ReturnLeaseContextIncluded,
                            (uint)leaseContext.LeaseState, leaseContext.Flags, leasingConfig);
                    }
                    else
                    {
                        this.CreateResponse((ModelSmb2Status)status, ReturnLeaseContextType.ReturnLeaseContextNotIncluded,
                            (uint)LeaseStateValues.SMB2_LEASE_NONE, LeaseFlagsValues.NONE, leasingConfig);
                    }
                }
                else
                {
                    Site.Assume.Fail("Unexpected type: {0}", leaseContextType);
                }
            }
            else
            {
                this.CreateResponse((ModelSmb2Status)status, ReturnLeaseContextType.ReturnLeaseContextNotIncluded,
                    (uint)LeaseStateValues.SMB2_LEASE_NONE, LeaseFlagsValues.NONE, leasingConfig);
            }
            #endregion

            #region Write Data
            if (status == Smb2Status.STATUS_SUCCESS && (connectTargetType == ConnectTargetType.ConnectToNonDirectory))
            {
                WRITE_Response writeResponse;
                byte[] data = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomString(1));
                status = originalClient.Client.Write(1, 1, originalClient.Flags, originalClient.MessageId++, originalClient.SessionId, originalClient.TreeId, 0, originalClient.FileId,
                    Channel_Values.CHANNEL_NONE, WRITE_Request_Flags_Values.None, new byte[0], data, out header, out writeResponse);
                originalClient.GrantedCredit = header.CreditRequestResponse;
                Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Write data to the file {0} failed with error code={1}", originalClient.File, Smb2Status.GetStatusCode(status));

                FLUSH_Response flushResponse;
                status = originalClient.Client.Flush(1, 1, originalClient.Flags, originalClient.MessageId++, originalClient.SessionId, originalClient.TreeId, originalClient.FileId,
                    out header, out flushResponse);
                originalClient.GrantedCredit = header.CreditRequestResponse;
                Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Flush data to the file {0} failed with error code={1}", originalClient.File, Smb2Status.GetStatusCode(status));
            }
            #endregion

            if (status == Smb2Status.STATUS_SUCCESS)
            {
                clients[(int)OperatorType.SameClientId].CreateContexts = originalClient.CreateContexts;
            }
        }
        public static void CreateResponse(ModelSmb2Status status, ReturnLeaseContextType returnLeaseContextType, uint leaseState,
                                          LeaseFlagsValues leaseFlags, LeasingConfig c)
        {
            Condition.IsTrue(state == ModelState.Connected);

            ModelCreateLeaseRequest createRequest = ModelHelper.RetrieveOutstandingRequest <ModelCreateLeaseRequest>(ref request);

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

            if (!c.IsLeasingSupported)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.9: If the server does not support leasing and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST ignore the \"RqLs\" create context.");
                ModelHelper.Log(LogType.TestInfo, "The above conditions are met.");
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextNotIncluded);
                return;
            }

            if ((negotiateDialect == DialectRevision.Smb21 || Smb2Utility.IsSmb3xFamily(negotiateDialect)) &&
                c.IsLeasingSupported &&
                (createRequest.ContextType == LeaseContextType.LeaseV1))    // the DataLength field equals 0x20
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.9: If the server supports leasing, the name of the create context is \"RqLs\" as defined in section 2.2.13.2, " +
                    "and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST do the following:");
                ModelHelper.Log(
                    LogType.Requirement,
                    "\tIf Connection.Dialect is \"2.100\" or belongs to the \"3.x\" dialect family, and the DataLength field equals 0x20, " +
                    "the server MUST attempt to acquire a lease on the open from the underlying object store as described in section 3.3.5.9.8.");
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met.");

                // 3.3.5.9.8   Handling the SMB2_CREATE_REQUEST_LEASE Create Context
                #region Handle SMB2_CREATE_REQUEST_LEASE
                Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextIncluded);
                ModelCreateRequestLease requestLease = null;

                requestLease = createRequest.LeaseContext as ModelCreateRequestLease;

                smb2Lease = new Smb2Lease();
                if (Smb2Utility.IsSmb3xFamily(negotiateDialect))
                {
                    ModelHelper.Log(LogType.Requirement, "3.3.5.9.8: If Connection.Dialect belongs to the SMB 3.x dialect family, Lease.Version is set to 1.");
                    smb2Lease.Version = 1;
                }

                if (requestLease.LeaseState != smb2Lease.LeaseState && ((~requestLease.LeaseState) & smb2Lease.LeaseState) == 0 && !smb2Lease.Breaking)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.8: If the lease state requested is a superset of Lease.LeaseState and Lease.Breaking is FALSE, " +
                        "the server MUST request promotion of the lease state from the underlying object store to the new caching state.");
                    ModelHelper.Log(LogType.TestInfo, "The above conditions are met.");
                    //If the object store succeeds this request, Lease.LeaseState MUST be set to the new caching state.
                    smb2Lease.LeaseState = requestLease.LeaseState;
                }

                // LeaseState MUST be set to Lease.LeaseState.
                Condition.IsTrue((uint)leaseState == smb2Lease.LeaseState);
                #endregion

                Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
                return;
            }

            if (Smb2Utility.IsSmb3xFamily(negotiateDialect) &&
                c.IsLeasingSupported &&
                (createRequest.ContextType == LeaseContextType.LeaseV2))    // the DataLength field equals 0x34
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.9: If the server supports leasing, the name of the create context is \"RqLs\" as defined in section 2.2.13.2, " +
                    "and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST do the following:");
                ModelHelper.Log(
                    LogType.Requirement,
                    "\tIf Connection.Dialect belongs to the \"3.x\" dialect family, and the DataLength field equals 0x34, " +
                    "the server MUST attempt to acquire a lease on the open from the underlying object store, as described in section 3.3.5.9.11.");
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met.");

                // 3.3.5.9.11   Handling the SMB2_CREATE_REQUEST_LEASE_V2 Create Context
                #region Handle SMB2_CREATE_REQUEST_LEASE_V2
                Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextIncluded);
                ModelCreateRequestLeaseV2 requestLease = null;

                requestLease = createRequest.LeaseContext as ModelCreateRequestLeaseV2;

                smb2Lease = new Smb2Lease(2);

                // To reduce parameters and states, use CreateOptions instead of FileAttributes here, as we assume settings in CreateOptions and FileAtributes are consistent.
                if (createRequest.CreateOptions.HasFlag(CreateOptions_Values.FILE_DIRECTORY_FILE) &&
                    (requestLease.LeaseState & (uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING) != 0)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.11: If the FileAttributes field in the request indicates that this operation is on a directory and " +
                        "LeaseState includes SMB2_LEASE_WRITE_CACHING, the server MUST clear the bit SMB2_LEASE_WRITE_CACHING in the LeaseState field.");
                    ModelHelper.Log(LogType.TestInfo, "SMB2_LEASE_WRITE_CACHING is cleared.");
                    requestLease.LeaseState &= ~(uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING;
                }

                if (requestLease.LeaseState != smb2Lease.LeaseState && ((~requestLease.LeaseState) & smb2Lease.LeaseState) == 0 && !smb2Lease.Breaking)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.8: If the lease state requested is a superset of Lease.LeaseState and Lease.Breaking is FALSE, " +
                        "the server MUST request promotion of the lease state from the underlying object store to the new caching state.<271> " +
                        "If the object store succeeds this request, Lease.LeaseState MUST be set to the new caching state.");
                    smb2Lease.LeaseState = requestLease.LeaseState;
                    // The server MUST increment Lease.Epoch by 1.
                    ModelHelper.Log(LogType.TestInfo, "Lease.Epoch is incremented by 1.");
                    smb2Lease.Epoch++;
                }

                // LeaseState MUST be set to Lease.LeaseState.
                Condition.IsTrue((uint)leaseState == smb2Lease.LeaseState);

                if (requestLease.LeaseFlags.HasFlag(LeaseFlagsValues.SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET))
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.11: If SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET bit is set in the Flags field of the request, " +
                        "ParentLeaseKey MUST be set to the ParentLeaseKey in the request and SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET bit MUST be set in the Flags field of the response.");
                    ModelHelper.Log(LogType.TestInfo, "SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET bit is set.");
                    Condition.IsTrue(leaseFlags.HasFlag(LeaseFlagsValues.SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET));
                }
                #endregion

                Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
                return;
            }

            Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextNotIncluded);
            Condition.IsTrue(leaseState == (uint)LeaseStateValues.SMB2_LEASE_NONE);
            Condition.IsTrue(leaseFlags == LeaseFlagsValues.NONE);
            Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
        }
 private Smb2CreateRequestLeaseV2 createLeaseV2RequestContext(Guid leaseKey       = new Guid(), LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING,
                                                              Guid parentLeaseKey = new Guid(), LeaseFlagsValues leaseFlag  = LeaseFlagsValues.SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET)
 {
     return(new Smb2CreateRequestLeaseV2
     {
         LeaseKey = leaseKey == Guid.Empty ? Guid.NewGuid() : leaseKey,
         LeaseState = leaseState,
         ParentLeaseKey = parentLeaseKey == Guid.Empty ? Guid.NewGuid() : parentLeaseKey,
         LeaseFlags = (uint)leaseFlag
     });
 }
 /// <summary>
 /// Initializes a new instance of the DefaultLeaseV2ResponseChecker class with specified TestSite, LeaseKey, LeaseState and ParentLeaseKey.
 /// </summary>
 /// <param name="TestSite">The TestSite used to provide logging, assertions, and SUT adapters.</param>
 /// <param name="leaseKey">The expected LeaseKey value in the response.</param>
 /// <param name="leaseState">The expected LeaseState value in the response.</param>
 /// <param name="leaseFlag">The expected LeaseFlag value in the response.</param>
 /// <param name="parentLeaseKey">The expected ParentLeaseKey value in the response. Default value indicates not checking this field.</param>
 public DefaultLeaseV2ResponseChecker(ITestSite TestSite, Guid leaseKey, LeaseStateValues leaseState, LeaseFlagsValues leaseFlag, Guid parentLeaseKey = default(Guid))
     : base(TestSite, typeof(Smb2CreateResponseLeaseV2))
 {
     this.leaseKey = leaseKey;
     this.leaseState = leaseState;
     this.leaseFlag = leaseFlag;
     this.parentLeaseKey = parentLeaseKey;
 }
 /// <summary>
 /// Initializes a new instance of the DefaultLeaseResponseChecker class with specified TestSite, LeaseKey and LeaseState.
 /// </summary>
 /// <param name="TestSite">The TestSite used to provide logging, assertions, and SUT adapters.</param>
 /// <param name="leaseKey">The expected LeaseKey value in the response.</param>
 /// <param name="leaseState">The expected LeaseState value in the response.</param>
 /// <param name="leaseFlag">The expected LeaseFlag value in the response.</param>
 public DefaultLeaseResponseChecker(ITestSite TestSite, Guid leaseKey, LeaseStateValues leaseState, LeaseFlagsValues leaseFlag)
     : base(TestSite, typeof(Smb2CreateResponseLease))
 {
     this.leaseKey = leaseKey;
     this.leaseState = leaseState;
     this.leaseFlag = leaseFlag;
 }
        public static void CreateResponse(ModelSmb2Status status, ReturnLeaseContextType returnLeaseContextType, uint leaseState, 
            LeaseFlagsValues leaseFlags, LeasingConfig c)
        {
            Condition.IsTrue(state == ModelState.Connected);

            ModelCreateLeaseRequest createRequest = ModelHelper.RetrieveOutstandingRequest<ModelCreateLeaseRequest>(ref request);

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

            if (!c.IsLeasingSupported)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.9: If the server does not support leasing and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST ignore the \"RqLs\" create context.");
                ModelHelper.Log(LogType.TestInfo, "The above conditions are met.");
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextNotIncluded);
                return;
            }

            if ((negotiateDialect == DialectRevision.Smb21 || Smb2Utility.IsSmb3xFamily(negotiateDialect))
                && c.IsLeasingSupported
                && (createRequest.ContextType == LeaseContextType.LeaseV1)) // the DataLength field equals 0x20
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.9: If the server supports leasing, the name of the create context is \"RqLs\" as defined in section 2.2.13.2, " +
                    "and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST do the following:");
                ModelHelper.Log(
                    LogType.Requirement,
                    "\tIf Connection.Dialect is \"2.100\" or belongs to the \"3.x\" dialect family, and the DataLength field equals 0x20, " +
                        "the server MUST attempt to acquire a lease on the open from the underlying object store as described in section 3.3.5.9.8.");
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met.");

                // 3.3.5.9.8   Handling the SMB2_CREATE_REQUEST_LEASE Create Context
                #region Handle SMB2_CREATE_REQUEST_LEASE
                Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextIncluded);
                ModelCreateRequestLease requestLease = null;

                requestLease = createRequest.LeaseContext as ModelCreateRequestLease;

                smb2Lease = new Smb2Lease();
                if (Smb2Utility.IsSmb3xFamily(negotiateDialect))
                {
                    ModelHelper.Log(LogType.Requirement, "3.3.5.9.8: If Connection.Dialect belongs to the SMB 3.x dialect family, Lease.Version is set to 1.");
                    smb2Lease.Version = 1;
                }

                if (requestLease.LeaseState != smb2Lease.LeaseState && ((~requestLease.LeaseState) & smb2Lease.LeaseState) == 0 && !smb2Lease.Breaking)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.8: If the lease state requested is a superset of Lease.LeaseState and Lease.Breaking is FALSE, " +
                        "the server MUST request promotion of the lease state from the underlying object store to the new caching state.");
                    ModelHelper.Log(LogType.TestInfo, "The above conditions are met.");
                    //If the object store succeeds this request, Lease.LeaseState MUST be set to the new caching state.
                    smb2Lease.LeaseState = requestLease.LeaseState;
                }

                // LeaseState MUST be set to Lease.LeaseState.
                Condition.IsTrue((uint)leaseState == smb2Lease.LeaseState);
                #endregion

                Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
                return;
            }

            if (Smb2Utility.IsSmb3xFamily(negotiateDialect)
                && c.IsLeasingSupported
                && (createRequest.ContextType == LeaseContextType.LeaseV2)) // the DataLength field equals 0x34
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.9: If the server supports leasing, the name of the create context is \"RqLs\" as defined in section 2.2.13.2, " +
                    "and RequestedOplockLevel is set to SMB2_OPLOCK_LEVEL_LEASE, the server MUST do the following:");
                ModelHelper.Log(
                    LogType.Requirement,
                    "\tIf Connection.Dialect belongs to the \"3.x\" dialect family, and the DataLength field equals 0x34, " +
                    "the server MUST attempt to acquire a lease on the open from the underlying object store, as described in section 3.3.5.9.11.");
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met.");

                // 3.3.5.9.11   Handling the SMB2_CREATE_REQUEST_LEASE_V2 Create Context
                #region Handle SMB2_CREATE_REQUEST_LEASE_V2
                Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextIncluded);
                ModelCreateRequestLeaseV2 requestLease = null;

                requestLease = createRequest.LeaseContext as ModelCreateRequestLeaseV2;

                smb2Lease = new Smb2Lease(2);

                // To reduce parameters and states, use CreateOptions instead of FileAttributes here, as we assume settings in CreateOptions and FileAtributes are consistent.
                if (createRequest.CreateOptions.HasFlag(CreateOptions_Values.FILE_DIRECTORY_FILE)
                    && (requestLease.LeaseState & (uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING) != 0)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.11: If the FileAttributes field in the request indicates that this operation is on a directory and " +
                        "LeaseState includes SMB2_LEASE_WRITE_CACHING, the server MUST clear the bit SMB2_LEASE_WRITE_CACHING in the LeaseState field.");
                    ModelHelper.Log(LogType.TestInfo, "SMB2_LEASE_WRITE_CACHING is cleared.");
                    requestLease.LeaseState &= ~(uint)LeaseStateValues.SMB2_LEASE_WRITE_CACHING;
                }

                if (requestLease.LeaseState != smb2Lease.LeaseState && ((~requestLease.LeaseState) & smb2Lease.LeaseState) == 0 && !smb2Lease.Breaking)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.8: If the lease state requested is a superset of Lease.LeaseState and Lease.Breaking is FALSE, " +
                        "the server MUST request promotion of the lease state from the underlying object store to the new caching state.<271> " +
                        "If the object store succeeds this request, Lease.LeaseState MUST be set to the new caching state.");
                    smb2Lease.LeaseState = requestLease.LeaseState;
                    // The server MUST increment Lease.Epoch by 1.
                    ModelHelper.Log(LogType.TestInfo, "Lease.Epoch is incremented by 1.");
                    smb2Lease.Epoch++;
                }

                // LeaseState MUST be set to Lease.LeaseState.
                Condition.IsTrue((uint)leaseState == smb2Lease.LeaseState);

                if (requestLease.LeaseFlags.HasFlag(LeaseFlagsValues.SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET))
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.5.9.11: If SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET bit is set in the Flags field of the request, " +
                        "ParentLeaseKey MUST be set to the ParentLeaseKey in the request and SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET bit MUST be set in the Flags field of the response.");
                    ModelHelper.Log(LogType.TestInfo, "SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET bit is set.");
                    Condition.IsTrue(leaseFlags.HasFlag(LeaseFlagsValues.SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET));
                }
                #endregion

                Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
                return;
            }

            Condition.IsTrue(returnLeaseContextType == ReturnLeaseContextType.ReturnLeaseContextNotIncluded);
            Condition.IsTrue(leaseState == (uint)LeaseStateValues.SMB2_LEASE_NONE);
            Condition.IsTrue(leaseFlags == LeaseFlagsValues.NONE);
            Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
        }