1use std::collections::HashMap;
2use std::error::Error;
3
4use once_cell::sync::Lazy;
5use rayon::prelude::*;
6use regex::Regex;
7use crate::enums::ldaptype::*;
8use crate::objects::common::Link;
9use crate::objects::{
10 user::User,
11 computer::Computer,
12 group::Group,
13 ou::Ou,
14 domain::Domain,
15 trust::Trust,
16 common::{Member, GPOChange, LdapObject}
17};
18use crate::transport::ldap::prepare_ldap_dc;
20use crate::utils::format::domain_to_dc;
21use crate::enums::regex::{COMMON_RE1,DOMAIN_SID_RE1};
22use indicatif::ProgressBar;
23use log::{error,trace};
24
25pub fn add_default_groups(
28 vec_groups: &mut Vec<Group>,
29 vec_computers: &[Computer],
30 domain: String
31) -> Result<(), Box<dyn Error>> {
32 let mut member_sid = "".to_owned();
33 let mut domain_sid = "".to_owned();
34
35 let mut template_member = Member::new();
36 *template_member.object_type_mut() = "Computer".to_string();
37
38 let mut edc_group = Group::new();
40 let mut sid = domain.to_uppercase();
41 sid.push_str("-S-1-5-9");
42
43 let mut name = "ENTERPRISE DOMAIN CONTROLLERS@".to_owned();
44 name.push_str(&domain.to_uppercase());
45
46 let mut vec_members: Vec<Member> = Vec::new();
47 for computer in vec_computers {
48 if computer.properties().get_is_dc().to_owned()
49 {
50 *template_member.object_identifier_mut() = computer.object_identifier().clone();
60 vec_members.push(template_member.clone());
61 if let Some(capture) = COMMON_RE1.captures(computer.object_identifier()) {
62
63 member_sid = capture.get(0).map(|m| m.as_str().to_string()).unwrap_or_default();
64
65 if let Some(capture) = DOMAIN_SID_RE1.captures(computer.object_identifier()) {
66 domain_sid = capture.get(0).unwrap().as_str().to_string();
67 }
68
69 }
70 }
71 }
72
73 *edc_group.object_identifier_mut() = sid;
74 *edc_group.properties_mut().name_mut() = name;
75 *edc_group.members_mut() = vec_members;
76 *edc_group.properties_mut().domain_mut() = domain.to_owned();
77 *edc_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
78 vec_groups.push(edc_group);
79
80 let mut account_operators_group = Group::new();
82 sid = domain.to_owned().to_uppercase();
83 sid.push_str("-S-1-5-32-548");
84 let mut name = "ACCOUNT OPERATORS@".to_owned();
85 name.push_str(&domain.to_uppercase());
86
87 *account_operators_group.object_identifier_mut() = sid;
88 *account_operators_group.properties_mut().name_mut() = name;
89 *account_operators_group.properties_mut().highvalue_mut() = true;
90 *account_operators_group.properties_mut().domain_mut() = domain.to_owned();
91 *account_operators_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
92 vec_groups.push(account_operators_group);
93
94 let mut waag_group = Group::new();
96 sid = domain.to_uppercase();
97 sid.push_str("-S-1-5-32-560");
98 let mut name = "WINDOWS AUTHORIZATION ACCESS GROUP@".to_owned();
99 name.push_str(&domain.to_uppercase());
100 *waag_group.object_identifier_mut() = sid;
101 *waag_group.properties_mut().name_mut() = name;
102 *waag_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
103 vec_groups.push(waag_group);
104
105 let mut everyone_group = Group::new();
107 sid = domain.to_uppercase();
108 sid.push_str("-S-1-1-0");
109 let mut name = "EVERYONE@".to_owned();
110 name.push_str(&domain.to_uppercase());
111
112 let mut vec_everyone_members: Vec<Member> = Vec::new();
113 let mut member_id = member_sid.to_owned();
114 member_id.push_str("-515");
115 *template_member.object_identifier_mut() = member_id.to_owned();
116 *template_member.object_type_mut() = "Group".to_string();
117 vec_everyone_members.push(template_member.to_owned());
118
119 member_id = member_sid.to_owned();
120 member_id.push_str("-513");
121 *template_member.object_identifier_mut() = member_id.to_owned();
122 *template_member.object_type_mut() = "Group".to_string();
123 vec_everyone_members.push(template_member.to_owned());
124
125 *everyone_group.object_identifier_mut() = sid;
126 *everyone_group.properties_mut().name_mut() = name;
127 *everyone_group.properties_mut().domain_mut() = domain.to_owned();
128 *everyone_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
129 *everyone_group.members_mut() = vec_everyone_members;
130 vec_groups.push(everyone_group);
131
132 let mut auth_users_group = Group::new();
134 sid = domain.to_uppercase();
135 sid.push_str("-S-1-5-11");
136 let mut name = "AUTHENTICATED USERS@".to_owned();
137 name.push_str(&domain.to_uppercase());
138
139 let mut vec_auth_users_members: Vec<Member> = Vec::new();
140 member_id = member_sid.to_owned();
141 member_id.push_str("-515");
142 *template_member.object_identifier_mut() = member_id.to_owned();
143 *template_member.object_type_mut() = "Group".to_string();
144 vec_auth_users_members.push(template_member.to_owned());
145
146 member_id = member_sid.to_owned();
147 member_id.push_str("-513");
148 *template_member.object_identifier_mut() = member_id.to_owned();
149 *template_member.object_type_mut() = "Group".to_string();
150 vec_auth_users_members.push(template_member.to_owned());
151
152 *auth_users_group.object_identifier_mut() = sid;
153 *auth_users_group.properties_mut().name_mut() = name;
154 *auth_users_group.properties_mut().domain_mut() = domain.to_owned();
155 *auth_users_group.members_mut() = vec_auth_users_members;
156 *auth_users_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
157 vec_groups.push(auth_users_group);
158
159 let mut administrators_group = Group::new();
161 sid = domain.to_uppercase();
162 sid.push_str("-S-1-5-32-544");
163 let mut name = "ADMINISTRATORS@".to_owned();
164 name.push_str(&domain.to_uppercase());
165
166 *administrators_group.object_identifier_mut() = sid;
167 *administrators_group.properties_mut().name_mut() = name;
168 *administrators_group.properties_mut().highvalue_mut() = true;
169 *administrators_group.properties_mut().domain_mut() = domain.to_owned();
170 *administrators_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
171 vec_groups.push(administrators_group);
172
173 let mut pw2000ca_group = Group::new();
175 sid = domain.to_uppercase();
176 sid.push_str("-S-1-5-32-554");
177 let mut name = "PRE-WINDOWS 2000 COMPATIBLE ACCESS@".to_owned();
178 name.push_str(&domain.to_uppercase());
179
180 *pw2000ca_group.object_identifier_mut() = sid;
181 *pw2000ca_group.properties_mut().name_mut() = name;
182 *pw2000ca_group.properties_mut().domain_mut() = domain.to_owned();
183 *pw2000ca_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
184 vec_groups.push(pw2000ca_group);
185
186 let mut interactive_group = Group::new();
188 sid = domain.to_uppercase();
189 sid.push_str("-S-1-5-4");
190 let mut name = "INTERACTIVE@".to_owned();
191 name.push_str(&domain.to_uppercase());
192
193 *interactive_group.object_identifier_mut() = sid;
194 *interactive_group.properties_mut().name_mut() = name;
195 *interactive_group.properties_mut().domain_mut() = domain.to_owned();
196 *interactive_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
197 vec_groups.push(interactive_group);
198
199 let mut print_operators_group = Group::new();
201 sid = domain.to_uppercase();
202 sid.push_str("-S-1-5-32-550");
203 let mut name = "PRINT OPERATORS@".to_owned();
204 name.push_str(&domain.to_uppercase());
205
206 *print_operators_group.object_identifier_mut() = sid;
207 *print_operators_group.properties_mut().name_mut() = name;
208 *print_operators_group.properties_mut().highvalue_mut() = true;
209 *print_operators_group.properties_mut().domain_mut() = domain.to_owned();
210 *print_operators_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
211 vec_groups.push(print_operators_group);
212
213 let mut tsls_group = Group::new();
215 sid = domain.to_uppercase();
216 sid.push_str("-S-1-5-32-561");
217 let mut name = "TERMINAL SERVER LICENSE SERVERS@".to_owned();
218 name.push_str(&domain.to_uppercase());
219
220 *tsls_group.object_identifier_mut() = sid;
221 *tsls_group.properties_mut().name_mut() = name;
222 *tsls_group.properties_mut().domain_mut() = domain.to_owned();
223 *tsls_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
224 vec_groups.push(tsls_group);
225
226 let mut iftb_group = Group::new();
228 sid = domain.to_uppercase();
229 sid.push_str("-S-1-5-32-557");
230 let mut name = "INCOMING FOREST TRUST BUILDERS@".to_owned();
231 name.push_str(&domain.to_uppercase());
232
233 *iftb_group.object_identifier_mut() = sid;
234 *iftb_group.properties_mut().name_mut() = name;
235 *iftb_group.properties_mut().domain_mut() = domain.to_owned();
236 *iftb_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
237 vec_groups.push(iftb_group);
238
239 let mut this_organization_group = Group::new();
241 sid = domain.to_uppercase();
242 sid.push_str("-S-1-5-15");
243 let mut name = "THIS ORGANIZATION@".to_owned();
244 name.push_str(&domain.to_uppercase());
245
246 *this_organization_group.object_identifier_mut() = sid;
247 *this_organization_group.properties_mut().name_mut() = name;
248 *this_organization_group.properties_mut().domain_mut() = domain.to_owned();
249 *this_organization_group.properties_mut().domainsid_mut() = domain_sid.to_owned();
250 vec_groups.push(this_organization_group);
251 Ok(())
252}
253
254pub fn add_default_users(
257 vec_users: &mut Vec<User>,
258 domain: String
259) -> Result<(), Box<dyn Error>> {
260 let mut ntauthority_user = User::new();
262 let mut sid = domain.to_uppercase();
263 sid.push_str("-S-1-5-20");
264 let mut name = "NT AUTHORITY@".to_owned();
265 name.push_str(&domain.to_uppercase());
266 *ntauthority_user.properties_mut().name_mut() = name;
267 *ntauthority_user.object_identifier_mut() = sid;
268
269 if let Some(first_user) = vec_users.get(0) {
270 *ntauthority_user.properties_mut().domainsid_mut() = first_user.properties().domainsid().to_string();
271 } else {
272 error!("vec_users is empty, skipping domain SID assignment");
273 }
274
275 vec_users.push(ntauthority_user);
276 Ok(())
277}
278
279fn build_sid_to_dn(dn_sid: &HashMap<String, String>) -> HashMap<&str, &str> {
284 let mut sid_to_dn: HashMap<&str, &str> = HashMap::with_capacity(dn_sid.len());
285 for (dn, sid) in dn_sid {
286 sid_to_dn
290 .entry(sid.as_str())
291 .and_modify(|existing| {
292 if dn.as_str() < *existing {
293 *existing = dn.as_str();
294 }
295 })
296 .or_insert(dn.as_str());
297 }
298 sid_to_dn
299}
300
301pub fn add_childobjects_members<T: LdapObject + Send>(
303 vec_replaced: &mut [T],
304 dn_sid: &HashMap<String, String>,
305 sid_type: &HashMap<String, String>,
306) -> Result<(), Box<dyn Error>> {
307 let sid_to_dn = build_sid_to_dn(dn_sid);
309
310 let dn_upper: Vec<(String, &String)> =
314 dn_sid.iter().map(|(dn, sid)| (dn.to_uppercase(), sid)).collect();
315
316 vec_replaced.par_iter_mut().for_each(|object| {
318 let sid = object.get_object_identifier().to_uppercase();
320 let dn: &str = sid_to_dn.get(sid.as_str()).copied().unwrap_or(sid.as_str());
321 let name = get_name_from_full_distinguishedname(dn);
322
323 let direct_members: Vec<Member> = dn_upper
325 .iter()
326 .filter_map(|(dn_object_upper, value_sid)| {
327 if dn_object_upper.contains(dn)
329 && dn_object_upper.as_str() != dn
330 && dn_object_upper
331 .split(',')
332 .nth(1)
333 .and_then(|s| s.split('=').nth(1))
334 == Some(name.as_str())
335 {
336 let mut member = Member::new();
337 *member.object_identifier_mut() = (*value_sid).clone();
338 *member.object_type_mut() =
339 sid_type.get(*value_sid).unwrap_or(value_sid).to_string();
340 if !member.object_identifier().is_empty() {
341 return Some(member);
342 }
343 }
344 None
345 })
346 .collect();
347
348 object.set_child_objects(direct_members);
350 });
351
352 Ok(())
353}
354
355pub fn add_childobjects_members_for_ou(
357 vec_replaced: &mut [Ou],
358 dn_sid: &HashMap<String, String>,
359 sid_type: &HashMap<String, String>,
360) -> Result<(), Box<dyn Error>> {
361 let total = vec_replaced.len();
363 let pb = ProgressBar::new(total as u64);
364
365 let null = "NULL".to_string();
367
368 for (count, object) in vec_replaced.iter_mut().enumerate() {
369 if count % (total / 100).max(1) == 0 {
371 pb.set_position(count as u64);
372 }
373
374 let mut direct_members = Vec::new();
375 let mut affected_computers = Vec::new();
376
377 let dn = object.properties().distinguishedname();
379 let mut name = object.properties().name().to_owned();
380 let sid = dn_sid.get(dn).unwrap_or(&null);
381 let otype = sid_type.get(sid).unwrap_or(&null);
382
383 if otype != "Domain" {
385 if let Some(first_part) = name.split('@').next() {
386 name = first_part.to_string();
387 }
388 }
389
390 for (dn_object, value_sid) in dn_sid {
392 let dn_object_upper = dn_object.to_uppercase();
393
394 let first = dn_object_upper
396 .split(',')
397 .nth(1)
398 .and_then(|part| part.split('=').nth(1))
399 .unwrap_or("");
400
401 if otype != "Domain" {
402 if dn_object_upper.contains(dn) && &dn_object_upper != dn && first == name {
404 let mut member = Member::new();
405 *member.object_identifier_mut() = value_sid.clone();
406 let object_type = sid_type.get(value_sid).unwrap_or(&null).to_string();
407 *member.object_type_mut() = object_type.clone();
408
409 direct_members.push(member.clone());
410
411 if object_type == "Computer" {
413 affected_computers.push(member);
414 }
415 }
416 } else {
417 if let Some(cn) = name.split('.').next() {
419 if first.contains(cn) {
420 let mut member = Member::new();
421 *member.object_identifier_mut() = value_sid.clone();
422 *member.object_type_mut() = sid_type.get(value_sid).unwrap_or(&null).to_string();
423 direct_members.push(member);
424 }
425 }
426 }
427 }
428
429 *object.child_objects_mut() = direct_members;
431 if otype == "OU" {
432 let mut gpo_changes = GPOChange::new();
433 *gpo_changes.affected_computers_mut() = affected_computers;
434 *object.gpo_changes_mut() = gpo_changes;
435 }
436 }
437
438 pb.finish_and_clear();
439 Ok(())
440}
441
442pub fn replace_guid_gplink<T: LdapObject + Send>(
444 vec_replaced: &mut [T],
445 dn_sid: &HashMap<String, String>,
446) -> Result<(), Box<dyn Error>> {
447 vec_replaced.par_iter_mut().for_each(|object| {
449 if !object.get_links().is_empty() {
451 let updated_links: Vec<Link> = object
453 .get_links()
454 .iter()
455 .map(|link| {
456 let mut new_link = link.clone(); if let Some(new_guid) = dn_sid
458 .iter()
459 .find(|(key, _)| key.contains(link.guid()))
460 .map(|(_, guid)| guid.to_owned())
461 {
462 *new_link.guid_mut() = new_guid;
463 }
464 new_link
465 })
466 .collect();
467
468 object.set_links(updated_links);
470 }
471 });
472
473 Ok(())
474}
475
476pub fn add_affected_computers(
478 vec_domains: &mut [Domain],
479 sid_type: &HashMap<String, String>,
480) -> Result<(), Box<dyn Error>> {
481 let vec_affected_computers: Vec<Member> = sid_type
483 .iter()
484 .filter(|&(_, obj_type)| obj_type == "Computer")
485 .map(|(sid, _)| {
486 let mut member = Member::new();
487 *member.object_type_mut() = "Computer".to_string();
488 *member.object_identifier_mut() = sid.clone();
489 member
490 })
491 .collect();
492
493 if let Some(domain) = vec_domains.get_mut(0) {
495 let mut gpo_changes = GPOChange::new();
496 *gpo_changes.affected_computers_mut() = vec_affected_computers;
497 *domain.gpo_changes_mut() = gpo_changes;
498 }
499 Ok(())
500}
501
502pub fn add_affected_computers_for_ou(
504 vec_ous: &mut [Ou],
505 dn_sid: &HashMap<String, String>,
506 sid_type: &HashMap<String, String>,
507) -> Result<(), Box<dyn Error>> {
508 let mut computers_by_parent: HashMap<String, Vec<Member>> = HashMap::new();
511 for (dn, sid) in dn_sid {
512 if sid_type.get(sid).map(|t| t == "Computer").unwrap_or(false) {
513 let parent = get_contained_by_name_from_distinguishedname(
514 &get_cn_object_name_from_full_distinguishedname(dn),
515 dn,
516 );
517 let mut member = Member::new();
518 *member.object_identifier_mut() = sid.to_string();
519 *member.object_type_mut() = "Computer".to_string();
520 computers_by_parent.entry(parent).or_default().push(member);
521 }
522 }
523
524 let sid_to_dn = build_sid_to_dn(dn_sid);
527
528 for ou in vec_ous.iter_mut() {
531 let Some(ou_dn) = sid_to_dn.get(ou.get_object_identifier().as_str()) else {
532 continue;
533 };
534 let affected = computers_by_parent.get(*ou_dn).cloned().unwrap_or_default();
535 let mut gpo_changes = GPOChange::new();
536 *gpo_changes.affected_computers_mut() = affected;
537 *ou.gpo_changes_mut() = gpo_changes;
538 }
539 Ok(())
540}
541
542pub fn replace_fqdn_by_sid<T: LdapObject + Send>(
544 object_type: Type,
545 vec_src: &mut [T],
546 fqdn_sid: &HashMap<String, String>,
547) -> Result<(), Box<dyn Error>> {
548 match object_type {
551 Type::User => {
552 vec_src.par_iter_mut().for_each(|obj| {
553 for target in obj.get_spntargets_mut().iter_mut() {
555 let sid = fqdn_sid
556 .get(target.computer_sid())
557 .unwrap_or_else(|| target.computer_sid());
558 *target.computer_sid_mut() = sid.to_string();
559 }
560
561 for target in obj.get_allowed_to_delegate_mut().iter_mut() {
563 let sid = fqdn_sid
564 .get(target.object_identifier())
565 .unwrap_or_else(|| target.object_identifier());
566 *target.object_identifier_mut() = sid.to_string();
567 }
568 });
569 }
570 Type::Computer => {
571 vec_src.par_iter_mut().for_each(|obj| {
572 for delegate in obj.get_allowed_to_delegate_mut().iter_mut() {
574 let sid = fqdn_sid
575 .get(delegate.object_identifier())
576 .unwrap_or_else(|| delegate.object_identifier());
577 *delegate.object_identifier_mut() = sid.to_string();
578 }
579 });
580 }
581 _ => {}
582 }
583
584 Ok(())
585}
586
587pub fn replace_sid_members(
589 vec_groups: &mut [Group],
590 dn_sid: &HashMap<String, String>,
591 sid_type: &HashMap<String, String>,
592 vec_trusts: &[Trust],
593) -> Result<(), Box<dyn Error>> {
594 let default_type = "Group".to_string();
595
596 vec_groups.par_iter_mut().for_each(|group| {
599 for member in group.members_mut() {
600 let member_dn = member.object_identifier();
601
602 if member_dn.trim().is_empty() || member_dn.eq_ignore_ascii_case("SID") {
604 error!("Skipping empty/invalid member DN in group");
605 continue;
606 }
607
608 if let Some(sid) = dn_sid.get(member_dn) {
610 if !sid.is_empty() && sid != "NULL" {
611 let type_object =
612 sid_type.get(sid).cloned().unwrap_or_else(|| default_type.clone());
613 *member.object_identifier_mut() = sid.clone();
614 *member.object_type_mut() = type_object;
615 continue;
616 }
617 }
618
619 match sid_maker_from_another_domain(vec_trusts, member_dn) {
621 Ok(generated_sid) if !generated_sid.is_empty() => {
622 *member.object_identifier_mut() = generated_sid;
623 *member.object_type_mut() = default_type.clone();
624 }
625 Ok(_) => {
626 error!("Could not resolve SID for member DN: {}", member_dn);
627 }
628 Err(e) => {
629 error!("Failed to resolve member DN {}: {}", member_dn, e);
630 }
631 }
632 }
633 });
634
635 Ok(())
636}
637
638fn sid_maker_from_another_domain(
640 vec_trusts: &[Trust],
641 object_identifier: &String,
642) -> Result<String, Box<dyn Error>> {
643 static SID_REGEX: Lazy<Regex> =
645 Lazy::new(|| Regex::new(r"S-[0-9]+-[0-9]+-[0-9]+(?:-[0-9]+)+").unwrap());
646 let sid_regex = &*SID_REGEX;
647
648 for trust in vec_trusts {
650 let ldap_dc = prepare_ldap_dc(trust.target_domain_name());
651 if object_identifier.contains(&ldap_dc[0]) {
652 let id = get_id_from_objectidentifier(object_identifier)?;
653 return Ok(format!("{}{}", trust.target_domain_name(), id))
654 }
655 }
656
657 if object_identifier.contains("CN=S-") {
659 if let Some(capture) = sid_regex.captures(object_identifier).and_then(|cap| cap.get(0)) {
660 return Ok(capture.as_str().to_owned())
661 }
662 }
663
664 Ok(object_identifier.to_string())
666}
667
668fn get_id_from_objectidentifier(
671 object_identifier: &str
672) -> Result<String, Box<dyn Error>> {
673
674 const NAME_TO_RID: [(&str, &str); 16] = [
684 ("DOMAIN ADMINS", "-512"),
686 ("ADMINISTRATEURS DU DOMAINE", "-512"),
687 ("DOMAIN USERS", "-513"),
689 ("UTILISATEURS DU DOMAINE", "-513"),
690 ("DOMAIN GUESTS", "-514"),
692 ("INVITES DE DOMAINE", "-514"),
693 ("DOMAIN COMPUTERS", "-515"),
695 ("ORDINATEURS DE DOMAINE", "-515"),
696 ("DOMAIN CONTROLLERS", "-516"),
698 ("CONTRÔLEURS DE DOMAINE", "-516"),
699 ("CERT PUBLISHERS", "-517"),
701 ("EDITEURS DE CERTIFICATS", "-517"),
702 ("SCHEMA ADMINS", "-518"),
704 ("ADMINISTRATEURS DU SCHEMA", "-518"),
705 ("ENTERPRISE ADMINS", "-519"),
707 ("ADMINISTRATEURS DE L'ENTREPRISE", "-519"),
708 ];
709
710 for (name, rid) in NAME_TO_RID.iter() {
712 if object_identifier.contains(name) {
713 return Ok(rid.to_string())
714 }
715 }
716
717 Ok("NULL_ID1".to_string())
719}
720
721pub fn add_trustdomain(
723 vec_domains: &mut Vec<Domain>,
724 vec_trusts: &mut [Trust]
725) -> Result<(), Box<dyn Error>> {
726 if !&vec_trusts[0].target_domain_sid().to_string().contains("SID") {
727 let mut trusts: Vec<Trust> = Vec::new();
728 for trust in vec_trusts {
729 trusts.push(trust.to_owned());
730 let mut new_domain = Domain::new();
731 *new_domain.object_identifier_mut() = trust.target_domain_sid().to_string();
732 *new_domain.properties_mut().name_mut() = trust.target_domain_name().to_string();
733 *new_domain.properties_mut().domain_mut() = trust.target_domain_name().to_string();
734 *new_domain.properties_mut().distinguishedname_mut() = domain_to_dc(trust.target_domain_name());
735 *new_domain.properties_mut().highvalue_mut() = true;
736 vec_domains.push(new_domain);
737 }
738 *vec_domains[0].trusts_mut() = trusts.to_owned();
739 }
740 Ok(())
741}
742
743pub fn add_type_for_ace<T: LdapObject + Send>(
745 object: &mut [T],
746 sid_type: &HashMap<String, String>,
747) -> Result<(), Box<dyn Error>> {
748 let default_type = "Group".to_string();
750
751 object.par_iter_mut().for_each(|obj| {
754 for ace in obj.get_aces_mut() {
755 let type_object = sid_type
757 .get(ace.principal_sid())
758 .unwrap_or(&default_type)
759 .clone();
760
761 *ace.principal_type_mut() = type_object;
763 }
764 });
765
766 Ok(())
767}
768
769pub fn add_type_for_allowtedtoact(
771 computer: &mut [Computer],
772 sid_type: &HashMap<String, String>,
773) -> Result<(), Box<dyn Error>> {
774 let default_type = "Computer".to_string();
776
777 computer.par_iter_mut().for_each(|comp| {
779 for allowed in comp.allowed_to_act_mut() {
781 let type_object = sid_type
782 .get(allowed.object_identifier())
783 .unwrap_or(&default_type)
784 .clone();
785
786 *allowed.object_type_mut() = type_object;
787 }
788 });
789
790 Ok(())
791}
792
793pub fn add_contained_by_for<T: LdapObject + Send>(
795 vec_replaced: &mut [T],
796 dn_sid: &HashMap<String, String>,
797 sid_type: &HashMap<String, String>,
798) -> Result<(), Box<dyn Error>> {
799 let default_type = "Group".to_string();
801
802 let sid_to_dn = build_sid_to_dn(dn_sid);
806
807 vec_replaced.par_iter_mut().for_each(|object| {
810 let sid = object.get_object_identifier();
812 let Some(dn) = sid_to_dn.get(sid.as_str()).copied() else {
813 return;
814 };
815
816 let otype = sid_type.get(sid).unwrap_or(&default_type);
817 if otype != "Domain" {
818 let dn_owned = dn.to_string();
820 let cn_name = get_cn_object_name_from_full_distinguishedname(&dn_owned);
821 let contained_by_name = get_contained_by_name_from_distinguishedname(&cn_name, &dn_owned);
822
823 if let Some(sid_contained_by) = dn_sid.get(&contained_by_name) {
825 let type_contained_by = sid_type.get(sid_contained_by).unwrap_or(&default_type);
826
827 let mut contained_by = Member::new();
829 *contained_by.object_identifier_mut() = sid_contained_by.to_string();
830 *contained_by.object_type_mut() = type_contained_by.to_string();
831 object.set_contained_by(Some(contained_by));
832 }
833 }
834 });
835
836 Ok(())
837}
838
839pub fn get_name_from_full_distinguishedname(dn_object: &str) -> String {
841 trace!("get_name_from_full_distinguishedname() {:?}",&dn_object);
844 let split1 = dn_object.split(",");
845 let vec1 = split1.collect::<Vec<&str>>();
846 let split2 = vec1[0].split("=");
847 let vec2 = split2.collect::<Vec<&str>>();
848 let name = vec2[1].to_owned();
849 name
851}
852
853fn get_cn_object_name_from_full_distinguishedname(dn_object: &String) -> String {
855 let name = dn_object.to_owned();
858 let split = name.split(",");
859 let vec = split.collect::<Vec<&str>>();
860 let name = vec[0].to_owned();
861 name
863}
864
865fn get_contained_by_name_from_distinguishedname(cn_name: &str, dn_object: &str) -> String {
867 let name = format!("{},",cn_name);
870 let split = dn_object.split(&name);
871 let vec = split.collect::<Vec<&str>>();
872 let dn_contained_by = vec[1].to_owned();
873 dn_contained_by
875}
876
877#[cfg(test)]
880mod tests {
881
882 use crate::json::checker::common::{
883 get_name_from_full_distinguishedname,
884 get_cn_object_name_from_full_distinguishedname,
885 get_contained_by_name_from_distinguishedname
886 };
887
888 #[test]
889 #[rustfmt::skip]
890 pub fn test_get_name_from_full_distinguishedname() {
891 let dn_object = "CN=G0H4N,CN=USERS,DC=ESSOS,DC=LOCAL".to_string();
894 let cn_name = get_name_from_full_distinguishedname(&dn_object);
895 println!("dn_object: {:?}",dn_object);
896 println!("cn_name: {:?}",cn_name);
897 assert_eq!(cn_name, "G0H4N".to_string());
898 }
899
900 #[test]
901 #[rustfmt::skip]
902 pub fn test_get_cn_object_name_from_full_distinguishedname() {
903 let dn_object = "CN=G0H4N,CN=USERS,DC=ESSOS,DC=LOCAL".to_string();
906 let cn_name = get_cn_object_name_from_full_distinguishedname(&dn_object);
907 println!("dn_object: {:?}",dn_object);
908 println!("cn_name: {:?}",cn_name);
909 assert_eq!(cn_name, "CN=G0H4N".to_string());
910 }
911
912 #[test]
913 #[rustfmt::skip]
914 pub fn test_get_contained_by_name_from_name() {
915 let dn_object = "CN=G0H4N,CN=USERS,DC=ESSOS,DC=LOCAL".to_string();
918 let cn_name = "CN=G0H4N".to_string();
919 let contained_by_dn = get_contained_by_name_from_distinguishedname(&cn_name, &dn_object);
920 println!("dn_object: {:?}",dn_object);
921 println!("contained_by_dn: {:?}",contained_by_dn);
922 assert_eq!(contained_by_dn, "CN=USERS,DC=ESSOS,DC=LOCAL".to_string());
923 }
924}