public void ComNegotiateRequest(Sequence<string> 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.MultiProtocolNegotiate(dialects.ToArray(), out selectedDialect, out smb2ClientGssToken, out responseHeader, out responsePayload);
                if (status != ModelSmb2Status.STATUS_SUCCESS)
                {
                    selectedDialect = DialectRevision.Smb2Unknown;
                }
                this.NegotiateResponse(status, selectedDialect);
                if (selectedDialect == DialectRevision.Smb2Wildcard)
                {
                    messageId = 1;
                }
            }
            catch
            {
            }
        }
        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 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 virtual uint Negotiate(
            ushort creditCharge,
            ushort creditRequest,
            ulong messageId,
            Guid clientGuid,
            out DialectRevision selectedDialect,
            out byte[] gssToken,
            out Packet_Header responseHeader,
            out NEGOTIATE_Response responsePayload)
        {
            uint status = client.Negotiate(
                            creditCharge,
                            creditRequest,
                            Packet_Header_Flags_Values.NONE,
                            messageId,
                            new DialectRevision[] { DialectRevision.Smb2002 },
                            SecurityMode_Values.NONE,
                            Capabilities_Values.NONE,
                            clientGuid,
                            out selectedDialect,
                            out gssToken,
                            out responseHeader,
                            out responsePayload);

            negotiatedDialect = selectedDialect;

            serverCapabilities = (Capabilities_Values)responsePayload.Capabilities;

            return status;
        }
        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)
                {
                    EncryptionAlgorithm expectedEnAlg = EncryptionAlgorithm.ENCRYPTION_NONE;
                    foreach (var alg in encryptionAlgs)
                    {
                        if (TestConfig.SupportedEncryptionAlgorithmList.Contains(alg))
                        {
                            expectedEnAlg = alg;
                            break;
                        }
                    }
                    BaseTestSite.Assert.AreEqual(
                        expectedEnAlg,
                        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. ");
            }
        }
        /// <summary>
        /// Negotiate, SessionSetup and TreeConnect
        /// </summary>
        public void SetupConnection(ModelDialectRevision dialect, ModelCapabilities capabilities, SecurityMode_Values securityMode)
        {
            #region Connect to server
            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);
            #endregion

            // It MUST be a GUID generated by the client, if the Dialects field contains a value other than 0x0202. Otherwise, the client MUST set this to 0.
            Guid clientGuid = (dialect == ModelDialectRevision.Smb2002) ? Guid.Empty : Guid.NewGuid();

            #region negotiate
            testClient.Negotiate(
                Packet_Header_Flags_Values.NONE,
                Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(dialect)),
                securityMode,
                (Capabilities_Values)capabilities,
                clientGuid,
                (header, response) =>
                {
                    Site.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, header.Status, "{0} should succeed", header.Command);
                    negotiateResponse = response;
                });
            #endregion

            #region session setup
            testClient.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken,
                (SESSION_SETUP_Request_SecurityMode_Values)securityMode);
            #endregion

            #region treeconnect
            testClient.TreeConnect(
                Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare),
                out treeId);
            #endregion

            Connection_Dialect = ModelUtility.GetModelDialectRevision(negotiateResponse.DialectRevision);
            Connection_ClientCapabilities = (Capabilities_Values)capabilities;
            Connection_ClientSecurityMode = securityMode;
            Connection_ClientGuid = clientGuid;
        }
 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)
 {
     if (supportV2)
     {
         return client.Negotiate(
         creditCharge,
         creditRequest,
         Packet_Header_Flags_Values.NONE,
         messageId,
         new DialectRevision[] { DialectRevision.Smb30 },
         SecurityMode_Values.NONE,
         Capabilities_Values.NONE,
         clientGuid,
         out selectedDialect,
         out gssToken,
         out responseHeader,
         out responsePayload);
     }
     else
     {
         return client.Negotiate(
         creditCharge,
         creditRequest,
         Packet_Header_Flags_Values.NONE,
         messageId,
         new DialectRevision[] { DialectRevision.Smb21 },
         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.");
            }
        }
        /// <summary>
        /// Delegate to check negotiate response header and payload in this class.
        /// </summary>
        /// <param name="responseHeader">Response header to be checked</param>
        /// <param name="response">Negotiate response payload to be checked</param>
        public void ReplayNegotiateResponseChecker(Packet_Header responseHeader, NEGOTIATE_Response response)
        {
            BaseTestSite.Assert.AreEqual(
                Smb2Status.STATUS_SUCCESS,
                responseHeader.Status,
                "Negotiation should succeed, actually server returns {0}.", Smb2Status.GetStatusCode(responseHeader.Status));

            TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response);
        }