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 dissector<hooks> d;
00146 const hooks& h = d.hooks();
00147
00148 if (mac)
00149 {
00150 assert(caplen >= phy_len);
00151 d(mac, caplen - phy_len);
00152 }
00153
00154 const size_t anon_caplen = (h.end?
00155 h.end - mac + phy_len:
00156 caplen);
00157 pcapxx::pkthdr* const anon_pcap = new pcapxx::pkthdr (*pcap);
00158 uint8_t* const anon_bytes = new uint8_t[anon_caplen];
00159
00160 memcpy(anon_bytes, phy, anon_caplen);
00161 anonymize_addrs(phy_u8, h.addrs, anon_bytes, anon_caplen);
00162 anon_pcap->caplen =
00163 anonymize_ssid(frm, h.ssid, anon_bytes, anon_caplen);
00164
00165 this->value() = value_type (pkthdr_ptr (anon_pcap),
00166 bytes_ptr (anon_bytes), frm.id());
00167 ++next_;
00168 }
00169
00170 template <class I, class P, class A, class B1, class B2>
00171 void
00172 anonymizer_iterator<I, P, A, B1, B2>::
00173 anonymize_addrs(const uint8_t* const phy,
00174 const std::set<const addr*>& addrs,
00175 uint8_t* const anon_bytes,
00176 const size_t anon_caplen)
00177 {
00178 BOOST_FOREACH(const addr* a, addrs)
00179 {
00180 const ptrdiff_t offset = (reinterpret_cast<const uint8_t*>(a) -
00181 phy);
00182 addr* const anon_addr = reinterpret_cast<addr*>
00183 (anon_bytes + offset);
00184
00185 if (offset + sizeof (*anon_addr) <= anon_caplen)
00186 *anon_addr = (*this)[*a];
00187 }
00188 }
00189
00190 template <class I, class P, class A, class B1, class B2>
00191 size_t
00192 anonymizer_iterator<I, P, A, B1, B2>::
00193 anonymize_ssid(const typename I::value_type& frm,
00194 const ssid_elt* const ssid,
00195 uint8_t* const anon_bytes,
00196 const size_t anon_caplen)
00197 {
00198 if (not ssid)
00199 return anon_caplen;
00200 if (ssid->elt_id != 0)
00201 {
00202 std::cerr << frm << ": SSID element ID not found, skipping ("
00203 << unsigned (ssid->elt_id) << " instead of 0)."
00204 << std::endl;
00205 return anon_caplen;
00206 }
00207
00208 const size_t& caplen = frm.pcap_header()->caplen;
00209 const uint8_t* const phy = frm.bytes().get();
00210 const ptrdiff_t ssid_offset = ssid->ssid - phy;
00211
00212 size_t ssid_len = ssid->length;
00213
00214 if (ssid_offset > ptrdiff_t (anon_caplen))
00215 return anon_caplen;
00216
00217 if (ssid_len > 32)
00218 {
00219 std::cerr << frm << ": Invalid SSID length of " << ssid_len
00220 << ", truncating frame (should be between 0 and 32)."
00221 << std::endl;
00222 return ssid_offset;
00223 }
00224
00225 if (ssid->ssid + ssid_len > phy + caplen)
00226 {
00227 std::cerr << frm << ": SSID overruns captured bytes, truncating."
00228 << std::endl;
00229 ssid_len = caplen - (ssid->ssid - phy);
00230 }
00231
00232 const essid ssid_str (*ssid, ssid_len);
00233 essid anon_ssid_str = (*this)[ssid_str];
00234
00235 if (anon_ssid_str.size() > ssid_len)
00236 throw std::runtime_error ("Anonymized ESSID is too big");
00237 anon_ssid_str.append(ssid_len - anon_ssid_str.size(), '\0');
00238
00239 if (ssid_offset + ssid_len > anon_caplen)
00240 ssid_len = anon_caplen - ssid_offset;
00241 memcpy(anon_bytes + ssid_offset, anon_ssid_str.data(), ssid_len);
00242
00243 return anon_caplen;
00244 }
00245
00246
00247
00248
00249
00250 template <class I, class P, class A, class B1, class B2>
00251 anonymizer_iterator<I, P, A, B1, B2>::hooks::hooks():
00252 ty (type::reserved),
00253 end (0),
00254 ssid (0)
00255 {
00256 }
00257
00258 template <class I, class P, class A, class B1, class B2>
00259 void
00260 anonymizer_iterator<I, P, A, B1, B2>::
00261 hooks::addr_hook(const void* f, size_t, unsigned n, const addr& a)
00262 {
00263 if (n == 1)
00264 ty = type_of(f);
00265
00266 addrs.insert(&a);
00267 }
00268
00269 template <class I, class P, class A, class B1, class B2>
00270 void
00271 anonymizer_iterator<I, P, A, B1, B2>::
00272 hooks::end_of_frame_headers_hook(const void* f, size_t caplen,
00273 const void* eofh)
00274 {
00275 const uint8_t* const eofh_u8 = static_cast<const uint8_t*> (eofh);
00276 const uint8_t* const eof = static_cast<const uint8_t*> (f) + caplen;
00277 const uint8_t* tmp_ssid = 0;
00278
00279 switch (ty)
00280 {
00281 case type::data:
00282 end = eofh_u8;
00283 break;
00284
00285 case type::management:
00286 switch (subtype_of(f))
00287 {
00288 case mgt::subtype::assoc_req:
00289
00290 tmp_ssid = eofh_u8 + 4;
00291 break;
00292
00293 case mgt::subtype::reassoc_req:
00294
00295 tmp_ssid = eofh_u8 + 10;
00296 break;
00297
00298 case mgt::subtype::probe_req:
00299 tmp_ssid = eofh_u8;
00300 break;
00301
00302 case mgt::subtype::probe_resp:
00303 case mgt::subtype::beacon:
00304
00305 tmp_ssid = eofh_u8 + 12;
00306 break;
00307 }
00308 break;
00309
00310 default:
00311 break;
00312 }
00313 if (tmp_ssid and tmp_ssid + sizeof (ssid_elt) < eof)
00314 ssid = reinterpret_cast<const ssid_elt*> (tmp_ssid);
00315 }
00316
00317 }
00318
00319
00320 template <class I, class P, class A, class B>
00321 anonymizer<I, P, A, B>::anonymizer(const I& first, const I& last,
00322 const A& anon_policy):
00323 A (anon_policy),
00324 first_ (first),
00325 last_ (last)
00326 {
00327 }
00328
00329 }
00330
00331 }
00332
00333 }
00334
00335 #endif // ! WIFI_FRAME_FILTER_ANONYMIZER_HXX_