From 87d6cd27ca5f8b332816a7b3571ead107340efb9 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 15:28:53 -0400 Subject: [PATCH 01/47] tests: factor out creating an invalid keyring --- src/tests/add.rs | 8 +++----- src/tests/utils/mod.rs | 9 +++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/tests/add.rs b/src/tests/add.rs index a145f5b..0e8483b 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -27,8 +27,9 @@ use std::iter; use crate::keytypes::User; -use crate::{Keyring, KeyringSerial, SpecialKeyring}; +use crate::{Keyring, SpecialKeyring}; +use super::utils; use super::utils::kernel::*; use super::utils::keys::*; @@ -106,10 +107,7 @@ fn overlong_user_description() { #[test] fn invalid_keyring() { - // Yes, we're explicitly breaking the NonZeroI32 rules here. However, it is not passing - // through any bits which care (e.g., `Option`), so this is purely to test that using an - // invalid keyring ID gives back `EINVAL` as expected. - let mut keyring = unsafe { Keyring::new(KeyringSerial::new_unchecked(0)) }; + let mut keyring = utils::invalid_keyring(); let err = keyring .add_key::("desc", "payload".as_bytes()) .unwrap_err(); diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index 36a3282..911d2e1 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -24,5 +24,14 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +use crate::{Keyring, KeyringSerial}; + pub mod kernel; pub mod keys; + +pub fn invalid_keyring() -> Keyring { + // Yes, we're explicitly breaking the NonZeroI32 rules here. However, it is not passing through + // any bits which care (e.g., `Option`), so this is purely to test that using an invalid + // keyring ID gives back `EINVAL` as expected. + unsafe { Keyring::new(KeyringSerial::new_unchecked(0)) } +} From e55d2a04b0b12383e948def574aa6415debd56d3 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 15:30:08 -0400 Subject: [PATCH 02/47] tests: use test names as key descriptions --- src/tests/add.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tests/add.rs b/src/tests/add.rs index 0e8483b..5da9a6d 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -109,7 +109,7 @@ fn overlong_user_description() { fn invalid_keyring() { let mut keyring = utils::invalid_keyring(); let err = keyring - .add_key::("desc", "payload".as_bytes()) + .add_key::("invalid_keyring", "payload".as_bytes()) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); } @@ -118,7 +118,9 @@ fn invalid_keyring() { fn add_key_to_session() { let mut keyring = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); let expected = "stuff".as_bytes(); - let mut key = keyring.add_key::("wibble", expected).unwrap(); + let mut key = keyring + .add_key::("add_key_to_session", expected) + .unwrap(); let payload = key.read().unwrap(); assert_eq!(payload, expected); let new_expected = "lizard".as_bytes(); From 58b940a4f16ba73ca727dff78dc70654c8d78320 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 15:30:31 -0400 Subject: [PATCH 03/47] tests/add: add a test for treating a key as a keyring --- src/api.rs | 5 +++++ src/tests/add.rs | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/api.rs b/src/api.rs index 4ddcd7c..196f29d 100644 --- a/src/api.rs +++ b/src/api.rs @@ -524,6 +524,11 @@ impl Key { } } + #[cfg(test)] + pub(crate) fn serial(&self) -> KeyringSerial { + self.id + } + /// Requests a key with the given description by searching the thread, process, and session /// keyrings. pub fn request(description: D) -> Result diff --git a/src/tests/add.rs b/src/tests/add.rs index 5da9a6d..65092fb 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -114,6 +114,23 @@ fn invalid_keyring() { assert_eq!(err, errno::Errno(libc::EINVAL)); } +#[test] +fn add_key_to_non_keyring() { + let mut keyring = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + let expected = "stuff".as_bytes(); + let key = keyring + .add_key::("add_key_to_non_keyring", expected) + .unwrap(); + + let mut not_a_keyring = unsafe { Keyring::new(key.serial()) }; + let err = not_a_keyring + .add_key::("add_key_to_non_keyring", expected) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.unlink_key(&key).unwrap(); +} + #[test] fn add_key_to_session() { let mut keyring = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); From 9891f15c5668b91831b3e9b0ee1d1cac77e49f6c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 15:30:49 -0400 Subject: [PATCH 04/47] tests/add: whitespace nit --- src/tests/add.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/add.rs b/src/tests/add.rs index 65092fb..fd5d94d 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -140,6 +140,7 @@ fn add_key_to_session() { .unwrap(); let payload = key.read().unwrap(); assert_eq!(payload, expected); + let new_expected = "lizard".as_bytes(); key.update(new_expected).unwrap(); let new_payload = key.read().unwrap(); From 6a7de94e77fe5f7fd2e4f2e4cd26b2c043061bfa Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 20:15:56 -0400 Subject: [PATCH 05/47] tests: move test keyring creation to tests/utils --- src/api.rs | 49 ++++++++++++++++-------------------------- src/tests/add.rs | 22 +++++++++---------- src/tests/mod.rs | 2 +- src/tests/utils/mod.rs | 16 +++++++++++++- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/src/api.rs b/src/api.rs index 196f29d..a030779 100644 --- a/src/api.rs +++ b/src/api.rs @@ -819,25 +819,14 @@ impl KeyManager { #[cfg(test)] mod tests { - use std::sync::atomic; use std::thread; use super::*; - - // For testing, each test gets a new keyring attached to the Thread keyring. - // This makes sure tests don't interfere with eachother, and keys are not - // prematurely garbage collected. - fn new_test_keyring() -> Result { - let mut thread_keyring = Keyring::attach_or_create(SpecialKeyring::Thread)?; - - static KEYRING_COUNT: atomic::AtomicUsize = atomic::AtomicUsize::new(0); - let num = KEYRING_COUNT.fetch_add(1, atomic::Ordering::SeqCst); - thread_keyring.add_keyring(format!("test:rust-keyutils{}", num)) - } + use crate::tests::utils; #[test] fn test_add_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:add_key"; @@ -857,7 +846,7 @@ mod tests { #[test] fn test_clear_keyring() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let (keys, keyrings) = keyring.read().unwrap(); assert_eq!(keys.len(), 0); @@ -889,7 +878,7 @@ mod tests { #[test] fn test_describe_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let desc = "test:rust-keyutils:describe_key"; @@ -910,7 +899,7 @@ mod tests { #[test] fn test_invalidate_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:invalidate_key"; @@ -930,7 +919,7 @@ mod tests { #[test] fn test_link_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); // Create the key. @@ -955,7 +944,7 @@ mod tests { #[test] fn test_link_keyring() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); let new_inner_keyring = keyring.add_keyring("new_inner_keyring").unwrap(); @@ -974,7 +963,7 @@ mod tests { #[test] fn test_read_keyring() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let (keys, keyrings) = keyring.read().unwrap(); assert_eq!(keys.len(), 0); @@ -999,7 +988,7 @@ mod tests { #[test] fn test_read_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:read_key"; @@ -1019,7 +1008,7 @@ mod tests { #[test] fn test_create_keyring() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let new_keyring = keyring.add_keyring("new_keyring").unwrap(); let (keys, keyrings) = keyring.read().unwrap(); @@ -1034,7 +1023,7 @@ mod tests { #[test] fn test_chmod_keyring() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let description = keyring.description().unwrap(); let perms = description.perms; let new_perms = { @@ -1060,7 +1049,7 @@ mod tests { #[test] fn test_request_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:request_key"; @@ -1081,7 +1070,7 @@ mod tests { #[test] fn test_revoke_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:revoke_key"; @@ -1103,7 +1092,7 @@ mod tests { #[test] fn test_search_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); let mut new_inner_keyring = new_keyring.add_keyring("new_inner_keyring").unwrap(); @@ -1128,7 +1117,7 @@ mod tests { #[test] fn test_search_keyring() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); let new_inner_keyring = new_keyring.add_keyring("new_inner_keyring").unwrap(); @@ -1143,7 +1132,7 @@ mod tests { #[test] fn test_key_timeout() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:key_timeout"; @@ -1171,7 +1160,7 @@ mod tests { #[test] fn test_unlink_keyring() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the keyring. let description = "test:rust-keyutils:unlink_keyring"; @@ -1198,7 +1187,7 @@ mod tests { #[test] fn test_unlink_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:unlink_key"; @@ -1228,7 +1217,7 @@ mod tests { #[test] fn test_update_key() { - let mut keyring = new_test_keyring().unwrap(); + let mut keyring = utils::new_test_keyring(); // Create the key. let description = "test:rust-keyutils:update_key"; diff --git a/src/tests/add.rs b/src/tests/add.rs index fd5d94d..ffa4c48 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -27,7 +27,7 @@ use std::iter; use crate::keytypes::User; -use crate::{Keyring, SpecialKeyring}; +use crate::Keyring; use super::utils; use super::utils::kernel::*; @@ -35,42 +35,42 @@ use super::utils::keys::*; #[test] fn empty_key_type() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); } #[test] fn unsupported_key_type() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENODEV)); } #[test] fn invalid_key_type() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); } #[test] fn maxlen_key_type() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENODEV)); } #[test] fn overlong_key_type() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); } #[test] fn keyring_with_payload() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); let err = keyring .add_key::("", "payload") .unwrap_err(); @@ -79,7 +79,7 @@ fn keyring_with_payload() { #[test] fn max_user_description() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); // Subtract one because the NUL is added in the kernel API. let maxdesc: String = iter::repeat('a').take(*PAGE_SIZE - 1).collect(); let res = keyring.add_key::(maxdesc.as_ref(), "payload".as_bytes()); @@ -95,7 +95,7 @@ fn max_user_description() { #[test] fn overlong_user_description() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Process).unwrap(); + let mut keyring = utils::new_test_keyring(); // On MIPS with < 3.19, there is a bug where this is allowed. 3.19 was released in Feb 2015, // so this is being ignored here. let toolarge: String = iter::repeat('a').take(*PAGE_SIZE).collect(); @@ -116,7 +116,7 @@ fn invalid_keyring() { #[test] fn add_key_to_non_keyring() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + let mut keyring = utils::new_test_keyring(); let expected = "stuff".as_bytes(); let key = keyring .add_key::("add_key_to_non_keyring", expected) @@ -133,7 +133,7 @@ fn add_key_to_non_keyring() { #[test] fn add_key_to_session() { - let mut keyring = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + let mut keyring = utils::new_test_keyring(); let expected = "stuff".as_bytes(); let mut key = keyring .add_key::("add_key_to_session", expected) diff --git a/src/tests/mod.rs b/src/tests/mod.rs index ad7f5bb..f837ea9 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -26,6 +26,6 @@ //! The test structure here comes from the structure in libkeyutils. -mod utils; +pub(crate) mod utils; mod add; diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index 911d2e1..bcee736 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -24,11 +24,25 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use crate::{Keyring, KeyringSerial}; +use std::sync::atomic; + +use crate::{Keyring, KeyringSerial, SpecialKeyring}; pub mod kernel; pub mod keys; +// For testing, each test gets a new keyring attached to the Thread keyring. This makes sure tests +// don't interfere with each other, and keys are not prematurely garbage collected. +pub fn new_test_keyring() -> Keyring { + let mut thread_keyring = Keyring::attach_or_create(SpecialKeyring::Thread).unwrap(); + + static KEYRING_COUNT: atomic::AtomicUsize = atomic::AtomicUsize::new(0); + let num = KEYRING_COUNT.fetch_add(1, atomic::Ordering::SeqCst); + thread_keyring + .add_keyring(format!("test:rust-keyutils{}", num)) + .unwrap() +} + pub fn invalid_keyring() -> Keyring { // Yes, we're explicitly breaking the NonZeroI32 rules here. However, it is not passing through // any bits which care (e.g., `Option`), so this is purely to test that using an invalid From 25820b0e1ea86a39b81414480ffba302f4a49271 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 20:17:13 -0400 Subject: [PATCH 06/47] tests: remove unnecessary cloning --- src/api.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/api.rs b/src/api.rs index a030779..30f4f7c 100644 --- a/src/api.rs +++ b/src/api.rs @@ -834,10 +834,7 @@ mod tests { let key = keyring .add_key::(description, payload.as_bytes()) .unwrap(); - assert_eq!( - key.read().unwrap(), - payload.as_bytes().iter().cloned().collect::>() - ); + assert_eq!(key.read().unwrap(), payload.as_bytes()); // Clean up. keyring.unlink_key(&key).unwrap(); @@ -996,10 +993,7 @@ mod tests { let key = keyring .add_key::(description, payload.as_bytes()) .unwrap(); - assert_eq!( - key.read().unwrap(), - payload.as_bytes().iter().cloned().collect::>() - ); + assert_eq!(key.read().unwrap(), payload.as_bytes()); // Clean up. keyring.unlink_key(&key).unwrap(); @@ -1232,10 +1226,7 @@ mod tests { .add_key::(description, new_payload.as_bytes()) .unwrap(); assert_eq!(key, updated_key); - assert_eq!( - updated_key.read().unwrap(), - new_payload.as_bytes().iter().cloned().collect::>() - ); + assert_eq!(updated_key.read().unwrap(), new_payload.as_bytes()); // Clean up. keyring.unlink_key(&key).unwrap(); From 4156e625ab6e7e6cdb89f1ac6e7b92a25195af33 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 20:23:01 -0400 Subject: [PATCH 07/47] tests: clean up test keyrings --- src/tests/add.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/tests/add.rs b/src/tests/add.rs index ffa4c48..7e85199 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -38,6 +38,8 @@ fn empty_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() } #[test] @@ -45,6 +47,8 @@ fn unsupported_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENODEV)); + + keyring.invalidate().unwrap() } #[test] @@ -52,6 +56,8 @@ fn invalid_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() } #[test] @@ -59,6 +65,8 @@ fn maxlen_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENODEV)); + + keyring.invalidate().unwrap() } #[test] @@ -66,6 +74,8 @@ fn overlong_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() } #[test] @@ -75,6 +85,8 @@ fn keyring_with_payload() { .add_key::("", "payload") .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() } #[test] @@ -91,6 +103,8 @@ fn max_user_description() { assert_eq!(key.description().unwrap().description, maxdesc); key.invalidate().unwrap(); } + + keyring.invalidate().unwrap() } #[test] @@ -103,6 +117,8 @@ fn overlong_user_description() { .add_key::(toolarge.as_ref(), "payload".as_bytes()) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() } #[test] @@ -129,6 +145,8 @@ fn add_key_to_non_keyring() { assert_eq!(err, errno::Errno(libc::ENOTDIR)); keyring.unlink_key(&key).unwrap(); + + keyring.invalidate().unwrap() } #[test] @@ -146,4 +164,5 @@ fn add_key_to_session() { let new_payload = key.read().unwrap(); assert_eq!(new_payload, new_expected); keyring.unlink_key(&key).unwrap(); + keyring.invalidate().unwrap() } From 7d1c913de6764ab824b7171f2ec1747a4b9ad46e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 20:23:40 -0400 Subject: [PATCH 08/47] tests/add: migrate old test_add_key test --- src/api.rs | 41 --------------------------------------- src/tests/add.rs | 50 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 50 deletions(-) diff --git a/src/api.rs b/src/api.rs index 30f4f7c..387a291 100644 --- a/src/api.rs +++ b/src/api.rs @@ -824,23 +824,6 @@ mod tests { use super::*; use crate::tests::utils; - #[test] - fn test_add_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:add_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - assert_eq!(key.read().unwrap(), payload.as_bytes()); - - // Clean up. - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_clear_keyring() { let mut keyring = utils::new_test_keyring(); @@ -1208,28 +1191,4 @@ mod tests { // Clean up. keyring.invalidate().unwrap(); } - - #[test] - fn test_update_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:update_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - - // Update the key. - let new_payload = "new_payload"; - let updated_key = keyring - .add_key::(description, new_payload.as_bytes()) - .unwrap(); - assert_eq!(key, updated_key); - assert_eq!(updated_key.read().unwrap(), new_payload.as_bytes()); - - // Clean up. - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap(); - } } diff --git a/src/tests/add.rs b/src/tests/add.rs index 7e85199..fbb8b78 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -150,19 +150,51 @@ fn add_key_to_non_keyring() { } #[test] -fn add_key_to_session() { +fn add_key() { let mut keyring = utils::new_test_keyring(); - let expected = "stuff".as_bytes(); + + let payload = "stuff".as_bytes(); + let key = keyring.add_key::("add_key", payload).unwrap(); + assert_eq!(key.read().unwrap(), payload); + + keyring.unlink_key(&key).unwrap(); + keyring.invalidate().unwrap() +} + +#[test] +fn update_key() { + let mut keyring = utils::new_test_keyring(); + + let payload = "stuff".as_bytes(); let mut key = keyring - .add_key::("add_key_to_session", expected) + .add_key::("update_key", payload) .unwrap(); - let payload = key.read().unwrap(); - assert_eq!(payload, expected); + assert_eq!(key.read().unwrap(), payload); + + let payload = "lizard".as_bytes(); + key.update(payload).unwrap(); + assert_eq!(key.read().unwrap(), payload); + + keyring.unlink_key(&key).unwrap(); + keyring.invalidate().unwrap() +} + +#[test] +fn update_key_via_add() { + let mut keyring = utils::new_test_keyring(); + + let description = "update_key_via_add"; + + let payload = "stuff".as_bytes(); + let key = keyring.add_key::(description, payload).unwrap(); + assert_eq!(key.read().unwrap(), payload); + + let payload = "lizard".as_bytes(); + let key_updated = keyring.add_key::(description, payload).unwrap(); + assert_eq!(key, key_updated); + assert_eq!(key.read().unwrap(), payload); + assert_eq!(key_updated.read().unwrap(), payload); - let new_expected = "lizard".as_bytes(); - key.update(new_expected).unwrap(); - let new_payload = key.read().unwrap(); - assert_eq!(new_payload, new_expected); keyring.unlink_key(&key).unwrap(); keyring.invalidate().unwrap() } From 19cb0f5ee91b498233b89bb423e0a6655624b3b5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 15:31:15 -0400 Subject: [PATCH 09/47] tests/clear: add tests for clearing keyrings --- src/api.rs | 32 -------- src/tests/clear.rs | 196 +++++++++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + 3 files changed, 197 insertions(+), 32 deletions(-) create mode 100644 src/tests/clear.rs diff --git a/src/api.rs b/src/api.rs index 387a291..fd4f83f 100644 --- a/src/api.rs +++ b/src/api.rs @@ -824,38 +824,6 @@ mod tests { use super::*; use crate::tests::utils; - #[test] - fn test_clear_keyring() { - let mut keyring = utils::new_test_keyring(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 0); - - // Create a key. - keyring - .add_key::( - "test:rust-keyutils:clear_keyring", - "payload".as_bytes(), - ) - .unwrap(); - keyring.add_keyring("description").unwrap(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 1); - assert_eq!(keyrings.len(), 1); - - // Clear the keyring. - keyring.clear().unwrap(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap(); - } - #[test] fn test_describe_key() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/clear.rs b/src/tests/clear.rs new file mode 100644 index 0000000..8adb8d8 --- /dev/null +++ b/src/tests/clear.rs @@ -0,0 +1,196 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::User; +use crate::Keyring; + +use super::utils; + +#[test] +fn invalid_keyring() { + let mut keyring = utils::invalid_keyring(); + let err = keyring.clear().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn clear_non_keyring() { + let mut keyring = utils::new_test_keyring(); + let key = keyring + .add_key::("clear_non_keyring", "payload".as_bytes()) + .unwrap(); + + // Try clearing a non-keyring. + let mut not_a_keyring = unsafe { Keyring::new(key.serial()) }; + let err = not_a_keyring.clear().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.unlink_key(&key).unwrap(); + keyring.invalidate().unwrap() +} + +#[test] +fn clear_deleted_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut sub_keyring = keyring.add_keyring("clear_deleted_keyring").unwrap(); + + keyring.unlink_keyring(&sub_keyring).unwrap(); + + // Keys are deleted asynchronously; permissions are revoked until it is actually deleted. + loop { + let err = sub_keyring.clear().unwrap_err(); + if err == errno::Errno(libc::EACCES) { + continue; + } + assert_eq!(err, errno::Errno(libc::ENOKEY)); + break; + } + + keyring.invalidate().unwrap() +} + +#[test] +fn clear_empty_keyring() { + let mut keyring = utils::new_test_keyring(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + // Clear the keyring. + keyring.clear().unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + // Clean up. + keyring.invalidate().unwrap() +} + +#[test] +fn clear_keyring_one_key() { + let mut keyring = utils::new_test_keyring(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + let key_desc = "clear_keyring:key"; + + // Create a key. + let payload = "payload".as_bytes(); + keyring.add_key::(key_desc, payload).unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keyrings.len(), 0); + + assert_eq!(keys[0].description().unwrap().description, key_desc); + + // Clear the keyring. + keyring.clear().unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + // Clean up. + keyring.invalidate().unwrap() +} + +#[test] +fn clear_keyring_many_keys() { + let mut keyring = utils::new_test_keyring(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + let count = 40; + let payload = "payload".as_bytes(); + let mut descs = Vec::with_capacity(count); + for i in 0..count { + let key_desc = format!("clear_keyring:key{:02}", i); + + // Create a key. + keyring + .add_key::(key_desc.as_ref(), payload) + .unwrap(); + descs.push(key_desc); + } + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), count); + assert_eq!(keyrings.len(), 0); + + let mut actual_descs = keys + .iter() + .map(|key| key.description().unwrap().description) + .collect::>(); + actual_descs.sort(); + assert_eq!(actual_descs, descs); + + // Clear the keyring. + keyring.clear().unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + // Clean up. + keyring.invalidate().unwrap() +} + +#[test] +fn clear_keyring_keyring() { + let mut keyring = utils::new_test_keyring(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + let keyring_desc = "clear_keyring:keyring"; + + // Create a key. + keyring.add_keyring(keyring_desc).unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 1); + + assert_eq!(keyrings[0].description().unwrap().description, keyring_desc); + + // Clear the keyring. + keyring.clear().unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 0); + + // Clean up. + keyring.invalidate().unwrap() +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index f837ea9..be0710d 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -29,3 +29,4 @@ pub(crate) mod utils; mod add; +mod clear; From ee811f0cfbaf2dd7d300f4d9227db615ee84bc98 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 21:27:39 -0400 Subject: [PATCH 10/47] tests/utils/kernel: add statics for the uid and gid --- src/tests/utils/kernel.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/tests/utils/kernel.rs b/src/tests/utils/kernel.rs index c39a80f..bea01de 100644 --- a/src/tests/utils/kernel.rs +++ b/src/tests/utils/kernel.rs @@ -32,6 +32,8 @@ use regex::{Captures, Regex}; lazy_static! { pub static ref PAGE_SIZE: usize = page_size(); + pub static ref UID: libc::uid_t = getuid(); + pub static ref GID: libc::gid_t = getgid(); pub static ref KEY_INFO: KeyQuota = key_user_info(); } @@ -120,3 +122,11 @@ fn key_user_info() -> KeyQuota { .get(&uid) .expect("the current user has no keys?") } + +fn getuid() -> libc::uid_t { + unsafe { libc::getuid() } +} + +fn getgid() -> libc::gid_t { + unsafe { libc::getgid() } +} From a2a04fbbf72adc85200a3d159f664a2501cfa491 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 21:27:56 -0400 Subject: [PATCH 11/47] tests/utils: add a function to create an invalid key --- src/tests/utils/mod.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index bcee736..351d7ae 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -26,7 +26,7 @@ use std::sync::atomic; -use crate::{Keyring, KeyringSerial, SpecialKeyring}; +use crate::{Key, Keyring, KeyringSerial, SpecialKeyring}; pub mod kernel; pub mod keys; @@ -43,9 +43,17 @@ pub fn new_test_keyring() -> Keyring { .unwrap() } -pub fn invalid_keyring() -> Keyring { +unsafe fn invalid_serial() -> KeyringSerial { // Yes, we're explicitly breaking the NonZeroI32 rules here. However, it is not passing through // any bits which care (e.g., `Option`), so this is purely to test that using an invalid // keyring ID gives back `EINVAL` as expected. - unsafe { Keyring::new(KeyringSerial::new_unchecked(0)) } + KeyringSerial::new_unchecked(0) +} + +pub fn invalid_keyring() -> Keyring { + unsafe { Keyring::new(invalid_serial()) } +} + +pub fn invalid_key() -> Key { + unsafe { Key::new(invalid_serial()) } } From e33d00a465eac0a863f5744d56119390b64969b7 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sun, 7 Jul 2019 21:29:28 -0400 Subject: [PATCH 12/47] tests/describe: port description tests from libkeyutils --- src/api.rs | 21 ------ src/tests/describe.rs | 145 ++++++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + 3 files changed, 146 insertions(+), 21 deletions(-) create mode 100644 src/tests/describe.rs diff --git a/src/api.rs b/src/api.rs index fd4f83f..5c1797f 100644 --- a/src/api.rs +++ b/src/api.rs @@ -824,27 +824,6 @@ mod tests { use super::*; use crate::tests::utils; - #[test] - fn test_describe_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let desc = "test:rust-keyutils:describe_key"; - let payload = "payload"; - let key = keyring - .add_key::(desc, payload.as_bytes()) - .unwrap(); - - // Check its description. - let description = key.description().unwrap(); - assert_eq!(&description.type_, keytypes::User::name()); - assert_eq!(&description.description, desc); - - // Clean up. - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_invalidate_key() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/describe.rs b/src/tests/describe.rs new file mode 100644 index 0000000..4766ef9 --- /dev/null +++ b/src/tests/describe.rs @@ -0,0 +1,145 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::{Keyring, User}; +use crate::{Key, KeyType, Permission}; + +use super::utils; +use super::utils::kernel::*; + +#[test] +fn invalid_key() { + let key = utils::invalid_key(); + let err = key.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_keyring() { + let keyring = utils::invalid_keyring(); + let err = keyring.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn non_existent_key() { + let mut keyring = utils::new_test_keyring(); + let key = keyring + .add_key::("non_existent_key", "payload".as_bytes()) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + + // Keys are deleted asynchronously; describing the key succeeds until it has been garbage + // collected. + loop { + match key.description() { + Ok(_) => (), + Err(errno::Errno(libc::ENOKEY)) => break, + e @ Err(_) => { + e.unwrap(); + unreachable!() + }, + } + } + + keyring.invalidate().unwrap() +} + +#[test] +fn describe_keyring() { + let mut keyring = utils::new_test_keyring(); + let description = "describe_keyring"; + let keyring = keyring.add_keyring(description).unwrap(); + + let perms = Permission::POSSESSOR_ALL | Permission::USER_VIEW; + + let desc = keyring.description().unwrap(); + assert_eq!(desc.type_, Keyring::name()); + assert_eq!(desc.uid, *UID); + assert_eq!(desc.gid, *GID); + assert_eq!(desc.perms, perms); + assert_eq!(desc.description, description); + + keyring.invalidate().unwrap() +} + +#[test] +fn describe_key() { + let mut keyring = utils::new_test_keyring(); + let description = "describe_key"; + let key = keyring + .add_key::(description, "payload".as_bytes()) + .unwrap(); + + let perms = Permission::POSSESSOR_ALL | Permission::USER_VIEW; + + let desc = key.description().unwrap(); + assert_eq!(desc.type_, User::name()); + assert_eq!(desc.uid, *UID); + assert_eq!(desc.gid, *GID); + assert_eq!(desc.perms, perms); + assert_eq!(desc.description, description); +} + +#[test] +fn describe_key_no_perm() { + let mut keyring = utils::new_test_keyring(); + let description = "describe_key_no_perm"; + let mut key = keyring + .add_key::(description, "payload".as_bytes()) + .unwrap(); + + let old_perms = key.description().unwrap().perms; + let perms = { + let mut perms = old_perms; + let view_bits = Permission::POSSESSOR_VIEW | Permission::USER_VIEW; + perms.remove(view_bits); + perms + }; + key.set_permissions(perms).unwrap(); + + let err = key.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + keyring.invalidate().unwrap() +} + +#[test] +fn describe_revoked_key() { + let mut keyring = utils::new_test_keyring(); + let key = keyring + .add_key::("describe_revoked_key", "payload".as_bytes()) + .unwrap(); + + let key_mirror = unsafe { Key::new(key.serial()) }; + key.revoke().unwrap(); + + let err = key_mirror.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + keyring.invalidate().unwrap() +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index be0710d..87c21af 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -30,3 +30,4 @@ pub(crate) mod utils; mod add; mod clear; +mod describe; From c12e3c1d7e0f61442e1153eefce111ccb0f40b45 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 24 Jul 2019 09:02:55 -0400 Subject: [PATCH 13/47] tests/utils/kernel: explicitly use the lazy_static macro --- src/lib.rs | 4 ---- src/tests/utils/kernel.rs | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 303ddd1..6641af3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,10 +30,6 @@ #![warn(missing_docs)] -#[cfg(test)] -#[macro_use] -extern crate lazy_static; - mod api; mod constants; mod keytype; diff --git a/src/tests/utils/kernel.rs b/src/tests/utils/kernel.rs index bea01de..909cc8e 100644 --- a/src/tests/utils/kernel.rs +++ b/src/tests/utils/kernel.rs @@ -28,6 +28,7 @@ use std::collections::HashMap; use std::fs; use std::str::FromStr; +use lazy_static::lazy_static; use regex::{Captures, Regex}; lazy_static! { From b32d2e4608a52d909be1a9d36c72e25a3ee05519 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 24 Jul 2019 15:03:31 -0400 Subject: [PATCH 14/47] tests/session: add session-based tests --- Cargo.toml | 2 + src/tests/mod.rs | 1 + src/tests/session.rs | 110 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 src/tests/session.rs diff --git a/Cargo.toml b/Cargo.toml index 35ce3c6..56e9f34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ members = ["keyutils-raw"] [dev-dependencies] lazy_static = "1" regex = "1" +serial_test = "*" +serial_test_derive = "*" [dependencies] bitflags = "1.0.4" diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 87c21af..fd35d3e 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -31,3 +31,4 @@ pub(crate) mod utils; mod add; mod clear; mod describe; +mod session; diff --git a/src/tests/session.rs b/src/tests/session.rs new file mode 100644 index 0000000..3831629 --- /dev/null +++ b/src/tests/session.rs @@ -0,0 +1,110 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use serial_test_derive::serial; + +use crate::keytypes; +use crate::{KeyType, Keyring, Permission, SpecialKeyring}; + +use super::utils::kernel::*; + +#[test] +#[serial(join_session)] +fn join_anonymous_session() { + let session_before = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + let keyring = Keyring::join_anonymous_session().unwrap(); + let session_after = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + + assert_ne!(session_before, keyring); + assert_eq!(session_after, keyring); + + let desc = keyring.description().unwrap(); + assert_eq!(desc.type_, keytypes::Keyring::name()); + assert_eq!(desc.uid, *UID); + assert_eq!(desc.gid, *GID); + assert_eq!( + desc.perms, + Permission::POSSESSOR_ALL | Permission::USER_VIEW | Permission::USER_READ + ); + assert_eq!(desc.description, "_ses"); + + keyring.invalidate().unwrap() +} + +#[test] +#[serial(join_session)] +fn join_new_named_session() { + let session_before = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + let name = "join_new_named_session"; + let keyring = Keyring::join_session(name).unwrap(); + let session_after = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + + assert_ne!(session_before, keyring); + assert_eq!(session_after, keyring); + + let desc = keyring.description().unwrap(); + assert_eq!(desc.type_, keytypes::Keyring::name()); + assert_eq!(desc.uid, *UID); + assert_eq!(desc.gid, *GID); + assert_eq!( + desc.perms, + Permission::POSSESSOR_ALL + | Permission::USER_VIEW + | Permission::USER_READ + | Permission::USER_LINK + ); + assert_eq!(desc.description, name); + + keyring.invalidate().unwrap() +} + +#[test] +#[serial(join_session)] +fn join_existing_named_session() { + let name = "join_existing_named_session"; + + let session_before = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + let keyring = Keyring::join_session(name).unwrap(); + let session_after = Keyring::attach_or_create(SpecialKeyring::Session).unwrap(); + + assert_ne!(session_before, keyring); + assert_eq!(session_after, keyring); + + let desc = keyring.description().unwrap(); + assert_eq!(desc.type_, keytypes::Keyring::name()); + assert_eq!(desc.uid, *UID); + assert_eq!(desc.gid, *GID); + assert_eq!( + desc.perms, + Permission::POSSESSOR_ALL + | Permission::USER_VIEW + | Permission::USER_READ + | Permission::USER_LINK + ); + assert_eq!(desc.description, name); + + keyring.invalidate().unwrap() +} From d0b3225d96144e321fd42ccd73bd53d212934536 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Jul 2019 18:13:53 -0400 Subject: [PATCH 15/47] tests/utils: refactor out waiting for key garbage collection --- src/tests/describe.rs | 14 +------------- src/tests/utils/mod.rs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/tests/describe.rs b/src/tests/describe.rs index 4766ef9..23b4a8c 100644 --- a/src/tests/describe.rs +++ b/src/tests/describe.rs @@ -52,19 +52,7 @@ fn non_existent_key() { .unwrap(); keyring.unlink_key(&key).unwrap(); - - // Keys are deleted asynchronously; describing the key succeeds until it has been garbage - // collected. - loop { - match key.description() { - Ok(_) => (), - Err(errno::Errno(libc::ENOKEY)) => break, - e @ Err(_) => { - e.unwrap(); - unreachable!() - }, - } - } + utils::wait_for_key_gc(&key); keyring.invalidate().unwrap() } diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index 351d7ae..9d01c08 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -57,3 +57,18 @@ pub fn invalid_keyring() -> Keyring { pub fn invalid_key() -> Key { unsafe { Key::new(invalid_serial()) } } + +/// Keys are deleted asynchronously; describing the key succeeds until it has been garbage +/// collected. +pub fn wait_for_key_gc(key: &Key) { + loop { + match key.description() { + Ok(_) => (), + Err(errno::Errno(libc::ENOKEY)) => break, + e @ Err(_) => { + e.unwrap(); + unreachable!() + }, + } + } +} From bac112c7efa718dc975fee79cc179f1e8d09a4c2 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Jul 2019 18:14:36 -0400 Subject: [PATCH 16/47] utils/kernel: add functions for extracting the kernel version --- src/tests/utils/kernel.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/tests/utils/kernel.rs b/src/tests/utils/kernel.rs index 909cc8e..6255e41 100644 --- a/src/tests/utils/kernel.rs +++ b/src/tests/utils/kernel.rs @@ -25,19 +25,44 @@ // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use std::collections::HashMap; +use std::ffi::CStr; use std::fs; +use std::mem; use std::str::FromStr; use lazy_static::lazy_static; use regex::{Captures, Regex}; lazy_static! { + pub static ref KERNEL_VERSION: String = kernel_version(); + pub static ref SEMVER_KERNEL_VERSION: &'static str = semver_kernel_version(); pub static ref PAGE_SIZE: usize = page_size(); pub static ref UID: libc::uid_t = getuid(); pub static ref GID: libc::gid_t = getgid(); pub static ref KEY_INFO: KeyQuota = key_user_info(); } +// The full version of the running kernel. +fn kernel_version() -> String { + let mut utsname = unsafe { mem::zeroed() }; + let ret = unsafe { libc::uname(&mut utsname) }; + if ret < 0 { + panic!("failed to query the kernel version: {}", errno::errno()); + } + let cstr = unsafe { CStr::from_ptr(utsname.release.as_ptr()) }; + cstr.to_str() + .expect("kernel version should be ASCII") + .into() +} + +// A semver-compatible string for the kernel version. +fn semver_kernel_version() -> &'static str { + match (*KERNEL_VERSION).find('-') { + Some(pos) => &(*KERNEL_VERSION)[..pos], + None => &*KERNEL_VERSION, + } +} + fn page_size() -> usize { errno::set_errno(errno::Errno(0)); let ret = unsafe { libc::sysconf(libc::_SC_PAGESIZE) }; From 396a24ceb0f1213854cc23339238fa7eb168d678 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Jul 2019 18:15:20 -0400 Subject: [PATCH 17/47] tests/invalidate: test key and keyring invalidation --- Cargo.toml | 1 + src/api.rs | 20 ------ src/tests/invalidate.rs | 128 ++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + src/tests/utils/kernel.rs | 19 ++++++ src/tests/utils/mod.rs | 15 +++++ 6 files changed, 164 insertions(+), 20 deletions(-) create mode 100644 src/tests/invalidate.rs diff --git a/Cargo.toml b/Cargo.toml index 56e9f34..51decba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ lazy_static = "1" regex = "1" serial_test = "*" serial_test_derive = "*" +semver = "*" [dependencies] bitflags = "1.0.4" diff --git a/src/api.rs b/src/api.rs index 5c1797f..9f45b60 100644 --- a/src/api.rs +++ b/src/api.rs @@ -824,26 +824,6 @@ mod tests { use super::*; use crate::tests::utils; - #[test] - fn test_invalidate_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:invalidate_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - key.invalidate().unwrap(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap(); - } - #[test] fn test_link_key() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/invalidate.rs b/src/tests/invalidate.rs new file mode 100644 index 0000000..0e094df --- /dev/null +++ b/src/tests/invalidate.rs @@ -0,0 +1,128 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::User; + +use super::utils; +use super::utils::kernel::*; + +#[test] +fn have_invalidate() { + let can_test = *HAVE_INVALIDATE; + if !can_test { + eprintln!( + "This kernel does not support key invalidation. Please ignore test failures in \ + this test failure." + ); + } +} + +#[test] +fn invalid_key() { + let key = utils::invalid_key(); + let err = key.invalidate().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_keyring() { + let keyring = utils::invalid_keyring(); + let err = keyring.invalidate().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = key.invalidate().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalidate_key() { + let mut keyring = utils::new_test_keyring(); + + { + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + } + + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("invalidate_key", payload) + .unwrap(); + let key_observer = key.clone(); + + key.invalidate().unwrap(); + utils::wait_for_key_gc(&key_observer); + + { + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + } + + keyring.invalidate().unwrap() +} + +#[test] +fn invalidate_keyring() { + let mut keyring = utils::new_test_keyring(); + + { + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + } + + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("invalidate_keyring", payload) + .unwrap(); + let keyring_observer = keyring.clone(); + + keyring.invalidate().unwrap(); + utils::wait_for_keyring_gc(&keyring_observer); + + let err = keyring_observer.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + utils::wait_for_key_gc(&key); + + let err = key.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index fd35d3e..e1032a4 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -31,4 +31,5 @@ pub(crate) mod utils; mod add; mod clear; mod describe; +mod invalidate; mod session; diff --git a/src/tests/utils/kernel.rs b/src/tests/utils/kernel.rs index 6255e41..2f6c196 100644 --- a/src/tests/utils/kernel.rs +++ b/src/tests/utils/kernel.rs @@ -32,10 +32,12 @@ use std::str::FromStr; use lazy_static::lazy_static; use regex::{Captures, Regex}; +use semver::{Version, VersionReq}; lazy_static! { pub static ref KERNEL_VERSION: String = kernel_version(); pub static ref SEMVER_KERNEL_VERSION: &'static str = semver_kernel_version(); + pub static ref HAVE_INVALIDATE: bool = have_invalidate(); pub static ref PAGE_SIZE: usize = page_size(); pub static ref UID: libc::uid_t = getuid(); pub static ref GID: libc::gid_t = getgid(); @@ -63,6 +65,23 @@ fn semver_kernel_version() -> &'static str { } } +// Whether the kernel supports the `invalidate` action on a key. +fn have_invalidate() -> bool { + match Version::parse(*SEMVER_KERNEL_VERSION) { + Ok(ver) => { + let minver = VersionReq::parse(">=3.5").unwrap(); + minver.matches(&ver) + }, + Err(err) => { + eprintln!( + "failed to parse kernel version `{}` ({}): assuming incompatibility", + *SEMVER_KERNEL_VERSION, err + ); + false + }, + } +} + fn page_size() -> usize { errno::set_errno(errno::Errno(0)); let ret = unsafe { libc::sysconf(libc::_SC_PAGESIZE) }; diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index 9d01c08..f81f5a8 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -72,3 +72,18 @@ pub fn wait_for_key_gc(key: &Key) { } } } + +/// Keys are deleted asynchronously; describing the key succeeds until it has been garbage +/// collected. +pub fn wait_for_keyring_gc(keyring: &Keyring) { + loop { + match keyring.read() { + Ok(_) | Err(errno::Errno(libc::EACCES)) => (), + Err(errno::Errno(libc::ENOKEY)) => break, + e @ Err(_) => { + e.unwrap(); + unreachable!() + }, + } + } +} From 711205569d2f4ca3fb31717f095abd0835f9d780 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Jul 2019 19:34:34 -0400 Subject: [PATCH 18/47] tests/update: port update tests from libkeyutils --- src/api.rs | 5 +++ src/tests/add.rs | 18 --------- src/tests/mod.rs | 1 + src/tests/update.rs | 86 ++++++++++++++++++++++++++++++++++++++++++ src/tests/utils/mod.rs | 4 ++ 5 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 src/tests/update.rs diff --git a/src/api.rs b/src/api.rs index 9f45b60..211db38 100644 --- a/src/api.rs +++ b/src/api.rs @@ -101,6 +101,11 @@ impl Keyring { } } + #[cfg(test)] + pub(crate) fn serial(&self) -> KeyringSerial { + self.id + } + /// Set the default keyring to use when implicit requests on the current thread. /// /// Returns the old default keyring. diff --git a/src/tests/add.rs b/src/tests/add.rs index fbb8b78..806eb1b 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -161,24 +161,6 @@ fn add_key() { keyring.invalidate().unwrap() } -#[test] -fn update_key() { - let mut keyring = utils::new_test_keyring(); - - let payload = "stuff".as_bytes(); - let mut key = keyring - .add_key::("update_key", payload) - .unwrap(); - assert_eq!(key.read().unwrap(), payload); - - let payload = "lizard".as_bytes(); - key.update(payload).unwrap(); - assert_eq!(key.read().unwrap(), payload); - - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap() -} - #[test] fn update_key_via_add() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index e1032a4..92315f9 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -33,3 +33,4 @@ mod clear; mod describe; mod invalidate; mod session; +mod update; diff --git a/src/tests/update.rs b/src/tests/update.rs new file mode 100644 index 0000000..fc5f60e --- /dev/null +++ b/src/tests/update.rs @@ -0,0 +1,86 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::User; + +use super::utils; + +#[test] +fn keyring() { + let keyring = utils::new_test_keyring(); + let mut key = utils::keyring_as_key(&keyring); + + let payload = "payload".as_bytes(); + let err = key.update(payload).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EOPNOTSUPP)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalid_key() { + let mut key = utils::invalid_key(); + + let payload = "payload".as_bytes(); + let err = key.update(payload).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let payload = "payload".as_bytes(); + let err = key.update(payload).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn user_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring.add_key::("user_key", payload).unwrap(); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + let payload = "updated_payload".as_bytes(); + key.update(payload).unwrap(); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index f81f5a8..0249959 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -58,6 +58,10 @@ pub fn invalid_key() -> Key { unsafe { Key::new(invalid_serial()) } } +pub fn keyring_as_key(keyring: &Keyring) -> Key { + unsafe { Key::new(keyring.serial()) } +} + /// Keys are deleted asynchronously; describing the key succeeds until it has been garbage /// collected. pub fn wait_for_key_gc(key: &Key) { From bd7b8afb3bd966593901544543ff997af2db56ba Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 26 Jul 2019 19:45:35 -0400 Subject: [PATCH 19/47] tests/revoke: add key and keyring revokation tests --- src/api.rs | 22 --------- src/tests/mod.rs | 1 + src/tests/revoke.rs | 113 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 src/tests/revoke.rs diff --git a/src/api.rs b/src/api.rs index 211db38..3cf68b3 100644 --- a/src/api.rs +++ b/src/api.rs @@ -977,28 +977,6 @@ mod tests { keyring.invalidate().unwrap(); } - #[test] - fn test_revoke_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:revoke_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - let key_copy = key.clone(); - - key.revoke().unwrap(); - - let err = key_copy.read().unwrap_err(); - assert_eq!(err.0, libc::EKEYREVOKED); - - // Clean up. - keyring.unlink_key(&key_copy).unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_search_key() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 92315f9..82cb281 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -32,5 +32,6 @@ mod add; mod clear; mod describe; mod invalidate; +mod revoke; mod session; mod update; diff --git a/src/tests/revoke.rs b/src/tests/revoke.rs new file mode 100644 index 0000000..e014200 --- /dev/null +++ b/src/tests/revoke.rs @@ -0,0 +1,113 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::time::Duration; + +use crate::keytypes::User; + +use super::utils; + +#[test] +fn invalid_key() { + let key = utils::invalid_key(); + let err = key.revoke().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_keyring() { + let keyring = utils::invalid_keyring(); + let err = keyring.revoke().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = key.revoke().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn revoked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("revoked_key", payload) + .unwrap(); + let mut key_observer = key.clone(); + + key.revoke().unwrap(); + + let err = key_observer.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + let err = key_observer.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + let duration = Duration::from_secs(1); + let err = key_observer.set_timeout(duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + let err = key_observer.invalidate().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + keyring.invalidate().unwrap() +} + +#[test] +fn revoked_keyring() { + let mut keyring = utils::new_test_keyring(); + let new_keyring = keyring.add_keyring("revoked_keyring").unwrap(); + let mut keyring_observer = new_keyring.clone(); + + new_keyring.revoke().unwrap(); + + let err = keyring_observer.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + let err = keyring_observer.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + let duration = Duration::from_secs(1); + let err = keyring_observer.set_timeout(duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + let err = keyring_observer.invalidate().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); + + keyring.invalidate().unwrap() +} From 192315cfeb6bca4ac6453370dfdb05fac17bad8c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 29 Jul 2019 18:27:00 -0400 Subject: [PATCH 20/47] tests/timeout: test setting timeouts on keys and keyrings --- src/api.rs | 30 --------- src/tests/mod.rs | 1 + src/tests/timeout.rs | 154 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 30 deletions(-) create mode 100644 src/tests/timeout.rs diff --git a/src/api.rs b/src/api.rs index 3cf68b3..be84481 100644 --- a/src/api.rs +++ b/src/api.rs @@ -824,8 +824,6 @@ impl KeyManager { #[cfg(test)] mod tests { - use std::thread; - use super::*; use crate::tests::utils; @@ -1017,34 +1015,6 @@ mod tests { keyring.invalidate().unwrap(); } - #[test] - fn test_key_timeout() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:key_timeout"; - let payload = "payload"; - let mut key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - - // Set the timeout on the key. - let duration = Duration::from_secs(1); - let timeout_duration = duration + duration; - key.set_timeout(duration).unwrap(); - - // Sleep the timeout away. - thread::sleep(timeout_duration); - - // Try to read the key. - let err = key.read().unwrap_err(); - assert_eq!(err.0, libc::EKEYEXPIRED); - - // Clean up. - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_unlink_keyring() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 82cb281..e66a547 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -34,4 +34,5 @@ mod describe; mod invalidate; mod revoke; mod session; +mod timeout; mod update; diff --git a/src/tests/timeout.rs b/src/tests/timeout.rs new file mode 100644 index 0000000..0a811cc --- /dev/null +++ b/src/tests/timeout.rs @@ -0,0 +1,154 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::thread; +use std::time::Duration; + +use crate::keytypes::User; + +use super::utils; + +#[test] +fn invalid_key() { + let mut key = utils::invalid_key(); + let duration = Duration::from_secs(1); + let err = key.set_timeout(duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_keyring() { + let mut keyring = utils::invalid_keyring(); + let duration = Duration::from_secs(1); + let err = keyring.set_timeout(duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let duration = Duration::from_secs(1); + let err = key.set_timeout(duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn big_timeout_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("unlinked_key", payload) + .unwrap(); + + let duration = Duration::from_secs(1024); + key.set_timeout(duration).unwrap(); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} + +#[test] +fn big_timeout_keyring() { + let mut keyring = utils::new_test_keyring(); + + let duration = Duration::from_secs(1024); + keyring.set_timeout(duration).unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn expired_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("expired_key", payload) + .unwrap(); + let key_observer1 = key.clone(); + let key_observer2 = key.clone(); + + let duration = Duration::from_secs(1); + key.set_timeout(duration).unwrap(); + + thread::sleep(duration); + thread::sleep(duration); + + let err = key.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); + + let err = key.set_timeout(duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); + + let err = key.invalidate().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); + + let err = key_observer1.revoke().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); + + keyring.unlink_key(&key_observer2).unwrap(); + + keyring.invalidate().unwrap() +} + +#[test] +fn expired_keyring() { + let mut keyring = utils::new_test_keyring(); + let keyring_observer = keyring.clone(); + + let duration = Duration::from_secs(1); + keyring.set_timeout(duration).unwrap(); + + thread::sleep(duration); + thread::sleep(duration); + + let err = keyring.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); + + let err = keyring.set_timeout(duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); + + let err = keyring.invalidate().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); + + let err = keyring_observer.revoke().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); +} From d7c251a850e7732e576b875184f83892cf5fb8c6 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 29 Jul 2019 19:07:51 -0400 Subject: [PATCH 21/47] tests/newring: add keyring creation tests --- src/api.rs | 15 ----- src/tests/mod.rs | 1 + src/tests/newring.rs | 146 +++++++++++++++++++++++++++++++++++++++++ src/tests/utils/mod.rs | 4 ++ 4 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 src/tests/newring.rs diff --git a/src/api.rs b/src/api.rs index be84481..3650281 100644 --- a/src/api.rs +++ b/src/api.rs @@ -913,21 +913,6 @@ mod tests { keyring.invalidate().unwrap(); } - #[test] - fn test_create_keyring() { - let mut keyring = utils::new_test_keyring(); - let new_keyring = keyring.add_keyring("new_keyring").unwrap(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 1); - assert_eq!(keyrings[0], new_keyring); - - // Clean up. - new_keyring.invalidate().unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_chmod_keyring() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index e66a547..1c84b4e 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -32,6 +32,7 @@ mod add; mod clear; mod describe; mod invalidate; +mod newring; mod revoke; mod session; mod timeout; diff --git a/src/tests/newring.rs b/src/tests/newring.rs new file mode 100644 index 0000000..9e668be --- /dev/null +++ b/src/tests/newring.rs @@ -0,0 +1,146 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::iter; + +use crate::keytypes::User; + +use super::utils; +use super::utils::kernel::*; + +#[test] +fn invalid_keyring() { + let mut keyring = utils::invalid_keyring(); + let err = keyring.add_keyring("invalid_keyring").unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn unlinked_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut unlinked_keyring = keyring.add_keyring("unlinked_keyring_unlinked").unwrap(); + + keyring.unlink_keyring(&unlinked_keyring).unwrap(); + utils::wait_for_keyring_gc(&unlinked_keyring); + + let err = unlinked_keyring + .add_keyring("unlinked_keyring") + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn not_a_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("not_a_keyring_key", payload) + .unwrap(); + let mut not_a_keyring = utils::key_as_keyring(&key); + + let err = not_a_keyring.add_keyring("not_a_keyring").unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.invalidate().unwrap() +} + +#[test] +fn empty_keyring_description() { + let mut keyring = utils::new_test_keyring(); + let err = keyring.add_keyring("").unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn max_keyring_description() { + let mut keyring = utils::new_test_keyring(); + // Subtract one because the NUL is added in the kernel API. + let maxdesc: String = iter::repeat('a').take(*PAGE_SIZE - 1).collect(); + let res = keyring.add_keyring(maxdesc.as_ref()); + // If the user's quota is smaller than this, it's an error. + if KEY_INFO.maxbytes < *PAGE_SIZE { + assert_eq!(res.unwrap_err(), errno::Errno(libc::EDQUOT)); + } else { + let keyring = res.unwrap(); + assert_eq!(keyring.description().unwrap().description, maxdesc); + keyring.invalidate().unwrap(); + } + + keyring.invalidate().unwrap() +} + +#[test] +fn overlong_keyring_description() { + let mut keyring = utils::new_test_keyring(); + // On MIPS with < 3.19, there is a bug where this is allowed. 3.19 was released in Feb 2015, + // so this is being ignored here. + let maxdesc: String = iter::repeat('a').take(*PAGE_SIZE).collect(); + let err = keyring.add_keyring(maxdesc.as_ref()).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn new_keyring() { + let mut keyring = utils::new_test_keyring(); + let new_keyring = keyring.add_keyring("new_keyring").unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 0); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], new_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn duplicate_keyring_names() { + let mut keyring = utils::new_test_keyring(); + let new_keyring1 = keyring.add_keyring("duplicate_keyring_names").unwrap(); + let new_keyring2 = keyring.add_keyring("duplicate_keyring_names").unwrap(); + + // The keyring should have been displaced. + assert_ne!(new_keyring1, new_keyring2); + + // The original keyring should not be in the parent keyring. + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(1, keyrings.len()); + assert_eq!(new_keyring2, keyrings[0]); + + utils::wait_for_keyring_gc(&new_keyring1); + + // It should be inaccessible. + let err = new_keyring1.description().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index 0249959..e3b0ddd 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -62,6 +62,10 @@ pub fn keyring_as_key(keyring: &Keyring) -> Key { unsafe { Key::new(keyring.serial()) } } +pub fn key_as_keyring(key: &Key) -> Keyring { + unsafe { Keyring::new(key.serial()) } +} + /// Keys are deleted asynchronously; describing the key succeeds until it has been garbage /// collected. pub fn wait_for_key_gc(key: &Key) { From 9f59d832b42f546cf0515b184372a9a37f94c88d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 30 Jul 2019 09:53:44 -0400 Subject: [PATCH 22/47] tests/reading: add tests for reading keys and keyrings --- src/api.rs | 42 ---------- src/tests/mod.rs | 1 + src/tests/reading.rs | 183 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 42 deletions(-) create mode 100644 src/tests/reading.rs diff --git a/src/api.rs b/src/api.rs index 3650281..3d2f677 100644 --- a/src/api.rs +++ b/src/api.rs @@ -871,48 +871,6 @@ mod tests { keyring.invalidate().unwrap(); } - #[test] - fn test_read_keyring() { - let mut keyring = utils::new_test_keyring(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 0); - - let key = keyring - .add_key::( - "test:rust-keyutils:read_keyring", - "payload".as_bytes(), - ) - .unwrap(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 1); - assert_eq!(keys[0], key); - assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap(); - } - - #[test] - fn test_read_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:read_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - assert_eq!(key.read().unwrap(), payload.as_bytes()); - - // Clean up. - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_chmod_keyring() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 1c84b4e..cf81832 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -33,6 +33,7 @@ mod clear; mod describe; mod invalidate; mod newring; +mod reading; mod revoke; mod session; mod timeout; diff --git a/src/tests/reading.rs b/src/tests/reading.rs new file mode 100644 index 0000000..598aa21 --- /dev/null +++ b/src/tests/reading.rs @@ -0,0 +1,183 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::User; +use crate::Permission; + +use super::utils; + +#[test] +fn invalid_key() { + let key = utils::invalid_key(); + let err = key.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); +} + +#[test] +fn invalid_keyring() { + let keyring = utils::invalid_keyring(); + let err = keyring.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); +} + +#[test] +fn unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = key.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlinked_keyring() { + let mut keyring = utils::new_test_keyring(); + let new_keyring = keyring.add_keyring("unlinked_keyring").unwrap(); + + keyring.unlink_keyring(&new_keyring).unwrap(); + utils::wait_for_keyring_gc(&new_keyring); + + let err = new_keyring.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn read_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring.add_key::("read_key", payload).unwrap(); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} + +#[test] +fn read_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("read_keyring", payload) + .unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(1, keys.len()); + assert_eq!(key, keys[0]); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn read_no_read_perm_with_search() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("read_no_read_perm_with_search", payload) + .unwrap(); + + // Remove the "read" permission from the key. + let no_read_search_perms = Permission::USER_ALL - Permission::USER_READ; + key.set_permissions(no_read_search_perms).unwrap(); + + // This should still work because we have "search" permission on its keyring. + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} + +#[test] +fn read_no_read_search_perm_with_search() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("read_no_read_search_perm_with_search", payload) + .unwrap(); + + // Remove the "read" and "search" permissions from the key. + let no_read_perms = Permission::USER_ALL - Permission::USER_READ - Permission::USER_SEARCH; + key.set_permissions(no_read_perms).unwrap(); + + let err = key.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + keyring.invalidate().unwrap() +} + +#[test] +fn read_rely_on_possessor() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("read_rely_on_possessor", payload) + .unwrap(); + + // Remove the "read" and "search" permissions from the key. + let no_read_perms = Permission::POSSESSOR_ALL - Permission::POSSESSOR_READ; + key.set_permissions(no_read_perms).unwrap(); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} + +#[test] +fn reinstated_read_perm() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("reinstated_read_perm", payload) + .unwrap(); + + // Remove the "read" and "search" permissions from the key. + let no_read_perms = Permission::USER_ALL - Permission::USER_READ - Permission::USER_SEARCH; + key.set_permissions(no_read_perms).unwrap(); + + let err = key.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + // Reinstate "read" permissions. + let no_read_perms = Permission::USER_ALL - Permission::USER_SEARCH; + key.set_permissions(no_read_perms).unwrap(); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} From 758866178f63b36e788d411bd42a52292484fc90 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 1 Aug 2019 21:46:04 -0400 Subject: [PATCH 23/47] tests/add: remove unnecessary key unlinking The invalidation of the keyring is enough. --- src/tests/add.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/tests/add.rs b/src/tests/add.rs index 806eb1b..53dae55 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -144,8 +144,6 @@ fn add_key_to_non_keyring() { .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap() } @@ -157,7 +155,6 @@ fn add_key() { let key = keyring.add_key::("add_key", payload).unwrap(); assert_eq!(key.read().unwrap(), payload); - keyring.unlink_key(&key).unwrap(); keyring.invalidate().unwrap() } @@ -177,6 +174,5 @@ fn update_key_via_add() { assert_eq!(key.read().unwrap(), payload); assert_eq!(key_updated.read().unwrap(), payload); - keyring.unlink_key(&key).unwrap(); keyring.invalidate().unwrap() } From 5d697d4afbc13a58fa6807fa7e42b91309a37ded Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 1 Aug 2019 21:46:20 -0400 Subject: [PATCH 24/47] tests/add: simplify the payload values a bit --- src/tests/add.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/add.rs b/src/tests/add.rs index 53dae55..a6251b3 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -151,7 +151,7 @@ fn add_key_to_non_keyring() { fn add_key() { let mut keyring = utils::new_test_keyring(); - let payload = "stuff".as_bytes(); + let payload = "payload".as_bytes(); let key = keyring.add_key::("add_key", payload).unwrap(); assert_eq!(key.read().unwrap(), payload); @@ -164,11 +164,11 @@ fn update_key_via_add() { let description = "update_key_via_add"; - let payload = "stuff".as_bytes(); + let payload = "payload".as_bytes(); let key = keyring.add_key::(description, payload).unwrap(); assert_eq!(key.read().unwrap(), payload); - let payload = "lizard".as_bytes(); + let payload = "updated_payload".as_bytes(); let key_updated = keyring.add_key::(description, payload).unwrap(); assert_eq!(key, key_updated); assert_eq!(key.read().unwrap(), payload); From 911f06fe761a9899acaa1b103f35f54c1d1aff3e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 2 Aug 2019 08:05:18 -0400 Subject: [PATCH 25/47] tests/add: use a utility function to transform a keyring --- src/tests/add.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tests/add.rs b/src/tests/add.rs index a6251b3..69411a7 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -27,7 +27,6 @@ use std::iter; use crate::keytypes::User; -use crate::Keyring; use super::utils; use super::utils::kernel::*; @@ -138,7 +137,7 @@ fn add_key_to_non_keyring() { .add_key::("add_key_to_non_keyring", expected) .unwrap(); - let mut not_a_keyring = unsafe { Keyring::new(key.serial()) }; + let mut not_a_keyring = utils::key_as_keyring(&key); let err = not_a_keyring .add_key::("add_key_to_non_keyring", expected) .unwrap_err(); From 375d8c8c77b719057351df07f13a259ae4184287 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 1 Aug 2019 20:27:59 -0400 Subject: [PATCH 26/47] KeyManager: fix API to match kernel semantics The documentation states that a keyring may be given or a special keyring used. The special IDs are looked up in the requesting process' namespace. An ID of `0` means that no link is requested. --- keyutils-raw/src/functions.rs | 6 ++-- src/api.rs | 65 +++++++++++++++++++++++++++++++---- src/constants.rs | 1 + 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/keyutils-raw/src/functions.rs b/keyutils-raw/src/functions.rs index 2a29a29..966308c 100644 --- a/keyutils-raw/src/functions.rs +++ b/keyutils-raw/src/functions.rs @@ -100,12 +100,12 @@ extern "C" { id: KeyringSerial, payload: *const libc::c_void, plen: libc::size_t, - ringid: KeyringSerial) + ringid: Option) -> libc::c_long; pub fn keyctl_negate( id: KeyringSerial, timeout: TimeoutSeconds, - ringid: KeyringSerial) + ringid: Option) -> libc::c_long; pub fn keyctl_set_reqkey_keyring( reqkey_defl: libc::c_int) @@ -128,7 +128,7 @@ extern "C" { id: KeyringSerial, timeout: TimeoutSeconds, error: libc::c_uint, - ringid: KeyringSerial) + ringid: Option) -> libc::c_long; pub fn keyctl_invalidate( id: KeyringSerial) diff --git a/src/api.rs b/src/api.rs index 3d2f677..972d69e 100644 --- a/src/api.rs +++ b/src/api.rs @@ -748,6 +748,48 @@ impl Description { } } +/// The destination keyring of an instantiation request. +#[derive(Debug)] +pub enum TargetKeyring<'a> { + /// A special keyring. + Special(SpecialKeyring), + /// A specific keyring. + Keyring(&'a mut Keyring), +} + +impl<'a> TargetKeyring<'a> { + fn serial(self) -> KeyringSerial { + match self { + TargetKeyring::Special(special) => special.serial(), + TargetKeyring::Keyring(keyring) => keyring.id, + } + } +} + +impl<'a> From for TargetKeyring<'a> { + fn from(special: SpecialKeyring) -> Self { + TargetKeyring::Special(special) + } +} + +impl<'a> From<&'a mut Keyring> for TargetKeyring<'a> { + fn from(keyring: &'a mut Keyring) -> Self { + TargetKeyring::Keyring(keyring) + } +} + +impl<'a> From for Option> { + fn from(special: SpecialKeyring) -> Self { + Some(special.into()) + } +} + +impl<'a> From<&'a mut Keyring> for Option> { + fn from(keyring: &'a mut Keyring) -> Self { + Some(keyring.into()) + } +} + /// A manager for a key to respond to instantiate a key request by the kernel. #[derive(Debug, PartialEq, Eq)] pub struct KeyManager { @@ -776,8 +818,9 @@ impl KeyManager { } /// Instantiate the key with the given payload. - pub fn instantiate

(self, keyring: &Keyring, payload: P) -> Result<()> + pub fn instantiate<'a, T, P>(self, keyring: T, payload: P) -> Result<()> where + T: Into>>, P: AsRef<[u8]>, { let payload = payload.as_ref(); @@ -786,7 +829,7 @@ impl KeyManager { self.key.id, payload.as_ptr() as *const libc::c_void, payload.len(), - keyring.id, + keyring.into().map(TargetKeyring::serial), ) }) } @@ -797,14 +840,17 @@ impl KeyManager { /// seconds are ignored). This is to prevent a denial-of-service by /// requesting a non-existant key repeatedly. The requester must have /// `write` permission on the keyring. - pub fn reject(self, keyring: &Keyring, timeout: Duration, error: errno::Errno) -> Result<()> { + pub fn reject<'a, T>(self, keyring: T, timeout: Duration, error: errno::Errno) -> Result<()> + where + T: Into>>, + { let errno::Errno(errval) = error; check_call(unsafe { keyctl_reject( self.key.id, timeout.as_secs() as TimeoutSeconds, errval as u32, - keyring.id, + keyring.into().map(TargetKeyring::serial), ) }) } @@ -815,9 +861,16 @@ impl KeyManager { /// seconds are ignored). This is to prevent a denial-of-service by /// requesting a non-existant key repeatedly. The requester must have /// `write` permission on the keyring. - pub fn negate(self, keyring: &Keyring, timeout: Duration) -> Result<()> { + pub fn negate<'a, T>(self, keyring: T, timeout: Duration) -> Result<()> + where + T: Into>>, + { check_call(unsafe { - keyctl_negate(self.key.id, timeout.as_secs() as TimeoutSeconds, keyring.id) + keyctl_negate( + self.key.id, + timeout.as_secs() as TimeoutSeconds, + keyring.into().map(TargetKeyring::serial), + ) }) } } diff --git a/src/constants.rs b/src/constants.rs index 6b43190..7682c3a 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -28,6 +28,7 @@ use bitflags::bitflags; use keyutils_raw::*; /// Special keyrings predefined for a process. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum SpecialKeyring { /// A thread-specific keyring. Thread, From 30f0e53984f308d88415373eb64500a39e95fd61 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 1 Aug 2019 20:56:33 -0400 Subject: [PATCH 27/47] tests/instantiate: add tests for key instantiation --- src/api.rs | 5 + src/tests/instantiate.rs | 224 +++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + 3 files changed, 230 insertions(+) create mode 100644 src/tests/instantiate.rs diff --git a/src/api.rs b/src/api.rs index 972d69e..d9cfdef 100644 --- a/src/api.rs +++ b/src/api.rs @@ -803,6 +803,11 @@ impl KeyManager { } } + #[cfg(test)] + pub(crate) fn test_new(key: Key) -> Self { + Self::new(key) + } + /// Requests the authorization key created by `request_key`. /// /// This key must be present in an available keyring before `Key::manage` may be called. diff --git a/src/tests/instantiate.rs b/src/tests/instantiate.rs new file mode 100644 index 0000000..a139f98 --- /dev/null +++ b/src/tests/instantiate.rs @@ -0,0 +1,224 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::time::Duration; + +use crate::keytypes::User; +use crate::KeyManager; + +use super::utils; + +#[test] +fn instantiate_invalid_key() { + let key = utils::invalid_key(); + let manager = KeyManager::test_new(key); + + let payload = "payload".as_bytes(); + let err = manager.instantiate(None, payload).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); +} + +#[test] +fn reject_invalid_key() { + let key = utils::invalid_key(); + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let errno = errno::Errno(libc::EKEYREJECTED); + let err = manager.reject(None, duration, errno).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); +} + +#[test] +fn negate_invalid_key() { + let key = utils::invalid_key(); + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let err = manager.negate(None, duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); +} + +#[test] +fn instantiate_into_not_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("instantiate_into_not_key", payload) + .unwrap(); + let mut not_a_keyring = utils::key_as_keyring(&key); + let manager = KeyManager::test_new(key); + + let payload = "payload".as_bytes(); + let err = manager + .instantiate(&mut not_a_keyring, payload) + .unwrap_err(); + // Should be ENOTDIR, but the kernel doesn't have an authorization key for us to use. + assert_eq!(err, errno::Errno(libc::EPERM)); +} + +#[test] +fn reject_into_not_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("reject_into_not_key", payload) + .unwrap(); + let mut not_a_keyring = utils::key_as_keyring(&key); + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let errno = errno::Errno(libc::EKEYREJECTED); + let err = manager + .reject(&mut not_a_keyring, duration, errno) + .unwrap_err(); + // Should be ENOTDIR, but the kernel doesn't have an authorization key for us to use. + assert_eq!(err, errno::Errno(libc::EPERM)); +} + +#[test] +fn negate_into_not_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("negate_into_not_key", payload) + .unwrap(); + let mut not_a_keyring = utils::key_as_keyring(&key); + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let err = manager.negate(&mut not_a_keyring, duration).unwrap_err(); + // Should be ENOTDIR, but the kernel doesn't have an authorization key for us to use. + assert_eq!(err, errno::Errno(libc::EPERM)); +} + +#[test] +fn instantiate_already_instantiated() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("instantiate_already_instantiated", payload) + .unwrap(); + let manager = KeyManager::test_new(key); + + let err = manager.instantiate(None, payload).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() +} + +#[test] +fn reject_already_instantiated() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("reject_already_instantiated", payload) + .unwrap(); + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let errno = errno::Errno(libc::EKEYREJECTED); + let err = manager.reject(None, duration, errno).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() +} + +#[test] +fn negate_already_instantiated() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("negate_already_instantiated", payload) + .unwrap(); + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let err = manager.negate(None, duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() +} + +#[test] +fn instantiate_unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("instantiate_unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let manager = KeyManager::test_new(key); + + let err = manager.instantiate(None, payload).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() +} + +#[test] +fn reject_unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("reject_unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let errno = errno::Errno(libc::EKEYREJECTED); + let err = manager.reject(None, duration, errno).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() +} + +#[test] +fn negate_unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("negate_unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let manager = KeyManager::test_new(key); + + let duration = Duration::from_secs(1); + let err = manager.negate(None, duration).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index cf81832..de729ba 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -31,6 +31,7 @@ pub(crate) mod utils; mod add; mod clear; mod describe; +mod instantiate; mod invalidate; mod newring; mod reading; From ba3637da280828c778fdfd299057f8a8ac1a1554 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 2 Aug 2019 08:35:26 -0400 Subject: [PATCH 28/47] Keyring::read: guard against a key-as-keyring panic The parser for the key payload is blindly trusting that the key ID is actually a keyring and not transformed or replaced in some way. Guard against this case be ensuring that we actually have a keyring ID. --- src/api.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/api.rs b/src/api.rs index d9cfdef..47a8a6f 100644 --- a/src/api.rs +++ b/src/api.rs @@ -261,6 +261,18 @@ impl Keyring { /// /// Requires `read` permission on the keyring. pub fn read(&self) -> Result<(Vec, Vec)> { + // The `description` check below hides this error code from the kernel. + if self.id.get() == 0 { + return Err(errno::Errno(libc::ENOKEY)); + } + + // Avoid a panic in the code below be ensuring that we actually have a keyring. Parsing + // a key's payload as a keyring payload. + let desc = self.description()?; + if desc.type_ != keytypes::Keyring::name() { + return Err(errno::Errno(libc::ENOTDIR)); + } + let sz = unsafe { keyctl_read(self.id, ptr::null_mut(), 0) }; check_call(sz)?; let mut buffer = Vec::with_capacity((sz as usize) / mem::size_of::()); From b2839041f97ee44d76f0b563d349e361e6a8ab62 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 2 Aug 2019 08:36:42 -0400 Subject: [PATCH 29/47] tests/reading: test reading keys and keyrings as each other --- src/tests/reading.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/tests/reading.rs b/src/tests/reading.rs index 598aa21..4d68554 100644 --- a/src/tests/reading.rs +++ b/src/tests/reading.rs @@ -102,6 +102,32 @@ fn read_keyring() { keyring.invalidate().unwrap() } +#[test] +fn read_key_as_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("read_key_as_keyring", payload) + .unwrap(); + let not_a_keyring = utils::key_as_keyring(&key); + + let err = not_a_keyring.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.invalidate().unwrap() +} + +#[test] +fn read_keyring_as_key() { + let keyring = utils::new_test_keyring(); + let not_a_key = utils::keyring_as_key(&keyring); + + let payload = not_a_key.read().unwrap(); + assert_eq!(b"", payload.as_slice()); + + keyring.invalidate().unwrap() +} + #[test] fn read_no_read_perm_with_search() { let mut keyring = utils::new_test_keyring(); From 317a16cbb6c1210404138b91082713a828ad9647 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 12 Aug 2019 20:58:27 -0400 Subject: [PATCH 30/47] constants: fix a typo in the Permission docstring --- src/constants.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.rs b/src/constants.rs index 7682c3a..272bbae 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -66,7 +66,7 @@ bitflags! { /// keyring, and a third set which is used when neither of the other two match. /// /// The fourth set is combined with the permission set used above (priority to user, then - /// group, finaly other) where either set granting a permission allows it. This set is, + /// group, finally other) where either set granting a permission allows it. This set is, /// however, only used if the caller is a "possessor" of they key or keyring. Generally, /// "possession" requires the `search` permission, association from the calling thread /// (the session, process, and thread keyrings), or is linked to from a possessed keyring. See From 2e0c1b947ffc2db08a394928633160c626d4525c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 12 Aug 2019 20:59:20 -0400 Subject: [PATCH 31/47] encrypted: add support for the `enc32` format --- src/keytypes/encrypted.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/keytypes/encrypted.rs b/src/keytypes/encrypted.rs index 46234ad..fef2674 100644 --- a/src/keytypes/encrypted.rs +++ b/src/keytypes/encrypted.rs @@ -60,6 +60,11 @@ pub enum Format { /// Keys of this format must have a description of exactly 16 hexadecimal characters. The /// keylength must also be 64. Ecryptfs, + /// Encrypted keys with a payload size of 32 bytes. + /// + /// Intended for nvdimm security, but may be used for other 32-byte payload use cases in the + /// future. + Enc32, } impl Format { @@ -68,6 +73,7 @@ impl Format { match *self { Format::Default => "default", Format::Ecryptfs => "ecryptfs", + Format::Enc32 => "enc32", } } } From 8e054fc3e97c89f56353d59b1c5014978d0cecf7 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 13 Aug 2019 20:32:55 -0400 Subject: [PATCH 32/47] tests/link: add tests for link behavior --- src/api.rs | 44 ------- src/tests/link.rs | 323 ++++++++++++++++++++++++++++++++++++++++++++++ src/tests/mod.rs | 1 + 3 files changed, 324 insertions(+), 44 deletions(-) create mode 100644 src/tests/link.rs diff --git a/src/api.rs b/src/api.rs index 47a8a6f..28c4af5 100644 --- a/src/api.rs +++ b/src/api.rs @@ -897,50 +897,6 @@ mod tests { use super::*; use crate::tests::utils; - #[test] - fn test_link_key() { - let mut keyring = utils::new_test_keyring(); - let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); - - // Create the key. - let description = "test:rust-keyutils:link_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - - new_keyring.link_key(&key).unwrap(); - - let (keys, keyrings) = new_keyring.read().unwrap(); - assert_eq!(keys.len(), 1); - assert_eq!(keys[0], key); - assert_eq!(keyrings.len(), 0); - - // Clean up. - key.invalidate().unwrap(); - new_keyring.invalidate().unwrap(); - keyring.invalidate().unwrap(); - } - - #[test] - fn test_link_keyring() { - let mut keyring = utils::new_test_keyring(); - let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); - let new_inner_keyring = keyring.add_keyring("new_inner_keyring").unwrap(); - - new_keyring.link_keyring(&new_inner_keyring).unwrap(); - - let (keys, keyrings) = new_keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 1); - assert_eq!(keyrings[0], new_inner_keyring); - - // Clean up. - new_inner_keyring.invalidate().unwrap(); - new_keyring.invalidate().unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_chmod_keyring() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/link.rs b/src/tests/link.rs new file mode 100644 index 0000000..7579b95 --- /dev/null +++ b/src/tests/link.rs @@ -0,0 +1,323 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::User; +use crate::Permission; + +use super::utils; + +#[test] +fn invalid_target() { + let mut invalid_keyring = utils::invalid_keyring(); + let keyring = utils::new_test_keyring(); + + let err = invalid_keyring.link_keyring(&keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalid_source() { + let invalid_keyring = utils::invalid_keyring(); + let mut keyring = utils::new_test_keyring(); + + let err = keyring.link_keyring(&invalid_keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_to_non_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("link_to_non_keyring", payload) + .unwrap(); + let linked_key = keyring + .add_key::("link_to_non_keyring_linked", payload) + .unwrap(); + let mut not_a_keyring = utils::key_as_keyring(&key); + + let err = not_a_keyring.link_key(&linked_key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("link_unlinked_key", payload) + .unwrap(); + let mut target_keyring = keyring.add_keyring("link_unlinked_key_target").unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = target_keyring.link_key(&key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_into_unlinked_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("link_into_unlinked_keyring", payload) + .unwrap(); + let mut target_keyring = keyring + .add_keyring("link_into_unlinked_keyring_target") + .unwrap(); + + keyring.unlink_keyring(&target_keyring).unwrap(); + utils::wait_for_keyring_gc(&target_keyring); + + let err = target_keyring.link_key(&key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_self() { + let mut keyring = utils::new_test_keyring(); + let keyring_observer = keyring.clone(); + + let err = keyring.link_keyring(&keyring_observer).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EDEADLK)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_self_via_child() { + let mut keyring = utils::new_test_keyring(); + let mut target_keyring = keyring.add_keyring("link_self_via_child").unwrap(); + + let err = target_keyring.link_keyring(&keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EDEADLK)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_self_via_child_chains() { + let mut keyring = utils::new_test_keyring(); + let mut target_keyring = keyring.clone(); + let perms = Permission::POSSESSOR_ALL | Permission::USER_ALL; + target_keyring.set_permissions(perms).unwrap(); + + let maxdepth = 8; + for depth in 1..maxdepth { + let mut new_keyring = keyring + .add_keyring(format!("link_self_via_child_chains{}", depth)) + .unwrap(); + new_keyring.set_permissions(perms).unwrap(); + + target_keyring.link_keyring(&new_keyring).unwrap(); + target_keyring = new_keyring; + + let err = target_keyring.link_keyring(&keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EDEADLK)); + } + + let mut new_keyring = keyring + .add_keyring(format!("link_self_via_child_chains{}", maxdepth)) + .unwrap(); + new_keyring.set_permissions(perms).unwrap(); + + target_keyring.link_keyring(&new_keyring).unwrap(); + keyring.unlink_keyring(&new_keyring).unwrap(); + target_keyring = new_keyring; + + let err = target_keyring.link_keyring(&keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ELOOP)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_self_via_keyring_stacks() { + let mut keyring = utils::new_test_keyring(); + let keyring_a_root = keyring + .add_keyring("link_self_via_keyring_stacks_a") + .unwrap(); + let keyring_b_root = keyring + .add_keyring("link_self_via_keyring_stacks_b") + .unwrap(); + let mut keyring_a = keyring_a_root.clone(); + let mut keyring_b = keyring_b_root.clone(); + + let maxdepth = 4; + for depth in 1..maxdepth { + keyring_a = keyring_a + .add_keyring(format!("link_self_via_keyring_stacks_a{}", depth)) + .unwrap(); + keyring_b = keyring_b + .add_keyring(format!("link_self_via_keyring_stacks_b{}", depth)) + .unwrap(); + } + + keyring_b.link_keyring(&keyring_a_root).unwrap(); + + let err = keyring_a.link_keyring(&keyring_b_root).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EDEADLK)); + + keyring_b.unlink_keyring(&keyring_a_root).unwrap(); + + keyring_a.link_keyring(&keyring_b_root).unwrap(); + + let err = keyring_b.link_keyring(&keyring_a_root).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EDEADLK)); + + keyring.invalidate().unwrap() +} + +#[test] +fn link_self_via_keyring_deep_stacks() { + let mut keyring = utils::new_test_keyring(); + let keyring_a_root = keyring + .add_keyring("link_self_via_keyring_deep_stacks_a") + .unwrap(); + let keyring_b_root = keyring + .add_keyring("link_self_via_keyring_deep_stacks_b") + .unwrap(); + let mut keyring_a = keyring_a_root.clone(); + let mut keyring_b = keyring_b_root.clone(); + + let maxdepth = 5; + for depth in 1..maxdepth { + keyring_a = keyring_a + .add_keyring(format!("link_self_via_keyring_deep_stacks_a{}", depth)) + .unwrap(); + keyring_b = keyring_b + .add_keyring(format!("link_self_via_keyring_deep_stacks_b{}", depth)) + .unwrap(); + } + + keyring_b.link_keyring(&keyring_a_root).unwrap(); + + let err = keyring_a.link_keyring(&keyring_b_root).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ELOOP)); + + keyring_b.unlink_keyring(&keyring_a_root).unwrap(); + + keyring_a.link_keyring(&keyring_b_root).unwrap(); + + let err = keyring_b.link_keyring(&keyring_a_root).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ELOOP)); + + keyring.invalidate().unwrap() +} + +#[test] +fn multiply_link_key_into_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("multiply_link_key_into_keyring") + .unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], new_keyring); + + let payload = "payload".as_bytes(); + let key = new_keyring + .add_key::("multiply_link_key_into_keyring_key", payload) + .unwrap(); + + let (keys, keyrings) = new_keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], key); + assert!(keyrings.is_empty()); + + keyring.link_key(&key).unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], key); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], new_keyring); + + // Linking the same key should not change the result. + keyring.link_key(&key).unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], key); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], new_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn multiply_link_keyring_into_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("multiply_link_keyring_into_keyring") + .unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], new_keyring); + + let inner_keyring = new_keyring + .add_keyring("multiply_link_keyring_into_keyring_keyring_inner") + .unwrap(); + + let (keys, keyrings) = new_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], inner_keyring); + + keyring.link_keyring(&inner_keyring).unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 2); + assert_eq!(keyrings[0], new_keyring); + assert_eq!(keyrings[1], inner_keyring); + + // Linking the same keyring should not change the result. + keyring.link_keyring(&inner_keyring).unwrap(); + + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 2); + assert_eq!(keyrings[0], new_keyring); + assert_eq!(keyrings[1], inner_keyring); + + keyring.invalidate().unwrap() +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index de729ba..8cd6fa4 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -33,6 +33,7 @@ mod clear; mod describe; mod instantiate; mod invalidate; +mod link; mod newring; mod reading; mod revoke; From afa55af372fee24ebf13f17a2c8fc044dc02c013 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 13 Aug 2019 20:54:03 -0400 Subject: [PATCH 33/47] tests/unlink: add tests for unlinking keyrings and keys --- src/api.rs | 57 ---------- src/tests/mod.rs | 1 + src/tests/unlink.rs | 256 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 257 insertions(+), 57 deletions(-) create mode 100644 src/tests/unlink.rs diff --git a/src/api.rs b/src/api.rs index 28c4af5..b7dcdf7 100644 --- a/src/api.rs +++ b/src/api.rs @@ -983,61 +983,4 @@ mod tests { new_keyring.invalidate().unwrap(); keyring.invalidate().unwrap(); } - - #[test] - fn test_unlink_keyring() { - let mut keyring = utils::new_test_keyring(); - - // Create the keyring. - let description = "test:rust-keyutils:unlink_keyring"; - let new_keyring = keyring.add_keyring(description).unwrap(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 1); - - // Unlink the key. - keyring.unlink_keyring(&new_keyring).unwrap(); - - // Use the keyring. - let err = new_keyring.read().unwrap_err(); - assert_eq!(err.0, libc::EACCES); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap(); - } - - #[test] - fn test_unlink_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:unlink_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 1); - assert_eq!(keyrings.len(), 0); - - // Unlink the key. - keyring.unlink_key(&key).unwrap(); - - // Use the key. - let err = key.read().unwrap_err(); - assert_eq!(err.0, libc::EACCES); - - let (keys, keyrings) = keyring.read().unwrap(); - assert_eq!(keys.len(), 0); - assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap(); - } } diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 8cd6fa4..b2e6c02 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -39,4 +39,5 @@ mod reading; mod revoke; mod session; mod timeout; +mod unlink; mod update; diff --git a/src/tests/unlink.rs b/src/tests/unlink.rs new file mode 100644 index 0000000..e2f288f --- /dev/null +++ b/src/tests/unlink.rs @@ -0,0 +1,256 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::User; + +use super::utils; + +#[test] +fn invalid_target_key() { + let mut invalid_keyring = utils::invalid_keyring(); + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("invalid_target_key", payload) + .unwrap(); + + let err = invalid_keyring.unlink_key(&key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalid_target_keyring() { + let mut invalid_keyring = utils::invalid_keyring(); + let keyring = utils::new_test_keyring(); + + let err = invalid_keyring.unlink_keyring(&keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalid_source_key() { + let mut keyring = utils::new_test_keyring(); + let invalid_key = utils::invalid_key(); + + let err = keyring.unlink_key(&invalid_key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalid_source_keyring() { + let mut keyring = utils::new_test_keyring(); + let invalid_keyring = utils::invalid_keyring(); + + let err = keyring.unlink_keyring(&invalid_keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_key_from_non_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlink_key_from_non_keyring", payload) + .unwrap(); + let mut not_a_keyring = utils::key_as_keyring(&key); + + let err = not_a_keyring.unlink_key(&key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_keyring_from_non_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlink_keyring_from_non_keyring", payload) + .unwrap(); + let mut not_a_keyring = utils::key_as_keyring(&key); + + let err = not_a_keyring.unlink_keyring(&keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_key_as_keyring() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlink_keyring_from_non_keyring", payload) + .unwrap(); + let not_a_keyring = utils::key_as_keyring(&key); + + // This is OK because the kernel doesn't have the type knowledge that our API does. + keyring.unlink_keyring(¬_a_keyring).unwrap(); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_keyring_as_key() { + let mut keyring = utils::new_test_keyring(); + let new_keyring = keyring.add_keyring("unlink_keyring_as_key").unwrap(); + let not_a_key = utils::keyring_as_key(&new_keyring); + + // This is OK because the kernel doesn't have the type knowledge that our API does. + keyring.unlink_key(¬_a_key).unwrap(); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_unlinked_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlink_unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = keyring.unlink_key(&key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_unlinked_keyring() { + let mut keyring = utils::new_test_keyring(); + let new_keyring = keyring.add_keyring("unlink_unlinked_keyring").unwrap(); + + keyring.unlink_keyring(&new_keyring).unwrap(); + utils::wait_for_keyring_gc(&new_keyring); + + let err = keyring.unlink_keyring(&new_keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_key_from_unlinked_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut keyring_observer = keyring.clone(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlink_key_from_unlinked_keyring", payload) + .unwrap(); + + keyring.invalidate().unwrap(); + utils::wait_for_keyring_gc(&keyring_observer); + + let err = keyring_observer.unlink_key(&key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); +} + +#[test] +fn unlink_keyring_from_unlinked_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut keyring_observer = keyring.clone(); + let new_keyring = keyring.add_keyring("unlink_from_unlinked_keyring").unwrap(); + + keyring.invalidate().unwrap(); + utils::wait_for_keyring_gc(&keyring_observer); + + let err = keyring_observer.unlink_keyring(&new_keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); +} + +#[test] +fn unlink_unassociated_key() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring.add_keyring("unlink_unassociated_key").unwrap(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlink_unassociated_key", payload) + .unwrap(); + + let err = new_keyring.unlink_key(&key).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOENT)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_unassociated_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring.add_keyring("unlink_unassociated_keyring").unwrap(); + let inner_keyring = keyring + .add_keyring("unlink_unassociated_keyring_keyring") + .unwrap(); + + let err = new_keyring.unlink_keyring(&inner_keyring).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOENT)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("unlink_unlinked_key", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn unlink_keyring() { + let mut keyring = utils::new_test_keyring(); + let new_keyring = keyring.add_keyring("unlink_keyring").unwrap(); + + keyring.unlink_keyring(&new_keyring).unwrap(); + utils::wait_for_keyring_gc(&new_keyring); + + let (keys, keyrings) = keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} From fdbfb5a614dab9192ed6c744b261dc401347b939 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 13 Aug 2019 21:51:30 -0400 Subject: [PATCH 34/47] Keyring: fix API for searching The destination keyring does not need to be the same as the one that is searched. Fix the API and remove the now-broken tests. --- keyutils-raw/src/functions.rs | 2 +- src/api.rs | 66 ++++++++++------------------------- 2 files changed, 19 insertions(+), 49 deletions(-) diff --git a/keyutils-raw/src/functions.rs b/keyutils-raw/src/functions.rs index 966308c..cd8bf07 100644 --- a/keyutils-raw/src/functions.rs +++ b/keyutils-raw/src/functions.rs @@ -89,7 +89,7 @@ extern "C" { ringid: KeyringSerial, type_: *const libc::c_char, description: *const libc::c_char, - destringid: KeyringSerial) + destringid: Option) -> libc::c_long; pub fn keyctl_read( id: KeyringSerial, diff --git a/src/api.rs b/src/api.rs index b7dcdf7..c336685 100644 --- a/src/api.rs +++ b/src/api.rs @@ -218,14 +218,19 @@ impl Keyring { check_call(unsafe { keyctl_unlink(keyring.id, self.id) }) } - fn search_impl(&self, description: &str) -> KeyringSerial + fn search_impl(&self, description: &str, destination: Option<&mut Keyring>) -> KeyringSerial where K: KeyType, { let type_cstr = CString::new(K::name()).unwrap(); let desc_cstr = CString::new(description).unwrap(); into_serial(unsafe { - keyctl_search(self.id, type_cstr.as_ptr(), desc_cstr.as_ptr(), self.id) + keyctl_search( + self.id, + type_cstr.as_ptr(), + desc_cstr.as_ptr(), + destination.map(|dest| dest.id), + ) }) } @@ -234,12 +239,15 @@ impl Keyring { /// If it is found, it is attached to the keyring (if `write` permission to the keyring and /// `link` permission on the key exist) and return it. Requires the `search` permission on the /// keyring. Any children keyrings without the `search` permission are ignored. - pub fn search_for_key(&self, description: D) -> Result + pub fn search_for_key<'a, K, D, DK>(&self, description: D, destination: DK) -> Result where K: KeyType, D: Borrow, + DK: Into>, { - check_call_key(self.search_impl::(&description.borrow().description())) + check_call_key( + self.search_impl::(&description.borrow().description(), destination.into()), + ) } /// Recursively search the keyring for a keyring with the matching description. @@ -248,13 +256,15 @@ impl Keyring { /// `link` permission on the found keyring exist) and return it. Requires the `search` /// permission on the keyring. Any children keyrings without the `search` permission are /// ignored. - pub fn search_for_keyring(&self, description: D) -> Result + pub fn search_for_keyring<'a, D, DK>(&self, description: D, destination: DK) -> Result where D: Borrow<::Description>, + DK: Into>, { - check_call_keyring( - self.search_impl::(&description.borrow().description()), - ) + check_call_keyring(self.search_impl::( + &description.borrow().description(), + destination.into(), + )) } /// Return all immediate children of the keyring. @@ -943,44 +953,4 @@ mod tests { keyring.unlink_key(&key).unwrap(); keyring.invalidate().unwrap(); } - - #[test] - fn test_search_key() { - let mut keyring = utils::new_test_keyring(); - let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); - let mut new_inner_keyring = new_keyring.add_keyring("new_inner_keyring").unwrap(); - - // Create the key. - let description = "test:rust-keyutils:search_key"; - let payload = "payload"; - let key = new_inner_keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - - let found_key = keyring - .search_for_key::(description) - .unwrap(); - assert_eq!(found_key, key); - - // Clean up. - new_inner_keyring.unlink_key(&key).unwrap(); - new_inner_keyring.invalidate().unwrap(); - new_keyring.invalidate().unwrap(); - keyring.invalidate().unwrap(); - } - - #[test] - fn test_search_keyring() { - let mut keyring = utils::new_test_keyring(); - let mut new_keyring = keyring.add_keyring("new_keyring").unwrap(); - let new_inner_keyring = new_keyring.add_keyring("new_inner_keyring").unwrap(); - - let found_keyring = keyring.search_for_keyring("new_inner_keyring").unwrap(); - assert_eq!(found_keyring, new_inner_keyring); - - // Clean up. - new_inner_keyring.invalidate().unwrap(); - new_keyring.invalidate().unwrap(); - keyring.invalidate().unwrap(); - } } From 2c2c748863dfd41ca49b2f0abe0880c308db0c3b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 13 Aug 2019 22:15:31 -0400 Subject: [PATCH 35/47] tests/search: test searching for keys and keyrings --- src/tests/mod.rs | 1 + src/tests/search.rs | 763 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 764 insertions(+) create mode 100644 src/tests/search.rs diff --git a/src/tests/mod.rs b/src/tests/mod.rs index b2e6c02..d971f00 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -37,6 +37,7 @@ mod link; mod newring; mod reading; mod revoke; +mod search; mod session; mod timeout; mod unlink; diff --git a/src/tests/search.rs b/src/tests/search.rs new file mode 100644 index 0000000..3f3c113 --- /dev/null +++ b/src/tests/search.rs @@ -0,0 +1,763 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::iter; + +use crate::keytypes::User; +use crate::Permission; + +use super::utils; +use super::utils::kernel::*; +use super::utils::keys::*; + +#[test] +fn empty_key_type() { + let keyring = utils::new_test_keyring(); + + let err = keyring + .search_for_key::("empty_key_type", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn unsupported_key_type() { + let keyring = utils::new_test_keyring(); + + let err = keyring + .search_for_key::("unsupported_key_type", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalid_key_type() { + let keyring = utils::new_test_keyring(); + + let err = keyring + .search_for_key::("invalid_key_type", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EPERM)); + + keyring.invalidate().unwrap() +} + +#[test] +fn max_key_type() { + let keyring = utils::new_test_keyring(); + + let err = keyring + .search_for_key::("invalid_key_type", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn overlong_key_type() { + let keyring = utils::new_test_keyring(); + + let err = keyring + .search_for_key::("overlong_key_type", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn max_user_description() { + let keyring = utils::new_test_keyring(); + + // Subtract one because the NUL is added in the kernel API. + let maxdesc: String = iter::repeat('a').take(*PAGE_SIZE - 1).collect(); + let err = keyring + .search_for_key::(maxdesc, None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn overlong_user_description() { + let keyring = utils::new_test_keyring(); + + // On MIPS with < 3.19, there is a bug where this is allowed. 3.19 was released in Feb 2015, + // so this is being ignored here. + let maxdesc: String = iter::repeat('a').take(*PAGE_SIZE).collect(); + let err = keyring + .search_for_key::(maxdesc, None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap() +} + +#[test] +fn invalid_keyring() { + let keyring = utils::invalid_keyring(); + + let err = keyring + .search_for_key::("invalid_keyring", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn search_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let key = keyring + .add_key::("search_key", payload) + .unwrap(); + let not_a_keyring = utils::key_as_keyring(&key); + + let err = not_a_keyring + .search_for_key::("search_key", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_key_no_result() { + let keyring = utils::new_test_keyring(); + + let err = keyring + .search_for_key::("search_key_no_result", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_keyring_no_result() { + let keyring = utils::new_test_keyring(); + + let err = keyring + .search_for_keyring("search_keyring_no_result", None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_key_mismatched_type() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring.add_keyring("search_key_mismatched_type").unwrap(); + let description = "search_key_mismatched_type_keyring"; + let _ = new_keyring.add_keyring(description).unwrap(); + + let err = keyring + .search_for_key::(description, None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_keyring_mismatched_type() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_keyring_mismatched_type") + .unwrap(); + let description = "search_keyring_mismatched_type_key"; + let payload = "payload".as_bytes(); + let _ = new_keyring + .add_key::(description, payload) + .unwrap(); + + let err = keyring.search_for_keyring(description, None).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring.add_keyring("search_and_find_key").unwrap(); + let description = "search_and_find_key_key"; + let payload = "payload".as_bytes(); + let key = new_keyring + .add_key::(description, payload) + .unwrap(); + + let found_key = keyring + .search_for_key::(description, None) + .unwrap(); + assert_eq!(found_key, key); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring.add_keyring("search_and_find_keyring").unwrap(); + let description = "search_and_find_keyring_keyring"; + let target_keyring = new_keyring.add_keyring(description).unwrap(); + + let found_keyring = keyring.search_for_keyring(description, None).unwrap(); + assert_eq!(found_keyring, target_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_no_search_perm_interm() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_key_no_search_perm_interm") + .unwrap(); + let description = "search_and_find_key_no_search_perm_interm_key"; + let payload = "payload".as_bytes(); + let _ = new_keyring + .add_key::(description, payload) + .unwrap(); + + let perms = { + let mut orig_perms = new_keyring.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_SEARCH); + orig_perms.remove(Permission::USER_SEARCH); + orig_perms.remove(Permission::GROUP_SEARCH); + orig_perms.remove(Permission::OTHER_SEARCH); + orig_perms + }; + new_keyring.set_permissions(perms).unwrap(); + + let err = keyring + .search_for_key::(description, None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_no_search_perm_interm() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_keyring_no_search_perm_interm") + .unwrap(); + let description = "search_and_find_keyring_no_search_perm_interm_keyring"; + let _ = new_keyring.add_keyring(description).unwrap(); + + let perms = { + let mut orig_perms = new_keyring.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_SEARCH); + orig_perms.remove(Permission::USER_SEARCH); + orig_perms.remove(Permission::GROUP_SEARCH); + orig_perms.remove(Permission::OTHER_SEARCH); + orig_perms + }; + new_keyring.set_permissions(perms).unwrap(); + + let err = keyring.search_for_keyring(description, None).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_no_search_perm_direct() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_key_no_search_perm_direct") + .unwrap(); + let description = "search_and_find_key_no_search_perm_direct_key"; + let payload = "payload".as_bytes(); + let mut key = new_keyring + .add_key::(description, payload) + .unwrap(); + + let perms = { + let mut orig_perms = key.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_SEARCH); + orig_perms.remove(Permission::USER_SEARCH); + orig_perms.remove(Permission::GROUP_SEARCH); + orig_perms.remove(Permission::OTHER_SEARCH); + orig_perms + }; + key.set_permissions(perms).unwrap(); + + let err = keyring + .search_for_key::(description, None) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_no_search_perm_direct() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_keyring_no_search_perm_direct") + .unwrap(); + let description = "search_and_find_keyring_no_search_perm_direct_keyring"; + let mut target_keyring = new_keyring.add_keyring(description).unwrap(); + + let perms = { + let mut orig_perms = target_keyring.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_SEARCH); + orig_perms.remove(Permission::USER_SEARCH); + orig_perms.remove(Permission::GROUP_SEARCH); + orig_perms.remove(Permission::OTHER_SEARCH); + orig_perms + }; + target_keyring.set_permissions(perms).unwrap(); + + let err = keyring.search_for_keyring(description, None).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_link() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring.add_keyring("search_and_find_key_link").unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_key_link_destination") + .unwrap(); + let description = "search_and_find_key_link_key"; + let payload = "payload".as_bytes(); + let key = new_keyring + .add_key::(description, payload) + .unwrap(); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + let found_key = keyring + .search_for_key::(description, &mut destination_keyring) + .unwrap(); + assert_eq!(found_key, key); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], key); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_link() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring.add_keyring("search_and_find_keyring_link").unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_keyring_link_destination") + .unwrap(); + let description = "search_and_find_keyring_link_keyring"; + let target_keyring = new_keyring.add_keyring(description).unwrap(); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + let found_keyring = keyring + .search_for_keyring(description, &mut destination_keyring) + .unwrap(); + assert_eq!(found_keyring, target_keyring); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], target_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_link_replace() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_key_link_replace") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_key_link_replace_destination") + .unwrap(); + let description = "search_and_find_key_link_replace_key"; + let payload = "payload".as_bytes(); + let key = new_keyring + .add_key::(description, payload) + .unwrap(); + let other_payload = "payload".as_bytes(); + let orig_key = destination_keyring + .add_key::(description, other_payload) + .unwrap(); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], orig_key); + assert!(keyrings.is_empty()); + + let found_key = keyring + .search_for_key::(description, &mut destination_keyring) + .unwrap(); + assert_eq!(found_key, key); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + // The original key should have been replaced. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], key); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_link_replace_keyring() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_key_link_replace_keyring") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_key_link_replace_keyring_destination") + .unwrap(); + let description = "search_and_find_key_link_replace_keyring_key"; + let payload = "payload".as_bytes(); + let key = new_keyring + .add_key::(description, payload) + .unwrap(); + let orig_keyring = destination_keyring.add_keyring(description).unwrap(); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], orig_keyring); + + let found_key = keyring + .search_for_key::(description, &mut destination_keyring) + .unwrap(); + assert_eq!(found_key, key); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + // The original keyring should not have been replaced. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], key); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], orig_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_link_replace() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_keyring_link_replace") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_keyring_link_replace_destination") + .unwrap(); + let description = "search_and_find_keyring_link_replace_keyring"; + let target_keyring = new_keyring.add_keyring(description).unwrap(); + let orig_keyring = destination_keyring.add_keyring(description).unwrap(); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], orig_keyring); + + let found_keyring = keyring + .search_for_keyring(description, &mut destination_keyring) + .unwrap(); + assert_eq!(found_keyring, target_keyring); + + // The original keyring should have been replaced. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], target_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_link_replace_key() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_keyring_link_replace_key") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_keyring_link_replace_key_destination") + .unwrap(); + let description = "search_and_find_keyring_link_replace_key_keyring"; + let target_keyring = new_keyring.add_keyring(description).unwrap(); + let payload = "payload".as_bytes(); + let orig_key = destination_keyring + .add_key::(description, payload) + .unwrap(); + + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], orig_key); + assert!(keyrings.is_empty()); + + let found_keyring = keyring + .search_for_keyring(description, &mut destination_keyring) + .unwrap(); + assert_eq!(found_keyring, target_keyring); + + // The original keyring should not have been replaced. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert_eq!(keys.len(), 1); + assert_eq!(keys[0], orig_key); + assert_eq!(keyrings.len(), 1); + assert_eq!(keyrings[0], target_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_no_link_perm_no_dest() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_key_no_link_perm_no_dest") + .unwrap(); + let description = "search_and_find_key_no_link_perm_no_dest_key"; + let payload = "payload".as_bytes(); + let mut key = new_keyring + .add_key::(description, payload) + .unwrap(); + + let perms = { + let mut orig_perms = key.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_LINK); + orig_perms.remove(Permission::USER_LINK); + orig_perms.remove(Permission::GROUP_LINK); + orig_perms.remove(Permission::OTHER_LINK); + orig_perms + }; + key.set_permissions(perms).unwrap(); + + let found_key = keyring + .search_for_key::(description, None) + .unwrap(); + assert_eq!(found_key, key); + + let actual_payload = key.read().unwrap(); + assert_eq!(payload, actual_payload.as_slice()); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_no_link_perm_no_dest() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_keyring_no_link_perm_no_dest") + .unwrap(); + let description = "search_and_find_keyring_no_link_perm_no_dest_keyring"; + let mut target_keyring = new_keyring.add_keyring(description).unwrap(); + + let perms = { + let mut orig_perms = target_keyring.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_LINK); + orig_perms.remove(Permission::USER_LINK); + orig_perms.remove(Permission::GROUP_LINK); + orig_perms.remove(Permission::OTHER_LINK); + orig_perms + }; + target_keyring.set_permissions(perms).unwrap(); + + let found_keyring = keyring.search_for_keyring(description, None).unwrap(); + assert_eq!(found_keyring, target_keyring); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_no_link_perm() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_key_no_link_perm") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_key_no_link_perm_destination") + .unwrap(); + let description = "search_and_find_key_no_link_perm_key"; + let payload = "payload".as_bytes(); + let mut key = new_keyring + .add_key::(description, payload) + .unwrap(); + + let perms = { + let mut orig_perms = key.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_LINK); + orig_perms.remove(Permission::USER_LINK); + orig_perms.remove(Permission::GROUP_LINK); + orig_perms.remove(Permission::OTHER_LINK); + orig_perms + }; + key.set_permissions(perms).unwrap(); + + let err = keyring + .search_for_key::(description, &mut destination_keyring) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + // Assert that it was not linked to the destination keyring. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_no_link_perm() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_keyring_no_link_perm") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_keyring_no_link_perm_destination") + .unwrap(); + let description = "search_and_find_keyring_no_link_perm_keyring"; + let mut target_keyring = new_keyring.add_keyring(description).unwrap(); + + let perms = { + let mut orig_perms = target_keyring.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_LINK); + orig_perms.remove(Permission::USER_LINK); + orig_perms.remove(Permission::GROUP_LINK); + orig_perms.remove(Permission::OTHER_LINK); + orig_perms + }; + target_keyring.set_permissions(perms).unwrap(); + + let err = keyring + .search_for_keyring(description, &mut destination_keyring) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + // Assert that it was not linked to the destination keyring. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_key_no_write_perm() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_key_no_write_perm") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_key_no_write_perm_destination") + .unwrap(); + let description = "search_and_find_key_no_write_perm_key"; + let payload = "payload".as_bytes(); + let _ = new_keyring + .add_key::(description, payload) + .unwrap(); + + let perms = { + let mut orig_perms = destination_keyring.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_WRITE); + orig_perms.remove(Permission::USER_WRITE); + orig_perms.remove(Permission::GROUP_WRITE); + orig_perms.remove(Permission::OTHER_WRITE); + orig_perms + }; + destination_keyring.set_permissions(perms).unwrap(); + + let err = keyring + .search_for_key::(description, &mut destination_keyring) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + // Assert that it was not linked to the destination keyring. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn search_and_find_keyring_no_write_perm() { + let mut keyring = utils::new_test_keyring(); + let mut new_keyring = keyring + .add_keyring("search_and_find_keyring_no_write_perm") + .unwrap(); + let mut destination_keyring = keyring + .add_keyring("search_and_find_keyring_no_write_perm_destination") + .unwrap(); + let description = "search_and_find_keyring_no_write_perm_keyring"; + let _ = new_keyring.add_keyring(description).unwrap(); + + let perms = { + let mut orig_perms = destination_keyring.description().unwrap().perms; + orig_perms.remove(Permission::POSSESSOR_WRITE); + orig_perms.remove(Permission::USER_WRITE); + orig_perms.remove(Permission::GROUP_WRITE); + orig_perms.remove(Permission::OTHER_WRITE); + orig_perms + }; + destination_keyring.set_permissions(perms).unwrap(); + + let err = keyring + .search_for_keyring(description, &mut destination_keyring) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + // Assert that it was not linked to the destination keyring. + let (keys, keyrings) = destination_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} From 05b8ddb479822951e5216d54e7e6603e199aeada Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 14 Aug 2019 14:46:18 -0400 Subject: [PATCH 36/47] tests/permitting: add tests for permission modification --- src/api.rs | 36 ++--- src/tests/mod.rs | 1 + src/tests/permitting.rs | 285 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 296 insertions(+), 26 deletions(-) create mode 100644 src/tests/permitting.rs diff --git a/src/api.rs b/src/api.rs index c336685..c43e122 100644 --- a/src/api.rs +++ b/src/api.rs @@ -470,6 +470,11 @@ impl Keyring { check_call(unsafe { keyctl_setperm(self.id, perms.bits()) }) } + #[cfg(test)] + pub(crate) fn set_permissions_raw(&mut self, perms: KeyPermissions) -> Result<()> { + check_call(unsafe { keyctl_setperm(self.id, perms) }) + } + fn description_raw(&self) -> Result { let sz = unsafe { keyctl_describe(self.id, ptr::null_mut(), 0) }; check_call(sz)?; @@ -628,6 +633,11 @@ impl Key { Keyring::new_impl(self.id).set_permissions(perms) } + #[cfg(test)] + pub(crate) fn set_permissions_raw(&mut self, perms: KeyPermissions) -> Result<()> { + Keyring::new_impl(self.id).set_permissions_raw(perms) + } + /// Retrieve metadata about the key. /// /// # Panics @@ -907,32 +917,6 @@ mod tests { use super::*; use crate::tests::utils; - #[test] - fn test_chmod_keyring() { - let mut keyring = utils::new_test_keyring(); - let description = keyring.description().unwrap(); - let perms = description.perms; - let new_perms = { - let mut tmp_perms = perms.clone(); - let write_bits = Permission::POSSESSOR_WRITE - | Permission::USER_WRITE - | Permission::GROUP_WRITE - | Permission::OTHER_WRITE; - tmp_perms.remove(write_bits); - tmp_perms - }; - keyring.set_permissions(new_perms).unwrap(); - let err = keyring.add_keyring("new_keyring").unwrap_err(); - assert_eq!(err.0, libc::EACCES); - - keyring.set_permissions(perms).unwrap(); - let new_keyring = keyring.add_keyring("new_keyring").unwrap(); - - // Clean up. - new_keyring.invalidate().unwrap(); - keyring.invalidate().unwrap(); - } - #[test] fn test_request_key() { let mut keyring = utils::new_test_keyring(); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index d971f00..7e63d40 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -35,6 +35,7 @@ mod instantiate; mod invalidate; mod link; mod newring; +mod permitting; mod reading; mod revoke; mod search; diff --git a/src/tests/permitting.rs b/src/tests/permitting.rs new file mode 100644 index 0000000..e125b69 --- /dev/null +++ b/src/tests/permitting.rs @@ -0,0 +1,285 @@ +// Copyright (c) 2019, Ben Boeckel +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of this project nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::keytypes::User; +use crate::{KeyPermissions, Permission}; + +use super::utils; +use super::utils::kernel::*; + +#[test] +fn invalid_key_chown() { + let mut key = utils::invalid_key(); + let err = key.chown(*UID).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_key_chgrp() { + let mut key = utils::invalid_key(); + let err = key.chgrp(*GID).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_key_chmod() { + let mut key = utils::invalid_key(); + let err = key.set_permissions(Permission::POSSESSOR_VIEW).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_keyring_chown() { + let mut keyring = utils::invalid_key(); + let err = keyring.chown(*UID).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_keyring_chgrp() { + let mut keyring = utils::invalid_key(); + let err = keyring.chgrp(*GID).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_keyring_chmod() { + let mut keyring = utils::invalid_keyring(); + let err = keyring.set_permissions(Permission::empty()).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); +} + +#[test] +fn invalid_key_permissions() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("invalid_key_permissions", payload) + .unwrap(); + + let err = key + .set_permissions_raw(KeyPermissions::max_value()) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap(); +} + +#[test] +fn invalid_keyring_permissions() { + let mut keyring = utils::new_test_keyring(); + + let err = keyring + .set_permissions_raw(KeyPermissions::max_value()) + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::EINVAL)); + + keyring.invalidate().unwrap(); +} + +#[test] +fn unlinked_key_chown() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("unlinked_key_chown", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = key.chown(*UID).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap(); +} + +#[test] +fn unlinked_key_chgrp() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("unlinked_key_chgrp", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = key.chgrp(*GID).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap(); +} + +#[test] +fn unlinked_key_chmod() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("unlinked_key_chmod", payload) + .unwrap(); + + keyring.unlink_key(&key).unwrap(); + utils::wait_for_key_gc(&key); + + let err = key.set_permissions(Permission::POSSESSOR_VIEW).unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOKEY)); + + keyring.invalidate().unwrap(); +} + +#[test] +fn chown_keyring() { + let mut keyring = utils::new_test_keyring(); + + if *UID == 0 { + keyring.chown(1).unwrap(); + keyring.chown(0).unwrap(); + } else { + let err = keyring.chown(1).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + } + + keyring.invalidate().unwrap(); +} + +#[test] +fn chown_key() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring.add_key::("chown_key", payload).unwrap(); + + if *UID == 0 { + key.chown(1).unwrap(); + key.chown(0).unwrap(); + } else { + let err = key.chown(1).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + } + + keyring.invalidate().unwrap(); +} + +#[test] +fn set_each_permission_bit() { + let permission_bits = [ + Permission::OTHER_VIEW, + Permission::OTHER_READ, + Permission::OTHER_WRITE, + Permission::OTHER_SEARCH, + Permission::OTHER_LINK, + Permission::OTHER_SET_ATTRIBUTE, + Permission::GROUP_VIEW, + Permission::GROUP_READ, + Permission::GROUP_WRITE, + Permission::GROUP_SEARCH, + Permission::GROUP_LINK, + Permission::GROUP_SET_ATTRIBUTE, + Permission::USER_VIEW, + Permission::USER_READ, + Permission::USER_WRITE, + Permission::USER_SEARCH, + Permission::USER_LINK, + Permission::USER_SET_ATTRIBUTE, + Permission::POSSESSOR_VIEW, + Permission::POSSESSOR_READ, + Permission::POSSESSOR_WRITE, + Permission::POSSESSOR_SEARCH, + Permission::POSSESSOR_LINK, + Permission::POSSESSOR_SET_ATTRIBUTE, + ]; + let required_permissions = Permission::USER_SET_ATTRIBUTE | Permission::USER_VIEW; + + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("set_each_permission_bit", payload) + .unwrap(); + + for permission_bit in &permission_bits { + let perms = required_permissions | *permission_bit; + key.set_permissions(perms).unwrap(); + let description = key.description().unwrap(); + assert_eq!(perms, description.perms); + } + + keyring.invalidate().unwrap() +} + +#[test] +fn cannot_view_via_group() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("cannot_view_via_group", payload) + .unwrap(); + + let perms = Permission::GROUP_ALL | Permission::USER_SET_ATTRIBUTE; + key.set_permissions(perms).unwrap(); + + let err = key.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + keyring.invalidate().unwrap() +} + +#[test] +fn cannot_view_via_other() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("cannot_view_via_other", payload) + .unwrap(); + + let perms = Permission::OTHER_ALL | Permission::USER_SET_ATTRIBUTE; + key.set_permissions(perms).unwrap(); + + let err = key.read().unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + keyring.invalidate().unwrap() +} + +#[test] +fn remove_setattr() { + let mut keyring = utils::new_test_keyring(); + let payload = "payload".as_bytes(); + let mut key = keyring + .add_key::("remove_setattr", payload) + .unwrap(); + + let perms = Permission::all() + - (Permission::POSSESSOR_SET_ATTRIBUTE + | Permission::USER_SET_ATTRIBUTE + | Permission::GROUP_SET_ATTRIBUTE + | Permission::OTHER_SET_ATTRIBUTE); + key.set_permissions(perms).unwrap(); + + let err = key.set_permissions(Permission::all()).unwrap_err(); + assert_eq!(err, errno::Errno(libc::EACCES)); + + keyring.invalidate().unwrap() +} From 87003faf284ea02ffde36aa52b9e1700e7c2eca6 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 14 Aug 2019 15:39:42 -0400 Subject: [PATCH 37/47] api: fix request methods The API did not match what is actually possible with the kernel API. Instead, just offer two simple methods which do what is needed. Also remove the old test which doesn't match what the API looks like anymore. --- src/api.rs | 167 ++++++++++------------------------------------------- 1 file changed, 29 insertions(+), 138 deletions(-) diff --git a/src/api.rs b/src/api.rs index c43e122..60b1529 100644 --- a/src/api.rs +++ b/src/api.rs @@ -66,6 +66,7 @@ fn into_serial(res: libc::c_long) -> KeyringSerial { KeyringSerial::new(res as i32).unwrap() } +/// Request a key from the kernel. fn request_impl( description: &str, info: Option<&str>, @@ -122,31 +123,24 @@ impl Keyring { /// Requests a keyring with the given description by searching the thread, process, and session /// keyrings. - pub fn request(description: D) -> Result + /// + /// If it is not found, the `info` string (if provided) will be handed off to + /// `/sbin/request-key` to generate the key. + /// + /// If `target` is given, the found keyring will be linked into it. If `target` is not given + /// and a new key is constructed due to the request, it will be linked into the default + /// keyring (see `Keyring::set_default`). + pub fn request<'a, D, I, IS, T>(description: D, info: I, target: T) -> Result where D: AsRef, + I: Into>, + IS: AsRef, + T: Into>>, { check_call_keyring(request_impl::( description.as_ref(), - None, - None, - )) - } - - /// Requests a keyring with the given description by searching the thread, process, and session - /// keyrings. - /// - /// If it is not found, the `info` string will be handed off to `/sbin/request-key` to generate - /// the key. - pub fn request_with_fallback(description: D, info: I) -> Result - where - D: Borrow<::Description>, - I: AsRef, - { - check_call_keyring(request_impl::( - &description.borrow().description(), - Some(info.as_ref()), - None, + info.into().as_ref().copied(), + target.into().map(TargetKeyring::serial), )) } @@ -371,74 +365,6 @@ impl Keyring { check_call_keyring(self.add_key_impl::(description.borrow(), &())) } - /// Requests a key with the given description by searching the thread, process, and session - /// keyrings. - /// - /// If it is found, it is attached to the keyring. - pub fn request_key(&self, description: D) -> Result - where - K: KeyType, - D: Borrow, - { - check_call_key(request_impl::( - &description.borrow().description(), - None, - Some(self.id), - )) - } - - /// Requests a keyring with the given description by searching the thread, process, and session - /// keyrings. - /// - /// If it is found, it is attached to the keyring. - pub fn request_keyring(&self, description: D) -> Result - where - D: Borrow<::Description>, - { - check_call_keyring(request_impl::( - &description.borrow().description(), - None, - Some(self.id), - )) - } - - /// Requests a key with the given description by searching the thread, process, and session - /// keyrings. - /// - /// If it is not found, the `info` string will be handed off to `/sbin/request-key` to generate - /// the key. If found, it will be attached to the current keyring. Requires `write` permission - /// to the keyring. - pub fn request_key_with_fallback(&self, description: D, info: I) -> Result - where - K: KeyType, - D: Borrow, - I: AsRef, - { - check_call_key(request_impl::( - &description.borrow().description(), - Some(info.as_ref()), - Some(self.id), - )) - } - - /// Requests a keyring with the given description by searching the thread, process, and session - /// keyrings. - /// - /// If it is not found, the `info` string will be handed off to `/sbin/request-key` to generate - /// the key. If found, it will be attached to the current keyring. Requires `write` permission - /// to the keyring. - pub fn request_keyring_with_fallback(&self, description: D, info: I) -> Result - where - D: Borrow<::Description>, - I: AsRef, - { - check_call_keyring(request_impl::( - &description.borrow().description(), - Some(info.as_ref()), - Some(self.id), - )) - } - /// Revokes the keyring. /// /// Requires `write` permission on the keyring. @@ -561,35 +487,27 @@ impl Key { self.id } - /// Requests a key with the given description by searching the thread, process, and session - /// keyrings. - pub fn request(description: D) -> Result - where - K: KeyType, - D: Borrow, - { - check_call_key(request_impl::( - &description.borrow().description(), - None, - None, - )) - } - - /// Requests a key with the given description by searching the thread, process, and session - /// keyrings. + /// Requests a key with the given type and description by searching the thread, process, and + /// session keyrings. /// - /// If it is not found, the `info` string will be handed off to `/sbin/request-key` to generate - /// the key. - pub fn request_with_fallback(description: D, info: I) -> Result + /// If it is not found, the `info` string (if provided) will be handed off to + /// `/sbin/request-key` to generate the key. + /// + /// If `target` is given, the found keyring will be linked into it. If `target` is not given + /// and a new key is constructed due to the request, it will be linked into the default + /// keyring (see `Keyring::set_default`). + pub fn request<'a, K, D, I, IS, T>(description: D, info: I, target: T) -> Result where K: KeyType, D: Borrow, - I: AsRef, + I: Into>, + IS: AsRef, + T: Into>>, { - check_call_key(request_impl::( + check_call_key(request_impl::( &description.borrow().description(), - Some(info.as_ref()), - None, + info.into().as_ref().copied(), + target.into().map(TargetKeyring::serial), )) } @@ -911,30 +829,3 @@ impl KeyManager { }) } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::tests::utils; - - #[test] - fn test_request_key() { - let mut keyring = utils::new_test_keyring(); - - // Create the key. - let description = "test:rust-keyutils:request_key"; - let payload = "payload"; - let key = keyring - .add_key::(description, payload.as_bytes()) - .unwrap(); - - let found_key = keyring - .request_key::(description) - .unwrap(); - assert_eq!(found_key, key); - - // Clean up. - keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap(); - } -} From 8a6eeb652c0d5bd5a1ed84b49da3b4c28e5f9f14 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 30 Sep 2019 10:55:13 -0400 Subject: [PATCH 38/47] tests/add: expand on tests for adding keyrings --- src/tests/add.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/tests/add.rs b/src/tests/add.rs index 69411a7..fbfeb71 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -146,6 +146,23 @@ fn add_key_to_non_keyring() { keyring.invalidate().unwrap() } +#[test] +fn add_keyring_to_non_keyring() { + let mut keyring = utils::new_test_keyring(); + let expected = "stuff".as_bytes(); + let key = keyring + .add_key::("add_keyring_to_non_keyring", expected) + .unwrap(); + + let mut not_a_keyring = utils::key_as_keyring(&key); + let err = not_a_keyring + .add_keyring("add_keyring_to_non_keyring") + .unwrap_err(); + assert_eq!(err, errno::Errno(libc::ENOTDIR)); + + keyring.invalidate().unwrap() +} + #[test] fn add_key() { let mut keyring = utils::new_test_keyring(); @@ -158,10 +175,22 @@ fn add_key() { } #[test] -fn update_key_via_add() { +fn add_keyring() { let mut keyring = utils::new_test_keyring(); + let new_keyring = keyring.add_keyring("add_keyring").unwrap(); - let description = "update_key_via_add"; + let (keys, keyrings) = new_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} + +#[test] +fn add_key_replace() { + let mut keyring = utils::new_test_keyring(); + + let description = "add_key_replace"; let payload = "payload".as_bytes(); let key = keyring.add_key::(description, payload).unwrap(); @@ -175,3 +204,24 @@ fn update_key_via_add() { keyring.invalidate().unwrap() } + +#[test] +fn add_keyring_replace() { + let mut keyring = utils::new_test_keyring(); + + let description = "add_keyring_replace"; + let new_keyring = keyring.add_keyring(description).unwrap(); + + let (keys, keyrings) = new_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + let updated_keyring = keyring.add_keyring(description).unwrap(); + assert_ne!(new_keyring, updated_keyring); + + let (keys, keyrings) = updated_keyring.read().unwrap(); + assert!(keys.is_empty()); + assert!(keyrings.is_empty()); + + keyring.invalidate().unwrap() +} From bd5dcd75758238c6683d8f1c68226e29c0f155fc Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 30 Sep 2019 10:55:41 -0400 Subject: [PATCH 39/47] api: fix the `request` API This is more ergonomic and allows for just passing a plain string around. --- src/api.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/api.rs b/src/api.rs index 60b1529..aa42232 100644 --- a/src/api.rs +++ b/src/api.rs @@ -130,11 +130,10 @@ impl Keyring { /// If `target` is given, the found keyring will be linked into it. If `target` is not given /// and a new key is constructed due to the request, it will be linked into the default /// keyring (see `Keyring::set_default`). - pub fn request<'a, D, I, IS, T>(description: D, info: I, target: T) -> Result + pub fn request<'s, 'a, D, I, T>(description: D, info: I, target: T) -> Result where D: AsRef, - I: Into>, - IS: AsRef, + I: Into>, T: Into>>, { check_call_keyring(request_impl::( @@ -496,12 +495,11 @@ impl Key { /// If `target` is given, the found keyring will be linked into it. If `target` is not given /// and a new key is constructed due to the request, it will be linked into the default /// keyring (see `Keyring::set_default`). - pub fn request<'a, K, D, I, IS, T>(description: D, info: I, target: T) -> Result + pub fn request<'s, 'a, K, D, I, T>(description: D, info: I, target: T) -> Result where K: KeyType, D: Borrow, - I: Into>, - IS: AsRef, + I: Into>, T: Into>>, { check_call_key(request_impl::( From 1a70ad2fbd582d6b9773c5dbb1aa286c7c5e8edd Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 2 Oct 2019 20:28:39 -0400 Subject: [PATCH 40/47] tests: make a ScopedKeyring for handling cleanup automatically Some tests handle it manually to test behavior once the keyring is deallocated, so leave the old functionality there. --- src/tests/add.rs | 28 ------------------- src/tests/clear.rs | 15 ---------- src/tests/describe.rs | 6 ---- src/tests/instantiate.rs | 12 -------- src/tests/invalidate.rs | 6 +--- src/tests/link.rs | 24 ---------------- src/tests/newring.rs | 14 ---------- src/tests/permitting.rs | 22 --------------- src/tests/reading.rs | 20 -------------- src/tests/revoke.rs | 6 ---- src/tests/search.rs | 60 ---------------------------------------- src/tests/timeout.rs | 10 +------ src/tests/unlink.rs | 32 ++------------------- src/tests/update.rs | 6 ---- src/tests/utils/mod.rs | 37 ++++++++++++++++++++++++- 15 files changed, 40 insertions(+), 258 deletions(-) diff --git a/src/tests/add.rs b/src/tests/add.rs index fbfeb71..6182a36 100644 --- a/src/tests/add.rs +++ b/src/tests/add.rs @@ -37,8 +37,6 @@ fn empty_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -46,8 +44,6 @@ fn unsupported_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENODEV)); - - keyring.invalidate().unwrap() } #[test] @@ -55,8 +51,6 @@ fn invalid_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } #[test] @@ -64,8 +58,6 @@ fn maxlen_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENODEV)); - - keyring.invalidate().unwrap() } #[test] @@ -73,8 +65,6 @@ fn overlong_key_type() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_key::("", ()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -84,8 +74,6 @@ fn keyring_with_payload() { .add_key::("", "payload") .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -102,8 +90,6 @@ fn max_user_description() { assert_eq!(key.description().unwrap().description, maxdesc); key.invalidate().unwrap(); } - - keyring.invalidate().unwrap() } #[test] @@ -116,8 +102,6 @@ fn overlong_user_description() { .add_key::(toolarge.as_ref(), "payload".as_bytes()) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -142,8 +126,6 @@ fn add_key_to_non_keyring() { .add_key::("add_key_to_non_keyring", expected) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -159,8 +141,6 @@ fn add_keyring_to_non_keyring() { .add_keyring("add_keyring_to_non_keyring") .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -170,8 +150,6 @@ fn add_key() { let payload = "payload".as_bytes(); let key = keyring.add_key::("add_key", payload).unwrap(); assert_eq!(key.read().unwrap(), payload); - - keyring.invalidate().unwrap() } #[test] @@ -182,8 +160,6 @@ fn add_keyring() { let (keys, keyrings) = new_keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -201,8 +177,6 @@ fn add_key_replace() { assert_eq!(key, key_updated); assert_eq!(key.read().unwrap(), payload); assert_eq!(key_updated.read().unwrap(), payload); - - keyring.invalidate().unwrap() } #[test] @@ -222,6 +196,4 @@ fn add_keyring_replace() { let (keys, keyrings) = updated_keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } diff --git a/src/tests/clear.rs b/src/tests/clear.rs index 8adb8d8..c617f01 100644 --- a/src/tests/clear.rs +++ b/src/tests/clear.rs @@ -49,7 +49,6 @@ fn clear_non_keyring() { assert_eq!(err, errno::Errno(libc::ENOTDIR)); keyring.unlink_key(&key).unwrap(); - keyring.invalidate().unwrap() } #[test] @@ -68,8 +67,6 @@ fn clear_deleted_keyring() { assert_eq!(err, errno::Errno(libc::ENOKEY)); break; } - - keyring.invalidate().unwrap() } #[test] @@ -86,9 +83,6 @@ fn clear_empty_keyring() { let (keys, keyrings) = keyring.read().unwrap(); assert_eq!(keys.len(), 0); assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap() } #[test] @@ -117,9 +111,6 @@ fn clear_keyring_one_key() { let (keys, keyrings) = keyring.read().unwrap(); assert_eq!(keys.len(), 0); assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap() } #[test] @@ -160,9 +151,6 @@ fn clear_keyring_many_keys() { let (keys, keyrings) = keyring.read().unwrap(); assert_eq!(keys.len(), 0); assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap() } #[test] @@ -190,7 +178,4 @@ fn clear_keyring_keyring() { let (keys, keyrings) = keyring.read().unwrap(); assert_eq!(keys.len(), 0); assert_eq!(keyrings.len(), 0); - - // Clean up. - keyring.invalidate().unwrap() } diff --git a/src/tests/describe.rs b/src/tests/describe.rs index 23b4a8c..ecff11c 100644 --- a/src/tests/describe.rs +++ b/src/tests/describe.rs @@ -53,8 +53,6 @@ fn non_existent_key() { keyring.unlink_key(&key).unwrap(); utils::wait_for_key_gc(&key); - - keyring.invalidate().unwrap() } #[test] @@ -112,8 +110,6 @@ fn describe_key_no_perm() { let err = key.description().unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); - - keyring.invalidate().unwrap() } #[test] @@ -128,6 +124,4 @@ fn describe_revoked_key() { let err = key_mirror.description().unwrap_err(); assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); - - keyring.invalidate().unwrap() } diff --git a/src/tests/instantiate.rs b/src/tests/instantiate.rs index a139f98..4c935c0 100644 --- a/src/tests/instantiate.rs +++ b/src/tests/instantiate.rs @@ -126,8 +126,6 @@ fn instantiate_already_instantiated() { let err = manager.instantiate(None, payload).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } #[test] @@ -143,8 +141,6 @@ fn reject_already_instantiated() { let errno = errno::Errno(libc::EKEYREJECTED); let err = manager.reject(None, duration, errno).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } #[test] @@ -159,8 +155,6 @@ fn negate_already_instantiated() { let duration = Duration::from_secs(1); let err = manager.negate(None, duration).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } #[test] @@ -178,8 +172,6 @@ fn instantiate_unlinked_key() { let err = manager.instantiate(None, payload).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } #[test] @@ -199,8 +191,6 @@ fn reject_unlinked_key() { let errno = errno::Errno(libc::EKEYREJECTED); let err = manager.reject(None, duration, errno).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } #[test] @@ -219,6 +209,4 @@ fn negate_unlinked_key() { let duration = Duration::from_secs(1); let err = manager.negate(None, duration).unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } diff --git a/src/tests/invalidate.rs b/src/tests/invalidate.rs index 0e094df..e8b351b 100644 --- a/src/tests/invalidate.rs +++ b/src/tests/invalidate.rs @@ -67,8 +67,6 @@ fn unlinked_key() { let err = key.invalidate().unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -95,13 +93,11 @@ fn invalidate_key() { assert!(keys.is_empty()); assert!(keyrings.is_empty()); } - - keyring.invalidate().unwrap() } #[test] fn invalidate_keyring() { - let mut keyring = utils::new_test_keyring(); + let mut keyring = utils::new_test_keyring_manual(); { let (keys, keyrings) = keyring.read().unwrap(); diff --git a/src/tests/link.rs b/src/tests/link.rs index 7579b95..c8c6e07 100644 --- a/src/tests/link.rs +++ b/src/tests/link.rs @@ -36,8 +36,6 @@ fn invalid_target() { let err = invalid_keyring.link_keyring(&keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -47,8 +45,6 @@ fn invalid_source() { let err = keyring.link_keyring(&invalid_keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -65,8 +61,6 @@ fn link_to_non_keyring() { let err = not_a_keyring.link_key(&linked_key).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -83,8 +77,6 @@ fn link_unlinked_key() { let err = target_keyring.link_key(&key).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -103,8 +95,6 @@ fn link_into_unlinked_keyring() { let err = target_keyring.link_key(&key).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -114,8 +104,6 @@ fn link_self() { let err = keyring.link_keyring(&keyring_observer).unwrap_err(); assert_eq!(err, errno::Errno(libc::EDEADLK)); - - keyring.invalidate().unwrap() } #[test] @@ -125,8 +113,6 @@ fn link_self_via_child() { let err = target_keyring.link_keyring(&keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::EDEADLK)); - - keyring.invalidate().unwrap() } #[test] @@ -161,8 +147,6 @@ fn link_self_via_child_chains() { let err = target_keyring.link_keyring(&keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::ELOOP)); - - keyring.invalidate().unwrap() } #[test] @@ -198,8 +182,6 @@ fn link_self_via_keyring_stacks() { let err = keyring_b.link_keyring(&keyring_a_root).unwrap_err(); assert_eq!(err, errno::Errno(libc::EDEADLK)); - - keyring.invalidate().unwrap() } #[test] @@ -235,8 +217,6 @@ fn link_self_via_keyring_deep_stacks() { let err = keyring_b.link_keyring(&keyring_a_root).unwrap_err(); assert_eq!(err, errno::Errno(libc::ELOOP)); - - keyring.invalidate().unwrap() } #[test] @@ -277,8 +257,6 @@ fn multiply_link_key_into_keyring() { assert_eq!(keys[0], key); assert_eq!(keyrings.len(), 1); assert_eq!(keyrings[0], new_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -318,6 +296,4 @@ fn multiply_link_keyring_into_keyring() { assert_eq!(keyrings.len(), 2); assert_eq!(keyrings[0], new_keyring); assert_eq!(keyrings[1], inner_keyring); - - keyring.invalidate().unwrap() } diff --git a/src/tests/newring.rs b/src/tests/newring.rs index 9e668be..6df9669 100644 --- a/src/tests/newring.rs +++ b/src/tests/newring.rs @@ -50,8 +50,6 @@ fn unlinked_keyring() { .add_keyring("unlinked_keyring") .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -65,8 +63,6 @@ fn not_a_keyring() { let err = not_a_keyring.add_keyring("not_a_keyring").unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -74,8 +70,6 @@ fn empty_keyring_description() { let mut keyring = utils::new_test_keyring(); let err = keyring.add_keyring("").unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -92,8 +86,6 @@ fn max_keyring_description() { assert_eq!(keyring.description().unwrap().description, maxdesc); keyring.invalidate().unwrap(); } - - keyring.invalidate().unwrap() } #[test] @@ -104,8 +96,6 @@ fn overlong_keyring_description() { let maxdesc: String = iter::repeat('a').take(*PAGE_SIZE).collect(); let err = keyring.add_keyring(maxdesc.as_ref()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -117,8 +107,6 @@ fn new_keyring() { assert_eq!(keys.len(), 0); assert_eq!(keyrings.len(), 1); assert_eq!(keyrings[0], new_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -141,6 +129,4 @@ fn duplicate_keyring_names() { // It should be inaccessible. let err = new_keyring1.description().unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } diff --git a/src/tests/permitting.rs b/src/tests/permitting.rs index e125b69..79e6aa3 100644 --- a/src/tests/permitting.rs +++ b/src/tests/permitting.rs @@ -84,8 +84,6 @@ fn invalid_key_permissions() { .set_permissions_raw(KeyPermissions::max_value()) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap(); } #[test] @@ -96,8 +94,6 @@ fn invalid_keyring_permissions() { .set_permissions_raw(KeyPermissions::max_value()) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap(); } #[test] @@ -113,8 +109,6 @@ fn unlinked_key_chown() { let err = key.chown(*UID).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap(); } #[test] @@ -130,8 +124,6 @@ fn unlinked_key_chgrp() { let err = key.chgrp(*GID).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap(); } #[test] @@ -147,8 +139,6 @@ fn unlinked_key_chmod() { let err = key.set_permissions(Permission::POSSESSOR_VIEW).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap(); } #[test] @@ -162,8 +152,6 @@ fn chown_keyring() { let err = keyring.chown(1).unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); } - - keyring.invalidate().unwrap(); } #[test] @@ -179,8 +167,6 @@ fn chown_key() { let err = key.chown(1).unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); } - - keyring.invalidate().unwrap(); } #[test] @@ -225,8 +211,6 @@ fn set_each_permission_bit() { let description = key.description().unwrap(); assert_eq!(perms, description.perms); } - - keyring.invalidate().unwrap() } #[test] @@ -242,8 +226,6 @@ fn cannot_view_via_group() { let err = key.read().unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); - - keyring.invalidate().unwrap() } #[test] @@ -259,8 +241,6 @@ fn cannot_view_via_other() { let err = key.read().unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); - - keyring.invalidate().unwrap() } #[test] @@ -280,6 +260,4 @@ fn remove_setattr() { let err = key.set_permissions(Permission::all()).unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); - - keyring.invalidate().unwrap() } diff --git a/src/tests/reading.rs b/src/tests/reading.rs index 4d68554..cb308f6 100644 --- a/src/tests/reading.rs +++ b/src/tests/reading.rs @@ -56,8 +56,6 @@ fn unlinked_key() { let err = key.read().unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -70,8 +68,6 @@ fn unlinked_keyring() { let err = new_keyring.read().unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -82,8 +78,6 @@ fn read_key() { let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } #[test] @@ -98,8 +92,6 @@ fn read_keyring() { assert_eq!(1, keys.len()); assert_eq!(key, keys[0]); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -113,8 +105,6 @@ fn read_key_as_keyring() { let err = not_a_keyring.read().unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -124,8 +114,6 @@ fn read_keyring_as_key() { let payload = not_a_key.read().unwrap(); assert_eq!(b"", payload.as_slice()); - - keyring.invalidate().unwrap() } #[test] @@ -143,8 +131,6 @@ fn read_no_read_perm_with_search() { // This should still work because we have "search" permission on its keyring. let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } #[test] @@ -161,8 +147,6 @@ fn read_no_read_search_perm_with_search() { let err = key.read().unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); - - keyring.invalidate().unwrap() } #[test] @@ -179,8 +163,6 @@ fn read_rely_on_possessor() { let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } #[test] @@ -204,6 +186,4 @@ fn reinstated_read_perm() { let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } diff --git a/src/tests/revoke.rs b/src/tests/revoke.rs index e014200..0005894 100644 --- a/src/tests/revoke.rs +++ b/src/tests/revoke.rs @@ -57,8 +57,6 @@ fn unlinked_key() { let err = key.revoke().unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -84,8 +82,6 @@ fn revoked_key() { let err = key_observer.invalidate().unwrap_err(); assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); - - keyring.invalidate().unwrap() } #[test] @@ -108,6 +104,4 @@ fn revoked_keyring() { let err = keyring_observer.invalidate().unwrap_err(); assert_eq!(err, errno::Errno(libc::EKEYREVOKED)); - - keyring.invalidate().unwrap() } diff --git a/src/tests/search.rs b/src/tests/search.rs index 3f3c113..fa5c110 100644 --- a/src/tests/search.rs +++ b/src/tests/search.rs @@ -41,8 +41,6 @@ fn empty_key_type() { .search_for_key::("empty_key_type", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -53,8 +51,6 @@ fn unsupported_key_type() { .search_for_key::("unsupported_key_type", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -65,8 +61,6 @@ fn invalid_key_type() { .search_for_key::("invalid_key_type", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EPERM)); - - keyring.invalidate().unwrap() } #[test] @@ -77,8 +71,6 @@ fn max_key_type() { .search_for_key::("invalid_key_type", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -89,8 +81,6 @@ fn overlong_key_type() { .search_for_key::("overlong_key_type", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -103,8 +93,6 @@ fn max_user_description() { .search_for_key::(maxdesc, None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -118,8 +106,6 @@ fn overlong_user_description() { .search_for_key::(maxdesc, None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -145,8 +131,6 @@ fn search_key() { .search_for_key::("search_key", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -157,8 +141,6 @@ fn search_key_no_result() { .search_for_key::("search_key_no_result", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -169,8 +151,6 @@ fn search_keyring_no_result() { .search_for_keyring("search_keyring_no_result", None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -184,8 +164,6 @@ fn search_key_mismatched_type() { .search_for_key::(description, None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -202,8 +180,6 @@ fn search_keyring_mismatched_type() { let err = keyring.search_for_keyring(description, None).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -223,8 +199,6 @@ fn search_and_find_key() { let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } #[test] @@ -236,8 +210,6 @@ fn search_and_find_keyring() { let found_keyring = keyring.search_for_keyring(description, None).unwrap(); assert_eq!(found_keyring, target_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -266,8 +238,6 @@ fn search_and_find_key_no_search_perm_interm() { .search_for_key::(description, None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -291,8 +261,6 @@ fn search_and_find_keyring_no_search_perm_interm() { let err = keyring.search_for_keyring(description, None).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -321,8 +289,6 @@ fn search_and_find_key_no_search_perm_direct() { .search_for_key::(description, None) .unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); - - keyring.invalidate().unwrap() } #[test] @@ -346,8 +312,6 @@ fn search_and_find_keyring_no_search_perm_direct() { let err = keyring.search_for_keyring(description, None).unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); - - keyring.invalidate().unwrap() } #[test] @@ -379,8 +343,6 @@ fn search_and_find_key_link() { assert_eq!(keys.len(), 1); assert_eq!(keys[0], key); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -406,8 +368,6 @@ fn search_and_find_keyring_link() { assert!(keys.is_empty()); assert_eq!(keyrings.len(), 1); assert_eq!(keyrings[0], target_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -447,8 +407,6 @@ fn search_and_find_key_link_replace() { assert_eq!(keys.len(), 1); assert_eq!(keys[0], key); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -486,8 +444,6 @@ fn search_and_find_key_link_replace_keyring() { assert_eq!(keys[0], key); assert_eq!(keyrings.len(), 1); assert_eq!(keyrings[0], orig_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -518,8 +474,6 @@ fn search_and_find_keyring_link_replace() { assert!(keys.is_empty()); assert_eq!(keyrings.len(), 1); assert_eq!(keyrings[0], target_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -554,8 +508,6 @@ fn search_and_find_keyring_link_replace_key() { assert_eq!(keys[0], orig_key); assert_eq!(keyrings.len(), 1); assert_eq!(keyrings[0], target_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -587,8 +539,6 @@ fn search_and_find_key_no_link_perm_no_dest() { let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } #[test] @@ -612,8 +562,6 @@ fn search_and_find_keyring_no_link_perm_no_dest() { let found_keyring = keyring.search_for_keyring(description, None).unwrap(); assert_eq!(found_keyring, target_keyring); - - keyring.invalidate().unwrap() } #[test] @@ -650,8 +598,6 @@ fn search_and_find_key_no_link_perm() { let (keys, keyrings) = destination_keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -685,8 +631,6 @@ fn search_and_find_keyring_no_link_perm() { let (keys, keyrings) = destination_keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -723,8 +667,6 @@ fn search_and_find_key_no_write_perm() { let (keys, keyrings) = destination_keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -758,6 +700,4 @@ fn search_and_find_keyring_no_write_perm() { let (keys, keyrings) = destination_keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } diff --git a/src/tests/timeout.rs b/src/tests/timeout.rs index 0a811cc..003f834 100644 --- a/src/tests/timeout.rs +++ b/src/tests/timeout.rs @@ -61,8 +61,6 @@ fn unlinked_key() { let duration = Duration::from_secs(1); let err = key.set_timeout(duration).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -78,8 +76,6 @@ fn big_timeout_key() { let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } #[test] @@ -92,8 +88,6 @@ fn big_timeout_keyring() { let (keys, keyrings) = keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -125,13 +119,11 @@ fn expired_key() { assert_eq!(err, errno::Errno(libc::EKEYEXPIRED)); keyring.unlink_key(&key_observer2).unwrap(); - - keyring.invalidate().unwrap() } #[test] fn expired_keyring() { - let mut keyring = utils::new_test_keyring(); + let mut keyring = utils::new_test_keyring_manual(); let keyring_observer = keyring.clone(); let duration = Duration::from_secs(1); diff --git a/src/tests/unlink.rs b/src/tests/unlink.rs index e2f288f..92fabe3 100644 --- a/src/tests/unlink.rs +++ b/src/tests/unlink.rs @@ -39,8 +39,6 @@ fn invalid_target_key() { let err = invalid_keyring.unlink_key(&key).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -50,8 +48,6 @@ fn invalid_target_keyring() { let err = invalid_keyring.unlink_keyring(&keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -61,8 +57,6 @@ fn invalid_source_key() { let err = keyring.unlink_key(&invalid_key).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -72,8 +66,6 @@ fn invalid_source_keyring() { let err = keyring.unlink_keyring(&invalid_keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::EINVAL)); - - keyring.invalidate().unwrap() } #[test] @@ -87,8 +79,6 @@ fn unlink_key_from_non_keyring() { let err = not_a_keyring.unlink_key(&key).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -102,8 +92,6 @@ fn unlink_keyring_from_non_keyring() { let err = not_a_keyring.unlink_keyring(&keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOTDIR)); - - keyring.invalidate().unwrap() } #[test] @@ -117,8 +105,6 @@ fn unlink_key_as_keyring() { // This is OK because the kernel doesn't have the type knowledge that our API does. keyring.unlink_keyring(¬_a_keyring).unwrap(); - - keyring.invalidate().unwrap() } #[test] @@ -129,8 +115,6 @@ fn unlink_keyring_as_key() { // This is OK because the kernel doesn't have the type knowledge that our API does. keyring.unlink_key(¬_a_key).unwrap(); - - keyring.invalidate().unwrap() } #[test] @@ -146,8 +130,6 @@ fn unlink_unlinked_key() { let err = keyring.unlink_key(&key).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -160,13 +142,11 @@ fn unlink_unlinked_keyring() { let err = keyring.unlink_keyring(&new_keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] fn unlink_key_from_unlinked_keyring() { - let mut keyring = utils::new_test_keyring(); + let mut keyring = utils::new_test_keyring_manual(); let mut keyring_observer = keyring.clone(); let payload = "payload".as_bytes(); let key = keyring @@ -182,7 +162,7 @@ fn unlink_key_from_unlinked_keyring() { #[test] fn unlink_keyring_from_unlinked_keyring() { - let mut keyring = utils::new_test_keyring(); + let mut keyring = utils::new_test_keyring_manual(); let mut keyring_observer = keyring.clone(); let new_keyring = keyring.add_keyring("unlink_from_unlinked_keyring").unwrap(); @@ -204,8 +184,6 @@ fn unlink_unassociated_key() { let err = new_keyring.unlink_key(&key).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOENT)); - - keyring.invalidate().unwrap() } #[test] @@ -218,8 +196,6 @@ fn unlink_unassociated_keyring() { let err = new_keyring.unlink_keyring(&inner_keyring).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOENT)); - - keyring.invalidate().unwrap() } #[test] @@ -236,8 +212,6 @@ fn unlink_key() { let (keys, keyrings) = keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } #[test] @@ -251,6 +225,4 @@ fn unlink_keyring() { let (keys, keyrings) = keyring.read().unwrap(); assert!(keys.is_empty()); assert!(keyrings.is_empty()); - - keyring.invalidate().unwrap() } diff --git a/src/tests/update.rs b/src/tests/update.rs index fc5f60e..47b8ea5 100644 --- a/src/tests/update.rs +++ b/src/tests/update.rs @@ -36,8 +36,6 @@ fn keyring() { let payload = "payload".as_bytes(); let err = key.update(payload).unwrap_err(); assert_eq!(err, errno::Errno(libc::EOPNOTSUPP)); - - keyring.invalidate().unwrap() } #[test] @@ -63,8 +61,6 @@ fn unlinked_key() { let payload = "payload".as_bytes(); let err = key.update(payload).unwrap_err(); assert_eq!(err, errno::Errno(libc::ENOKEY)); - - keyring.invalidate().unwrap() } #[test] @@ -81,6 +77,4 @@ fn user_key() { let actual_payload = key.read().unwrap(); assert_eq!(payload, actual_payload.as_slice()); - - keyring.invalidate().unwrap() } diff --git a/src/tests/utils/mod.rs b/src/tests/utils/mod.rs index e3b0ddd..4f669b3 100644 --- a/src/tests/utils/mod.rs +++ b/src/tests/utils/mod.rs @@ -24,6 +24,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +use std::ops::{Deref, DerefMut}; use std::sync::atomic; use crate::{Key, Keyring, KeyringSerial, SpecialKeyring}; @@ -31,9 +32,35 @@ use crate::{Key, Keyring, KeyringSerial, SpecialKeyring}; pub mod kernel; pub mod keys; +#[derive(Debug)] +pub struct ScopedKeyring { + keyring: Keyring, +} + +impl Drop for ScopedKeyring { + fn drop(&mut self) { + self.keyring.clone().invalidate().unwrap(); + wait_for_keyring_gc(&self.keyring); + } +} + +impl Deref for ScopedKeyring { + type Target = Keyring; + + fn deref(&self) -> &Self::Target { + &self.keyring + } +} + +impl DerefMut for ScopedKeyring { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.keyring + } +} + // For testing, each test gets a new keyring attached to the Thread keyring. This makes sure tests // don't interfere with each other, and keys are not prematurely garbage collected. -pub fn new_test_keyring() -> Keyring { +pub fn new_test_keyring_manual() -> Keyring { let mut thread_keyring = Keyring::attach_or_create(SpecialKeyring::Thread).unwrap(); static KEYRING_COUNT: atomic::AtomicUsize = atomic::AtomicUsize::new(0); @@ -43,6 +70,14 @@ pub fn new_test_keyring() -> Keyring { .unwrap() } +// For testing, each test gets a new keyring attached to the Thread keyring. This makes sure tests +// don't interfere with each other, and keys are not prematurely garbage collected. +pub fn new_test_keyring() -> ScopedKeyring { + ScopedKeyring { + keyring: new_test_keyring_manual(), + } +} + unsafe fn invalid_serial() -> KeyringSerial { // Yes, we're explicitly breaking the NonZeroI32 rules here. However, it is not passing through // any bits which care (e.g., `Option`), so this is purely to test that using an invalid From 21f2f021655d9aad2373b39b80e9824e2d6e0559 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jan 2020 20:15:40 -0500 Subject: [PATCH 41/47] ci: run tests with a single thread --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 25df65e..048573c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -31,7 +31,7 @@ linux_task: folder: $CARGO_HOME/registry fingerprint_script: cat Cargo.lock build_script: cargo build - test_script: cargo test + test_script: cargo test -- --test-threads 1 before_cache_script: rm -rf $CARGO_HOME/registry/index minimal_version_task: From 7004edc58b7e20d9853bdc466c22c49566569c2f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jan 2020 20:30:58 -0500 Subject: [PATCH 42/47] tests: disable session tests (for now) --- src/tests/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 7e63d40..3e93f17 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -39,7 +39,8 @@ mod permitting; mod reading; mod revoke; mod search; -mod session; +// FIXME(#39): These tests fail when run in the same process. Something should be done about this. +// mod session; mod timeout; mod unlink; mod update; From f39e205d063772c6601d429cbe23b3beed89253a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jan 2020 20:34:44 -0500 Subject: [PATCH 43/47] ci: update to tarpaulin 0.10.0 --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 048573c..69f60bd 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -53,7 +53,7 @@ coverage_task: keyutils_script: apt-get update && apt-get install libkeyutils-dev tarpaulin_cache: folder: $CARGO_HOME/bin - populate_script: cargo install --version 0.8.7 cargo-tarpaulin + populate_script: cargo install --version 0.10.0 cargo-tarpaulin fingerprint_script: cargo install --list lockfile_script: cargo generate-lockfile cargo_cache: From 2f6daae6bd46676404b9c7a22788e8080ea30fee Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jan 2020 20:34:54 -0500 Subject: [PATCH 44/47] clippy: add safety sections to unsafe functions --- src/api.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/api.rs b/src/api.rs index aa42232..314f5e4 100644 --- a/src/api.rs +++ b/src/api.rs @@ -90,6 +90,10 @@ impl Keyring { /// Instantiate a keyring from an ID. /// /// This is unsafe because no keyring is known to exist with the given ID. + /// + /// # Safety + /// + /// This method assumes that the given serial is a valid keyring ID at the kernel level. pub unsafe fn new(id: KeyringSerial) -> Self { Keyring { id, @@ -471,6 +475,10 @@ impl Key { /// Instantiate a key from an ID. /// /// This is unsafe because no key is known to exist with the given ID. + /// + /// # Safety + /// + /// This method assumes that the given serial is a valid key ID at the kernel level. pub unsafe fn new(id: KeyringSerial) -> Self { Self::new_impl(id) } From dbac0f04c42612f29c4d0771d67e3854f4c6678d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jan 2020 20:36:22 -0500 Subject: [PATCH 45/47] ci: require 1.35.0 for Option::copied --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 69f60bd..4aed467 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -19,7 +19,7 @@ rustfmt_task: linux_task: matrix: - container: - image: rust:1.34.0 + image: rust:1.35.0 - container: image: rust:latest - allow_failures: true From da585d147ea0fa0a1a63921d4328902e6ce5fd45 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jan 2020 20:40:52 -0500 Subject: [PATCH 46/47] tests/permitting: allow root not having chown permission too Probably related to not having a user `1` available on the machine. --- src/tests/permitting.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/tests/permitting.rs b/src/tests/permitting.rs index 79e6aa3..a081b9f 100644 --- a/src/tests/permitting.rs +++ b/src/tests/permitting.rs @@ -146,8 +146,12 @@ fn chown_keyring() { let mut keyring = utils::new_test_keyring(); if *UID == 0 { - keyring.chown(1).unwrap(); - keyring.chown(0).unwrap(); + match keyring.chown(1) { + // If that worked, make sure we can move it back. + Ok(_) => keyring.chown(0).unwrap(), + // Otherwise, we got the right error. + Err(err) => assert_eq!(err, errno::Errno(libc::EACCES)), + } } else { let err = keyring.chown(1).unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); @@ -161,9 +165,12 @@ fn chown_key() { let mut key = keyring.add_key::("chown_key", payload).unwrap(); if *UID == 0 { - key.chown(1).unwrap(); - key.chown(0).unwrap(); - } else { + match key.chown(1) { + // If that worked, make sure we can move it back. + Ok(_) => key.chown(0).unwrap(), + // Otherwise, we got the right error. + Err(err) => assert_eq!(err, errno::Errno(libc::EACCES)), + } let err = key.chown(1).unwrap_err(); assert_eq!(err, errno::Errno(libc::EACCES)); } From 7728edad5553cf3765695aa5df81340734dfd943 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Jan 2020 20:44:12 -0500 Subject: [PATCH 47/47] ci: download a precompiled cargo-tarpaulin binary --- .ci/tarpaulin.sh | 15 +++++++++++++++ .cirrus.yml | 8 ++++---- 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100755 .ci/tarpaulin.sh diff --git a/.ci/tarpaulin.sh b/.ci/tarpaulin.sh new file mode 100755 index 0000000..e146b75 --- /dev/null +++ b/.ci/tarpaulin.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +set -e + +readonly version="0.10.0" +readonly sha256sum="6843be8384bf14385b36a3118efc1ed2d25d531acb8df954cd3f93d44018b09e" +readonly filename="cargo-tarpaulin-$version-travis" +readonly tarball="$filename.tar.gz" + +cd .ci + +echo "$sha256sum $tarball" > tarpaulin.sha256sum +curl -OL "https://github.com/xd009642/tarpaulin/releases/download/$version/$tarball" +sha256sum --check tarpaulin.sha256sum +tar xf "$tarball" diff --git a/.cirrus.yml b/.cirrus.yml index 4aed467..2314e9b 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -52,13 +52,13 @@ coverage_task: CODECOV_TOKEN: ENCRYPTED[1e221ef78a37c960613ff80db7141f3158e3218031934395466f4720f450b7acfd74e587819435ce9be0b13fa1b68f1b] keyutils_script: apt-get update && apt-get install libkeyutils-dev tarpaulin_cache: - folder: $CARGO_HOME/bin - populate_script: cargo install --version 0.10.0 cargo-tarpaulin - fingerprint_script: cargo install --list + folder: .ci + populate_script: .ci/tarpaulin.sh + fingerprint_script: cat .ci/tarpaulin.sh lockfile_script: cargo generate-lockfile cargo_cache: folder: $CARGO_HOME/registry fingerprint_script: cat Cargo.lock - coverage_script: cargo tarpaulin --out Xml + coverage_script: PATH=$PATH:$PWD/.ci cargo tarpaulin --out Xml upload_script: bash <(curl -s https://codecov.io/bash) -X gcov before_cache_script: rm -rf $CARGO_HOME/registry/index