summaryrefslogtreecommitdiff
path: root/vendor/security-framework/src/trust_settings.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/security-framework/src/trust_settings.rs')
-rw-r--r--vendor/security-framework/src/trust_settings.rs305
1 files changed, 0 insertions, 305 deletions
diff --git a/vendor/security-framework/src/trust_settings.rs b/vendor/security-framework/src/trust_settings.rs
deleted file mode 100644
index 8ccdedc2..00000000
--- a/vendor/security-framework/src/trust_settings.rs
+++ /dev/null
@@ -1,305 +0,0 @@
-//! Querying trust settings.
-
-use core_foundation::array::{CFArray, CFArrayRef};
-use core_foundation::base::{CFIndex, TCFType};
-use core_foundation::dictionary::CFDictionary;
-use core_foundation::number::CFNumber;
-use core_foundation::string::CFString;
-
-use core_foundation_sys::base::CFTypeRef;
-use security_framework_sys::base::errSecNoTrustSettings;
-use security_framework_sys::base::errSecSuccess;
-use security_framework_sys::trust_settings::*;
-
-use std::ptr;
-
-use crate::base::Error;
-use crate::base::Result;
-use crate::certificate::SecCertificate;
-use crate::cvt;
-
-/// Which set of trust settings to query
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-#[repr(u32)]
-pub enum Domain {
- /// Per-user trust settings
- User = kSecTrustSettingsDomainUser,
- /// Locally administered, system-wide trust settings
- Admin = kSecTrustSettingsDomainAdmin,
- /// System trust settings
- System = kSecTrustSettingsDomainSystem,
-}
-
-impl From<Domain> for SecTrustSettingsDomain {
- #[inline]
- fn from(domain: Domain) -> SecTrustSettingsDomain {
- match domain {
- Domain::User => kSecTrustSettingsDomainUser,
- Domain::Admin => kSecTrustSettingsDomainAdmin,
- Domain::System => kSecTrustSettingsDomainSystem,
- }
- }
-}
-
-/// Trust settings for a specific certificate in a specific domain
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum TrustSettingsForCertificate {
- /// Not used
- Invalid,
-
- /// This is a root certificate and is trusted, either explicitly or
- /// implicitly.
- TrustRoot,
-
- /// This is a non-root certificate but is explicitly trusted.
- TrustAsRoot,
-
- /// Cert is explicitly distrusted.
- Deny,
-
- /// Neither trusted nor distrusted.
- Unspecified,
-}
-
-impl TrustSettingsForCertificate {
- /// Create from `kSecTrustSettingsResult*` constant
- fn new(value: i64) -> Self {
- if value < 0 || value > i64::from(u32::max_value()) {
- return Self::Invalid;
- }
- match value as u32 {
- kSecTrustSettingsResultTrustRoot => Self::TrustRoot,
- kSecTrustSettingsResultTrustAsRoot => Self::TrustAsRoot,
- kSecTrustSettingsResultDeny => Self::Deny,
- kSecTrustSettingsResultUnspecified => Self::Unspecified,
- _ => Self::Invalid,
- }
- }
-}
-
-/// Allows access to the certificates and their trust settings in a given domain.
-pub struct TrustSettings {
- domain: Domain,
-}
-
-impl TrustSettings {
- /// Create a new `TrustSettings` for the given domain.
- ///
- /// You can call `iter()` to discover the certificates with settings in this domain.
- ///
- /// Then you can call `tls_trust_settings_for_certificate()` with a given certificate
- /// to learn what the aggregate trust setting for that certificate within this domain.
- #[inline(always)]
- #[must_use]
- pub fn new(domain: Domain) -> Self {
- Self { domain }
- }
-
- /// Create an iterator over the certificates with settings in this domain.
- /// This produces an empty iterator if there are no such certificates.
- pub fn iter(&self) -> Result<TrustSettingsIter> {
- let array = unsafe {
- let mut array_ptr: CFArrayRef = ptr::null_mut();
-
- // SecTrustSettingsCopyCertificates returns errSecNoTrustSettings
- // if no items have trust settings in the given domain. We map
- // that to an empty TrustSettings iterator.
- match SecTrustSettingsCopyCertificates(self.domain.into(), &mut array_ptr) {
- errSecNoTrustSettings => CFArray::from_CFTypes(&[]),
- errSecSuccess => CFArray::<SecCertificate>::wrap_under_create_rule(array_ptr),
- err => return Err(Error::from_code(err)),
- }
- };
-
- Ok(TrustSettingsIter { index: 0, array })
- }
-
- ///set trust settings to ""always trust this root certificate regardless of use.".
- /// Sets the trust settings for the provided certificate to "always trust this root certificate
- /// regardless of use."
- ///
- /// This method configures the trust settings for the specified certificate, indicating that it should
- /// always be trusted as a TLS root certificate, regardless of its usage.
- ///
- /// If successful, the trust settings are updated for the certificate in the given domain. If the
- /// certificate had no previous trust settings in the domain, new trust settings are created. If the
- /// certificate had existing trust settings, they are replaced with the new settings.
- ///
- /// It is not possible to modify per-user trust settings when not running in a GUI
- /// environment, if you try it will return error `2070: errSecInternalComponent`
- #[cfg(target_os="macos")]
- pub fn set_trust_settings_always(&self, cert: &SecCertificate) -> Result<()> {
- let domain = self.domain;
- let trust_settings: CFTypeRef = ptr::null_mut();
- cvt(unsafe {
- SecTrustSettingsSetTrustSettings(
- cert.as_CFTypeRef() as *mut _,
- domain.into(),
- trust_settings,
- )
- })
- }
-
- /// Returns the aggregate trust setting for the given certificate.
- ///
- /// This tells you whether the certificate should be trusted as a TLS
- /// root certificate.
- ///
- /// If the certificate has no trust settings in the given domain, the
- /// `errSecItemNotFound` error is returned.
- ///
- /// If the certificate has no specific trust settings for TLS in the
- /// given domain `None` is returned.
- ///
- /// Otherwise, the specific trust settings are aggregated and returned.
- pub fn tls_trust_settings_for_certificate(&self, cert: &SecCertificate)
- -> Result<Option<TrustSettingsForCertificate>> {
- let trust_settings = unsafe {
- let mut array_ptr: CFArrayRef = ptr::null_mut();
- let cert_ptr = cert.as_CFTypeRef() as *mut _;
- cvt(SecTrustSettingsCopyTrustSettings(cert_ptr,
- self.domain.into(),
- &mut array_ptr))?;
- CFArray::<CFDictionary>::wrap_under_create_rule(array_ptr)
- };
-
- for settings in trust_settings.iter() {
- // Reject settings for non-SSL policies
- let is_not_ssl_policy = {
- let policy_name_key = CFString::from_static_string("kSecTrustSettingsPolicyName");
- let ssl_policy_name = CFString::from_static_string("sslServer");
-
- let maybe_name: Option<CFString> = settings
- .find(policy_name_key.as_CFTypeRef().cast())
- .map(|name| unsafe { CFString::wrap_under_get_rule((*name).cast()) });
-
- matches!(maybe_name, Some(ref name) if name != &ssl_policy_name)
- };
-
- if is_not_ssl_policy {
- continue;
- }
-
- // Evaluate "effective trust settings" for this usage constraint.
- let maybe_trust_result = {
- let settings_result_key = CFString::from_static_string("kSecTrustSettingsResult");
- settings
- .find(settings_result_key.as_CFTypeRef().cast())
- .map(|num| unsafe { CFNumber::wrap_under_get_rule((*num).cast()) })
- .and_then(|num| num.to_i64())
- };
-
- // "Note that an empty Trust Settings array means "always trust this cert,
- // with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot"."
- let trust_result = TrustSettingsForCertificate::new(maybe_trust_result
- .unwrap_or_else(|| i64::from(kSecTrustSettingsResultTrustRoot)));
-
- match trust_result {
- TrustSettingsForCertificate::Unspecified |
- TrustSettingsForCertificate::Invalid => { continue; },
- _ => return Ok(Some(trust_result)),
- }
- }
-
- // There were no more specific settings. This might mean the certificate
- // is to be trusted anyway (since, eg, it's in system store), but leave
- // the caller to make this decision.
- Ok(None)
- }
-}
-
-/// Iterator over certificates.
-pub struct TrustSettingsIter {
- array: CFArray<SecCertificate>,
- index: CFIndex,
-}
-
-impl Iterator for TrustSettingsIter {
- type Item = SecCertificate;
-
- #[inline]
- fn next(&mut self) -> Option<Self::Item> {
- if self.index >= self.array.len() {
- None
- } else {
- let cert = self.array.get(self.index).unwrap();
- self.index += 1;
- Some(cert.clone())
- }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let left = (self.array.len() as usize).saturating_sub(self.index as usize);
- (left, Some(left))
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use crate::test::certificate;
-
- fn list_for_domain(domain: Domain) {
- println!("--- domain: {domain:?}");
- let ts = TrustSettings::new(domain);
- let iterator = ts.iter().unwrap();
-
- for (i, cert) in iterator.enumerate() {
- println!("cert({i:?}) = {cert:?}");
- println!(" settings = {:?}", ts.tls_trust_settings_for_certificate(&cert));
- }
- println!("---");
- }
-
- #[test]
- fn list_for_user() {
- list_for_domain(Domain::User);
- }
-
- #[test]
- fn list_for_system() {
- list_for_domain(Domain::System);
- }
-
- #[test]
- fn list_for_admin() {
- list_for_domain(Domain::Admin);
- }
-
- #[test]
- fn test_system_certs_are_present() {
- let system = TrustSettings::new(Domain::System).iter().unwrap().count();
-
- // 168 at the time of writing
- assert!(system > 100);
- }
-
- #[test]
- fn test_isrg_root_exists_and_is_trusted() {
- let ts = TrustSettings::new(Domain::System);
- assert_eq!(
- ts.iter()
- .unwrap()
- .find(|cert| cert.subject_summary() == "ISRG Root X1")
- .and_then(|cert| ts.tls_trust_settings_for_certificate(&cert).unwrap()),
- None
- );
- // ^ this is a case where None means "always trust", according to Apple docs:
- //
- // "Note that an empty Trust Settings array means "always trust this cert,
- // with a resulting kSecTrustSettingsResult of kSecTrustSettingsResultTrustRoot"."
- }
-
- #[test]
- fn test_unknown_cert_is_not_trusted() {
- let ts = TrustSettings::new(Domain::System);
- let cert = certificate();
- assert_eq!(ts.tls_trust_settings_for_certificate(&cert)
- .err()
- .unwrap()
- .message(),
- Some("The specified item could not be found in the keychain.".into()));
- }
-}
-