1use super::{Decryptor, PrefixedStream};
2use crate::pwp::PROTOCOL_STRING;
3use bytes::BufMut;
4use std::io;
5use std::mem::MaybeUninit;
6use tokio::io::{AsyncRead, AsyncReadExt, ReadBuf};
7
8pub enum MaybeEncrypted<T> {
10 Plain(T),
11 Encrypted(T),
12}
13
14pub async fn detect_encryption<S: AsyncRead + Unpin>(
18 mut stream: S,
19) -> io::Result<MaybeEncrypted<PrefixedStream<io::Cursor<[u8; PROTOCOL_STRING.len()]>, S>>> {
20 let mut buf = [0u8; PROTOCOL_STRING.len()];
21 stream.read_exact(&mut buf).await?;
22 let is_unecrypted = buf == PROTOCOL_STRING;
23
24 let stream = PrefixedStream::new(io::Cursor::new(buf), stream);
25 if is_unecrypted {
26 Ok(MaybeEncrypted::Plain(stream))
27 } else {
28 Ok(MaybeEncrypted::Encrypted(stream))
29 }
30}
31
32macro_rules! sha1_of {
36 ($($slices:expr),+) => {{
37 let mut hasher = sha1_smol::Sha1::new();
38 $(hasher.update($slices);)+
39 hasher.digest().bytes()
40 }};
41}
42pub(super) use sha1_of;
43
44pub(super) fn xor_arrays<const N: usize>(arr1: [u8; N], arr2: [u8; N]) -> [u8; N] {
45 let mut result = [0u8; N];
46 for i in 0..N {
47 result[i] = arr1[i] ^ arr2[i];
48 }
49 result
50}
51
52pub(super) async fn consume_encrypted<const MAX_LEN: usize>(
54 mut stream: impl AsyncReadExt + Unpin,
55 len: usize,
56 decryptor: &mut Decryptor,
57 what: &'static str,
58) -> io::Result<()> {
59 let mut buf = [MaybeUninit::<u8>::uninit(); MAX_LEN];
60 let mut rd = ReadBuf::uninit(&mut buf);
61 let mut rd = rd.take(len);
62
63 while 0 != stream.read_buf(&mut rd).await? {}
64
65 if rd.filled().len() != len {
66 return Err(io::Error::new(
67 io::ErrorKind::UnexpectedEof,
68 format!("stream exhausted before {what} fully read"),
69 ));
70 }
71
72 decryptor.decrypt(rd.filled_mut());
73 Ok(())
74}
75
76pub(super) async fn consume_through<const N: usize>(
79 mut source: impl AsyncReadExt + Unpin,
80 pattern: &[u8; N],
81) -> io::Result<()> {
82 let mut storage = [MaybeUninit::<u8>::uninit(); N];
83 let mut buf = ReadBuf::uninit(&mut storage);
84
85 let mut overlap_ind = None;
86
87 loop {
88 let max_to_read = overlap_ind.unwrap_or(N);
89 let bytes_read = source.read_buf(&mut buf.take(max_to_read)).await?;
90 if 0 == bytes_read {
91 return Err(io::Error::new(
92 io::ErrorKind::UnexpectedEof,
93 "stream exhausted before pattern found",
94 ));
95 }
96 unsafe { buf.advance_mut(bytes_read) }
97
98 if let Some(last_n) = buf.filled().last_chunk::<N>() {
99 overlap_ind = overlap_start_index(pattern, last_n);
100
101 match overlap_ind {
102 Some(0) => break,
103 None => buf.clear(),
104 Some(n) => {
105 buf.filled_mut().copy_within(n.., 0);
106 buf.set_filled(N - n);
107 }
108 }
109 }
110 }
111
112 Ok(())
113}
114
115fn overlap_start_index<const N: usize>(pattern: &[u8; N], data: &[u8; N]) -> Option<usize> {
117 let mut data_ind = 0;
118 let mut pattern_ind = 0;
119 let mut ret = None;
120
121 while data_ind < N {
122 if data[data_ind] == pattern[pattern_ind] {
123 ret.get_or_insert(data_ind);
124 data_ind += 1;
125 pattern_ind += 1;
126 } else {
127 if let Some(old_ret) = ret.take() {
128 data_ind = old_ret;
129 pattern_ind = 0;
130 }
131 data_ind += 1;
132 }
133 }
134
135 ret
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use std::iter;
142
143 #[test]
144 fn test_overlap_start_index() {
145 assert_eq!(overlap_start_index(b"wxyz", b"abcd"), None);
147
148 assert_eq!(overlap_start_index(b"abcd", b"abcd"), Some(0));
150
151 assert_eq!(overlap_start_index(b"cdef", b"abcd"), Some(2));
153
154 assert_eq!(overlap_start_index(b"axyz", b"bcda"), Some(3));
156
157 assert_eq!(overlap_start_index(&[1, 2, 1, 2], &[1, 2, 1, 2]), Some(0));
159
160 assert_eq!(overlap_start_index(&[1, 1, 1, 2], &[1, 1, 1, 1]), Some(1));
162
163 assert_eq!(overlap_start_index(&[1, 2, 3], &[1, 1, 2]), Some(1));
165
166 assert_eq!(overlap_start_index(&[1, 2, 1, 2, 3], &[1, 2, 1, 2, 1]), Some(2));
168 }
169
170 #[tokio::test]
171 async fn test_consume_through_pattern_at_start() {
172 let pattern: [u8; 4] = [7, 8, 9, 10];
173 let tail = [100u8, 101, 102, 103];
174
175 let mut input = Vec::new();
176 input.extend_from_slice(&pattern);
177 input.extend_from_slice(&tail);
178
179 let mut source = io::Cursor::new(input);
180 consume_through(&mut source, &pattern).await.unwrap();
181
182 let mut buf = Vec::new();
183 source.read_to_end(&mut buf).await.unwrap();
184 assert_eq!(buf.as_slice(), &tail);
185 }
186
187 #[tokio::test]
188 async fn test_consume_through_empty_tail() {
189 let head = [0u8, 1, 2, 3, 4, 5];
191 let pattern: [u8; 4] = [7, 8, 9, 10];
192
193 let mut input = Vec::new();
194 input.extend_from_slice(&head);
195 input.extend_from_slice(&pattern);
196
197 let mut source = io::Cursor::new(input);
198 consume_through(&mut source, &pattern).await.unwrap();
199
200 let mut buf = Vec::new();
201 source.read_to_end(&mut buf).await.unwrap();
202 assert!(buf.is_empty());
203 }
204
205 #[tokio::test]
206 async fn test_consume_through_not_found() {
207 let pattern: [u8; 4] = [7, 8, 9, 10];
209 let data = [0u8, 1, 2, 3, 4, 5];
210
211 let mut source = io::Cursor::new(data);
212 let err = consume_through(&mut source, &pattern).await.unwrap_err();
213 assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof);
214 }
215
216 #[tokio::test]
217 async fn test_consume_through_self_overlapping_pattern() {
218 let pattern: [u8; 5] = [1, 2, 1, 2, 3];
222 let tail = [99u8, 100];
223
224 let mut input: Vec<u8> = vec![1, 2, 1, 2, 1, 2, 3]; input.extend_from_slice(&tail);
226
227 let mut source = io::Cursor::new(input);
228 consume_through(&mut source, &pattern).await.unwrap();
229
230 let mut buf = Vec::new();
231 source.read_to_end(&mut buf).await.unwrap();
232 assert_eq!(buf.as_slice(), &tail);
233 }
234
235 #[tokio::test]
236 async fn test_consume_through_multiple_occurrences_stops_at_first() {
237 let pattern: [u8; 3] = [1, 2, 3];
239 let between = [50u8, 51, 52];
240
241 let mut input = Vec::new();
242 input.extend_from_slice(&[9u8, 8, 7]); input.extend_from_slice(&pattern);
244 input.extend_from_slice(&between);
245 input.extend_from_slice(&pattern); let mut source = io::Cursor::new(input);
248 consume_through(&mut source, &pattern).await.unwrap();
249
250 let mut buf = Vec::new();
251 source.read_to_end(&mut buf).await.unwrap();
252
253 let mut expected = Vec::new();
254 expected.extend_from_slice(&between);
255 expected.extend_from_slice(&pattern);
256 assert_eq!(buf, expected);
257 }
258
259 #[tokio::test]
260 async fn test_consume_through_buffer_exhaustion() {
261 let data: &[u8] = &[
262 144, 37, 224, 143, 67, 254, 129, 194, 32, 127, 151, 215, 163, 80, 106, 252, 181, 23,
263 132, 37, 53, 13, 156, 161, 189, 157, 209, 38, 142, 221, 192, 27, 229, 224, 50, 204, 91,
264 99, 94, 173, 25, 201, 161, 160, 251, 41, 58, 128, 156, 233, 160, 195, 234, 179, 140,
265 160, 14, 194, 161, 87, 203, 148, 114, 2, 24, 122, 18, 117, 196, 86, 153, 147, 35, 241,
266 182, 173, 212, 107, 80, 14, 49, 125, 91, 100, 10, 232, 36, 166, 250, 241, 82, 118, 6,
267 53, 188, 24, 41, 176, 109, 20, 99, 120, 191, 218, 114, 91, 161, 178, 27, 137, 184, 251,
268 52, 222, 116, 232, 153, 101, 173, 121, 229, 39, 247, 65, 1, 46, 216, 14, 1, 2, 3, 4, 5,
269 162, 244, 37, 212, 65, 33, 45, 215, 68, 110, 244, 216, 155, 107, 160, 199, 149, 175,
270 168, 75, 51, 195, 151, 235, 166, 68, 181, 163, 12, 153, 243, 211, 245, 148, 122, 106,
271 250, 195, 215, 122, 218, 43, 0, 204, 241, 186, 223, 201, 101, 188, 170, 244, 226, 195,
272 86, 254, 81, 157, 192, 141, 100, 12, 62, 179,
273 ];
274 let pattern: [u8; 5] = [1, 2, 3, 4, 5];
275
276 let mut source = io::Cursor::new(data);
277 consume_through(&mut source, &pattern).await.unwrap();
278
279 let expected_tail = [
280 162, 244, 37, 212, 65, 33, 45, 215, 68, 110, 244, 216, 155, 107, 160, 199, 149, 175,
281 168, 75, 51, 195, 151, 235, 166, 68, 181, 163, 12, 153, 243, 211, 245, 148, 122, 106,
282 250, 195, 215, 122, 218, 43, 0, 204, 241, 186, 223, 201, 101, 188, 170, 244, 226, 195,
283 86, 254, 81, 157, 192, 141, 100, 12, 62, 179,
284 ];
285 let mut buf = Vec::new();
286 source.read_to_end(&mut buf).await.unwrap();
287 assert_eq!(buf.as_slice(), &expected_tail);
288 }
289
290 #[tokio::test]
291 async fn test_consume_through_fuzz() {
292 for _ in 0..10_000 {
293 let pattern: [u8; 5] = [1, 2, 3, 4, 5];
294 let tail = b"tail data";
295
296 let input = {
297 let head_len = (rand::random::<u16>() % 512) as usize;
298 let mut tmp: Vec<u8> = iter::repeat_with(rand::random).take(head_len).collect();
299 tmp.extend_from_slice(&pattern);
300 tmp.extend_from_slice(tail);
301 tmp
302 };
303
304 let mut source = io::Cursor::new(input);
305 if let Err(e) = consume_through(&mut source, &pattern).await {
306 panic!("consume_through failed: {:?}\n{:?}", e, source.get_ref());
307 }
308
309 let mut buf = Vec::new();
310 source.read_to_end(&mut buf).await.unwrap();
311 assert_eq!(buf, tail);
312 }
313 }
314
315 #[tokio::test]
316 async fn test_detect_encryption() {
317 let unencrypted_stream = io::Cursor::new(PROTOCOL_STRING);
318 match detect_encryption(unencrypted_stream).await.unwrap() {
319 MaybeEncrypted::Plain(mut stream) => {
320 let mut buf = Vec::new();
321 stream.read_to_end(&mut buf).await.unwrap();
322 assert_eq!(buf, PROTOCOL_STRING);
323 }
324 MaybeEncrypted::Encrypted(_) => panic!("unencrypted stream misclassified as encrypted"),
325 }
326
327 let encrypted_stream = io::Cursor::new(b"not the protocol string");
328 match detect_encryption(encrypted_stream).await.unwrap() {
329 MaybeEncrypted::Plain(_) => panic!("encrypted stream misclassified as unencrypted"),
330 MaybeEncrypted::Encrypted(mut stream) => {
331 let mut buf = Vec::new();
332 stream.read_to_end(&mut buf).await.unwrap();
333 assert_eq!(buf, b"not the protocol string");
334 }
335 }
336 }
337}