Skip to content

Commit 89a1635

Browse files
authored
Merge branch 'rust-lang:master' into issue-2848
2 parents 5893916 + 5225e87 commit 89a1635

File tree

10 files changed

+753
-332
lines changed

10 files changed

+753
-332
lines changed

Cargo.lock

Lines changed: 554 additions & 247 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ opener = "0.5.0"
4343
# Used by `curl` or `reqwest` backend although it isn't imported
4444
# by our rustup.
4545
openssl = {version = "0.10", optional = true}
46-
pgp = {version = "0.7", default-features = false}
4746
pulldown-cmark = {version = "0.8", default-features = false}
4847
rand = "0.8"
4948
regex = "1"
@@ -52,6 +51,7 @@ same-file = "1"
5251
scopeguard = "1"
5352
semver = "0.11"
5453
serde = {version = "1.0", features = ["derive"]}
54+
sequoia-openpgp = { version = "1.5", default-features = false, features = ["crypto-rust", "allow-experimental-crypto", "allow-variable-time-crypto"] }
5555
sha2 = "0.9"
5656
sharded-slab = "0.1.1"
5757
strsim = "0.10"

src/cli/rustup_mode.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,11 @@ fn update(cfg: &mut Cfg, m: &ArgMatches<'_>) -> Result<utils::ExitCode> {
10261026
check_rustup_update()?;
10271027
}
10281028

1029+
if self_update::NEVER_SELF_UPDATE {
1030+
info!("self-update is disabled for this build of rustup");
1031+
info!("any updates to rustup will need to be fetched with your system package manager")
1032+
}
1033+
10291034
Ok(utils::ExitCode(0))
10301035
}
10311036

@@ -1046,8 +1051,7 @@ fn which(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<utils::ExitCode> {
10461051
cfg.which_binary_by_toolchain(toolchain, binary)?
10471052
} else {
10481053
cfg.which_binary(&utils::current_dir()?, binary)?
1049-
}
1050-
.expect("binary not found");
1054+
};
10511055

10521056
utils::assert_is_file(&binary_path)?;
10531057

src/cli/self_update.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ home directory, located at:
153153
154154
This can be modified with the RUSTUP_HOME environment variable.
155155
156-
The Cargo home directory located at:
156+
The Cargo home directory is located at:
157157
158158
{cargo_home}
159159
@@ -209,15 +209,15 @@ but will not be added automatically."
209209
#[cfg(not(windows))]
210210
macro_rules! post_install_msg_unix {
211211
() => {
212-
r"# Rust is installed now. Great!
212+
r#"# Rust is installed now. Great!
213213
214214
To get started you may need to restart your current shell.
215215
This would reload your `PATH` environment variable to include
216216
Cargo's bin directory ({cargo_home}/bin).
217217
218218
To configure your current shell, run:
219-
source {cargo_home}/env
220-
"
219+
source "{cargo_home}/env"
220+
"#
221221
};
222222
}
223223

@@ -237,14 +237,14 @@ Cargo's bin directory ({cargo_home}\\bin).
237237
#[cfg(not(windows))]
238238
macro_rules! post_install_msg_unix_no_modify_path {
239239
() => {
240-
r"# Rust is installed now. Great!
240+
r#"# Rust is installed now. Great!
241241
242242
To get started you need Cargo's bin directory ({cargo_home}/bin) in your `PATH`
243243
environment variable. This has not been done automatically.
244244
245245
To configure your current shell, run:
246-
source {cargo_home}/env
247-
"
246+
source "{cargo_home}/env"
247+
"#
248248
};
249249
}
250250

src/config.rs

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::str::FromStr;
77
use std::sync::Arc;
88

99
use anyhow::{anyhow, bail, Context, Result};
10-
use pgp::{Deserializable, SignedPublicKey};
10+
use sequoia_openpgp::{parse::Parse, policy, Cert};
1111
use serde::Deserialize;
1212
use thiserror::Error as ThisError;
1313

@@ -155,22 +155,21 @@ impl<'a> OverrideCfg<'a> {
155155
}
156156

157157
lazy_static::lazy_static! {
158-
static ref BUILTIN_PGP_KEY: SignedPublicKey = pgp::SignedPublicKey::from_armor_single(
159-
io::Cursor::new(&include_bytes!("rust-key.pgp.ascii")[..])
160-
).unwrap().0;
158+
static ref BUILTIN_PGP_KEY: Cert =
159+
Cert::from_bytes(&include_bytes!("rust-key.pgp.ascii")[..]).unwrap();
161160
}
162161

163162
#[allow(clippy::large_enum_variant)] // Builtin is tiny, the rest are sane
164163
#[derive(Debug)]
165164
pub enum PgpPublicKey {
166165
Builtin,
167-
FromEnvironment(PathBuf, SignedPublicKey),
168-
FromConfiguration(PathBuf, SignedPublicKey),
166+
FromEnvironment(PathBuf, Cert),
167+
FromConfiguration(PathBuf, Cert),
169168
}
170169

171170
impl PgpPublicKey {
172171
/// Retrieve the key.
173-
pub(crate) fn key(&self) -> &SignedPublicKey {
172+
pub(crate) fn cert(&self) -> &Cert {
174173
match self {
175174
Self::Builtin => &*BUILTIN_PGP_KEY,
176175
Self::FromEnvironment(_, k) => k,
@@ -194,18 +193,17 @@ impl PgpPublicKey {
194193
}
195194
Ok(ret)
196195
}
197-
use pgp::types::KeyTrait;
198196
let mut ret = vec![format!("from {}", self)];
199-
let key = self.key();
200-
let keyid = format_hex(&key.key_id().to_vec(), "-", 4)?;
201-
let algo = key.algorithm();
202-
let fpr = format_hex(&key.fingerprint(), " ", 2)?;
203-
let uid0 = key
204-
.details
205-
.users
206-
.get(0)
207-
.map(|u| u.id.id())
208-
.unwrap_or("<No User ID>");
197+
let cert = self.cert();
198+
let keyid = format_hex(cert.keyid().as_bytes(), "-", 4)?;
199+
let algo = cert.primary_key().pk_algo();
200+
let fpr = format_hex(cert.fingerprint().as_bytes(), " ", 2)?;
201+
let p = policy::StandardPolicy::new();
202+
let uid0 = cert
203+
.with_policy(&p, None)?
204+
.primary_userid()
205+
.map(|u| u.userid().to_string())
206+
.unwrap_or("<No User ID>".into());
209207
ret.push(format!(" {:?}/{} - {}", algo, keyid, uid0));
210208
ret.push(format!(" Fingerprint: {}", fpr));
211209
Ok(ret)
@@ -277,11 +275,9 @@ impl Cfg {
277275
if let Some(ref s_path) = process().var_os("RUSTUP_PGP_KEY") {
278276
let path = PathBuf::from(s_path);
279277
let file = utils::open_file("RUSTUP_PGP_KEY", &path)?;
280-
let (key, _) = SignedPublicKey::from_armor_single(file).map_err(|error| {
281-
RustupError::InvalidPgpKey {
282-
path: s_path.into(),
283-
source: error,
284-
}
278+
let key = Cert::from_reader(file).map_err(|error| RustupError::InvalidPgpKey {
279+
path: s_path.into(),
280+
source: error,
285281
})?;
286282

287283
pgp_keys.push(PgpPublicKey::FromEnvironment(path, key));
@@ -290,7 +286,7 @@ impl Cfg {
290286
if let Some(s) = &s.pgp_keys {
291287
let path = PathBuf::from(s);
292288
let file = utils::open_file("PGP Key from config", &path)?;
293-
let (key, _) = SignedPublicKey::from_armor_single(file).map_err(|error| {
289+
let key = Cert::from_reader(file).map_err(|error| {
294290
anyhow!(RustupError::InvalidPgpKey {
295291
path: s.into(),
296292
source: error,
@@ -478,20 +474,20 @@ impl Cfg {
478474

479475
pub(crate) fn which_binary_by_toolchain(
480476
&self,
481-
toolchain: &str,
477+
toolchain_name: &str,
482478
binary: &str,
483-
) -> Result<Option<PathBuf>> {
484-
let toolchain = self.get_toolchain(toolchain, false)?;
479+
) -> Result<PathBuf> {
480+
let toolchain = self.get_toolchain(toolchain_name, false)?;
485481
if toolchain.exists() {
486-
Ok(Some(toolchain.binary_file(binary)))
482+
Ok(toolchain.binary_file(binary))
487483
} else {
488-
Ok(None)
484+
Err(RustupError::ToolchainNotInstalled(toolchain_name.to_string()).into())
489485
}
490486
}
491487

492-
pub(crate) fn which_binary(&self, path: &Path, binary: &str) -> Result<Option<PathBuf>> {
488+
pub(crate) fn which_binary(&self, path: &Path, binary: &str) -> Result<PathBuf> {
493489
let (toolchain, _) = self.find_or_install_override_toolchain_or_default(path)?;
494-
Ok(Some(toolchain.binary_file(binary)))
490+
Ok(toolchain.binary_file(binary))
495491
}
496492

497493
pub(crate) fn upgrade_data(&self) -> Result<()> {
@@ -1003,11 +999,13 @@ impl Cfg {
1003999
}
10041000

10051001
pub(crate) fn resolve_toolchain(&self, name: &str) -> Result<String> {
1006-
if let Ok(desc) = dist::PartialToolchainDesc::from_str(name) {
1002+
// remove trailing slashes in toolchain name
1003+
let normalized_name = name.trim_end_matches('/');
1004+
if let Ok(desc) = dist::PartialToolchainDesc::from_str(normalized_name) {
10071005
let host = self.get_default_host_triple()?;
10081006
Ok(desc.resolve(&host)?.to_string())
10091007
} else {
1010-
Ok(name.to_owned())
1008+
Ok(normalized_name.to_owned())
10111009
}
10121010
}
10131011
}

src/dist/signatures.rs

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,83 @@
44

55
use std::io::Read;
66

7-
use anyhow::{Context, Result};
8-
use pgp::types::KeyTrait;
9-
use pgp::{Deserializable, StandaloneSignature};
7+
use anyhow::Result;
8+
9+
use sequoia_openpgp::{
10+
parse::{stream::*, Parse},
11+
policy, Cert, KeyHandle,
12+
};
1013

1114
use crate::config::PgpPublicKey;
1215

13-
pub(crate) fn verify_signature<T: Read>(
14-
mut content: T,
16+
/// Returns the index of the cert in `certs` that verifies a
17+
/// signature.
18+
///
19+
/// Ignores any signatures that are bad for any reason. If no
20+
/// signature could be verified, returns `None`.
21+
// XXX: This is a bit of an odd policy. Shouldn't we fail if we
22+
// encounter a single bad signature (bad as in checksum doesn't check
23+
// out, not bad as in we don't have the key)?
24+
pub(crate) fn verify_signature<T: Read + Send + Sync>(
25+
content: T,
1526
signature: &str,
16-
keys: &[PgpPublicKey],
27+
certs: &[PgpPublicKey],
1728
) -> Result<Option<usize>> {
18-
let mut content_buf = Vec::new();
19-
content.read_to_end(&mut content_buf)?;
20-
let (signatures, _) =
21-
StandaloneSignature::from_string_many(signature).context("error verifying signature")?;
22-
23-
for signature in signatures {
24-
let signature = signature.context("error verifying signature")?;
25-
26-
for (idx, key) in keys.iter().enumerate() {
27-
let actual_key = key.key();
28-
if actual_key.is_signing_key() && signature.verify(actual_key, &content_buf).is_ok() {
29-
return Ok(Some(idx));
30-
}
29+
let p = policy::StandardPolicy::new();
30+
let helper = Helper::new(certs);
31+
let mut v = DetachedVerifierBuilder::from_reader(signature.as_bytes())?
32+
.with_policy(&p, None, helper)?;
33+
v.verify_reader(content)?;
34+
Ok(v.into_helper().index)
35+
}
36+
37+
struct Helper<'a> {
38+
certs: &'a [PgpPublicKey],
39+
// The index of the cert in certs that successfully verified a
40+
// signature.
41+
index: Option<usize>,
42+
}
43+
44+
impl<'a> Helper<'a> {
45+
fn new(certs: &'a [PgpPublicKey]) -> Self {
46+
Helper { certs, index: None }
47+
}
48+
}
49+
50+
impl VerificationHelper for Helper<'_> {
51+
fn get_certs(&mut self, _: &[KeyHandle]) -> anyhow::Result<Vec<Cert>> {
52+
Ok(self.certs.iter().map(|c| c.cert().clone()).collect())
53+
}
3154

32-
for sub_key in &actual_key.public_subkeys {
33-
if sub_key.is_signing_key() && signature.verify(sub_key, &content_buf).is_ok() {
34-
return Ok(Some(idx));
55+
fn check(&mut self, structure: MessageStructure<'_>) -> anyhow::Result<()> {
56+
for layer in structure.into_iter() {
57+
match layer {
58+
MessageLayer::SignatureGroup { results } => {
59+
for result in results {
60+
match result {
61+
Ok(GoodChecksum { ka, .. }) => {
62+
// A good signature! Find the index
63+
// of the singer key and return
64+
// success.
65+
self.index = self.certs.iter().position(|c| c.cert() == ka.cert());
66+
assert!(self.index.is_some());
67+
return Ok(());
68+
}
69+
_ => {
70+
// We ignore any errors.
71+
}
72+
}
73+
}
74+
}
75+
MessageLayer::Compression { .. } => {
76+
unreachable!("we're verifying detached signatures")
77+
}
78+
MessageLayer::Encryption { .. } => {
79+
unreachable!("we're verifying detached signatures")
3580
}
3681
}
3782
}
38-
}
3983

40-
Ok(None)
84+
Ok(())
85+
}
4186
}

src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub enum RustupError {
3838
#[error("unable to read the PGP key '{}'", .path.display())]
3939
InvalidPgpKey {
4040
path: PathBuf,
41-
source: pgp::errors::Error,
41+
source: anyhow::Error,
4242
},
4343
#[error("invalid toolchain name: '{0}'")]
4444
InvalidToolchainName(String),

tests/cli-misc.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,36 @@ fn which() {
860860
});
861861
}
862862

863+
#[test]
864+
fn which_asking_uninstalled_toolchain() {
865+
setup(&|config| {
866+
let path_1 = config.customdir.join("custom-1");
867+
let path_1 = path_1.to_string_lossy();
868+
expect_ok(
869+
config,
870+
&["rustup", "toolchain", "link", "custom-1", &path_1],
871+
);
872+
expect_ok(config, &["rustup", "default", "custom-1"]);
873+
#[cfg(windows)]
874+
expect_stdout_ok(
875+
config,
876+
&["rustup", "which", "rustc"],
877+
"\\toolchains\\custom-1\\bin\\rustc",
878+
);
879+
#[cfg(not(windows))]
880+
expect_stdout_ok(
881+
config,
882+
&["rustup", "which", "rustc"],
883+
"/toolchains/custom-1/bin/rustc",
884+
);
885+
expect_err(
886+
config,
887+
&["rustup", "which", "--toolchain=nightly", "rustc"],
888+
"toolchain 'nightly' is not installed",
889+
);
890+
});
891+
}
892+
863893
#[test]
864894
fn override_by_toolchain_on_the_command_line() {
865895
setup(&|config| {

0 commit comments

Comments
 (0)