private void CheckApplicability()
 {
     #region Check Applicability
     TestConfig.CheckDialect(DialectRevision.Smb311);
     TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID, CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_VERSION);
     #endregion
 }
        public void AppInstanceId_Smb302()
        {
            // Client1 opens a file with create context AppInstanceId, no create context DurableHandleRequestV2
            // Client1 writes to that file.
            // Client2 opens that file with the same AppInstanceId successfully.
            // Client1 writes to check if the Open is closed.
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb302);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID);
            #endregion

            // If Open.CreateGuid is NULL, and Open.TreeConnect.Share.IsCA is FALSE, the server
            // SHOULD < 298 > close the open as specified in section 3.3.4.17.
            // <298> Section 3.3.5.9.13: Windows Server 2012 and Windows Server 2012 R2 servers do not close the open.
            var is2012Or2012R2 = TestConfig.Platform == Platform.WindowsServer2012 ||
                                 TestConfig.Platform == Platform.WindowsServer2012R2;

            var expectedCreateResponseStatus = is2012Or2012R2 ?
                                               Smb2Status.STATUS_SHARING_VIOLATION :
                                               Smb2Status.STATUS_SUCCESS;

            var expectedInitialOpenStatusAfterReopen = is2012Or2012R2 ?
                                                       Smb2Status.STATUS_SUCCESS :
                                                       Smb2Status.STATUS_FILE_CLOSED;

            AppInstanceIdTest(
                sameAppInstanceId: true,
                containCreateDurableContext: false,
                expectedCreateResponseStatus: expectedCreateResponseStatus,
                expectedInitialOpenStatusAfterReopen: expectedInitialOpenStatusAfterReopen);
        }
        public void DurableHandleV1_WithLeaseV1_WithoutHandleCaching()
        {
            /// 1. Client requests a durable handle with LeaseV1 context, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState.
            /// 2. Durable Handle is not granted.

            #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_REQUEST_LEASE);
            #endregion

            string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            fileName = "DurableHandleV1_WithLeaseV1_WithoutHandleCaching" + Guid.NewGuid() + ".txt";
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);

            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a durable handle, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState.");

            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb21, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null);
            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;
            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));
                // Durable Handle should not be granted.
                CheckCreateContextResponsesNotExist(serverCreateContexts, new DefaultDurableHandleResponseChecker(BaseTestSite));
            });

            clientBeforeDisconnection.TreeDisconnect(treeIdBeforeDisconnection);
            clientBeforeDisconnection.LogOff();
            clientBeforeDisconnection.Disconnect();
        }
        public void DurableHandleV2_NoPersistenceGrantedOnNonCAShare()
        {
            /// 1. Client requests a durable handle V2 to a Non-CA share
            /// 2. Expect the create response contains Smb2CreateDurableHandleResponseV2 context but no persistent flag is set.

            #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

            durableHandleUncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            fileName = "DurableHandleV2_NoPersistenceGrantedOnNonCAShare" + Guid.NewGuid() + ".txt";
            Guid clientGuid = Guid.NewGuid();

            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a durable handle");

            #region client connect to server
            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShare, out treeIdBeforeDisconnection, null);

            Smb2CreateContextResponse[] serverCreateContexts = null;
            FILEID fileIdBeforeDisconnection;
            Guid   createGuid = Guid.NewGuid();
            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));
            });

            BaseTestSite.Assert.AreEqual(
                null,
                serverCreateContexts,
                "The server should ignore the create context when TreeConnect.Share.IsCA is FALSE.");
            #endregion

            clientBeforeDisconnection.Close(treeIdBeforeDisconnection, fileIdBeforeDisconnection);
            clientBeforeDisconnection.TreeDisconnect(treeIdBeforeDisconnection);
            clientBeforeDisconnection.LogOff();
        }
Esempio n. 5
0
        public void BVT_ResilientHandle_Reconnect()
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            Guid clientGuid = Guid.NewGuid();

            #region clientBeforeDisconnection Create a File
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the first client to create a file by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT");
            clientBeforeDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientBeforeDisconnection.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            uint treeId;
            clientBeforeDisconnection.TreeConnect(sharePath, out treeId);
            FILEID fileId;
            Smb2CreateContextResponse[] createContextResponse;
            clientBeforeDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse);
            #endregion

            #region Request Resilient Handle
            IOCTL_Response IOCTLResponse;
            byte[]         inputInResponse;
            byte[]         outputInResponse;
            Packet_Header  packetHeader;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends an IOCTL FSCTL_LMR_REQUEST_RESILLIENCY request.");
            clientBeforeDisconnection.ResiliencyRequest(treeId, fileId, TestConfig.MaxResiliencyTimeoutInSecond * 1000,
                                                        NETWORK_RESILIENCY_REQUEST_SIZE, out packetHeader, out IOCTLResponse, out inputInResponse, out outputInResponse);
            #endregion

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the first client by sending DISCONNECT request.");
            clientBeforeDisconnection.Disconnect();

            #region ClientAfterDisconnection Opens the Previously Created File with DurableHandleReconnect
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a second client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT");
            clientAfterDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientAfterDisconnection.ReconnectSessionSetup(clientBeforeDisconnection,
                                                           TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            clientAfterDisconnection.TreeConnect(sharePath, out treeId);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The second client sends CREATE request with SMB2_CREATE_DURABLE_HANDLE_RECONNECT create context to open the same file created by the first client.");
            clientAfterDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                                            new Smb2CreateContextRequest[]
            {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = fileId
                }
            });
            #endregion

            #region Tear Down Client
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            clientAfterDisconnection.Close(treeId, fileId);
            clientAfterDisconnection.TreeDisconnect(treeId);
            clientAfterDisconnection.LogOff();
            #endregion
        }
        public void ResilientOpenScavengerTimer_ReconnectBeforeTimeout()
        {
            /// 1. Open Resilient Handle with specific timeout.
            /// 2. Disconnect to start the Resilient Timer.
            /// 3. Wait for specific timeout - 1 seconds.
            /// 4. Reconnect the resilient handle and expect the result is success.
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            Smb2FunctionalClient prepareClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            uint   timeoutInSecond = testConfig.MaxResiliencyTimeoutInSecond / 2;
            Guid   clientGuid      = Guid.NewGuid();
            string fileName        = "ResilientHandle_" + Guid.NewGuid() + ".txt";
            FILEID fileId;

            // Open file & Resiliency request
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Create resilient handle to file '{0}' and timeout is {1} seconds", fileName, timeoutInSecond);
            OpenFileAndResilientRequest(
                prepareClient,
                clientGuid,
                fileName,
                timeoutInSecond * 1000, // convert second to millisecond
                out fileId);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Disconnect the client to start the Resilient Open Scavenger Timer on server");
            prepareClient.Disconnect();

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Wait {0} seconds before Resilient Open Scavenger Timer expired.", timeoutInSecond - 1);
            Thread.Sleep(TimeSpan.FromSeconds(timeoutInSecond - 1));

            Smb2FunctionalClient reconnectClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Re-establish Resilient Open, verify the returned status is STATUS_SUCCESS.");
            ReconnectResilientHandle(
                reconnectClient,
                clientGuid,
                fileName,
                fileId,
                NtStatus.STATUS_SUCCESS,
                "Reconnect resilient handle should be successful.");

            // clean
            reconnectClient.Disconnect();
        }
        public void AppInstanceId_Negative_DifferentAppInstanceIdInReopen()
        {
            // Client1 opens a file with DurableHandleRequestV2 and AppInstanceId.
            // Client2 opens that file with DurableHandleRequestV2 and with the different AppInstanceId, but fails.
            // Client1 writes to that file and succeeds since the first open is not closed.
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2);
            #endregion

            AppInstanceIdTest(sameAppInstanceId: false, containCreateDurableContext: true);
        }
        public void BVT_AppInstanceId()
        {
            // Client1 opens a file with DurableHandleRequestV2 and AppInstanceId.
            // Client2 opens that file with DurableHandleRequestV2 and with the same AppInstanceId successfully.
            // Client1 writes to that file but fails since the first open is closed.
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2);
            #endregion

            AppInstanceIdTest(sameAppInstanceId: true, containCreateDurableContext: true);
        }
        public void AppInstanceId_Smb311()
        {
            // Client1 opens a file with create context AppInstanceId, no create context DurableHandleRequestV2
            // Client1 writes to that file.
            // Client2 opens that file with the same AppInstanceId successfully.
            // Client1 writes to that file but fails since the first open is closed.
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID);
            #endregion

            AppInstanceIdTest(sameAppInstanceId: true, containCreateDurableContext: false);
        }
        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. 11
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 AppInstanceId_Smb311()
        {
            // Client1 opens a file with create context AppInstanceId, no create context DurableHandleRequestV2
            // Client1 writes to that file.
            // Client2 opens that file with the same AppInstanceId successfully.
            // Client1 writes to that file but fails since the first open is closed.
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_APP_INSTANCE_ID);
            #endregion

            AppInstanceIdTest(
                sameAppInstanceId: true,
                containCreateDurableContext: false,
                expectedCreateResponseStatus: Smb2Status.STATUS_SUCCESS,
                expectedInitialOpenStatusAfterReopen: Smb2Status.STATUS_FILE_CLOSED);
        }
        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);
        }
        /// <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();
        }
Esempio n. 15
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 ResilientOpenScavengerTimer_ReconnectBeforeTimeout_Zero()
        {
            /// 1. Open Resilient Handle with timeout = 0. When server receive resilient handle with timeout = 0,
            /// it will set the Open.ResilientTimeout as implementation-specific value.
            /// 2. Disconnect to start the Resilient Timer.
            /// 3. Wait for specific timeout - 1 seconds.
            /// 4. Reconnect the resilient handle and expect the result is success.
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            Smb2FunctionalClient prepareClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            Guid   clientGuid = Guid.NewGuid();
            string fileName   = "ResilientHandle_" + Guid.NewGuid() + ".txt";
            FILEID fileId;

            // Open file & Resiliency request
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Create resilient handle to file '{0}' and timeout is {1} seconds", fileName, 0);
            OpenFileAndResilientRequest(
                prepareClient,
                clientGuid,
                fileName,
                0, // convert second to millisecond
                out fileId);

            /// Open.ResiliencyTimeout SHOULD be set to an implementation-specific value.<294>
            uint timeout = DEFAULT_RESILIENT_TIMEOUT_IN_SECONDS;
            if (TestConfig.Platform == Platform.WindowsServer2012)
            {
                /// <294> Section 3.3.5.15.9: Windows 7 and Windows Server 2008 R2 servers keep the resilient
                /// handle open indefinitely when the requested Timeout value is equal to zero.
                /// Windows 8 and Windows Server 2012 servers set a constant value of 120 seconds.
                timeout = DEFAULT_RESILIENT_TIMEOUT_IN_SECONDS;
            }
            else
            {
                timeout = testConfig.DefaultResiliencyTimeoutInSecond;
            }
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Server should set the timeout of resilient handle to implementation-specific timeout {0} seconds", timeout);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Disconnect the client to start the Resilient Open Scavenger Timer on server");
            prepareClient.Disconnect();

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Wait {0} seconds before Resilient Open Scavenger Timer expired.", timeout - 1);

            Thread.Sleep(TimeSpan.FromSeconds(timeout - 1));

            Smb2FunctionalClient reconnectClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Re-establish Resilient Open, verify the returned status is STATUS_SUCCESS.");
            ReconnectResilientHandle(
                reconnectClient,
                clientGuid,
                fileName,
                fileId,
                NtStatus.STATUS_SUCCESS,
                "Reconnect resilient handle should be successful.");

            // clean
            reconnectClient.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();
        }
        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. 19
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();
        }
Esempio n. 20
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();
        }
        private void DurableHandleV1_Reconnect_WithoutLogoff(bool isPreviousSessionIdSet)
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb2002);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);
            fileName = "DurableHandleV1_Reconnect_WithoutLogoff" + 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.Smb21, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null);

            FILEID fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequest
                {
                    DurableRequest = Guid.Empty
                }
            },
                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

            #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, isPreviousSessionIdSet ? clientBeforeDisconnection : null);

            FILEID fileIdAfterDisconnection;

            ResponseChecker <CREATE_Response> createResponseChecker = null;
            if (isPreviousSessionIdSet)
            {
                if (testConfig.Platform == Platform.WindowsServer2012R2)
                {
                    // 6   Appendix A: Product Behavior
                    // <265> Section 3.3.5.9.7: If the Session was established by specifying PreviousSessionId in the SMB2 SESSION_SETUP request,
                    // therefore invalidating the previous session, Windows 8.1 and Windows Server 2012 R2 close the durable opens established on the previous session.
                    createResponseChecker = (header, response) =>
                    {
                        BaseTestSite.Assert.AreNotEqual(
                            Smb2Status.STATUS_SUCCESS,
                            header.Status,
                            "{0} should not be successful if Server is Windows Server 2012R2 and the Session was established by specifying PreviousSessionId in the SMB2 SESSION_SETUP request. " +
                            "Actually server returns {1}.", header.Command, 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);
                    };
                }
                else
                {
                    createResponseChecker = (header, response) =>
                    {
                        BaseTestSite.Assert.AreEqual(
                            Smb2Status.STATUS_SUCCESS,
                            header.Status,
                            "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                    };
                }
            }
            else
            {
                createResponseChecker = (header, response) =>
                {
                    BaseTestSite.Assert.AreNotEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should not be successful if Open.Session is not NULL, actually server returns {1}.", header.Command, 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);
                };
            }

            clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: createResponseChecker);
            #endregion

            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);

            clientAfterDisconnection.LogOff();

            clientAfterDisconnection.Disconnect();
        }
        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
        }
        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();
        }
Esempio n. 24
0
        public void BVT_ResilientHandle_LockSequence()
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            Guid clientGuid = Guid.NewGuid();

            #region clientBeforeDisconnection Create a File
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start the first client to create a file by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            clientBeforeDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientBeforeDisconnection.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            uint treeId;
            clientBeforeDisconnection.TreeConnect(sharePath, out treeId);
            FILEID fileId;
            Smb2CreateContextResponse[] createContextResponse;
            clientBeforeDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse);
            #endregion

            #region Request Resilient Handle
            IOCTL_Response IOCTLResponse;
            byte[]         inputInResponse;
            byte[]         outputInResponse;
            Packet_Header  packetHeader;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends an IOCTL FSCTL_LMR_REQUEST_RESILLIENCY request.");
            clientBeforeDisconnection.ResiliencyRequest(treeId, fileId, TestConfig.MaxResiliencyTimeoutInSecond * 1000,
                                                        NETWORK_RESILIENCY_REQUEST_SIZE, out packetHeader, out IOCTLResponse, out inputInResponse, out outputInResponse);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends WRITE request.");
            clientBeforeDisconnection.Write(treeId, fileId, "12345678");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends Flush request.");
            clientBeforeDisconnection.Flush(treeId, fileId);
            #endregion

            //The LockSequence field of the SMB2 lock request MUST be set to (BucketNumber<< 4) + BucketSequence.
            int  bucketNum    = 1;
            int  bucketSeq    = 1;
            uint lockSequence = (uint)bucketNum << 4 + bucketSeq;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends LOCK request with LockSequence set to (BucketNumber<< 4) + BucketSequence");
            clientBeforeDisconnection.Lock(treeId,
                                           lockSequence,
                                           fileId,
                                           new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            });

            clientBeforeDisconnection.Disconnect();

            #region clientAfterDisconnection Opens the Previously Created File
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start the second client to reconnect to the file created by the first client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE (with SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context).");
            clientAfterDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientAfterDisconnection.ReconnectSessionSetup(clientBeforeDisconnection,
                                                           TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            clientAfterDisconnection.TreeConnect(sharePath, out treeId);
            clientAfterDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                                            new Smb2CreateContextRequest[]
            {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = fileId
                }
            });
            #endregion

            //If the sequence numbers are equal, the server MUST complete the lock/unlock request with success.
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The second client sends LOCK request with the same LockSequence with the first client.");
            clientAfterDisconnection.Lock(treeId,
                                          lockSequence, //Using same Lock Sequence
                                          fileId,
                                          new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            });

            clientAfterDisconnection.Lock(treeId,
                                          lockSequence + 1, //Using different Lock Sequence
                                          fileId,
                                          new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            },
                                          (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_LOCK_NOT_GRANTED,
                    header.Status,
                    "If the range being locked is already locked by another open in a way that does not allow this open to take a lock on the range, " +
                    "and if SMB2_LOCKFLAG_FAIL_IMMEDIATELY is set, the server MUST fail the request with STATUS_LOCK_NOT_GRANTED. " +
                    "Actually server returns {0}.",
                    Smb2Status.GetStatusCode(header.Status));
            });

            #region Tear Down Client
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            clientAfterDisconnection.Close(treeId, fileId);
            clientAfterDisconnection.TreeDisconnect(treeId);
            clientAfterDisconnection.LogOff();
            #endregion
        }
        public void BVT_PersistentHandle_Reconnect()
        {
            /// 1. Client requests a persistent handle
            /// 2. Client disconnects from the server
            /// 3. Client reconnects the persistent handle, and expects success.

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2);
            #endregion

            string content    = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            Guid   clientGuid = Guid.NewGuid();
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName);
            fileName = "BVT_PersistentHandle_Reconnect_" + Guid.NewGuid() + ".txt";

            #region client connect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client connects to server and opens file with a persistent handle");

            uint treeIdBeforeDisconnection;
            Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdBeforeDisconnection, null);

            Guid   createGuid = Guid.NewGuid();
            FILEID fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            status = clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequestV2
                {
                    CreateGuid = createGuid,
                    Flags      = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT, uint.MaxValue));
            });

            status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content);
            #endregion

            clientBeforeDisconnection.Disconnect();

            #region client reconnect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client opens the same file and reconnects the persistent handle");

            uint treeIdAfterDisconnection;
            Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdAfterDisconnection, clientBeforeDisconnection);

            FILEID fileIdAfterDisconnection;
            status = clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnectV2
                {
                    CreateGuid = createGuid,
                    Flags      = CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT,
                    FileId     = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                }
            },
                shareAccess: ShareAccess_Values.NONE);

            string readContent;
            status = clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent);

            BaseTestSite.Assert.IsTrue(
                readContent.Equals(content),
                "The written content should equal to read content.");
            #endregion

            clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection);
            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            clientAfterDisconnection.LogOff();
            clientAfterDisconnection.Disconnect();
        }
        public void BVT_DurableHandleV1_Reconnect_WithBatchOplock()
        {
            /// 1. Client requests a durable handle with BatchOplock
            /// 2. Client sends Disconnect to lose connection
            /// 3. Client reconnects the durable handle with BatchOplock, and expects success.

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb2002);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);
            fileName = "BVT_DurableHandleV1_Reconnect_WithBatchOplock" + Guid.NewGuid() + ".txt";
            durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);

            #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);

            FILEID fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends CREATE request, with OPLOCK_LEVEL_BATCH and SMB2_CREATE_DURABLE_HANDLE_REQUEST.", clientGuid);
            clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequest
                {
                    DurableRequest = Guid.Empty,
                }
            },
                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);
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "The client with clientGuid {0} connects to server and opens file with a durable handle.", clientGuid.ToString());
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The client with clientGuid {0} sends DISCONECT request.", clientGuid.ToString());
            clientBeforeDisconnection.Disconnect();

            #region client reconnect to server
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "The client with clientGuid {0} opens the same file and reconnects the durable handle.", clientGuid);

            uint treeIdAfterDisconnection;
            Connect(DialectRevision.Smb21, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection);

            FILEID fileIdAfterDisconnection;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends CREATE request, with OPLOCK_LEVEL_BATCH and SMB2_CREATE_DURABLE_HANDLE_RECONNECT.", clientGuid);
            clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                }
            },
                shareAccess: ShareAccess_Values.NONE);

            string readContent;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends READ request.", clientGuid.ToString());
            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.");
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client opens the same file and reconnects the durable handle");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client with clientGuid {0} by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF; DISCONNECT.", clientGuid.ToString());
            clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection);
            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            clientAfterDisconnection.LogOff();
            clientAfterDisconnection.Disconnect();
            #endregion
        }
        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();
        }
Esempio n. 28
0
        public void ResilientOpenScavengerTimer_ReconnectAfterTimeout()
        {
            /// 1. Wait for MaxResiliencyTimeoutInSecond seconds to expire the Resilient Timer and make sure that the Timer is not started.
            /// 2. Open Resilient Handle with specific timeout.
            /// 3. Disconnect to start the Resilient Timer.
            /// 4. Wait for specific timeout + 1 seconds.
            /// 5. Reconnect the resilient handle and expect the handle is terminated.

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Wait {0} seconds to make sure Resilient Timer is not started.", testConfig.MaxResiliencyTimeoutInSecond);
            Thread.Sleep(TimeSpan.FromSeconds((int)testConfig.MaxResiliencyTimeoutInSecond));

            Smb2FunctionalClient prepareClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            uint   timeoutInSecond = testConfig.MaxResiliencyTimeoutInSecond / 2;
            Guid   clientGuid      = Guid.NewGuid();
            string fileName        = GetTestFileName(Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare));
            FILEID fileId;

            // Open file & Resiliency request
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Create resilient handle to file '{0}' and timeout is {1} seconds", fileName, timeoutInSecond);
            OpenFileAndResilientRequest(
                prepareClient,
                clientGuid,
                fileName,
                timeoutInSecond * 1000, // convert second to millisecond
                out fileId);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Disconnect the client to start the Resilient Open Scavenger Timer on server");
            prepareClient.Disconnect();

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Wait {0} seconds before Resilient Open Scavenger Timer expired.", timeoutInSecond + 10);
            Thread.Sleep(TimeSpan.FromSeconds(timeoutInSecond + 10));

            Smb2FunctionalClient reconnectClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Re-establish Resilient Open, verify the returned status is STATUS_OBJECT_NAME_NOT_FOUND.");
            ReconnectResilientHandle(
                reconnectClient,
                clientGuid,
                fileName,
                fileId,
                NtStatus.STATUS_OBJECT_NAME_NOT_FOUND,
                "Resilient handle should be terminated.");

            // clean
            reconnectClient.Disconnect();
        }