1use std::fmt::Debug;
2use std::future::Future;
3use std::pin::Pin;
4
5use crate::generator::NetworkRequest;
6use crate::Result;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum NetworkProtocol {
10 Tcp,
11 Udp,
12 Http,
13 Https,
14}
15
16impl NetworkProtocol {
17 pub const ALL: &'static [Self] = &[Self::Tcp, Self::Udp, Self::Http, Self::Https];
18
19 pub(crate) fn from_url_scheme(scheme: &str) -> Option<Self> {
20 match scheme {
21 "tcp" => Some(Self::Tcp),
22 "udp" => Some(Self::Udp),
23 "http" => Some(Self::Http),
24 "https" => Some(Self::Https),
25 _ => None,
26 }
27 }
28}
29
30pub trait AsyncNetworkClient: Send + Sync {
35 fn send<'a>(
41 &'a mut self,
42 network_request: &'a NetworkRequest,
43 ) -> Pin<Box<dyn Future<Output = Result<Vec<u8>>> + 'a>>;
44}
45
46pub trait NetworkClient: Send + Sync {
47 fn send(&self, request: &NetworkRequest) -> Result<Vec<u8>>;
52}
53
54#[cfg(feature = "network_client")]
55pub mod reqwest_network_client {
56 use std::io::{Read, Write};
57 use std::net::{IpAddr, Ipv4Addr, TcpStream, UdpSocket};
58
59 use byteorder::{BigEndian, ReadBytesExt};
60 use url::Url;
61
62 use super::{NetworkClient, NetworkProtocol};
63 use crate::generator::NetworkRequest;
64 use crate::{Error, ErrorKind, Result};
65
66 #[derive(Debug, Clone, Default)]
67 pub struct ReqwestNetworkClient;
68
69 impl ReqwestNetworkClient {
70 fn send_tcp(&self, url: &Url, data: &[u8]) -> Result<Vec<u8>> {
71 let addr = format!("{}:{}", url.host_str().unwrap_or_default(), url.port().unwrap_or(88));
72 let mut stream = TcpStream::connect(addr)
73 .map_err(|e| Error::new(ErrorKind::NoAuthenticatingAuthority, format!("{:?}", e)))?;
74
75 stream
76 .write(data)
77 .map_err(|e| Error::new(ErrorKind::NoAuthenticatingAuthority, format!("{:?}", e)))?;
78
79 let len = stream
80 .read_u32::<BigEndian>()
81 .map_err(|e| Error::new(ErrorKind::NoAuthenticatingAuthority, format!("{:?}", e)))?;
82
83 let mut buf = vec![0; len as usize + 4];
84 buf[0..4].copy_from_slice(&(len.to_be_bytes()));
85
86 stream
87 .read_exact(&mut buf[4..])
88 .map_err(|e| Error::new(ErrorKind::NoAuthenticatingAuthority, format!("{:?}", e)))?;
89
90 Ok(buf)
91 }
92
93 fn send_udp(&self, url: &Url, data: &[u8]) -> Result<Vec<u8>> {
94 let port =
95 portpicker::pick_unused_port().ok_or_else(|| Error::new(ErrorKind::InternalError, "No free ports"))?;
96 let udp_socket = UdpSocket::bind((IpAddr::V4(Ipv4Addr::LOCALHOST), port))?;
97
98 let addr = format!("{}:{}", url.host_str().unwrap_or_default(), url.port().unwrap_or(88));
99 udp_socket.send_to(data, addr)?;
100
101 let mut buf = vec![0; 0xbb80];
103
104 let n = udp_socket.recv(&mut buf)?;
105
106 let mut reply_buf = Vec::with_capacity(n + 4);
107 reply_buf.extend_from_slice(&(n as u32).to_be_bytes());
108 reply_buf.extend_from_slice(&buf[0..n]);
109
110 Ok(reply_buf)
111 }
112
113 fn send_http(&self, url: &Url, data: &[u8]) -> Result<Vec<u8>> {
114 crate::rustls::install_default_crypto_provider_if_necessary().map_err(|()| {
115 Error::new(
116 ErrorKind::SecurityPackageNotFound,
117 "failed to install the default crypto provider for TLS",
118 )
119 })?;
120
121 let client = crate::rustls::load_native_certs(reqwest::blocking::ClientBuilder::new())
122 .build()
123 .map_err(|e| {
124 Error::new(
125 ErrorKind::NoAuthenticatingAuthority,
126 format!("failed to build reqwest client: {e}"),
127 )
128 })?;
129
130 let response = client
131 .post(url.clone())
132 .body(data.to_vec())
133 .send()
134 .map_err(|err| match err {
135 err if err.to_string().to_lowercase().contains("certificate") => Error::new(
136 ErrorKind::CertificateUnknown,
137 format!("Invalid certificate data: {:?}", err),
138 ),
139 _ => Error::new(
140 ErrorKind::NoAuthenticatingAuthority,
141 format!("Unable to send the data to the KDC Proxy: {:?}", err),
142 ),
143 })?
144 .error_for_status()
145 .map_err(|err| Error::new(ErrorKind::NoAuthenticatingAuthority, format!("KDC Proxy: {err}")))?;
146
147 let body = response.bytes().map_err(|err| {
148 Error::new(
149 ErrorKind::NoAuthenticatingAuthority,
150 format!("Unable to read the response data from the KDC Proxy: {:?}", err),
151 )
152 })?;
153
154 let body = Vec::from(body);
156
157 Ok(body)
158 }
159 }
160
161 impl NetworkClient for ReqwestNetworkClient {
162 fn send(&self, request: &NetworkRequest) -> Result<Vec<u8>> {
163 match request.protocol {
164 NetworkProtocol::Tcp => self.send_tcp(&request.url, &request.data),
165 NetworkProtocol::Udp => self.send_udp(&request.url, &request.data),
166 NetworkProtocol::Http | NetworkProtocol::Https => self.send_http(&request.url, &request.data),
167 }
168 }
169 }
170}