feat: ssh agent, not works yet
This commit is contained in:
@@ -1,91 +1,57 @@
|
||||
use std::error::Error;
|
||||
use std::fs::remove_file;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::util_msg::when_debug;
|
||||
use rust_util::XResult;
|
||||
use ssh_agent::proto::message::{self, Message};
|
||||
use ssh_agent::proto::public_key::PublicKey;
|
||||
use ssh_agent::proto::{from_bytes, to_bytes, EcDsaPublicKey};
|
||||
use ssh_agent::Agent;
|
||||
|
||||
use crate::ecdsautil::{generate_ecdsa_keypair, EcdsaAlgorithm};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use rust_util::XResult;
|
||||
use ssh_agent_lib::agent::{listen, Session};
|
||||
use ssh_agent_lib::error::AgentError;
|
||||
use ssh_agent_lib::proto::{Identity, SignRequest};
|
||||
use ssh_agent_lib::ssh_key::public::KeyData;
|
||||
use ssh_agent_lib::ssh_key::{Algorithm, Signature};
|
||||
use tokio::net::UnixListener as Listener;
|
||||
|
||||
use crate::ecdsautil;
|
||||
|
||||
struct SshAgent {
|
||||
#[derive(Default, Clone)]
|
||||
struct MySshAgent {
|
||||
private_key_pem: String,
|
||||
comment: String,
|
||||
}
|
||||
|
||||
impl SshAgent {
|
||||
impl MySshAgent {
|
||||
fn new() -> XResult<Self> {
|
||||
let (_, private_key_pem, _, _, _) = generate_ecdsa_keypair(EcdsaAlgorithm::P256)?;
|
||||
Ok(SshAgent {
|
||||
Ok(MySshAgent {
|
||||
private_key_pem,
|
||||
comment: "test".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_message(&self, request: Message) -> Result<Message, Box<dyn Error>> {
|
||||
debugging!("Request: {:?}", request);
|
||||
let response = match request {
|
||||
Message::RequestIdentities => {
|
||||
let p256_private_key_d =
|
||||
ecdsautil::parse_p256_private_key(&self.private_key_pem).unwrap();
|
||||
|
||||
let ec_dsa_public_key = EcDsaPublicKey {
|
||||
identifier: "nistp256".to_string(),
|
||||
q: p256_private_key_d,
|
||||
};
|
||||
let public_key = PublicKey::EcDsa(ec_dsa_public_key);
|
||||
let identities = vec![message::Identity {
|
||||
pubkey_blob: to_bytes(&public_key)?,
|
||||
comment: self.comment.clone(),
|
||||
}];
|
||||
when_debug(|| {
|
||||
debugging!("Return {} identities", identities.len());
|
||||
for (i, identity) in identities.iter().enumerate() {
|
||||
debugging!("#{} - {:?}", i, identity)
|
||||
}
|
||||
});
|
||||
Ok(Message::IdentitiesAnswer(identities))
|
||||
}
|
||||
Message::RemoveIdentity(ref _identity) => {
|
||||
Err(From::from(format!("Not supported message: {:?}", request)))
|
||||
}
|
||||
Message::AddIdentity(ref _identity) => {
|
||||
Err(From::from(format!("Not supported message: {:?}", request)))
|
||||
}
|
||||
Message::SignRequest(sign_request) => {
|
||||
let pubkey: PublicKey = from_bytes(&sign_request.pubkey_blob)?;
|
||||
|
||||
println!("{:?}", pubkey);
|
||||
|
||||
Err(From::from(format!(
|
||||
"Not supported message: {:?}",
|
||||
sign_request
|
||||
)))
|
||||
}
|
||||
_ => Err(From::from(format!("Unknown message: {:?}", request))),
|
||||
};
|
||||
debugging!("Response {:?}", response);
|
||||
response
|
||||
}
|
||||
}
|
||||
|
||||
impl Agent for SshAgent {
|
||||
type Error = ();
|
||||
#[ssh_agent_lib::async_trait]
|
||||
impl Session for MySshAgent {
|
||||
async fn request_identities(&mut self) -> Result<Vec<Identity>, AgentError> {
|
||||
debugging!("request_identities");
|
||||
// let p256_private_key_d = ecdsautil::parse_p256_private_key(&self.private_key_pem).unwrap();
|
||||
let public_key_point = hex::decode("0474b7b8dcac7587afc8c461e96d713d05a4caae9dc4188924697fcb8dec2b8001d337e9ff4da1fb30042fef53375bde0cbe4964c71298b9d56bd9131c347119f3").unwrap();
|
||||
Ok(vec![Identity {
|
||||
pubkey: KeyData::Ecdsa(
|
||||
ssh_key::public::EcdsaPublicKey::from_sec1_bytes(&public_key_point).unwrap(),
|
||||
),
|
||||
comment: "".to_string(),
|
||||
}])
|
||||
}
|
||||
|
||||
fn handle(&self, message: Message) -> Result<Message, ()> {
|
||||
debugging!("Message: {:?}", message);
|
||||
self.handle_message(message).or_else(|error| {
|
||||
warning!("Error handling message - {:?}", error);
|
||||
Ok(Message::Failure)
|
||||
})
|
||||
async fn sign(&mut self, request: SignRequest) -> Result<Signature, AgentError> {
|
||||
debugging!("sign, request: {:?}", request);
|
||||
// get the signature by signing `request.data`
|
||||
let signature = vec![];
|
||||
Ok(Signature::new(
|
||||
Algorithm::new("algorithm").map_err(AgentError::other)?,
|
||||
signature,
|
||||
)
|
||||
.map_err(AgentError::other)?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +74,7 @@ impl Command for CommandImpl {
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
failure!("Not works!");
|
||||
warning!("Not works yet.");
|
||||
|
||||
debugging!("Sub args: {:?}", sub_arg_matches);
|
||||
|
||||
@@ -125,17 +91,32 @@ impl Command for CommandImpl {
|
||||
Err(e) => warning!("Get canonicalized sock file path failed: {}", e),
|
||||
}
|
||||
|
||||
let ssh_agent = SshAgent::new()?;
|
||||
// TODO information!("{}", &ssh_agent.ssh_string);
|
||||
// let ssh_agent = SshAgent::new()?;
|
||||
// // TODO information!("{}", &ssh_agent.ssh_string);
|
||||
|
||||
let _ = remove_file(sock_file);
|
||||
|
||||
information!("Start unix socket: {}", sock_file);
|
||||
opt_result!(
|
||||
ssh_agent.run_unix(sock_file),
|
||||
"Run unix socket: {}, failed: {}",
|
||||
sock_file
|
||||
);
|
||||
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
rt.block_on(async move {
|
||||
listen(
|
||||
Listener::bind(sock_file).unwrap(),
|
||||
MySshAgent::new().unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
// opt_result!(
|
||||
// ssh_agent.run_unix(sock_file),
|
||||
// "Run unix socket: {}, failed: {}",
|
||||
// sock_file
|
||||
// );
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user