Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

Anon.cc

Go to the documentation of this file.
00001 // $Id: Anon.cc,v 1.1 2004/07/14 20:15:39 jason Exp $
00002 
00003 #include <stdlib.h>
00004 #include <unistd.h>
00005 #include <assert.h>
00006 #include <sys/time.h>
00007 
00008 #include "util.h"
00009 #include "net_util.h"
00010 #include "md5.h"
00011 #include "Anon.h"
00012 #include "Val.h"
00013 #include "NetVar.h"
00014 
00015 
00016 AnonymizeIPAddr* ip_anonymizer[NUM_ADDR_ANONYMIZATION_METHODS] = {0};
00017 
00018 static uint32 rand32()
00019         {
00020         return ((random() & 0xffff) << 16) | (random() & 0xffff);
00021         }
00022 
00023 // from tcpdpriv
00024 int bi_ffs(uint32 value)
00025         {
00026         int add = 0;
00027         static uint8 bvals[] = { 0, 4, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 };
00028 
00029         if ( (value & 0xFFFF0000) == 0 )
00030                 {
00031                 if ( value == 0 )
00032                         // zero input ==> zero output.
00033                         return 0;
00034 
00035                 add += 16;
00036                 }
00037 
00038         else
00039                 value >>= 16;
00040 
00041         if ( (value & 0xFF00) == 0 )
00042                 add += 8;
00043         else
00044                 value >>= 8;
00045 
00046         if ( (value & 0xF0) == 0 )
00047                 add += 4;
00048         else
00049                 value >>= 4;
00050 
00051         return add + bvals[value & 0xf];
00052         }
00053 
00054 #define first_n_bit_mask(n)     (~(0xFFFFFFFFU >> n))
00055 
00056 ipaddr32_t AnonymizeIPAddr::Anonymize(ipaddr32_t addr)
00057         {
00058         map<ipaddr32_t, ipaddr32_t>::iterator p = mapping.find(addr);
00059         if ( p != mapping.end() )
00060                 return p->second;
00061         else
00062                 {
00063                 ipaddr32_t new_addr = anonymize(addr);
00064                 mapping[addr] = new_addr;
00065 
00066                 return new_addr;
00067                 }
00068         }
00069 
00070 int AnonymizeIPAddr::PreserveNet(ipaddr32_t input)
00071         {
00072         switch ( addr_to_class(ntohl(input)) ) {
00073         case 'A':
00074                 return PreservePrefix(input, 8);
00075         case 'B':
00076                 return PreservePrefix(input, 16);
00077         case 'C':
00078                 return PreservePrefix(input, 24);
00079         default:
00080                 return 0;
00081         }
00082         }
00083 
00084 ipaddr32_t AnonymizeIPAddr_Seq::anonymize(ipaddr32_t /* input */)
00085         {
00086         return htonl(seq++);
00087         }
00088 
00089 ipaddr32_t AnonymizeIPAddr_RandomMD5::anonymize(ipaddr32_t input)
00090         {
00091         uint8 digest[16];
00092         ipaddr32_t output = 0;
00093 
00094         hmac_md5(sizeof(input), (u_char*)(&input), digest);
00095 
00096         for ( int i = 0; i < 4; ++i )
00097                 output = (output << 8) | digest[i];
00098 
00099         return output;
00100         }
00101 
00102 ipaddr32_t AnonymizeIPAddr_PrefixMD5::anonymize(ipaddr32_t input)
00103         {
00104         uint8 digest[16];
00105         ipaddr32_t prefix_mask = 0xffffffff;
00106         ipaddr32_t output = input;
00107 
00108         for ( int i = 0; i < 32; ++i )
00109                 {
00110                 prefix.len = 32 - i;
00111                 prefix.prefix = input & prefix_mask;
00112 
00113                 hmac_md5(sizeof(prefix), (u_char*)(&prefix), digest);
00114 
00115                 ipaddr32_t bit_mask = (digest[0] & 1) << i;
00116                 output ^= bit_mask;
00117                 }
00118 
00119         return output;
00120         }
00121 
00122 AnonymizeIPAddr_A50::~AnonymizeIPAddr_A50()
00123         {
00124         for ( unsigned int i = 0; i < blocks.size(); ++i )
00125                 delete [] blocks[i];
00126 
00127         blocks.clear();
00128         }
00129 
00130 void AnonymizeIPAddr_A50::init()
00131         {
00132         root = next_free_node = 0;
00133 
00134         // Prepare special nodes for 0.0.0.0 and 255.255.255.255.
00135         memset(&special_nodes[0], 0, sizeof(special_nodes));
00136         special_nodes[0].input = special_nodes[0].output = 0;
00137         special_nodes[1].input = special_nodes[1].output = 0xFFFFFFFF;
00138 
00139         before_anonymization = 1;
00140         }
00141 
00142 int AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits)
00143         {
00144         DEBUG_MSG(fmt("%s/%d\n", dotted_addr(input), num_bits));
00145 
00146         if ( ! before_anonymization )
00147                 {
00148                 run_time("prefix perservation specified after anonymization begun");
00149                 return 0;
00150                 }
00151 
00152         input = ntohl(input);
00153 
00154         // Sanitize input.
00155         input = input & first_n_bit_mask(num_bits);
00156 
00157         Node* n = find_node(input);
00158 
00159         // Preserve the first num_bits bits of addr.
00160         if ( num_bits == 32 )
00161                 n->output = input;
00162 
00163         else if ( num_bits > 0 )
00164                 {
00165                 assert((0xFFFFFFFFU >> 1) == 0x7FFFFFFFU);
00166                 uint32 suffix_mask = (0xFFFFFFFFU >> num_bits);
00167                 uint32 prefix_mask = ~suffix_mask;
00168                 n->output = (input & prefix_mask) | (rand32() & suffix_mask);
00169                 }
00170 
00171         return 1;
00172         }
00173 
00174 ipaddr32_t AnonymizeIPAddr_A50::anonymize(ipaddr32_t a)
00175         {
00176         before_anonymization = 0;
00177         new_mapping = 0;
00178 
00179         if ( Node* n = find_node(ntohl(a)) )
00180                 {
00181                 ipaddr32_t output = htonl(n->output);
00182                 return output;
00183                 }
00184         else
00185                 return 0;
00186         }
00187 
00188 AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node_block()
00189         {
00190         assert(! next_free_node);
00191 
00192         int block_size = 1024;
00193         Node* block = new Node[block_size];
00194         if ( ! block )
00195                 internal_error("out of memory!");
00196 
00197         blocks.push_back(block);
00198 
00199         for ( int i = 1; i < block_size - 1; ++i )
00200                 block[i].child[0] = &block[i+1];
00201 
00202         block[block_size - 1].child[0] = 0;
00203         next_free_node = &block[1];
00204 
00205         return &block[0];
00206         }
00207 
00208 inline AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::new_node()
00209         {
00210         new_mapping = 1;
00211 
00212         if ( next_free_node )
00213                 {
00214                 Node* n = next_free_node;
00215                 next_free_node = n->child[0];
00216                 return n;
00217                 }
00218         else
00219                 return new_node_block();
00220         }
00221 
00222 inline void AnonymizeIPAddr_A50::free_node(Node *n)
00223         {
00224         n->child[0] = next_free_node;
00225         next_free_node = n;
00226         }
00227 
00228 ipaddr32_t AnonymizeIPAddr_A50::make_output(ipaddr32_t old_output, int swivel) const
00229         {
00230         // -A50 anonymization
00231         if ( swivel == 32 )
00232                 return old_output ^ 1;
00233         else
00234                 {
00235                 // Bits up to swivel are unchanged; bit swivel is flipped.
00236                 ipaddr32_t known_part =
00237                         ((old_output >> (32 - swivel)) ^ 1) << (32 - swivel);
00238 
00239                 // Remainder of bits are random.
00240                 return known_part | ((rand32() & 0x7FFFFFFF) >> swivel);
00241                 }
00242         }
00243 
00244 AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::make_peer(ipaddr32_t a, Node* n)
00245         {
00246         if ( a == 0 || a == 0xFFFFFFFFU )
00247                 internal_error("0.0.0.0 and 255.255.255.255 should never get into the tree");
00248 
00249         // Become a peer.
00250         // Algorithm: create two nodes, the two peers.  Leave orig node as
00251         // the parent of the two new ones.
00252 
00253         Node* down[2];
00254 
00255         if ( ! (down[0] = new_node()) )
00256                 return 0;
00257 
00258         if ( ! (down[1] = new_node()) )
00259                 {
00260                 free_node(down[0]);
00261                 return 0;
00262                 }
00263 
00264         // swivel is first bit 'a' and 'old->input' differ.
00265         int swivel = bi_ffs(a ^ n->input);
00266 
00267         // bitvalue is the value of that bit of 'a'.
00268         int bitvalue = (a >> (32 - swivel)) & 1;
00269 
00270         down[bitvalue]->input = a;
00271         down[bitvalue]->output = make_output(n->output, swivel);
00272         down[bitvalue]->child[0] = down[bitvalue]->child[1] = 0;
00273 
00274         *down[1 - bitvalue] = *n;       // copy orig node down one level
00275 
00276         n->input = down[1]->input;      // NB: 1s to the right (0s to the left)
00277         n->output = down[1]->output;
00278         n->child[0] = down[0];          // point to children
00279         n->child[1] = down[1];
00280 
00281         return down[bitvalue];
00282         }
00283 
00284 AnonymizeIPAddr_A50::Node* AnonymizeIPAddr_A50::find_node(ipaddr32_t a)
00285         {
00286         // Watch out for special IP addresses, which never make it
00287         // into the tree.
00288         if ( a == 0 || a == 0xFFFFFFFFU )
00289                 return &special_nodes[a & 1];
00290 
00291         if ( ! root )
00292                 {
00293                 root = new_node();
00294                 root->input = a;
00295                 root->output = rand32();
00296                 root->child[0] = root->child[1] = 0;
00297 
00298                 return root;
00299                 }
00300 
00301         // Straight from tcpdpriv.
00302         Node* n = root;
00303         while ( n )
00304                 {
00305                 if ( n->input == a )
00306                         return n;
00307 
00308                 if ( ! n->child[0] )
00309                         n = make_peer(a, n);
00310 
00311                 else
00312                         {
00313                         // swivel is the first bit in which the two children
00314                         // differ.
00315                         int swivel =
00316                                 bi_ffs(n->child[0]->input ^ n->child[1]->input);
00317 
00318                         if ( bi_ffs(a ^ n->input) < swivel )
00319                                 // Input differs earlier.
00320                                 n = make_peer(a, n);
00321 
00322                         else if ( a & (1 << (32 - swivel)) )
00323                                 n = n->child[1];
00324 
00325                         else
00326                                 n = n->child[0];
00327                         }
00328                 }
00329 
00330         internal_error("out of memory!");
00331         return 0;
00332         }
00333 
00334 void init_ip_addr_anonymizers()
00335         {
00336         ip_anonymizer[KEEP_ORIG_ADDR] = 0;
00337         ip_anonymizer[SEQUENTIALLY_NUMBERED] = new AnonymizeIPAddr_Seq();
00338         ip_anonymizer[RANDOM_MD5] = new AnonymizeIPAddr_RandomMD5();
00339         ip_anonymizer[PREFIX_PRESERVING_A50] = new AnonymizeIPAddr_A50();
00340         ip_anonymizer[PREFIX_PRESERVING_MD5] = new AnonymizeIPAddr_PrefixMD5();
00341         }
00342 
00343 ipaddr32_t anonymize_ip(ipaddr32_t ip, enum ip_addr_anonymization_class_t cl)
00344         {
00345         TableVal* preserve_addr = 0;
00346         AddrVal addr(ip);
00347 
00348         int method = -1;
00349 
00350         switch ( cl ) {
00351         case ORIG_ADDR: // client address
00352                 preserve_addr = preserve_orig_addr;
00353                 method = orig_addr_anonymization;
00354                 break;
00355 
00356         case RESP_ADDR: // server address
00357                 preserve_addr = preserve_resp_addr;
00358                 method = resp_addr_anonymization;
00359                 break;
00360 
00361         default:
00362                 preserve_addr = preserve_other_addr;
00363                 method = other_addr_anonymization;
00364                 break;
00365         }
00366 
00367         ipaddr32_t new_ip = 0;
00368                 
00369         if ( preserve_addr && preserve_addr->Lookup(&addr) )
00370                 new_ip = ip;
00371 
00372         else if ( method >= 0 && method < NUM_ADDR_ANONYMIZATION_METHODS )
00373                 {
00374                 if ( method == KEEP_ORIG_ADDR ) 
00375                         new_ip = ip;
00376 
00377                 else if ( ! ip_anonymizer[method] )
00378                         internal_error("IP anonymizer not initialized");
00379 
00380                 else
00381                         new_ip = ip_anonymizer[method]->Anonymize(ip);
00382                 }
00383 
00384         else
00385                 internal_error("invalid IP anonymization method");
00386 
00387 #ifdef LOG_ANONYMIZATION_MAPPING
00388         log_anonymization_mapping(ip, new_ip);
00389 #endif
00390         return new_ip;
00391         }
00392 
00393 #ifdef LOG_ANONYMIZATION_MAPPING
00394 
00395 #include "NetVar.h"
00396 #include "Event.h"
00397 
00398 void log_anonymization_mapping(ipaddr32_t input, ipaddr32_t output)
00399         {
00400         if ( anonymization_mapping )
00401                 {
00402                 val_list* vl = new val_list;
00403                 vl->append(new AddrVal(input));
00404                 vl->append(new AddrVal(output));
00405                 mgr.QueueEvent(anonymization_mapping, vl);
00406                 }
00407         }
00408 
00409 #endif

Generated on Wed Sep 14 02:55:57 2005 for bro_docs by doxygen 1.3.5