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