Add Debug trait for X509 and other types.
This currently leaves out at least two useful things: - The detailed SubjectPublicKeyInfo, e.g. the modulus of RSA keys. - Extensions.
This commit is contained in:
parent
7446f9fa68
commit
6482f419b8
|
|
@ -67,12 +67,16 @@ foreign_type_and_impl_send_sync! {
|
|||
impl fmt::Display for Asn1GeneralizedTimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unsafe {
|
||||
let mem_bio = MemBio::new()?;
|
||||
cvt(ffi::ASN1_GENERALIZEDTIME_print(
|
||||
match MemBio::new() {
|
||||
Err(_) => f.write_str(""),
|
||||
Ok(mem_bio) => match cvt(ffi::ASN1_GENERALIZEDTIME_print(
|
||||
mem_bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
))?;
|
||||
write!(f, "{}", str::from_utf8_unchecked(mem_bio.get_buf()))
|
||||
)) {
|
||||
Err(_) => f.write_str(""),
|
||||
Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -207,12 +211,22 @@ impl<'a> PartialOrd<Asn1Time> for &'a Asn1TimeRef {
|
|||
impl fmt::Display for Asn1TimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
unsafe {
|
||||
let mem_bio = MemBio::new()?;
|
||||
cvt(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.as_ptr()))?;
|
||||
write!(f, "{}", str::from_utf8_unchecked(mem_bio.get_buf()))
|
||||
match MemBio::new() {
|
||||
Err(_) => f.write_str("error"),
|
||||
Ok(mem_bio) => match cvt(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.as_ptr())) {
|
||||
Err(_) => f.write_str("error"),
|
||||
Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1TimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1Time {
|
||||
fn new() -> Result<Asn1Time, ErrorStack> {
|
||||
|
|
@ -389,6 +403,15 @@ impl Asn1StringRef {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1StringRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.as_utf8() {
|
||||
Ok(openssl_string) => openssl_string.fmt(fmt),
|
||||
Err(_) => fmt.write_str("error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_INTEGER;
|
||||
fn drop = ffi::ASN1_INTEGER_free;
|
||||
|
|
@ -527,11 +550,19 @@ impl fmt::Display for Asn1ObjectRef {
|
|||
self.as_ptr(),
|
||||
0,
|
||||
);
|
||||
let s = str::from_utf8(&buf[..len as usize]).map_err(|_| fmt::Error)?;
|
||||
fmt.write_str(s)
|
||||
match str::from_utf8(&buf[..len as usize]) {
|
||||
Err(_) => fmt.write_str("error"),
|
||||
Ok(s) => fmt.write_str(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1ObjectRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.write_str(self.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ use ffi;
|
|||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_int, c_long};
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
|
|
@ -286,6 +287,27 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for PKey<T> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
let alg = match self.id() {
|
||||
Id::RSA => "RSA",
|
||||
Id::HMAC => "HMAC",
|
||||
Id::DSA => "DSA",
|
||||
Id::DH => "DH",
|
||||
Id::EC => "EC",
|
||||
#[cfg(ossl111)]
|
||||
Id::ED25519 => "Ed25519",
|
||||
#[cfg(ossl111)]
|
||||
Id::ED448 => "Ed448",
|
||||
_ => "unknown",
|
||||
};
|
||||
fmt.debug_struct("public_key")
|
||||
.field("algorithm", &alg)
|
||||
.finish()
|
||||
// TODO: Print details for each specific type of key
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for PKey<T> {
|
||||
fn clone(&self) -> PKey<T> {
|
||||
PKeyRef::to_owned(self)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
|
|||
use libc::c_int;
|
||||
use std::borrow::Borrow;
|
||||
use std::convert::AsRef;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
|
|
@ -43,6 +44,15 @@ pub struct Stack<T: Stackable>(*mut T::StackType);
|
|||
unsafe impl<T: Stackable + Send> Send for Stack<T> {}
|
||||
unsafe impl<T: Stackable + Sync> Sync for Stack<T> {}
|
||||
|
||||
impl<T> fmt::Debug for Stack<T>
|
||||
where
|
||||
T: Stackable,
|
||||
T::Ref: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt.debug_list().entries(self).finish()
|
||||
}
|
||||
}
|
||||
impl<T: Stackable> Drop for Stack<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -671,6 +671,35 @@ impl Clone for X509 {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for X509 {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let serial = match &self.serial_number().to_bn() {
|
||||
Ok(bn) => match bn.to_hex_str() {
|
||||
Ok(hex) => hex.to_string(),
|
||||
Err(_) => "".to_string(),
|
||||
},
|
||||
Err(_) => "".to_string(),
|
||||
};
|
||||
let mut debug_struct = formatter.debug_struct("X509");
|
||||
debug_struct.field("serial_number", &serial);
|
||||
debug_struct.field("signature_algorithm", &self.signature_algorithm().object());
|
||||
debug_struct.field("issuer", &self.issuer_name());
|
||||
debug_struct.field("subject", &self.subject_name());
|
||||
if let Some(subject_alt_names) = &self.subject_alt_names() {
|
||||
debug_struct.field("subject_alt_names", subject_alt_names);
|
||||
}
|
||||
debug_struct.field("not_before", &self.not_before());
|
||||
debug_struct.field("not_after", &self.not_after());
|
||||
|
||||
if let Ok(public_key) = &self.public_key() {
|
||||
debug_struct.field("public_key", public_key);
|
||||
};
|
||||
// TODO: Print extensions once they are supported on the X509 struct.
|
||||
|
||||
debug_struct.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<X509Ref> for X509Ref {
|
||||
fn as_ref(&self) -> &X509Ref {
|
||||
self
|
||||
|
|
@ -867,6 +896,12 @@ impl X509NameRef {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for X509NameRef {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.debug_list().entries(self.entries()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A type to destructure and examine an `X509Name`.
|
||||
pub struct X509NameEntries<'a> {
|
||||
name: &'a X509NameRef,
|
||||
|
|
@ -942,6 +977,12 @@ impl X509NameEntryRef {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for X509NameEntryRef {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_fmt(format_args!("{:?} = {:?}", self.object(), self.data()))
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder used to construct an `X509Req`.
|
||||
pub struct X509ReqBuilder(X509Req);
|
||||
|
||||
|
|
@ -1298,6 +1339,25 @@ impl GeneralNameRef {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for GeneralNameRef {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if let Some(email) = self.email() {
|
||||
return formatter.write_str(email);
|
||||
}
|
||||
if let Some(dnsname) = self.dnsname() {
|
||||
return formatter.write_str(dnsname);
|
||||
}
|
||||
if let Some(uri) = self.uri() {
|
||||
return formatter.write_str(uri);
|
||||
}
|
||||
if let Some(ipaddress) = self.ipaddress() {
|
||||
let result = String::from_utf8_lossy(ipaddress);
|
||||
return formatter.write_str(&result);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Stackable for GeneralName {
|
||||
type StackType = ffi::stack_st_GENERAL_NAME;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,34 @@ fn test_cert_loading() {
|
|||
assert_eq!(hash_vec, &*fingerprint);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let debugged = format!("{:#?}", cert);
|
||||
let expected = r#"X509 {
|
||||
serial_number: "8771F7BDEE982FA5",
|
||||
signature_algorithm: sha256WithRSAEncryption,
|
||||
issuer: [
|
||||
countryName = "AU",
|
||||
stateOrProvinceName = "Some-State",
|
||||
organizationName = "Internet Widgits Pty Ltd",
|
||||
],
|
||||
subject: [
|
||||
countryName = "AU",
|
||||
stateOrProvinceName = "Some-State",
|
||||
organizationName = "Internet Widgits Pty Ltd",
|
||||
commonName = "foobar.com",
|
||||
],
|
||||
not_before: Aug 14 17:00:03 2016 GMT,
|
||||
not_after: Aug 12 17:00:03 2026 GMT,
|
||||
public_key: public_key {
|
||||
algorithm: "RSA",
|
||||
},
|
||||
}"#;
|
||||
assert_eq!(expected, debugged);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cert_issue_validity() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
|
|
|
|||
Loading…
Reference in New Issue