-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathmod.rs
More file actions
130 lines (109 loc) · 3.79 KB
/
mod.rs
File metadata and controls
130 lines (109 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#![allow(dead_code)]
use std::path::PathBuf;
use crate::error::Error;
use crate::net::socket::WithSocket;
use crate::net::Socket;
#[cfg(feature = "_tls-rustls")]
mod tls_rustls;
#[cfg(feature = "_tls-native-tls")]
mod tls_native_tls;
mod util;
/// X.509 Certificate input, either a file path or a PEM encoded inline certificate(s).
#[derive(Clone, Debug)]
pub enum CertificateInput {
/// PEM encoded certificate(s)
Inline(Vec<u8>),
/// Path to a file containing PEM encoded certificate(s)
File(PathBuf),
}
impl From<String> for CertificateInput {
fn from(value: String) -> Self {
// Leading and trailing whitespace/newlines
let trimmed = value.trim();
// Heuristic for PEM encoded inputs:
// https://tools.ietf.org/html/rfc7468
if trimmed.starts_with("-----BEGIN") && trimmed.ends_with("-----") {
CertificateInput::Inline(value.as_bytes().to_vec())
} else {
CertificateInput::File(PathBuf::from(value))
}
}
}
impl CertificateInput {
async fn data(&self) -> Result<Vec<u8>, std::io::Error> {
use crate::fs;
match self {
CertificateInput::Inline(v) => Ok(v.clone()),
CertificateInput::File(path) => fs::read(path).await,
}
}
}
impl std::fmt::Display for CertificateInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CertificateInput::Inline(v) => write!(f, "{}", String::from_utf8_lossy(v.as_slice())),
CertificateInput::File(path) => write!(f, "file: {}", path.display()),
}
}
}
pub struct TlsConfig<'a> {
pub accept_invalid_certs: bool,
pub accept_invalid_hostnames: bool,
pub root_cert_path: Option<&'a CertificateInput>,
pub client_cert_path: Option<&'a CertificateInput>,
pub client_key_path: Option<&'a CertificateInput>,
}
#[cfg(feature = "_tls-native-tls")]
pub use self::tls_native_tls::NativeTlsConnector as TlsConnector;
#[cfg(all(feature = "_tls-rustls", not(feature = "_tls-native-tls")))]
pub use self::tls_rustls::RustlsConnector as TlsConnector;
#[cfg(not(any(feature = "_tls-native-tls", feature = "_tls-rustls")))]
#[derive(Debug, Clone)]
pub struct TlsConnector(std::convert::Infallible);
pub async fn connector(config: TlsConfig<'_>) -> crate::Result<TlsConnector> {
#[cfg(feature = "_tls-native-tls")]
return tls_native_tls::connector(config).await;
#[cfg(all(feature = "_tls-rustls", not(feature = "_tls-native-tls")))]
return tls_rustls::connector(config).await;
#[cfg(not(any(feature = "_tls-native-tls", feature = "_tls-rustls")))]
{
_ = config;
panic!("one of the `runtime-*-native-tls` or `runtime-*-rustls` features must be enabled")
}
}
pub async fn handshake<S, Ws>(
socket: S,
hostname: &str,
connector: &TlsConnector,
with_socket: Ws,
) -> crate::Result<Ws::Output>
where
S: Socket,
Ws: WithSocket,
{
#[cfg(feature = "_tls-native-tls")]
return Ok(with_socket
.with_socket(tls_native_tls::handshake(socket, hostname, connector).await?)
.await);
#[cfg(all(feature = "_tls-rustls", not(feature = "_tls-native-tls")))]
return Ok(with_socket
.with_socket(tls_rustls::handshake(socket, hostname, connector).await?)
.await);
#[cfg(not(any(feature = "_tls-native-tls", feature = "_tls-rustls")))]
{
drop((socket, hostname, with_socket));
match connector.0 {}
}
}
pub fn available() -> bool {
cfg!(any(feature = "_tls-native-tls", feature = "_tls-rustls"))
}
pub fn error_if_unavailable() -> crate::Result<()> {
if !available() {
return Err(Error::tls(
"TLS upgrade required by connect options \
but SQLx was built without TLS support enabled",
));
}
Ok(())
}