/// <summary>
        /// Send valid link referral request and verify response.
        /// </summary>
        /// <param name="entryType"></param>
        /// <param name="isEx"></param>
        /// <param name="containSiteName"></param>
        private void ValidLinkReferral(ReferralEntryType_Values entryType, bool isEx = false, bool containSiteName = false)
        {
            uint   status;
            string reqPath = TestConfig.ValidLinkPathDomain;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends a {0} Link referral request to DC.", entryType.ToString());
            DfscReferralResponsePacket respPacket = utility.SendAndReceiveDFSReferral(out status, client, entryType, reqPath, true, isEx, containSiteName);
            bool DChostingDFSServer = TestConfig.DCServerName.Equals(TestConfig.DFSServerName, StringComparison.OrdinalIgnoreCase);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server response.");
            if (DChostingDFSServer)
            {
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Link Referral to DC Response should succeed, actual status is {0}", Smb2Status.GetStatusCode(status));
                string target = TestConfig.LinkTarget;
                utility.VerifyReferralResponse(ReferralResponseType.LinkTarget, entryType, reqPath, target, respPacket);
            }
            else
            {
                // Section 3.3.5.5   Receiving a Root Referral Request or Link Referral Request
                // A DC MUST fail the link referral request with STATUS_NOT_FOUND,
                // if it’s not the DFS root target for the DFS namespace specified in the link referral request.
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_NOT_FOUND, status, "Server should fail the referral request with STATUS_NOT_FOUND. "
                                             + "Actual status is " + Smb2Status.GetStatusCode(status));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Read and write the file within the locking byte range when lock or unlock is taken
        /// </summary>
        /// <param name="isLocked">Set true to indicate that access the file when lock operation is taken</param>
        private void ValidateByteLockRangeFromAnotherClient(bool isLocked)
        {
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

            status = client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES);

            status = client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            uint treeId;

            status = client.TreeConnect(uncSharePath, out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileId;

            status = client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);

            string data;
            Random random = new Random();
            uint   offset = (uint)random.Next(0, TestConfig.WriteBufferLengthInKb * 1024 - 1);
            uint   length = (uint)random.Next(0, (int)(TestConfig.WriteBufferLengthInKb * 1024 - offset));

            status = client.Read(treeId, fileId, offset, length, out data);

            status = client.Write(treeId, fileId, contentWrite, checker: (header, response) => { });
            if (isLocked)
            {
                BaseTestSite.Assert.AreNotEqual(
                    Smb2Status.STATUS_SUCCESS,
                    status,
                    "Write content to locked range of file from different client is not expected to success");
                BaseTestSite.CaptureRequirementIfAreEqual(
                    Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                    status,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
            }
            else
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    status,
                    "Write content in file failed with error code=" + Smb2Status.GetStatusCode(status));
            }
        }
        public void BVT_SetZeroData()
        {
            CheckHvrsCapability(TestConfig.IsSetZeroDataImplemented,
                                "If the server supports the FSCTL_SET_ZERO_DATA command, " +
                                "as specified in [MS-FSA] section 2.1.5.9.36, " +
                                "then Hyper-V can issue this command to optimize the performance of virtual-disk-creation operations.");

            FsCtl_Set_ZeroData_IsZeroDataSupported(
                smb2Functionalclient,
                checker: (Packet_Header header, IOCTL_Response response) =>
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify the server response.");
                if (!TestConfig.IsSetZeroDataImplemented)
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_INVALID_DEVICE_REQUEST,
                        header.Status,
                        @"If the object store does not implement this functionality, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST. 
                            The response status is {0}", Smb2Status.GetStatusCode(header.Status));
                }
                else if (header.Status == Smb2Status.STATUS_SUCCESS)
                {
                    BaseTestSite.Log.Add(LogEntryKind.TestStep, "This server supports the FSCTL_SET_ZERO_DATA command, and returns STATUS_SUCCESS.");
                }
                else
                {
                    BaseTestSite.Log.Add(LogEntryKind.Warning, "Unexpected Response: {0}", Smb2Status.GetStatusCode(header.Status));
                }
            });
        }
        private void OpenFile(out uint treeId, out FILEID fileId)
        {
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Open the file by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

            client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "Negotiate should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
            });

            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            client.TreeConnect(Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare), out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            client.Create(
                treeId,
                string.Format("BVT_EnumerateSnapShots_{0}.txt", Guid.NewGuid()),
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);
        }
        public void FileLevelTrim_Negative_NonZeroKeyInRequest()
        {
            uint   treeId;
            FILEID fileId;

            PrepareFileForTrimming(out treeId, out fileId);

            FSCTL_FILE_LEVEL_TRIM_RANGE fileLevelTrimRange;
            Random random = new Random();
            uint   offset = (uint)random.Next(0, TestConfig.WriteBufferLengthInKb * 1024);
            uint   length = (uint)random.Next(0, (int)(TestConfig.WriteBufferLengthInKb * 1024 - offset));

            fileLevelTrimRange.Offset = offset;
            fileLevelTrimRange.Length = length;

            FSCTL_FILE_LEVEL_TRIM_INPUT fileLevelTrimInput;

            fileLevelTrimInput.Key       = (uint)random.Next(1, int.MaxValue); // Set the Key field a non-zero value
            fileLevelTrimInput.NumRanges = 1;
            fileLevelTrimInput.Ranges    = new FSCTL_FILE_LEVEL_TRIM_RANGE[] { fileLevelTrimRange };

            byte[] buffer = TypeMarshal.ToBytes <FSCTL_FILE_LEVEL_TRIM_INPUT>(fileLevelTrimInput);
            byte[] respOutput;
            status = client.FileLevelTrim(
                treeId,
                fileId,
                buffer,
                out respOutput,
                (header, response) => Assert.AreEqual(
                    Smb2Status.STATUS_INVALID_PARAMETER,
                    header.Status,
                    "If the Key field in FSCTL_FILE_LEVEL_TRIM, as specified in [MS-FSCC] section 2.3.73, is not zero," +
                    " the server MUST fail the request with an error code of STATUS_INVALID_PARAMETER. " +
                    "Actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)));
        }
        public void InvalidRootReferralDomainToDFSServer()
        {
            string invalidRootPathDomain = string.Format(@"\{0}\{1}", TestConfig.DomainFQDNName, DFSCTestUtility.Consts.InvalidComponent);
            uint   status;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends a DFS root referral request v4 to DFS Server, the request path is domain-based and invalid, expects negative response.");
            utility.SendAndReceiveDFSReferral(out status, client, ReferralEntryType_Values.DFS_REFERRAL_V4, invalidRootPathDomain, false);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server response.");
            // Section 6
            // <22> Section 3.2.5.5: Windows NT Server 4.0, Windows 2000, Windows Server 2003, Windows Server 2003 R2, and Windows Server 2008
            // fail the referral request with a STATUS_NOT_FOUND (0xC0000225) return code.
            if (TestConfig.Platform == Platform.WindowsServer2008 || TestConfig.Platform == Platform.WindowsServer2008R2)
            {
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_NOT_FOUND, status,
                                             "Server SHOULD fail the referral request with STATUS_NOT_FOUND for 2008 and 2008R2. Actual status is: "
                                             + Smb2Status.GetStatusCode(status));
            }
            else if (TestConfig.IsWindowsPlatform)
            {
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_DFS_UNAVAILABLE, status,
                                             "Server SHOULD fail the referral request with STATUS_DFS_UNAVAILABLE. Actual status is: "
                                             + Smb2Status.GetStatusCode(status));
            }
            else
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                                                "Server SHOULD fail the referral request. Actual status is " + Smb2Status.GetStatusCode(status));
            }
        }
Beispiel #7
0
        /// <summary>
        /// Read and write file within byte lock range when the file is locked or unlocked
        /// </summary>
        /// <param name="isLocked">Set true to indicate that byte lock range is taken on the file</param>
        /// <param name="serverName">Name of file server to access</param>
        /// <param name="targetFileName">Target file name to read and write</param>
        private void ValidateByteLockRangeFromAnotherClient(bool isLocked, string serverName, string targetFileName)
        {
            uint status = 0;

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

            client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client.ConnectToServer(TestConfig.UnderlyingTransport, serverName, currentAccessIp);

            status = client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);

            status = client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                serverName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            uint treeId;

            status = client.TreeConnect(uncSharePath, out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileId;

            status = client.Create(
                treeId,
                targetFileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);

            string data;
            Random random = new Random();
            uint   offset = (uint)random.Next(0, TestConfig.WriteBufferLengthInKb * 1024 - 1);
            uint   length = (uint)random.Next(0, (int)(TestConfig.WriteBufferLengthInKb * 1024 - offset));

            status = client.Read(treeId, fileId, offset, length, out data);

            status = client.Write(treeId, fileId, contentWrite, checker: (header, response) => { });
            if (isLocked)
            {
                BaseTestSite.Assert.AreNotEqual(
                    Smb2Status.STATUS_SUCCESS,
                    status,
                    "Write content to locked range of file from different client is not expected to success");
                BaseTestSite.CaptureRequirementIfAreEqual(
                    Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                    status,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
            }
            else
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    status,
                    "Write content in file should succeed, actual status is {0}", Smb2Status.GetStatusCode(status));
            }
        }
Beispiel #8
0
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R NEGOTIATE");

            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", Dialect=" + PayLoad.DialectRevision);
                if (NegotiateContext_PREAUTH != null)
                {
                    sb.Append(", HashAlgorithms={");
                    foreach (var hashId in NegotiateContext_PREAUTH.Value.HashAlgorithms)
                    {
                        sb.Append(hashId.ToString() + ",");
                    }
                    sb.Length--;
                    sb.Append("}");
                }
                if (NegotiateContext_ENCRYPTION != null)
                {
                    sb.Append(", Ciphers={");
                    foreach (var alg in NegotiateContext_ENCRYPTION.Value.Ciphers)
                    {
                        sb.Append(alg.ToString() + ",");
                    }
                    sb.Length--;
                    sb.Append("}");
                }
                if (NegotiateContext_SIGNING != null)
                {
                    sb.Append(", SigningAlgorithms={");
                    foreach (var signingId in NegotiateContext_SIGNING.Value.SigningAlgorithms)
                    {
                        sb.Append(signingId.ToString() + ",");
                    }
                    sb.Length--;
                    sb.Append("}");
                }
                if (NegotiateContext_RDMA != null)
                {
                    sb.Append(", TransformIds={");
                    foreach (var transformId in NegotiateContext_RDMA.Value.RDMATransformIds)
                    {
                        sb.Append(transformId.ToString() + ",");
                    }
                    sb.Length--;
                    sb.Append("}");
                }
                sb.Append(", Capabilities=" + PayLoad.Capabilities);
            }
            return(sb.ToString());
        }
Beispiel #9
0
        /// <summary>
        /// Delegate to check negotiate response header and payload in this class.
        /// </summary>
        /// <param name="responseHeader">Response header to be checked</param>
        /// <param name="response">Negotiate response payload to be checked</param>
        public void ReplayNegotiateResponseChecker(Packet_Header responseHeader, NEGOTIATE_Response response)
        {
            BaseTestSite.Assert.AreEqual(
                Smb2Status.STATUS_SUCCESS,
                responseHeader.Status,
                "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(responseHeader.Status));

            TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response);
        }
        /// <summary>
        /// Convert the status from uint to string
        /// </summary>
        /// <param name="status">The status in uint</param>
        /// <returns>The status in string format</returns>
        public string GetStatus(uint status)
        {
            if (Enum.IsDefined(typeof(RsvdStatus), status))
            {
                return(((RsvdStatus)status).ToString());
            }

            return(Smb2Status.GetStatusCode(status));
        }
        private void CheckNegotiateResponse(
            Packet_Header header,
            NEGOTIATE_Response response,
            DialectRevision clientMaxDialectSupported,
            EncryptionAlgorithm[] encryptionAlgs)
        {
            DialectRevision expectedDialect = clientMaxDialectSupported < TestConfig.MaxSmbVersionSupported
                        ? clientMaxDialectSupported : TestConfig.MaxSmbVersionSupported;

            BaseTestSite.Assert.AreEqual(
                Smb2Status.STATUS_SUCCESS,
                header.Status,
                "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
            BaseTestSite.Assert.AreEqual(expectedDialect, response.DialectRevision, "Selected dialect should be {0}", expectedDialect);

            if (expectedDialect >= DialectRevision.Smb311)
            {
                BaseTestSite.Assert.AreEqual(
                    PreauthIntegrityHashID.SHA_512,
                    client.SelectedPreauthIntegrityHashID,
                    "[MS-SMB2] 3.3.5.4 The server MUST set Connection.PreauthIntegrityHashId to one of the hash algorithms " +
                    "in the client's SMB2_PREAUTH_INTEGRITY_CAPABILITIES HashAlgorithms array.");

                if (encryptionAlgs != null)
                {
                    BaseTestSite.Assert.IsTrue(
                        TestConfig.SupportedEncryptionAlgorithmList.Contains(client.SelectedCipherID),
                        "[MS-SMB2] 3.3.5.4 The server MUST set Connection.CipherId to one of the ciphers in the client's " +
                        "SMB2_ENCRYPTION_CAPABILITIES Ciphers array in an implementation-specific manner.");
                }
                else
                {
                    BaseTestSite.Assert.AreEqual(
                        EncryptionAlgorithm.ENCRYPTION_NONE,
                        client.SelectedCipherID,
                        "[MS-SMB2] if client doesn't present SMB2_ENCRYPTION_CAPABILITIES context in negotiate request, " +
                        "server should not present this context in negotiate response.");
                }
            }
            else
            {
                // If server supported dialect version is lower than 3.11, server should ignore the negotiate contexts.
                BaseTestSite.Assert.AreEqual(
                    PreauthIntegrityHashID.HashAlgorithm_NONE,
                    client.SelectedPreauthIntegrityHashID,
                    "[MS-SMB2] The server must ignore the SMB2_PREAUTH_INTEGRITY_CAPABILITIES context if Connection.Dialect is less than 3.11. ");
                BaseTestSite.Assert.AreEqual(
                    EncryptionAlgorithm.ENCRYPTION_NONE,
                    client.SelectedCipherID,
                    "[MS-SMB2] The server must ignore the SMB2_ENCRYPTION_CAPABILITIES context if Connection.Dialect is less than 3.11. ");
            }

            CheckServerCapabilities(response);
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R QUERY DIRECTORY");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }

            return(sb.ToString());
        }
        public void Signing_VerifyAesGmacSigning()
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckSigning();
            #endregion

            var signingAlgorithms = new SigningAlgorithm[] { SigningAlgorithm.AES_GMAC };
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE with the Aes-GMAC signing algorithm and NEGOTIATE_SIGNING_REQUIRED.");
            client.NegotiateWithContexts(
                Packet_Header_Flags_Values.NONE,
                Smb2Utility.GetDialects(DialectRevision.Smb311),
                SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED,
                preauthHashAlgs: new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 },
                compressionFlags: SMB2_COMPRESSION_CAPABILITIES_Flags.SMB2_COMPRESSION_CAPABILITIES_FLAG_NONE,
                signingAlgorithms: signingAlgorithms,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "SUT MUST return STATUS_SUCCESS if the negotiation finished successfully.");
            });

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request and expects response.");
            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken,
                SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED);

            string uncSharepath =
                Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            uint treeId;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT to share: {0}", uncSharepath);
            client.TreeConnect(
                uncSharepath,
                out treeId,
                (Packet_Header header, TREE_CONNECT_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "TreeConnect should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));

                BaseTestSite.Assert.AreEqual(
                    Packet_Header_Flags_Values.FLAGS_SIGNED,
                    Packet_Header_Flags_Values.FLAGS_SIGNED & header.Flags,
                    "Server should set SMB2_FLAGS_SIGNED bit in the Flags field of the SMB2 header");
            });

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF");
            client.TreeDisconnect(treeId);
            client.LogOff();
        }
        private void PrepareFileForTrimming(out uint treeId, out FILEID fileId)
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_FILE_LEVEL_TRIM);
            #endregion

            string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            string fileName     = GetTestFileName(uncSharePath);
            string contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            smb2Functionalclient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

            uint status = smb2Functionalclient.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "CREATE should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));

                TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
            });

            status = smb2Functionalclient.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            status = smb2Functionalclient.TreeConnect(uncSharePath, out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            status = smb2Functionalclient.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);

            status = smb2Functionalclient.Write(treeId, fileId, contentWrite);

            status = smb2Functionalclient.Close(treeId, fileId);

            status = smb2Functionalclient.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);
        }
        /// <summary>
        /// Negotiate, SessionSetup, TreeConnect
        /// </summary>
        /// <returns>Return true for success, false for failure</returns>
        private void ConnectToShare(
            string sharename,
            DetectionInfo info,
            Smb2Client client,
            out ulong messageId,
            out ulong sessionId,
            out uint treeId)
        {
            Packet_Header      header;
            Guid               clientGuid;
            NEGOTIATE_Response negotiateResp;
            bool               encryptionRequired = false;

            UserLogon(info, client, out messageId, out sessionId, out clientGuid, out negotiateResp, out encryptionRequired);

            #region TreeConnect

            TREE_CONNECT_Response treeConnectResp;
            string uncSharePath = Smb2Utility.GetUncPath(info.targetSUT, sharename);
            logWriter.AddLog(DetectLogLevel.Information, "Client sends TreeConnect to server");
            if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) // When dialect is 3.11, TreeConnect must be signed or encrypted.
            {
                client.EnableSessionSigningAndEncryption(sessionId, true, encryptionRequired);
            }

            client.TreeConnect(
                1,
                1,
                (info.smb2Info.IsRequireMessageSigning || info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE,
                messageId++,
                sessionId,
                uncSharePath,
                out treeId,
                out header,
                out treeConnectResp);

            // When dialect is 3.11, for the messages other than TreeConnect, signing is not required.
            // Set it back to the configuration of the SUT.
            if (info.smb2Info.MaxSupportedDialectRevision == DialectRevision.Smb311)
            {
                client.EnableSessionSigningAndEncryption(sessionId, info.smb2Info.IsRequireMessageSigning, encryptionRequired);
            }

            if (header.Status != Smb2Status.STATUS_SUCCESS)
            {
                LogFailedStatus("TREECONNECT", header.Status);
                throw new Exception("TREECONNECT failed with " + Smb2Status.GetStatusCode(header.Status));
            }

            #endregion
        }
Beispiel #16
0
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R Lease Break NOTIFICATION");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", LeaseState was changed from " + PayLoad.CurrentLeaseState + " to " + PayLoad.NewLeaseState);
            }
            return(sb.ToString());
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R IOCTL");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", CtlCode=" + (CtlCode_Values)PayLoad.CtlCode);
            }
            return(sb.ToString());
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R TREE CONNECT");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", TreeId=" + string.Format("0x{0:x}", Header.TreeId));
            }
            return(sb.ToString());
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R WRITE");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", Written " + PayLoad.Count + " bytes");
            }
            return(sb.ToString());
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R READ");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", Read " + PayLoad.DataLength + " bytes");
            }
            return(sb.ToString());
        }
        public Smb2Info FetchSmb2Info(DetectionInfo info)
        {
            Smb2Info smb2Info = new Smb2Info();

            using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds)))
            {
                logWriter.AddLog(DetectLogLevel.Information, "Client connects to server");
                smb2Client.ConnectOverTCP(SUTIpAddress);

                DialectRevision    selectedDialect;
                byte[]             gssToken;
                Packet_Header      responseHeader;
                NEGOTIATE_Response responsePayload;
                ulong messageId = 1;
                logWriter.AddLog(DetectLogLevel.Information, "Client sends multi-protocol Negotiate to server");
                MultiProtocolNegotiate(
                    smb2Client,
                    0,
                    1,
                    Packet_Header_Flags_Values.NONE,
                    ref messageId,
                    info.requestDialect,
                    SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                    Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                    Guid.NewGuid(),
                    out selectedDialect,
                    out gssToken,
                    out responseHeader,
                    out responsePayload);

                if (responseHeader.Status != Smb2Status.STATUS_SUCCESS)
                {
                    LogFailedStatus("NEGOTIATE", responseHeader.Status);
                    throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(responseHeader.Status)));
                }

                smb2Info.MaxSupportedDialectRevision = responsePayload.DialectRevision;
                smb2Info.SupportedCapabilities       = (Capabilities_Values)responsePayload.Capabilities;
                smb2Info.SelectedCipherID            = smb2Client.SelectedCipherID;
                smb2Info.IsRequireMessageSigning     = responsePayload.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED);
            }

            FetchSmb2CompressionInfo(smb2Info);

            FetchSmb2EncryptionInfo(smb2Info);

            return(smb2Info);
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R CREATE");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", FileId=");
                sb.Append(PayLoad.FileId.ToString());
            }
            return(sb.ToString());
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("N Oplock Break Notification");
            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", FileId=");
                sb.Append(PayLoad.FileId.ToString());
                sb.Append(", OplockLevel=" + PayLoad.OplockLevel);
            }
            return(sb.ToString());
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("R SESSION_SETUP");

            if (Header.Status != 0) // Append error code if fail.
            {
                sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status));
            }
            else
            {
                sb.Append(", SessionFlags=" + PayLoad.SessionFlags);
                sb.Append(", SessionId=" + Header.SessionId);
            }
            return(sb.ToString());
        }
Beispiel #25
0
        public void BVT_SessionMgmt_Reauthentication()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE request.");
            client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);

            var credential = TestConfig.AccountCredential;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request with SESSION_ID set to ZERO.");
            client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, credential, TestConfig.UseServerGssToken);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends another SESSION-SETUP request for reauthentication.");
            client.SessionSetup(
                testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, // The second session setup should set signed flag if server supports signing to keep consistency with SDK.
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                credential,
                TestConfig.UseServerGssToken,
                SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                checker: (header, response) =>
            {
                // <225> Section 3.3.5.5: Windows Vista SP1 and Windows Server 2008 servers fail the session setup request with STATUS_REQUEST_NOT_ACCEPTED.
                if (TestConfig.Platform == Platform.WindowsServer2008)
                {
                    BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_REQUEST_NOT_ACCEPTED,
                                                 header.Status,
                                                 "Windows Vista SP1 and Windows Server 2008 should return STATUS_REQUEST_NOT_ACCEPTED. Actually it returns {0}.",
                                                 Smb2Status.GetStatusCode(header.Status));
                }
                else if (header.Status != Smb2Status.STATUS_SUCCESS)
                {
                    // 3.3.5.5   Receiving an SMB2 SESSION_SETUP Request
                    // 6.	If Session.State is Valid, the server SHOULD<225> process the session setup request as specified in section 3.3.5.5.2.
                    if (TestConfig.Platform == Platform.NonWindows)
                    {
                        BaseTestSite.Assert.Fail("Reauthentication is not supported in the server.");
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format("Unexpected status {0}", Smb2Status.GetStatusCode(header.Status)));
                    }
                }
            });
        }
        private void UpdateCounters(
            Guid logicalFlowId,
            Guid initiatorId,
            ulong ioCountIncrement,
            ulong normalizedIoCountIncrement,
            ulong latencyIncrement,
            ulong lowerLatencyIncrement,
            ulong bandwidthLimit,
            ulong kilobyteCountIncrement)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends an SQOS request to update counters to a logical flow and expects success");
            SqosResponsePacket sqosResponse;

            SqosRequestPacket sqosRequest = new SqosRequestPacket(TestConfig.SqosClientDialect == SQOS_PROTOCOL_VERSION.Sqos10 ? SqosRequestType.V10 : SqosRequestType.V11,
                                                                  (ushort)TestConfig.SqosClientDialect,
                                                                  SqosOptions_Values.STORAGE_QOS_CONTROL_FLAG_UPDATE_COUNTERS,
                                                                  logicalFlowId,
                                                                  TestConfig.SqosPolicyId,
                                                                  initiatorId,
                                                                  TestConfig.SqosInitiatorName,
                                                                  TestConfig.SqosInitiatorNodeName,
                                                                  0,
                                                                  0,
                                                                  ioCountIncrement,
                                                                  normalizedIoCountIncrement,
                                                                  latencyIncrement,
                                                                  lowerLatencyIncrement,
                                                                  bandwidthLimit,
                                                                  kilobyteCountIncrement
                                                                  );
            uint status = client.SendAndReceiveSqosPacket(
                sqosRequest,
                out sqosResponse);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Update counters should succeed, actual status: {0}",
                Smb2Status.GetStatusCode(status));
        }
        private void SetOrProbePolicy(Guid logicalFlowId, Guid initiatorId, bool setPolicy)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends an SQOS request to {0} policy to a logical flow and expects success", setPolicy ? "set" : "probe");
            SqosResponsePacket sqosResponse;
            SqosRequestPacket  sqosRequest = new SqosRequestPacket(TestConfig.SqosClientDialect == SQOS_PROTOCOL_VERSION.Sqos10 ? SqosRequestType.V10 : SqosRequestType.V11,
                                                                   (ushort)TestConfig.SqosClientDialect,
                                                                   setPolicy ? SqosOptions_Values.STORAGE_QOS_CONTROL_FLAG_SET_POLICY : SqosOptions_Values.STORAGE_QOS_CONTROL_FLAG_PROBE_POLICY,
                                                                   logicalFlowId,
                                                                   TestConfig.SqosPolicyId,
                                                                   initiatorId,
                                                                   TestConfig.SqosInitiatorName,
                                                                   TestConfig.SqosInitiatorNodeName);

            uint status = client.SendAndReceiveSqosPacket(
                sqosRequest,
                out sqosResponse);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "{0} policy should succeed, actual status: {1}",
                setPolicy ? "SetPolicy": "ProbePolicy",
                Smb2Status.GetStatusCode(status));
        }
Beispiel #28
0
        // [MS-SMB2] 3.3.5.9   Receiving an SMB2 CREATE Request
        // If the request received has SMB2_FLAGS_DFS_OPERATIONS set in the Flags field of the SMB2 header, and TreeConnect.Share.IsDfs is TRUE, the server MUST verify the value of IsDfsCapable:
        // If IsDfsCapable is TRUE, the server MUST invoke the interface defined in [MS-DFSC] section 3.2.4.1 to normalize the path name by supplying the target path name.

        // [MS-DFSC] 3.2.4.1   Handling a Path Normalization Request
        // As specified in [MS-SMB2] section 3.3.5.9 and [MS-SMB] section 3.3.5.5, the SMB server invokes the DFS server to normalize the path name.
        // When DFS server matches the path name against DFS metadata:
        // If the path matches or contains a DFS link, the DFS server MUST respond to the path normalization request with STATUS_PATH_NOT_COVERED,
        //     indicating to the client to resolve the path by using a DFS link referral request.
        // Otherwise, the DFS server MUST change the path name to a path relative to the root of the namespace and return STATUS_SUCCESS.
        private void PathNormalize(bool containDFSLink)
        {
            smb2client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            smb2client.ConnectToServerOverTCP(TestConfig.SutIPAddress);
            smb2client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            smb2client.SessionSetup(TestConfig.DefaultSecurityPackage,
                                    TestConfig.SutComputerName,
                                    TestConfig.AccountCredential,
                                    TestConfig.UseServerGssToken);

            string dfsRootShare = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.StandaloneNamespace);

            smb2client.TreeConnect(dfsRootShare, out treeId);
            Smb2CreateContextResponse[] contextResp;

            // [MS-SMB2] 2.2.13   SMB2 CREATE Request
            // If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of the SMB2 header,
            // the file name can be prefixed with DFS link information that will be removed during DFS name normalization as specified in section 3.3.5.9.
            string fileName = dfsRootShare + @"\";

            fileName += containDFSLink ? (TestConfig.DFSLink + @"\") : "";
            fileName += "PathNormalization_" + Guid.NewGuid();

            this.AddTestFileName(dfsRootShare, fileName);

            if (containDFSLink)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SMB2 create request to open a file in a DFS path contains DFS Link.");
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SMB2 create request to open a file in a DFS path does not contain DFS Link.");
            }

            uint status = smb2client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                Packet_Header_Flags_Values.FLAGS_DFS_OPERATIONS | Packet_Header_Flags_Values.FLAGS_SIGNED,
                out fileId,
                out contextResp,
                checker: (header, response) =>
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server response.");
                if (containDFSLink)
                {
                    BaseTestSite.Assert.AreEqual(
                        (uint)NtStatus.STATUS_PATH_NOT_COVERED,
                        header.Status,
                        "DFS server matches the path name against DFS metadata. If the path matches or contains a DFS link, " +
                        "the DFS server MUST respond to the path normalization request with STATUS_PATH_NOT_COVERED, indicating to the client to resolve the path by using a DFS link referral request");
                }
                else
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "The DFS server MUST change the path name to a path relative to the root of the namespace and return STATUS_SUCCESS, actual status is {0}", Smb2Status.GetStatusCode(header.Status));
                }
            });
        }
        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();
        }
        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();
        }