public static void LogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId) { VerifyConnection(connectionId); Condition.IsNull(ConnectionList[connectionId].Request); // Reduce states Combination.NWise(1, connectionId, sessionId); // If no session exists before, then any session id is invalid Condition.IfThen(ConnectionList[connectionId].Session == null, sessionId == ModelSessionId.InvalidSessionId); // If the session id in LogOff request is different from the existing one, then the id is invalid. Condition.IfThen(ConnectionList[connectionId].Session != null && ConnectionList[connectionId].Session.SessionId != sessionId, sessionId == ModelSessionId.InvalidSessionId); if (ConnectionList[connectionId].Session == null && ConnectionList[connectionId].ConstrainedConnection) { ModelHelper.Log(LogType.Requirement, "3.3.5.2.9: The server MUST look up the Session in Connection.SessionTable by using the SessionId in the SMB2 header of the request. " + "If Connection.SessionTable is empty and Connection.ConstrainedConnection is TRUE, the server SHOULD<210> disconnect the connection. "); ModelHelper.Log(LogType.TestInfo, "Connection.SessionTable is empty and Connection.ConstrainedConnection is TRUE"); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); // server SHOULD disconnect the connection ConnectionList[connectionId].ConnectionState = ModelState.Disconnected; return; } ConnectionList[connectionId].Request = new ModelLogOffRequest(connectionId, sessionId); }
private static bool VerifyFootnote(ModelConnectionId connectionId, SessionMgmtConfig c, ModelSmb2Status?status) { Condition.IsTrue(config.Platform == c.Platform); if ((config.Platform == Platform.WindowsServer2008 || config.Platform == Platform.WindowsServer2008R2) && ConnectionList.ContainsKey(connectionId) && ConnectionList[connectionId].Session == null) { ModelHelper.Log(LogType.Requirement, "<210> Section 3.3.5.2.9: Windows Vista, Windows Server 2008, Windows 7, and Windows Server 2008 R2 fail the request with STATUS_USER_SESSION_DELETED. " + "If Connection.ConstrainedConnection is FALSE and Connection.SessionTable is empty, then server MUST fail any request with STATUS_USER_SESSION_DELETED. "); // No matter Connection.ConstrainedConnection is FALSE or TRUE, Windows Server 2008 and 2008 R2 will fail the Log off request. ModelHelper.Log(LogType.TestInfo, "The SUT platform is {0}, Connection.ConstrainedConnection is {1}, and Connection.SessionTable is empty", config.Platform, ConnectionList[connectionId].ConstrainedConnection); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); if (status == null) { // null means SUT terminates the connection. // but SUT should return STATUS_USER_SESSION_DELETED Condition.IsTrue(false); } else { Condition.IsTrue(status.Value == ModelSmb2Status.STATUS_USER_SESSION_DELETED); } // Return true stands for this function handles the message, no more actions needed. return(true); } // Go on processing message. return(false); }
public static void SessionSetupRequest( ModelConnectionId connectionId, ModelSessionId sessionId, ModelSessionId previousSessionId, ModelSigned signed, ModelFlags flags, ModelUser user, ModelAllowReauthentication ReAuthentication) { VerifyConnection(connectionId); Condition.IsNull(ConnectionList[connectionId].Request); #region Combinations Combination.NWise(1, connectionId, sessionId, previousSessionId, signed, flags, user); #endregion #region Other contraints // Do not estabilish 2nd session if no session exist yet Condition.IfThen(GlobalSessionTable.Count == 0, sessionId != ModelSessionId.AlternativeSessionId && user == ModelUser.DefaultUser); // Do not establish new session if there's one in the requested connection Condition.IfThen(ConnectionList[connectionId].Session != null, sessionId != ModelSessionId.ZeroSessionId); // Do not establish new session if 2 sessions exist Condition.IfThen(GlobalSessionTable.Count == 2, sessionId != ModelSessionId.ZeroSessionId); // Do not set previousSessionId to session1 if currently establish session1 Condition.IfThen(GlobalSessionTable.Count == 0 && sessionId == ModelSessionId.ZeroSessionId, previousSessionId != ModelSessionId.MainSessionId); // If session id is zero, it's the same that the binding flag is set or not. Condition.IfThen(sessionId == ModelSessionId.ZeroSessionId, flags == ModelFlags.NotBinding); // Restrict the condition to no session exist yet as we only simulate one session in this Model Condition.IsNull(ConnectionList[connectionId].Session); // If we need to skip SessionSetup when it's re-auth an existing one if (ReAuthentication == ModelAllowReauthentication.NotAllowReauthentication) { Condition.IsTrue(ConnectionList[connectionId].Session == null || ConnectionList[connectionId].Session.State != ModelSessionState.Valid); } #endregion ConnectionList[connectionId].Request = new ModelSessionSetupRequest( connectionId, sessionId, previousSessionId, signed == ModelSigned.SignFlagSet, flags, user); }
private static T RetrieveOutstandingRequest <T>(ModelConnectionId connectionId) where T : ModelSMB2Request { ModelSMB2Request request = ConnectionList[connectionId].Request; ConnectionList[connectionId].Request = null; Condition.IsTrue(request is T); return(request as T); }
public void LogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId) { ulong adapterSessionId; #region sessionId if (sessionTable.ContainsKey(sessionId)) { adapterSessionId = sessionTable[sessionId]; } else { Random r = new Random(); adapterSessionId = (ulong)r.Next(1, int.MaxValue); } #endregion PrintCurrentSessionTable("Before LogOff Request"); #region Send Request try { uint status; // Use desired explored sessionId ulong oldSessionId = connectionList[connectionId].SessionId; connectionList[connectionId].SessionId = adapterSessionId; status = connectionList[connectionId].LogOff( (header, response) => { // do nothing, avoid exception when status != status_success }); // Restore original sessionId connectionList[connectionId].SessionId = oldSessionId; if (status == Smb2Status.STATUS_SUCCESS) { sessionTable.Remove(sessionId); } PrintCurrentSessionTable("After LogOff Request"); LogOffResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig); return; } catch { } Site.Assert.IsTrue(connectionList[connectionId].Smb2Client.IsServerDisconnected, "Logoff failure should be caused by transport connection termination"); ExpectDisconnect(connectionId, sessionMgmtConfig); sessionTable.Remove(sessionId); connectionList.Remove(connectionId); #endregion }
private Guid GetClientGuid(ModelConnectionId connectionId, DialectRevision[] dialects) { if (dialects.Length == 1 && dialects[0] == DialectRevision.Smb2002) { return(Guid.Empty); } else if (connectionId == ModelConnectionId.MainConnection) { this.clientGuid = Guid.NewGuid(); return(this.clientGuid); } else { return(this.clientGuid); } }
public ModelSessionSetupRequest( ModelConnectionId connectionId, ModelSessionId sessionId, ModelSessionId previousSessionId, bool isSigned, ModelFlags flags, ModelUser user ) : base(0) { this.connectionId = connectionId; this.sessionId = sessionId; this.previousSessionId = previousSessionId; this.isSigned = isSigned; this.flags = flags; this.user = user; }
public static void TerminateConnection(ModelConnectionId connectionId) { VerifyConnection(connectionId); if (ConnectionList[connectionId].Session != null) { ModelHelper.Log(LogType.Requirement, "3.3.7.1: the Session MUST be removed from GlobalSessionTable and freed. "); GlobalSessionTable.Remove(ConnectionList[connectionId].Session.SessionId); } // Disconnect and remove the connection ConnectionList[connectionId].ConnectionState = ModelState.Disconnected; ModelHelper.Log(LogType.Requirement, "3.3.7.1: The connection MUST be removed from ConnectionList and MUST be freed."); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); ConnectionList.Remove(connectionId); }
public static void SetupConnection(ModelConnectionId connectionId, ModelDialectRevision clientMaxDialect) { // Restrict model contains 2 connections at most Condition.IsTrue(!ConnectionList.ContainsKey(connectionId)); // Reduce states Combination.NWise(1, connectionId, clientMaxDialect); DialectRevision dialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, config.MaxSmbVersionSupported); // Establish new connection ConnectionList.Add( connectionId, new ModelConnection(dialect)); ConnectionList[connectionId].ConnectionState = ModelState.Connected; ModelHelper.Log(LogType.Requirement, "3.3.5.1: Connection.ConstrainedConnection is set to TRUE."); ConnectionList[connectionId].ConstrainedConnection = true; }
public static void ExpectDisconnect(ModelConnectionId connectionId, SessionMgmtConfig c) { if (VerifyFootnote(connectionId, c, null)) { return; } Condition.IsTrue(ConnectionList.ContainsKey(connectionId)); Condition.IsTrue(ConnectionList[connectionId].ConnectionState == ModelState.Disconnected); if (ConnectionList[connectionId].Session != null) { ModelHelper.Log(LogType.Requirement, "3.3.7.1: the Session MUST be removed from GlobalSessionTable and freed. "); GlobalSessionTable.Remove(ConnectionList[connectionId].Session.SessionId); } ModelHelper.Log(LogType.Requirement, "3.3.7.1: The connection MUST be removed from ConnectionList and MUST be freed."); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); ConnectionList.Remove(connectionId); }
public ModelLogOffRequest(ModelConnectionId connectionId, ModelSessionId sessionId) : base(0) { this.connectionId = connectionId; this.sessionId = sessionId; }
public void TerminateConnection(ModelConnectionId connectionId) { connectionList[connectionId].Disconnect(); sessionTable.Remove(ModelSessionId.MainSessionId); connectionList.Remove(connectionId); }
public void SessionSetupRequest( ModelConnectionId connectionId, ModelSessionId sessionId, ModelSessionId previousSessionId, ModelSigned signed, ModelFlags flags, ModelUser user, ModelAllowReauthentication ReAuthentication) { ulong adapterSessionId; ulong adapterPreviousSessionId; Packet_Header_Flags_Values headerFlags; SESSION_SETUP_Request_Flags sessionSetupFlags; AccountCredential credential; #region sessionId if (sessionTable.ContainsKey(sessionId)) { adapterSessionId = sessionTable[sessionId]; // For sessionId is 0 which indicates session creation // assign a new one if (sessionId == ModelSessionId.ZeroSessionId) { if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId)) { sessionId = ModelSessionId.MainSessionId; } else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId)) { sessionId = ModelSessionId.AlternativeSessionId; } } } else { Random r = new Random(); adapterSessionId = (ulong)r.Next(1, int.MaxValue); } Site.Log.Add( LogEntryKind.Debug, "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}", sessionId, adapterSessionId); #endregion #region previousSessionId if (sessionTable.ContainsKey(previousSessionId)) { adapterPreviousSessionId = sessionTable[previousSessionId]; } else { Random r = new Random(); adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue); } Site.Log.Add( LogEntryKind.Debug, "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}", sessionId, adapterPreviousSessionId); #endregion #region isSigned headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; #endregion #region flags switch (flags) { case ModelFlags.Binding: { sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING; break; } case ModelFlags.NotBinding: { sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE; break; } default: throw new ArgumentException("flags"); } #endregion #region user switch (user) { case ModelUser.DefaultUser: { credential = testConfig.AccountCredential; break; } case ModelUser.DiffUser: { credential = testConfig.NonAdminAccountCredential; break; } default: throw new ArgumentException("user"); } #endregion #region MultipleChannel // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect); #endregion PrintCurrentSessionTable("Before SessionSetup Request"); #region Send Request uint status; SESSION_SETUP_Response? sessionSetupResponse = null; string serverName = testConfig.SutComputerName; SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage; bool useServerGssToken = testConfig.UseServerGssToken; // Use desired explored sessionId ulong oldSessionId = connectionList[connectionId].SessionId; connectionList[connectionId].SessionId = adapterSessionId; // alternative connection and never session setup if (connectionId == ModelConnectionId.AlternativeConnection && sessionId == ModelSessionId.MainSessionId && connectionList[connectionId].SessionKey == null && connectionList.ContainsKey(ModelConnectionId.MainConnection)) { connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true); } status = connectionList[connectionId].SessionSetup( headerFlags, sessionSetupFlags, adapterPreviousSessionId, securityPackageType, serverName, credential, useServerGssToken, isMultipleChannelSupported, (header, response) => { sessionSetupResponse = response; }); if (status != Smb2Status.STATUS_SUCCESS && status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED) { // Restore original sessionId if request failed connectionList[connectionId].SessionId = oldSessionId; } #endregion // Insert session to session table if (!sessionTable.ContainsKey(sessionId) && (status == Smb2Status.STATUS_SUCCESS || status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)) { sessionTable.Add(sessionId, connectionList[connectionId].SessionId); } PrintCurrentSessionTable("After SessionSetup Request"); SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig); }
private static void VerifyConnection(ModelConnectionId connectionId) { // Ensure connection exist and connected Condition.IsTrue(ConnectionList.ContainsKey(connectionId)); Condition.IsTrue(ConnectionList[connectionId].ConnectionState == ModelState.Connected); }
public static void LogOffResponse(ModelSmb2Status status, ModelConnectionId connectionId, SessionMgmtConfig c) { Condition.IsTrue(config.Platform == c.Platform); if (config.Platform == Platform.NonWindows && ConnectionList.ContainsKey(connectionId) && ConnectionList[connectionId].Session == null && ConnectionList[connectionId].ConstrainedConnection) { // The TD statements are logged in LogOffRequest ModelHelper.Log(LogType.TestInfo, "SUT platform is NonWindows, so server could return an error code instead of disconnect the connection."); Condition.IsTrue(status != ModelSmb2Status.STATUS_SUCCESS); return; } if (VerifyFootnote(connectionId, c, status)) { return; } VerifyConnection(connectionId); Condition.IsNotNull(ConnectionList[connectionId].Request); ModelLogOffRequest logOffRequest = RetrieveOutstandingRequest <ModelLogOffRequest>(connectionId); if (ConnectionList[connectionId].Session != null && ConnectionList[connectionId].Session.SessionId != logOffRequest.sessionId) { ModelHelper.Log(LogType.Requirement, "3.3.5.2.9: If Connection.SessionTable is not empty and SessionId is not found in Connection.SessionTable, " + "the server MUST fail the request with STATUS_USER_SESSION_DELETED."); ModelHelper.Log(LogType.TestInfo, "Connection.SessionTable is not empty and SessionId of Logoff Request is not found in Connection.SessionTable"); ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier); Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED); return; } if (!ConnectionList[connectionId].ConstrainedConnection && ConnectionList[connectionId].Session == null) { ModelHelper.Log(LogType.Requirement, "3.3.5.2.9: If Connection.ConstrainedConnection is FALSE and Connection.SessionTable is empty, then the server MUST fail any request with STATUS_USER_SESSION_DELETED."); ModelHelper.Log(LogType.TestInfo, "Connection.ConstrainedConnection is FALSE and Connection.SessionTable is empty."); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED); return; } if (GlobalSessionTable.ContainsKey(logOffRequest.sessionId)) { if (GlobalSessionTable[logOffRequest.sessionId].State == ModelSessionState.InProgress) { ModelHelper.Log(LogType.Requirement, "3.3.5.2.9: If Session.State is InProgress, the server MUST continue to process the SMB2 LOGOFF, SMB2 CLOSE, and SMB2 LOCK commands. "); ModelHelper.Log(LogType.TestInfo, "Session.State is InProgress"); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); // Do nothing for LOGOFF and continue } ModelHelper.Log(LogType.Requirement, "3.3.5.6: The server MUST remove this session from the GlobalSessionTable and also from the Connection.SessionTable"); GlobalSessionTable.Remove(logOffRequest.sessionId); ConnectionList[logOffRequest.connectionId].Session = null; } ModelHelper.Log(LogType.TestInfo, "Verifying the Session succeeds."); Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS); }
public void SetupConnection(ModelConnectionId connectionId, ModelDialectRevision clientMaxDialect) { connectionList.Add(connectionId, new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site)); if (connectionId == ModelConnectionId.MainConnection) { connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic1IPAddress); } else { connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic2IPAddress); } DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect)); uint status; NEGOTIATE_Response? negotiateResponse = null; status = connectionList[connectionId].Negotiate( dialects, testConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, clientGuid: GetClientGuid(connectionId, dialects), checker: (header, response) => { Site.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); DialectRevision expectedDialect; if (clientMaxDialect < sessionMgmtConfig.MaxSmbVersionSupported) { expectedDialect = ModelUtility.GetDialectRevision(clientMaxDialect); } else { expectedDialect = ModelUtility.GetDialectRevision(sessionMgmtConfig.MaxSmbVersionSupported); } Site.Assert.AreEqual( expectedDialect, negotiateResponse.Value.DialectRevision, "DialectRevision {0} is expected", expectedDialect); if (ModelUtility.IsSmb3xFamily(negotiateResponse.Value.DialectRevision) && sessionMgmtConfig.IsMultiChannelCapable) { // SMB2_GLOBAL_CAP_MULTI_CHANNEL if Connection.Dialect belongs to the SMB 3.x dialect family, // IsMultiChannelCapable is TRUE, and SMB2_GLOBAL_CAP_MULTI_CHANNEL is set in the Capabilities field of the request. Site.Assert.AreEqual( Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities, ""); } else { Site.Assert.AreNotEqual( Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities, ""); } }
public static void SessionSetupResponse(ModelSmb2Status status, ModelConnectionId connectionId, SessionMgmtConfig c) { VerifyConnection(connectionId); Condition.IsNotNull(ConnectionList[connectionId].Request); Condition.IsTrue(config.Platform == c.Platform); Condition.IsTrue(config.IsMultiChannelCapable == c.IsMultiChannelCapable); ModelSessionSetupRequest sessionSetupRequest = RetrieveOutstandingRequest <ModelSessionSetupRequest>(connectionId); if (sessionSetupRequest.isSigned) { ModelHelper.Log(LogType.Requirement, "3.3.5.2.4: If the SMB2 header of the request has SMB2_FLAGS_SIGNED set in the Flags field, the server MUST verify the signature."); ModelHelper.Log(LogType.TestInfo, "SMB2_FLAGS_SIGNED is set in the SMB2 header of the SessionSetup Request."); // If server does not support Multiple channel then whether binding is set is meaningless. if (config.IsMultiChannelCapable && sessionSetupRequest.flags == ModelFlags.Binding) { ModelHelper.Log(LogType.Requirement, "If the request is for binding the session, the server MUST look up the session in the GlobalSessionTable using the SessionId in the SMB2 header of the request. "); ModelHelper.Log(LogType.TestInfo, "SMB2_SESSION_FLAG_BINDING bit is set."); if (!GlobalSessionTable.ContainsKey(sessionSetupRequest.sessionId)) { ModelHelper.Log(LogType.Requirement, "If the session is not found, the request MUST be failed, as specified in section Sending an Error Response (section 3.3.4.4), " + "with the error code STATUS_USER_SESSION_DELETED. "); ModelHelper.Log(LogType.TestInfo, "The session is not found in GlobalSessionTable."); ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier); Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED); return; } } else { ModelHelper.Log(LogType.Requirement, "For all other requests, the server MUST look up the session in the Connection.SessionTable using the SessionId in the SMB2 header of the request."); ModelHelper.Log(LogType.TestInfo, "SMB2_SESSION_FLAG_BINDING bit is not set."); if (ConnectionList[connectionId].Session == null || ConnectionList[connectionId].Session.SessionId != sessionSetupRequest.sessionId) { ModelHelper.Log(LogType.Requirement, "If the session is not found, the request MUST be failed, as specified in section Sending an Error Response (section 3.3.4.4), " + "with the error code STATUS_USER_SESSION_DELETED. "); ModelHelper.Log(LogType.TestInfo, "The session is not found in Connection.SessionTable."); ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier); Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED); return; } } } if (sessionSetupRequest.sessionId == ModelSessionId.ZeroSessionId) { ModelHelper.Log(LogType.Requirement, "3.3.5.5: 3. If SessionId in the SMB2 header of the request is zero, the server MUST process the authentication request as specified in section 3.3.5.5.1."); ModelHelper.Log(LogType.TestInfo, "The SessionId of the SessionSetup Request is zero"); AuthNewSession(status, sessionSetupRequest); Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS || status == ModelSmb2Status.STATUS_MORE_PROCESSING_REQUIRED); return; } if (ModelUtility.IsSmb3xFamily(ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect) && config.IsMultiChannelCapable && sessionSetupRequest.flags == ModelFlags.Binding) { ModelHelper.Log(LogType.Requirement, "3.3.5.5: 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:" + "The server MUST look up the session in GlobalSessionTable using the SessionId from the SMB2 header."); ModelHelper.Log(LogType.TestInfo, "Connection.Dialect is {0}, IsMultiChannelCapable is TRUE, and the SMB2_SESSION_FLAG_BINDING bit is set", ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect); if (!GlobalSessionTable.ContainsKey(sessionSetupRequest.sessionId)) { ModelHelper.Log(LogType.Requirement, "If the session is not found, the server MUST fail the session setup request with STATUS_USER_SESSION_DELETED."); ModelHelper.Log(LogType.TestInfo, "The SessionId cannot be found in GlobalSessionTable"); ModelHelper.Log(LogType.TestTag, TestTag.InvalidIdentifier); Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED); return; } ModelHelper.Log(LogType.Requirement, "If a session is found, the server MUST do the following:"); if (ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect != GlobalSessionTable[sessionSetupRequest.sessionId].Dialect) { ModelHelper.Log(LogType.Requirement, "If Connection.Dialect is not the same as Session.Connection.Dialect, the server MUST fail the request with STATUS_INVALID_PARAMETER."); ModelHelper.Log(LogType.TestInfo, "The Connection.Dialect is {0}, Session.Connection.Dialect is {1}", ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect, GlobalSessionTable[sessionSetupRequest.sessionId].Dialect); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER); return; } if (!sessionSetupRequest.isSigned) { ModelHelper.Log(LogType.Requirement, "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."); ModelHelper.Log(LogType.TestInfo, "The SMB2_FLAGS_SIGNED bit is not set in the SessionSetup Request"); ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields); Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER); return; } if (GlobalSessionTable[sessionSetupRequest.sessionId].State == ModelSessionState.InProgress) { ModelHelper.Log(LogType.Requirement, "If Session.State is InProgress, the server MUST fail the request with STATUS_REQUEST_NOT_ACCEPTED."); ModelHelper.Log(LogType.TestInfo, "Session.State is InProgress"); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED); return; } // If Session.IsAnonymousor Session.IsGuestis TRUE, the server MUST fail the request with STATUS_NOT_SUPPORTED. // Skip above requirement according to assumption 6. if (ConnectionList[sessionSetupRequest.connectionId].Session != null && ConnectionList[sessionSetupRequest.connectionId].Session.SessionId == sessionSetupRequest.sessionId) { ModelHelper.Log(LogType.Requirement, "If there is a session in Connection.SessionTable identified by the SessionId in the request, the server MUST fail the request with STATUS_REQUEST_NOT_ACCEPTED."); ModelHelper.Log(LogType.TestInfo, "There is a session in Connection.SessionTable which has a same SessionId in the request"); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED); return; } // The server MUST verify the signature as specified in section 3.3.5.2.4, using the Session.SessionKey. // Skip above requirement as it is verified in signing model if (sessionSetupRequest.user == ModelUser.DiffUser) { ModelHelper.Log(LogType.Requirement, "The server MUST obtain the security context from the GSS authentication subsystem, " + "and it MUST invoke the GSS_Inquire_context call as specified in [RFC2743] section 2.2.6, " + "passing the security context as the input parameter." + "If the returned \"src_name\" does not match with the Session.Username, the server MUST fail the request with error code STATUS_NOT_SUPPORTED."); ModelHelper.Log(LogType.TestInfo, "A different user is used when binding to an existing session"); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(status == ModelSmb2Status.STATUS_NOT_SUPPORTED); return; } } else { if (config.Platform == Platform.WindowsServer2012 && sessionSetupRequest.flags == ModelFlags.Binding) { ModelHelper.Log(LogType.Requirement, "<232> Section 3.3.5.5: Windows 8 and Windows Server 2012 look up the session in GlobalSessionTable using the SessionId from the SMB2 header " + "if the SMB2_SESSION_FLAG_BINDING bit is set in the Flags field of the request. "); ModelHelper.Log(LogType.TestInfo, "The SUT platform is {0}. The SMB2_SESSION_FLAG_BINDING bit is set.", config.Platform); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); if (GlobalSessionTable.ContainsKey(sessionSetupRequest.sessionId)) { ModelHelper.Log(LogType.Requirement, "If the session is found, the server fails the request with STATUS_REQUEST_NOT_ACCEPTED. "); ModelHelper.Log(LogType.TestInfo, "The session is found"); Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED); return; } else { ModelHelper.Log(LogType.Requirement, "If the session is not found, the server fails the request with STATUS_USER_SESSION_DELETED."); ModelHelper.Log(LogType.TestInfo, "The session is not found"); Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED); return; } } if (ModelUtility.IsSmb3xFamily(config.MaxSmbVersionSupported) && ((ModelUtility.IsSmb2Family(ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect) || !config.IsMultiChannelCapable)) && sessionSetupRequest.flags == ModelFlags.Binding) { ModelHelper.Log(LogType.Requirement, "3.3.5.5: Otherwise, if the server implements the SMB 3.x dialect family, " + "and Connection.Dialect is equal to \"2.002\" or \"2.100\" or IsMultiChannelCapable is FALSE, " + "and SMB2_SESSION_FLAG_BINDING bit is set in the Flags field of the request, " + "the server SHOULD<225> fail the session setup request with STATUS_REQUEST_NOT_ACCEPTED."); ModelHelper.Log(LogType.TestInfo, "Connection.Dialect is {0}, IsMultiChannelCapable is {1}, SUT platform is {2}, Max Smb version supported is {3} and SMB2_SESSION_FLAG_BINDING bit is set.", ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect, config.IsMultiChannelCapable, config.Platform, config.MaxSmbVersionSupported); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); if (config.Platform != Platform.NonWindows) { Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED); } else { ModelHelper.Log(LogType.TestInfo, "The SUT platform is NonWindows, so the server could fail the request with other error code."); Condition.IsTrue(status != ModelSmb2Status.STATUS_SUCCESS); } return; } else { if (ConnectionList[sessionSetupRequest.connectionId].Session == null || ConnectionList[sessionSetupRequest.connectionId].Session.SessionId != sessionSetupRequest.sessionId) { ModelHelper.Log(LogType.Requirement, "3.3.5.5: Otherwise, the server MUST look up the session in Connection.SessionTable using the SessionId from the SMB2 header." + "If the session is not found, the server MUST fail the session setup request with STATUS_USER_SESSION_DELETED. "); ModelHelper.Log(LogType.TestInfo, "The session is not found using the SessionId of the request"); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(status == ModelSmb2Status.STATUS_USER_SESSION_DELETED); return; } } } if (GlobalSessionTable[sessionSetupRequest.sessionId].State == ModelSessionState.Valid) { ModelHelper.Log(LogType.Requirement, "3.3.5.5: 6. If Session.State is Valid, the server SHOULD process the session setup request as specified in section 3.3.5.5.2."); ModelHelper.Log(LogType.TestInfo, "Session.State is Valid"); if (config.Platform == Platform.WindowsServer2008) { ModelHelper.Log(LogType.Requirement, "Footnote: Windows Vista SP1 and Windows Server 2008 servers fail the session setup request with STATUS_REQUEST_NOT_ACCEPTED."); ModelHelper.Log(LogType.TestInfo, "The SUT platform is Windows Server 2008"); ModelHelper.Log(LogType.TestTag, TestTag.Compatibility); Condition.IsTrue(status == ModelSmb2Status.STATUS_REQUEST_NOT_ACCEPTED); return; } if (config.Platform != Platform.NonWindows) { ModelHelper.Log(LogType.TestInfo, "The SUT platform is Windows"); ReAuthentication(status, sessionSetupRequest); Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS || status == ModelSmb2Status.STATUS_MORE_PROCESSING_REQUIRED); return; } } ModelHelper.Log(LogType.Requirement, "3.3.5.5: 7. The server MUST continue processing the request as specified in section 3.3.5.5.3."); HandleGssApiAuth(status, sessionSetupRequest); ModelHelper.Log(LogType.TestInfo, "The authentication should succeed."); Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS || status == ModelSmb2Status.STATUS_MORE_PROCESSING_REQUIRED); }
public void SessionSetupRequest( ModelConnectionId connectionId, ModelSessionId sessionId, ModelSessionId previousSessionId, ModelSigned signed, ModelFlags flags, ModelUser user, ModelAllowReauthentication ReAuthentication) { ulong adapterSessionId; ulong adapterPreviousSessionId; Packet_Header_Flags_Values headerFlags; SESSION_SETUP_Request_Flags sessionSetupFlags; AccountCredential credential; #region sessionId if (sessionTable.ContainsKey(sessionId)) { adapterSessionId = sessionTable[sessionId]; // For sessionId is 0 which indicates session creation // assign a new one if (sessionId == ModelSessionId.ZeroSessionId) { if (!sessionTable.ContainsKey(ModelSessionId.MainSessionId)) { sessionId = ModelSessionId.MainSessionId; } else if (!sessionTable.ContainsKey(ModelSessionId.AlternativeSessionId)) { sessionId = ModelSessionId.AlternativeSessionId; } } } else { Random r = new Random(); adapterSessionId = (ulong)r.Next(1, int.MaxValue); } Site.Log.Add( LogEntryKind.Debug, "ModelSessionId: {0}, AdapterSessionId: 0x{1:x8}", sessionId, adapterSessionId); #endregion #region previousSessionId if (sessionTable.ContainsKey(previousSessionId)) { adapterPreviousSessionId = sessionTable[previousSessionId]; } else { Random r = new Random(); adapterPreviousSessionId = (ulong)r.Next(1, int.MaxValue); } Site.Log.Add( LogEntryKind.Debug, "ModelSessionId: {0}, adapterPreviousSessionId: 0x{1:x8}", sessionId, adapterPreviousSessionId); #endregion #region isSigned headerFlags = (signed == ModelSigned.SignFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE; #endregion #region flags switch (flags) { case ModelFlags.Binding: { sessionSetupFlags = SESSION_SETUP_Request_Flags.SESSION_FLAG_BINDING; break; } case ModelFlags.NotBinding: { sessionSetupFlags = SESSION_SETUP_Request_Flags.NONE; break; } default: throw new ArgumentException("flags"); } #endregion #region user switch (user) { case ModelUser.DefaultUser: { credential = testConfig.AccountCredential; break; } case ModelUser.DiffUser: { credential = testConfig.NonAdminAccountCredential; break; } default: throw new ArgumentException("user"); } #endregion #region MultipleChannel // Multiple Channel only takes affect when Connection.Dialect belongs to the SMB 3.x dialect family bool isMultipleChannelSupported = sessionMgmtConfig.IsMultiChannelCapable && ModelUtility.IsSmb3xFamily(connectionList[connectionId].Dialect); #endregion PrintCurrentSessionTable("Before SessionSetup Request"); #region Send Request uint status; SESSION_SETUP_Response?sessionSetupResponse = null; string serverName = testConfig.SutComputerName; SecurityPackageType securityPackageType = testConfig.DefaultSecurityPackage; bool useServerGssToken = testConfig.UseServerGssToken; // Use desired explored sessionId ulong oldSessionId = connectionList[connectionId].SessionId; connectionList[connectionId].SessionId = adapterSessionId; // alternative connection and never session setup if (connectionId == ModelConnectionId.AlternativeConnection && sessionId == ModelSessionId.MainSessionId && connectionList[connectionId].SessionKey == null && connectionList.ContainsKey(ModelConnectionId.MainConnection)) { connectionList[connectionId].GenerateCryptoKeys(testConfig.SendSignedRequest, false, connectionList[ModelConnectionId.MainConnection], true); } status = connectionList[connectionId].SessionSetup( headerFlags, sessionSetupFlags, adapterPreviousSessionId, securityPackageType, serverName, credential, useServerGssToken, isMultipleChannelSupported, (header, response) => { sessionSetupResponse = response; }); if (status != Smb2Status.STATUS_SUCCESS && status != Smb2Status.STATUS_MORE_PROCESSING_REQUIRED) { // Restore original sessionId if request failed connectionList[connectionId].SessionId = oldSessionId; } #endregion // Insert session to session table if (!sessionTable.ContainsKey(sessionId) && (status == Smb2Status.STATUS_SUCCESS || status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED)) { sessionTable.Add(sessionId, connectionList[connectionId].SessionId); } PrintCurrentSessionTable("After SessionSetup Request"); SessionSetupResponse((ModelSmb2Status)status, connectionId, sessionMgmtConfig); }
private Guid GetClientGuid(ModelConnectionId connectionId, DialectRevision[] dialects) { if (dialects.Length == 1 && dialects[0] == DialectRevision.Smb2002) { return Guid.Empty; } else if (connectionId == ModelConnectionId.MainConnection) { this.clientGuid = Guid.NewGuid(); return this.clientGuid; } else { return this.clientGuid; } }
public void SetupConnection(ModelConnectionId connectionId, ModelDialectRevision clientMaxDialect) { connectionList.Add(connectionId, new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site)); if (connectionId == ModelConnectionId.MainConnection) { connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic1IPAddress); } else { connectionList[connectionId].ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress, testConfig.ClientNic2IPAddress); } DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect)); uint status; NEGOTIATE_Response?negotiateResponse = null; status = connectionList[connectionId].Negotiate( dialects, testConfig.IsSMB1NegotiateEnabled, capabilityValue: Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, clientGuid: GetClientGuid(connectionId, dialects), checker: (header, response) => { Site.Assert.AreEqual( Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command); negotiateResponse = response; }); DialectRevision expectedDialect; if (clientMaxDialect < sessionMgmtConfig.MaxSmbVersionSupported) { expectedDialect = ModelUtility.GetDialectRevision(clientMaxDialect); } else { expectedDialect = ModelUtility.GetDialectRevision(sessionMgmtConfig.MaxSmbVersionSupported); } Site.Assert.AreEqual( expectedDialect, negotiateResponse.Value.DialectRevision, "DialectRevision {0} is expected", expectedDialect); if (ModelUtility.IsSmb3xFamily(negotiateResponse.Value.DialectRevision) && sessionMgmtConfig.IsMultiChannelCapable) { // SMB2_GLOBAL_CAP_MULTI_CHANNEL if Connection.Dialect belongs to the SMB 3.x dialect family, // IsMultiChannelCapable is TRUE, and SMB2_GLOBAL_CAP_MULTI_CHANNEL is set in the Capabilities field of the request. Site.Assert.AreEqual( Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities, ""); } else { Site.Assert.AreNotEqual( Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL & (Capabilities_Values)negotiateResponse.Value.Capabilities, ""); } }