rusthound_ce/objects/
fsp.rs1use serde_json::value::Value;
2use serde::{Deserialize, Serialize};
3use ldap3::SearchEntry;
4use log::{debug, trace};
5use std::collections::HashMap;
6use std::error::Error;
7
8use crate::enums::regex::OBJECT_SID_RE1;
9use crate::objects::common::{LdapObject, AceTemplate, SPNTarget, Link, Member};
10use crate::utils::date::string_to_epoch;
11use crate::enums::secdesc::LdapSid;
12use crate::enums::sid::{objectsid_to_vec8, sid_maker};
13
14#[derive(Debug, Clone, Deserialize, Serialize, Default)]
16pub struct Fsp {
17 #[serde(rename = "Properties")]
18 properties: FspProperties,
19 #[serde(rename = "Aces")]
20 aces: Vec<AceTemplate>,
21 #[serde(rename = "ObjectIdentifier")]
22 object_identifier: String,
23 #[serde(rename = "IsDeleted")]
24 is_deleted: bool,
25 #[serde(rename = "IsACLProtected")]
26 is_acl_protected: bool,
27 #[serde(rename = "ContainedBy")]
28 contained_by: Option<Member>,
29}
30
31impl Fsp {
32 pub fn new() -> Self {
34 Self { ..Default::default() }
35 }
36
37 pub fn parse(
39 &mut self,
40 result: SearchEntry,
41 domain: &str,
42 dn_sid: &mut HashMap<String, String>,
43 sid_type: &mut HashMap<String, String>,
44 ) -> Result<(), Box<dyn Error>> {
45 let result_dn: String = result.dn.to_uppercase();
46 let result_attrs: HashMap<String, Vec<String>> = result.attrs;
47 let result_bin: HashMap<String, Vec<Vec<u8>>> = result.bin_attrs;
48
49 debug!("Parse ForeignSecurityPrincipal: {result_dn}");
51
52 for (key, value) in &result_attrs {
54 trace!(" {key:?}:{value:?}");
55 }
56 for (key, value) in &result_bin {
58 trace!(" {key:?}:{value:?}");
59 }
60
61 self.properties.domain = domain.to_uppercase();
63 self.properties.distinguishedname = result_dn;
64
65 #[allow(unused_assignments)]
66 let mut sid: String = "".to_owned();
67 let mut ftype: &str = "Base";
68
69 for (key, value) in &result_attrs {
71 match key.as_str() {
72 "name" => {
73 let name = format!("{}-{}", domain, &value.first().unwrap_or(&"".to_owned()));
74 self.properties.name = name.to_uppercase();
75
76 let split = value[0].split("-").collect::<Vec<&str>>();
79
80 if split.len() >= 17 {
83 ftype = "User";
84 } else {
85 ftype = "Group";
86 }
87 }
88 "whenCreated" => {
89 let epoch = string_to_epoch(&value[0])?;
90 if epoch.is_positive() {
91 self.properties.whencreated = epoch;
92 }
93 }
94 "objectSid" => {
95 let vec_sid = objectsid_to_vec8(&value[0]);
97 sid = sid_maker(LdapSid::parse(&vec_sid).unwrap().1, domain);
98 self.object_identifier = sid.to_owned();
99
100 for domain_sid in OBJECT_SID_RE1.captures_iter(&sid) {
101 self.properties.domainsid = domain_sid[0].to_owned().to_string();
102 }
103 }
104 "IsDeleted" => {
105 self.is_deleted = true;
106 }
107 _ => {}
108 }
109 }
110
111 if self.object_identifier != "SID" {
113 dn_sid.insert(
114 self.properties.distinguishedname.to_string(),
115 self.object_identifier.to_string()
116 );
117 sid_type.insert(self.object_identifier.to_string(), ftype.to_string());
119 }
120
121 Ok(())
124 }
125}
126
127#[derive(Debug, Clone, Deserialize, Serialize, Default)]
129pub struct FspProperties {
130 domain: String,
131 name: String,
132 distinguishedname: String,
133 domainsid: String,
134 isaclprotected: bool,
135 highvalue: bool,
136 description: Option<String>,
137 whencreated: i64,
138}
139
140impl FspProperties {
141 pub fn new(domain: String) -> Self {
143 Self {
144 domain,
145 whencreated: -1,
146 ..Default::default() }
147 }
148
149 pub fn domain(&self) -> &String {
151 &self.domain
152 }
153 pub fn name(&self) -> &String {
154 &self.name
155 }
156 pub fn distinguishedname(&self) -> &String {
157 &self.distinguishedname
158 }
159 pub fn domainsid(&self) -> &String {
160 &self.domainsid
161 }
162 pub fn highvalue(&self) -> &bool {
163 &self.highvalue
164 }
165 pub fn description(&self) -> &Option<String> {
166 &self.description
167 }
168 pub fn whencreated(&self) -> &i64 {
169 &self.whencreated
170 }
171
172 pub fn domain_mut(&mut self) -> &mut String {
174 &mut self.domain
175 }
176 pub fn name_mut(&mut self) -> &mut String {
177 &mut self.name
178 }
179 pub fn distinguishedname_mut(&mut self) -> &mut String {
180 &mut self.distinguishedname
181 }
182 pub fn domainsid_mut(&mut self) -> &mut String {
183 &mut self.domainsid
184 }
185 pub fn highvalue_mut(&mut self) -> &mut bool {
186 &mut self.highvalue
187 }
188 pub fn description_mut(&mut self) -> &mut Option<String> {
189 &mut self.description
190 }
191 pub fn whencreated_mut(&mut self) -> &mut i64 {
192 &mut self.whencreated
193 }
194}
195
196impl LdapObject for Fsp {
197 fn to_json(&self) -> Value {
199 serde_json::to_value(self).unwrap()
200 }
201
202 fn get_object_identifier(&self) -> &String {
204 &self.object_identifier
205 }
206 fn get_is_acl_protected(&self) -> &bool {
207 &self.is_acl_protected
208 }
209 fn get_aces(&self) -> &Vec<AceTemplate> {
210 &self.aces
211 }
212 fn get_spntargets(&self) -> &Vec<SPNTarget> {
213 panic!("Not used by current object.");
214 }
215 fn get_allowed_to_delegate(&self) -> &Vec<Member> {
216 panic!("Not used by current object.");
217 }
218 fn get_links(&self) -> &Vec<Link> {
219 panic!("Not used by current object.");
220 }
221 fn get_contained_by(&self) -> &Option<Member> {
222 &self.contained_by
223 }
224 fn get_child_objects(&self) -> &Vec<Member> {
225 panic!("Not used by current object.");
226 }
227 fn get_haslaps(&self) -> &bool {
228 &false
229 }
230
231 fn get_aces_mut(&mut self) -> &mut Vec<AceTemplate> {
233 &mut self.aces
234 }
235 fn get_spntargets_mut(&mut self) -> &mut Vec<SPNTarget> {
236 panic!("Not used by current object.");
237 }
238 fn get_allowed_to_delegate_mut(&mut self) -> &mut Vec<Member> {
239 panic!("Not used by current object.");
240 }
241
242 fn set_is_acl_protected(&mut self, is_acl_protected: bool) {
244 self.is_acl_protected = is_acl_protected;
245 self.properties.isaclprotected = is_acl_protected;
246 }
247 fn set_aces(&mut self, aces: Vec<AceTemplate>) {
248 self.aces = aces;
249 }
250 fn set_spntargets(&mut self, _spn_targets: Vec<SPNTarget>) {
251 }
253 fn set_allowed_to_delegate(&mut self, _allowed_to_delegate: Vec<Member>) {
254 }
256 fn set_links(&mut self, _links: Vec<Link>) {
257 }
259 fn set_contained_by(&mut self, contained_by: Option<Member>) {
260 self.contained_by = contained_by;
261 }
262 fn set_child_objects(&mut self, _child_objects: Vec<Member>) {
263 }
265}