1use std::collections::HashMap;
2use std::error::Error;
3
4use regex::Regex;
5use crate::enums::ldaptype::*;
6use crate::objects::common::Link;
7use crate::objects::{
8 user::User,
9 computer::Computer,
10 group::Group,
11 ou::Ou,
12 domain::Domain,
13 trust::Trust,
14 common::{Member, GPOChange, LdapObject}
15};
16use crate::ldap::prepare_ldap_dc;
18use crate::utils::format::domain_to_dc;
19use crate::enums::regex::COMMON_RE1;
20use indicatif::ProgressBar;
21use log::trace;
22
23pub fn add_default_groups(
26 vec_groups: &mut Vec<Group>,
27 vec_computers: &[Computer],
28 domain: String
29) -> Result<(), Box<dyn Error>> {
30 let mut domain_sid = "".to_owned();
31 let mut template_member = Member::new();
32 *template_member.object_type_mut() = "Computer".to_string();
33
34 let mut edc_group = Group::new();
36 let mut sid = domain.to_uppercase();
37 sid.push_str("-S-1-5-9");
38
39 let mut name = "ENTERPRISE DOMAIN CONTROLLERS@".to_owned();
40 name.push_str(&domain.to_uppercase());
41
42 let mut vec_members: Vec<Member> = Vec::new();
43 for computer in vec_computers {
44 if computer.properties().get_is_dc().to_owned()
45 {
46 *template_member.object_identifier_mut() = computer.object_identifier().clone();
56 vec_members.push(template_member.clone());
57 if let Some(capture) = COMMON_RE1.captures(computer.object_identifier()) {
58 domain_sid = capture.get(0).map(|m| m.as_str().to_string()).unwrap_or_default();
59 }
60 }
61 }
62
63 *edc_group.object_identifier_mut() = sid;
64 *edc_group.properties_mut().name_mut() = name;
65 *edc_group.members_mut() = vec_members;
66 vec_groups.push(edc_group);
67
68 let mut account_operators_group = Group::new();
70 sid = domain.to_uppercase();
71 sid.push_str("-S-1-5-32-548");
72 let mut name = "ACCOUNT OPERATORS@".to_owned();
73 name.push_str(&domain.to_uppercase());
74
75 *account_operators_group.object_identifier_mut() = sid;
76 *account_operators_group.properties_mut().name_mut() = name;
77 *account_operators_group.properties_mut().highvalue_mut() = true;
78 vec_groups.push(account_operators_group);
79
80 let mut waag_group = Group::new();
82 sid = domain.to_uppercase();
83 sid.push_str("-S-1-5-32-560");
84 let mut name = "WINDOWS AUTHORIZATION ACCESS GROUP@".to_owned();
85 name.push_str(&domain.to_uppercase());
86 *waag_group.object_identifier_mut() = sid;
87 *waag_group.properties_mut().name_mut() = name;
88 vec_groups.push(waag_group);
89
90 let mut everyone_group = Group::new();
92 sid = domain.to_uppercase();
93 sid.push_str("-S-1-1-0");
94 let mut name = "EVERYONE@".to_owned();
95 name.push_str(&domain.to_uppercase());
96
97 let mut vec_everyone_members: Vec<Member> = Vec::new();
98 let mut member_id = domain_sid.to_owned();
99 member_id.push_str("-515");
100 *template_member.object_identifier_mut() = member_id.to_owned();
101 *template_member.object_type_mut() = "Group".to_string();
102 vec_everyone_members.push(template_member.to_owned());
103
104 member_id = domain_sid.to_owned();
105 member_id.push_str("-513");
106 *template_member.object_identifier_mut() = member_id.to_owned();
107 *template_member.object_type_mut() = "Group".to_string();
108 vec_everyone_members.push(template_member.to_owned());
109
110 *everyone_group.object_identifier_mut() = sid;
111 *everyone_group.properties_mut().name_mut() = name;
112 *everyone_group.members_mut() = vec_everyone_members;
113 vec_groups.push(everyone_group);
114
115 let mut auth_users_group = Group::new();
117 sid = domain.to_uppercase();
118 sid.push_str("-S-1-5-11");
119 let mut name = "AUTHENTICATED USERS@".to_owned();
120 name.push_str(&domain.to_uppercase());
121
122 let mut vec_auth_users_members: Vec<Member> = Vec::new();
123 member_id = domain_sid.to_owned();
124 member_id.push_str("-515");
125 *template_member.object_identifier_mut() = member_id.to_owned();
126 *template_member.object_type_mut() = "Group".to_string();
127 vec_auth_users_members.push(template_member.to_owned());
128
129 member_id = domain_sid.to_owned();
130 member_id.push_str("-513");
131 *template_member.object_identifier_mut() = member_id.to_owned();
132 *template_member.object_type_mut() = "Group".to_string();
133 vec_auth_users_members.push(template_member.to_owned());
134
135 *auth_users_group.object_identifier_mut() = sid;
136 *auth_users_group.properties_mut().name_mut() = name;
137 *auth_users_group.members_mut() = vec_auth_users_members;
138 vec_groups.push(auth_users_group);
139
140 let mut administrators_group = Group::new();
142 sid = domain.to_uppercase();
143 sid.push_str("-S-1-5-32-544");
144 let mut name = "ADMINISTRATORS@".to_owned();
145 name.push_str(&domain.to_uppercase());
146
147 *administrators_group.object_identifier_mut() = sid;
148 *administrators_group.properties_mut().name_mut() = name;
149 *administrators_group.properties_mut().highvalue_mut() = true;
150 vec_groups.push(administrators_group);
151
152 let mut pw2000ca_group = Group::new();
154 sid = domain.to_uppercase();
155 sid.push_str("-S-1-5-32-554");
156 let mut name = "PRE-WINDOWS 2000 COMPATIBLE ACCESS@".to_owned();
157 name.push_str(&domain.to_uppercase());
158
159 *pw2000ca_group.object_identifier_mut() = sid;
160 *pw2000ca_group.properties_mut().name_mut() = name;
161 vec_groups.push(pw2000ca_group);
162
163 let mut interactive_group = Group::new();
165 sid = domain.to_uppercase();
166 sid.push_str("-S-1-5-4");
167 let mut name = "INTERACTIVE@".to_owned();
168 name.push_str(&domain.to_uppercase());
169
170 *interactive_group.object_identifier_mut() = sid;
171 *interactive_group.properties_mut().name_mut() = name;
172 vec_groups.push(interactive_group);
173
174 let mut print_operators_group = Group::new();
176 sid = domain.to_uppercase();
177 sid.push_str("-S-1-5-32-550");
178 let mut name = "PRINT OPERATORS@".to_owned();
179 name.push_str(&domain.to_uppercase());
180
181 *print_operators_group.object_identifier_mut() = sid;
182 *print_operators_group.properties_mut().name_mut() = name;
183 *print_operators_group.properties_mut().highvalue_mut() = true;
184 vec_groups.push(print_operators_group);
185
186 let mut tsls_group = Group::new();
188 sid = domain.to_uppercase();
189 sid.push_str("-S-1-5-32-561");
190 let mut name = "TERMINAL SERVER LICENSE SERVERS@".to_owned();
191 name.push_str(&domain.to_uppercase());
192
193 *tsls_group.object_identifier_mut() = sid;
194 *tsls_group.properties_mut().name_mut() = name;
195 vec_groups.push(tsls_group);
196
197 let mut iftb_group = Group::new();
199 sid = domain.to_uppercase();
200 sid.push_str("-S-1-5-32-557");
201 let mut name = "INCOMING FOREST TRUST BUILDERS@".to_owned();
202 name.push_str(&domain.to_uppercase());
203
204 *iftb_group.object_identifier_mut() = sid;
205 *iftb_group.properties_mut().name_mut() = name;
206 vec_groups.push(iftb_group);
207
208 let mut this_organization_group = Group::new();
210 sid = domain.to_uppercase();
211 sid.push_str("-S-1-5-15");
212 let mut name = "THIS ORGANIZATION@".to_owned();
213 name.push_str(&domain.to_uppercase());
214
215 *this_organization_group.object_identifier_mut() = sid;
216 *this_organization_group.properties_mut().name_mut() = name;
217 vec_groups.push(this_organization_group);
218 Ok(())
219}
220
221pub fn add_default_users(
224 vec_users: &mut Vec<User>,
225 domain: String
226) -> Result<(), Box<dyn Error>> {
227 let mut ntauthority_user = User::new();
229 let mut sid = domain.to_uppercase();
230 sid.push_str("-S-1-5-20");
231 let mut name = "NT AUTHORITY@".to_owned();
232 name.push_str(&domain.to_uppercase());
233 *ntauthority_user.properties_mut().name_mut() = name;
234 *ntauthority_user.object_identifier_mut() = sid;
235 *ntauthority_user.properties_mut().domainsid_mut() = vec_users[0].properties().domainsid().to_string();
236 vec_users.push(ntauthority_user);
237 Ok(())
238}
239
240pub fn add_childobjects_members<T: LdapObject>(
242 vec_replaced: &mut [T],
243 dn_sid: &HashMap<String, String>,
244 sid_type: &HashMap<String, String>,
245) -> Result<(), Box<dyn Error>> {
246 let total = vec_replaced.len();
248 let pb = ProgressBar::new(total as u64);
249
250 for (count, object) in vec_replaced.iter_mut().enumerate() {
252 if count % (total / 100).max(1) == 0 {
254 pb.set_position(count as u64);
255 }
256
257 let sid = object.get_object_identifier().to_uppercase();
259 let dn = dn_sid
260 .iter()
261 .find(|(_, v)| **v == sid)
262 .map(|(k, _)| k)
263 .unwrap_or(&sid);
264 let name = get_name_from_full_distinguishedname(dn);
265 let _otype = sid_type.get(&sid).unwrap();
266
267 let direct_members: Vec<Member> = dn_sid
269 .iter()
270 .filter_map(|(dn_object, value_sid)| {
271 let dn_object_upper = dn_object.to_uppercase();
272
273 if dn_object_upper.contains(dn)
275 && &dn_object_upper != dn
276 && dn_object_upper.split(',')
277 .nth(1)
278 .and_then(|s| s.split('=').nth(1))
279 == Some(&name)
280 {
281 let mut member = Member::new();
282 *member.object_identifier_mut() = value_sid.clone();
283 *member.object_type_mut() = sid_type.get(value_sid).unwrap_or(&value_sid).to_string();
284 if !member.object_identifier().is_empty() {
285 return Some(member);
286 }
287 }
288 None
289 })
290 .collect();
291
292 object.set_child_objects(direct_members);
294 }
295
296 pb.finish_and_clear();
297 Ok(())
298}
299
300pub fn add_childobjects_members_for_ou(
302 vec_replaced: &mut [Ou],
303 dn_sid: &HashMap<String, String>,
304 sid_type: &HashMap<String, String>,
305) -> Result<(), Box<dyn Error>> {
306 let total = vec_replaced.len();
308 let pb = ProgressBar::new(total as u64);
309
310 let null = "NULL".to_string();
312
313 for (count, object) in vec_replaced.iter_mut().enumerate() {
314 if count % (total / 100).max(1) == 0 {
316 pb.set_position(count as u64);
317 }
318
319 let mut direct_members = Vec::new();
320 let mut affected_computers = Vec::new();
321
322 let dn = object.properties().distinguishedname();
324 let mut name = object.properties().name().to_owned();
325 let sid = dn_sid.get(dn).unwrap_or(&null);
326 let otype = sid_type.get(sid).unwrap_or(&null);
327
328 if otype != "Domain" {
330 if let Some(first_part) = name.split('@').next() {
331 name = first_part.to_string();
332 }
333 }
334
335 for (dn_object, value_sid) in dn_sid {
337 let dn_object_upper = dn_object.to_uppercase();
338
339 let first = dn_object_upper
341 .split(',')
342 .nth(1)
343 .and_then(|part| part.split('=').nth(1))
344 .unwrap_or("");
345
346 if otype != "Domain" {
347 if dn_object_upper.contains(dn) && &dn_object_upper != dn && first == name {
349 let mut member = Member::new();
350 *member.object_identifier_mut() = value_sid.clone();
351 let object_type = sid_type.get(value_sid).unwrap_or(&null).to_string();
352 *member.object_type_mut() = object_type.clone();
353
354 direct_members.push(member.clone());
355
356 if object_type == "Computer" {
358 affected_computers.push(member);
359 }
360 }
361 } else {
362 if let Some(cn) = name.split('.').next() {
364 if first.contains(cn) {
365 let mut member = Member::new();
366 *member.object_identifier_mut() = value_sid.clone();
367 *member.object_type_mut() = sid_type.get(value_sid).unwrap_or(&null).to_string();
368 direct_members.push(member);
369 }
370 }
371 }
372 }
373
374 *object.child_objects_mut() = direct_members;
376 if otype == "OU" {
377 let mut gpo_changes = GPOChange::new();
378 *gpo_changes.affected_computers_mut() = affected_computers;
379 *object.gpo_changes_mut() = gpo_changes;
380 }
381 }
382
383 pb.finish_and_clear();
384 Ok(())
385}
386
387pub fn replace_guid_gplink<T: LdapObject>(
389 vec_replaced: &mut [T],
390 dn_sid: &HashMap<String, String>,
391) -> Result<(), Box<dyn Error>> {
392 let total = vec_replaced.len();
394 let pb = ProgressBar::new(total as u64);
395
396 for (count, object) in vec_replaced.iter_mut().enumerate() {
398 if count % (total / 100).max(1) == 0 {
400 pb.set_position(count as u64);
401 }
402
403 if !object.get_links().is_empty() {
405 let updated_links: Vec<Link> = object
407 .get_links()
408 .iter()
409 .map(|link| {
410 let mut new_link = link.clone(); if let Some(new_guid) = dn_sid
412 .iter()
413 .find(|(key, _)| key.contains(link.guid()))
414 .map(|(_, guid)| guid.to_owned())
415 {
416 *new_link.guid_mut() = new_guid;
417 }
418 new_link
419 })
420 .collect();
421
422 object.set_links(updated_links);
424 }
425 }
426
427 pb.finish_and_clear();
428 Ok(())
429}
430
431pub fn add_affected_computers(
433 vec_domains: &mut [Domain],
434 sid_type: &HashMap<String, String>,
435) -> Result<(), Box<dyn Error>> {
436 let vec_affected_computers: Vec<Member> = sid_type
438 .iter()
439 .filter(|&(_, obj_type)| obj_type == "Computer")
440 .map(|(sid, _)| {
441 let mut member = Member::new();
442 *member.object_type_mut() = "Computer".to_string();
443 *member.object_identifier_mut() = sid.clone();
444 member
445 })
446 .collect();
447
448 if let Some(domain) = vec_domains.get_mut(0) {
450 let mut gpo_changes = GPOChange::new();
451 *gpo_changes.affected_computers_mut() = vec_affected_computers;
452 *domain.gpo_changes_mut() = gpo_changes;
453 }
454 Ok(())
455}
456
457pub fn add_affected_computers_for_ou(
459 vec_ous: &mut [Ou],
460 dn_sid: &HashMap<String, String>,
461 sid_type: &HashMap<String, String>,
462) -> Result<(), Box<dyn Error>> {
463 let dn_sid_filtered: Vec<(&String, &String)> = dn_sid
465 .iter()
466 .filter(|(_, sid)| sid_type.get(*sid).map(|t| t == "Computer").unwrap_or(false))
467 .collect();
468
469 let ou_dn_map: HashMap<String, String> = vec_ous
471 .iter()
472 .filter_map(|ou| {
473 dn_sid
474 .iter()
475 .find_map(|(dn, sid)| {
476 if *sid == *ou.get_object_identifier() {
477 Some((ou.get_object_identifier().to_owned(), dn.clone()))
478 } else {
479 None
480 }
481 })
482 })
483 .collect();
484
485 for ou in vec_ous.iter_mut() {
487 if let Some(ou_dn) = ou_dn_map.get(ou.get_object_identifier()) {
488 let vec_affected_computers: Vec<Member> = dn_sid_filtered
489 .iter()
490 .filter_map(|(dn, sid)| {
491 if get_contained_by_name_from_distinguishedname(
492 &get_cn_object_name_from_full_distinguishedname(dn),
493 dn,
494 ) == *ou_dn
495 {
496 let mut member = Member::new();
497 *member.object_identifier_mut() = sid.to_string();
498 *member.object_type_mut() = "Computer".to_string();
499 Some(member)
500 } else {
501 None
502 }
503 })
504 .collect();
505
506 let mut gpo_changes = GPOChange::new();
508 *gpo_changes.affected_computers_mut() = vec_affected_computers;
509 *ou.gpo_changes_mut() = gpo_changes;
510 }
511 }
512 Ok(())
513}
514
515pub fn replace_fqdn_by_sid<T: LdapObject>(
517 object_type: Type,
518 vec_src: &mut [T],
519 fqdn_sid: &HashMap<String, String>,
520) -> Result<(), Box<dyn Error>> {
521 let total = vec_src.len();
523 let pb = ProgressBar::new(total as u64);
524
525 match object_type {
527 Type::User => {
528 for (count, obj) in vec_src.iter_mut().enumerate() {
529 if count % (total / 100).max(1) == 0 {
531 pb.set_position(count as u64);
532 }
533
534 for target in obj.get_spntargets_mut().iter_mut() {
536 let sid = fqdn_sid
537 .get(target.computer_sid())
538 .unwrap_or_else(|| target.computer_sid());
539 *target.computer_sid_mut() = sid.to_string();
540 }
541
542 for target in obj.get_allowed_to_delegate_mut().iter_mut() {
544 let sid = fqdn_sid
545 .get(target.object_identifier())
546 .unwrap_or_else(|| target.object_identifier());
547 *target.object_identifier_mut() = sid.to_string();
548 }
549 }
550 }
551 Type::Computer => {
552 for (count, obj) in vec_src.iter_mut().enumerate() {
553 if count % (total / 100).max(1) == 0 {
555 pb.set_position(count as u64);
556 }
557
558 for delegate in obj.get_allowed_to_delegate_mut().iter_mut() {
560 let sid = fqdn_sid
561 .get(delegate.object_identifier())
562 .unwrap_or_else(|| delegate.object_identifier());
563 *delegate.object_identifier_mut() = sid.to_string();
564 }
565 }
566 }
567 _ => {}
568 }
569
570 pb.finish_and_clear();
571 Ok(())
572}
573
574pub fn replace_sid_members(
576 vec_groups: &mut [Group],
577 dn_sid: &HashMap<String, String>,
578 sid_type: &HashMap<String, String>,
579 vec_trusts: &[Trust],
580) -> Result<(), Box<dyn Error>> {
581 let total = vec_groups.len();
583 let pb = ProgressBar::new(total as u64);
584
585 let default_sid = "NULL".to_string();
587 let default_type = "Group".to_string();
588
589 for (count, group) in vec_groups.iter_mut().enumerate() {
591 if count % (total / 100).max(1) == 0 {
593 pb.set_position(count as u64);
594 }
595
596 for member in group.members_mut() {
598 let member_dn = member.object_identifier();
599
600 let sid = dn_sid.get(member_dn).unwrap_or(&default_sid);
602 if sid == "NULL" {
603 let generated_sid = sid_maker_from_another_domain(vec_trusts, member_dn)?;
605 *member.object_identifier_mut() = generated_sid.to_owned();
606 *member.object_type_mut() = default_type.clone();
607 } else {
608 let type_object = sid_type.get(sid).unwrap_or(&default_type).to_owned();
610 *member.object_identifier_mut() = sid.to_owned();
611 *member.object_type_mut() = type_object;
612 }
613 }
614 }
615
616 pb.finish_and_clear();
617 Ok(())
618}
619
620fn sid_maker_from_another_domain(
622 vec_trusts: &[Trust],
623 object_identifier: &String,
624) -> Result<String, Box<dyn Error>> {
625 let sid_regex = Regex::new(r"S-[0-9]+-[0-9]+-[0-9]+(?:-[0-9]+)+")?;
627
628 for trust in vec_trusts {
630 let ldap_dc = prepare_ldap_dc(trust.target_domain_name());
631 if object_identifier.contains(&ldap_dc[0]) {
632 let id = get_id_from_objectidentifier(object_identifier)?;
633 return Ok(format!("{}{}", trust.target_domain_name(), id))
634 }
635 }
636
637 if object_identifier.contains("CN=S-") {
639 if let Some(capture) = sid_regex.captures(object_identifier).and_then(|cap| cap.get(0)) {
640 return Ok(capture.as_str().to_owned())
641 }
642 }
643
644 Ok(object_identifier.to_string())
646}
647
648fn get_id_from_objectidentifier(
651 object_identifier: &str
652) -> Result<String, Box<dyn Error>> {
653
654 const NAME_TO_RID: [(&str, &str); 16] = [
656 ("DOMAIN ADMINS", "-512"),
657 ("ADMINISTRATEURS DU DOMAINE", "-512"),
658 ("DOMAIN USERS", "-513"),
659 ("UTILISATEURS DU DOMAINE", "-513"),
660 ("DOMAIN GUESTS", "-514"),
661 ("INVITES DE DOMAINE", "-514"),
662 ("DOMAIN COMPUTERS", "-515"),
663 ("ORDINATEURS DE DOMAINE", "-515"),
664 ("DOMAIN CONTROLLERS", "-516"),
665 ("CONTRÔLEURS DE DOMAINE", "-516"),
666 ("CERT PUBLISHERS", "-517"),
667 ("EDITEURS DE CERTIFICATS", "-517"),
668 ("SCHEMA ADMINS", "-518"),
669 ("ADMINISTRATEURS DU SCHEMA", "-518"),
670 ("ENTERPRISE ADMINS", "-519"),
671 ("ADMINISTRATEURS DE L'ENTREPRISE", "-519"),
672 ];
673
674 for (name, rid) in NAME_TO_RID.iter() {
676 if object_identifier.contains(name) {
677 return Ok(rid.to_string())
678 }
679 }
680
681 Ok("NULL_ID1".to_string())
683}
684
685pub fn add_trustdomain(
687 vec_domains: &mut Vec<Domain>,
688 vec_trusts: &mut [Trust]
689) -> Result<(), Box<dyn Error>> {
690 if !&vec_trusts[0].target_domain_sid().to_string().contains("SID") {
691 let mut trusts: Vec<Trust> = Vec::new();
692 for trust in vec_trusts {
693 trusts.push(trust.to_owned());
694 let mut new_domain = Domain::new();
695 *new_domain.object_identifier_mut() = trust.target_domain_sid().to_string();
696 *new_domain.properties_mut().name_mut() = trust.target_domain_name().to_string();
697 *new_domain.properties_mut().domain_mut() = trust.target_domain_name().to_string();
698 *new_domain.properties_mut().distinguishedname_mut() = domain_to_dc(trust.target_domain_name());
699 *new_domain.properties_mut().highvalue_mut() = true;
700 vec_domains.push(new_domain);
701 }
702 *vec_domains[0].trusts_mut() = trusts.to_owned();
703 }
704 Ok(())
705}
706
707pub fn add_type_for_ace<T: LdapObject>(
709 object: &mut [T],
710 sid_type: &HashMap<String, String>,
711) -> Result<(), Box<dyn Error>> {
712 let total = object.len();
714 let pb = ProgressBar::new(total as u64);
715
716 let default_type = "Group".to_string();
718
719 for (count, obj) in object.iter_mut().enumerate() {
721 if count % (total / 100).max(1) == 0 {
723 pb.set_position(count as u64);
724 }
725
726 for ace in obj.get_aces_mut() {
728 let type_object = sid_type
730 .get(ace.principal_sid())
731 .unwrap_or(&default_type)
732 .clone();
733
734 *ace.principal_type_mut() = type_object;
736 }
737 }
738
739 pb.finish_and_clear();
740 Ok(())
741}
742
743pub fn add_type_for_allowtedtoact(
745 computer: &mut [Computer],
746 sid_type: &HashMap<String, String>,
747) -> Result<(), Box<dyn Error>> {
748 let total = computer.len();
750 let pb = ProgressBar::new(total as u64);
751
752 let default_type = "Computer".to_string();
754
755 for (count, comp) in computer.iter_mut().enumerate() {
757 if count % (total / 100).max(1) == 0 {
759 pb.set_position(count as u64);
760 }
761
762 for allowed in comp.allowed_to_act_mut() {
764 let type_object = sid_type
765 .get(allowed.object_identifier())
766 .unwrap_or(&default_type)
767 .clone();
768
769 *allowed.object_type_mut() = type_object;
770 }
771 }
772
773 pb.finish_and_clear();
774 Ok(())
775}
776
777pub fn add_contained_by_for<T: LdapObject>(
779 vec_replaced: &mut [T],
780 dn_sid: &HashMap<String, String>,
781 sid_type: &HashMap<String, String>,
782) -> Result<(), Box<dyn Error>> {
783 let total = vec_replaced.len();
785 let pb = ProgressBar::new(total as u64);
786
787 let default_type = "Group".to_string();
789
790 for (count, object) in vec_replaced.iter_mut().enumerate() {
791 if count % (total / 100).max(1) == 0 {
793 pb.set_position(count as u64);
794 }
795
796 let sid = object.get_object_identifier();
798 let dn = dn_sid.iter().find_map(|(key, value)| if value == sid { Some(key) } else { None });
799
800 if let Some(dn) = dn {
801 let otype = sid_type.get(sid).unwrap_or(&default_type);
802
803 if otype != "Domain" {
804 let cn_name = get_cn_object_name_from_full_distinguishedname(dn);
806 let contained_by_name = get_contained_by_name_from_distinguishedname(&cn_name, dn);
807
808 if let Some(sid_contained_by) = dn_sid.get(&contained_by_name) {
810 let type_contained_by = sid_type.get(sid_contained_by).unwrap_or(&default_type);
811
812 let mut contained_by = Member::new();
814 *contained_by.object_identifier_mut() = sid_contained_by.to_string();
815 *contained_by.object_type_mut() = type_contained_by.to_string();
816 object.set_contained_by(Some(contained_by));
817 }
818 }
819 }
820 }
821
822 pb.finish_and_clear();
823 Ok(())
824}
825
826pub fn get_name_from_full_distinguishedname(dn_object: &str) -> String {
828 trace!("get_name_from_full_distinguishedname() {:?}",&dn_object);
831 let split1 = dn_object.split(",");
832 let vec1 = split1.collect::<Vec<&str>>();
833 let split2 = vec1[0].split("=");
834 let vec2 = split2.collect::<Vec<&str>>();
835 let name = vec2[1].to_owned();
836 name
838}
839
840fn get_cn_object_name_from_full_distinguishedname(dn_object: &String) -> String {
842 let name = dn_object.to_owned();
845 let split = name.split(",");
846 let vec = split.collect::<Vec<&str>>();
847 let name = vec[0].to_owned();
848 name
850}
851
852fn get_contained_by_name_from_distinguishedname(cn_name: &str, dn_object: &str) -> String {
854 let name = format!("{},",cn_name);
857 let split = dn_object.split(&name);
858 let vec = split.collect::<Vec<&str>>();
859 let dn_contained_by = vec[1].to_owned();
860 dn_contained_by
862}
863
864#[cfg(test)]
867mod tests {
868
869 use crate::json::checker::common::{
870 get_name_from_full_distinguishedname,
871 get_cn_object_name_from_full_distinguishedname,
872 get_contained_by_name_from_distinguishedname
873 };
874
875 #[test]
876 #[rustfmt::skip]
877 pub fn test_get_name_from_full_distinguishedname() {
878 let dn_object = "CN=G0H4N,CN=USERS,DC=ESSOS,DC=LOCAL".to_string();
881 let cn_name = get_name_from_full_distinguishedname(&dn_object);
882 println!("dn_object: {:?}",dn_object);
883 println!("cn_name: {:?}",cn_name);
884 assert_eq!(cn_name, "G0H4N".to_string());
885 }
886
887 #[test]
888 #[rustfmt::skip]
889 pub fn test_get_cn_object_name_from_full_distinguishedname() {
890 let dn_object = "CN=G0H4N,CN=USERS,DC=ESSOS,DC=LOCAL".to_string();
893 let cn_name = get_cn_object_name_from_full_distinguishedname(&dn_object);
894 println!("dn_object: {:?}",dn_object);
895 println!("cn_name: {:?}",cn_name);
896 assert_eq!(cn_name, "CN=G0H4N".to_string());
897 }
898
899 #[test]
900 #[rustfmt::skip]
901 pub fn test_get_contained_by_name_from_name() {
902 let dn_object = "CN=G0H4N,CN=USERS,DC=ESSOS,DC=LOCAL".to_string();
905 let cn_name = "CN=G0H4N".to_string();
906 let contained_by_dn = get_contained_by_name_from_distinguishedname(&cn_name, &dn_object);
907 println!("dn_object: {:?}",dn_object);
908 println!("contained_by_dn: {:?}",contained_by_dn);
909 assert_eq!(contained_by_dn, "CN=USERS,DC=ESSOS,DC=LOCAL".to_string());
910 }
911}