//! Internet protocols, including SSL/TLS, which is the basis for HTTPS,
//! the secure protocol for browsing the web.
-use ffi;
+use cfg_if::cfg_if;
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::{c_int, c_long};
use std::error::Error;
use std::slice;
use std::str;
-use asn1::{Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef};
-use bio::MemBioSlice;
-use conf::ConfRef;
-use error::ErrorStack;
-use ex_data::Index;
-use hash::{DigestBytes, MessageDigest};
-use nid::Nid;
-use pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
-use ssl::SslRef;
-use stack::{Stack, StackRef, Stackable};
-use string::OpensslString;
-use {cvt, cvt_n, cvt_p};
+use crate::asn1::{
+ Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef, Asn1Type,
+};
+use crate::bio::MemBioSlice;
+use crate::conf::ConfRef;
+use crate::error::ErrorStack;
+use crate::ex_data::Index;
+use crate::hash::{DigestBytes, MessageDigest};
+use crate::nid::Nid;
+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::{ForeignTypeExt, ForeignTypeRefExt};
+use crate::{cvt, cvt_n, cvt_p};
#[cfg(any(ossl102, libressl261))]
pub mod verify;
pub fn current_cert(&self) -> Option<&X509Ref> {
unsafe {
let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr());
- if ptr.is_null() {
- None
- } else {
- Some(X509Ref::from_ptr(ptr))
- }
+ X509Ref::from_const_ptr_opt(ptr)
}
}
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("subject name must not be null")
}
}
+ /// Returns the hash of the certificates subject
+ ///
+ /// This corresponds to `X509_subject_name_hash`.
+ pub fn subject_name_hash(&self) -> u32 {
+ unsafe { ffi::X509_subject_name_hash(self.as_ptr()) as u32 }
+ }
+
/// Returns this certificate's issuer name.
///
/// This corresponds to [`X509_get_issuer_name`].
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)
+ X509NameRef::from_const_ptr_opt(name).expect("issuer name must not be null")
}
}
ptr::null_mut(),
ptr::null_mut(),
);
- if stack.is_null() {
- None
- } else {
- Some(Stack::from_ptr(stack as *mut _))
- }
+ Stack::from_ptr_opt(stack as *mut _)
}
}
ptr::null_mut(),
ptr::null_mut(),
);
- if stack.is_null() {
- None
- } else {
- Some(Stack::from_ptr(stack as *mut _))
- }
+ Stack::from_ptr_opt(stack as *mut _)
+ }
+ }
+
+ /// Returns this certificate's [`authority information access`] entries, if they exist.
+ ///
+ /// This corresponds to [`X509_get_ext_d2i`] called with `NID_info_access`.
+ ///
+ /// [`X509_get_ext_d2i`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_get_ext_d2i.html
+ /// [`authority information access`]: https://tools.ietf.org/html/rfc5280#section-4.2.2.1
+ pub fn authority_info(&self) -> Option<Stack<AccessDescription>> {
+ unsafe {
+ let stack = ffi::X509_get_ext_d2i(
+ self.as_ptr(),
+ ffi::NID_info_access,
+ ptr::null_mut(),
+ ptr::null_mut(),
+ );
+ Stack::from_ptr_opt(stack as *mut _)
}
}
pub fn not_after(&self) -> &Asn1TimeRef {
unsafe {
let date = X509_getm_notAfter(self.as_ptr());
- assert!(!date.is_null());
- Asn1TimeRef::from_ptr(date)
+ Asn1TimeRef::from_const_ptr_opt(date).expect("not_after must not be null")
}
}
pub fn not_before(&self) -> &Asn1TimeRef {
unsafe {
let date = X509_getm_notBefore(self.as_ptr());
- assert!(!date.is_null());
- Asn1TimeRef::from_ptr(date)
+ Asn1TimeRef::from_const_ptr_opt(date).expect("not_before must not be null")
}
}
unsafe {
let mut signature = ptr::null();
X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr());
- assert!(!signature.is_null());
- Asn1BitStringRef::from_ptr(signature as *mut _)
+ Asn1BitStringRef::from_const_ptr_opt(signature).expect("signature must not be null")
}
}
unsafe {
let mut algor = ptr::null();
X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr());
- assert!(!algor.is_null());
- X509AlgorithmRef::from_ptr(algor as *mut _)
+ X509AlgorithmRef::from_const_ptr_opt(algor)
+ .expect("signature algorithm must not be null")
}
}
}
}
+ /// Returns certificate version. If this certificate has no explicit version set, it defaults to
+ /// version 1.
+ ///
+ /// Note that `0` return value stands for version 1, `1` for version 2 and so on.
+ ///
+ /// This corresponds to [`X509_get_version`].
+ ///
+ /// [`X509_get_version`]: https://www.openssl.org/docs/man1.1.1/man3/X509_get_version.html
+ #[cfg(ossl110)]
+ pub fn version(&self) -> i32 {
+ // Covered with `x509_ref_version()`, `x509_ref_version_no_version_set()` tests
+ unsafe { ffi::X509_get_version(self.as_ptr()) as i32 }
+ }
+
/// Check if the certificate is signed using the given public key.
///
/// Only the signature is checked: no other checks (such as certificate chain validity)
pub fn serial_number(&self) -> &Asn1IntegerRef {
unsafe {
let r = ffi::X509_get_serialNumber(self.as_ptr());
- assert!(!r.is_null());
- Asn1IntegerRef::from_ptr(r)
+ Asn1IntegerRef::from_const_ptr_opt(r).expect("serial number must not be null")
}
}
}
impl fmt::Debug for X509 {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ 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(),
/// See the extension module for builder types which will construct certain common extensions.
pub fn new(
conf: Option<&ConfRef>,
- context: Option<&X509v3Context>,
+ context: Option<&X509v3Context<'_>>,
name: &str,
value: &str,
) -> Result<X509Extension, ErrorStack> {
/// See the extension module for builder types which will construct certain common extensions.
pub fn new_nid(
conf: Option<&ConfRef>,
- context: Option<&X509v3Context>,
+ context: Option<&X509v3Context<'_>>,
name: Nid,
value: &str,
) -> Result<X509Extension, ErrorStack> {
}
}
+ /// Add a field entry by str with a specific type.
+ ///
+ /// This corresponds to [`X509_NAME_add_entry_by_txt`].
+ ///
+ /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_txt.html
+ pub fn append_entry_by_text_with_type(
+ &mut self,
+ field: &str,
+ value: &str,
+ ty: Asn1Type,
+ ) -> Result<(), ErrorStack> {
+ unsafe {
+ let field = CString::new(field).unwrap();
+ assert!(value.len() <= c_int::max_value() as usize);
+ cvt(ffi::X509_NAME_add_entry_by_txt(
+ self.0.as_ptr(),
+ field.as_ptr() as *mut _,
+ ty.as_raw(),
+ value.as_ptr(),
+ value.len() as c_int,
+ -1,
+ 0,
+ ))
+ .map(|_| ())
+ }
+ }
+
/// Add a field entry by NID.
///
/// This corresponds to [`X509_NAME_add_entry_by_NID`].
}
}
+ /// Add a field entry by NID with a specific type.
+ ///
+ /// This corresponds to [`X509_NAME_add_entry_by_NID`].
+ ///
+ /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html
+ pub fn append_entry_by_nid_with_type(
+ &mut self,
+ field: Nid,
+ value: &str,
+ ty: Asn1Type,
+ ) -> Result<(), ErrorStack> {
+ unsafe {
+ assert!(value.len() <= c_int::max_value() as usize);
+ cvt(ffi::X509_NAME_add_entry_by_NID(
+ self.0.as_ptr(),
+ field.as_raw(),
+ ty.as_raw(),
+ value.as_ptr() as *mut _,
+ value.len() as c_int,
+ -1,
+ 0,
+ ))
+ .map(|_| ())
+ }
+ }
+
/// Return an `X509Name`.
pub fn build(self) -> X509Name {
self.0
}
impl fmt::Debug for X509NameRef {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.debug_list().entries(self.entries()).finish()
}
}
}
let entry = ffi::X509_NAME_get_entry(self.name.as_ptr(), self.loc);
- assert!(!entry.is_null());
- Some(X509NameEntryRef::from_ptr(entry))
+ Some(X509NameEntryRef::from_const_ptr_opt(entry).expect("entry must not be null"))
}
}
}
}
impl fmt::Debug for X509NameEntryRef {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_fmt(format_args!("{:?} = {:?}", self.object(), self.data()))
}
}
pub fn subject_name(&self) -> &X509NameRef {
unsafe {
let name = X509_REQ_get_subject_name(self.as_ptr());
- assert!(!name.is_null());
- X509NameRef::from_ptr(name)
+ X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null")
}
}
pub struct X509VerifyResult(c_int);
impl fmt::Debug for X509VerifyResult {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("X509VerifyResult")
.field("code", &self.0)
.field("error", &self.error_string())
}
impl fmt::Display for X509VerifyResult {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str(self.error_string())
}
}
}
impl fmt::Debug for GeneralNameRef {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(email) = self.email() {
formatter.write_str(email)
} else if let Some(dnsname) = self.dnsname() {
type StackType = ffi::stack_st_GENERAL_NAME;
}
+foreign_type_and_impl_send_sync! {
+ type CType = ffi::ACCESS_DESCRIPTION;
+ fn drop = ffi::ACCESS_DESCRIPTION_free;
+
+ /// `AccessDescription` of certificate authority information.
+ pub struct AccessDescription;
+ /// Reference to `AccessDescription`.
+ pub struct AccessDescriptionRef;
+}
+
+impl AccessDescriptionRef {
+ /// Returns the access method OID.
+ pub fn method(&self) -> &Asn1ObjectRef {
+ unsafe { Asn1ObjectRef::from_ptr((*self.as_ptr()).method) }
+ }
+
+ // Returns the access location.
+ pub fn location(&self) -> &GeneralNameRef {
+ unsafe { GeneralNameRef::from_ptr((*self.as_ptr()).location) }
+ }
+}
+
+impl Stackable for AccessDescription {
+ type StackType = ffi::stack_st_ACCESS_DESCRIPTION;
+}
+
foreign_type_and_impl_send_sync! {
type CType = ffi::X509_ALGOR;
fn drop = ffi::X509_ALGOR_free;
unsafe {
let mut oid = ptr::null();
X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr());
- assert!(!oid.is_null());
- Asn1ObjectRef::from_ptr(oid as *mut _)
+ Asn1ObjectRef::from_const_ptr_opt(oid).expect("algorithm oid must not be null")
}
}
}
pub fn x509(&self) -> Option<&X509Ref> {
unsafe {
let ptr = X509_OBJECT_get0_X509(self.as_ptr());
- if ptr.is_null() {
- None
- } else {
- Some(X509Ref::from_ptr(ptr))
- }
+ X509Ref::from_const_ptr_opt(ptr)
}
}
}