cerbero_lib/communication/
mod.rs1mod channel_trait;
5pub use channel_trait::KrbChannel;
6
7mod tcp_channel;
8use tcp_channel::TcpChannel;
9
10mod udp_channel;
11use udp_channel::UdpChannel;
12
13use crate::Result;
14use std::collections::HashMap;
15use std::net::{IpAddr, SocketAddr};
16use trust_dns_resolver::config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts};
17use trust_dns_resolver::Resolver;
18
19#[derive(Debug, PartialEq, Clone, Copy)]
21pub enum TransportProtocol
22{
23 TCP,
24 UDP,
25}
26
27#[derive(Debug, Clone)]
29pub struct Kdcs
30{
31 kdcs: HashMap<String, IpAddr>,
32}
33
34impl Default for Kdcs
35{
36 fn default() -> Self
37 {
38 Self::new()
39 }
40}
41
42impl Kdcs
43{
44 pub fn new() -> Self
45 {
46 Self { kdcs: HashMap::new() }
47 }
48
49 pub fn insert(&mut self, realm: String, ip: IpAddr)
57 {
58 self.kdcs.insert(realm.to_lowercase(), ip);
59 }
60
61 pub fn get(&self, realm: &str) -> Option<&IpAddr>
62 {
63 self.kdcs.get(&realm.to_lowercase())
64 }
65
66 pub fn ips(&self) -> Vec<&IpAddr>
67 {
68 self.kdcs.values().collect()
69 }
70
71 pub fn get_clone(&self, realm: &str) -> Option<IpAddr>
72 {
73 self.get(realm).copied()
74 }
75}
76
77#[derive(Clone)]
79pub struct KdcComm
80{
81 kdcs: Kdcs,
82 protocol: TransportProtocol,
83}
84
85impl KdcComm
86{
87 pub fn new(kdcs: Kdcs, protocol: TransportProtocol) -> Self
98 {
99 Self { kdcs, protocol }
100 }
101
102 pub fn create_channel(&mut self, realm: &str) -> Result<Box<dyn KrbChannel>>
115 {
116 resolve_krb_channel(realm, &mut self.kdcs, self.protocol)
117 }
118}
119
120const KERBEROS_PORT: u16 = 88;
121pub fn new_krb_channel(dst_ip: IpAddr, transport_protocol: TransportProtocol) -> Box<dyn KrbChannel>
123{
124 let dst_address = SocketAddr::new(dst_ip, KERBEROS_PORT);
125 match transport_protocol
126 {
127 TransportProtocol::TCP => Box::new(TcpChannel::new(dst_address)),
128 TransportProtocol::UDP => Box::new(UdpChannel::new(dst_address)),
129 }
130}
131
132pub fn resolve_krb_channel(realm: &str,
133 kdcs: &mut Kdcs,
134 channel_protocol: TransportProtocol)
135 -> Result<Box<dyn KrbChannel>>
136{
137 let kdc_ip = resolve_kdc_ip(realm, kdcs)?;
138 kdcs.insert(realm.to_string(), kdc_ip);
139
140 Ok(new_krb_channel(kdc_ip, channel_protocol))
141}
142
143pub fn resolve_kdc_ip(realm: &str, kdcs: &Kdcs) -> Result<IpAddr>
144{
145 Ok(match kdcs.get_clone(realm)
146 {
147 Some(ip) => ip,
148 None =>
149 {
150 let dns_servers = kdcs.ips().iter().map(|ip| SocketAddr::new(**ip, 53)).collect();
151 resolve_host(realm, dns_servers)?
152 },
153 })
154}
155
156pub fn resolve_host(realm: &str, dns_servers: Vec<SocketAddr>) -> Result<IpAddr>
157{
158 let resolver = if dns_servers.is_empty()
159 {
160 Resolver::from_system_conf().map_err(|err| format!("Unable to use dns system configuration: {}", err))?
161 }
162 else
163 {
164 let mut resolver_config = ResolverConfig::new();
165 for server in dns_servers
166 {
167 resolver_config.add_name_server(NameServerConfig { socket_addr: server,
168 protocol: Protocol::Tcp,
169 tls_dns_name: None,
170 trust_nx_responses: false });
171 }
172 Resolver::new(resolver_config, ResolverOpts::default()).unwrap()
173 };
174
175 let ips = resolver.lookup_ip(realm).map_err(|err| format!("Error resolving '{}' : '{}'", realm, err))?;
176
177 let ip = ips.iter().next().ok_or(format!("Error resolving '{}': No entries found", realm))?;
178
179 Ok(ip)
180}