@@ -608,7 +608,27 @@ impl Opts {
608
608
self . inner . mysql_opts . stmt_cache_size
609
609
}
610
610
611
- /// Driver will require SSL connection if this opts isn't `None` (default to `None`).
611
+ /// Driver will require SSL connection if this opts isn't `None` (defaults to `None`).
612
+ ///
613
+ /// # Connection URL parameters
614
+ ///
615
+ /// Note that for securty reasons:
616
+ ///
617
+ /// * CA and IDENTITY verifications are opt-out
618
+ /// * there is no way to give an idenity or root certs via query URL
619
+ ///
620
+ /// URL Parameters:
621
+ ///
622
+ /// * `require_ssl: bool` (defaults to `false`) – requires SSL with default [`SslOpts`]
623
+ /// * `verify_ca: bool` (defaults to `true`) – requires server Certificate Authority (CA)
624
+ /// certificate validation against the configured CA certificates.
625
+ /// Makes no sence if `require_ssl` equals `false`.
626
+ /// * `verify_identity: bool` (defaults to `true`) – perform host name identity verification
627
+ /// by checking the host name the client uses for connecting to the server against
628
+ /// the identity in the certificate that the server sends to the client.
629
+ /// Makes no sence if `require_ssl` equals `false`.
630
+ ///
631
+ ///
612
632
pub fn ssl_opts ( & self ) -> Option < & SslOpts > {
613
633
self . inner . mysql_opts . ssl_opts . as_ref ( )
614
634
}
@@ -1078,6 +1098,10 @@ fn mysqlopts_from_url(url: &Url) -> std::result::Result<MysqlOpts, UrlError> {
1078
1098
let ( mut opts, query_pairs) : ( MysqlOpts , _ ) = from_url_basic ( url) ?;
1079
1099
let mut pool_min = DEFAULT_POOL_CONSTRAINTS . min ;
1080
1100
let mut pool_max = DEFAULT_POOL_CONSTRAINTS . max ;
1101
+
1102
+ let mut skip_domain_validation = false ;
1103
+ let mut accept_invalid_certs = false ;
1104
+
1081
1105
for ( key, value) in query_pairs {
1082
1106
if key == "pool_min" {
1083
1107
match usize:: from_str ( & * value) {
@@ -1240,6 +1264,40 @@ fn mysqlopts_from_url(url: &Url) -> std::result::Result<MysqlOpts, UrlError> {
1240
1264
value,
1241
1265
} ) ;
1242
1266
}
1267
+ } else if key == "require_ssl" {
1268
+ match bool:: from_str ( & * value) {
1269
+ Ok ( x) => opts. ssl_opts = x. then ( SslOpts :: default) ,
1270
+ _ => {
1271
+ return Err ( UrlError :: InvalidParamValue {
1272
+ param : "require_ssl" . into ( ) ,
1273
+ value,
1274
+ } ) ;
1275
+ }
1276
+ }
1277
+ } else if key == "verify_ca" {
1278
+ match bool:: from_str ( & * value) {
1279
+ Ok ( x) => {
1280
+ accept_invalid_certs = !x;
1281
+ }
1282
+ _ => {
1283
+ return Err ( UrlError :: InvalidParamValue {
1284
+ param : "verify_ca" . into ( ) ,
1285
+ value,
1286
+ } ) ;
1287
+ }
1288
+ }
1289
+ } else if key == "verify_identity" {
1290
+ match bool:: from_str ( & * value) {
1291
+ Ok ( x) => {
1292
+ skip_domain_validation = !x;
1293
+ }
1294
+ _ => {
1295
+ return Err ( UrlError :: InvalidParamValue {
1296
+ param : "verify_identity" . into ( ) ,
1297
+ value,
1298
+ } ) ;
1299
+ }
1300
+ }
1243
1301
} else {
1244
1302
return Err ( UrlError :: UnknownParameter { param : key } ) ;
1245
1303
}
@@ -1254,6 +1312,11 @@ fn mysqlopts_from_url(url: &Url) -> std::result::Result<MysqlOpts, UrlError> {
1254
1312
} ) ;
1255
1313
}
1256
1314
1315
+ if let Some ( ref mut ssl_opts) = opts. ssl_opts . as_mut ( ) {
1316
+ ssl_opts. accept_invalid_certs = accept_invalid_certs;
1317
+ ssl_opts. skip_domain_validation = skip_domain_validation;
1318
+ }
1319
+
1257
1320
Ok ( opts)
1258
1321
}
1259
1322
@@ -1276,7 +1339,7 @@ impl<'a> TryFrom<&'a str> for Opts {
1276
1339
#[ cfg( test) ]
1277
1340
mod test {
1278
1341
use super :: { HostPortOrUrl , MysqlOpts , Opts , Url } ;
1279
- use crate :: error:: UrlError :: InvalidParamValue ;
1342
+ use crate :: { error:: UrlError :: InvalidParamValue , SslOpts } ;
1280
1343
1281
1344
use std:: str:: FromStr ;
1282
1345
@@ -1345,6 +1408,41 @@ mod test {
1345
1408
assert_eq ! ( opts. ip_or_hostname( ) , "[::1]" ) ;
1346
1409
}
1347
1410
1411
+ #[ test]
1412
+ fn should_parse_ssl_params ( ) {
1413
+ const URL1 : & str = "mysql://localhost/foo?require_ssl=false" ;
1414
+ let opts = Opts :: from_url ( URL1 ) . unwrap ( ) ;
1415
+ assert_eq ! ( opts. ssl_opts( ) , None ) ;
1416
+
1417
+ const URL2 : & str = "mysql://localhost/foo?require_ssl=true" ;
1418
+ let opts = Opts :: from_url ( URL2 ) . unwrap ( ) ;
1419
+ assert_eq ! ( opts. ssl_opts( ) , Some ( & SslOpts :: default ( ) ) ) ;
1420
+
1421
+ const URL3 : & str = "mysql://localhost/foo?require_ssl=true&verify_ca=false" ;
1422
+ let opts = Opts :: from_url ( URL3 ) . unwrap ( ) ;
1423
+ assert_eq ! (
1424
+ opts. ssl_opts( ) ,
1425
+ Some ( & SslOpts :: default ( ) . with_danger_accept_invalid_certs( true ) )
1426
+ ) ;
1427
+
1428
+ const URL4 : & str =
1429
+ "mysql://localhost/foo?require_ssl=true&verify_ca=false&verify_identity=false" ;
1430
+ let opts = Opts :: from_url ( URL4 ) . unwrap ( ) ;
1431
+ assert_eq ! (
1432
+ opts. ssl_opts( ) ,
1433
+ Some (
1434
+ & SslOpts :: default ( )
1435
+ . with_danger_accept_invalid_certs( true )
1436
+ . with_danger_skip_domain_validation( true )
1437
+ )
1438
+ ) ;
1439
+
1440
+ const URL5 : & str =
1441
+ "mysql://localhost/foo?require_ssl=false&verify_ca=false&verify_identity=false" ;
1442
+ let opts = Opts :: from_url ( URL5 ) . unwrap ( ) ;
1443
+ assert_eq ! ( opts. ssl_opts( ) , None ) ;
1444
+ }
1445
+
1348
1446
#[ test]
1349
1447
#[ should_panic]
1350
1448
fn should_panic_on_invalid_url ( ) {
0 commit comments