sqlx_mysql/connection/
tls.rs1use crate::collation::{CharSet, Collation};
2use crate::connection::{MySqlStream, Waiting};
3use crate::error::Error;
4use crate::net::tls::TlsConfig;
5use crate::net::{tls, BufferedSocket, Socket, WithSocket};
6use crate::protocol::connect::SslRequest;
7use crate::protocol::Capabilities;
8use crate::{MySqlConnectOptions, MySqlSslMode};
9use std::collections::VecDeque;
10
11struct MapStream {
12 server_version: (u16, u16, u16),
13 capabilities: Capabilities,
14 sequence_id: u8,
15 waiting: VecDeque<Waiting>,
16 charset: CharSet,
17 collation: Collation,
18}
19
20pub(super) async fn maybe_upgrade<S: Socket>(
21 mut stream: MySqlStream<S>,
22 options: &MySqlConnectOptions,
23) -> Result<MySqlStream, Error> {
24 let server_supports_tls = stream.capabilities.contains(Capabilities::SSL);
25
26 if matches!(options.ssl_mode, MySqlSslMode::Disabled) || !tls::available() {
27 stream.capabilities.remove(Capabilities::SSL);
29 }
30
31 match options.ssl_mode {
33 MySqlSslMode::Disabled => return Ok(stream.boxed_socket()),
34
35 MySqlSslMode::Preferred => {
36 if !tls::available() {
37 tracing::debug!("not performing TLS upgrade: TLS support not compiled in");
39 return Ok(stream.boxed_socket());
40 }
41
42 if !server_supports_tls {
43 tracing::debug!("not performing TLS upgrade: unsupported by server");
45 return Ok(stream.boxed_socket());
46 }
47 }
48
49 MySqlSslMode::Required | MySqlSslMode::VerifyIdentity | MySqlSslMode::VerifyCa => {
50 tls::error_if_unavailable()?;
51
52 if !server_supports_tls {
53 return Err(Error::Tls("server does not support TLS".into()));
55 }
56 }
57 }
58
59 let tls_config = TlsConfig {
60 accept_invalid_certs: !matches!(
61 options.ssl_mode,
62 MySqlSslMode::VerifyCa | MySqlSslMode::VerifyIdentity
63 ),
64 accept_invalid_hostnames: !matches!(options.ssl_mode, MySqlSslMode::VerifyIdentity),
65 hostname: &options.host,
66 root_cert_path: options.ssl_ca.as_ref(),
67 client_cert_path: options.ssl_client_cert.as_ref(),
68 client_key_path: options.ssl_client_key.as_ref(),
69 };
70
71 stream.write_packet(SslRequest {
73 max_packet_size: super::MAX_PACKET_SIZE,
74 collation: stream.collation as u8,
75 })?;
76
77 stream.flush().await?;
78
79 tls::handshake(
80 stream.socket.into_inner(),
81 tls_config,
82 MapStream {
83 server_version: stream.server_version,
84 capabilities: stream.capabilities,
85 sequence_id: stream.sequence_id,
86 waiting: stream.waiting,
87 charset: stream.charset,
88 collation: stream.collation,
89 },
90 )
91 .await
92}
93
94impl WithSocket for MapStream {
95 type Output = MySqlStream;
96
97 async fn with_socket<S: Socket>(self, socket: S) -> Self::Output {
98 MySqlStream {
99 socket: BufferedSocket::new(Box::new(socket)),
100 server_version: self.server_version,
101 capabilities: self.capabilities,
102 sequence_id: self.sequence_id,
103 waiting: self.waiting,
104 charset: self.charset,
105 collation: self.collation,
106 is_tls: true,
107 }
108 }
109}