/// <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; }
/// <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 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 }); }
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); }