diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-15 16:37:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-17 16:30:22 -0600 |
| commit | 45df4d0d9b577fecee798d672695fe24ff57fb1b (patch) | |
| tree | 1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/security-framework/src/os | |
| parent | f94f79608393d4ab127db63cc41668445ef6b243 (diff) | |
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based
authorization system with SpiceDB's relation-based authorization.
Key changes:
- Migrate from Rust to Go implementation
- Replace Cedar policies with SpiceDB schema and relationships
- Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks
- Update build system and dependencies for Go ecosystem
- Maintain Envoy integration for external authorization
This change enables more flexible permission modeling through SpiceDB's
Google Zanzibar inspired relation-based system, supporting complex
hierarchical permissions that were difficult to express in Cedar.
Breaking change: Existing Cedar policies and Rust-based configuration
will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/security-framework/src/os')
17 files changed, 0 insertions, 3350 deletions
diff --git a/vendor/security-framework/src/os/macos/access.rs b/vendor/security-framework/src/os/macos/access.rs deleted file mode 100644 index 1c41d85d..00000000 --- a/vendor/security-framework/src/os/macos/access.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! Access functionality. - -use core_foundation::base::TCFType; -use security_framework_sys::access::SecAccessGetTypeID; -use security_framework_sys::base::SecAccessRef; - -declare_TCFType! { - /// A type representing access settings. - SecAccess, SecAccessRef -} -impl_TCFType!(SecAccess, SecAccessRef, SecAccessGetTypeID); - -unsafe impl Sync for SecAccess {} -unsafe impl Send for SecAccess {} diff --git a/vendor/security-framework/src/os/macos/certificate.rs b/vendor/security-framework/src/os/macos/certificate.rs deleted file mode 100644 index b50ee52d..00000000 --- a/vendor/security-framework/src/os/macos/certificate.rs +++ /dev/null @@ -1,267 +0,0 @@ -//! OSX specific extensions to certificate functionality. - -use core_foundation::array::{CFArray, CFArrayIterator}; -use core_foundation::base::TCFType; -use core_foundation::base::ToVoid; -use core_foundation::data::CFData; -use core_foundation::dictionary::CFDictionary; -use core_foundation::error::CFError; -use core_foundation::string::CFString; -use security_framework_sys::certificate::*; -use std::os::raw::c_void; -use std::ptr; - -use crate::base::Error; -use crate::certificate::SecCertificate; -use crate::cvt; -use crate::key::SecKey; -use crate::os::macos::certificate_oids::CertificateOid; -use crate::os::macos::digest_transform::{Builder, DigestType}; - -/// An extension trait adding OSX specific functionality to `SecCertificate`. -pub trait SecCertificateExt { - /// Returns the common name associated with the certificate. - fn common_name(&self) -> Result<String, Error>; - - /// Returns the public key associated with the certificate. - #[cfg_attr(not(feature = "OSX_10_14"), deprecated(note = "Uses deprecated SecCertificateCopyPublicKey. Enable OSX_10_14 feature to avoid it"))] - fn public_key(&self) -> Result<SecKey, Error>; - - /// Returns the set of properties associated with the certificate. - /// - /// The `keys` argument can optionally be used to filter the properties loaded to an explicit - /// subset. - fn properties(&self, keys: Option<&[CertificateOid]>) - -> Result<CertificateProperties, CFError>; - - /// Returns the SHA-256 fingerprint of the certificate. - fn fingerprint(&self) -> Result<[u8; 32], CFError> { unimplemented!() } -} - -impl SecCertificateExt for SecCertificate { - fn common_name(&self) -> Result<String, Error> { - unsafe { - let mut string = ptr::null(); - cvt(SecCertificateCopyCommonName( - self.as_concrete_TypeRef(), - &mut string, - ))?; - Ok(CFString::wrap_under_create_rule(string).to_string()) - } - } - - #[cfg(feature = "OSX_10_14")] - fn public_key(&self) -> Result<SecKey, Error> { - unsafe { - let key = SecCertificateCopyKey(self.as_concrete_TypeRef()); - if key.is_null() { - return Err(Error::from_code(-26275)); - } - Ok(SecKey::wrap_under_create_rule(key)) - } - } - - #[cfg(not(feature = "OSX_10_14"))] - fn public_key(&self) -> Result<SecKey, Error> { - #[allow(deprecated)] - unsafe { - let mut key = ptr::null_mut(); - cvt(SecCertificateCopyPublicKey( - self.as_concrete_TypeRef(), - &mut key, - ))?; - Ok(SecKey::wrap_under_create_rule(key)) - } - } - - fn properties( - &self, - keys: Option<&[CertificateOid]>, - ) -> Result<CertificateProperties, CFError> { - unsafe { - let keys = keys.map(|oids| { - let oids = oids.iter().map(|oid| oid.to_str()).collect::<Vec<_>>(); - CFArray::from_CFTypes(&oids) - }); - - let keys = match keys { - Some(ref keys) => keys.as_concrete_TypeRef(), - None => ptr::null_mut(), - }; - - let mut error = ptr::null_mut(); - - let dictionary = SecCertificateCopyValues(self.as_concrete_TypeRef(), keys, &mut error); - - if error.is_null() { - Ok(CertificateProperties(CFDictionary::wrap_under_create_rule( - dictionary, - ))) - } else { - Err(CFError::wrap_under_create_rule(error)) - } - } - } - - /// Returns the SHA-256 fingerprint of the certificate. - fn fingerprint(&self) -> Result<[u8; 32], CFError> { - let data = CFData::from_buffer(&self.to_der()); - let hash = Builder::new() - .type_(DigestType::sha2()) - .length(256) - .execute(&data)?; - Ok(hash.bytes().try_into().unwrap()) - } -} - -/// Properties associated with a certificate. -pub struct CertificateProperties(CFDictionary); - -impl CertificateProperties { - /// Retrieves a specific property identified by its OID. - #[must_use] pub fn get(&self, oid: CertificateOid) -> Option<CertificateProperty> { - unsafe { - self.0.find(oid.as_ptr().cast::<c_void>()).map(|value| { - CertificateProperty(CFDictionary::wrap_under_get_rule(*value as *mut _)) - }) - } - } -} - -/// A property associated with a certificate. -pub struct CertificateProperty(CFDictionary); - -impl CertificateProperty { - /// Returns the label of this property. - #[must_use] - pub fn label(&self) -> CFString { - unsafe { - CFString::wrap_under_get_rule((*self.0.get(kSecPropertyKeyLabel.to_void())).cast()) - } - } - - /// Returns an enum of the underlying data for this property. - #[must_use] - pub fn get(&self) -> PropertyType { - unsafe { - let type_ = - CFString::wrap_under_get_rule(*self.0.get(kSecPropertyKeyType.to_void()) as *mut _); - let value = self.0.get(kSecPropertyKeyValue.to_void()); - - if type_ == CFString::wrap_under_get_rule(kSecPropertyTypeSection) { - PropertyType::Section(PropertySection(CFArray::wrap_under_get_rule( - (*value).cast(), - ))) - } else if type_ == CFString::wrap_under_get_rule(kSecPropertyTypeString) { - PropertyType::String(CFString::wrap_under_get_rule((*value).cast())) - } else { - PropertyType::__Unknown - } - } - } -} - -/// A "section" property. -/// -/// Sections are sequences of other properties. -pub struct PropertySection(CFArray<CFDictionary>); - -impl PropertySection { - /// Returns an iterator over the properties in this section. - #[inline(always)] - #[must_use] - pub fn iter(&self) -> PropertySectionIter<'_> { - PropertySectionIter(self.0.iter()) - } -} - -impl<'a> IntoIterator for &'a PropertySection { - type IntoIter = PropertySectionIter<'a>; - type Item = CertificateProperty; - - #[inline(always)] - fn into_iter(self) -> PropertySectionIter<'a> { - self.iter() - } -} - -/// An iterator over the properties in a section. -pub struct PropertySectionIter<'a>(CFArrayIterator<'a, CFDictionary>); - -impl<'a> Iterator for PropertySectionIter<'a> { - type Item = CertificateProperty; - - #[inline] - fn next(&mut self) -> Option<CertificateProperty> { - self.0.next().map(|t| CertificateProperty(t.clone())) - } - - #[inline(always)] - fn size_hint(&self) -> (usize, Option<usize>) { - self.0.size_hint() - } -} - -/// An enum of the various types of properties. -pub enum PropertyType { - /// A section. - Section(PropertySection), - /// A string. - String(CFString), - #[doc(hidden)] - __Unknown, -} - -#[cfg(test)] -mod test { - use super::*; - use crate::test::certificate; - use std::collections::HashMap; - - #[test] - fn common_name() { - let certificate = certificate(); - assert_eq!("foobar.com", p!(certificate.common_name())); - } - - #[test] - #[allow(deprecated)] - fn public_key() { - let certificate = certificate(); - p!(certificate.public_key()); - } - - #[test] - fn fingerprint() { - let certificate = certificate(); - let fingerprint = p!(certificate.fingerprint()); - assert_eq!( - "af9dd180a326ae08b37e6398f9262f8b9d4c55674a233a7c84975024f873655d", - hex::encode(fingerprint) - ); - } - - #[test] - fn signature_algorithm() { - let certificate = certificate(); - let properties = certificate - .properties(Some(&[CertificateOid::x509_v1_signature_algorithm()])) - .unwrap(); - let value = properties - .get(CertificateOid::x509_v1_signature_algorithm()) - .unwrap(); - let section = match value.get() { - PropertyType::Section(section) => section, - _ => panic!(), - }; - let properties = section - .iter() - .map(|p| (p.label().to_string(), p.get())) - .collect::<HashMap<_, _>>(); - let algorithm = match properties["Algorithm"] { - PropertyType::String(ref s) => s.to_string(), - _ => panic!(), - }; - assert_eq!(algorithm, "1.2.840.113549.1.1.5"); - } -} diff --git a/vendor/security-framework/src/os/macos/certificate_oids.rs b/vendor/security-framework/src/os/macos/certificate_oids.rs deleted file mode 100644 index d820afe4..00000000 --- a/vendor/security-framework/src/os/macos/certificate_oids.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! OIDs associated with certificate properties. -use core_foundation::base::TCFType; -use core_foundation::string::CFString; -use core_foundation_sys::string::CFStringRef; -use security_framework_sys::certificate_oids::kSecOIDX509V1SignatureAlgorithm; - -/// An identifier of a property of a certificate. -#[derive(Copy, Clone)] -pub struct CertificateOid(CFStringRef); - -#[allow(missing_docs)] -impl CertificateOid { - #[inline(always)] - #[must_use] - pub fn x509_v1_signature_algorithm() -> Self { - unsafe { Self(kSecOIDX509V1SignatureAlgorithm) } - } - - /// Returns the underlying raw pointer corresponding to this OID. - #[inline(always)] - #[must_use] - pub fn as_ptr(&self) -> CFStringRef { - self.0 - } - - /// Returns the string representation of the OID. - #[inline] - #[must_use] - pub fn to_str(&self) -> CFString { - unsafe { CFString::wrap_under_get_rule(self.0) } - } -} diff --git a/vendor/security-framework/src/os/macos/code_signing.rs b/vendor/security-framework/src/os/macos/code_signing.rs deleted file mode 100644 index b42917c1..00000000 --- a/vendor/security-framework/src/os/macos/code_signing.rs +++ /dev/null @@ -1,486 +0,0 @@ -//! Code signing services. - -use std::{fmt::Debug, mem::MaybeUninit, str::FromStr}; - -use core_foundation::{ - base::{TCFType, TCFTypeRef, ToVoid}, - data::CFDataRef, - dictionary::CFMutableDictionary, - number::CFNumber, - string::{CFString, CFStringRef}, - url::CFURL, -}; -use libc::pid_t; -use security_framework_sys::code_signing::{ - kSecCSBasicValidateOnly, kSecCSCheckAllArchitectures, kSecCSCheckGatekeeperArchitectures, - kSecCSCheckNestedCode, kSecCSCheckTrustedAnchors, kSecCSConsiderExpiration, - kSecCSDoNotValidateExecutable, kSecCSDoNotValidateResources, kSecCSEnforceRevocationChecks, - kSecCSFullReport, kSecCSNoNetworkAccess, kSecCSQuickCheck, kSecCSReportProgress, - kSecCSRestrictSidebandData, kSecCSRestrictSymlinks, kSecCSRestrictToAppLike, - kSecCSSingleThreaded, kSecCSStrictValidate, kSecCSUseSoftwareSigningCert, kSecCSValidatePEH, - kSecGuestAttributeAudit, kSecGuestAttributePid, SecCodeCheckValidity, - SecCodeCopyGuestWithAttributes, SecCodeCopyPath, SecCodeCopySelf, SecCodeGetTypeID, SecCodeRef, - SecRequirementCreateWithString, SecRequirementGetTypeID, SecRequirementRef, - SecStaticCodeCheckValidity, SecStaticCodeCreateWithPath, SecStaticCodeGetTypeID, - SecStaticCodeRef, -}; - -use crate::{cvt, Result}; - -bitflags::bitflags! { - - /// Values that can be used in the flags parameter to most code signing - /// functions. - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] - pub struct Flags: u32 { - /// Use the default behaviour. - const NONE = 0; - - /// For multi-architecture (universal) Mach-O programs, validate all - /// architectures included. - const CHECK_ALL_ARCHITECTURES = kSecCSCheckAllArchitectures; - - /// Do not validate the contents of the main executable. - const DO_NOT_VALIDATE_EXECUTABLE = kSecCSDoNotValidateExecutable; - - /// Do not validate the presence and contents of all bundle resources - /// if any. - const DO_NOT_VALIDATE_RESOURCES = kSecCSDoNotValidateResources; - - /// Do not validate either the main executable or the bundle resources, - /// if any. - const BASIC_VALIDATE_ONLY = kSecCSBasicValidateOnly; - - /// For code in bundle form, locate and recursively check embedded code. - const CHECK_NESTED_CODE = kSecCSCheckNestedCode; - - /// Perform additional checks to ensure the validity of code in bundle - /// form. - const STRICT_VALIDATE = kSecCSStrictValidate; - - /// Apple have not documented this flag. - const FULL_REPORT = kSecCSFullReport; - - /// Apple have not documented this flag. - const CHECK_GATEKEEPER_ARCHITECTURES = kSecCSCheckGatekeeperArchitectures; - - /// Apple have not documented this flag. - const RESTRICT_SYMLINKS = kSecCSRestrictSymlinks; - - /// Apple have not documented this flag. - const RESTRICT_TO_APP_LIKE = kSecCSRestrictToAppLike; - - /// Apple have not documented this flag. - const RESTRICT_SIDEBAND_DATA = kSecCSRestrictSidebandData; - - /// Apple have not documented this flag. - const USE_SOFTWARE_SIGNING_CERT = kSecCSUseSoftwareSigningCert; - - /// Apple have not documented this flag. - const VALIDATE_PEH = kSecCSValidatePEH; - - /// Apple have not documented this flag. - const SINGLE_THREADED = kSecCSSingleThreaded; - - /// Apple have not documented this flag. - const QUICK_CHECK = kSecCSQuickCheck; - - /// Apple have not documented this flag. - const CHECK_TRUSTED_ANCHORS = kSecCSCheckTrustedAnchors; - - /// Apple have not documented this flag. - const REPORT_PROGRESS = kSecCSReportProgress; - - /// Apple have not documented this flag. - const NO_NETWORK_ACCESS = kSecCSNoNetworkAccess; - - /// Apple have not documented this flag. - const ENFORCE_REVOCATION_CHECKS = kSecCSEnforceRevocationChecks; - - /// Apple have not documented this flag. - const CONSIDER_EXPIRATION = kSecCSConsiderExpiration; - } -} - -impl Default for Flags { - #[inline(always)] - fn default() -> Self { - Self::NONE - } -} - -/// A helper to create guest attributes, which are normally passed as a -/// `CFDictionary` with varying types. -pub struct GuestAttributes { - inner: CFMutableDictionary, -} - -impl GuestAttributes { - // Not implemented: - // - architecture - // - canonical - // - dynamic code - // - dynamic code info plist - // - hash - // - mach port - // - sub-architecture - - /// Creates a new, empty `GuestAttributes`. You must add values to it in - /// order for it to be of any use. - #[must_use] - pub fn new() -> Self { - Self { - inner: CFMutableDictionary::new(), - } - } - - /// The guest's audit token. - pub fn set_audit_token(&mut self, token: CFDataRef) { - let key = unsafe { CFString::wrap_under_get_rule(kSecGuestAttributeAudit) }; - self.inner.add(&key.as_CFTypeRef(), &token.to_void()); - } - - /// The guest's pid. - pub fn set_pid(&mut self, pid: pid_t) { - let key = unsafe { CFString::wrap_under_get_rule(kSecGuestAttributePid) }; - let pid = CFNumber::from(pid); - self.inner.add(&key.as_CFTypeRef(), &pid.as_CFTypeRef()); - } - - /// Support for arbirtary guest attributes. - pub fn set_other<V: ToVoid<V>>(&mut self, key: CFStringRef, value: V) { - self.inner.add(&key.as_void_ptr(), &value.to_void()); - } -} - -impl Default for GuestAttributes { - fn default() -> Self { - Self::new() - } -} - -declare_TCFType! { - /// A code object representing signed code running on the system. - SecRequirement, SecRequirementRef -} -impl_TCFType!(SecRequirement, SecRequirementRef, SecRequirementGetTypeID); - -impl FromStr for SecRequirement { - type Err = crate::base::Error; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - let text = CFString::new(s); - let mut requirement = MaybeUninit::uninit(); - - unsafe { - cvt(SecRequirementCreateWithString( - text.as_concrete_TypeRef(), - 0, - requirement.as_mut_ptr(), - ))?; - - Ok(Self::wrap_under_create_rule(requirement.assume_init())) - } - } -} - -declare_TCFType! { - /// A code object representing signed code running on the system. - SecCode, SecCodeRef -} -impl_TCFType!(SecCode, SecCodeRef, SecCodeGetTypeID); - -impl Debug for SecCode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("SecCode") - } -} - -impl SecCode { - /// Retrieves the code object for the code making the call. - pub fn for_self(flags: Flags) -> Result<Self> { - let mut code = MaybeUninit::uninit(); - - unsafe { - cvt(SecCodeCopySelf(flags.bits(), code.as_mut_ptr()))?; - Ok(Self::wrap_under_create_rule(code.assume_init())) - } - } - - /// Performs dynamic validation of signed code. - pub fn check_validity(&self, flags: Flags, requirement: &SecRequirement) -> Result<()> { - unsafe { - cvt(SecCodeCheckValidity( - self.as_concrete_TypeRef(), - flags.bits(), - requirement.as_concrete_TypeRef(), - )) - } - } - - /// Asks a code host to identify one of its guests given - /// the type and value of specific attributes of the guest code. - /// - /// If `host` is `None` then the code signing root of trust (currently, the - // system kernel) should be used as the code host. - pub fn copy_guest_with_attribues( - host: Option<&SecCode>, - attrs: &GuestAttributes, - flags: Flags, - ) -> Result<SecCode> { - let mut code = MaybeUninit::uninit(); - - let host = match host { - Some(host) => host.as_concrete_TypeRef(), - None => std::ptr::null_mut(), - }; - - unsafe { - cvt(SecCodeCopyGuestWithAttributes( - host, - attrs.inner.as_concrete_TypeRef(), - flags.bits(), - code.as_mut_ptr(), - ))?; - - Ok(SecCode::wrap_under_create_rule(code.assume_init())) - } - } - - /// Retrieves the location on disk of signed code, given a code or static - /// code object. - pub fn path(&self, flags: Flags) -> Result<CFURL> { - let mut url = MaybeUninit::uninit(); - - // The docs say we can pass a SecCodeRef instead of a SecStaticCodeRef. - unsafe { - cvt(SecCodeCopyPath( - self.as_CFTypeRef() as _, - flags.bits(), - url.as_mut_ptr(), - ))?; - - Ok(CFURL::wrap_under_create_rule(url.assume_init())) - } - } -} - -declare_TCFType! { - /// A static code object representing signed code on disk. - SecStaticCode, SecStaticCodeRef -} -impl_TCFType!(SecStaticCode, SecStaticCodeRef, SecStaticCodeGetTypeID); - -impl SecStaticCode { - /// Creates a static code object representing the code at a specified file - /// system path. - pub fn from_path(path: &CFURL, flags: Flags) -> Result<Self> { - let mut code = MaybeUninit::uninit(); - - unsafe { - cvt(SecStaticCodeCreateWithPath( - path.as_concrete_TypeRef(), - flags.bits(), - code.as_mut_ptr(), - ))?; - - Ok(Self::wrap_under_create_rule(code.assume_init())) - } - } - - /// Retrieves the location on disk of signed code, given a code or static - /// code object. - pub fn path(&self, flags: Flags) -> Result<CFURL> { - let mut url = MaybeUninit::uninit(); - - // The docs say we can pass a SecCodeRef instead of a SecStaticCodeRef. - unsafe { - cvt(SecCodeCopyPath( - self.as_concrete_TypeRef(), - flags.bits(), - url.as_mut_ptr(), - ))?; - - Ok(CFURL::wrap_under_create_rule(url.assume_init())) - } - } - - /// Performs dynamic validation of signed code. - pub fn check_validity(&self, flags: Flags, requirement: &SecRequirement) -> Result<()> { - unsafe { - cvt(SecStaticCodeCheckValidity( - self.as_concrete_TypeRef(), - flags.bits(), - requirement.as_concrete_TypeRef(), - )) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - use core_foundation::data::CFData; - use libc::{c_uint, c_void, KERN_SUCCESS}; - - #[test] - fn path_to_static_code_and_back() { - let path = CFURL::from_path("/bin/bash", false).unwrap(); - let code = SecStaticCode::from_path(&path, Flags::NONE).unwrap(); - assert_eq!(code.path(Flags::NONE).unwrap(), path); - } - - #[test] - fn self_to_path() { - let path = CFURL::from_path(std::env::current_exe().unwrap(), false).unwrap(); - let code = SecCode::for_self(Flags::NONE).unwrap(); - assert_eq!(code.path(Flags::NONE).unwrap(), path); - } - - #[test] - fn bash_is_signed_by_apple() { - let path = CFURL::from_path("/bin/bash", false).unwrap(); - let code = SecStaticCode::from_path(&path, Flags::NONE).unwrap(); - let requirement: SecRequirement = "anchor apple".parse().unwrap(); - code.check_validity(Flags::NONE, &requirement).unwrap(); - } - - #[cfg(target_arch = "aarch64")] - #[test] - fn self_is_not_signed_by_apple() { - let code = SecCode::for_self(Flags::NONE).unwrap(); - let requirement: SecRequirement = "anchor apple".parse().unwrap(); - - assert_eq!( - code.check_validity(Flags::NONE, &requirement) - .unwrap_err() - .code(), - // "code failed to satisfy specified code requirement(s)" - -67050 - ); - } - - #[cfg(not(target_arch = "aarch64"))] - #[test] - fn self_is_not_signed_by_apple() { - let code = SecCode::for_self(Flags::NONE).unwrap(); - let requirement: SecRequirement = "anchor apple".parse().unwrap(); - - assert_eq!( - code.check_validity(Flags::NONE, &requirement) - .unwrap_err() - .code(), - // "code object is not signed at all" - -67062 - ); - } - - #[test] - fn copy_kernel_guest_with_launchd_pid() { - let mut attrs = GuestAttributes::new(); - attrs.set_pid(1); - - assert_eq!( - SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE) - .unwrap() - .path(Flags::NONE) - .unwrap() - .get_string() - .to_string(), - "file:///sbin/launchd" - ); - } - - #[test] - fn copy_current_guest_with_launchd_pid() { - let host_code = SecCode::for_self(Flags::NONE).unwrap(); - - let mut attrs = GuestAttributes::new(); - attrs.set_pid(1); - - assert_eq!( - SecCode::copy_guest_with_attribues(Some(&host_code), &attrs, Flags::NONE) - .unwrap_err() - .code(), - // "host has no guest with the requested attributes" - -67065 - ); - } - - #[test] - fn copy_kernel_guest_with_unmatched_pid() { - let mut attrs = GuestAttributes::new(); - attrs.set_pid(999_999_999); - - assert_eq!( - SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE) - .unwrap_err() - .code(), - // "UNIX[No such process]" - 100003 - ); - } - - #[test] - fn copy_kernel_guest_with_current_token() { - let mut token: [u8; 32] = [0; 32]; - let mut token_len = 32u32; - - enum OpaqueTaskName {} - - extern "C" { - fn mach_task_self() -> *const OpaqueTaskName; - fn task_info( - task_name: *const OpaqueTaskName, - task_flavor: u32, - out: *mut c_void, - out_len: *mut u32, - ) -> i32; - } - - const TASK_AUDIT_TOKEN: c_uint = 15; - - let result = unsafe { - task_info( - mach_task_self(), - TASK_AUDIT_TOKEN, - token.as_mut_ptr().cast::<c_void>(), - &mut token_len, - ) - }; - - assert_eq!(result, KERN_SUCCESS); - - let token_data = CFData::from_buffer(&token); - - let mut attrs = GuestAttributes::new(); - attrs.set_audit_token(token_data.as_concrete_TypeRef()); - - assert_eq!( - SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE) - .unwrap() - .path(Flags::NONE) - .unwrap() - .to_path() - .unwrap(), - std::env::current_exe().unwrap() - ); - } - - #[test] - fn copy_kernel_guest_with_unmatched_token() { - let token: [u8; 32] = [0; 32]; - let token_data = CFData::from_buffer(&token); - - let mut attrs = GuestAttributes::new(); - attrs.set_audit_token(token_data.as_concrete_TypeRef()); - - assert_eq!( - SecCode::copy_guest_with_attribues(None, &attrs, Flags::NONE) - .unwrap_err() - .code(), - // "UNIX[No such process]" - 100003 - ); - } -} diff --git a/vendor/security-framework/src/os/macos/digest_transform.rs b/vendor/security-framework/src/os/macos/digest_transform.rs deleted file mode 100644 index c086ed1a..00000000 --- a/vendor/security-framework/src/os/macos/digest_transform.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! Digest Transform support - -use core_foundation::base::{CFIndex, TCFType}; -use core_foundation::data::CFData; -use core_foundation::error::CFError; -use core_foundation::string::CFString; -use core_foundation_sys::base::CFTypeRef; -use core_foundation_sys::data::CFDataRef; -use core_foundation_sys::string::CFStringRef; -use security_framework_sys::digest_transform::*; -use security_framework_sys::transform::kSecTransformInputAttributeName; -use std::ptr; - -use crate::os::macos::transform::SecTransform; - -#[derive(Debug, Copy, Clone)] -/// A type of digest. -pub struct DigestType(CFStringRef); - -#[allow(missing_docs)] -impl DigestType { - #[inline(always)] - #[must_use] - pub fn hmac_md5() -> Self { - unsafe { Self(kSecDigestHMACMD5) } - } - - #[inline(always)] - #[must_use] - pub fn hmac_sha1() -> Self { - unsafe { Self(kSecDigestHMACSHA1) } - } - - #[inline(always)] - #[must_use] - pub fn hmac_sha2() -> Self { - unsafe { Self(kSecDigestHMACSHA2) } - } - - #[inline(always)] - #[must_use] - pub fn md2() -> Self { - unsafe { Self(kSecDigestMD2) } - } - - #[inline(always)] - #[must_use] - pub fn md4() -> Self { - unsafe { Self(kSecDigestMD4) } - } - - #[inline(always)] - #[must_use] - pub fn md5() -> Self { - unsafe { Self(kSecDigestMD5) } - } - - #[inline(always)] - #[must_use] - pub fn sha1() -> Self { - unsafe { Self(kSecDigestSHA1) } - } - - #[inline(always)] - #[must_use] - pub fn sha2() -> Self { - unsafe { Self(kSecDigestSHA2) } - } - - #[inline(always)] - fn to_type(self) -> CFTypeRef { - self.0 as CFTypeRef - } -} - -/// A builder for digest transform operations. -pub struct Builder { - digest_type: Option<DigestType>, - digest_length: Option<CFIndex>, - hmac_key: Option<CFData>, -} - -impl Default for Builder { - #[inline(always)] - fn default() -> Self { - Self::new() - } -} - -impl Builder { - /// Returns a new builder with default settings. - #[inline(always)] - #[must_use] - pub fn new() -> Self { - Self { - digest_type: None, - digest_length: None, - hmac_key: None, - } - } - - /// Sets the type of digest to perform. - /// - /// If not set, an appropriate digest will be selected for you. - #[inline] - pub fn type_(&mut self, digest_type: DigestType) -> &mut Self { - self.digest_type = Some(digest_type); - self - } - - /// Sets the output length of the digest. - /// - /// If not set, an appropriate length will be selected for you. Some digest - /// types only support specific output lengths. - #[inline] - pub fn length(&mut self, digest_length: CFIndex) -> &mut Self { - self.digest_length = Some(digest_length); - self - } - - /// Sets the key used for HMAC digests. - /// - /// Only applies to `HmacMd5`, `HmacSha1`, and `HmacSha2` digests. - #[inline] - pub fn hmac_key(&mut self, hmac_key: CFData) -> &mut Self { - self.hmac_key = Some(hmac_key); - self - } - - /// Computes the digest of the data. - pub fn execute(&self, data: &CFData) -> Result<CFData, CFError> { - unsafe { - let digest_type = match self.digest_type { - Some(ref digest_type) => digest_type.to_type(), - None => ptr::null(), - }; - - let digest_length = self.digest_length.unwrap_or(0); - - let mut error = ptr::null_mut(); - let transform = SecDigestTransformCreate(digest_type, digest_length, &mut error); - if transform.is_null() { - return Err(CFError::wrap_under_create_rule(error)); - } - let mut transform = SecTransform::wrap_under_create_rule(transform); - - if let Some(ref hmac_key) = self.hmac_key { - let key = CFString::wrap_under_get_rule(kSecDigestHMACKeyAttribute); - transform.set_attribute(&key, hmac_key)?; - } - - let key = CFString::wrap_under_get_rule(kSecTransformInputAttributeName); - transform.set_attribute(&key, data)?; - - let result = transform.execute()?; - Ok(CFData::wrap_under_get_rule( - result.as_CFTypeRef() as CFDataRef - )) - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn md5() { - let data = CFData::from_buffer("The quick brown fox jumps over the lazy dog".as_bytes()); - let hash = Builder::new() - .type_(DigestType::md5()) - .execute(&data) - .unwrap(); - assert_eq!( - hex::encode(hash.bytes()), - "9e107d9d372bb6826bd81d3542a419d6" - ); - } - - #[test] - fn hmac_sha1() { - let data = CFData::from_buffer("The quick brown fox jumps over the lazy dog".as_bytes()); - let key = CFData::from_buffer(b"key"); - let hash = Builder::new() - .type_(DigestType::hmac_sha1()) - .hmac_key(key) - .execute(&data) - .unwrap(); - assert_eq!( - hex::encode(hash.bytes()), - "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9" - ); - } -} diff --git a/vendor/security-framework/src/os/macos/encrypt_transform.rs b/vendor/security-framework/src/os/macos/encrypt_transform.rs deleted file mode 100644 index 7b9736da..00000000 --- a/vendor/security-framework/src/os/macos/encrypt_transform.rs +++ /dev/null @@ -1,254 +0,0 @@ -//! Encryption and Decryption transform support. - -use core_foundation::base::TCFType; -use core_foundation::data::CFData; -use core_foundation::error::CFError; -use core_foundation::string::CFString; -use core_foundation_sys::data::CFDataRef; -use core_foundation_sys::string::CFStringRef; -use security_framework_sys::encrypt_transform::*; -use security_framework_sys::transform::kSecTransformInputAttributeName; -use std::ptr; - -use crate::key::SecKey; -use crate::os::macos::transform::SecTransform; - -#[derive(Debug, Copy, Clone)] -/// The padding scheme to use for encryption. -pub struct Padding(CFStringRef); - -impl Padding { - /// Do not pad. - #[inline(always)] - #[must_use] - pub fn none() -> Self { - unsafe { Self(kSecPaddingNoneKey) } - } - - /// Use PKCS#1 padding. - #[inline(always)] - #[must_use] - pub fn pkcs1() -> Self { - unsafe { Self(kSecPaddingPKCS1Key) } - } - - /// Use PKCS#5 padding. - #[inline(always)] - #[must_use] - pub fn pkcs5() -> Self { - unsafe { Self(kSecPaddingPKCS5Key) } - } - - /// Use PKCS#7 padding. - #[inline(always)] - #[must_use] - pub fn pkcs7() -> Self { - unsafe { Self(kSecPaddingPKCS7Key) } - } - - /// Use OAEP padding. - #[inline(always)] - #[must_use] - pub fn oaep() -> Self { - unsafe { Self(kSecPaddingOAEPKey) } - } - - #[inline] - fn to_str(self) -> CFString { - unsafe { CFString::wrap_under_get_rule(self.0) } - } -} - -/// The cipher mode to use. -/// -/// Only applies to AES encryption. -#[derive(Debug, Copy, Clone)] -pub struct Mode(CFStringRef); - -#[allow(missing_docs)] -impl Mode { - #[inline(always)] - #[must_use] - pub fn none() -> Self { - unsafe { Self(kSecModeNoneKey) } - } - - #[inline(always)] - #[must_use] - pub fn ecb() -> Self { - unsafe { Self(kSecModeECBKey) } - } - - #[inline(always)] - #[must_use] - pub fn cbc() -> Self { - unsafe { Self(kSecModeCBCKey) } - } - - #[inline(always)] - #[must_use] - pub fn cfb() -> Self { - unsafe { Self(kSecModeCFBKey) } - } - - #[inline(always)] - #[must_use] - pub fn ofb() -> Self { - unsafe { Self(kSecModeOFBKey) } - } - - fn to_str(self) -> CFString { - unsafe { CFString::wrap_under_get_rule(self.0) } - } -} - -/// A builder for encryption and decryption transform operations. -#[derive(Default)] -pub struct Builder { - padding: Option<Padding>, - mode: Option<Mode>, - iv: Option<CFData>, -} - -impl Builder { - /// Creates a new `Builder` with a default configuration. - #[inline(always)] - #[must_use] - pub fn new() -> Self { - Self::default() - } - - /// Selects the padding scheme to use. - /// - /// If not set, an appropriate scheme will be selected for you. - #[inline(always)] - pub fn padding(&mut self, padding: Padding) -> &mut Self { - self.padding = Some(padding); - self - } - - /// Selects the encryption mode to use. - /// - /// If not set, an appropriate mode will be selected for you. - #[inline(always)] - pub fn mode(&mut self, mode: Mode) -> &mut Self { - self.mode = Some(mode); - self - } - - /// Sets the initialization vector to use. - /// - /// If not set, an appropriate value will be supplied for you. - #[inline(always)] - pub fn iv(&mut self, iv: CFData) -> &mut Self { - self.iv = Some(iv); - self - } - - /// Encrypts data with a provided key. - pub fn encrypt(&self, key: &SecKey, data: &CFData) -> Result<CFData, CFError> { - unsafe { - let mut error = ptr::null_mut(); - let transform = SecEncryptTransformCreate(key.as_concrete_TypeRef(), &mut error); - if transform.is_null() { - return Err(CFError::wrap_under_create_rule(error)); - } - let transform = SecTransform::wrap_under_create_rule(transform); - - self.finish(transform, data) - } - } - - /// Decrypts data with a provided key. - pub fn decrypt(&self, key: &SecKey, data: &CFData) -> Result<CFData, CFError> { - unsafe { - let mut error = ptr::null_mut(); - let transform = SecDecryptTransformCreate(key.as_concrete_TypeRef(), &mut error); - if transform.is_null() { - return Err(CFError::wrap_under_create_rule(error)); - } - let transform = SecTransform::wrap_under_create_rule(transform); - - self.finish(transform, data) - } - } - - fn finish(&self, mut transform: SecTransform, data: &CFData) -> Result<CFData, CFError> { - unsafe { - if let Some(ref padding) = self.padding { - let key = CFString::wrap_under_get_rule(kSecPaddingKey); - transform.set_attribute(&key, &padding.to_str())?; - } - - if let Some(ref mode) = self.mode { - let key = CFString::wrap_under_get_rule(kSecEncryptionMode); - transform.set_attribute(&key, &mode.to_str())?; - } - - if let Some(ref iv) = self.iv { - let key = CFString::wrap_under_get_rule(kSecIVKey); - transform.set_attribute(&key, iv)?; - } - - let key = CFString::wrap_under_get_rule(kSecTransformInputAttributeName); - transform.set_attribute(&key, data)?; - - let result = transform.execute()?; - Ok(CFData::wrap_under_get_rule( - result.as_CFTypeRef() as CFDataRef - )) - } - } -} - -#[cfg(test)] -mod test { - use hex::FromHex; - - use super::*; - use crate::os::macos::item::KeyType; - use crate::os::macos::key::SecKeyExt; - - #[test] - fn cbc_mmt_256() { - // test 9 - let key = "87725bd43a45608814180773f0e7ab95a3c859d83a2130e884190e44d14c6996"; - let iv = "e49651988ebbb72eb8bb80bb9abbca34"; - let ciphertext = "5b97a9d423f4b97413f388d9a341e727bb339f8e18a3fac2f2fb85abdc8f135deb30054a\ - 1afdc9b6ed7da16c55eba6b0d4d10c74e1d9a7cf8edfaeaa684ac0bd9f9d24ba674955c7\ - 9dc6be32aee1c260b558ff07e3a4d49d24162011ff254db8be078e8ad07e648e6bf56793\ - 76cb4321a5ef01afe6ad8816fcc7634669c8c4389295c9241e45fff39f3225f7745032da\ - eebe99d4b19bcb215d1bfdb36eda2c24"; - let plaintext = "bfe5c6354b7a3ff3e192e05775b9b75807de12e38a626b8bf0e12d5fff78e4f1775aa7d79\ - 2d885162e66d88930f9c3b2cdf8654f56972504803190386270f0aa43645db187af41fcea\ - 639b1f8026ccdd0c23e0de37094a8b941ecb7602998a4b2604e69fc04219585d854600e0a\ - d6f99a53b2504043c08b1c3e214d17cde053cbdf91daa999ed5b47c37983ba3ee254bc5c7\ - 93837daaa8c85cfc12f7f54f699f"; - - let key = Vec::<u8>::from_hex(key).unwrap(); - let key = CFData::from_buffer(&key); - let key = SecKey::from_data(KeyType::aes(), &key).unwrap(); - - let iv = Vec::<u8>::from_hex(iv).unwrap(); - - let ciphertext = Vec::<u8>::from_hex(ciphertext).unwrap(); - - let plaintext = Vec::<u8>::from_hex(plaintext).unwrap(); - - let decrypted = Builder::new() - .padding(Padding::none()) - .iv(CFData::from_buffer(&iv)) - .decrypt(&key, &CFData::from_buffer(&ciphertext)) - .unwrap(); - - assert_eq!(plaintext, decrypted.bytes()); - - let encrypted = Builder::new() - .padding(Padding::none()) - .iv(CFData::from_buffer(&iv)) - .encrypt(&key, &CFData::from_buffer(&plaintext)) - .unwrap(); - - assert_eq!(ciphertext, encrypted.bytes()); - } -} diff --git a/vendor/security-framework/src/os/macos/identity.rs b/vendor/security-framework/src/os/macos/identity.rs deleted file mode 100644 index 0f8da464..00000000 --- a/vendor/security-framework/src/os/macos/identity.rs +++ /dev/null @@ -1,85 +0,0 @@ -//! OSX specific extensions to identity functionality. -use core_foundation::array::CFArray; -use core_foundation::base::TCFType; -use security_framework_sys::identity::SecIdentityCreateWithCertificate; -use std::ptr; - -use crate::base::Result; -use crate::certificate::SecCertificate; -use crate::cvt; -use crate::identity::SecIdentity; -use crate::os::macos::keychain::SecKeychain; - -/// An extension trait adding OSX specific functionality to `SecIdentity`. -pub trait SecIdentityExt { - /// Creates an identity corresponding to a certificate, looking in the - /// provided keychains for the corresponding private key. - /// - /// To search the default keychains, use an empty slice for `keychains`. - /// - /// <https://developer.apple.com/documentation/security/1401160-secidentitycreatewithcertificate> - fn with_certificate( - keychains: &[SecKeychain], - certificate: &SecCertificate, - ) -> Result<SecIdentity>; -} - -impl SecIdentityExt for SecIdentity { - fn with_certificate(keychains: &[SecKeychain], certificate: &SecCertificate) -> Result<Self> { - let keychains = CFArray::from_CFTypes(keychains); - unsafe { - let mut identity = ptr::null_mut(); - cvt(SecIdentityCreateWithCertificate( - if keychains.len() > 0 {keychains.as_CFTypeRef()} else {ptr::null()}, - certificate.as_concrete_TypeRef(), - &mut identity, - ))?; - Ok(Self::wrap_under_create_rule(identity)) - } - } -} - -#[cfg(test)] -mod test { - use tempfile::tempdir; - - use super::*; - use crate::os::macos::certificate::SecCertificateExt; - use crate::os::macos::import_export::ImportOptions; - use crate::os::macos::keychain::CreateOptions; - use crate::os::macos::test::identity; - use crate::test; - - #[test] - fn certificate() { - let dir = p!(tempdir()); - let identity = identity(dir.path()); - let certificate = p!(identity.certificate()); - assert_eq!("foobar.com", p!(certificate.common_name())); - } - - #[test] - fn private_key() { - let dir = p!(tempdir()); - let identity = identity(dir.path()); - p!(identity.private_key()); - } - - #[test] - fn with_certificate() { - let dir = p!(tempdir()); - - let mut keychain = p!(CreateOptions::new() - .password("foobar") - .create(dir.path().join("test.keychain"))); - - let key = include_bytes!("../../../test/server.key"); - p!(ImportOptions::new() - .filename("server.key") - .keychain(&mut keychain) - .import(key)); - - let cert = test::certificate(); - p!(SecIdentity::with_certificate(&[keychain], &cert)); - } -} diff --git a/vendor/security-framework/src/os/macos/import_export.rs b/vendor/security-framework/src/os/macos/import_export.rs deleted file mode 100644 index 830d9483..00000000 --- a/vendor/security-framework/src/os/macos/import_export.rs +++ /dev/null @@ -1,344 +0,0 @@ -//! OSX specific extensions to import/export functionality. - -use core_foundation::array::CFArray; -use core_foundation::base::{CFType, TCFType}; -use core_foundation::data::CFData; -use core_foundation::string::CFString; -use security_framework_sys::base::errSecSuccess; -use security_framework_sys::import_export::*; -use std::ptr; -use std::str::FromStr; - -use crate::base::{Error, Result}; -use crate::certificate::SecCertificate; -use crate::identity::SecIdentity; -use crate::import_export::Pkcs12ImportOptions; -use crate::key::SecKey; -use crate::os::macos::access::SecAccess; -use crate::os::macos::keychain::SecKeychain; - -/// An extension trait adding OSX specific functionality to `Pkcs12ImportOptions`. -pub trait Pkcs12ImportOptionsExt { - /// Specifies the keychain in which to import the identity. - /// - /// If this is not called, the default keychain will be used. - fn keychain(&mut self, keychain: SecKeychain) -> &mut Self; - - /// Specifies the access control to be associated with the identity. - fn access(&mut self, access: SecAccess) -> &mut Self; -} - -impl Pkcs12ImportOptionsExt for Pkcs12ImportOptions { - #[inline(always)] - fn keychain(&mut self, keychain: SecKeychain) -> &mut Self { - crate::Pkcs12ImportOptionsInternals::keychain(self, keychain) - } - - #[inline(always)] - fn access(&mut self, access: SecAccess) -> &mut Self { - crate::Pkcs12ImportOptionsInternals::access(self, access) - } -} - -/// A builder type to import Security Framework types from serialized formats. -#[derive(Default)] -pub struct ImportOptions<'a> { - filename: Option<CFString>, - passphrase: Option<CFType>, - secure_passphrase: bool, - no_access_control: bool, - alert_title: Option<CFString>, - alert_prompt: Option<CFString>, - items: Option<&'a mut SecItems>, - keychain: Option<SecKeychain>, -} - -impl<'a> ImportOptions<'a> { - /// Creates a new builder with default options. - #[inline(always)] - #[must_use] - pub fn new() -> ImportOptions<'a> { - ImportOptions::default() - } - - /// Sets the filename from which the imported data came. - /// - /// The extension of the file will used as a hint for parsing. - #[inline] - pub fn filename(&mut self, filename: &str) -> &mut ImportOptions<'a> { - self.filename = Some(CFString::from_str(filename).unwrap()); - self - } - - /// Sets the passphrase to be used to decrypt the imported data. - #[inline] - pub fn passphrase(&mut self, passphrase: &str) -> &mut ImportOptions<'a> { - self.passphrase = Some(CFString::from_str(passphrase).unwrap().into_CFType()); - self - } - - /// Sets the passphrase to be used to decrypt the imported data. - #[inline] - pub fn passphrase_bytes(&mut self, passphrase: &[u8]) -> &mut ImportOptions<'a> { - self.passphrase = Some(CFData::from_buffer(passphrase).into_CFType()); - self - } - - /// If set, the user will be prompted to imput the passphrase used to - /// decrypt the imported data. - #[inline(always)] - pub fn secure_passphrase(&mut self, secure_passphrase: bool) -> &mut ImportOptions<'a> { - self.secure_passphrase = secure_passphrase; - self - } - - /// If set, imported items will have no access controls imposed on them. - #[inline(always)] - pub fn no_access_control(&mut self, no_access_control: bool) -> &mut ImportOptions<'a> { - self.no_access_control = no_access_control; - self - } - - /// Sets the title of the alert popup used with the `secure_passphrase` - /// option. - #[inline] - pub fn alert_title(&mut self, alert_title: &str) -> &mut ImportOptions<'a> { - self.alert_title = Some(CFString::from_str(alert_title).unwrap()); - self - } - - /// Sets the prompt of the alert popup used with the `secure_passphrase` - /// option. - #[inline] - pub fn alert_prompt(&mut self, alert_prompt: &str) -> &mut ImportOptions<'a> { - self.alert_prompt = Some(CFString::from_str(alert_prompt).unwrap()); - self - } - - /// Sets the object into which imported items will be placed. - #[inline(always)] - pub fn items(&mut self, items: &'a mut SecItems) -> &mut ImportOptions<'a> { - self.items = Some(items); - self - } - - /// Sets the keychain into which items will be imported. - /// - /// This must be specified to import `SecIdentity`s. - #[inline] - pub fn keychain(&mut self, keychain: &SecKeychain) -> &mut ImportOptions<'a> { - self.keychain = Some(keychain.clone()); - self - } - - /// Imports items from serialized data. - pub fn import(&mut self, data: &[u8]) -> Result<()> { - let data = CFData::from_buffer(data); - let data = data.as_concrete_TypeRef(); - - let filename = match self.filename { - Some(ref filename) => filename.as_concrete_TypeRef(), - None => ptr::null(), - }; - - let mut key_params = SecItemImportExportKeyParameters { - version: SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION, - flags: 0, - passphrase: ptr::null(), - alertTitle: ptr::null(), - alertPrompt: ptr::null(), - accessRef: ptr::null_mut(), - keyUsage: ptr::null_mut(), - keyAttributes: ptr::null(), - }; - - if let Some(ref passphrase) = self.passphrase { - key_params.passphrase = passphrase.as_CFTypeRef(); - } - - if self.secure_passphrase { - key_params.flags |= kSecKeySecurePassphrase; - } - - if self.no_access_control { - key_params.flags |= kSecKeyNoAccessControl; - } - - if let Some(ref alert_title) = self.alert_title { - key_params.alertTitle = alert_title.as_concrete_TypeRef(); - } - - if let Some(ref alert_prompt) = self.alert_prompt { - key_params.alertPrompt = alert_prompt.as_concrete_TypeRef(); - } - - let keychain = match self.keychain { - Some(ref keychain) => keychain.as_concrete_TypeRef(), - None => ptr::null_mut(), - }; - - let mut raw_items = ptr::null(); - let items_ref = match self.items { - Some(_) => std::ptr::addr_of_mut!(raw_items), - None => ptr::null_mut(), - }; - - unsafe { - let ret = SecItemImport( - data, - filename, - ptr::null_mut(), - ptr::null_mut(), - 0, - &key_params, - keychain, - items_ref, - ); - if ret != errSecSuccess { - return Err(Error::from_code(ret)); - } - - if let Some(ref mut items) = self.items { - let raw_items = CFArray::<CFType>::wrap_under_create_rule(raw_items); - for item in raw_items.iter() { - let type_id = item.type_of(); - if type_id == SecCertificate::type_id() { - items.certificates.push(SecCertificate::wrap_under_get_rule( - item.as_CFTypeRef() as *mut _, - )); - } else if type_id == SecIdentity::type_id() { - items.identities.push(SecIdentity::wrap_under_get_rule( - item.as_CFTypeRef() as *mut _, - )); - } else if type_id == SecKey::type_id() { - items - .keys - .push(SecKey::wrap_under_get_rule(item.as_CFTypeRef() as *mut _)); - } else { - panic!("Got bad type from SecItemImport: {type_id}"); - } - } - } - } - - Ok(()) - } -} - -/// A type which holds items imported from serialized data. -/// -/// Pass a reference to `ImportOptions::items`. -#[derive(Default)] -pub struct SecItems { - /// Imported certificates. - pub certificates: Vec<SecCertificate>, - /// Imported identities. - pub identities: Vec<SecIdentity>, - /// Imported keys. - pub keys: Vec<SecKey>, -} - -#[cfg(test)] -mod test { - use super::*; - use crate::import_export::*; - use crate::os::macos::keychain; - use tempfile::tempdir; - - #[test] - fn certificate() { - let data = include_bytes!("../../../test/server.der"); - let mut items = SecItems::default(); - ImportOptions::new() - .filename("server.der") - .items(&mut items) - .import(data) - .unwrap(); - assert_eq!(1, items.certificates.len()); - assert_eq!(0, items.identities.len()); - assert_eq!(0, items.keys.len()); - } - - #[test] - fn key() { - let data = include_bytes!("../../../test/server.key"); - let mut items = SecItems::default(); - ImportOptions::new() - .filename("server.key") - .items(&mut items) - .import(data) - .unwrap(); - assert_eq!(0, items.certificates.len()); - assert_eq!(0, items.identities.len()); - assert_eq!(1, items.keys.len()); - } - - #[test] - fn identity() { - let dir = tempdir().unwrap(); - let keychain = keychain::CreateOptions::new() - .password("password") - .create(dir.path().join("identity.keychain")) - .unwrap(); - - let data = include_bytes!("../../../test/server.p12"); - let mut items = SecItems::default(); - ImportOptions::new() - .filename("server.p12") - .passphrase("password123") - .items(&mut items) - .keychain(&keychain) - .import(data) - .unwrap(); - assert_eq!(1, items.identities.len()); - assert_eq!(0, items.certificates.len()); - assert_eq!(0, items.keys.len()); - } - - #[test] - #[ignore] // since it requires manual intervention - fn secure_passphrase_identity() { - let dir = tempdir().unwrap(); - let keychain = keychain::CreateOptions::new() - .password("password") - .create(dir.path().join("identity.keychain")) - .unwrap(); - - let data = include_bytes!("../../../test/server.p12"); - let mut items = SecItems::default(); - ImportOptions::new() - .filename("server.p12") - .secure_passphrase(true) - .alert_title("alert title") - .alert_prompt("alert prompt") - .items(&mut items) - .keychain(&keychain) - .import(data) - .unwrap(); - assert_eq!(1, items.identities.len()); - assert_eq!(0, items.certificates.len()); - assert_eq!(0, items.keys.len()); - } - - #[test] - fn pkcs12_import() { - use super::Pkcs12ImportOptionsExt; - - let dir = tempdir().unwrap(); - let keychain = keychain::CreateOptions::new() - .password("password") - .create(dir.path().join("pkcs12_import")) - .unwrap(); - - let data = include_bytes!("../../../test/server.p12"); - let identities = p!(Pkcs12ImportOptions::new() - .passphrase("password123") - .keychain(keychain) - .import(data)); - assert_eq!(1, identities.len()); - assert_eq!( - hex::encode(identities[0].key_id.as_ref().unwrap()), - "ed6492936dcc8907e397e573b36e633458dc33f1" - ); - } -} diff --git a/vendor/security-framework/src/os/macos/item.rs b/vendor/security-framework/src/os/macos/item.rs deleted file mode 100644 index 18a4d2e8..00000000 --- a/vendor/security-framework/src/os/macos/item.rs +++ /dev/null @@ -1,47 +0,0 @@ -//! OSX specific functionality for items. -use crate::item::ItemSearchOptions; -use crate::os::macos::keychain::SecKeychain; -use crate::ItemSearchOptionsInternals; - -// Moved to crate::Key -pub use crate::key::KeyType; - -/// An extension trait adding OSX specific functionality to `ItemSearchOptions`. -pub trait ItemSearchOptionsExt { - /// Search within the specified keychains. - /// - /// If this is not called, the default keychain will be searched. - fn keychains(&mut self, keychains: &[SecKeychain]) -> &mut Self; -} - -impl ItemSearchOptionsExt for ItemSearchOptions { - #[inline(always)] - fn keychains(&mut self, keychains: &[SecKeychain]) -> &mut Self { - ItemSearchOptionsInternals::keychains(self, keychains) - } -} - -#[cfg(test)] -mod test { - use crate::item::*; - use crate::os::macos::certificate::SecCertificateExt; - use crate::os::macos::item::ItemSearchOptionsExt; - use crate::os::macos::test::keychain; - use tempfile::tempdir; - - #[test] - fn find_certificate() { - let dir = p!(tempdir()); - let keychain = keychain(dir.path()); - let results = p!(ItemSearchOptions::new() - .keychains(&[keychain]) - .class(ItemClass::certificate()) - .search()); - assert_eq!(1, results.len()); - let certificate = match results[0] { - SearchResult::Ref(Reference::Certificate(ref cert)) => cert, - _ => panic!("expected certificate"), - }; - assert_eq!("foobar.com", p!(certificate.common_name())); - } -} diff --git a/vendor/security-framework/src/os/macos/key.rs b/vendor/security-framework/src/os/macos/key.rs deleted file mode 100644 index f6a20e93..00000000 --- a/vendor/security-framework/src/os/macos/key.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! OSX specific functionality for keys. -use core_foundation::base::TCFType; -use core_foundation::data::CFData; -use core_foundation::dictionary::CFDictionary; -use core_foundation::error::CFError; -use core_foundation::string::CFString; -use security_framework_sys::item::kSecAttrKeyType; -use security_framework_sys::key::SecKeyCreateFromData; -use std::ptr; - -use crate::key::{KeyType, SecKey}; - -/// An extension trait adding OSX specific functionality to `SecKey`. -pub trait SecKeyExt { - /// Creates a new `SecKey` from a buffer containing key data. - fn from_data(key_type: KeyType, key_data: &CFData) -> Result<SecKey, CFError>; -} - -impl SecKeyExt for SecKey { - fn from_data(key_type: KeyType, key_data: &CFData) -> Result<Self, CFError> { - unsafe { - let key = CFString::wrap_under_get_rule(kSecAttrKeyType); - let dict = CFDictionary::from_CFType_pairs(&[(key, key_type.to_str())]); - - let mut err = ptr::null_mut(); - let key = SecKeyCreateFromData( - dict.as_concrete_TypeRef(), - key_data.as_concrete_TypeRef(), - &mut err, - ); - if key.is_null() { - Err(CFError::wrap_under_create_rule(err)) - } else { - Ok(Self::wrap_under_create_rule(key)) - } - } - } -} diff --git a/vendor/security-framework/src/os/macos/keychain.rs b/vendor/security-framework/src/os/macos/keychain.rs deleted file mode 100644 index bce5e00a..00000000 --- a/vendor/security-framework/src/os/macos/keychain.rs +++ /dev/null @@ -1,281 +0,0 @@ -//! Keychain support. - -use core_foundation::base::{Boolean, TCFType}; -use security_framework_sys::base::{errSecSuccess, SecKeychainRef}; -use security_framework_sys::keychain::*; -use std::ffi::CString; -use std::os::raw::c_void; -use std::os::unix::ffi::OsStrExt; -use std::path::Path; -use std::ptr; - -use crate::base::{Error, Result}; -use crate::cvt; -use crate::os::macos::access::SecAccess; - -pub use security_framework_sys::keychain::SecPreferencesDomain; - -declare_TCFType! { - /// A type representing a keychain. - SecKeychain, SecKeychainRef -} -impl_TCFType!(SecKeychain, SecKeychainRef, SecKeychainGetTypeID); - -unsafe impl Sync for SecKeychain {} -unsafe impl Send for SecKeychain {} - -impl SecKeychain { - /// Creates a `SecKeychain` object corresponding to the user's default - /// keychain. - #[inline] - #[allow(clippy::should_implement_trait)] - pub fn default() -> Result<Self> { - unsafe { - let mut keychain = ptr::null_mut(); - cvt(SecKeychainCopyDefault(&mut keychain))?; - Ok(Self::wrap_under_create_rule(keychain)) - } - } - - /// Creates a `SecKeychain` object corresponding to the user's default - /// keychain for the given domain. - pub fn default_for_domain(domain: SecPreferencesDomain) -> Result<Self> { - unsafe { - let mut keychain = ptr::null_mut(); - cvt(SecKeychainCopyDomainDefault(domain, &mut keychain))?; - Ok(Self::wrap_under_create_rule(keychain)) - } - } - - /// Opens a keychain from a file. - pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> { - let path_name = [ - path.as_ref().as_os_str().as_bytes(), - std::slice::from_ref(&0) - ].concat(); - - unsafe { - let mut keychain = ptr::null_mut(); - cvt(SecKeychainOpen(path_name.as_ptr().cast(), &mut keychain))?; - Ok(Self::wrap_under_create_rule(keychain)) - } - } - - /// Unlocks the keychain. - /// - /// If a password is not specified, the user will be prompted to enter it. - pub fn unlock(&mut self, password: Option<&str>) -> Result<()> { - let (len, ptr, use_password) = match password { - Some(password) => (password.len(), password.as_ptr().cast(), true), - None => (0, ptr::null(), false), - }; - - unsafe { - cvt(SecKeychainUnlock( - self.as_concrete_TypeRef(), - len as u32, - ptr, - Boolean::from(use_password), - )) - } - } - - /// Sets settings of the keychain. - #[inline] - pub fn set_settings(&mut self, settings: &KeychainSettings) -> Result<()> { - unsafe { - cvt(SecKeychainSetSettings( - self.as_concrete_TypeRef(), - &settings.0, - )) - } - } - - #[cfg(target_os = "macos")] - /// Disables the user interface for keychain services functions that - /// automatically display a user interface. - pub fn disable_user_interaction() -> Result<KeychainUserInteractionLock> { - let code = unsafe { SecKeychainSetUserInteractionAllowed(0u8) }; - - if code != errSecSuccess { - Err(Error::from_code(code)) - } else { - Ok(KeychainUserInteractionLock) - } - } - - #[cfg(target_os = "macos")] - /// Indicates whether keychain services functions that normally display a - /// user interaction are allowed to do so. - pub fn user_interaction_allowed() -> Result<bool> { - let mut state: Boolean = 0; - let code = unsafe { SecKeychainGetUserInteractionAllowed(&mut state) }; - - if code != errSecSuccess { - Err(Error::from_code(code)) - } else { - Ok(state != 0) - } - } -} - -/// A builder type to create new keychains. -#[derive(Default)] -pub struct CreateOptions { - password: Option<String>, - prompt_user: bool, - access: Option<SecAccess>, -} - -impl CreateOptions { - /// Creates a new builder with default options. - #[inline(always)] - #[must_use] - pub fn new() -> Self { - Self::default() - } - - /// Sets the password to be used to protect the keychain. - #[inline] - pub fn password(&mut self, password: &str) -> &mut Self { - self.password = Some(password.into()); - self - } - - /// If set, the user will be prompted to provide a password used to - /// protect the keychain. - #[inline(always)] - pub fn prompt_user(&mut self, prompt_user: bool) -> &mut Self { - self.prompt_user = prompt_user; - self - } - - /// Sets the access control applied to the keychain. - #[inline(always)] - pub fn access(&mut self, access: SecAccess) -> &mut Self { - self.access = Some(access); - self - } - - /// Creates a new keychain at the specified location on the filesystem. - pub fn create<P: AsRef<Path>>(&self, path: P) -> Result<SecKeychain> { - unsafe { - let path_name = path.as_ref().as_os_str().as_bytes(); - // FIXME - let path_name = CString::new(path_name).unwrap(); - - let (password, password_len) = match self.password { - Some(ref password) => (password.as_ptr().cast::<c_void>(), password.len() as u32), - None => (ptr::null(), 0), - }; - - let access = match self.access { - Some(ref access) => access.as_concrete_TypeRef(), - None => ptr::null_mut(), - }; - - let mut keychain = ptr::null_mut(); - cvt(SecKeychainCreate( - path_name.as_ptr(), - password_len, - password, - Boolean::from(self.prompt_user), - access, - &mut keychain, - ))?; - - Ok(SecKeychain::wrap_under_create_rule(keychain)) - } - } -} - -/// Settings associated with a `SecKeychain`. -pub struct KeychainSettings(SecKeychainSettings); - -impl KeychainSettings { - /// Creates a new `KeychainSettings` with default settings. - #[inline] - #[must_use] - pub fn new() -> Self { - Self(SecKeychainSettings { - version: SEC_KEYCHAIN_SETTINGS_VERS1, - lockOnSleep: 0, - useLockInterval: 0, - lockInterval: i32::max_value() as u32, - }) - } - - /// If set, the keychain will automatically lock when the computer sleeps. - /// - /// Defaults to `false`. - #[inline(always)] - pub fn set_lock_on_sleep(&mut self, lock_on_sleep: bool) { - self.0.lockOnSleep = Boolean::from(lock_on_sleep); - } - - /// Sets the interval of time in seconds after which the keychain is - /// automatically locked. - /// - /// Defaults to `None`. - pub fn set_lock_interval(&mut self, lock_interval: Option<u32>) { - match lock_interval { - Some(lock_interval) => { - self.0.useLockInterval = 1; - self.0.lockInterval = lock_interval; - } - None => { - self.0.useLockInterval = 0; - self.0.lockInterval = i32::max_value() as u32; - } - } - } -} - -impl Default for KeychainSettings { - #[inline(always)] - fn default() -> Self { - Self::new() - } -} - -#[cfg(target_os = "macos")] -#[must_use = "The user interaction is disabled for the lifetime of the returned object"] -/// Automatically re-enables user interaction. -pub struct KeychainUserInteractionLock; - -#[cfg(target_os = "macos")] -impl Drop for KeychainUserInteractionLock { - #[inline(always)] - fn drop(&mut self) { - unsafe { SecKeychainSetUserInteractionAllowed(1u8) }; - } -} - -#[cfg(test)] -mod test { - use tempfile::tempdir; - - use super::*; - - #[test] - fn create_options() { - let dir = tempdir().unwrap(); - - let mut keychain = CreateOptions::new() - .password("foobar") - .create(dir.path().join("test.keychain")) - .unwrap(); - - keychain.set_settings(&KeychainSettings::new()).unwrap(); - } - - #[test] - fn disable_user_interaction() { - assert!(SecKeychain::user_interaction_allowed().unwrap()); - { - let _lock = SecKeychain::disable_user_interaction().unwrap(); - assert!(!SecKeychain::user_interaction_allowed().unwrap()); - } - assert!(SecKeychain::user_interaction_allowed().unwrap()); - } -} diff --git a/vendor/security-framework/src/os/macos/keychain_item.rs b/vendor/security-framework/src/os/macos/keychain_item.rs deleted file mode 100644 index fd7b452a..00000000 --- a/vendor/security-framework/src/os/macos/keychain_item.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Keychain item support. - -use core_foundation::base::TCFType; -use security_framework_sys::base::SecKeychainItemRef; -use security_framework_sys::keychain_item::SecKeychainItemGetTypeID; -use std::fmt; - -declare_TCFType! { - /// A type representing a keychain item. - SecKeychainItem, SecKeychainItemRef -} -impl_TCFType!( - SecKeychainItem, - SecKeychainItemRef, - SecKeychainItemGetTypeID -); - -unsafe impl Sync for SecKeychainItem {} -unsafe impl Send for SecKeychainItem {} - -impl fmt::Debug for SecKeychainItem { - #[cold] - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("SecKeychainItem").finish_non_exhaustive() - } -} diff --git a/vendor/security-framework/src/os/macos/mod.rs b/vendor/security-framework/src/os/macos/mod.rs deleted file mode 100644 index 3e468fc3..00000000 --- a/vendor/security-framework/src/os/macos/mod.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! OSX specific extensions. - -pub mod access; -pub mod certificate; -pub mod certificate_oids; -pub mod code_signing; -pub mod digest_transform; -pub mod encrypt_transform; -pub mod identity; -pub mod import_export; -pub mod item; -pub mod key; -pub mod keychain; -pub mod keychain_item; -pub mod passwords; -pub mod secure_transport; -pub mod transform; - -#[cfg(test)] -pub mod test { - use crate::identity::SecIdentity; - use crate::item::{ItemClass, ItemSearchOptions, Reference, SearchResult}; - use crate::os::macos::item::ItemSearchOptionsExt; - use crate::os::macos::keychain::SecKeychain; - use std::fs::File; - use std::io::prelude::*; - use std::path::Path; - - #[must_use] pub fn identity(dir: &Path) -> SecIdentity { - // FIXME https://github.com/rust-lang/rust/issues/30018 - let keychain = keychain(dir); - let mut items = p!(ItemSearchOptions::new() - .class(ItemClass::identity()) - .keychains(&[keychain]) - .search()); - match items.pop().unwrap() { - SearchResult::Ref(Reference::Identity(identity)) => identity, - _ => panic!("expected identity"), - } - } - - #[must_use] pub fn keychain(dir: &Path) -> SecKeychain { - let path = dir.join("server.keychain"); - let mut file = p!(File::create(&path)); - p!(file.write_all(include_bytes!("../../../test/server.keychain"))); - drop(file); - - let mut keychain = p!(SecKeychain::open(&path)); - p!(keychain.unlock(Some("password123"))); - keychain - } -} diff --git a/vendor/security-framework/src/os/macos/passwords.rs b/vendor/security-framework/src/os/macos/passwords.rs deleted file mode 100644 index 8587a3c5..00000000 --- a/vendor/security-framework/src/os/macos/passwords.rs +++ /dev/null @@ -1,525 +0,0 @@ -//! Password support. - -use crate::os::macos::keychain::SecKeychain; -use crate::os::macos::keychain_item::SecKeychainItem; -use core_foundation::array::CFArray; -use core_foundation::base::TCFType; -pub use security_framework_sys::keychain::{SecAuthenticationType, SecProtocolType}; -use security_framework_sys::keychain::{ - SecKeychainAddGenericPassword, SecKeychainAddInternetPassword, SecKeychainFindGenericPassword, - SecKeychainFindInternetPassword, -}; -use security_framework_sys::keychain_item::{ - SecKeychainItemDelete, SecKeychainItemFreeContent, SecKeychainItemModifyAttributesAndData, -}; -use std::fmt; -use std::fmt::Write; -use std::ops::Deref; -use std::ptr; -use std::slice; - -use crate::base::Result; -use crate::cvt; - -/// Password slice. Use `.as_ref()` to get `&[u8]` or `.to_owned()` to get `Vec<u8>` -pub struct SecKeychainItemPassword { - data: *const u8, - data_len: usize, -} - -impl fmt::Debug for SecKeychainItemPassword { - #[cold] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for _ in 0..self.data_len { - f.write_char('•')?; - } - Ok(()) - } -} - -impl AsRef<[u8]> for SecKeychainItemPassword { - #[inline] - fn as_ref(&self) -> &[u8] { - unsafe { slice::from_raw_parts(self.data, self.data_len) } - } -} - -impl Deref for SecKeychainItemPassword { - type Target = [u8]; - #[inline(always)] - fn deref(&self) -> &Self::Target { - self.as_ref() - } -} - -impl Drop for SecKeychainItemPassword { - #[inline] - fn drop(&mut self) { - unsafe { - SecKeychainItemFreeContent(ptr::null_mut(), self.data as *mut _); - } - } -} - -impl SecKeychainItem { - /// Modify keychain item in-place, replacing its password with the given one - pub fn set_password(&mut self, password: &[u8]) -> Result<()> { - unsafe { - cvt(SecKeychainItemModifyAttributesAndData( - self.as_CFTypeRef() as *mut _, - ptr::null(), - password.len() as u32, - password.as_ptr().cast(), - ))?; - } - Ok(()) - } - - /// Delete this item from its keychain - #[inline] - pub fn delete(self) { - unsafe { - SecKeychainItemDelete(self.as_CFTypeRef() as *mut _); - } - } -} - -/// Find a generic password. -/// -/// The underlying system supports passwords with 0 values, so this -/// returns a vector of bytes rather than a string. -/// -/// * `keychains` is an array of keychains to search or None to search -/// the default keychain. -/// * `service` is the name of the service to search for. -/// * `account` is the name of the account to search for. -pub fn find_generic_password( - keychains: Option<&[SecKeychain]>, - service: &str, - account: &str, -) -> Result<(SecKeychainItemPassword, SecKeychainItem)> { - let keychains_or_none = keychains.map(CFArray::from_CFTypes); - - let keychains_or_null = match keychains_or_none { - None => ptr::null(), - Some(ref keychains) => keychains.as_CFTypeRef(), - }; - - let mut data_len = 0; - let mut data = ptr::null_mut(); - let mut item = ptr::null_mut(); - - unsafe { - cvt(SecKeychainFindGenericPassword( - keychains_or_null, - service.len() as u32, - service.as_ptr().cast(), - account.len() as u32, - account.as_ptr().cast(), - &mut data_len, - &mut data, - &mut item, - ))?; - Ok(( - SecKeychainItemPassword { - data: data as *const _, - data_len: data_len as usize, - }, - SecKeychainItem::wrap_under_create_rule(item), - )) - } -} - -/// * `keychains` is an array of keychains to search or None to search -/// the default keychain. -/// * `server`: server name. -/// * `security_domain`: security domain. This parameter is optional. -/// * `account`: account name. -/// * `path`: the path. -/// * `port`: The TCP/IP port number. -/// * `protocol`: The protocol associated with this password. -/// * `authentication_type`: The authentication scheme used. -#[allow(clippy::too_many_arguments)] -pub fn find_internet_password( - keychains: Option<&[SecKeychain]>, - server: &str, - security_domain: Option<&str>, - account: &str, - path: &str, - port: Option<u16>, - protocol: SecProtocolType, - authentication_type: SecAuthenticationType, -) -> Result<(SecKeychainItemPassword, SecKeychainItem)> { - let keychains_or_none = keychains.map(CFArray::from_CFTypes); - - let keychains_or_null = match keychains_or_none { - None => ptr::null(), - Some(ref keychains) => keychains.as_CFTypeRef(), - }; - - let mut data_len = 0; - let mut data = ptr::null_mut(); - let mut item = ptr::null_mut(); - - unsafe { - cvt(SecKeychainFindInternetPassword( - keychains_or_null, - server.len() as u32, - server.as_ptr().cast(), - security_domain.map_or(0, |s| s.len() as u32), - security_domain - .map_or(ptr::null(), |s| s.as_ptr().cast()), - account.len() as u32, - account.as_ptr().cast(), - path.len() as u32, - path.as_ptr().cast(), - port.unwrap_or(0), - protocol, - authentication_type, - &mut data_len, - &mut data, - &mut item, - ))?; - Ok(( - SecKeychainItemPassword { - data: data as *const _, - data_len: data_len as usize, - }, - SecKeychainItem::wrap_under_create_rule(item), - )) - } -} - -impl SecKeychain { - /// Find application password in this keychain - #[inline] - pub fn find_generic_password( - &self, - service: &str, - account: &str, - ) -> Result<(SecKeychainItemPassword, SecKeychainItem)> { - find_generic_password(Some(&[self.clone()]), service, account) - } - - /// Find internet password in this keychain - #[inline] - #[allow(clippy::too_many_arguments)] - pub fn find_internet_password( - &self, - server: &str, - security_domain: Option<&str>, - account: &str, - path: &str, - port: Option<u16>, - protocol: SecProtocolType, - authentication_type: SecAuthenticationType, - ) -> Result<(SecKeychainItemPassword, SecKeychainItem)> { - find_internet_password( - Some(&[self.clone()]), - server, - security_domain, - account, - path, - port, - protocol, - authentication_type, - ) - } - - /// Update existing or add new internet password - #[allow(clippy::too_many_arguments)] - pub fn set_internet_password( - &self, - server: &str, - security_domain: Option<&str>, - account: &str, - path: &str, - port: Option<u16>, - protocol: SecProtocolType, - authentication_type: SecAuthenticationType, - password: &[u8], - ) -> Result<()> { - match self.find_internet_password( - server, - security_domain, - account, - path, - port, - protocol, - authentication_type, - ) { - Ok((_, mut item)) => item.set_password(password), - _ => self.add_internet_password( - server, - security_domain, - account, - path, - port, - protocol, - authentication_type, - password, - ), - } - } - - /// Set a generic password. - /// - /// * `keychain_opt` is the keychain to use or None to use the default - /// keychain. - /// * `service` is the associated service name for the password. - /// * `account` is the associated account name for the password. - /// * `password` is the password itself. - pub fn set_generic_password( - &self, - service: &str, - account: &str, - password: &[u8], - ) -> Result<()> { - match self.find_generic_password(service, account) { - Ok((_, mut item)) => item.set_password(password), - _ => self.add_generic_password(service, account, password), - } - } - - /// Add application password to the keychain, without checking if it exists already - /// - /// See `set_generic_password()` - #[inline] - pub fn add_generic_password( - &self, - service: &str, - account: &str, - password: &[u8], - ) -> Result<()> { - unsafe { - cvt(SecKeychainAddGenericPassword( - self.as_CFTypeRef() as *mut _, - service.len() as u32, - service.as_ptr().cast(), - account.len() as u32, - account.as_ptr().cast(), - password.len() as u32, - password.as_ptr().cast(), - ptr::null_mut(), - ))?; - } - Ok(()) - } - - /// Add internet password to the keychain, without checking if it exists already - /// - /// See `set_internet_password()` - #[inline] - #[allow(clippy::too_many_arguments)] - pub fn add_internet_password( - &self, - server: &str, - security_domain: Option<&str>, - account: &str, - path: &str, - port: Option<u16>, - protocol: SecProtocolType, - authentication_type: SecAuthenticationType, - password: &[u8], - ) -> Result<()> { - unsafe { - cvt(SecKeychainAddInternetPassword( - self.as_CFTypeRef() as *mut _, - server.len() as u32, - server.as_ptr().cast(), - security_domain.map_or(0, |s| s.len() as u32), - security_domain - .map_or(ptr::null(), |s| s.as_ptr().cast()), - account.len() as u32, - account.as_ptr().cast(), - path.len() as u32, - path.as_ptr().cast(), - port.unwrap_or(0), - protocol, - authentication_type, - password.len() as u32, - password.as_ptr().cast(), - ptr::null_mut(), - ))?; - } - Ok(()) - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::os::macos::keychain::CreateOptions; - use tempfile::tempdir; - use tempfile::TempDir; - - fn temp_keychain_setup(name: &str) -> (TempDir, SecKeychain) { - let dir = tempdir().expect("TempDir::new"); - let keychain = CreateOptions::new() - .password("foobar") - .create(dir.path().join(name.to_string() + ".keychain")) - .expect("create keychain"); - - (dir, keychain) - } - - fn temp_keychain_teardown(dir: TempDir) { - dir.close().expect("temp dir close"); - } - - #[test] - fn missing_password_temp() { - let (dir, keychain) = temp_keychain_setup("missing_password"); - let keychains = vec![keychain]; - - let service = "temp_this_service_does_not_exist"; - let account = "this_account_is_bogus"; - let found = find_generic_password(Some(&keychains), service, account); - - assert!(found.is_err()); - - temp_keychain_teardown(dir); - } - - #[test] - #[cfg(feature = "default_keychain_tests")] - fn missing_password_default() { - let service = "default_this_service_does_not_exist"; - let account = "this_account_is_bogus"; - let found = find_generic_password(None, service, account); - - assert!(found.is_err()); - } - - #[test] - fn round_trip_password_temp() { - let (dir, keychain) = temp_keychain_setup("round_trip_password"); - - let service = "test_round_trip_password_temp"; - let account = "temp_this_is_the_test_account"; - let password = String::from("deadbeef").into_bytes(); - - keychain - .set_generic_password(service, account, &password) - .expect("set_generic_password"); - let (found, item) = keychain - .find_generic_password(service, account) - .expect("find_generic_password"); - assert_eq!(found.to_owned(), password); - - item.delete(); - - temp_keychain_teardown(dir); - } - - #[test] - #[cfg(feature = "default_keychain_tests")] - fn round_trip_password_default() { - let service = "test_round_trip_password_default"; - let account = "this_is_the_test_account"; - let password = String::from("deadbeef").into_bytes(); - - SecKeychain::default() - .expect("default keychain") - .set_generic_password(service, account, &password) - .expect("set_generic_password"); - let (found, item) = - find_generic_password(None, service, account).expect("find_generic_password"); - assert_eq!(&*found, &password[..]); - - item.delete(); - } - - #[test] - fn change_password_temp() { - let (dir, keychain) = temp_keychain_setup("change_password"); - let keychains = vec![keychain]; - - let service = "test_change_password_temp"; - let account = "this_is_the_test_account"; - let pw1 = String::from("password1").into_bytes(); - let pw2 = String::from("password2").into_bytes(); - - keychains[0] - .set_generic_password(service, account, &pw1) - .expect("set_generic_password1"); - let (found, _) = find_generic_password(Some(&keychains), service, account) - .expect("find_generic_password1"); - assert_eq!(found.as_ref(), &pw1[..]); - - keychains[0] - .set_generic_password(service, account, &pw2) - .expect("set_generic_password2"); - let (found, item) = find_generic_password(Some(&keychains), service, account) - .expect("find_generic_password2"); - assert_eq!(&*found, &pw2[..]); - - item.delete(); - - temp_keychain_teardown(dir); - } - - #[test] - #[cfg(feature = "default_keychain_tests")] - fn change_password_default() { - let service = "test_change_password_default"; - let account = "this_is_the_test_account"; - let pw1 = String::from("password1").into_bytes(); - let pw2 = String::from("password2").into_bytes(); - - SecKeychain::default() - .expect("default keychain") - .set_generic_password(service, account, &pw1) - .expect("set_generic_password1"); - let (found, _) = - find_generic_password(None, service, account).expect("find_generic_password1"); - assert_eq!(found.to_owned(), pw1); - - SecKeychain::default() - .expect("default keychain") - .set_generic_password(service, account, &pw2) - .expect("set_generic_password2"); - let (found, item) = - find_generic_password(None, service, account).expect("find_generic_password2"); - assert_eq!(found.to_owned(), pw2); - - item.delete(); - } - - #[test] - fn cross_keychain_corruption_temp() { - let (dir1, keychain1) = temp_keychain_setup("cross_corrupt1"); - let (dir2, keychain2) = temp_keychain_setup("cross_corrupt2"); - let keychains1 = vec![keychain1.clone()]; - let keychains2 = vec![keychain2.clone()]; - let both_keychains = vec![keychain1, keychain2]; - - let service = "temp_this_service_does_not_exist"; - let account = "this_account_is_bogus"; - let password = String::from("deadbeef").into_bytes(); - - // Make sure this password doesn't exist in either keychain. - let found = find_generic_password(Some(&both_keychains), service, account); - assert!(found.is_err()); - - // Set a password in one keychain. - keychains1[0] - .set_generic_password(service, account, &password) - .expect("set_generic_password"); - - // Make sure it's found in that keychain. - let (found, item) = find_generic_password(Some(&keychains1), service, account) - .expect("find_generic_password1"); - assert_eq!(found.to_owned(), password); - - // Make sure it's _not_ found in the other keychain. - let found = find_generic_password(Some(&keychains2), service, account); - assert!(found.is_err()); - - // Cleanup. - item.delete(); - - temp_keychain_teardown(dir1); - temp_keychain_teardown(dir2); - } -} diff --git a/vendor/security-framework/src/os/macos/secure_transport.rs b/vendor/security-framework/src/os/macos/secure_transport.rs deleted file mode 100644 index 7d01f066..00000000 --- a/vendor/security-framework/src/os/macos/secure_transport.rs +++ /dev/null @@ -1,647 +0,0 @@ -//! OSX specific extensions to Secure Transport functionality. - -use core_foundation::array::CFArray; -use core_foundation::base::TCFType; -use security_framework_sys::secure_transport::*; -use std::ptr; -use std::slice; - -use crate::base::Result; -use crate::certificate::SecCertificate; -use crate::secure_transport::{MidHandshakeSslStream, SslContext}; -use crate::{cvt, AsInner}; - -/// An extension trait adding OSX specific functionality to the `SslContext` -/// type. -pub trait SslContextExt { - /// Returns the DER encoded data specifying the parameters used for - /// Diffie-Hellman key exchange. - fn diffie_hellman_params(&self) -> Result<Option<&[u8]>>; - - /// Sets the parameters used for Diffie-Hellman key exchange, in the - /// DER format used by OpenSSL. - /// - /// If a cipher suite which uses Diffie-Hellman key exchange is selected, - /// parameters will automatically be generated if none are provided with - /// this method, but this process can take up to 30 seconds. - /// - /// This can only be called on server-side sessions. - fn set_diffie_hellman_params(&mut self, dh_params: &[u8]) -> Result<()>; - - /// Returns the certificate authorities used to validate client - /// certificates. - fn certificate_authorities(&self) -> Result<Option<Vec<SecCertificate>>>; - - /// Sets the certificate authorities used to validate client certificates, - /// replacing any that are already present. - fn set_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()>; - - /// Adds certificate authorities used to validate client certificates. - fn add_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()>; - - /// If enabled, server identity changes are allowed during renegotiation. - /// - /// It is disabled by default to protect against triple handshake attacks. - /// - /// Requires the `OSX_10_11` (or greater) feature. - #[cfg(feature = "OSX_10_11")] - fn allow_server_identity_change(&self) -> Result<bool>; - - /// If enabled, server identity changes are allowed during renegotiation. - /// - /// It is disabled by default to protect against triple handshake attacks. - /// - /// Requires the `OSX_10_11` (or greater) feature. - #[cfg(feature = "OSX_10_11")] - fn set_allow_server_identity_change(&mut self, value: bool) -> Result<()>; - - /// If enabled, fallback countermeasures will be used during negotiation. - /// - /// It should be enabled when renegotiating with a peer with a lower - /// maximum protocol version due to an earlier failure to connect. - /// - /// Requires the `OSX_10_10` (or greater) feature. - #[cfg(feature = "OSX_10_10")] - fn fallback(&self) -> Result<bool>; - - /// If enabled, fallback countermeasures will be used during negotiation. - /// - /// It should be enabled when renegotiating with a peer with a lower - /// maximum protocol version due to an earlier failure to connect. - /// - /// Requires the `OSX_10_10` (or greater) feature. - #[cfg(feature = "OSX_10_10")] - fn set_fallback(&mut self, value: bool) -> Result<()>; - - /// If enabled, the handshake process will pause and return when the client - /// hello is recieved to support server name identification. - /// - /// Requires the `OSX_10_11` (or greater) feature. - #[cfg(feature = "OSX_10_11")] - fn break_on_client_hello(&self) -> Result<bool>; - - /// If enabled, the handshake process will pause and return when the client - /// hello is recieved to support server name identification. - /// - /// Requires the `OSX_10_11` (or greater) feature. - #[cfg(feature = "OSX_10_11")] - fn set_break_on_client_hello(&mut self, value: bool) -> Result<()>; -} - -macro_rules! impl_options { - ($($(#[$a:meta])* const $opt:ident: $get:ident & $set:ident,)*) => { - $( - $(#[$a])* - #[inline] - fn $set(&mut self, value: bool) -> Result<()> { - unsafe { - cvt(SSLSetSessionOption(self.as_inner(), - $opt, - value as ::core_foundation::base::Boolean)) - } - } - - $(#[$a])* - #[inline] - fn $get(&self) -> Result<bool> { - let mut value = 0; - unsafe { cvt(SSLGetSessionOption(self.as_inner(), $opt, &mut value))?; } - Ok(value != 0) - } - )* - } -} - -impl SslContextExt for SslContext { - fn diffie_hellman_params(&self) -> Result<Option<&[u8]>> { - unsafe { - let mut ptr = ptr::null(); - let mut len = 0; - cvt(SSLGetDiffieHellmanParams( - self.as_inner(), - &mut ptr, - &mut len, - ))?; - if ptr.is_null() { - Ok(None) - } else { - Ok(Some(slice::from_raw_parts(ptr.cast::<u8>(), len))) - } - } - } - - fn set_diffie_hellman_params(&mut self, dh_params: &[u8]) -> Result<()> { - unsafe { - cvt(SSLSetDiffieHellmanParams( - self.as_inner(), - dh_params.as_ptr().cast(), - dh_params.len(), - )) - } - } - - fn certificate_authorities(&self) -> Result<Option<Vec<SecCertificate>>> { - unsafe { - let mut raw_certs = ptr::null(); - cvt(SSLCopyCertificateAuthorities( - self.as_inner(), - &mut raw_certs, - ))?; - if raw_certs.is_null() { - Ok(None) - } else { - let certs = CFArray::<SecCertificate>::wrap_under_create_rule(raw_certs) - .iter() - .map(|c| c.clone()) - .collect(); - Ok(Some(certs)) - } - } - } - - fn set_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()> { - unsafe { - let certs = CFArray::from_CFTypes(certs); - cvt(SSLSetCertificateAuthorities( - self.as_inner(), - certs.as_CFTypeRef(), - 1, - )) - } - } - - fn add_certificate_authorities(&mut self, certs: &[SecCertificate]) -> Result<()> { - unsafe { - let certs = CFArray::from_CFTypes(certs); - cvt(SSLSetCertificateAuthorities( - self.as_inner(), - certs.as_CFTypeRef(), - 0, - )) - } - } - - impl_options! { - #[cfg(feature = "OSX_10_11")] - const kSSLSessionOptionAllowServerIdentityChange: allow_server_identity_change & set_allow_server_identity_change, - #[cfg(feature = "OSX_10_10")] - const kSSLSessionOptionFallback: fallback & set_fallback, - #[cfg(feature = "OSX_10_11")] - const kSSLSessionOptionBreakOnClientHello: break_on_client_hello & set_break_on_client_hello, - } -} - -/// An extension trait adding OSX specific functionality to the -/// `MidHandshakeSslStream` type. -pub trait MidHandshakeSslStreamExt { - /// Returns `true` iff `break_on_client_hello` was set and the handshake - /// has progressed to that point. - /// - /// Requires the `OSX_10_11` (or greater) feature. - #[cfg(feature = "OSX_10_11")] - fn client_hello_received(&self) -> bool; -} - -impl<S> MidHandshakeSslStreamExt for MidHandshakeSslStream<S> { - #[cfg(feature = "OSX_10_11")] - fn client_hello_received(&self) -> bool { - self.error().code() == errSSLClientHelloReceived - } -} - -#[cfg(test)] -mod test { - use std::io::prelude::*; - use std::net::{TcpListener, TcpStream}; - use std::thread; - use tempfile::tempdir; - - use super::*; - use crate::cipher_suite::CipherSuite; - use crate::os::macos::test::identity; - use crate::secure_transport::*; - use crate::test::certificate; - - #[test] - fn server_client() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - - let stream = p!(listener.accept()).0; - let mut stream = p!(ctx.handshake(stream)); - - let mut buf = [0; 12]; - p!(stream.read(&mut buf)); - assert_eq!(&buf[..], b"hello world!"); - }); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::CLIENT, - SslConnectionType::STREAM - )); - p!(ctx.set_break_on_server_auth(true)); - let stream = p!(TcpStream::connect(("localhost", port))); - - let stream = match ctx.handshake(stream) { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Interrupted(stream)) => stream, - Err(err) => panic!("unexpected error {err:?}"), - }; - - assert!(stream.server_auth_completed()); - let mut peer_trust = p!(stream.context().peer_trust2()).unwrap(); - p!(peer_trust.set_anchor_certificates(&[certificate()])); - p!(peer_trust.evaluate_with_error()); - - let mut stream = p!(stream.handshake()); - p!(stream.write_all(b"hello world!")); - - handle.join().unwrap(); - } - - #[test] - #[ignore] - fn server_client_builders() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let identity = identity(dir.path()); - let builder = ServerBuilder::new(&identity, &[]); - - let stream = p!(listener.accept()).0; - let mut stream = p!(builder.handshake(stream)); - - let mut buf = [0; 12]; - p!(stream.read(&mut buf)); - assert_eq!(&buf[..], b"hello world!"); - }); - - let stream = p!(TcpStream::connect(("localhost", port))); - let mut stream = p!(ClientBuilder::new() - .anchor_certificates(&[certificate()]) - .handshake("foobar.com", stream)); - - p!(stream.write_all(b"hello world!")); - - handle.join().unwrap(); - } - - #[test] - fn client_bad_cert() { - let _ = env_logger::try_init(); - - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - - let stream = p!(listener.accept()).0; - let _ = ctx.handshake(stream); - }); - - let stream = p!(TcpStream::connect(("localhost", port))); - assert!(ClientBuilder::new() - .handshake("foobar.com", stream) - .is_err()); - - handle.join().unwrap(); - } - - #[test] - #[ignore] - fn client() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - - let stream = p!(listener.accept()).0; - let mut stream = p!(ctx.handshake(stream)); - - let mut buf = [0; 12]; - p!(stream.read(&mut buf)); - assert_eq!(&buf[..], b"hello world!"); - }); - - let stream = p!(TcpStream::connect(("localhost", port))); - let mut stream = p!(ClientBuilder::new() - .anchor_certificates(&[certificate()]) - .handshake("foobar.com", stream)); - p!(stream.write_all(b"hello world!")); - - handle.join().unwrap(); - } - - #[test] - fn negotiated_cipher() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - p!(ctx.set_enabled_ciphers(&[ - CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - ])); - - let stream = p!(listener.accept()).0; - let mut stream = p!(ctx.handshake(stream)); - assert_eq!( - CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - p!(stream.context().negotiated_cipher()) - ); - let mut buf = [0; 1]; - p!(stream.read(&mut buf)); - }); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::CLIENT, - SslConnectionType::STREAM - )); - p!(ctx.set_break_on_server_auth(true)); - p!(ctx.set_enabled_ciphers(&[ - CipherSuite::TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - ])); - let stream = p!(TcpStream::connect(("localhost", port))); - - let stream = match ctx.handshake(stream) { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Interrupted(stream)) => stream, - Err(err) => panic!("unexpected error {err:?}"), - }; - - let mut stream = p!(stream.handshake()); - assert_eq!( - CipherSuite::TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - p!(stream.context().negotiated_cipher()) - ); - p!(stream.write(&[0])); - - handle.join().unwrap(); - } - - #[test] - fn dh_params() { - let params = include_bytes!("../../../test/dhparam.der"); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - assert!(p!(ctx.diffie_hellman_params()).is_none()); - p!(ctx.set_diffie_hellman_params(params)); - assert_eq!(p!(ctx.diffie_hellman_params()).unwrap(), ¶ms[..]); - } - - #[test] - fn try_authenticate_no_cert() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - p!(ctx.set_client_side_authenticate(SslAuthenticate::TRY)); - let cert = certificate(); - p!(ctx.add_certificate_authorities(&[cert])); - - let stream = p!(listener.accept()).0; - let mut stream = p!(ctx.handshake(stream)); - let mut buf = [0; 1]; - p!(stream.read(&mut buf)); - }); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::CLIENT, - SslConnectionType::STREAM - )); - p!(ctx.set_break_on_server_auth(true)); - let stream = p!(TcpStream::connect(("localhost", port))); - - let stream = match ctx.handshake(stream) { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Interrupted(stream)) => stream, - Err(err) => panic!("unexpected error {err:?}"), - }; - - let mut stream = p!(stream.handshake()); - p!(stream.write(&[0])); - - handle.join().unwrap(); - } - - #[test] - fn always_authenticate_no_cert() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - p!(ctx.set_client_side_authenticate(SslAuthenticate::ALWAYS)); - - let stream = p!(listener.accept()).0; - - match ctx.handshake(stream) { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Failure(_)) => {} - Err(err) => panic!("unexpected error {err:?}"), - } - }); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::CLIENT, - SslConnectionType::STREAM - )); - p!(ctx.set_break_on_server_auth(true)); - let stream = p!(TcpStream::connect(("localhost", port))); - - let stream = match ctx.handshake(stream) { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Interrupted(stream)) => stream, - Err(err) => panic!("unexpected error {err:?}"), - }; - - match stream.handshake() { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Failure(_)) => {} - Err(err) => panic!("unexpected error {err:?}"), - } - - handle.join().unwrap(); - } - - #[test] - fn always_authenticate_with_cert() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - p!(ctx.set_client_side_authenticate(SslAuthenticate::ALWAYS)); - - let stream = p!(listener.accept()).0; - - match ctx.handshake(stream) { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Failure(_)) => {} - Err(err) => panic!("unexpected error {err:?}"), - } - }); - - let mut ctx = p!(SslContext::new( - SslProtocolSide::CLIENT, - SslConnectionType::STREAM - )); - p!(ctx.set_break_on_server_auth(true)); - let dir = p!(tempdir()); - let identity = identity(dir.path()); - p!(ctx.set_certificate(&identity, &[])); - let stream = p!(TcpStream::connect(("localhost", port))); - - let stream = match ctx.handshake(stream) { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Interrupted(stream)) => stream, - Err(err) => panic!("unexpected error {err:?}"), - }; - - match stream.handshake() { - Ok(_) => panic!("unexpected success"), - Err(HandshakeError::Failure(_)) => {} - Err(err) => panic!("unexpected error {err:?}"), - } - - handle.join().unwrap(); - } - - #[test] - fn certificate_authorities() { - let mut ctx = p!(SslContext::new( - SslProtocolSide::SERVER, - SslConnectionType::STREAM - )); - assert!(p!(ctx.certificate_authorities()).is_none()); - p!(ctx.set_certificate_authorities(&[certificate()])); - assert_eq!(p!(ctx.certificate_authorities()).unwrap().len(), 1); - } - - #[test] - #[ignore] - fn close() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let identity = identity(dir.path()); - let builder = ServerBuilder::new(&identity, &[]); - - let stream = p!(listener.accept()).0; - let mut stream = p!(builder.handshake(stream)); - p!(stream.close()); - }); - - let stream = p!(TcpStream::connect(("localhost", port))); - let mut stream = p!(ClientBuilder::new() - .anchor_certificates(&[certificate()]) - .handshake("foobar.com", stream)); - - let mut buf = [0; 1]; - assert_eq!(p!(stream.read(&mut buf)), 0); - p!(stream.close()); - - p!(handle.join()); - } - - #[test] - #[ignore] - fn short_read() { - let listener = p!(TcpListener::bind("localhost:0")); - let port = p!(listener.local_addr()).port(); - - let handle = thread::spawn(move || { - let dir = p!(tempdir()); - - let identity = identity(dir.path()); - let builder = ServerBuilder::new(&identity, &[]); - - let stream = p!(listener.accept()).0; - let mut stream = p!(builder.handshake(stream)); - - stream.write_all(b"hello").unwrap(); - // make sure stream doesn't close - stream - }); - - let stream = p!(TcpStream::connect(("localhost", port))); - let mut stream = p!(ClientBuilder::new() - .anchor_certificates(&[certificate()]) - .handshake("foobar.com", stream)); - - let mut b = [0; 1]; - stream.read_exact(&mut b).unwrap(); - assert_eq!(stream.context().buffered_read_size().unwrap(), 4); - let mut b = [0; 5]; - let read = stream.read(&mut b).unwrap(); - assert_eq!(read, 4); - - p!(handle.join()); - } -} diff --git a/vendor/security-framework/src/os/macos/transform.rs b/vendor/security-framework/src/os/macos/transform.rs deleted file mode 100644 index d03bc1f7..00000000 --- a/vendor/security-framework/src/os/macos/transform.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Transform support - -use core_foundation::base::{CFType, TCFType}; -use core_foundation::error::CFError; -use core_foundation::string::CFString; -use security_framework_sys::transform::*; -use std::ptr; - -declare_TCFType! { - /// A type representing a transform. - SecTransform, SecTransformRef -} -impl_TCFType!(SecTransform, SecTransformRef, SecTransformGetTypeID); - -unsafe impl Sync for SecTransform {} -unsafe impl Send for SecTransform {} - -impl SecTransform { - /// Sets an attribute of the transform. - pub fn set_attribute<T>(&mut self, key: &CFString, value: &T) -> Result<(), CFError> - where - T: TCFType, - { - unsafe { - let mut error = ptr::null_mut(); - SecTransformSetAttribute( - self.0, - key.as_concrete_TypeRef(), - value.as_CFTypeRef(), - &mut error, - ); - if !error.is_null() { - return Err(CFError::wrap_under_create_rule(error)); - } - - Ok(()) - } - } - - /// Executes the transform. - /// - /// The return type depends on the type of transform. - pub fn execute(&mut self) -> Result<CFType, CFError> { - unsafe { - let mut error = ptr::null_mut(); - let result = SecTransformExecute(self.0, &mut error); - if result.is_null() { - return Err(CFError::wrap_under_create_rule(error)); - } - - Ok(CFType::wrap_under_create_rule(result)) - } - } -} diff --git a/vendor/security-framework/src/os/mod.rs b/vendor/security-framework/src/os/mod.rs deleted file mode 100644 index ec7e38b3..00000000 --- a/vendor/security-framework/src/os/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! OS specific extensions. - -#[cfg(target_os = "macos")] -pub mod macos; |
