From 57264ed433873f56611bcd22520bca220404629e Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 9 Apr 2023 11:53:46 -0700 Subject: [PATCH] Fix credential token format validation. --- crates/crates-io/lib.rs | 9 ++++---- tests/testsuite/login.rs | 49 ++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/crates/crates-io/lib.rs b/crates/crates-io/lib.rs index ad3ea76763d..35cf8a8e993 100644 --- a/crates/crates-io/lib.rs +++ b/crates/crates-io/lib.rs @@ -522,10 +522,11 @@ pub fn check_token(token: &str) -> Result<()> { bail!("please provide a non-empty token"); } if token.bytes().all(|b| { - b >= 32 // undefined in ISO-8859-1, in ASCII/ UTF-8 not-printable character - && b < 128 // utf-8: the first bit signals a multi-byte character - && b != 127 // 127 is a control character in ascii and not in ISO 8859-1 - || b == b't' // tab is also allowed (even when < 32) + // This is essentially the US-ASCII limitation of + // https://www.rfc-editor.org/rfc/rfc9110#name-field-values. That is, + // visible ASCII characters (0x21-0x7e), space, and tab. We want to be + // able to pass this in an HTTP header without encoding. + b >= 32 && b < 127 || b == b'\t' }) { Ok(()) } else { diff --git a/tests/testsuite/login.rs b/tests/testsuite/login.rs index 19387aed57c..7ff16fad010 100644 --- a/tests/testsuite/login.rs +++ b/tests/testsuite/login.rs @@ -134,40 +134,45 @@ fn invalid_login_token() { .build(); setup_new_credentials(); - let check = |stdin: &str, stderr: &str| { + let check = |stdin: &str, stderr: &str, status: i32| { cargo_process("login") .replace_crates_io(registry.index_url()) .with_stdout("please paste the token found on [..]/me below") .with_stdin(stdin) .with_stderr(stderr) - .with_status(101) + .with_status(status) .run(); }; - check( - "😄", - "\ -[UPDATING] crates.io index -[ERROR] token contains invalid characters. + let invalid = |stdin: &str| { + check( + stdin, + "[ERROR] token contains invalid characters. Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header.", - ); - check( - "\u{0016}", - "\ -[ERROR] token contains invalid characters. -Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header.", - ); + 101, + ) + }; + let valid = |stdin: &str| check(stdin, "[LOGIN] token for `crates.io` saved", 0); + + // Update config.json so that the rest of the tests don't need to care + // whether or not `Updating` is printed. check( - "\u{0000}", + "test", "\ -[ERROR] token contains invalid characters. -Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header.", +[UPDATING] crates.io index +[LOGIN] token for `crates.io` saved +", + 0, ); - check( - "你好", - "\ -[ERROR] token contains invalid characters. -Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header.", + + invalid("😄"); + invalid("\u{0016}"); + invalid("\u{0000}"); + invalid("你好"); + valid("foo\tbar"); + valid("foo bar"); + valid( + r##"!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"##, ); }