crowdstrike_cloudproto/services/ts/
acceptor.rs1use crate::framing::CloudProtoError::ClosedByPeer;
2use crate::framing::{CloudProtoError, CloudProtoPacket, CloudProtoSocket, CloudProtoVersion};
3use crate::services::ts::{TsConnectInfo, TsConnectResponse, TsEventSocket, TsPacketKind};
4use crate::services::CloudProtoMagic;
5use bytes::Buf;
6use futures_util::{SinkExt, StreamExt};
7use std::io::Read;
8use tokio::io::{AsyncRead, AsyncWrite};
9
10pub struct TsEventAcceptor<IO: AsyncRead + AsyncWrite> {
12 io: CloudProtoSocket<IO>,
13}
14
15impl<IO> TsEventAcceptor<IO>
16where
17 IO: AsyncRead + AsyncWrite,
18{
19 pub async fn listen(
21 mut io: CloudProtoSocket<IO>,
22 ) -> Result<(Self, TsConnectInfo), CloudProtoError> {
23 let pkt = match io.next().await {
24 None => return Err(ClosedByPeer("TS client closed connection".into())),
25 Some(Err(e)) => return Err(e),
26 Some(Ok(pkt)) => pkt,
27 };
28 if pkt.magic != CloudProtoMagic::TS {
29 return Err(CloudProtoError::BadMagic(pkt.magic, CloudProtoMagic::TS));
30 }
31 if pkt.kind != TsPacketKind::Connect {
32 return Err(CloudProtoError::WrongConnectionPacketKind(
33 pkt.kind,
34 TsPacketKind::Connect.into(),
35 ));
36 }
37 if pkt.version != CloudProtoVersion::Connect {
38 return Err(CloudProtoError::BadVersion(
39 pkt.version,
40 CloudProtoVersion::Connect,
41 ));
42 }
43
44 if pkt.payload.len() != 4 * 16 + 8 {
45 return Err(CloudProtoError::PayloadInvalidSize(
46 pkt.payload.len(),
47 4 * 16 + 8,
48 ));
49 }
50 let mut info = TsConnectInfo {
51 cid: [0; 16],
52 unk0: [0; 16],
53 aid: [0; 16],
54 bootid: [0; 16],
55 pt: [0; 8],
56 };
57 let mut rd = pkt.payload.reader();
58 rd.read_exact(&mut info.cid)?;
59 rd.read_exact(&mut info.unk0)?;
60 rd.read_exact(&mut info.aid)?;
61 rd.read_exact(&mut info.bootid)?;
62 rd.read_exact(&mut info.pt)?;
63
64 Ok((Self { io }, info))
65 }
66
67 pub async fn accept(
69 mut self,
70 reply: TsConnectResponse,
71 ) -> Result<TsEventSocket<IO>, CloudProtoError> {
72 let mut payload = Vec::with_capacity(1 + 16);
73 payload.push(reply.agent_id_status as u8);
74 payload.extend_from_slice(&reply.aid);
75 let pkt = CloudProtoPacket {
76 magic: CloudProtoMagic::TS,
77 kind: TsPacketKind::ConnectionEstablished.into(),
78 version: CloudProtoVersion::Normal,
79 payload,
80 };
81 self.io.send(pkt).await?;
82
83 Ok(TsEventSocket::new(self.io))
84 }
85}