Пример #1
0
        public void TestEncryption()
        {
            byte[] encryptionKey = new byte[] { 0x26, 0x1B, 0x72, 0x35, 0x05, 0x58, 0xF2, 0xE9, 0xDC, 0xF6, 0x13, 0x07, 0x03, 0x83, 0xED, 0xBF };
            byte[] nonce         = new byte[] { 0x66, 0xE6, 0x9A, 0x11, 0x18, 0x92, 0x58, 0x4F, 0xB5, 0xED, 0x52 };
            ulong  sessionID     = 0x8e40014000011;

            byte[] message = new byte[] { 0xFE, 0x53, 0x4D, 0x42, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x40, 0x00,
                                          0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0xFF, 0xFE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x14, 0x00, 0xE4, 0x08, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x31, 0x00, 0x70, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x15, 0x01, 0x00, 0x00, 0x39, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x53, 0x6D, 0x62, 0x33, 0x20, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6F, 0x6E, 0x20,
                                          0x74, 0x65, 0x73, 0x74, 0x69, 0x6E, 0x67 };

            byte[] expectedEncrypted = new byte[] { 0x25, 0xC8, 0xFE, 0xE1, 0x66, 0x05, 0xA4, 0x37, 0x83, 0x2D, 0x1C, 0xD5, 0x2D, 0xA9, 0xF4, 0x64,
                                                    0x53, 0x33, 0x48, 0x2A, 0x17, 0x5F, 0xE5, 0x38, 0x45, 0x63, 0xF4, 0x5F, 0xCD, 0xAF, 0xAE, 0xF3,
                                                    0x8B, 0xC6, 0x2B, 0xA4, 0xD5, 0xC6, 0x28, 0x97, 0x99, 0x66, 0x25, 0xA4, 0x4C, 0x29, 0xBE, 0x56,
                                                    0x58, 0xDE, 0x2E, 0x61, 0x17, 0x58, 0x57, 0x79, 0xE7, 0xB5, 0x9F, 0xFD, 0x97, 0x12, 0x78, 0xD0,
                                                    0x85, 0x80, 0xD7, 0xFA, 0x89, 0x9E, 0x41, 0x0E, 0x91, 0x0E, 0xAB, 0xF5, 0xAA, 0x1D, 0xB4, 0x30,
                                                    0x50, 0xB3, 0x3B, 0x49, 0x18, 0x26, 0x37, 0x75, 0x9A, 0xC1, 0x5D, 0x84, 0xBF, 0xCD, 0xF5, 0xB6,
                                                    0xB2, 0x38, 0x99, 0x3C, 0x0F, 0x4C, 0xF4, 0xD6, 0x01, 0x20, 0x23, 0xF6, 0xC6, 0x27, 0x29, 0x70,
                                                    0x75, 0xD8, 0x4B, 0x78, 0x03, 0x91, 0x2D, 0x0A, 0x96, 0x39, 0x63, 0x44, 0x53, 0x59, 0x5E, 0xF3,
                                                    0xE3, 0x3F, 0xFE, 0x4E, 0x7A, 0xC2, 0xAB };

            byte[] expectedSignature = new byte[] { 0x81, 0xA2, 0x86, 0x53, 0x54, 0x15, 0x44, 0x5D, 0xAE, 0x39, 0x39, 0x21, 0xE4, 0x4F, 0xA4, 0x2E };

            byte[] signature;
            byte[] encryptedMessage = SMB2Cryptography.EncryptMessage(encryptionKey, nonce, message, sessionID, out signature);

            Assert.True(ByteUtils.AreByteArraysEqual(expectedEncrypted, encryptedMessage));
            // The associated data in this sample include non-zero nonce padding so we ignore signature validation
        }
Пример #2
0
        public void TestDecryption()
        {
            byte[] decryptionKey = new byte[] { 0x8F, 0xE2, 0xB5, 0x7E, 0xC3, 0x4D, 0x2D, 0xB5, 0xB1, 0xA9, 0x72, 0x7F, 0x52, 0x6B, 0xBD, 0xB5 };

            byte[] transformedPacket = new byte[] { 0xFD, 0x53, 0x4D, 0x42, 0xA6, 0x01, 0x55, 0x30, 0xA1, 0x8F, 0x6D, 0x9A, 0xFF, 0xE2, 0x2A, 0xFA,
                                                    0xE8, 0xE6, 0x64, 0x84, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x14,
                                                    0x00, 0xE4, 0x08, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x14,
                                                    0x00, 0xE4, 0x08, 0x00, 0xDB, 0xF4, 0x64, 0x35, 0xC5, 0xF1, 0x41, 0x69, 0x29, 0x3C, 0xE0, 0x79,
                                                    0xE3, 0x44, 0x47, 0x9B, 0xF6, 0x70, 0x22, 0x7E, 0x49, 0x87, 0x3F, 0x45, 0x86, 0x72, 0xC3, 0x09,
                                                    0x8D, 0xAC, 0x46, 0x7D, 0xD5, 0x80, 0x9F, 0x36, 0x9D, 0x67, 0x40, 0x91, 0x66, 0x51, 0x57, 0x87,
                                                    0x14, 0x83, 0xE0, 0x1F, 0x7B, 0xEC, 0xD0, 0x20, 0x64, 0xEA, 0xC3, 0xE2, 0x35, 0xF9, 0x13, 0x66,
                                                    0x8B, 0xBC, 0x2F, 0x09, 0x79, 0x80, 0xD4, 0xB3, 0x78, 0xF1, 0x99, 0x3E, 0xFF, 0x6E, 0x60, 0xD1,
                                                    0x77, 0x30, 0x9E, 0x5B };

            byte[] expectedDecryptedMessage = new byte[] { 0xFE, 0x53, 0x4D, 0x42, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x21, 0x00,
                                                           0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                                           0xFF, 0xFE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x14, 0x00, 0xE4, 0x08, 0x00,
                                                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                                           0x11, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

            SMB2TransformHeader transformHeader = new SMB2TransformHeader(transformedPacket, 0);

            byte[] encryptedMessage = ByteReader.ReadBytes(transformedPacket, SMB2TransformHeader.Length, (int)transformHeader.OriginalMessageSize);
            byte[] decryptedMessage = SMB2Cryptography.DecryptMessage(decryptionKey, transformHeader, encryptedMessage);

            Assert.True(ByteUtils.AreByteArraysEqual(expectedDecryptedMessage, decryptedMessage));
        }
Пример #3
0
        public NTStatus Login(string domainName, string userName, string password, AuthenticationMethod authenticationMethod)
        {
            if (!m_isConnected)
            {
                throw new InvalidOperationException("A connection must be successfully established before attempting login");
            }

            byte[] negotiateMessage = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod);
            if (negotiateMessage == null)
            {
                return(NTStatus.SEC_E_INVALID_TOKEN);
            }

            SessionSetupRequest request = new SessionSetupRequest();

            request.SecurityMode   = SecurityMode.SigningEnabled;
            request.SecurityBuffer = negotiateMessage;
            TrySendCommand(request);
            SMB2Command response = WaitForCommand(SMB2CommandName.SessionSetup);

            if (response != null)
            {
                if (response.Header.Status == NTStatus.STATUS_MORE_PROCESSING_REQUIRED && response is SessionSetupResponse)
                {
                    byte[] authenticateMessage = NTLMAuthenticationHelper.GetAuthenticateMessage(((SessionSetupResponse)response).SecurityBuffer, domainName, userName, password, authenticationMethod, out m_sessionKey);
                    if (authenticateMessage == null)
                    {
                        return(NTStatus.SEC_E_INVALID_TOKEN);
                    }

                    m_sessionID            = response.Header.SessionID;
                    request                = new SessionSetupRequest();
                    request.SecurityMode   = SecurityMode.SigningEnabled;
                    request.SecurityBuffer = authenticateMessage;
                    TrySendCommand(request);
                    response = WaitForCommand(SMB2CommandName.SessionSetup);
                    if (response != null)
                    {
                        m_isLoggedIn = (response.Header.Status == NTStatus.STATUS_SUCCESS);
                        if (m_isLoggedIn)
                        {
                            m_signingKey = SMB2Cryptography.GenerateSigningKey(m_sessionKey, m_dialect, null);
                            if (m_dialect == SMB2Dialect.SMB300)
                            {
                                m_encryptSessionData = (((SessionSetupResponse)response).SessionFlags & SessionFlags.EncryptData) > 0;
                                m_encryptionKey      = SMB2Cryptography.GenerateClientEncryptionKey(m_sessionKey, SMB2Dialect.SMB300, null);
                                m_decryptionKey      = SMB2Cryptography.GenerateClientDecryptionKey(m_sessionKey, SMB2Dialect.SMB300, null);
                            }
                        }
                        return(response.Header.Status);
                    }
                }
                else
                {
                    return(response.Header.Status);
                }
            }
            return(NTStatus.STATUS_INVALID_SMB);
        }
Пример #4
0
        public void TestDecryptionKeyGeneration()
        {
            byte[] sessionKey = new byte[] { 0xB4, 0x54, 0x67, 0x71, 0xB5, 0x15, 0xF7, 0x66, 0xA8, 0x67, 0x35, 0x53, 0x2D, 0xD6, 0xC4, 0xF0 };

            byte[] decryptionKey = SMB2Cryptography.GenerateClientDecryptionKey(sessionKey, SMB2Dialect.SMB300, null);

            byte[] expectedDecryptionKey = new byte[] { 0x8F, 0xE2, 0xB5, 0x7E, 0xC3, 0x4D, 0x2D, 0xB5, 0xB1, 0xA9, 0x72, 0x7F, 0x52, 0x6B, 0xBD, 0xB5 };

            Assert.True(ByteUtils.AreByteArraysEqual(expectedDecryptionKey, decryptionKey));
        }
Пример #5
0
        public void TestEncryptionKeyGeneration()
        {
            byte[] sessionKey = new byte[] { 0xB4, 0x54, 0x67, 0x71, 0xB5, 0x15, 0xF7, 0x66, 0xA8, 0x67, 0x35, 0x53, 0x2D, 0xD6, 0xC4, 0xF0 };

            byte[] expectedEncryptionKey = new byte[] { 0x26, 0x1B, 0x72, 0x35, 0x05, 0x58, 0xF2, 0xE9, 0xDC, 0xF6, 0x13, 0x07, 0x03, 0x83, 0xED, 0xBF };

            byte[] encryptionKey = SMB2Cryptography.GenerateClientEncryptionKey(sessionKey, SMB2Dialect.SMB300, null);

            Assert.True(ByteUtils.AreByteArraysEqual(expectedEncryptionKey, encryptionKey));
        }
Пример #6
0
        internal void TrySendCommand(SMB2Command request, bool encryptData)
        {
            if (m_dialect == SMB2Dialect.SMB202 || m_transport == SMBTransportType.NetBiosOverTCP)
            {
                request.Header.CreditCharge = 0;
                request.Header.Credits      = 1;
                m_availableCredits         -= 1;
            }
            else
            {
                if (request.Header.CreditCharge == 0)
                {
                    request.Header.CreditCharge = 1;
                }

                if (m_availableCredits < request.Header.CreditCharge)
                {
                    throw new Exception("Not enough credits");
                }

                m_availableCredits -= request.Header.CreditCharge;

                if (m_availableCredits < DesiredCredits)
                {
                    request.Header.Credits += (ushort)(DesiredCredits - m_availableCredits);
                }
            }

            request.Header.MessageID = m_messageID;
            request.Header.SessionID = m_sessionID;
            // [MS-SMB2] If the client encrypts the message [..] then the client MUST set the Signature field of the SMB2 header to zero
            if (m_signingRequired && !encryptData)
            {
                request.Header.IsSigned = (m_sessionID != 0 && ((request.CommandName == SMB2CommandName.TreeConnect || request.Header.TreeID != 0) ||
                                                                (m_dialect == SMB2Dialect.SMB300 && request.CommandName == SMB2CommandName.Logoff)));
                if (request.Header.IsSigned)
                {
                    request.Header.Signature = new byte[16]; // Request could be reused
                    byte[] buffer    = request.GetBytes();
                    byte[] signature = SMB2Cryptography.CalculateSignature(m_signingKey, m_dialect, buffer, 0, buffer.Length);
                    // [MS-SMB2] The first 16 bytes of the hash MUST be copied into the 16-byte signature field of the SMB2 Header.
                    request.Header.Signature = ByteReader.ReadBytes(signature, 0, 16);
                }
            }
            TrySendCommand(m_clientSocket, request, encryptData ? m_encryptionKey : null);
            if (m_dialect == SMB2Dialect.SMB202 || m_transport == SMBTransportType.NetBiosOverTCP)
            {
                m_messageID++;
            }
            else
            {
                m_messageID += request.Header.CreditCharge;
            }
        }
Пример #7
0
        public static void TrySendCommand(Socket socket, SMB2Command request, byte[] encryptionKey)
        {
            SessionMessagePacket packet = new SessionMessagePacket();

            if (encryptionKey != null)
            {
                byte[] requestBytes = request.GetBytes();
                packet.Trailer = SMB2Cryptography.TransformMessage(encryptionKey, requestBytes, request.Header.SessionID);
            }
            else
            {
                packet.Trailer = request.GetBytes();
            }
            TrySendPacket(socket, packet);
        }
Пример #8
0
        public void TestSMB210SignatureCalculation()
        {
            byte[] exportedSessionKey = new byte[] { 0x04, 0xE7, 0x07, 0x57, 0x1F, 0x8E, 0x03, 0x53, 0xB7, 0x7A, 0x94, 0xC3, 0x65, 0x3B, 0x87, 0xB5 };

            byte[] message = new byte[] { 0xfe, 0x53, 0x4d, 0x42, 0x40, 0x00, 0x01, 0x00, 0x28, 0x01, 0x00, 0xc0, 0x0b, 0x00, 0x07, 0x00,
                                          0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0xff, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
                                          0xa1, 0x64, 0xff, 0xe5, 0x3d, 0x68, 0x11, 0x98, 0x1f, 0x38, 0x67, 0x72, 0xe3, 0x87, 0xe0, 0x6f,
                                          0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff };

            ByteWriter.WriteBytes(message, 48, new byte[16]);

            byte[] signature = SMB2Cryptography.CalculateSignature(exportedSessionKey, SMB2Dialect.SMB210, message, 0, message.Length);
            signature = ByteReader.ReadBytes(signature, 0, 16);
            byte[] expected = new byte[] { 0xa1, 0x64, 0xff, 0xe5, 0x3d, 0x68, 0x11, 0x98, 0x1f, 0x38, 0x67, 0x72, 0xe3, 0x87, 0xe0, 0x6f };
            Assert.True(ByteUtils.AreByteArraysEqual(signature, expected));
        }
Пример #9
0
        public void TestSMB202SignatureCalculation()
        {
            byte[] exportedSessionKey = new byte[] { 0xD3, 0x83, 0x54, 0xCC, 0x37, 0x43, 0x39, 0xF0, 0x52, 0x4F, 0x78, 0x91, 0x46, 0x78, 0x99, 0x21 };

            byte[] message = new byte[] { 0xfe, 0x53, 0x4d, 0x42, 0x40, 0x00, 0x01, 0x00, 0x28, 0x01, 0x00, 0xc0, 0x0b, 0x00, 0x07, 0x00,
                                          0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0xff, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
                                          0xfb, 0xd2, 0x84, 0x34, 0x03, 0x24, 0xc6, 0x2f, 0xbe, 0xbb, 0x65, 0xdd, 0x10, 0x51, 0xf3, 0xae,
                                          0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff };

            ByteWriter.WriteBytes(message, 48, new byte[16]);

            byte[] signature = SMB2Cryptography.CalculateSignature(exportedSessionKey, SMB2Dialect.SMB202, message, 0, message.Length);
            signature = ByteReader.ReadBytes(signature, 0, 16);
            byte[] expected = new byte[] { 0xfb, 0xd2, 0x84, 0x34, 0x03, 0x24, 0xc6, 0x2f, 0xbe, 0xbb, 0x65, 0xdd, 0x10, 0x51, 0xf3, 0xae };
            Assert.True(ByteUtils.AreByteArraysEqual(signature, expected));
        }
Пример #10
0
        public void TestSMB300SignatureCalculation()
        {
            byte[] exportedSessionKey = new byte[] { 0x35, 0x40, 0x24, 0xCB, 0xCA, 0x4F, 0x94, 0xAA, 0x51, 0xD4, 0x03, 0x3E, 0x6E, 0x9B, 0x2F, 0x98 };
            byte[] signingKey         = SMB2Cryptography.GenerateSigningKey(exportedSessionKey, SMB2Dialect.SMB300, null);

            byte[] message = new byte[] { 0xFE, 0x53, 0x4D, 0x42, 0x40, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
                                          0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x20, 0x00, 0x70, 0x00, 0x00,
                                          0x73, 0xF2, 0xCC, 0x56, 0x09, 0x3E, 0xD2, 0xB5, 0xD7, 0x10, 0x66, 0x6C, 0xE4, 0x28, 0x2D, 0xD1,
                                          0x09, 0x00, 0x00, 0x00, 0x48, 0x00, 0x09, 0x00, 0xA1, 0x07, 0x30, 0x05, 0xA0, 0x03, 0x0A, 0x01, 0x00 };

            ByteWriter.WriteBytes(message, 48, new byte[16]);

            byte[] signature = SMB2Cryptography.CalculateSignature(signingKey, SMB2Dialect.SMB300, message, 0, message.Length);
            signature = ByteReader.ReadBytes(signature, 0, 16);
            byte[] expected = new byte[] { 0x73, 0xF2, 0xCC, 0x56, 0x09, 0x3E, 0xD2, 0xB5, 0xD7, 0x10, 0x66, 0x6C, 0xE4, 0x28, 0x2D, 0xD1 };
            Assert.True(ByteUtils.AreByteArraysEqual(signature, expected));
        }
Пример #11
0
        internal static SMB2Command GetSessionSetupResponse(SessionSetupRequest request, GSSProvider securityProvider, SMB2ConnectionState state)
        {
            // [MS-SMB2] Windows [..] will also accept raw Kerberos messages and implicit NTLM messages as part of GSS authentication.
            SessionSetupResponse response = new SessionSetupResponse();

            byte[]   outputToken;
            NTStatus status = securityProvider.AcceptSecurityContext(ref state.AuthenticationContext, request.SecurityBuffer, out outputToken);

            if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.SEC_I_CONTINUE_NEEDED)
            {
                string userName    = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string;
                string domainName  = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string;
                string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string;
                string osVersion   = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string;
                state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), NTStatus: {4}", userName, domainName, machineName, osVersion, status);
                return(new ErrorResponse(request.CommandName, status));
            }

            if (outputToken != null)
            {
                response.SecurityBuffer = outputToken;
            }

            // According to [MS-SMB2] 3.3.5.5.3, response.Header.SessionID must be allocated if the server returns STATUS_MORE_PROCESSING_REQUIRED
            if (request.Header.SessionID == 0)
            {
                ulong?sessionID = state.AllocateSessionID();
                if (!sessionID.HasValue)
                {
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_TOO_MANY_SESSIONS));
                }
                response.Header.SessionID = sessionID.Value;
            }

            if (status == NTStatus.SEC_I_CONTINUE_NEEDED)
            {
                response.Header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED;
            }
            else // status == STATUS_SUCCESS
            {
                string userName    = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string;
                string domainName  = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string;
                string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string;
                string osVersion   = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string;
                byte[] sessionKey  = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.SessionKey) as byte[];
                object accessToken = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.AccessToken);
                bool?  isGuest     = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.IsGuest) as bool?;
                if (!isGuest.HasValue || !isGuest.Value)
                {
                    state.LogToServer(Severity.Information, "Session Setup: User '{0}' authenticated successfully (Domain: '{1}', Workstation: '{2}', OS version: '{3}').", userName, domainName, machineName, osVersion);
                    bool        signingRequired = (request.SecurityMode & SecurityMode.SigningRequired) > 0;
                    SMB2Dialect smb2Dialect     = SMBServer.ToSMB2Dialect(state.Dialect);
                    byte[]      signingKey      = SMB2Cryptography.GenerateSigningKey(sessionKey, smb2Dialect, null);
                    state.CreateSession(request.Header.SessionID, userName, machineName, sessionKey, accessToken, signingRequired, signingKey);
                }
                else
                {
                    state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), logged in as guest.", userName, domainName, machineName, osVersion);
                    state.CreateSession(request.Header.SessionID, "Guest", machineName, sessionKey, accessToken, false, null);
                    response.SessionFlags = SessionFlags.IsGuest;
                }
            }
            return(response);
        }
Пример #12
0
        private void ProcessPacket(SessionPacket packet, ConnectionState state)
        {
            if (packet is SessionMessagePacket)
            {
                byte[] messageBytes;
                if (m_dialect == SMB2Dialect.SMB300 && SMB2TransformHeader.IsTransformHeader(packet.Trailer, 0))
                {
                    SMB2TransformHeader transformHeader = new SMB2TransformHeader(packet.Trailer, 0);
                    byte[] encryptedMessage             = ByteReader.ReadBytes(packet.Trailer, SMB2TransformHeader.Length, (int)transformHeader.OriginalMessageSize);
                    messageBytes = SMB2Cryptography.DecryptMessage(m_decryptionKey, transformHeader, encryptedMessage);
                }
                else
                {
                    messageBytes = packet.Trailer;
                }

                SMB2Command command;
                try
                {
                    command = SMB2Command.ReadResponse(messageBytes, 0);
                }
                catch (Exception ex)
                {
                    Log("Invalid SMB2 response: " + ex.Message);
                    state.ClientSocket.Close();
                    m_isConnected = false;
                    return;
                }

                m_availableCredits += command.Header.Credits;

                if (m_transport == SMBTransportType.DirectTCPTransport && command is NegotiateResponse)
                {
                    NegotiateResponse negotiateResponse = (NegotiateResponse)command;
                    if ((negotiateResponse.Capabilities & Capabilities.LargeMTU) > 0)
                    {
                        // [MS-SMB2] 3.2.5.1 Receiving Any Message - If the message size received exceeds Connection.MaxTransactSize, the client MUST disconnect the connection.
                        // Note: Windows clients do not enforce the MaxTransactSize value, we add 256 bytes.
                        int maxPacketSize = SessionPacket.HeaderLength + (int)Math.Min(negotiateResponse.MaxTransactSize, ClientMaxTransactSize) + 256;
                        if (maxPacketSize > state.ReceiveBuffer.Buffer.Length)
                        {
                            state.ReceiveBuffer.IncreaseBufferSize(maxPacketSize);
                        }
                    }
                }

                // [MS-SMB2] 3.2.5.1.2 - If the MessageId is 0xFFFFFFFFFFFFFFFF, this is not a reply to a previous request,
                // and the client MUST NOT attempt to locate the request, but instead process it as follows:
                // If the command field in the SMB2 header is SMB2 OPLOCK_BREAK, it MUST be processed as specified in 3.2.5.19.
                // Otherwise, the response MUST be discarded as invalid.
                if (command.Header.MessageID != 0xFFFFFFFFFFFFFFFF || command.Header.Command == SMB2CommandName.OplockBreak)
                {
                    lock (m_incomingQueueLock)
                    {
                        m_incomingQueue.Add(command);
                        m_incomingQueueEventHandle.Set();
                    }
                }
            }
            else if ((packet is PositiveSessionResponsePacket || packet is NegativeSessionResponsePacket) && m_transport == SMBTransportType.NetBiosOverTCP)
            {
                m_sessionResponsePacket = packet;
                m_sessionResponseEventHandle.Set();
            }
            else if (packet is SessionKeepAlivePacket && m_transport == SMBTransportType.NetBiosOverTCP)
            {
                // [RFC 1001] NetBIOS session keep alives do not require a response from the NetBIOS peer
            }
            else
            {
                Log("Inappropriate NetBIOS session packet");
                state.ClientSocket.Close();
            }
        }