1
2use colored::Colorize;
3use ldap3::SearchEntry;
4use log::{info, debug, trace, error};
5use regex::Regex;
6use serde_json::json;
7use std::collections::HashMap;
8use x509_parser::prelude::*;
9
10use crate::enums::acl::{parse_ntsecuritydescriptor,parse_gmsa};
11use crate::enums::date::{convert_timestamp,string_to_epoch};
12use crate::enums::forestlevel::get_forest_level;
13use crate::enums::gplink::parse_gplink;
14use crate::enums::secdesc::LdapSid;
15use crate::enums::sid::{decode_guid, objectsid_to_vec8, sid_maker};
16use crate::enums::spntasks::check_spn;
17use crate::enums::uacflags::get_flag;
18use crate::enums::trusts::get_trust_flag;
19
20use crate::json::templates::bh_41::*;
21pub fn parse_user(
44 result: SearchEntry,
45 domain: &String,
46 dn_sid: &mut HashMap<String, String>,
47 sid_type: &mut HashMap<String, String>,
48 adcs: bool,
49) -> serde_json::value::Value {
50
51 let result_dn: String;
52 result_dn = result.dn.to_uppercase();
53
54 let result_attrs: HashMap<String, Vec<String>>;
55 result_attrs = result.attrs;
56
57 let result_bin: HashMap<String, Vec<Vec<u8>>>;
58 result_bin = result.bin_attrs;
59
60 debug!("Parse user: {}", result_dn);
61 let mut user_json = prepare_user_json_template();
71
72 user_json["Properties"]["domain"] = domain.to_uppercase().into();
74 user_json["Properties"]["distinguishedname"] = result_dn.into();
75
76 let mut group_id: String = "".to_owned();
78 for (key, value) in &result_attrs {
79 match key.as_str() {
80 "sAMAccountName" => {
81 let name = &value[0];
82 let email = format!("{}@{}",name.to_owned(),domain);
83 user_json["Properties"]["name"] = email.to_uppercase().into();
84 user_json["Properties"]["samaccountname"] = name.to_owned().into();
85 }
86 "description" => {
87 user_json["Properties"]["description"] = value[0].to_owned().into();
88 }
89 "mail" => {
90 user_json["Properties"]["email"] = value[0].to_owned().into();
91 }
92 "title" => {
93 user_json["Properties"]["title"] = value[0].to_owned().into();
94 }
95 "userPassword" => {
96 user_json["Properties"]["userpassword"] = value[0].to_owned().into();
97 }
98 "unixUserPassword" => {
99 user_json["Properties"]["unixpassword"] = value[0].to_owned().into();
100 }
101 "unicodepwd" => {
102 user_json["Properties"]["unicodepassword"] = value[0].to_owned().into();
103 }
104 "sfupassword" => {
105 }
107 "displayName" => {
108 user_json["Properties"]["displayname"] = value[0].to_owned().into();
109 }
110 "adminCount" => {
111 let isadmin = &value[0];
112 let mut admincount = false;
113 if isadmin == "1" {
114 admincount = true;
115 }
116 user_json["Properties"]["admincount"] = admincount.into();
117 }
118 "homeDirectory" => {
119 user_json["Properties"]["homedirectory"] = value[0].to_owned().into();
120 }
121 "scriptpath" => {
122 user_json["Properties"]["logonscript"] = value[0].to_owned().into();
123 }
124 "userAccountControl" => {
125 let uac = &value[0].parse::<u32>().unwrap_or(0);
126 let uac_flags = get_flag(*uac);
127 for flag in uac_flags {
129 if flag.contains("AccountDisable") {
130 user_json["Properties"]["enabled"] = false.into();
131 };
132 if flag.contains("PasswordNotRequired") {
134 user_json["Properties"]["passwordnotreqd"] = true.into();
135 };
136 if flag.contains("DontExpirePassword") {
137 user_json["Properties"]["pwdneverexpires"] = true.into();
138 };
139 if flag.contains("DontReqPreauth") {
140 user_json["Properties"]["dontreqpreauth"] = true.into();
141 };
142 if flag.contains("TrustedForDelegation") {
144 user_json["Properties"]["unconstraineddelegation"] = true.into();
145 };
146 if flag.contains("NotDelegated") {
147 user_json["Properties"]["sensitive"] = true.into();
148 };
149 if flag.contains("TrustedToAuthForDelegation") {
151 user_json["Properties"]["trustedtoauth"] = true.into();
152 };
153 }
154 }
155 "msDS-AllowedToDelegateTo" => {
156 user_json["Properties"]["allowedtodelegate"] = value.to_owned().into();
159 let mut vec_members: Vec<serde_json::value::Value> = Vec::new();
161 let mut allowed_to_delegate = prepare_member_json_template();
162 for objet in value {
163 let split = objet.split("/");
164 let fqdn = split.collect::<Vec<&str>>()[1];
165 let mut checker = false;
166 for member in &vec_members {
167 if member["ObjectIdentifier"].to_string().contains(fqdn.to_uppercase().as_str()) {
168 checker = true;
169 }
170 }
171 if !checker {
172 allowed_to_delegate["ObjectIdentifier"] = fqdn.to_uppercase().to_owned().to_uppercase().into();
173 allowed_to_delegate["ObjectType"] = "Computer".to_owned().into();
174 vec_members.push(allowed_to_delegate.to_owned());
175 }
176 }
177 user_json["AllowedToDelegate"] = vec_members.to_owned().into();
178 }
179 "lastLogon" => {
180 let lastlogon = &value[0].parse::<i64>().unwrap_or(0);
181 if lastlogon.is_positive() {
182 let epoch = convert_timestamp(*lastlogon);
183 user_json["Properties"]["lastlogon"] = epoch.into();
184 }
185 }
186 "lastLogonTimestamp" => {
187 let lastlogontimestamp = &value[0].parse::<i64>().unwrap_or(0);
188 if lastlogontimestamp.is_positive() {
189 let epoch = convert_timestamp(*lastlogontimestamp);
190 user_json["Properties"]["lastlogontimestamp"] = epoch.into();
191 }
192 }
193 "pwdLastSet" => {
194 let pwdlastset = &value[0].parse::<i64>().unwrap_or(0);
195 if pwdlastset.is_positive() {
196 let epoch = convert_timestamp(*pwdlastset);
197 user_json["Properties"]["pwdlastset"] = epoch.into();
198 }
199 }
200 "whenCreated" => {
201 let epoch = string_to_epoch(&value[0]);
202 if epoch.is_positive() {
203 user_json["Properties"]["whencreated"] = epoch.into();
204 }
205 }
206 "servicePrincipalName" => {
207 let mut result: Vec<String> = Vec::new();
208 let mut targets: Vec<serde_json::value::Value> = Vec::new();
210
211 let mut added: bool = false;
212 for v in value {
213 result.push(v.to_owned());
214 let target = check_spn(v).to_owned();
216 if target.to_string().contains("Port") && !added {
217 targets.push(target.to_owned());
218 added = true;
219 }
220 }
221 user_json["Properties"]["serviceprincipalnames"] = result.to_owned().into();
222 user_json["Properties"]["hasspn"] = true.into();
223 user_json["SPNTargets"] = targets.into();
224 }
225 "primaryGroupID" => {
226 group_id = value[0].to_owned();
227 }
228 "IsDeleted" => {
229 user_json["IsDeleted"] = true.into();
233 }
234 _ => {}
235 }
236 }
237
238 let mut sid: String = "".to_owned();
240 for (key, value) in &result_bin {
241 match key.as_str() {
242 "objectSid" => {
243 sid = sid_maker(LdapSid::parse(&value[0]).unwrap().1, domain);
244 user_json["ObjectIdentifier"] = sid.to_owned().into();
245
246 let re = Regex::new(r"^S-[0-9]{1}-[0-9]{1}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}").unwrap();
247 for domain_sid in re.captures_iter(&sid)
248 {
249 user_json["Properties"]["domainsid"] = domain_sid[0].to_owned().to_string().into();
250 }
251 }
252 "nTSecurityDescriptor" => {
253 let entry_type = "user".to_string();
255 let relations_ace = parse_ntsecuritydescriptor(
257 &mut user_json,
258 &value[0],
259 entry_type,
260 &result_attrs,
261 &result_bin,
262 &domain,
263 );
264 user_json["Aces"] = relations_ace.into();
265 }
266 "sIDHistory" => {
267 let mut list_sid_history: Vec<String> = Vec::new();
270 for bsid in value {
271 debug!("sIDHistory: {:?}", &bsid);
272 list_sid_history.push(sid_maker(LdapSid::parse(&bsid).unwrap().1, domain));
273 }
275 user_json["Properties"]["sidhistory"] = list_sid_history.into();
276 }
277 "msDS-GroupMSAMembership" => {
278 let entry_type = "user".to_string();
279 let mut relations_ace = parse_ntsecuritydescriptor(
281 &mut user_json,
282 &value[0],
283 entry_type,
284 &result_attrs,
285 &result_bin,
286 &domain,
287 );
288 let mut relations_ace_b = user_json["Aces"].as_array_mut().unwrap();
290 trace!("msDS-GroupMSAMembership ACE ? {:?}", relations_ace);
291 parse_gmsa(&mut relations_ace, &mut relations_ace_b);
293 }
295 "userCertificate" => {
296 if !adcs {
299 let res = X509Certificate::from_der(&value[0]);
300 match res {
301 Ok((_rem, cert)) => {
302
303 info!("ADCS found {}, use {} args to collect the certificate templates and certificate authority.",cert.issuer().to_string().replace(" ","").bold().green(),&"--adcs".bold().yellow());
304 },
305 _ => error!("CA x509 certificate parsing failed: {:?}", res),
306
307 }
308 }
309 }
310 _ => {}
311 }
312 }
313
314 #[allow(irrefutable_let_patterns)]
316 if let id = group_id {
317 let re = Regex::new(r"S-.*-").unwrap();
318 let part1 = re.find(&sid).unwrap();
319 let mut primary_group_id: String = "".to_owned();
320 primary_group_id.push_str(&part1.as_str());
321 primary_group_id.push_str(&id.as_str());
322 user_json["PrimaryGroupSID"] = primary_group_id.to_owned().into();
323 }
324
325 dn_sid.insert(
327 user_json["Properties"]["distinguishedname"]
328 .as_str()
329 .unwrap()
330 .to_string(),
331 user_json["ObjectIdentifier"].as_str().unwrap().to_string(),
332 );
333 sid_type.insert(
335 user_json["ObjectIdentifier"].as_str().unwrap().to_string(),
336 "User".to_string(),
337 );
338
339 return user_json;
340}
341
342pub fn parse_group(
350 result: SearchEntry,
351 domain: &String,
352 dn_sid: &mut HashMap<String, String>,
353 sid_type: &mut HashMap<String, String>,
354) -> serde_json::value::Value {
355 let result_dn: String;
356 result_dn = result.dn.to_uppercase();
357
358 let result_attrs: HashMap<String, Vec<String>>;
359 result_attrs = result.attrs;
360
361 let result_bin: HashMap<String, Vec<Vec<u8>>>;
362 result_bin = result.bin_attrs;
363
364 debug!("Parse group: {}", result_dn);
365 let mut group_json = prepare_group_json_template();
375
376 let mut vec_members: Vec<serde_json::value::Value> = Vec::new();
378 let mut member_json = prepare_member_json_template();
379
380 group_json["Properties"]["domain"] = domain.to_uppercase().into();
382 group_json["Properties"]["distinguishedname"] = result_dn.into();
383
384 #[allow(unused_assignments)]
385 let mut sid: String = "".to_owned();
386 for (key, value) in &result_attrs {
388 match key.as_str() {
389 "name" => {
390 let name = &value[0];
391 let email = format!("{}@{}",name.to_owned(),domain);
392 group_json["Properties"]["name"] = email.to_uppercase().into();
393 }
394 "description" => {
395 group_json["Properties"]["description"] = value[0].to_owned().into();
396 }
397 "adminCount" => {
398 let isadmin = &value[0];
399 let mut admincount = false;
400 if isadmin == "1" {
401 admincount = true;
402 }
403 group_json["Properties"]["admincount"] = admincount.into();
404 }
405 "sAMAccountName" => {
406 group_json["Properties"]["samaccountname"] = value[0].to_owned().into();
407 }
408 "member" => {
409 if value.len() > 0 {
410 for member in value {
411 member_json["ObjectIdentifier"] = member.to_owned().to_uppercase().into();
412 if member_json["ObjectIdentifier"].as_str().unwrap_or("SID") != "SID" {
413 vec_members.push(member_json.to_owned());
414 }
415 }
416 group_json["Members"] = vec_members.to_owned().into();
417 }
418 }
419 "objectSid" => {
420 let vec_sid = objectsid_to_vec8(&value[0]);
422 sid = sid_maker(LdapSid::parse(&vec_sid).unwrap().1, domain);
423 group_json["ObjectIdentifier"] = sid.to_owned().into();
424
425 if sid.ends_with("-512")
433 || sid.ends_with("-516")
434 || sid.ends_with("-519")
435 || sid.ends_with("-520")
436 {
437 group_json["Properties"]["highvalue"] = true.into();
438 }
439 else if sid.ends_with("S-1-5-32-544")
440 || sid.ends_with("S-1-5-32-548")
441 || sid.ends_with("S-1-5-32-549")
442 || sid.ends_with("S-1-5-32-550")
443 || sid.ends_with("S-1-5-32-551")
444 {
445 group_json["Properties"]["highvalue"] = true.into();
446 }
447 else {
448 group_json["Properties"]["highvalue"] = false.into();
449 }
450 }
451 "whenCreated" => {
452 let epoch = string_to_epoch(&value[0]);
453 if epoch.is_positive() {
454 group_json["Properties"]["whencreated"] = epoch.into();
455 }
456 }
457 "IsDeleted" => {
458 group_json["IsDeleted"] = true.into();
459 }
460 _ => {}
461 }
462 }
463
464 for (key, value) in &result_bin {
466 match key.as_str() {
467 "objectSid" => {
468 sid = sid_maker(LdapSid::parse(&value[0]).unwrap().1, domain);
470 group_json["ObjectIdentifier"] = sid.to_owned().into();
471
472 let re = Regex::new(r"^S-[0-9]{1}-[0-9]{1}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}").unwrap();
473 for domain_sid in re.captures_iter(&sid)
474 {
475 group_json["Properties"]["domainsid"] = domain_sid[0].to_owned().to_string().into();
476 }
477
478 if sid.ends_with("-512")
480 || sid.ends_with("-516")
481 || sid.ends_with("-519")
482 || sid.ends_with("-520")
483 {
484 group_json["Properties"]["highvalue"] = true.into();
485 }
486 else if sid.ends_with("S-1-5-32-544")
487 || sid.ends_with("S-1-5-32-548")
488 || sid.ends_with("S-1-5-32-549")
489 || sid.ends_with("S-1-5-32-550")
490 || sid.ends_with("S-1-5-32-551")
491 {
492 group_json["Properties"]["highvalue"] = true.into();
493 }
494 else {
495 group_json["Properties"]["highvalue"] = false.into();
496 }
497 }
498 "nTSecurityDescriptor" => {
499 let entry_type = "group".to_string();
501 let relations_ace = parse_ntsecuritydescriptor(
503 &mut group_json,
504 &value[0],
505 entry_type,
506 &result_attrs,
507 &result_bin,
508 &domain,
509 );
510 group_json["Aces"] = relations_ace.into();
511 }
512 _ => {}
513 }
514 }
515
516 dn_sid.insert(
518 group_json["Properties"]["distinguishedname"]
519 .as_str()
520 .unwrap()
521 .to_string(),
522 group_json["ObjectIdentifier"].as_str().unwrap().to_string(),
523 );
524 sid_type.insert(
526 group_json["ObjectIdentifier"].as_str().unwrap().to_string(),
527 "Group".to_string(),
528 );
529
530 return group_json;
531}
532
533pub fn parse_computer(
541 result: SearchEntry,
542 domain: &String,
543 dn_sid: &mut HashMap<String, String>,
544 sid_type: &mut HashMap<String, String>,
545 fqdn_sid: &mut HashMap<String, String>,
546 fqdn_ip: &mut HashMap<String, String>,
547) -> serde_json::value::Value {
548 let result_dn: String;
549 result_dn = result.dn.to_uppercase();
550
551 let result_attrs: HashMap<String, Vec<String>>;
552 result_attrs = result.attrs;
553
554 let result_bin: HashMap<String, Vec<Vec<u8>>>;
555 result_bin = result.bin_attrs;
556
557 debug!("Parse computer: {}", result_dn);
558 let mut computer_json = prepare_computer_json_template();
568
569 let mut vec_localadmins: Vec<serde_json::value::Value> = Vec::new();
570 let mut localadmin_json = json!({
571 "MemberId": "SID",
572 "MemberType": "Type"
573 });
574
575 computer_json["Properties"]["domain"] = domain.to_uppercase().into();
577 computer_json["Properties"]["distinguishedname"] = result_dn.into();
578 let mut sid: String = "".to_owned();
579 let mut group_id: String = "".to_owned();
580 for (key, value) in &result_attrs {
582 match key.as_str() {
583 "name" => {
584 let name = &value[0];
585 let email = format!("{}@{}",name.to_owned(),domain);
586 computer_json["Properties"]["name"] = email.to_uppercase().into();
587 }
588 "sAMAccountName" => {
589 computer_json["Properties"]["samaccountname"] = value[0].to_owned().into();
590 }
591 "dNSHostName" => {
592 computer_json["Properties"]["name"] = value[0].to_uppercase().into();
593 }
594 "description" => {
595 computer_json["Properties"]["description"] = value[0].to_owned().into();
596 }
597 "operatingSystem" => {
598 computer_json["Properties"]["operatingsystem"] = value[0].to_owned().into();
599 }
600 "member" => {
611 for member in value {
612 localadmin_json["MemberId"] = member.to_owned().into();
613 vec_localadmins.push(localadmin_json.to_owned());
614 }
615 computer_json["Members"] = vec_localadmins.to_owned().into();
616 }
617 "lastLogon" => {
618 let lastlogon = &value[0].parse::<i64>().unwrap_or(0);
619 if lastlogon.is_positive() {
620 let epoch = convert_timestamp(*lastlogon);
621 computer_json["Properties"]["lastlogon"] = epoch.into();
622 }
623 }
624 "lastLogonTimestamp" => {
625 let lastlogontimestamp = &value[0].parse::<i64>().unwrap_or(0);
626 if lastlogontimestamp.is_positive() {
627 let epoch = convert_timestamp(*lastlogontimestamp);
628 computer_json["Properties"]["lastlogontimestamp"] = epoch.into();
629 }
630 }
631 "pwdLastSet" => {
632 let pwdlastset = &value[0].parse::<i64>().unwrap_or(0);
633 if pwdlastset.is_positive() {
634 let epoch = convert_timestamp(*pwdlastset);
635 computer_json["Properties"]["pwdlastset"] = epoch.into();
636 }
637 }
638 "whenCreated" => {
639 let epoch = string_to_epoch(&value[0]);
640 if epoch.is_positive() {
641 computer_json["Properties"]["whencreated"] = epoch.into();
642 }
643 }
644 "servicePrincipalName" => {
645 let mut result: Vec<String> = Vec::new();
647 for value in &result_attrs["servicePrincipalName"] {
648 result.push(value.to_owned());
649 }
650 computer_json["Properties"]["serviceprincipalnames"] = result.to_owned().into();
651 }
652 "userAccountControl" => {
653 let uac = &value[0].parse::<u32>().unwrap();
655 let uac_flags = get_flag(*uac);
656 for flag in uac_flags {
658 if flag.contains("AccountDisable") {
659 computer_json["Properties"]["enabled"] = false.into();
660 };
661 if flag.contains("TrustedForDelegation") {
664 computer_json["Properties"]["unconstraineddelegation"] = true.into();
665 };
666 if flag.contains("TrustedToAuthForDelegation") {
668 computer_json["Properties"]["trustedtoauth"] = true.into();
669 };
670 }
671 }
672 "msDS-AllowedToDelegateTo" => {
673 computer_json["Properties"]["allowedtodelegate"] = value.to_owned().into();
676 let mut vec_members: Vec<serde_json::value::Value> = Vec::new();
678 let mut allowed_to_delegate = prepare_member_json_template();
679 for objet in value {
680 let split = objet.split("/");
681 let fqdn = split.collect::<Vec<&str>>()[1];
682 let mut checker = false;
683 for member in &vec_members {
684 if member["ObjectIdentifier"].to_string().contains(fqdn.to_uppercase().as_str()) {
685 checker = true;
686 }
687 }
688 if !checker {
689 allowed_to_delegate["ObjectIdentifier"] = fqdn.to_uppercase().to_owned().to_uppercase().into();
690 allowed_to_delegate["ObjectType"] = "Computer".to_owned().into();
691 vec_members.push(allowed_to_delegate.to_owned());
692 }
693 }
694 computer_json["AllowedToDelegate"] = vec_members.to_owned().into();
695 }
696 "ms-Mcs-AdmPwd" => {
697 info!(
700 "Your user can read LAPS password on {}: {}",
701 &result_attrs["name"][0].yellow().bold(),
702 &result_attrs["ms-Mcs-AdmPwd"][0].yellow().bold()
703 );
704 computer_json["Properties"]["haslaps"] = true.into();
705 }
706 "ms-Mcs-AdmPwdExpirationTime" => {
707 computer_json["Properties"]["haslaps"] = true.into();
709 }
710 "primaryGroupID" => {
711 group_id = value[0].to_owned();
712 }
713 "IsDeleted" => {
714 computer_json["IsDeleted"] = true.into();
715 }
716 _ => {}
717 }
718 }
719 for (key, value) in &result_bin {
721 match key.as_str() {
722 "objectSid" => {
723 sid = sid_maker(LdapSid::parse(&value[0]).unwrap().1, domain);
725 computer_json["ObjectIdentifier"] = sid.to_owned().into();
726
727 let re = Regex::new(r"^S-[0-9]{1}-[0-9]{1}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}").unwrap();
728 for domain_sid in re.captures_iter(&sid)
729 {
730 computer_json["Properties"]["domainsid"] = domain_sid[0].to_owned().to_string().into();
731 }
732
733 }
734 "nTSecurityDescriptor" => {
735 let entry_type = "computer".to_string();
737 let relations_ace = parse_ntsecuritydescriptor(
739 &mut computer_json,
740 &value[0],
741 entry_type,
742 &result_attrs,
743 &result_bin,
744 &domain,
745 );
746 computer_json["Aces"] = relations_ace.into();
747 }
748 "msDS-AllowedToActOnBehalfOfOtherIdentity" => {
749 let entry_type = "computer".to_string();
752 let relations_ace = parse_ntsecuritydescriptor(
754 &mut computer_json,
755 &value[0],
756 entry_type,
757 &result_attrs,
758 &result_bin,
759 &domain,
760 );
761 let mut vec_members: Vec<serde_json::value::Value> = Vec::new();
762 let mut allowed_to_act = prepare_member_json_template();
763 for delegated in relations_ace {
764 if delegated["RightName"] == "GenericAll" {
767 allowed_to_act["ObjectIdentifier"] = delegated["PrincipalSID"].as_str().unwrap().to_string().into();
768 vec_members.push(allowed_to_act.to_owned());
769 continue
770 }
771 }
772 computer_json["AllowedToAct"] = vec_members.into();
773 }
774 _ => {}
775 }
776 }
777 #[allow(irrefutable_let_patterns)]
779 if let id = group_id {
780 let re = Regex::new(r"S-.*-").unwrap();
781 let part1 = re.find(&sid).unwrap();
782 let mut primary_group_id: String = "".to_owned();
783 primary_group_id.push_str(&part1.as_str());
784 primary_group_id.push_str(&id.as_str());
785 computer_json["PrimaryGroupSID"] = primary_group_id.to_owned().into();
786 }
787
788 dn_sid.insert(
790 computer_json["Properties"]["distinguishedname"]
791 .as_str()
792 .unwrap()
793 .to_string(),
794 computer_json["ObjectIdentifier"]
795 .as_str()
796 .unwrap()
797 .to_string(),
798 );
799 sid_type.insert(
801 computer_json["ObjectIdentifier"]
802 .as_str()
803 .unwrap()
804 .to_string(),
805 "Computer".to_string(),
806 );
807
808 fqdn_sid.insert(
809 computer_json["Properties"]["name"]
810 .as_str()
811 .unwrap()
812 .to_string(),
813 computer_json["ObjectIdentifier"]
814 .as_str()
815 .unwrap()
816 .to_string(),
817 );
818
819 fqdn_ip.insert(
820 computer_json["Properties"]["name"]
821 .as_str()
822 .unwrap()
823 .to_string(),
824 "".to_string(),
825 );
826
827 return computer_json;
828}
829
830pub fn parse_ou(
838 result: SearchEntry,
839 domain: &String,
840 dn_sid: &mut HashMap<String, String>,
841 sid_type: &mut HashMap<String, String>,
842) -> serde_json::value::Value {
843
844 let result_dn: String;
845 result_dn = result.dn.to_uppercase();
846
847 let result_attrs: HashMap<String, Vec<String>>;
848 result_attrs = result.attrs;
849
850 let result_bin: HashMap<String, Vec<Vec<u8>>>;
851 result_bin = result.bin_attrs;
852
853 debug!("Parse OU: {}", result_dn);
855 let mut ou_json = prepare_ou_json_template();
865
866 ou_json["Properties"]["domain"] = domain.to_uppercase().into();
867 ou_json["Properties"]["distinguishedname"] = result_dn.into();
868 for (key, value) in &result_attrs {
870 match key.as_str() {
871 "name" => {
872 let name = &value[0];
873 let email = format!("{}@{}",name.to_owned(),domain);
874 ou_json["Properties"]["name"] = email.to_uppercase().into();
875 }
876 "description" => {
877 ou_json["Properties"]["description"] = value[0].to_owned().into();
878 }
879 "whenCreated" => {
880 let epoch = string_to_epoch(&value[0]);
881 if epoch.is_positive() {
882 ou_json["Properties"]["whencreated"] = epoch.into();
883 }
884 }
885 "gPLink" => {
886 ou_json["Links"] = parse_gplink(value[0].to_string()).into();
887 }
888 "IsDeleted" => {
889 ou_json["IsDeleted"] = true.into();
890 }
891 _ => {}
892 }
893 }
894
895 #[allow(unused_assignments)]
897 let mut guid: String = "".to_owned();
898 for (key, value) in &result_bin {
899 match key.as_str() {
900 "objectGUID" => {
901 guid = decode_guid(&value[0]);
903 ou_json["ObjectIdentifier"] = guid.to_owned().into();
904 }
905 "nTSecurityDescriptor" => {
906 trace!("nTSecurityDescriptor ACES ACLS ?");
907 let entry_type = "ou".to_string();
909 let relations_ace = parse_ntsecuritydescriptor(
911 &mut ou_json,
912 &value[0],
913 entry_type,
914 &result_attrs,
915 &result_bin,
916 &domain,
917 );
918 ou_json["Aces"] = relations_ace.into();
919 }
920 _ => {}
921 }
922 }
923 dn_sid.insert(
925 ou_json["Properties"]["distinguishedname"]
926 .as_str()
927 .unwrap()
928 .to_string(),
929 ou_json["ObjectIdentifier"].as_str().unwrap().to_string(),
930 );
931 sid_type.insert(
933 ou_json["ObjectIdentifier"].as_str().unwrap().to_string(),
934 "OU".to_string(),
935 );
936
937 return ou_json;
938}
939pub fn parse_domain(
947 result: SearchEntry,
948 domain: &String,
949 dn_sid: &mut HashMap<String, String>,
950 sid_type: &mut HashMap<String, String>,
951) -> serde_json::value::Value {
952
953 let _result_dn: String;
954 _result_dn = result.dn.to_uppercase();
955
956 let result_attrs: HashMap<String, Vec<String>>;
957 result_attrs = result.attrs;
958
959 let result_bin: HashMap<String, Vec<Vec<u8>>>;
960 result_bin = result.bin_attrs;
961
962 let mut domain_json = prepare_domain_json_template();
974
975 #[allow(unused_assignments)]
977 let mut sid: String = "".to_owned();
978 for (key, value) in &result_attrs {
980 match key.as_str() {
981 "distinguishedName" => {
982 domain_json["Properties"]["distinguishedname"] = value[0].to_owned().to_uppercase().into();
984 let split = value[0].split(",");
985 let vec = split.collect::<Vec<&str>>();
986 let first = vec[0].split("DC=");
987 let vec1 = first.collect::<Vec<&str>>();
988 let last = vec[1].split("DC=");
989 let vec2 = last.collect::<Vec<&str>>();
990 let mut name = "".to_string();
991 name.push_str(vec1[1]);
992 name.push_str(".");
993 name.push_str(vec2[1]);
994 domain_json["Properties"]["name"] = name.to_uppercase().into();
995 domain_json["Properties"]["domain"] = name.to_uppercase().into();
996 }
997 "msDS-Behavior-Version" => {
998 let level = get_forest_level(value[0].to_string());
999 domain_json["Properties"]["functionallevel"] = level.into();
1000 }
1001 "whenCreated" => {
1002 let epoch = string_to_epoch(&value[0]);
1003 if epoch.is_positive() {
1004 domain_json["Properties"]["whencreated"] = epoch.into();
1005 }
1006 }
1007 "gPLink" => {
1008 domain_json["Links"] = parse_gplink(value[0].to_string()).into();
1009 }
1010 "isCriticalSystemObject" => {
1011 let mut iscriticalsystemobject = false;
1012 if value[0].contains("TRUE") {
1013 iscriticalsystemobject = true;
1014 }
1015 domain_json["Properties"]["highvalue"] = iscriticalsystemobject.into();
1016 }
1017 "ms-DS-MachineAccountQuota" => {
1019 let machine_account_quota = value[0].parse::<i32>().unwrap_or(0);
1020 if machine_account_quota > 0 {
1021 info!("MachineAccountQuota: {}",machine_account_quota.to_string().yellow().bold());
1022 }
1023 }
1024 "IsDeleted" => {
1025 domain_json["IsDeleted"] = true.into();
1026 }
1027 _ => {}
1028 }
1029 }
1030 for (key, value) in &result_bin {
1032 match key.as_str() {
1033 "objectSid" => {
1034 sid = sid_maker(LdapSid::parse(&value[0]).unwrap().1, domain);
1036 domain_json["ObjectIdentifier"] = sid.to_owned().into();
1037
1038 let re = Regex::new(r"^S-[0-9]{1}-[0-9]{1}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}").unwrap();
1039 for domain_sid in re.captures_iter(&sid)
1040 {
1041 domain_json["Properties"]["domainsid"] = domain_sid[0].to_owned().to_string().into();
1042 }
1043 }
1044 "nTSecurityDescriptor" => {
1045 let entry_type = "domain".to_string();
1047 let relations_ace = parse_ntsecuritydescriptor(
1049 &mut domain_json,
1050 &value[0],
1051 entry_type,
1052 &result_attrs,
1053 &result_bin,
1054 &domain,
1055 );
1056 domain_json["Aces"] = relations_ace.into();
1057 }
1058 _ => {}
1059 }
1060 }
1061
1062 dn_sid.insert(
1064 domain_json["Properties"]["distinguishedname"]
1065 .as_str()
1066 .unwrap()
1067 .to_string(),
1068 domain_json["ObjectIdentifier"]
1069 .as_str()
1070 .unwrap()
1071 .to_string(),
1072 );
1073 sid_type.insert(
1075 domain_json["ObjectIdentifier"]
1076 .as_str()
1077 .unwrap()
1078 .to_string(),
1079 "Domain".to_string(),
1080 );
1081
1082 return domain_json;
1083}
1084pub fn parse_gpo(
1092 result: SearchEntry,
1093 domain: &String,
1094 dn_sid: &mut HashMap<String, String>,
1095 sid_type: &mut HashMap<String, String>,
1096) -> serde_json::value::Value {
1097
1098 let result_dn: String;
1099 result_dn = result.dn.to_uppercase();
1100
1101 let result_attrs: HashMap<String, Vec<String>>;
1102 result_attrs = result.attrs;
1103
1104 let result_bin: HashMap<String, Vec<Vec<u8>>>;
1105 result_bin = result.bin_attrs;
1106
1107 debug!("Parse gpo: {}", result_dn);
1109 let mut gpo_json = prepare_gpo_json_template();
1119 gpo_json["Properties"]["domain"] = domain.to_uppercase().into();
1120 gpo_json["Properties"]["distinguishedname"] = result_dn.into();
1121
1122 for (key, value) in &result_attrs {
1124 match key.as_str() {
1125 "displayName" => {
1126 let name = &value[0];
1127 let email = format!("{}@{}",name.to_owned(),domain);
1128 gpo_json["Properties"]["name"] = email.to_uppercase().into();
1129 }
1130 "description" => {
1131 gpo_json["Properties"]["description"] = value[0].to_owned().into();
1132 }
1133 "whenCreated" => {
1134 let epoch = string_to_epoch(&value[0]);
1135 if epoch.is_positive() {
1136 gpo_json["Properties"]["whencreated"] = epoch.into();
1137 }
1138 }
1139 "gPCFileSysPath" => {
1140 gpo_json["Properties"]["gpcpath"] = value[0].to_owned().into();
1141 }
1142 "IsDeleted" => {
1143 gpo_json["IsDeleted"] = true.into();
1144 }
1145 _ => {}
1146 }
1147 }
1148
1149 for (key, value) in &result_bin {
1151 match key.as_str() {
1152 "objectGUID" => {
1153 let guid = decode_guid(&value[0]);
1155 gpo_json["ObjectIdentifier"] = guid.to_owned().into();
1156 }
1157 "nTSecurityDescriptor" => {
1158 let entry_type = "gpo".to_string();
1160 let relations_ace = parse_ntsecuritydescriptor(
1162 &mut gpo_json,
1163 &value[0],
1164 entry_type,
1165 &result_attrs,
1166 &result_bin,
1167 &domain,
1168 );
1169 gpo_json["Aces"] = relations_ace.into();
1170 }
1171 _ => {}
1172 }
1173 }
1174
1175 dn_sid.insert(
1177 gpo_json["Properties"]["distinguishedname"]
1178 .as_str()
1179 .unwrap()
1180 .to_string(),
1181 gpo_json["ObjectIdentifier"].as_str().unwrap().to_string(),
1182 );
1183 sid_type.insert(
1185 gpo_json["ObjectIdentifier"].as_str().unwrap().to_string(),
1186 "Gpo".to_string(),
1187 );
1188
1189 return gpo_json;
1190}
1191pub fn parse_fsp(
1198 result: SearchEntry,
1199 domain: &String,
1200 dn_sid: &mut HashMap<String, String>,
1201 sid_type: &mut HashMap<String, String>,
1202) -> serde_json::value::Value {
1203
1204 let result_dn: String;
1205 result_dn = result.dn.to_uppercase();
1206
1207 let result_attrs: HashMap<String, Vec<String>>;
1208 result_attrs = result.attrs;
1209
1210 let _result_bin: HashMap<String, Vec<Vec<u8>>>;
1211 _result_bin = result.bin_attrs;
1212
1213 debug!("Parse ForeignSecurityPrincipal: {}", result_dn);
1215 let mut fsp_json = prepare_fsp_json_template();
1225 fsp_json["Properties"]["distinguishedname"] = result_dn.into();
1226
1227 #[allow(unused_assignments)]
1228 let mut sid: String = "".to_owned();
1229 for (key, value) in &result_attrs {
1231 match key.as_str() {
1232 "name" => {
1233 let name = format!("{}-{}",domain,&value[0]);
1234 fsp_json["Properties"]["name"] = name.to_uppercase().into();
1235
1236 let split = value[0].split("-");
1239 let vec = split.collect::<Vec<&str>>();
1240 let len = vec.len();
1241 let last = vec[len - 1].parse::<i32>().unwrap_or(0);
1242 if last >= 17 {
1243 fsp_json["Properties"]["type"] = "User".into();
1244 } else {
1245 fsp_json["Properties"]["type"] = "Group".into();
1246 }
1247 }
1248 "whenCreated" => {
1249 let epoch = string_to_epoch(&value[0]);
1250 if epoch.is_positive() {
1251 fsp_json["Properties"]["whencreated"] = epoch.into();
1252 }
1253 }
1254 "objectSid" => {
1255 let vec_sid = objectsid_to_vec8(&value[0]);
1257 sid = sid_maker(LdapSid::parse(&vec_sid).unwrap().1, domain);
1258 fsp_json["ObjectIdentifier"] = sid.to_owned().into();
1259
1260 let re = Regex::new(r"^S-[0-9]{1}-[0-9]{1}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}-[0-9]{1,}").unwrap();
1261 for domain_sid in re.captures_iter(&sid)
1262 {
1263 fsp_json["Properties"]["domainsid"] = domain_sid[0].to_owned().to_string().into();
1264 }
1265 }
1266 "IsDeleted" => {
1267 fsp_json["IsDeleted"] = true.into();
1268 }
1269 _ => {}
1270 }
1271 }
1272
1273 if fsp_json["ObjectIdentifier"].as_str().unwrap() != "SID" {
1275 dn_sid.insert(
1276 fsp_json["Properties"]["distinguishedname"]
1277 .as_str()
1278 .unwrap()
1279 .to_string(),
1280 fsp_json["ObjectIdentifier"].as_str().unwrap().to_string(),
1281 );
1282 sid_type.insert(
1284 fsp_json["ObjectIdentifier"].as_str().unwrap().to_string(),
1285 fsp_json["Properties"]["type"].as_str().unwrap().to_string(),
1286 );
1287 }
1288
1289 return fsp_json;
1290}
1291
1292
1293pub fn parse_container(
1300 result: SearchEntry,
1301 domain: &String,
1302 dn_sid: &mut HashMap<String, String>,
1303 sid_type: &mut HashMap<String, String>,
1304) -> serde_json::value::Value {
1305
1306 let result_dn: String;
1307 result_dn = result.dn.to_uppercase();
1308
1309 let result_attrs: HashMap<String, Vec<String>>;
1310 result_attrs = result.attrs;
1311
1312 let result_bin: HashMap<String, Vec<Vec<u8>>>;
1313 result_bin = result.bin_attrs;
1314
1315 debug!("Parse Container: {}", result_dn.to_uppercase());
1317 let mut container_json = prepare_container_json_template();
1327 container_json["Properties"]["domain"] = domain.to_owned().to_uppercase().into();
1328 container_json["Properties"]["distinguishedname"] = result_dn.into();
1329
1330 for (key, value) in &result_attrs {
1332 match key.as_str() {
1333 "name" => {
1334 let name = &value[0];
1335 let email = format!("{}@{}",name.to_owned(),domain);
1336 container_json["Properties"]["name"] = email.to_uppercase().into();
1337 }
1338 _ => {}
1339 }
1340 }
1341 for (key, value) in &result_bin {
1343 match key.as_str() {
1344 "objectGUID" => {
1345 let guid = decode_guid(&value[0]);
1346 container_json["ObjectIdentifier"] = guid.to_owned().into();
1347 }
1348 "nTSecurityDescriptor" => {
1349 let entry_type = "container".to_string();
1351 let relations_ace = parse_ntsecuritydescriptor(
1353 &mut container_json,
1354 &value[0],
1355 entry_type,
1356 &result_attrs,
1357 &result_bin,
1358 &domain,
1359 );
1360 container_json["Aces"] = relations_ace.into();
1361 }
1362 "IsDeleted" => {
1363 container_json["IsDeleted"] = true.into();
1364 }
1365 _ => {}
1366 }
1367 }
1368
1369 dn_sid.insert(
1371 container_json["Properties"]["distinguishedname"]
1372 .as_str()
1373 .unwrap()
1374 .to_string(),
1375 container_json["ObjectIdentifier"].as_str().unwrap().to_string(),
1376 );
1377 sid_type.insert(
1379 container_json["ObjectIdentifier"].as_str().unwrap().to_string(),
1380 "Container".to_string(),
1381 );
1382
1383 return container_json;
1384}
1385
1386pub fn parse_trust(result: SearchEntry, domain: &String) -> serde_json::value::Value {
1393
1394 let result_dn: String;
1395 result_dn = result.dn.to_uppercase();
1396
1397 let result_attrs: HashMap<String, Vec<String>>;
1398 result_attrs = result.attrs;
1399
1400 let result_bin: HashMap<String, Vec<Vec<u8>>>;
1401 result_bin = result.bin_attrs;
1402
1403 let mut trust_json = prepare_trust_json_template();
1404
1405 debug!("Parse TrustDomain: {}", result_dn);
1407 for (key, value) in &result_attrs {
1417 match key.as_str() {
1418 "name" => {
1419 trust_json["TargetDomainName"] = value[0].to_uppercase().into();
1420 }
1421 "trustDirection" => {
1422 let trustdirection: u8 = value[0].parse::<u8>().unwrap_or(0);
1423 match trustdirection {
1425 1 => { trust_json["TrustDirection"] = "Inbound".into(); }
1426 2 => { trust_json["TrustDirection"] = "Outbound".into(); }
1427 3 => { trust_json["TrustDirection"] = "Bidirectional".into(); }
1428 _ => { trust_json["TrustDirection"] = "Disable".into(); }
1429 }
1430 }
1431 "trustAttributes" => {
1432 let trustflag: u32 = value[0].parse::<u32>().unwrap_or(0);
1433 get_trust_flag(trustflag, &mut trust_json);
1434 }
1435 _ => {}
1436 }
1437 }
1438 for (key, value) in &result_bin {
1440 match key.as_str() {
1441 "securityIdentifier" => {
1442 let sid = sid_maker(LdapSid::parse(&value[0]).unwrap().1, domain);
1443 trust_json["TargetDomainSid"] = sid.to_owned().into();
1444 }
1445 _ => {}
1446 }
1447 }
1448 return trust_json
1450}
1451
1452pub fn parse_unknown(result: SearchEntry, _domain: &String) -> serde_json::value::Value {
1459
1460 let _result_dn = result.dn.to_uppercase();
1461
1462 let _result_attrs: HashMap<String, Vec<String>>;
1463 _result_attrs = result.attrs;
1464
1465 let _result_bin: HashMap<String, Vec<Vec<u8>>>;
1466 _result_bin = result.bin_attrs;
1467
1468 let unknown_json = json!({
1469 "unknown": null,
1470 });
1471
1472 return unknown_json
1483}