Skip to content

Commit 73976c1

Browse files
authored
Merge pull request #323 from goffrie/disable-built-in-roots
Add SslOpts::disable_built_in_roots flag
2 parents e9de7ed + add2a39 commit 73976c1

File tree

3 files changed

+76
-10
lines changed

3 files changed

+76
-10
lines changed

src/io/tls/native_tls_io.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl Endpoint {
3636
}
3737
builder.danger_accept_invalid_hostnames(ssl_opts.skip_domain_validation());
3838
builder.danger_accept_invalid_certs(ssl_opts.accept_invalid_certs());
39+
builder.disable_built_in_roots(ssl_opts.disable_built_in_roots());
3940
let tls_connector: tokio_native_tls::TlsConnector = builder.build()?.into();
4041

4142
*self = match self {

src/io/tls/rustls_io.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ impl Endpoint {
4646
}
4747

4848
let mut root_store = RootCertStore::empty();
49-
root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().map(|x| x.to_owned()));
49+
if !ssl_opts.disable_built_in_roots() {
50+
root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().map(|x| x.to_owned()));
51+
}
5052

5153
for cert in ssl_opts.load_root_certs().await? {
5254
root_store.add(cert)?;

src/opts/mod.rs

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ pub struct SslOpts {
214214
#[cfg(any(feature = "native-tls-tls", feature = "rustls-tls"))]
215215
client_identity: Option<ClientIdentity>,
216216
root_certs: Vec<PathOrBuf<'static>>,
217+
disable_built_in_roots: bool,
217218
skip_domain_validation: bool,
218219
accept_invalid_certs: bool,
219220
tls_hostname_override: Option<Cow<'static, str>>,
@@ -236,15 +237,61 @@ impl SslOpts {
236237
self
237238
}
238239

239-
/// The way to not validate the server's domain
240-
/// name against its certificate (defaults to `false`).
240+
/// If `true`, use only the root certificates configured via [`SslOpts::with_root_certs`],
241+
/// not any system or built-in certs. By default system built-in certs _will be_ used.
242+
///
243+
/// # Connection URL
244+
///
245+
/// Use `built_in_roots` URL parameter to set this value:
246+
///
247+
/// ```
248+
/// # use mysql_async::*;
249+
/// # use std::time::Duration;
250+
/// # fn main() -> Result<()> {
251+
/// let opts = Opts::from_url("mysql://localhost/db?require_ssl=true&built_in_roots=false")?;
252+
/// assert_eq!(opts.ssl_opts().unwrap().disable_built_in_roots(), true);
253+
/// # Ok(()) }
254+
/// ```
255+
pub fn with_disable_built_in_roots(mut self, disable_built_in_roots: bool) -> Self {
256+
self.disable_built_in_roots = disable_built_in_roots;
257+
self
258+
}
259+
260+
/// The way to not validate the server's domain name against its certificate.
261+
/// By default domain name _will be_ validated.
262+
///
263+
/// # Connection URL
264+
///
265+
/// Use `verify_identity` URL parameter to set this value:
266+
///
267+
/// ```
268+
/// # use mysql_async::*;
269+
/// # use std::time::Duration;
270+
/// # fn main() -> Result<()> {
271+
/// let opts = Opts::from_url("mysql://localhost/db?require_ssl=true&verify_identity=false")?;
272+
/// assert_eq!(opts.ssl_opts().unwrap().skip_domain_validation(), true);
273+
/// # Ok(()) }
274+
/// ```
241275
pub fn with_danger_skip_domain_validation(mut self, value: bool) -> Self {
242276
self.skip_domain_validation = value;
243277
self
244278
}
245279

246-
/// If `true` then client will accept invalid certificate (expired, not trusted, ..)
247-
/// (defaults to `false`).
280+
/// If `true` then client will accept invalid certificate (expired, not trusted, ..).
281+
/// Invalid certificates _won't get_ accepted by default.
282+
///
283+
/// # Connection URL
284+
///
285+
/// Use `verify_ca` URL parameter to set this value:
286+
///
287+
/// ```
288+
/// # use mysql_async::*;
289+
/// # use std::time::Duration;
290+
/// # fn main() -> Result<()> {
291+
/// let opts = Opts::from_url("mysql://localhost/db?require_ssl=true&verify_ca=false")?;
292+
/// assert_eq!(opts.ssl_opts().unwrap().accept_invalid_certs(), true);
293+
/// # Ok(()) }
294+
/// ```
248295
pub fn with_danger_accept_invalid_certs(mut self, value: bool) -> Self {
249296
self.accept_invalid_certs = value;
250297
self
@@ -271,6 +318,10 @@ impl SslOpts {
271318
&self.root_certs
272319
}
273320

321+
pub fn disable_built_in_roots(&self) -> bool {
322+
self.disable_built_in_roots
323+
}
324+
274325
pub fn skip_domain_validation(&self) -> bool {
275326
self.skip_domain_validation
276327
}
@@ -1584,6 +1635,7 @@ fn mysqlopts_from_url(url: &Url) -> std::result::Result<MysqlOpts, UrlError> {
15841635

15851636
let mut skip_domain_validation = false;
15861637
let mut accept_invalid_certs = false;
1638+
let mut disable_built_in_roots = false;
15871639

15881640
for (key, value) in query_pairs {
15891641
if key == "pool_min" {
@@ -1684,10 +1736,7 @@ fn mysqlopts_from_url(url: &Url) -> std::result::Result<MysqlOpts, UrlError> {
16841736
}
16851737
} else if key == "max_allowed_packet" {
16861738
match usize::from_str(&value) {
1687-
Ok(value) => {
1688-
opts.max_allowed_packet =
1689-
Some(std::cmp::max(1024, std::cmp::min(1073741824, value)))
1690-
}
1739+
Ok(value) => opts.max_allowed_packet = Some(value.clamp(1024, 1073741824)),
16911740
_ => {
16921741
return Err(UrlError::InvalidParamValue {
16931742
param: "max_allowed_packet".into(),
@@ -1839,6 +1888,18 @@ fn mysqlopts_from_url(url: &Url) -> std::result::Result<MysqlOpts, UrlError> {
18391888
});
18401889
}
18411890
}
1891+
} else if key == "built_in_roots" {
1892+
match bool::from_str(&value) {
1893+
Ok(x) => {
1894+
disable_built_in_roots = !x;
1895+
}
1896+
_ => {
1897+
return Err(UrlError::InvalidParamValue {
1898+
param: "built_in_roots".into(),
1899+
value,
1900+
});
1901+
}
1902+
}
18421903
} else {
18431904
return Err(UrlError::UnknownParameter { param: key });
18441905
}
@@ -1856,6 +1917,7 @@ fn mysqlopts_from_url(url: &Url) -> std::result::Result<MysqlOpts, UrlError> {
18561917
if let Some(ref mut ssl_opts) = opts.ssl_opts.as_mut() {
18571918
ssl_opts.accept_invalid_certs = accept_invalid_certs;
18581919
ssl_opts.skip_domain_validation = skip_domain_validation;
1920+
ssl_opts.disable_built_in_roots = disable_built_in_roots;
18591921
}
18601922

18611923
Ok(opts)
@@ -1973,14 +2035,15 @@ mod test {
19732035
);
19742036

19752037
const URL4: &str =
1976-
"mysql://localhost/foo?require_ssl=true&verify_ca=false&verify_identity=false";
2038+
"mysql://localhost/foo?require_ssl=true&verify_ca=false&verify_identity=false&built_in_roots=false";
19772039
let opts = Opts::from_url(URL4).unwrap();
19782040
assert_eq!(
19792041
opts.ssl_opts(),
19802042
Some(
19812043
&SslOpts::default()
19822044
.with_danger_accept_invalid_certs(true)
19832045
.with_danger_skip_domain_validation(true)
2046+
.with_disable_built_in_roots(true)
19842047
)
19852048
);
19862049

0 commit comments

Comments
 (0)