linux_keyutils/
permissions.rs

1//! Create a more rust-like permissions construct, ported from the unix
2//! permissions defined in keyutils.h
3use bitflags::bitflags;
4
5/// Construct key permissions for use with [Key::set_perms](crate::Key::set_perms)
6/// or returned by [Metadata::get_perms](crate::Metadata::get_perms).
7///
8/// Usage:
9///
10/// ```
11/// use linux_keyutils::{Permission, KeyPermissions};
12///
13/// let mut perms = KeyPermissions::new();
14/// perms.set_user_perms(Permission::ALL);
15/// perms.set_group_perms(Permission::VIEW);
16/// ```
17#[derive(Debug, Copy, Clone)]
18pub struct KeyPermissions(u32);
19
20/// Construct key permissions with the builder pattern.
21///
22/// Usage:
23///
24/// ```
25/// use linux_keyutils::{Permission, KeyPermissionsBuilder};
26///
27/// let perms = KeyPermissionsBuilder::builder()
28///             .user(Permission::ALL)
29///             .group(Permission::VIEW)
30///             .build();
31/// ```
32#[derive(Debug, Copy, Clone)]
33pub struct KeyPermissionsBuilder(KeyPermissions);
34
35bitflags! {
36    /// Pre-defined bit-flags to construct permissions easily.
37    #[repr(transparent)]
38    pub struct Permission: u8 {
39        /// Allows viewing a key's attributes
40        const VIEW = 0x1;
41        /// Allows reading a key's payload / viewing a keyring
42        const READ = 0x2;
43        /// Allows writing/updating a key's payload / adding a link to keyring
44        const WRITE = 0x4;
45        /// Allows finding a key in search / searching a keyring
46        const SEARCH = 0x8;
47        /// Allows creating a link to a key/keyring
48        const LINK = 0x10;
49        /// Allows setting attributes for a key
50        const SETATTR = 0x20;
51        /// Allows all actions
52        const ALL = 0x3f;
53    }
54}
55
56impl Default for KeyPermissions {
57    fn default() -> Self {
58        Self::new()
59    }
60}
61
62impl KeyPermissions {
63    /// Create a new KeyPermissions object, defaults to empty permissions
64    pub fn new() -> Self {
65        Self(0)
66    }
67
68    /// Construct the permissions manually
69    pub fn from_u32(raw: u32) -> Self {
70        Self(raw)
71    }
72
73    /// Obtain the u32 bits for this set
74    pub fn bits(&self) -> u32 {
75        self.0
76    }
77
78    /// Set the permissions available to the key's possessor
79    pub fn set_posessor_perms(&mut self, perm: Permission) {
80        self.0 &= !(0xFF << 24);
81        self.0 += (perm.bits() as u32) << 24;
82    }
83
84    /// Set the permissions available to the key's owning user (UID)
85    pub fn set_user_perms(&mut self, perm: Permission) {
86        self.0 &= !(0xFF << 16);
87        self.0 += (perm.bits() as u32) << 16;
88    }
89
90    /// Set the permissions available to the key's owning group (GID)
91    pub fn set_group_perms(&mut self, perm: Permission) {
92        self.0 &= !(0xFF << 8);
93        self.0 += (perm.bits() as u32) << 8;
94    }
95
96    /// Set the permissions available to any 3rd party
97    pub fn set_world_perms(&mut self, perm: Permission) {
98        self.0 &= !0xFF;
99        self.0 += perm.bits() as u32;
100    }
101}
102
103impl KeyPermissionsBuilder {
104    /// Start a KeyPermissionsBuilder
105    pub fn builder() -> Self {
106        Self(KeyPermissions::default())
107    }
108
109    /// Set the permissions available to the key's possessor
110    pub fn posessor(mut self, perm: Permission) -> Self {
111        self.0.set_posessor_perms(perm);
112        self
113    }
114
115    /// Set the permissions available to the key's owning user (UID)
116    pub fn user(mut self, perm: Permission) -> Self {
117        self.0.set_user_perms(perm);
118        self
119    }
120
121    /// Set the permissions available to the key's owning group (GID)
122    pub fn group(mut self, perm: Permission) -> Self {
123        self.0.set_group_perms(perm);
124        self
125    }
126
127    /// Set the permissions available to any 3rd party
128    pub fn world(mut self, perm: Permission) -> Self {
129        self.0.set_world_perms(perm);
130        self
131    }
132
133    /// Finish the build and obtain the created KeyPermissions
134    pub fn build(self) -> KeyPermissions {
135        self.0
136    }
137}
138
139#[test]
140fn test_posessor_perms() {
141    let mut perm = KeyPermissions::default();
142
143    // Initial
144    perm.set_posessor_perms(Permission::ALL);
145    assert_eq!(perm.0, 0x3f000000);
146
147    // Update
148    perm.set_posessor_perms(Permission::SEARCH);
149    assert_eq!(perm.0, 0x08000000);
150
151    // Combination
152    perm.set_posessor_perms(Permission::SEARCH | Permission::VIEW);
153    assert_eq!(perm.0, 0x09000000);
154
155    // Combination two
156    perm.set_posessor_perms(
157        Permission::SETATTR | Permission::VIEW | Permission::READ | Permission::WRITE,
158    );
159    assert_eq!(perm.0, 0x27000000);
160}
161
162#[test]
163fn test_user_perms() {
164    let mut perm = KeyPermissions::default();
165
166    // Initial
167    perm.set_user_perms(Permission::ALL);
168    assert_eq!(perm.0, 0x003f0000);
169
170    // Update
171    perm.set_user_perms(Permission::SEARCH);
172    assert_eq!(perm.0, 0x00080000);
173
174    // Combination
175    perm.set_user_perms(Permission::SEARCH | Permission::VIEW);
176    assert_eq!(perm.0, 0x00090000);
177
178    // Combination2
179    perm.set_user_perms(
180        Permission::SETATTR | Permission::VIEW | Permission::READ | Permission::WRITE,
181    );
182    assert_eq!(perm.0, 0x00270000);
183}
184
185#[test]
186fn test_group_perms() {
187    let mut perm = KeyPermissions::default();
188
189    // Initial
190    perm.set_group_perms(Permission::ALL);
191    assert_eq!(perm.0, 0x00003f00);
192
193    // Update
194    perm.set_group_perms(Permission::SEARCH);
195    assert_eq!(perm.0, 0x00000800);
196
197    // Combination
198    perm.set_group_perms(Permission::SEARCH | Permission::VIEW);
199    assert_eq!(perm.0, 0x00000900);
200
201    // Combination2
202    perm.set_group_perms(
203        Permission::SETATTR | Permission::VIEW | Permission::READ | Permission::WRITE,
204    );
205    assert_eq!(perm.0, 0x00002700);
206}
207
208#[test]
209fn test_world_perms() {
210    let mut perm = KeyPermissions::default();
211
212    // Initial
213    perm.set_world_perms(Permission::ALL);
214    assert_eq!(perm.0, 0x0000003f);
215
216    // Update
217    perm.set_world_perms(Permission::SEARCH);
218    assert_eq!(perm.0, 0x00000008);
219
220    // Combination
221    perm.set_world_perms(Permission::SEARCH | Permission::VIEW);
222    assert_eq!(perm.0, 0x00000009);
223
224    // Combination2
225    perm.set_world_perms(
226        Permission::SETATTR | Permission::VIEW | Permission::READ | Permission::WRITE,
227    );
228    assert_eq!(perm.0, 0x00000027);
229}
230
231#[test]
232fn test_combined_perms() {
233    let mut perm = KeyPermissions::default();
234
235    // Posessor
236    perm.set_posessor_perms(Permission::ALL);
237    assert_eq!(perm.0, 0x3f000000);
238
239    // User
240    perm.set_user_perms(Permission::VIEW | Permission::READ | Permission::WRITE);
241    assert_eq!(perm.0, 0x3f070000);
242
243    // Group
244    perm.set_group_perms(Permission::SEARCH | Permission::VIEW);
245    assert_eq!(perm.0, 0x3f070900);
246
247    // World
248    perm.set_world_perms(
249        Permission::SETATTR | Permission::VIEW | Permission::READ | Permission::WRITE,
250    );
251    assert_eq!(perm.0, 0x3f070927);
252}