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);
        }
Esempio n. 2
0
        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.");
        }
Esempio n. 7
0
        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();
        }
Esempio n. 11
0
        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);
        }
Esempio n. 13
0
        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();
        }
Esempio n. 14
0
        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
        }
Esempio n. 16
0
        /// <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();
        }
Esempio n. 24
0
        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
        }