Пример #1
0
        private static void ReAuthentication(ModelSmb2Status status, ModelSessionSetupRequest sessionSetupRequest)
        {
            // Update both GlobalSessionTable and ConnectionList
            ModelHelper.Log(LogType.Requirement, "3.3.5.5.2: Session.State MUST be set to InProgress");
            GlobalSessionTable[sessionSetupRequest.sessionId].State = ModelSessionState.InProgress;

            ModelHelper.Log(LogType.Requirement, "Authentication is continued as specified in section 3.3.5.5.3.");
            HandleGssApiAuth(status, sessionSetupRequest);
        }
Пример #2
0
        private static void AuthNewSession(ModelSmb2Status status, ModelSessionSetupRequest sessionSetupRequest)
        {
            ModelHelper.Log(LogType.Requirement, "3.3.5.5.1: A session object MUST be allocated for this request. ");

            ModelSession   session   = new ModelSession();
            ModelSessionId?sessionId = null;

            if (!GlobalSessionTable.ContainsKey(ModelSessionId.MainSessionId))
            {
                sessionId = ModelSessionId.MainSessionId;
            }
            else
            {
                sessionId = ModelSessionId.AlternativeSessionId;
            }

            // Update sessionId to new created one from zero
            sessionSetupRequest.sessionId = sessionId.Value;

            ModelHelper.Log(LogType.Requirement, "The other values MUST be initialized as follows:");
            session.Dialect = ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect;

            ModelHelper.Log(LogType.Requirement, "Session.State is set to InProgress.");
            session.State     = ModelSessionState.InProgress;
            session.SessionId = sessionId.Value;

            ModelHelper.Log(LogType.Requirement,
                            "The session MUST be inserted into the GlobalSessionTable and a unique Session.SessionId is assigned to serve as a lookup key in the table. ");
            GlobalSessionTable.Add(sessionSetupRequest.sessionId, session);

            ModelHelper.Log(LogType.Requirement, "The session MUST be inserted into Connection.SessionTable. ");
            ConnectionList[sessionSetupRequest.connectionId].Session = session;

            ModelHelper.Log(LogType.Requirement, "Using this session, authentication is continued as specified in section 3.3.5.5.3.");
            HandleGssApiAuth(status, sessionSetupRequest);
        }
Пример #3
0
        private static void HandleGssApiAuth(ModelSmb2Status status, ModelSessionSetupRequest sessionSetupRequest)
        {
            ModelHelper.Log(LogType.Requirement, "3.3.5.5.3: 1. The status code in the SMB2 header of the response MUST be set to STATUS_SUCCESS. ");
            if (status != ModelSmb2Status.STATUS_SUCCESS)
            {
                return;
            }

            if (ModelUtility.IsSmb3xFamily(ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect))
            {
                ModelHelper.Log(LogType.Requirement, "If Connection.Dialect belongs to the SMB 3.x dialect family, the server MUST insert the Session into Connection.SessionTable. ");
                ModelHelper.Log(LogType.TestInfo, "Connection.Dialect is {0}", ConnectionList[sessionSetupRequest.connectionId].NegotiateDialect);
                ConnectionList[sessionSetupRequest.connectionId].Session
                    = GlobalSessionTable[sessionSetupRequest.sessionId];
            }

            ModelHelper.Log(LogType.Requirement, "If Session.IsAnonymous is FALSE, the server MUST set Connection.ConstrainedConnection to FALSE.");
            ModelHelper.Log(LogType.TestInfo, "Session.IsAnonymous is FALSE, so set Connection.ConstrainedConnection to FALSE");
            ConnectionList[sessionSetupRequest.connectionId].ConstrainedConnection = false;

            /*
             * Assuming STATUS_SUCCESS indicates final message in the authentication exchange
             *
             * Skip following requirement according to assumption 6.
             * If the returned anon_state is TRUE, the server MUST set Session.IsAnonymous to TRUE and the server MAY set
             * the SMB2_SESSION_FLAG_IS_NULL flag in the SessionFlags field of the SMB2 SESSION_SETUP Response.
             * Otherwise, if the returned src_name corresponds to an implementation-specific guest user,<211>
             * the server MUST set the SMB2_SESSION_FLAG_IS_GUEST in the SessionFlags field of the SMB2 SESSION_SETUP Response
             * and MUST set Session.IsGuest to TRUE.
             */

            if (sessionSetupRequest.previousSessionId != ModelSessionId.ZeroSessionId)
            {
                ModelHelper.Log(LogType.Requirement, "12. If the PreviousSessionId field of the request is not equal to zero, the server MUST take the following actions:");
                ModelHelper.Log(LogType.TestInfo, "PreviousSessionId is not equal to zero.");

                ModelHelper.Log(LogType.Requirement, "1. The server MUST look up the old session in GlobalSessionTable, where Session.SessionId matches PreviousSessionId. ");
                if (GlobalSessionTable.ContainsKey(sessionSetupRequest.previousSessionId))
                {
                    ModelHelper.Log(LogType.Requirement,
                                    "If a session is found with Session.SessionId equal to PreviousSessionId, " +
                                    "the server MUST determine if the old session and the newly established session are created by the same user " +
                                    "by comparing the user identifiers obtained from the Session.SecurityContext on the new and old session.");
                    ModelHelper.Log(LogType.TestInfo, "There is a session with Session.SessionId equal to PreviousSessionId.");

                    if (sessionSetupRequest.previousSessionId == sessionSetupRequest.sessionId)
                    {
                        ModelHelper.Log(LogType.Requirement, "1. If the PreviousSessionId and SessionId values in the SMB2 header of the request are equal, " +
                                        "the server SHOULD<230> ignore PreviousSessionId and no other processing is required.");
                        ModelHelper.Log(LogType.TestInfo, "PreviousSessionId is equal to SessionId.");
                        // Do nothing
                    }
                    else if (sessionSetupRequest.user == ModelUser.DefaultUser)
                    {
                        ModelHelper.Log(LogType.Requirement,
                                        "2.	Otherwise, if the server determines the authentications were for the same user, " +
                                        "the server MUST remove the old session from the GlobalSessionTable and also from the Connection.SessionTable, as specified in section 3.3.7.1.");
                        ModelHelper.Log(LogType.TestInfo, "The authentications were for the same user");
                        GlobalSessionTable.Remove(sessionSetupRequest.previousSessionId);
                    }
                }
            }

            ModelHelper.Log(LogType.Requirement, "13. Session.State MUST be set to Valid.");
            // Update both GlobalSessionTable and ConnectionList
            GlobalSessionTable[sessionSetupRequest.sessionId].State        = ModelSessionState.Valid;
            ConnectionList[sessionSetupRequest.connectionId].Session.State = ModelSessionState.Valid;
        }
Пример #4
0
        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);
        }