rusthound_ce/objects/
trust.rs

1use ldap3::SearchEntry;
2use log::{debug, trace};
3use std::collections::HashMap;
4use std::error::Error;
5use serde::{Deserialize, Serialize};
6
7use crate::enums::secdesc::LdapSid;
8use crate::enums::sid::sid_maker;
9use crate::enums::trusts::get_trust_flag;
10
11/// Trust structure
12#[derive(Debug, Clone, Deserialize, Serialize, Default)]
13pub struct Trust {
14   #[serde(rename = "TargetDomainSid")]
15   target_domain_sid: String,
16   #[serde(rename = "TargetDomainName")]
17   target_domain_name: String,
18   #[serde(rename = "IsTransitive")]
19   is_transitive: bool,
20   #[serde(rename = "SidFilteringEnabled")]
21   sid_filtering_enabled: bool,
22   #[serde(rename = "TrustAttributes")]
23   trust_attributes: u32,
24   #[serde(rename = "TrustDirection")]
25   trust_direction: String,
26   #[serde(rename = "TrustType")]
27   trust_type: String,
28}
29
30impl Trust {
31   // New trust link for domain.
32    pub fn new() -> Self { 
33      Self {
34         ..Default::default()
35      } 
36   }
37
38   // Imutable access.
39   pub fn target_domain_sid(&self) -> &String {
40      &self.target_domain_sid
41   }
42   pub fn target_domain_name(&self) -> &String {
43      &self.target_domain_name
44   }
45
46   // Mutable access.
47   pub fn is_transitive_mut(&mut self) -> &mut bool {
48      &mut self.is_transitive
49   }
50   pub fn sid_filtering_enabled_mut(&mut self) -> &mut bool {
51      &mut self.sid_filtering_enabled
52   }
53   pub fn trust_type_mut(&mut self) -> &mut String {
54      &mut self.trust_type
55   }
56
57   /// Function to parse and replace value for trust domain object.
58   pub fn parse(
59      &mut self,
60      result: SearchEntry,
61      domain: &str
62   ) -> Result<(), Box<dyn Error>> {
63      let result_dn: String = result.dn.to_uppercase();
64      let result_attrs: HashMap<String, Vec<String>> = result.attrs;
65      let result_bin: HashMap<String, Vec<Vec<u8>>> = result.bin_attrs;
66
67      // Debug for current object
68      debug!("Parse TrustDomain: {result_dn}");
69
70      // Trace all result attributes
71      for (key, value) in &result_attrs {
72         trace!("  {key:?}:{value:?}");
73      }
74      // Trace all bin result attributes
75      for (key, value) in &result_bin {
76         trace!("  {key:?}:{value:?}");
77      }
78
79      // With a check
80      for (key, value) in &result_attrs {
81         match key.as_str() {
82            "name" => {
83                  self.target_domain_name = value[0].to_uppercase();
84            }
85            "trustDirection" => {
86                  let trustdirection: u8 = value[0].parse::<u8>().unwrap_or(0);
87                  // <https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/5026a939-44ba-47b2-99cf-386a9e674b04>
88                  self.trust_direction = match trustdirection { 
89                     1 => "Inbound",
90                     2 => "Outbound",
91                     3 => "Bidirectional",
92                     _ => "Disabled"
93                  }.to_string()
94            }
95            "trustAttributes" => {
96                  let trustflag: u32 = value[0].parse::<u32>().unwrap_or(0);
97                  get_trust_flag(trustflag, self);
98                  self.trust_attributes = trustflag;
99            }
100            _ => {}
101         }
102      }
103      // For all, bins attributs
104      for (key, value) in &result_bin {
105         match key.as_str() {
106            "securityIdentifier" => {
107                  let sid = sid_maker(LdapSid::parse(&value[0]).unwrap().1, domain);
108                  self.target_domain_sid = sid.to_owned();
109            }
110            _ => {}
111         }
112      }
113      
114      // Trace and return tRUST struct
115      // trace!("TRUST VALUE: {:?}",&self);
116      Ok(())
117   }
118}