public void AppInstanceId_DirectoryLeasing_NoLeaseInReOpen() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); #endregion AppInstanceIdTestWithLeasing( true, LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING, AccessMask.GENERIC_READ, AccessMask.DELETE); }
public void BVT_Leasing_FileLeasingV2() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); #endregion Smb2CreateContextRequest leaseContext = new Smb2CreateRequestLeaseV2 { LeaseKey = Guid.NewGuid(), LeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING }; TestFileLeasing(leaseContext); }
public void MultipleChannel_NicRedundantOnClient() { string contentWrite; string contentRead; uint treeId; FILEID fileId; #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); TestConfig.CheckSigning(); #endregion contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb); BaseTestSite.Assert.IsTrue( clientIps.Count > 1, "Client should have more than one IP address"); BaseTestSite.Assert.IsTrue( serverIps.Count > 0, "Server should have at least one IP address"); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start to write content to file from main channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString()); WriteFromMainChannel( serverIps[0], clientIps[0], contentWrite, false, out treeId, out fileId); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start to read content from file from alternative channel with client {0} and server {1}", clientIps[1].ToString(), serverIps[0].ToString()); ReadFromAlternativeChannel( serverIps[0], clientIps[1], (uint)contentWrite.Length, treeId, fileId, out contentRead); BaseTestSite.Assert.IsTrue(contentWrite.Equals(contentRead), "Content should be identical to content written."); }
private void CheckCompressionAndEncryptionApplicability(CompressionAlgorithm?compressionAlgorithm = null, bool needEncryption = false) { // Check platform if (TestConfig.IsWindowsPlatform) { BaseTestSite.Assume.IsFalse(TestConfig.Platform < Platform.WindowsServerV1903, "Windows 10 v1809 operating system and prior, Windows Server v1809 operating system and prior, and Windows Server 2019 and prior do not support compression."); } // Check dialect BaseTestSite.Assume.IsTrue(TestConfig.MaxSmbVersionSupported >= DialectRevision.Smb311, "The SMB 3.1.1 dialect introduces supporting the compression of messages between client and server."); // Check SUT supported compression algorithms TestConfig.CheckCompressionAlgorithm(compressionAlgorithm); // Check whether SUT supports encryption if (needEncryption) { TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION); } }
/// <summary> /// Test AppInstanceId with encryption /// </summary> /// <param name="encryptionInInitialOpen">Set true if encryption is enabled in initial open, otherwise set false</param> /// <param name="encryptionInReOpen">Set true if encryption is enabled in re-open, otherwise set false</param> private void AppInstanceIdTestWithEncryption(bool encryptionInInitialOpen, bool encryptionInReOpen) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.EncryptedFileShare); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "InitialOpen: Connect to share via Nic1."); FILEID fileIdForInitialOpen; uint treeIdForInitialOpen; ConnectShare(TestConfig.SutIPAddress, TestConfig.ClientNic1IPAddress, clientForInitialOpen, out treeIdForInitialOpen, encryptionInInitialOpen); // Skip the verification of signature when sending a non-encrypted CREATE request to an encrypted share if (!encryptionInInitialOpen) { clientForInitialOpen.Smb2Client.DisableVerifySignature = true; } #region CREATE an open with AppInstanceId BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "InitialOpen: CREATE an open with AppInstanceId."); Smb2CreateContextResponse[] serverCreateContexts; status = clientForInitialOpen.Create( treeIdForInitialOpen, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdForInitialOpen, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid(), }, new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { }); #endregion if (!encryptionInInitialOpen) { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, status, "Create durable handle request to encrypted share without encryption should not SUCCESS "); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_ACCESS_DENIED, status, RequirementCategory.STATUS_ACCESS_DENIED.Id, RequirementCategory.STATUS_ACCESS_DENIED.Description); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, status, "Create durable handle request V2 should succeed, actual status is {0}", Smb2Status.GetStatusCode(status)); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "InitialOpen: Write contents to file."); status = clientForInitialOpen.Write(treeIdForInitialOpen, fileIdForInitialOpen, contentWrite); } FILEID fileIdForReOpen; uint treeIdForReOpen; BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Connect to same share via Nic2."); ConnectShare(TestConfig.SutIPAddress, TestConfig.ClientNic2IPAddress, clientForReOpen, out treeIdForReOpen, encryptionInReOpen); // Skip the verification of signature when sending a non-encrypted CREATE request to an encrypted share if (!encryptionInReOpen) { clientForReOpen.Smb2Client.DisableVerifySignature = true; } #region CREATE an open with same AppInstanceId for reopen BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: CREATE an open with same AppInstanceId for reopen."); status = clientForReOpen.Create( treeIdForReOpen, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdForReOpen, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid(), }, new Smb2CreateAppInstanceId { // Use the same application instance id to force the server close all files AppInstanceId = appInstanceId } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { }); #endregion if (encryptionInInitialOpen && encryptionInReOpen) { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, status, "Create durable handle request should succeed, actual status is {0}", Smb2Status.GetStatusCode(status)); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Read the contents written by InitialOpen."); status = clientForReOpen.Read(treeIdForReOpen, fileIdForReOpen, 0, (uint)contentWrite.Length, out contentRead); BaseTestSite.Assert.IsTrue( contentRead.Equals(contentWrite), "The written content should equal to read content."); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Close file."); status = clientForReOpen.Close(treeIdForReOpen, fileIdForReOpen); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Disconnect the share."); status = clientForReOpen.TreeDisconnect(treeIdForReOpen); } else if (encryptionInInitialOpen && !encryptionInReOpen) { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, status, "Create durable handle request to encrypted share without encryption should not SUCCESS "); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_ACCESS_DENIED, status, RequirementCategory.STATUS_ACCESS_DENIED.Id, RequirementCategory.STATUS_ACCESS_DENIED.Description); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Disconnect the share."); status = clientForReOpen.TreeDisconnect(treeIdForReOpen, (header, response) => { }); BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, status, "TreeDisconnect should not SUCCESS"); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_ACCESS_DENIED, status, RequirementCategory.STATUS_ACCESS_DENIED.Id, RequirementCategory.STATUS_ACCESS_DENIED.Description); } else if (!encryptionInInitialOpen && encryptionInReOpen) { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, status, "Create durable handle request should succeed, actual status is {0}", Smb2Status.GetStatusCode(status)); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Close file."); status = clientForReOpen.Close(treeIdForReOpen, fileIdForReOpen); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Disconnect from the share."); status = clientForReOpen.TreeDisconnect(treeIdForReOpen); } BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Log off."); status = clientForReOpen.LogOff(); }
public void MultipleChannel_SecondChannelSessionSetupFailAtFirstTime() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb311); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); #endregion string contentWrite; string contentRead; uint treeId; FILEID fileId; contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb); BaseTestSite.Assert.IsTrue( clientIps.Count > 0, "Client should have at least one IP address"); BaseTestSite.Assert.IsTrue( serverIps.Count > 0, "Server should have more than one IP address"); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start to write content to file from main channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString()); WriteFromMainChannel( serverIps[0], clientIps[0], contentWrite, false, out treeId, out fileId); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Set up alternative channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString()); alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIps[1], clientIps[1]); alternativeChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: 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, clientGuid: clientGuid, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(DialectRevision.Smb311, response); if (Smb2Utility.IsSmb3xFamily(DialectRevision.Smb311)) { TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response); } }); status = alternativeChannelClient.AlternativeChannelSessionSetup( mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, checker: (header, response) => { }, invalidToken: true); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_INVALID_PARAMETER, status, "The first SessionSetup from alternative channel should return STATUS_INVALID_PARAMETER since the token in buffer field is set to an invalid value."); status = alternativeChannelClient.AlternativeChannelSessionSetup( mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, checker: (header, response) => { }); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "The second SessionSetup from alternative channel should succeed"); contentRead = ""; status = alternativeChannelClient.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead); // Read should succeed. // If Read response returns STATUS_ACCESS_DEINIED, it means signingkey used by server is wrong, and so that the PreauthIntegrityHashValue (which is used to generate the signingkey) calculated by server is wrong. // It is very possible that server uses the first failed session setup request/response (alternative channel) to calculate PreauthIntegrityHashValue, which is wrong. BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Read from the alternative channel should succeed"); alternativeChannelClient.Close(treeId, fileId); alternativeChannelClient.TreeDisconnect(treeId); alternativeChannelClient.LogOff(); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Verify the contents read from alternative channel are the same as the one written by main channel."); BaseTestSite.Assert.IsTrue( contentWrite.Equals(contentRead), "Content read should be identical to content written."); }
public void MultipleChannel_FileLease() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); #endregion mainChannelClient.Smb2Client.LeaseBreakNotificationReceived += new Action <Packet_Header, LEASE_BREAK_Notification_Packet>(base.OnLeaseBreakNotificationReceived); uint treeId; FILEID fileId; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Establish main channel with client {0} and server {1}.", clientIps[0].ToString(), serverIps[0].ToString()); EstablishMainChannel( TestConfig.RequestDialects, serverIps[0], clientIps[0], out treeId); #region CREATE to open file to request lease BaseTestSite.Log.Add(LogEntryKind.TestStep, "Main channel: CREATE to open file to request lease."); LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; // Add expected NewLeaseState expectedNewLeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING; Smb2CreateContextResponse[] serverCreateContexts; status = mainChannelClient.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateRequestLeaseV2 { LeaseKey = Guid.NewGuid(), LeaseState = leaseState, } }, accessMask: AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE); #endregion #region WRITE content BaseTestSite.Log.Add(LogEntryKind.TestStep, "Main channel: WRITE content."); status = mainChannelClient.Write(treeId, fileId, contentWrite); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "Establish alternative channel with client {0} and server {1}.", clientIps[1].ToString(), serverIps[1].ToString()); EstablishAlternativeChannel( TestConfig.RequestDialects, serverIps[1], clientIps[1], treeId); // Create a timer that signals the delegate to invoke CheckBreakNotification after 5 seconds Timer timer = new Timer(CheckBreakNotification, treeId, 5000, Timeout.Infinite); Smb2FunctionalClient clientTriggeringBreak = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client3 connect to same server."); clientTriggeringBreak.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIps[1], clientIps[1]); base.clientToAckLeaseBreak = mainChannelClient; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Request CREATE from Client3 to trigger lease break notification."); BaseTestSite.Log.Add(LogEntryKind.Debug, "The operation will be blocked until notification is acknowledged or 35 seconds timeout."); TriggerBreakFromClient( clientTriggeringBreak, TestConfig.RequestDialects, false, LeaseStateValues.SMB2_LEASE_NONE, AccessMask.GENERIC_WRITE); ClientTearDown(alternativeChannelClient, treeId, fileId); }
public void BVT_MultiCredit_OneRequestWithMultiCredit() { TestConfig.CheckDialect(DialectRevision.Smb21); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LARGE_MTU); Guid clientGuid = Guid.NewGuid(); string fileName = "MultiCredit_" + clientGuid.ToString() + ".txt"; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: 1. NEGOTIATE; 2. SESSION_SETUP; 3. TREE_CONNECT"); Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); client.ConnectToServerOverTCP(TestConfig.SutIPAddress); Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_LARGE_MTU; client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); uint treeId; client.TreeConnect(uncSharePath, out treeId); int bufferSize = (int)client.MaxBufferSize; FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; ushort grantedCredit = 0; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with {0} credits", client.Credits); client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Log.Add(LogEntryKind.Debug, "The MaxBufferSize of the server is {0}.", client.MaxBufferSize); BaseTestSite.Log.Add(LogEntryKind.Debug, "Server has granted {0} credits to the client.", client.Credits); // Make sure client hold enough credits for test ushort maxBufferSizeInCredit = (ushort)((client.MaxBufferSize - 1) / 65536 + 1); if (client.Credits < maxBufferSizeInCredit) { if (client.Credits < 2) { BaseTestSite.Assert.Inconclusive( "This test case is not applicable when the server only grants {0} credits", client.Credits); } // Test max buffer according to granted credits. bufferSize = (client.Credits - 1) * 65536; } grantedCredit = header.CreditRequestResponse; }); contentWrite = Smb2Utility.CreateRandomStringInByte(bufferSize); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client attempts to write {0} bytes content to file when server grants {1} credits", client.MaxBufferSize, client.Credits); client.Write( treeId, fileId, contentWrite, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); grantedCredit = header.CreditRequestResponse; }); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client attempts to read {0} bytes content from file when server grants {1} credit", bufferSize, client.Credits); client.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: 1. CLOSE; 2. TREE_DISCONNECT; 3. LOG_OFF; 4. DISCONNECT"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); client.Disconnect(); }
public void PersistentHandle_ReOpenFromDiffClient() { /// 1. A client requests a persistent handle and succeeds /// 2. The client disconnects from the server /// 3. Another client (different client guid) opens the same file /// 4. The expected result of the second OPEN is STATUS_FILE_NOT_AVAILABLE according to section 3.3.5.9: /// If Connection.Dialect belongs to the SMB 3.x dialect family and the request does not contain SMB2_CREATE_DURABLE_HANDLE_RECONNECT /// Create Context or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context, the server MUST look up an existing open in the GlobalOpenTable /// where Open.FileName matches the file name in the Buffer field of the request. /// If an Open entry is found, and if all the following conditions are satisfied, the server SHOULD fail the request with STATUS_FILE_NOT_AVAILABLE. /// Open.IsPersistent is TRUE /// Open.Connection is NULL #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); #endregion Smb2FunctionalClient clientBeforeDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName); // It will cost 3 minutes to delete this file, so do not add it to testFiles to skip auto-clean. string fileName = CurrentTestCaseName + "_" + Guid.NewGuid().ToString(); BaseTestSite.Log.Add(LogEntryKind.TestStep, "1. A client requests a persistent handle and succeeds"); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, Guid.NewGuid(), testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdBeforeDisconnection, null); FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid(), Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT, uint.MaxValue)); }); // Disconnect BaseTestSite.Log.Add( LogEntryKind.TestStep, "2. The client disconnects from the server"); clientBeforeDisconnection.Disconnect(); //If an Open entry is found, and if all the following conditions are satisfied, the server SHOULD<276> fail the request with STATUS_FILE_NOT_AVAILABLE. // Open.IsPersistent is TRUE // Open.Connection is NULL //<276> Section 3.3.5.9: If Open.ClientGuid is not equal to the ClientGuid of the connection that received this request, Open.Lease.LeaseState is equal to RWH, or Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH, // Windows-based servers will attempt to break the lease/oplock and return STATUS_PENDING to process the create request asynchronously. Otherwise, if Open.Lease.LeaseState does not include SMB2_LEASE_HANDLE_CACHING and // Open.OplockLevel is not equal to SMB2_OPLOCK_LEVEL_BATCH, Windows-based servers return STATUS_FILE_NOT_AVAILABLE. // Open from another client Smb2FunctionalClient anotherClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); BaseTestSite.Log.Add( LogEntryKind.TestStep, "3. Open the same file from different client (different client guid), the expected result of OPEN is STATUS_FILE_NOT_AVAILABLE"); uint treeIdAfterDisconnection; Connect(DialectRevision.Smb30, anotherClient, Guid.NewGuid(), testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdAfterDisconnection, null); FILEID fileIdAfterDisconnection; status = anotherClient.Create( treeIdAfterDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid(), Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { if (TestConfig.Platform == Platform.NonWindows) { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "The server SHOULD fail the request with STATUS_FILE_NOT_AVAILABLE."); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_FILE_NOT_AVAILABLE, header.Status, "The server SHOULD fail the request with STATUS_FILE_NOT_AVAILABLE."); } }); }
public void BVT_PersistentHandle_Reconnect() { /// 1. Client requests a persistent handle /// 2. Client disconnects from the server /// 3. Client reconnects the persistent handle, and expects success. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName); fileName = "BVT_PersistentHandle_Reconnect_" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a persistent handle"); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT, uint.MaxValue)); }); status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the persistent handle"); uint treeIdAfterDisconnection; Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; status = clientAfterDisconnection.Create( treeIdAfterDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT, FileId = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } } }, shareAccess: ShareAccess_Values.NONE); string readContent; status = clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( readContent.Equals(content), "The written content should equal to read content."); #endregion clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection); clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); }
public void Signing_VerifySignatureWhenEncrypted() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE with the capability GLOBAL_CAP_ENCRYPTION."); client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED, capabilityValue: Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION ); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request and expects response."); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); string uncSharepath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.EncryptedFileShare); uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT to share: {0}", uncSharepath); client.TreeConnect( uncSharepath, out treeId, (Packet_Header header, TREE_CONNECT_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "TreeConnect should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Assert.AreEqual( ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA, ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA & response.ShareFlags, "Server should set SMB2_SHAREFLAG_ENCRYPT_DATA for ShareFlags field in TREE_CONNECT response"); }); // After calling this method, client will send encrypted message after tree connect. BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client enables per share encryption: TreeId=0x{0:x}", treeId); client.SetTreeEncryption(treeId, true); FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrypted CREATE request and expects success."); client.Create( treeId, CurrentTestCaseName + "_" + Guid.NewGuid() + ".txt", CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, shareAccess: ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, checker: (header, response) => { BaseTestSite.Assert.IsTrue( !header.Signature.Any(e => e != 0), "[MS-SMB2] 3.3.4.1.1 If the server encrypts the message, as specified in section 3.1.4.3, the server MUST set the Signature field of the SMB2 header to zero, actually the Signature field is [{0}].", string.Join(", ", header.Signature)); }); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); }
public void ResilientWithPersistentHandle_OpenFromDiffClient() { /// 1. Open Persistent Handle with lease /// 2. Send Resiliency request /// 3. Disconnect /// 4. Open the same file from different client (different client guid) /// 5. The expected result of OPEN is successful. /// /// Covered TD, section /// If Connection.Dialect is "3.000" and the request does not contain SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context /// or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context, the server MUST look up an existing open in the /// GlobalOpenTable where Open.FileName matches the file name in the Buffer field of the request. If an Open entry is found, /// if Open.IsPersistent is TRUE, *Open.IsResilient is TRUE* and if Open.Connection is NULL, the server MUST fail the request with STATUS_FILE_NOT_AVAILABLE. /// #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); #endregion Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); Guid clientGuid = Guid.NewGuid(); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); string fileName = "ResilientWithPersistentHandle_" + Guid.NewGuid() + ".txt"; FILEID fileId; uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Open Persistent Handle with lease."); OpenFile( client, clientGuid, fileName, true, out createGuid, out treeId, out fileId); // resiliency request Packet_Header ioCtlHeader; IOCTL_Response ioCtlResponse; byte[] inputInResponse; byte[] outputInResponse; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Send resiliency request with timeout {0} milliseconds", testConfig.MaxResiliencyTimeoutInSecond); client.ResiliencyRequest( treeId, fileId, testConfig.MaxResiliencyTimeoutInSecond, (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)), out ioCtlHeader, out ioCtlResponse, out inputInResponse, out outputInResponse ); // Disconnect BaseTestSite.Log.Add( LogEntryKind.TestStep, "Disconnect the resilient handle"); client.Disconnect(); // open from another client Smb2FunctionalClient anotherClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Open the same file from different client (different client guid), the expected result of OPEN is successful"); OpenFile( anotherClient, Guid.NewGuid(), fileName, false, out createGuid, out treeId, out fileId); }
public void BVT_Replay_WriteWithInvalidChannelSequence() { ///1. mainChannelClient opens a file and write to it. ///2. mainChannelClient loses connection. ///3. ChannelSequence is set to 0x8000 which exceeds the max value. ///4. alternativeChannelClient opens the same file and try to write to it. ///5. Server should fail the write request with STATUS_FILE_NOT_AVAILABLE. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2); // According to TD, server must support signing when it supports multichannel. // 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request // 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: // 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. TestConfig.CheckSigning(); #endregion Guid clientGuid = Guid.NewGuid(); Capabilities_Values capabilityValue = Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; channelSequence = 0; #region MainChannelClient Create a File BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start a client from main channel by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE."); mainChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); mainChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilityValue, clientGuid: clientGuid, checker: ReplayNegotiateResponseChecker); mainChannelClient.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); mainChannelClient.SessionChannelSequence = channelSequence; uint treeId; mainChannelClient.TreeConnect(sharePath, out treeId); FILEID fileId; Smb2CreateContextResponse[] createContextResponse; mainChannelClient.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid() } }); CheckCreateContextResponses(createContextResponse, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); #endregion #region alternativeChannelClient Opens the Previously Created File BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client from alternative channel by sending NEGOTIATE request."); alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutAlternativeIPAddress); alternativeChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilityValue, clientGuid: clientGuid, checker: ReplayNegotiateResponseChecker); BaseTestSite.Log.Add( LogEntryKind.TestStep, "The alternative client sends SESSION_SETUP request binding the previous session created by the main channel client."); alternativeChannelClient.AlternativeChannelSessionSetup(mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); alternativeChannelClient.SessionChannelSequence = channelSequence; #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "The main channel client sends WRITE request to write content to file."); mainChannelClient.Write(treeId, fileId, " "); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the main channel client by sending DISCONNECT request."); mainChannelClient.Disconnect(); //Network Disconnection Increase the Channel Sequence //Server MUST fail SMB2 WRITE, SET_INFO, and IOCTL requests with STATUS_FILE_NOT_AVAILABLE //if the difference between the ChannelSequence in the header and Open.ChannelSequence is greater than 0x7FFF BaseTestSite.Log.Add(LogEntryKind.TestStep, "Set the channel sequence of the alternative channel client to an invalid value."); alternativeChannelClient.SessionChannelSequence = 0x8000; BaseTestSite.Log.Add( LogEntryKind.TestStep, "The alternative client sends WRITE request to write content to the file created by the main channel client."); alternativeChannelClient.Write(treeId, fileId, " ", checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_FILE_NOT_AVAILABLE, header.Status, "Server MUST fail the {0} request with STATUS_FILE_NOT_AVAILABLE if the difference between the ChannelSequence in the header and Open.ChannelSequence is greater than 0x7FFF. " + "Actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); }, isReplay: true); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the alternative channel client by sending TREE_DISCONNECT and LOG_OFF requests."); alternativeChannelClient.TreeDisconnect(treeId); alternativeChannelClient.LogOff(); }
public void BVT_Replay_ReplayCreate() { ///1. mainChannelClient opens a file ///2. mainChannelClient loses connection. ///3. ChannelSequence is increased by 1. ///4. alternativeChannelClient opens the same file with replay flag set. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2); // According to TD, server must support signing when it supports multichannel. // 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request // 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: // 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. TestConfig.CheckSigning(); #endregion Guid durableHandleGuid = Guid.NewGuid(); Guid clientGuid = Guid.NewGuid(); Capabilities_Values capabilityValue = Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; #region MainChannelClient Finish Session Setup and AlternativeChannelClient Establish Another Channel BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start a client from main channel by sending the following requests: NEGOTIATE; SESSION_SETUP"); mainChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); mainChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilityValue, clientGuid: clientGuid, checker: ReplayNegotiateResponseChecker); mainChannelClient.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start another client from alternative channel by sending the following requests: NEGOTIATE SESSION_SETUP"); alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutAlternativeIPAddress); alternativeChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilityValue, clientGuid: clientGuid, checker: ReplayNegotiateResponseChecker); alternativeChannelClient.AlternativeChannelSessionSetup(mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); #endregion #region MainChannelClient Create a File with DurableHandleV1 and BatchOpLock uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "The main channel client sends TREE_CONNECT request."); mainChannelClient.TreeConnect(sharePath, out treeId); FILEID fileId; Smb2CreateContextResponse[] createContextResponse; BaseTestSite.Log.Add( LogEntryKind.TestStep, "The main channel client sends CREATE request with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context."); mainChannelClient.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = durableHandleGuid } }); CheckCreateContextResponses(createContextResponse, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the main channel client by sending DISCONNECT request."); mainChannelClient.Disconnect(); alternativeChannelClient.SessionChannelSequence++; #region AlternativeChannelClient Opens the Previously Created File with Replay Flag Set FILEID alternativeFileId; BaseTestSite.Log.Add( LogEntryKind.TestStep, "The alternative client sends CREATE request with replay flag set and SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 to open the same file with the main channel client."); alternativeChannelClient.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, Packet_Header_Flags_Values.FLAGS_REPLAY_OPERATION | (testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE), out alternativeFileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = durableHandleGuid } }); CheckCreateContextResponses(createContextResponse, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the alternative channel client by sending the following requests: TREE_DISCONNECT; LOG_OFF"); alternativeChannelClient.TreeDisconnect(treeId); alternativeChannelClient.LogOff(); }
private void DurableHandleV1_Reconnect_WithLeaseV1(bool sameFileName) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb21); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); string fileName = GetTestFileName(durableHandleUncSharePath); #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a durable handle"); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb21, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid leaseKey = Guid.NewGuid(); LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequest { DurableRequest = Guid.Empty, }, new Smb2CreateRequestLease { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleResponseChecker(BaseTestSite)); }); clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "The client with clientGuid {0} sends DISCONNECT request.", clientGuid.ToString()); clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the durable handle"); uint treeIdAfterDisconnection; Connect(DialectRevision.Smb21, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; uint status = clientAfterDisconnection.Create( treeIdAfterDisconnection, sameFileName ? fileName : GetTestFileName(durableHandleUncSharePath), CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnect { Data = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } }, new Smb2CreateRequestLease { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => {}); if (sameFileName) { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Reconnect a durable handle should be successful"); string readContent; clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( content.Equals(readContent), "The written content is expected to be equal to read content."); clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_INVALID_PARAMETER, status, "If Open.Lease is not NULL and Open.FileName does not match the file name specified in the Buffer field of the SMB2 CREATE request, " + "the server MUST fail the request with STATUS_INVALID_PARAMETER."); } clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); #endregion }
/// <summary> /// Establish alternative channel and lock/unlock byte range of a file from same or different channel client /// </summary> /// <param name="lockUnlockOnSameChannel">Set this parameter to true if the unlock operation is taken from the same channel client</param> private void MultipleChannelTestWithLock(bool lockUnlockOnSameChannel) { uint treeId; FILEID fileId; #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "Establish main channel with client {0} and server {1}.", clientIps[0].ToString(), serverIps[0].ToString()); EstablishMainChannel( TestConfig.RequestDialects, serverIps[0], clientIps[0], out treeId); #region CREATE to open file for WRITE and LOCK BaseTestSite.Log.Add( LogEntryKind.TestStep, "Main channel: CREATE file."); Smb2CreateContextResponse[] serverCreateContexts; status = mainChannelClient.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts); #endregion #region WRITE content to file BaseTestSite.Log.Add( LogEntryKind.TestStep, "Main channel: WRITE content to file."); status = mainChannelClient.Write(treeId, fileId, contentWrite); #endregion #region Request byte lock range //Construct LOCK_ELEMENT LOCK_ELEMENT[] locks = new LOCK_ELEMENT[1]; uint lockSequence = 0; locks[0].Offset = 0; locks[0].Length = (ulong)TestConfig.WriteBufferLengthInKb * 1024; locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Main channel client starts to lock a byte range for file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})", fileName, locks[0].Offset, locks[0].Length, locks[0].Flags.ToString()); status = mainChannelClient.Lock(treeId, lockSequence++, fileId, locks); #endregion #region WRITE content within the locking range BaseTestSite.Log.Add( LogEntryKind.TestStep, "Main channel: attempts to write content within the locking range."); status = mainChannelClient.Write( treeId, fileId, contentWrite, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Write should not success when shared lock is taken"); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_FILE_LOCK_CONFLICT, header.Status, RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id, RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description); }); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "Establish alternative channel with client {0} and server {1}.", clientIps[1].ToString(), serverIps[1].ToString()); EstablishAlternativeChannel( TestConfig.RequestDialects, serverIps[1], clientIps[1], treeId); #region READ/WRITE from alternative channel within the locking range Random random = new Random(); uint offset = (uint)random.Next(0, TestConfig.WriteBufferLengthInKb * 1024 - 1); uint length = (uint)random.Next(0, (int)(TestConfig.WriteBufferLengthInKb * 1024 - offset)); BaseTestSite.Log.Add( LogEntryKind.Debug, "Alternative channel: attempts to randomly read the locking range with offset: {0} and length: {1}", offset, length); status = alternativeChannelClient.Read(treeId, fileId, offset, length, out contentRead); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Alternative channel: attempts to write content to the locking range"); status = alternativeChannelClient.Write( treeId, fileId, contentWrite, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set"); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_FILE_LOCK_CONFLICT, header.Status, RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id, RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description); }); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "Read and write the locking range from Client3 when the file is locked"); ValidateByteLockRangeFromAnotherClient(true); locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK; if (lockUnlockOnSameChannel) { BaseTestSite.Log.Add( LogEntryKind.TestStep, "From main channel client unlock the range"); status = mainChannelClient.Lock(treeId, lockSequence++, fileId, locks); } else { BaseTestSite.Log.Add( LogEntryKind.TestStep, "From alternative channel client unlock the range"); status = alternativeChannelClient.Lock(treeId, lockSequence++, fileId, locks); } BaseTestSite.Log.Add( LogEntryKind.TestStep, "Read and write the locking range from Client3 when the file is unlocked"); ValidateByteLockRangeFromAnotherClient(false); ClientTearDown(mainChannelClient, treeId, fileId); }
public void MultipleChannel_EncryptionOnBothChannels() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); #endregion uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.EncryptedFileShare); uint treeId; FILEID fileId; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Establish main channel with client {0} and server {1}, encryption is enabled.", clientIps[0].ToString(), serverIps[0].ToString()); EstablishMainChannel( TestConfig.RequestDialects, serverIps[0], clientIps[0], out treeId, true); #region CREATE BaseTestSite.Log.Add(LogEntryKind.TestStep, "Main channel: Create file {0}.", fileName); Smb2CreateContextResponse[] serverCreateContexts; status = mainChannelClient.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts); #endregion #region WRITE BaseTestSite.Log.Add(LogEntryKind.TestStep, "Main channel: Write content to file."); status = mainChannelClient.Write(treeId, fileId, contentWrite); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "Establish alternative channel with client {0} and server {1}, encryption is enabled.", clientIps[1].ToString(), serverIps[1].ToString()); EstablishAlternativeChannel( TestConfig.RequestDialects, serverIps[1], clientIps[1], treeId, true); #region READ BaseTestSite.Log.Add(LogEntryKind.TestStep, "Alternative channel: Read content from file."); status = alternativeChannelClient.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "Verify the contents read from alternative channel are the same as the one written by main channel."); BaseTestSite.Assert.IsTrue( contentRead.Equals(contentWrite), "Read content should be consistent with written content"); ClientTearDown(alternativeChannelClient, treeId, fileId); }
private void DirecotryLeasing( DialectRevision[] requestDialect, DialectRevision expectedDialect, LeaseStateValues leaseState, LeaseBreakAckType leaseBreakAckType = LeaseBreakAckType.None) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); #endregion BaseTestSite.Log.Add( LogEntryKind.Comment, @"Start to create a directory on share \\{0}\{1} with lease state {2}", TestConfig.SutComputerName, TestConfig.BasicFileShare, leaseState); string testDirectory = CreateTestDirectory(TestConfig.SutComputerName, TestConfig.BasicFileShare); client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); #region Negotiate BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); Capabilities_Values capabilities = 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; status = client.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilities, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(expectedDialect, response); if (expectedDialect >= DialectRevision.Smb30) { TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING, response); } }); #endregion #region SESSION_SETUP status = client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region TREE_CONNECT to share string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); uint treeId; status = client.TreeConnect(uncSharePath, out treeId); #endregion #region CREATE FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client sends CREATE request for the directory with the LeaseState set to {0} in SMB2_CREATE_REQUEST_LEASE_V2.", leaseState); status = client.Create( treeId, testDirectory, CreateOptions_Values.FILE_DIRECTORY_FILE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateRequestLeaseV2 { LeaseKey = Guid.NewGuid(), LeaseState = leaseState } }, checker: (Packet_Header header, CREATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "CREATE should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); if (expectedDialect == DialectRevision.Smb2002 || expectedDialect == DialectRevision.Smb21) { BaseTestSite.Assert.AreEqual( OplockLevel_Values.OPLOCK_LEVEL_NONE, response.OplockLevel, "The expected oplock level is OPLOCK_LEVEL_NONE."); } }); #endregion if (expectedDialect >= DialectRevision.Smb30) { // Break the lease with creating another file in the directory sutProtocolController.CreateFile(Path.Combine(Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare), testDirectory), CurrentTestCaseName, string.Empty); // Wait until LEASE_BREAK_Notification is received BaseTestSite.Assert.IsTrue( // Wait 5 seconds for notification arrival notificationReceived.WaitOne(SMB2TestConfig.WAIT_TIMEOUT_IN_MILLISECONDS), "LeaseBreakNotification should be raised."); if (receivedLeaseBreakNotify.Flags == LEASE_BREAK_Notification_Packet_Flags_Values.SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { BaseTestSite.Log.Add( LogEntryKind.Debug, "Server requires an LEASE_BREAK_ACK on this LEASE_BREAK_NOTIFY"); #region LEASE_BREAK_ACK switch (leaseBreakAckType) { case LeaseBreakAckType.None: status = client.LeaseBreakAcknowledgment(treeId, receivedLeaseBreakNotify.LeaseKey, receivedLeaseBreakNotify.NewLeaseState); break; case LeaseBreakAckType.InvalidLeaseState: LeaseStateValues newLeaseState = LeaseStateValues.SMB2_LEASE_WRITE_CACHING; BaseTestSite.Log.Add( LogEntryKind.Comment, "Client attempts to send LEASE_BREAK_ACK with an invalid LeaseState {0} on this LEASE_BREAK_NOTIFY", newLeaseState); status = client.LeaseBreakAcknowledgment( treeId, receivedLeaseBreakNotify.LeaseKey, newLeaseState, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "LEASE_BREAK_ACK with invalid LeaseState is not expected to SUCCESS, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_REQUEST_NOT_ACCEPTED, header.Status, RequirementCategory.STATUS_REQUEST_NOT_ACCEPTED.Id, RequirementCategory.STATUS_REQUEST_NOT_ACCEPTED.Description); }); break; case LeaseBreakAckType.InvalidLeaseKey: Guid invalidLeaseKey = Guid.NewGuid(); BaseTestSite.Log.Add( LogEntryKind.Debug, "Client attempts to send LEASE_BREAK_ACK with an invalid LeaseKey {0} on this LEASE_BREAK_NOTIFY", invalidLeaseKey); status = client.LeaseBreakAcknowledgment( treeId, invalidLeaseKey, receivedLeaseBreakNotify.NewLeaseState, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "LEASE_BREAK_ACK with invalid LeaseKey is not expected to SUCCESS, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_OBJECT_NAME_NOT_FOUND, header.Status, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Id, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Description); }); break; case LeaseBreakAckType.InvalidClientGuid: BaseTestSite.Log.Add(LogEntryKind.Debug, "Initialize a new different client to attempts to send LEASE_BREAK_ACK"); Smb2FunctionalClient newClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); newClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); #region Negotiate status = newClient.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: 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); #endregion #region SESSION_SETUP status = newClient.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region TREE_CONNECT to share uint newTreeId; status = newClient.TreeConnect(uncSharePath, out newTreeId); #endregion status = newClient.LeaseBreakAcknowledgment( newTreeId, receivedLeaseBreakNotify.LeaseKey, receivedLeaseBreakNotify.NewLeaseState, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "LEASE_BREAK_ACK is not expected to SUCCESS when the open is closed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_OBJECT_NAME_NOT_FOUND, header.Status, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Id, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Description); }); status = newClient.TreeDisconnect(newTreeId); status = newClient.LogOff(); BaseTestSite.Log.Add( LogEntryKind.Comment, "Initialize a new different client to attempts to send LEASE_BREAK_ACK"); break; default: throw new InvalidOperationException("Unexpected LeaseBreakAckType " + leaseBreakAckType); } #endregion } else { BaseTestSite.Log.Add( LogEntryKind.Debug, "Server does not require an LEASE_BREAK_ACK on this LEASE_BREAK_NOTIFY"); } } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF"); #region TREE_DISCONNECT status = client.TreeDisconnect(treeId); #endregion #region LOGOFF status = client.LogOff(); #endregion BaseTestSite.Log.Add( LogEntryKind.Comment, @"Complete creating a directory on share \\{0}\{1} with lease state {2}", TestConfig.SutComputerName, TestConfig.BasicFileShare, leaseState); }
public void DurableHandleV2_Reconnect_WithoutPersistence() { /// 1. Client requests a durable handle V2 without persistent flag /// 2. Lose connection by disabling NIC /// 3. Client reconnects the durable handle V2 without persistent flag. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "DurableHandleV2_Reconnect_WithoutPersistence" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a durable handle"); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); }); clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the durable handle"); uint treeIdAfterDisconnection; Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; clientAfterDisconnection.Create( treeIdAfterDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { CreateGuid = createGuid, FileId = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE); string readContent; clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( content.Equals(readContent), "The written content is expected to be equal to read content."); #endregion clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection); clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); }
public void DurableHandleV2_WithLeaseV2_WithoutHandleCaching() { /// 1. Client requests a durable handle with LeaseV2 context, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState. /// 2. Durable Handle v2 is not granted. /// #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "DurableHandleV2_WithLeaseV2_WithoutHandleCaching" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a durable handle v2, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState."); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); // SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); // Durable Handle should not be granted. CheckCreateContextResponsesNotExist( serverCreateContexts, new DefaultDurableHandleV2ResponseChecker( BaseTestSite, 0, uint.MaxValue)); }); #endregion clientBeforeDisconnection.TreeDisconnect(treeIdBeforeDisconnection); clientBeforeDisconnection.LogOff(); clientBeforeDisconnection.Disconnect(); }
public void ResilientWithPersistentHandle_OpenFromDiffClient() { /// 1. Open Persistent Handle with lease /// 2. Send Resiliency request /// 3. Disconnect /// 4. Open the same file from different client (different client guid) /// 5. The expected result of OPEN is STATUS_FILE_NOT_AVAILABLE according to section 3.3.5.9: /// If Connection.Dialect belongs to the SMB 3.x dialect family and the request does not contain SMB2_CREATE_DURABLE_HANDLE_RECONNECT /// Create Context or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context, the server MUST look up an existing open in the GlobalOpenTable /// where Open.FileName matches the file name in the Buffer field of the request. /// If an Open entry is found, and if all the following conditions are satisfied, the server MUST fail the request with STATUS_FILE_NOT_AVAILABLE. /// ¡ì Open.IsPersistent is TRUE /// ¡ì Open.Connection is NULL /// ¡ì Open.OplockLevel is not equal to SMB2_OPLOCK_LEVEL_BATCH /// ¡ì Open.OplockLevel is not equal to SMB2_OPLOCK_LEVEL_LEASE or Open.Lease.LeaseState does not include SMB2_LEASE_HANDLE_CACHING #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); #endregion Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); Guid clientGuid = Guid.NewGuid(); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); string fileName = "ResilientWithPersistentHandle_" + Guid.NewGuid() + ".txt"; FILEID fileId; uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Open Persistent Handle with lease."); OpenFile( client, clientGuid, fileName, true, out createGuid, out treeId, out fileId); // resiliency request Packet_Header ioCtlHeader; IOCTL_Response ioCtlResponse; byte[] inputInResponse; byte[] outputInResponse; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Send resiliency request with timeout {0} milliseconds", testConfig.MaxResiliencyTimeoutInSecond); client.ResiliencyRequest( treeId, fileId, testConfig.MaxResiliencyTimeoutInSecond, (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)), out ioCtlHeader, out ioCtlResponse, out inputInResponse, out outputInResponse ); // Disconnect BaseTestSite.Log.Add( LogEntryKind.TestStep, "Disconnect the resilient handle"); client.Disconnect(); // open from another client Smb2FunctionalClient anotherClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Open the same file from different client (different client guid), the expected result of OPEN is successful"); OpenFile( anotherClient, Guid.NewGuid(), fileName, false, out createGuid, out treeId, out fileId, responseChecker: (Packet_Header header, CREATE_Response response) => { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_FILE_NOT_AVAILABLE, header.Status, "The server MUST fail the request with STATUS_FILE_NOT_AVAILABLE."); }); }
private void DurableHandleV2_Reconnect_WithLeaseV1(bool sameFileName, bool persistent = false) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities( persistent ? NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES: NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = persistent ? Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName) : Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = (persistent ? "PersistentHandle" : "DurableHandleV2") + "_Reconnect_WithLeaseV1" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a {0} handle", persistent ? "persistent" : "durable"); uint treeIdBeforeDisconnection; Connect( DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, persistent ? ConnectShareType.CAShare : ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Flags = persistent? CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0, }, new Smb2CreateRequestLease { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses( serverCreateContexts, new DefaultDurableHandleV2ResponseChecker( BaseTestSite, persistent ? CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0, uint.MaxValue)); }); status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the {0} handle", persistent ? "durable" : "persistent"); uint treeIdAfterDisconnection; Connect( DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, persistent ? ConnectShareType.CAShare : ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; status = clientAfterDisconnection.Create( treeIdAfterDisconnection, sameFileName ? fileName : (persistent ? "PersistentHandle" : "DurableHandleV2" + "_Reconnect_WithLeaseV1_WithDifferentFileName" + Guid.NewGuid() + ".txt"), CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { CreateGuid = createGuid, Flags = persistent ? CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0, FileId = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } }, new Smb2CreateRequestLease { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { }); if (sameFileName) { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Reconnect a durable handle should be successful"); string readContent; status = clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( readContent.Equals(content), "The written content should equal to read content."); clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_INVALID_PARAMETER, status, "If Open.Lease is not NULL and Open.FileName does not match the file name specified in the Buffer field of the SMB2 CREATE request, " + "the server MUST fail the request with STATUS_INVALID_PARAMETER."); } #endregion clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); }
public void DurableHandleV2_Reconnect_WithDifferentDurableOwner() { /// 1. Client requests a durable handle V2 with LeaseV1 context /// 2. Client disconnects /// 3. Client reconnects the durable handle V2 with a different durable owner, and expects that server will return STATUS_ACCESS_DENIED. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); string fileName = GetTestFileName(durableHandleUncSharePath); #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a durable handle"); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); }); status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the durable handle"); uint treeIdAfterDisconnection; Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.NonAdminAccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; clientAfterDisconnection.Create( treeIdAfterDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { CreateGuid = createGuid, FileId = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should not be successful if the DurableOwner is different, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_ACCESS_DENIED, header.Status, RequirementCategory.STATUS_ACCESS_DENIED.Id, RequirementCategory.STATUS_ACCESS_DENIED.Description); }); #endregion clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); }
public void ResilientWithPersistentHandle_OpenFromDiffClient() { /// 1. Open Persistent Handle with lease /// 2. Send Resiliency request /// 3. Disconnect /// 4. Open the same file from different client (different client guid) /// 5. The expected result of OPEN is successful. /// #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); #endregion Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); Guid clientGuid = Guid.NewGuid(); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); string fileName = "ResilientWithPersistentHandle_" + Guid.NewGuid() + ".txt"; FILEID fileId; uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Open Persistent Handle with lease."); OpenFile( client, clientGuid, fileName, true, out createGuid, out treeId, out fileId); // resiliency request Packet_Header ioCtlHeader; IOCTL_Response ioCtlResponse; byte[] inputInResponse; byte[] outputInResponse; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Send resiliency request with timeout {0} milliseconds", testConfig.MaxResiliencyTimeoutInSecond); client.ResiliencyRequest( treeId, fileId, testConfig.MaxResiliencyTimeoutInSecond, (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)), out ioCtlHeader, out ioCtlResponse, out inputInResponse, out outputInResponse ); // Disconnect BaseTestSite.Log.Add( LogEntryKind.TestStep, "Disconnect the resilient handle"); client.Disconnect(); // open from another client Smb2FunctionalClient anotherClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Open the same file from different client (different client guid), the expected result of OPEN is successful"); OpenFile( anotherClient, Guid.NewGuid(), fileName, false, out createGuid, out treeId, out fileId); }
public void AppInstanceId_Lock_ExpectNoLockInReOpen() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2); #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "InitialOpen: Connect to share via Nic1."); FILEID fileIdForInitialOpen; uint treeIdForInitialOpen; ConnectShare(TestConfig.SutIPAddress, TestConfig.ClientNic1IPAddress, clientForInitialOpen, out treeIdForInitialOpen); #region Create an open with AppInstanceId BaseTestSite.Log.Add(LogEntryKind.TestStep, "InitialOpen: Create an open with AppInstanceId."); Guid appInstanceId = Guid.NewGuid(); Smb2CreateContextResponse[] serverCreateContexts; status = clientForInitialOpen.Create( treeIdForInitialOpen, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdForInitialOpen, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid(), Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, }, new Smb2CreateAppInstanceId { AppInstanceId = appInstanceId } }, accessMask: AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE, shareAccess: ShareAccess_Values.NONE); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "InitialOpen: Write contents to file."); status = clientForInitialOpen.Write(treeIdForInitialOpen, fileIdForInitialOpen, contentWrite); #region Request ByteRangeLock BaseTestSite.Log.Add(LogEntryKind.TestStep, "InitialOpen: Request ByteRangeLock."); LOCK_ELEMENT[] locks = new LOCK_ELEMENT[1]; uint lockSequence = 0; locks[0].Offset = 0; locks[0].Length = (ulong)TestConfig.WriteBufferLengthInKb * 1024; locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK; BaseTestSite.Log.Add( LogEntryKind.Debug, "Client starts to lock a byte range for file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3}", fileName, locks[0].Offset, locks[0].Length, locks[0].Flags.ToString()); status = clientForInitialOpen.Lock(treeIdForInitialOpen, lockSequence++, fileIdForInitialOpen, locks); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "ReOpen: Connect to share via Nic2."); FILEID fileIdForReOpen; uint treeIdForReOpen; ConnectShare(TestConfig.SutIPAddress, TestConfig.ClientNic2IPAddress, clientForReOpen, out treeIdForReOpen); #region Create an open with same AppInstanceId BaseTestSite.Log.Add(LogEntryKind.TestStep, "ReOpen: Create an open with same AppInstanceId."); status = clientForReOpen.Create( treeIdForReOpen, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdForReOpen, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid(), Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, }, new Smb2CreateAppInstanceId { // Use the same application instance id to force the server close all files // and will clear previous ByteRangeLock AppInstanceId = appInstanceId } }, accessMask: AccessMask.GENERIC_READ); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "ReOpen: Read the contents written by InitialOpen."); status = clientForReOpen.Read(treeIdForReOpen, fileIdForReOpen, 0, (uint)contentWrite.Length, out contentRead); BaseTestSite.Assert.IsTrue( contentRead.Equals(contentWrite), "The written content should equal to read content."); #region AfterFailover: Attempt to access same file with previous byte lock range BaseTestSite.Log.Add( LogEntryKind.TestStep, "ReOpen: Attempt to access same file with previous byte lock range."); ValidateByteLockRangeFromAnotherClient(false); #endregion #region Client tear down BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Close file."); status = clientForReOpen.Close(treeIdForReOpen, fileIdForReOpen); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Disconnect from the share."); status = clientForReOpen.TreeDisconnect(treeIdForReOpen); BaseTestSite.Log.Add(TestTools.LogEntryKind.TestStep, "ReOpen: Log off."); status = clientForReOpen.LogOff(); #endregion }