diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/access/sshsig.rs | 19 |
1 files changed, 17 insertions, 2 deletions
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 <base64> [comment]`. pub(crate) fn parse(line: &str) -> Result<Self, String> { @@ -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<String, String> { let key = Self::parse(line)?; - let comment: Vec<&str> = line.split_whitespace().skip(2).collect(); + let comment = line + .split_whitespace() + .skip(2) + .collect::<Vec<&str>>() + .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. |
