private void InitializeAlternativeChannel( Guid clientGuid, uint treeId, bool isClientSupportPersistent = true) { Site.Assume.IsNull(smb2ClientAlternativeChannel, "Expect smb2ClientAlternativeChannel is NULL."); testConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); smb2ClientAlternativeChannel = new Smb2FunctionalClient(testConfig.Timeout, testConfig, Site); smb2ClientAlternativeChannel.Smb2Client.LeaseBreakNotificationReceived += new Action <Packet_Header, LEASE_BREAK_Notification_Packet>(OnLeaseBreakNotificationReceived); smb2ClientAlternativeChannel.Smb2Client.OplockBreakNotificationReceived += new Action <Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived); smb2ClientAlternativeChannel.ConnectToServer(testConfig.UnderlyingTransport, serverNameMainChannel, serverIpMainChannel); uint status; #region Negotiate Capabilities_Values capability = isClientSupportPersistent ? 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.GLOBAL_CAP_ENCRYPTION : 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_ENCRYPTION; NEGOTIATE_Response?negotiateResponse = null; status = smb2ClientAlternativeChannel.Negotiate( new DialectRevision[] { dialectMainChannel }, testConfig.IsSMB1NegotiateEnabled, capabilityValue: ModelUtility.IsSmb3xFamily(dialectMainChannel) ? capability : Capabilities_Values.NONE, clientGuid: dialectMainChannel == DialectRevision.Smb2002 ? Guid.Empty : clientGuid, checker: (header, response) => { Site.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); Site.Assert.AreEqual( dialectMainChannel, negotiateResponse.Value.DialectRevision, "DialectRevision {0} is expected", dialectMainChannel); #endregion #region SESSION_SETUP status = smb2ClientAlternativeChannel.AlternativeChannelSessionSetup( smb2ClientMainChannel, testConfig.DefaultSecurityPackage, principleNameMainChannel, testConfig.AccountCredential, testConfig.UseServerGssToken); Site.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion }
/// <summary> /// Establish alternative channel, which includes NEGOTIATE, SESSION_SETUP /// </summary> /// <param name="requestDialect">Dialects in request</param> /// <param name="serverIp">Ip address on server side</param> /// <param name="clientIp">Ip address on client side</param> /// <param name="treeId">Tree id that is used to set encryption</param> /// <param name="enableEncryptionPerShare">Set true if enable encryption on share, otherwise set false</param> private void EstablishAlternativeChannel( DialectRevision[] requestDialect, IPAddress serverIp, IPAddress clientIp, uint treeId, bool enableEncryptionPerShare = false) { BaseTestSite.Log.Add( LogEntryKind.Debug, "Establish alternative channel to connect share {0}", uncSharePath); alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp); #region Negotiate Capabilities_Values alternativeChannelClientCapabilities = 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.GLOBAL_CAP_ENCRYPTION; status = alternativeChannelClient.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid, capabilityValue: alternativeChannelClientCapabilities, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "CREATE should succeed."); TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response); } ); #endregion #region SESSION_SETUP status = alternativeChannelClient.AlternativeChannelSessionSetup( mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion alternativeChannelClient.SetTreeEncryption(treeId, enableEncryptionPerShare); BaseTestSite.Log.Add( LogEntryKind.Debug, "Per share encryption for TreeId=0x{0:x} : {1}", treeId, enableEncryptionPerShare); BaseTestSite.Log.Add( LogEntryKind.Debug, "Establish alternative channel to connect share {0}", uncSharePath); }
private void ReadFromAlternativeChannel( DialectRevision[] requestDialect, DialectRevision expectedDialect, IPAddress serverIp, IPAddress clientIp, uint lengthRead, uint treeId, FILEID fileId, out string contentRead) { contentRead = ""; alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp); #region Negotiate status = alternativeChannelClient.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, clientGuid: clientGuid, 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 (Smb2Utility.IsSmb3xFamily(expectedDialect)) { TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response); } }); #endregion #region SESSION_SETUP status = alternativeChannelClient.AlternativeChannelSessionSetup( mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, checker: (header, response) => { }); #endregion if (expectedDialect == DialectRevision.Smb2002 || expectedDialect == DialectRevision.Smb21) { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_REQUEST_NOT_ACCEPTED, status, "SessionSetup is expected to fail with STATUS_REQUEST_NOT_ACCEPTED."); BaseTestSite.Log.Add( LogEntryKind.Debug, "Dialect " + expectedDialect + " is not supported for multiple channel and fail as expected with STATUS_REQUEST_NOT_ACCEPTED."); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, status, "SessionSetup should succeed"); #region READ status = alternativeChannelClient.Read(treeId, fileId, 0, lengthRead, out contentRead); #endregion #region CLOSE file status = alternativeChannelClient.Close(treeId, fileId); #endregion #region TREE_DISCONNECT status = alternativeChannelClient.TreeDisconnect(treeId); #endregion #region LOGOFF status = alternativeChannelClient.LogOff(); #endregion } alternativeChannelClient.Disconnect(); }
public void MultipleChannel_SecondChannelSessionSetupFailAtFirstTime() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb311); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); #endregion string contentWrite; string contentRead; uint treeId; FILEID fileId; contentWrite = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb); BaseTestSite.Assert.IsTrue( clientIps.Count > 0, "Client should have at least one IP address"); BaseTestSite.Assert.IsTrue( serverIps.Count > 0, "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, false, out treeId, out fileId); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Set up alternative channel with client {0} and server {1}", clientIps[0].ToString(), serverIps[0].ToString()); alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIps[1], clientIps[1]); alternativeChannelClient.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, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(DialectRevision.Smb311, response); if (Smb2Utility.IsSmb3xFamily(DialectRevision.Smb311)) { TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response); } }); status = alternativeChannelClient.AlternativeChannelSessionSetup( mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, checker: (header, response) => { }, invalidToken: true); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_INVALID_PARAMETER, status, "The first SessionSetup from alternative channel should return STATUS_INVALID_PARAMETER since the token in buffer field is set to an invalid value."); status = alternativeChannelClient.AlternativeChannelSessionSetup( mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, checker: (header, response) => { }); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "The second SessionSetup from alternative channel should succeed"); contentRead = ""; status = alternativeChannelClient.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead); // Read should succeed. // If Read response returns STATUS_ACCESS_DEINIED, it means signingkey used by server is wrong, and so that the PreauthIntegrityHashValue (which is used to generate the signingkey) calculated by server is wrong. // It is very possible that server uses the first failed session setup request/response (alternative channel) to calculate PreauthIntegrityHashValue, which is wrong. BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Read from the alternative channel should succeed"); alternativeChannelClient.Close(treeId, fileId); alternativeChannelClient.TreeDisconnect(treeId); alternativeChannelClient.LogOff(); 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 read should be identical to content written."); }
public void BVT_Replay_WriteWithInvalidChannelSequence() { ///1. mainChannelClient opens a file and write to it. ///2. mainChannelClient loses connection. ///3. ChannelSequence is set to 0x8000 which exceeds the max value. ///4. alternativeChannelClient opens the same file and try to write to it. ///5. Server should fail the write request with STATUS_FILE_NOT_AVAILABLE. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2); // According to TD, server must support signing when it supports multichannel. // 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request // 4. If Connection.Dialect belongs to the SMB 3.x dialect family, IsMultiChannelCapable is TRUE, and the SMB2_SESSION_FLAG_BINDING bit is // set in the Flags field of the request, the server MUST perform the following: // If the SMB2_FLAGS_SIGNED bit is not set in the Flags field in the header, the server MUST fail the request with error STATUS_INVALID_PARAMETER. TestConfig.CheckSigning(); #endregion Guid clientGuid = Guid.NewGuid(); Capabilities_Values capabilityValue = Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; channelSequence = 0; #region MainChannelClient Create a File BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start a client from main channel by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE."); mainChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); mainChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilityValue, clientGuid: clientGuid, checker: ReplayNegotiateResponseChecker); mainChannelClient.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); mainChannelClient.SessionChannelSequence = channelSequence; uint treeId; mainChannelClient.TreeConnect(sharePath, out treeId); FILEID fileId; Smb2CreateContextResponse[] createContextResponse; mainChannelClient.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = Guid.NewGuid() } }); CheckCreateContextResponses(createContextResponse, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); #endregion #region alternativeChannelClient Opens the Previously Created File BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client from alternative channel by sending NEGOTIATE request."); alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutAlternativeIPAddress); alternativeChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilityValue, clientGuid: clientGuid, checker: ReplayNegotiateResponseChecker); BaseTestSite.Log.Add( LogEntryKind.TestStep, "The alternative client sends SESSION_SETUP request binding the previous session created by the main channel client."); alternativeChannelClient.AlternativeChannelSessionSetup(mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); alternativeChannelClient.SessionChannelSequence = channelSequence; #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "The main channel client sends WRITE request to write content to file."); mainChannelClient.Write(treeId, fileId, " "); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the main channel client by sending DISCONNECT request."); mainChannelClient.Disconnect(); //Network Disconnection Increase the Channel Sequence //Server MUST fail SMB2 WRITE, SET_INFO, and IOCTL requests with STATUS_FILE_NOT_AVAILABLE //if the difference between the ChannelSequence in the header and Open.ChannelSequence is greater than 0x7FFF BaseTestSite.Log.Add(LogEntryKind.TestStep, "Set the channel sequence of the alternative channel client to an invalid value."); alternativeChannelClient.SessionChannelSequence = 0x8000; BaseTestSite.Log.Add( LogEntryKind.TestStep, "The alternative client sends WRITE request to write content to the file created by the main channel client."); alternativeChannelClient.Write(treeId, fileId, " ", checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_FILE_NOT_AVAILABLE, header.Status, "Server MUST fail the {0} request with STATUS_FILE_NOT_AVAILABLE if the difference between the ChannelSequence in the header and Open.ChannelSequence is greater than 0x7FFF. " + "Actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); }, isReplay: true); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the alternative channel client by sending TREE_DISCONNECT and LOG_OFF requests."); alternativeChannelClient.TreeDisconnect(treeId); alternativeChannelClient.LogOff(); }
private void InitializeAlternativeChannel( Guid clientGuid, uint treeId, bool isClientSupportPersistent = true) { Site.Assume.IsNull(smb2ClientAlternativeChannel, "Expect smb2ClientAlternativeChannel is NULL."); testConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL); smb2ClientAlternativeChannel = new Smb2FunctionalClient(testConfig.Timeout, testConfig, Site); smb2ClientAlternativeChannel.Smb2Client.LeaseBreakNotificationReceived += new Action<Packet_Header, LEASE_BREAK_Notification_Packet>(OnLeaseBreakNotificationReceived); smb2ClientAlternativeChannel.Smb2Client.OplockBreakNotificationReceived += new Action<Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived); smb2ClientAlternativeChannel.ConnectToServer(testConfig.UnderlyingTransport, serverNameMainChannel, serverIpMainChannel); uint status; #region Negotiate Capabilities_Values capability = isClientSupportPersistent ? 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.GLOBAL_CAP_ENCRYPTION : 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_ENCRYPTION; NEGOTIATE_Response? negotiateResponse = null; status = smb2ClientAlternativeChannel.Negotiate( new DialectRevision[] { dialectMainChannel }, testConfig.IsSMB1NegotiateEnabled, capabilityValue: ModelUtility.IsSmb3xFamily(dialectMainChannel) ? capability : Capabilities_Values.NONE, clientGuid: dialectMainChannel == DialectRevision.Smb2002 ? Guid.Empty : clientGuid, checker: (header, response) => { Site.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); Site.Assert.AreEqual( dialectMainChannel, negotiateResponse.Value.DialectRevision, "DialectRevision {0} is expected", dialectMainChannel); #endregion #region SESSION_SETUP status = smb2ClientAlternativeChannel.AlternativeChannelSessionSetup( smb2ClientMainChannel, testConfig.DefaultSecurityPackage, principleNameMainChannel, testConfig.AccountCredential, testConfig.UseServerGssToken); Site.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion }