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("agentos"));
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
76 .homedir
77 .unwrap_or_else(|| String::from("/home/agentos")),
78 shell: config.shell.unwrap_or_else(|| String::from("/bin/sh")),
79 gecos: config.gecos.unwrap_or_default(),
80 group_name: config.group_name.unwrap_or(username),
81 supplementary_gids,
82 }
83 }
84
85 pub fn identity(&self) -> ProcessIdentity {
86 ProcessIdentity {
87 uid: self.uid,
88 gid: self.gid,
89 euid: self.euid,
90 egid: self.egid,
91 supplementary_gids: self.supplementary_gids.clone(),
92 }
93 }
94
95 pub fn getgroups(&self) -> Vec<u32> {
96 self.supplementary_gids.clone()
97 }
98
99 pub fn getpwuid(&self, uid: u32) -> Option<String> {
100 if uid == self.uid {
101 return Some(format!(
102 "{}:x:{}:{}:{}:{}:{}",
103 self.username, self.uid, self.gid, self.gecos, self.homedir, self.shell
104 ));
105 }
106
107 None
108 }
109
110 pub fn getgrgid(&self, gid: u32) -> Option<String> {
111 if gid == self.gid {
112 return Some(format!(
113 "{}:x:{}:{}",
114 self.group_name, self.gid, self.username
115 ));
116 }
117
118 if self.supplementary_gids.contains(&gid) {
119 let group_name = format!("group{gid}");
122 return Some(format!("{group_name}:x:{gid}:{}", self.username));
123 }
124
125 None
126 }
127}
128
129fn normalize_supplementary_gids(primary_gid: u32, supplementary_gids: Vec<u32>) -> Vec<u32> {
130 let mut normalized = Vec::with_capacity(supplementary_gids.len() + 1);
131 normalized.push(primary_gid);
132 for gid in supplementary_gids {
133 if !normalized.contains(&gid) {
134 normalized.push(gid);
135 }
136 }
137 normalized
138}