crowdstrike_cloudproto/services/
ts.rs1mod acceptor;
4mod event;
5mod pkt_kind;
6mod socket;
7
8pub use acceptor::TsEventAcceptor;
9pub use event::{Event, EventId};
10pub use pkt_kind::TsPacketKind;
11pub use socket::TsEventSocket;
12
13use crate::services::{DEFAULT_BOOTID_HEX, DEFAULT_UNK0_HEX};
14
15#[repr(u8)]
17#[derive(Eq, PartialEq, Debug, Copy, Clone)]
18pub enum AgentIdStatus {
19 Unchanged = 0x1,
20 Changed = 0x2,
21}
22
23#[derive(Eq, PartialEq, Debug, Clone)]
25pub struct TsConnectInfo {
26 pub cid: [u8; 16],
30 pub unk0: [u8; 16],
32 pub aid: [u8; 16],
34 pub bootid: [u8; 16],
36 pub pt: [u8; 8],
38}
39
40impl TsConnectInfo {
41 pub fn new_simple(cid: [u8; 16]) -> Self {
46 Self {
47 cid,
48 unk0: hex::decode(DEFAULT_UNK0_HEX).unwrap().try_into().unwrap(),
49 aid: [0; 16],
50 bootid: hex::decode(DEFAULT_BOOTID_HEX).unwrap().try_into().unwrap(),
51 pt: [0; 8],
52 }
53 }
54
55 pub fn new_custom(
56 cid: [u8; 16],
57 unk0: [u8; 16],
58 aid: [u8; 16],
59 bootid: [u8; 16],
60 pt: [u8; 8],
61 ) -> Self {
62 Self {
63 cid,
64 unk0,
65 aid,
66 bootid,
67 pt,
68 }
69 }
70}
71
72#[derive(Eq, PartialEq, Debug, Clone)]
74pub struct TsConnectResponse {
75 pub agent_id_status: AgentIdStatus,
77 pub aid: [u8; 16],
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::framing::{CloudProtoError, CloudProtoSocket};
85 use futures_util::{SinkExt, StreamExt};
86 use tokio::spawn;
87
88 #[tokio::test]
89 async fn test_simple_client_server() -> Result<(), CloudProtoError> {
90 let (client, server) = tokio::io::duplex(16 * 1024);
91 let cid = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8];
92 let old_aid = [4, 4, 4, 4, 2, 2, 2, 2, 8, 8, 8, 8, 1, 1, 1, 1];
93 let new_aid = [9, 9, 9, 9, 0, 0, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0];
94
95 let server_task = spawn(async move {
96 let (server, info) = TsEventAcceptor::listen(CloudProtoSocket::new(server)).await?;
97 assert_eq!(info.cid, cid);
98 assert_eq!(info.aid, old_aid);
99 let mut sock = server
100 .accept(TsConnectResponse {
101 agent_id_status: AgentIdStatus::Changed,
102 aid: new_aid,
103 })
104 .await?;
105 let ev = sock.next().await.unwrap()?;
106 assert_eq!(ev.event_id, Some(EventId::AgentOnline));
107 sock.send(Event::new(
108 EventId::LfoDownloadFromManifestRecord,
109 vec![1, 2, 3],
110 ))
111 .await?;
112
113 Ok::<_, CloudProtoError>(sock) });
115
116 let mut client = TsEventSocket::connect(
117 CloudProtoSocket::new(client),
118 TsConnectInfo::new_custom(cid, [0; 16], old_aid, [0; 16], [0; 8]),
119 )
120 .await?;
121 client
122 .send(Event::new(EventId::AgentOnline, vec![]))
123 .await?;
124 let ev = client.next().await.unwrap()?;
125 assert_eq!(ev.event_id, Some(EventId::LfoDownloadFromManifestRecord));
126 assert_eq!(ev.data, &[1, 2, 3]);
127 server_task.await.expect("Server task join error!")?;
128 Ok(())
129 }
130}