cc! certtool + fix ncpf/netcatpf
This commit is contained in:
parent
cbe8dee8a3
commit
f438935954
|
@ -1,12 +1,15 @@
|
|||
use clap::{Parser, Subcommand};
|
||||
use inquire::{Confirm, Select, Text};
|
||||
use libepf::ca_pool::load_ca_pool;
|
||||
use libepf::pki::{
|
||||
EPFCertificate, EPFCertificateDetails, EpfPkiCertificateOps, EpfPkiSerializable, EpfPrivateKey,
|
||||
EpfPublicKey,
|
||||
};
|
||||
use rand::rngs::OsRng;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use clap::{Parser, Subcommand};
|
||||
use inquire::{Confirm, Select, Text};
|
||||
use rand::rngs::OsRng;
|
||||
use libepf::ca_pool::load_ca_pool;
|
||||
use libepf::pki::{EPFCertificate, EPFCertificateDetails, EpfPkiCertificateOps, EpfPkiSerializable, EpfPrivateKey, EpfPublicKey};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
|
@ -22,31 +25,27 @@ enum Commands {
|
|||
#[arg(short = 'p', long)]
|
||||
out_public_key: PathBuf,
|
||||
#[arg(short = 'k', long)]
|
||||
out_private_key: PathBuf
|
||||
out_private_key: PathBuf,
|
||||
},
|
||||
/// Create a new **unsigned** certificate
|
||||
CreateCertificate {
|
||||
#[arg(short, long)]
|
||||
output: PathBuf,
|
||||
#[arg(short, long)]
|
||||
public_key: PathBuf
|
||||
public_key: PathBuf,
|
||||
},
|
||||
/// Dump information about the certificate
|
||||
DumpCertificate {
|
||||
cert: PathBuf
|
||||
},
|
||||
DumpCertificate { cert: PathBuf },
|
||||
/// Verify the certificate
|
||||
VerifyCertificate {
|
||||
cert: PathBuf
|
||||
},
|
||||
VerifyCertificate { cert: PathBuf },
|
||||
/// Sign the certificate using the given private key
|
||||
SignCertificate {
|
||||
cert: PathBuf,
|
||||
#[arg(short, long)]
|
||||
key: PathBuf,
|
||||
#[arg(short, long)]
|
||||
output: PathBuf
|
||||
}
|
||||
output: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -54,7 +53,10 @@ fn main() {
|
|||
|
||||
if let Some(subcommand) = args.command {
|
||||
match subcommand {
|
||||
Commands::GenerateKeypair { out_private_key, out_public_key } => {
|
||||
Commands::GenerateKeypair {
|
||||
out_private_key,
|
||||
out_public_key,
|
||||
} => {
|
||||
let private_key = EpfPrivateKey::generate(&mut OsRng);
|
||||
let public_key = private_key.verifying_key();
|
||||
|
||||
|
@ -88,7 +90,7 @@ fn main() {
|
|||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Commands::CreateCertificate { output, public_key } => {
|
||||
// load public key
|
||||
let public_key_pem = match fs::read(public_key) {
|
||||
|
@ -114,14 +116,20 @@ fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
let options = vec!["1 day", "1 week", "1 month", "6 months", "1 year", "2 years", "5 years", "10 years", "Forever"];
|
||||
let expires_in = match Select::new("How long should the certificate be valid for?", options).prompt() {
|
||||
Ok(expires_in) => expires_in,
|
||||
Err(e) => {
|
||||
println!("Error with prompt: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let options = vec![
|
||||
"1 day", "1 week", "1 month", "6 months", "1 year", "2 years", "5 years",
|
||||
"10 years", "Forever",
|
||||
];
|
||||
let expires_in =
|
||||
match Select::new("How long should the certificate be valid for?", options)
|
||||
.prompt()
|
||||
{
|
||||
Ok(expires_in) => expires_in,
|
||||
Err(e) => {
|
||||
println!("Error with prompt: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let expires_in = match expires_in {
|
||||
"1 day" => 60 * 60 * 24,
|
||||
"1 week" => 60 * 60 * 24 * 7,
|
||||
|
@ -132,10 +140,15 @@ fn main() {
|
|||
"5 years" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 5,
|
||||
"10 years" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 10,
|
||||
"Forever" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 100000, // 100,000 years
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let add_claims = match Confirm::new("Would you like to add additional claims to the certificate?").with_default(false).prompt() {
|
||||
let add_claims = match Confirm::new(
|
||||
"Would you like to add additional claims to the certificate?",
|
||||
)
|
||||
.with_default(false)
|
||||
.prompt()
|
||||
{
|
||||
Ok(ac) => ac,
|
||||
Err(e) => {
|
||||
println!("Error with prompt: {}", e);
|
||||
|
@ -162,7 +175,12 @@ fn main() {
|
|||
}
|
||||
};
|
||||
claims.insert(name, value);
|
||||
let add_another = match Confirm::new("Would you like to add additional claims to the certificate?").with_default(true).prompt() {
|
||||
let add_another = match Confirm::new(
|
||||
"Would you like to add additional claims to the certificate?",
|
||||
)
|
||||
.with_default(true)
|
||||
.prompt()
|
||||
{
|
||||
Ok(ac) => ac,
|
||||
Err(e) => {
|
||||
println!("Error with prompt: {}", e);
|
||||
|
@ -178,8 +196,15 @@ fn main() {
|
|||
let mut cert = EPFCertificate {
|
||||
details: EPFCertificateDetails {
|
||||
name,
|
||||
not_before: SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs(),
|
||||
not_after: SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs() + expires_in,
|
||||
not_before: SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Time went backwards")
|
||||
.as_secs(),
|
||||
not_after: SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Time went backwards")
|
||||
.as_secs()
|
||||
+ expires_in,
|
||||
public_key: public_key.to_bytes(),
|
||||
issuer_public_key: [0u8; 32],
|
||||
claims,
|
||||
|
@ -209,7 +234,7 @@ fn main() {
|
|||
println!("Error saving certificate: {}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Commands::DumpCertificate { cert } => {
|
||||
// load cert
|
||||
let cert_pem = match fs::read(cert) {
|
||||
|
@ -227,8 +252,8 @@ fn main() {
|
|||
}
|
||||
};
|
||||
println!("{}", cert);
|
||||
},
|
||||
Commands::SignCertificate { cert, key, output }=> {
|
||||
}
|
||||
Commands::SignCertificate { cert, key, output } => {
|
||||
// load cert
|
||||
let cert_pem = match fs::read(cert) {
|
||||
Ok(pem) => pem,
|
||||
|
@ -283,7 +308,7 @@ fn main() {
|
|||
println!("Error saving certificate: {}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Commands::VerifyCertificate { cert } => {
|
||||
// load cert
|
||||
let cert_pem = match fs::read(cert) {
|
||||
|
@ -314,13 +339,13 @@ fn main() {
|
|||
println!("Certificate valid but not trusted");
|
||||
std::process::exit(3);
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Certificate invalid: {}", e);
|
||||
std::process::exit(2);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("No subcommand specified. Run with -h/--help for help.");
|
||||
|
|
|
@ -76,6 +76,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
pub fn ca_pool_error_display_test() {
|
||||
println!("{}", EpfCaPoolLoaderError::CertDirDoesNotExist("".to_string()));
|
||||
println!(
|
||||
"{}",
|
||||
EpfCaPoolLoaderError::CertDirDoesNotExist("".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,9 +38,14 @@ mod tests {
|
|||
pub fn error_display_test() {
|
||||
println!("{}", EpfHandshakeError::AlreadyTunnelled);
|
||||
println!("{}", EpfHandshakeError::UnsupportedProtocolVersion(0));
|
||||
println!("{}", EpfHandshakeError::InvalidCertificate(EpfPkiCertificateValidationError::ValidAfterSigner));
|
||||
println!(
|
||||
"{}",
|
||||
EpfHandshakeError::InvalidCertificate(
|
||||
EpfPkiCertificateValidationError::ValidAfterSigner
|
||||
)
|
||||
);
|
||||
println!("{}", EpfHandshakeError::UntrustedCertificate);
|
||||
println!("{}", EpfHandshakeError::EncryptionError);
|
||||
println!("{}", EpfHandshakeError::MissingKeyProof);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use crate::ca_pool::{EpfCaPool};
|
||||
use crate::ca_pool::EpfCaPool;
|
||||
use crate::danger_trace;
|
||||
use crate::error::EpfHandshakeError;
|
||||
use crate::pki::{
|
||||
EPFCertificate, EpfPkiCertificateOps, EpfPrivateKey, EpfPublicKey,
|
||||
};
|
||||
use crate::pki::{EPFCertificate, EpfPkiCertificateOps, EpfPrivateKey, EpfPublicKey};
|
||||
use crate::protocol::{
|
||||
encode_packet, recv_packet, EpfApplicationData, EpfClientHello, EpfClientState, EpfFinished,
|
||||
EpfMessage, EpfServerHello, EpfServerState, PACKET_APPLICATION_DATA, PACKET_CLIENT_HELLO,
|
||||
|
@ -12,8 +10,8 @@ use crate::protocol::{
|
|||
use async_trait::async_trait;
|
||||
use chacha20poly1305::aead::{Aead, Payload};
|
||||
use chacha20poly1305::{AeadCore, Key, KeyInit, XChaCha20Poly1305, XNonce};
|
||||
use ed25519_dalek::{SigningKey};
|
||||
use log::{trace};
|
||||
use ed25519_dalek::SigningKey;
|
||||
use log::trace;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::Rng;
|
||||
use std::error::Error;
|
||||
|
@ -701,13 +699,13 @@ mod tests {
|
|||
EpfServerHandshaker, EpfServerUpgradable, EpfServerUpgraded, EpfStreamOps,
|
||||
};
|
||||
use crate::pki::{EPFCertificate, EPFCertificateDetails, EpfPkiCertificateOps};
|
||||
use ed25519_dalek::{SigningKey};
|
||||
use ed25519_dalek::SigningKey;
|
||||
use log::{debug, trace};
|
||||
|
||||
|
||||
use serial_test::serial;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use serial_test::serial;
|
||||
|
||||
use tokio::join;
|
||||
use tokio::net::{TcpListener, TcpSocket, TcpStream};
|
||||
|
@ -856,11 +854,8 @@ mod tests {
|
|||
|
||||
cert_pool_2.insert(&server_cert);
|
||||
|
||||
let mut c: EpfClientUpgraded<TcpStream> = EpfClientUpgradable::upgrade(
|
||||
c,
|
||||
ClientAuthentication::Ephemeral,
|
||||
)
|
||||
.await;
|
||||
let mut c: EpfClientUpgraded<TcpStream> =
|
||||
EpfClientUpgradable::upgrade(c, ClientAuthentication::Ephemeral).await;
|
||||
let mut s: EpfServerUpgraded<TcpStream> =
|
||||
EpfServerUpgradable::upgrade(s, server_cert, server_private_key).await;
|
||||
|
||||
|
|
|
@ -646,7 +646,12 @@ mod tests {
|
|||
|
||||
let ca_pool = EpfCaPool::new();
|
||||
|
||||
assert!(matches!(fingerprint_does_not_match_cert.verify(&ca_pool).unwrap_err(), EpfPkiCertificateValidationError::FingerprintDoesNotMatch { .. }));
|
||||
assert!(matches!(
|
||||
fingerprint_does_not_match_cert
|
||||
.verify(&ca_pool)
|
||||
.unwrap_err(),
|
||||
EpfPkiCertificateValidationError::FingerprintDoesNotMatch { .. }
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -680,7 +685,12 @@ mod tests {
|
|||
|
||||
let ca_pool = EpfCaPool::new();
|
||||
|
||||
assert!(matches!(fingerprint_does_not_match_cert.verify(&ca_pool).unwrap_err(), EpfPkiCertificateValidationError::InvalidSignature { .. }));
|
||||
assert!(matches!(
|
||||
fingerprint_does_not_match_cert
|
||||
.verify(&ca_pool)
|
||||
.unwrap_err(),
|
||||
EpfPkiCertificateValidationError::InvalidSignature { .. }
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
use std::error::Error;
|
||||
use std::io::{Write};
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use clap::{Parser};
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::net::{TcpSocket};
|
||||
use tokio::select;
|
||||
use clap::Parser;
|
||||
use libepf::ca_pool::load_ca_pool;
|
||||
use libepf::handshake_stream::{ClientAuthentication, EpfClientHandshaker, EpfClientUpgradable, EpfStreamOps};
|
||||
use libepf::handshake_stream::{
|
||||
ClientAuthentication, EpfClientHandshaker, EpfClientUpgradable, EpfStreamOps,
|
||||
};
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::net::TcpSocket;
|
||||
use tokio::select;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
connect_ip: IpAddr,
|
||||
connect_port: u16
|
||||
connect_port: u16,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
|
@ -85,4 +87,4 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use std::error::Error;
|
||||
use std::{fs, io};
|
||||
use std::io::{Write};
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
use clap::{Parser};
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::select;
|
||||
use clap::Parser;
|
||||
use libepf::ca_pool::load_ca_pool;
|
||||
use libepf::handshake_stream::{EpfServerHandshaker, EpfServerUpgradable, EpfStreamOps};
|
||||
use libepf::pki::{EPFCertificate, EpfPkiSerializable, EpfPrivateKey};
|
||||
use std::error::Error;
|
||||
use std::io::Write;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::select;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
|
@ -99,4 +99,4 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue