/// <summary> /// Check whether actual dialect is bigger than expected dialect or not. /// </summary> /// <param name="expectedMinimalDialect">Expected minimal dialect.</param> /// <param name="response">Negotiate response header.</param> public void CheckNegotiateDialect(DialectRevision expectedMinimalDialect, NEGOTIATE_Response response) { if (response.DialectRevision < expectedMinimalDialect) { Site.Assert.Inconclusive( "This test case is not applicable due to that actual dialect {0} is less than expected minimal dialect {1}", (DialectRevision)response.DialectRevision, (DialectRevision)expectedMinimalDialect); } }
private void CheckNegotiateResponse( Packet_Header header, NEGOTIATE_Response response, DialectRevision clientMaxDialectSupported, EncryptionAlgorithm[] encryptionAlgs) { DialectRevision expectedDialect = clientMaxDialectSupported < TestConfig.MaxSmbVersionSupported ? clientMaxDialectSupported : TestConfig.MaxSmbVersionSupported; BaseTestSite.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed, actually server returns {1}.", header.Command, Smb2Status.GetStatusCode(header.Status)); BaseTestSite.Assert.AreEqual(expectedDialect, response.DialectRevision, "Selected dialect should be {0}", expectedDialect); if (expectedDialect >= DialectRevision.Smb311) { BaseTestSite.Assert.AreEqual( PreauthIntegrityHashID.SHA_512, client.SelectedPreauthIntegrityHashID, "[MS-SMB2] 3.3.5.4 The server MUST set Connection.PreauthIntegrityHashId to one of the hash algorithms " + "in the client's SMB2_PREAUTH_INTEGRITY_CAPABILITIES HashAlgorithms array."); if (encryptionAlgs != null) { BaseTestSite.Assert.IsTrue( TestConfig.SupportedEncryptionAlgorithmList.Contains(client.SelectedCipherID), "[MS-SMB2] 3.3.5.4 The server MUST set Connection.CipherId to one of the ciphers in the client's " + "SMB2_ENCRYPTION_CAPABILITIES Ciphers array in an implementation-specific manner."); } else { BaseTestSite.Assert.AreEqual( EncryptionAlgorithm.ENCRYPTION_NONE, client.SelectedCipherID, "[MS-SMB2] if client doesn't present SMB2_ENCRYPTION_CAPABILITIES context in negotiate request, " + "server should not present this context in negotiate response."); } } else { // If server supported dialect version is lower than 3.11, server should ignore the negotiate contexts. BaseTestSite.Assert.AreEqual( PreauthIntegrityHashID.HashAlgorithm_NONE, client.SelectedPreauthIntegrityHashID, "[MS-SMB2] The server must ignore the SMB2_PREAUTH_INTEGRITY_CAPABILITIES context if Connection.Dialect is less than 3.11. "); BaseTestSite.Assert.AreEqual( EncryptionAlgorithm.ENCRYPTION_NONE, client.SelectedCipherID, "[MS-SMB2] The server must ignore the SMB2_ENCRYPTION_CAPABILITIES context if Connection.Dialect is less than 3.11. "); } CheckServerCapabilities(response); }
/// <summary> /// Negotiate, SessionSetup and TreeConnect /// </summary> public void SetupConnection(ModelDialectRevision dialect, ModelCapabilities capabilities, SecurityMode_Values securityMode) { #region Connect to server testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site); testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress); #endregion // It MUST be a GUID generated by the client, if the Dialects field contains a value other than 0x0202. Otherwise, the client MUST set this to 0. Guid clientGuid = (dialect == ModelDialectRevision.Smb2002) ? Guid.Empty : Guid.NewGuid(); #region negotiate testClient.Negotiate( Packet_Header_Flags_Values.NONE, Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(dialect)), securityMode, (Capabilities_Values)capabilities, clientGuid, (header, response) => { Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); #endregion #region session setup testClient.SessionSetup( testConfig.DefaultSecurityPackage, testConfig.SutComputerName, testConfig.AccountCredential, testConfig.UseServerGssToken, (SESSION_SETUP_Request_SecurityMode_Values)securityMode); #endregion #region treeconnect testClient.TreeConnect( Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare), out treeId); #endregion Connection_Dialect = ModelUtility.GetModelDialectRevision(negotiateResponse.DialectRevision); Connection_ClientCapabilities = (Capabilities_Values)capabilities; if (dialect >= ModelDialectRevision.Smb30) // GLOBAL_CAP_ENCRYPTION will be added in Functional client when dialect >= SMB30 { Connection_ClientCapabilities |= Capabilities_Values.GLOBAL_CAP_ENCRYPTION; } Connection_ClientSecurityMode = securityMode; Connection_ClientGuid = clientGuid; }
public void NegotiateRequest(Sequence <DialectRevision> dialects) { Packet_Header responseHeader = new Packet_Header(); DialectRevision selectedDialect = DialectRevision.Smb2Unknown; NEGOTIATE_Response responsePayload = new NEGOTIATE_Response(); byte[] smb2ClientGssToken; ModelSmb2Status status = ModelSmb2Status.STATUS_SUCCESS; try { status = (ModelSmb2Status)smb2Client.Negotiate(0, 1, Packet_Header_Flags_Values.NONE, messageId++, dialects.ToArray(), SecurityMode_Values.NONE, Capabilities_Values.NONE, Guid.NewGuid(), out selectedDialect, out smb2ClientGssToken, out responseHeader, out responsePayload); if (status != ModelSmb2Status.STATUS_SUCCESS) { selectedDialect = DialectRevision.Smb2Unknown; } this.NegotiateResponse(status, selectedDialect); } catch { } }
public void CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values capValue, NEGOTIATE_Response response) { if (!response.Capabilities.HasFlag(capValue)) { Site.Assert.Inconclusive("This test case is not applicable due to following capability is not supported: {0}", (Capabilities_Values)capValue); } }
public void UserLogon( DetectionInfo info, Smb2Client client, out ulong messageId, out ulong sessionId, out Guid clientGuid, out NEGOTIATE_Response negotiateResp, out bool encryptionRequired) { messageId = 1; sessionId = 0; logWriter.AddLog(LogLevel.Information, "Client connects to server"); client.ConnectOverTCP(SUTIpAddress); #region Negotiate DialectRevision selectedDialect; byte[] gssToken; Packet_Header header; clientGuid = Guid.NewGuid(); logWriter.AddLog(LogLevel.Information, "Client sends multi-protocol Negotiate to server"); MultiProtocolNegotiate( client, 1, 1, Packet_Header_Flags_Values.NONE, messageId++, info.requestDialect, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES | Capabilities_Values.GLOBAL_CAP_ENCRYPTION, clientGuid, out selectedDialect, out gssToken, out header, out negotiateResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", header.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(header.Status))); } #endregion #region Session Setup SESSION_SETUP_Response sessionSetupResp; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( SecurityPackageType, Credential, Smb2Utility.GetCifsServicePrincipalName(SUTName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); // Server GSS token is used only for Negotiate authentication when enabled if (SecurityPackageType == SecurityPackageType.Negotiate) { sspiClientGss.Initialize(gssToken); } else { sspiClientGss.Initialize(null); } do { logWriter.AddLog(LogLevel.Information, "Client sends SessionSetup to server"); client.SessionSetup( 1, 64, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out gssToken, out header, out sessionSetupResp); if ((header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || header.Status == Smb2Status.STATUS_SUCCESS) && gssToken != null && gssToken.Length > 0) { sspiClientGss.Initialize(gssToken); } } while (header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SESSIONSETUP", header.Status); throw new Exception(string.Format("SESSIONSETUP failed with {0}", Smb2Status.GetStatusCode(header.Status))); } byte[] sessionKey; sessionKey = sspiClientGss.SessionKey; encryptionRequired = sessionSetupResp.SessionFlags == SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA; client.GenerateCryptoKeys( sessionId, sessionKey, info.smb2Info.IsRequireMessageSigning, // Enable signing according to the configuration of SUT encryptionRequired, null, false); #endregion }
/// <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); }
protected override uint Negotiate(ushort creditCharge, ushort creditRequest, ulong messageId, Guid clientGuid, out DialectRevision selectedDialect, out byte[] gssToken, out Packet_Header responseHeader, out NEGOTIATE_Response responsePayload) { return(client.Negotiate( creditCharge, creditRequest, Packet_Header_Flags_Values.NONE, messageId, new DialectRevision[] { this.dialect }, SecurityMode_Values.NONE, Capabilities_Values.NONE, clientGuid, out selectedDialect, out gssToken, out responseHeader, out responsePayload)); }
private void CheckServerCapabilities(NEGOTIATE_Response response) { // Check capability: Leasing if (TestConfig.IsLeasingSupported && response.DialectRevision != DialectRevision.Smb2002) { BaseTestSite.Assert.AreEqual <NEGOTIATE_Response_Capabilities_Values>( NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING, response.Capabilities & NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LEASING, "The \"Capabilities\" of Negotiate Response should has flag GLOBAL_CAP_LEASING set."); } // Check capability: Large MTU if (TestConfig.IsMultiCreditSupported && response.DialectRevision != DialectRevision.Smb2002) { BaseTestSite.Assert.AreEqual <NEGOTIATE_Response_Capabilities_Values>( NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LARGE_MTU, response.Capabilities & NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_LARGE_MTU, "The \"Capabilities\" of Negotiate Response should has flag GLOBAL_CAP_LARGE_MTU set."); } // Check capability: MultiChannel if (TestConfig.IsMultiChannelCapable && response.DialectRevision != DialectRevision.Smb2002 && response.DialectRevision != DialectRevision.Smb21) { BaseTestSite.Assert.AreEqual <NEGOTIATE_Response_Capabilities_Values>( NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response.Capabilities & NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, "The \"Capabilities\" of Negotiate Response should has flag GLOBAL_CAP_MULTI_CHANNEL set."); } // Check capability: Persistent Handle if (TestConfig.IsPersistentHandlesSupported && response.DialectRevision != DialectRevision.Smb2002 && response.DialectRevision != DialectRevision.Smb21) { BaseTestSite.Assert.AreEqual <NEGOTIATE_Response_Capabilities_Values>( NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, response.Capabilities & NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, "The \"Capabilities\" of Negotiate Response should has flag GLOBAL_CAP_PERSISTENT_HANDLES set."); } // Check capability: Directory Leasing if (TestConfig.IsDirectoryLeasingSupported && response.DialectRevision != DialectRevision.Smb2002 && response.DialectRevision != DialectRevision.Smb21) { BaseTestSite.Assert.AreEqual <NEGOTIATE_Response_Capabilities_Values>( NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING, response.Capabilities & NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING, "The \"Capabilities\" of Negotiate Response should has flag GLOBAL_CAP_DIRECTORY_LEASING set."); } // Check capability: Encryption if (TestConfig.IsEncryptionSupported && response.DialectRevision == DialectRevision.Smb30 && response.DialectRevision == DialectRevision.Smb302) { BaseTestSite.Assert.AreEqual <NEGOTIATE_Response_Capabilities_Values>( NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION, response.Capabilities & NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION, "The \"Capabilities\" of Negotiate Response should has flag GLOBAL_CAP_ENCRYPTION set."); } }
private bool UserLogon(DetectionInfo info, Smb2Client client, out ulong messageId, out ulong sessionId, out Guid clientGuid, out NEGOTIATE_Response negotiateResp) { messageId = 0; sessionId = 0; client.ConnectOverTCP(Dns.GetHostAddresses(info.ContentServerName)[0]); #region Negotiate DialectRevision selectedDialect; byte[] gssToken; Packet_Header header; clientGuid = Guid.NewGuid(); client.Negotiate( 1, 1, Packet_Header_Flags_Values.NONE, messageId++, new DialectRevision[] { DialectRevision.Smb30 }, SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES, clientGuid, out selectedDialect, out gssToken, out header, out negotiateResp); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("NEGOTIATE", header.Status); throw new Exception(string.Format("NEGOTIATE failed with {0}", Smb2Status.GetStatusCode(header.Status))); } #endregion #region Session Setup SESSION_SETUP_Response sessionSetupResp; SspiClientSecurityContext sspiClientGss = new SspiClientSecurityContext( SecurityPackageType, Credential, Smb2Utility.GetCifsServicePrincipalName(ContentServerName), ClientSecurityContextAttribute.None, SecurityTargetDataRepresentation.SecurityNativeDrep); // Server GSS token is used only for Negotiate authentication when enabled if (SecurityPackageType == SecurityPackageType.Negotiate) { sspiClientGss.Initialize(gssToken); } else { sspiClientGss.Initialize(null); } do { client.SessionSetup( 1, 64, Packet_Header_Flags_Values.NONE, messageId++, sessionId, SESSION_SETUP_Request_Flags.NONE, SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED, SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS, 0, sspiClientGss.Token, out sessionId, out gssToken, out header, out sessionSetupResp); if ((header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || header.Status == Smb2Status.STATUS_SUCCESS) && gssToken != null && gssToken.Length > 0) { sspiClientGss.Initialize(gssToken); } } while (header.Status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED); if (header.Status != Smb2Status.STATUS_SUCCESS) { LogFailedStatus("SESSIONSETUP", header.Status); throw new Exception(string.Format("SESSIONSETUP failed with {0}", Smb2Status.GetStatusCode(header.Status))); } byte[] sessionKey; sessionKey = sspiClientGss.SessionKey; client.GenerateCryptoKeys(sessionId, sessionKey, true, false, null, false); #endregion return(true); }