Introduce ForeignTypeExt and ForeignTypeRefExt

`ForeignTypeExt` and `ForeignTypeRefExt` are inspired by
https://github.com/sfackler/rust-openssl/pull/1345, which make dealing
with FFI safer and more ergonomic. The new APIs (e.g.
from_const_ptr_opt`) also allow for gracefully handling instances where
the initial API call results in `NULL`. Instead of crashing the program,
`None` will be returned.
This commit is contained in:
Rushil Mehra 2024-08-13 17:24:42 -07:00 committed by Rushil Mehra
parent 1b5ae3251f
commit 2be6e100b6
2 changed files with 48 additions and 33 deletions

View File

@ -1,10 +1,10 @@
use crate::error::ErrorStack;
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::{c_char, c_int, c_void};
use std::any::Any;
use std::panic::{self, AssertUnwindSafe};
use std::slice;
use crate::error::ErrorStack;
/// Wraps a user-supplied callback and a slot for panics thrown inside the callback (while FFI
/// frames are on the stack).
///
@ -65,3 +65,30 @@ where
}
}
}
#[allow(dead_code)]
pub trait ForeignTypeExt: ForeignType {
unsafe fn from_ptr_opt(ptr: *mut Self::CType) -> Option<Self> {
if ptr.is_null() {
None
} else {
Some(Self::from_ptr(ptr))
}
}
}
impl<FT: ForeignType> ForeignTypeExt for FT {}
pub trait ForeignTypeRefExt: ForeignTypeRef {
unsafe fn from_const_ptr<'a>(ptr: *const Self::CType) -> &'a Self {
Self::from_ptr(ptr as *mut Self::CType)
}
unsafe fn from_const_ptr_opt<'a>(ptr: *const Self::CType) -> Option<&'a Self> {
if ptr.is_null() {
None
} else {
Some(Self::from_const_ptr(ptr as *mut Self::CType))
}
}
}
impl<FT: ForeignTypeRef> ForeignTypeRefExt for FT {}

View File

@ -36,6 +36,7 @@ use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
use crate::ssl::SslRef;
use crate::stack::{Stack, StackRef, Stackable};
use crate::string::OpensslString;
use crate::util::ForeignTypeRefExt;
use crate::x509::verify::X509VerifyParamRef;
use crate::{cvt, cvt_n, cvt_p};
@ -407,8 +408,7 @@ impl X509Ref {
pub fn subject_name(&self) -> &X509NameRef {
unsafe {
let name = ffi::X509_get_subject_name(self.as_ptr());
assert!(!name.is_null());
X509NameRef::from_ptr(name)
X509NameRef::from_const_ptr_opt(name).expect("issuer name must not be null")
}
}
@ -419,19 +419,6 @@ impl X509Ref {
unsafe { ffi::X509_subject_name_hash(self.as_ptr()) as u32 }
}
/// Returns this certificate's issuer name.
///
/// This corresponds to [`X509_get_issuer_name`].
///
/// [`X509_get_issuer_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_get_subject_name.html
pub fn issuer_name(&self) -> &X509NameRef {
unsafe {
let name = ffi::X509_get_issuer_name(self.as_ptr());
assert!(!name.is_null());
X509NameRef::from_ptr(name)
}
}
/// Returns this certificate's subject alternative name entries, if they exist.
///
/// This corresponds to [`X509_get_ext_d2i`] called with `NID_subject_alt_name`.
@ -453,6 +440,15 @@ impl X509Ref {
}
}
/// Returns this certificate's issuer name.
#[corresponds(X509_get_issuer_name)]
pub fn issuer_name(&self) -> &X509NameRef {
unsafe {
let name = ffi::X509_get_issuer_name(self.as_ptr());
X509NameRef::from_const_ptr_opt(name).expect("issuer name must not be null")
}
}
/// Returns this certificate's issuer alternative name entries, if they exist.
///
/// This corresponds to [`X509_get_ext_d2i`] called with `NID_issuer_alt_name`.
@ -474,27 +470,19 @@ impl X509Ref {
}
}
/// Returns this certificate's subject key id.
///
/// This corresponds to [`X509_get0_subject_key_id`].
///
/// [`X509_get0_subject_key_id`]: https://docs.openssl.org/1.1.1/man3/X509_get_extension_flags/
pub fn subject_key_id(&self) -> &Asn1StringRef {
/// Returns this certificate's subject key id, if it exists.
pub fn subject_key_id(&self) -> Option<&Asn1StringRef> {
unsafe {
let name = ffi::X509_get0_subject_key_id(self.as_ptr());
Asn1StringRef::from_ptr(name as _)
let data = ffi::X509_get0_subject_key_id(self.as_ptr());
Asn1StringRef::from_const_ptr_opt(data)
}
}
/// Returns this certificate's authority key id.
///
/// This corresponds to [`X509_get0_authority_key_id`].
///
/// [`X509_get0_authority_key_id`]: https://docs.openssl.org/1.1.1/man3/X509_get_extension_flags/
pub fn authority_key_id(&self) -> &Asn1StringRef {
/// Returns this certificate's authority key id, if it exists.
pub fn authority_key_id(&self) -> Option<&Asn1StringRef> {
unsafe {
let name = ffi::X509_get0_authority_key_id(self.as_ptr());
Asn1StringRef::from_ptr(name as _)
let data = ffi::X509_get0_authority_key_id(self.as_ptr());
Asn1StringRef::from_const_ptr_opt(data)
}
}