Esempio n. 1
0
        public void BVT_Signing()
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb2002);
            testConfig.CheckServerEncrypt();
            TestConfig.CheckSigning();
            #endregion

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE request with NEGOTIATE_SIGNING_REQUIRED flag set.");
            client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request with NEGOTIATE_SIGNING_REQUIRED flag set.");
            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken,
                SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED);

            string uncSharepath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            uint   treeId;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request.");
            client.TreeConnect(
                uncSharepath,
                out treeId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF");
            client.TreeDisconnect(treeId);
            client.LogOff();
        }
        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. 3
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
        }
Esempio n. 4
0
        /// <summary>
        /// Determine if a share has shi*_type set to STYPE_CLUSTER_SOFS
        /// </summary>
        /// <param name="server">Server of the share</param>
        /// <param name="sharePath">Path of the share</param>
        /// <returns>Return true if share has shi*_type set to STYPE_CLUSTER_SOFS, otherwise return false</returns>
        private bool ShareContainsSofs(string server, string sharePath)
        {
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            client.ConnectToServerOverTCP(SWNTestUtility.GetCurrentAccessIP(server));

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

            client.SessionSetup(TestConfig.DefaultSecurityPackage, server, TestConfig.AccountCredential, false);

            uint treeId;
            bool ret = false;

            client.TreeConnect(sharePath, out treeId,
                               (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful.", header.Command);

                ret = response.Capabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_SCALEOUT);
            });

            client.TreeDisconnect(treeId);

            client.LogOff();

            client.Disconnect();

            return(ret);
        }
        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();
        }
Esempio n. 6
0
        protected _SECURITY_DESCRIPTOR QuerySecurityDescriptor(string sharePath, string fileName, AdditionalInformation_Values securityAttributesToQuery)
        {
            Smb2FunctionalClient clientAdmin;

            clientAdmin = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientAdmin.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            uint treeId;

            ConnectToShare(clientAdmin, TestConfig.AccountCredential, sharePath, out treeId);

            FILEID fileId;

            Smb2CreateContextResponse[] createContextResponses;
            clientAdmin.Create(treeId,
                               fileName,
                               fileName == null ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                               out fileId,
                               out createContextResponses,
                               accessMask: AccessMask.READ_CONTROL | AccessMask.WRITE_DAC | AccessMask.FILE_READ_ATTRIBUTES,
                               shareAccess: ShareAccess_Values.FILE_SHARE_DELETE | ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE,
                               createDisposition: CreateDisposition_Values.FILE_OPEN);
            _SECURITY_DESCRIPTOR sd;

            clientAdmin.QuerySecurityDescriptor(treeId, fileId, securityAttributesToQuery, out sd);
            clientAdmin.Close(treeId, fileId);
            clientAdmin.TreeDisconnect(treeId);
            clientAdmin.LogOff();
            clientAdmin.Disconnect();
            return(sd);
        }
Esempio n. 7
0
        public override void Reset()
        {
            if (testClient != null)
            {
                try
                {
                    testClient.Close(treeId, fileId);
                    testClient.TreeDisconnect(treeId);
                    testClient.LogOff();

                    testClient.Disconnect();
                }
                catch
                {
                }
                finally
                {
                    testClient = null;
                }
            }

            try
            {
                sutProtocolController.DeleteFile(uncSharePath, fileName);
            }
            catch
            {
            }

            base.Reset();
        }
Esempio n. 8
0
        /// <summary>
        /// Get share capabilities
        /// </summary>
        /// <param name="server">The host node</param>
        /// <param name="sharePath">The path to the share</param>
        /// <param name="flags">Tree Connect flag</param>
        /// <returns>Share capabilities</returns>
        private Share_Capabilities_Values GetShareCapabilities(string server, string sharePath, TreeConnect_Flags flags = TreeConnect_Flags.SMB2_SHAREFLAG_NONE)
        {
            IPAddress shareIpAddr = Dns.GetHostEntry(server).AddressList[0];

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

            client.ConnectToServer(TestConfig.UnderlyingTransport, server, shareIpAddr);
            client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            client.SessionSetup(TestConfig.DefaultSecurityPackage, server, TestConfig.AccountCredential, false);
            Share_Capabilities_Values shareCaps = Share_Capabilities_Values.NONE;
            uint treeId;
            uint status = client.TreeConnect(
                sharePath,
                out treeId,
                (header, response) =>
            {
                shareCaps = response.Capabilities;
            },
                flags);

            if (status == Smb2Status.STATUS_SUCCESS)
            {
                client.TreeDisconnect(treeId);
            }
            client.LogOff();
            client.Disconnect();
            return(shareCaps);
        }
        /// <summary>
        /// Create or delete a file or directory with a given name.
        /// </summary>
        /// <param name="client">the functional client used to create</param>
        /// <param name="isDirectory">true for file and false for directory</param>
        /// <param name="isDeleteFlagSet">true for delete flag set</param>
        /// <param name="isNonAdmin">true for non admin account credential</param>
        /// <param name="fileNametype">the file name type: ValidFileName, SymbolicLinkInMiddle, SymbolicLinkAtLast, InvalidSymbolicLink</param>
        /// <param name="isValidAccessMask">true for valid access mask, which should contain DELETE or GENERIC_ALL</param>
        private void OperateFileOrDirectory(Smb2FunctionalClient client, bool isDirectory, bool isDeleteFlagSet, bool isNonAdmin, FileNameType fileNameType, bool isValidAccessMask)
        {
            CreateOptions_Values     createOption;
            CreateDisposition_Values createDisposition;

            if (isDirectory)
            {
                createOption = CreateOptions_Values.FILE_DIRECTORY_FILE;
            }
            else
            {
                createOption = CreateOptions_Values.FILE_NON_DIRECTORY_FILE;
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT.");
            client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            AccountCredential accountCredential = isNonAdmin ? TestConfig.NonAdminAccountCredential : TestConfig.AccountCredential;

            client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, accountCredential, false);
            uint treeId;

            client.TreeConnect(sharePath, out treeId);
            FILEID fileId;

            Smb2CreateContextResponse[] createContextResponse;

            AccessMask accessMask = AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE;

            accessMask = isValidAccessMask ? accessMask : AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE;
            // The delete flag is set in the following situations: 1. Delete an existed file; 2. Test CreateOptions_Values.FILE_DELETE_ON_CLOSE combined with DesiredAccess
            createOption = isDeleteFlagSet ? (createOption | CreateOptions_Values.FILE_DELETE_ON_CLOSE) : createOption;
            // The createDisposition is set to FILE_OPEN if the file already existed; else, if it's the first time to create a file, this field should be set to FILE_CREATE
            createDisposition = (fileNameType == FileNameType.ExistedValidFileName) ? CreateDisposition_Values.FILE_OPEN : CreateDisposition_Values.FILE_CREATE;
            fileName          = GetFileName(isDirectory, fileNameType);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with create option: {0} and create disposition: {1}", createOption, createDisposition);
            uint status = client.Create(
                treeId,
                fileName,
                createOption,
                out fileId,
                out createContextResponse,
                accessMask: accessMask,
                createDisposition: createDisposition,
                checker: (header, response) =>
            {
                CheckCreateResponse(isNonAdmin, createOption, accessMask, header, response, fileNameType);
            });

            AddTestFileName(sharePath, fileName);

            if (status == Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF.");
                client.Close(treeId, fileId);
            }

            client.TreeDisconnect(treeId);
            client.LogOff();
        }
        private void ClientTearDown(Smb2FunctionalClient client, uint treeId, FILEID fileId)
        {
            status = client.Close(treeId, fileId);

            status = client.TreeDisconnect(treeId);

            status = client.LogOff();
        }
 private void TearDownClient(Smb2FunctionalClient client, uint clientTreeId, FILEID clientFileId)
 {
     if (ClientTreeConnectSessionExists(clientTreeId))
     {
         client.Close(clientTreeId, clientFileId);
         client.TreeDisconnect(clientTreeId);
         client.LogOff();
     }
 }
        private bool ConnectToShare(string uncSharePath, out uint treeId)
        {
            treeId = 0;

            string serverName = Smb2Utility.GetServerName(uncSharePath);
            var    serverIPs  = Dns.GetHostEntry(serverName).AddressList;

            if (serverIPs == null || serverIPs.Length == 0)
            {
                return(false);
            }

            uint status = 0;

            foreach (var ip in serverIPs) // Try to connect to each IP since not all of them can be connected successfully.
            {
                try
                {
                    client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, Site);
                    client.ConnectToServer(Smb2TransportType.Tcp, serverName, ip);
                    status = client.Negotiate(
                        Smb2Utility.GetDialects(testConfig.MaxSmbVersionSupported),
                        true,
                        checker: (header, response) => { });
                    if (status != Smb2Status.STATUS_SUCCESS)
                    {
                        continue;
                    }

                    status = client.SessionSetup(testConfig.DefaultSecurityPackage, serverName, testConfig.AccountCredential, false, checker: (header, response) => { });
                    if (status != Smb2Status.STATUS_SUCCESS)
                    {
                        client.Disconnect();
                        continue;
                    }

                    status = client.TreeConnect(uncSharePath, out treeId, checker: (header, response) => { });
                    if (status == Smb2Status.STATUS_SUCCESS)
                    {
                        return(true);
                    }
                    else
                    {
                        client.LogOff();
                        client.Disconnect();
                    }
                }
                catch
                {
                    // Catch the exceptions thrown in Negotiage/SessionSetup/TreeConnect
                    // Try next IP
                }
            }

            return(false);
        }
 private void DisconnectToShare(uint treeId, FILEID fileId)
 {
     if (fileId.Persistent != 0 || fileId.Volatile != 0)
     {
         client.Close(treeId, fileId);
     }
     client.TreeDisconnect(treeId);
     client.LogOff();
     client.Disconnect();
 }
Esempio n. 14
0
        protected bool TryReadFile(Smb2FunctionalClient client, AccountCredential user, string sharePath, string fileName)
        {
            bool accessSucceed = true;

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends NEGOTIATE message.");
            client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends SESSION_SETUP message using account: {0}@{1}.", user.AccountName, user.DomainName);
            client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, user, false);

            uint treeId;

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends TREE_CONNECT message to access share: {0}.", sharePath);
            client.TreeConnect(sharePath, out treeId);

            FILEID fileId;

            Smb2CreateContextResponse[] createContexResponse;

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends CREATE request.");
            uint status = client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out createContexResponse,
                accessMask: AccessMask.FILE_READ_DATA | AccessMask.FILE_READ_ATTRIBUTES,
                createDisposition: CreateDisposition_Values.FILE_OPEN,
                checker: (header, response) =>
            {
                if (header.Status == Smb2Status.STATUS_SUCCESS)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Successfully opened the file with Access Mask: FILE_READ_DATA | FILE_READ_ATTRIBUTES.");
                    accessSucceed = true;
                }
                else if (header.Status == Smb2Status.STATUS_ACCESS_DENIED)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Fail to open the file with Access Mask: FILE_READ_DATA | FILE_READ_ATTRIBUTES.");
                    accessSucceed = false;
                }
                else
                {
                    BaseTestSite.Assert.Fail("Unexpected error code in CREATE response: {0}", Smb2Status.GetStatusCode(header.Status));
                }
            });

            if (status == Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF.");
                client.Close(treeId, fileId);
            }
            client.TreeDisconnect(treeId);
            client.LogOff();
            return(accessSucceed);
        }
        public void BVT_FileLevelTrim()
        {
            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       = 0;
            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) => BaseTestSite.Assert.AreEqual(
                    true,
                    header.Status == Smb2Status.STATUS_SUCCESS || header.Status == Smb2Status.STATUS_NO_RANGES_PROCESSED,
                    // The operation was successful, but no range was processed.
                    "{0} should complete with STATUS_SUCCESS or STATUS_NO_RANGES_PROCESSED, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)));

            if (status != Smb2Status.STATUS_NO_RANGES_PROCESSED && // Skip parsing the response when server returns STATUS_NO_RANGES_PROCESSED
                respOutput != null)    // Skip parsing the response if no output buffer is returned
            {
                FSCTL_FILE_LEVEL_TRIM_OUTPUT fileLevelTrimOutput = TypeMarshal.ToStruct <FSCTL_FILE_LEVEL_TRIM_OUTPUT>(respOutput);
                BaseTestSite.Log.Add(
                    LogEntryKind.Debug,
                    "Number of ranges that were processed: {0}", fileLevelTrimOutput.NumRangesProcessed);
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "No range was processed during this operation.");
            }

            status = client.Close(treeId, fileId);

            status = client.TreeDisconnect(treeId);

            status = client.LogOff();
        }
        private void Compound_RelatedRequests(string fileName, bool isEncrypted)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Initialize the test client.");
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            uint treeId;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Connect to the SMB2 basic share by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT.");
            ConnectToShare(client, out treeId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct Create packet.");
            Smb2CreateRequestPacket createPacket = ConstructCreatePacket(client.SessionId, treeId, fileName);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct Write packet, flag FLAGS_RELATED_OPERATIONS is set.");
            Smb2WriteRequestPacket writePacket = ConstructRelatedWritePacket();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct Close packet, flag FLAGS_RELATED_OPERATIONS is set.");
            Smb2CloseRequestPacket closePacket = ConstructRelatedClosePacket();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send {0}compounded Create, Write and Close requests to SUT.", isEncrypted ? "encrypted " : "");
            List <Smb2SinglePacket> requestPackets = new List <Smb2SinglePacket>();

            requestPackets.Add(createPacket);
            requestPackets.Add(writePacket);
            requestPackets.Add(closePacket);

            if (isEncrypted)
            {
                // Enable encryption
                client.EnableSessionSigningAndEncryption(enableSigning: testConfig.SendSignedRequest, enableEncryption: true);
            }
            List <Smb2SinglePacket> responsePackets = client.SendAndReceiveCompoundPacket(requestPackets);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify responses to the compounded request.");
            foreach (var responsePacket in responsePackets)
            {
                if (TestConfig.Platform == Platform.WindowsServer2016 && responsePacket.Header.Status != Smb2Status.STATUS_SUCCESS)
                {
                }
                else
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        responsePacket.Header.Status,
                        "{0} should succeed, actual status is {1}", responsePacket.Header.Command, Smb2Status.GetStatusCode(responsePacket.Header.Status));
                }
            }

            client.TreeDisconnect(treeId);
            client.LogOff();
            client.Disconnect();
        }
        public void InvalidCreateRequestStructureSize()
        {
            uint status;

            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, this.Site);
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

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

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

            uint treeId;

            status = client1.TreeConnect(uncSharePath, out treeId);
            string fileName = "BVT_SMB2Basic_InvalidCreateRequestStructureSize" + Guid.NewGuid();

            FILEID fileID;

            Smb2CreateContextResponse[] serverCreateContexts;

            // [MS-SMB2] Section 2.2.13 SMB2 CREATE Request
            // StructureSize (2 bytes):  The client MUST set this field to 57, indicating the size of the request structure, not including the header.
            // The client MUST set it to this value regardless of how long Buffer[] actually is in the request being sent.

            // So set the StuctureSize to 58 here to make "the size of the SMB2 CREATE Request is less than specified in the StructureSize field".
            client1.BeforeSendingPacket(ReplacePacketByStructureSize);
            status = client1.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileID,
                out serverCreateContexts,
                checker: (header, response) => { });

            BaseTestSite.Assert.AreEqual(
                Smb2Status.STATUS_INVALID_PARAMETER,
                status,
                "The size of the SMB2 CREATE Request (excluding the SMB2 header) is less than specified in the StructureSize field, then the request MUST be failed with STATUS_ INVALID_PARAMETER");

            client1.TreeDisconnect(treeId);
            client1.LogOff();
        }
        public void Send_Multiple_Requests()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Initialize the test client.");
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            uint treeId;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Connect to the SMB2 basic share by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT.");
            ConnectToShare(client, out treeId);

            List <Smb2SinglePacket> requestPackets = new List <Smb2SinglePacket>();

            for (int i = 1; i <= 10; i++)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct the {0} Create packet.", i);
                string fileName = string.Format("FileNew_{0}_{1}.txt", i, Guid.NewGuid());

                Task <Smb2CreateRequestPacket> t1 = Task <Smb2CreateRequestPacket> .Factory.StartNew(() =>
                                                                                                     ConstructCreatePacket(client.SessionId, treeId, fileName));

                requestPackets.Add(t1.Result);
            }

            client.EnableSessionSigningAndEncryption(enableSigning: testConfig.SendSignedRequest, enableEncryption: false);

            Task <List <ulong> > sendRequest = Task <List <ulong> > .Factory.StartNew(() => client.SendCompoundPacket(requestPackets));

            List <Smb2SinglePacket> responsePackets = client.ReceiveCompoundPacket(sendRequest.Result);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify responses to the compounded request.");
            foreach (var responsePacket in responsePackets)
            {
                if (TestConfig.Platform == Platform.WindowsServer2016 && responsePacket.Header.Status != Smb2Status.STATUS_SUCCESS)
                {
                }
                else
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        responsePacket.Header.Status,
                        "{0} should succeed, actual status is {1}", responsePacket.Header.Command, Smb2Status.GetStatusCode(responsePacket.Header.Status));
                }
            }

            client.TreeDisconnect(treeId);
            client.LogOff();
            client.Disconnect();
        }
        public override void Reset()
        {
            try
            {
                testClient.LogOff();
                testClient.Disconnect();
            }
            catch
            {
            }
            finally
            {
                testClient = null;
            }

            base.Reset();
        }
Esempio n. 20
0
        private void SMB2CompressionTest(CompressionAlgorithm[] compressionAlgorithms, bool enableEncryption, CompressionTestVariant variant)
        {
            uint   treeId;
            FILEID fileId;

            CreateTestFile(compressionAlgorithms, enableEncryption, out treeId, out fileId);

            var instances = CompressionTestRunner.Generate(variant);

            foreach (var instance in instances)
            {
                instance.Run(client, treeId, fileId);
            }

            client.Close(treeId, fileId);
            client.TreeDisconnect(treeId);
            client.LogOff();
        }
        protected override void TestCleanup()
        {
            if (client != null)
            {
                try
                {
                    client.Close(treeId, fileId);
                    client.TreeDisconnect(treeId);
                    client.LogOff();
                    client.Disconnect();
                }
                catch (Exception ex)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Unexpected exception when disconnect client: {0}", ex.ToString());
                }
            }

            base.TestCleanup();
        }
Esempio n. 22
0
        protected override void TestCleanup()
        {
            if (smb2client != null)
            {
                if (!fileId.Equals(FILEID.Invalid) && treeId != 0xFFFF)
                {
                    smb2client.Close(treeId, fileId, (header, response) => { });
                }

                if (treeId != 0xFFFF)
                {
                    smb2client.TreeDisconnect(treeId, (header, response) => { });
                }

                smb2client.LogOff((header, response) => { });
                smb2client.Disconnect();
            }

            base.TestCleanup();
        }
        private void PrepareTestFile()
        {
            uint treeId;
            Smb2FunctionalClient client = InitializeClient(testConfig.ScaleOutFileServerIP1, out treeId);

            // Initialize file name
            fileName = "ConflictModel_" + Guid.NewGuid() + ".txt";
            FILEID fileId;
            Smb2CreateContextResponse[] contexts;
            client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out contexts);
            client.Write(treeId, fileId, Smb2Utility.CreateRandomString(DEFAULT_WRITE_BUFFER_SIZE_IN_KB));
            client.Close(treeId, fileId);
            client.LogOff();
            client.Disconnect();
        }
Esempio n. 24
0
        private void Compound_UnrelatedRequests(string firstFileName, string secondFileName, bool isEncrypted)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Initialize the test client.");
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            uint treeId;

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Connect to the SMB2 basic share by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT.");
            ConnectToShare(client, out treeId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct the first Create packet.");
            Smb2CreateRequestPacket firstCreatePacket = ConstructCreatePacket(client.SessionId, treeId, firstFileName);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct the second Create packet.");
            Smb2CreateRequestPacket secondCreatePacket = ConstructCreatePacket(client.SessionId, treeId, secondFileName);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send the two {0}compounded Create packets to SUT.", isEncrypted ? "encrypted " : "");
            List <Smb2SinglePacket> requestPackets = new List <Smb2SinglePacket>();

            requestPackets.Add(firstCreatePacket);
            requestPackets.Add(secondCreatePacket);

            if (isEncrypted)
            {
                // Enable encryption
                client.EnableSessionSigningAndEncryption(enableSigning: testConfig.SendSignedRequest, enableEncryption: true);
            }
            List <Smb2SinglePacket> responsePackets = client.SendAndReceiveCompoundPacket(false, requestPackets);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify responses to the compounded request.");
            foreach (var responsePacket in responsePackets)
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    responsePacket.Header.Status,
                    "{0} should succeed, actual status is {1}", responsePacket.Header.Command, Smb2Status.GetStatusCode(responsePacket.Header.Status));
            }

            client.TreeDisconnect(treeId);
            client.LogOff();
            client.Disconnect();
        }
Esempio n. 25
0
        protected bool ShareExists(AccountCredential user, string sharePath)
        {
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Test whether the specific share exists: {0}", sharePath);
            Smb2FunctionalClient clientAdmin;

            clientAdmin = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientAdmin.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            uint treeId;
            bool connected = ConnectToShare(clientAdmin, user, sharePath, out treeId);

            if (connected)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Share exists: {0}", sharePath);
                clientAdmin.TreeDisconnect(treeId);
                clientAdmin.LogOff();
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Share does not exist: {0}", sharePath);
            }
            clientAdmin.Disconnect();
            return(connected);
        }
Esempio n. 26
0
        public override void Reset()
        {
            if (testClient != null)
            {
                try
                {
                    testClient.Close(treeId, fileId);
                    testClient.TreeDisconnect(treeId);
                    testClient.LogOff();

                    testClient.Disconnect();
                }
                catch
                {
                }
                finally
                {
                    testClient = null;
                }
            }

            base.Reset();
        }
Esempio n. 27
0
        public void BVT_SessionMgmt_ReconnectSessionSetup()
        {
            Guid clientGuid = (TestConfig.RequestDialects.Length == 1 && TestConfig.RequestDialects[0] == DialectRevision.Smb2002) ? Guid.Empty : Guid.NewGuid();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a first client by sending NEGOTIATE request.");
            client.Negotiate(TestConfig.RequestDialects,
                             TestConfig.IsSMB1NegotiateEnabled,
                             SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                             null, // capability value will be set inside the method according to requested dialects.
                             clientGuid);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends SESSION_SETUP request with SESSION_ID set to ZARO.");
            client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken);

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

            #region Reconnect and Do Session Setup with PreviousSessionId set.
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a second client by sending NEGOTIATE request.");
            Smb2FunctionalClient client2 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            client2.Negotiate(TestConfig.RequestDialects,
                              TestConfig.IsSMB1NegotiateEnabled,
                              SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                              null, // capability value will be set inside the method according to requested dialects.
                              clientGuid);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The second client sends SESSION_SETUP request with SESSION_ID set to the value in the previous SESSION_SETUP response.");
            client2.ReconnectSessionSetup(client, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            #endregion

            #region Tear Down Client
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: LOG_OFF; DISCONNECT");
            client2.LogOff();
            client2.Disconnect();
            #endregion
        }
        public void Write_Data_To_File()
        {
            uint treeId;

            try
            {
                Smb2FunctionalClient client = InitializeClient(TestConfig.SutIPAddress, out treeId);

                // Initialize file name
                fileName = "ConflictModel_" + Guid.NewGuid() + ".txt";
                FILEID fileId;
                Smb2CreateContextResponse[] contexts;

                client.Create(
                    treeId,
                    fileName,
                    CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    out fileId,
                    out contexts);
                //client.Write(treeId, fileId, Smb2Utility.CreateRandomString(DEFAULT_WRITE_BUFFER_SIZE_IN_KB));

                client.Write(treeId, fileId, "this is a random string");
                client.Write(treeId, fileId, "this is a random string2");

                client.Close(treeId, fileId);

                client.LogOff();

                client.Disconnect();
            }
            catch (Exception ex)
            {
                File.AppendAllText(@"C:\Code\error.txt", ex.Message);
                File.AppendAllText(@"C:\Code\error.txt", ex.StackTrace);
                //throw;
            }
        }
        protected override void TestCleanup()
        {
            // The persistent handle requested by the clientBeforeDisconnect needs to be closed t make sure that server will not preserve the handle.
            // Or else others test cases execution will be affected
            if (clientBeforeDisconnect != null)
            {
                try
                {
                    clientBeforeDisconnect.Close(treeIdBeforeDisconnect, fileIdBeforeDisconnect);
                    clientBeforeDisconnect.TreeDisconnect(treeIdBeforeDisconnect);
                    clientBeforeDisconnect.LogOff();
                    clientBeforeDisconnect.Disconnect();
                }
                catch (Exception ex)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Unexpected exception when release clientBeforeDisconnect: {0}", ex.ToString());
                }
            }

            if (clientAfterDisconnect != null)
            {
                try
                {
                    clientAfterDisconnect.Close(treeIdBeforeDisconnect, fileIdBeforeDisconnect);
                    clientAfterDisconnect.TreeDisconnect(treeIdBeforeDisconnect);
                    clientAfterDisconnect.LogOff();
                    clientAfterDisconnect.Disconnect();
                }
                catch (Exception ex)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Unexpected exception when release clientAfterDisconnect: {0}", ex.ToString());
                }
            }

            base.TestCleanup();
        }
        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 for notification arrival
                    notificationReceived.WaitOne(TestConfig.WaitTimeoutInMilliseconds),
                    "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);
        }
        private void CreateFile(string uncShare, string fileName, int lengthInByte)
        {
            Site.Log.Add(
                LogEntryKind.Debug,
                "Create file {0} in share {1}", fileName, uncShare);

            Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            client.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);

            client.CreditGoal = 32;

            client.Negotiate(
                new DialectRevision[] { ModelUtility.GetDialectRevision(config.MaxSmbVersionSupported) },
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_LARGE_MTU);

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

            uint tId;
            client.TreeConnect(
                uncShare,
                out tId);

            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fId;
            client.Create(
                tId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fId,
                out serverCreateContexts);

            string content;
            if (isMultiCreditSupportedOnConnection)
            {
                content = Smb2Utility.CreateRandomStringInByte(lengthInByte);
                client.Write(tId, fId, content);
            }
            else
            {
                // Write several times if server does not support multi credit
                int writeTimes = lengthInByte / (64 * 1024);
                int rest = lengthInByte % (64 * 1024);
                ulong offset = 0;

                for (int time = 0; time < writeTimes; time++)
                {
                    content = Smb2Utility.CreateRandomString(64);
                    client.Write(tId, fId, content, offset);
                    offset += 64 * 1024;
                }

                if (rest != 0)
                {
                    content = Smb2Utility.CreateRandomStringInByte(rest);
                    client.Write(tId, fId, content, offset);
                }
            }

            client.Close(tId, fId);

            client.TreeDisconnect(tId);

            client.LogOff();

            client.Disconnect();

            Site.Log.Add(
                LogEntryKind.Debug,
                "Create file {0} in share {1}", fileName, uncShare);
        }
        /// <summary>
        /// Determine if a share has shi*_type set to STYPE_CLUSTER_SOFS
        /// </summary>
        /// <param name="server">Server of the share</param>
        /// <param name="sharePath">Path of the share</param>
        /// <returns>Return true if share has shi*_type set to STYPE_CLUSTER_SOFS, otherwise return false</returns>
        private bool ShareContainsSofs(string server, string sharePath)
        {
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);

            client.ConnectToServerOverTCP(SWNTestUtility.GetCurrentAccessIP(server));

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

            client.SessionSetup(TestConfig.DefaultSecurityPackage, server, TestConfig.AccountCredential, false);

            uint treeId;
            bool ret = false;
            client.TreeConnect(sharePath, out treeId,
                (header, response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should be successful.", header.Command);

                    ret = response.Capabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_SCALEOUT);
                });

            client.TreeDisconnect(treeId);

            client.LogOff();

            client.Disconnect();

            return ret;
        }
 protected bool ShareExists(AccountCredential user, string sharePath)
 {
     BaseTestSite.Log.Add(LogEntryKind.Debug, "Test whether the specific share exists: {0}", sharePath);
     Smb2FunctionalClient clientAdmin;
     clientAdmin = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
     clientAdmin.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
     uint treeId;
     bool connected = ConnectToShare(clientAdmin, user, sharePath, out treeId);
     if (connected)
     {
         BaseTestSite.Log.Add(LogEntryKind.Debug, "Share exists: {0}", sharePath);
         clientAdmin.TreeDisconnect(treeId);
         clientAdmin.LogOff();
     }
     else
     {
         BaseTestSite.Log.Add(LogEntryKind.Debug, "Share does not exist: {0}", sharePath);
     }
     clientAdmin.Disconnect();
     return connected;
 }
        public void ReconnectSharedVHDWithoutDeviceContext()
        {
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "1.	Client opens a shared virtual disk file with SMB2 create contexts " +
                "SVHDX_OPEN_DEVICE_CONTEXT and SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 (persistent bit is set). ");

            Smb2FunctionalClient clientBeforeDisconnect = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            uint treeId;
            Guid clientGuid = Guid.NewGuid();
            ConnectToShare(clientBeforeDisconnect, clientGuid, TestConfig.FullPathShareContainingSharedVHD, out treeId);

            Guid createGuid = Guid.NewGuid();
            Guid initiatorId = Guid.NewGuid();
            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileIdBeforeDisconnect;
            clientBeforeDisconnect.Create
                (treeId,
                TestConfig.NameOfSharedVHDX + fileNameSuffix,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnect,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                new Smb2CreateContextRequest[]
                {
                    new Smb2CreateSvhdxOpenDeviceContext
                    {
                        Version = (uint)RSVD_PROTOCOL_VERSION.RSVD_PROTOCOL_VERSION_1,
                        OriginatorFlags = (uint)OriginatorFlag.SVHDX_ORIGINATOR_PVHDPARSER,
                        InitiatorHostName = TestConfig.InitiatorHostName,
                        InitiatorHostNameLength = (ushort)(TestConfig.InitiatorHostName.Length * 2),  // InitiatorHostName is a null-terminated Unicode UTF-16 string
                        InitiatorId = initiatorId
                    },
                    new Smb2CreateDurableHandleRequestV2
                    {
                        CreateGuid = createGuid,
                        Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT
                    }
                });

            bool persistentHandleReturned = false;
            if (serverCreateContexts != null && serverCreateContexts[0] is Smb2CreateDurableHandleResponseV2)
            {
                var durableResponse = serverCreateContexts[0] as Smb2CreateDurableHandleResponseV2;
                if (durableResponse.Flags.HasFlag(CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT))
                {
                    persistentHandleReturned = true;
                }
            }

            BaseTestSite.Assert.IsTrue(persistentHandleReturned, "Server should return a persistent handle.");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "2.	Client disconnects from the server.");
            clientBeforeDisconnect.Disconnect();

            Smb2FunctionalClient clientAfterDisconnect = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            ConnectToShare(clientAfterDisconnect, clientGuid, TestConfig.FullPathShareContainingSharedVHD, out treeId);
            FILEID fileIdAfterDisconnect;
            uint status = clientAfterDisconnect.Create
                (treeId,
                TestConfig.NameOfSharedVHDX + fileNameSuffix,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnect,
                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 = fileIdBeforeDisconnect.Persistent }
                    }
                },
                checker: (header, response) => { });

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "3. Client reconnects the persistent handle without create context SVHDX_OPEN_DEVICE_CONTEXT and expects success. Actual status is: {0}",
                GetStatus(status));

            clientAfterDisconnect.Close(treeId, fileIdAfterDisconnect);
            clientAfterDisconnect.TreeDisconnect(treeId);
            clientAfterDisconnect.LogOff();
            clientAfterDisconnect.Disconnect();
        }
        public void ReconnectOpenRequest(
            DurableV1ReconnectContext durableV1ReconnectContext,
            DurableV2ReconnectContext durableV2ReconnectContext,
            OplockLeaseType oplockLeaseType,
            LeaseKeyDifferentialType leaseKeyDifferentialType,
            ClientIdType clientIdType,
            CreateGuidType createGuidType)
        {
            if ((oplockLeaseType == OplockLeaseType.LeaseV1 || oplockLeaseType == OplockLeaseType.LeaseV2)
                && !testConfig.IsLeasingSupported)
                Site.Assert.Inconclusive("Test case is applicable in servers that support leasing.");

            bool isSameLeaseKey = (leaseKeyDifferentialType == LeaseKeyDifferentialType.SameLeaseKey);
            bool isSameClient = (clientIdType == ClientIdType.SameClient);
            bool isSameCreateGuid = (createGuidType == CreateGuidType.SameCreateGuid);

            FILEID fileIdAfterDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts;
            IPAddress targetIPAddress;
            string targetServer;
            string targetShare;

            #region Construct Create Contexts
            Smb2CreateContextRequest[] smb2CreateContextRequest = GetOpenFileCreateContext(
                DurableV1RequestContext.DurableV1RequestContextNotExist,
                DurableV2RequestContext.DurableV2RequestContextNotExist,
                durableV1ReconnectContext,
                durableV2ReconnectContext,
                oplockLeaseType,
                isSameLeaseKey,
                isSameCreateGuid);
            #endregion

            #region Client reconnect to server

            Site.Log.Add(LogEntryKind.Debug, "Client reconnect to server");

            #region Reconnect to Common Share or CA Share
            if (!isCAShare)
            {
                targetIPAddress = testConfig.SutIPAddress;
                targetServer = testConfig.SutComputerName;
                targetShare = testConfig.BasicFileShare;
            }
            else
            {
                targetIPAddress = testConfig.CAShareServerIP;
                targetServer = testConfig.CAShareServerName;
                targetShare = testConfig.CAShareName;
            }

            // Connect to Server
            testClientAfterDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClientAfterDisconnection.CreditGoal = 10;
            testClientAfterDisconnection.ConnectToServer(testConfig.UnderlyingTransport, targetServer, targetIPAddress);

            // Negotiate
            testClientAfterDisconnection.Negotiate(
                requestDialect,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: clientCapabilities,
                // If the reconnect use the same client guid, then keep client guid the same value, otherwise use a new client guid.
                clientGuid: (isSameClient ? clientGuid : Guid.NewGuid()));

            uint status = testClientAfterDisconnection.SessionSetup(
                testConfig.DefaultSecurityPackage,
                targetServer,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);
            Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Reconnect Session Setup should be successful, actual status is {0}", Smb2Status.GetStatusCode(status));

            // TreeConnect
            testClientAfterDisconnection.TreeConnect(sharePath, out treeIdAfterDisconnection);

            #endregion

            #region Send Create request according to different context combination

            RequestedOplockLevel_Values requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE;
            switch (oplockLeaseType)
            {
                case OplockLeaseType.NoOplockOrLease:
                    {
                        requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE;
                    }
                    break;

                case OplockLeaseType.BatchOplock:
                    {
                        requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH;
                    }
                    break;

                case OplockLeaseType.LeaseV1:
                case OplockLeaseType.LeaseV2:
                    {
                        requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE;
                    }
                    break;
            }

            status = OpenCreate(
                testClientAfterDisconnection,
                treeIdAfterDisconnection,
                fileName,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                requestedOplockLevel,
                smb2CreateContextRequest);

            #endregion

            DurableHandleResponseContext durableHandleResponse;
            LeaseResponseContext leaseResponse;
            CheckResponseContexts(serverCreateContexts, out durableHandleResponse, out leaseResponse);
            OpenResponse((ModelSmb2Status)status, durableHandleResponse, leaseResponse, handleConfig);

            testClientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            testClientAfterDisconnection.LogOff();

            #endregion
        }
        /// <summary>
        /// Create or delete a file or directory with a given name.
        /// </summary>
        /// <param name="client">the functional client used to create</param>
        /// <param name="isDirectory">true for file and false for directory</param>
        /// <param name="isDeleteFlagSet">true for delete flag set</param>
        /// <param name="isNonAdmin">true for non admin account credential</param>
        /// <param name="fileNametype">the file name type: ValidFileName, SymbolicLinkInMiddle, SymbolicLinkAtLast, InvalidSymbolicLink</param>
        /// <param name="isValidAccessMask">true for valid access mask, which should contain DELETE or GENERIC_ALL</param>
        private void OperateFileOrDirectory(Smb2FunctionalClient client, bool isDirectory, bool isDeleteFlagSet, bool isNonAdmin, FileNameType fileNameType, bool isValidAccessMask)
        {
            CreateOptions_Values createOption;
            CreateDisposition_Values createDisposition;
            if (isDirectory)
            {
                createOption = CreateOptions_Values.FILE_DIRECTORY_FILE;
            }
            else
            {
                createOption = CreateOptions_Values.FILE_NON_DIRECTORY_FILE;
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT.");
            client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            AccountCredential accountCredential = isNonAdmin ? TestConfig.NonAdminAccountCredential : TestConfig.AccountCredential;
            client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, accountCredential, false);
            uint treeId;
            client.TreeConnect(sharePath, out treeId);
            FILEID fileId;
            Smb2CreateContextResponse[] createContextResponse;

            AccessMask accessMask = AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE;
            accessMask = isValidAccessMask ? accessMask : AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE;
            // The delete flag is set in the following situations: 1. Delete an existed file; 2. Test CreateOptions_Values.FILE_DELETE_ON_CLOSE combined with DesiredAccess
            createOption = isDeleteFlagSet ? (createOption | CreateOptions_Values.FILE_DELETE_ON_CLOSE) : createOption;
            // The createDisposition is set to FILE_OPEN if the file already existed; else, if it's the first time to create a file, this field should be set to FILE_CREATE
            createDisposition = (fileNameType == FileNameType.ExistedValidFileName) ? CreateDisposition_Values.FILE_OPEN : CreateDisposition_Values.FILE_CREATE;
            fileName = GetFileName(isDirectory, fileNameType);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with create option: {0} and create disposition: {1}", createOption, createDisposition);
            uint status = client.Create(
                treeId,
                fileName,
                createOption,
                out fileId,
                out createContextResponse,
                accessMask: accessMask,
                createDisposition: createDisposition,
                checker: (header, response) =>
                {
                    CheckCreateResponse(isNonAdmin, createOption, accessMask, header, response, fileNameType);
                });

            if (status == Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF.");
                client.Close(treeId, fileId);
            }

            client.TreeDisconnect(treeId);
            client.LogOff();
        }
        /// <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>
        private void ValidateByteLockRangeFromAnotherClient(bool isLocked)
        {
            uint status = 0;

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

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

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

            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 should succeed, actual status is {0}", Smb2Status.GetStatusCode(status));
            }

            status = client.Close(treeId, fileId);

            status = client.TreeDisconnect(treeId);

            status = client.LogOff();

            client.Disconnect();
        }
        /// <summary>
        /// Read content after failover
        /// </summary>
        /// <param name="server">File server name.</param>
        /// <param name="serverAccessIp">File server access IP.</param>
        /// <param name="uncSharePath">The share path to read the file.</param>
        /// <param name="file">The file name for reading content.</param>
        /// <param name="content">The content to read.</param>
        /// <param name="clientGuid">Smb2 client Guid.</param>
        /// <param name="createGuid">The Guid for smb2 create request.</param>
        /// <returns></returns>
        protected bool ReadContentAfterFailover(string server,
            IPAddress serverAccessIp,
            string uncSharePath,
            string file,
            string content,
            Guid clientGuid,
            Guid createGuid)
        {
            uint status;

            BaseTestSite.Assert.AreNotEqual(
                null,
                serverAccessIp,
                "Access IP to the file server should not be empty");
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Got IP {0} to access the file server", serverAccessIp.ToString());

            Smb2FunctionalClient afterFailover = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);
            DoUntilSucceed(() => afterFailover.ConnectToServer(TestConfig.UnderlyingTransport, server, serverAccessIp), TestConfig.FailoverTimeout,
                "Retry to connect to server until succeed within timeout span");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE request with the same clientguid of previous client.");
            status = afterFailover.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                clientGuid: clientGuid);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Negotiate failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request with the same SESSION_ID of previous client.");
            status = afterFailover.ReconnectSessionSetup(
                        beforeFailover,
                        TestConfig.DefaultSecurityPackage,
                        server,
                        TestConfig.AccountCredential,
                        TestConfig.UseServerGssToken);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "ReconnectSessionSetup failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            // Retry TreeConnect because network path may not be available immediately
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client retries TREE_CONNECT to {0} until succeed or timeout in {1} because network path may not be available immediately.", uncSharePath, TestConfig.FailoverTimeout);
            uint treeId = 0;
            status = afterFailover.TreeConnect(uncSharePath, out treeId, (header, response) => { });
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "TreeConnect failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            // Retry Create because file may not be available immediately
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client retries to send CREATE request with SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 context with PERSISTENT flag set until succeed or timeout in {0}.", TestConfig.FailoverTimeout);
            FILEID fileId = new FILEID();
            Smb2CreateContextResponse[] serverCreateContexts;
            status = DoUntilSucceed(
                () => afterFailover.Create(
                        treeId,
                        file,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId,
                        out serverCreateContexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                        new Smb2CreateContextRequest[] {
                            new Smb2CreateDurableHandleReconnectV2
                            {
                                FileId = new FILEID { Persistent = fileId.Persistent },
                                CreateGuid = createGuid,
                                Flags = CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT
                            },
                        },
                        checker: (header, response) => { }),
                TestConfig.FailoverTimeout,
                "Retry Create until succeed within timeout span");
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Create failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            string readContent;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends READ request to read content.");
            status = afterFailover.Read(treeId, fileId, 0, (uint)content.Length, out readContent);
            if (status != Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Warning, "Read failed with {0}.", Smb2Status.GetStatusCode(status));
                return false;
            }

            BaseTestSite.Assert.IsTrue(
                content.Equals(readContent),
                "Content read after failover should be identical to that written before failover");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            status = afterFailover.Close(treeId, fileId);
            status = afterFailover.TreeDisconnect(treeId);
            status = afterFailover.LogOff();
            afterFailover.Disconnect();
            return true;
        }
        public void BVT_SMB2Basic_CancelRegisteredChangeNotify()
        {
            uint status;
            string testDirectory = CreateTestDirectory(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Test directory \"{0}\" was created on share \"{1}\"", testDirectory, TestConfig.BasicFileShare);

            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client1.Smb2Client.ChangeNotifyResponseReceived += new Action<FILE_NOTIFY_INFORMATION[],Packet_Header,CHANGE_NOTIFY_Response>(OnChangeNotifyResponseReceived);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client to create a file by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE");
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client1.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client1.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId1;
            status = client1.TreeConnect(uncSharePath, out treeId1);
            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileId1;
            status = client1.Create(
                treeId1,
                testDirectory,
                CreateOptions_Values.FILE_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client starts to register CHANGE_NOTIFY on directory \"{0}\"", testDirectory);
            client1.ChangeNotify(treeId1, fileId1, CompletionFilter_Values.FILE_NOTIFY_CHANGE_LAST_ACCESS);

            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "Client starts to cancel the registered CHANGE_NOTIFY on directory \"{0}\"", testDirectory);
            client1.Cancel();

            BaseTestSite.Assert.IsTrue(
                changeNotificationReceived.WaitOne(TestConfig.WaitTimeoutInMilliseconds),
                "Change notification should be received within {0} milliseconds", TestConfig.WaitTimeoutInMilliseconds);

            BaseTestSite.Assert.AreNotEqual(
                Smb2Status.STATUS_SUCCESS,
                receivedChangeNotifyHeader.Status, "CHANGE_NOTIFY is not expected to success after cancel, actually server returns {0}.",
                Smb2Status.GetStatusCode(receivedChangeNotifyHeader.Status));
            BaseTestSite.CaptureRequirementIfAreEqual(
                Smb2Status.STATUS_CANCELLED,
                receivedChangeNotifyHeader.Status,
                RequirementCategory.STATUS_CANCELLED.Id,
                RequirementCategory.STATUS_CANCELLED.Description);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client1.Close(treeId1, fileId1);
            client1.TreeDisconnect(treeId1);
            client1.LogOff();
        }
        public void BVT_SessionMgmt_ReconnectSessionSetup()
        {
            Guid clientGuid = (TestConfig.RequestDialects.Length == 1 && TestConfig.RequestDialects[0] == DialectRevision.Smb2002) ? Guid.Empty : Guid.NewGuid();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a first client by sending NEGOTIATE request.");
            client.Negotiate(TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                null, // capability value will be set inside the method according to requested dialects.
                clientGuid);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends SESSION_SETUP request with SESSION_ID set to ZARO.");
            client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken);

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

            #region Reconnect and Do Session Setup with PreviousSessionId set.
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a second client by sending NEGOTIATE request.");
            Smb2FunctionalClient client2 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            client2.Negotiate(TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                null, // capability value will be set inside the method according to requested dialects.
                clientGuid);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The second client sends SESSION_SETUP request with SESSION_ID set to the value in the previous SESSION_SETUP response.");
            client2.ReconnectSessionSetup(client, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            #endregion

            #region Tear Down Client
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: LOG_OFF; DISCONNECT");
            client2.LogOff();
            client2.Disconnect();
            #endregion
        }
        private void TestAsymmetricShare(DialectRevision requestMaxDialect, string serverName, bool isAsymmetricShare)
        {
            int ret = 0;
            uint callId = 0;
            Guid clientGuid = Guid.NewGuid();
            WITNESS_INTERFACE_INFO registerInterface;
            string shareName = isAsymmetricShare ? TestConfig.AsymmetricShare : TestConfig.BasicFileShare;

            #region Get the file server to access it through SMB2
            IPAddress currentAccessIp = SWNTestUtility.GetCurrentAccessIP(serverName);
            BaseTestSite.Assert.IsNotNull(currentAccessIp, "IP address of the file server should NOT be empty");
            BaseTestSite.Log.Add(LogEntryKind.Debug, "Got the IP {0} to access the file server", currentAccessIp.ToString());
            #endregion

            #region Connect to the asymmetric share
            uncSharePath = Smb2Utility.GetUncPath(serverName, shareName);
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);
            testDirectory = CreateTestDirectory(uncSharePath);
            string file = Path.Combine(testDirectory, Guid.NewGuid().ToString());

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP");
            smb2Client = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);
            smb2Client.ConnectToServerOverTCP(currentAccessIp);
            smb2Client.Negotiate(
                Smb2Utility.GetDialects(requestMaxDialect),
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                clientGuid: clientGuid,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "Negotiate should succeed.");
                    BaseTestSite.Assert.AreEqual(
                        requestMaxDialect,
                        response.DialectRevision,
                        "The server is expected to use dialect {0}. Actual dialect is {1}",
                        requestMaxDialect,
                        response.DialectRevision);
                });
            smb2Client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                serverName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            uint treeId = 0;
            Share_Capabilities_Values shareCapabilities = Share_Capabilities_Values.NONE;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request to the {0} on the {1}", shareName, serverName);
            DoUntilSucceed(
                () => smb2Client.TreeConnect(uncSharePath, out treeId, (header, response) => { shareCapabilities = response.Capabilities; }),
                TestConfig.FailoverTimeout,
                "Retry TreeConnect until succeed within timeout span");

            if (requestMaxDialect == DialectRevision.Smb302 && isAsymmetricShare)
            {
                BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_ASYMMETRIC),
                    "The capabilities of the share should contain SHARE_CAP_ASYMMETRIC. The actual capabilities is {0}.", shareCapabilities);
            }
            else
            {
                BaseTestSite.Assert.IsFalse(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_ASYMMETRIC),
                    "The capabilities of the share should not contain SHARE_CAP_ASYMMETRIC. The actual capabilities is {0}.", shareCapabilities);

                #region Disconnect current SMB2 connection
                smb2Client.TreeDisconnect(treeId);
                smb2Client.LogOff();
                smb2Client.Disconnect();
                #endregion
                return;
            }

            FILEID fileId;
            Smb2CreateContextResponse[] serverCreateContexts;
            Guid createGuid = Guid.NewGuid();
            Guid leaseKey = Guid.NewGuid();
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file.");
            smb2Client.Create(
                treeId,
                file,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
            smb2Client.Write(treeId, fileId, content);

            string readContent;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client reads from the file.");
            smb2Client.Read(treeId, fileId, 0, (uint)content.Length, out readContent);
            BaseTestSite.Assert.IsTrue(
                content.Equals(readContent),
                "Content read should be identical to that written.");
            #endregion

            #region Get register interface
            DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForInterface, currentAccessIp,
                TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, serverName), TestConfig.FailoverTimeout,
                "Retry BindServer until succeed within timeout span");

            WITNESS_INTERFACE_LIST interfaceList = new WITNESS_INTERFACE_LIST();
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrGetInterfaceList.");
            DoUntilSucceed(() =>
            {
                ret = swnClientForInterface.WitnessrGetInterfaceList(out interfaceList);
                BaseTestSite.Assert.AreEqual<SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrGetInterfaceList returns with result code = 0x{0:x8}", ret);
                return SWNTestUtility.VerifyInterfaceList(interfaceList, TestConfig.Platform);
            }, TestConfig.FailoverTimeout, "Retry to call WitnessrGetInterfaceList until succeed within timeout span");

            swnClientForInterface.SwnUnbind(TestConfig.Timeout);

            SWNTestUtility.GetRegisterInterface(interfaceList, out registerInterface);

            #endregion

            #region Get SHARE_MOVE_NOTIFICATION
            DoUntilSucceed(() => SWNTestUtility.BindServer(swnClientForWitness,
                (registerInterface.Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(registerInterface.IPV4) : SWNTestUtility.ConvertIPV6(registerInterface.IPV6),
                TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, TestConfig.DefaultSecurityPackage,
                TestConfig.DefaultRpceAuthenticationLevel, TestConfig.Timeout, serverName), TestConfig.FailoverTimeout,
                "Retry BindServer until succeed within timeout span");

            string clientName = TestConfig.WitnessClientName;

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Register witness:");
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tNetName: {0}", serverName);
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tIPAddress: {0}", currentAccessIp.ToString());
            BaseTestSite.Log.Add(LogEntryKind.Debug, "\tClient Name: {0}", clientName);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrRegisterEx.");
            ret = swnClientForWitness.WitnessrRegisterEx(SwnVersion.SWN_VERSION_2,
                serverName,
                shareName,
                currentAccessIp.ToString(),
                clientName,
                WitnessrRegisterExFlagsValue.WITNESS_REGISTER_IP_NOTIFICATION,
                120,
                out pContext);
            BaseTestSite.Assert.AreEqual<SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrRegisterEx returns with result code = 0x{0:x8}", ret);

            BaseTestSite.Assert.IsNotNull(pContext, "Expect pContext is not null.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrAsyncNotify.");
            callId = swnClientForWitness.WitnessrAsyncNotify(pContext);
            BaseTestSite.Assert.AreNotEqual<uint>(0, callId, "WitnessrAsyncNotify returns callId = {0}", callId);

            // NOTICE
            // This comment is for current Windows Cluster test environment.
            // Current test environment has only two nodes and both they are optimum nodes.
            // So whatever the server name is, SHARE_MOVE_NOTIFICATION notification will be recieved.
            // The configuration items 'OptimumNodeOfAsymmetricShare' and 'NonOptimumNodeOfAsymmetricShare' are assigned the same default value.
            // The code in if block will be executed all the time.
            if (serverName == TestConfig.NonOptimumNodeOfAsymmetricShare)
            {
                #region Expect that SHARE_MOVE_NOTIFICATION notification will be received  when the client connects to the asymmetric share on the non-optimum share
                RESP_ASYNC_NOTIFY respNotify;
                ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify);
                BaseTestSite.Assert.AreEqual<SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrAsyncNotify returns with result code = 0x{0:x8}", ret);
                SWNTestUtility.PrintNotification(respNotify);
                SWNTestUtility.VerifyClientMoveShareMoveAndIpChange(respNotify, SwnMessageType.SHARE_MOVE_NOTIFICATION, (uint)SwnIPAddrInfoFlags.IPADDR_V4, TestConfig.Platform);

                #region Get the new IpAddr
                IPADDR_INFO_LIST ipAddrInfoList;
                SwnUtility.ParseIPAddrInfoList(respNotify, out ipAddrInfoList);
                currentAccessIp = (ipAddrInfoList.IPAddrList[0].Flags & (uint)SwnNodeFlagsValue.IPv4) != 0 ? new IPAddress(ipAddrInfoList.IPAddrList[0].IPV4) : SWNTestUtility.ConvertIPV6(ipAddrInfoList.IPAddrList[0].IPV6);
                #endregion

                #region Unregister SWN Witness
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrUnRegister.");
                ret = swnClientForWitness.WitnessrUnRegister(pContext);
                BaseTestSite.Assert.AreEqual<SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrUnRegister returns with result code = 0x{0:x8}", ret);
                pContext = IntPtr.Zero;
                swnClientForWitness.SwnUnbind(TestConfig.Timeout);
                #endregion

                #region Disconnect current SMB2 connection
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT.");
                smb2Client.TreeDisconnect(treeId);
                smb2Client.LogOff();
                smb2Client.Disconnect();
                #endregion
                #endregion
            }
            else
            {
                #region Expect that no SHARE_MOVE_NOTIFICATION notification will be received when the client connects to the asymmetric share on the optimum share
                bool isNotificationReceived = false;
                try
                {
                    RESP_ASYNC_NOTIFY respNotify;
                    ret = swnClientForWitness.ExpectWitnessrAsyncNotify(callId, out respNotify);
                    isNotificationReceived = true;
                }
                catch (TimeoutException)
                {
                    isNotificationReceived = false;
                }

                #region Disconnect current SMB2 connection
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT");
                smb2Client.TreeDisconnect(treeId);
                smb2Client.LogOff();
                smb2Client.Disconnect();
                #endregion

                #region Unregister SWN Witness
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client calls WitnessrUnRegister.");
                ret = swnClientForWitness.WitnessrUnRegister(pContext);
                BaseTestSite.Assert.AreEqual<SwnErrorCode>(SwnErrorCode.ERROR_SUCCESS, (SwnErrorCode)ret, "WitnessrUnRegister returns with result code = 0x{0:x8}", ret);
                pContext = IntPtr.Zero;
                swnClientForWitness.SwnUnbind(TestConfig.Timeout);
                #endregion

                BaseTestSite.Assert.IsFalse(isNotificationReceived, "Expect that no notification will be received when the client has connected to asymmetric share on the optimum node.");
                #endregion

                return;
            }
            #endregion

            #region Connect to the share on the optimum node
            smb2Client = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Got the IP {0} to access the file server", currentAccessIp.ToString());

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP");
            smb2Client.ConnectToServerOverTCP(currentAccessIp);
            smb2Client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                clientGuid: clientGuid,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "Negotiate should succeed.");
                });
            smb2Client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                serverName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client sends TREE_CONNECT and wait for a response until timeout.");
            DoUntilSucceed(
                () => smb2Client.TreeConnect(uncSharePath, out treeId, (header, response) => { }),
                TestConfig.FailoverTimeout,
                "Retry TreeConnect until succeed within timeout span");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client writes to the file.");
            smb2Client.Create(
                treeId,
                file,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
            smb2Client.Write(treeId, fileId, content);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client reads from the file.");
            smb2Client.Read(treeId, fileId, 0, (uint)content.Length, out readContent);
            BaseTestSite.Assert.IsTrue(
                content.Equals(readContent),
                "Content read should be identical to that written.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT.");
            smb2Client.TreeDisconnect(treeId);
            smb2Client.LogOff();
            smb2Client.Disconnect();
            #endregion
        }
        public void SharePermission_CreateClose_DeleteFile_MaximalAccessNotIncludeDeleteOrGenericAll()
        {
            _SID sid = DtypUtility.GetSidFromAccount(TestConfig.DomainName, azUser01Name);
            if (!dynamicallyConfigurableShareExist)
            {
                BaseTestSite.Assert.Inconclusive("Required share: {0} does not exist!", dynamicallyConfigurableShareName);
            }
            object ace = DtypUtility.CreateAccessAllowedAce(sid, (DtypUtility.ACCESS_MASK_STANDARD_RIGHTS_ALL | DtypUtility.ACCESS_MASK_SPECIFIC_RIGHTS_ALL) & ~DtypUtility.ACCESS_MASK_DELETE, ACE_FLAGS.None);
            SetSecurityDescriptorOnDynamicallyConfigurableShare(ace);
            string shareName = dynamicallyConfigurableShareName;
            string shareUncPath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, shareName);

            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            AccountCredential user = new AccountCredential(TestConfig.DomainName, azUser01Name, TestConfig.UserPassword);
            try
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends NEGOTIATE message.");
                client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends SESSION_SETUP message using account: {0}@{1}.", user.AccountName, user.DomainName);
                client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, user, false);

                uint treeId;
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends TREE_CONNECT message to access share: {0}.", shareUncPath);
                client.TreeConnect(shareUncPath, out treeId, checker: (header, response) =>
                {
                    BaseTestSite.Assert.IsTrue((response.MaximalAccess.ACCESS_MASK & (DtypUtility.ACCESS_MASK_DELETE | DtypUtility.ACCESS_MASK_GENERIC_ALL)) == 0,
                        "Treeconnect.MaximalAccess does not include DELETE or GENERIC_ALL.");
                });

                string fileName = string.Format("SharePermission_CreateClose_InvalidMaximalAccess_{0}.txt", Guid.NewGuid());
                FILEID fileId;
                Smb2CreateContextResponse[] createContexResponse;
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create the file: {0}", fileName);
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends CREATE request.");
                uint status = client.Create(
                    treeId,
                    fileName,
                    CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    out fileId,
                    out createContexResponse,
                    accessMask: AccessMask.FILE_READ_DATA | AccessMask.FILE_WRITE_DATA | AccessMask.FILE_APPEND_DATA |
                    AccessMask.FILE_READ_ATTRIBUTES | AccessMask.FILE_READ_EA | AccessMask.FILE_WRITE_ATTRIBUTES |
                    AccessMask.FILE_WRITE_EA | AccessMask.READ_CONTROL | AccessMask.WRITE_DAC | AccessMask.SYNCHRONIZE, // Windows client behavior
                    shareAccess: ShareAccess_Values.NONE,
                    createDisposition: CreateDisposition_Values.FILE_CREATE);
                client.Close(treeId, fileId);

                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Delete the file: {0}", fileName);
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends CREATE request with FILE_DELETE_ON_CLOSE flag set in CreateOptions .");
                status = client.Create(
                    treeId,
                    fileName,
                    CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE,
                    out fileId,
                    out createContexResponse,
                    accessMask: AccessMask.DELETE | AccessMask.FILE_READ_ATTRIBUTES | AccessMask.SYNCHRONIZE, // Windows client behavior
                    shareAccess: ShareAccess_Values.FILE_SHARE_DELETE,
                    createDisposition: CreateDisposition_Values.FILE_OPEN,
                    checker:(header, response) =>
                    {
                        if(TestConfig.Platform == Platform.NonWindows)
                        {
                            BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, header.Status,
                                "If the FILE_DELETE_ON_CLOSE flag is set in CreateOptions and " +
                                "Treeconnect.MaximalAccess does not include DELETE or GENERIC_ALL, " +
                                "the server SHOULD fail the request with STATUS_ACCESS_DENIED");
                        }
                        else
                        {
                            BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_ACCESS_DENIED, header.Status,
                                "If the FILE_DELETE_ON_CLOSE flag is set in CreateOptions and " +
                                "Treeconnect.MaximalAccess does not include DELETE or GENERIC_ALL, " +
                                "the server SHOULD fail the request with STATUS_ACCESS_DENIED");
                        }
                    });

                client.TreeDisconnect(treeId);
                client.LogOff();
            }
            catch(Exception e)
            {
                BaseTestSite.Assert.Fail("Case failed due to: {0}", e.Message);
            }
            finally
            {
                client.Disconnect();
            }
        }
        protected _SECURITY_DESCRIPTOR QuerySecurityDescriptor(string sharePath, string fileName, AdditionalInformation_Values securityAttributesToQuery)
        {
            Smb2FunctionalClient clientAdmin;
            clientAdmin = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientAdmin.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            uint treeId;
            ConnectToShare(clientAdmin, TestConfig.AccountCredential, sharePath, out treeId);

            FILEID fileId;
            Smb2CreateContextResponse[] createContextResponses;
            clientAdmin.Create(treeId,
                fileName,
                fileName == null ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out createContextResponses,
                accessMask: AccessMask.READ_CONTROL | AccessMask.WRITE_DAC | AccessMask.FILE_READ_ATTRIBUTES,
                shareAccess: ShareAccess_Values.FILE_SHARE_DELETE | ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE,
                createDisposition: CreateDisposition_Values.FILE_OPEN);
            _SECURITY_DESCRIPTOR sd;
            clientAdmin.QuerySecurityDescriptor(treeId, fileId, securityAttributesToQuery, out sd);
            clientAdmin.Close(treeId, fileId);
            clientAdmin.TreeDisconnect(treeId);
            clientAdmin.LogOff();
            clientAdmin.Disconnect();
            return sd;
        }
        public void OpenRequest(
            ModelDialectRevision clientMaxDialect,
            PersistentBitType persistentBit,
            CAShareType connectToCAShare,
            OplockLeaseType oplockLeaseType,
            DurableV1RequestContext durableV1RequestContext,
            DurableV2RequestContext durableV2RequestContext,
            DurableV1ReconnectContext durableV1ReconnectContext,
            DurableV2ReconnectContext durableV2ReconnectContext)
        {
            requestDialect = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect));
            clientCapabilities = 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;
            if (persistentBit == PersistentBitType.PersistentBitSet)
            {
                clientCapabilities |= Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES;
            }

            clientGuid = Guid.NewGuid();
            requestedContext = oplockLeaseType;
            isCAShare = (connectToCAShare == CAShareType.CAShare);
            IPAddress targetIPAddress;
            string targetServer;

            #region Connect to Common Share or CA Share
            if (!isCAShare)
            {
                sharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);
                fileName = "PrepareHandle_ConnectTo_CommonShareFile_" + Guid.NewGuid() + ".txt";
                targetIPAddress = testConfig.SutIPAddress;
                targetServer = testConfig.SutComputerName;
            }
            else
            {
                sharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName);
                fileName = "PrepareHandle_ConnectTo_CAShareFile_" + Guid.NewGuid().ToString() + ".txt";
                targetIPAddress = testConfig.CAShareServerIP;
                targetServer = testConfig.CAShareServerName;
            }

            testClientBeforeDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClientBeforeDisconnection.CreditGoal = 20;
            testClientBeforeDisconnection.ConnectToServer(testConfig.UnderlyingTransport, targetServer, targetIPAddress);

            testClientBeforeDisconnection.Negotiate(
                requestDialect,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: clientCapabilities,
                clientGuid: clientGuid,
                checker: (header, response) =>
                {
                    if (Smb2Utility.IsSmb3xFamily(response.DialectRevision)
                        && handleConfig.IsPersistentHandleSupported
                        && persistentBit == PersistentBitType.PersistentBitSet)
                    {
                        Site.Assert.IsTrue(
                            response.Capabilities.HasFlag(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES),
                            "The server MUST set SMB2_GLOBAL_CAP_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " +
                            "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles. " +
                            "Actual capabilities are {0}", response.Capabilities);
                    }
                });

            testClientBeforeDisconnection.SessionSetup(
                    testConfig.DefaultSecurityPackage,
                    targetServer,
                    testConfig.AccountCredential,
                    testConfig.UseServerGssToken);

            testClientBeforeDisconnection.TreeConnect(sharePath, out treeIdBeforeDisconnection);

            #endregion

            #region Construct Create Contexts
            Smb2CreateContextRequest[] smb2CreateContextRequest = GetOpenFileCreateContext(
                durableV1RequestContext,
                durableV2RequestContext,
                durableV1ReconnectContext,
                durableV2ReconnectContext,
                oplockLeaseType,
                false,
                false);
            #endregion

            #region Send Create request according to different context combination
            RequestedOplockLevel_Values requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE;
            switch (oplockLeaseType)
            {
                case OplockLeaseType.NoOplockOrLease:
                    {
                        requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE;
                    }
                    break;

                case OplockLeaseType.BatchOplock:
                    {
                        requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH;
                    }
                    break;

                case OplockLeaseType.LeaseV1:
                case OplockLeaseType.LeaseV2:
                    {
                        requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE;
                    }
                    break;
            }

            FILEID fileId;
            Smb2CreateContextResponse[] serverCreateContexts;
            uint status = OpenCreate(
                testClientBeforeDisconnection,
                treeIdBeforeDisconnection,
                fileName,
                out fileId,
                out serverCreateContexts,
                requestedOplockLevel,
                smb2CreateContextRequest);

            #endregion

            DurableHandleResponseContext durableHandleResponse;
            LeaseResponseContext leaseResponse;
            CheckResponseContexts(serverCreateContexts, out durableHandleResponse, out leaseResponse);
            OpenResponse((ModelSmb2Status)status, durableHandleResponse, leaseResponse, handleConfig);

            testClientBeforeDisconnection.TreeDisconnect(treeIdAfterDisconnection, (header, response) => { });
            testClientBeforeDisconnection.LogOff();
        }
        private void Compound_RelatedRequests(string fileName, bool isEncrypted)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Initialize the test client.");
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            uint treeId;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Connect to the SMB2 basic share by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT.");
            ConnectToShare(client, out treeId);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct Create packet.");
            Smb2CreateRequestPacket createPacket = ConstructCreatePacket(client.SessionId, treeId, fileName);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct Write packet, flag FLAGS_RELATED_OPERATIONS is set.");
            Smb2WriteRequestPacket writePacket = ConstructRelatedWritePacket();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Construct Close packet, flag FLAGS_RELATED_OPERATIONS is set.");
            Smb2CloseRequestPacket closePacket = ConstructRelatedClosePacket();

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send {0}compounded Create, Write and Close requests to SUT.", isEncrypted ? "encrypted " : "");
            List<Smb2SinglePacket> requestPackets = new List<Smb2SinglePacket>();
            requestPackets.Add(createPacket);
            requestPackets.Add(writePacket);
            requestPackets.Add(closePacket);

            if (isEncrypted)
            {
                // Enable encryption
                client.EnableSessionSigningAndEncryption(enableSigning: testConfig.SendSignedRequest, enableEncryption: true);
            }
            List<Smb2SinglePacket> responsePackets = client.SendAndReceiveCompoundPacket(requestPackets);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify responses to the compounded request.");
            foreach (var responsePacket in responsePackets)
            {
                if (TestConfig.Platform == Platform.WindowsServer2016 && responsePacket.Header.Status != Smb2Status.STATUS_SUCCESS)
                {

                }
                else
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        responsePacket.Header.Status,
                        "{0} should succeed, actual status is {1}", responsePacket.Header.Command, Smb2Status.GetStatusCode(responsePacket.Header.Status));
                }
            }

            client.TreeDisconnect(treeId);
            client.LogOff();
            client.Disconnect();
        }
        public void BVT_MultiCredit_OneRequestWithMultiCredit()
        {
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LARGE_MTU);

            Guid clientGuid = Guid.NewGuid();
            string fileName = "MultiCredit_" + clientGuid.ToString() + ".txt";

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: 1. NEGOTIATE; 2. SESSION_SETUP; 3. TREE_CONNECT");
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client.ConnectToServerOverTCP(TestConfig.SutIPAddress);
            Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_LARGE_MTU;
            client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: clientCapabilities);
            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId;
            client.TreeConnect(uncSharePath, out treeId);

            int bufferSize = (int)client.MaxBufferSize;
            FILEID fileId;
            Smb2CreateContextResponse[] serverCreateContexts;
            ushort grantedCredit = 0;
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with {0} credits", client.Credits);
            client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));

                    BaseTestSite.Log.Add(LogEntryKind.Debug,
                        "The MaxBufferSize of the server is {0}.",
                        client.MaxBufferSize);
                    BaseTestSite.Log.Add(LogEntryKind.Debug,
                        "Server has granted {0} credits to the client.",
                        client.Credits);

                    // Make sure client hold enough credits for test
                    ushort maxBufferSizeInCredit = (ushort)((client.MaxBufferSize -1)/ 65536 + 1);
                    if (client.Credits < maxBufferSizeInCredit)
                    {
                        if (client.Credits < 2)
                        {
                            BaseTestSite.Assert.Inconclusive(
                                "This test case is not applicable when the server only grants {0} credits",
                                client.Credits);
                        }
                        // Test max buffer according to granted credits.
                        bufferSize = (client.Credits - 1) * 65536;
                    }

                    grantedCredit = header.CreditRequestResponse;
                });

            contentWrite = Smb2Utility.CreateRandomStringInByte(bufferSize);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client attempts to write {0} bytes content to file when server grants {1} credits",
                client.MaxBufferSize, client.Credits);

            client.Write(
                treeId,
                fileId,
                contentWrite,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));

                    grantedCredit = header.CreditRequestResponse;
                });

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client attempts to read {0} bytes content from file when server grants {1} credit",
                bufferSize, client.Credits);
            client.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: 1. CLOSE; 2. TREE_DISCONNECT; 3. LOG_OFF; 4. DISCONNECT");
            client.Close(treeId, fileId);
            client.TreeDisconnect(treeId);
            client.LogOff();
            client.Disconnect();
        }
        private void TestValidateNegotiateInfo(Smb2FunctionalClient client, ValidateNegotiateInfoRequestType requestType, DialectRevision[] invalidDialects = null)
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO);
            TestConfig.CheckDialectIOCTLCompatibility(CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO);
            // Server will terminate connection if Validate Negotiate Info Request is not signed.
            TestConfig.CheckSigning();
            #endregion

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE;  SESSION_SETUP; TREE_CONNECT");

            Guid clientGuid = Guid.NewGuid();
            DialectRevision[] requestDialects = TestConfig.RequestDialects;
            Capabilities_Values clientCapabilities = 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;
            SecurityMode_Values clientSecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED;
            NEGOTIATE_Response? negotiateResponse = null;
            status = client.Negotiate(
                requestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                clientSecurityMode,
                clientCapabilities,
                clientGuid,
                (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));

                    TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);

                    negotiateResponse = response;
                });

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

            uint treeId;
            string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName);
            status = client.TreeConnect(ipcPath, out treeId);

            VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq;
            switch (requestType)
            {
                case ValidateNegotiateInfoRequestType.None:
                case ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse:
                    validateNegotiateInfoReq.Guid = clientGuid;
                    validateNegotiateInfoReq.Capabilities = clientCapabilities;
                    validateNegotiateInfoReq.SecurityMode = clientSecurityMode;
                    validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length;
                    validateNegotiateInfoReq.Dialects = requestDialects;
                    break;

                case ValidateNegotiateInfoRequestType.InvalidDialects:
                    validateNegotiateInfoReq.Guid = clientGuid;
                    validateNegotiateInfoReq.Capabilities = clientCapabilities;
                    validateNegotiateInfoReq.SecurityMode = clientSecurityMode;
                    validateNegotiateInfoReq.DialectCount = (ushort)invalidDialects.Length;
                    validateNegotiateInfoReq.Dialects = invalidDialects;
                    break;

                case ValidateNegotiateInfoRequestType.InvalidGuid:
                    validateNegotiateInfoReq.Guid = Guid.NewGuid();
                    validateNegotiateInfoReq.Capabilities = clientCapabilities;
                    validateNegotiateInfoReq.SecurityMode = clientSecurityMode;
                    validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length;
                    validateNegotiateInfoReq.Dialects = requestDialects;
                    break;

                case ValidateNegotiateInfoRequestType.InvalidSecurityMode:
                    validateNegotiateInfoReq.Guid = clientGuid;
                    validateNegotiateInfoReq.Capabilities = clientCapabilities;
                    validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NONE;
                    validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length;
                    validateNegotiateInfoReq.Dialects = requestDialects;
                    break;

                case ValidateNegotiateInfoRequestType.InvalidCapabilities:
                    validateNegotiateInfoReq.Guid = clientGuid;
                    validateNegotiateInfoReq.Capabilities = Capabilities_Values.NONE;
                    validateNegotiateInfoReq.SecurityMode = clientSecurityMode;
                    validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length;
                    validateNegotiateInfoReq.Dialects = requestDialects;
                    break;

                default:
                    throw new InvalidOperationException("Unexpected ValidateNegotiateInfo request type " + requestType);
            }

            byte[] inputBuffer = TypeMarshal.ToBytes<VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq);
            byte[] outputBuffer;
            VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResp;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Attempt to validate negotiate info with info Guid: {0}, Capabilities: {1}, SecurityMode: {2}, DialectCount: {3}, Dialects: {4}",
                validateNegotiateInfoReq.Guid, validateNegotiateInfoReq.Capabilities, validateNegotiateInfoReq.SecurityMode, validateNegotiateInfoReq.DialectCount, Smb2Utility.GetArrayString(validateNegotiateInfoReq.Dialects));

            if (requestType == ValidateNegotiateInfoRequestType.None)
            {
                status = client.ValidateNegotiateInfo(treeId, inputBuffer, out outputBuffer, checker: (header, response) => { });

                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status,
                    "ValidateNegotiateInfo should succeed ");

                validateNegotiateInfoResp = TypeMarshal.ToStruct<VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer);
                BaseTestSite.Log.Add(
                    LogEntryKind.Debug,
                    "Capabilities returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.Capabilities);
                BaseTestSite.Assert.AreEqual(
                    (Capabilities_Values)negotiateResponse.Value.Capabilities,
                    validateNegotiateInfoResp.Capabilities,
                    "Capabilities returned in ValidateNegotiateInfo response should be equal to server capabilities in original Negotiate response");

                BaseTestSite.Log.Add(
                    LogEntryKind.Debug,
                    "Guid returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.Guid);
                BaseTestSite.Assert.AreEqual(
                    negotiateResponse.Value.ServerGuid,
                    validateNegotiateInfoResp.Guid,
                    "ServerGuid returned in ValidateNegotiateInfo response should be equal to server ServerGuid in original Negotiate response");

                BaseTestSite.Log.Add(
                    LogEntryKind.Debug,
                    "SecurityMode returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.SecurityMode);
                BaseTestSite.Assert.AreEqual(
                    (SecurityMode_Values)negotiateResponse.Value.SecurityMode,
                    validateNegotiateInfoResp.SecurityMode,
                    "SecurityMode returned in ValidateNegotiateInfo response should be equal to server SecurityMode in original Negotiate response");

                BaseTestSite.Log.Add(
                    LogEntryKind.Debug,
                    "Dialect returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.Dialect);
                BaseTestSite.Assert.AreEqual(
                    negotiateResponse.Value.DialectRevision,
                    validateNegotiateInfoResp.Dialect,
                    "DialectRevision returned in ValidateNegotiateInfo response should be equal to server DialectRevision in original Negotiate response");

                client.TreeDisconnect(treeId);
                client.LogOff();
                return;
            }

            uint maxOutputResponse = (requestType == ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse) ? (uint)0: 64 * 1024;

            try
            {
                client.ValidateNegotiateInfo(treeId, inputBuffer, out outputBuffer, maxOutputResponse, (header, response) => { });

                client.TreeDisconnect(treeId);
                client.LogOff();
                return;
            }
            catch
            {
            }

            string errCondition = requestType == ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse ?
                "MaxOutputResponse in the request is less than the size of a VALIDATE_NEGOTIATE_INFO Response" : "there's invalid info in the request";

            BaseTestSite.Assert.IsTrue(client.Smb2Client.IsServerDisconnected, "Transport connection should be terminated when {0}", errCondition);
        }
        private void ClientTearDown(Smb2FunctionalClient client, uint treeId, FILEID fileId)
        {
            status = client.Close(treeId, fileId);

            status = client.TreeDisconnect(treeId);

            status = client.LogOff();
        }
        private void AppInstanceIdTest(bool sameAppInstanceId, bool containCreateDurableContext)
        {
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            #region Client 1 Connect to Server
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the first client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT");
            clientForInitialOpen = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientForInitialOpen.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress, TestConfig.ClientNic1IPAddress);
            clientForInitialOpen.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            clientForInitialOpen.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeIdForInitialOpen;
            clientForInitialOpen.TreeConnect(sharePath, out treeIdForInitialOpen);

            Guid appInstanceId = Guid.NewGuid();
            FILEID fileIdForInitialOpen;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends CREATE request for exclusive open with SMB2_CREATE_APP_INSTANCE_ID create context.");
            Smb2CreateContextResponse[] serverCreateContexts;
            Smb2CreateContextRequest[] createContextsRequestForInitialOpen = null;
            if (containCreateDurableContext)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is also included in the CREATE request.");
                createContextsRequestForInitialOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateDurableHandleRequestV2
                    {
                         CreateGuid = Guid.NewGuid()
                    },
                    new Smb2CreateAppInstanceId
                    {
                         AppInstanceId = appInstanceId
                    }
                };
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is not included in the CREATE request.");
                createContextsRequestForInitialOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateAppInstanceId
                    {
                         AppInstanceId = appInstanceId
                    }
                };
            }

            clientForInitialOpen.Create(
                treeIdForInitialOpen,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdForInitialOpen,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                createContextsRequestForInitialOpen,
                shareAccess: ShareAccess_Values.NONE);
            #endregion

            #region Client 2 Connect to Server

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the second client by sending the following requests: NEGOTIATE; SESSION-SETUP; TREE_CONNECT");
            clientForReOpen = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            clientForReOpen.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress, TestConfig.ClientNic2IPAddress);
            clientForReOpen.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            clientForReOpen.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeIdForReOpen;
            clientForReOpen.TreeConnect(sharePath, out treeIdForReOpen);

            FILEID fileIdForReOpen;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The second client sends CREATE request for exclusive open with the {0} SMB2_CREATE_APP_INSTANCE_ID of the first client.", sameAppInstanceId ? "same" : "different");
            Smb2CreateContextRequest[] createContextsRequestForReOpen = null;
            if (containCreateDurableContext)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is also included in the CREATE request.");
                createContextsRequestForReOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateDurableHandleRequestV2
                    {
                         CreateGuid = Guid.NewGuid()
                    },
                    new Smb2CreateAppInstanceId
                    {
                         AppInstanceId = sameAppInstanceId ? appInstanceId : Guid.NewGuid()
                    }
                };
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context is not included in the CREATE request.");
                createContextsRequestForReOpen = new Smb2CreateContextRequest[] {
                    new Smb2CreateAppInstanceId
                    {
                         AppInstanceId = sameAppInstanceId ? appInstanceId : Guid.NewGuid()
                    }
                };
            }

            clientForReOpen.Create(
                treeIdForReOpen,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdForReOpen,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                createContextsRequestForReOpen,
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
                {
                    if (sameAppInstanceId)
                    {
                        BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "The second client should create the open successfully.");
                    }
                    else
                    {
                        BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, header.Status, "The second client should not create the open successfully.");
                    }
                });

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends another WRITE request.");

            if (sameAppInstanceId)
            {
                clientForInitialOpen.Write(treeIdForInitialOpen, fileIdForInitialOpen, content,
                    checker: (header, response) =>
                    {
                        BaseTestSite.Assert.AreNotEqual(
                            Smb2Status.STATUS_SUCCESS,
                            header.Status,
                            "The initial open is closed. Write should not succeed. Actually server returns with {0}.", Smb2Status.GetStatusCode(header.Status));
                        BaseTestSite.CaptureRequirementIfAreEqual(
                            Smb2Status.STATUS_FILE_CLOSED,
                            header.Status,
                            RequirementCategory.STATUS_FILE_CLOSED.Id,
                            RequirementCategory.STATUS_FILE_CLOSED.Description);
                    });

                // The first open is closed, no need to do clean up job.
                // Clean up the second client.
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF; DISCONNECT");
                clientForReOpen.Close(treeIdForReOpen, fileIdForReOpen);
                clientForReOpen.TreeDisconnect(treeIdForReOpen);
                clientForReOpen.LogOff();
                clientForReOpen.Disconnect();
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "The initial open is not closed. Write should succeed.");
                clientForInitialOpen.Write(treeIdForInitialOpen, fileIdForInitialOpen, content);

                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the first client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
                clientForInitialOpen.Close(treeIdForInitialOpen, fileIdForInitialOpen);
                clientForInitialOpen.TreeDisconnect(treeIdForInitialOpen);
                clientForInitialOpen.LogOff();

                // The second client doesn't create the open succesfully, so no need to close the open.
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: TREE_DISCONNECT; LOG_OFF; DISCONNECT");
                clientForReOpen.TreeDisconnect(treeIdForReOpen);
                clientForReOpen.LogOff();
                clientForReOpen.Disconnect();
            }

            #endregion
        }
        public void BVT_SMB2Basic_LockAndUnLock()
        {
            uint status;
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            #region From client1 lock a byte range and try to write content to the file within the range
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client1 locks a byte range and try to write content to the file within the range.");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client1 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client1.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client1.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId1;
            status = client1.TreeConnect(uncSharePath, out treeId1);
            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileId1;
            string fileName = Guid.NewGuid().ToString() + ".txt";
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 writes content to the file created.");
            status = client1.Write(treeId1, fileId1, content);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending CLOSE request.");
            client1.Close(treeId1, fileId1);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 sends CREATE request.");
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locks = new LOCK_ELEMENT[1];
            uint lockSequence = 0;
            locks[0].Offset = 0;
            locks[0].Length = (ulong)TestConfig.WriteBufferLengthInKb * 1024;
            locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 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 = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 sends WRITE request to write content to the locking range");
            status = client1.Write(
                treeId1,
                fileId1,
                content,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreNotEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                    BaseTestSite.CaptureRequirementIfAreEqual(
                        Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                        header.Status,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
                });
            #endregion

            #region From client2 to read and write the locking range of the same file after lock
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client2 to read and take shared lock on the locking range of the same file after lock");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client2 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client2 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client2.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client2.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId2;
            status = client2.TreeConnect(uncSharePath, out treeId2);
            FILEID fileId2;
            status = client2.Create(
                treeId2,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId2,
                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));
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends READ request to read a random area in the locking range of file \"{0}\" with offset: {1}, length: {2}",
                fileName, offset, length);
            status = client2.Read(treeId2, fileId2, offset, length, out data);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locksFromOtherOpen = new LOCK_ELEMENT[1];
            locksFromOtherOpen[0].Offset = offset;
            locksFromOtherOpen[0].Length = (ulong)length;
            locksFromOtherOpen[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to take a shared lock on random range of file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})",
                fileName, locksFromOtherOpen[0].Offset, locksFromOtherOpen[0].Length, locksFromOtherOpen[0].Flags.ToString());
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            locksFromOtherOpen[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to unlock the range");
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write a random area in the locking range of file \"{0}\" after lock", fileName);
            status = client2.Write(
                treeId2,
                fileId2,
                content,
                offset,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreNotEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                    BaseTestSite.CaptureRequirementIfAreEqual(
                        Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                        header.Status,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
                });
            #endregion

            #region From client1 unlock the range
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 unlocks the range");
            locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client1 attempts to unlock the range");
            status = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client1.Close(treeId1, fileId1);
            client1.TreeDisconnect(treeId1);
            client1.LogOff();
            #endregion

            #region From client2 write content to the previous locking range after unlock
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write content to the previous locking range after unlock");
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client2 attempts to write a random area in the locking range of file \"{0}\" after unlock", fileName);
            status = client2.Write(treeId2, fileId2, content, offset);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client2 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client2.Close(treeId2, fileId2);
            client2.TreeDisconnect(treeId2);
            client2.LogOff();
            #endregion
        }
        protected bool AccessShare(AccountCredential user, string sharePath)
        {
            bool accessSucceed = true;
            Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            try
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends NEGOTIATE message.");
                client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends SESSION_SETUP message using account: {0}@{1}.", user.AccountName, user.DomainName);
                client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, user, false);

                uint treeId;
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends TREE_CONNECT message to access share: {0}.", sharePath);
                client.TreeConnect(sharePath, out treeId, checker: (header, response) =>
                {
                    if (header.Status == Smb2Status.STATUS_SUCCESS)
                    {
                        BaseTestSite.Log.Add(LogEntryKind.Debug, "Access succeeded in TREE_CONNECT phase.");
                        accessSucceed = true;
                    }
                    else if (header.Status == Smb2Status.STATUS_ACCESS_DENIED)
                    {
                        BaseTestSite.Log.Add(LogEntryKind.Debug, "Access denied in TREE_CONNECT phase.");
                        accessSucceed = false;
                    }
                    else
                    {
                        BaseTestSite.Assert.Fail("Unexpected error code in TREE_CONNECT response: {0}", Smb2Status.GetStatusCode(header.Status));
                    }
                });

                if (!accessSucceed)
                {
                    client.LogOff();
                    return false;
                }

                FILEID fileId;
                Smb2CreateContextResponse[] createContexResponse;

                BaseTestSite.Log.Add(LogEntryKind.Debug, "Client sends CREATE request.");
                uint status = client.Create(
                    treeId,
                    null,
                    CreateOptions_Values.FILE_DIRECTORY_FILE,
                    out fileId,
                    out createContexResponse,
                    accessMask: AccessMask.FILE_READ_DATA | AccessMask.FILE_READ_ATTRIBUTES,
                    createDisposition: CreateDisposition_Values.FILE_OPEN,
                    checker: (header, response) =>
                    {
                        if (header.Status == Smb2Status.STATUS_SUCCESS)
                        {
                            BaseTestSite.Log.Add(LogEntryKind.Debug, "Access succeeded in CREATE phase.");
                            accessSucceed = true;
                        }
                        else if (header.Status == Smb2Status.STATUS_ACCESS_DENIED)
                        {
                            BaseTestSite.Log.Add(LogEntryKind.Debug, "Access denied in CREATE phase.");
                            accessSucceed = false;
                        }
                        else
                        {
                            BaseTestSite.Assert.Fail("Unexpected error code in CREATE response: {0}", Smb2Status.GetStatusCode(header.Status));
                        }
                    });

                if (status == Smb2Status.STATUS_SUCCESS)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF.");
                    client.Close(treeId, fileId);
                }
                client.TreeDisconnect(treeId);
                client.LogOff();
            }
            finally
            {
                client.Disconnect();
            }
            return accessSucceed;
        }
        public void DurableHandleV2_Reconnect_WithoutPersistence()
        {
            /// 1. Client requests a durable handle V2 without persistent flag
            /// 2. Lose connection by disabling NIC
            /// 3. Client reconnects the durable handle V2 without persistent flag.

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

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

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

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

            Guid                        createGuid = Guid.NewGuid();
            Guid                        leaseKey   = Guid.NewGuid();
            LeaseStateValues            leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING;
            FILEID                      fileIdBeforeDisconnection;
            Smb2CreateContextResponse[] serverCreateContexts = null;
            clientBeforeDisconnection.Create(
                treeIdBeforeDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdBeforeDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleRequestV2
                {
                    CreateGuid = createGuid,
                },
                new Smb2CreateRequestLeaseV2
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                }
            },
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status));
                CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue));
            });

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

            clientBeforeDisconnection.Disconnect();

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

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

            FILEID fileIdAfterDisconnection;
            clientAfterDisconnection.Create(
                treeIdAfterDisconnection,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileIdAfterDisconnection,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[] {
                new Smb2CreateDurableHandleReconnectV2
                {
                    CreateGuid = createGuid,
                    FileId     = new FILEID {
                        Persistent = fileIdBeforeDisconnection.Persistent
                    }
                },
                new Smb2CreateRequestLeaseV2
                {
                    LeaseKey   = leaseKey,
                    LeaseState = leaseState,
                }
            },
                shareAccess: ShareAccess_Values.NONE);

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

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

            clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection);
            clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection);
            clientAfterDisconnection.LogOff();
            clientAfterDisconnection.Disconnect();
        }
        public void BVT_SMB2Basic_QueryAndSet_FileInfo()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Starts a client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT.");
            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            client1.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            client1.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId1;
            client1.TreeConnect(uncSharePath, out treeId1);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with desired access set to GENERIC_READ and GENERIC_WRITE to create a file.");
            Smb2CreateContextResponse[] serverCreateContexts;
            CREATE_Response? createResponse = null;
            string fileName = Guid.NewGuid().ToString() + ".txt";
            FILEID fileId1;
            client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts,
                accessMask: AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE,
                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));

                        BaseTestSite.Log.Add(LogEntryKind.TestStep,
                            "FileBasicInformation in CREATE response: \r\nCreationTime: {0}\r\nLastAccessTime:{1}\r\nLastWriteTime: {2}\r\nChangeTime: {3}\r\nFileAttributes: {4}",
                            Smb2Utility.ConvertToDateTimeUtc(response.CreationTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                            Smb2Utility.ConvertToDateTimeUtc(response.LastAccessTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                            Smb2Utility.ConvertToDateTimeUtc(response.LastWriteTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                            Smb2Utility.ConvertToDateTimeUtc(response.ChangeTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                            response.FileAttributes);
                        createResponse = response;
                    });

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends QUERY_INFO request to query file attributes.");
            byte[] outputBuffer;
            client1.QueryFileAttributes(
                treeId1,
                (byte)FileInformationClasses.FileBasicInformation,
                QUERY_INFO_Request_Flags_Values.SL_RESTART_SCAN,
                fileId1,
                new byte[0] { },
                out outputBuffer);

            FileBasicInformation fileBasicInfo = TypeMarshal.ToStruct<FileBasicInformation>(outputBuffer);
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "FileBasicInformation in QUERY_INFO response: \r\nCreationTime: {0}\r\nLastAccessTime:{1}\r\nLastWriteTime: {2}\r\nChangeTime: {3}\r\nFileAttributes: {4}",
                Smb2Utility.ConvertToDateTimeUtc(fileBasicInfo.CreationTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                Smb2Utility.ConvertToDateTimeUtc(fileBasicInfo.LastAccessTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                Smb2Utility.ConvertToDateTimeUtc(fileBasicInfo.LastWriteTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                Smb2Utility.ConvertToDateTimeUtc(fileBasicInfo.ChangeTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"),
                fileBasicInfo.FileAttributes);

            BaseTestSite.Assert.AreEqual(createResponse.Value.CreationTime, fileBasicInfo.CreationTime, "CreationTime received in QUERY_INFO response should be identical with that got in CREATE response");
            BaseTestSite.Assert.AreEqual(createResponse.Value.LastAccessTime, fileBasicInfo.LastAccessTime, "LastAccessTime received in QUERY_INFO response should be identical with that got in CREATE response");
            BaseTestSite.Assert.AreEqual(createResponse.Value.LastWriteTime, fileBasicInfo.LastWriteTime, "LastWriteTime received in QUERY_INFO response should be identical with that got in CREATE response");
            BaseTestSite.Assert.AreEqual(createResponse.Value.ChangeTime, fileBasicInfo.ChangeTime, "ChangeTime received in QUERY_INFO response should be identical with that got in CREATE response");
            BaseTestSite.Assert.AreEqual(createResponse.Value.FileAttributes, fileBasicInfo.FileAttributes, "FileAttributes received in QUERY_INFO response should be identical with that got in CREATE response");

            FileBasicInformation fileBasicInfoToSet = fileBasicInfo;
            DateTime dateTimeToSet = DateTime.UtcNow;
            fileBasicInfoToSet.LastAccessTime = Smb2Utility.ConvertToFileTime(dateTimeToSet);

            byte[] inputBuffer;
            inputBuffer = TypeMarshal.ToBytes<FileBasicInformation>(fileBasicInfoToSet);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client sends SetFileAttributes request to set LastAccessTime for the file to {0}", dateTimeToSet.ToString("MM/dd/yyy hh:mm:ss.ffffff"));
            client1.SetFileAttributes(
                treeId1,
                (byte)FileInformationClasses.FileBasicInformation,
                fileId1,
                inputBuffer);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends QUERY request to query file attributes.");
            client1.QueryFileAttributes(
                treeId1,
                (byte)FileInformationClasses.FileBasicInformation,
                QUERY_INFO_Request_Flags_Values.SL_RESTART_SCAN,
                fileId1,
                new byte[0] { },
                out outputBuffer);
            fileBasicInfo = TypeMarshal.ToStruct<FileBasicInformation>(outputBuffer);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "LastAccessTime in QUERY_INFO response after SET_INFO {0}",
                Smb2Utility.ConvertToDateTimeUtc(fileBasicInfo.LastAccessTime).ToString("MM/dd/yyy hh:mm:ss.ffffff"));

            BaseTestSite.Assert.AreNotEqual(
                createResponse.Value.LastAccessTime,
                fileBasicInfo.LastAccessTime,
                "LastAccessTime (dwHighDateTime:{0}, dwLowDateTime:{1}) after SET_INFO should not be equal to the value (dwHighDateTime:{2}, dwLowDateTime:{3}) before SET_INFO",
                fileBasicInfo.LastAccessTime.dwHighDateTime, fileBasicInfo.LastAccessTime.dwLowDateTime, createResponse.Value.LastAccessTime.dwHighDateTime, createResponse.Value.LastAccessTime.dwLowDateTime);

            BaseTestSite.Assert.AreEqual(
                fileBasicInfoToSet.LastAccessTime,
                fileBasicInfo.LastAccessTime,
                "LastAccessTime (dwHighDateTime:{0}, dwLowDateTime:{1}) queried after SET_INFO should be equal to the desired value (dwHighDateTime:{2}, dwLowDateTime:{3})",
                fileBasicInfo.LastAccessTime.dwHighDateTime, fileBasicInfo.LastAccessTime.dwLowDateTime, fileBasicInfoToSet.LastAccessTime.dwHighDateTime, fileBasicInfoToSet.LastAccessTime.dwLowDateTime);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client1.Close(treeId1, fileId1);
            client1.TreeDisconnect(treeId1);
            client1.LogOff();
        }
 private void Logoff(Smb2FunctionalClient client)
 {
     client.LogOff();
     client.Disconnect();
 }
        public void InvalidCreateRequestStructureSize()
        {
            uint status;

            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, this.Site);
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

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

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

            uint treeId;
            status = client1.TreeConnect(uncSharePath, out treeId);
            string fileName = "BVT_SMB2Basic_InvalidCreateRequestStructureSize" + Guid.NewGuid();

            FILEID fileID;
            Smb2CreateContextResponse[] serverCreateContexts;

            // [MS-SMB2] Section 2.2.13 SMB2 CREATE Request
            // StructureSize (2 bytes):  The client MUST set this field to 57, indicating the size of the request structure, not including the header.
            // The client MUST set it to this value regardless of how long Buffer[] actually is in the request being sent.

            // So set the StuctureSize to 58 here to make "the size of the SMB2 CREATE Request is less than specified in the StructureSize field".
            client1.BeforeSendingPacket(ReplacePacketByStructureSize);
            status = client1.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileID,
                out serverCreateContexts,
                checker: (header, response) => { });

            BaseTestSite.Assert.AreEqual(
                Smb2Status.STATUS_INVALID_PARAMETER,
                status,
                "The size of the SMB2 CREATE Request (excluding the SMB2 header) is less than specified in the StructureSize field, then the request MUST be failed with STATUS_ INVALID_PARAMETER");

            client1.TreeDisconnect(treeId);
            client1.LogOff();
        }