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."); } }
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."); }
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 "); }); }
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); }
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; }
/// <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; }
/// <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; }
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); }
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); }
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); }