Skip to content

Commit 576f21f

Browse files
authored
Merge pull request #62 from wiktor-k/jcspencer/session-bind-verify
Add `verify()` method to `SessionBind` extension message struct
2 parents 7472903 + 1f92958 commit 576f21f

File tree

5 files changed

+92
-2
lines changed

5 files changed

+92
-2
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ tokio = { version = "1", optional = true, features = ["rt", "net", "time"] }
2727
tokio-util = { version = "0.7.1", optional = true, features = ["codec"] }
2828
service-binding = { version = "^2.1" }
2929
ssh-encoding = { version = "0.2.0" }
30-
ssh-key = { version = "0.6.6", features = ["rsa", "alloc"] }
30+
ssh-key = { version = "0.6.6", features = ["crypto", "alloc"] }
3131
thiserror = "1.0.58"
3232
#uuid = { version = "1.8.0", features = ["v4"] }
3333
subtle = { version = "2", default-features = false }
34+
signature = { version = "2.2.0", features = ["alloc"] }
3435

3536
[features]
3637
default = ["agent"]

examples/key_storage.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,10 @@ impl Session for KeyStorage {
212212
}
213213
"session-bind@openssh.com" => match extension.parse_message::<SessionBind>()? {
214214
Some(bind) => {
215-
info!("Bind: {bind:?}");
215+
bind.verify_signature()
216+
.map_err(|_| AgentError::ExtensionFailure)?;
217+
218+
info!("Session binding: {bind:?}");
216219
Ok(None)
217220
}
218221
None => Err(AgentError::Failure),

src/proto/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ pub enum ProtoError {
2323
#[error("SSH key error: {0}")]
2424
SshKey(#[from] ssh_key::Error),
2525

26+
/// SSH signature error.
27+
#[error("SSH signature error: {0}")]
28+
SshSignature(#[from] signature::Error),
29+
2630
/// Received command was not supported.
2731
#[error("Command not supported ({command})")]
2832
UnsupportedCommand {

src/proto/extension/message.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//! - [draft-miller-ssh-agent-14](https://www.ietf.org/archive/id/draft-miller-ssh-agent-14.html)
55
//! - [OpenSSH `PROTOCOL.agent`](https://github.com/openssh/openssh-portable/blob/cbbdf868bce431a59e2fa36ca244d5739429408d/PROTOCOL.agent)
66
7+
use signature::Verifier;
78
use ssh_encoding::{CheckedSum, Decode, Encode, Error as EncodingError, Reader, Writer};
89
use ssh_key::{public::KeyData, Signature};
910

@@ -109,6 +110,21 @@ impl Encode for SessionBind {
109110
}
110111
}
111112

113+
impl SessionBind {
114+
/// Verify the server's signature of the session identifier
115+
/// using the public `host_key`.
116+
///
117+
/// > When an agent receives \[a `session-bind@openssh.com` message\],
118+
/// > it will verify the signature.
119+
///
120+
/// Described in [OpenSSH PROTOCOL.agent § 1](https://github.com/openssh/openssh-portable/blob/cbbdf868bce431a59e2fa36ca244d5739429408d/PROTOCOL.agent#L31)
121+
pub fn verify_signature(&self) -> Result<(), ProtoError> {
122+
self.host_key
123+
.verify(self.session_id.as_slice(), &self.signature)?;
124+
Ok(())
125+
}
126+
}
127+
112128
impl MessageExtension for SessionBind {
113129
const NAME: &'static str = "session-bind@openssh.com";
114130
}
@@ -149,6 +165,10 @@ mod tests {
149165
let bind = SessionBind::decode(&mut buffer)?;
150166
eprintln!("Bind: {bind:#?}");
151167

168+
// Check `signature` (of `session_id`) against
169+
// server public-key `host_key`
170+
bind.verify_signature()?;
171+
152172
round_trip(bind)?;
153173

154174
Ok(())

0 commit comments

Comments
 (0)