/// <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 TestValidateNegotiateInfo(Smb2FunctionalClient client, ValidateNegotiateInfoRequestType requestType, DialectRevision[] invalidDialects = null) { #region Check Applicability TestConfig.CheckDialect(DialectRevision.Smb30); TestConfig.CheckIOCTL(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"); DialectRevision[] requestDialects; if (requestType == ValidateNegotiateInfoRequestType.InvalidSMB311Dialect) { requestDialects = Smb2Utility.GetDialects(DialectRevision.Smb311); } else { // FSCTL_VALIDATE_NEGOTIATE_INFO is only supported in SMB30 and SMB302. For SMB311 and later, we use SMB30 to test the server behavior. requestDialects = (TestConfig.MaxSmbVersionClientSupported > DialectRevision.Smb302) ? Smb2Utility.GetDialects(DialectRevision.Smb30) : TestConfig.RequestDialects; } Guid clientGuid = Guid.NewGuid(); 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; 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; }); client.SessionSetup( TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, TestConfig.UseServerGssToken); uint treeId; string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName); client.TreeConnect(ipcPath, out treeId); VALIDATE_NEGOTIATE_INFO_Request validateNegotiateInfoReq; switch (requestType) { case ValidateNegotiateInfoRequestType.None: case ValidateNegotiateInfoRequestType.InvalidSMB311Dialect: 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; 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) { uint status = client.ValidateNegotiateInfo(treeId, inputBuffer, out outputBuffer, checker: (header, response) => { }); BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "ValidateNegotiateInfo should succeed "); VALIDATE_NEGOTIATE_INFO_Response 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"); } else { string errCondition; switch (requestType) { case ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse: errCondition = "MaxOutputResponse in the request is less than the size of a VALIDATE_NEGOTIATE_INFO Response"; break; case ValidateNegotiateInfoRequestType.InvalidSMB311Dialect: errCondition = "Connection.Dialect is \"3.1.1\""; break; case ValidateNegotiateInfoRequestType.InvalidDialects: errCondition = "there is no greatest common dialect between Dialects field in VALIDATE_NEGOTIATE_INFO Request and the server implemented dialect, or the greatest common dialect is not equal to Connection.Dialect"; break; case ValidateNegotiateInfoRequestType.InvalidGuid: errCondition = "Guid field in VALIDATE_NEGOTIATE_INFO request is not equal to the ClientGuid sent in the original SMB2 NEGOTIATE request"; break; case ValidateNegotiateInfoRequestType.InvalidSecurityMode: errCondition = "SecurityMode field in VALIDATE_NEGOTIATE_INFO request is not equal to the SecurityMode sent in the original SMB2 NEGOTIATE request"; break; case ValidateNegotiateInfoRequestType.InvalidCapabilities: errCondition = "Capabilities field in VALIDATE_NEGOTIATE_INFO request is not equal to the Capabilities sent in the original SMB2 NEGOTIATE request"; break; default: throw new InvalidOperationException("Unexpected ValidateNegotiateInfo request type " + requestType); } try { uint maxOutputResponse = (requestType == ValidateNegotiateInfoRequestType.InvalidMaxOutputResponse) ? (uint)0 : Smb2FunctionalClient.DefaultMaxOutputResponse; client.ValidateNegotiateInfo(treeId, inputBuffer, out outputBuffer, maxOutputResponse, checker: (header, response) => { }); client.TreeDisconnect(treeId); client.LogOff(); } catch { } BaseTestSite.Assert.IsTrue(client.Smb2Client.IsServerDisconnected, "Transport connection should be terminated when {0}", errCondition); } }