1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-27 04:11:35 +01:00

Added RSNHandshakeCapturer class.

This commit is contained in:
Matias Fontanini
2013-05-25 18:00:20 -03:00
parent 28c8d393d6
commit 8147a2bfb7
6 changed files with 300 additions and 36 deletions

View File

@@ -13,6 +13,7 @@ AM_CXXFLAGS = -Wall -pedantic -I@LIBTINS_INCLUDE_DIR@
libtins_la_SOURCES=src/arp.cpp \
src/bootp.cpp \
src/handshake_capturer.cpp \
src/stp.cpp \
src/pppoe.cpp \
src/crypto.cpp \
@@ -60,6 +61,7 @@ libtins_include_HEADERS = include/internals.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
include/handshake_capturer.h \
include/ipv6.h \
include/icmpv6.h \
include/ieee802_3.h \

View File

@@ -58,8 +58,9 @@ subdir = .
DIST_COMMON = README $(am__configure_deps) $(libtins_include_HEADERS) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/libtins.pc.in $(top_srcdir)/configure \
$(top_srcdir)/include/config.h.in AUTHORS THANKS TODO \
config.guess config.sub depcomp install-sh ltmain.sh missing
$(top_srcdir)/include/config.h.in AUTHORS COPYING INSTALL \
THANKS TODO config.guess config.sub depcomp install-sh \
ltmain.sh missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx_11.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
@@ -105,12 +106,13 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
LTLIBRARIES = $(lib_LTLIBRARIES)
libtins_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp
am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo src/stp.lo \
src/pppoe.lo src/crypto.lo src/dhcp.lo src/dhcpv6.lo \
src/dns.lo src/dns_record.lo src/dot11.lo src/dot3.lo \
src/dot1q.lo src/eapol.lo src/ethernetII.lo src/icmp.lo \
src/icmpv6.lo src/internals.lo src/ip.lo src/ip_address.lo \
src/ipv6.lo src/ipv6_address.lo src/llc.lo src/loopback.lo \
am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo \
src/handshake_capturer.lo src/stp.lo src/pppoe.lo \
src/crypto.lo src/dhcp.lo src/dhcpv6.lo src/dns.lo \
src/dns_record.lo src/dot11.lo src/dot3.lo src/dot1q.lo \
src/eapol.lo src/ethernetII.lo src/icmp.lo src/icmpv6.lo \
src/internals.lo src/ip.lo src/ip_address.lo src/ipv6.lo \
src/ipv6_address.lo src/llc.lo src/loopback.lo \
src/network_interface.lo src/packet_sender.lo \
src/packet_writer.lo src/pdu.lo src/radiotap.lo src/rawpdu.lo \
src/rsn_information.lo src/sll.lo src/snap.lo src/sniffer.lo \
@@ -295,6 +297,7 @@ libtins_la_LDFLAGS = -version-info @LIBTINS_VERSION@
AM_CXXFLAGS = -Wall -pedantic -I@LIBTINS_INCLUDE_DIR@
libtins_la_SOURCES = src/arp.cpp \
src/bootp.cpp \
src/handshake_capturer.cpp \
src/stp.cpp \
src/pppoe.cpp \
src/crypto.cpp \
@@ -342,6 +345,7 @@ libtins_include_HEADERS = include/internals.h \
include/eapol.h \
include/tcp_stream.h \
include/pppoe.h \
include/handshake_capturer.h \
include/ipv6.h \
include/icmpv6.h \
include/ieee802_3.h \
@@ -477,6 +481,8 @@ src/$(DEPDIR)/$(am__dirstamp):
@: > src/$(DEPDIR)/$(am__dirstamp)
src/arp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/bootp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/handshake_capturer.lo: src/$(am__dirstamp) \
src/$(DEPDIR)/$(am__dirstamp)
src/stp.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/pppoe.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/crypto.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
@@ -545,6 +551,8 @@ mostlyclean-compile:
-rm -f src/eapol.lo
-rm -f src/ethernetII.$(OBJEXT)
-rm -f src/ethernetII.lo
-rm -f src/handshake_capturer.$(OBJEXT)
-rm -f src/handshake_capturer.lo
-rm -f src/icmp.$(OBJEXT)
-rm -f src/icmp.lo
-rm -f src/icmpv6.$(OBJEXT)
@@ -611,6 +619,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dot3.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/eapol.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ethernetII.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/handshake_capturer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/icmp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/icmpv6.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/internals.Plo@am__quote@

View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_HANDSHAKE_CAPTURER_H
#define TINS_HANDSHAKE_CAPTURER_H
#include <vector>
#include <map>
#include <utility>
#include "hw_address.h"
#include "eapol.h"
// .h
namespace Tins {
/**
* \brief Generic EAPOL handshake.
*
* Stores both the client and supplicant addresses, as well as
* all of the EAPOL packets used during the handshake.
*/
template<typename T>
class EAPOLHandshake {
public:
typedef std::vector<T> container_type;
typedef HWAddress<6> address_type;
/**
* Constructs an EAPOLHandshake object.
*
* \param client_address The client address.
* \param supplicant_address The supplicant address.
* \param cont The container that holds the EAPOL packets used
* in the handshake.
*/
EAPOLHandshake(const address_type &client_address,
const address_type &supplicant_address, const container_type &cont)
: cl_address_(client_address), suppl_address_(supplicant_address),
handshake_(cont)
{
}
/**
* \return const address_type&
*/
const address_type &client_address() const {
return cl_address_;
}
/**
* \return const address_type&
*/
const address_type &supplicant_address() const {
return suppl_address_;
}
/**
* \return const container_type&
*/
const container_type &handshake() const {
return handshake_;
}
private:
address_type cl_address_, suppl_address_;
container_type handshake_;
};
/**
* The type used to store RSN handshakes.
*/
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
/**
* Captures 802.1X RSN handshakes.
*/
class RSNHandshakeCapturer {
public:
/**
* The type of handshakes that will be captured.
*/
typedef RSNHandshake handshake_type;
/**
* The type in which all of the captured handshakes
* will be stored.
*/
typedef std::vector<handshake_type> handshakes_type;
/**
* \brief Processes a packet.
*
* This will fetch the RSNEAPOL layer, if any, and store
* it in an intermediate storage. When a handshake is
* completed, it will be stored separately.
*
* \sa RSNHandshakeCapturer::handshakes
*/
bool process_packet(const PDU &pdu);
/**
* \brief Retrieves the completed handshakes.
*
* This will return the handshakes that have been completed
* so far. A handshake is completed when the 4-way handshake
* is captured.
*
* \sa RSNHandshakeCapturer::clear_handshakes
*/
const handshakes_type &handshakes() const {
return completed_handshakes_;
}
/**
* \brief Clears the completed handshakes.
*
* Since completed handshakes are stored in a std::vector,
* it is advisable to remove all of them once they have been
* processed.
*/
void clear_handshakes() {
completed_handshakes_.clear();
}
private:
typedef handshake_type::address_type address_type;
typedef handshake_type::container_type eapol_list;
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
bool do_insert(const handshake_map::key_type &key, const RSNEAPOL *eapol,
size_t expected);
handshake_map handshakes_;
handshakes_type completed_handshakes_;
};
}
#endif // TINS_HANDSHAKE_CAPTURER_H

View File

@@ -345,36 +345,34 @@ void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator en
template<typename DataFunctor, typename EndFunctor>
bool TCPStreamFollower::callback(PDU &pdu, const DataFunctor &data_fun, const EndFunctor &end_fun) {
IP *ip = pdu.find_pdu<IP>();
TCP *tcp = pdu.find_pdu<TCP>();
if(ip && tcp) {
TCPStream::StreamInfo info(
ip->src_addr(), ip->dst_addr(),
tcp->sport(), tcp->dport()
);
sessions_type::iterator it = sessions.find(info);
if(it == sessions.end()) {
std::swap(info.client_addr, info.server_addr);
std::swap(info.client_port, info.server_port);
if((it = sessions.find(info)) == sessions.end()) {
if(tcp->get_flag(TCP::SYN) && !tcp->get_flag(TCP::ACK)) {
sessions.insert(
std::make_pair(
info,
TCPStream(ip, tcp, last_identifier++)
)
);
}
return true;
IP &ip = pdu.rfind_pdu<IP>();
TCP &tcp = pdu.rfind_pdu<TCP>();
TCPStream::StreamInfo info(
ip.src_addr(), ip.dst_addr(),
tcp.sport(), tcp.dport()
);
sessions_type::iterator it = sessions.find(info);
if(it == sessions.end()) {
std::swap(info.client_addr, info.server_addr);
std::swap(info.client_port, info.server_port);
if((it = sessions.find(info)) == sessions.end()) {
if(tcp.get_flag(TCP::SYN) && !tcp.get_flag(TCP::ACK)) {
sessions.insert(
std::make_pair(
info,
TCPStream(&ip, &tcp, last_identifier++)
)
);
}
return true;
}
if(it->second.update(ip, tcp))
data_fun(it->second);
// We're done with this stream
if(it->second.is_finished()) {
end_fun(it->second);
sessions.erase(it);
}
}
if(it->second.update(&ip, &tcp))
data_fun(it->second);
// We're done with this stream
if(it->second.is_finished()) {
end_fun(it->second);
sessions.erase(it);
}
return true;
}

View File

@@ -67,5 +67,6 @@
#include "dhcpv6.h"
#include "pppoe.h"
#include "stp.h"
#include "handshake_capturer.h"
#endif // TINS_TINS_H

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2012, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "handshake_capturer.h"
#include "dot11.h"
namespace Tins {
bool RSNHandshakeCapturer::process_packet(const PDU &pdu) {
const RSNEAPOL *eapol = pdu.find_pdu<RSNEAPOL>();
const Dot11Data *dot11 = pdu.find_pdu<Dot11Data>();
if(!eapol || !dot11)
return false;
std::pair<address_type, address_type> addresses;
if(dot11->to_ds()) {
addresses.first = dot11->addr1();
addresses.second = dot11->addr2();
}
else if(dot11->from_ds()) {
addresses.first = dot11->addr2();
addresses.second = dot11->addr1();
}
else
return false;
// 1st
if(eapol->key_t() && eapol->key_ack() && !eapol->key_mic() && !eapol->install()) {
handshakes_[addresses].assign(eapol, eapol + 1);
}
else if(eapol->key_t() && eapol->key_mic() && !eapol->install() && !eapol->key_ack()) {
if(!eapol->secure())
do_insert(addresses, eapol, 1);
else if(do_insert(addresses, eapol, 3)) {
completed_handshakes_.push_back(
handshake_type(
addresses.first,
addresses.second,
handshakes_[addresses]
)
);
handshakes_.erase(addresses);
return true;
}
}
else if(eapol->key_t() && eapol->install() && eapol->key_ack() && eapol->key_mic()) {
do_insert(addresses, eapol, 2);
}
return false;
}
bool RSNHandshakeCapturer::do_insert(const handshake_map::key_type &key,
const RSNEAPOL *eapol, size_t expected)
{
handshake_map::iterator iter = handshakes_.find(key);
if(iter != handshakes_.end()) {
if(iter->second.size() != expected)
iter->second.clear();
else {
iter->second.push_back(*eapol);
return true;
}
}
return false;
}
} // namespace Tins;