public Smb2Info FetchSmb2Info(DetectionInfo info) { Smb2Info smb2Info = new Smb2Info(); using (Smb2Client smb2Client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds))) { logWriter.AddLog(LogLevel.Information, "Client connects to server"); smb2Client.ConnectOverTCP(SUTIpAddress); DialectRevision selectedDialect; byte[] gssToken; Packet_Header responseHeader; NEGOTIATE_Response responsePayload; ulong messageId = 1; logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( smb2Client, 0, 1, Packet_Header_Flags_Values.NONE, ref messageId, info.requestDialect, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, Guid.NewGuid(), out selectedDialect, out gssToken, out responseHeader, out responsePayload); if (responseHeader.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", responseHeader.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(responseHeader.Status))); } smb2Info.MaxSupportedDialectRevision = responsePayload.DialectRevision; smb2Info.SupportedCapabilities = (Capabilities_Values)responsePayload.Capabilities; smb2Info.SelectedCipherID = smb2Client.SelectedCipherID; smb2Info.IsRequireMessageSigning = responsePayload.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); } FetchSmb2CompressionInfo(smb2Info); return(smb2Info); }
public void BVT_SessionMgmt_Reauthentication() { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE request."); client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled); var credential = TestConfig.AccountCredential; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request with SESSION_ID set to ZERO."); client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, credential, TestConfig.UseServerGssToken); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends another SESSION-SETUP request for reauthentication."); client.SessionSetup( testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE, // The second session setup should set signed flag if server supports signing to keep consistency with SDK. TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, credential, TestConfig.UseServerGssToken, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, checker: (header, response) => { // <225> Section 3.3.5.5: Windows Vista SP1 and Windows Server 2008 servers fail the session setup request with STATUS_REQUEST_NOT_ACCEPTED. if (TestConfig.Platform == Platform.WindowsServer2008) { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_REQUEST_NOT_ACCEPTED, header.Status, "Windows Vista SP1 and Windows Server 2008 should return STATUS_REQUEST_NOT_ACCEPTED. Actually it returns {0}.", Smb2Status.GetStatusCode(header.Status)); } else if (header.Status != Smb2Status.STATUS_SUCCESS) { // 3.3.5.5 Receiving an SMB2 SESSION_SETUP Request // 6. If Session.State is Valid, the server SHOULD<225> process the session setup request as specified in section 3.3.5.5.2. if (TestConfig.Platform == Platform.NonWindows) { BaseTestSite.Assert.Fail("Reauthentication is not supported in the server."); } else { throw new InvalidOperationException(string.Format("Unexpected status {0}", Smb2Status.GetStatusCode(header.Status))); } } }); }
private void UpdateCounters( Guid logicalFlowId, Guid initiatorId, ulong ioCountIncrement, ulong normalizedIoCountIncrement, ulong latencyIncrement, ulong lowerLatencyIncrement, ulong bandwidthLimit, ulong kilobyteCountIncrement) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends an SQOS request to update counters to a logical flow and expects success"); SqosResponsePacket sqosResponse; SqosRequestPacket sqosRequest = new SqosRequestPacket(TestConfig.SqosClientDialect == SQOS_PROTOCOL_VERSION.Sqos10 ? SqosRequestType.V10 : SqosRequestType.V11, (ushort)TestConfig.SqosClientDialect, SqosOptions_Values.STORAGE_QOS_CONTROL_FLAG_UPDATE_COUNTERS, logicalFlowId, TestConfig.SqosPolicyId, initiatorId, TestConfig.SqosInitiatorName, TestConfig.SqosInitiatorNodeName, 0, 0, ioCountIncrement, normalizedIoCountIncrement, latencyIncrement, lowerLatencyIncrement, bandwidthLimit, kilobyteCountIncrement ); uint status = client.SendAndReceiveSqosPacket( sqosRequest, out sqosResponse); BaseTestSite.Assert.AreEqual( (uint)Smb2Status.STATUS_SUCCESS, status, "Update counters should succeed, actual status: {0}", Smb2Status.GetStatusCode(status)); }
public void InvalidRootReferralDomainToDFSServer() { bool dfsServerIsDC = TestConfig.SutComputerName.ParseIPAddress().Equals(TestConfig.DCServerName.ParseIPAddress()); if (dfsServerIsDC) { BaseTestSite.Assume.Inconclusive("This test case is only applicable when the DFS server does not also act as domain controller."); } string invalidRootPathDomain = string.Format(@"\{0}\{1}", TestConfig.DomainFQDNName, DFSCTestUtility.Consts.InvalidComponent); uint status; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends a DFS root referral request v4 to DFS Server, the request path is domain-based and invalid, expects negative response."); utility.SendAndReceiveDFSReferral(out status, client, ReferralEntryType_Values.DFS_REFERRAL_V4, invalidRootPathDomain, false); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server response."); // Section 6 // <22> Section 3.2.5.5: Windows NT Server 4.0, Windows 2000, Windows Server 2003, Windows Server 2003 R2, Windows Server 2008, and Windows Server 2008 R2 // fail the referral request with a STATUS_NOT_FOUND (0xC0000225) return code. if (TestConfig.Platform == Platform.WindowsServer2008 || TestConfig.Platform == Platform.WindowsServer2008R2) { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_NOT_FOUND, status, "Server SHOULD fail the referral request with STATUS_NOT_FOUND for 2008 and 2008R2. Actual status is: " + Smb2Status.GetStatusCode(status)); } else if (TestConfig.IsWindowsPlatform) { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_DFS_UNAVAILABLE, status, "Server SHOULD fail the referral request with STATUS_DFS_UNAVAILABLE. Actual status is: " + Smb2Status.GetStatusCode(status)); } else { BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Server SHOULD fail the referral request. Actual status is " + Smb2Status.GetStatusCode(status)); } }
public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("R NEGOTIATE"); if (Header.Status != 0) // Append error code if fail. { sb.Append(", ErrorCode=" + Smb2Status.GetStatusCode(Header.Status)); } else { sb.Append(", Dialect=" + PayLoad.DialectRevision); if (NegotiateContext_PREAUTH != null) { sb.Append(", HashAlgorithms={"); foreach (var hashId in NegotiateContext_PREAUTH.Value.HashAlgorithms) { sb.Append(hashId.ToString() + ","); } sb.Length--; sb.Append("}"); } if (NegotiateContext_ENCRYPTION != null) { sb.Append(", Ciphers={"); foreach (var alg in NegotiateContext_ENCRYPTION.Value.Ciphers) { sb.Append(alg.ToString() + ","); } sb.Length--; sb.Append("}"); } sb.Append(", Capabilities=" + PayLoad.Capabilities); } return(sb.ToString()); }
private void SetOrProbePolicy(Guid logicalFlowId, Guid initiatorId, bool setPolicy) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends an SQOS request to {0} policy to a logical flow and expects success", setPolicy ? "set" : "probe"); SqosResponsePacket sqosResponse; SqosRequestPacket sqosRequest = new SqosRequestPacket(TestConfig.SqosClientDialect == SQOS_PROTOCOL_VERSION.Sqos10 ? SqosRequestType.V10 : SqosRequestType.V11, (ushort)TestConfig.SqosClientDialect, setPolicy ? SqosOptions_Values.STORAGE_QOS_CONTROL_FLAG_SET_POLICY : SqosOptions_Values.STORAGE_QOS_CONTROL_FLAG_PROBE_POLICY, logicalFlowId, TestConfig.SqosPolicyId, initiatorId, TestConfig.SqosInitiatorName, TestConfig.SqosInitiatorNodeName); uint status = client.SendAndReceiveSqosPacket( sqosRequest, out sqosResponse); BaseTestSite.Assert.AreEqual( (uint)Smb2Status.STATUS_SUCCESS, status, "{0} policy should succeed, actual status: {1}", setPolicy ? "SetPolicy": "ProbePolicy", Smb2Status.GetStatusCode(status)); }
public void DurableHandleV2_Reconnect_WithoutPersistence() { /// 1. Client requests a durable handle V2 without persistent flag /// 2. Lose connection by disabling NIC /// 3. Client reconnects the durable handle V2 without persistent flag. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "DurableHandleV2_Reconnect_WithoutPersistence" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a durable handle"); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); }); clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the durable handle"); uint treeIdAfterDisconnection; Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; clientAfterDisconnection.Create( treeIdAfterDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { CreateGuid = createGuid, FileId = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE); string readContent; clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( content.Equals(readContent), "The written content is expected to be equal to read content."); #endregion clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection); clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); }
public void BVT_PersistentHandle_Reconnect() { /// 1. Client requests a persistent handle /// 2. Client disconnects from the server /// 3. Client reconnects the persistent handle, and expects success. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName); fileName = "BVT_PersistentHandle_Reconnect_" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a persistent handle"); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses(serverCreateContexts, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT, uint.MaxValue)); }); status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the persistent handle"); uint treeIdAfterDisconnection; Connect(DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.CAShare, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; status = clientAfterDisconnection.Create( treeIdAfterDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT, FileId = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } } }, shareAccess: ShareAccess_Values.NONE); string readContent; status = clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( readContent.Equals(content), "The written content should equal to read content."); #endregion clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection); clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); }
public void DurableHandleV2_NoPersistenceGrantedOnNonCAShare() { /// 1. Client requests a durable handle V2 to a Non-CA share /// 2. Expect the create response contains Smb2CreateDurableHandleResponseV2 context but no persistent flag is set. #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion durableHandleUncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); fileName = "DurableHandleV2_NoPersistenceGrantedOnNonCAShare" + Guid.NewGuid() + ".txt"; Guid clientGuid = Guid.NewGuid(); BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a durable handle"); #region client connect to server uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShare, out treeIdBeforeDisconnection, null); Smb2CreateContextResponse[] serverCreateContexts = null; FILEID fileIdBeforeDisconnection; Guid createGuid = Guid.NewGuid(); clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, }, }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); }); BaseTestSite.Assert.AreEqual( null, serverCreateContexts, "The server should ignore the create context when TreeConnect.Share.IsCA is FALSE."); #endregion clientBeforeDisconnection.Close(treeIdBeforeDisconnection, fileIdBeforeDisconnection); clientBeforeDisconnection.TreeDisconnect(treeIdBeforeDisconnection); clientBeforeDisconnection.LogOff(); }
public void UserLogon( DetectionInfo info, Smb2Client client, out ulong messageId, out ulong sessionId, out Guid clientGuid, out NEGOTIATE_Response negotiateResp, out bool encryptionRequired) { messageId = 1; sessionId = 0; logWriter.AddLog(LogLevel.Information, "Client connects to server"); client.ConnectOverTCP(SUTIpAddress); #region Negotiate DialectRevision selectedDialect; byte[] gssToken; Packet_Header header; clientGuid = Guid.NewGuid(); logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( client, 1, 1, Packet_Header_Flags_Values.NONE, messageId++, info.requestDialect, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, 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, clientGuid, out selectedDialect, out gssToken, out header, out negotiateResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", header.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(header.Status))); } #endregion #region Session Setup SESSION_SETUP_Response sessionSetupResp; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( SecurityPackageType, Credential, Smb2Utility.GetCifsServicePrincipalName(SUTName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); // Server GSS token is used only for Negotiate authentication when enabled if (SecurityPackageType == SecurityPackageType.Negotiate) { sspiClientGss.Initialize(gssToken); } else { sspiClientGss.Initialize(null); } do { logWriter.AddLog(LogLevel.Information, "Client sends SessionSetup to server"); client.SessionSetup( 1, 64, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out gssToken, out header, out sessionSetupResp); if ((header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || header.Status == Smb2Status.STATUS_SUCCESS) && gssToken != null && gssToken.Length > 0) { sspiClientGss.Initialize(gssToken); } } while (header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SESSIONSETUP", header.Status); throw new Exception(string.Format("SESSIONSETUP failed with {0}", Smb2Status.GetStatusCode(header.Status))); } byte[] sessionKey; sessionKey = sspiClientGss.SessionKey; encryptionRequired = sessionSetupResp.SessionFlags == SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA; client.GenerateCryptoKeys( sessionId, sessionKey, info.smb2Info.IsRequireMessageSigning, // Enable signing according to the configuration of SUT encryptionRequired, null, false); #endregion }
public void TreeMgmt_SMB311_COMPRESS_DATA() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb311); TestConfig.CheckPlatform(Platform.WindowsServer2022); if (string.IsNullOrEmpty(testConfig.CompressedFileShare)) { Assert.Inconclusive("This test requires a share with compression enabled"); } #endregion var compressedSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.CompressedFileShare); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP"); client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled); client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request and expects STATUS_SUCCESS with flag SMB2_SHAREFLAG_COMPRESS_DATA."); uint treeId; client.TreeConnect(compressedSharePath, out treeId, (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Assert.IsTrue( response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_COMPRESS_DATA), "The share should support compress data, actually server returns {0}.", response.ShareFlags.ToString()); }); client.TreeDisconnect(treeId); }
public void TreeMgmt_SMB311_CLUSTER_RECONNECT() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb311); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP"); client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled); client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request with flag SMB2_SHAREFLAG_CLUSTER_RECONNECT and expects STATUS_SUCCESS."); uint treeId; client.TreeConnect(sharePath, out treeId, (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); }, TreeConnect_Flags.SMB2_SHAREFLAG_CLUSTER_RECONNECT); client.TreeDisconnect(treeId); }
public void InvalidSysvolReferralToDC() { uint status; string invalidFQDNSysvolPath = string.Format(@"\{0}\{1}", DFSCTestUtility.Consts.InvalidComponent, DfscConsts.SysvolShare); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends a v1 Sysvol referral request with invalid Domain name to DC."); utility.SendAndReceiveDFSReferral(out status, client, ReferralEntryType_Values.DFS_REFERRAL_V1, invalidFQDNSysvolPath, true); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server response."); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_NOT_FOUND, status, "Server should fail the referral request with STATUS_NOT_FOUND. Actual status is " + Smb2Status.GetStatusCode(status)); }
public void BVT_EnumerateSnapShots() { #region Check Applicability TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_SRV_ENUMERATE_SNAPSHOTS); #endregion uint treeId; FILEID fileId; OpenFile(out treeId, out fileId); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Enumerate snapshots by sending the first IOCTL request: FSCTL_SRV_ENUMERATE_SNAPSHOTS, with MaxOutputResponse set to 16."); SRV_SNAPSHOT_ARRAY snapShotArray; client.EnumerateSnapShots( treeId, fileId, SizeOfEmptySnapShotArray, out snapShotArray, checker: (Packet_Header header, IOCTL_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "FSCTL_SRV_ENUMERATE_SNAPSHOTS should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); }); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Verify SRV_SNAPSHOT_ARRAY returned in response."); BaseTestSite.Assert.AreEqual( TestConfig.NumberOfPreviousVersions, snapShotArray.NumberOfSnapShots, "NumberOfSnapShots should be {0}.", TestConfig.NumberOfPreviousVersions); BaseTestSite.Assert.AreEqual( (uint)0, snapShotArray.NumberOfSnapShotsReturned, "NumberOfSnapShotsReturned should be 0."); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Enumerate snapshots by sending the second IOCTL request: FSCTL_SRV_ENUMERATE_SNAPSHOTS, with MaxOutputResponse set to 65536."); client.EnumerateSnapShots( treeId, fileId, Smb2FunctionalClient.DefaultMaxOutputResponse, out snapShotArray, checker: (Packet_Header header, IOCTL_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "FSCTL_SRV_ENUMERATE_SNAPSHOTS should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); }); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Verify SRV_SNAPSHOT_ARRAY returned in response."); BaseTestSite.Assert.AreEqual( TestConfig.NumberOfPreviousVersions, snapShotArray.NumberOfSnapShots, "NumberOfSnapShots should be {0}.", TestConfig.NumberOfPreviousVersions); BaseTestSite.Log.Add(LogEntryKind.Debug, "NumberOfSnapShotsReturned is {0}.", snapShotArray.NumberOfSnapShotsReturned); string[] versionArray = System.Text.Encoding.Unicode.GetString(snapShotArray.SnapShots).Split('\0'); BaseTestSite.Assert.AreEqual( snapShotArray.NumberOfSnapShotsReturned + 2, (uint)versionArray.Length, "The field \"SnapShots\" should be separated by UNICODE null characters and terminated by two UNICODE null characters."); DateTime dt; for (int i = 0; i < snapShotArray.NumberOfSnapShotsReturned; ++i) { BaseTestSite.Assert.IsTrue( DateTime.TryParseExact(versionArray[i], "@GMT-yyyy.MM.dd-HH.mm.ss", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out dt), "This SnapShot is {0}. The format of each SnapShot should be \"@GMT-YYYY.MM.DD-HH.MM.SS\". ", versionArray[i]); } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); }
public void InvalidNamespaceLinkReferralToDC() { uint status; string invalidNamespaceLinkPath = string.Format(@"\{0}\{1}\{2}", TestConfig.DomainFQDNName, DFSCTestUtility.Consts.InvalidComponent, TestConfig.DFSLink); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends a v4 Link referral request to DC with invalid namespace."); utility.SendAndReceiveDFSReferral(out status, client, ReferralEntryType_Values.DFS_REFERRAL_V4, invalidNamespaceLinkPath, true); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server response."); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_NOT_FOUND, status, "Expected Link Referral v4 to DC Response is STATUS_NOT_FOUND, actual status is {0}", Smb2Status.GetStatusCode(status)); }
public void Signing_VerifySignatureWhenEncrypted() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends NEGOTIATE with the capability GLOBAL_CAP_ENCRYPTION."); client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED, capabilityValue: Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION ); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request and expects response."); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); string uncSharepath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.EncryptedFileShare); uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT to share: {0}", uncSharepath); client.TreeConnect( uncSharepath, out treeId, (Packet_Header header, TREE_CONNECT_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "TreeConnect should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Assert.AreEqual( ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA, ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA & response.ShareFlags, "Server should set SMB2_SHAREFLAG_ENCRYPT_DATA for ShareFlags field in TREE_CONNECT response"); }); // After calling this method, client will send encrypted message after tree connect. BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client enables per share encryption: TreeId=0x{0:x}", treeId); client.SetTreeEncryption(treeId, true); FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrypted CREATE request and expects success."); client.Create( treeId, CurrentTestCaseName + "_" + Guid.NewGuid() + ".txt", CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, shareAccess: ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE, checker: (header, response) => { BaseTestSite.Assert.IsTrue( !header.Signature.Any(e => e != 0), "[MS-SMB2] 3.3.4.1.1 If the server encrypts the message, as specified in section 3.1.4.3, the server MUST set the Signature field of the SMB2 header to zero, actually the Signature field is [{0}].", string.Join(", ", header.Signature)); }); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); }
/// <summary> /// Acknowledge LeaseBreakNotification received from server /// </summary> /// <param name="client">Client to send the acknowledgement</param> /// <param name="treeId">TreeId associated to send the acknowledgement</param> /// <param name="leaseBreakNotify">LeaseBreakNotification received from server</param> protected virtual void AcknowledgeLeaseBreak(Smb2FunctionalClient client, uint treeId, LEASE_BREAK_Notification_Packet leaseBreakNotify) { if (receivedLeaseBreakNotify.Flags == LEASE_BREAK_Notification_Packet_Flags_Values.SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { BaseTestSite.Log.Add( LogEntryKind.Debug, "Server requires an LEASE_BREAK_ACK on this LEASE_BREAK_NOTIFY"); // Will add verification for response after SDK change uint status = client.LeaseBreakAcknowledgment(treeId, leaseBreakNotify.LeaseKey, leaseBreakNotify.NewLeaseState); BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, status, "LeaseBreakAcknowledgement should succeed, actual status is {0}", Smb2Status.GetStatusCode(status)); } else { BaseTestSite.Log.Add( LogEntryKind.Debug, "Server does not require an LEASE_BREAK_ACK on this LEASE_BREAK_NOTIFY"); } }
private void TestValidateNegotiateInfo(Smb2FunctionalClient client, ValidateNegotiateInfoRequestType requestType, DialectRevision[] invalidDialects = null) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO); TestConfig.CheckDialectIOCTLCompatibility(CtlCode_Values.FSCTL_VALIDATE_NEGOTIATE_INFO); // Server will terminate connection if Validate Negotiate Info Request is not signed. TestConfig.CheckSigning(); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); Guid clientGuid = Guid.NewGuid(); DialectRevision[] requestDialects = TestConfig.RequestDialects; Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES; SecurityMode_Values clientSecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; NEGOTIATE_Response? negotiateResponse = null; status = client.Negotiate( requestDialects, TestConfig.IsSMB1NegotiateEnabled, clientSecurityMode, clientCapabilities, clientGuid, (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); negotiateResponse = response; }); status = client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); uint treeId; string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName); status = client.TreeConnect(ipcPath, out treeId); VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq; switch (requestType) { case ValidateNegotiateInfoRequestType.None: case ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse: validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = clientCapabilities; validateNegotiateInfoReq.SecurityMode = clientSecurityMode; validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length; validateNegotiateInfoReq.Dialects = requestDialects; break; case ValidateNegotiateInfoRequestType.InvalidDialects: validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = clientCapabilities; validateNegotiateInfoReq.SecurityMode = clientSecurityMode; validateNegotiateInfoReq.DialectCount = (ushort)invalidDialects.Length; validateNegotiateInfoReq.Dialects = invalidDialects; break; case ValidateNegotiateInfoRequestType.InvalidGuid: validateNegotiateInfoReq.Guid = Guid.NewGuid(); validateNegotiateInfoReq.Capabilities = clientCapabilities; validateNegotiateInfoReq.SecurityMode = clientSecurityMode; validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length; validateNegotiateInfoReq.Dialects = requestDialects; break; case ValidateNegotiateInfoRequestType.InvalidSecurityMode: validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = clientCapabilities; validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NONE; validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length; validateNegotiateInfoReq.Dialects = requestDialects; break; case ValidateNegotiateInfoRequestType.InvalidCapabilities: validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = Capabilities_Values.NONE; validateNegotiateInfoReq.SecurityMode = clientSecurityMode; validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length; validateNegotiateInfoReq.Dialects = requestDialects; break; default: throw new InvalidOperationException("Unexpected ValidateNegotiateInfo request type " + requestType); } byte[] inputBuffer = TypeMarshal.ToBytes <VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq); byte[] outputBuffer; VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResp; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Attempt to validate negotiate info with info Guid: {0}, Capabilities: {1}, SecurityMode: {2}, DialectCount: {3}, Dialects: {4}", validateNegotiateInfoReq.Guid, validateNegotiateInfoReq.Capabilities, validateNegotiateInfoReq.SecurityMode, validateNegotiateInfoReq.DialectCount, Smb2Utility.GetArrayString(validateNegotiateInfoReq.Dialects)); if (requestType == ValidateNegotiateInfoRequestType.None) { status = client.ValidateNegotiateInfo(treeId, inputBuffer, out outputBuffer, checker: (header, response) => { }); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "ValidateNegotiateInfo should succeed "); validateNegotiateInfoResp = TypeMarshal.ToStruct <VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer); BaseTestSite.Log.Add( LogEntryKind.Debug, "Capabilities returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.Capabilities); BaseTestSite.Assert.AreEqual( (Capabilities_Values)negotiateResponse.Value.Capabilities, validateNegotiateInfoResp.Capabilities, "Capabilities returned in ValidateNegotiateInfo response should be equal to server capabilities in original Negotiate response"); BaseTestSite.Log.Add( LogEntryKind.Debug, "Guid returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.Guid); BaseTestSite.Assert.AreEqual( negotiateResponse.Value.ServerGuid, validateNegotiateInfoResp.Guid, "ServerGuid returned in ValidateNegotiateInfo response should be equal to server ServerGuid in original Negotiate response"); BaseTestSite.Log.Add( LogEntryKind.Debug, "SecurityMode returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.SecurityMode); BaseTestSite.Assert.AreEqual( (SecurityMode_Values)negotiateResponse.Value.SecurityMode, validateNegotiateInfoResp.SecurityMode, "SecurityMode returned in ValidateNegotiateInfo response should be equal to server SecurityMode in original Negotiate response"); BaseTestSite.Log.Add( LogEntryKind.Debug, "Dialect returned in ValidateNegotiateInfo response: {0}", validateNegotiateInfoResp.Dialect); BaseTestSite.Assert.AreEqual( negotiateResponse.Value.DialectRevision, validateNegotiateInfoResp.Dialect, "DialectRevision returned in ValidateNegotiateInfo response should be equal to server DialectRevision in original Negotiate response"); client.TreeDisconnect(treeId); client.LogOff(); return; } uint maxOutputResponse = (requestType == ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse) ? (uint)0: 64 * 1024; try { client.ValidateNegotiateInfo(treeId, inputBuffer, out outputBuffer, maxOutputResponse, (header, response) => { }); client.TreeDisconnect(treeId); client.LogOff(); return; } catch { } string errCondition = requestType == ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse ? "MaxOutputResponse in the request is less than the size of a VALIDATE_NEGOTIATE_INFO Response" : "there's invalid info in the request"; BaseTestSite.Assert.IsTrue(client.Smb2Client.IsServerDisconnected, "Transport connection should be terminated when {0}", errCondition); }
public void TreeMgmt_SMB311_TREE_CONNECT_EXTENSION_PRESENT() { #region Check Applicability TestConfig.CheckPlatform(Platform.WindowsServer2019); TestConfig.CheckDialect(DialectRevision.Smb311); #endregion Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: CONNECT; NEGOTIATE; SESSION_SETUP"); client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled); //Use domain credential to do session setup (e.g. contoso.com\administrator) client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); string infraSharePath = string.Format(@"\\{0}\{1}", TestConfig.ClusteredInfrastructureFileServerName, TestConfig.InfrastructureRootShare); uint treeId; string anotherUserName = TestConfig.NonAdminUserName; _WindowsIdentity identity = sutCommonControlAdapterAccessor.GetWindowsIdentity(anotherUserName); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request with extension context and expects success"); //Use another domain account(e.g. contoso\nonadmin) as an idenity passed in tree connect extension client.TreeConnect( infraSharePath, out treeId, (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Assert.IsTrue( response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_IDENTITY_REMOTING), "The share should support identity remoting, actually server returns {0}.", response.ShareFlags.ToString()); }, TreeConnect_Flags.SMB2_SHAREFLAG_EXTENSION_PRESENT, identity); FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client impersonates another log in user to send CREATE request and expects success."); client.Create( treeId, GetTestFileName(infraSharePath), CreateOptions_Values.FILE_DIRECTORY_FILE, out fileId, out serverCreateContexts, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); } ); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); }
public void ValidateNegotiateInfo_Negative_SMB311() { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb311); // Server will terminate connection if Validate Negotiate Info Request is not signed. TestConfig.CheckSigning(); #endregion Smb2FunctionalClient testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); Guid clientGuid = Guid.NewGuid(); DialectRevision[] requestDialects = Smb2Utility.GetDialects(DialectRevision.Smb311); Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES; SecurityMode_Values clientSecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; NEGOTIATE_Response? negotiateResponse = null; status = client.Negotiate( requestDialects, TestConfig.IsSMB1NegotiateEnabled, clientSecurityMode, clientCapabilities, clientGuid, (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(DialectRevision.Smb311, response); negotiateResponse = response; }); status = client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); uint treeId; string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName); status = client.TreeConnect(ipcPath, out treeId); VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq = new VALIDATE_NEGOTIATE_INFO_Request(); validateNegotiateInfoReq.Guid = clientGuid; validateNegotiateInfoReq.Capabilities = clientCapabilities; validateNegotiateInfoReq.SecurityMode = SecurityMode_Values.NONE; validateNegotiateInfoReq.DialectCount = (ushort)requestDialects.Length; validateNegotiateInfoReq.Dialects = requestDialects; byte[] inputBuffer = TypeMarshal.ToBytes <VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoReq); byte[] outputBuffer; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Attempt to validate negotiate info with info Guid: {0}, Capabilities: {1}, SecurityMode: {2}, DialectCount: {3}, Dialects: {4}", validateNegotiateInfoReq.Guid, validateNegotiateInfoReq.Capabilities, validateNegotiateInfoReq.SecurityMode, validateNegotiateInfoReq.DialectCount, Smb2Utility.GetArrayString(validateNegotiateInfoReq.Dialects)); try { BaseTestSite.Log.Add( LogEntryKind.TestStep, "Attempt to send a request with an SMB2 header with a Command value equal to SMB2 IOCTL, and a CtlCode of FSCTL_VALIDATE_NEGOTIATE_INFO."); client.ValidateNegotiateInfo( treeId, inputBuffer, out outputBuffer ); } catch { } BaseTestSite.Assert.IsTrue(client.Smb2Client.IsServerDisconnected, "Transport connection should be terminated when Connection.Dialect is \"3.1.1\"."); }
public void BVT_TreeMgmt_TreeConnectAndDisconnect() { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP"); client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled); client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT request"); uint treeId; client.TreeConnect(sharePath, out treeId, (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Assert.AreNotEqual <uint>(header.TreeId, uint.MaxValue, "The SMB2 server MUST reserve -1 for invalid TreeId."); }); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_DISCONNECT request."); client.TreeDisconnect(treeId); }
private void WriteFromMainChannel( DialectRevision[] requestDialect, DialectRevision expectedDialect, IPAddress serverIp, IPAddress clientIp, string contentWrite, bool isNicRedundantOnServer, out uint treeId, out FILEID fileId) { mainChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp); #region Negotiate mainChannelClient.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 mainChannelClient.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region Retrieve 2nd IP on server for alternative channel if there is if (TestConfig.UnderlyingTransport == Smb2TransportType.Tcp && isNicRedundantOnServer && TestConfig.IsIoCtlCodeSupported(CtlCode_Values.FSCTL_QUERY_NETWORK_INTERFACE_INFO)) { #region TREE_CONNECT to IPC$ string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName); mainChannelClient.TreeConnect(ipcPath, out treeId); #endregion #region IOCTL FSCTL_QUERY_NETWORK_INTERFACE_INFO NETWORK_INTERFACE_INFO_Response[] networkInfoResponses; string interfaceAddress; bool secondAddressQueried = false; mainChannelClient.QueryNetworkInterfaceInfo(treeId, out networkInfoResponses); foreach (NETWORK_INTERFACE_INFO_Response netInfoResp in networkInfoResponses) { interfaceAddress = netInfoResp.AddressStorage.Address; if (interfaceAddress != null) { BaseTestSite.Log.Add(LogEntryKind.Debug, "Get NETWORK_INTERFACE_INFO: " + interfaceAddress); if (interfaceAddress == serverIps[1].ToString()) { secondAddressQueried = true; BaseTestSite.Log.Add(LogEntryKind.Debug, "Address queried by IOCTL request with FSCTL_QUERY_NETWORK_INTERFACE_INFO matches server second address {0}", serverIps[1].ToString()); break; } } } BaseTestSite.Assert.IsTrue( secondAddressQueried, "Second address {0} should be queried by IOCTL request with FSCTL_QUERY_NETWORK_INTERFACE_INFO", serverIps[1].ToString()); #endregion } #endregion #region TREE_CONNECT to share string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); mainChannelClient.TreeConnect(uncSharePath, out treeId); #endregion #region CREATE Smb2CreateContextResponse[] serverCreateContexts; mainChannelClient.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts); #endregion if (Smb2Utility.IsSmb3xFamily(expectedDialect)) { #region WRITE mainChannelClient.Write(treeId, fileId, contentWrite); #endregion } }
private void LogFailedStatus(string operation, uint status) { logWriter.AddLog(LogLevel.Information, string.Format(operation + " failed, status: {0}", Smb2Status.GetStatusCode(status))); }
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 DurableHandleV2_WithLeaseV2_WithoutHandleCaching() { /// 1. Client requests a durable handle with LeaseV2 context, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState. /// 2. Durable Handle v2 is not granted. /// #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "DurableHandleV2_WithLeaseV2_WithoutHandleCaching" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a durable handle v2, SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState."); uint treeIdBeforeDisconnection; Connect(DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); // SMB2_LEASE_HANDLE_CACHING bit is not set in LeaseState LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, }, new Smb2CreateRequestLeaseV2 { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); // Durable Handle should not be granted. CheckCreateContextResponsesNotExist( serverCreateContexts, new DefaultDurableHandleV2ResponseChecker( BaseTestSite, 0, uint.MaxValue)); }); #endregion clientBeforeDisconnection.TreeDisconnect(treeIdBeforeDisconnection); clientBeforeDisconnection.LogOff(); clientBeforeDisconnection.Disconnect(); }
public void ReconnectOpenRequest( DurableV1ReconnectContext durableV1ReconnectContext, DurableV2ReconnectContext durableV2ReconnectContext, OplockLeaseType oplockLeaseType, LeaseKeyDifferentialType leaseKeyDifferentialType, ClientIdType clientIdType, CreateGuidType createGuidType) { if ((oplockLeaseType == OplockLeaseType.LeaseV1 || oplockLeaseType == OplockLeaseType.LeaseV2) && !testConfig.IsLeasingSupported) { Site.Assert.Inconclusive("Test case is applicable in servers that support leasing."); } bool isSameLeaseKey = (leaseKeyDifferentialType == LeaseKeyDifferentialType.SameLeaseKey); bool isSameClient = (clientIdType == ClientIdType.SameClient); bool isSameCreateGuid = (createGuidType == CreateGuidType.SameCreateGuid); FILEID fileIdAfterDisconnection; Smb2CreateContextResponse[] serverCreateContexts; IPAddress targetIPAddress; string targetServer; string targetShare; #region Construct Create Contexts Smb2CreateContextRequest[] smb2CreateContextRequest = GetOpenFileCreateContext( DurableV1RequestContext.DurableV1RequestContextNotExist, DurableV2RequestContext.DurableV2RequestContextNotExist, durableV1ReconnectContext, durableV2ReconnectContext, oplockLeaseType, isSameLeaseKey, isSameCreateGuid); #endregion #region Client reconnect to server Site.Log.Add(LogEntryKind.Debug, "Client reconnect to server"); #region Reconnect to Common Share or CA Share if (!isCAShare) { targetIPAddress = testConfig.SutIPAddress; targetServer = testConfig.SutComputerName; targetShare = testConfig.BasicFileShare; } else { targetIPAddress = testConfig.CAShareServerIP; targetServer = testConfig.CAShareServerName; targetShare = testConfig.CAShareName; } // Connect to Server testClientAfterDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClientAfterDisconnection.CreditGoal = 10; testClientAfterDisconnection.ConnectToServer(testConfig.UnderlyingTransport, targetServer, targetIPAddress); // Negotiate testClientAfterDisconnection.Negotiate( requestDialect, testConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities, // If the reconnect use the same client guid, then keep client guid the same value, otherwise use a new client guid. clientGuid: (isSameClient ? clientGuid : Guid.NewGuid())); uint status = testClientAfterDisconnection.SessionSetup( testConfig.DefaultSecurityPackage, targetServer, testConfig.AccountCredential, testConfig.UseServerGssToken); Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Reconnect Session Setup should be successful, actual status is {0}", Smb2Status.GetStatusCode(status)); // TreeConnect testClientAfterDisconnection.TreeConnect(sharePath, out treeIdAfterDisconnection); #endregion #region Send Create request according to different context combination RequestedOplockLevel_Values requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; switch (oplockLeaseType) { case OplockLeaseType.NoOplockOrLease: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; } break; case OplockLeaseType.BatchOplock: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH; } break; case OplockLeaseType.LeaseV1: case OplockLeaseType.LeaseV2: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE; } break; } status = OpenCreate( testClientAfterDisconnection, treeIdAfterDisconnection, fileName, out fileIdAfterDisconnection, out serverCreateContexts, requestedOplockLevel, smb2CreateContextRequest); #endregion DurableHandleResponseContext durableHandleResponse; LeaseResponseContext leaseResponse; CheckResponseContexts(serverCreateContexts, out durableHandleResponse, out leaseResponse); OpenResponse((ModelSmb2Status)status, durableHandleResponse, leaseResponse, handleConfig); testClientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); testClientAfterDisconnection.LogOff(); #endregion }
private void DurableHandleV2_Reconnect_WithLeaseV1(bool sameFileName, bool persistent = false) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities( persistent ? NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING | NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES: NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2, CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2, CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); #endregion string content = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb); Guid clientGuid = Guid.NewGuid(); durableHandleUncSharePath = persistent ? Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName) : Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = (persistent ? "PersistentHandle" : "DurableHandleV2") + "_Reconnect_WithLeaseV1" + Guid.NewGuid() + ".txt"; #region client connect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client connects to server and opens file with a {0} handle", persistent ? "persistent" : "durable"); uint treeIdBeforeDisconnection; Connect( DialectRevision.Smb30, clientBeforeDisconnection, clientGuid, testConfig.AccountCredential, persistent ? ConnectShareType.CAShare : ConnectShareType.BasicShareWithoutAssert, out treeIdBeforeDisconnection, null); Guid createGuid = Guid.NewGuid(); Guid leaseKey = Guid.NewGuid(); LeaseStateValues leaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING | LeaseStateValues.SMB2_LEASE_HANDLE_CACHING | LeaseStateValues.SMB2_LEASE_WRITE_CACHING; FILEID fileIdBeforeDisconnection; Smb2CreateContextResponse[] serverCreateContexts = null; status = clientBeforeDisconnection.Create( treeIdBeforeDisconnection, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Flags = persistent? CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0, }, new Smb2CreateRequestLease { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); CheckCreateContextResponses( serverCreateContexts, new DefaultDurableHandleV2ResponseChecker( BaseTestSite, persistent ? CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0, uint.MaxValue)); }); status = clientBeforeDisconnection.Write(treeIdBeforeDisconnection, fileIdBeforeDisconnection, content); #endregion clientBeforeDisconnection.Disconnect(); #region client reconnect to server BaseTestSite.Log.Add( LogEntryKind.Comment, "Client opens the same file and reconnects the {0} handle", persistent ? "durable" : "persistent"); uint treeIdAfterDisconnection; Connect( DialectRevision.Smb30, clientAfterDisconnection, clientGuid, testConfig.AccountCredential, persistent ? ConnectShareType.CAShare : ConnectShareType.BasicShareWithoutAssert, out treeIdAfterDisconnection, clientBeforeDisconnection); FILEID fileIdAfterDisconnection; status = clientAfterDisconnection.Create( treeIdAfterDisconnection, sameFileName ? fileName : (persistent ? "PersistentHandle" : "DurableHandleV2" + "_Reconnect_WithLeaseV1_WithDifferentFileName" + Guid.NewGuid() + ".txt"), CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterDisconnection, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleReconnectV2 { CreateGuid = createGuid, Flags = persistent ? CREATE_DURABLE_HANDLE_RECONNECT_V2_Flags.DHANDLE_FLAG_PERSISTENT : 0, FileId = new FILEID { Persistent = fileIdBeforeDisconnection.Persistent } }, new Smb2CreateRequestLease { LeaseKey = leaseKey, LeaseState = leaseState, } }, shareAccess: ShareAccess_Values.NONE, checker: (header, response) => { }); if (sameFileName) { BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Reconnect a durable handle should be successful"); string readContent; status = clientAfterDisconnection.Read(treeIdAfterDisconnection, fileIdAfterDisconnection, 0, (uint)content.Length, out readContent); BaseTestSite.Assert.IsTrue( readContent.Equals(content), "The written content should equal to read content."); clientAfterDisconnection.Close(treeIdAfterDisconnection, fileIdAfterDisconnection); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_INVALID_PARAMETER, status, "If Open.Lease is not NULL and Open.FileName does not match the file name specified in the Buffer field of the SMB2 CREATE request, " + "the server MUST fail the request with STATUS_INVALID_PARAMETER."); } #endregion clientAfterDisconnection.TreeDisconnect(treeIdAfterDisconnection); clientAfterDisconnection.LogOff(); clientAfterDisconnection.Disconnect(); }
private void DirecotryLeasing( DialectRevision[] requestDialect, DialectRevision expectedDialect, LeaseStateValues leaseState, LeaseBreakAckType leaseBreakAckType = LeaseBreakAckType.None) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING); TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); #endregion BaseTestSite.Log.Add( LogEntryKind.Comment, @"Start to create a directory on share \\{0}\{1} with lease state {2}", TestConfig.SutComputerName, TestConfig.BasicFileShare, leaseState); string testDirectory = CreateTestDirectory(TestConfig.SutComputerName, TestConfig.BasicFileShare); client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); #region Negotiate BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start the client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT"); Capabilities_Values capabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES; status = client.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilities, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); TestConfig.CheckNegotiateDialect(expectedDialect, response); if (expectedDialect >= DialectRevision.Smb30) { TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING, response); } }); #endregion #region SESSION_SETUP status = client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region TREE_CONNECT to share string uncSharePath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); uint treeId; status = client.TreeConnect(uncSharePath, out treeId); #endregion #region CREATE FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client sends CREATE request for the directory with the LeaseState set to {0} in SMB2_CREATE_REQUEST_LEASE_V2.", leaseState); status = client.Create( treeId, testDirectory, CreateOptions_Values.FILE_DIRECTORY_FILE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE, new Smb2CreateContextRequest[] { new Smb2CreateRequestLeaseV2 { LeaseKey = Guid.NewGuid(), LeaseState = leaseState } }, checker: (Packet_Header header, CREATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "CREATE should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); if (expectedDialect == DialectRevision.Smb2002 || expectedDialect == DialectRevision.Smb21) { BaseTestSite.Assert.AreEqual( OplockLevel_Values.OPLOCK_LEVEL_NONE, response.OplockLevel, "The expected oplock level is OPLOCK_LEVEL_NONE."); } }); #endregion if (expectedDialect >= DialectRevision.Smb30) { // Break the lease with creating another file in the directory sutProtocolController.CreateFile(Path.Combine(Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare), testDirectory), CurrentTestCaseName, string.Empty); // Wait until LEASE_BREAK_Notification is received BaseTestSite.Assert.IsTrue( // Wait 5 seconds for notification arrival notificationReceived.WaitOne(SMB2TestConfig.WAIT_TIMEOUT_IN_MILLISECONDS), "LeaseBreakNotification should be raised."); if (receivedLeaseBreakNotify.Flags == LEASE_BREAK_Notification_Packet_Flags_Values.SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED) { BaseTestSite.Log.Add( LogEntryKind.Debug, "Server requires an LEASE_BREAK_ACK on this LEASE_BREAK_NOTIFY"); #region LEASE_BREAK_ACK switch (leaseBreakAckType) { case LeaseBreakAckType.None: status = client.LeaseBreakAcknowledgment(treeId, receivedLeaseBreakNotify.LeaseKey, receivedLeaseBreakNotify.NewLeaseState); break; case LeaseBreakAckType.InvalidLeaseState: LeaseStateValues newLeaseState = LeaseStateValues.SMB2_LEASE_WRITE_CACHING; BaseTestSite.Log.Add( LogEntryKind.Comment, "Client attempts to send LEASE_BREAK_ACK with an invalid LeaseState {0} on this LEASE_BREAK_NOTIFY", newLeaseState); status = client.LeaseBreakAcknowledgment( treeId, receivedLeaseBreakNotify.LeaseKey, newLeaseState, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "LEASE_BREAK_ACK with invalid LeaseState is not expected to SUCCESS, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_REQUEST_NOT_ACCEPTED, header.Status, RequirementCategory.STATUS_REQUEST_NOT_ACCEPTED.Id, RequirementCategory.STATUS_REQUEST_NOT_ACCEPTED.Description); }); break; case LeaseBreakAckType.InvalidLeaseKey: Guid invalidLeaseKey = Guid.NewGuid(); BaseTestSite.Log.Add( LogEntryKind.Debug, "Client attempts to send LEASE_BREAK_ACK with an invalid LeaseKey {0} on this LEASE_BREAK_NOTIFY", invalidLeaseKey); status = client.LeaseBreakAcknowledgment( treeId, invalidLeaseKey, receivedLeaseBreakNotify.NewLeaseState, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "LEASE_BREAK_ACK with invalid LeaseKey is not expected to SUCCESS, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_OBJECT_NAME_NOT_FOUND, header.Status, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Id, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Description); }); break; case LeaseBreakAckType.InvalidClientGuid: BaseTestSite.Log.Add(LogEntryKind.Debug, "Initialize a new different client to attempts to send LEASE_BREAK_ACK"); Smb2FunctionalClient newClient = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); newClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); #region Negotiate status = newClient.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES); #endregion #region SESSION_SETUP status = newClient.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region TREE_CONNECT to share uint newTreeId; status = newClient.TreeConnect(uncSharePath, out newTreeId); #endregion status = newClient.LeaseBreakAcknowledgment( newTreeId, receivedLeaseBreakNotify.LeaseKey, receivedLeaseBreakNotify.NewLeaseState, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "LEASE_BREAK_ACK is not expected to SUCCESS when the open is closed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); BaseTestSite.CaptureRequirementIfAreEqual( Smb2Status.STATUS_OBJECT_NAME_NOT_FOUND, header.Status, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Id, RequirementCategory.STATUS_OBJECT_NAME_NOT_FOUND.Description); }); status = newClient.TreeDisconnect(newTreeId); status = newClient.LogOff(); BaseTestSite.Log.Add( LogEntryKind.Comment, "Initialize a new different client to attempts to send LEASE_BREAK_ACK"); break; default: throw new InvalidOperationException("Unexpected LeaseBreakAckType " + leaseBreakAckType); } #endregion } else { BaseTestSite.Log.Add( LogEntryKind.Debug, "Server does not require an LEASE_BREAK_ACK on this LEASE_BREAK_NOTIFY"); } } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: TREE_DISCONNECT; LOG_OFF"); #region TREE_DISCONNECT status = client.TreeDisconnect(treeId); #endregion #region LOGOFF status = client.LogOff(); #endregion BaseTestSite.Log.Add( LogEntryKind.Comment, @"Complete creating a directory on share \\{0}\{1} with lease state {2}", TestConfig.SutComputerName, TestConfig.BasicFileShare, leaseState); }
// [MS-SMB2] 3.3.5.9 Receiving an SMB2 CREATE Request // If the request received has SMB2_FLAGS_DFS_OPERATIONS set in the Flags field of the SMB2 header, and TreeConnect.Share.IsDfs is TRUE, the server MUST verify the value of IsDfsCapable: // If IsDfsCapable is TRUE, the server MUST invoke the interface defined in [MS-DFSC] section 3.2.4.1 to normalize the path name by supplying the target path name. // [MS-DFSC] 3.2.4.1 Handling a Path Normalization Request // As specified in [MS-SMB2] section 3.3.5.9 and [MS-SMB] section 3.3.5.5, the SMB server invokes the DFS server to normalize the path name. // When DFS server matches the path name against DFS metadata: // If the path matches or contains a DFS link, the DFS server MUST respond to the path normalization request with STATUS_PATH_NOT_COVERED, // indicating to the client to resolve the path by using a DFS link referral request. // Otherwise, the DFS server MUST change the path name to a path relative to the root of the namespace and return STATUS_SUCCESS. private void PathNormalize(bool containDFSLink) { smb2client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); smb2client.ConnectToServerOverTCP(TestConfig.SutIPAddress); smb2client.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled); smb2client.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); string dfsRootShare = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.StandaloneNamespace); smb2client.TreeConnect(dfsRootShare, out treeId); Smb2CreateContextResponse[] contextResp; // [MS-SMB2] 2.2.13 SMB2 CREATE Request // If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of the SMB2 header, // the file name can be prefixed with DFS link information that will be removed during DFS name normalization as specified in section 3.3.5.9. string fileName = dfsRootShare + @"\"; fileName += containDFSLink ? (TestConfig.DFSLink + @"\") : ""; fileName += "PathNormalization_" + Guid.NewGuid(); this.AddTestFileName(dfsRootShare, fileName); if (containDFSLink) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SMB2 create request to open a file in a DFS path contains DFS Link."); } else { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SMB2 create request to open a file in a DFS path does not contain DFS Link."); } uint status = smb2client.Create( treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, Packet_Header_Flags_Values.FLAGS_DFS_OPERATIONS | Packet_Header_Flags_Values.FLAGS_SIGNED, out fileId, out contextResp, checker: (header, response) => { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server response."); if (containDFSLink) { BaseTestSite.Assert.AreEqual( (uint)NtStatus.STATUS_PATH_NOT_COVERED, header.Status, "DFS server matches the path name against DFS metadata. If the path matches or contains a DFS link, " + "the DFS server MUST respond to the path normalization request with STATUS_PATH_NOT_COVERED, indicating to the client to resolve the path by using a DFS link referral request"); } else { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "The DFS server MUST change the path name to a path relative to the root of the namespace and return STATUS_SUCCESS, actual status is {0}", Smb2Status.GetStatusCode(header.Status)); } }); }
/// <summary> /// Operations after Negotiate, from Session Setup to Log off. /// </summary> private void PostNegotiateOperations(EnableEncryptionType enableEncryptionType, bool connectEncryptedShare) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends SESSION_SETUP request and expects response."); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); if (enableEncryptionType == EnableEncryptionType.EnableEncryptionPerSession) { // After calling this method, client will send encrypted message after session setup BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client enables global encryption."); client.EnableSessionSigningAndEncryption(enableSigning: false, enableEncryption: true); } string uncSharepath = Smb2Utility.GetUncPath(TestConfig.SutComputerName, connectEncryptedShare ? TestConfig.EncryptedFileShare : TestConfig.BasicFileShare); uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends TREE_CONNECT to share: {0}", uncSharepath); client.TreeConnect( uncSharepath, out treeId, (Packet_Header header, TREE_CONNECT_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "TreeConnect should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status)); if (connectEncryptedShare) { BaseTestSite.Assert.AreEqual( ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA, ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA & response.ShareFlags, "Server should set SMB2_SHAREFLAG_ENCRYPT_DATA for ShareFlags field in TREE_CONNECT response"); } else { BaseTestSite.Assert.AreNotEqual( ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA, ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA & response.ShareFlags, "Server should not set SMB2_SHAREFLAG_ENCRYPT_DATA for ShareFlags field in TREE_CONNECT response"); } }); if (enableEncryptionType == EnableEncryptionType.EnableEncryptionPerShare) { // After calling this method, client will send encrypted message after tree connect. BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client enables per share encryption: TreeId=0x{0:x}", treeId); client.SetTreeEncryption(treeId, true); } FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrypted CREATE request and expects success."); client.Create( treeId, CurrentTestCaseName + "_" + Guid.NewGuid() + ".txt", CreateOptions_Values.FILE_NON_DIRECTORY_FILE | CreateOptions_Values.FILE_DELETE_ON_CLOSE, out fileId, out serverCreateContexts); string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrpyted WRITE request and expects success."); client.Write(treeId, fileId, content); string actualContent; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends encrypted READ request and expects success."); client.Read(treeId, fileId, 0, (uint)content.Length, out actualContent); BaseTestSite.Assert.IsTrue( content.Equals(actualContent), "File content read should be identical to that has been written."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); }