Skip to content

Commit 8c1f5c8

Browse files
authored
Merge pull request #46 from mathstuf/support-key-restrictions
Support key restrictions
2 parents 58ff948 + 2aea40c commit 8c1f5c8

File tree

4 files changed

+147
-2
lines changed

4 files changed

+147
-2
lines changed

keyutils-raw/src/functions.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,3 +378,38 @@ pub fn keyctl_dh_compute(
378378
}
379379
.map(size)
380380
}
381+
382+
pub enum Restriction<'a> {
383+
AllLinks,
384+
ByType {
385+
type_: &'a str,
386+
restriction: &'a str,
387+
},
388+
}
389+
390+
pub fn keyctl_restrict_keyring(keyring: KeyringSerial, restriction: Restriction) -> Result<()> {
391+
let type_cstr;
392+
let restriction_cstr;
393+
394+
let (type_ptr, restriction_ptr) = match restriction {
395+
Restriction::AllLinks => (ptr::null(), ptr::null()),
396+
Restriction::ByType {
397+
type_,
398+
restriction,
399+
} => {
400+
type_cstr = cstring(type_);
401+
restriction_cstr = cstring(restriction);
402+
403+
(type_cstr.as_ptr(), restriction_cstr.as_ptr())
404+
},
405+
};
406+
unsafe {
407+
keyctl!(
408+
libc::KEYCTL_RESTRICT_KEYRING,
409+
keyring.get(),
410+
type_ptr,
411+
restriction_ptr,
412+
)
413+
}
414+
.map(ignore)
415+
}

src/api.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ impl Keyring {
101101
}
102102
}
103103

104-
#[cfg(test)]
105104
pub(crate) fn serial(&self) -> KeyringSerial {
106105
self.id
107106
}
@@ -403,6 +402,32 @@ impl Keyring {
403402
keyctl_setperm(self.id, perms)
404403
}
405404

405+
/// Restrict all links into the keyring.
406+
///
407+
/// Requires the `setattr` permission on the keyring and the SysAdmin capability to change it to
408+
/// anything other than the current user.
409+
pub fn restrict_all(&mut self) -> Result<()> {
410+
keyctl_restrict_keyring(self.id, Restriction::AllLinks)
411+
}
412+
413+
/// Restrict links into the keyring.
414+
///
415+
/// Requires the `setattr` permission on the keyring and the SysAdmin capability to change it to
416+
/// anything other than the current user.
417+
pub fn restrict_by_type<K, R>(&mut self, restriction: R) -> Result<()>
418+
where
419+
K: RestrictableKeyType,
420+
R: Borrow<K::Restriction>,
421+
{
422+
keyctl_restrict_keyring(
423+
self.id,
424+
Restriction::ByType {
425+
type_: K::name(),
426+
restriction: &restriction.borrow().restriction(),
427+
},
428+
)
429+
}
430+
406431
fn description_raw(&self) -> Result<String> {
407432
// Get the size of the description.
408433
let mut sz = keyctl_describe(self.id, None)?;
@@ -504,7 +529,6 @@ impl Key {
504529
}
505530
}
506531

507-
#[cfg(test)]
508532
pub(crate) fn serial(&self) -> KeyringSerial {
509533
self.id
510534
}

src/keytype.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,27 @@ impl KeyPayload for Vec<u8> {
9090
Cow::Borrowed(&self)
9191
}
9292
}
93+
94+
/// A key which may be restricted into being added to a keyring.
95+
pub trait RestrictableKeyType: KeyType {
96+
/// The type for representing a restriction for adding keys of this type.
97+
type Restriction: KeyRestriction + ?Sized;
98+
}
99+
100+
/// A restriction for a key.
101+
pub trait KeyRestriction {
102+
/// The restriction string of the key.
103+
fn restriction(&self) -> Cow<str>;
104+
}
105+
106+
impl KeyRestriction for str {
107+
fn restriction(&self) -> Cow<str> {
108+
Cow::Borrowed(&self)
109+
}
110+
}
111+
112+
impl KeyRestriction for String {
113+
fn restriction(&self) -> Cow<str> {
114+
Cow::Borrowed(&self)
115+
}
116+
}

src/keytypes/asymmetric.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626

2727
//! Asymmetric keys
2828
29+
use std::borrow::Cow;
30+
2931
use crate::keytype::*;
32+
use crate::{Key, Keyring, KeyringSerial};
3033

3134
/// Asymmetric keys support encrypting, decrypting, signing, and verifying data.
3235
///
@@ -54,3 +57,62 @@ impl KeyType for Asymmetric {
5457
"asymmetric"
5558
}
5659
}
60+
61+
/// A restriction that may be placed onto a keyring using an asymmetric key.
62+
#[derive(Debug, Clone, PartialEq, Eq)]
63+
pub enum AsymmetricRestriction {
64+
/// Only allow keys which have been signed by a key on the builtin trusted keyring.
65+
BuiltinTrusted,
66+
/// Only allow keys which have been signed by a key on the builtin or secondary trusted
67+
/// keyrings.
68+
BuiltinAndSecondaryTrusted,
69+
/// Only allow keys which have been signed by the given key.
70+
Key {
71+
/// The signing key.
72+
key: Key,
73+
/// Whether or not chaining should be used (see `Chained`).
74+
chained: bool,
75+
},
76+
/// Only allow keys which have been signed by a key on the given keyring.
77+
Keyring {
78+
/// The keyring with permitted signing keys.
79+
keyring: Keyring,
80+
/// Whether or not chaining should be used (see `Chained`).
81+
chained: bool,
82+
},
83+
/// When chaining the destination keyring is also searched for signing keys.
84+
///
85+
/// This allows building up a chain of trust in the destination keyring.
86+
Chained,
87+
}
88+
89+
impl AsymmetricRestriction {
90+
fn restriction_str(id: KeyringSerial, chained: bool) -> String {
91+
let chain_suffix = if chained { ":chain" } else { "" };
92+
format!("key_or_keyring:{}{}", id, chain_suffix)
93+
}
94+
}
95+
96+
impl KeyRestriction for AsymmetricRestriction {
97+
fn restriction(&self) -> Cow<str> {
98+
match self {
99+
AsymmetricRestriction::BuiltinTrusted => "builtin_trusted".into(),
100+
AsymmetricRestriction::BuiltinAndSecondaryTrusted => {
101+
"builtin_and_secondary_trusted".into()
102+
},
103+
AsymmetricRestriction::Key {
104+
key,
105+
chained,
106+
} => Self::restriction_str(key.serial(), *chained).into(),
107+
AsymmetricRestriction::Keyring {
108+
keyring,
109+
chained,
110+
} => Self::restriction_str(keyring.serial(), *chained).into(),
111+
AsymmetricRestriction::Chained => "key_or_keyring:0:chain".into(),
112+
}
113+
}
114+
}
115+
116+
impl RestrictableKeyType for Asymmetric {
117+
type Restriction = AsymmetricRestriction;
118+
}

0 commit comments

Comments
 (0)