secure_exec_kernel/
user.rs1#[derive(Debug, Clone, PartialEq, Eq)]
2pub struct ProcessIdentity {
3 pub uid: u32,
4 pub gid: u32,
5 pub euid: u32,
6 pub egid: u32,
7 pub supplementary_gids: Vec<u32>,
8}
9
10impl Default for ProcessIdentity {
11 fn default() -> Self {
12 Self {
13 uid: 1000,
14 gid: 1000,
15 euid: 1000,
16 egid: 1000,
17 supplementary_gids: vec![1000],
18 }
19 }
20}
21
22#[derive(Debug, Clone, Default, PartialEq, Eq)]
23pub struct UserConfig {
24 pub uid: Option<u32>,
25 pub gid: Option<u32>,
26 pub euid: Option<u32>,
27 pub egid: Option<u32>,
28 pub username: Option<String>,
29 pub homedir: Option<String>,
30 pub shell: Option<String>,
31 pub gecos: Option<String>,
32 pub group_name: Option<String>,
33 pub supplementary_gids: Vec<u32>,
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct UserManager {
40 pub uid: u32,
41 pub gid: u32,
42 pub euid: u32,
43 pub egid: u32,
44 pub username: String,
45 pub homedir: String,
46 pub shell: String,
47 pub gecos: String,
48 pub group_name: String,
49 pub supplementary_gids: Vec<u32>,
50}
51
52impl Default for UserManager {
53 fn default() -> Self {
54 Self::from_config(UserConfig::default())
55 }
56}
57
58impl UserManager {
59 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn from_config(config: UserConfig) -> Self {
64 let uid = config.uid.unwrap_or(1000);
65 let gid = config.gid.unwrap_or(1000);
66 let username = config.username.unwrap_or_else(|| String::from("user"));
67 let supplementary_gids = normalize_supplementary_gids(gid, config.supplementary_gids);
68
69 Self {
70 uid,
71 gid,
72 euid: config.euid.unwrap_or(uid),
73 egid: config.egid.unwrap_or(gid),
74 username: username.clone(),
75 homedir: config.homedir.unwrap_or_else(|| String::from("/home/user")),
76 shell: config.shell.unwrap_or_else(|| String::from("/bin/sh")),
77 gecos: config.gecos.unwrap_or_default(),
78 group_name: config.group_name.unwrap_or(username),
79 supplementary_gids,
80 }
81 }
82
83 pub fn identity(&self) -> ProcessIdentity {
84 ProcessIdentity {
85 uid: self.uid,
86 gid: self.gid,
87 euid: self.euid,
88 egid: self.egid,
89 supplementary_gids: self.supplementary_gids.clone(),
90 }
91 }
92
93 pub fn getgroups(&self) -> Vec<u32> {
94 self.supplementary_gids.clone()
95 }
96
97 pub fn getpwuid(&self, uid: u32) -> Option<String> {
98 if uid == self.uid {
99 return Some(format!(
100 "{}:x:{}:{}:{}:{}:{}",
101 self.username, self.uid, self.gid, self.gecos, self.homedir, self.shell
102 ));
103 }
104
105 None
106 }
107
108 pub fn getgrgid(&self, gid: u32) -> Option<String> {
109 if gid == self.gid {
110 return Some(format!(
111 "{}:x:{}:{}",
112 self.group_name, self.gid, self.username
113 ));
114 }
115
116 if self.supplementary_gids.contains(&gid) {
117 let group_name = format!("group{gid}");
120 return Some(format!("{group_name}:x:{gid}:{}", self.username));
121 }
122
123 None
124 }
125}
126
127fn normalize_supplementary_gids(primary_gid: u32, supplementary_gids: Vec<u32>) -> Vec<u32> {
128 let mut normalized = Vec::with_capacity(supplementary_gids.len() + 1);
129 normalized.push(primary_gid);
130 for gid in supplementary_gids {
131 if !normalized.contains(&gid) {
132 normalized.push(gid);
133 }
134 }
135 normalized
136}