1extern crate url;
6use address::{Address, ExplicitlyTypedAddress};
7use std::collections::HashMap;
8use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
9use std::num::Wrapping;
10
11pub trait AnonymizingClone {
12 fn masked_clone(&self, anon: &mut StatefulSdpAnonymizer) -> Self;
13}
14
15pub trait ToBytesVec {
16 fn to_byte_vec(&self) -> Vec<u8>;
17}
18
19impl ToBytesVec for u64 {
20 fn to_byte_vec(&self) -> Vec<u8> {
21 let mut bytes = Vec::new();
22 let mut val = *self;
23 for _ in 0..8 {
24 bytes.push(val as u8);
25 val <<= 8;
26 }
27 bytes.reverse();
28 bytes
29 }
30}
31
32pub struct StatefulSdpAnonymizer {
41 ips: HashMap<IpAddr, IpAddr>,
42 ip_v4_inc: Wrapping<u32>,
43 ip_v6_inc: Wrapping<u128>,
44 host_names: AnonymizationStrMap,
45 ports: HashMap<u32, u32>,
46 port_inc: Wrapping<u32>,
47 origin_users: AnonymizationStrMap,
48 ice_passwords: AnonymizationStrMap,
49 ice_users: AnonymizationStrMap,
50 cert_finger_prints: HashMap<Vec<u8>, Vec<u8>>,
51 cert_finger_print_inc: Wrapping<u64>,
52 cnames: AnonymizationStrMap,
53}
54
55impl Default for StatefulSdpAnonymizer {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl StatefulSdpAnonymizer {
62 pub fn new() -> Self {
63 StatefulSdpAnonymizer {
64 ips: HashMap::new(),
65 ip_v4_inc: Wrapping(0),
66 ip_v6_inc: Wrapping(0),
67 host_names: AnonymizationStrMap::new("fqdn-", 8),
68 ports: HashMap::new(),
69 port_inc: Wrapping(0),
70 origin_users: AnonymizationStrMap::new("origin-user-", 8),
71 ice_passwords: AnonymizationStrMap::new("ice-password-", 8),
72 ice_users: AnonymizationStrMap::new("ice-user-", 8),
73 cert_finger_prints: HashMap::new(),
74 cert_finger_print_inc: Wrapping(0),
75 cnames: AnonymizationStrMap::new("cname-", 8),
76 }
77 }
78
79 pub fn mask_host(&mut self, host: &str) -> String {
80 self.host_names.mask(host)
81 }
82
83 pub fn mask_ip(&mut self, addr: &IpAddr) -> IpAddr {
84 if let Some(address) = self.ips.get(addr) {
85 return *address;
86 }
87 let mapped = match addr {
88 IpAddr::V4(_) => {
89 self.ip_v4_inc += Wrapping(1);
90 IpAddr::V4(Ipv4Addr::from(self.ip_v4_inc.0))
91 }
92 IpAddr::V6(_) => {
93 self.ip_v6_inc += Wrapping(1);
94 IpAddr::V6(Ipv6Addr::from(self.ip_v6_inc.0))
95 }
96 };
97 self.ips.insert(*addr, mapped);
98 mapped
99 }
100
101 pub fn mask_address(&mut self, address: &Address) -> Address {
102 match address {
103 Address::Fqdn(host) => Address::Fqdn(self.mask_host(host)),
104 Address::Ip(ip) => Address::Ip(self.mask_ip(ip)),
105 }
106 }
107
108 pub fn mask_typed_address(
109 &mut self,
110 address: &ExplicitlyTypedAddress,
111 ) -> ExplicitlyTypedAddress {
112 match address {
113 ExplicitlyTypedAddress::Fqdn {
114 address_type,
115 domain,
116 } => ExplicitlyTypedAddress::Fqdn {
117 address_type: *address_type,
118 domain: self.mask_host(domain),
119 },
120 ExplicitlyTypedAddress::Ip(ip) => ExplicitlyTypedAddress::Ip(self.mask_ip(ip)),
121 }
122 }
123
124 pub fn mask_port(&mut self, port: u32) -> u32 {
125 if let Some(stored) = self.ports.get(&port) {
126 return *stored;
127 }
128 self.port_inc += Wrapping(1);
129 self.ports.insert(port, self.port_inc.0);
130 self.port_inc.0
131 }
132
133 pub fn mask_origin_user(&mut self, user: &str) -> String {
134 self.origin_users.mask(user)
135 }
136
137 pub fn mask_ice_password(&mut self, password: &str) -> String {
138 self.ice_passwords.mask(password)
139 }
140
141 pub fn mask_ice_user(&mut self, user: &str) -> String {
142 self.ice_users.mask(user)
143 }
144
145 pub fn mask_cert_finger_print(&mut self, finger_print: &[u8]) -> Vec<u8> {
146 if let Some(stored) = self.cert_finger_prints.get(finger_print) {
147 return stored.clone();
148 }
149 self.cert_finger_print_inc += Wrapping(1);
150 self.cert_finger_prints.insert(
151 finger_print.to_vec(),
152 self.cert_finger_print_inc.0.to_byte_vec(),
153 );
154 self.cert_finger_print_inc.0.to_byte_vec()
155 }
156
157 pub fn mask_cname(&mut self, cname: &str) -> String {
158 self.cnames.mask(cname)
159 }
160}
161
162struct AnonymizationStrMap {
163 map: HashMap<String, String>,
164 counter: Wrapping<u64>,
165 prefix: &'static str,
166 padding: usize,
167}
168
169impl AnonymizationStrMap {
170 pub fn new(prefix: &'static str, padding: usize) -> Self {
171 Self {
172 map: HashMap::new(),
173 counter: Wrapping(0),
174 prefix,
175 padding,
176 }
177 }
178
179 pub fn mask(&mut self, value: &str) -> String {
180 let key = value.to_owned();
181 if let Some(stored) = self.map.get(&key) {
182 return stored.clone();
183 }
184 self.counter += Wrapping(1);
185 let store = format!(
186 "{}{:0padding$}",
187 self.prefix,
188 self.counter.0,
189 padding = self.padding
190 );
191 self.map.insert(key, store.clone());
192 store
193 }
194}
195
196#[cfg(test)]
197#[path = "./anonymizer_tests.rs"]
198mod tests;