示例#1
0
        public void NegotiateRequest(ModelDialectRevision maxSmbVersionClientSupported, SigningFlagType signingFlagType, SigningEnabledType signingEnabledType, SigningRequiredType signingRequiredType)
        {
            testClient = new Smb2FunctionalClient(testConfig.Timeout, testConfig, this.Site);
            testClient.ConnectToServer(testConfig.UnderlyingTransport, testConfig.SutComputerName, testConfig.SutIPAddress);

            DialectRevision[]          dialects    = Smb2Utility.GetDialects(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported));
            Packet_Header_Flags_Values headerFlags = (signingFlagType == SigningFlagType.SignedFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            SigningEnabledType  resSigningEnabledType  = SigningEnabledType.SigningEnabledNotSet;
            SigningRequiredType resSigningRequiredType = SigningRequiredType.SigningRequiredNotSet;
            uint status = testClient.Negotiate(
                headerFlags,
                dialects,
                GetNegotiateSecurityMode(signingEnabledType, signingRequiredType),
                checker: (header, response) =>
            {
                resSigningEnabledType =
                    response.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_ENABLED) ?
                    SigningEnabledType.SigningEnabledSet : SigningEnabledType.SigningEnabledNotSet;
                resSigningRequiredType =
                    response.SecurityMode.HasFlag(NEGOTIATE_Response_SecurityMode_Values.NEGOTIATE_SIGNING_REQUIRED) ?
                    SigningRequiredType.SigningRequiredSet : SigningRequiredType.SigningRequiredNotSet;
            });

            NegotiateResponse((ModelSmb2Status)status, resSigningEnabledType, resSigningRequiredType, signingConfig);
        }
示例#2
0
        public void TreeConnectRequest(SigningFlagType signingFlagType)
        {
            uint treeId;
            SigningModelSessionId modelSessionId          = SigningModelSessionId.ZeroSessionId;
            SigningFlagType       responseSigningFlagType = SigningFlagType.SignedFlagNotSet;
            string sharePath = Smb2Utility.GetUncPath(testConfig.SutComputerName, testConfig.BasicFileShare);
            Packet_Header_Flags_Values headerFlags = (signingFlagType == SigningFlagType.SignedFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            // Inform SDK to disable/enable signing according to SigningFlagType.
            bool isEnableSigning = !(signingFlagType == SigningFlagType.SignedFlagNotSet);

            testClient.EnableSessionSigningAndEncryption(enableSigning: isEnableSigning, enableEncryption: false);

            uint status = testClient.TreeConnect(
                headerFlags,
                sharePath,
                out treeId,
                checker: (header, response) =>
            {
                modelSessionId          = GetModelSessionId(header.SessionId);
                responseSigningFlagType = GetSigningFlagType(header.Flags);
            });

            TreeConnectResponse((ModelSmb2Status)status, modelSessionId, responseSigningFlagType);
        }
示例#3
0
        private void LogOffSession(Smb2Client client, Packet_Header_Flags_Values packetHeader, ulong messageId, ulong sessionId, uint treeId, FILEID fileId)
        {
            if (fileId.Persistent != 0 || fileId.Volatile != 0)
            {
                client.Close(
                    1,
                    1,
                    packetHeader,
                    messageId++,
                    sessionId,
                    treeId,
                    fileId,
                    Flags_Values.NONE,
                    out _,
                    out _);
            }

            client.TreeDisconnect(
                1,
                1,
                packetHeader,
                messageId++,
                sessionId,
                treeId,
                out _,
                out _);
            client.LogOff(
                1,
                1,
                packetHeader,
                messageId++,
                sessionId,
                out _,
                out _);
        }
        private uint SessionSetup(
            Packet_Header_Flags_Values headerFlags,
            SESSION_SETUP_Request_Flags sessionSetupFlags,
            SESSION_SETUP_Request_SecurityMode_Values securityMode,
            SESSION_SETUP_Request_Capabilities_Values capabilities,
            ulong previousSessionId,
            SecurityPackageType securityPackageType,
            string serverName,
            byte[] token,
            out byte[] serverGssToken,
            ushort creditRequest = 64)
        {
            Packet_Header          header;
            SESSION_SETUP_Response sessionSetupResponse;

            uint status;

            status = client.SessionSetup(
                1,
                creditRequest,
                headerFlags,
                messageId++,
                sessionId,
                sessionSetupFlags,
                securityMode,
                capabilities,
                previousSessionId,
                token,
                out sessionId,
                out serverGssToken,
                out header,
                out sessionSetupResponse);

            return(status);
        }
        /// <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);
        }
示例#6
0
        private void SendIoctlPayload(
            Smb2Client client,
            CtlCode_Values code,
            byte[] payload,
            Packet_Header_Flags_Values headerFlags,
            ulong messageId,
            uint treeId,
            ulong sessionId,
            FILEID fileId)
        {
            if (client == null)
            {
                throw new InvalidOperationException("The transport is not connected.");
            }

            if (payload == null)
            {
                throw new ArgumentNullException("payload");
            }

            var request = new Smb2IOCtlRequestPacket();

            request.Header.CreditCharge          = 1;
            request.Header.Command               = Smb2Command.IOCTL;
            request.Header.CreditRequestResponse = 1;
            request.Header.Flags     = headerFlags;
            request.Header.MessageId = messageId;
            request.Header.TreeId    = treeId;
            request.Header.SessionId = sessionId;

            request.PayLoad.CtlCode = code;

            if (code == CtlCode_Values.FSCTL_DFS_GET_REFERRALS || code == CtlCode_Values.FSCTL_DFS_GET_REFERRALS_EX)
            {
                request.PayLoad.FileId = FILEID.Invalid;
            }
            else
            {
                request.PayLoad.FileId = fileId;
            }

            if (payload.Length > 0)
            {
                request.PayLoad.InputOffset = request.BufferOffset;
                request.PayLoad.InputCount  = (ushort)payload.Length;
                request.Buffer = payload;
            }

            request.PayLoad.MaxInputResponse  = 0;
            request.PayLoad.MaxOutputResponse = 4096;
            request.PayLoad.Flags             = IOCTL_Request_Flags_Values.SMB2_0_IOCTL_IS_FSCTL;

            ioctlRequestMessageIds.Enqueue(request.Header.MessageId);
            client.SendPacket(request);
        }
示例#7
0
        private SigningFlagType GetSigningFlagType(Packet_Header_Flags_Values flags)
        {
            SigningFlagType signingFlag;

            if (flags.HasFlag(Packet_Header_Flags_Values.FLAGS_SIGNED))
            {
                signingFlag = SigningFlagType.SignedFlagSet;
            }
            else
            {
                signingFlag = SigningFlagType.SignedFlagNotSet;
            }

            return(signingFlag);
        }
        public uint Create(
            uint treeId,
            string fileName,
            CreateOptions_Values createOptions,
            out FILEID fileId,
            out Smb2CreateContextResponse[] serverCreateContexts,
            RequestedOplockLevel_Values requestedOplockLevel_Values = RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
            Smb2CreateContextRequest[] createContexts = null,
            Packet_Header_Flags_Values headerFlag     = Packet_Header_Flags_Values.FLAGS_SIGNED,
            AccessMask accessMask                     = AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE,
            ShareAccess_Values shareAccess            = ShareAccess_Values.FILE_SHARE_READ | ShareAccess_Values.FILE_SHARE_WRITE | ShareAccess_Values.FILE_SHARE_DELETE,
            ResponseChecker <CREATE_Response> checker = null,
            ushort creditRequest = 64)
        {
            Packet_Header   header;
            CREATE_Response createResponse;

            uint status = client.Create(
                1,
                creditRequest,
                headerFlag,
                messageId++,
                sessionId,
                treeId,
                fileName,
                accessMask,
                shareAccess,
                createOptions,
                CreateDisposition_Values.FILE_OPEN_IF,
                File_Attributes.NONE,
                ImpersonationLevel_Values.Impersonation,
                SecurityFlags_Values.NONE,
                requestedOplockLevel_Values,
                createContexts,
                out fileId,
                out serverCreateContexts,
                out header,
                out createResponse);

            InnerResponseChecker(checker, header, createResponse);

            grantedCredit = header.CreditRequestResponse;

            return(status);
        }
示例#9
0
        /// <summary>
        /// Send an SMB2 SESSION_SETUP request with specified parameters
        /// </summary>
        /// <param name="headerFlags">A Flags field indicates how to process the operation.</param>
        /// <param name="sessionSetupFlags">To bind an existing session to a new connection,set to SMB2_SESSION_FLAG_BINDING to bind; otherwise set it to NONE.</param>
        /// <param name="securityMode">The security mode field specifies whether SMB signing is enabled, required at the server, or both</param>
        /// <param name="capabilities">Specifies protocol capabilities for the client.</param>
        /// <param name="token">Gss token to send</param>
        /// <param name="serverToken">GssToken returned from server</param>
        /// <param name="isResponseEncryptedSessionFlag">check if SESSION_FLAG_ENCRYPT_DATA returned from server</param>
        /// <param name="creditRequest">The number of credits the client is requesting. Default value is 64.</param>
        /// <param name="previousSessionId">For reconnect, set it to previous sessionId, otherwise set it to 0. Default value is 0.</param>
        /// <returns>The status code for SESSION_SETUP Response.</returns>
        public uint SessionSetup(
            Packet_Header_Flags_Values headerFlags,
            SESSION_SETUP_Request_Flags sessionSetupFlags,
            SESSION_SETUP_Request_SecurityMode_Values securityMode,
            SESSION_SETUP_Request_Capabilities_Values capabilities,
            byte[] token,
            out byte[] serverToken,
            out bool isResponseEncryptedSessionFlag,
            ushort creditRequest    = 64,
            ulong previousSessionId = 0)
        {
            Packet_Header          header;
            SESSION_SETUP_Response sessionSetupResponse;

            ulong  messageId    = generateMessageId(sequenceWindow);
            ushort creditCharge = generateCreditCharge(1);

            // Need to consume credit from sequence window first according to TD
            ConsumeCredit(messageId, creditCharge);

            uint status = Smb2Client.SessionSetup(
                1,
                creditRequest,
                headerFlags,
                messageId,
                sessionId,
                sessionSetupFlags,
                securityMode,
                capabilities,
                previousSessionId,
                token,
                out sessionId,
                out serverToken,
                out header,
                out sessionSetupResponse);

            isResponseEncryptedSessionFlag = sessionSetupResponse.SessionFlags.HasFlag(SessionFlags_Values.SESSION_FLAG_ENCRYPT_DATA);

            ProduceCredit(messageId, header);

            return(status);
        }
        /// <summary>
        /// Send an SMB2 SESSION_SETUP request with specified parameters
        /// </summary>
        /// <param name="headerFlags">A Flags field indicates how to process the operation.</param>
        /// <param name="sessionSetupFlags">To bind an existing session to a new connection,set to SMB2_SESSION_FLAG_BINDING to bind; otherwise set it to NONE.</param>
        /// <param name="securityMode">The security mode field specifies whether SMB signing is enabled, required at the server, or both</param>
        /// <param name="capabilities">Specifies protocol capabilities for the client.</param>
        /// <param name="token">Gss token to send</param>
        /// <param name="serverToken">GssToken returned from server</param>
        /// <param name="creditRequest">The number of credits the client is requesting. Default value is 64.</param>
        /// <param name="previousSessionId">For reconnect, set it to previous sessionId, otherwise set it to 0. Default value is 0.</param>
        /// <returns>The status code for SESSION_SETUP Response.</returns>
        public uint SessionSetup(
            Packet_Header_Flags_Values headerFlags,
            SESSION_SETUP_Request_Flags sessionSetupFlags,
            SESSION_SETUP_Request_SecurityMode_Values securityMode,
            SESSION_SETUP_Request_Capabilities_Values capabilities,
            byte[] token,
            out byte[] serverToken,
            ushort creditRequest = 64,
            ulong previousSessionId = 0)
        {
            Packet_Header header;
            SESSION_SETUP_Response sessionSetupResponse;

            ulong messageId = generateMessageId(sequenceWindow);
            ushort creditCharge = generateCreditCharge(1);

            // Need to consume credit from sequence window first according to TD
            ConsumeCredit(messageId, creditCharge);

            uint status = Smb2Client.SessionSetup(
                1,
                creditRequest,
                headerFlags,
                messageId,
                sessionId,
                sessionSetupFlags,
                securityMode,
                capabilities,
                previousSessionId,
                token,
                out sessionId,
                out serverToken,
                out header,
                out sessionSetupResponse);

            ProduceCredit(messageId, header);

            return status;
        }
示例#11
0
        public void SessionSetupRequest(SigningFlagType signingFlagType, SigningEnabledType signingEnabledType, SigningRequiredType signingRequiredType, UserType userType)
        {
            SigningModelSessionId      modelSessionId          = SigningModelSessionId.ZeroSessionId;
            SessionFlags_Values        sessionFlag             = SessionFlags_Values.NONE;
            SigningFlagType            responseSigningFlagType = SigningFlagType.SignedFlagNotSet;
            Packet_Header_Flags_Values headerFlags             = (signingFlagType == SigningFlagType.SignedFlagSet) ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            uint status = testClient.SessionSetup(
                headerFlags,
                testConfig.DefaultSecurityPackage,
                testConfig.SutComputerName,
                GetAccountCredential(userType),
                true,
                GetSessionSetupSecurityMode(signingEnabledType, signingRequiredType),
                checker: (header, response) =>
            {
                modelSessionId          = GetModelSessionId(header.SessionId);
                responseSigningFlagType = GetSigningFlagType(header.Flags);
                sessionFlag             = response.SessionFlags;
            });

            SessionSetupResponse((ModelSmb2Status)status, modelSessionId, responseSigningFlagType, sessionFlag, signingConfig);
        }
        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);
        }
 protected virtual uint TreeConnect(
     ushort creditCharge,
     ushort creditRequest,
     Packet_Header_Flags_Values flags,
     ulong messageId,
     ulong sessionId,
     string server,
     string share,
     out Packet_Header header,
     out TREE_CONNECT_Response response)
 {
     return client.TreeConnect(
                 creditCharge,
                 creditRequest,
                 flags,
                 messageId,
                 sessionId,
                 string.Format(@"\\{0}\{1}", server, share),
                 out treeId,
                 out header,
                 out response);
 }
            protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId, 
                string server, string share, out Packet_Header header, out TREE_CONNECT_Response response)
            {
                uint treeConnectResponseCode = base.TreeConnect(creditCharge, creditRequest, flags, messageId, sessionId, server, share, out header, out response);

                if (supportV1)
                {
                    testSite.Assert.IsTrue(
                    response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1),
                    "The share content should enable hash v1");
                }
                if (supportV2)
                {
                    testSite.Assert.IsTrue(
                    response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2),
                    "The share content should enable hash v2");
                }

                return treeConnectResponseCode;
            }
示例#15
0
        private uint ReadHash(
            Smb2Client client,
            Packet_Header_Flags_Values headerFlags,
            ulong messageId,
            uint treeId,
            ulong sessionId,
            FILEID fileId,
            SRV_READ_HASH_Request_HashType_Values hashType,
            SRV_READ_HASH_Request_HashVersion_Values hashVersion,
            SRV_READ_HASH_Request_HashRetrievalType_Values hashRetrievalType,
            ulong offset,
            uint length,
            out HASH_HEADER hashHeader,
            out byte[] hashData)
        {
            hashHeader = new HASH_HEADER();
            hashData   = null;

            SRV_READ_HASH_Request readHashRequest = new SRV_READ_HASH_Request();

            readHashRequest.HashType          = hashType;
            readHashRequest.HashVersion       = hashVersion;
            readHashRequest.HashRetrievalType = hashRetrievalType;
            readHashRequest.Offset            = offset;
            readHashRequest.Length            = length;

            byte[] requestInput = TypeMarshal.ToBytes(readHashRequest);
            byte[] responseOutput;

            uint status;

            SendIoctlPayload(client, CtlCode_Values.FSCTL_SRV_READ_HASH, requestInput, Packet_Header_Flags_Values.FLAGS_SIGNED, messageId, treeId, sessionId, fileId);
            ExpectIoctlPayload(client, out status, out responseOutput);

            if (status != Smb2Status.STATUS_SUCCESS)
            {
                return(status);
            }

            byte[] hashHeaderDataBuffer = null;
            switch (hashRetrievalType)
            {
            case SRV_READ_HASH_Request_HashRetrievalType_Values.SRV_HASH_RETRIEVE_HASH_BASED:
                hashHeaderDataBuffer = TypeMarshal.ToStruct <SRV_HASH_RETRIEVE_HASH_BASED>(responseOutput).Buffer;
                break;

            case SRV_READ_HASH_Request_HashRetrievalType_Values.SRV_HASH_RETRIEVE_FILE_BASED:
                hashHeaderDataBuffer = TypeMarshal.ToStruct <SRV_HASH_RETRIEVE_FILE_BASED>(responseOutput).Buffer;
                break;

            default:
                throw new NotImplementedException(hashRetrievalType.ToString());
            }

            int hashHeaderLength = 0;

            hashHeader = TypeMarshal.ToStruct <HASH_HEADER>(hashHeaderDataBuffer, ref hashHeaderLength);
            hashData   = hashHeaderDataBuffer.Skip(hashHeaderLength).ToArray();

            return(status);
        }
            protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId,
                                                string server, string share, out Packet_Header header, out TREE_CONNECT_Response response)
            {
                uint treeConnectResponseCode = base.TreeConnect(creditCharge, creditRequest, flags, messageId, sessionId, server, share, out header, out response);

                if (supportV1)
                {
                    testSite.Assert.IsTrue(
                        response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1),
                        "The share content should enable hash v1");
                }
                if (supportV2)
                {
                    testSite.Assert.IsTrue(
                        response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2),
                        "The share content should enable hash v2");
                }

                return(treeConnectResponseCode);
            }
示例#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));
        }
        /// <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;
        }
示例#19
0
        public void CreateRequest(
            CreateFileNameType fileNameType,
            CreateOptionsFileOpenReparsePointType fileOpenReparsePointType,
            CreateOptionsFileDeleteOnCloseType fileDeleteOnCloseType,
            CreateContextType contextType,
            ImpersonationLevelType impersonationType,
            CreateFileType fileType)
        {
            #region Header
            Packet_Header_Flags_Values headerFlag = testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE;

            #endregion

            #region File Name
            string fileName = GetFileName(fileNameType);
            #endregion

            #region CreateOptions
            CreateOptions_Values createOptions = fileType == CreateFileType.DirectoryFile ? CreateOptions_Values.FILE_DIRECTORY_FILE : CreateOptions_Values.FILE_NON_DIRECTORY_FILE;
            if (fileOpenReparsePointType == CreateOptionsFileOpenReparsePointType.FileOpenReparsePointSet)
            {
                createOptions |= CreateOptions_Values.FILE_OPEN_REPARSE_POINT;
            }
            if (fileDeleteOnCloseType == CreateOptionsFileDeleteOnCloseType.FileDeteteOnCloseSet)
            {
                createOptions |= CreateOptions_Values.FILE_DELETE_ON_CLOSE;
            }
            #endregion

            #region CreateContexts
            Smb2CreateContextRequest[] createContexts = new Smb2CreateContextRequest[] { };
            Create_ContextType = contextType;
            switch (contextType)
            {
            case CreateContextType.NoCreateContext:
                break;

            case CreateContextType.InvalidCreateContext:
            case CreateContextType.InvalidCreateContextSize:
                testClient.BeforeSendingPacket(ReplacePacketByInvalidCreateContext);
                break;

            case CreateContextType.ValidCreateContext:
                testConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_QUERY_ON_DISK_ID);

                createContexts = createContexts.Append(new Smb2CreateQueryOnDiskId());
                break;

            default:
                throw new ArgumentException("contextType");
            }
            #endregion

            #region ImpersonationLevel
            ImpersonationLevel_Values impersonation = ImpersonationLevel_Values.Impersonation;
            if (impersonationType == ImpersonationLevelType.InvalidImpersonationLevel)
            {
                impersonation = (ImpersonationLevel_Values)0x00000004; //Non-existed impersonation level
            }

            #endregion

            #region DesiredAccess
            AccessMask accessMask = AccessMask.GENERIC_READ | AccessMask.GENERIC_WRITE | AccessMask.DELETE;
            #endregion

            Smb2CreateContextResponse[] contextResponse;

            uint status = testClient.Create(
                treeId,
                fileName,
                createOptions,
                headerFlag,
                out fileID,
                out contextResponse,
                createContexts: createContexts,
                accessMask: accessMask,
                checker: (header, response) => { },
                impersonationLevel: impersonation);

            CreateResponse((ModelSmb2Status)status, createCloseConfig);
        }
            protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId,
                string server, string share, out Packet_Header header, out TREE_CONNECT_Response response)
            {
                uint treeConnectResponseCode = base.TreeConnect(
                    creditCharge,
                    creditRequest,
                    flags,
                    messageId,
                    sessionId,
                    server,
                    share,
                    out header,
                    out response);

                this.isShareHashEnabled = response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1)
                    || response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2);
                BaseTestSite.Assert.AreEqual(
                    true,
                    this.isShareHashEnabled,
                    "The share folder should enable hash V1 or hash V2");

                return treeConnectResponseCode;
            }
示例#21
0
            protected override uint TreeConnect(ushort creditCharge, ushort creditRequest, Packet_Header_Flags_Values flags, ulong messageId, ulong sessionId,
                                                string server, string share, out Packet_Header header, out TREE_CONNECT_Response response)
            {
                uint treeConnectResponseCode = base.TreeConnect(
                    creditCharge,
                    creditRequest,
                    flags,
                    messageId,
                    sessionId,
                    server,
                    share,
                    out header,
                    out response);

                this.isShareHashEnabled = response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V1) ||
                                          response.ShareFlags.HasFlag(ShareFlags_Values.SHAREFLAG_ENABLE_HASH_V2);
                BaseTestSite.Assert.AreEqual(
                    true,
                    this.isShareHashEnabled,
                    "The share folder should enable hash V1 or hash V2");

                return(treeConnectResponseCode);
            }
        public void OpenFile(
            string server,
            string share,
            string file,
            SecurityPackageType securityPackageType,
            string domainName,
            string userName,
            string password,
            AccessMask accessMask)
        {
            IPHostEntry hostEntry = Dns.GetHostEntry(server);
            client.ConnectOverTCP(hostEntry.AddressList[0]);
            serverPrincipleName = Smb2Utility.GetPrincipleName(hostEntry.HostName);

            Packet_Header header;
            NEGOTIATE_Response negotiateResponse;
            DialectRevision selectedDialect;
            byte[] serverGssToken;

            CheckStatusCode(
                Negotiate(
                1,
                1,
                messageId++,
                clientGuid,
                out selectedDialect,
                out serverGssToken,
                out header,
                out negotiateResponse));

            // 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_Response sessionSetupResponse;

            SspiClientSecurityContext sspiClientGss =
                new SspiClientSecurityContext(
                    securityPackageType,
                    new AccountCredential(domainName, userName, password),
                    Smb2Utility.GetCifsServicePrincipalName(server),
                    ClientSecurityContextAttribute.None,
                    SecurityTargetDataRepresentation.SecurityNativeDrep);

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

            uint status;
            do
            {
                status = client.SessionSetup(
                    1,
                    1,
                    Packet_Header_Flags_Values.NONE,
                    messageId++,
                    sessionId,
                    SESSION_SETUP_Request_Flags.NONE,
                    SESSION_SETUP_Request_SecurityMode_Values.NONE,
                    SESSION_SETUP_Request_Capabilities_Values.NONE,
                    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);

            client.GenerateCryptoKeys(sessionId, sspiClientGss.SessionKey, session_SigningRequired, false);

            TREE_CONNECT_Response treeConnectResponse;

            CheckStatusCode(
                TreeConnect(
                1,
                1,
                headerFlags,
                messageId++,
                sessionId,
                server,
                share,
                out header,
                out treeConnectResponse));

            CREATE_Response createResponse;
            Smb2CreateContextResponse[] serverCreateContexts;

            CheckStatusCode(
                client.Create(
                    1,
                    1,
                    headerFlags,
                    messageId++,
                    sessionId,
                    treeId,
                    file,
                    accessMask,
                    ShareAccess_Values.FILE_SHARE_READ,
                    CreateOptions_Values.NONE,
                    CreateDisposition_Values.FILE_OPEN_IF,
                    File_Attributes.NONE,
                    ImpersonationLevel_Values.Impersonation,
                    SecurityFlags_Values.NONE,
                    RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                    null,
                    out fileId,
                    out serverCreateContexts,
                    out header,
                    out createResponse));
        }
        private SigningFlagType GetSigningFlagType(Packet_Header_Flags_Values flags)
        {
            SigningFlagType signingFlag;

            if (flags.HasFlag(Packet_Header_Flags_Values.FLAGS_SIGNED))
            {
                signingFlag = SigningFlagType.SignedFlagSet;
            }
            else
            {
                signingFlag = SigningFlagType.SignedFlagNotSet;
            }

            return signingFlag;
        }
        /// <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;
        }
示例#25
0
        /// <summary>
        /// Terminate the named pipe transport.
        /// </summary>
        public void Disconnect()
        {
            if (smb2Client == null || !smb2Client.IsConnected)
            {
                return;
            }

            if (fileId.Persistent != 0 || fileId.Volatile != 0)
            {
                var status = smb2Client.Close(
                    creditCharge: 1,
                    creditRequest: 1,
                    flags: defaultFlags,
                    messageId: messageId++,
                    sessionId: sessionId,
                    treeId: treeId,
                    fileId: fileId,
                    closeFlags: Flags_Values.NONE,
                    out _,
                    out _);
                CheckStatusCode(status, nameof(Smb2Client.Close));

                fileId = default(FILEID);
            }

            if (treeId != 0)
            {
                var status = smb2Client.TreeDisconnect(
                    creditCharge: 1,
                    creditRequest: 1,
                    flags: defaultFlags,
                    messageId: messageId++,
                    sessionId: sessionId,
                    treeId: treeId,
                    out _,
                    out _);
                CheckStatusCode(status, nameof(Smb2Client.TreeDisconnect));

                treeId = 0;
            }

            if (sessionId != 0)
            {
                var status = smb2Client.LogOff(
                    creditCharge: 1,
                    creditRequest: 1,
                    flags: defaultFlags,
                    messageId: messageId++,
                    sessionId: sessionId,
                    out _,
                    out _);
                CheckStatusCode(status, nameof(Smb2Client.LogOff));

                sessionId = 0;
            }

            defaultFlags = Packet_Header_Flags_Values.NONE;
            messageId    = 0;
            smb2Client.Disconnect();
            smb2Client = null;
        }