Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to http.sslVerify #1135

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions gix-transport/src/client/blocking_io/http/curl/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ pub fn new() -> (
verbose,
ssl_ca_info,
ssl_version,
ssl_verify,
http_version,
backend,
},
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 4 additions & 0 deletions gix-transport/src/client/blocking_io/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ pub struct Options {
pub ssl_ca_info: Option<PathBuf>,
/// The SSL version or version range to use, or `None` to let the TLS backend determine which versions are acceptable.
pub ssl_version: Option<SslVersionRangeInclusive>,
/// 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<HttpVersion>,
/// Backend specific options, if available.
Expand Down
3 changes: 3 additions & 0 deletions gix/src/config/tree/sections/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
11 changes: 11 additions & 0 deletions gix/src/repository/config/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,17 @@ impl crate::Repository {
}
}

{
let key = "http.sslVerify";
opts.ssl_verify = config
.boolean_filter_by_key(key, &mut trusted_only)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take a look around and note that each of the keys above in some way references a respective static version of the key they access. This must be done here as well, and there should be a Http::SSL_VERIFY constant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a debug_assert to ensure the key match the constants, is that what you meant?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's close. The question is why it shouldn't (potentially) fail if the value can't be read. In this line there is an example for how to do this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I understand what you mean, I added it.

.map(|value| config::tree::Http::SSL_VERIFY.enrich_error(value))
.transpose()
.with_leniency(lenient)
.map_err(config::transport::http::Error::from)?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicit mapping shouldn't be required here, even though it might be required where it was copied from.

.unwrap_or(true);
}

#[cfg(feature = "blocking-http-transport-curl")]
{
let key = "http.schannelCheckRevoke";
Expand Down
5 changes: 5 additions & 0 deletions gix/tests/fixtures/make_config_repos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
13 changes: 13 additions & 0 deletions gix/tests/repository/config/transport_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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));
}

Expand Down Expand Up @@ -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);
}
}
4 changes: 0 additions & 4 deletions src/plumbing/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,10 +408,6 @@ static GIT_CONFIG: &[Record] = &[
config: "http.sslCipherList",
usage: NotPlanned { reason: "on demand" }
},
Record {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good rule of thumb that whenever something is removed here, it should be added as a constant.

Copy link
Contributor Author

@Alvenix Alvenix Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the constant, but I am not sure if I should link it with the environment variable: GIT_SSL_NO_VERIFY, as I didn't add support for it and it is the negation of sslVerify.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's a great point!

Keys can have an environment variable attached to it using this method. These then needs to be initialized here. However, as it is a negation, we'd need add our own version of that variable as gitoxide.http.sslNoVerify, link it with (with a description()) GIT_SSL_NO_VERIFY, initialize it, test it, and then let it override any value that http.sslVerify may have just like git.

Hooking up variables is quite involved, but that separation is needed to avoid global state (like environment variables) to sneak in. This way they are controlled and used exactly in one or two places in the codebase, while being introspectable via gix config and controllable (as one can turn off certain kinds of environment variables from being read).

config: "http.sslVerify",
usage: NotPlanned { reason: "on demand" }
},
Record {
config: "http.sslCert",
usage: NotPlanned { reason: "on demand" }
Expand Down
Loading