From e59be7214b1fc1998f76a34f7e4429ee4259494c Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 9 Nov 2026 15:38:41 +0000 Subject: access: a key's comment 256 bytes at most Review 4, 1250's note: a key's comment was kept as given, unbounded but by the request limit (2 MiB), in protocol data every node holds and the dashboard shows. It says whose and where the key is: at most 256 bytes now (`sshsig::MAX_COMMENT`), a longer one refused with the key. --- src/access/sshsig.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'src/access/sshsig.rs') diff --git a/src/access/sshsig.rs b/src/access/sshsig.rs index 799cb87..e25d8a7 100644 --- a/src/access/sshsig.rs +++ b/src/access/sshsig.rs @@ -22,6 +22,10 @@ const END: &str = "-----END SSH SIGNATURE-----"; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) struct PublicKey(pub(crate) [u8; 32]); +/// A key's comment kept at most, in bytes (`PublicKey::kept_line`): what says whose and +/// where the key is, not a place for text. +pub(crate) const MAX_COMMENT: usize = 256; + impl PublicKey { /// From an `authorized_keys` line: `ssh-ed25519 [comment]`. pub(crate) fn parse(line: &str) -> Result { @@ -70,11 +74,20 @@ impl PublicKey { /// made one). The comment is for whoever reads it: the key alone checks a signature. pub(crate) fn kept_line(line: &str) -> Result { let key = Self::parse(line)?; - let comment: Vec<&str> = line.split_whitespace().skip(2).collect(); + let comment = line + .split_whitespace() + .skip(2) + .collect::>() + .join(" "); + if comment.len() > MAX_COMMENT { + return Err(format!( + "the key's comment is longer than {MAX_COMMENT} bytes" + )); + } Ok(if comment.is_empty() { key.line() } else { - format!("{} {}", key.line(), comment.join(" ")) + format!("{} {comment}", key.line()) }) } @@ -263,6 +276,8 @@ DNg4vBWp1j1gLRiBMOF+gwYNegDg== assert_eq!(commented, format!("{} alice@laptop 2026", key.line())); assert_eq!(PublicKey::parse(&commented), Ok(key)); assert_eq!(PublicKey::kept_line(&key.line()), Ok(key.line())); + let long = format!("{} {}", key.line(), "x".repeat(MAX_COMMENT + 1)); + assert!(PublicKey::kept_line(&long).is_err()); } /// What `sign` makes checks, and reads as `ssh-keygen` writes it. -- cgit v1.3.1