Skip to content

Commit

Permalink
Add verify_signature() method to SessionBind extension message st…
Browse files Browse the repository at this point in the history
…ruct

Signed-off-by: James Spencer <[email protected]>
  • Loading branch information
jcspencer committed Apr 29, 2024
1 parent 7472903 commit 1f92958
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 2 deletions.
62 changes: 62 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ tokio = { version = "1", optional = true, features = ["rt", "net", "time"] }
tokio-util = { version = "0.7.1", optional = true, features = ["codec"] }
service-binding = { version = "^2.1" }
ssh-encoding = { version = "0.2.0" }
ssh-key = { version = "0.6.6", features = ["rsa", "alloc"] }
ssh-key = { version = "0.6.6", features = ["crypto", "alloc"] }
thiserror = "1.0.58"
#uuid = { version = "1.8.0", features = ["v4"] }
subtle = { version = "2", default-features = false }
signature = { version = "2.2.0", features = ["alloc"] }

[features]
default = ["agent"]
Expand Down
5 changes: 4 additions & 1 deletion examples/key_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@ impl Session for KeyStorage {
}
"[email protected]" => match extension.parse_message::<SessionBind>()? {
Some(bind) => {
info!("Bind: {bind:?}");
bind.verify_signature()
.map_err(|_| AgentError::ExtensionFailure)?;

info!("Session binding: {bind:?}");
Ok(None)
}
None => Err(AgentError::Failure),
Expand Down
4 changes: 4 additions & 0 deletions src/proto/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ pub enum ProtoError {
#[error("SSH key error: {0}")]
SshKey(#[from] ssh_key::Error),

/// SSH signature error.
#[error("SSH signature error: {0}")]
SshSignature(#[from] signature::Error),

/// Received command was not supported.
#[error("Command not supported ({command})")]
UnsupportedCommand {
Expand Down
20 changes: 20 additions & 0 deletions src/proto/extension/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! - [draft-miller-ssh-agent-14](https://www.ietf.org/archive/id/draft-miller-ssh-agent-14.html)
//! - [OpenSSH `PROTOCOL.agent`](https://github.com/openssh/openssh-portable/blob/cbbdf868bce431a59e2fa36ca244d5739429408d/PROTOCOL.agent)
use signature::Verifier;
use ssh_encoding::{CheckedSum, Decode, Encode, Error as EncodingError, Reader, Writer};
use ssh_key::{public::KeyData, Signature};

Expand Down Expand Up @@ -109,6 +110,21 @@ impl Encode for SessionBind {
}
}

impl SessionBind {
/// Verify the server's signature of the session identifier
/// using the public `host_key`.
///
/// > When an agent receives \[a `[email protected]` message\],
/// > it will verify the signature.
///
/// Described in [OpenSSH PROTOCOL.agent § 1](https://github.com/openssh/openssh-portable/blob/cbbdf868bce431a59e2fa36ca244d5739429408d/PROTOCOL.agent#L31)
pub fn verify_signature(&self) -> Result<(), ProtoError> {
self.host_key
.verify(self.session_id.as_slice(), &self.signature)?;
Ok(())
}
}

impl MessageExtension for SessionBind {
const NAME: &'static str = "[email protected]";
}
Expand Down Expand Up @@ -149,6 +165,10 @@ mod tests {
let bind = SessionBind::decode(&mut buffer)?;
eprintln!("Bind: {bind:#?}");

// Check `signature` (of `session_id`) against
// server public-key `host_key`
bind.verify_signature()?;

round_trip(bind)?;

Ok(())
Expand Down

0 comments on commit 1f92958

Please sign in to comment.