|
1 | | -use crate::data::CLIENT_CONFIG; |
| 1 | +use crate::{ |
| 2 | + data::CLIENT_CONFIG, |
| 3 | + types::{LogLevel, LogMessage}, |
| 4 | +}; |
2 | 5 | use common::{ |
3 | | - net::{HandshakePacket, StreamReader, StreamWriter}, |
| 6 | + net::{AsyncStream, HandshakePacket, StreamReader, StreamWriter}, |
4 | 7 | utils::{enc as encutils, net as netutils}, |
5 | 8 | }; |
6 | 9 | use rsa::RsaPrivateKey; |
| 10 | +use rustls::{ClientConfig, pki_types::ServerName}; |
| 11 | +use std::sync::Arc; |
| 12 | +use tokio::{ |
| 13 | + net::TcpStream, |
| 14 | + time::{Duration, timeout}, |
| 15 | +}; |
| 16 | +use tokio_rustls::TlsConnector; |
7 | 17 |
|
8 | 18 | /// ### Perform the initial handshake with the server. |
9 | | -/// |
| 19 | +/// |
10 | 20 | /// This function handles the entire handshake process, including |
11 | 21 | /// sending the initial handshake packet, receiving the server's |
12 | 22 | /// response, and completing the handshake by establishing a |
@@ -83,3 +93,58 @@ pub async fn perform_handshake( |
83 | 93 |
|
84 | 94 | Ok(session_key) |
85 | 95 | } |
| 96 | + |
| 97 | +pub async fn create_tls_connector() -> Result<TlsConnector, Box<dyn std::error::Error + Send + Sync>> |
| 98 | +{ |
| 99 | + // Load the root certificates from the webpki-roots crate |
| 100 | + let mut root_store = rustls::RootCertStore::empty(); |
| 101 | + root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); |
| 102 | + |
| 103 | + // Create the client configuration |
| 104 | + let config = ClientConfig::builder() |
| 105 | + .with_root_certificates(root_store) |
| 106 | + .with_no_client_auth(); |
| 107 | + |
| 108 | + // Create the async TLS connector |
| 109 | + let connector = TlsConnector::from(Arc::new(config)); |
| 110 | + Ok(connector) |
| 111 | +} |
| 112 | + |
| 113 | +pub async fn try_tls_handshake( |
| 114 | + host_name: String, |
| 115 | + stream: TcpStream, |
| 116 | +) -> Option<Box<dyn AsyncStream>> { |
| 117 | + // Convert the hostname string to a ServerName |
| 118 | + let domain = match ServerName::try_from(host_name) { |
| 119 | + Ok(name) => name, |
| 120 | + Err(_) => return None, |
| 121 | + }; |
| 122 | + |
| 123 | + let tls_connector = match create_tls_connector().await { |
| 124 | + Ok(connector) => connector, |
| 125 | + Err(e) => { |
| 126 | + LogMessage::log( |
| 127 | + LogLevel::ERROR, |
| 128 | + format!("Failed to create TLS connector: {}", e), |
| 129 | + 0, |
| 130 | + ) |
| 131 | + .await; |
| 132 | + return None; |
| 133 | + } |
| 134 | + }; |
| 135 | + |
| 136 | + let timeout_duration = Duration::from_secs(10); // 10-second timeout |
| 137 | + |
| 138 | + // The handshake future |
| 139 | + let handshake_future = tls_connector.connect(domain, stream); |
| 140 | + |
| 141 | + // Apply the timeout |
| 142 | + let result = timeout(timeout_duration, handshake_future).await; |
| 143 | + |
| 144 | + let tls = match result { |
| 145 | + Ok(Ok(tls)) => tls, |
| 146 | + _ => return None, |
| 147 | + }; |
| 148 | + |
| 149 | + Some(Box::new(tls)) |
| 150 | +} |
0 commit comments