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. "
                    );
            }
                );
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="piHashId">The context hash ID.</param>
 public PreauthIntegrityContext(PreauthIntegrityHashID piHashId)
 {
     preauthIntegrityHashID = piHashId;
     connectionPreauthIntegrityHashValue = null;
     sessionPreauthIntegrityHashValueTable = new Dictionary<ulong, byte[]>();
     completedSessionSet = new HashSet<ulong>();
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="piHashId">The context hash ID.</param>
 public PreauthIntegrityContext(PreauthIntegrityHashID piHashId)
 {
     preauthIntegrityHashID = piHashId;
     connectionPreauthIntegrityHashValue   = null;
     sessionPreauthIntegrityHashValueTable = new Dictionary <ulong, byte[]>();
     completedSessionSet = new HashSet <ulong>();
 }
        public void Negotiate_SMB311_InvalidHashAlgorithm()
        {
            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.HashAlgorithm_Invalid };

            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 " +
                "set HashAlgorithm to an invalid value: 0xFFFF.");
            NegotiateWithNegotiateContexts(
                DialectRevision.Smb311,
                preauthHashAlgs,
                encryptionAlgs: null,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server fails the negotiate request with STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP.");
                BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP, header.Status,
                                             "[MS-SMB2] 3.3.5.4 If the SMB2_PREAUTH_INTEGRITY_CAPABILITIES HashAlgorithms array does not contain any hash algorithms " +
                                             "that the server supports, then the server MUST fail the negotiate request with STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP (0xC05D0000).");
            });
        }
Example #5
0
        private void NegotiateWithEncryptionCapabilitiesContext(EncryptionAlgorithm cipherId)
        {
            if (cipherId == EncryptionAlgorithm.ENCRYPTION_NONE)
            {
                throw new ArgumentException("CipherId should be either AES-128-CCM or AES-128-GCM.");
            }

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION);
            TestConfig.CheckEncryptionAlgorithm(cipherId);
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client sends NEGOTIATE request with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context. {0} is as the preferred cipher algorithm. ", cipherId);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Server should reply NEGOTIATE response with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context and {0} as cipher algorithm. ", cipherId);
            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
            EncryptionAlgorithm[]    encryptionAlgs  = new EncryptionAlgorithm[] {
                cipherId,
                cipherId == EncryptionAlgorithm.ENCRYPTION_AES128_CCM? EncryptionAlgorithm.ENCRYPTION_AES128_GCM : EncryptionAlgorithm.ENCRYPTION_AES128_CCM
            };
            client.NegotiateWithContexts(
                Packet_Header_Flags_Values.NONE,
                TestConfig.RequestDialects,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION,
                preauthHashAlgs: preauthHashAlgs,
                encryptionAlgs: encryptionAlgs);
            BaseTestSite.Assert.AreEqual(cipherId, client.SelectedCipherID, "The selected Cipher Id should be {0}", cipherId);
        }
        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);
            }
                );
        }
        /// <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 NegotiateWithEncryptionCapabilitiesContext(EncryptionAlgorithm cipherId, bool sendCipherArray = false)
        {
            if (cipherId == EncryptionAlgorithm.ENCRYPTION_NONE)
            {
                throw new ArgumentException("CipherId should be either AES-128-CCM or AES-128-GCM.");
            }

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION);
            TestConfig.CheckEncryptionAlgorithm(cipherId);
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client sends NEGOTIATE request with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context. {0} is as the preferred cipher algorithm. ", cipherId);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Server should reply NEGOTIATE response with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context and {0} as cipher algorithm. ", cipherId);
            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
            EncryptionAlgorithm[]    encryptionAlgs  = null;
            if (sendCipherArray)
            {
                encryptionAlgs = new EncryptionAlgorithm[] {
                    cipherId,
                    cipherId == EncryptionAlgorithm.ENCRYPTION_AES128_CCM? EncryptionAlgorithm.ENCRYPTION_AES128_GCM : EncryptionAlgorithm.ENCRYPTION_AES128_CCM
                };
            }
            else
            {
                encryptionAlgs = new EncryptionAlgorithm[] { cipherId };
            }

            client.NegotiateWithContexts(
                Packet_Header_Flags_Values.NONE,
                TestConfig.RequestDialects,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION,
                preauthHashAlgs: preauthHashAlgs,
                encryptionAlgs: encryptionAlgs);

            if (sendCipherArray)
            {
                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(cipherId, client.SelectedCipherID, "The selected Cipher Id should be {0}", cipherId);
            }
        }
        public void Smb2Negotiate(DialectRevision[] requestDialects)
        {
            Packet_Header packetHeader;

            NEGOTIATE_Response response;

            PreauthIntegrityHashID[] preauthHashAlgs = null;
            EncryptionAlgorithm[]    encryptionAlgs  = null;
            if (requestDialects.Contains(DialectRevision.Smb311))
            {
                // initial negotiation context for SMB 3.1.1 dialect
                preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
                encryptionAlgs  = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_CCM, EncryptionAlgorithm.ENCRYPTION_AES128_GCM };
            }

            uint status = Negotiate(
                0,
                RequestAndConsumeCredit(),
                Packet_Header_Flags_Values.NONE,
                GetMessageId(),
                requestDialects,
                SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                Capabilities_Values.GLOBAL_CAP_ENCRYPTION,
                clientGuid,
                out selectedDialect,
                out serverGssToken,
                out packetHeader,
                out response,
                0,
                preauthHashAlgs,
                encryptionAlgs
                );

            UpdateCredit(packetHeader);

            if (status != Smb2Status.STATUS_SUCCESS)
            {
                throw new InvalidOperationException(String.Format("Negotiate failed with {0:X08}.", status));
            }

            signingRequired = response.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED);

            negotiated = true;

            maxReadSize = response.MaxReadSize;

            maxWriteSize = response.MaxWriteSize;
        }
Example #10
0
        public uint Smb2Negotiate(DialectRevision[] requestDialects, out DialectRevision selectedDialect)
        {
            uint status;
            NEGOTIATE_Response negotiateResponse;

            clientGuid = Guid.NewGuid();

            PreauthIntegrityHashID[] preauthHashAlgs = null;
            EncryptionAlgorithm[]    encryptionAlgs  = null;
            if (requestDialects.Contains(DialectRevision.Smb311))
            {
                // initial negotiation context for SMB 3.1.1 dialect
                preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
                encryptionAlgs  = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_CCM, EncryptionAlgorithm.ENCRYPTION_AES128_GCM };
            }

            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,
                0,
                preauthHashAlgs,
                encryptionAlgs
                );

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

            CalculateSmb2AvailableCredits(1, packetHeader.CreditRequestResponse);
            return(status);
        }
        public void BVT_Negotiate_SMB311_Preauthentication()
        {
            DialectRevision clientMaxDialectSupported = DialectRevision.Smb311;

            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };

            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 and SMB2_PREAUTH_INTEGRITY_CAPABILITIES context.");
            NegotiateWithNegotiateContexts(
                clientMaxDialectSupported,
                preauthHashAlgs,
                null,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                CheckNegotiateResponse(header, response, clientMaxDialectSupported, null);
            });
        }
        public void BVT_Negotiate_SMB311()
        {
            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.");
            NegotiateWithNegotiateContexts(
                clientMaxDialectSupported,
                preauthHashAlgs,
                encryptionAlgs,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
            {
                CheckNegotiateResponse(header, response, clientMaxDialectSupported, encryptionAlgs);
            });
        }
        public void BVT_Negotiate_SMB311_Preauthentication()
        {
            DialectRevision clientMaxDialectSupported = DialectRevision.Smb311;
            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };

            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 and SMB2_PREAUTH_INTEGRITY_CAPABILITIES context.");
            NegotiateWithNegotiateContexts(
                clientMaxDialectSupported,
                preauthHashAlgs,
                null,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    CheckNegotiateResponse(header, response, clientMaxDialectSupported, null);
                }
                );
        }
        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);
        }
        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 void BVT_Negotiate_SMB311()
        {
            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.");
            NegotiateWithNegotiateContexts(
                clientMaxDialectSupported,
                preauthHashAlgs,
                encryptionAlgs,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    CheckNegotiateResponse(header, response, clientMaxDialectSupported, encryptionAlgs);
                }
                );
        }
Example #17
0
        /// <summary>
        /// Connect to the Server and establish the named pipe transport.
        /// </summary>
        private void ConnectToServer()
        {
            smb2Client = new Smb2Client(smb2ClientTimeout);

            if (IPAddress.TryParse(serverName, out var serverIp))
            {
                smb2Client.ConnectOverTCP(serverIp);
            }
            else
            {
                var serverHostEntry = Dns.GetHostEntry(serverName);
                smb2Client.ConnectOverTCP(serverHostEntry.AddressList[0]);
            }

            var validDialects = new DialectRevision[]
            {
                DialectRevision.Smb2002,
                DialectRevision.Smb21,
                DialectRevision.Smb30,
                DialectRevision.Smb302,
                DialectRevision.Smb311
            };

            var preauthIntegrityHashIDs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
            var encryptionAlgorithms    = new EncryptionAlgorithm[] { EncryptionAlgorithm.ENCRYPTION_AES128_GCM, EncryptionAlgorithm.ENCRYPTION_AES128_CCM };
            var status = smb2Client.Negotiate(
                creditCharge: 1,
                creditRequest: 1,
                flags: defaultFlags,
                messageId: messageId++,
                // Will negotiate highest dialect server supports
                dialects: validDialects,
                securityMode: SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                capabilities: Capabilities_Values.GLOBAL_CAP_DFS | Capabilities_Values.GLOBAL_CAP_ENCRYPTION | Capabilities_Values.GLOBAL_CAP_MULTI_CHANNEL | Capabilities_Values.GLOBAL_CAP_LARGE_MTU,
                clientGuid: Guid.NewGuid(),
                out var selectedDialect,
                out var serverGssToken,
                out Packet_Header _,
                out var negotiateResponse,
                preauthHashAlgs: preauthIntegrityHashIDs,
                encryptionAlgs: encryptionAlgorithms);

            CheckStatusCode(status, nameof(Smb2Client.Negotiate));

            var sessionSiginingRequired = negotiateResponse.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED);

            if (sessionSiginingRequired)
            {
                defaultFlags |= Packet_Header_Flags_Values.FLAGS_SIGNED;
            }

            var usedSecurityPackageType = (SecurityPackageType)Enum.Parse(typeof(SecurityPackageType), securityPackage);
            var sspiClientGss           = new SspiClientSecurityContext(
                usedSecurityPackageType,
                new AccountCredential(domainName, userName, password),
                Smb2Utility.GetCifsServicePrincipalName(serverName),
                ClientSecurityContextAttribute.None,
                SecurityTargetDataRepresentation.SecurityNativeDrep);

            if (usedSecurityPackageType == SecurityPackageType.Negotiate && useServerGssToken)
            {
                sspiClientGss.Initialize(serverGssToken);
            }
            else
            {
                sspiClientGss.Initialize(null);
            }

            do
            {
                status = smb2Client.SessionSetup(
                    creditCharge: 1,
                    creditRequest: 1,
                    flags: Packet_Header_Flags_Values.NONE,
                    messageId: messageId++,
                    sessionId: sessionId,
                    sessionSetupFlags: SESSION_SETUP_Request_Flags.NONE,
                    securityMode: SESSION_SETUP_Request_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED,
                    capabilities: SESSION_SETUP_Request_Capabilities_Values.GLOBAL_CAP_DFS,
                    previousSessionId: 0,
                    clientGssToken: sspiClientGss.Token,
                    out sessionId,
                    out serverGssToken,
                    out _,
                    out _);
                CheckStatusCode(status, nameof(Smb2Client.SessionSetup));

                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);

            var treeConnectSigningRequired = sessionSiginingRequired || (selectedDialect >= DialectRevision.Smb311);

            smb2Client.GenerateCryptoKeys(
                sessionId,
                sspiClientGss.SessionKey,
                treeConnectSigningRequired,
                false);

            status = smb2Client.TreeConnect(
                creditCharge: 1,
                creditRequest: 1,
                flags: treeConnectSigningRequired ? defaultFlags | Packet_Header_Flags_Values.FLAGS_SIGNED : defaultFlags,
                messageId: messageId++,
                sessionId: sessionId,
                $"\\\\{serverName}\\IPC$",
                out treeId,
                out _,
                out _);
            CheckStatusCode(status, nameof(Smb2Client.TreeConnect));

            smb2Client.EnableSessionSigningAndEncryption(sessionId, sessionSiginingRequired, false);

            status = smb2Client.Create(
                creditCharge: 1,
                creditRequest: 1,
                flags: defaultFlags,
                messageId: messageId++,
                sessionId: sessionId,
                treeId: treeId,
                path: pipeName,
                desiredAccess: AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE,
                shareAccess: ShareAccess_Values.FILE_SHARE_READ,
                createOptions: CreateOptions_Values.NONE,
                createDispositions: CreateDisposition_Values.FILE_OPEN_IF,
                fileAttributes: File_Attributes.NONE,
                impersonationLevel: ImpersonationLevel_Values.Impersonation,
                securityFlag: SecurityFlags_Values.NONE,
                requestedOplockLevel: RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                createContexts: null,
                out fileId,
                out _,
                out _,
                out _);
            CheckStatusCode(status, nameof(Smb2Client.Create));
        }
        private void NegotiateWithEncryptionCapabilitiesContext(EncryptionAlgorithm cipherId, bool sendCipherArray = false)
        {
            if (cipherId == EncryptionAlgorithm.ENCRYPTION_NONE)
            {
                throw new ArgumentException("CipherId should be either AES-128-CCM or AES-128-GCM.");
            }

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION);
            TestConfig.CheckEncryptionAlgorithm(cipherId);
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client sends NEGOTIATE request with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context. {0} is as the preferred cipher algorithm. ", cipherId);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Server should reply NEGOTIATE response with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context and {0} as cipher algorithm. ", cipherId);
            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
            EncryptionAlgorithm[] encryptionAlgs = null;
            if (sendCipherArray)
            {
                encryptionAlgs = new EncryptionAlgorithm[] {
                    cipherId,
                    cipherId == EncryptionAlgorithm.ENCRYPTION_AES128_CCM? EncryptionAlgorithm.ENCRYPTION_AES128_GCM : EncryptionAlgorithm.ENCRYPTION_AES128_CCM };
            }
            else
            {
                encryptionAlgs = new EncryptionAlgorithm[] { cipherId };
            }

            client.NegotiateWithContexts(
                Packet_Header_Flags_Values.NONE,
                TestConfig.RequestDialects,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION,
                preauthHashAlgs: preauthHashAlgs,
                encryptionAlgs: encryptionAlgs);

            if (sendCipherArray)
            {
                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(cipherId, client.SelectedCipherID, "The selected Cipher Id should be {0}", cipherId);
            }
        }
        /// <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 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);
                }
                );
        }
        public void Negotiate_SMB311_InvalidHashAlgorithm()
        {
            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.HashAlgorithm_Invalid };

            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 " +
               "set HashAlgorithm to an invalid value: 0xFFFF.");
            NegotiateWithNegotiateContexts(
                DialectRevision.Smb311,
                preauthHashAlgs,
                encryptionAlgs: null,
                checker: (Packet_Header header, NEGOTIATE_Response response) =>
                {
                    BaseTestSite.Log.Add(LogEntryKind.TestStep, "Verify server fails the negotiate request with STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP.");
                    BaseTestSite.Assert.AreEqual(Smb2Status.STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP, header.Status,
                        "[MS-SMB2] 3.3.5.4 If the SMB2_PREAUTH_INTEGRITY_CAPABILITIES HashAlgorithms array does not contain any hash algorithms " +
                        "that the server supports, then the server MUST fail the negotiate request with STATUS_SMB_NO_PREAUTH_INTEGRITY_HASH_OVERLAP (0xC05D0000).");
                });
        }
        private void NegotiateWithEncryptionCapabilitiesContext(EncryptionAlgorithm cipherId)
        {
            if (cipherId == EncryptionAlgorithm.ENCRYPTION_NONE)
            {
                throw new ArgumentException("CipherId should be either AES-128-CCM or AES-128-GCM.");
            }

            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb311);
            TestConfig.CheckCapabilities(NEGOTIATE_Response_Capabilities_Values.GLOBAL_CAP_ENCRYPTION);
            TestConfig.CheckEncryptionAlgorithm(cipherId);
            #endregion

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client sends NEGOTIATE request with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context. {0} is as the preferred cipher algorithm. ", cipherId);
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Server should reply NEGOTIATE response with dialect 3.11, SMB2_ENCRYPTION_CAPABILITIES context and {0} as cipher algorithm. ", cipherId);
            PreauthIntegrityHashID[] preauthHashAlgs = new PreauthIntegrityHashID[] { PreauthIntegrityHashID.SHA_512 };
            EncryptionAlgorithm[] encryptionAlgs = new EncryptionAlgorithm[] {
                cipherId,
                cipherId == EncryptionAlgorithm.ENCRYPTION_AES128_CCM? EncryptionAlgorithm.ENCRYPTION_AES128_GCM : EncryptionAlgorithm.ENCRYPTION_AES128_CCM };
            client.NegotiateWithContexts(
                Packet_Header_Flags_Values.NONE,
                TestConfig.RequestDialects,
                capabilityValue: Capabilities_Values.GLOBAL_CAP_DIRECTORY_LEASING | Capabilities_Values.GLOBAL_CAP_LARGE_MTU | Capabilities_Values.GLOBAL_CAP_LEASING | Capabilities_Values.GLOBAL_CAP_ENCRYPTION,
                preauthHashAlgs: preauthHashAlgs,
                encryptionAlgs: encryptionAlgs);
            BaseTestSite.Assert.AreEqual(cipherId, client.SelectedCipherID, "The selected Cipher Id should be {0}", cipherId);
        }