Skip to content

Commit 8ae8b5e

Browse files
committed
Auto merge of #7308 - guanqun:add-ssl-version, r=alexcrichton
add an option to specify ssl version Fixes #6684
2 parents 99c034a + 852cf05 commit 8ae8b5e

File tree

5 files changed

+157
-6
lines changed

5 files changed

+157
-6
lines changed

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ cargo-platform = { path = "crates/cargo-platform", version = "0.1" }
2525
crates-io = { path = "crates/crates-io", version = "0.29" }
2626
crossbeam-utils = "0.6"
2727
crypto-hash = "0.3.1"
28-
curl = { version = "0.4.21", features = ['http2'] }
29-
curl-sys = "0.4.18"
28+
curl = { version = "0.4.23", features = ['http2'] }
29+
curl-sys = "0.4.21"
3030
env_logger = "0.7.0"
3131
pretty_env_logger = { version = "0.3", optional = true }
3232
failure = "0.1.5"

src/cargo/ops/registry.rs

+37-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::time::Duration;
77
use std::{cmp, env};
88

99
use crates_io::{NewCrate, NewCrateDependency, Registry};
10-
use curl::easy::{Easy, InfoType, SslOpt};
10+
use curl::easy::{Easy, InfoType, SslOpt, SslVersion};
1111
use failure::{bail, format_err};
1212
use log::{log, Level};
1313
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
@@ -18,7 +18,7 @@ use crate::core::source::Source;
1818
use crate::core::{Package, SourceId, Workspace};
1919
use crate::ops;
2020
use crate::sources::{RegistrySource, SourceConfigMap, CRATES_IO_REGISTRY};
21-
use crate::util::config::{self, Config};
21+
use crate::util::config::{self, Config, SslVersionConfig, SslVersionConfigRange};
2222
use crate::util::errors::{CargoResult, CargoResultExt};
2323
use crate::util::important_paths::find_root_manifest_for_wd;
2424
use crate::util::IntoUrl;
@@ -413,12 +413,14 @@ pub fn needs_custom_http_transport(config: &Config) -> CargoResult<bool> {
413413
let cainfo = config.get_path("http.cainfo")?;
414414
let check_revoke = config.get_bool("http.check-revoke")?;
415415
let user_agent = config.get_string("http.user-agent")?;
416+
let ssl_version = config.get::<Option<SslVersionConfig>>("http.ssl-version")?;
416417

417418
Ok(proxy_exists
418419
|| timeout
419420
|| cainfo.is_some()
420421
|| check_revoke.is_some()
421-
|| user_agent.is_some())
422+
|| user_agent.is_some()
423+
|| ssl_version.is_some())
422424
}
423425

424426
/// Configure a libcurl http handle with the defaults options for Cargo
@@ -438,6 +440,38 @@ pub fn configure_http_handle(config: &Config, handle: &mut Easy) -> CargoResult<
438440
handle.useragent(&version().to_string())?;
439441
}
440442

443+
fn to_ssl_version(s: &str) -> CargoResult<SslVersion> {
444+
let version = match s {
445+
"default" => SslVersion::Default,
446+
"tlsv1" => SslVersion::Tlsv1,
447+
"tlsv1.0" => SslVersion::Tlsv10,
448+
"tlsv1.1" => SslVersion::Tlsv11,
449+
"tlsv1.2" => SslVersion::Tlsv12,
450+
"tlsv1.3" => SslVersion::Tlsv13,
451+
_ => bail!(
452+
"Invalid ssl version `{}`,\
453+
choose from 'default', 'tlsv1', 'tlsv1.0', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3'.",
454+
s
455+
),
456+
};
457+
Ok(version)
458+
}
459+
if let Some(ssl_version) = config.get::<Option<SslVersionConfig>>("http.ssl-version")? {
460+
match ssl_version {
461+
SslVersionConfig::Single(s) => {
462+
let version = to_ssl_version(s.as_str())?;
463+
handle.ssl_version(version)?;
464+
}
465+
SslVersionConfig::Range(SslVersionConfigRange { min, max }) => {
466+
let min_version =
467+
min.map_or(Ok(SslVersion::Default), |s| to_ssl_version(s.as_str()))?;
468+
let max_version =
469+
max.map_or(Ok(SslVersion::Default), |s| to_ssl_version(s.as_str()))?;
470+
handle.ssl_min_max_version(min_version, max_version)?;
471+
}
472+
}
473+
}
474+
441475
if let Some(true) = config.get::<Option<bool>>("http.debug")? {
442476
handle.verbose(true)?;
443477
handle.debug_function(|kind, data| {

src/cargo/util/config.rs

+26
Original file line numberDiff line numberDiff line change
@@ -1854,3 +1854,29 @@ pub fn clippy_driver() -> PathBuf {
18541854
.unwrap_or_else(|_| "clippy-driver".into())
18551855
.into()
18561856
}
1857+
1858+
/// Configuration for `ssl-version` in `http` section
1859+
/// There are two ways to configure:
1860+
///
1861+
/// ```text
1862+
/// [http]
1863+
/// ssl-version = "tlsv1.3"
1864+
/// ```
1865+
///
1866+
/// ```text
1867+
/// [http]
1868+
/// ssl-version.min = "tlsv1.2"
1869+
/// ssl-version.max = "tlsv1.3"
1870+
/// ```
1871+
#[derive(Clone, Debug, Deserialize)]
1872+
#[serde(untagged)]
1873+
pub enum SslVersionConfig {
1874+
Single(String),
1875+
Range(SslVersionConfigRange),
1876+
}
1877+
1878+
#[derive(Clone, Debug, Deserialize)]
1879+
pub struct SslVersionConfigRange {
1880+
pub min: Option<String>,
1881+
pub max: Option<String>,
1882+
}

src/doc/src/reference/config.md

+7
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ proxy = "host:port" # HTTP proxy to use for HTTP requests (defaults to none)
107107
timeout = 30 # Timeout for each HTTP request, in seconds
108108
cainfo = "cert.pem" # Path to Certificate Authority (CA) bundle (optional)
109109
check-revoke = true # Indicates whether SSL certs are checked for revocation
110+
ssl-version = "tlsv1.3" # Indicates which SSL version or above to use (options are
111+
# "default", "tlsv1", "tlsv1.0", "tlsv1.1", "tlsv1.2", "tlsv1.3")
112+
# To better control SSL version, we can even use
113+
# `ssl-version.min = "..."` and `ssl-version.max = "..."`
114+
# where "..." is one of the above options. But note these two forms
115+
# ("setting `ssl-version`" and "setting both `min`/`max`)
116+
# can't co-exist.
110117
low-speed-limit = 5 # Lower threshold for bytes/sec (10 = default, 0 = disabled)
111118
multiplexing = true # whether or not to use HTTP/2 multiplexing where possible
112119

tests/testsuite/config.rs

+85-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::os;
66
use std::path::Path;
77

88
use cargo::core::{enable_nightly_features, Shell};
9-
use cargo::util::config::{self, Config};
9+
use cargo::util::config::{self, Config, SslVersionConfig};
1010
use cargo::util::toml::{self, VecStringOrBool as VSOB};
1111
use cargo_test_support::{paths, project, t};
1212
use serde::Deserialize;
@@ -833,3 +833,87 @@ i64max = 9223372036854775807
833833
invalid value: integer `123456789`, expected i8",
834834
);
835835
}
836+
837+
#[cargo_test]
838+
fn config_get_ssl_version_missing() {
839+
write_config(
840+
"\
841+
[http]
842+
hello = 'world'
843+
",
844+
);
845+
846+
let config = new_config(&[]);
847+
848+
assert!(config
849+
.get::<Option<SslVersionConfig>>("http.ssl-version")
850+
.unwrap()
851+
.is_none());
852+
}
853+
854+
#[cargo_test]
855+
fn config_get_ssl_version_single() {
856+
write_config(
857+
"\
858+
[http]
859+
ssl-version = 'tlsv1.2'
860+
",
861+
);
862+
863+
let config = new_config(&[]);
864+
865+
let a = config
866+
.get::<Option<SslVersionConfig>>("http.ssl-version")
867+
.unwrap()
868+
.unwrap();
869+
match a {
870+
SslVersionConfig::Single(v) => assert_eq!(&v, "tlsv1.2"),
871+
SslVersionConfig::Range(_) => panic!("Did not expect ssl version min/max."),
872+
};
873+
}
874+
875+
#[cargo_test]
876+
fn config_get_ssl_version_min_max() {
877+
write_config(
878+
"\
879+
[http]
880+
ssl-version.min = 'tlsv1.2'
881+
ssl-version.max = 'tlsv1.3'
882+
",
883+
);
884+
885+
let config = new_config(&[]);
886+
887+
let a = config
888+
.get::<Option<SslVersionConfig>>("http.ssl-version")
889+
.unwrap()
890+
.unwrap();
891+
match a {
892+
SslVersionConfig::Single(_) => panic!("Did not expect exact ssl version."),
893+
SslVersionConfig::Range(range) => {
894+
assert_eq!(range.min, Some(String::from("tlsv1.2")));
895+
assert_eq!(range.max, Some(String::from("tlsv1.3")));
896+
}
897+
};
898+
}
899+
900+
#[cargo_test]
901+
fn config_get_ssl_version_both_forms_configured() {
902+
// this is not allowed
903+
write_config(
904+
"\
905+
[http]
906+
ssl-version = 'tlsv1.1'
907+
ssl-version.min = 'tlsv1.2'
908+
ssl-version.max = 'tlsv1.3'
909+
",
910+
);
911+
912+
let config = new_config(&[]);
913+
914+
assert!(config.get::<SslVersionConfig>("http.ssl-version").is_err());
915+
assert!(config
916+
.get::<Option<SslVersionConfig>>("http.ssl-version")
917+
.unwrap()
918+
.is_none());
919+
}

0 commit comments

Comments
 (0)