use openssl::pkey::{PKey, Private};
use openssl::x509::X509;
use regex::Regex;
use std::fmt::Display;
use std::path::PathBuf;
#[derive(Debug)]
pub struct ParseError {
pub msg: String,
}
impl std::error::Error for ParseError {}
impl Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Failed to parse certificate: {}", self.msg)
}
}
#[derive(Debug)]
pub enum CommonName {
Literal(String),
Pattern(Regex),
}
impl Display for CommonName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Literal(string) => write!(f, "{string}"),
Self::Pattern(pattern) => write!(f, "{pattern}"),
}
}
}
impl CommonName {
pub fn matches(&self, cn: &str) -> bool {
match self {
Self::Literal(string) => string == cn,
Self::Pattern(pattern) => pattern.is_match(cn),
}
}
}
#[derive(Debug)]
pub enum Verb {
Find { cn: CommonName },
Replace {
cn: CommonName,
cert: Cert,
privkey: Option<PrivKey>,
},
}
impl Display for Verb {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Find { cn } => {
write!(f, "Finding certificates and associated private keys with common name matching: {}", cn)
},
Self::Replace {
cn,
cert: _,
privkey,
} => match privkey.is_some() {
true => write!(f, "Replacing certificates and associated private keys with common name matching: {}", cn),
false => write!(f, "Replacing certificates only with common name matching: {}", cn),
},
}
}
}
impl Verb {
pub fn cn(&self) -> &CommonName {
match self {
Self::Find { cn } => cn,
Self::Replace {
cn,
cert: _,
privkey: _,
} => cn,
}
}
pub fn privkeys(&self) -> bool {
match self {
Self::Find { .. } => true,
Self::Replace {
cn: _,
cert: _,
privkey,
} => privkey.is_some(),
}
}
}
#[derive(Debug, Clone)]
pub struct Cert {
pub cert: X509,
pub common_name: String,
pub locator: PEMLocator,
}
#[derive(Debug, Clone)]
pub struct PrivKey {
pub key: PKey<Private>,
pub locator: PEMLocator,
}
#[derive(Debug)]
pub enum PKIObject {
Cert(Cert),
PrivKey(PrivKey),
}
#[derive(Debug, PartialEq, Eq)]
pub struct PEMPart<'a> {
pub label: String,
pub data: &'a [u8],
pub start: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PEMKind {
Cert,
PrivKey,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PEMLocator {
pub kind: PEMKind,
pub path: PathBuf,
pub start: usize,
pub end: usize,
}