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::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.");

View File

@ -76,6 +76,9 @@ mod tests {
#[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() {
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);
}
}
}

View File

@ -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;

View File

@ -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]

View File

@ -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(())
}
}

View File

@ -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(())
}
}