blob: f280341c844b9242bd868edcea777e24ce7f4050 [file] [log] [blame]
Janis Danisevskis78bd48c2020-07-21 12:27:13 -07001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! This crate provides access control primitives for Keystore 2.0.
16//! It provides high level functions for checking permissions in the keystore2 and keystore2_key
17//! SELinux classes based on the keystore2_selinux backend.
18//! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
19//! defined by keystore2 and keystore2_key respectively.
20
Janis Danisevskisa2f48502021-10-18 16:07:09 -070021use crate::error::Error as KsError;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070022use android_system_keystore2::aidl::android::system::keystore2::{
23 Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
24};
Janis Danisevskisa2f48502021-10-18 16:07:09 -070025use anyhow::Context as AnyhowContext;
26use keystore2_selinux as selinux;
27use lazy_static::lazy_static;
Janis Danisevskis56af0312021-10-18 16:11:41 -070028use selinux::{implement_class, Backend, ClassPermission};
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070029use std::cmp::PartialEq;
30use std::convert::From;
Janis Danisevskis935e6c62020-08-18 12:52:27 -070031use std::ffi::CStr;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070032
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070033// Replace getcon with a mock in the test situation
34#[cfg(not(test))]
35use selinux::getcon;
36#[cfg(test)]
37use tests::test_getcon as getcon;
38
Janis Danisevskis4ad056f2020-08-05 19:46:46 +000039lazy_static! {
40 // Panicking here is allowed because keystore cannot function without this backend
41 // and it would happen early and indicate a gross misconfiguration of the device.
42 static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
43 selinux::KeystoreKeyBackend::new().unwrap();
44}
45
46fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
47 KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
48}
49
Janis Danisevskis39d57e72021-10-19 16:56:20 -070050implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070051 /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
52 /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
Janis Danisevskis39d57e72021-10-19 16:56:20 -070053 /// the SELinux permissions.
54 #[repr(i32)]
55 #[selinux(class_name = keystore2_key)]
56 #[derive(Clone, Copy, Debug, PartialEq)]
57 pub enum KeyPerm {
58 /// Checked when convert_storage_key_to_ephemeral is called.
59 #[selinux(name = convert_storage_key_to_ephemeral)]
60 ConvertStorageKeyToEphemeral = KeyPermission::CONVERT_STORAGE_KEY_TO_EPHEMERAL.0,
61 /// Checked when the caller tries do delete a key.
62 #[selinux(name = delete)]
63 Delete = KeyPermission::DELETE.0,
64 /// Checked when the caller tries to use a unique id.
65 #[selinux(name = gen_unique_id)]
66 GenUniqueId = KeyPermission::GEN_UNIQUE_ID.0,
67 /// Checked when the caller tries to load a key.
68 #[selinux(name = get_info)]
69 GetInfo = KeyPermission::GET_INFO.0,
70 /// Checked when the caller attempts to grant a key to another uid.
71 /// Also used for gating key migration attempts.
72 #[selinux(name = grant)]
73 Grant = KeyPermission::GRANT.0,
74 /// Checked when the caller attempts to use Domain::BLOB.
75 #[selinux(name = manage_blob)]
76 ManageBlob = KeyPermission::MANAGE_BLOB.0,
77 /// Checked when the caller tries to create a key which implies rebinding
78 /// an alias to the new key.
79 #[selinux(name = rebind)]
80 Rebind = KeyPermission::REBIND.0,
81 /// Checked when the caller attempts to create a forced operation.
82 #[selinux(name = req_forced_op)]
83 ReqForcedOp = KeyPermission::REQ_FORCED_OP.0,
84 /// Checked when the caller attempts to update public key artifacts.
85 #[selinux(name = update)]
86 Update = KeyPermission::UPDATE.0,
87 /// Checked when the caller attempts to use a private or public key.
88 #[selinux(name = use)]
89 Use = KeyPermission::USE.0,
90 /// Checked when the caller attempts to use device ids for attestation.
91 #[selinux(name = use_dev_id)]
92 UseDevId = KeyPermission::USE_DEV_ID.0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070093 }
94);
95
Janis Danisevskis56af0312021-10-18 16:11:41 -070096implement_class!(
Janis Danisevskis78bd48c2020-07-21 12:27:13 -070097 /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
98 /// Using the implement_permission macro we get the same features as `KeyPerm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -070099 #[selinux(class_name = keystore2)]
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700100 #[derive(Clone, Copy, Debug, PartialEq)]
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700101 pub enum KeystorePerm {
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700102 /// Checked when a new auth token is installed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700103 #[selinux(name = add_auth)]
104 AddAuth,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700105 /// Checked when an app is uninstalled or wiped.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700106 #[selinux(name = clear_ns)]
107 ClearNs,
Hasini Gunasinghe9ee18412021-03-11 20:12:44 +0000108 /// Checked when the user state is queried from Keystore 2.0.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700109 #[selinux(name = get_state)]
110 GetState,
Janis Danisevskisee10b5f2020-09-22 16:42:35 -0700111 /// Checked when Keystore 2.0 is asked to list a namespace that the caller
112 /// does not have the get_info permission for.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700113 #[selinux(name = list)]
114 List,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700115 /// Checked when Keystore 2.0 gets locked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700116 #[selinux(name = lock)]
117 Lock,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700118 /// Checked when Keystore 2.0 shall be reset.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700119 #[selinux(name = reset)]
120 Reset,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700121 /// Checked when Keystore 2.0 shall be unlocked.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700122 #[selinux(name = unlock)]
123 Unlock,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000124 /// Checked when user is added or removed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700125 #[selinux(name = change_user)]
126 ChangeUser,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000127 /// Checked when password of the user is changed.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700128 #[selinux(name = change_password)]
129 ChangePassword,
Hasini Gunasinghe803c2d42021-01-27 00:48:40 +0000130 /// Checked when a UID is cleared.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700131 #[selinux(name = clear_uid)]
132 ClearUID,
Hasini Gunasinghe5fc95252020-12-04 00:35:08 +0000133 /// Checked when Credstore calls IKeystoreAuthorization to obtain auth tokens.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700134 #[selinux(name = get_auth_token)]
135 GetAuthToken,
Satya Tangirala5b9e5b12021-03-09 12:54:21 -0800136 /// Checked when earlyBootEnded() is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700137 #[selinux(name = early_boot_ended)]
138 EarlyBootEnded,
Janis Danisevskis333b7c02021-03-23 18:57:41 -0700139 /// Checked when IKeystoreMaintenance::onDeviceOffBody is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700140 #[selinux(name = report_off_body)]
141 ReportOffBody,
142 /// Checked when IkeystoreMetrics::pullMetrics is called.
143 #[selinux(name = pull_metrics)]
144 PullMetrics,
Paul Crowley46c703e2021-08-06 15:13:53 -0700145 /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
Janis Danisevskis751d2c82021-10-18 15:37:09 -0700146 #[selinux(name = delete_all_keys)]
147 DeleteAllKeys,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700148 }
149);
150
151/// Represents a set of `KeyPerm` permissions.
152/// `IntoIterator` is implemented for this struct allowing the iteration through all the
153/// permissions in the set.
154/// It also implements a function `includes(self, other)` that checks if the permissions
155/// in `other` are included in `self`.
156///
157/// KeyPermSet can be created with the macro `key_perm_set![]`.
158///
159/// ## Example
160/// ```
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700161/// let perms1 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob, KeyPerm::Grant];
162/// let perms2 = key_perm_set![KeyPerm::Use, KeyPerm::ManageBlob];
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700163///
164/// assert!(perms1.includes(perms2))
165/// assert!(!perms2.includes(perms1))
166///
167/// let i = perms1.into_iter();
168/// // iteration in ascending order of the permission's numeric representation.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700169/// assert_eq(Some(KeyPerm::ManageBlob), i.next());
170/// assert_eq(Some(KeyPerm::Grant), i.next());
171/// assert_eq(Some(KeyPerm::Use), i.next());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700172/// assert_eq(None, i.next());
173/// ```
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700174#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
175pub struct KeyPermSet(pub i32);
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700176
177mod perm {
178 use super::*;
179
180 pub struct IntoIter {
181 vec: KeyPermSet,
182 pos: u8,
183 }
184
185 impl IntoIter {
186 pub fn new(v: KeyPermSet) -> Self {
187 Self { vec: v, pos: 0 }
188 }
189 }
190
191 impl std::iter::Iterator for IntoIter {
192 type Item = KeyPerm;
193
194 fn next(&mut self) -> Option<Self::Item> {
195 loop {
196 if self.pos == 32 {
197 return None;
198 }
199 let p = self.vec.0 & (1 << self.pos);
200 self.pos += 1;
201 if p != 0 {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700202 return Some(KeyPerm::from(p));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700203 }
204 }
205 }
206 }
207}
208
209impl From<KeyPerm> for KeyPermSet {
210 fn from(p: KeyPerm) -> Self {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700211 Self(p as i32)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700212 }
213}
214
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700215/// allow conversion from the AIDL wire type i32 to a permission set.
216impl From<i32> for KeyPermSet {
217 fn from(p: i32) -> Self {
218 Self(p)
219 }
220}
221
222impl From<KeyPermSet> for i32 {
223 fn from(p: KeyPermSet) -> i32 {
224 p.0
225 }
226}
227
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700228impl KeyPermSet {
229 /// Returns true iff this permission set has all of the permissions that are in `other`.
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700230 pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700231 let o: KeyPermSet = other.into();
232 (self.0 & o.0) == o.0
233 }
234}
235
236/// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
237///
238/// ## Example
239/// ```
240/// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
241/// ```
242#[macro_export]
243macro_rules! key_perm_set {
244 () => { KeyPermSet(0) };
245 ($head:expr $(, $tail:expr)* $(,)?) => {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700246 KeyPermSet($head as i32 $(| $tail as i32)*)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700247 };
248}
249
250impl IntoIterator for KeyPermSet {
251 type Item = KeyPerm;
252 type IntoIter = perm::IntoIter;
253
254 fn into_iter(self) -> Self::IntoIter {
255 Self::IntoIter::new(self)
256 }
257}
258
Janis Danisevskis56af0312021-10-18 16:11:41 -0700259/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` may access
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700260/// the given permision `perm` of the `keystore2` security class.
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700261pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700262 let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
Janis Danisevskis56af0312021-10-18 16:11:41 -0700263 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700264}
265
Janis Danisevskis56af0312021-10-18 16:11:41 -0700266/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt` has
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700267/// all the permissions indicated in `access_vec` for the target domain indicated by the key
268/// descriptor `key` in the security class `keystore2_key`.
269///
270/// Also checks if the caller has the grant permission for the given target domain.
271///
272/// Attempts to grant the grant permission are always denied.
273///
274/// The only viable target domains are
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700275/// * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
276/// * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700277/// SELinux keystore key backend, and the result is used
278/// as target context.
279pub fn check_grant_permission(
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700280 caller_ctx: &CStr,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700281 access_vec: KeyPermSet,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700282 key: &KeyDescriptor,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700283) -> anyhow::Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700284 let target_context = match key.domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700285 Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
286 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
287 .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700288 _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
289 };
290
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700291 selinux::check_permission(caller_ctx, &target_context, KeyPerm::Grant)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700292 .context("Grant permission is required when granting.")?;
293
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700294 if access_vec.includes(KeyPerm::Grant) {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700295 return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
296 }
297
298 for p in access_vec.into_iter() {
Janis Danisevskis56af0312021-10-18 16:11:41 -0700299 selinux::check_permission(caller_ctx, &target_context, p).context(format!(
300 "check_grant_permission: check_permission failed. \
301 The caller may have tried to grant a permission that they don't possess. {:?}",
302 p
303 ))?
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700304 }
305 Ok(())
306}
307
Janis Danisevskis56af0312021-10-18 16:11:41 -0700308/// Uses `selinux::check_permission` to check if the given caller context `caller_cxt`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700309/// has the permissions indicated by `perm` for the target domain indicated by the key
310/// descriptor `key` in the security class `keystore2_key`.
311///
312/// The behavior differs slightly depending on the selected target domain:
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700313/// * `Domain::APP` u:r:keystore:s0 is used as target context.
314/// * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700315/// backend, and the result is used as target context.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700316/// * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700317/// to the one supplied in `perm`.
Janis Danisevskis56af0312021-10-18 16:11:41 -0700318/// * `Domain::GRANT` Does not use selinux::check_permission. Instead the `access_vector`
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700319/// parameter is queried for permission, which must be supplied in this case.
320///
321/// ## Return values.
322/// * Ok(()) If the requested permissions were granted.
323/// * Err(selinux::Error::perm()) If the requested permissions were denied.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700324/// * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
325/// was supplied. It is also produced if `Domain::KEY_ID` was selected, and
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700326/// on various unexpected backend failures.
327pub fn check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800328 caller_uid: u32,
Janis Danisevskis935e6c62020-08-18 12:52:27 -0700329 caller_ctx: &CStr,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700330 perm: KeyPerm,
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700331 key: &KeyDescriptor,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700332 access_vector: &Option<KeyPermSet>,
333) -> anyhow::Result<()> {
Janis Danisevskis45760022021-01-19 16:34:10 -0800334 // If an access vector was supplied, the key is either accessed by GRANT or by KEY_ID.
335 // In the former case, key.domain was set to GRANT and we check the failure cases
336 // further below. If the access is requested by KEY_ID, key.domain would have been
337 // resolved to APP or SELINUX depending on where the key actually resides.
338 // Either way we can return here immediately if the access vector covers the requested
339 // permission. If it does not, we can still check if the caller has access by means of
340 // ownership.
341 if let Some(access_vector) = access_vector {
342 if access_vector.includes(perm) {
343 return Ok(());
344 }
345 }
346
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700347 let target_context = match key.domain {
348 // apps get the default keystore context
Janis Danisevskis45760022021-01-19 16:34:10 -0800349 Domain::APP => {
350 if caller_uid as i64 != key.nspace {
351 return Err(selinux::Error::perm())
352 .context("Trying to access key without ownership.");
353 }
354 getcon().context("check_key_permission: getcon failed.")?
355 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700356 Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
357 .context("check_key_permission: Domain::SELINUX: Failed to lookup namespace.")?,
358 Domain::GRANT => {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700359 match access_vector {
Janis Danisevskis45760022021-01-19 16:34:10 -0800360 Some(_) => {
361 return Err(selinux::Error::perm())
Janis Danisevskis56af0312021-10-18 16:11:41 -0700362 .context(format!("\"{}\" not granted", perm.name()));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700363 }
364 None => {
365 // If DOMAIN_GRANT was selected an access vector must be supplied.
366 return Err(KsError::sys()).context(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700367 "Cannot check permission for Domain::GRANT without access vector.",
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700368 );
369 }
370 }
371 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700372 Domain::KEY_ID => {
373 // We should never be called with `Domain::KEY_ID. The database
374 // lookup should have converted this into one of `Domain::APP`
375 // or `Domain::SELINUX`.
376 return Err(KsError::sys()).context("Cannot check permission for Domain::KEY_ID.");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700377 }
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700378 Domain::BLOB => {
379 let tctx = lookup_keystore2_key_context(key.nspace)
380 .context("Domain::BLOB: Failed to lookup namespace.")?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700381 // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
382 // permission in addition to the requested permission.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700383 selinux::check_permission(caller_ctx, &tctx, KeyPerm::ManageBlob)?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700384
385 tctx
386 }
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700387 _ => {
388 return Err(KsError::sys())
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700389 .context(format!("Unknown domain value: \"{:?}\".", key.domain))
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700390 }
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700391 };
392
Janis Danisevskis56af0312021-10-18 16:11:41 -0700393 selinux::check_permission(caller_ctx, &target_context, perm)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700394}
395
396#[cfg(test)]
397mod tests {
398 use super::*;
399 use anyhow::anyhow;
400 use anyhow::Result;
401 use keystore2_selinux::*;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700402
403 const ALL_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700404 KeyPerm::ManageBlob,
405 KeyPerm::Delete,
406 KeyPerm::UseDevId,
407 KeyPerm::ReqForcedOp,
408 KeyPerm::GenUniqueId,
409 KeyPerm::Grant,
410 KeyPerm::GetInfo,
411 KeyPerm::Rebind,
412 KeyPerm::Update,
413 KeyPerm::Use,
414 KeyPerm::ConvertStorageKeyToEphemeral,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700415 ];
416
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800417 const SYSTEM_SERVER_PERMISSIONS_NO_GRANT: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700418 KeyPerm::Delete,
419 KeyPerm::UseDevId,
420 // No KeyPerm::Grant
421 KeyPerm::GetInfo,
422 KeyPerm::Rebind,
423 KeyPerm::Update,
424 KeyPerm::Use,
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800425 ];
426
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700427 const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700428 KeyPerm::ManageBlob,
429 KeyPerm::Delete,
430 KeyPerm::UseDevId,
431 KeyPerm::ReqForcedOp,
432 KeyPerm::GenUniqueId,
433 // No KeyPerm::Grant
434 KeyPerm::GetInfo,
435 KeyPerm::Rebind,
436 KeyPerm::Update,
437 KeyPerm::Use,
438 KeyPerm::ConvertStorageKeyToEphemeral,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700439 ];
440
441 const UNPRIV_PERMS: KeyPermSet = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700442 KeyPerm::Delete,
443 KeyPerm::GetInfo,
444 KeyPerm::Rebind,
445 KeyPerm::Update,
446 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700447 ];
448
449 /// The su_key namespace as defined in su.te and keystore_key_contexts of the
450 /// SePolicy (system/sepolicy).
451 const SU_KEY_NAMESPACE: i32 = 0;
452 /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
453 /// SePolicy (system/sepolicy).
454 const SHELL_KEY_NAMESPACE: i32 = 1;
455
456 pub fn test_getcon() -> Result<Context> {
457 Context::new("u:object_r:keystore:s0")
458 }
459
460 // This macro evaluates the given expression and checks that
461 // a) evaluated to Result::Err() and that
462 // b) the wrapped error is selinux::Error::perm() (permission denied).
463 // We use a macro here because a function would mask which invocation caused the failure.
464 //
465 // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
466 macro_rules! assert_perm_failed {
467 ($test_function:expr) => {
468 let result = $test_function;
469 assert!(result.is_err(), "Permission check should have failed.");
470 assert_eq!(
471 Some(&selinux::Error::perm()),
472 result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
473 );
474 };
475 }
476
477 fn check_context() -> Result<(selinux::Context, i32, bool)> {
478 // Calling the non mocked selinux::getcon here intended.
479 let context = selinux::getcon()?;
480 match context.to_str().unwrap() {
481 "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
482 "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
483 c => Err(anyhow!(format!(
484 "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
485 c
486 ))),
487 }
488 }
489
490 #[test]
491 fn check_keystore_permission_test() -> Result<()> {
492 let system_server_ctx = Context::new("u:r:system_server:s0")?;
Janis Danisevskisa916d992021-10-19 15:46:09 -0700493 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::AddAuth).is_ok());
494 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearNs).is_ok());
495 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::GetState).is_ok());
496 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Lock).is_ok());
497 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Reset).is_ok());
498 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::Unlock).is_ok());
499 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangeUser).is_ok());
500 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ChangePassword).is_ok());
501 assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::ClearUID).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700502 let shell_ctx = Context::new("u:r:shell:s0")?;
Janis Danisevskisa916d992021-10-19 15:46:09 -0700503 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::AddAuth));
504 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearNs));
505 assert!(check_keystore_permission(&shell_ctx, KeystorePerm::GetState).is_ok());
506 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::List));
507 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Lock));
508 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Reset));
509 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::Unlock));
510 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangeUser));
511 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ChangePassword));
512 assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::ClearUID));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700513 Ok(())
514 }
515
516 #[test]
517 fn check_grant_permission_app() -> Result<()> {
518 let system_server_ctx = Context::new("u:r:system_server:s0")?;
519 let shell_ctx = Context::new("u:r:shell:s0")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700520 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800521 check_grant_permission(&system_server_ctx, SYSTEM_SERVER_PERMISSIONS_NO_GRANT, &key)
522 .expect("Grant permission check failed.");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700523
Janis Danisevskisa31dd9e2021-01-30 00:13:17 -0800524 // attempts to grant the grant permission must always fail even when privileged.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700525 assert_perm_failed!(check_grant_permission(
526 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700527 KeyPerm::Grant.into(),
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700528 &key
529 ));
530 // unprivileged grant attempts always fail. shell does not have the grant permission.
531 assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
532 Ok(())
533 }
534
535 #[test]
536 fn check_grant_permission_selinux() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700537 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700538 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700539 domain: Domain::SELINUX,
540 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700541 alias: None,
542 blob: None,
543 };
544 if is_su {
545 assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
546 // attempts to grant the grant permission must always fail even when privileged.
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700547 assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::Grant.into(), &key));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700548 } else {
549 // unprivileged grant attempts always fail. shell does not have the grant permission.
550 assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
551 }
552 Ok(())
553 }
554
555 #[test]
556 fn check_key_permission_domain_grant() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700557 let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700558
559 assert_perm_failed!(check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800560 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700561 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700562 KeyPerm::Grant,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700563 &key,
564 &Some(UNPRIV_PERMS)
565 ));
566
567 check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800568 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700569 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700570 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700571 &key,
572 &Some(ALL_PERMS),
573 )
574 }
575
576 #[test]
577 fn check_key_permission_domain_app() -> Result<()> {
578 let system_server_ctx = Context::new("u:r:system_server:s0")?;
579 let shell_ctx = Context::new("u:r:shell:s0")?;
580 let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700581
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700582 let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700583
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700584 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Use, &key, &None).is_ok());
585 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Delete, &key, &None).is_ok());
586 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
587 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Rebind, &key, &None).is_ok());
588 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Update, &key, &None).is_ok());
589 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::Grant, &key, &None).is_ok());
590 assert!(check_key_permission(0, &system_server_ctx, KeyPerm::UseDevId, &key, &None).is_ok());
591 assert!(check_key_permission(0, &gmscore_app, KeyPerm::GenUniqueId, &key, &None).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700592
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700593 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Use, &key, &None).is_ok());
594 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Delete, &key, &None).is_ok());
595 assert!(check_key_permission(0, &shell_ctx, KeyPerm::GetInfo, &key, &None).is_ok());
596 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Rebind, &key, &None).is_ok());
597 assert!(check_key_permission(0, &shell_ctx, KeyPerm::Update, &key, &None).is_ok());
598 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::Grant, &key, &None));
599 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ReqForcedOp, &key, &None));
600 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::ManageBlob, &key, &None));
601 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::UseDevId, &key, &None));
602 assert_perm_failed!(check_key_permission(0, &shell_ctx, KeyPerm::GenUniqueId, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700603
Janis Danisevskis45760022021-01-19 16:34:10 -0800604 // Also make sure that the permission fails if the caller is not the owner.
605 assert_perm_failed!(check_key_permission(
606 1, // the owner is 0
607 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700608 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800609 &key,
610 &None
611 ));
612 // Unless there was a grant.
613 assert!(check_key_permission(
614 1,
615 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700616 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800617 &key,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700618 &Some(key_perm_set![KeyPerm::Use])
Janis Danisevskis45760022021-01-19 16:34:10 -0800619 )
620 .is_ok());
621 // But fail if the grant did not cover the requested permission.
622 assert_perm_failed!(check_key_permission(
623 1,
624 &system_server_ctx,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700625 KeyPerm::Use,
Janis Danisevskis45760022021-01-19 16:34:10 -0800626 &key,
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700627 &Some(key_perm_set![KeyPerm::GetInfo])
Janis Danisevskis45760022021-01-19 16:34:10 -0800628 ));
629
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700630 Ok(())
631 }
632
633 #[test]
634 fn check_key_permission_domain_selinux() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700635 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700636 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700637 domain: Domain::SELINUX,
638 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700639 alias: None,
640 blob: None,
641 };
642
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700643 assert!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None).is_ok());
644 assert!(check_key_permission(0, &sctx, KeyPerm::Delete, &key, &None).is_ok());
645 assert!(check_key_permission(0, &sctx, KeyPerm::GetInfo, &key, &None).is_ok());
646 assert!(check_key_permission(0, &sctx, KeyPerm::Rebind, &key, &None).is_ok());
647 assert!(check_key_permission(0, &sctx, KeyPerm::Update, &key, &None).is_ok());
Chris Wailes3877f292021-07-26 19:24:18 -0700648
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700649 if is_su {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700650 assert!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None).is_ok());
651 assert!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None).is_ok());
652 assert!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None).is_ok());
653 assert!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None).is_ok());
654 assert!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None).is_ok());
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700655 } else {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700656 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Grant, &key, &None));
657 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ReqForcedOp, &key, &None));
658 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::ManageBlob, &key, &None));
659 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::UseDevId, &key, &None));
660 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::GenUniqueId, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700661 }
662 Ok(())
663 }
664
665 #[test]
666 fn check_key_permission_domain_blob() -> Result<()> {
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700667 let (sctx, namespace, is_su) = check_context()?;
Janis Danisevskis1b3a6e22020-08-07 12:39:56 -0700668 let key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700669 domain: Domain::BLOB,
670 nspace: namespace as i64,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700671 alias: None,
672 blob: None,
673 };
674
675 if is_su {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700676 check_key_permission(0, &sctx, KeyPerm::Use, &key, &None)
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700677 } else {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700678 assert_perm_failed!(check_key_permission(0, &sctx, KeyPerm::Use, &key, &None));
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700679 Ok(())
680 }
681 }
682
683 #[test]
684 fn check_key_permission_domain_key_id() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700685 let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700686
687 assert_eq!(
688 Some(&KsError::sys()),
689 check_key_permission(
Janis Danisevskis45760022021-01-19 16:34:10 -0800690 0,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700691 &selinux::Context::new("ignored").unwrap(),
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700692 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700693 &key,
694 &None
695 )
696 .err()
697 .unwrap()
698 .root_cause()
699 .downcast_ref::<KsError>()
700 );
701 Ok(())
702 }
703
704 #[test]
705 fn key_perm_set_all_test() {
706 let v = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700707 KeyPerm::ManageBlob,
708 KeyPerm::Delete,
709 KeyPerm::UseDevId,
710 KeyPerm::ReqForcedOp,
711 KeyPerm::GenUniqueId,
712 KeyPerm::Grant,
713 KeyPerm::GetInfo,
714 KeyPerm::Rebind,
715 KeyPerm::Update,
716 KeyPerm::Use // Test if the macro accepts missing comma at the end of the list.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700717 ];
718 let mut i = v.into_iter();
Janis Danisevskis56af0312021-10-18 16:11:41 -0700719 assert_eq!(i.next().unwrap().name(), "delete");
720 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
721 assert_eq!(i.next().unwrap().name(), "get_info");
722 assert_eq!(i.next().unwrap().name(), "grant");
723 assert_eq!(i.next().unwrap().name(), "manage_blob");
724 assert_eq!(i.next().unwrap().name(), "rebind");
725 assert_eq!(i.next().unwrap().name(), "req_forced_op");
726 assert_eq!(i.next().unwrap().name(), "update");
727 assert_eq!(i.next().unwrap().name(), "use");
728 assert_eq!(i.next().unwrap().name(), "use_dev_id");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700729 assert_eq!(None, i.next());
730 }
731 #[test]
732 fn key_perm_set_sparse_test() {
733 let v = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700734 KeyPerm::ManageBlob,
735 KeyPerm::ReqForcedOp,
736 KeyPerm::GenUniqueId,
737 KeyPerm::Update,
738 KeyPerm::Use, // Test if macro accepts the comma at the end of the list.
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700739 ];
740 let mut i = v.into_iter();
Janis Danisevskis56af0312021-10-18 16:11:41 -0700741 assert_eq!(i.next().unwrap().name(), "gen_unique_id");
742 assert_eq!(i.next().unwrap().name(), "manage_blob");
743 assert_eq!(i.next().unwrap().name(), "req_forced_op");
744 assert_eq!(i.next().unwrap().name(), "update");
745 assert_eq!(i.next().unwrap().name(), "use");
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700746 assert_eq!(None, i.next());
747 }
748 #[test]
749 fn key_perm_set_empty_test() {
750 let v = key_perm_set![];
751 let mut i = v.into_iter();
752 assert_eq!(None, i.next());
753 }
754 #[test]
755 fn key_perm_set_include_subset_test() {
756 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700757 KeyPerm::ManageBlob,
758 KeyPerm::Delete,
759 KeyPerm::UseDevId,
760 KeyPerm::ReqForcedOp,
761 KeyPerm::GenUniqueId,
762 KeyPerm::Grant,
763 KeyPerm::GetInfo,
764 KeyPerm::Rebind,
765 KeyPerm::Update,
766 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700767 ];
768 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700769 KeyPerm::ManageBlob,
770 KeyPerm::Delete,
771 KeyPerm::Rebind,
772 KeyPerm::Update,
773 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700774 ];
775 assert!(v1.includes(v2));
776 assert!(!v2.includes(v1));
777 }
778 #[test]
779 fn key_perm_set_include_equal_test() {
780 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700781 KeyPerm::ManageBlob,
782 KeyPerm::Delete,
783 KeyPerm::Rebind,
784 KeyPerm::Update,
785 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700786 ];
787 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700788 KeyPerm::ManageBlob,
789 KeyPerm::Delete,
790 KeyPerm::Rebind,
791 KeyPerm::Update,
792 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700793 ];
794 assert!(v1.includes(v2));
795 assert!(v2.includes(v1));
796 }
797 #[test]
798 fn key_perm_set_include_overlap_test() {
799 let v1 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700800 KeyPerm::ManageBlob,
801 KeyPerm::Delete,
802 KeyPerm::Grant, // only in v1
803 KeyPerm::Rebind,
804 KeyPerm::Update,
805 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700806 ];
807 let v2 = key_perm_set![
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700808 KeyPerm::ManageBlob,
809 KeyPerm::Delete,
810 KeyPerm::ReqForcedOp, // only in v2
811 KeyPerm::Rebind,
812 KeyPerm::Update,
813 KeyPerm::Use,
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700814 ];
815 assert!(!v1.includes(v2));
816 assert!(!v2.includes(v1));
817 }
818 #[test]
819 fn key_perm_set_include_no_overlap_test() {
Janis Danisevskis39d57e72021-10-19 16:56:20 -0700820 let v1 = key_perm_set![KeyPerm::ManageBlob, KeyPerm::Delete, KeyPerm::Grant,];
821 let v2 =
822 key_perm_set![KeyPerm::ReqForcedOp, KeyPerm::Rebind, KeyPerm::Update, KeyPerm::Use,];
Janis Danisevskis78bd48c2020-07-21 12:27:13 -0700823 assert!(!v1.includes(v2));
824 assert!(!v2.includes(v1));
825 }
826}