コード例 #1
0
        private void ProcessPacket(SessionPacket packet, ref ConnectionState state)
        {
            if (packet is SessionRequestPacket && m_transport == SMBTransportType.NetBiosOverTCP)
            {
                PositiveSessionResponsePacket response = new PositiveSessionResponsePacket();
                state.SendQueue.Enqueue(response);
            }
            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 if (packet is SessionMessagePacket)
            {
                // Note: To be compatible with SMB2 specifications, we must accept SMB_COM_NEGOTIATE.
                // We will disconnect the connection if m_enableSMB1 == false and the client does not support SMB2.
                bool acceptSMB1 = (state.Dialect == SMBDialect.NotSet || state.Dialect == SMBDialect.NTLM012);
                bool acceptSMB2 = (m_enableSMB2 && (state.Dialect == SMBDialect.NotSet || state.Dialect == SMBDialect.SMB202 || state.Dialect == SMBDialect.SMB210));

                if (SMB1Header.IsValidSMB1Header(packet.Trailer))
                {
                    if (!acceptSMB1)
                    {
                        state.LogToServer(Severity.Verbose, "Rejected SMB1 message");
                        state.ClientSocket.Close();
                        return;
                    }

                    SMB1Message message = null;
                    try
                    {
                        message = SMB1Message.GetSMB1Message(packet.Trailer);
                    }
                    catch (Exception ex)
                    {
                        state.LogToServer(Severity.Warning, "Invalid SMB1 message: " + ex.Message);
                        state.ClientSocket.Close();
                        return;
                    }
                    state.LogToServer(Severity.Verbose, "SMB1 message received: {0} requests, First request: {1}, Packet length: {2}", message.Commands.Count, message.Commands[0].CommandName.ToString(), packet.Length);
                    if (state.Dialect == SMBDialect.NotSet && m_enableSMB2)
                    {
                        // Check if the client supports SMB 2
                        List <string> smb2Dialects = SMB2.NegotiateHelper.FindSMB2Dialects(message);
                        if (smb2Dialects.Count > 0)
                        {
                            SMB2Command response = SMB2.NegotiateHelper.GetNegotiateResponse(smb2Dialects, m_securityProvider, state, m_serverGuid, m_serverStartTime);
                            if (state.Dialect != SMBDialect.NotSet)
                            {
                                state = new SMB2ConnectionState(state);
                                m_connectionManager.AddConnection(state);
                            }
                            EnqueueResponse(state, response);
                            return;
                        }
                    }

                    if (m_enableSMB1)
                    {
                        ProcessSMB1Message(message, ref state);
                    }
                    else
                    {
                        // [MS-SMB2] 3.3.5.3.2 If the string is not present in the dialect list and the server does not implement SMB,
                        // the server MUST disconnect the connection [..] without sending a response.
                        state.LogToServer(Severity.Verbose, "Rejected SMB1 message");
                        state.ClientSocket.Close();
                    }
                }
                else if (SMB2Header.IsValidSMB2Header(packet.Trailer))
                {
                    if (!acceptSMB2)
                    {
                        state.LogToServer(Severity.Verbose, "Rejected SMB2 message");
                        state.ClientSocket.Close();
                        return;
                    }

                    List <SMB2Command> requestChain;
                    try
                    {
                        requestChain = SMB2Command.ReadRequestChain(packet.Trailer, 0);
                    }
                    catch (Exception ex)
                    {
                        state.LogToServer(Severity.Warning, "Invalid SMB2 request chain: " + ex.Message);
                        state.ClientSocket.Close();
                        return;
                    }
                    state.LogToServer(Severity.Verbose, "SMB2 request chain received: {0} requests, First request: {1}, Packet length: {2}", requestChain.Count, requestChain[0].CommandName.ToString(), packet.Length);
                    ProcessSMB2RequestChain(requestChain, ref state);
                }
                else
                {
                    state.LogToServer(Severity.Warning, "Invalid SMB message");
                    state.ClientSocket.Close();
                }
            }
            else
            {
                state.LogToServer(Severity.Warning, "Invalid NetBIOS packet");
                state.ClientSocket.Close();
                return;
            }
        }
コード例 #2
0
        // This method accepts new connections
        private void ConnectRequestCallback(IAsyncResult ar)
        {
            Socket listenerSocket = (Socket)ar.AsyncState;

            Socket clientSocket;

            try
            {
                clientSocket = listenerSocket.EndAccept(ar);
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (SocketException ex)
            {
                const int WSAECONNRESET = 10054; // The client may have closed the connection before we start to process the connection request.
                const int WSAETIMEDOUT  = 10060; // The client did not properly respond after a period of time.
                // When we get WSAECONNRESET or WSAETIMEDOUT, we have to continue to accept other connection requests.
                // See http://stackoverflow.com/questions/7704417/socket-endaccept-error-10054
                if (ex.ErrorCode == WSAECONNRESET || ex.ErrorCode == WSAETIMEDOUT)
                {
                    listenerSocket.BeginAccept(ConnectRequestCallback, listenerSocket);
                }
                Log(Severity.Debug, "Connection request error {0}", ex.ErrorCode);
                return;
            }

            // Windows will set the TCP keepalive timeout to 120 seconds for an SMB connection
            SocketUtils.SetKeepAlive(clientSocket, TimeSpan.FromMinutes(2));
            // Disable the Nagle Algorithm for this tcp socket:
            clientSocket.NoDelay = true;
            IPEndPoint clientEndPoint = (IPEndPoint)clientSocket.RemoteEndPoint;
            EventHandler <ConnectionRequestEventArgs> handler = ConnectionRequested;
            bool acceptConnection = true;

            if (handler != null)
            {
                ConnectionRequestEventArgs connectionRequestArgs = new ConnectionRequestEventArgs(clientEndPoint);
                handler(this, connectionRequestArgs);
                acceptConnection = connectionRequestArgs.Accept;
            }

            if (acceptConnection)
            {
                ConnectionState state = new ConnectionState(clientSocket, clientEndPoint, Log);
                state.LogToServer(Severity.Verbose, "New connection request accepted");
                Thread senderThread = new Thread(delegate()
                {
                    ProcessSendQueue(state);
                });
                senderThread.IsBackground = true;
                senderThread.Start();

                try
                {
                    // Direct TCP transport packet is actually an NBT Session Message Packet,
                    // So in either case (NetBios over TCP or Direct TCP Transport) we will receive an NBT packet.
                    clientSocket.BeginReceive(state.ReceiveBuffer.Buffer, state.ReceiveBuffer.WriteOffset, state.ReceiveBuffer.AvailableLength, 0, ReceiveCallback, state);
                }
                catch (ObjectDisposedException)
                {
                }
                catch (SocketException)
                {
                }
            }
            else
            {
                Log(Severity.Verbose, "[{0}:{1}] New connection request rejected", clientEndPoint.Address, clientEndPoint.Port);
                clientSocket.Close();
            }

            listenerSocket.BeginAccept(ConnectRequestCallback, listenerSocket);
        }
コード例 #3
0
        private void ReceiveCallback(IAsyncResult result)
        {
            ConnectionState state        = (ConnectionState)result.AsyncState;
            Socket          clientSocket = state.ClientSocket;

            if (!m_listening)
            {
                clientSocket.Close();
                return;
            }

            int numberOfBytesReceived;

            try
            {
                numberOfBytesReceived = clientSocket.EndReceive(result);
            }
            catch (ObjectDisposedException)
            {
                state.LogToServer(Severity.Debug, "The connection was terminated");
                m_connectionManager.ReleaseConnection(state);
                return;
            }
            catch (SocketException ex)
            {
                const int WSAECONNRESET = 10054;
                if (ex.ErrorCode == WSAECONNRESET)
                {
                    state.LogToServer(Severity.Debug, "The connection was forcibly closed by the remote host");
                }
                else
                {
                    state.LogToServer(Severity.Debug, "The connection was terminated, Socket error code: {0}", ex.ErrorCode);
                }
                m_connectionManager.ReleaseConnection(state);
                return;
            }

            if (numberOfBytesReceived == 0)
            {
                state.LogToServer(Severity.Debug, "The client closed the connection");
                m_connectionManager.ReleaseConnection(state);
                return;
            }

            state.UpdateLastReceiveDT();
            NBTConnectionReceiveBuffer receiveBuffer = state.ReceiveBuffer;

            receiveBuffer.SetNumberOfBytesReceived(numberOfBytesReceived);
            ProcessConnectionBuffer(ref state);

            if (clientSocket.Connected)
            {
                try
                {
                    clientSocket.BeginReceive(state.ReceiveBuffer.Buffer, state.ReceiveBuffer.WriteOffset, state.ReceiveBuffer.AvailableLength, 0, ReceiveCallback, state);
                }
                catch (ObjectDisposedException)
                {
                    m_connectionManager.ReleaseConnection(state);
                }
                catch (SocketException)
                {
                    m_connectionManager.ReleaseConnection(state);
                }
            }
        }
コード例 #4
0
        private void ReceiveCallback(object sender, SocketAsyncEventArgs result)
        {
            ConnectionState state        = (ConnectionState)result.UserToken;
            Socket          clientSocket = state.ClientSocket;

            if (!m_listening)
            {
                clientSocket.Dispose();
                return;
            }

            int numberOfBytesReceived;

            try
            {
                numberOfBytesReceived = result.BytesTransferred;
            }
            catch (ObjectDisposedException)
            {
                state.LogToServer(Severity.Debug, "The connection was terminated");
                m_connectionManager.ReleaseConnection(state);
                return;
            }
            catch (SocketException ex)
            {
                ///const int WSAECONNRESET = 10054;
                if (ex.SocketErrorCode == SocketError.ConnectionReset)
                {
                    state.LogToServer(Severity.Debug, "The connection was forcibly closed by the remote host");
                }
                else
                {
                    state.LogToServer(Severity.Debug, "The connection was terminated, Socket error code: {0}", ex.SocketErrorCode);
                }
                m_connectionManager.ReleaseConnection(state);
                return;
            }

            if (numberOfBytesReceived == 0)
            {
                state.LogToServer(Severity.Debug, "The client closed the connection");
                m_connectionManager.ReleaseConnection(state);
                return;
            }

            state.UpdateLastReceiveDT();
            NBTConnectionReceiveBuffer receiveBuffer = state.ReceiveBuffer;

            receiveBuffer.SetNumberOfBytesReceived(numberOfBytesReceived);
            ProcessConnectionBuffer(ref state);

            if (clientSocket.Connected)
            {
                try
                {
                    SocketAsyncEventArgs args = new SocketAsyncEventArgs();
                    args.SetBuffer(state.ReceiveBuffer.Buffer, state.ReceiveBuffer.WriteOffset, state.ReceiveBuffer.AvailableLength);
                    args.Completed += ReceiveCallback;
                    args.UserToken  = state;
                    //m_currentAsyncResult =
                    if (!clientSocket.ReceiveAsync(args))
                    {
                        ReceiveCallback(sender, args);
                    }
                }
                catch (ObjectDisposedException)
                {
                    m_connectionManager.ReleaseConnection(state);
                }
                catch (SocketException)
                {
                    m_connectionManager.ReleaseConnection(state);
                }
            }
        }