public static void Disconnect() { Condition.IsTrue(Open != null); if (Open.IsPersistent // TDI, server will preserve the open for reconnect if Open.IsPersistent is true. || (Open.IsDurable && (Open.IsBatchOplockExisted || Open.IsLeaseExisted))) { ModelHelper.Log(LogType.Requirement, "3.3.7.1: The server MUST iterate over the Session.OpenTable and determine whether each Open is to be preserved for reconnect. " + "If any of the following conditions is satisfied, it indicates that the Open is to be preserved for reconnect. "); if (Open.IsBatchOplockExisted) { ModelHelper.Log(LogType.Requirement, "\tOpen.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH and Open.OplockState is equal to Held, and Open.IsDurable is TRUE."); ModelHelper.Log(LogType.TestInfo, "The above condition is met."); } if (Open.IsLeaseExisted) { ModelHelper.Log(LogType.Requirement, "\tOpen.OplockLevel is equal to SMB2_OPLOCK_LEVEL_LEASE, Lease.LeaseState contains SMB2_LEASE_HANDLE_CACHING, " + "Open.OplockState is equal to Held, and Open.IsDurable is TRUE."); ModelHelper.Log(LogType.TestInfo, "The above condition is met."); } ModelHelper.Log(LogType.TestInfo, "The Open is to be preserved."); ModelHelper.Log(LogType.Requirement, "If the Open is to be preserved for reconnect, perform the following actions: "); ModelHelper.Log(LogType.Requirement, "\tSet Open.Connection to NULL, Open.Session to NULL, Open.TreeConnect to NULL. "); ModelHelper.Log(LogType.TestInfo, "Open.Connection and Open.Session are set to NULL."); Open.IsConnectionExisted = false; Open.IsSessionExisted = false; } else { ModelHelper.Log(LogType.Requirement, "3.3.7.1: If the Open is not to be preserved for reconnect, the server MUST close the Open as specified in section 3.3.4.17."); ModelHelper.Log(LogType.TestInfo, "The Open is closed."); Open = null; } }
public static void LogOff() { Condition.IsTrue(Open != null); if (!Open.IsDurable) { ModelHelper.Log(LogType.Requirement, "3.3.5.6: The server MUST close every Open in Session.OpenTable of the old session, " + "where Open.IsDurable is FALSE and Open.IsResilient is FALSE, as specified in section 3.3.4.17. "); ModelHelper.Log(LogType.TestInfo, "Open.IsDurable is FALSE and Open.IsResilient is FALSE, so the open is closed."); Open = null; } else { ModelHelper.Log(LogType.Requirement, "3.3.5.6: For all opens in Session.OpenTable where Open.IsDurable is TRUE or Open.IsResilient is TRUE, " + "the server MUST set Open.Session, Open.Connection, and Open.TreeConnect to NULL. "); ModelHelper.Log(LogType.TestInfo, "Open.IsDurable is TRUE, so Open.Session, Open.Connection is set to NULL."); Open.IsSessionExisted = false; Open.IsConnectionExisted = false; } }
public static void PrepareOpen( ModelDialectRevision clientMaxDialect, PersistentBitType persistentBit, CAShareType connectToCAShare, ModelHandleType modelHandleType, OplockLeaseType oplockLeaseType) { Condition.IsNull(Request); Condition.IsNull(Open); // CAShare, Persistent Handle , Durable Handle v2 and Lease V2 are only applied for SMB 3.x family. Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), connectToCAShare == CAShareType.NonCAShare); Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), persistentBit == PersistentBitType.PersistentBitNotSet); Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), modelHandleType == ModelHandleType.DurableHandleV1); // Case will go to non-accpeting state if clientMaxDialect > Config.MaxSmbVersionSupported. NegotiateDialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, Config.MaxSmbVersionSupported); // Restrict the params combination Combination.Pairwise(clientMaxDialect, persistentBit, connectToCAShare, modelHandleType, oplockLeaseType); Share_IsCA = (connectToCAShare == CAShareType.CAShare); Open = new HandleModelOpen(); Open.IsConnectionExisted = true; Open.IsSessionExisted = true; if (oplockLeaseType == OplockLeaseType.LeaseV1) { Open.IsLeaseExisted = true; Open.LeaseVersion = 1; } else if (oplockLeaseType == OplockLeaseType.LeaseV2) { Open.IsLeaseExisted = true; Open.LeaseVersion = 2; } else if (oplockLeaseType == OplockLeaseType.BatchOplock) { Open.IsBatchOplockExisted = true; } if (modelHandleType == ModelHandleType.DurableHandleV1) { if (!Open.IsBatchOplockExisted && !Open.IsLeaseExisted) { ModelHelper.Log(LogType.Requirement, "3.3.5.9.6: If the RequestedOplockLevel field in the create request is not set to SMB2_OPLOCK_LEVEL_BATCH and " + "the create request does not include an SMB2_CREATE_REQUEST_LEASE create context with a LeaseState field that " + "includes the SMB2_LEASE_HANDLE_CACHING bit value, " + "the server MUST ignore this create context and skip this section."); ModelHelper.Log(LogType.TestInfo, "This section is skipped."); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); return; } ModelHelper.Log(LogType.Requirement, "3.3.5.9.6: In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE. "); ModelHelper.Log(LogType.TestInfo, "Open.IsDurable is set to TRUE."); Open.IsDurable = true; } else if (modelHandleType == ModelHandleType.DurableHandleV2 || modelHandleType == ModelHandleType.PersistentHandle) { ModelHelper.Log(LogType.Requirement, "3.3.5.9.10: This section applies only to servers that implement the SMB 3.x dialect family. "); if (!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported)) { ModelHelper.Log(LogType.TestInfo, "The server implements the dialect {0}.", Config.MaxSmbVersionSupported); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); return; } if (modelHandleType != ModelHandleType.PersistentHandle && !Open.IsBatchOplockExisted && !Open.IsLeaseExisted) { ModelHelper.Log(LogType.Requirement, "If the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of this create context, " + "if RequestedOplockLevel in the create request is not set to SMB2_OPLOCK_LEVEL_BATCH, " + "and if the create request does not include a SMB2_CREATE_REQUEST_LEASE or " + "SMB2_CREATE_REQUEST_LEASE_V2 create context with a LeaseState field that includes SMB2_LEASE_HANDLE_CACHING, " + "the server MUST ignore this create context and skip this section."); ModelHelper.Log(LogType.TestInfo, "This section is skipped."); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); return; } if (ModelUtility.IsSmb3xFamily(NegotiateDialect) && persistentBit == PersistentBitType.PersistentBitSet && Config.IsPersistentHandleSupported) { 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_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " + "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles."); ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. So SMB2_DHANDLE_FLAG_PERSISTENT bit is set in Connection.ServerCapabilities."); ServerCapabilities_PersistentBitSet = true; } if (modelHandleType == ModelHandleType.PersistentHandle && !(Share_IsCA && ServerCapabilities_PersistentBitSet)) { // TDI: if client asks for a persistent handle to a non CA share or // Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_PERSISTENT_HANDLES // The persistent handle is not granted. ModelHelper.Log( LogType.TestInfo, "Share is not a CA share or Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_PERSISTENT_HANDLES."); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); return; } ModelHelper.Log(LogType.Requirement, "In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE. "); ModelHelper.Log(LogType.TestInfo, "Open.IsDurable is set to TRUE."); Open.IsDurable = true; if (modelHandleType == ModelHandleType.PersistentHandle && Share_IsCA && ServerCapabilities_PersistentBitSet) { ModelHelper.Log(LogType.Requirement, "3.3.5.9.10: If the SMB2_DHANDLE_FLAG_PERSISTENT bit is set in the Flags field of the request, " + "TreeConnect.Share.IsCA is TRUE, " + "and Connection.ServerCapabilities includes SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, " + "the server MUST set Open.IsPersistent to TRUE."); ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. So Open.IsPersistent is set to TRUE."); Open.IsPersistent = true; } } }
/// <summary> /// This method is used to verify the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context /// Cover TD section: 3.3.5.9.10 /// Return true means the message is handled by this function. /// Return false means the message needs further processing. /// </summary> private static bool Handling_SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2_CreateContext( ModelSmb2Status status, ModelOpenFileRequest modelOpenFileRequest, DurableHandleResponseContext durableHandleResponseContext) { ModelHelper.Log(LogType.Requirement, "3.3.5.9.10: Handling the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context"); if (modelOpenFileRequest.durableV1RequestContext == DurableV1RequestContext.DurableV1RequestContextExist || modelOpenFileRequest.durableV1ReconnectContext == DurableV1ReconnectContext.DurableV1ReconnectContextExist || modelOpenFileRequest.durableV2ReconnectContext != DurableV2ReconnectContext.DurableV2ReconnectContextNotExist) { ModelHelper.Log(LogType.Requirement, "If the create request also includes an SMB2_CREATE_DURABLE_HANDLE_REQUEST create context, " + "or an SMB2_CREATE_DURABLE_HANDLE_RECONNECT or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 create context, " + "the server MUST fail the create request with STATUS_INVALID_PARAMETER."); ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedContext); if (modelOpenFileRequest.durableV1RequestContext == DurableV1RequestContext.DurableV1RequestContextExist) ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_REQUEST is included."); if (modelOpenFileRequest.durableV1ReconnectContext == DurableV1ReconnectContext.DurableV1ReconnectContextExist) ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RECONNECT is included."); if (modelOpenFileRequest.durableV2ReconnectContext != DurableV2ReconnectContext.DurableV2ReconnectContextNotExist) ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is included."); Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER); return true; } if (modelOpenFileRequest.durableV2RequestContext == DurableV2RequestContext.DurableV2RequestContextExistWithoutPersistent && modelOpenFileRequest.oplockLeaseType == OplockLeaseType.NoOplockOrLease) { ModelHelper.Log(LogType.Requirement, "If the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of this create context, " + "if RequestedOplockLevel in the create request is not set to SMB2_OPLOCK_LEVEL_BATCH, " + "and if the create request does not include a SMB2_CREATE_REQUEST_LEASE or SMB2_CREATE_REQUEST_LEASE_V2 create context " + "with a LeaseState field that includes SMB2_LEASE_HANDLE_CACHING, the server MUST ignore this create context and skip this section."); ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. "); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(durableHandleResponseContext == DurableHandleResponseContext.NONE); return false; } if (Open != null && modelOpenFileRequest.isSameClient && modelOpenFileRequest.isSameCreateGuid) { ModelHelper.Log(LogType.Requirement, "The server MUST locate the Open in GlobalOpenTable where Open.CreateGuid matches the CreateGuid in the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context, " + "and Open.ClientGuid matches the ClientGuid of the connection that received this request."); ModelHelper.Log(LogType.TestInfo, "The Open is found."); ModelHelper.Log(LogType.Requirement, "If an Open is found and the SMB2_FLAGS_REPLAY_OPERATION bit is not set in the SMB2 header, the server MUST fail the request with STATUS_DUPLICATE_OBJECTID."); ModelHelper.Log(LogType.TestInfo, "SMB2_FLAGS_REPLAY_OPERATION is not set."); ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields); Condition.IsTrue(status == ModelSmb2Status.STATUS_DUPLICATE_OBJECTID); return true; } if (Open == null) { ModelHelper.Log(LogType.Requirement, "If an Open is not found, the server MUST continue the create process specified in the \"Open Execution\" Phase, and perform the following additional steps:"); Open = new HandleModelOpen(); ModelHelper.Log(LogType.Requirement, "In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE. "); Open.IsDurable = true; if (modelOpenFileRequest.durableV2RequestContext == DurableV2RequestContext.DurableV2RequestContextExistWithPersistent && Share_IsCA && ServerCapabilities_PersistentBitSet) { ModelHelper.Log(LogType.Requirement, "If the SMB2_DHANDLE_FLAG_PERSISTENT bit is set in the Flags field of the request, TreeConnect.Share.IsCA is TRUE, " + "and Connection.ServerCapabilities includes SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, the server MUST set Open.IsPersistent to TRUE."); ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. Open.IsPersistent is set to TRUE."); Open.IsPersistent = true; } } if (modelOpenFileRequest.durableV2RequestContext != DurableV2RequestContext.DurableV2RequestContextExistWithPersistent && modelOpenFileRequest.oplockLeaseType == OplockLeaseType.NoOplockOrLease) { ModelHelper.Log(LogType.Requirement, "The server MUST skip the construction of the SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 create context " + "if the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of the request and if neither of the following conditions are met:" + "\tOpen.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH. " + "\tOpen.Lease.LeaseState has SMB2_LEASE_HANDLE_CACHING bit set."); ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. " + "So the server skips the construction of the SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 create context."); Condition.IsTrue(durableHandleResponseContext == DurableHandleResponseContext.NONE); } else { ModelHelper.Log(LogType.Requirement, "If Open.IsPersistent is TRUE, the server MUST set the SMB2_DHANDLE_FLAG_PERSISTENT bit in the Flags field. "); ModelHelper.Log(LogType.TestInfo, "Open.IsPersistent is {0}", Open.IsPersistent); if (Open.IsPersistent) { Condition.IsTrue(durableHandleResponseContext == DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2_WITH_PERSISTENT); } } return false; }