78 lines
2.7 KiB
Rust
78 lines
2.7 KiB
Rust
|
use signature::Signer;
|
||
|
use ssh_agent_lib::agent::{Agent, Session};
|
||
|
use ssh_agent_lib::proto::message::Message;
|
||
|
use ssh_key::public::PublicKey;
|
||
|
use ssh_key::private::PrivateKey;
|
||
|
use tokio::net::UnixListener;
|
||
|
|
||
|
|
||
|
struct SshAgent;
|
||
|
|
||
|
impl std::default::Default for SshAgent {
|
||
|
fn default() -> Self {
|
||
|
SshAgent {}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[ssh_agent_lib::async_trait]
|
||
|
impl Session for SshAgent {
|
||
|
async fn handle(&mut self, message: Message) -> Result<Message, Box<dyn std::error::Error>> {
|
||
|
println!("Received message");
|
||
|
match message {
|
||
|
Message::RequestIdentities => {
|
||
|
let p = std::path::PathBuf::from("/home/joe/.ssh/id_ed25519.pub");
|
||
|
let pubkey = PublicKey::read_openssh_file(&p).unwrap();
|
||
|
let id = ssh_agent_lib::proto::message::Identity {
|
||
|
pubkey_blob: pubkey.to_bytes().unwrap(),
|
||
|
comment: pubkey.comment().to_owned(),
|
||
|
};
|
||
|
Ok(Message::IdentitiesAnswer(vec![id]))
|
||
|
},
|
||
|
Message::SignRequest(req) => {
|
||
|
println!("Received sign request");
|
||
|
let mut req_bytes = vec![13];
|
||
|
encode_string(&mut req_bytes, &req.pubkey_blob);
|
||
|
encode_string(&mut req_bytes, &req.data);
|
||
|
req_bytes.extend(req.flags.to_be_bytes());
|
||
|
std::fs::File::create("/tmp/signreq").unwrap().write(&req_bytes).unwrap();
|
||
|
|
||
|
let p = std::path::PathBuf::from("/home/joe/.ssh/id_ed25519");
|
||
|
let passphrase = std::env::var("PRIVKEY_PASSPHRASE").unwrap();
|
||
|
let privkey = PrivateKey::read_openssh_file(&p)
|
||
|
.unwrap()
|
||
|
.decrypt(passphrase.as_bytes())
|
||
|
.unwrap();
|
||
|
|
||
|
|
||
|
|
||
|
let sig = Signer::sign(&privkey, &req.data);
|
||
|
use std::io::Write;
|
||
|
std::fs::File::create("/tmp/sig").unwrap().write(sig.as_bytes()).unwrap();
|
||
|
|
||
|
let mut payload = Vec::with_capacity(128);
|
||
|
encode_string(&mut payload, "ssh-ed25519".as_bytes());
|
||
|
encode_string(&mut payload, sig.as_bytes());
|
||
|
println!("Payload length: {}", payload.len());
|
||
|
std::fs::File::create("/tmp/payload").unwrap().write(&payload).unwrap();
|
||
|
Ok(Message::SignResponse(payload))
|
||
|
},
|
||
|
_ => Ok(Message::Failure),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
fn encode_string(buf: &mut Vec<u8>, s: &[u8]) {
|
||
|
let len = s.len() as u32;
|
||
|
buf.extend(len.to_be_bytes());
|
||
|
buf.extend(s);
|
||
|
}
|
||
|
|
||
|
|
||
|
pub async fn run() {
|
||
|
let socket = "/tmp/creddy-agent.sock";
|
||
|
let _ = std::fs::remove_file(socket);
|
||
|
let listener = UnixListener::bind(socket).unwrap();
|
||
|
SshAgent.listen(listener).await.unwrap();
|
||
|
}
|