1+ package io .sentrius .sso .core .services ;
2+
3+ import io .sentrius .sso .automation .auditing .Trigger ;
4+ import io .sentrius .sso .automation .auditing .TriggerAction ;
5+ import io .sentrius .sso .core .integrations .ssh .DataSession ;
6+ import io .sentrius .sso .core .model .ConnectedSystem ;
7+ import io .sentrius .sso .core .services .security .CryptoService ;
8+ import io .sentrius .sso .core .services .terminal .SessionTrackingService ;
9+ import io .sentrius .sso .protobuf .Session ;
10+ import lombok .RequiredArgsConstructor ;
11+ import lombok .extern .slf4j .Slf4j ;
12+ import org .springframework .beans .factory .annotation .Qualifier ;
13+ import org .springframework .scheduling .annotation .Async ;
14+ import org .springframework .stereotype .Service ;
15+ import org .springframework .web .socket .TextMessage ;
16+
17+ import java .io .IOException ;
18+ import java .security .GeneralSecurityException ;
19+ import java .util .Base64 ;
20+ import java .util .HashMap ;
21+ import java .util .Map ;
22+ import java .util .concurrent .ConcurrentHashMap ;
23+ import java .util .concurrent .ConcurrentMap ;
24+ import java .util .concurrent .Executor ;
25+ import java .util .concurrent .TimeUnit ;
26+
27+ /**
28+ * RDP listener service that monitors and manages RDP sessions.
29+ * Similar to SshListenerService but adapted for RDP protocol.
30+ */
31+ @ Slf4j
32+ @ Service
33+ @ RequiredArgsConstructor
34+ public class RdpListenerService {
35+
36+ private final SessionTrackingService sessionTrackingService ;
37+ private final CryptoService cryptoService ;
38+
39+ @ Qualifier ("rdpTaskExecutor" ) // Use RDP-specific executor
40+ private final Executor taskExecutor ;
41+
42+ private final ConcurrentMap <String , DataSession > activeSessions = new ConcurrentHashMap <>();
43+
44+ public void startAuditingSession (String terminalSessionId , DataSession session ) throws GeneralSecurityException {
45+ var sessionIdStr = cryptoService .decrypt (terminalSessionId );
46+ var sessionIdLong = Long .parseLong (sessionIdStr );
47+
48+ log .info ("Starting to audit RDP session: {}" , terminalSessionId );
49+ activeSessions .putIfAbsent (terminalSessionId , session );
50+ }
51+
52+ public void endAuditingSession (String terminalSessionId ) throws GeneralSecurityException {
53+ log .info ("Ending RDP audit session: {}" , terminalSessionId );
54+ activeSessions .remove (terminalSessionId );
55+ }
56+
57+ public void startListeningToRdpServer (String terminalSessionId , DataSession session ) throws GeneralSecurityException {
58+ var sessionIdStr = cryptoService .decrypt (terminalSessionId );
59+ var sessionIdLong = Long .parseLong (sessionIdStr );
60+
61+ var connectedSystem = sessionTrackingService .getConnectedSession (sessionIdLong );
62+
63+ log .info ("Starting to listen to RDP server for session: {}" , terminalSessionId );
64+
65+ activeSessions .putIfAbsent (terminalSessionId , session );
66+ connectedSystem .setWebsocketSessionId (session .getId ());
67+
68+ taskExecutor .execute (() -> {
69+ log .info ("Listening to RDP server for session: {}" , terminalSessionId );
70+ while (!Thread .currentThread ().isInterrupted () &&
71+ activeSessions .get (terminalSessionId ) != null &&
72+ !connectedSystem .getSession ().getClosed ()) {
73+ try {
74+ // Logic for receiving data from RDP server
75+ var rdpData = sessionTrackingService .getOutput (connectedSystem , 1L , TimeUnit .SECONDS ,
76+ output -> (!connectedSystem .getSession ().getClosed () &&
77+ (activeSessions .get (terminalSessionId ) != null &&
78+ activeSessions .get (terminalSessionId ).isOpen ())));
79+
80+ // Send data to the specific terminal session
81+ if (rdpData != null ) {
82+ for (Session .TerminalMessage terminalMessage : rdpData ) {
83+ if (terminalMessage .getTrigger () == null ) {
84+ sendToTerminalSession (terminalSessionId , connectedSystem , terminalMessage );
85+ }
86+ }
87+ for (Session .TerminalMessage terminalMessage : rdpData ) {
88+ if (terminalMessage .getTrigger () != null ) {
89+ sendToTerminalSession (terminalSessionId , connectedSystem , terminalMessage );
90+ }
91+ }
92+ } else {
93+ log .trace ("No RDP data to return" );
94+ }
95+
96+ } catch (Exception e ) {
97+ log .error ("Error while listening to RDP server: " , e );
98+ Thread .currentThread ().interrupt (); // Ensure the thread can exit cleanly on exception
99+ }
100+ }
101+ log .trace ("***Leaving RDP thread" );
102+ });
103+ }
104+
105+ public void stopListeningToRdpServer (ConnectedSystem connectedSystem ) {
106+ sessionTrackingService .closeSession (connectedSystem );
107+ }
108+
109+ private Session .TerminalMessage getTrigger (Trigger trigger ) {
110+ var terminalMessage = Session .TerminalMessage .newBuilder ();
111+ if (trigger .getAsk () != null ) {
112+ terminalMessage .setType (Session .MessageType .PROMPT_DATA );
113+ } else {
114+ terminalMessage .setType (Session .MessageType .USER_DATA );
115+ }
116+ Session .Trigger .Builder triggerBuilder = Session .Trigger .newBuilder ();
117+ switch (trigger .getAction ()){
118+ case DENY_ACTION :
119+ triggerBuilder .setAction (Session .TriggerAction .DENY_ACTION );
120+ break ;
121+ case JIT_ACTION :
122+ triggerBuilder .setAction (Session .TriggerAction .JIT_ACTION );
123+ break ;
124+ case RECORD_ACTION :
125+ triggerBuilder .setAction (Session .TriggerAction .RECORD_ACTION );
126+ break ;
127+ case APPROVE_ACTION :
128+ triggerBuilder .setAction (Session .TriggerAction .APPROVE_ACTION );
129+ break ;
130+ case WARN_ACTION :
131+ triggerBuilder .setAction (Session .TriggerAction .WARN_ACTION );
132+ break ;
133+ case PERSISTENT_MESSAGE :
134+ triggerBuilder .setAction (Session .TriggerAction .PERSISTENT_MESSAGE );
135+ break ;
136+ case PROMPT_ACTION :
137+ triggerBuilder .setAction (Session .TriggerAction .PROMPT_ACTION );
138+ break ;
139+ default :
140+ break ;
141+ }
142+ triggerBuilder .setDescription (trigger .getDescription ().isEmpty () ? "" : trigger .getDescription ());
143+ terminalMessage .setTrigger (triggerBuilder .build ());
144+ return terminalMessage .build ();
145+ }
146+
147+ @ Async
148+ public void sendToTerminalSession (String terminalSessionId , ConnectedSystem connectedSystem ,
149+ Session .TerminalMessage rdpData ) {
150+ DataSession session = activeSessions .get (terminalSessionId );
151+ log .info ("Sending RDP message to session: {}" , terminalSessionId );
152+ if (session != null && session .isOpen ()) {
153+ try {
154+ byte [] messageBytes = rdpData .toByteArray ();
155+ String base64Message = Base64 .getEncoder ().encodeToString (messageBytes );
156+ log .trace ("Sending RDP message to session: {}" , rdpData );
157+ session .sendMessage (new TextMessage (base64Message ));
158+ } catch (IOException e ) {
159+ log .error ("Error sending RDP data to terminal session: " + terminalSessionId , e );
160+ }
161+ } else {
162+ log .debug ("RDP Session {} is not available or closed" , terminalSessionId );
163+ }
164+ }
165+
166+ public void processTerminalMessage (
167+ String sessionId , ConnectedSystem connectedSystem , String message ) {
168+
169+ try {
170+ log .debug ("Processing RDP terminal message for session: {}" , sessionId );
171+
172+ // Process RDP-specific commands and data
173+ if (message .startsWith ("RDP_COMMAND:" )) {
174+ handleRdpCommand (connectedSystem , message .substring (12 ));
175+ } else {
176+ // Regular RDP data
177+ handleRdpData (connectedSystem , message );
178+ }
179+
180+ } catch (Exception e ) {
181+ log .error ("Error processing RDP terminal message" , e );
182+ }
183+ }
184+
185+ private void handleRdpCommand (ConnectedSystem connectedSystem , String command ) {
186+ log .info ("Handling RDP command: {} for session: {}" , command , connectedSystem .getSession ().getId ());
187+ // TODO: Implement RDP-specific command handling
188+ }
189+
190+ private void handleRdpData (ConnectedSystem connectedSystem , String data ) {
191+ log .debug ("Handling RDP data for session: {}" , connectedSystem .getSession ().getId ());
192+ // TODO: Implement RDP data processing and forwarding
193+ }
194+
195+ public void removeSession (String sessionId ) {
196+ log .trace ("Removing RDP session: {}" , sessionId );
197+ activeSessions .remove (sessionId );
198+ }
199+ }
0 commit comments