Skip to main content

security/
policy.rs

1use serde::Serialize;
2use serde_json::Value;
3
4use crate::bridge::{self, Handle};
5use crate::error::{Result, SecurityError};
6
7/// Mirrors `SecRevocationFlags`.
8pub type RevocationFlags = u32;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11/// Mirrors named `SecPolicyCreate*` policy selectors.
12pub enum PolicyIdentifier {
13    /// Mirrors a named `SecPolicyCreate*` selector.
14    AppleX509Basic,
15    /// Mirrors a named `SecPolicyCreate*` selector.
16    AppleSsl,
17    /// Mirrors a named `SecPolicyCreate*` selector.
18    AppleSmime,
19    /// Mirrors a named `SecPolicyCreate*` selector.
20    AppleEap,
21    /// Mirrors a named `SecPolicyCreate*` selector.
22    AppleIpsec,
23    /// Mirrors a named `SecPolicyCreate*` selector.
24    ApplePkinitClient,
25    /// Mirrors a named `SecPolicyCreate*` selector.
26    ApplePkinitServer,
27    /// Mirrors a named `SecPolicyCreate*` selector.
28    AppleCodeSigning,
29    /// Mirrors a named `SecPolicyCreate*` selector.
30    MacAppStoreReceipt,
31    /// Mirrors a named `SecPolicyCreate*` selector.
32    AppleIdValidation,
33    /// Mirrors a named `SecPolicyCreate*` selector.
34    AppleTimeStamping,
35    /// Mirrors a named `SecPolicyCreate*` selector.
36    AppleRevocation,
37    /// Mirrors a named `SecPolicyCreate*` selector.
38    ApplePassbookSigning,
39    /// Mirrors a named `SecPolicyCreate*` selector.
40    ApplePayIssuerEncryption,
41    /// Mirrors a named `SecPolicyCreate*` selector.
42    AppleSslServer,
43    /// Mirrors a named `SecPolicyCreate*` selector.
44    AppleSslClient,
45    /// Mirrors a named `SecPolicyCreate*` selector.
46    AppleEapServer,
47    /// Mirrors a named `SecPolicyCreate*` selector.
48    AppleEapClient,
49    /// Mirrors a named `SecPolicyCreate*` selector.
50    AppleIpsecServer,
51    /// Mirrors a named `SecPolicyCreate*` selector.
52    AppleIpsecClient,
53}
54
55impl PolicyIdentifier {
56    const fn as_bridge_name(self) -> &'static str {
57        match self {
58            Self::AppleX509Basic => "apple_x509_basic",
59            Self::AppleSsl => "apple_ssl",
60            Self::AppleSmime => "apple_smime",
61            Self::AppleEap => "apple_eap",
62            Self::AppleIpsec => "apple_ipsec",
63            Self::ApplePkinitClient => "apple_pkinit_client",
64            Self::ApplePkinitServer => "apple_pkinit_server",
65            Self::AppleCodeSigning => "apple_code_signing",
66            Self::MacAppStoreReceipt => "mac_app_store_receipt",
67            Self::AppleIdValidation => "apple_id_validation",
68            Self::AppleTimeStamping => "apple_time_stamping",
69            Self::AppleRevocation => "apple_revocation",
70            Self::ApplePassbookSigning => "apple_passbook_signing",
71            Self::ApplePayIssuerEncryption => "apple_pay_issuer_encryption",
72            Self::AppleSslServer => "apple_ssl_server",
73            Self::AppleSslClient => "apple_ssl_client",
74            Self::AppleEapServer => "apple_eap_server",
75            Self::AppleEapClient => "apple_eap_client",
76            Self::AppleIpsecServer => "apple_ipsec_server",
77            Self::AppleIpsecClient => "apple_ipsec_client",
78        }
79    }
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
83#[serde(untagged)]
84/// Mirrors name inputs passed to `SecPolicyCreateWithProperties`.
85pub enum PolicyName {
86    /// Mirrors a name form accepted by `SecPolicyCreateWithProperties`.
87    Single(String),
88    /// Mirrors a name form accepted by `SecPolicyCreateWithProperties`.
89    Multiple(Vec<String>),
90}
91
92impl From<String> for PolicyName {
93    fn from(value: String) -> Self {
94        Self::Single(value)
95    }
96}
97
98impl From<&str> for PolicyName {
99    fn from(value: &str) -> Self {
100        Self::Single(value.to_owned())
101    }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
105/// Mirrors the property dictionary passed to `SecPolicyCreateWithProperties`.
106pub struct PolicyProperties {
107    #[serde(skip_serializing_if = "Option::is_none")]
108    /// Mirrors a property accepted by `SecPolicyCreateWithProperties`.
109    pub name: Option<PolicyName>,
110    #[serde(skip_serializing_if = "Option::is_none")]
111    /// Mirrors a property accepted by `SecPolicyCreateWithProperties`.
112    pub client: Option<bool>,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    /// Mirrors a property accepted by `SecPolicyCreateWithProperties`.
115    pub revocation_flags: Option<RevocationFlags>,
116    #[serde(skip_serializing_if = "Option::is_none")]
117    /// Mirrors a property accepted by `SecPolicyCreateWithProperties`.
118    pub team_identifier: Option<String>,
119}
120
121impl PolicyProperties {
122    const fn is_empty(&self) -> bool {
123        self.name.is_none()
124            && self.client.is_none()
125            && self.revocation_flags.is_none()
126            && self.team_identifier.is_none()
127    }
128}
129
130#[derive(Debug)]
131/// Wraps `SecPolicyRef`.
132pub struct Policy {
133    handle: Handle,
134}
135
136impl Policy {
137    /// Wraps the corresponding `SecPolicyRef` operation.
138    pub fn type_id() -> usize {
139        unsafe { bridge::security_policy_get_type_id() }
140    }
141
142    pub(crate) fn from_handle(handle: Handle) -> Self {
143        Self { handle }
144    }
145
146    pub(crate) fn handle(&self) -> &Handle {
147        &self.handle
148    }
149
150    /// Wraps the corresponding `SecPolicyRef` operation.
151    pub fn basic_x509() -> Result<Self> {
152        let mut status = 0;
153        let mut error = std::ptr::null_mut();
154        let raw = unsafe { bridge::security_policy_create_basic_x509(&mut status, &mut error) };
155        bridge::required_handle("security_policy_create_basic_x509", raw, status, error)
156            .map(Self::from_handle)
157    }
158
159    /// Wraps the corresponding `SecPolicyRef` operation.
160    pub fn ssl(server: bool, hostname: Option<&str>) -> Result<Self> {
161        let hostname = hostname.map(bridge::cstring).transpose()?;
162        let mut status = 0;
163        let mut error = std::ptr::null_mut();
164        let raw = unsafe {
165            bridge::security_policy_create_ssl(
166                server,
167                hostname
168                    .as_ref()
169                    .map_or(std::ptr::null(), |value| value.as_c_str().as_ptr()),
170                &mut status,
171                &mut error,
172            )
173        };
174        bridge::required_handle("security_policy_create_ssl", raw, status, error)
175            .map(Self::from_handle)
176    }
177
178    /// Wraps the corresponding `SecPolicyRef` operation.
179    pub fn revocation(flags: RevocationFlags) -> Result<Self> {
180        let mut status = 0;
181        let mut error = std::ptr::null_mut();
182        let raw =
183            unsafe { bridge::security_policy_create_revocation(flags, &mut status, &mut error) };
184        bridge::required_handle("security_policy_create_revocation", raw, status, error)
185            .map(Self::from_handle)
186    }
187
188    /// Wraps the corresponding `SecPolicyRef` operation.
189    pub fn with_properties(
190        identifier: PolicyIdentifier,
191        properties: &PolicyProperties,
192    ) -> Result<Self> {
193        let identifier = bridge::cstring(identifier.as_bridge_name())?;
194        let properties = if properties.is_empty() {
195            None
196        } else {
197            let json = serde_json::to_string(properties).map_err(|error| {
198                SecurityError::Serialization(format!("policy properties JSON failed: {error}"))
199            })?;
200            Some(bridge::cstring(&json)?)
201        };
202        let mut status = 0;
203        let mut error = std::ptr::null_mut();
204        let raw = unsafe {
205            bridge::security_policy_create_with_properties(
206                identifier.as_ptr(),
207                properties
208                    .as_ref()
209                    .map_or(std::ptr::null(), |value| value.as_c_str().as_ptr()),
210                &mut status,
211                &mut error,
212            )
213        };
214        bridge::required_handle("security_policy_create_with_properties", raw, status, error)
215            .map(Self::from_handle)
216    }
217
218    /// Wraps the corresponding `SecPolicyRef` operation.
219    pub fn properties(&self) -> Result<Value> {
220        let mut status = 0;
221        let mut error = std::ptr::null_mut();
222        let raw = unsafe {
223            bridge::security_policy_copy_properties(self.handle.as_ptr(), &mut status, &mut error)
224        };
225        bridge::required_json("security_policy_copy_properties", raw, status, error)
226    }
227}