Closed
Description
Given the work occurring in #26 (with encode/decode support now supported for the entire spec), the project is now relatively close to being able to implement support for acting as an SSH agent client.
I imagine this would entail:
- Splitting
MessageCodec
into it's ownpub(crate)
module, as it would be shared between theagent
andclient
. - Implementing some kind of generic
ClientSocket
trait to support Unix Sockets / TCP / Named Pipes as transports. - Implementing a
Client
trait which provides helper methods for sending messages over the aClientSocket
.
It's probably worth noting that from a client perspective, one connection == one session, so the Agent/Session-style split would not be required.
I'm also unsure whether the interface needs to be async
, or whether a synchronous interface would be sufficient?
Interested to hear your thoughts!
A sample trait for a client could look something like:
pub trait Client {
fn request_identities(&self) -> Result<Message, AgentError> {
let message = Message::RequestIdentities;
todo!()
}
fn sign(
&self,
public_key: KeyData,
data: Vec<u8>,
flags: u32
) -> Result<Message, AgentError> {
let message = Message::SignRequest(SignRequest {
pubkey: public_key,
data,
flags
});
todo!()
}
fn add_identity(
&self,
private_key: KeypairData,
comment: String,
constraints: Option<Vec<KeyConstraint>>
) -> Result<Message, AgentError> {
let identity = AddIdentity {
privkey: private_key,
comment
};
let message = match constraints {
Some(constraints) => {
Message::AddIdConstrained(AddIdentityConstrained {
identity,
constraints
})
},
None => {
Message::AddIdentity(identity)
}
};
todo!()
}
fn remove_identity(&self, public_key: KeyData) -> Result<Message, AgentError> {
let message = Message::RemoveIdentity(RemoveIdentity {
pubkey: public_key
});
todo!()
}
fn remove_all_identities(&self) -> Result<Message, AgentError> {
let message = Message::RemoveAllIdentities;
todo!()
}
fn add_smartcard_key(
&self,
id: String,
pin: String,
constraints: Option<Vec<KeyConstraint>>
) -> Result<Message, AgentError> {
let key = SmartcardKey { id, pin };
let message = match constraints {
Some(constraints) => {
Message::AddSmartcardKeyConstrained(AddSmartcardKeyConstrained {
key,
constraints
})
},
None => {
Message::AddSmartcardKey(key)
}
};
todo!()
}
fn remove_smartcard_key(&self, id: String, pin: String) -> Result<Message, AgentError> {
let key = SmartcardKey { id, pin };
let message = Message::RemoveSmartcardKey(key);
todo!()
}
fn lock(&self, passphrase: Passphrase) -> Result<Message, AgentError> {
let message = Message::Lock(passphrase);
todo!()
}
fn unlock(&self, passphrase: Passphrase) -> Result<Message, AgentError> {
let message = Message::Unlock(passphrase);
todo!()
}
fn extension<T>(&self, name: String, data: T) -> Result<Message, AgentError>
where
T: Encode
{
let mut buffer: Vec<u8> = vec![];
data.encode(&mut buffer)?;
let extention = Extension {
name,
details: Unparsed(buffer)
};
let message = Message::Extension(extension);
todo!()
}
}
Metadata
Assignees
Labels
No labels