]> git.proxmox.com Git - cargo.git/blobdiff - vendor/openssl/src/x509/mod.rs
New upstream version 0.52.0
[cargo.git] / vendor / openssl / src / x509 / mod.rs
index 39190b7ab04f67254ebe79ffe6b5ca2c4981d9cd..8df2818a5ee2040757a4dd01df5e4fa0800d8cd5 100644 (file)
@@ -7,7 +7,7 @@
 //! 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;
@@ -20,18 +20,21 @@ use std::ptr;
 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;
@@ -181,11 +184,7 @@ impl X509StoreContextRef {
     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)
         }
     }
 
@@ -393,11 +392,17 @@ 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("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`].
@@ -406,8 +411,7 @@ impl X509Ref {
     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")
         }
     }
 
@@ -424,11 +428,7 @@ impl X509Ref {
                 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 _)
         }
     }
 
@@ -445,11 +445,25 @@ impl X509Ref {
                 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 _)
         }
     }
 
@@ -493,8 +507,7 @@ impl X509Ref {
     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")
         }
     }
 
@@ -502,8 +515,7 @@ impl X509Ref {
     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")
         }
     }
 
@@ -512,8 +524,7 @@ impl X509Ref {
         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")
         }
     }
 
@@ -522,8 +533,8 @@ impl X509Ref {
         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")
         }
     }
 
@@ -541,6 +552,20 @@ impl X509Ref {
         }
     }
 
+    /// 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)
@@ -566,8 +591,7 @@ impl X509Ref {
     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")
         }
     }
 
@@ -672,7 +696,7 @@ impl Clone for X509 {
 }
 
 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(),
@@ -743,7 +767,7 @@ impl X509Extension {
     /// 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> {
@@ -769,7 +793,7 @@ impl X509Extension {
     /// 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> {
@@ -820,6 +844,33 @@ impl X509NameBuilder {
         }
     }
 
+    /// 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`].
@@ -841,6 +892,32 @@ impl X509NameBuilder {
         }
     }
 
+    /// 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
@@ -897,7 +974,7 @@ impl X509NameRef {
 }
 
 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()
     }
 }
@@ -933,9 +1010,8 @@ impl<'a> Iterator for X509NameEntries<'a> {
             }
 
             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"))
         }
     }
 }
@@ -978,7 +1054,7 @@ impl X509NameEntryRef {
 }
 
 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()))
     }
 }
@@ -1179,8 +1255,7 @@ impl X509ReqRef {
     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")
         }
     }
 
@@ -1226,7 +1301,7 @@ impl X509ReqRef {
 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())
@@ -1235,7 +1310,7 @@ impl fmt::Debug for X509VerifyResult {
 }
 
 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())
     }
 }
@@ -1340,7 +1415,7 @@ impl GeneralNameRef {
 }
 
 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() {
@@ -1360,6 +1435,32 @@ impl Stackable for GeneralName {
     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;
@@ -1376,8 +1477,7 @@ impl X509AlgorithmRef {
         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")
         }
     }
 }
@@ -1396,11 +1496,7 @@ impl X509ObjectRef {
     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)
         }
     }
 }