1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 extern crate url;
6 use address::{Address, ExplicitlyTypedAddress};
7 use std::collections::HashMap;
8 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
9 use std::num::Wrapping;
10 
11 pub trait AnonymizingClone {
masked_clone(&self, anon: &mut StatefulSdpAnonymizer) -> Self12     fn masked_clone(&self, anon: &mut StatefulSdpAnonymizer) -> Self;
13 }
14 
15 pub trait ToBytesVec {
to_byte_vec(&self) -> Vec<u8>16     fn to_byte_vec(&self) -> Vec<u8>;
17 }
18 
19 impl ToBytesVec for u64 {
to_byte_vec(&self) -> Vec<u8>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 
32 /*
33 * Anonymizes SDP in a stateful fashion, such that a pre-anonymized value will
34 * always be transformed into the same anonymized value within the context of
35 * the anonymizer.
36 * Stores the opaque state necessary for intelligent anonymization of SDP. This
37 * state can be stored and reused during the offer-answer period, and it
38 * will maintain a stable set of masked values.
39 */
40 pub 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 
55 impl Default for StatefulSdpAnonymizer {
default() -> Self56     fn default() -> Self {
57         Self::new()
58     }
59 }
60 
61 impl StatefulSdpAnonymizer {
new() -> Self62     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 
mask_host(&mut self, host: &str) -> String79     pub fn mask_host(&mut self, host: &str) -> String {
80         self.host_names.mask(host)
81     }
82 
mask_ip(&mut self, addr: &IpAddr) -> IpAddr83     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 
mask_address(&mut self, address: &Address) -> Address101     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 
mask_typed_address( &mut self, address: &ExplicitlyTypedAddress, ) -> ExplicitlyTypedAddress108     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 
mask_port(&mut self, port: u32) -> u32124     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 
mask_origin_user(&mut self, user: &str) -> String133     pub fn mask_origin_user(&mut self, user: &str) -> String {
134         self.origin_users.mask(user)
135     }
136 
mask_ice_password(&mut self, password: &str) -> String137     pub fn mask_ice_password(&mut self, password: &str) -> String {
138         self.ice_passwords.mask(password)
139     }
140 
mask_ice_user(&mut self, user: &str) -> String141     pub fn mask_ice_user(&mut self, user: &str) -> String {
142         self.ice_users.mask(user)
143     }
144 
mask_cert_finger_print(&mut self, finger_print: &[u8]) -> Vec<u8>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 
mask_cname(&mut self, cname: &str) -> String157     pub fn mask_cname(&mut self, cname: &str) -> String {
158         self.cnames.mask(cname)
159     }
160 }
161 
162 struct AnonymizationStrMap {
163     map: HashMap<String, String>,
164     counter: Wrapping<u64>,
165     prefix: &'static str,
166     padding: usize,
167 }
168 
169 impl AnonymizationStrMap {
new(prefix: &'static str, padding: usize) -> Self170     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 
mask(&mut self, value: &str) -> String179     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 mod tests {
198     use super::*;
199 
200     #[test]
test_mask_ip()201     fn test_mask_ip() {
202         let mut anon = StatefulSdpAnonymizer::default();
203         let v4 = [
204             Ipv4Addr::new(127, 0, 0, 1),
205             Ipv4Addr::new(10, 0, 0, 1),
206             Ipv4Addr::new(1, 1, 1, 1),
207         ];
208         let v4_masked = [
209             Ipv4Addr::new(0, 0, 0, 1),
210             Ipv4Addr::new(0, 0, 0, 2),
211             Ipv4Addr::new(0, 0, 0, 3),
212         ];
213         let v6 = [
214             Ipv6Addr::from(0),
215             Ipv6Addr::from(528_189_235),
216             Ipv6Addr::from(1_623_734_988_148_990),
217         ];
218         let v6_masked = [Ipv6Addr::from(1), Ipv6Addr::from(2), Ipv6Addr::from(3)];
219         for _ in 0..2 {
220             assert_eq!(anon.mask_ip(&IpAddr::V4(v4[0])), v4_masked[0]);
221             assert_eq!(anon.mask_ip(&IpAddr::V6(v6[0])), v6_masked[0]);
222 
223             assert_eq!(anon.mask_ip(&IpAddr::V4(v4[1])), v4_masked[1]);
224             assert_eq!(anon.mask_ip(&IpAddr::V6(v6[1])), v6_masked[1]);
225 
226             assert_eq!(anon.mask_ip(&IpAddr::V4(v4[2])), v4_masked[2]);
227             assert_eq!(anon.mask_ip(&IpAddr::V6(v6[2])), v6_masked[2]);
228         }
229     }
230 
231     #[test]
test_mask_port()232     fn test_mask_port() {
233         let mut anon = StatefulSdpAnonymizer::default();
234         let ports = [0, 125, 12346];
235         let masked_ports = [1, 2, 3];
236         for _ in 0..2 {
237             assert_eq!(anon.mask_port(ports[0]), masked_ports[0]);
238             assert_eq!(anon.mask_port(ports[1]), masked_ports[1]);
239             assert_eq!(anon.mask_port(ports[2]), masked_ports[2]);
240         }
241     }
242 
243     #[test]
test_mask_ice_password()244     fn test_mask_ice_password() {
245         let mut anon = StatefulSdpAnonymizer::default();
246         let passwords = ["vasdfioqwenl14082`14", "0", "ncp	HY878hp(poh"];
247         let masked_passwords = [
248             "ice-password-00000001",
249             "ice-password-00000002",
250             "ice-password-00000003",
251         ];
252         for _ in 0..2 {
253             assert_eq!(anon.mask_ice_password(passwords[0]), masked_passwords[0]);
254             assert_eq!(anon.mask_ice_password(passwords[1]), masked_passwords[1]);
255             assert_eq!(anon.mask_ice_password(passwords[2]), masked_passwords[2]);
256         }
257     }
258 
259     #[test]
test_mask_ice_user()260     fn test_mask_ice_user() {
261         let mut anon = StatefulSdpAnonymizer::default();
262         let users = ["user1", "user2", "8109q2asdf"];
263         let masked_users = [
264             "ice-user-00000001",
265             "ice-user-00000002",
266             "ice-user-00000003",
267         ];
268         for _ in 0..2 {
269             assert_eq!(anon.mask_ice_user(users[0]), masked_users[0]);
270             assert_eq!(anon.mask_ice_user(users[1]), masked_users[1]);
271             assert_eq!(anon.mask_ice_user(users[2]), masked_users[2]);
272         }
273     }
274 
275     #[test]
test_mask_cert_fingerprint()276     fn test_mask_cert_fingerprint() {
277         let mut anon = StatefulSdpAnonymizer::default();
278         let prints: [Vec<u8>; 3] = [
279             vec![
280                 0x59u8, 0x4A, 0x8B, 0x73, 0xA7, 0x73, 0x53, 0x71, 0x88, 0xD7, 0x4D, 0x58, 0x28,
281                 0x0C, 0x79, 0x72, 0x31, 0x29, 0x9B, 0x05, 0x37, 0xDD, 0x58, 0x43, 0xC2, 0xD4, 0x85,
282                 0xA2, 0xB3, 0x66, 0x38, 0x7A,
283             ],
284             vec![
285                 0x30u8, 0xFF, 0x8E, 0x2B, 0xAC, 0x9D, 0xED, 0x70, 0x18, 0x10, 0x67, 0xC8, 0xAE,
286                 0x9E, 0x68, 0xF3, 0x86, 0x53, 0x51, 0xB0, 0xAC, 0x31, 0xB7, 0xBE, 0x6D, 0xCF, 0xA4,
287                 0x2E, 0xD3, 0x6E, 0xB4, 0x28,
288             ],
289             vec![
290                 0xDFu8, 0x2E, 0xAC, 0x8A, 0xFD, 0x0A, 0x8E, 0x99, 0xBF, 0x5D, 0xE8, 0x3C, 0xE7,
291                 0xFA, 0xFB, 0x08, 0x3B, 0x3C, 0x54, 0x1D, 0xD7, 0xD4, 0x05, 0x77, 0xA0, 0x72, 0x9B,
292                 0x14, 0x08, 0x6D, 0x0F, 0x4C,
293             ],
294         ];
295 
296         let masked_prints = [1u64.to_byte_vec(), 2u64.to_byte_vec(), 3u64.to_byte_vec()];
297         for _ in 0..2 {
298             assert_eq!(anon.mask_cert_finger_print(&prints[0]), masked_prints[0]);
299             assert_eq!(anon.mask_cert_finger_print(&prints[1]), masked_prints[1]);
300             assert_eq!(anon.mask_cert_finger_print(&prints[2]), masked_prints[2]);
301         }
302     }
303 
304     #[test]
test_mask_cname()305     fn test_mask_cname() {
306         let mut anon = StatefulSdpAnonymizer::default();
307         let cnames = ["mailto:foo@bar", "JohnDoe", "Jane Doe"];
308         let masked_cnames = ["cname-00000001", "cname-00000002", "cname-00000003"];
309         for _ in 0..2 {
310             assert_eq!(anon.mask_cname(cnames[0]), masked_cnames[0]);
311             assert_eq!(anon.mask_cname(cnames[1]), masked_cnames[1]);
312             assert_eq!(anon.mask_cname(cnames[2]), masked_cnames[2]);
313         }
314     }
315 }
316