From 5345b29f8cec858580eb410cff08b71707fce2b2 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Mon, 4 Nov 2013 23:05:00 -0300 Subject: [PATCH] Added support for IPSec. --- Makefile.am | 5 +- Makefile.in | 20 +++- include/internals.h | 2 +- include/ipsec.h | 264 ++++++++++++++++++++++++++++++++++++++++++++ include/pdu.h | 2 + src/internals.cpp | 26 +++++ src/ip.cpp | 29 +---- src/ipsec.cpp | 135 ++++++++++++++++++++++ src/ipv6.cpp | 30 +---- tests/depends.d | 52 ++++++++- tests/src/ipsec.cpp | 171 ++++++++++++++++++++++++++++ 11 files changed, 679 insertions(+), 57 deletions(-) create mode 100644 include/ipsec.h create mode 100644 src/ipsec.cpp create mode 100644 tests/src/ipsec.cpp diff --git a/Makefile.am b/Makefile.am index 98b6fcd..adb943d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,9 +28,11 @@ libtins_la_SOURCES=src/arp.cpp \ src/icmp.cpp \ src/icmpv6.cpp \ src/internals.cpp \ - src/ip.cpp src/ip_address.cpp \ + src/ip.cpp \ + src/ip_address.cpp \ src/ipv6.cpp \ src/ipv6_address.cpp \ + src/ipsec.cpp \ src/llc.cpp \ src/loopback.cpp \ src/network_interface.cpp \ @@ -67,6 +69,7 @@ libtins_HEADERS = include/internals.h \ include/dot3.h \ include/small_uint.h \ include/ip.h \ + include/ipsec.h \ include/dns_record.h \ include/eapol.h \ include/tcp_stream.h \ diff --git a/Makefile.in b/Makefile.in index 9ee3881..ad1168a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -112,11 +112,12 @@ am_libtins_la_OBJECTS = src/arp.lo src/bootp.lo \ src/dns_record.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/ppi.lo \ - src/pdu.lo src/radiotap.lo src/address_range.lo src/rawpdu.lo \ - src/rsn_information.lo src/sll.lo src/snap.lo src/sniffer.lo \ - src/tcp.lo src/tcp_stream.lo src/udp.lo src/utils.lo \ + src/ipsec.lo src/llc.lo src/loopback.lo \ + src/network_interface.lo src/packet_sender.lo \ + src/packet_writer.lo src/ppi.lo src/pdu.lo src/radiotap.lo \ + src/address_range.lo src/rawpdu.lo src/rsn_information.lo \ + src/sll.lo src/snap.lo src/sniffer.lo src/tcp.lo \ + src/tcp_stream.lo src/udp.lo src/utils.lo \ src/dot11/dot11_base.lo src/dot11/dot11_data.lo \ src/dot11/dot11_mgmt.lo src/dot11/dot11_beacon.lo \ src/dot11/dot11_assoc.lo src/dot11/dot11_auth.lo \ @@ -316,9 +317,11 @@ libtins_la_SOURCES = src/arp.cpp \ src/icmp.cpp \ src/icmpv6.cpp \ src/internals.cpp \ - src/ip.cpp src/ip_address.cpp \ + src/ip.cpp \ + src/ip_address.cpp \ src/ipv6.cpp \ src/ipv6_address.cpp \ + src/ipsec.cpp \ src/llc.cpp \ src/loopback.cpp \ src/network_interface.cpp \ @@ -354,6 +357,7 @@ libtins_HEADERS = include/internals.h \ include/dot3.h \ include/small_uint.h \ include/ip.h \ + include/ipsec.h \ include/dns_record.h \ include/eapol.h \ include/tcp_stream.h \ @@ -528,6 +532,7 @@ src/ip.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/ip_address.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/ipv6.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/ipv6_address.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/ipsec.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/llc.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/loopback.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/network_interface.lo: src/$(am__dirstamp) \ @@ -630,6 +635,8 @@ mostlyclean-compile: -rm -f src/ip.lo -rm -f src/ip_address.$(OBJEXT) -rm -f src/ip_address.lo + -rm -f src/ipsec.$(OBJEXT) + -rm -f src/ipsec.lo -rm -f src/ipv6.$(OBJEXT) -rm -f src/ipv6.lo -rm -f src/ipv6_address.$(OBJEXT) @@ -694,6 +701,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/internals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ip_address.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ipsec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ipv6.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ipv6_address.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/llc.Plo@am__quote@ diff --git a/include/internals.h b/include/internals.h index e1bee6f..4b6d691 100644 --- a/include/internals.h +++ b/include/internals.h @@ -113,10 +113,10 @@ PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer, uint32_t size, bool rawpdu_on_no_match = true); PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer, uint32_t size, bool rawpdu_on_no_match = true); - PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size); Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag); +Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag); template bool increment_buffer(T &addr) { diff --git a/include/ipsec.h b/include/ipsec.h new file mode 100644 index 0000000..92ccba6 --- /dev/null +++ b/include/ipsec.h @@ -0,0 +1,264 @@ +/* + * 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_IPSEC_H +#define TINS_IPSEC_H + +#include "pdu.h" +#include "endianness.h" +#include "small_uint.h" + +namespace Tins { +/** + * \brief Represents an IPSec Authentication Header. + */ +class IPSecAH : public PDU { +public: + /** + * This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::IPSEC_AH; + + /** + * \brief Default constructor. + * + * The ICV field is initialized with four 0 bytes. The length + * field is initialized appropriately. + */ + IPSecAH(); + + /** + * \brief Constructs an IPSecAH object from a buffer and adds all + * identifiable PDUs found in the buffer as children of this + * one. + * + * If there is not enough size for an IPSecAH header, a + * malformed_packet exception is thrown. + * + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + IPSecAH(const uint8_t *buffer, uint32_t total_sz); + + // Getters + + /** + * \brief Getter for the Next header field. + * \return The stored Next header field value. + */ + uint8_t next_header() const { + return _header.next_header; + } + + /** + * \brief Getter for the Length field. + * \return The stored Length field value. + */ + uint8_t length() const { + return _header.length; + } + + /** + * \brief Getter for the Security Parameters Index field. + * \return The stored Security Parameters Index field value. + */ + uint32_t spi() const { + return Endian::be_to_host(_header.spi); + } + + /** + * \brief Getter for the Sequence number field. + * \return The stored Sequence number field value. + */ + uint32_t seq_number() const { + return Endian::be_to_host(_header.seq_number); + } + + /** + * \brief Getter for the ICV field. + * \return The stored ICV field value. + */ + const byte_array &icv() const { + return _icv; + } + + // Setters + + /** + * \brief Setter for the Next header field. + * \param new_next_header The new Next header field value. + */ + void next_header(uint8_t new_next_header); + + /** + * \brief Setter for the Length field. + * \param new_length The new Length field value. + */ + void length(uint8_t new_length); + + /** + * \brief Setter for the Security Parameters Index field. + * \param new_spi The new Security Parameters Index field value. + */ + void spi(uint32_t new_spi); + + /** + * \brief Setter for the Sequence number field. + * \param new_seq_number The new Sequence number field value. + */ + void seq_number(uint32_t new_seq_number); + + /** + * \brief Setter for the ICV field. + * \param new_icv The new ICV field value. + */ + void icv(const byte_array &new_icv); + + /** + * \brief Returns the header size. + * + * This metod overrides PDU::header_size. \sa PDU::header_size + */ + uint32_t header_size() const; + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return pdu_flag; } + + /** + * \sa PDU::clone + */ + IPSecAH *clone() const { + return new IPSecAH(*this); + } +private: + struct header { + uint8_t next_header, length; + uint32_t spi, seq_number; + }; + + void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *); + + header _header; + byte_array _icv; +}; + +/** + * \brief Represents an IPSec Authentication Header. + */ +class IPSecESP : public PDU { +public: + /** + * This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::IPSEC_ESP; + + /** + * \brief Default constructor. + */ + IPSecESP(); + + /** + * \brief Constructs an IPSecESP object from a buffer and adds all + * identifiable PDUs found in the buffer as children of this + * one. + * + * If there is not enough size for an IPSecESP header, a + * malformed_packet exception is thrown. + * + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + IPSecESP(const uint8_t *buffer, uint32_t total_sz); + + // Getters + + /** + * \brief Getter for the Security Parameters Index field. + * \return The stored Security Parameters Index field value. + */ + uint32_t spi() const { + return Endian::be_to_host(_header.spi); + } + + /** + * \brief Getter for the Sequence number field. + * \return The stored Sequence number field value. + */ + uint32_t seq_number() const { + return Endian::be_to_host(_header.seq_number); + } + + // Setters + + /** + * \brief Setter for the Security Parameters Index field. + * \param new_spi The new Security Parameters Index field value. + */ + void spi(uint32_t new_spi); + + /** + * \brief Setter for the Sequence number field. + * \param new_seq_number The new Sequence number field value. + */ + void seq_number(uint32_t new_seq_number); + + /** + * \brief Returns the header size. + * + * This metod overrides PDU::header_size. \sa PDU::header_size + */ + uint32_t header_size() const; + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return pdu_flag; } + + /** + * \sa PDU::clone + */ + IPSecESP *clone() const { + return new IPSecESP(*this); + } +private: + struct header { + uint32_t spi, seq_number; + }; + + void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *); + + header _header; +}; +} + +#endif // TINS_IPSEC_H diff --git a/include/pdu.h b/include/pdu.h index f6f5a49..db56abe 100644 --- a/include/pdu.h +++ b/include/pdu.h @@ -119,6 +119,8 @@ namespace Tins { PPPOE, STP, PPI, + IPSEC_AH, + IPSEC_ESP, USER_DEFINED_PDU = 1000 }; diff --git a/src/internals.cpp b/src/internals.cpp index 66e04f6..d2dc7bb 100644 --- a/src/internals.cpp +++ b/src/internals.cpp @@ -36,6 +36,7 @@ #include "ipv6.h" #include "tcp.h" #include "udp.h" +#include "ipsec.h" #include "icmp.h" #include "icmpv6.h" #include "arp.h" @@ -120,6 +121,10 @@ Tins::PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer, return new Tins::ICMPv6(buffer, size); case Constants::IP::PROTO_IPV6: return new Tins::IPv6(buffer, size); + case Constants::IP::PROTO_AH: + return new Tins::IPSecAH(buffer, size); + case Constants::IP::PROTO_ESP: + return new Tins::IPSecESP(buffer, size); default: break; } @@ -194,6 +199,27 @@ Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) { } } +Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag) { + switch(flag) { + case PDU::IP: + return Constants::IP::PROTO_IPIP; + case PDU::TCP: + return Constants::IP::PROTO_TCP; + case PDU::UDP: + return Constants::IP::PROTO_UDP; + case PDU::ICMP: + return Constants::IP::PROTO_ICMP; + case PDU::ICMPv6: + return Constants::IP::PROTO_ICMPV6; + case PDU::IPSEC_AH: + return Constants::IP::PROTO_AH; + case PDU::IPSEC_ESP: + return Constants::IP::PROTO_ESP; + default: + return static_cast(0xff); + }; +} + bool increment(IPv4Address &addr) { uint32_t addr_int = Endian::be_to_host(addr); bool reached_end = ++addr_int == 0xffffffff; diff --git a/src/ip.cpp b/src/ip.cpp index cd1179e..d40755f 100644 --- a/src/ip.cpp +++ b/src/ip.cpp @@ -385,29 +385,12 @@ void IP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU* pare #endif checksum(0); if(inner_pdu()) { - uint32_t new_flag; - switch(inner_pdu()->pdu_type()) { - case PDU::IP: - new_flag = Constants::IP::PROTO_IPIP; - break; - case PDU::TCP: - new_flag = Constants::IP::PROTO_TCP; - break; - case PDU::UDP: - new_flag = Constants::IP::PROTO_UDP; - break; - case PDU::ICMP: - new_flag = Constants::IP::PROTO_ICMP; - break; - default: - if(Internals::pdu_type_registered(inner_pdu()->pdu_type())) - new_flag = static_cast( - Internals::pdu_type_to_id(inner_pdu()->pdu_type()) - ); - else - // check for other protos - new_flag = 0xff; - }; + uint32_t new_flag = Internals::pdu_flag_to_ip_type(inner_pdu()->pdu_type()); + if(new_flag == 0xff && Internals::pdu_type_registered(inner_pdu()->pdu_type())) { + new_flag = static_cast( + Internals::pdu_type_to_id(inner_pdu()->pdu_type()) + ); + } protocol(new_flag); //flag(new_flag); } diff --git a/src/ipsec.cpp b/src/ipsec.cpp new file mode 100644 index 0000000..4926cf9 --- /dev/null +++ b/src/ipsec.cpp @@ -0,0 +1,135 @@ +/* + * 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 +#include "ipsec.h" +#include "internals.h" +#include "rawpdu.h" + +namespace Tins { + +IPSecAH::IPSecAH() +: _header(), _icv(4) { + length(2); +} + +IPSecAH::IPSecAH(const uint8_t *buffer, uint32_t total_sz) { + // At least size for the header + 32bits of ICV + if(total_sz < sizeof(_header) + sizeof(uint32_t)) + throw malformed_packet(); + std::memcpy(&_header, buffer, sizeof(_header)); + const uint32_t ah_len = 4 * (static_cast(length()) + 2); + if(ah_len > total_sz) + throw malformed_packet(); + _icv.assign(buffer + sizeof(_header), buffer + ah_len); + buffer += ah_len; + total_sz -= ah_len; + if(total_sz) { + inner_pdu( + Internals::pdu_from_flag( + static_cast(next_header()), + buffer, + total_sz, + true + ) + ); + } +} + +void IPSecAH::next_header(uint8_t new_next_header) { + _header.next_header = new_next_header; +} + +void IPSecAH::length(uint8_t new_length) { + _header.length = new_length; +} + +void IPSecAH::spi(uint32_t new_spi) { + _header.spi = Endian::host_to_be(new_spi); +} + +void IPSecAH::seq_number(uint32_t new_seq_number) { + _header.seq_number = Endian::host_to_be(new_seq_number); +} + +void IPSecAH::icv(const byte_array &new_icv) { + _icv = new_icv; +} + +uint32_t IPSecAH::header_size() const { + return sizeof(_header) + _icv.size(); +} + +void IPSecAH::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { + if(inner_pdu()) + next_header(Internals::pdu_flag_to_ip_type(inner_pdu()->pdu_type())); + std::memcpy(buffer, &_header, sizeof(_header)); + std::copy( + _icv.begin(), + _icv.end(), + buffer + sizeof(_header) + ); +} + +// IPSecESP + +IPSecESP::IPSecESP() +: _header() +{ + +} + +IPSecESP::IPSecESP(const uint8_t *buffer, uint32_t total_sz) { + if(total_sz < sizeof(_header)) + throw malformed_packet(); + std::memcpy(&_header, buffer, sizeof(_header)); + buffer += sizeof(_header); + total_sz -= sizeof(_header); + if(total_sz) { + inner_pdu(new RawPDU(buffer, total_sz)); + } +} + +void IPSecESP::spi(uint32_t new_spi) { + _header.spi = Endian::host_to_be(new_spi); +} + +void IPSecESP::seq_number(uint32_t new_seq_number) { + _header.seq_number = Endian::host_to_be(new_seq_number); +} + +uint32_t IPSecESP::header_size() const { + return sizeof(_header); +} + +void IPSecESP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { + std::memcpy(buffer, &_header, sizeof(_header)); +} + +} diff --git a/src/ipv6.cpp b/src/ipv6.cpp index 62e79ea..8959d07 100644 --- a/src/ipv6.cpp +++ b/src/ipv6.cpp @@ -200,30 +200,12 @@ void IPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *pa assert(total_sz >= header_size()); #endif if(inner_pdu()) { - uint8_t new_flag = 0xff; - switch(inner_pdu()->pdu_type()) { - case PDU::IP: - new_flag = Constants::IP::PROTO_IPIP; - break; - case PDU::TCP: - new_flag = Constants::IP::PROTO_TCP; - break; - case PDU::UDP: - new_flag = Constants::IP::PROTO_UDP; - break; - case PDU::ICMP: - new_flag = Constants::IP::PROTO_ICMP; - break; - case PDU::ICMPv6: - new_flag = Constants::IP::PROTO_ICMPV6; - break; - default: - if(Internals::pdu_type_registered(inner_pdu()->pdu_type())) - new_flag = static_cast( - Internals::pdu_type_to_id(inner_pdu()->pdu_type()) - ); - break; - }; + uint8_t new_flag = Internals::pdu_flag_to_ip_type(inner_pdu()->pdu_type()); + if(new_flag == 0xff && Internals::pdu_type_registered(inner_pdu()->pdu_type())) { + new_flag = static_cast( + Internals::pdu_type_to_id(inner_pdu()->pdu_type()) + ); + } set_last_next_header(new_flag); } payload_length(total_sz - sizeof(_header)); diff --git a/tests/depends.d b/tests/depends.d index fce9bdc..b01ceb9 100644 --- a/tests/depends.d +++ b/tests/depends.d @@ -901,7 +901,8 @@ ../include/dot11/../pdu_option.h ../include/dot11/../small_uint.h \ ../include/dot11/../hw_address.h ../include/dot11/../endianness.h \ ../include/dot11/../cxxstd.h ../include/dot11/../macros.h \ - ../include/ipv6.h ../include/ipv6_address.h ../include/arp.h \ + ../include/ipv6.h ../include/ipv6_address.h ../include/tcp.h \ + ../include/udp.h ../include/icmp.h ../include/icmpv6.h ../include/arp.h \ ../include/eapol.h ../include/rawpdu.h ../include/dot1q.h \ ../include/pppoe.h ../include/ip_address.h ../include/ipv6_address.h \ ../include/pdu_allocator.h @@ -958,6 +959,14 @@ ../include/ipv6_address.h: +../include/tcp.h: + +../include/udp.h: + +../include/icmp.h: + +../include/icmpv6.h: + ../include/arp.h: ../include/eapol.h: @@ -1060,6 +1069,23 @@ ../include/exceptions.h: ../include/hw_address.h: +../src/ipsec.o: ../src/ipsec.cpp ../include/ipsec.h ../include/pdu.h \ + ../include/macros.h ../include/cxxstd.h ../include/exceptions.h \ + ../include/endianness.h ../include/small_uint.h + +../include/ipsec.h: + +../include/pdu.h: + +../include/macros.h: + +../include/cxxstd.h: + +../include/exceptions.h: + +../include/endianness.h: + +../include/small_uint.h: ../src/ipv6.o: ../src/ipv6.cpp ../include/ipv6.h ../include/macros.h \ ../include/pdu.h ../include/cxxstd.h ../include/exceptions.h \ ../include/endianness.h ../include/small_uint.h ../include/pdu_option.h \ @@ -1067,7 +1093,8 @@ ../include/packet_sender.h ../include/network_interface.h \ ../include/hw_address.h ../include/ip_address.h ../include/ip.h \ ../include/tcp.h ../include/udp.h ../include/icmp.h ../include/icmpv6.h \ - ../include/rawpdu.h ../include/exceptions.h ../include/pdu_allocator.h + ../include/rawpdu.h ../include/exceptions.h ../include/pdu_allocator.h \ + ../include/internals.h ../include/constants.h ../include/ipv6.h: @@ -1112,6 +1139,10 @@ ../include/exceptions.h: ../include/pdu_allocator.h: + +../include/internals.h: + +../include/constants.h: ../src/ipv6_address.o: ../src/ipv6_address.cpp ../include/macros.h \ ../include/ipv6_address.h ../include/cxxstd.h ../include/address_range.h \ ../include/endianness.h ../include/macros.h ../include/internals.h \ @@ -3126,6 +3157,23 @@ src/ipaddress.o: src/ipaddress.cpp ../include/ip_address.h \ ../include/pdu.h: ../include/exceptions.h: +src/ipsec.o: src/ipsec.cpp ../include/ipsec.h ../include/pdu.h \ + ../include/macros.h ../include/cxxstd.h ../include/exceptions.h \ + ../include/endianness.h ../include/small_uint.h + +../include/ipsec.h: + +../include/pdu.h: + +../include/macros.h: + +../include/cxxstd.h: + +../include/exceptions.h: + +../include/endianness.h: + +../include/small_uint.h: src/ipv6.o: src/ipv6.cpp ../include/ipv6.h ../include/macros.h \ ../include/pdu.h ../include/cxxstd.h ../include/exceptions.h \ ../include/endianness.h ../include/small_uint.h ../include/pdu_option.h \ diff --git a/tests/src/ipsec.cpp b/tests/src/ipsec.cpp new file mode 100644 index 0000000..19077b1 --- /dev/null +++ b/tests/src/ipsec.cpp @@ -0,0 +1,171 @@ +#include +#include +#include "ipsec.h" +#include "ethernetII.h" +#include "rawpdu.h" + +using namespace Tins; + +class IPSecAHTest : public testing::Test { +public: + static const uint8_t expected_packet[]; +}; + +class IPSecESPTest : public testing::Test { +public: + static const uint8_t expected_packet[]; +}; + +const uint8_t whole_packet[] = { + 194, 1, 87, 117, 0, 0, 194, 0, 87, 117, 0, 0, 8, 0, 69, 0, 0, 180, + 0, 107, 0, 0, 255, 51, 166, 169, 10, 0, 0, 1, 10, 0, 0, 2, 50, 4, 0, + 0, 129, 121, 183, 5, 0, 0, 0, 1, 39, 207, 192, 165, 228, 61, 105, + 179, 114, 142, 197, 176, 72, 218, 194, 228, 0, 0, 0, 1, 7, 65, 190, + 127, 138, 222, 64, 192, 43, 216, 26, 238, 15, 80, 111, 44, 70, 220, + 189, 73, 172, 173, 48, 187, 90, 9, 112, 128, 195, 214, 136, 212, + 155, 95, 34, 92, 232, 113, 132, 209, 249, 248, 173, 98, 103, 250, + 26, 162, 24, 151, 15, 209, 53, 182, 153, 55, 36, 84, 68, 95, 107, + 211, 204, 25, 177, 95, 183, 1, 178, 52, 217, 74, 7, 236, 107, 252, + 45, 61, 19, 53, 179, 1, 53, 102, 180, 116, 215, 195, 37, 155, 127, + 228, 185, 34, 165, 191, 163, 208, 144, 200, 154, 155, 109, 106, 183, + 242, 186, 17, 255, 199, 163, 135, 182, 5, 88, 122, 36, 168, 41, 156, + 125, 137, 194, 33, 153, 161, 189, 0 +}; + +const uint8_t IPSecAHTest::expected_packet[] = { + 50, 4, 0, 0, 129, 121, 183, 5, 0, 0, 0, 1, 39, 207, 192, 165, 228, + 61, 105, 179, 114, 142, 197, 176, 72, 218, 194, 228, 0, 0, 0, 1, 7, + 65, 190, 127, 138, 222, 64, 192, 43, 216, 26, 238, 15, 80, 111, 44, + 70, 220, 189, 73, 172, 173, 48, 187, 90, 9, 112, 128, 195, 214, 136, + 212, 155, 95, 34, 92, 232, 113, 132, 209, 249, 248, 173, 98, 103, + 250, 26, 162, 24, 151, 15, 209, 53, 182, 153, 55, 36, 84, 68, 95, + 107, 211, 204, 25, 177, 95, 183, 1, 178, 52, 217, 74, 7, 236, 107, + 252, 45, 61, 19, 53, 179, 1, 53, 102, 180, 116, 215, 195, 37, 155, + 127, 228, 185, 34, 165, 191, 163, 208, 144, 200, 154, 155, 109, 106, + 183, 242, 186, 17, 255, 199, 163, 135, 182, 5, 88, 122, 36, 168, 41, + 156, 125, 137, 194, 33, 153, 161, 189, 0 +}; + +const uint8_t IPSecESPTest::expected_packet[] = { + 72, 218, 194, 228, 0, 0, 0, 1, 7, 65, 190, 127, 138, 222, 64, 192, + 43, 216, 26, 238, 15, 80, 111, 44, 70, 220, 189, 73, 172, 173, 48, + 187, 90, 9, 112, 128, 195, 214, 136, 212, 155, 95, 34, 92, 232, 113, + 132, 209, 249, 248, 173, 98, 103, 250, 26, 162, 24, 151, 15, 209, + 53, 182, 153, 55, 36, 84, 68, 95, 107, 211, 204, 25, 177, 95, 183, + 1, 178, 52, 217, 74, 7, 236, 107, 252, 45, 61, 19, 53, 179, 1, 53, + 102, 180, 116, 215, 195, 37, 155, 127, 228, 185, 34, 165, 191, 163, + 208, 144, 200, 154, 155, 109, 106, 183, 242, 186, 17, 255, 199, 163, + 135, 182, 5, 88, 122, 36, 168, 41, 156, 125, 137, 194, 33, 153, 161, + 189, 0 +}; + +// AH + +TEST_F(IPSecAHTest, DefaultConstructor) { + IPSecAH ipsec; + EXPECT_EQ(0, ipsec.next_header()); + EXPECT_EQ(2, ipsec.length()); + EXPECT_EQ(0, ipsec.spi()); + EXPECT_EQ(0, ipsec.seq_number()); + EXPECT_EQ(4, ipsec.icv().size()); +} + +TEST_F(IPSecAHTest, EthPacket) { + EthernetII eth(whole_packet, sizeof(whole_packet)); + EXPECT_TRUE(eth.find_pdu()); + EXPECT_TRUE(eth.find_pdu()); + EXPECT_TRUE(eth.find_pdu()); +} + +TEST_F(IPSecAHTest, ConstructorFromBuffer) { + IPSecAH ipsec(expected_packet, sizeof(expected_packet)); + const char *icv_ptr = "\x27\xcf\xc0\xa5\xe4\x3d\x69\xb3\x72\x8e\xc5\xb0"; + EXPECT_EQ(0x32, ipsec.next_header()); + EXPECT_EQ(4, ipsec.length()); + EXPECT_EQ(0x8179b705, ipsec.spi()); + EXPECT_EQ(1, ipsec.seq_number()); + ASSERT_EQ(12, ipsec.icv().size()); + EXPECT_EQ(ipsec.icv(), byte_array(icv_ptr, icv_ptr + 12)); + EXPECT_TRUE(ipsec.find_pdu()); + EXPECT_TRUE(ipsec.find_pdu()); +} + +TEST_F(IPSecAHTest, Serialize) { + IPSecAH ipsec(expected_packet, sizeof(expected_packet)); + EXPECT_EQ( + byte_array(expected_packet, expected_packet + sizeof(expected_packet)), + ipsec.serialize() + ); +} + +TEST_F(IPSecAHTest, NextHeader) { + IPSecAH ipsec; + ipsec.next_header(0x73); + EXPECT_EQ(0x73, ipsec.next_header()); +} + +TEST_F(IPSecAHTest, Length) { + IPSecAH ipsec; + ipsec.length(0x73); + EXPECT_EQ(0x73, ipsec.length()); +} + +TEST_F(IPSecAHTest, SPI) { + IPSecAH ipsec; + ipsec.spi(0x73a625fa); + EXPECT_EQ(0x73a625fa, ipsec.spi()); +} + +TEST_F(IPSecAHTest, SeqNumber) { + IPSecAH ipsec; + ipsec.seq_number(0x73a625fa); + EXPECT_EQ(0x73a625fa, ipsec.seq_number()); +} + +TEST_F(IPSecAHTest, ICV) { + IPSecAH ipsec; + byte_array data; + data.push_back(0x29); + data.push_back(0x52); + data.push_back(0x9a); + data.push_back(0x73); + ipsec.icv(data); + EXPECT_EQ(data, ipsec.icv()); +} + + + +// IPSecESP + +TEST_F(IPSecESPTest, DefaultConstructor) { + IPSecESP ipsec; + EXPECT_EQ(0, ipsec.spi()); + EXPECT_EQ(0, ipsec.seq_number()); +} + +TEST_F(IPSecESPTest, ConstructorFromBuffer) { + IPSecESP ipsec(expected_packet, sizeof(expected_packet)); + EXPECT_EQ(0x48dac2e4, ipsec.spi()); + EXPECT_EQ(1, ipsec.seq_number()); + EXPECT_TRUE(ipsec.find_pdu()); +} + +TEST_F(IPSecESPTest, SPI) { + IPSecESP ipsec; + ipsec.spi(0x73a625fa); + EXPECT_EQ(0x73a625fa, ipsec.spi()); +} + +TEST_F(IPSecESPTest, SeqNumber) { + IPSecESP ipsec; + ipsec.seq_number(0x73a625fa); + EXPECT_EQ(0x73a625fa, ipsec.seq_number()); +} + +TEST_F(IPSecESPTest, Serialize) { + IPSecESP ipsec(expected_packet, sizeof(expected_packet)); + EXPECT_EQ( + byte_array(expected_packet, expected_packet + sizeof(expected_packet)), + ipsec.serialize() + ); +}