Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate back to using AgentError in Session methods #52

Merged
merged 1 commit into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ On Unix it uses `ssh-agent.sock` Unix domain socket while on Windows it uses a n
use tokio::net::UnixListener as Listener;
#[cfg(windows)]
use ssh_agent_lib::agent::NamedPipeListener as Listener;

use ssh_agent_lib::error::AgentError;
use ssh_agent_lib::agent::{Session, Agent};
use ssh_agent_lib::proto::{Identity, SignRequest};
use ssh_key::{Algorithm, Signature};
Expand All @@ -27,17 +27,17 @@ struct MyAgent;

#[ssh_agent_lib::async_trait]
impl Session for MyAgent {
async fn request_identities(&mut self) -> Result<Vec<Identity>, Box<dyn std::error::Error>> {
async fn request_identities(&mut self) -> Result<Vec<Identity>, AgentError> {
Ok(vec![ /* public keys that this agent knows of */ ])
}

async fn sign(&mut self, request: SignRequest) -> Result<Signature, Box<dyn std::error::Error>> {
async fn sign(&mut self, request: SignRequest) -> Result<Signature, AgentError> {
// get the signature by signing `request.data`
let signature = vec![];
Ok(Signature::new(
Algorithm::new("algorithm")?,
Algorithm::new("algorithm").map_err(AgentError::other)?,
signature,
)?)
).map_err(AgentError::other)?)
}
}

Expand Down
61 changes: 23 additions & 38 deletions examples/key_storage.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::error::Error;
use std::sync::{Arc, Mutex};

use async_trait::async_trait;
Expand All @@ -11,6 +10,7 @@ use sha1::Sha1;
#[cfg(windows)]
use ssh_agent_lib::agent::NamedPipeListener as Listener;
use ssh_agent_lib::agent::Session;
use ssh_agent_lib::error::AgentError;
use ssh_agent_lib::proto::extension::SessionBind;
use ssh_agent_lib::proto::{
message, signature, AddIdentity, AddIdentityConstrained, AddSmartcardKeyConstrained,
Expand Down Expand Up @@ -60,24 +60,21 @@ impl KeyStorage {
}
}

fn identity_remove(&self, pubkey: &PublicKey) -> Result<(), Box<dyn Error>> {
fn identity_remove(&self, pubkey: &PublicKey) -> Result<(), AgentError> {
let mut identities = self.identities.lock().unwrap();

if let Some(index) = Self::identity_index_from_pubkey(&identities, pubkey) {
identities.remove(index);
Ok(())
} else {
Err(From::from("Failed to remove identity: identity not found"))
Err(std::io::Error::other("Failed to remove identity: identity not found").into())
}
}
}

#[crate::async_trait]
impl Session for KeyStorage {
async fn sign(
&mut self,
sign_request: SignRequest,
) -> Result<Signature, Box<dyn std::error::Error>> {
async fn sign(&mut self, sign_request: SignRequest) -> Result<Signature, AgentError> {
let pubkey: PublicKey = sign_request.pubkey.clone().into();

if let Some(identity) = self.identity_from_pubkey(&pubkey) {
Expand All @@ -90,7 +87,8 @@ impl Session for KeyStorage {
BigUint::from_bytes_be(key.public.e.as_bytes()),
BigUint::from_bytes_be(key.private.d.as_bytes()),
vec![],
)?;
)
.map_err(AgentError::other)?;
let mut rng = rand::thread_rng();
let data = &sign_request.data;

Expand All @@ -105,20 +103,19 @@ impl Session for KeyStorage {
SigningKey::<Sha1>::new(private_key).sign_with_rng(&mut rng, data)
};
Ok(Signature::new(
Algorithm::new(algorithm)?,
Algorithm::new(algorithm).map_err(AgentError::other)?,
signature.to_bytes().to_vec(),
)?)
)
.map_err(AgentError::other)?)
}
_ => Err(From::from("Signature for key type not implemented")),
_ => Err(std::io::Error::other("Signature for key type not implemented").into()),
}
} else {
Err(From::from("Failed to create signature: identity not found"))
Err(std::io::Error::other("Failed to create signature: identity not found").into())
}
}

async fn request_identities(
&mut self,
) -> Result<Vec<message::Identity>, Box<dyn std::error::Error>> {
async fn request_identities(&mut self) -> Result<Vec<message::Identity>, AgentError> {
let mut identities = vec![];
for identity in self.identities.lock().unwrap().iter() {
identities.push(message::Identity {
Expand All @@ -129,12 +126,9 @@ impl Session for KeyStorage {
Ok(identities)
}

async fn add_identity(
&mut self,
identity: AddIdentity,
) -> Result<(), Box<dyn std::error::Error>> {
async fn add_identity(&mut self, identity: AddIdentity) -> Result<(), AgentError> {
if let Credential::Key { privkey, comment } = identity.credential {
let privkey = PrivateKey::try_from(privkey)?;
let privkey = PrivateKey::try_from(privkey).map_err(AgentError::other)?;
self.identity_add(Identity {
pubkey: PublicKey::from(&privkey),
privkey,
Expand All @@ -150,7 +144,7 @@ impl Session for KeyStorage {
async fn add_identity_constrained(
&mut self,
identity: AddIdentityConstrained,
) -> Result<(), Box<dyn std::error::Error>> {
) -> Result<(), AgentError> {
let AddIdentityConstrained {
identity,
constraints,
Expand All @@ -164,7 +158,7 @@ impl Session for KeyStorage {
}
}
if let Credential::Key { privkey, comment } = identity.credential.clone() {
let privkey = PrivateKey::try_from(privkey)?;
let privkey = PrivateKey::try_from(privkey).map_err(AgentError::other)?;
self.identity_add(Identity {
pubkey: PublicKey::from(&privkey),
privkey,
Expand All @@ -176,19 +170,13 @@ impl Session for KeyStorage {
self.add_identity(identity).await
}

async fn remove_identity(
&mut self,
identity: RemoveIdentity,
) -> Result<(), Box<dyn std::error::Error>> {
async fn remove_identity(&mut self, identity: RemoveIdentity) -> Result<(), AgentError> {
let pubkey: PublicKey = identity.pubkey.into();
self.identity_remove(&pubkey)?;
Ok(())
}

async fn add_smartcard_key(
&mut self,
key: SmartcardKey,
) -> Result<(), Box<dyn std::error::Error>> {
async fn add_smartcard_key(&mut self, key: SmartcardKey) -> Result<(), AgentError> {
info!("Adding smartcard key: {key:?}");

Ok(())
Expand All @@ -197,24 +185,21 @@ impl Session for KeyStorage {
async fn add_smartcard_key_constrained(
&mut self,
key: AddSmartcardKeyConstrained,
) -> Result<(), Box<dyn std::error::Error>> {
) -> Result<(), AgentError> {
info!("Adding smartcard key with constraints: {key:?}");
Ok(())
}
async fn lock(&mut self, pwd: String) -> Result<(), Box<dyn std::error::Error>> {
async fn lock(&mut self, pwd: String) -> Result<(), AgentError> {
info!("Locked with password: {pwd:?}");
Ok(())
}

async fn unlock(&mut self, pwd: String) -> Result<(), Box<dyn std::error::Error>> {
async fn unlock(&mut self, pwd: String) -> Result<(), AgentError> {
info!("Unlocked with password: {pwd:?}");
Ok(())
}

async fn extension(
&mut self,
mut extension: Extension,
) -> Result<(), Box<dyn std::error::Error>> {
async fn extension(&mut self, mut extension: Extension) -> Result<(), AgentError> {
info!("Extension: {extension:?}");
if extension.name == "[email protected]" {
let bind = extension.details.parse::<SessionBind>()?;
Expand Down Expand Up @@ -245,7 +230,7 @@ impl Agent for KeyStorageAgent {
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
async fn main() -> Result<(), AgentError> {
env_logger::init();

#[cfg(not(windows))]
Expand Down
89 changes: 49 additions & 40 deletions src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,76 +81,85 @@ impl ListeningSocket for NamedPipeListener {

#[async_trait]
pub trait Session: 'static + Sync + Send + Sized {
async fn request_identities(&mut self) -> Result<Vec<Identity>, Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 11 }))
async fn request_identities(&mut self) -> Result<Vec<Identity>, AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 11,
}))
}

async fn sign(
&mut self,
_request: SignRequest,
) -> Result<Signature, Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 13 }))
async fn sign(&mut self, _request: SignRequest) -> Result<Signature, AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 13,
}))
}

async fn add_identity(
&mut self,
_identity: AddIdentity,
) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 17 }))
async fn add_identity(&mut self, _identity: AddIdentity) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 17,
}))
}

async fn add_identity_constrained(
&mut self,
_identity: AddIdentityConstrained,
) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 25 }))
) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 25,
}))
}

async fn remove_identity(
&mut self,
_identity: RemoveIdentity,
) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 18 }))
async fn remove_identity(&mut self, _identity: RemoveIdentity) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 18,
}))
}

async fn remove_all_identities(&mut self) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 19 }))
async fn remove_all_identities(&mut self) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 19,
}))
}

async fn add_smartcard_key(
&mut self,
_key: SmartcardKey,
) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 20 }))
async fn add_smartcard_key(&mut self, _key: SmartcardKey) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 20,
}))
}

async fn add_smartcard_key_constrained(
&mut self,
_key: AddSmartcardKeyConstrained,
) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 26 }))
) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 26,
}))
}

async fn remove_smartcard_key(
&mut self,
_key: SmartcardKey,
) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 21 }))
async fn remove_smartcard_key(&mut self, _key: SmartcardKey) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 21,
}))
}

async fn lock(&mut self, _key: String) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 22 }))
async fn lock(&mut self, _key: String) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 22,
}))
}

async fn unlock(&mut self, _key: String) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 23 }))
async fn unlock(&mut self, _key: String) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 23,
}))
}

async fn extension(&mut self, _extension: Extension) -> Result<(), Box<dyn std::error::Error>> {
Err(Box::new(ProtoError::UnsupportedCommand { command: 27 }))
async fn extension(&mut self, _extension: Extension) -> Result<(), AgentError> {
Err(AgentError::from(ProtoError::UnsupportedCommand {
command: 27,
}))
}

async fn handle(&mut self, message: Request) -> Result<Response, Box<dyn std::error::Error>> {
async fn handle(&mut self, message: Request) -> Result<Response, AgentError> {
match message {
Request::RequestIdentities => {
return Ok(Response::IdentitiesAnswer(self.request_identities().await?))
Expand Down
8 changes: 8 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,12 @@ pub enum AgentError {
Proto(#[from] ProtoError),
#[error("Agent: I/O error: {0}")]
IO(#[from] io::Error),
#[error("Other error: {0:#}")]
Other(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
}

impl AgentError {
pub fn other(error: impl std::error::Error + Send + Sync + 'static) -> Self {
Self::Other(Box::new(error))
}
}
Loading