From ec01eeadc620f3c1d48a083a9c442e9bb1fa93cc Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Fri, 10 Jul 2020 10:51:11 +0200 Subject: [PATCH] refactor CertInfo to tools we want to reuse some of the functionality elsewhere Signed-off-by: Dominik Csapak --- src/bin/proxmox_backup_manager/cert.rs | 29 ++--------- src/tools.rs | 1 + src/tools/cert.rs | 67 ++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 src/tools/cert.rs diff --git a/src/bin/proxmox_backup_manager/cert.rs b/src/bin/proxmox_backup_manager/cert.rs index f5f725a3..845c8edc 100644 --- a/src/bin/proxmox_backup_manager/cert.rs +++ b/src/bin/proxmox_backup_manager/cert.rs @@ -1,32 +1,18 @@ -use std::path::PathBuf; - use anyhow::{bail, Error}; use proxmox::api::{api, cli::*}; use proxmox_backup::config; -use proxmox_backup::configdir; use proxmox_backup::auth_helpers::*; - -fn x509name_to_string(name: &openssl::x509::X509NameRef) -> Result { - let mut parts = Vec::new(); - for entry in name.entries() { - parts.push(format!("{} = {}", entry.object().nid().short_name()?, entry.data().as_utf8()?)); - } - Ok(parts.join(", ")) -} +use proxmox_backup::tools::cert::CertInfo; #[api] /// Display node certificate information. fn cert_info() -> Result<(), Error> { - let cert_path = PathBuf::from(configdir!("/proxy.pem")); + let cert = CertInfo::new()?; - let cert_pem = proxmox::tools::fs::file_get_contents(&cert_path)?; - - let cert = openssl::x509::X509::from_pem(&cert_pem)?; - - println!("Subject: {}", x509name_to_string(cert.subject_name())?); + println!("Subject: {}", cert.subject_name()?); if let Some(san) = cert.subject_alt_names() { for name in san.iter() { @@ -42,17 +28,12 @@ fn cert_info() -> Result<(), Error> { } } - println!("Issuer: {}", x509name_to_string(cert.issuer_name())?); + println!("Issuer: {}", cert.issuer_name()?); println!("Validity:"); println!(" Not Before: {}", cert.not_before()); println!(" Not After : {}", cert.not_after()); - let fp = cert.digest(openssl::hash::MessageDigest::sha256())?; - let fp_string = proxmox::tools::digest_to_hex(&fp); - let fp_string = fp_string.as_bytes().chunks(2).map(|v| std::str::from_utf8(v).unwrap()) - .collect::>().join(":"); - - println!("Fingerprint (sha256): {}", fp_string); + println!("Fingerprint (sha256): {}", cert.fingerprint()?); let pubkey = cert.public_key()?; println!("Public key type: {}", openssl::nid::Nid::from_raw(pubkey.id().as_raw()).long_name()?); diff --git a/src/tools.rs b/src/tools.rs index 75c8d9f5..4bfc35c8 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -23,6 +23,7 @@ pub use proxmox::tools::fd::Fd; pub mod acl; pub mod async_io; pub mod borrow; +pub mod cert; pub mod daemon; pub mod disks; pub mod fs; diff --git a/src/tools/cert.rs b/src/tools/cert.rs new file mode 100644 index 00000000..0c7e9e5d --- /dev/null +++ b/src/tools/cert.rs @@ -0,0 +1,67 @@ +use std::path::PathBuf; + +use anyhow::Error; +use openssl::x509::{X509, GeneralName}; +use openssl::stack::Stack; +use openssl::pkey::{Public, PKey}; + +use crate::configdir; + +pub struct CertInfo { + x509: X509, +} + +fn x509name_to_string(name: &openssl::x509::X509NameRef) -> Result { + let mut parts = Vec::new(); + for entry in name.entries() { + parts.push(format!("{} = {}", entry.object().nid().short_name()?, entry.data().as_utf8()?)); + } + Ok(parts.join(", ")) +} + +impl CertInfo { + pub fn new() -> Result { + Self::from_path(PathBuf::from(configdir!("/proxy.pem"))) + } + + pub fn from_path(path: PathBuf) -> Result { + let cert_pem = proxmox::tools::fs::file_get_contents(&path)?; + let x509 = openssl::x509::X509::from_pem(&cert_pem)?; + Ok(Self{ + x509 + }) + } + + pub fn subject_alt_names(&self) -> Option> { + self.x509.subject_alt_names() + } + + pub fn subject_name(&self) -> Result { + Ok(x509name_to_string(self.x509.subject_name())?) + } + + pub fn issuer_name(&self) -> Result { + Ok(x509name_to_string(self.x509.issuer_name())?) + } + + pub fn fingerprint(&self) -> Result { + let fp = self.x509.digest(openssl::hash::MessageDigest::sha256())?; + let fp_string = proxmox::tools::digest_to_hex(&fp); + let fp_string = fp_string.as_bytes().chunks(2).map(|v| std::str::from_utf8(v).unwrap()) + .collect::>().join(":"); + Ok(fp_string) + } + + pub fn public_key(&self) -> Result, Error> { + let pubkey = self.x509.public_key()?; + Ok(pubkey) + } + + pub fn not_before(&self) -> &openssl::asn1::Asn1TimeRef { + self.x509.not_before() + } + + pub fn not_after(&self) -> &openssl::asn1::Asn1TimeRef { + self.x509.not_after() + } +}