public void Negotiate_SMB311_ContextID_NetName()
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send NEGOTIATE request with SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context.");

            DialectRevision clientMaxDialectSupported = DialectRevision.Smb311;

            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
            EncryptionAlgorithm[]    encryptionAlgs  = new EncryptionAlgorithm[] {
                EncryptionAlgorithm.ENCRYPTION_AES128_GCM,
                EncryptionAlgorithm.ENCRYPTION_AES128_CCM
            };

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Send Negotiate request with dialect SMB 3.11, SMB2_PREAUTH_INTEGRITY_CAPABILITIES context and " +
                "SMB2_ENCRYPTION_CAPABILITIES context and SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context.");

            NegotiateWithNegotiateContexts(
                clientMaxDialectSupported,
                preauthHashAlgs,
                encryptionAlgs,
                addNetNameContextId: true,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "[MS-SMB2] section 2.2.3.1.3: The SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context is specified in an SMB2 NEGOTIATE request to indicate the server name the client connects to. The server MUST ignore this context. "
                    );
            }
                );
        }
Example #2
0
        public TestConfigBase(ITestSite site)
        {
            Site = site;

            WriteBufferLengthInKb = DEFAULT_WRITE_BUFFER_SIZE_IN_KB;

            string activeTDIsProperty = GetProperty("ActiveTDIs", false);

            if (!string.IsNullOrEmpty(activeTDIsProperty))
            {
                ActiveTDIs = new List <string>(activeTDIsProperty.Split(';'));
            }
            else
            {
                ActiveTDIs = new List <string>();
            }

            MaxSmbVersionSupported = ParsePropertyToEnum <DialectRevision>(GetProperty("MaxSmbVersionSupported"), "MaxSmbVersionSupported");

            MaxSmbVersionClientSupported = ParsePropertyToEnum <DialectRevision>(GetProperty("MaxSmbVersionClientSupported"), "MaxSmbVersionClientSupported");

            SupportedEncryptionAlgorithmList = ParsePropertyToList <EncryptionAlgorithm>("SupportedEncryptionAlgorithms");

            SupportedCompressionAlgorithmList = ParsePropertyToList <CompressionAlgorithm>("SupportedCompressionAlgorithms");
        }
Example #3
0
        protected byte[] SendAndRecieveSmb2Ap(FileServer fileServer, byte[] gssApiToken)
        {
            BaseTestSite.Log.Add(LogEntryKind.Comment, "SMB2 AP Exchange.");
            Smb2FunctionalTestClient smb2Client = new Smb2FunctionalTestClient(KerberosConstValue.TIMEOUT_FOR_SMB2AP);

            smb2Client.ConnectToServerOverTCP(System.Net.IPAddress.Parse(fileServer.IPAddress));
            DialectRevision smb2Dialect = (DialectRevision)Enum.Parse(typeof(DialectRevision), fileServer.Smb2Dialect);
            DialectRevision selectedDialect;
            uint            status = smb2Client.Negotiate(
                new DialectRevision[] { smb2Dialect },
                SecurityMode_Values.NONE,
                Capabilities_Values.GLOBAL_CAP_DFS,
                Guid.NewGuid(),
                out selectedDialect);

            BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Negotiate failed with error.");

            byte[] repToken;
            status = smb2Client.SessionSetup(
                SESSION_SETUP_Request_SecurityMode_Values.NONE,
                SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS,
                SecurityPackageType.Kerberos,
                fileServer.FQDN,
                gssApiToken,
                out repToken);

            if (status == Smb2Status.STATUS_SUCCESS)
            {
                status = smb2Client.LogOff();
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SUCCESS, status, "Logoff failed with error.");
            }
            smb2Client.Disconnect();

            return(repToken);
        }
        public uint Smb2Negotiate(DialectRevision[] requestDialects, out DialectRevision selectedDialect)
        {
            uint status;
            NEGOTIATE_Response negotiateResponse;

            clientGuid = Guid.NewGuid();
            status     = this.Negotiate(
                1,
                1,
                Packet_Header_Flags_Values.NONE,
                this.messageId,
                requestDialects,
                SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                CAPABILITIES,
                clientGuid,
                out selectedDialect,
                out this.gssToken,
                out packetHeader,
                out negotiateResponse
                );

            this.Smb2MaxReadSize  = negotiateResponse.MaxReadSize;
            this.Smb2MaxWriteSize = negotiateResponse.MaxWriteSize;

            CalculateSmb2AvailableCredits(1, packetHeader.CreditRequestResponse);
            return(status);
        }
        private void NegotiateWithSpecificDialect(DialectRevision clientMaxDialectSupported)
        {
            DialectRevision serverMaxDialectSupported = TestConfig.MaxSmbVersionSupported;

            DialectRevision[] negotiateDialects = Smb2Utility.GetDialects(clientMaxDialectSupported);

            if (clientMaxDialectSupported > TestConfig.MaxSmbVersionClientSupported)
            {
                BaseTestSite.Assert.Inconclusive("Stop to run this test case because the configured MaxSmbVersionClientSupported {0} is lower than {1}.",
                                                 TestConfig.MaxSmbVersionClientSupported,
                                                 clientMaxDialectSupported);
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send Negotiate request with maximum dialect: {0}.", clientMaxDialectSupported);
            client.Negotiate(
                Packet_Header_Flags_Values.NONE,
                negotiateDialects,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                DialectRevision expectedDialect = clientMaxDialectSupported < serverMaxDialectSupported
                        ? clientMaxDialectSupported : serverMaxDialectSupported;

                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Check negotiate response contains expected dialect.");
                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);
            });
        }
        public bool CheckSmbDialect()
        {
            DetectorUtil.WriteLog("Check the supported SMB dialects of SUT...");

            bool result = false;

            var dialects = new DialectRevision[] { DialectRevision.Smb30, DialectRevision.Smb302, DialectRevision.Smb311 };

            var ipList = GetIPAdressOfSut();

            // try all reachable SUT IP address
            foreach (var ip in ipList)
            {
                var supportedDialects = TryNegotiateDialects(ip, dialects);
                if (supportedDialects.Length > 0)
                {
                    DetectionInfo.SupportedSmbDialects = supportedDialects;
                    DetectorUtil.WriteLog(String.Format("SMB dialects supported by SUT: {0}", String.Join(",", supportedDialects)));
                    result = true;
                    break;
                }
            }

            if (result)
            {
                DetectorUtil.WriteLog("Finished", false, LogStyle.StepPassed);
                return(true);
            }
            else
            {
                DetectorUtil.WriteLog("Failed", false, LogStyle.StepFailed);
                return(false);
            }
        }
        /// <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);
            }


            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);
        }
        private void NegotiateWithNegotiateContexts(
            DialectRevision clientMaxDialectSupported,
            PreauthIntegrityHashID[] preauthHashAlgs,
            EncryptionAlgorithm[] encryptionAlgs         = null,
            ResponseChecker <NEGOTIATE_Response> checker = null)
        {
            // ensure clientMaxDialectSupported higher than 3.11
            if (clientMaxDialectSupported < DialectRevision.Smb311)
            {
                clientMaxDialectSupported = DialectRevision.Smb311;
            }
            DialectRevision[] negotiateDialects = Smb2Utility.GetDialects(clientMaxDialectSupported);

            if (clientMaxDialectSupported > TestConfig.MaxSmbVersionClientSupported)
            {
                BaseTestSite.Assert.Inconclusive("Stop to run this test case because the configured MaxSmbVersionClientSupported {0} is lower than {1}.",
                                                 TestConfig.MaxSmbVersionClientSupported,
                                                 clientMaxDialectSupported);
            }

            status = client.NegotiateWithContexts(
                Packet_Header_Flags_Values.NONE,
                negotiateDialects,
                preauthHashAlgs: preauthHashAlgs,
                encryptionAlgs: encryptionAlgs,
                checker: checker);
        }
        public TestConfigBase(ITestSite site)
        {
            Site = site;

            WriteBufferLengthInKb = DEFAULT_WRITE_BUFFER_SIZE_IN_KB;

            string activeTDIsProperty = GetProperty("ActiveTDIs", false);

            if (!string.IsNullOrEmpty(activeTDIsProperty))
            {
                ActiveTDIs = new List <string>(activeTDIsProperty.Split(';'));
            }
            else
            {
                ActiveTDIs = new List <string>();
            }

            MaxSmbVersionSupported = ParsePropertyToEnum <DialectRevision>(GetProperty("MaxSmbVersionSupported"), "MaxSmbVersionSupported");

            MaxSmbVersionClientSupported = ParsePropertyToEnum <DialectRevision>(GetProperty("MaxSmbVersionClientSupported"), "MaxSmbVersionClientSupported");

            SupportedEncryptionAlgorithmList = ParsePropertyToList <EncryptionAlgorithm>("SupportedEncryptionAlgorithms");

            SupportedCompressionAlgorithmList = ParsePropertyToList <CompressionAlgorithm>("SupportedCompressionAlgorithms");

            SendSignedRequest = Boolean.Parse(GetProperty("SendSignedRequest"));

            if (!SendSignedRequest && MaxSmbVersionSupported == DialectRevision.Smb311)
            {
                Site.Assume.Fail("The config \"SendSignedRequest\" should not be false if \"MaxSmbVersionSupported\" is \"Smb311\".");
            }
        }
Example #10
0
        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 static void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ClientSupportsEncryptionType clientSupportsEncryptionType)
        {
            Condition.IsTrue(state == ModelState.Initialized);
            Condition.IsNull(request);

            negotiateDialect = ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported, config.MaxSmbVersionSupported);

            Connection_ClientCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION = (clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption) ? true : false;

            if (ModelUtility.IsSmb3xFamily(negotiateDialect) && clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption)
            {
                ModelHelper.Log(LogType.Requirement,
                                "3.3.5.4: The Capabilities field MUST be set to a combination of zero or more of the following bit values, as specified in section 2.2.4:");
                ModelHelper.Log(LogType.Requirement,
                                "\tSMB2_GLOBAL_CAP_ENCRYPTION if Connection.Dialect belongs to the SMB 3.x dialect family, the server supports encryption, " +
                                "and SMB2_GLOBAL_CAP_ENCRYPTION is set in the Capabilities field of the request.");

                // Encrpytion Model only applies to server that supports encryption.
                ModelHelper.Log(LogType.TestInfo,
                                "Connection.Dialect is {0}, the server supports encryption and SMB2_GLOBAL_CAP_ENCRYPTION is set. " +
                                "So SMB2_GLOBAL_CAP_ENCRYPTION bit is set in Capabilities field.", negotiateDialect);
                Connection_ServerCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION = true;
            }

            state = ModelState.Connected;
        }
Example #12
0
        public static void SetupConnection()
        {
            Condition.IsTrue(State == ModelState.Initialized);

            Request = null;
            ModelHelper.Log(
                LogType.Requirement,
                "3.3.5.1: Connection.CommandSequenceWindow is set to a sequence window, as specified in section 3.3.1.1, with a starting receive sequence of 0 and a window size of 1");

            MessageId = 0;

            ModelHelper.Log(
                LogType.TestInfo,
                "Connection.CommandSequenceWindow to receive sequence of 0.");

            ModelHelper.Log(
                LogType.Requirement,
                "Connection.NegotiateDialect is set to 0xFFFF");

            NegotiateDialect = DialectRevision.Smb2Unknown;

            ModelHelper.Log(
                LogType.TestInfo,
                "Connection.NegotiateDialect is set to {0}", NegotiateDialect);

            State = ModelState.Connected;
        }
        public void BVT_Negotiate_SMB311_Preauthentication_Encryption_GCM()
        {
            DialectRevision clientMaxDialectSupported = DialectRevision.Smb311;

            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
            EncryptionAlgorithm[]    encryptionAlgs  = new EncryptionAlgorithm[] {
                EncryptionAlgorithm.ENCRYPTION_AES128_GCM,
                EncryptionAlgorithm.ENCRYPTION_AES128_CCM
            };

            if (TestConfig.MaxSmbVersionSupported < DialectRevision.Smb311)
            {
                BaseTestSite.Assert.Inconclusive("Stop to run this test case because the configured server max dialect is lower than 3.11.");
            }

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Send Negotiate request with dialect SMB 3.11, SMB2_PREAUTH_INTEGRITY_CAPABILITIES context and " +
                "SMB2_ENCRYPTION_CAPABILITIES context with AES-128-GCM preferred.");
            NegotiateWithNegotiateContexts(
                clientMaxDialectSupported,
                preauthHashAlgs,
                encryptionAlgs,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                CheckNegotiateResponse(header, response, clientMaxDialectSupported, encryptionAlgs);
            }
                );
        }
Example #14
0
 public ModelReplayChannel(DialectRevision Connection_NegotiateDialect,
                           ReplayModelShareType Connection_Session_TreeConnect_Share_IsCA,
                           bool Connection_ClientCapabilities_SupportPersistent)
 {
     this.Connection_NegotiateDialect = Connection_NegotiateDialect;
     this.Connection_Session_TreeConnect_Share_IsCA       = Connection_Session_TreeConnect_Share_IsCA;
     this.Connection_ClientCapabilities_SupportPersistent = Connection_ClientCapabilities_SupportPersistent;
 }
Example #15
0
 public ModelConnection(DialectRevision dialect)
 {
     this.ConnectionState       = ModelState.Initialized;
     this.NegotiateDialect      = dialect;
     this.Session               = null;
     this.Request               = null;
     this.ConstrainedConnection = false;
 }
        public static void PrepareOpen(ModelDialectRevision clientMaxDialect, DurableHandle durableHandle)
        {
            Condition.IsTrue(State == ModelState.Initialized);

            Connection_Dialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, Config.MaxSmbVersionSupported);

            State = ModelState.Connected;
            Open  = new ModelOpen(durableHandle == DurableHandle.DurableHandle? true : false);
        }
 /// <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);
        }
 public void CheckDialect(DialectRevision dialect)
 {
     if (MaxSmbVersionSupported < dialect)
     {
         Site.Assert.Inconclusive("Test case is applicable in servers that implement dialect {0}.", dialect);
     }
     if (MaxSmbVersionClientSupported < dialect)
     {
         Site.Assert.Inconclusive("Test case is applicable when the ptf property value of MaxSmbVersionClientSupported is larger than or equal to {0}.", dialect);
     }
 }
        public static void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ClientSupportDirectoryLeasingType clientSupportDirectoryLeasingType)
        {
            Condition.IsTrue(state == ModelState.Initialized);

            // Current leasing only supports to test leasing on the file. So limit the exploration.
            Condition.IsTrue(clientSupportDirectoryLeasingType == ClientSupportDirectoryLeasingType.ClientNotSupportDirectoryLeasing);

            request          = null;
            negotiateDialect = DialectRevision.Smb2Unknown;
            smb2Lease        = null;

            negotiateDialect = ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported, config.MaxSmbVersionSupported);

            state = ModelState.Connected;
        }
Example #21
0
        private static void ComNegotiateHandleSmb2002InResponse(DialectRevision dialectRevision)
        {
            ModelHelper.Log(
                LogType.Requirement,
                "3.3.5.3.2: DialectRevision MUST be set to 0x0202.<218>");
            //<218> Section 3.3.5.3.2: A Windows Vista RTM–based server sets DialectRevision to 6

            Condition.IsTrue(dialectRevision == DialectRevision.Smb2002);

            ModelHelper.Log(
                LogType.Requirement,
                "3.3.5.3.2: Connection.Dialect MUST be set to \"2.002\", Connection.NegotiateDialect MUST be set to 0x0202, and the response is sent to the client");

            NegotiateDialect = DialectRevision.Smb2002;
        }
Example #22
0
        public static void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ModelShareFlag shareFlag, ModelShareType shareType)
        {
            Condition.IsTrue(State == ModelState.Initialized);

            Open               = null;
            Request            = null;
            Connection_Dialect = DialectRevision.Smb2Unknown;

            Connection_Dialect = ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported, Config.MaxSmbVersionSupported);

            Share_ForceLevel2Oplock = shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK;
            Share_Type_Include_STYPE_CLUSTER_SOFS = shareType == ModelShareType.STYPE_CLUSTER_SOFS;

            State = ModelState.Connected;
        }
        private bool CheckSMBDReadWriteRDMAV1Invalidate()
        {
            var dialectSupportingInvalidate = new DialectRevision[] { DialectRevision.Smb302, DialectRevision.Smb311 };

            var dialects = dialectSupportingInvalidate.Intersect(DetectionInfo.SupportedSmbDialects);

            if (dialects.Count() == 0)
            {
                return(false);
            }

            bool result = CheckSMBDReadWrite(DetectionInfo.SupportedSmbDialects, Channel_Values.CHANNEL_RDMA_V1_INVALIDATE);

            return(result);
        }
        /// <summary>
        /// Establish SMB2 connection over RDMA and open file
        /// 1. Connect to server over RDMA
        /// 2. SMBD Negotiation over RDMA
        /// 3. Establish SMB2 session and open file with specific dialect
        /// </summary>
        /// <param name="fileName">File name to open</param>
        /// <param name="negotiatedDialect">Optional to set the SMB2 dialect used for SMB2 connection</param>
        protected virtual void EstablishConnectionAndOpenFile(string fileName, DialectRevision negotiatedDialect = DialectRevision.Smb30)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Establish SMB2 connection over RDMA and open file " + fileName);

            // Connect to server over RDMA
            NtStatus status = smbdAdapter.ConnectToServerOverRDMA();

            BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMBD connection is {0}", status);

            // SMBD Negotiate
            status = smbdAdapter.SmbdNegotiate();
            BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMBD negotiate is {0}", status);

            status = smbdAdapter.Smb2EstablishSessionAndOpenFile(fileName, negotiatedDialect);
            BaseTestSite.Assert.AreEqual <NtStatus>(NtStatus.STATUS_SUCCESS, status, "Status of SMB2 establish session and open file is {0}", status);
        }
Example #25
0
        public static void ReadConfigReturn(EncryptionConfig c)
        {
            Condition.IsTrue(state == ModelState.Uninitialized);
            Condition.IsNotNull(c);

            negotiateDialect = DialectRevision.Smb2Unknown;
            // Force SE to expand Config.MaxSmbVersionServerSupported
            Condition.IsTrue(c.MaxSmbVersionSupported == ModelDialectRevision.Smb2002 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb21 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb30 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb302);
            config = c;

            request = null;
            state   = ModelState.Initialized;
        }
        public static void ReadConfigReturn(CreditMgmtConfig c)
        {
            Condition.IsTrue(state == ModelState.Uninitialized);
            Condition.IsNotNull(c);

            Condition.IsTrue(
                c.MaxSmbVersionSupported == ModelDialectRevision.Smb2002 ||
                c.MaxSmbVersionSupported == ModelDialectRevision.Smb21 ||
                c.MaxSmbVersionSupported == ModelDialectRevision.Smb30 ||
                c.MaxSmbVersionSupported == ModelDialectRevision.Smb302);

            negotiateDialect   = DialectRevision.Smb2Unknown;
            config             = c;
            request            = null;
            state              = ModelState.Initialized;
            acceptingCondition = false;
        }
        public static void ReadConfigReturn(SigningConfig c)
        {
            Condition.IsTrue(State == ModelState.Uninitialized);
            Condition.IsNotNull(c);

            NegotiateDialect = DialectRevision.Smb2Unknown;

            Condition.IsTrue(c.MaxSmbVersionSupported == ModelDialectRevision.Smb2002 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb21 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb30 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb302);
            Config = c;

            Request = null;

            State = ModelState.Initialized;
        }
        /// <summary>
        /// Convert dialect from DialectRevision to ModelDialectRevision.
        /// </summary>
        /// <param name="dialect">DialectRevision</param>
        /// <returns>ModelDialectRevision</returns>
        public static ModelDialectRevision GetModelDialectRevision(DialectRevision dialect)
        {
            ModelDialectRevision revision = (ModelDialectRevision)(uint)dialect;

            if (Enum.IsDefined(typeof(ModelDialectRevision), revision))
            {
                return revision;
            }
            else if (dialect > DialectRevision.Smb302 && dialect != DialectRevision.Smb2Unknown)
            {
                return ModelDialectRevision.Smb302; // Model cases only test Dialect lower than 3.11
            }
            else
            {
                throw new ArgumentException("Unexpected dialect");
            }
        }
        /// <summary>
        /// Convert dialect from DialectRevision to ModelDialectRevision.
        /// </summary>
        /// <param name="dialect">DialectRevision</param>
        /// <returns>ModelDialectRevision</returns>
        public static ModelDialectRevision GetModelDialectRevision(DialectRevision dialect)
        {
            ModelDialectRevision revision = (ModelDialectRevision)(uint)dialect;

            if (Enum.IsDefined(typeof(ModelDialectRevision), revision))
            {
                return(revision);
            }
            else if (dialect > DialectRevision.Smb302 && dialect != DialectRevision.Smb2Unknown)
            {
                return(ModelDialectRevision.Smb302); // Model cases only test Dialect lower than 3.11
            }
            else
            {
                throw new ArgumentException("Unexpected dialect");
            }
        }
Example #30
0
 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));
 }
Example #31
0
 public bool CheckHigherDialect(DialectRevision MaxSupported, DialectRevision ComTarget)
 {
     if (MaxSupported == DialectRevision.Smb2Wildcard || MaxSupported == DialectRevision.Smb2Unknown)
     {
         return(false);
     }
     else
     {
         if (MaxSupported.GetHashCode() < ComTarget.GetHashCode())
         {
             return(false);
         }
         else
         {
             return(true);
         }
     }
 }
        /// <summary>
        /// Establish main channel, which includes NEGOTIATE, SESSION_SETUP and TREE_CONNECT
        /// </summary>
        /// <param name="requestDialect">Dialects in request</param>
        /// <param name="serverIp">Ip address on server side</param>
        /// <param name="clientIp">Ip address on client side</param>
        /// <param name="treeId">Out param for tree Id that connected</param>
        /// <param name="enableEncryptionPerShare">Set true if enable encryption on share, otherwise set false</param>
        private void EstablishMainChannel(
            DialectRevision[] requestDialect,
            IPAddress serverIp,
            IPAddress clientIp,
            out uint treeId,
            bool enableEncryptionPerShare = false)
        {
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Establish main channel to connect share {0} with following steps.", uncSharePath);

            mainChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp);

            #region Negotiate
            Capabilities_Values mainChannelClientCapabilities = 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;
            status = mainChannelClient.Negotiate(
                requestDialect,
                TestConfig.IsSMB1NegotiateEnabled,
                clientGuid: clientGuid,
                capabilityValue: mainChannelClientCapabilities,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                           Smb2Status.STATUS_SUCCESS,
                           header.Status,
                           "CREATE should succeed.");

                    TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
                    TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response);
                }
                );

            #endregion

            #region SESSION_SETUP
            status = mainChannelClient.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Global encryption disabled");
            #endregion

            #region Retrieve 2nd IP on server for alternative channel if there is
            #region TREE_CONNECT to IPC$
            string ipcPath = Smb2Utility.GetIPCPath(TestConfig.SutComputerName);
            status = mainChannelClient.TreeConnect(ipcPath, out treeId);
            #endregion

            if (TestConfig.UnderlyingTransport == Smb2TransportType.Tcp)
            {
                #region IOCTL FSCTL_QUERY_NETWORK_INTERFACE_INFO
                NETWORK_INTERFACE_INFO_Response[] networkInfoResponses;
                string interfaceAddress;
                bool secondAddressQueried = false;
                status = mainChannelClient.QueryNetworkInterfaceInfo(treeId, out networkInfoResponses);

                foreach (NETWORK_INTERFACE_INFO_Response netInfoResp in networkInfoResponses)
                {
                    interfaceAddress = netInfoResp.AddressStorage.Address;
                    if (interfaceAddress != null)
                    {
                        BaseTestSite.Log.Add(
                            LogEntryKind.Debug,
                            "Get NETWORK_INTERFACE_INFO: " + interfaceAddress);
                        if (interfaceAddress == serverIps[1].ToString())
                        {
                            secondAddressQueried = true;
                            BaseTestSite.Log.Add(
                                LogEntryKind.Debug,
                                "Address queried by IOCTL request with FSCTL_QUERY_NETWORK_INTERFACE_INFO matches server second address {0}", serverIps[1].ToString());
                            break;
                        }
                    }
                }
                BaseTestSite.Assert.IsTrue(
                    secondAddressQueried,
                    "Second address {0} should be queried by IOCTL request with FSCTL_QUERY_NETWORK_INTERFACE_INFO", serverIps[1].ToString());
                #endregion
            }
            #endregion

            #region TREE_CONNECT to share
            status = mainChannelClient.TreeConnect(
                uncSharePath,
                out treeId,
                (Packet_Header header, TREE_CONNECT_Response response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "TreeConnect should succeed.");

                    if (enableEncryptionPerShare)
                    {
                        BaseTestSite.Assert.AreEqual(
                            ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA,
                            ShareFlags_Values.SHAREFLAG_ENCRYPT_DATA & response.ShareFlags,
                            "Server should set SMB2_SHAREFLAG_ENCRYPT_DATA for ShareFlags field in TREE_CONNECT response");
                    }
                });

            mainChannelClient.SetTreeEncryption(treeId, enableEncryptionPerShare);
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Per share encryption for TreeId=0x{0:x} : {1}", treeId, enableEncryptionPerShare);
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Finish establishing main channel to connect share {0}", uncSharePath);
        }
        private void AppInstanceVersionTest(
            ulong? firstClientAppInstanceVersionHigh,
            ulong? firstClientAppInstanceVersionLow,
            DialectRevision firstClientDialect,
            ulong? secondClientAppInstanceVersionHigh,
            ulong? secondClientAppInstanceVersionLow,
            DialectRevision secondClientDialect,
            uint expectedReopenStatus,
            uint expectedInitialOpenStatusAfterReopen,
            bool logoff = true
            )
        {
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            #region Client1 connects to Server
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 connects to the file server by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT");
            uint treeIdForInitialOpen;
            FILEID fileIdForInitialOpen;
            Guid appInstanceId = Guid.NewGuid();
            SendCreateRequestWithSpecificAppInstanceversion(
                clientForInitialOpen,
                appInstanceId,
                firstClientAppInstanceVersionHigh,
                firstClientAppInstanceVersionLow,
                firstClientDialect,
                Smb2Status.STATUS_SUCCESS,
                out treeIdForInitialOpen,
                out fileIdForInitialOpen
                );

            #endregion

            #region Client2 connects to Server
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client2 connects to file server by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT with dialect {0}.", secondClientDialect);
            uint treeIdForReOpen;
            FILEID fileIdForReOpen;
            SendCreateRequestWithSpecificAppInstanceversion(
                clientForReOpen,
                appInstanceId,
                secondClientAppInstanceVersionHigh,
                secondClientAppInstanceVersionLow,
                secondClientDialect,
                expectedReopenStatus,
                out treeIdForReOpen,
                out fileIdForReOpen
                );
            #endregion

            #region Client1 reconnects to Server
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 sends another WRITE request.");
            clientForInitialOpen.Write(
                treeIdForInitialOpen,
                fileIdForInitialOpen,
                content,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        expectedInitialOpenStatusAfterReopen,
                        header.Status,
                        (expectedInitialOpenStatusAfterReopen == Smb2Status.STATUS_SUCCESS ?
                        "The initial open is not closed. Write should succeed. Actually server returns with {0}."
                        : "The initial open is closed. Write should not succeed. Actually server returns with {0}."),
                         Smb2Status.GetStatusCode(header.Status));
                });
            #endregion

            #region Disconnect Client1 or Client2 to Server according to the expectedReopenStatus and expectedInitialOpenStatusAfterReopen
            if (expectedReopenStatus == Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client2 by sending CLOSE requests.");
                clientForReOpen.Close(treeIdForReOpen, fileIdForReOpen);
            }

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client2 by sending TREE_DISCONNECT request.");
            clientForReOpen.TreeDisconnect(treeIdForReOpen);

            if (logoff)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client1 by sending the following requests: LOG_OFF; DISCONNECT");
                Logoff(clientForReOpen);
            }

            if (expectedInitialOpenStatusAfterReopen == Smb2Status.STATUS_SUCCESS)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client2 by sending CLOSE requests.");
                clientForInitialOpen.Close(treeIdForInitialOpen, fileIdForInitialOpen);
            }

            BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client2 by sending TREE_DISCONNECT request.");
            clientForInitialOpen.TreeDisconnect(treeIdForInitialOpen);

            if (logoff)
            {
                BaseTestSite.Log.Add(LogEntryKind.Debug, "Tear down the client2 by sending the following requests: LOG_OFF; DISCONNECT");
                Logoff(clientForInitialOpen);
            }
            #endregion
        }
 public bool CheckHigherDialect(DialectRevision MaxSupported, DialectRevision ComTarget)
 {
     if (MaxSupported == DialectRevision.Smb2Wildcard || MaxSupported == DialectRevision.Smb2Unknown)
         return false;
     else
     {
         if (MaxSupported.GetHashCode() < ComTarget.GetHashCode())
             return false;
         else
             return true;
     }
 }
 public ModelReplayChannel(DialectRevision Connection_NegotiateDialect)
 {
     this.Connection_NegotiateDialect = Connection_NegotiateDialect;
 }
        /// <summary>
        /// Common method used to connect to target server, including the following message sequences:
        /// 1. Negotiate
        /// 2. Session Setup
        /// 3. Tree Connect
        /// </summary>
        /// <param name="smb2Dialect"></param>
        /// <param name="client"></param>
        /// <param name="clientGuid"></param>
        /// <param name="account"></param>
        /// <param name="connectShareType"></param>
        /// <param name="treeId"></param>
        /// <param name="clientBeforeDisconnection"></param>
        protected virtual void Connect(DialectRevision smb2Dialect, Smb2FunctionalClient client, Guid clientGuid, AccountCredential account, ConnectShareType connectShareType, out uint treeId, Smb2FunctionalClient clientBeforeDisconnection)
        {
            DialectRevision[] requestDialect = Smb2Utility.GetDialects(smb2Dialect);
            Capabilities_Values clientCapabilities = Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_PERSISTENT_HANDLES;
            SecurityMode_Values clientSecurityMode = SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED;

            IPAddress targetIPAddress = (connectShareType == ConnectShareType.CAShare) ? testConfig.CAShareServerIP : testConfig.SutIPAddress;
            string targetServer = (connectShareType == ConnectShareType.CAShare) ? testConfig.CAShareServerName : testConfig.SutComputerName;

            client.ConnectToServer(TestConfig.UnderlyingTransport, targetServer, targetIPAddress);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends NEGOTIATE request.", clientGuid);
            client.Negotiate(
                requestDialect,
                TestConfig.IsSMB1NegotiateEnabled,
                clientSecurityMode,
                clientCapabilities,
                clientGuid);

            if (null != clientBeforeDisconnection)
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends SESSION_SETUP request to reconnect to the previous session.", clientGuid);
                client.ReconnectSessionSetup(
                    clientBeforeDisconnection,
                    testConfig.DefaultSecurityPackage,
                    targetServer,
                    account,
                    testConfig.UseServerGssToken);
            }
            else
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends SESSION_SETUP request.", clientGuid);
                client.SessionSetup(
                    testConfig.DefaultSecurityPackage,
                    targetServer,
                    account,
                    testConfig.UseServerGssToken);
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The client with clientGuid {0} sends TREE_CONNECT request.", clientGuid);
            client.TreeConnect(
                durableHandleUncSharePath,
                out treeId,
                checker: (header, response) =>
                {
                    BaseTestSite.Log.Add(
                        LogEntryKind.Debug,
                        "Capabilities in TREE_CONNECT response: {0}", response.Capabilities);

                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should be successful", header.Command);

                    if (connectShareType == ConnectShareType.CAShare)
                    {
                        BaseTestSite.Assert.AreEqual(
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY,
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY & response.Capabilities,
                            "The share should have SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY capability");
                    }

                    if (connectShareType == ConnectShareType.BasicShare)
                    {
                        BaseTestSite.Assert.AreNotEqual(
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY,
                            Share_Capabilities_Values.SHARE_CAP_CONTINUOUS_AVAILABILITY & response.Capabilities,
                            "The share should not have SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY capability");
                    }
                });
        }
        private void InternalConnectShare(string domain, string userName, string password, string shareName, TimeSpan timeout,
            SecurityPackageType securityPackage, bool useServerToken)
        {
            uint status;
            DialectRevision selectedDialect;
            Packet_Header header;
            byte[] serverGssToken;

            Array allDialects = Enum.GetValues(typeof(DialectRevision));
            DialectRevision[] validDialects = new DialectRevision[allDialects.Length - 2];
            int index = 0;
            foreach (var dialect in allDialects)
            {
                if ((DialectRevision)dialect != DialectRevision.Smb2Unknown && (DialectRevision)dialect != DialectRevision.Smb2Wildcard)
                {
                    validDialects[index++] = (DialectRevision)dialect;
                }
            }

            PreauthIntegrityHashID[] preauthIntegrityHashIDArray = null;
            EncryptionAlgorithm[] encryptionAlgorithmArray = null;
            if (validDialects.Contains(DialectRevision.Smb311))
            {
                preauthIntegrityHashIDArray = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
                encryptionAlgorithmArray = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM };
            }

            // Negotiate:
            NEGOTIATE_Response negotiateResponse;
            CheckStatusCode(
                client.Negotiate(
                    1,
                    1,
                    Packet_Header_Flags_Values.NONE,
                    messageId++,
                    // Will negotiate highest dialect server supports
                    validDialects,
                    SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                    Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_LARGE_MTU,
                    clientGuid,
                    out selectedDialect,
                    out serverGssToken,
                    out header,
                    out negotiateResponse,
                    preauthHashAlgs: preauthIntegrityHashIDArray,
                    encryptionAlgs: encryptionAlgorithmArray));

            negotiatedDialect = selectedDialect;

            serverCapabilities = (Capabilities_Values)negotiateResponse.Capabilities;

            // 3.2.5.2: If the SecurityMode field in the SMB2 header of the response has the SMB2_NEGOTIATE_SIGNING_REQUIRED bit set,
            // the client MUST set Connection.RequireSigning to TRUE.
            // 3.2.5.3.1: If the global setting RequireMessageSigning is set to TRUE or
            // Connection.RequireSigning is set to TRUE then Session.SigningRequired MUST be set to TRUE
            bool session_SigningRequired = negotiateResponse.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED);
            if (session_SigningRequired)
            {
                // 3.2.4.1.1: If the client signs the request, it MUST set the SMB2_FLAGS_SIGNED bit in the Flags field of the SMB2 header.
                headerFlags |= Packet_Header_Flags_Values.FLAGS_SIGNED;
            }

            // Session setup:
            SESSION_SETUP_Response sessionSetupResponse;

            SspiClientSecurityContext sspiClientGss =
                new SspiClientSecurityContext(
                    securityPackage,
                    new AccountCredential(domain, userName, password),
                    Smb2Utility.GetCifsServicePrincipalName(serverPrincipleName),
                    ClientSecurityContextAttribute.None,
                    SecurityTargetDataRepresentation.SecurityNativeDrep);

            if (securityPackage == SecurityPackageType.Negotiate)
                sspiClientGss.Initialize(serverGssToken);
            else
                sspiClientGss.Initialize(null);

            do
            {
                status = client.SessionSetup(
                    1,
                    1,
                    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 serverGssToken,
                    out header,
                    out sessionSetupResponse);

                CheckStatusCode(status);

                if ((status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED || status == Smb2Status.STATUS_SUCCESS) &&
                    serverGssToken != null && serverGssToken.Length > 0)
                {
                    sspiClientGss.Initialize(serverGssToken);
                }
            } while (status == Smb2Status.STATUS_MORE_PROCESSING_REQUIRED);

            // 3.2.4.1.1 If Connection.Dialect is "3.1.1" and the message being sent is a TREE_CONNECT Request and the session identified by SessionId has Session.EncryptData equal to FALSE
            bool treeconnect_SigningRequired = session_SigningRequired || (selectedDialect >= DialectRevision.Smb311);
            client.GenerateCryptoKeys(sessionId, sspiClientGss.SessionKey, treeconnect_SigningRequired, false);

            this.sessionId = header.SessionId;

            // Session Key will be used in the MS-LSA SDK, see LsaClient.cs Line 179 SessionKey
            // Insert the session key to the global context
            Smb2ClientSession smb2CliSession = new Smb2ClientSession();
            smb2CliSession.SessionKey = client.GetSessionKeyForAuthenticatedContext(sessionId);

            Smb2ClientConnection smb2CliConn = new Smb2ClientConnection();
            smb2CliConn.SessionTable = new Dictionary<ulong, Smb2ClientSession>();
            smb2CliConn.SessionTable.Add(sessionId, smb2CliSession);

            context.ConnectionTable = new Dictionary<string, Smb2ClientConnection>();
            context.ConnectionTable.Add("Smb2ClientConnection", smb2CliConn);

            // Tree connect:
            TREE_CONNECT_Response treeConnectResponse;

            status = client.TreeConnect(
                    1,
                    1,
                    treeconnect_SigningRequired? headerFlags| Packet_Header_Flags_Values.FLAGS_SIGNED:headerFlags,
                    messageId++,
                    sessionId,
                    "\\\\" + serverPrincipleName + "\\" + shareName,
                    out treeId,
                    out header,
                    out treeConnectResponse);

            this.treeId = header.TreeId;

            // For the messages followed by TREE_CONNECT, set them as signed/not signed following the normal proces
            client.EnableSessionSigningAndEncryption(sessionId, session_SigningRequired, false);
        }
        public static void PrepareOpen(
            ModelDialectRevision clientMaxDialect,
            PersistentBitType persistentBit,
            CAShareType connectToCAShare,
            ModelHandleType modelHandleType,
            OplockLeaseType oplockLeaseType)
        {
            Condition.IsNull(Request);
            Condition.IsNull(Open);

            // CAShare, Persistent Handle , Durable Handle v2 and Lease V2 are only applied for SMB 3.x family.
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), connectToCAShare == CAShareType.NonCAShare);
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), persistentBit == PersistentBitType.PersistentBitNotSet);
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), modelHandleType == ModelHandleType.DurableHandleV1);

            // Case will go to non-accpeting state if clientMaxDialect > Config.MaxSmbVersionSupported.
            NegotiateDialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, Config.MaxSmbVersionSupported);

            // Restrict the params combination
            Combination.Pairwise(clientMaxDialect, persistentBit, connectToCAShare, modelHandleType, oplockLeaseType);

            Share_IsCA = (connectToCAShare == CAShareType.CAShare);

            Open = new HandleModelOpen();
            Open.IsConnectionExisted = true;
            Open.IsSessionExisted = true;

            if (oplockLeaseType == OplockLeaseType.LeaseV1)
            {
                Open.IsLeaseExisted = true;
                Open.LeaseVersion = 1;
            }
            else if (oplockLeaseType == OplockLeaseType.LeaseV2)
            {
                Open.IsLeaseExisted = true;
                Open.LeaseVersion = 2;
            }
            else if (oplockLeaseType == OplockLeaseType.BatchOplock)
            {
                Open.IsBatchOplockExisted = true;
            }

            if (modelHandleType == ModelHandleType.DurableHandleV1)
            {
                if (!Open.IsBatchOplockExisted && !Open.IsLeaseExisted)
                {
                    ModelHelper.Log(LogType.Requirement,
                        "3.3.5.9.6: If the RequestedOplockLevel field in the create request is not set to SMB2_OPLOCK_LEVEL_BATCH and " +
                        "the create request does not include an SMB2_CREATE_REQUEST_LEASE create context with a LeaseState field that " +
                        "includes the SMB2_LEASE_HANDLE_CACHING bit value, " +
                        "the server MUST ignore this create context and skip this section.");
                    ModelHelper.Log(LogType.TestInfo, "This section is skipped.");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    return;
                }

                ModelHelper.Log(LogType.Requirement, "3.3.5.9.6: In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE. ");
                ModelHelper.Log(LogType.TestInfo, "Open.IsDurable is set to TRUE.");
                Open.IsDurable = true;
            }
            else if (modelHandleType == ModelHandleType.DurableHandleV2 || modelHandleType == ModelHandleType.PersistentHandle)
            {
                ModelHelper.Log(LogType.Requirement, "3.3.5.9.10: This section applies only to servers that implement the SMB 3.x dialect family. ");
                if (!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported))
                {
                    ModelHelper.Log(LogType.TestInfo, "The server implements the dialect {0}.", Config.MaxSmbVersionSupported);
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    return;
                }

                if (modelHandleType != ModelHandleType.PersistentHandle && !Open.IsBatchOplockExisted && !Open.IsLeaseExisted)
                {
                    ModelHelper.Log(LogType.Requirement,
                        "If the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of this create context, " +
                        "if RequestedOplockLevel in the create request is not set to SMB2_OPLOCK_LEVEL_BATCH, " +
                        "and if the create request does not include a SMB2_CREATE_REQUEST_LEASE or " +
                        "SMB2_CREATE_REQUEST_LEASE_V2 create context with a LeaseState field that includes SMB2_LEASE_HANDLE_CACHING, " +
                        "the server MUST ignore this create context and skip this section.");
                    ModelHelper.Log(LogType.TestInfo, "This section is skipped.");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                    return;
                }

                if (ModelUtility.IsSmb3xFamily(NegotiateDialect)
                    && persistentBit == PersistentBitType.PersistentBitSet
                    && Config.IsPersistentHandleSupported)
                {
                    ModelHelper.Log(LogType.Requirement,
                        "3.3.5.4: The Capabilities field MUST be set to a combination of zero or more of the following bit values, as specified in section 2.2.4:");
                    ModelHelper.Log(LogType.Requirement,
                        "\tSMB2_GLOBAL_CAP_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " +
                        "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles.");
                    ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. So SMB2_DHANDLE_FLAG_PERSISTENT bit is set in Connection.ServerCapabilities.");
                    ServerCapabilities_PersistentBitSet = true;
                }

                if (modelHandleType == ModelHandleType.PersistentHandle
                    && !(Share_IsCA && ServerCapabilities_PersistentBitSet))
                {
                    // TDI: if client asks for a persistent handle to a non CA share or
                    // Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_PERSISTENT_HANDLES
                    // The persistent handle is not granted.
                    ModelHelper.Log(
                        LogType.TestInfo,
                        "Share is not a CA share or Connection.ServerCapabilities does not include SMB2_GLOBAL_CAP_PERSISTENT_HANDLES.");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                    return;
                }

                ModelHelper.Log(LogType.Requirement, "In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE. ");
                ModelHelper.Log(LogType.TestInfo, "Open.IsDurable is set to TRUE.");
                Open.IsDurable = true;

                if (modelHandleType == ModelHandleType.PersistentHandle && Share_IsCA && ServerCapabilities_PersistentBitSet)
                {
                    ModelHelper.Log(LogType.Requirement,
                        "3.3.5.9.10: If the SMB2_DHANDLE_FLAG_PERSISTENT bit is set in the Flags field of the request, " +
                        "TreeConnect.Share.IsCA is TRUE, " +
                        "and Connection.ServerCapabilities includes SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, " +
                        "the server MUST set Open.IsPersistent to TRUE.");
                    ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. So Open.IsPersistent is set to TRUE.");
                    Open.IsPersistent = true;
                }
            }
        }
        public static void OpenRequest(
            ModelDialectRevision clientMaxDialect,
            PersistentBitType persistentBit,
            CAShareType connectToCAShare,
            OplockLeaseType oplockLeaseType,
            DurableV1RequestContext durableV1RequestContext,
            DurableV2RequestContext durableV2RequestContext,
            DurableV1ReconnectContext durableV1ReconnectContext,
            DurableV2ReconnectContext durableV2ReconnectContext)
        {
            Condition.IsNull(Request);
            Condition.IsNull(Open);

            // CAShare, Persistent Handle and Durable Handle V2 are only applied for SMB 3.x family.
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), connectToCAShare == CAShareType.NonCAShare);
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), persistentBit == PersistentBitType.PersistentBitNotSet);
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), durableV2RequestContext == DurableV2RequestContext.DurableV2RequestContextNotExist);
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), durableV2ReconnectContext == DurableV2ReconnectContext.DurableV2ReconnectContextNotExist);
            Condition.IfThen(!ModelUtility.IsSmb3xFamily(Config.MaxSmbVersionSupported), oplockLeaseType != OplockLeaseType.LeaseV2);

            // If leasing is not supported, do not test LeaseV1 or LeaseV2.
            Condition.IfThen(!Config.IsLeasingSupported, oplockLeaseType != OplockLeaseType.LeaseV1 && oplockLeaseType != OplockLeaseType.LeaseV2);

            Combination.Pairwise(
                clientMaxDialect,
                persistentBit,
                connectToCAShare,
                oplockLeaseType,
                durableV1RequestContext,
                durableV2RequestContext,
                durableV1ReconnectContext,
                durableV2ReconnectContext);

            NegotiateDialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, Config.MaxSmbVersionSupported);

            Share_IsCA = (connectToCAShare == CAShareType.CAShare);

            if (ModelUtility.IsSmb3xFamily(NegotiateDialect)
                && persistentBit == PersistentBitType.PersistentBitSet
                && Config.IsPersistentHandleSupported)
            {
                ModelHelper.Log(LogType.Requirement,
                    "3.3.5.4: The Capabilities field MUST be set to a combination of zero or more of the following bit values, as specified in section 2.2.4:");
                ModelHelper.Log(LogType.Requirement,
                    "\tSMB2_GLOBAL_CAP_PERSISTENT_HANDLES if Connection.Dialect belongs to the SMB 3.x dialect family, " +
                    "SMB2_GLOBAL_CAP_PERSISTENT_HANDLES is set in the Capabilities field of the request, and the server supports persistent handles.");
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. So SMB2_DHANDLE_FLAG_PERSISTENT bit is set in Connection.ServerCapabilities.");
                ServerCapabilities_PersistentBitSet = true;
            }

            Request = new ModelOpenFileRequest(
                durableV1RequestContext,
                durableV2RequestContext,
                durableV1ReconnectContext,
                durableV2ReconnectContext,
                oplockLeaseType,
                false,
                false,
                false);
        }
        public static void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ClientSupportsEncryptionType clientSupportsEncryptionType)
        {
            Condition.IsTrue(state == ModelState.Initialized);
            Condition.IsNull(request);

            negotiateDialect = ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported, config.MaxSmbVersionSupported);

            Connection_ClientCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION = (clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption) ? true : false;

            if (ModelUtility.IsSmb3xFamily(negotiateDialect) && clientSupportsEncryptionType == ClientSupportsEncryptionType.ClientSupportsEncryption)
            {
                ModelHelper.Log(LogType.Requirement,
                    "3.3.5.4: The Capabilities field MUST be set to a combination of zero or more of the following bit values, as specified in section 2.2.4:");
                ModelHelper.Log(LogType.Requirement,
                    "\tSMB2_GLOBAL_CAP_ENCRYPTION if Connection.Dialect belongs to the SMB 3.x dialect family, the server supports encryption, " +
                    "and SMB2_GLOBAL_CAP_ENCRYPTION is set in the Capabilities field of the request.");

                // Encrpytion Model only applies to server that supports encryption.
                ModelHelper.Log(LogType.TestInfo,
                    "Connection.Dialect is {0}, the server supports encryption and SMB2_GLOBAL_CAP_ENCRYPTION is set. " +
                    "So SMB2_GLOBAL_CAP_ENCRYPTION bit is set in Capabilities field.", negotiateDialect);
                Connection_ServerCapabilities_SMB2_GLOBAL_CAP_ENCRYPTION = true;
            }

            state = ModelState.Connected;
        }
        public static void ReadConfigReturn(EncryptionConfig c)
        {
            Condition.IsTrue(state == ModelState.Uninitialized);
            Condition.IsNotNull(c);

            negotiateDialect = DialectRevision.Smb2Unknown;
            // Force SE to expand Config.MaxSmbVersionServerSupported
            Condition.IsTrue(c.MaxSmbVersionSupported == ModelDialectRevision.Smb2002 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb21 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb30 ||
                             c.MaxSmbVersionSupported == ModelDialectRevision.Smb302);
            config = c;

            request = null;
            state = ModelState.Initialized;
        }
        public DetectResult CheckCreateContexts_HandleV1BatchOplock(string sharename, DialectRevision smb2Dialect, ref DetectionInfo info)
        {
            logWriter.AddLog(LogLevel.Information, "===== Detecting create context HandleV1 with Batch oplock =====");
            using (Smb2Client client = new Smb2Client(new TimeSpan(0, 0, defaultTimeoutInSeconds)))
            {
                ulong messageId;
                ulong sessionId;
                uint treeId;
                ConnectToShare(sharename, info, client, out messageId, out sessionId, out treeId);

                Packet_Header header;

                #region Create
                FILEID fileId;
                Smb2CreateContextResponse[] serverCreateContexts = null;
                string fileName = "DurableHandleV1BatchOplock_" + Guid.NewGuid() + ".txt";
                CREATE_Response createResponse;
                logWriter.AddLog(LogLevel.Information, "Client opens file with a durable handle v1 and batch oplock");
                uint status = client.Create(
                    1,
                    1,
                    info.smb2Info.IsRequireMessageSigning ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE,
                    messageId++,
                    sessionId,
                    treeId,
                    fileName,
                    AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE,
                    ShareAccess_Values.NONE,
                    CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    CreateDisposition_Values.FILE_OPEN_IF,
                    File_Attributes.NONE,
                    ImpersonationLevel_Values.Impersonation,
                    SecurityFlags_Values.NONE,
                    RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                    new Smb2CreateContextRequest[]
                    {
                        new Smb2CreateDurableHandleRequest
                        {
                             DurableRequest = Guid.Empty,
                        },
                    },
                    out fileId,
                    out serverCreateContexts,
                    out header,
                    out createResponse,
                    0);

                if (header.Status != Smb2Status.STATUS_SUCCESS)
                {
                    LogFailedStatus("Create durable handle v1 with batch oplock", header.Status);
                    return DetectResult.UnSupported;
                }

                #endregion

                if (serverCreateContexts != null)
                {
                    foreach (Smb2CreateContextResponse ctx in serverCreateContexts)
                    {
                        if (ctx is Smb2CreateDurableHandleResponse)
                        {
                            logWriter.AddLog(LogLevel.Information, "Create context HandleV1 with Batch oplock is supported");
                            return DetectResult.Supported;
                        }
                    }
                }

                logWriter.AddLog(LogLevel.Information,
                    "The returned Create response doesn't contain handle v1 context. So Create context HandleV1 with Batch oplock is not supported");
                return DetectResult.UnSupported;
            }
        }
        public static void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ModelShareFlag shareFlag, ModelShareType shareType)
        {
            Condition.IsTrue(State == ModelState.Initialized);

            Open = null;
            Request = null;
            Connection_Dialect = DialectRevision.Smb2Unknown;

            Connection_Dialect = ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported, Config.MaxSmbVersionSupported);

            Share_ForceLevel2Oplock = shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK;
            Share_Type_Include_STYPE_CLUSTER_SOFS = shareType == ModelShareType.STYPE_CLUSTER_SOFS;

            State = ModelState.Connected;
        }
        private bool DetectAP(DomainInfo domain, Server ap, KerberosDetector detector)
        {
            logWriter.AddLog(string.Format("===== Detect Application Server in Domain {0} =====", domain.Name), LogLevel.Normal);

            string hostname = ap.FQDN;
            IPAddress ip = IPAddress.Loopback;
            try
            {
                var hostentry = Dns.GetHostEntry(hostname);
                ip = hostentry.AddressList[0];
                ap.IPv4 = ip.ToString();
                string computerName = hostentry.HostName;
                string machineName = computerName.Split('.')[0];
                ap.FQDN = ServerHelper.GetAccountAttribute(machineName, "Computers", "dNSHostName", domain.Name, domain.Admin, domain.AdminPassword);
                ap.IsWindows = detector.FetchPlatformInfo(computerName);
            }
            catch
            {
                logWriter.AddLog("Failed", LogLevel.Normal, false, LogStyle.StepFailed);
                logWriter.AddLineToLog(LogLevel.Advanced);
                return false;
            }

            if (ap.FQDN == null)
            {
                logWriter.AddLog("Failed", LogLevel.Normal, false, LogStyle.StepFailed);
                logWriter.AddLineToLog(LogLevel.Advanced);
                return false;
            }

            string[] tempArray = ap.FQDN.Split('.');
            ap.ComputerName = tempArray[0];

            try
            {
                ap.NetBIOS = ServerHelper.GetAccountAttribute(ap.ComputerName, "Computers", "sAMAccountName", domain.Name, domain.Admin, domain.AdminPassword);//DC01$: NetBIOS name
                ap.DefaultServiceName = "host/" + ap.FQDN.ToLower();
                ap.ServiceSalt = domain.Name.ToUpper() + "host" + ap.FQDN.ToLower();
                ap.smb2Service.SMB2ServiceName = "cifs/" + ap.FQDN.ToLower();
            }
            catch
            {
                logWriter.AddLog("Failed", LogLevel.Normal, false, LogStyle.StepFailed);
                logWriter.AddLineToLog(LogLevel.Advanced);
                return false;
            }

            try
            {
                if (detectionInfo.HasSmbServer)
                {
                    //get smb dialect
                    Smb2Client clientForInitialOpen = new Smb2Client(new TimeSpan(0, 0, 15));
                    byte[] gssToken;
                    Packet_Header header;
                    try
                    {
                        clientForInitialOpen.ConnectOverTCP(ip);

                        NEGOTIATE_Response negotiateResp;
                        DialectRevision connection_Dialect = DialectRevision.Smb2Unknown;
                        DialectRevision[] requestDialect = new DialectRevision[] { DialectRevision.Smb2002, DialectRevision.Smb21, DialectRevision.Smb30, DialectRevision.Smb302 };
                        ulong messageId = 0;

                        uint status = clientForInitialOpen.Negotiate(
                            1,
                            1,
                            Packet_Header_Flags_Values.NONE,
                            messageId++,
                            requestDialect,
                            SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                            Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU,
                            Guid.NewGuid(),
                            out connection_Dialect,
                            out gssToken,
                            out header,
                            out negotiateResp);

                        if (header.Status != Smb2Status.STATUS_SUCCESS)
                        {
                            logWriter.AddLog("Failed", LogLevel.Normal, false, LogStyle.StepFailed);
                            logWriter.AddLineToLog(LogLevel.Advanced);
                            return false;
                        }
                        else
                        {
                            ap.smb2Service.SMB2Dialect = connection_Dialect.ToString();
                        }

                    }
                    catch
                    {
                        logWriter.AddLog("Failed", LogLevel.Normal, false, LogStyle.StepFailed);
                        logWriter.AddLineToLog(LogLevel.Advanced);
                        return false;
                    }

                    //detect smb share

                    string[] shareList = ServerHelper.EnumShares(ap.IPv4, domain.Admin, domain.Name, domain.AdminPassword);
                    if (shareList.Length > 0)
                    {
                        //only get the first one as default value
                        //can ptftool support add more choices?
                        for (int i = 0; i < shareList.Length; i++)
                        {
                            if (shareList[i].Substring(shareList[i].Length - 1, 1) != "$")
                            {
                                ap.smb2Service.DACShare = shareList[i];
                                ap.smb2Service.CBACShare = shareList[i];
                                break;
                            }
                        }

                    }
                    else
                    {
                        ap.smb2Service.DACShare = string.Empty;
                        ap.smb2Service.CBACShare = string.Empty;
                    }
                }
                if (detectionInfo.HasHttpServer)
                {
                    //detect http server
                    ap.httpService.HttpServiceName = "http/" + ap.FQDN.ToLower();

                    try
                    {
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://" + ap.FQDN);
                        request.Credentials = new NetworkCredential(domain.Admin + "@" + domain.Name, domain.AdminPassword);
                        WebResponse response = request.GetResponse();

                        ap.httpService.Uri = response.ResponseUri.OriginalString;
                    }
                    catch
                    {
                        ap.httpService.Uri = string.Empty;
                    }
                }

            }
            catch
            {
                logWriter.AddLog("Failed", LogLevel.Normal, false, LogStyle.StepFailed);
                logWriter.AddLineToLog(LogLevel.Advanced);
                return false;
            }

            logWriter.AddLog("Success", LogLevel.Normal, false, LogStyle.StepPassed);
            logWriter.AddLineToLog(LogLevel.Advanced);
            return true;
        }
        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. ");
            }
        }
        private void NegotiateWithSpecificDialect(DialectRevision clientMaxDialectSupported)
        {
            DialectRevision serverMaxDialectSupported = TestConfig.MaxSmbVersionSupported;

            DialectRevision[] negotiateDialects = Smb2Utility.GetDialects(clientMaxDialectSupported);

            if (clientMaxDialectSupported > TestConfig.MaxSmbVersionClientSupported)
            {
                BaseTestSite.Assert.Inconclusive("Stop to run this test case because the configured MaxSmbVersionClientSupported {0} is lower than {1}.",
                    TestConfig.MaxSmbVersionClientSupported,
                    clientMaxDialectSupported);
            }

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Send Negotiate request with maximum dialect: {0}.", clientMaxDialectSupported);
            client.Negotiate(
                Packet_Header_Flags_Values.NONE,
                negotiateDialects,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    DialectRevision expectedDialect = clientMaxDialectSupported < serverMaxDialectSupported
                        ? clientMaxDialectSupported : serverMaxDialectSupported;

                    BaseTestSite.Log.Add(LogEntryKind.TestStep, "Check negotiate response contains expected dialect.");
                    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);
                });
        }
        private void NegotiateWithNegotiateContexts(
            DialectRevision clientMaxDialectSupported,
            PreauthIntegrityHashID[] preauthHashAlgs,
            EncryptionAlgorithm[] encryptionAlgs = null,
            ResponseChecker<NEGOTIATE_Response> checker = null)
        {
            // ensure clientMaxDialectSupported higher than 3.11
            if (clientMaxDialectSupported < DialectRevision.Smb311) clientMaxDialectSupported = DialectRevision.Smb311;
            DialectRevision[] negotiateDialects = Smb2Utility.GetDialects(clientMaxDialectSupported);

            if (clientMaxDialectSupported > TestConfig.MaxSmbVersionClientSupported)
            {
                BaseTestSite.Assert.Inconclusive("Stop to run this test case because the configured MaxSmbVersionClientSupported {0} is lower than {1}.",
                    TestConfig.MaxSmbVersionClientSupported,
                    clientMaxDialectSupported);
            }

            status = client.NegotiateWithContexts(
                Packet_Header_Flags_Values.NONE,
                negotiateDialects,
                preauthHashAlgs: preauthHashAlgs,
                encryptionAlgs: encryptionAlgs,
                checker: checker);
        }
        /// <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;
        }
        public static void ReadConfigReturn(CreditMgmtConfig c)
        {
            Condition.IsTrue(state == ModelState.Uninitialized);
            Condition.IsNotNull(c);

            Condition.IsTrue(
                c.MaxSmbVersionSupported == ModelDialectRevision.Smb2002
                || c.MaxSmbVersionSupported == ModelDialectRevision.Smb21
                || c.MaxSmbVersionSupported == ModelDialectRevision.Smb30
                || c.MaxSmbVersionSupported == ModelDialectRevision.Smb302);

            negotiateDialect = DialectRevision.Smb2Unknown;
            config = c;
            request = null;
            state = ModelState.Initialized;
            acceptingCondition = false;
        }
 public ModelConnection(DialectRevision dialect)
 {
     this.ConnectionState = ModelState.Initialized;
     this.NegotiateDialect = dialect;
     this.Session = null;
     this.Request = null;
     this.ConstrainedConnection = false;
 }
        public static void SetupConnection(ModelDialectRevision clientMaxDialect)
        {
            Condition.IsTrue(state == ModelState.Initialized);
            Condition.IsNull(request);

            negotiateDialect = ModelHelper.DetermineNegotiateDialect(clientMaxDialect, config.MaxSmbVersionSupported);

            if ((negotiateDialect == DialectRevision.Smb21 || ModelUtility.IsSmb3xFamily(negotiateDialect))
                && config.IsMultiCreditSupportedOnServer)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.4: If the common dialect is SMB 2.1 or 3.x dialect family and the underlying connection is either TCP port 445 or RDMA," +
                    "Connection.SupportsMultiCredit MUST be set to TRUE; otherwise, it MUST be set to FALSE.");
                ModelHelper.Log(
                    LogType.TestInfo,
                    "Common dialect is {0} and server implementation {1} multicredit", negotiateDialect,
                    config.IsMultiCreditSupportedOnServer ? "supports" : "does not support");

                isMultiCreditSupported = true;

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Connection.SupportsMultiCredit is set to TRUE");
            }
            else
            {
                isMultiCreditSupported = false;

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Connection.SupportsMultiCredit is set to FALSE");
            }

            state = ModelState.Connected;
        }
 public ModelReplayChannel(DialectRevision Connection_NegotiateDialect,
     ReplayModelShareType Connection_Session_TreeConnect_Share_IsCA,
     bool Connection_ClientCapabilities_SupportPersistent)
 {
     this.Connection_NegotiateDialect = Connection_NegotiateDialect;
     this.Connection_Session_TreeConnect_Share_IsCA = Connection_Session_TreeConnect_Share_IsCA;
     this.Connection_ClientCapabilities_SupportPersistent = Connection_ClientCapabilities_SupportPersistent;
 }
        /// <summary>
        /// Establish alternative channel, which includes NEGOTIATE, SESSION_SETUP
        /// </summary>
        /// <param name="requestDialect">Dialects in request</param>
        /// <param name="serverIp">Ip address on server side</param>
        /// <param name="clientIp">Ip address on client side</param>
        /// <param name="treeId">Tree id that is used to set encryption</param>
        /// <param name="enableEncryptionPerShare">Set true if enable encryption on share, otherwise set false</param>
        private void EstablishAlternativeChannel(
            DialectRevision[] requestDialect,
            IPAddress serverIp,
            IPAddress clientIp,
            uint treeId,
            bool enableEncryptionPerShare = false)
        {
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Establish alternative channel to connect share {0}", uncSharePath);

            alternativeChannelClient.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, serverIp, clientIp);

            #region Negotiate
            Capabilities_Values alternativeChannelClientCapabilities = 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;
            status = alternativeChannelClient.Negotiate(
                requestDialect,
                TestConfig.IsSMB1NegotiateEnabled,
                clientGuid: clientGuid,
                capabilityValue: alternativeChannelClientCapabilities,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "CREATE should succeed.");

                    TestConfig.CheckNegotiateDialect(DialectRevision.Smb30, response);
                    TestConfig.CheckNegotiateCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL, response);
                }
                );
            #endregion

            #region SESSION_SETUP
            status = alternativeChannelClient.AlternativeChannelSessionSetup(
                        mainChannelClient,
                        TestConfig.DefaultSecurityPackage,
                        TestConfig.SutComputerName,
                        TestConfig.AccountCredential,
                        TestConfig.UseServerGssToken);

            #endregion

            alternativeChannelClient.SetTreeEncryption(treeId, enableEncryptionPerShare);
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Per share encryption for TreeId=0x{0:x} : {1}", treeId, enableEncryptionPerShare);

            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Establish alternative channel to connect share {0}", uncSharePath);
        }
 public Smb2TransportAdapter(DialectRevision[] dialects)
 {
     this.requestDialects = dialects;
 }
        public void SetupConnection(ModelDialectRevision maxSmbVersionClientSupported, ModelShareFlag shareFlag, ModelShareType shareType)
        {
            IPAddress ip;
            if (shareType == ModelShareType.STYPE_CLUSTER_SOFS)
            {
                server = testConfig.ScaleOutFileServerName;
                ip = Dns.GetHostEntry(server).AddressList[0];

                if (shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK)
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.ScaleOutFileServerName, testConfig.ShareWithForceLevel2AndSOFS);
                }
                else
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.ScaleOutFileServerName, testConfig.ShareWithoutForceLevel2WithSOFS);
                }
            }
            else
            {
                server = testConfig.SutComputerName;
                ip = testConfig.SutIPAddress;
                if (shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK)
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.ShareWithForceLevel2WithoutSOFS);
                }
                else
                {
                    uncSharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.ShareWithoutForceLevel2OrSOFS);
                }
            }

            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.Smb2Client.OplockBreakNotificationReceived += new Action<Packet_Header, OPLOCK_BREAK_Notification_Packet>(OnOplockBreakNotificationReceived);

            testClient.ConnectToServer(testConfig.UnderlyingTransport, server, ip, testConfig.ClientNic1IPAddress);

            DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported));

            NEGOTIATE_Response? negotiateResponse = null;
            testClient.Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                checker: (header, response) =>
                    {
                        Site.Assert.AreEqual(
                            Smb2Status.STATUS_SUCCESS,
                            header.Status,
                            "{0} should succeed", header.Command);

                        negotiateResponse = response;
                    });

            negotiatedDialect = negotiateResponse.Value.DialectRevision;

            testClient.SessionSetup(
                testConfig.DefaultSecurityPackage,
                server,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);

            testClient.TreeConnect(
                uncSharePath,
                out treeId,
                checker: (header, response) =>
                {
                    Site.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should succeed", header.Command);

                    Site.Assert.AreEqual(
                        shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK,
                        response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_FORCE_LEVELII_OPLOCK),
                        "SHAREFLAG_FORCE_LEVELII_OPLOCK is{0}expected to be set",
                        shareFlag == ModelShareFlag.SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK ? " " : " not ");

                    if (ModelUtility.IsSmb3xFamily(negotiateResponse.Value.DialectRevision))
                    {
                        Site.Assert.AreEqual(
                            shareType == ModelShareType.STYPE_CLUSTER_SOFS,
                            response.Capabilities.HasFlag(Share_Capabilities_Values.SHARE_CAP_SCALEOUT),
                            "SHARE_CAP_SCALEOUT is{0}expected to be set",
                            shareType == ModelShareType.STYPE_CLUSTER_SOFS ? " " : " not ");
                    }
                });
        }
        /// <summary>
        /// Initialize all fields to the default values.
        /// </summary>
        private void Initialize()
        {
            Flags = testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;
            Dialect = DialectRevision.Smb2Unknown;
            MessageId = 0;
            GrantedCredit = 0;
            SessionKey = null;
            ServerGssToken = null;
            unchecked
            {
                TreeId = (uint)-1;
            }
            SessionId = 0;

            ParentDirectory = null;
            File = null;
            FileId = FILEID.Zero;
            IsDirectory = false;

            Locks = null;
            LockSequence = 0;
            LeaseState = LeaseStateValues.SMB2_LEASE_NONE;
            CreateContexts = null;
            OperationMessageId = 0;

            Client = new Smb2Client(Timeout);
            Client.DisableVerifySignature = this.testConfig.DisableVerifySignature;
        }
        /// <summary>
        /// Attempt to trigger LeaseBreakNotification from a separate client
        /// </summary>
        /// <param name="client">Client to trigger LeaseBreakNotification</param>
        /// <param name="requestDialect">Negotiate dialects</param>
        /// <param name="isDirectory">True value indicating to open a directory, false for a file</param>
        /// <param name="requestedLeaseState">LeaseState when open the directory or file</param>
        /// <param name="accessMask">AccessMask when open the directory or file</param>
        private void TriggerBreakFromClient(
            Smb2FunctionalClient client,
            DialectRevision[] requestDialect,
            bool isDirectory,
            LeaseStateValues requestedLeaseState,
            AccessMask accessMask)
        {
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Trigger a lease break notification by accessing same file/directory from a separate client with LeaseState {0} and AccessMask {1}", requestedLeaseState, accessMask);
            #region Negotiate
            status = client.Negotiate(
                requestDialect,
                TestConfig.IsSMB1NegotiateEnabled,
                capabilityValue: 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);
            #endregion

            #region SESSION_SETUP
            status = client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            #endregion

            #region TREE_CONNECT to share
            uint treeId;
            status = client.TreeConnect(uncSharePath, out treeId);
            #endregion

            #region CREATE
            FILEID fileId;
            Smb2CreateContextResponse[] serverCreateContexts;
            status = client.Create(
                treeId,
                isDirectory ? testDirectory : fileName,
                isDirectory ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                new Smb2CreateContextRequest[]
                {
                    new Smb2CreateRequestLeaseV2
                    {
                        LeaseKey = Guid.NewGuid(),
                        LeaseState = requestedLeaseState
                    }
                },
                accessMask: accessMask);
            #endregion
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Finish triggering lease break notification");
        }
        private void SendCreateRequestWithSpecificAppInstanceversion(
            Smb2FunctionalClient client,
            Guid appInstanceId,
            ulong? appInstanceVersionHigh,
            ulong? appInstanceVersionLow,
            DialectRevision dialect,
            uint expectedCreateResponseStatus,
            out uint treeId,
            out FILEID fileId
            )
        {
            #region Client connects to Server
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client connects to the file server by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT");
            client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress, TestConfig.ClientNic1IPAddress);
            client.Negotiate(Smb2Utility.GetDialects(dialect), TestConfig.IsSMB1NegotiateEnabled);
            client.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);

            client.TreeConnect(uncSharePath, out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            Smb2CreateAppInstanceVersion appInstanceVersion = new Smb2CreateAppInstanceVersion();
            Smb2CreateContextRequest[] clientCreateContexts;

            if (appInstanceVersionHigh.HasValue && appInstanceVersionLow.HasValue)
            {
                appInstanceVersion.AppInstanceVersionHigh = appInstanceVersionHigh.Value;
                appInstanceVersion.AppInstanceVersionLow = appInstanceVersionLow.Value;
                clientCreateContexts =
                new Smb2CreateContextRequest[] {
                    new Smb2CreateAppInstanceId
                    {
                        AppInstanceId = appInstanceId
                    },
                    appInstanceVersion
                };
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request with AppInstanceVersionHigh = {0}, AppInstanceVersionLow = {1}.", appInstanceVersion.AppInstanceVersionHigh, appInstanceVersion.AppInstanceVersionLow);
            }
            else
            {
                clientCreateContexts =
                new Smb2CreateContextRequest[] {
                    new Smb2CreateAppInstanceId
                    {
                        AppInstanceId = appInstanceId
                    }
                };
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends CREATE request without AppInstanceVersion.");
            }

            client.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts,
                RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                clientCreateContexts,
                shareAccess: ShareAccess_Values.NONE,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreEqual(
                        expectedCreateResponseStatus,
                        header.Status,
                        (expectedCreateResponseStatus == Smb2Status.STATUS_SUCCESS ?
                        "The open will be closed. Create should succeed. Actually server returns with {0}."
                        : "The open cannot be closed. Create should not succeed. Actually server returns with {0}."),
                        Smb2Status.GetStatusCode(header.Status));
                });

            #endregion
        }
        public void SetupConnection(ModelDialectRevision clientMaxDialect)
        {
            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);
            testClient.RequestSent += new Action<Packet_Header>(PrintSequenceWindow);

            DialectRevision[] dialects = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(clientMaxDialect));

            uint status;
            NEGOTIATE_Response? negotiateResponse = null;
            status = testClient.Negotiate(
                dialects,
                testConfig.IsSMB1NegotiateEnabled,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_LARGE_MTU,
                checker: (header, response) =>
                {
                    Site.Assert.AreEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "{0} should succeed", header.Command);

                    // The server MUST grant the client at least 1 credit when responding to SMB2 NEGOTIATE.
                    Site.Assert.IsTrue(
                        header.CreditRequestResponse >= 1,
                        "The server MUST grant the client at least 1 credit when responding to SMB2 NEGOTIATE");

                    negotiateResponse = response;
                });

            Site.Log.Add(
                LogEntryKind.Debug,
                "The maximum size, in bytes, of Length in READ/WRITE that server will accept on the connection is {0}",
                testClient.MaxBufferSize);

            Site.Assert.AreEqual(
                ModelUtility.GetDialectRevision(clientMaxDialect),
                negotiateResponse.Value.DialectRevision,
                "DialectRevision {0} is expected", ModelUtility.GetDialectRevision(clientMaxDialect));

            negotiateDialect = negotiateResponse.Value.DialectRevision;

            if ((negotiateDialect == DialectRevision.Smb21 || ModelUtility.IsSmb3xFamily(negotiateDialect))
                // In case server does not support multicredit even implement Smb21 or Smb30
                && testConfig.IsMultiCreditSupported)
            {
                isMultiCreditSupportedOnConnection = true;
            }
            else
            {
                isMultiCreditSupportedOnConnection = false;
            }

            status = testClient.SessionSetup(
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                testConfig.AccountCredential,
                testConfig.UseServerGssToken);

            status = testClient.TreeConnect(
                uncSharePath,
                out treeId);

            Smb2CreateContextResponse[] serverCreateContexts;
            fileName = Guid.NewGuid().ToString();
            status = testClient.Create(
                treeId,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId,
                out serverCreateContexts);
        }