00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_FRAME_FILTER_ANONYMIZER_HXX_
00023 # define WIFI_FRAME_FILTER_ANONYMIZER_HXX_
00024
00025 # include <cassert>
00026 # include <stdexcept>
00027
00028 # include <boost/foreach.hpp>
00029
00030 # include <wipal/wifi/frame/filter/anonymizer.hh>
00031
00032 # include <wipal/wifi/frame/dissector/dissector.hh>
00033
00034 namespace wifi
00035 {
00036 namespace frame
00037 {
00038
00039
00040
00041
00042
00043 namespace anon
00044 {
00045
00046 inline
00047 addr
00048 dummy_mac_policy::operator [] (const addr& mac_addr) const
00049 {
00050 return mac_addr;
00051 }
00052
00053 inline
00054 essid
00055 dummy_essid_policy::operator [] (const essid& essid) const
00056 {
00057 return essid;
00058 }
00059
00060 template <class MACAnonPolicy, class ESSIDAnonPolicy>
00061 generic_policy<MACAnonPolicy, ESSIDAnonPolicy>::
00062 generic_policy(const MACAnonPolicy& macp,
00063 const ESSIDAnonPolicy& essidp):
00064 MACAnonPolicy (macp),
00065 ESSIDAnonPolicy (essidp)
00066 {
00067 }
00068
00069 template <class MACAnonPolicy, class ESSIDAnonPolicy>
00070 addr
00071 generic_policy<MACAnonPolicy, ESSIDAnonPolicy>::
00072 operator [] (const addr& mac_addr)
00073 {
00074 return MACAnonPolicy::operator [] (mac_addr);
00075 }
00076
00077 template <class MACAnonPolicy, class ESSIDAnonPolicy>
00078 essid
00079 generic_policy<MACAnonPolicy, ESSIDAnonPolicy>::
00080 operator [] (const essid& essid)
00081 {
00082 return ESSIDAnonPolicy::operator [] (essid);
00083 }
00084
00085 }
00086
00087
00088 namespace filter
00089 {
00090
00091
00092
00093
00094
00095 namespace internals
00096 {
00097
00098 template <class I, class P, class A, class B1, class B2>
00099 anonymizer_iterator<I, P, A, B1, B2>::
00100 anonymizer_iterator(const iterable_type& iterable, bool end):
00101 A (iterable),
00102 next_ (end? iterable.last_ : iterable.first_),
00103 last_ (iterable.last_)
00104 {
00105 if (not end)
00106 increment();
00107 }
00108
00109 template <class I, class P, class A, class B1, class B2>
00110 bool
00111 anonymizer_iterator<I, P, A, B1, B2>::
00112 equal(const anonymizer_iterator& rhs) const
00113 {
00114 if (not rhs.value())
00115 return not this->value();
00116
00117 return next_ == rhs.next_;
00118 }
00119
00120 template <class I, class P, class A, class B1, class B2>
00121 void
00122 anonymizer_iterator<I, P, A, B1, B2>::increment()
00123 {
00124 typedef typename I::value_type input_frame;
00125 typedef typename input_frame::pkthdr_ptr pkthdr_ptr;
00126 typedef typename input_frame::bytes_ptr bytes_ptr;
00127
00128 if (next_ == last_)
00129 {
00130 this->value() = boost::none_t ();
00131 return;
00132 }
00133
00134 const input_frame& frm = *next_;
00135 const pkthdr_ptr pcap = frm.pcap_header();
00136 const uint8_t* const phy_u8 = frm.bytes().get();
00137 const P* const phy = reinterpret_cast<const P*> (phy_u8);
00138 const size_t caplen = pcap->caplen;
00139 const bool swapped = frm.swapped();
00140 const size_t phy_len = phy->len(caplen, swapped);
00141
00142 const uint8_t* const mac =
00143 reinterpret_cast<const uint8_t*> (phy->decapsulate(caplen,
00144 swapped));
00145
00146 const dissector<hooks> d (mac, caplen - phy_len);
00147 const hooks& h = d.hooks();
00148
00149 const size_t anon_caplen = (h.end?
00150 h.end - mac + phy_len:
00151 caplen);
00152 pcapxx::pkthdr* const anon_pcap = new pcapxx::pkthdr (*pcap);
00153 uint8_t* const anon_bytes = new uint8_t[anon_caplen];
00154
00155 memcpy(anon_bytes, phy, anon_caplen);
00156 anonymize_addrs(phy_u8, h.addrs, anon_bytes, anon_caplen);
00157 anon_pcap->caplen =
00158 anonymize_ssid(frm, h.ssid, anon_bytes, anon_caplen);
00159
00160 this->value() = value_type (pkthdr_ptr (anon_pcap),
00161 bytes_ptr (anon_bytes), frm.id());
00162 ++next_;
00163 }
00164
00165 template <class I, class P, class A, class B1, class B2>
00166 void
00167 anonymizer_iterator<I, P, A, B1, B2>::
00168 anonymize_addrs(const uint8_t* const phy,
00169 const std::set<const addr*>& addrs,
00170 uint8_t* const anon_bytes,
00171 const size_t anon_caplen)
00172 {
00173 BOOST_FOREACH(const addr* a, addrs)
00174 {
00175 const ptrdiff_t offset = (reinterpret_cast<const uint8_t*>(a) -
00176 phy);
00177 addr* const anon_addr = reinterpret_cast<addr*>
00178 (anon_bytes + offset);
00179
00180 if (offset + sizeof (*anon_addr) <= anon_caplen)
00181 *anon_addr = (*this)[*a];
00182 }
00183 }
00184
00185 template <class I, class P, class A, class B1, class B2>
00186 size_t
00187 anonymizer_iterator<I, P, A, B1, B2>::
00188 anonymize_ssid(const typename I::value_type& frm,
00189 const ssid_elt* const ssid,
00190 uint8_t* const anon_bytes,
00191 const size_t anon_caplen)
00192 {
00193 if (not ssid)
00194 return anon_caplen;
00195 if (ssid->elt_id != 0)
00196 {
00197 std::cerr << frm << ": SSID element ID not found, skipping ("
00198 << unsigned (ssid->elt_id) << " instead of 0)."
00199 << std::endl;
00200 return anon_caplen;
00201 }
00202
00203 const size_t& caplen = frm.pcap_header()->caplen;
00204 const uint8_t* const phy = frm.bytes().get();
00205 const ptrdiff_t ssid_offset = ssid->ssid - phy;
00206
00207 size_t ssid_len = ssid->length;
00208
00209 if (ssid_offset > anon_caplen)
00210 return anon_caplen;
00211
00212 if (ssid_len > 32)
00213 {
00214 std::cerr << frm << ": Invalid SSID length of " << ssid_len
00215 << ", truncating frame (should be between 0 and 32)."
00216 << std::endl;
00217 return ssid_offset;
00218 }
00219
00220 if (ssid->ssid + ssid_len > phy + caplen)
00221 {
00222 std::cerr << frm << ": SSID overruns captured bytes, truncating."
00223 << std::endl;
00224 ssid_len = caplen - (ssid->ssid - phy);
00225 }
00226
00227 const essid ssid_str (*ssid, ssid_len);
00228 essid anon_ssid_str = (*this)[ssid_str];
00229
00230 if (anon_ssid_str.size() > ssid_len)
00231 throw std::runtime_error ("Anonymized ESSID is too big");
00232 anon_ssid_str.append(ssid_len - anon_ssid_str.size(), '\0');
00233
00234 if (ssid_offset + ssid_len > anon_caplen)
00235 ssid_len = anon_caplen - ssid_offset;
00236 memcpy(anon_bytes + ssid_offset, anon_ssid_str.data(), ssid_len);
00237
00238 return anon_caplen;
00239 }
00240
00241
00242
00243
00244
00245 template <class I, class P, class A, class B1, class B2>
00246 anonymizer_iterator<I, P, A, B1, B2>::hooks::hooks():
00247 ty (type::reserved),
00248 end (0),
00249 ssid (0)
00250 {
00251 }
00252
00253 template <class I, class P, class A, class B1, class B2>
00254 void
00255 anonymizer_iterator<I, P, A, B1, B2>::
00256 hooks::addr_hook(const void* f, size_t, unsigned n, const addr& a)
00257 {
00258 if (n == 1)
00259 ty = type_of(f);
00260
00261 addrs.insert(&a);
00262 }
00263
00264 template <class I, class P, class A, class B1, class B2>
00265 void
00266 anonymizer_iterator<I, P, A, B1, B2>::
00267 hooks::end_of_frame_headers_hook(const void* f,
00268 size_t, const void* eofh)
00269 {
00270 const uint8_t* const eofh_u8 = static_cast<const uint8_t*> (eofh);
00271
00272 switch (ty)
00273 {
00274 case type::data:
00275 end = eofh_u8;
00276 break;
00277
00278 case type::management:
00279 switch (subtype_of(f))
00280 {
00281 case mgt::subtype::assoc_req:
00282
00283 ssid = reinterpret_cast<const ssid_elt*> (eofh_u8 + 4);
00284 break;
00285
00286 case mgt::subtype::reassoc_req:
00287
00288 ssid = reinterpret_cast<const ssid_elt*> (eofh_u8 + 10);
00289 break;
00290
00291 case mgt::subtype::probe_req:
00292 ssid = static_cast<const ssid_elt*> (eofh);
00293 break;
00294
00295 case mgt::subtype::probe_resp:
00296 case mgt::subtype::beacon:
00297
00298 ssid = reinterpret_cast<const ssid_elt*> (eofh_u8 + 12);
00299 break;
00300 }
00301 break;
00302 }
00303 }
00304
00305 }
00306
00307
00308 template <class I, class P, class A, class B>
00309 anonymizer<I, P, A, B>::anonymizer(const I& first, const I& last,
00310 const A& anon_policy):
00311 A (anon_policy),
00312 first_ (first),
00313 last_ (last)
00314 {
00315 }
00316
00317 }
00318
00319 }
00320
00321 }
00322
00323 #endif // ! WIFI_FRAME_FILTER_ANONYMIZER_HXX_