internal/honeypot/rdp/rdp_enhanced_test.go

package rdp

import (
	"fmt"
	"log/slog"
	"net"
	"os"
	"testing"
	"time"

	"honeypot/internal/logger"
	"honeypot/internal/types"
)

type mockSink struct {
	events []types.LogEvent
}

func (s *mockSink) EmitEvent(e types.LogEvent) {
	s.events = append(s.events, e)
}

func TestRDPLogging(t *testing.T) {
	sink := &mockSink{}
	logger.RegisterEventSink(sink)

	l := slog.New(slog.NewJSONHandler(os.Stdout, nil))
	hp := New(Config{
		ListenAddr: "127.0.0.1",
		Ports:      []uint16{0},
	})
	hp.(*rdpHoneypot).logger = l

	t.Run("RandomData", func(t *testing.T) {
		sink.events = nil
		c1, c2 := net.Pipe()
		go hp.(*rdpHoneypot).handleConn(c1)
		c2.SetDeadline(time.Now().Add(time.Second))
		fmt.Fprintf(c2, "hello world")
		c2.Close()
		time.Sleep(100 * time.Millisecond)
		found := false
		for _, e := range sink.events {
			if e.Event == types.EventTCPPacket && e.Fields["message"] == "non-rdp protocol detected" {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("expected non-rdp protocol detected")
		}
	})

	t.Run("TLSHandshake", func(t *testing.T) {
		sink.events = nil
		c1, c2 := net.Pipe()
		go hp.(*rdpHoneypot).handleConn(c1)
		c2.Write([]byte{0x16, 0x03, 0x01, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01, 0x00})
		c2.Close()
		time.Sleep(100 * time.Millisecond)
		found := false
		for _, e := range sink.events {
			if e.Event == types.EventTLSHandshake {
				found = true
				break
			}
		}
		if !found {
			t.Errorf("expected TLS handshake")
		}
	})

	t.Run("DeferredConnectionOnly", func(t *testing.T) {
		sink.events = nil
		c1, _ := net.Pipe()
		// Closing c1 will make sure handleConn returns WITHOUT logging an event if we don't send anything
		go func() {
			time.Sleep(50 * time.Millisecond)
			c1.Close()
		}()
		hp.(*rdpHoneypot).handleConn(c1)

		time.Sleep(100 * time.Millisecond)
		if len(sink.events) != 1 {
			t.Errorf("expected 1 event, got %d: %v", len(sink.events), sink.events)
			return
		}
		if sink.events[0].Fields["message"] != "connection closed without rdp events" {
			t.Errorf("expected deferred connection log, got: %v", sink.events[0].Fields["message"])
		}
	})
}