# $Id: anon.bro,v 1.3 2003/01/22 09:22:52 vern Exp $

redef anonymize_ip_addr = T;

const orig_addr_anonymization = SEQUENTIALLY_NUMBERED &redef;
const resp_addr_anonymization = SEQUENTIALLY_NUMBERED &redef;
const other_addr_anonymization = SEQUENTIALLY_NUMBERED &redef;

const preserved_subnet: set[subnet] = {
#	192.150.186/23,
} &redef;

const preserved_net: set[net] = {
#	192.150.186, 192.150.187,
} &redef;

global anon_log = open_log_file("anon") &redef;

event bro_init()
	{
	for ( n in preserved_net )
		preserve_net(n);
	}

# event new_connection(c: connection)
# 	{
# 	print fmt("%s %s", network_time(), id_string(c$id));
# 	anonymize_addr(c$id$orig_h);
# 	anonymize_addr(c$id$resp_h);
# 	}

function anonymize_address(a: addr, id: conn_id): addr
	{
	if ( a == id$orig_h )
		return anonymize_addr(a, orig_addr_anonymization);
	else if ( a == id$resp_h )
		return anonymize_addr(a, resp_addr_anonymization);
	else	
		return anonymize_addr(a, other_addr_anonymization);
	}

event anonymization_mapping(orig: addr, mapped: addr)
	{
	print anon_log, fmt("%s -> %s", orig, mapped);
	}

function string_anonymized(from: string, to: string, seed: count): any
	{
	print anon_log, fmt("\"%s\" %d=> \"%s\"", from, seed, to);
	}

global num_string_id: count = 0 &redef;
global anonymized_strings: table[string] of record {
	s: string;
	c: count;
} &redef;

# Hopefully, the total number of strings to anonymize is much less than
# 2^unique_string_length.
const unique_string_length = 8 &redef;
const anonymized_string_pattern = /U[0-9a-f0-9]+U/;
global unique_string_set: set[string];

event bro_init()
	{
	for ( s in anonymized_strings )
		add unique_string_set[anonymized_strings[s]$s];
	}

function unique_string(s: string, seed: count): string
	{
	local t = cat("U", sub_bytes(md5_hmac(seed, s),
					1, unique_string_length), "U");
	if ( t in unique_string_set )
		return unique_string(s, seed+1);

	anonymized_strings[s] = [$s = t, $c = 1];
	add unique_string_set[t];
	string_anonymized(s, t, seed);

	return t;
	}

function anonymize_string(from: string): string
	{
	if ( from in anonymized_strings )
		{
		++anonymized_strings[from]$c;
		return anonymized_strings[from]$s;
		}

	local t = unique_string(from, 0);
	return t;
	}

event bro_done()
	{
	for ( s in anonymized_strings )
		{
		print anon_log, fmt("appearance: %d: \"%s\" => \"%s\"",
			anonymized_strings[s]$c, s, anonymized_strings[s]$s);
		}
	}
