rusthound_ce/modules/
mod.rs1pub mod adcs;
3pub mod gpo;
4pub mod resolver;
5pub mod sessions;
6
7use std::error::Error;
8
9use futures::future;
10
11use crate::api::ADResults;
12use crate::args::{CollectionMethod, Options};
13use crate::modules::adcs::probe_enterpriseca_esc8;
14use crate::modules::gpo::sysvol::collect_sysvol_targets;
15
16pub async fn run_modules(
18 common_args: &Options,
19 ad: &mut ADResults
20) -> Result<(), Box<dyn Error>> {
21
22 let cert_auth = common_args.uses_cert();
23 if cert_auth {
24 log::warn!("Certificate authentication in use: skipping SMB-based modules \
25 (sessions and GPO/SYSVOL) no SMB credentials available.");
26 }
27
28 if common_args.fqdn_resolver {
30 resolver::resolv::resolving_all_fqdn(
31 common_args.dns_tcp,
32 &common_args.name_server,
33 &mut ad.mappings.fqdn_ip,
34 &ad.computers,
35 )
36 .await;
37 }
38
39 if common_args.collection_method.does_sessions() && !cert_auth {
46 sessions::run(common_args, &ad.users, &mut ad.computers).await?;
47 }
48
49 if !matches!(common_args.collection_method, CollectionMethod::DCOnly)
58 && !matches!(common_args.collection_method, CollectionMethod::LdapOnly)
59 && !ad.enterprisecas.is_empty()
60 {
61 log::info!(
62 "Starting ESC8 web enrollment probe on {} CA(s)...",
63 ad.enterprisecas.len()
64 );
65 let hosts: Vec<String> = ad
66 .enterprisecas
67 .iter()
68 .map(|ca| ca.dns_host().to_string())
69 .collect();
70 let probes = future::join_all(hosts.into_iter().map(|host| {
71 tokio::task::spawn_blocking(move || probe_enterpriseca_esc8(&host))
72 }))
73 .await;
74 for (ca, probe) in ad.enterprisecas.iter_mut().zip(probes) {
75 match probe {
76 Ok(esc8) => ca.apply_esc8(esc8.http_enrollment_endpoints),
77 Err(join_err) => log::warn!(
78 "[adcs] ESC8 probe task for {} did not complete ({}), skipping",
79 ca.dns_host(),
80 join_err
81 ),
82 }
83 }
84 }
85
86 if common_args.collection_method.does_gpo() && !cert_auth {
89 let computer_scope = gpo::sysvol::ComputerGpoScope::from_gpos(&ad.gpos);
90 let sysvol = match collect_sysvol_targets(common_args, &computer_scope).await {
91 Ok(v) => v,
92 Err(e) => {
93 log::warn!("[gpo] SYSVOL collection failed: {e}");
94 Vec::new()
95 }
96 };
97 if !sysvol.is_empty() {
98 log::info!(
99 "[gpo] mapping {} GPO(s) to GPOChanges / UserRights",
100 sysvol.len()
101 );
102 gpo::apply_gpo(
103 &mut ad.ous,
104 &mut ad.domains,
105 &ad.users,
106 &ad.groups,
107 &mut ad.computers,
108 &sysvol,
109 &ad.mappings.dn_sid,
110 );
111 }
112 }
113
114 Ok(())
116}