cc! certtool + fix ncpf/netcatpf

This commit is contained in:
c0repwn3r 2023-05-04 09:41:26 -04:00
parent cbe8dee8a3
commit f438935954
Signed by: core
GPG Key ID: FDBF740DADDCEECF
7 changed files with 116 additions and 76 deletions

View File

@ -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::collections::HashMap;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::{SystemTime, UNIX_EPOCH}; 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)] #[derive(Parser)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
@ -22,31 +25,27 @@ enum Commands {
#[arg(short = 'p', long)] #[arg(short = 'p', long)]
out_public_key: PathBuf, out_public_key: PathBuf,
#[arg(short = 'k', long)] #[arg(short = 'k', long)]
out_private_key: PathBuf out_private_key: PathBuf,
}, },
/// Create a new **unsigned** certificate /// Create a new **unsigned** certificate
CreateCertificate { CreateCertificate {
#[arg(short, long)] #[arg(short, long)]
output: PathBuf, output: PathBuf,
#[arg(short, long)] #[arg(short, long)]
public_key: PathBuf public_key: PathBuf,
}, },
/// Dump information about the certificate /// Dump information about the certificate
DumpCertificate { DumpCertificate { cert: PathBuf },
cert: PathBuf
},
/// Verify the certificate /// Verify the certificate
VerifyCertificate { VerifyCertificate { cert: PathBuf },
cert: PathBuf
},
/// Sign the certificate using the given private key /// Sign the certificate using the given private key
SignCertificate { SignCertificate {
cert: PathBuf, cert: PathBuf,
#[arg(short, long)] #[arg(short, long)]
key: PathBuf, key: PathBuf,
#[arg(short, long)] #[arg(short, long)]
output: PathBuf output: PathBuf,
} },
} }
fn main() { fn main() {
@ -54,7 +53,10 @@ fn main() {
if let Some(subcommand) = args.command { if let Some(subcommand) = args.command {
match subcommand { 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 private_key = EpfPrivateKey::generate(&mut OsRng);
let public_key = private_key.verifying_key(); let public_key = private_key.verifying_key();
@ -88,7 +90,7 @@ fn main() {
std::process::exit(1); std::process::exit(1);
} }
} }
}, }
Commands::CreateCertificate { output, public_key } => { Commands::CreateCertificate { output, public_key } => {
// load public key // load public key
let public_key_pem = match fs::read(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 options = vec![
let expires_in = match Select::new("How long should the certificate be valid for?", options).prompt() { "1 day", "1 week", "1 month", "6 months", "1 year", "2 years", "5 years",
Ok(expires_in) => expires_in, "10 years", "Forever",
Err(e) => { ];
println!("Error with prompt: {}", e); let expires_in =
std::process::exit(1); 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 { let expires_in = match expires_in {
"1 day" => 60 * 60 * 24, "1 day" => 60 * 60 * 24,
"1 week" => 60 * 60 * 24 * 7, "1 week" => 60 * 60 * 24 * 7,
@ -132,10 +140,15 @@ fn main() {
"5 years" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 5, "5 years" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 5,
"10 years" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 10, "10 years" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 10,
"Forever" => 60 * 60 * 24 * 7 * 4 * 6 * 2 * 100000, // 100,000 years "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, Ok(ac) => ac,
Err(e) => { Err(e) => {
println!("Error with prompt: {}", e); println!("Error with prompt: {}", e);
@ -162,7 +175,12 @@ fn main() {
} }
}; };
claims.insert(name, value); 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, Ok(ac) => ac,
Err(e) => { Err(e) => {
println!("Error with prompt: {}", e); println!("Error with prompt: {}", e);
@ -178,8 +196,15 @@ fn main() {
let mut cert = EPFCertificate { let mut cert = EPFCertificate {
details: EPFCertificateDetails { details: EPFCertificateDetails {
name, name,
not_before: SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs(), not_before: SystemTime::now()
not_after: SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs() + expires_in, .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(), public_key: public_key.to_bytes(),
issuer_public_key: [0u8; 32], issuer_public_key: [0u8; 32],
claims, claims,
@ -209,7 +234,7 @@ fn main() {
println!("Error saving certificate: {}", e); println!("Error saving certificate: {}", e);
} }
} }
}, }
Commands::DumpCertificate { cert } => { Commands::DumpCertificate { cert } => {
// load cert // load cert
let cert_pem = match fs::read(cert) { let cert_pem = match fs::read(cert) {
@ -227,8 +252,8 @@ fn main() {
} }
}; };
println!("{}", cert); println!("{}", cert);
}, }
Commands::SignCertificate { cert, key, output }=> { Commands::SignCertificate { cert, key, output } => {
// load cert // load cert
let cert_pem = match fs::read(cert) { let cert_pem = match fs::read(cert) {
Ok(pem) => pem, Ok(pem) => pem,
@ -283,7 +308,7 @@ fn main() {
println!("Error saving certificate: {}", e); println!("Error saving certificate: {}", e);
} }
} }
}, }
Commands::VerifyCertificate { cert } => { Commands::VerifyCertificate { cert } => {
// load cert // load cert
let cert_pem = match fs::read(cert) { let cert_pem = match fs::read(cert) {
@ -314,13 +339,13 @@ fn main() {
println!("Certificate valid but not trusted"); println!("Certificate valid but not trusted");
std::process::exit(3); std::process::exit(3);
} }
}, }
Err(e) => { Err(e) => {
println!("Certificate invalid: {}", e); println!("Certificate invalid: {}", e);
std::process::exit(2); std::process::exit(2);
} }
} }
}, }
} }
} else { } else {
println!("No subcommand specified. Run with -h/--help for help."); println!("No subcommand specified. Run with -h/--help for help.");

View File

@ -76,6 +76,9 @@ mod tests {
#[test] #[test]
pub fn ca_pool_error_display_test() { pub fn ca_pool_error_display_test() {
println!("{}", EpfCaPoolLoaderError::CertDirDoesNotExist("".to_string())); println!(
"{}",
EpfCaPoolLoaderError::CertDirDoesNotExist("".to_string())
);
} }
} }

View File

@ -38,9 +38,14 @@ mod tests {
pub fn error_display_test() { pub fn error_display_test() {
println!("{}", EpfHandshakeError::AlreadyTunnelled); println!("{}", EpfHandshakeError::AlreadyTunnelled);
println!("{}", EpfHandshakeError::UnsupportedProtocolVersion(0)); println!("{}", EpfHandshakeError::UnsupportedProtocolVersion(0));
println!("{}", EpfHandshakeError::InvalidCertificate(EpfPkiCertificateValidationError::ValidAfterSigner)); println!(
"{}",
EpfHandshakeError::InvalidCertificate(
EpfPkiCertificateValidationError::ValidAfterSigner
)
);
println!("{}", EpfHandshakeError::UntrustedCertificate); println!("{}", EpfHandshakeError::UntrustedCertificate);
println!("{}", EpfHandshakeError::EncryptionError); println!("{}", EpfHandshakeError::EncryptionError);
println!("{}", EpfHandshakeError::MissingKeyProof); println!("{}", EpfHandshakeError::MissingKeyProof);
} }
} }

View File

@ -1,9 +1,7 @@
use crate::ca_pool::{EpfCaPool}; use crate::ca_pool::EpfCaPool;
use crate::danger_trace; use crate::danger_trace;
use crate::error::EpfHandshakeError; use crate::error::EpfHandshakeError;
use crate::pki::{ use crate::pki::{EPFCertificate, EpfPkiCertificateOps, EpfPrivateKey, EpfPublicKey};
EPFCertificate, EpfPkiCertificateOps, EpfPrivateKey, EpfPublicKey,
};
use crate::protocol::{ use crate::protocol::{
encode_packet, recv_packet, EpfApplicationData, EpfClientHello, EpfClientState, EpfFinished, encode_packet, recv_packet, EpfApplicationData, EpfClientHello, EpfClientState, EpfFinished,
EpfMessage, EpfServerHello, EpfServerState, PACKET_APPLICATION_DATA, PACKET_CLIENT_HELLO, EpfMessage, EpfServerHello, EpfServerState, PACKET_APPLICATION_DATA, PACKET_CLIENT_HELLO,
@ -12,8 +10,8 @@ use crate::protocol::{
use async_trait::async_trait; use async_trait::async_trait;
use chacha20poly1305::aead::{Aead, Payload}; use chacha20poly1305::aead::{Aead, Payload};
use chacha20poly1305::{AeadCore, Key, KeyInit, XChaCha20Poly1305, XNonce}; use chacha20poly1305::{AeadCore, Key, KeyInit, XChaCha20Poly1305, XNonce};
use ed25519_dalek::{SigningKey}; use ed25519_dalek::SigningKey;
use log::{trace}; use log::trace;
use rand::rngs::OsRng; use rand::rngs::OsRng;
use rand::Rng; use rand::Rng;
use std::error::Error; use std::error::Error;
@ -701,13 +699,13 @@ mod tests {
EpfServerHandshaker, EpfServerUpgradable, EpfServerUpgraded, EpfStreamOps, EpfServerHandshaker, EpfServerUpgradable, EpfServerUpgraded, EpfStreamOps,
}; };
use crate::pki::{EPFCertificate, EPFCertificateDetails, EpfPkiCertificateOps}; use crate::pki::{EPFCertificate, EPFCertificateDetails, EpfPkiCertificateOps};
use ed25519_dalek::{SigningKey}; use ed25519_dalek::SigningKey;
use log::{debug, trace}; use log::{debug, trace};
use serial_test::serial;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::str::FromStr; use std::str::FromStr;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use serial_test::serial;
use tokio::join; use tokio::join;
use tokio::net::{TcpListener, TcpSocket, TcpStream}; use tokio::net::{TcpListener, TcpSocket, TcpStream};
@ -856,11 +854,8 @@ mod tests {
cert_pool_2.insert(&server_cert); cert_pool_2.insert(&server_cert);
let mut c: EpfClientUpgraded<TcpStream> = EpfClientUpgradable::upgrade( let mut c: EpfClientUpgraded<TcpStream> =
c, EpfClientUpgradable::upgrade(c, ClientAuthentication::Ephemeral).await;
ClientAuthentication::Ephemeral,
)
.await;
let mut s: EpfServerUpgraded<TcpStream> = let mut s: EpfServerUpgraded<TcpStream> =
EpfServerUpgradable::upgrade(s, server_cert, server_private_key).await; EpfServerUpgradable::upgrade(s, server_cert, server_private_key).await;

View File

@ -646,7 +646,12 @@ mod tests {
let ca_pool = EpfCaPool::new(); 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] #[test]
@ -680,7 +685,12 @@ mod tests {
let ca_pool = EpfCaPool::new(); 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] #[test]

View File

@ -1,19 +1,21 @@
use std::error::Error; use clap::Parser;
use std::io::{Write};
use std::net::{IpAddr, SocketAddr};
use clap::{Parser};
use tokio::io::AsyncReadExt;
use tokio::net::{TcpSocket};
use tokio::select;
use libepf::ca_pool::load_ca_pool; 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;
use std::io::Write;
use std::net::{IpAddr, SocketAddr};
use tokio::io::AsyncReadExt;
use tokio::net::TcpSocket;
use tokio::select;
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
pub struct Cli { pub struct Cli {
connect_ip: IpAddr, connect_ip: IpAddr,
connect_port: u16 connect_port: u16,
} }
#[tokio::main] #[tokio::main]
@ -85,4 +87,4 @@ async fn main() -> Result<(), Box<dyn Error>> {
} }
Ok(()) Ok(())
} }

View File

@ -1,15 +1,15 @@
use std::error::Error; use clap::Parser;
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 libepf::ca_pool::load_ca_pool; use libepf::ca_pool::load_ca_pool;
use libepf::handshake_stream::{EpfServerHandshaker, EpfServerUpgradable, EpfStreamOps}; use libepf::handshake_stream::{EpfServerHandshaker, EpfServerUpgradable, EpfStreamOps};
use libepf::pki::{EPFCertificate, EpfPkiSerializable, EpfPrivateKey}; 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)] #[derive(Parser)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]
@ -99,4 +99,4 @@ async fn main() -> Result<(), Box<dyn Error>> {
} }
Ok(()) Ok(())
} }