Skip to content

Commit ef56deb

Browse files
committed
Auto merge of #13970 - weihanglo:[email protected], r=ehuss
fix: adjust custom err from cert-check due to libgit2 1.8 change
2 parents 4a86f6f + 0978162 commit ef56deb

File tree

3 files changed

+31
-19
lines changed

3 files changed

+31
-19
lines changed

src/cargo/sources/git/known_hosts.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
//! and revoked markers. See "FIXME" comments littered in this file.
2424
2525
use crate::util::context::{Definition, GlobalContext, Value};
26+
use crate::CargoResult;
2627
use base64::engine::general_purpose::STANDARD;
2728
use base64::engine::general_purpose::STANDARD_NO_PAD;
2829
use base64::Engine as _;
@@ -137,7 +138,7 @@ pub fn certificate_check(
137138
port: Option<u16>,
138139
config_known_hosts: Option<&Vec<Value<String>>>,
139140
diagnostic_home_config: &str,
140-
) -> Result<CertificateCheckStatus, git2::Error> {
141+
) -> CargoResult<CertificateCheckStatus> {
141142
let Some(host_key) = cert.as_hostkey() else {
142143
// Return passthrough for TLS X509 certificates to use whatever validation
143144
// was done in git2.
@@ -150,13 +151,12 @@ pub fn certificate_check(
150151
_ => host.to_string(),
151152
};
152153
// The error message must be constructed as a string to pass through the libgit2 C API.
153-
let err_msg = match check_ssh_known_hosts(gctx, host_key, &host_maybe_port, config_known_hosts)
154-
{
154+
match check_ssh_known_hosts(gctx, host_key, &host_maybe_port, config_known_hosts) {
155155
Ok(()) => {
156156
return Ok(CertificateCheckStatus::CertificateOk);
157157
}
158158
Err(KnownHostError::CheckError(e)) => {
159-
format!("error: failed to validate host key:\n{:#}", e)
159+
anyhow::bail!("error: failed to validate host key:\n{:#}", e)
160160
}
161161
Err(KnownHostError::HostKeyNotFound {
162162
hostname,
@@ -193,7 +193,7 @@ pub fn certificate_check(
193193
}
194194
msg
195195
};
196-
format!("error: unknown SSH host key\n\
196+
anyhow::bail!("error: unknown SSH host key\n\
197197
The SSH host key for `{hostname}` is not known and cannot be validated.\n\
198198
\n\
199199
To resolve this issue, add the host key to {known_hosts_location}\n\
@@ -242,7 +242,7 @@ pub fn certificate_check(
242242
)
243243
}
244244
};
245-
format!("error: SSH host key has changed for `{hostname}`\n\
245+
anyhow::bail!("error: SSH host key has changed for `{hostname}`\n\
246246
*********************************\n\
247247
* WARNING: HOST KEY HAS CHANGED *\n\
248248
*********************************\n\
@@ -274,7 +274,7 @@ pub fn certificate_check(
274274
location,
275275
}) => {
276276
let key_type_short_name = key_type.short_name();
277-
format!(
277+
anyhow::bail!(
278278
"error: Key has been revoked for `{hostname}`\n\
279279
**************************************\n\
280280
* WARNING: REVOKED HOST KEY DETECTED *\n\
@@ -288,7 +288,7 @@ pub fn certificate_check(
288288
)
289289
}
290290
Err(KnownHostError::HostHasOnlyCertAuthority { hostname, location }) => {
291-
format!("error: Found a `@cert-authority` marker for `{hostname}`\n\
291+
anyhow::bail!("error: Found a `@cert-authority` marker for `{hostname}`\n\
292292
\n\
293293
Cargo doesn't support certificate authorities for host key verification. It is\n\
294294
recommended that the command line Git client is used instead. This can be achieved\n\
@@ -300,12 +300,7 @@ pub fn certificate_check(
300300
for more information.\n\
301301
")
302302
}
303-
};
304-
Err(git2::Error::new(
305-
git2::ErrorCode::GenericError,
306-
git2::ErrorClass::Callback,
307-
err_msg,
308-
))
303+
}
309304
}
310305

311306
/// Checks if the given host/host key pair is known.

src/cargo/sources/git/utils.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,10 @@ pub fn with_fetch_options(
831831
let config_known_hosts = ssh_config.and_then(|ssh| ssh.known_hosts.as_ref());
832832
let diagnostic_home_config = gctx.diagnostic_home_config();
833833
network::retry::with_retry(gctx, || {
834-
with_authentication(gctx, url, git_config, |f| {
834+
// Hack: libgit2 disallows overriding the error from check_cb since v1.8.0,
835+
// so we store the error additionally and unwrap it later
836+
let mut check_cb_result = Ok(());
837+
let auth_result = with_authentication(gctx, url, git_config, |f| {
835838
let port = Url::parse(url).ok().and_then(|url| url.port());
836839
let mut last_update = Instant::now();
837840
let mut rcb = git2::RemoteCallbacks::new();
@@ -840,14 +843,24 @@ pub fn with_fetch_options(
840843
let mut counter = MetricsCounter::<10>::new(0, last_update);
841844
rcb.credentials(f);
842845
rcb.certificate_check(|cert, host| {
843-
super::known_hosts::certificate_check(
846+
match super::known_hosts::certificate_check(
844847
gctx,
845848
cert,
846849
host,
847850
port,
848851
config_known_hosts,
849852
&diagnostic_home_config,
850-
)
853+
) {
854+
Ok(status) => Ok(status),
855+
Err(e) => {
856+
check_cb_result = Err(e);
857+
// This is not really used because it'll be overridden by libgit2
858+
// See https://github.com/libgit2/libgit2/commit/9a9f220119d9647a352867b24b0556195cb26548
859+
Err(git2::Error::from_str(
860+
"invalid or unknown remote ssh hostkey",
861+
))
862+
}
863+
}
851864
});
852865
rcb.transfer_progress(|stats| {
853866
let indexed_deltas = stats.indexed_deltas();
@@ -889,7 +902,11 @@ pub fn with_fetch_options(
889902
let mut opts = git2::FetchOptions::new();
890903
opts.remote_callbacks(rcb);
891904
cb(opts)
892-
})?;
905+
});
906+
if auth_result.is_err() {
907+
check_cb_result?;
908+
}
909+
auth_result?;
893910
Ok(())
894911
})
895912
}

tests/testsuite/https.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn self_signed_should_fail() {
3333
let err_msg = if cfg!(target_os = "macos") {
3434
"untrusted connection error; class=Ssl (16); code=Certificate (-17)"
3535
} else if cfg!(unix) {
36-
"the SSL certificate is invalid; class=Ssl (16); code=Certificate (-17)"
36+
"the SSL certificate is invalid; class=Ssl (16)[..]"
3737
} else if cfg!(windows) {
3838
"user cancelled certificate check; class=Http (34); code=Certificate (-17)"
3939
} else {

0 commit comments

Comments
 (0)