From 08d36f6458c3e1041e66a8ad8a9a7a215e23c74e Mon Sep 17 00:00:00 2001 From: Abdullah Alyan Date: Wed, 29 Nov 2023 15:30:26 +0300 Subject: [PATCH 1/3] feat: Add verify_ssl field to gix-transport Options which is used to disable SSL verification. Currently this option only works in the curl backend. --- gix-transport/src/client/blocking_io/http/curl/remote.rs | 3 +++ gix-transport/src/client/blocking_io/http/mod.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/gix-transport/src/client/blocking_io/http/curl/remote.rs b/gix-transport/src/client/blocking_io/http/curl/remote.rs index e6b0bee03fe..1557f5a9cbd 100644 --- a/gix-transport/src/client/blocking_io/http/curl/remote.rs +++ b/gix-transport/src/client/blocking_io/http/curl/remote.rs @@ -157,6 +157,7 @@ pub fn new() -> ( verbose, ssl_ca_info, ssl_version, + ssl_verify, http_version, backend, }, @@ -194,6 +195,8 @@ pub fn new() -> ( } } + handle.ssl_verify_peer(ssl_verify)?; + if let Some(http_version) = http_version { let version = match http_version { HttpVersion::V1_1 => curl::easy::HttpVersion::V11, diff --git a/gix-transport/src/client/blocking_io/http/mod.rs b/gix-transport/src/client/blocking_io/http/mod.rs index 055b4ea591a..dbdb400551e 100644 --- a/gix-transport/src/client/blocking_io/http/mod.rs +++ b/gix-transport/src/client/blocking_io/http/mod.rs @@ -179,6 +179,10 @@ pub struct Options { pub ssl_ca_info: Option, /// The SSL version or version range to use, or `None` to let the TLS backend determine which versions are acceptable. pub ssl_version: Option, + /// Controls whether to perform SSL identity verification or not. Turning this off is not recommended and can lead to + /// various security risks. An example where this may be needed is when an internal git server uses a self-signed + /// certificate and the user accepts the associated security risks. + pub ssl_verify: bool, /// The HTTP version to enforce. If unset, it is implementation defined. pub http_version: Option, /// Backend specific options, if available. From 7655be0c2e92f0cd3b0c685f7091ec951652ff5d Mon Sep 17 00:00:00 2001 From: Abdullah Alyan Date: Wed, 29 Nov 2023 15:34:30 +0300 Subject: [PATCH 2/3] feat: In gix read http.sslVerify config value and pass it to gix-transport. --- gix/src/config/tree/sections/http.rs | 3 +++ gix/src/repository/config/transport.rs | 11 +++++++++++ gix/tests/fixtures/make_config_repos.sh | 5 +++++ gix/tests/repository/config/transport_options.rs | 13 +++++++++++++ src/plumbing/progress.rs | 4 ---- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/gix/src/config/tree/sections/http.rs b/gix/src/config/tree/sections/http.rs index f45c3707616..2ceeeadc8a7 100644 --- a/gix/src/config/tree/sections/http.rs +++ b/gix/src/config/tree/sections/http.rs @@ -10,6 +10,9 @@ impl Http { .with_deviation( "accepts the new 'default' value which means to use the curl default just like the empty string does", ); + /// The `http.sslVerify` key. + pub const SSL_VERIFY: keys::Boolean = keys::Boolean::new_boolean("sslVerify", &config::Tree::HTTP) + .with_deviation("Only supported when using curl as https backend"); /// The `http.proxy` key. pub const PROXY: keys::String = keys::String::new_string("proxy", &config::Tree::HTTP).with_deviation("fails on strings with illformed UTF-8"); diff --git a/gix/src/repository/config/transport.rs b/gix/src/repository/config/transport.rs index 99b5a7f47ff..7d759c3bb03 100644 --- a/gix/src/repository/config/transport.rs +++ b/gix/src/repository/config/transport.rs @@ -405,6 +405,17 @@ impl crate::Repository { } } + { + let key = "http.sslVerify"; + opts.ssl_verify = config + .boolean_filter_by_key(key, &mut trusted_only) + .map(|value| config::tree::Http::SSL_VERIFY.enrich_error(value)) + .transpose() + .with_leniency(lenient) + .map_err(config::transport::http::Error::from)? + .unwrap_or(true); + } + #[cfg(feature = "blocking-http-transport-curl")] { let key = "http.schannelCheckRevoke"; diff --git a/gix/tests/fixtures/make_config_repos.sh b/gix/tests/fixtures/make_config_repos.sh index 447a7a72e07..dee8d1952af 100755 --- a/gix/tests/fixtures/make_config_repos.sh +++ b/gix/tests/fixtures/make_config_repos.sh @@ -164,3 +164,8 @@ mkdir not-a-repo-with-files; (cd not-a-repo-with-files touch this that ) + +git init no-ssl-verify +(cd no-ssl-verify + git config http.sslVerify false +) diff --git a/gix/tests/repository/config/transport_options.rs b/gix/tests/repository/config/transport_options.rs index 85f7b8e6299..16bdc3feb8d 100644 --- a/gix/tests/repository/config/transport_options.rs +++ b/gix/tests/repository/config/transport_options.rs @@ -55,6 +55,7 @@ mod http { verbose, ssl_ca_info, ssl_version, + ssl_verify, http_version, backend, } = http_options(&repo, None, "https://example.com/does/not/matter"); @@ -106,6 +107,9 @@ mod http { max: version }) ); + + assert!(ssl_verify, "SSL verification is enabled by default if not configured"); + assert_eq!(http_version, Some(HttpVersion::V1_1)); } @@ -314,4 +318,13 @@ mod http { assert_eq!(opts.proxy.as_deref(), Some("http://localhost:9090")); assert_eq!(opts.follow_redirects, FollowRedirects::Initial); } + + #[test] + fn no_ssl_verify() { + let repo = repo("no-ssl-verify"); + + let opts = http_options(&repo, None, "https://example.com/does/not/matter"); + + assert!(!opts.ssl_verify); + } } diff --git a/src/plumbing/progress.rs b/src/plumbing/progress.rs index 21b56fa71d8..5a9f033ec55 100644 --- a/src/plumbing/progress.rs +++ b/src/plumbing/progress.rs @@ -408,10 +408,6 @@ static GIT_CONFIG: &[Record] = &[ config: "http.sslCipherList", usage: NotPlanned { reason: "on demand" } }, - Record { - config: "http.sslVerify", - usage: NotPlanned { reason: "on demand" } - }, Record { config: "http.sslCert", usage: NotPlanned { reason: "on demand" } From 8fdd3110ebdf35e37736862ee93967e5ee207e4e Mon Sep 17 00:00:00 2001 From: Abdullah Alyan Date: Thu, 30 Nov 2023 14:24:27 +0300 Subject: [PATCH 3/3] feat: Add config value gitoxide.http.sslNoVerify This value can by overriden by GIT_SSL_NO_VERIFY env variable. We use the value to override http.sslVerify when specifying ssl_verify in transport Options. --- gix/src/config/cache/init.rs | 4 ++++ gix/src/config/tree/sections/gitoxide.rs | 10 ++++++++++ gix/src/repository/config/transport.rs | 20 +++++++++++++++++++- gix/tests/gix-init.rs | 2 ++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/gix/src/config/cache/init.rs b/gix/src/config/cache/init.rs index 7f6bc0ab3fc..4040a7e2f0b 100644 --- a/gix/src/config/cache/init.rs +++ b/gix/src/config/cache/init.rs @@ -384,6 +384,10 @@ fn apply_environment_overrides( let key = &gitoxide::Http::VERBOSE; (env(key), key.name) }, + { + let key = &gitoxide::Http::SSL_NO_VERIFY; + (env(key), key.name) + }, { let key = &gitoxide::Http::PROXY_AUTH_METHOD; (env(key), key.name) diff --git a/gix/src/config/tree/sections/gitoxide.rs b/gix/src/config/tree/sections/gitoxide.rs index f1eb7a23bd6..f386b43c0f7 100644 --- a/gix/src/config/tree/sections/gitoxide.rs +++ b/gix/src/config/tree/sections/gitoxide.rs @@ -179,6 +179,15 @@ mod subsections { http::SslVersion::new_ssl_version("sslVersionMax", &Gitoxide::HTTP).with_note( "entirely new to set the upper bound for the allowed ssl version range. Overwrites the max bound of `http.sslVersion` if set. Min and Max must be set to become effective.", ); + /// The `gitoxide.http.sslNoVerify` key. + /// + /// If set, disable SSL verification. Using this is discouraged as it can lead to + /// various security risks. An example where this may be needed is when an internal + /// git server uses a self-signed certificate and the user accepts the associated security risks. + pub const SSL_NO_VERIFY: keys::Boolean = keys::Boolean::new_boolean("sslNoVerify", &Gitoxide::HTTP) + .with_environment_override("GIT_SSL_NO_VERIFY") + .with_deviation("Only supported when using curl as https backend") + .with_note("Used to disable SSL verification. When this is enabled it takes prority over http.sslVerify."); /// The `gitoxide.http.proxyAuthMethod` key. pub const PROXY_AUTH_METHOD: http::ProxyAuthMethod = http::ProxyAuthMethod::new_proxy_auth_method("proxyAuthMethod", &Gitoxide::HTTP) @@ -199,6 +208,7 @@ mod subsections { &Self::CONNECT_TIMEOUT, &Self::SSL_VERSION_MIN, &Self::SSL_VERSION_MAX, + &Self::SSL_NO_VERIFY, &Self::PROXY_AUTH_METHOD, ] } diff --git a/gix/src/repository/config/transport.rs b/gix/src/repository/config/transport.rs index 7d759c3bb03..eb89e455b0a 100644 --- a/gix/src/repository/config/transport.rs +++ b/gix/src/repository/config/transport.rs @@ -407,13 +407,31 @@ impl crate::Repository { { let key = "http.sslVerify"; - opts.ssl_verify = config + let ssl_verify = config .boolean_filter_by_key(key, &mut trusted_only) .map(|value| config::tree::Http::SSL_VERIFY.enrich_error(value)) .transpose() .with_leniency(lenient) .map_err(config::transport::http::Error::from)? .unwrap_or(true); + + let ssl_no_verify = config + .boolean_filter( + "gitoxide", + Some("http".into()), + gitoxide::Http::SSL_NO_VERIFY.name, + &mut trusted_only, + ) + .and_then(Result::ok) + .unwrap_or_default(); + + // ssl_no_verify take prority here because it is based on environment variable + // and we try to match git behavior. + if ssl_no_verify { + opts.ssl_verify = false; + } else { + opts.ssl_verify = ssl_verify; + } } #[cfg(feature = "blocking-http-transport-curl")] diff --git a/gix/tests/gix-init.rs b/gix/tests/gix-init.rs index 531f89e9297..b6a51c5e1f7 100644 --- a/gix/tests/gix-init.rs +++ b/gix/tests/gix-init.rs @@ -19,6 +19,7 @@ mod with_overrides { .set("GIT_HTTP_LOW_SPEED_LIMIT", "1") .set("GIT_HTTP_LOW_SPEED_TIME", "1") .set("GIT_HTTP_PROXY_AUTHMETHOD", "proxy-auth-method-env") + .set("GIT_SSL_NO_VERIFY", "true") .set("GIT_CURL_VERBOSE", "true") .set("https_proxy", "https-lower-override") .set("HTTPS_PROXY", "https-upper") @@ -231,6 +232,7 @@ mod with_overrides { ] ); for (key, expected) in [ + ("gitoxide.http.sslNoVerify", "true"), ("gitoxide.http.verbose", "true"), ("gitoxide.allow.protocolFromUser", "file-allowed"), ("core.useReplaceRefs", "no-replace"),