/// <summary> /// Send ValidateNegotiateInfoRequest to Server, fill in the fields according to params. /// Verify the response. /// </summary> public void ValidateNegotiateInfoRequest(DialectType dialectType, CapabilitiesType capabilitiesType, SecurityModeType securityModeType, ClientGuidType clientGuidType) { Capabilities_Values capbilities = Connection_ClientCapabilities; if (capabilitiesType == CapabilitiesType.CapabilitiesDifferentFromNegotiate) { capbilities ^= Capabilities_Values.GLOBAL_CAP_DFS; } SecurityMode_Values securityMode = Connection_ClientSecurityMode; if (securityModeType == SecurityModeType.SecurityModeDifferentFromNegotiate) { securityMode ^= SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; } Guid guid = clientGuidType == ClientGuidType.ClientGuidSameWithNegotiate ? Connection_ClientGuid : Guid.NewGuid(); DialectRevision[] dialects = null; if (DialectType.None != dialectType) { ModelDialectRevision dialect = Connection_Dialect; if (DialectType.DialectDifferentFromNegotiate == dialectType) { dialect = ModelDialectRevision.Smb30 == Connection_Dialect ? ModelDialectRevision.Smb21 : ModelDialectRevision.Smb30; } dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(dialect)); } else { dialects = new DialectRevision[] { 0 } }; VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoRequest; validateNegotiateInfoRequest.Dialects = dialects; validateNegotiateInfoRequest.DialectCount = (ushort)dialects.Length; validateNegotiateInfoRequest.Capabilities = capbilities; validateNegotiateInfoRequest.SecurityMode = securityMode; validateNegotiateInfoRequest.Guid = guid; Site.Log.Add( LogEntryKind.Debug, "Dialects in ValidateNegotiateInfoRequest: {0}", Smb2Utility.GetArrayString(validateNegotiateInfoRequest.Dialects)); Site.Log.Add( LogEntryKind.Debug, "DialectCount in ValidateNegotiateInfoRequest: {0}", validateNegotiateInfoRequest.DialectCount); Site.Log.Add( LogEntryKind.Debug, "Capabilities in ValidateNegotiateInfoRequest: {0}", validateNegotiateInfoRequest.Capabilities); Site.Log.Add( LogEntryKind.Debug, "SecurityMode in ValidateNegotiateInfoRequest: {0}", validateNegotiateInfoRequest.SecurityMode); Site.Log.Add( LogEntryKind.Debug, "Guid in ValidateNegotiateInfoRequest: {0}", validateNegotiateInfoRequest.Guid); byte[] inputBuffer = TypeMarshal.ToBytes <VALIDATE_NEGOTIATE_INFO_Request>(validateNegotiateInfoRequest); byte[] outputBuffer; try { uint status = testClient.ValidateNegotiateInfo(treeId, inputBuffer, out outputBuffer, checker: CheckIoCtlResponse); if (Smb2Status.STATUS_SUCCESS == status) { VALIDATE_NEGOTIATE_INFO_Response validateNegotiateInfoResponse = TypeMarshal.ToStruct <VALIDATE_NEGOTIATE_INFO_Response>(outputBuffer); Site.Assert.AreEqual(negotiateResponse.DialectRevision, validateNegotiateInfoResponse.Dialect, "Dialect in Negotiate response({0}) and ValidateNegotiateInfo response({1}) should be the same", negotiateResponse.DialectRevision.ToString(), validateNegotiateInfoResponse.Dialect.ToString()); Site.Assert.AreEqual((uint)negotiateResponse.Capabilities, (uint)validateNegotiateInfoResponse.Capabilities, "Capabilities in Negotiate response({0}) and ValidateNegotiateResponse({1}) should be the same", negotiateResponse.Capabilities.ToString(), validateNegotiateInfoResponse.Capabilities.ToString()); Site.Assert.AreEqual((ushort)negotiateResponse.SecurityMode, (ushort)validateNegotiateInfoResponse.SecurityMode, "SecurityMode in Negotiate response({0}) and ValidateNegotiateInfo response({1}) should be the same", negotiateResponse.SecurityMode.ToString(), validateNegotiateInfoResponse.SecurityMode.ToString()); Site.Assert.AreEqual(negotiateResponse.ServerGuid, validateNegotiateInfoResponse.Guid, "ClientGuid in Negotiate response({0}) and ValidateNegotiateInfo response({1}) should be the same", negotiateResponse.ServerGuid.ToString(), validateNegotiateInfoResponse.Guid.ToString()); } testClient.TreeDisconnect(treeId); testClient.LogOff(); testClient.Disconnect(); this.ValidateNegotiateInfoResponse((ModelSmb2Status)status, validateNegotiateInfoConfig); return; } catch { } Site.Assert.IsTrue(testClient.Smb2Client.IsServerDisconnected, "ValidateNegotiationInfo failure should be caused by transport connection termination"); TerminateConnection(); }
private void InternalConnectShare(string domain, string userName, string password, string shareName, TimeSpan timeout, SecurityPackageType securityPackage, bool useServerToken) { uint status; DialectRevision selectedDialect; Packet_Header header; byte[] serverGssToken; Array allDialects = Enum.GetValues(typeof(DialectRevision)); DialectRevision[] validDialects = new DialectRevision[allDialects.Length - 2]; int index = 0; foreach (var dialect in allDialects) { if ((DialectRevision)dialect != DialectRevision.Smb2Unknown && (DialectRevision)dialect != DialectRevision.Smb2Wildcard) { validDialects[index++] = (DialectRevision)dialect; } } PreauthIntegrityHashID[] preauthIntegrityHashIDArray = null; EncryptionAlgorithm[] encryptionAlgorithmArray = null; if (validDialects.Contains(DialectRevision.Smb311)) { preauthIntegrityHashIDArray = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 }; encryptionAlgorithmArray = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM }; } // Negotiate: NEGOTIATE_Response negotiateResponse; CheckStatusCode( client.Negotiate( 1, 1, Packet_Header_Flags_Values.NONE, messageId++, // Will negotiate highest dialect server supports validDialects, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_LARGE_MTU, clientGuid, out selectedDialect, out serverGssToken, out header, out negotiateResponse, preauthHashAlgs: preauthIntegrityHashIDArray, encryptionAlgs: encryptionAlgorithmArray)); negotiatedDialect = selectedDialect; serverCapabilities = (Capabilities_Values)negotiateResponse.Capabilities; // 3.2.5.2: If the SecurityMode field in the SMB2 header of the response has the SMB2_NEGOTIATE_SIGNING_REQUIRED bit set, // the client MUST set Connection.RequireSigning to TRUE. // 3.2.5.3.1: If the global setting RequireMessageSigning is set to TRUE or // Connection.RequireSigning is set to TRUE then Session.SigningRequired MUST be set to TRUE bool session_SigningRequired = negotiateResponse.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED); if (session_SigningRequired) { // 3.2.4.1.1: If the client signs the request, it MUST set the SMB2_FLAGS_SIGNED bit in the Flags field of the SMB2 header. headerFlags |= Packet_Header_Flags_Values.FLAGS_SIGNED; } // Session setup: SESSION_SETUP_Response sessionSetupResponse; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( securityPackage, new AccountCredential(domain, userName, password), Smb2Utility.GetCifsServicePrincipalName(serverPrincipleName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); if (securityPackage == SecurityPackageType.Negotiate) sspiClientGss.Initialize(serverGssToken); else sspiClientGss.Initialize(null); do { status = client.SessionSetup( 1, 1, 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 serverGssToken, out header, out sessionSetupResponse); CheckStatusCode(status); if ((status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || status == Smb2Status.STATUS_SUCCESS) && serverGssToken != null && serverGssToken.Length > 0) { sspiClientGss.Initialize(serverGssToken); } } while (status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); // 3.2.4.1.1 If Connection.Dialect is "3.1.1" and the message being sent is a TREE_CONNECT Request and the session identified by SessionId has Session.EncryptData equal to FALSE bool treeconnect_SigningRequired = session_SigningRequired || (selectedDialect >= DialectRevision.Smb311); client.GenerateCryptoKeys(sessionId, sspiClientGss.SessionKey, treeconnect_SigningRequired, false); this.sessionId = header.SessionId; // Session Key will be used in the MS-LSA SDK, see LsaClient.cs Line 179 SessionKey // Insert the session key to the global context Smb2ClientSession smb2CliSession = new Smb2ClientSession(); smb2CliSession.SessionKey = client.GetSessionKeyForAuthenticatedContext(sessionId); Smb2ClientConnection smb2CliConn = new Smb2ClientConnection(); smb2CliConn.SessionTable = new Dictionary<ulong, Smb2ClientSession>(); smb2CliConn.SessionTable.Add(sessionId, smb2CliSession); context.ConnectionTable = new Dictionary<string, Smb2ClientConnection>(); context.ConnectionTable.Add("Smb2ClientConnection", smb2CliConn); // Tree connect: TREE_CONNECT_Response treeConnectResponse; status = client.TreeConnect( 1, 1, treeconnect_SigningRequired? headerFlags| Packet_Header_Flags_Values.FLAGS_SIGNED:headerFlags, messageId++, sessionId, "\\\\" + serverPrincipleName + "\\" + shareName, out treeId, out header, out treeConnectResponse); this.treeId = header.TreeId; // For the messages followed by TREE_CONNECT, set them as signed/not signed following the normal proces client.EnableSessionSigningAndEncryption(sessionId, session_SigningRequired, false); }
public Smb2TreeConnectResponsePacket CreateTreeConnectResponse( Smb2Endpoint endpoint, ulong messageId, uint treeId, ShareType_Values shareType, ShareFlags_Values shareFlags, Capabilities_Values capabilities, _ACCESS_MASK maximalAccess ) { Smb2TreeConnectResponsePacket packet = new Smb2TreeConnectResponsePacket(); SetHeader(packet, endpoint, messageId); packet.Header.TreeId = treeId; packet.PayLoad.Capabilities = capabilities; packet.PayLoad.MaximalAccess = maximalAccess; packet.PayLoad.Reserved = Reserved_Values.V1; packet.PayLoad.ShareFlags = shareFlags; packet.PayLoad.ShareType = shareType; packet.PayLoad.StructureSize = StructureSize_Values.V1; packet.Sign(); return packet; }
/// <summary> /// Connect to share on general clustered file server before failover happens, include NEGOTIATE, SESSION_SETUP, TREE_CONNECT /// </summary> /// <param name="server">Name of clustered file server</param> /// <param name="fsType">Type of clustered file server</param> /// <param name="treeId">Out param for tree Id that connected</param> /// <param name="enableEncryptionPerShare">Set true if enable encryption on share, otherwise set false</param> private void ConnectGeneralFileServerBeforeFailover(string server, out uint treeId, bool enableEncryptionPerShare = false) { BaseTestSite.Log.Add( LogEntryKind.Debug, "BeforeFailover: Connect share {0} on server {1} with following steps.", uncSharePath, server); GetGeneralFileServerClusterOwner(server); clientBeforeFailover.ConnectToServer(TestConfig.UnderlyingTransport, server, currentAccessIp); #region Negotiate Capabilities_Values clientCapabilitiesBeforeFAilover = 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 = clientBeforeFailover.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilitiesBeforeFAilover, clientGuid: clientGuid, checker: (Packet_Header header, NEGOTIATE_Response response) => { TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); } ); #endregion #region SESSION_SETUP status = clientBeforeFailover.SessionSetup( TestConfig.DefaultSecurityPackage, server, TestConfig.AccountCredential, TestConfig.UseServerGssToken); BaseTestSite.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion #region TREE_CONNECT to share status = clientBeforeFailover.TreeConnect( uncSharePath, out treeId, (Packet_Header header, TREE_CONNECT_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "TreeConnect should succeed."); if (enableEncryptionPerShare) { 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"); } BaseTestSite.Assert.IsTrue(response.Capabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY), "CA Share should have SHARE_CAP_CONTINUOUS_AVAILABILITY bit set for Capabilities in TreeConnect response."); }); clientBeforeFailover.SetTreeEncryption(treeId, enableEncryptionPerShare); BaseTestSite.Log.Add( LogEntryKind.Debug, "Per share encryption for TreeId=0x{0:x} : {1}", treeId, enableEncryptionPerShare); #endregion BaseTestSite.Log.Add( LogEntryKind.Debug, "BeforeFailover: Finish connecting to share {0} on server {1}", uncSharePath, server); }
public void OpenRequest( ModelDialectRevision clientMaxDialect, PersistentBitType persistentBit, CAShareType connectToCAShare, OplockLeaseType oplockLeaseType, DurableV1RequestContext durableV1RequestContext, DurableV2RequestContext durableV2RequestContext, DurableV1ReconnectContext durableV1ReconnectContext, DurableV2ReconnectContext durableV2ReconnectContext) { requestDialect = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect)); clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; if (persistentBit == PersistentBitType.PersistentBitSet) { clientCapabilities |= Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES; } clientGuid = Guid.NewGuid(); requestedContext = oplockLeaseType; isCAShare = (connectToCAShare == CAShareType.CAShare); IPAddress targetIPAddress; string targetServer; #region Connect to Common Share or CA Share if (!isCAShare) { sharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "PrepareHandle_ConnectTo_CommonShareFile_" + Guid.NewGuid() + ".txt"; targetIPAddress = testConfig.SutIPAddress; targetServer = testConfig.SutComputerName; } else { sharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName); fileName = "PrepareHandle_ConnectTo_CAShareFile_" + Guid.NewGuid().ToString() + ".txt"; targetIPAddress = testConfig.CAShareServerIP; targetServer = testConfig.CAShareServerName; } testClientBeforeDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClientBeforeDisconnection.CreditGoal = 20; testClientBeforeDisconnection.ConnectToServer(testConfig.UnderlyingTransport, targetServer, targetIPAddress); testClientBeforeDisconnection.Negotiate( requestDialect, testConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities, clientGuid: clientGuid, checker: (header, response) => { if (Smb2Utility.IsSmb3xFamily(response.DialectRevision) && handleConfig.IsPersistentHandleSupported && persistentBit == PersistentBitType.PersistentBitSet) { Site.Assert.IsTrue( response.Capabilities.HasFlag(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES), "The server MUST set SMB2_GLOBAL_CAP_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " + "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles. " + "Actual capabilities are {0}", response.Capabilities); } }); testClientBeforeDisconnection.SessionSetup( testConfig.DefaultSecurityPackage, targetServer, testConfig.AccountCredential, testConfig.UseServerGssToken); testClientBeforeDisconnection.TreeConnect(sharePath, out treeIdBeforeDisconnection); #endregion #region Construct Create Contexts Smb2CreateContextRequest[] smb2CreateContextRequest = GetOpenFileCreateContext( durableV1RequestContext, durableV2RequestContext, durableV1ReconnectContext, durableV2ReconnectContext, oplockLeaseType, false, false); #endregion #region Send Create request according to different context combination RequestedOplockLevel_Values requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; switch (oplockLeaseType) { case OplockLeaseType.NoOplockOrLease: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; } break; case OplockLeaseType.BatchOplock: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH; } break; case OplockLeaseType.LeaseV1: case OplockLeaseType.LeaseV2: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE; } break; } FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; uint status = OpenCreate( testClientBeforeDisconnection, treeIdBeforeDisconnection, fileName, out fileId, out serverCreateContexts, requestedOplockLevel, smb2CreateContextRequest); #endregion DurableHandleResponseContext durableHandleResponse; LeaseResponseContext leaseResponse; CheckResponseContexts(serverCreateContexts, out durableHandleResponse, out leaseResponse); OpenResponse((ModelSmb2Status)status, durableHandleResponse, leaseResponse, handleConfig); testClientBeforeDisconnection.TreeDisconnect(treeIdAfterDisconnection, (header, response) => { }); testClientBeforeDisconnection.LogOff(); }
private void 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 | Capabilities_Values.GLOBAL_CAP_ENCRYPTION; 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 FileServerFailover_BlockCreateFromDifferentClient() { uncSharePath = Smb2Utility.GetUncPath(TestConfig.ClusteredFileServerName, TestConfig.ClusteredFileShare); #region From one client open a file and request persistent handle before failover BaseTestSite.Log.Add(LogEntryKind.TestStep, "From one client open a file and request persistent handle before failover"); FILEID fileIdBeforeFailover; uint treeIdBeforeFailover; BaseTestSite.Log.Add(LogEntryKind.TestStep, "BeforeFailover: Connect to general file server {0}.", TestConfig.ClusteredFileServerName); ConnectGeneralFileServerBeforeFailover(TestConfig.ClusteredFileServerName, out treeIdBeforeFailover); #region CREATE a durable open with flag DHANDLE_FLAG_PERSISTENT BaseTestSite.Log.Add(LogEntryKind.TestStep, "BeforeFailover: CREATE a durable open with flag DHANDLE_FLAG_PERSISTENT."); Smb2CreateContextResponse[] serverCreateContexts; createGuid = Guid.NewGuid(); status = clientBeforeFailover.Create( treeIdBeforeFailover, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdBeforeFailover, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, Timeout = 3600000, }, }); #endregion #endregion BaseTestSite.Log.Add( LogEntryKind.TestStep, "Disable owner node to simulate failover"); FailoverServer(currentAccessIp, TestConfig.ClusteredFileServerName, FileServerType.GeneralFileServer); #region From a different client try to open the same file after failover BaseTestSite.Log.Add( LogEntryKind.TestStep, "AfterFailover: From a different client try to open the same file"); DoUntilSucceed(() => clientAfterFailover.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.ClusteredFileServerName, currentAccessIp), TestConfig.FailoverTimeout, "Retry to connect to server until succeed within timeout span"); #region Connect to the same share of the same general file server BaseTestSite.Log.Add(LogEntryKind.TestStep, "AfterFailover: Connect to the same share of the same general file server."); #region Negotiate Capabilities_Values clientCapabilitiesAfterFailover = 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 = clientAfterFailover.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilitiesAfterFailover, checker: (Packet_Header header, NEGOTIATE_Response response) => { TestConfig.CheckNegotiateDialect(DialectRevision.Smb21, response); }); #endregion #region SESSION_SETUP status = clientAfterFailover.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.ClusteredFileServerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); #endregion #region TREE_CONNECT to share uint treeIdAfterFailover = 0; //Retry TreeConnect until succeed within timeout span status = DoUntilSucceed( () => clientAfterFailover.TreeConnect(uncSharePath, out treeIdAfterFailover, (header, response) => { }), TestConfig.FailoverTimeout, "Retry TreeConnect until succeed within timeout span"); BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, status, "TreeConnect to {0} should succeed, actual status is {1}", uncSharePath, Smb2Status.GetStatusCode(status)); #endregion #endregion #region CREATE to open the same file BaseTestSite.Log.Add(LogEntryKind.TestStep, "AfterFailover: Send CREATE request using incompatible share access with previous CREATE and this should result violation"); FILEID fileIdAfterFailover; status = clientAfterFailover.Create( treeIdAfterFailover, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileIdAfterFailover, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, null, // Incompatible share access with previous CREATE request and will result violation shareAccess: ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_DELETE, checker: (header, response) => { BaseTestSite.Assert.AreNotEqual( Smb2Status.STATUS_SUCCESS, header.Status, "From a different client try to open the same file after failover should not success"); }); #endregion #endregion }
public void PrepareOpen( ModelDialectRevision clientMaxDialect, PersistentBitType persistentBit, CAShareType connectToCAShare, ModelHandleType modelHandleType, OplockLeaseType oplockLeaseType) { // Lease V2 cases only apply on the server implements SMB 3.x family. if (oplockLeaseType == OplockLeaseType.LeaseV2) { testConfig.CheckDialect(DialectRevision.Smb30); } // Lease V1 cases only apply on the server implements SMB 2.1 and 3.x family. if (oplockLeaseType == OplockLeaseType.LeaseV1) { testConfig.CheckDialect(DialectRevision.Smb21); } if ((oplockLeaseType == OplockLeaseType.LeaseV1 || oplockLeaseType == OplockLeaseType.LeaseV2) && !testConfig.IsLeasingSupported) { Site.Assert.Inconclusive("Test case is applicable in servers that support leasing."); } requestDialect = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect)); clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; if (persistentBit == PersistentBitType.PersistentBitSet) { clientCapabilities |= Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES; } clientGuid = Guid.NewGuid(); requestedContext = oplockLeaseType; isCAShare = (connectToCAShare == CAShareType.CAShare); IPAddress targetIPAddress; string targetServer; #region Connect to Common Share or CA Share if (!isCAShare) { sharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "PrepareHandle_ConnectTo_CommonShareFile_" + Guid.NewGuid() + ".txt"; targetIPAddress = testConfig.SutIPAddress; targetServer = testConfig.SutComputerName; } else { sharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName); fileName = "PrepareHandle_ConnectTo_CAShareFile_" + Guid.NewGuid().ToString() + ".txt"; targetIPAddress = testConfig.CAShareServerIP; targetServer = testConfig.CAShareServerName; } testClientBeforeDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClientBeforeDisconnection.CreditGoal = 20; testClientBeforeDisconnection.ConnectToServer(testConfig.UnderlyingTransport, targetServer, targetIPAddress); testClientBeforeDisconnection.Negotiate( requestDialect, testConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities, clientGuid: clientGuid, checker: (header, response) => { if (Smb2Utility.IsSmb3xFamily(response.DialectRevision) && handleConfig.IsPersistentHandleSupported && persistentBit == PersistentBitType.PersistentBitSet) { Site.Assert.IsTrue( response.Capabilities.HasFlag(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES), "The server MUST set SMB2_GLOBAL_CAP_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " + "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles. " + "Actual capabilities are {0}", response.Capabilities); } }); testClientBeforeDisconnection.SessionSetup( testConfig.DefaultSecurityPackage, targetServer, testConfig.AccountCredential, testConfig.UseServerGssToken); testClientBeforeDisconnection.TreeConnect(sharePath, out treeIdBeforeDisconnection); #endregion #region Create operation according to the handle type and context Smb2CreateContextRequest[] prepareRequestContext = null; Smb2CreateContextResponse[] serverCreateContexts = null; RequestedOplockLevel_Values requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; switch (oplockLeaseType) { case OplockLeaseType.LeaseV1: { testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); prepareRequestContext = GetPrepareOpenCreateContext(modelHandleType, oplockLeaseType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE; } break; case OplockLeaseType.LeaseV2: { testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); prepareRequestContext = GetPrepareOpenCreateContext(modelHandleType, oplockLeaseType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE; } break; case OplockLeaseType.BatchOplock: { prepareRequestContext = GetPrepareOpenHandleContext(modelHandleType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH; } break; case OplockLeaseType.NoOplockOrLease: { prepareRequestContext = GetPrepareOpenHandleContext(modelHandleType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; } break; } PrepareOpenCreate( testClientBeforeDisconnection, treeIdBeforeDisconnection, fileName, out fileIdBeforDisconnection, out serverCreateContexts, requestedOplockLevel, prepareRequestContext); #endregion }
public void OpenRequest( ModelDialectRevision clientMaxDialect, PersistentBitType persistentBit, CAShareType connectToCAShare, OplockLeaseType oplockLeaseType, DurableV1RequestContext durableV1RequestContext, DurableV2RequestContext durableV2RequestContext, DurableV1ReconnectContext durableV1ReconnectContext, DurableV2ReconnectContext durableV2ReconnectContext) { requestDialect = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect)); clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; if (persistentBit == PersistentBitType.PersistentBitSet) { clientCapabilities |= Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES; } clientGuid = Guid.NewGuid(); requestedContext = oplockLeaseType; isCAShare = (connectToCAShare == CAShareType.CAShare); IPAddress targetIPAddress; string targetServer; #region Connect to Common Share or CA Share if (!isCAShare) { sharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "PrepareHandle_ConnectTo_CommonShareFile_" + Guid.NewGuid() + ".txt"; targetIPAddress = testConfig.SutIPAddress; targetServer = testConfig.SutComputerName; } else { sharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName); fileName = "PrepareHandle_ConnectTo_CAShareFile_" + Guid.NewGuid().ToString() + ".txt"; targetIPAddress = testConfig.CAShareServerIP; targetServer = testConfig.CAShareServerName; } testClientBeforeDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClientBeforeDisconnection.CreditGoal = 20; testClientBeforeDisconnection.ConnectToServer(testConfig.UnderlyingTransport, targetServer, targetIPAddress); testClientBeforeDisconnection.Negotiate( requestDialect, testConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities, clientGuid: clientGuid, checker: (header, response) => { if (Smb2Utility.IsSmb3xFamily(response.DialectRevision) && handleConfig.IsPersistentHandleSupported && persistentBit == PersistentBitType.PersistentBitSet) { Site.Assert.IsTrue( response.Capabilities.HasFlag(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES), "The server MUST set SMB2_GLOBAL_CAP_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " + "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles. " + "Actual capabilities are {0}", response.Capabilities); } }); testClientBeforeDisconnection.SessionSetup( testConfig.DefaultSecurityPackage, targetServer, testConfig.AccountCredential, testConfig.UseServerGssToken); testClientBeforeDisconnection.TreeConnect(sharePath, out treeIdBeforeDisconnection); #endregion #region Construct Create Contexts Smb2CreateContextRequest[] smb2CreateContextRequest = GetOpenFileCreateContext( durableV1RequestContext, durableV2RequestContext, durableV1ReconnectContext, durableV2ReconnectContext, oplockLeaseType, false, false); #endregion #region Send Create request according to different context combination RequestedOplockLevel_Values requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; switch (oplockLeaseType) { case OplockLeaseType.NoOplockOrLease: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; } break; case OplockLeaseType.BatchOplock: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH; } break; case OplockLeaseType.LeaseV1: case OplockLeaseType.LeaseV2: { requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE; } break; } FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; uint status = OpenCreate( testClientBeforeDisconnection, treeIdBeforeDisconnection, fileName, out fileId, out serverCreateContexts, requestedOplockLevel, smb2CreateContextRequest); #endregion DurableHandleResponseContext durableHandleResponse; LeaseResponseContext leaseResponse; CheckResponseContexts(serverCreateContexts, out durableHandleResponse, out leaseResponse); OpenResponse((ModelSmb2Status)status, durableHandleResponse, leaseResponse, handleConfig); testClientBeforeDisconnection.TreeDisconnect(treeIdAfterDisconnection, (header, response) => { }); testClientBeforeDisconnection.LogOff(); }
/// <summary> /// Connect share on file server /// </summary> /// <param name="serverIp">Server IP address used for connection</param> /// <param name="clientIp">Client IP address used for connection</param> /// <param name="client">Client object to initialize the connection</param> /// <param name="treeId">Out param tree id connected</param> /// <param name="enableEncryptionPerShare">True indicates encryption enabled per share, otherwise disabled</param> private void ConnectShare(IPAddress serverIp, IPAddress clientIp, Smb2FunctionalClient client, out uint treeId, bool enableEncryptionPerShare = false) { BaseTestSite.Log.Add( LogEntryKind.Debug, "Connect to share {0} with following steps.", uncSharePath); BaseTestSite.Log.Add( LogEntryKind.Debug, "Connect to server via Nic with Ip {0}", clientIp.ToString()); client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp); #region Negotiate 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 | Capabilities_Values.GLOBAL_CAP_ENCRYPTION; status = client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities, checker: (Packet_Header header, NEGOTIATE_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "CREATE should succeed."); TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); }); #endregion #region SESSION_SETUP status = client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); BaseTestSite.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion #region TREE_CONNECT to share status = client.TreeConnect( uncSharePath, out treeId, (Packet_Header header, TREE_CONNECT_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "TreeConnect should succeed."); if (enableEncryptionPerShare) { 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"); } }); client.SetTreeEncryption(treeId, enableEncryptionPerShare); BaseTestSite.Log.Add( LogEntryKind.Debug, "Per share encryption for TreeId=0x{0:x} : {1}", treeId, enableEncryptionPerShare); #endregion BaseTestSite.Log.Add( LogEntryKind.Debug, "Finish connecting to share {0}", uncSharePath); }
/// <summary> /// Establish main channel, which includes NEGOTIATE, SESSION_SETUP and TREE_CONNECT /// </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">Out param for tree Id that connected</param> /// <param name="enableEncryptionPerShare">Set true if enable encryption on share, otherwise set false</param> private void EstablishMainChannel( DialectRevision[] requestDialect, IPAddress serverIp, IPAddress clientIp, out uint treeId, bool enableEncryptionPerShare = false) { BaseTestSite.Log.Add( LogEntryKind.Debug, "Establish main channel to connect share {0} with following steps.", uncSharePath); mainChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp); #region Negotiate Capabilities_Values mainChannelClientCapabilities = 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 = mainChannelClient.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid, capabilityValue: mainChannelClientCapabilities, 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 = mainChannelClient.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); BaseTestSite.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion #region Retrieve 2nd IP on server for alternative channel if there is #region TREE_CONNECT to IPC$ string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName); status = mainChannelClient.TreeConnect(ipcPath, out treeId); #endregion if (TestConfig.UnderlyingTransport == Smb2TransportType.Tcp) { #region IOCTL FSCTL_QUERY_NETWORK_INTERFACE_INFO NETWORK_INTERFACE_INFO_Response[] networkInfoResponses; string interfaceAddress; bool secondAddressQueried = false; status = 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 status = mainChannelClient.TreeConnect( uncSharePath, out treeId, (Packet_Header header, TREE_CONNECT_Response response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "TreeConnect should succeed."); if (enableEncryptionPerShare) { 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"); } }); mainChannelClient.SetTreeEncryption(treeId, enableEncryptionPerShare); BaseTestSite.Log.Add( LogEntryKind.Debug, "Per share encryption for TreeId=0x{0:x} : {1}", treeId, enableEncryptionPerShare); #endregion BaseTestSite.Log.Add( LogEntryKind.Debug, "Finish establishing main channel to connect share {0}", uncSharePath); }
private void InitializeMainChannel( ModelDialectRevision maxSmbVersionClientSupported, Guid clientGuid, ReplayModelShareType shareType, out uint treeId, bool isReconnect = false, bool isClientSupportPersistent = true) { Site.Assume.IsNull(smb2ClientMainChannel, "Expect smb2ClientMainChannel is NULL."); smb2ClientMainChannel = new Smb2FunctionalClient(testConfig.Timeout, testConfig, Site); smb2ClientMainChannel.Smb2Client.LeaseBreakNotificationReceived += new Action<Packet_Header, LEASE_BREAK_Notification_Packet>(OnLeaseBreakNotificationReceived); smb2ClientMainChannel.Smb2Client.OplockBreakNotificationReceived += new Action<Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived); serverIpMainChannel = (shareType == ReplayModelShareType.CAShare ? testConfig.CAShareServerIP : testConfig.SutIPAddress); serverNameMainChannel = (shareType == ReplayModelShareType.CAShare) ? testConfig.CAShareServerName : testConfig.SutComputerName; smb2ClientMainChannel.ConnectToServer(testConfig.UnderlyingTransport, serverNameMainChannel, serverIpMainChannel); DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported)); 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; clientCapabilitiesMainChannel = ModelUtility.IsSmb3xFamily(maxSmbVersionClientSupported)? capability : Capabilities_Values.NONE; status = smb2ClientMainChannel.Negotiate( dialects, testConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilitiesMainChannel, clientGuid: maxSmbVersionClientSupported == ModelDialectRevision.Smb2002 ? Guid.Empty : clientGuid, checker: (header, response) => { Site.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); dialectMainChannel = negotiateResponse.Value.DialectRevision; #endregion #region SESSION_SETUP principleNameMainChannel = (shareType == ReplayModelShareType.CAShare ? testConfig.CAShareServerName : testConfig.SutComputerName); if (isReconnect) { status = smb2ClientMainChannel.ReconnectSessionSetup( sessionIdMainChannel, testConfig.DefaultSecurityPackage, principleNameMainChannel, testConfig.AccountCredential, testConfig.UseServerGssToken); sessionIdMainChannel = smb2ClientMainChannel.SessionId; sessionKeyMainChannel = smb2ClientMainChannel.SessionKey; } else { status = smb2ClientMainChannel.SessionSetup( testConfig.DefaultSecurityPackage, principleNameMainChannel, testConfig.AccountCredential, testConfig.UseServerGssToken); sessionIdMainChannel = smb2ClientMainChannel.SessionId; sessionKeyMainChannel = smb2ClientMainChannel.SessionKey; } Site.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion #region TREE_CONNECT to share sharePathMainChannel = (shareType == ReplayModelShareType.CAShare ? Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName) : Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare)); status = smb2ClientMainChannel.TreeConnect( sharePathMainChannel, out treeId); Site.Log.Add( LogEntryKind.Debug, "Establish main channel to connect share {0}", sharePathMainChannel); smb2ClientMainChannel.SetTreeEncryption(treeId, false); #endregion }
private void Initialize() { smb2ClientMainChannel = null; smb2ClientAlternativeChannel = null; prepared = false; setIntegrityInfo.ChecksumAlgorithm = FSCTL_SET_INTEGRITY_INFO_INPUT_CHECKSUMALGORITHM.CHECKSUM_TYPE_CRC64; setIntegrityInfo.Flags = FSCTL_SET_INTEGRITY_INFO_INPUT_FLAGS.FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF; setIntegrityInfo.Reserved = FSCTL_SET_INTEGRITY_INFO_INPUT_RESERVED.V1; endOfFileInformation.EndOfFile = 2048; fileNameMainChannel = Guid.NewGuid().ToString(); leaseKeyMainChannel = Guid.NewGuid(); clientGuidMainChannel = Guid.NewGuid(); createGuidMainChannel = Guid.NewGuid(); clientCapabilitiesMainChannel = Capabilities_Values.NONE; }
/// <summary> /// Negotiate, SessionSetup and TreeConnect /// </summary> public void SetupConnection(ModelDialectRevision dialect, ModelCapabilities capabilities, SecurityMode_Values securityMode) { #region Connect to server testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress); #endregion // It MUST be a GUID generated by the client, if the Dialects field contains a value other than 0x0202. Otherwise, the client MUST set this to 0. Guid clientGuid = (dialect == ModelDialectRevision.Smb2002) ? Guid.Empty : Guid.NewGuid(); #region negotiate testClient.Negotiate( Packet_Header_Flags_Values.NONE, Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(dialect)), securityMode, (Capabilities_Values)capabilities, clientGuid, (header, response) => { Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); #endregion #region session setup testClient.SessionSetup( testConfig.DefaultSecurityPackage, testConfig.SutComputerName, testConfig.AccountCredential, testConfig.UseServerGssToken, (SESSION_SETUP_Request_SecurityMode_Values)securityMode); #endregion #region treeconnect testClient.TreeConnect( Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare), out treeId); #endregion Connection_Dialect = ModelUtility.GetModelDialectRevision(negotiateResponse.DialectRevision); Connection_ClientCapabilities = (Capabilities_Values)capabilities; Connection_ClientSecurityMode = securityMode; Connection_ClientGuid = clientGuid; }
/// <summary> /// Reconnect to share on clustered file server after failover happens, include NEGOTIATE, SESSION_SETUP, TREE_CONNECT /// </summary> /// <param name="server">Name of clustered file server</param> /// <param name="fsType">Type of clustered file server</param> /// <param name="treeId">Out param for tree Id that connected</param> /// <param name="enableEncryptionPerShare">Set true if enable encryption on share, otherwise set false</param> private void ReconnectServerAfterFailover(string server, FileServerType fsType, out uint treeId, bool enableEncryptionPerShare = false) { BaseTestSite.Log.Add( LogEntryKind.Debug, "AfterFailover: Connect share {0} on server {1} with following steps.", uncSharePath, server); if (fsType == FileServerType.ScaleOutFileServer) { // For scale-out file server case, retrieve and use another access IP for connection IPAddress oldAccessIp = currentAccessIp; currentAccessIp = null; foreach (var ip in accessIpList) { if (!ip.Equals(oldAccessIp)) { currentAccessIp = ip; break; } } } else if (fsType == FileServerType.GeneralFileServer) { currentAccessIp = null; DoUntilSucceed(() => { foreach (IPAddress ipAddress in accessIpList) { Smb2FunctionalClient pingClient = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite); try { pingClient.ConnectToServerOverTCP(ipAddress); pingClient.Disconnect(); pingClient = null; currentAccessIp = ipAddress; return(true); } catch { } } return(false); }, TestConfig.FailoverTimeout, "Retry to ping to server until succeed within timeout span"); } BaseTestSite.Assert.AreNotEqual( null, currentAccessIp, "Access IP to the file server should not be empty"); BaseTestSite.Log.Add( LogEntryKind.Debug, "Got IP {0} to access the file server", currentAccessIp.ToString()); DoUntilSucceed(() => clientAfterFailover.ConnectToServer(TestConfig.UnderlyingTransport, server, currentAccessIp), TestConfig.FailoverTimeout, "Retry to connect to server until succeed within timeout span"); #region Negotiate Capabilities_Values clientCapabilitiesAfterFailover = 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 = clientAfterFailover.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilitiesAfterFailover, clientGuid: clientGuid, checker: (Packet_Header header, NEGOTIATE_Response response) => { TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); }); #endregion #region SESSION_SETUP status = clientAfterFailover.ReconnectSessionSetup( clientBeforeFailover, TestConfig.DefaultSecurityPackage, server, TestConfig.AccountCredential, TestConfig.UseServerGssToken); BaseTestSite.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion #region TREE_CONNECT to share uint innerTreeId = 0; //Retry TreeConnect until succeed within timeout span status = DoUntilSucceed( () => clientAfterFailover.TreeConnect(uncSharePath, out innerTreeId, (header, response) => { }), TestConfig.FailoverTimeout, "Retry TreeConnect until succeed within timeout span"); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "TreeConnect to {0} should succeed, actual status is {1}", uncSharePath, Smb2Status.GetStatusCode(status)); treeId = innerTreeId; clientAfterFailover.SetTreeEncryption(innerTreeId, enableEncryptionPerShare); BaseTestSite.Log.Add( LogEntryKind.Debug, "Per share encryption for TreeId=0x{0:x} : {1}", treeId, enableEncryptionPerShare); #endregion BaseTestSite.Log.Add( LogEntryKind.Debug, "AfterFailover: Finish connecting to share {0} on server {1}", uncSharePath, server); }
public void BVT_Replay_ReplayCreate() { ///1. mainChannelClient opens a file ///2. mainChannelClient loses connection. ///3. ChannelSequence is increased by 1. ///4. alternativeChannelClient opens the same file with replay flag set. #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 durableHandleGuid = Guid.NewGuid(); Guid clientGuid = Guid.NewGuid(); Capabilities_Values capabilityValue = Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; #region MainChannelClient Finish Session Setup and AlternativeChannelClient Establish Another Channel BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start a client from main channel by sending the following requests: NEGOTIATE; SESSION_SETUP"); 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); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Start another client from alternative channel by sending the following requests: NEGOTIATE SESSION_SETUP"); alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutAlternativeIPAddress); alternativeChannelClient.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: capabilityValue, clientGuid: clientGuid, checker: ReplayNegotiateResponseChecker); alternativeChannelClient.AlternativeChannelSessionSetup(mainChannelClient, TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false); #endregion #region MainChannelClient Create a File with DurableHandleV1 and BatchOpLock uint treeId; BaseTestSite.Log.Add(LogEntryKind.TestStep, "The main channel client sends TREE_CONNECT request."); mainChannelClient.TreeConnect(sharePath, out treeId); FILEID fileId; Smb2CreateContextResponse[] createContextResponse; BaseTestSite.Log.Add( LogEntryKind.TestStep, "The main channel client sends CREATE request with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context."); mainChannelClient.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = durableHandleGuid } }); CheckCreateContextResponses(createContextResponse, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the main channel client by sending DISCONNECT request."); mainChannelClient.Disconnect(); alternativeChannelClient.SessionChannelSequence++; #region AlternativeChannelClient Opens the Previously Created File with Replay Flag Set FILEID alternativeFileId; BaseTestSite.Log.Add( LogEntryKind.TestStep, "The alternative client sends CREATE request with replay flag set and SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 to open the same file with the main channel client."); alternativeChannelClient.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, Packet_Header_Flags_Values.FLAGS_REPLAY_OPERATION | (testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE), out alternativeFileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = durableHandleGuid } }); CheckCreateContextResponses(createContextResponse, new DefaultDurableHandleV2ResponseChecker(BaseTestSite, 0, uint.MaxValue)); #endregion BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the alternative channel client by sending the following requests: TREE_DISCONNECT; LOG_OFF"); alternativeChannelClient.TreeDisconnect(treeId); alternativeChannelClient.LogOff(); }
/// <summary> /// Common method used to connect to target server, including the following message sequences: /// 1. Negotiate /// 2. Session Setup /// 3. Tree Connect /// </summary> /// <param name="smb2Dialect"></param> /// <param name="client"></param> /// <param name="clientGuid"></param> /// <param name="account"></param> /// <param name="connectShareType"></param> /// <param name="treeId"></param> /// <param name="clientBeforeDisconnection"></param> protected virtual void Connect(DialectRevision smb2Dialect, Smb2FunctionalClient client, Guid clientGuid, AccountCredential account, ConnectShareType connectShareType, out uint treeId, Smb2FunctionalClient clientBeforeDisconnection) { DialectRevision[] requestDialect = Smb2Utility.GetDialects(smb2Dialect); 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_PERSISTENT_HANDLES; SecurityMode_Values clientSecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED; IPAddress targetIPAddress = (connectShareType == ConnectShareType.CAShare) ? testConfig.CAShareServerIP : testConfig.SutIPAddress; string targetServer = (connectShareType == ConnectShareType.CAShare) ? testConfig.CAShareServerName : testConfig.SutComputerName; client.ConnectToServer(TestConfig.UnderlyingTransport, targetServer, targetIPAddress); BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends NEGOTIATE request.", clientGuid); client.Negotiate( requestDialect, TestConfig.IsSMB1NegotiateEnabled, clientSecurityMode, clientCapabilities, clientGuid); if (null != clientBeforeDisconnection) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends SESSION_SETUP request to reconnect to the previous session.", clientGuid); client.ReconnectSessionSetup( clientBeforeDisconnection, testConfig.DefaultSecurityPackage, targetServer, account, testConfig.UseServerGssToken); } else { BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends SESSION_SETUP request.", clientGuid); client.SessionSetup( testConfig.DefaultSecurityPackage, targetServer, account, testConfig.UseServerGssToken); } BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends TREE_CONNECT request.", clientGuid); client.TreeConnect( durableHandleUncSharePath, out treeId, checker: (header, response) => { BaseTestSite.Log.Add( LogEntryKind.Debug, "Capabilities in TREE_CONNECT response: {0}", response.Capabilities); BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should be successful", header.Command); if (connectShareType == ConnectShareType.CAShare) { BaseTestSite.Assert.AreEqual( Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY, Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY & response.Capabilities, "The share should have SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY capability"); } if (connectShareType == ConnectShareType.BasicShare) { BaseTestSite.Assert.AreNotEqual( Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY, Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY & response.Capabilities, "The share should not have SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY capability"); } }); }
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(); }
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_MultiCredit_OneRequestWithMultiCredit() { TestConfig.CheckDialect(DialectRevision.Smb21); TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LARGE_MTU); Guid clientGuid = Guid.NewGuid(); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: 1. NEGOTIATE; 2. SESSION_SETUP; 3. TREE_CONNECT"); Smb2FunctionalClient client = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite); client.ConnectToServerOverTCP(TestConfig.SutIPAddress); Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_LARGE_MTU; client.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); uint treeId; client.TreeConnect(uncSharePath, out treeId); int bufferSize = (int)client.MaxBufferSize; FILEID fileId; Smb2CreateContextResponse[] serverCreateContexts; ushort grantedCredit = 0; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with {0} credits", client.Credits); client.Create( treeId, GetTestFileName(uncSharePath), CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Log.Add(LogEntryKind.Debug, "The MaxBufferSize of the server is {0}.", client.MaxBufferSize); BaseTestSite.Log.Add(LogEntryKind.Debug, "Server has granted {0} credits to the client.", client.Credits); // Make sure client hold enough credits for test ushort maxBufferSizeInCredit = (ushort)((client.MaxBufferSize - 1) / 65536 + 1); if (client.Credits < maxBufferSizeInCredit) { if (client.Credits < 2) { BaseTestSite.Assert.Inconclusive( "This test case is not applicable when the server only grants {0} credits", client.Credits); } // Test max buffer according to granted credits. bufferSize = (client.Credits - 1) * 65536; } grantedCredit = header.CreditRequestResponse; }); contentWrite = Smb2Utility.CreateRandomStringInByte(bufferSize); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client attempts to write {0} bytes content to file when server grants {1} credits", client.MaxBufferSize, client.Credits); client.Write( treeId, fileId, contentWrite, checker: (header, response) => { BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); grantedCredit = header.CreditRequestResponse; }); BaseTestSite.Log.Add( LogEntryKind.TestStep, "Client attempts to read {0} bytes content from file when server grants {1} credit", bufferSize, client.Credits); client.Read(treeId, fileId, 0, (uint)contentWrite.Length, out contentRead); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the client by sending the following requests: 1. CLOSE; 2. TREE_DISCONNECT; 3. LOG_OFF; 4. DISCONNECT"); client.Close(treeId, fileId); client.TreeDisconnect(treeId); client.LogOff(); client.Disconnect(); }
/// <summary> /// This method will send ComNegotiate request before sending a Negotiate request to simulate windows client behaviour. /// If ComNegotiate failed, the Negotiate request will still be sent. /// </summary> public uint MultiProtocolNegotiate( Smb2Client client, ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ref ulong messageId, DialectRevision[] dialects, SecurityMode_Values securityMode, Capabilities_Values capabilities, Guid clientGuid, out DialectRevision selectedDialect, out byte[] gssToken, out Packet_Header responseHeader, out NEGOTIATE_Response responsePayload) { uint status = client.MultiProtocolNegotiate( new string[] { "SMB 2.002", "SMB 2.???" }, out selectedDialect, out gssToken, out responseHeader, out responsePayload); if (responseHeader.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("ComNegotiate", responseHeader.Status); } // If server only supports Smb2002, no further SMB2 negotiate needed if (selectedDialect == DialectRevision.Smb2002) { return(status); } PreauthIntegrityHashID[] preauthHashAlgs = null; EncryptionAlgorithm[] encryptionAlgs = null; // For back compatibility, if dialects contains SMB 3.11, preauthentication integrity context should be present. if (Array.IndexOf(dialects, DialectRevision.Smb311) >= 0) { preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 }; encryptionAlgs = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM }; } status = client.Negotiate( creditCharge, creditRequest, flags, messageId, dialects, securityMode, capabilities, clientGuid, out selectedDialect, out gssToken, out responseHeader, out responsePayload, 0, preauthHashAlgs, encryptionAlgs); // SMB2 negotiate is consume the message id messageId++; return(status); }
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); }
public void PrepareOpen( ModelDialectRevision clientMaxDialect, PersistentBitType persistentBit, CAShareType connectToCAShare, ModelHandleType modelHandleType, OplockLeaseType oplockLeaseType) { // Lease V2 cases only apply on the server implements SMB 3.x family. if (oplockLeaseType == OplockLeaseType.LeaseV2) testConfig.CheckDialect(DialectRevision.Smb30); // Lease V1 cases only apply on the server implements SMB 2.1 and 3.x family. if (oplockLeaseType == OplockLeaseType.LeaseV1) testConfig.CheckDialect(DialectRevision.Smb21); if ((oplockLeaseType == OplockLeaseType.LeaseV1 || oplockLeaseType == OplockLeaseType.LeaseV2) && !testConfig.IsLeasingSupported) Site.Assert.Inconclusive("Test case is applicable in servers that support leasing."); requestDialect = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect)); clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL; if (persistentBit == PersistentBitType.PersistentBitSet) { clientCapabilities |= Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES; } clientGuid = Guid.NewGuid(); requestedContext = oplockLeaseType; isCAShare = (connectToCAShare == CAShareType.CAShare); IPAddress targetIPAddress; string targetServer; #region Connect to Common Share or CA Share if (!isCAShare) { sharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare); fileName = "PrepareHandle_ConnectTo_CommonShareFile_" + Guid.NewGuid() + ".txt"; targetIPAddress = testConfig.SutIPAddress; targetServer = testConfig.SutComputerName; } else { sharePath = Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName); fileName = "PrepareHandle_ConnectTo_CAShareFile_" + Guid.NewGuid().ToString() + ".txt"; targetIPAddress = testConfig.CAShareServerIP; targetServer = testConfig.CAShareServerName; } testClientBeforeDisconnection = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClientBeforeDisconnection.CreditGoal = 20; testClientBeforeDisconnection.ConnectToServer(testConfig.UnderlyingTransport, targetServer, targetIPAddress); testClientBeforeDisconnection.Negotiate( requestDialect, testConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilities, clientGuid: clientGuid, checker: (header, response) => { if (Smb2Utility.IsSmb3xFamily(response.DialectRevision) && handleConfig.IsPersistentHandleSupported && persistentBit == PersistentBitType.PersistentBitSet) { Site.Assert.IsTrue( response.Capabilities.HasFlag(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES), "The server MUST set SMB2_GLOBAL_CAP_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " + "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles. " + "Actual capabilities are {0}", response.Capabilities); } }); testClientBeforeDisconnection.SessionSetup( testConfig.DefaultSecurityPackage, targetServer, testConfig.AccountCredential, testConfig.UseServerGssToken); testClientBeforeDisconnection.TreeConnect(sharePath, out treeIdBeforeDisconnection); #endregion #region Create operation according to the handle type and context Smb2CreateContextRequest[] prepareRequestContext = null; Smb2CreateContextResponse[] serverCreateContexts = null; RequestedOplockLevel_Values requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; switch (oplockLeaseType) { case OplockLeaseType.LeaseV1: { testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE); prepareRequestContext = GetPrepareOpenCreateContext(modelHandleType, oplockLeaseType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE; } break; case OplockLeaseType.LeaseV2: { testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_REQUEST_LEASE_V2); prepareRequestContext = GetPrepareOpenCreateContext(modelHandleType, oplockLeaseType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE; } break; case OplockLeaseType.BatchOplock: { prepareRequestContext = GetPrepareOpenHandleContext(modelHandleType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH; } break; case OplockLeaseType.NoOplockOrLease: { prepareRequestContext = GetPrepareOpenHandleContext(modelHandleType); requestedOplockLevel = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE; } break; } PrepareOpenCreate( testClientBeforeDisconnection, treeIdBeforeDisconnection, fileName, out fileIdBeforDisconnection, out serverCreateContexts, requestedOplockLevel, prepareRequestContext); #endregion }
public uint Negotiate(DialectRevision[] dialects, SecurityMode_Values securityMode, Capabilities_Values capabilityValue, Guid clientGuid, out DialectRevision selectedDialect, ushort creditRequest = 1) { Packet_Header header; NEGOTIATE_Response negotiateResponse; uint status = client.Negotiate( 0, creditRequest, Packet_Header_Flags_Values.NONE, messageId++, dialects, securityMode, capabilityValue, clientGuid, out selectedDialect, out serverGssToken, out header, out negotiateResponse); grantedCredit = header.CreditRequestResponse; return(status); }
protected virtual uint Negotiate( ushort creditCharge, ushort creditRequest, ulong messageId, Guid clientGuid, out DialectRevision selectedDialect, out byte[] gssToken, out Packet_Header responseHeader, out NEGOTIATE_Response responsePayload) { uint status = client.Negotiate( creditCharge, creditRequest, Packet_Header_Flags_Values.NONE, messageId, new DialectRevision[] { DialectRevision.Smb2002 }, SecurityMode_Values.NONE, Capabilities_Values.NONE, clientGuid, out selectedDialect, out gssToken, out responseHeader, out responsePayload); negotiatedDialect = selectedDialect; serverCapabilities = (Capabilities_Values)responsePayload.Capabilities; return status; }
/// <summary> /// Write content before failover /// </summary> /// <param name="fsType">FileServerType</param> /// <param name="server">File Server name.</param> /// <param name="serverAccessIp">File Server Access IP.</param> /// <param name="uncSharePath">The share path to write the file.</param> /// <param name="file">The file name for writing content.</param> /// <param name="content">The content to write.</param> /// <param name="clientGuid">Smb2 client Guid.</param> /// <param name="createGuid">The Guid for smb2 create request.</param> /// <param name="fileId">File id returned by server</param> /// <returns></returns> protected bool WriteContentBeforeFailover( FileServerType fsType, string server, IPAddress serverAccessIp, string uncSharePath, string file, string content, Guid clientGuid, Guid createGuid, out FILEID fileId) { uint status = 0; fileId = FILEID.Zero; beforeFailover = new Smb2FunctionalClient(TestConfig.FailoverTimeout, TestConfig, BaseTestSite); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Start a client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT to {0}", uncSharePath); beforeFailover.ConnectToServer(TestConfig.UnderlyingTransport, server, serverAccessIp); Capabilities_Values requestCapabilities = 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 = beforeFailover.Negotiate( TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, capabilityValue: requestCapabilities, clientGuid: clientGuid, checker: (header, response) => { TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response); }); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "Negotiate failed with {0}.", Smb2Status.GetStatusCode(status)); return(false); } status = beforeFailover.SessionSetup( TestConfig.DefaultSecurityPackage, server, TestConfig.AccountCredential, TestConfig.UseServerGssToken); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "SessionSetup failed with {0}.", Smb2Status.GetStatusCode(status)); return(false); } uint treeId = 0; Share_Capabilities_Values shareCapabilities = Share_Capabilities_Values.NONE; status = beforeFailover.TreeConnect(uncSharePath, out treeId, (header, response) => { shareCapabilities = response.Capabilities; }); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "TreeConnect failed with {0}.", Smb2Status.GetStatusCode(status)); return(false); } BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY), "CA Share should have SHARE_CAP_CONTINUOUS_AVAILABILITY bit set for Capabilities in TreeConnect response."); if (fsType == FileServerType.ScaleOutFileServer) { BaseTestSite.Assert.IsTrue(shareCapabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_SCALEOUT), "ScaleOut FS should have SHARE_CAP_SCALEOUT bit set for Capabilities in TreeConnect response."); } Smb2CreateContextResponse[] serverCreateContexts; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 with PERSISTENT flag set."); status = beforeFailover.Create( treeId, file, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out serverCreateContexts, RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE, new Smb2CreateContextRequest[] { new Smb2CreateDurableHandleRequestV2 { CreateGuid = createGuid, Flags = CREATE_DURABLE_HANDLE_REQUEST_V2_Flags.DHANDLE_FLAG_PERSISTENT, Timeout = 3600000, }, }); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "Create failed with {0}.", Smb2Status.GetStatusCode(status)); return(false); } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends WRITE request to write content to the file."); status = beforeFailover.Write(treeId, fileId, content); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "Write content failed with {0}.", Smb2Status.GetStatusCode(status)); return(false); } BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends FLUSH request."); status = beforeFailover.Flush(treeId, fileId); if (status != Smb2Status.STATUS_SUCCESS) { BaseTestSite.Log.Add(LogEntryKind.Warning, "Flush failed with {0}.", Smb2Status.GetStatusCode(status)); return(false); } return(true); }
/// <summary> /// This method will send ComNegotiate request before sending a Negotiate request to simulate windows client behaviour. /// If ComNegotiate failed, the Negotiate request will still be sent. /// </summary> public uint MultiProtocolNegotiate( Smb2Client client, ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, DialectRevision[] dialects, SecurityMode_Values securityMode, Capabilities_Values capabilities, Guid clientGuid, out DialectRevision selectedDialect, out byte[] gssToken, out Packet_Header responseHeader, out NEGOTIATE_Response responsePayload) { uint status = client.MultiProtocolNegotiate( new string[] { "SMB 2.002", "SMB 2.???" }, out selectedDialect, out gssToken, out responseHeader, out responsePayload); if (responseHeader.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("ComNegotiate", responseHeader.Status); } // If server only supports Smb2002, no further SMB2 negotiate needed if (selectedDialect == DialectRevision.Smb2002) { return status; } PreauthIntegrityHashID[] preauthHashAlgs = null; EncryptionAlgorithm[] encryptionAlgs = null; // For back compatibility, if dialects contains SMB 3.11, preauthentication integrity context should be present. if (Array.IndexOf(dialects, DialectRevision.Smb311) >= 0) { preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 }; encryptionAlgs = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM }; } status = client.Negotiate( creditCharge, creditRequest, flags, messageId, dialects, securityMode, capabilities, clientGuid, out selectedDialect, out gssToken, out responseHeader, out responsePayload, 0, preauthHashAlgs, encryptionAlgs); return status; }
private void InitializeMainChannel( ModelDialectRevision maxSmbVersionClientSupported, Guid clientGuid, ReplayModelShareType shareType, out uint treeId, bool isReconnect = false, bool isClientSupportPersistent = true) { Site.Assume.IsNull(smb2ClientMainChannel, "Expect smb2ClientMainChannel is NULL."); smb2ClientMainChannel = new Smb2FunctionalClient(testConfig.Timeout, testConfig, Site); smb2ClientMainChannel.Smb2Client.LeaseBreakNotificationReceived += new Action <Packet_Header, LEASE_BREAK_Notification_Packet>(OnLeaseBreakNotificationReceived); smb2ClientMainChannel.Smb2Client.OplockBreakNotificationReceived += new Action <Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived); serverIpMainChannel = (shareType == ReplayModelShareType.CAShare ? testConfig.CAShareServerIP : testConfig.SutIPAddress); serverNameMainChannel = (shareType == ReplayModelShareType.CAShare) ? testConfig.CAShareServerName : testConfig.SutComputerName; smb2ClientMainChannel.ConnectToServer(testConfig.UnderlyingTransport, serverNameMainChannel, serverIpMainChannel); DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported)); 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; clientCapabilitiesMainChannel = ModelUtility.IsSmb3xFamily(maxSmbVersionClientSupported)? capability : Capabilities_Values.NONE; status = smb2ClientMainChannel.Negotiate( dialects, testConfig.IsSMB1NegotiateEnabled, capabilityValue: clientCapabilitiesMainChannel, clientGuid: maxSmbVersionClientSupported == ModelDialectRevision.Smb2002 ? Guid.Empty : clientGuid, checker: (header, response) => { Site.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); dialectMainChannel = negotiateResponse.Value.DialectRevision; #endregion #region SESSION_SETUP principleNameMainChannel = (shareType == ReplayModelShareType.CAShare ? testConfig.CAShareServerName : testConfig.SutComputerName); if (isReconnect) { status = smb2ClientMainChannel.ReconnectSessionSetup( sessionIdMainChannel, testConfig.DefaultSecurityPackage, principleNameMainChannel, testConfig.AccountCredential, testConfig.UseServerGssToken); sessionIdMainChannel = smb2ClientMainChannel.SessionId; sessionKeyMainChannel = smb2ClientMainChannel.SessionKey; } else { status = smb2ClientMainChannel.SessionSetup( testConfig.DefaultSecurityPackage, principleNameMainChannel, testConfig.AccountCredential, testConfig.UseServerGssToken); sessionIdMainChannel = smb2ClientMainChannel.SessionId; sessionKeyMainChannel = smb2ClientMainChannel.SessionKey; } Site.Log.Add( LogEntryKind.Debug, "Global encryption disabled"); #endregion #region TREE_CONNECT to share sharePathMainChannel = (shareType == ReplayModelShareType.CAShare ? Smb2Utility.GetUncPath(testConfig.CAShareServerName, testConfig.CAShareName) : Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare)); status = smb2ClientMainChannel.TreeConnect( sharePathMainChannel, out treeId); Site.Log.Add( LogEntryKind.Debug, "Establish main channel to connect share {0}", sharePathMainChannel); smb2ClientMainChannel.SetTreeEncryption(treeId, false); #endregion }