예제 #1
0
        public void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ClientSupportsEncryptionType clientSupportsEncryptionType)
        {
            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);
            testClient.Smb2Client.Disconnected += new Action(OnServerDisconnected);

            DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported));

            //Set capabilities according to isClientSupportsEncryption
            Capabilities_Values commonCapability     = 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;
            Capabilities_Values encryptionCapability = (clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption) ? (commonCapability | Capabilities_Values.GLOBAL_CAP_ENCRYPTION) : commonCapability;

            uint               status;
            DialectRevision    selectedDialect;
            NEGOTIATE_Response?negotiateResponse = null;

            status = testClient.Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: encryptionCapability,
                checker: (header, response) =>
            {
                Site.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

                negotiateResponse = response;
            },
                ifHandleRejectUnencryptedAccessSeparately: true,
                ifAddGLOBAL_CAP_ENCRYPTION: false
                );

            selectedDialect = negotiateResponse.Value.DialectRevision;

            if (Smb2Utility.IsSmb3xFamily(selectedDialect) && clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption)
            {
                /// TD section 3.3.5.4
                /// SMB2_GLOBAL_CAP_ENCRYPTION if Connection.Dialect belongs to the SMB 3.x dialect, the server supports encryption,
                /// and SMB2_GLOBAL_CAP_ENCRYPTION is set in the Capabilities field of the request
                Site.Assert.IsTrue(
                    negotiateResponse.Value.Capabilities.HasFlag(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION),
                    "SMB2_GLOBAL_CAP_ENCRYPTION should be set in the negotiate response.");
            }
            else
            {
                Site.Assert.IsFalse(
                    negotiateResponse.Value.Capabilities.HasFlag(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION),
                    "SMB2_GLOBAL_CAP_ENCRYPTION should not be set in the negotiate response.");
            }
        }
예제 #2
0
        public void Smb2OverRdma_Smb300_Read_SMB2_CHANNEL_RDMA_V1_INVALIDATE()
        {
            EstablishConnectionAndOpenFile(fileName, Smb300OnlyDialects);

            uint fileSize = smbdAdapter.Smb2MaxReadSize;

            byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)fileSize);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE");
            SmbdBufferDescriptorV1 descp;
            NtStatus status = smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE,
                out descp);

            BaseTestSite.Assert.AreEqual(
                NtStatus.STATUS_SUCCESS,
                status,
                "Register buffer should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA.");
            status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1, descp);
            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_SUCCESS,
                status,
                "SMB2 WRITE over RDMA should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 READ.");
            smbdAdapter.SmbdRegisterBuffer(
                fileSize,
                SmbdBufferReadWrite.RDMA_WRITE_PERMISSION_FOR_READ_FILE,
                out descp);
            byte[] channelInfo = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(descp);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Read content from file over RDMA.");
            READ_Response readResponse;

            byte[] readData;
            status = (NtStatus)smbdAdapter.Smb2ReadOverRdmaChannel(
                0,
                (uint)fileSize,
                channelInfo,
                out readResponse,
                out readData,
                Channel_Values.CHANNEL_RDMA_V1_INVALIDATE);

            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_INVALID_PARAMETER,
                status,
                "SMB2 READ over RDMA should fail with STATUS_INVALID_PARAMETER if set Channel CHANNEL_RDMA_V1_INVALIDATE on SMB 3.0 dialect.");
        }
        public void BVT_DuplicateExtentsToFile()
        {
            // Check the platform and ReFS file system.
            // Prepare
            // Create a file
            uint   treeId;
            FILEID srcFileId;
            string fileName    = "DuplicateExtentsToFile_" + Guid.NewGuid() + ".txt";
            int    clusterSize = TestConfig.VolumnClusterSize;
            string content     = Smb2Utility.CreateRandomString(clusterSize * 2);

            NewTestFile(smb2Functionalclient, fileName, content, out treeId, out srcFileId);
            long sourceFileOffset = 0;
            long targetFileOffset = clusterSize * 1024;
            long byteCount        = clusterSize * 1024;

            smb2Functionalclient.DuplicateExtentsToFile(
                treeId,
                srcFileId,
                sourceFileOffset,
                targetFileOffset,
                byteCount,
                checker: (Packet_Header header, IOCTL_Response response) =>
            {
                if (header.Status == Smb2Status.STATUS_INVALID_DEVICE_REQUEST)
                {
                    // check if the server advertises the FILE_SUPPROTS_BLOCK_REFCOUNTING flag for a given open.
                    bool res = FSInfo_Query_FileFsAttributeInformation_IsSupported(smb2Functionalclient, treeId, srcFileId, FileSystemAttributes_Values.FILE_SUPPORTS_BLOCK_REFCOUNTING);
                    BaseTestSite.Assert.AreEqual(false, res,
                                                 "If the server adverties the FILE_SUPPORTS_BLOCK_REFCOUNTING flag for a given Open, " +
                                                 "the server must support the FSCTL_DUPLICATE_EXTENTS_TO_FILE command, " +
                                                 "as specified in [MS-FSA] section 2.1.5.9.4.");
                }
                else if (header.Status == Smb2Status.STATUS_SUCCESS)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "The server supports FSCTL_DUPLICATE_EXTENTS_TO_FILE, and response with STATUS_SUCCESS.");
                }
                else if (header.Status == Smb2Status.STATUS_MEDIA_WRITE_PROTECTED)
                {
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "If Open.File.Volume.IsReadOnly is TRUE, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.");
                }
                else
                {
                    BaseTestSite.Log.Add(LogEntryKind.Warning, "Unexpected Response: {0}", Smb2Status.GetStatusCode(header.Status));
                }
            });

            // Check the file content.

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

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

            #region TreeConnect

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

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

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

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

            #endregion
        }
        public void MultipleChannel_NicRedundantOnServer()
        {
            string contentWrite;
            string contentRead;
            uint   treeId;
            FILEID fileId;

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL);
            TestConfig.CheckSigning();
            #endregion

            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            BaseTestSite.Assert.IsTrue(
                clientIps.Count > 0,
                "Client should have at least one IP address");
            BaseTestSite.Assert.IsTrue(
                serverIps.Count > 1,
                "Server should have more than one IP address");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to write content to file from main channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString());
            WriteFromMainChannel(
                serverIps[0],
                clientIps[0],
                contentWrite,
                true,
                out treeId,
                out fileId);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to read content from file from alternative channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[1].ToString());
            ReadFromAlternativeChannel(
                serverIps[1],
                clientIps[0],
                (uint)contentWrite.Length,
                treeId,
                fileId,
                out contentRead);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Verify the contents read from alternative channel are the same as the one written by main channel.");
            BaseTestSite.Assert.IsTrue(
                contentWrite.Equals(contentRead),
                "Content should be identical.");
        }
        public void FileServerFailover_DirectoryLeasing()
        {
            uncSharePath  = Smb2Utility.GetUncPath(TestConfig.ClusteredFileServerName, TestConfig.ClusteredFileShare);
            testDirectory = CreateTestDirectory(uncSharePath);

            // Add expected NewLeaseState
            expectedNewLeaseState = LeaseStateValues.SMB2_LEASE_NONE;

            FileServerFailoverWithLeasing(
                true,
                LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING,
                AccessMask.GENERIC_READ,
                AccessMask.DELETE);
        }
        /// <summary>
        /// Write file content over RDMA. The file content will be writen with specific number of operations.
        /// The total size of the write content is SMB2 negotiated MaxWriteize, so content size
        /// in each SMB2 WRITE request is ( MaxWriteSize / operationCount )
        /// </summary>
        /// <param name="operationCount">count of SMB2 WRITE operation</param>
        public void WriteOverRdma(uint operationCount = 1)
        {
            string fileName = CreateRandomFileName();

            InitSmbdConnectionForTestCases(fileName);

            uint writeSize = smbdAdapter.Smb2MaxWriteSize / operationCount;
            uint totalSize = writeSize * operationCount;

            // SMB2 Write file
            byte[] fileContent = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)writeSize));

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send each write request according SMB2 write file limit.");
            for (int i = 0; i < operationCount; ++i)
            {
                // register memory and get buffer descriptor
                SmbdBufferDescriptorV1 descp;
                smbdAdapter.SmbdRegisterBuffer(
                    writeSize,
                    SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE,
                    out descp
                    );
                smbdAdapter.SmbdWriteRegisteredBuffer(fileContent, descp);
                byte[] channelInfo = TypeMarshal.ToBytes <SmbdBufferDescriptorV1>(descp);

                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA.");
                WRITE_Response writeResponse;
                NtStatus       status = (NtStatus)smbdAdapter.Smb2WriteOverRdmaChannel(
                    (UInt64)i * writeSize,
                    channelInfo,
                    writeSize,
                    out writeResponse
                    );
                BaseTestSite.Assert.AreEqual <NtStatus>(
                    NtStatus.STATUS_SUCCESS,
                    status,
                    "Status of SMB2 Write File offset {0} is {1}", i * writeSize, status);
                BaseTestSite.Assert.AreEqual <uint>(
                    (uint)writeSize,
                    writeResponse.Count,
                    "DataLength in WRITE response is {0}", writeResponse.Count);
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Validate file content.");
            ValidateFileContent(fileContent, totalSize);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Close file.");
            smbdAdapter.Smb2CloseFile();
        }
        public void BVT_MultipleChannel_NicRedundantOnBoth()
        {
            string contentWrite;
            string contentRead;
            uint   treeId;
            FILEID fileId;

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb30);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL);
            // According to TD, server must support signing when it supports multichannel.
            // 3.3.5.5   Receiving an SMB2 SESSION_SETUP Request
            // 4. If Connection.Dialect belongs to the SMB 3.x dialect family, IsMultiChannelCapable is TRUE, and the SMB2_SESSION_FLAG_BINDING bit is
            //    set in the Flags field of the request, the server MUST perform the following:
            //    If the SMB2_FLAGS_SIGNED bit is not set in the Flags field in the header, the server MUST fail the request with error STATUS_INVALID_PARAMETER.
            TestConfig.CheckSigning();
            #endregion

            contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            BaseTestSite.Assert.IsTrue(clientIps.Count > 1, "Client should have more than one IP address");
            BaseTestSite.Assert.IsTrue(serverIps.Count > 1, "Server should have more than one IP address");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to write content to file from main channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString());
            WriteFromMainChannel(
                serverIps[0],
                clientIps[0],
                contentWrite,
                true,
                out treeId,
                out fileId);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start to read content from file from alternative channel with client {0} and server {1}", clientIps[1].ToString(), serverIps[1].ToString());
            ReadFromAlternativeChannel(
                serverIps[1],
                clientIps[1],
                (uint)contentWrite.Length,
                treeId,
                fileId,
                out contentRead);

            BaseTestSite.Assert.IsTrue(
                contentWrite.Equals(contentRead),
                "Content read should be identical to content written.");
        }
예제 #9
0
        private void ConnectToShare(
            Smb2FunctionalClient client,
            Guid clientGuid,
            out uint treeId)
        {
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.CAShareServerName, TestConfig.CAShareServerIP);

            // Negotiate
            client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES,
                clientGuid: clientGuid,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual <NtStatus>(
                    NtStatus.STATUS_SUCCESS,
                    (NtStatus)header.Status,
                    "Negotiate should be successfully");

                TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
                TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, response);
            }
                );

            // SMB2 SESSION SETUP
            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.CAShareServerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            // SMB2 Tree Connect
            client.TreeConnect(
                Smb2Utility.GetUncPath(TestConfig.CAShareServerName, TestConfig.CAShareName),
                out treeId,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreEqual <NtStatus>(
                    NtStatus.STATUS_SUCCESS,
                    (NtStatus)header.Status,
                    "TreeConnect should be successfully");

                // Check IsCA
                BaseTestSite.Assert.IsTrue(
                    response.Capabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY),
                    "Share should support capabilities of SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY ");
            });
        }
예제 #10
0
        public void ReadConfig(out CreditMgmtConfig c)
        {
            uncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);

            c = new CreditMgmtConfig
            {
                MaxSmbVersionSupported = ModelUtility.GetModelDialectRevision(testConfig.MaxSmbVersionSupported),
                Platform = testConfig.Platform == Platform.WindowsServer2016 ? Platform.WindowsServer2012R2 : testConfig.Platform,
                IsMultiCreditSupportedOnServer = testConfig.IsMultiCreditSupported
            };

            config = c;

            Site.Log.Add(LogEntryKind.Debug, c.ToString());
        }
        /// <summary>
        /// Build a Smb2TreeConnectRequestPacket from a byte array
        /// </summary>
        /// <param name="data">The byte array</param>
        /// <param name="consumedLen">The consumed data length</param>
        /// <param name="expectedLen">The expected data length</param>
        internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen)
        {
            consumedLen  = 0;
            this.Header  = TypeMarshal.ToStruct <Packet_Header>(data, ref consumedLen);
            this.PayLoad = Smb2Utility.UnmarshalStructure <TREE_CONNECT_Request>(data.Skip(consumedLen).ToArray()); //based on .net unmarshal
            consumedLen += Marshal.SizeOf(typeof(TREE_CONNECT_Request));

            var packetBuffer = this as IPacketBuffer;
            int bufferLength = (int)packetBuffer.BufferLength;

            this.Buffer  = data.Skip(consumedLen).Take(bufferLength).ToArray();
            consumedLen += bufferLength;

            expectedLen = 0;
        }
        public static byte[] Decrypt(byte[] bytes, Dictionary <ulong, Smb2CryptoInfo> cryptoInfoTable, Smb2Role role)
        {
            // Client: If the size of the message received from the server is not greater than the size of SMB2 TRANSFORM_HEADER as specified, the client MUST discard the message.
            // Server: If the size of the message received from the client is not greater than the size of the SMB2 TRANSFORM_HEADER, the server MUST disconnect the connection.
            int minimumLength = Marshal.SizeOf(typeof(Transform_Header));

            if (bytes.Length < minimumLength)
            {
                throw new InvalidOperationException(
                          String.Format(
                              "Too less data for encrypted message. Expected length more than {0}, actual {1}.",
                              minimumLength,
                              bytes.Length
                              )
                          );
            }

            Transform_Header transformHeader = Smb2Utility.UnmarshalStructure <Transform_Header>(bytes);

            // Client: If the Flags/EncryptionAlgorithm in the SMB2 TRANSFORM_HEADER is not 0x0001, the client MUST discard the message.
            // Server: If the Flags/EncryptionAlgorithm in the SMB2 TRANSFORM_HEADER is not 0x0001, the server MUST disconnect the connection.
            if (transformHeader.Flags != TransformHeaderFlags.Encrypted)
            {
                throw new InvalidOperationException(
                          String.Format(
                              "Flags/EncryptionAlgorithm field is invalid for encrypted message. Expected value 0x0001, actual {0}.",
                              (ushort)transformHeader.Flags
                              )
                          );
            }

            if (transformHeader.SessionId == 0 || !cryptoInfoTable.ContainsKey(transformHeader.SessionId))
            {
                throw new InvalidOperationException("Invalid SessionId in TRANSFORM_HEADER.");
            }

            Smb2CryptoInfo cryptoInfo = cryptoInfoTable[transformHeader.SessionId];

            using (var bcrypt = new BCryptAlgorithm("AES"))
            {
                int nonceLength       = 0;
                BCryptCipherMode mode = BCryptCipherMode.NotAvailable;
                GetCryptoParams(cryptoInfo, CryptoOperationType.Decrypt, out mode, out nonceLength);
                bcrypt.Mode = mode;
                bcrypt.Key  = role == Smb2Role.Server ? cryptoInfo.ServerInKey : cryptoInfo.ServerOutKey;
                return(bcrypt.Decrypt(bytes.Skip(52).ToArray(), transformHeader.Nonce.ToByteArray().Take(nonceLength).ToArray(), bytes.Skip(20).Take(32).ToArray(), transformHeader.Signature));
            }
        }
        /// <summary>
        /// Negotiate, SessionSetup and TreeConnect
        /// </summary>
        public void SetupConnection(ModelDialectRevision dialect, ModelCapabilities capabilities, SecurityMode_Values securityMode)
        {
            #region Connect to server
            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);
            #endregion

            // It MUST be a GUID generated by the client, if the Dialects field contains a value other than 0x0202. Otherwise, the client MUST set this to 0.
            Guid clientGuid = (dialect == ModelDialectRevision.Smb2002) ? Guid.Empty : Guid.NewGuid();

            #region negotiate
            testClient.Negotiate(
                Packet_Header_Flags_Values.NONE,
                Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(dialect)),
                securityMode,
                (Capabilities_Values)capabilities,
                clientGuid,
                (header, response) =>
            {
                Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command);
                negotiateResponse = response;
            });
            #endregion

            #region session setup
            testClient.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken,
                (SESSION_SETUP_Request_SecurityMode_Values)securityMode);
            #endregion

            #region treeconnect
            testClient.TreeConnect(
                Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare),
                out treeId);
            #endregion

            Connection_Dialect            = ModelUtility.GetModelDialectRevision(negotiateResponse.DialectRevision);
            Connection_ClientCapabilities = (Capabilities_Values)capabilities;
            if (dialect >= ModelDialectRevision.Smb30) // GLOBAL_CAP_ENCRYPTION will be added in Functional client when dialect >= SMB30
            {
                Connection_ClientCapabilities |= Capabilities_Values.GLOBAL_CAP_ENCRYPTION;
            }
            Connection_ClientSecurityMode = securityMode;
            Connection_ClientGuid         = clientGuid;
        }
        /// <summary>
        /// Covert to a byte array
        /// </summary>
        /// <returns>The byte array</returns>
        public override byte[] ToBytes()
        {
            byte[] messageData = TypeMarshal.ToBytes(this.Header);
            messageData = messageData.Concat(Smb2Utility.MarshalStructure(this.PayLoad)).ToArray();

            if (this.Dialects != null & this.Dialects.Length > 0)
            {
                messageData = messageData.Concat(Smb2Utility.MarshalStructArray(Dialects)).ToArray();
            }

            if (NegotiateContext_PREAUTH != null)
            {
                Smb2Utility.Align8(ref messageData);
                messageData = messageData.Concat(TypeMarshal.ToBytes <SMB2_PREAUTH_INTEGRITY_CAPABILITIES>(NegotiateContext_PREAUTH.Value)).ToArray();
            }

            if (NegotiateContext_ENCRYPTION != null)
            {
                Smb2Utility.Align8(ref messageData);
                messageData = messageData.Concat(TypeMarshal.ToBytes <SMB2_ENCRYPTION_CAPABILITIES>(NegotiateContext_ENCRYPTION.Value)).ToArray();
            }

            if (NegotiateContext_COMPRESSION != null)
            {
                Smb2Utility.Align8(ref messageData);
                messageData = messageData.Concat(TypeMarshal.ToBytes <SMB2_COMPRESSION_CAPABILITIES>(NegotiateContext_COMPRESSION.Value)).ToArray();
            }

            if (NegotiateContext_NETNAME != null)
            {
                Smb2Utility.Align8(ref messageData);
                messageData = messageData.Concat(NegotiateContext_NETNAME.Marshal()).ToArray();
            }

            if (NegotiateContext_SIGNING != null)
            {
                Smb2Utility.Align8(ref messageData);
                messageData = messageData.Concat(TypeMarshal.ToBytes <SMB2_SIGNING_CAPABILITIES>(NegotiateContext_SIGNING.Value)).ToArray();
            }

            if (NegotiateContext_RDMA != null)
            {
                Smb2Utility.Align8(ref messageData);
                messageData = messageData.Concat(TypeMarshal.ToBytes <SMB2_RDMA_TRANSFORM_CAPABILITIES>(NegotiateContext_RDMA.Value)).ToArray();
            }

            return(messageData);
        }
예제 #15
0
        public bool ConnectToShare(string serverIp, string clientIp)
        {
            try
            {
                using (var client = new SMBDClient(DetectionInfo.ConnectionTimeout))
                {
                    client.Connect(IPAddress.Parse(serverIp), IPAddress.Parse(clientIp));

                    client.Smb2Negotiate(DetectionInfo.SupportedSmbDialects);

                    client.Smb2SessionSetup(DetectionInfo.Authentication, DetectionInfo.DomainName, DetectionInfo.SUTName, DetectionInfo.UserName, DetectionInfo.Password);

                    string path = Smb2Utility.GetUncPath(DetectionInfo.SUTName, DetectionInfo.ShareFolder);

                    uint treeId;

                    client.Smb2TreeConnect(path, out treeId);

                    FILEID fileId;

                    client.CreateRandomFile(treeId, out fileId);

                    uint fileLength = client.CalculateSmb2MaxReadWriteSize();

                    var buffer = Smb2Utility.CreateRandomByteArray((int)fileLength);

                    client.Smb2Write(treeId, fileId, 0, buffer);

                    byte[] output;

                    client.Smb2Read(treeId, fileId, 0, fileLength, out output);

                    bool result = Enumerable.SequenceEqual(buffer, output);

                    if (!result)
                    {
                        DetectorUtil.WriteLog("The content of read and write is inconsistent.");
                    }

                    return(result);
                }
            }
            catch (Exception ex)
            {
                DetectorUtil.WriteLog(String.Format("ConnectToShare threw exception: {0}", ex));
                return(false);
            }
        }
 private static byte[] Sign(Smb2CryptoInfo cryptoInfo, byte[] original)
 {
     if (Smb2Utility.IsSmb2Family(cryptoInfo.Dialect))
     {
         // [MS-SMB2] 3.1.4.1
         // 3. If Connection.Dialect is "2.002" or "2.100", the sender MUST compute a 32-byte hash using HMAC-SHA256 over the entire message,
         HMACSHA256 hmacSha = new HMACSHA256(cryptoInfo.SigningKey);
         return(hmacSha.ComputeHash(original));
     }
     else
     {
         // [MS-SMB2] 3.1.4.1
         // 2. If Connection.Dialect belongs to the SMB 3.x dialect family, the sender MUST compute a 16-byte hash using AES-128-CMAC over the entire message
         return(AesCmac128.ComputeHash(cryptoInfo.SigningKey, original));
     }
 }
        /// <summary>
        /// The two client connects to the two IP addresses of scaleout file server
        /// Negotiate, SessionSetup, TreeConnect
        /// </summary>
        private Smb2FunctionalClient InitializeClient(IPAddress ip, out uint treeId)
        {
            Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            client.ConnectToServerOverTCP(ip);
            client.Negotiate(
                Smb2Utility.GetDialects(DialectRevision.Smb21),
                testConfig.IsSMB1NegotiateEnabled);
            client.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.ScaleOutFileServerName,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);
            client.TreeConnect(Smb2Utility.GetUncPath(testConfig.ScaleOutFileServerName, testConfig.CAShareName), out treeId);

            return client;
        }
예제 #18
0
        /// <summary>
        /// Build a Smb2CompressedPacket from a byte array.
        /// </summary>
        /// <param name="data">The byte array.</param>
        /// <param name="consumedLen">The consumed data length.</param>
        /// <param name="expectedLen">The expected data length.</param>
        internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen)
        {
            int minimumLength = Marshal.SizeOf(Header);

            if (data.Length < minimumLength)
            {
                throw new InvalidOleVariantTypeException("Not enough data for Transform_Header!");
            }

            Header = Smb2Utility.UnmarshalStructure <Transform_Header>(data.Take(minimumLength).ToArray());

            EncryptdData = data.Skip(minimumLength).ToArray();

            consumedLen = data.Length;
            expectedLen = 0;
        }
        protected void RestoreClusterNodes(params string[] servers)
        {
            // Restore cluster node
            foreach (string node in servers)
            {
                DoUntilSucceed(() =>
                {
                    // Enable cluster node
                    BaseTestSite.Log.Add(LogEntryKind.Debug, "Enable cluster node {0}", node);
                    if (sutController.EnableClusterNode(node))
                    {
                        // Check node availability
                        BaseTestSite.Log.Add(LogEntryKind.Debug, "Make sure cluster node {0} is in Running state", node);
                        return(sutController.GetClusterNodeStatus(node) == "Running");
                    }
                    return(false);
                }, TestConfig.FailoverTimeout,
                               "Retry to restore cluster node {0} until succeed within timeout span", node);
            }

            // Only works for windows SUT.
            if (!TestConfig.IsWindowsPlatform)
            {
                return;
            }

            // Check cluster resource availability
            foreach (string resource in new string[] { TestConfig.ClusteredFileServerName, TestConfig.ClusteredScaleOutFileServerName })
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Make sure cluster resource {0} is ready.", resource);

                DoUntilSucceed(() => !string.IsNullOrEmpty(sutController.GetClusterResourceOwner(resource)), TestConfig.FailoverTimeout,
                               "Retry to make sure cluster resource {0} is ready.", resource);

                BaseTestSite.Log.Add(LogEntryKind.Debug, "Make sure cluster share {0} is ready.", TestConfig.ClusteredFileShare);
                string uncSharePath  = Smb2Utility.GetUncPath(resource, TestConfig.ClusteredFileShare);
                string testDirectory = "RestoreCluster_" + Guid.NewGuid().ToString();

                DoUntilSucceed(() => sutProtocolController.CreateDirectory(uncSharePath, testDirectory),
                               testConfig.Timeout,
                               "Retry to make sure cluster share is ready by creating test directory.");

                DoUntilSucceed(() => sutProtocolController.DeleteDirectory(uncSharePath, testDirectory),
                               testConfig.Timeout,
                               "Retry to make sure cluster share is ready by deleting test directory.");
            }
        }
        /// <summary>
        /// Build a Smb2Packet from a byte array
        /// </summary>
        /// <param name="data">The byte array</param>
        /// <param name="consumedLen">The consumed data length</param>
        /// <param name="expectedLen">The expected data length</param>
        internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen)
        {
            consumedLen = 0;
            this.Header = TypeMarshal.ToStruct <Packet_Header>(data, ref consumedLen);

            byte[] tempData = data.Skip(consumedLen).ToArray();
            this.PayLoad = Smb2Utility.UnmarshalStructure <NEGOTIATE_Request>(tempData);
            consumedLen += Marshal.SizeOf(this.PayLoad);

            this.Buffer = data.Skip(consumedLen).ToArray(); //Dialects + Padding + NegotiateContextList

            if (PayLoad.DialectCount > 0)
            {
                this.Dialects = Smb2Utility.UnmarshalStructArray <DialectRevision>(Buffer, PayLoad.DialectCount);
                consumedLen  += PayLoad.DialectCount * sizeof(DialectRevision);
            }

            while (data.Length > consumedLen)
            {
                // Skip padding
                int paddingLen = 8 - (consumedLen) % 8;
                if (paddingLen != 8)
                {
                    if (data.Length - consumedLen <= paddingLen)
                    {
                        break;
                    }
                    consumedLen += paddingLen;
                }

                if (data.Length - consumedLen < 8)
                {
                    break;
                }
                SMB2_NEGOTIATE_CONTEXT_Type_Values contextType = (SMB2_NEGOTIATE_CONTEXT_Type_Values)BitConverter.ToUInt16(data, consumedLen);
                if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_PREAUTH_INTEGRITY_CAPABILITIES)
                {
                    this.NegotiateContext_PREAUTH = TypeMarshal.ToStruct <SMB2_PREAUTH_INTEGRITY_CAPABILITIES>(data, ref consumedLen);
                }
                else if (contextType == SMB2_NEGOTIATE_CONTEXT_Type_Values.SMB2_ENCRYPTION_CAPABILITIES)
                {
                    this.NegotiateContext_ENCRYPTION = TypeMarshal.ToStruct <SMB2_ENCRYPTION_CAPABILITIES>(data, ref consumedLen);
                }
            }

            expectedLen = 0;
        }
예제 #21
0
        /// <summary>
        /// Build a Smb2CompressedPacket from a byte array.
        /// </summary>
        /// <param name="data">The byte array.</param>
        /// <param name="consumedLen">The consumed data length.</param>
        /// <param name="expectedLen">The expected data length.</param>
        internal override void FromBytes(byte[] data, out int consumedLen, out int expectedLen)
        {
            int minimumLength = Marshal.SizeOf(Header);

            if (data.Length < minimumLength)
            {
                throw new InvalidOperationException("[MS-SMB2] section 3.3.5.2.1.1 If the size of the message received from the client is not greater than" +
                                                    "the size of the SMB2 TRANSFORM_HEADER, the server MUST disconnect the connection.");
            }

            Header = Smb2Utility.UnmarshalStructure <Transform_Header>(data.Take(minimumLength).ToArray());

            EncryptdData = data.Skip(minimumLength).ToArray();

            consumedLen = data.Length;
            expectedLen = 0;
        }
예제 #22
0
        public void BVT_Smb2OverRdma_Smb302_Write_SMB2_CHANNEL_RDMA_V1_INVALIDATE()
        {
            EstablishConnectionAndOpenFile(fileName, Smb302AboveDialects);

            uint writeSize = smbdAdapter.Smb2MaxWriteSize;

            byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)writeSize);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE");
            SmbdBufferDescriptorV1 descp;
            NtStatus status = smbdAdapter.SmbdRegisterBuffer(
                writeSize,
                SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE,
                out descp);

            BaseTestSite.Assert.AreEqual(
                NtStatus.STATUS_SUCCESS,
                status,
                "Register buffer should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA.");
            status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1_INVALIDATE, descp);
            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_SUCCESS,
                status,
                "SMB2 WRITE over RDMA should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify file content.");
            ValidateFileContent(fileContent);

            try
            {
                fileContent = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)writeSize));

                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send Smb2 WRITE request using same descriptor which should be invalidated.");
                status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1_INVALIDATE, descp);
            }
            catch
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Verify connection is terminated .");
                smbdAdapter.WaitRdmaDisconnect();
            }

            BaseTestSite.Assert.IsFalse(smbdAdapter.ClientConnection.Endpoint.IsConnected, "Connection should be terminated when accessing a memory window which is already invalidated.");
        }
        /// <summary>
        /// Initialize the test client by
        /// ConnectToServer, Negotiate, SessionSetup and TreeConnect
        /// </summary>
        private Smb2FunctionalClient InitializeClient(IPAddress ip, out uint treeId)
        {
            Smb2FunctionalClient client = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);

            client.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, ip);

            client.Negotiate(
                // Model cases only test Dialect lower than 3.11
                Smb2Utility.GetDialects(testConfig.MaxSmbVersionClientSupported < DialectRevision.Smb311 ? testConfig.MaxSmbVersionClientSupported : DialectRevision.Smb302),
                testConfig.IsSMB1NegotiateEnabled);
            client.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);
            client.TreeConnect(Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare), out treeId);
            return(client);
        }
        protected void ConnectToVHD()
        {
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.FileServerNameContainingSqosVHD, TestConfig.FileServerIPContainingSqosVHD);
            BaseTestSite.Log.Add(LogEntryKind.TestStep,
                                 "Client creates an Open to a VHDX file by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE");
            client.Negotiate(
                TestConfig.RequestDialects,
                TestConfig.IsSMB1NegotiateEnabled);
            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.FileServerNameContainingSqosVHD,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            client.TreeConnect(Smb2Utility.GetUncPath(TestConfig.FileServerNameContainingSqosVHD, TestConfig.ShareContainingSqosVHD), out treeId);

            Smb2CreateContextResponse[] response;
            client.Create(treeId, TestConfig.NameOfSqosVHD, CreateOptions_Values.NONE, out fileId, out response, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
        }
        protected override void TestInitialize()
        {
            base.TestInitialize();
            if (FolderPermissionTestShareUncPath == null)
            {
                FolderPermissionTestShareUncPath = Smb2Utility.GetUncPath(testConfig.SutComputerName, TestConfig.FolderPermissionTestShare);
                FolderPermissionTestShareExist   = ShareExists(TestConfig.AccountCredential, FolderPermissionTestShareUncPath);
            }
            if (!FolderPermissionTestShareExist)
            {
                BaseTestSite.Assert.Inconclusive("Required share does not exist: {0}", FolderPermissionTestShareUncPath);
            }

            originalSD = QuerySecurityDescriptor(FolderPermissionTestShareUncPath, null,
                                                 AdditionalInformation_Values.DACL_SECURITY_INFORMATION |
                                                 AdditionalInformation_Values.GROUP_SECURITY_INFORMATION |
                                                 AdditionalInformation_Values.OWNER_SECURITY_INFORMATION);
        }
        /// <summary>
        /// Convert an Smb2ErrorResponsePacket to a byte array
        /// </summary>
        /// <returns>The byte array</returns>
        public override byte[] ToBytes()
        {
            byte[] messageData = TypeMarshal.ToBytes(this.Header);
            messageData = messageData.Concat(TypeMarshal.ToBytes <ushort>(this.PayLoad.StructureSize)).ToArray();
            messageData = messageData.Concat(TypeMarshal.ToBytes <byte>(this.PayLoad.ErrorContextCount)).ToArray();
            messageData = messageData.Concat(TypeMarshal.ToBytes <byte>(this.PayLoad.Reserved)).ToArray();
            messageData = messageData.Concat(TypeMarshal.ToBytes <uint>(this.PayLoad.ByteCount)).ToArray();

            if (this.PayLoad.ErrorContextCount > 0) //smb311
            {
                byte[] temp = new byte[] { };
                for (int i = 0; i < this.PayLoad.ErrorContextCount; i++)
                {
                    temp = temp.Concat(TypeMarshal.ToBytes <uint>(this.PayLoad.ErrorContextErrorData[i].ErrorDataLength)).ToArray();
                    temp = temp.Concat(TypeMarshal.ToBytes <Error_Id>(this.PayLoad.ErrorContextErrorData[i].ErrorId)).ToArray();

                    switch (this.Header.Status)
                    {
                    case Smb2Status.STATUS_STOPPED_ON_SYMLINK:
                        temp = temp.Concat(TypeMarshal.ToBytes <Symbolic_Link_Error_Response>(this.PayLoad.ErrorContextErrorData[i].ErrorData.SymbolicLinkErrorResponse)).ToArray();
                        break;

                    case Smb2Status.STATUS_BAD_NETWORK_NAME:
                        if (this.PayLoad.ErrorContextErrorData[i].ErrorId == Error_Id.ERROR_ID_SHARE_REDIRECT)
                        {
                            temp = temp.Concat(TypeMarshal.ToBytes <Share_Redirect_Error_Context_Response>(this.PayLoad.ErrorContextErrorData[i].ErrorData.ShareRedirectErrorContextResponse)).ToArray();
                        }
                        break;

                    case Smb2Status.STATUS_BUFFER_TOO_SMALL:
                        temp = temp.Concat(this.PayLoad.ErrorContextErrorData[i].ErrorData.BufferTooSmallErrorResponse).ToArray();
                        break;
                    }
                }
                Smb2Utility.Align8(ref temp);
                messageData = messageData.Concat(temp).ToArray();
            }
            else
            {
                messageData = messageData.Concat(this.PayLoad.ErrorData).ToArray();
            }

            return(messageData.ToArray());
        }
        private static void ConnectToShare(
            ITestSite testSite,
            SMB2ModelTestConfig testConfig,
            Smb2FunctionalClient client,
            DialectRevision[] dialects,
            Guid clientGuid,
            AccountCredential account,
            out DialectRevision responseDialect,
            out uint treeId)
        {
            client.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);

            // Negotiate
            NEGOTIATE_Response?negotiateResponse = null;

            client.Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                clientGuid: clientGuid,
                checker: (header, response) =>
            {
                testSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "{0} should succeed", header.Command);

                negotiateResponse = response;
            });

            responseDialect = negotiateResponse.Value.DialectRevision;

            // SMB2 SESSION SETUP
            client.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                account,
                testConfig.UseServerGssToken);

            // SMB2 Tree Connect
            client.TreeConnect(
                Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare),
                out treeId);
        }
예제 #28
0
        public void SetupConnection(ModelDialectRevision dialect)
        {
            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);

            testClient.Negotiate(Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(dialect)), testConfig.IsSMB1NegotiateEnabled);

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

            string share = testConfig.BasicFileShare;

            testClient.TreeConnect(
                Smb2Utility.GetUncPath(testConfig.SutComputerName, share),
                out treeId);
        }
        private void ConnectToShare(ModelDialectRevision dialect, Smb2FunctionalClient client, Guid guid, string share, out uint treeId)
        {
            #region Connect to server
            client.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);
            #endregion

            client.Negotiate(
                Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(dialect)),
                testConfig.IsSMB1NegotiateEnabled,
                clientGuid: guid);

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

            client.TreeConnect(Smb2Utility.GetUncPath(testConfig.SutComputerName, share), out treeId);
        }
예제 #30
0
        public void Smb2OverRdma_Write_SMB2_CHANNEL_RDMA_V1()
        {
            EstablishConnectionAndOpenFile(fileName);

            uint writeSize = smbdAdapter.Smb2MaxWriteSize;

            byte[] fileContent = Smb2Utility.CreateRandomByteArray((int)writeSize);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Register memory and get buffer descriptor for SMB2 WRITE");
            SmbdBufferDescriptorV1 descp;
            NtStatus status = smbdAdapter.SmbdRegisterBuffer(
                writeSize,
                SmbdBufferReadWrite.RDMA_READ_PERMISSION_FOR_WRITE_FILE,
                out descp);

            BaseTestSite.Assert.AreEqual(
                NtStatus.STATUS_SUCCESS,
                status,
                "Register buffer should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Write content to file over RDMA.");
            status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1, descp);
            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_SUCCESS,
                status,
                "SMB2 WRITE over RDMA should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify file content.");
            ValidateFileContent(fileContent);

            fileContent = Encoding.ASCII.GetBytes(Smb2Utility.CreateRandomStringInByte((int)writeSize));

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send Smb2 WRITE request using same descriptor.");
            status = Smb2WriteOverRdma(fileName, fileContent, Channel_Values.CHANNEL_RDMA_V1, descp);

            BaseTestSite.Assert.AreEqual <NtStatus>(
                NtStatus.STATUS_SUCCESS,
                status,
                "SMB2 WRITE over RDMA should succeed.");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify file content.");
            ValidateFileContent(fileContent);
        }