Skip to content

Commit 0ae910a

Browse files
committed
Merge remote-tracking branch 'upstream/owner' into owner
* upstream/owner: (21 commits) Don't place side-effect expressions in assert! macros. Add `_MS` suffix to retry constants. Add some more docs and comments to `SleepTracker`. Add delays to network retries. Allow RegistryBuilder responder URLs to be a String Split the `cargo::util::network` module into submodules Add a note to `cargo logout` that it does not revoke the token. Sync external-tools JSON docs. Disable test_profile test on windows-gnu Drop derive feature from serde in cargo-platform a{n =>} benchmark target documented working directory behaviour of cargo-test, cargo-bench and cargo-run commands chore: Upgrade to clap v4.2 docs(contrib): Link to office hours doc doc(contrib): missing quotation mark Update changelog for 1.68.2 Add the old github keys as revoked Update proptest Added new GitHub RSA Host Key doc: Fix registries.name.index for sparse ...
2 parents baf3020 + 6573a9e commit 0ae910a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+757
-161
lines changed

CHANGELOG.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@
6969

7070
- Added `-C` flag for changing current dir before build starts.
7171
[#10952](https://github.com/rust-lang/cargo/pull/10952)
72-
- Added support for SSH known hosts marker `@revoked`.
73-
[#11635](https://github.com/rust-lang/cargo/pull/11635)
7472
- Cargo now suggests `cargo fix` or `cargo clippy --fix`
7573
when compilation warnings/errors are auto-fixable.
7674
[#11558](https://github.com/rust-lang/cargo/pull/11558)
@@ -208,6 +206,20 @@
208206
[#11664](https://github.com/rust-lang/cargo/pull/11664)
209207
[#11679](https://github.com/rust-lang/cargo/pull/11679)
210208

209+
## Cargo 1.68.2 (2023-03-28)
210+
[115f3455...rust-1.68.0](https://github.com/rust-lang/cargo/compare/115f3455...rust-1.68.0)
211+
212+
- Updated the GitHub RSA SSH host key bundled within cargo.
213+
The key was [rotated by
214+
GitHub](https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/) on
215+
2023-03-24 after the old one leaked.
216+
[#11883](https://github.com/rust-lang/cargo/pull/11883)
217+
- Added support for SSH known hosts marker `@revoked`.
218+
[#11635](https://github.com/rust-lang/cargo/pull/11635)
219+
- Marked the old GitHub RSA host key as revoked. This will prevent Cargo from
220+
accepting the leaked key even when trusted by the system.
221+
[#11889](https://github.com/rust-lang/cargo/pull/11889)
222+
211223
## Cargo 1.68 (2023-03-09)
212224
[f6e737b1...rust-1.68.0](https://github.com/rust-lang/cargo/compare/f6e737b1...rust-1.68.0)
213225

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ base64 = "0.21.0"
2121
bytesize = "1.0"
2222
cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" }
2323
cargo-util = { path = "crates/cargo-util", version = "0.2.4" }
24-
clap = "4.1.3"
24+
clap = "4.2.0"
2525
crates-io = { path = "crates/crates-io", version = "0.36.0" }
2626
curl = { version = "0.4.44", features = ["http2"] }
2727
curl-sys = "0.4.61"
@@ -58,6 +58,7 @@ os_info = "3.5.0"
5858
pasetors = { version = "0.6.4", features = ["v3", "paserk", "std", "serde"] }
5959
pathdiff = "0.2"
6060
pretty_env_logger = { version = "0.4", optional = true }
61+
rand = "0.8.5"
6162
rustfix = "0.6.0"
6263
semver = { version = "1.0.3", features = ["serde"] }
6364
serde = { version = "1.0.123", features = ["derive"] }

crates/cargo-platform/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ documentation = "https://docs.rs/cargo-platform"
99
description = "Cargo's representation of a target platform."
1010

1111
[dependencies]
12-
serde = { version = "1.0.82", features = ['derive'] }
12+
serde = "1.0.82"

crates/cargo-test-support/src/registry.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub struct RegistryBuilder {
9797
/// Write the registry in configuration.
9898
configure_registry: bool,
9999
/// API responders.
100-
custom_responders: HashMap<&'static str, Box<dyn Send + Fn(&Request, &HttpServer) -> Response>>,
100+
custom_responders: HashMap<String, Box<dyn Send + Fn(&Request, &HttpServer) -> Response>>,
101101
/// If nonzero, the git index update to be delayed by the given number of seconds.
102102
delayed_index_update: usize,
103103
}
@@ -167,10 +167,11 @@ impl RegistryBuilder {
167167
#[must_use]
168168
pub fn add_responder<R: 'static + Send + Fn(&Request, &HttpServer) -> Response>(
169169
mut self,
170-
url: &'static str,
170+
url: impl Into<String>,
171171
responder: R,
172172
) -> Self {
173-
self.custom_responders.insert(url, Box::new(responder));
173+
self.custom_responders
174+
.insert(url.into(), Box::new(responder));
174175
self
175176
}
176177

@@ -601,7 +602,7 @@ pub struct HttpServer {
601602
addr: SocketAddr,
602603
token: Token,
603604
auth_required: bool,
604-
custom_responders: HashMap<&'static str, Box<dyn Send + Fn(&Request, &HttpServer) -> Response>>,
605+
custom_responders: HashMap<String, Box<dyn Send + Fn(&Request, &HttpServer) -> Response>>,
605606
delayed_index_update: usize,
606607
}
607608

@@ -621,10 +622,7 @@ impl HttpServer {
621622
api_path: PathBuf,
622623
token: Token,
623624
auth_required: bool,
624-
api_responders: HashMap<
625-
&'static str,
626-
Box<dyn Send + Fn(&Request, &HttpServer) -> Response>,
627-
>,
625+
api_responders: HashMap<String, Box<dyn Send + Fn(&Request, &HttpServer) -> Response>>,
628626
delayed_index_update: usize,
629627
) -> HttpServerHandle {
630628
let listener = TcpListener::bind("127.0.0.1:0").unwrap();

crates/resolver-tests/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ cargo = { path = "../.." }
88
cargo-util = { path = "../cargo-util" }
99
is-terminal = "0.4.0"
1010
lazy_static = "1.3.0"
11-
proptest = "0.9.1"
11+
proptest = "1.1.0"
1212
varisat = "0.2.1"

src/cargo/core/package.rs

Lines changed: 69 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ use crate::ops;
2828
use crate::util::config::PackageCacheLock;
2929
use crate::util::errors::{CargoResult, HttpNotSuccessful};
3030
use crate::util::interning::InternedString;
31-
use crate::util::network::Retry;
31+
use crate::util::network::retry::{Retry, RetryResult};
32+
use crate::util::network::sleep::SleepTracker;
3233
use crate::util::{self, internal, Config, Progress, ProgressStyle};
3334

3435
pub const MANIFEST_PREAMBLE: &str = "\
@@ -319,6 +320,8 @@ pub struct Downloads<'a, 'cfg> {
319320
/// Set of packages currently being downloaded. This should stay in sync
320321
/// with `pending`.
321322
pending_ids: HashSet<PackageId>,
323+
/// Downloads that have failed and are waiting to retry again later.
324+
sleeping: SleepTracker<(Download<'cfg>, Easy)>,
322325
/// The final result of each download. A pair `(token, result)`. This is a
323326
/// temporary holding area, needed because curl can report multiple
324327
/// downloads at once, but the main loop (`wait`) is written to only
@@ -442,6 +445,7 @@ impl<'cfg> PackageSet<'cfg> {
442445
next: 0,
443446
pending: HashMap::new(),
444447
pending_ids: HashSet::new(),
448+
sleeping: SleepTracker::new(),
445449
results: Vec::new(),
446450
progress: RefCell::new(Some(Progress::with_style(
447451
"Downloading",
@@ -800,7 +804,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
800804

801805
/// Returns the number of crates that are still downloading.
802806
pub fn remaining(&self) -> usize {
803-
self.pending.len()
807+
self.pending.len() + self.sleeping.len()
804808
}
805809

806810
/// Blocks the current thread waiting for a package to finish downloading.
@@ -831,51 +835,52 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
831835
let ret = {
832836
let timed_out = &dl.timed_out;
833837
let url = &dl.url;
834-
dl.retry
835-
.r#try(|| {
836-
if let Err(e) = result {
837-
// If this error is "aborted by callback" then that's
838-
// probably because our progress callback aborted due to
839-
// a timeout. We'll find out by looking at the
840-
// `timed_out` field, looking for a descriptive message.
841-
// If one is found we switch the error code (to ensure
842-
// it's flagged as spurious) and then attach our extra
843-
// information to the error.
844-
if !e.is_aborted_by_callback() {
845-
return Err(e.into());
846-
}
838+
dl.retry.r#try(|| {
839+
if let Err(e) = result {
840+
// If this error is "aborted by callback" then that's
841+
// probably because our progress callback aborted due to
842+
// a timeout. We'll find out by looking at the
843+
// `timed_out` field, looking for a descriptive message.
844+
// If one is found we switch the error code (to ensure
845+
// it's flagged as spurious) and then attach our extra
846+
// information to the error.
847+
if !e.is_aborted_by_callback() {
848+
return Err(e.into());
849+
}
847850

848-
return Err(match timed_out.replace(None) {
849-
Some(msg) => {
850-
let code = curl_sys::CURLE_OPERATION_TIMEDOUT;
851-
let mut err = curl::Error::new(code);
852-
err.set_extra(msg);
853-
err
854-
}
855-
None => e,
851+
return Err(match timed_out.replace(None) {
852+
Some(msg) => {
853+
let code = curl_sys::CURLE_OPERATION_TIMEDOUT;
854+
let mut err = curl::Error::new(code);
855+
err.set_extra(msg);
856+
err
856857
}
857-
.into());
858+
None => e,
858859
}
860+
.into());
861+
}
859862

860-
let code = handle.response_code()?;
861-
if code != 200 && code != 0 {
862-
let url = handle.effective_url()?.unwrap_or(url);
863-
return Err(HttpNotSuccessful {
864-
code,
865-
url: url.to_string(),
866-
body: data,
867-
}
868-
.into());
863+
let code = handle.response_code()?;
864+
if code != 200 && code != 0 {
865+
let url = handle.effective_url()?.unwrap_or(url);
866+
return Err(HttpNotSuccessful {
867+
code,
868+
url: url.to_string(),
869+
body: data,
869870
}
870-
Ok(data)
871-
})
872-
.with_context(|| format!("failed to download from `{}`", dl.url))?
871+
.into());
872+
}
873+
Ok(data)
874+
})
873875
};
874876
match ret {
875-
Some(data) => break (dl, data),
876-
None => {
877-
self.pending_ids.insert(dl.id);
878-
self.enqueue(dl, handle)?
877+
RetryResult::Success(data) => break (dl, data),
878+
RetryResult::Err(e) => {
879+
return Err(e.context(format!("failed to download from `{}`", dl.url)))
880+
}
881+
RetryResult::Retry(sleep) => {
882+
debug!("download retry {} for {sleep}ms", dl.url);
883+
self.sleeping.push(sleep, (dl, handle));
879884
}
880885
}
881886
};
@@ -963,6 +968,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
963968
// actually block waiting for I/O to happen, which we achieve with the
964969
// `wait` method on `multi`.
965970
loop {
971+
self.add_sleepers()?;
966972
let n = tls::set(self, || {
967973
self.set
968974
.multi
@@ -985,17 +991,31 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
985991
if let Some(pair) = results.pop() {
986992
break Ok(pair);
987993
}
988-
assert!(!self.pending.is_empty());
989-
let min_timeout = Duration::new(1, 0);
990-
let timeout = self.set.multi.get_timeout()?.unwrap_or(min_timeout);
991-
let timeout = timeout.min(min_timeout);
992-
self.set
993-
.multi
994-
.wait(&mut [], timeout)
995-
.with_context(|| "failed to wait on curl `Multi`")?;
994+
assert_ne!(self.remaining(), 0);
995+
if self.pending.is_empty() {
996+
let delay = self.sleeping.time_to_next().unwrap();
997+
debug!("sleeping main thread for {delay:?}");
998+
std::thread::sleep(delay);
999+
} else {
1000+
let min_timeout = Duration::new(1, 0);
1001+
let timeout = self.set.multi.get_timeout()?.unwrap_or(min_timeout);
1002+
let timeout = timeout.min(min_timeout);
1003+
self.set
1004+
.multi
1005+
.wait(&mut [], timeout)
1006+
.with_context(|| "failed to wait on curl `Multi`")?;
1007+
}
9961008
}
9971009
}
9981010

1011+
fn add_sleepers(&mut self) -> CargoResult<()> {
1012+
for (dl, handle) in self.sleeping.to_retry() {
1013+
self.pending_ids.insert(dl.id);
1014+
self.enqueue(dl, handle)?;
1015+
}
1016+
Ok(())
1017+
}
1018+
9991019
fn progress(&self, token: usize, total: u64, cur: u64) -> bool {
10001020
let dl = &self.pending[&token].0;
10011021
dl.total.set(total);
@@ -1061,7 +1081,7 @@ impl<'a, 'cfg> Downloads<'a, 'cfg> {
10611081
return Ok(());
10621082
}
10631083
}
1064-
let pending = self.pending.len();
1084+
let pending = self.remaining();
10651085
let mut msg = if pending == 1 {
10661086
format!("{} crate", pending)
10671087
} else {

src/cargo/ops/cargo_run.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ pub fn run(
9393
};
9494
let pkg = bins[0].0;
9595
let mut process = compile.target_process(exe, unit.kind, pkg, *script_meta)?;
96+
97+
// Sets the working directory of the child process to the current working
98+
// directory of the parent process.
99+
// Overrides the default working directory of the `ProcessBuilder` returned
100+
// by `compile.target_process` (the package's root directory)
96101
process.args(args).cwd(config.cwd());
97102

98103
config.shell().status("Running", process.to_string())?;

src/cargo/ops/registry.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,20 @@ pub fn registry_logout(config: &Config, reg: Option<&str>) -> CargoResult<()> {
956956
reg_name
957957
),
958958
)?;
959+
let location = if source_ids.original.is_crates_io() {
960+
"<https://crates.io/me>".to_string()
961+
} else {
962+
// The URL for the source requires network access to load the config.
963+
// That could be a fairly heavy operation to perform just to provide a
964+
// help message, so for now this just provides some generic text.
965+
// Perhaps in the future this could have an API to fetch the config if
966+
// it is cached, but avoid network access otherwise?
967+
format!("the `{reg_name}` website")
968+
};
969+
config.shell().note(format!(
970+
"This does not revoke the token on the registry server.\n \
971+
If you need to revoke the token, visit {location} and follow the instructions there."
972+
))?;
959973
Ok(())
960974
}
961975

src/cargo/sources/git/known_hosts.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,20 @@ use std::path::{Path, PathBuf};
4343
static BUNDLED_KEYS: &[(&str, &str, &str)] = &[
4444
("github.com", "ssh-ed25519", "AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl"),
4545
("github.com", "ecdsa-sha2-nistp256", "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg="),
46+
("github.com", "ssh-rsa", "AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="),
47+
];
48+
49+
/// List of keys that public hosts have rotated away from.
50+
///
51+
/// We explicitly distrust these keys as users with the old key in their
52+
/// local configuration will otherwise be vulnerable to MITM attacks if the
53+
/// attacker has access to the old key. As there is no other way to distribute
54+
/// revocations of ssh host keys, we need to bundle them with the client.
55+
///
56+
/// Unlike [`BUNDLED_KEYS`], these revocations will not be ignored if the user
57+
/// has their own entries: we *know* that these keys are bad.
58+
static BUNDLED_REVOCATIONS: &[(&str, &str, &str)] = &[
59+
// Used until March 24, 2023: https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/
4660
("github.com", "ssh-rsa", "AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ=="),
4761
];
4862

@@ -357,6 +371,16 @@ fn check_ssh_known_hosts(
357371
});
358372
}
359373
}
374+
for (patterns, key_type, key) in BUNDLED_REVOCATIONS {
375+
let key = STANDARD.decode(key).unwrap();
376+
known_hosts.push(KnownHost {
377+
location: KnownHostLocation::Bundled,
378+
patterns: patterns.to_string(),
379+
key_type: key_type.to_string(),
380+
key,
381+
line_type: KnownHostLineType::Revoked,
382+
});
383+
}
360384
check_ssh_known_hosts_loaded(&known_hosts, host, remote_key_type, remote_host_key)
361385
}
362386

src/cargo/sources/git/oxide.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub fn with_retry_and_progress(
2929
) -> CargoResult<()> {
3030
std::thread::scope(|s| {
3131
let mut progress_bar = Progress::new("Fetch", config);
32-
network::with_retry(config, || {
32+
network::retry::with_retry(config, || {
3333
let progress_root: Arc<gix::progress::tree::Root> =
3434
gix::progress::tree::root::Options {
3535
initial_capacity: 10,

src/cargo/sources/git/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ pub fn with_fetch_options(
739739
let ssh_config = config.net_config()?.ssh.as_ref();
740740
let config_known_hosts = ssh_config.and_then(|ssh| ssh.known_hosts.as_ref());
741741
let diagnostic_home_config = config.diagnostic_home_config();
742-
network::with_retry(config, || {
742+
network::retry::with_retry(config, || {
743743
with_authentication(config, url, git_config, |f| {
744744
let port = Url::parse(url).ok().and_then(|url| url.port());
745745
let mut last_update = Instant::now();

0 commit comments

Comments
 (0)