| //! Security Policies support. |
| #[cfg(any(feature = "OSX_10_9", target_os = "ios"))] |
| use core_foundation::base::CFOptionFlags; |
| use core_foundation::base::TCFType; |
| use core_foundation::string::CFString; |
| #[cfg(any(feature = "OSX_10_9", target_os = "ios"))] |
| use security_framework_sys::base::errSecParam; |
| use security_framework_sys::base::SecPolicyRef; |
| use security_framework_sys::policy::*; |
| use std::fmt; |
| use std::ptr; |
| |
| use crate::secure_transport::SslProtocolSide; |
| #[cfg(any(feature = "OSX_10_9", target_os = "ios"))] |
| use crate::Error; |
| |
| declare_TCFType! { |
| /// A type representing a certificate validation policy. |
| SecPolicy, SecPolicyRef |
| } |
| impl_TCFType!(SecPolicy, SecPolicyRef, SecPolicyGetTypeID); |
| |
| unsafe impl Sync for SecPolicy {} |
| unsafe impl Send for SecPolicy {} |
| |
| impl fmt::Debug for SecPolicy { |
| #[cold] |
| fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
| fmt.debug_struct("SecPolicy").finish() |
| } |
| } |
| |
| #[cfg(any(feature = "OSX_10_9", target_os = "ios"))] |
| bitflags::bitflags! { |
| /// The flags used to specify revocation policy options. |
| pub struct RevocationPolicy: CFOptionFlags { |
| /// Perform revocation checking using OCSP (Online Certificate Status Protocol). |
| const OCSP_METHOD = kSecRevocationOCSPMethod; |
| /// Perform revocation checking using the CRL (Certification Revocation List) method. |
| const CRL_METHOD = kSecRevocationCRLMethod; |
| /// Prefer CRL revocation checking over OCSP; by default, OCSP is preferred. |
| const PREFER_CRL = kSecRevocationPreferCRL; |
| /// Require a positive response to pass the policy. |
| const REQUIRE_POSITIVE_RESPONSE = kSecRevocationRequirePositiveResponse; |
| /// Consult only locally cached replies; do not use network access. |
| const NETWORK_ACCESS_DISABLED = kSecRevocationNetworkAccessDisabled; |
| /// Perform either OCSP or CRL checking. |
| const USE_ANY_METHOD_AVAILABLE = kSecRevocationUseAnyAvailableMethod; |
| } |
| } |
| |
| impl SecPolicy { |
| /// Creates a `SecPolicy` for evaluating SSL certificate chains. |
| /// |
| /// The side which you are evaluating should be provided (i.e. pass `SslSslProtocolSide::SERVER` if |
| /// you are a client looking to validate a server's certificate chain). |
| pub fn create_ssl(protocol_side: SslProtocolSide, hostname: Option<&str>) -> Self { |
| let hostname = hostname.map(CFString::new); |
| let hostname = hostname |
| .as_ref() |
| .map(|s| s.as_concrete_TypeRef()) |
| .unwrap_or(ptr::null_mut()); |
| let is_server = protocol_side == SslProtocolSide::SERVER; |
| unsafe { |
| let policy = SecPolicyCreateSSL(is_server as _, hostname); |
| Self::wrap_under_create_rule(policy) |
| } |
| } |
| |
| #[cfg(any(feature = "OSX_10_9", target_os = "ios"))] |
| /// Creates a `SecPolicy` for checking revocation of certificates. |
| /// |
| /// If you do not specify this policy creating a `SecTrust` object, the system defaults |
| /// will be used during evaluation. |
| pub fn create_revocation(options: RevocationPolicy) -> crate::Result<Self> { |
| let policy = unsafe { SecPolicyCreateRevocation(options.bits()) }; |
| |
| if policy.is_null() { |
| Err(Error::from_code(errSecParam)) |
| } else { |
| Ok(unsafe { Self::wrap_under_create_rule(policy) }) |
| } |
| } |
| |
| /// Returns a policy object for the default X.509 policy. |
| #[must_use] |
| pub fn create_x509() -> Self { |
| unsafe { |
| let policy = SecPolicyCreateBasicX509(); |
| Self::wrap_under_create_rule(policy) |
| } |
| } |
| } |
| |
| #[cfg(test)] |
| mod test { |
| use crate::policy::SecPolicy; |
| use crate::secure_transport::SslProtocolSide; |
| |
| #[test] |
| fn create_ssl() { |
| SecPolicy::create_ssl(SslProtocolSide::SERVER, Some("certifi.org")); |
| } |
| } |