From 8b452263b2ff0a5f10d1e9342aab385b48487020 Mon Sep 17 00:00:00 2001 From: yair Date: Thu, 19 Jul 2018 17:27:52 +0300 Subject: [PATCH 1/2] extra eap packets and dot11_action --- include/tins/dot11.h | 1 + include/tins/dot11/dot11_action.h | 154 +++++++++++++++++ include/tins/dot11/dot11_base.h | 4 +- include/tins/eapol.h | 265 ++++++++++++++++++++++++++---- include/tins/macros.h | 1 + include/tins/pdu.h | 2 + src/CMakeLists.txt | 2 + src/detail/pdu_helpers.cpp | 5 +- src/dot11/dot11_action.cpp | 76 +++++++++ src/dot11/dot11_base.cpp | 4 +- src/eapol.cpp | 150 +++++++++++++++-- 11 files changed, 614 insertions(+), 50 deletions(-) create mode 100644 include/tins/dot11/dot11_action.h create mode 100644 src/dot11/dot11_action.cpp diff --git a/include/tins/dot11.h b/include/tins/dot11.h index 89f2a6a2..c23dc1cf 100644 --- a/include/tins/dot11.h +++ b/include/tins/dot11.h @@ -40,5 +40,6 @@ #include #include #include +#include #endif // TINS_DOT_11 diff --git a/include/tins/dot11/dot11_action.h b/include/tins/dot11/dot11_action.h new file mode 100644 index 00000000..43dec3f5 --- /dev/null +++ b/include/tins/dot11/dot11_action.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2017, 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 + +#if !defined(TINS_DOT11_DOT11_ACTION_H) && defined(TINS_HAVE_DOT11) +#define TINS_DOT11_DOT11_ACTION_H + +#include +#include + +namespace Tins { + +/** + * \brief Represents an IEEE 802.11 Action. + * + */ +class TINS_API Dot11Action : public Dot11ManagementFrame { +public: + /** + * \brief This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::DOT11_ACTION; + + /** + * \brief Enum for the different action categories. + * + */ + enum ActionCategories { + SPECTRUMMANAGEMENT = 0, + QOS, + DLS, + BLOCKACK, + PUBLIC, + RADIOMEASUREMENT, + FASTBSS, + HT, + SAQUERY, + PROTECTEDPUBLIC, + VENDORSPECIFIC=127 + }; + + /** + * \brief Constructor for creating a 802.11 Action. + * + * Constructs a 802.11 Action taking destination, source and a category + * + * \param dst_hw_addr The destination hardware address. + * \param src_hw_addr The source hardware address. + * \param category the action category + */ + Dot11Action(const address_type& dst_hw_addr = address_type(), + const address_type& src_hw_addr = address_type(), + ActionCategories category = ActionCategories::PUBLIC); + + /** + * \brief Constructs a Dot11Action object from a buffer and adds + * all identifiable PDUs found in the buffer as children of this + * one. + * + * If the next PDU is not recognized, then a RawPDU is used. + * + * If there is not enough size for the header in the buffer + * or the input data is malformed, 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. + */ + Dot11Action(const uint8_t* buffer, uint32_t total_sz); + + /** + * \brief Getter for the category field. + * + * \return The stored category value. + */ + ActionCategories category() const { + return static_cast(body_.category); + } + + /** + * \brief Setter for the category field. + * + * \param new_category The category to be set. + */ + void category(ActionCategories new_category); + + uint32_t header_size() const; + + /** + * \brief Check whether this PDU matches the specified flag. + * \param flag The flag to match + * \sa PDU::matches_flag + */ + bool matches_flag(PDUType flag) const { + return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag); + } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone + */ + Dot11Action* clone() const { + return new Dot11Action(*this); + } + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { + return pdu_flag; + } +private: + TINS_BEGIN_PACK + struct dot11_action_body { + uint8_t category; + } TINS_END_PACK; + + void write_fixed_parameters(Memory::OutputMemoryStream& stream); + + dot11_action_body body_; +}; + +} // namespace Tins + +#endif // TINS_DOT11_DOT11_ACTION_H diff --git a/include/tins/dot11/dot11_base.h b/include/tins/dot11/dot11_base.h index a93ec21d..029c7941 100644 --- a/include/tins/dot11/dot11_base.h +++ b/include/tins/dot11/dot11_base.h @@ -148,7 +148,9 @@ class TINS_API Dot11 : public PDU { ATIM = 9, DISASSOC = 10, AUTH = 11, - DEAUTH = 12 + DEAUTH = 12, + ACTION = 13 + }; /** diff --git a/include/tins/eapol.h b/include/tins/eapol.h index 2fd3aacc..b7435047 100644 --- a/include/tins/eapol.h +++ b/include/tins/eapol.h @@ -60,15 +60,27 @@ class TINS_API EAPOL : public PDU { */ static const PDU::PDUType pdu_flag = PDU::EAPOL; + + /** + * the EAPOL packet types enum. + */ + enum PacketTypes + { + EAP_TYPE = 0, + START, + LOGOFF, + KEY + }; + /** - * The EAPOL type enum. + * EAPOL key types enum. */ - enum EAPOLTYPE { + enum KeyTypes { RC4 = 1, RSN, EAPOL_WPA = 254 }; - + /** * \brief Extracts metadata for this protocol based on the buffer provided * @@ -77,6 +89,19 @@ class TINS_API EAPOL : public PDU { */ static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief constructor that sets the packet_type field. + */ + EAPOL(PacketTypes packet_type); + + /** + * \brief Constructor which creates an EAPOL object from a buffer. + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + EAPOL(const uint8_t* buffer, uint32_t total_sz); + /** * \brief Static method to instantiate the correct EAPOL subclass * based on a raw buffer. @@ -117,14 +142,6 @@ class TINS_API EAPOL : public PDU { return Endian::be_to_host(header_.length); } - /** - * \brief Getter for the type field. - * \return The type field. - */ - uint8_t type() const { - return header_.type; - } - /* Setters */ /** @@ -143,39 +160,49 @@ class TINS_API EAPOL : public PDU { * \brief Sets the length field. * \param value The new length to be set. */ - void length(uint16_t value); + virtual void length(uint16_t value); /** - * \brief Sets the type field. - * \param value The new type to be set. + * \brief Returns the header size. + * + * This method overrides PDU::header_size. This size includes the + * payload and options size. + * + * \sa PDU::header_size */ - void type(uint8_t value); - + uint32_t header_size() const; + /** * \brief Getter for the PDU's type. * \return Returns the PDUType corresponding to the PDU. */ PDUType pdu_type() const { return PDU::EAPOL; } -protected: - /** - * \brief Protected constructor that sets the packet_type and type fields. - */ - EAPOL(uint8_t packet_type, EAPOLTYPE type); + /** - * \brief Constructor which creates an EAPOL object from a buffer. - * \param buffer The buffer from which this PDU will be constructed. - * \param total_sz The total size of the buffer. + * \brief Clones this PDU. + * + * \sa PDU::clone */ - EAPOL(const uint8_t* buffer, uint32_t total_sz); - + EAPOL* clone() const { + return new EAPOL(*this); + } +protected: TINS_BEGIN_PACK struct eapol_header { uint8_t version, packet_type; uint16_t length; - uint8_t type; } TINS_END_PACK; + TINS_BEGIN_PACK + struct overlapping_eapol_header { + uint8_t version, packet_type; + uint16_t length; + uint8_t subtype_code; + } TINS_END_PACK; + +private: + /** * \brief Virtual method which should serialize the subclass specific * body and save it in a byte array. @@ -183,14 +210,191 @@ class TINS_API EAPOL : public PDU { * \param buffer The pointer in which to save the serialization. * \param total_sz The total size of the buffer. */ - virtual void write_body(Memory::OutputMemoryStream& stream) = 0; -private: + virtual void write_body(Memory::OutputMemoryStream&); + void write_serialization(uint8_t* buffer, uint32_t total_sz); eapol_header header_; }; +class TINS_API Eap : public EAPOL { +public: + static const PDU::PDUType pdu_flag = PDU::EAP; + + /** + * A number to signify 'no value' for type + */ + static const uint8_t invalid_type = 255; + + /** + * EAP types enum. + */ + enum Codes { + REQUEST = 1, + RESPONSE, + SUCCESS, + FAILURE + }; + + /** + * \brief Default constructor. + */ + Eap(); + + /** + * \brief constructor that sets the code field (id is 0, type is Eap::invalid_type) + */ + Eap(Codes eap_code); + + /** + * \brief constructor that sets the code and id fields. (type is Eap::invalid_type) + */ + Eap(Codes eap_code, uint8_t id); + + /** + * \brief constructor that sets the code,id and and type fields. + */ + Eap(Codes eap_code, uint8_t id, uint8_t eap_type); + + /** + * \brief Constructs an Eap object from a buffer. + * + * If there is not enough size for a EAP header in the + * buffer, 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. + */ + Eap(const uint8_t* buffer, uint32_t total_sz); + + /* Getters */ + + /** + * \brief Getter for the length field. + * \return The length field. + */ + uint16_t length() const { + return Endian::be_to_host(eap_header_.length); + } + + /** + * \brief Getter for the code field. + * \return The code field. + */ + Codes code() const { + return static_cast(eap_header_.code); + } + + /** + * \brief Getter for the id field. + * \return The id field. + */ + uint8_t id() const { + return eap_header_.id; + } + + /** + * \brief Getter for the code field. + * \return The code field. + */ + uint8_t type() const { + if(eap_header_.type == invalid_type) { + throw option_not_found(); + } + return eap_header_.type; + } + /* Setters */ + + /** + * \brief Sets the key length field. + * \param value The new key length to be set. + */ + virtual void length(uint16_t new_length); + /** + * \brief Sets the code field. + * \param value The new code to be set. + */ + void code(Codes new_code); + + /** + * \brief Sets the id field. + * \param value The new id to be set. + */ + void id(uint8_t new_id); + + /** + * \brief Sets the type field. + * \param value The new type to be set. + */ + void type(uint8_t new_type); + + /* Virtual method override. */ + + /** + * \brief Returns the header size. + * + * This method overrides PDU::header_size. This size includes the + * payload and options size. + * + * \sa PDU::header_size + */ + uint32_t header_size() const; + + /** + * \brief Getter for the PDU's type. + * \return Returns the PDUType corresponding to the PDU. + */ + PDUType pdu_type() const { + return pdu_flag; + } + + /** + * \brief Check whether this PDU matches the specified flag. + * \param flag The flag to match + * \sa PDU::matches_flag + */ + bool matches_flag(PDUType flag) const { + return flag == pdu_flag || EAPOL::matches_flag(flag); + } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone + */ + Eap* clone() const { + return new Eap(*this); + } + +private: + + /* + * \brief common header in all eap types + */ + TINS_BEGIN_PACK + struct eap_header { + uint8_t code, id; + uint16_t length; + } TINS_END_PACK; + + /* + * \brief header when code is Codes::REQUEST, Codes::RESPONSE, otherwise type is Eap::invalid_type + */ + TINS_BEGIN_PACK + struct extended_eap_header { + uint8_t code, id; + uint16_t length; + uint8_t type; + } TINS_END_PACK; + + void write_body(Memory::OutputMemoryStream& stream); + + void init(Codes eap_code, uint8_t id, uint8_t eap_type); + + extended_eap_header eap_header_; + +}; /** * \brief Class that represents the RC4 EAPOL PDU. @@ -375,6 +579,7 @@ class TINS_API RC4EAPOL : public EAPOL { private: TINS_BEGIN_PACK struct rc4_eapol_header { + uint8_t type; uint16_t key_length; uint64_t replay_counter; uint8_t key_iv[key_iv_size]; @@ -390,7 +595,6 @@ class TINS_API RC4EAPOL : public EAPOL { rc4_eapol_header header_; }; - /** * \brief Class that represents the RSN EAPOL PDU. */ @@ -776,6 +980,7 @@ class TINS_API RSNEAPOL : public EAPOL { private: TINS_BEGIN_PACK struct rsn_eapol_header { + uint8_t type; #if TINS_IS_LITTLE_ENDIAN uint16_t key_mic:1, secure:1, diff --git a/include/tins/macros.h b/include/tins/macros.h index 168048af..581bea17 100644 --- a/include/tins/macros.h +++ b/include/tins/macros.h @@ -39,6 +39,7 @@ // Check if this is Visual Studio #ifdef _MSC_VER // This is Visual Studio + #define TINS_BEGIN_PACK __pragma( pack(push, 1) ) #define TINS_END_PACK __pragma( pack(pop) ) #define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) ) diff --git a/include/tins/pdu.h b/include/tins/pdu.h index 62dc0f82..0eadaf0e 100644 --- a/include/tins/pdu.h +++ b/include/tins/pdu.h @@ -152,6 +152,7 @@ class TINS_API PDU { DOT11_REASSOC_RESP, DOT11_RTS, DOT11_QOS_DATA, + DOT11_ACTION, LLC, SNAP, IP, @@ -162,6 +163,7 @@ class TINS_API PDU { BOOTP, DHCP, EAPOL, + EAP, RC4EAPOL, RSNEAPOL, DNS, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index af80586a..04a0b406 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -162,6 +162,7 @@ SET(DOT11_DEPENDENT_SOURCES dot11/dot11_auth.cpp dot11/dot11_probe.cpp dot11/dot11_control.cpp + dot11/dot11_action.cpp ) SET(DOT11_DEPENDENT_HEADERS @@ -174,6 +175,7 @@ SET(DOT11_DEPENDENT_HEADERS ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_auth.h ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_probe.h ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_control.h + ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_action.h ) IF(LIBTINS_ENABLE_DOT11) diff --git a/src/detail/pdu_helpers.cpp b/src/detail/pdu_helpers.cpp index 1b945957..060c4fd3 100644 --- a/src/detail/pdu_helpers.cpp +++ b/src/detail/pdu_helpers.cpp @@ -194,6 +194,7 @@ Tins::PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size case Tins::PDU::DOT11_REASSOC_RESP: case Tins::PDU::DOT11_RTS: case Tins::PDU::DOT11_QOS_DATA: + case Tins::PDU::DOT11_ACTION: return Tins::Dot11::from_bytes(buffer, size); #endif // TINS_HAVE_DOT11 default: @@ -215,6 +216,8 @@ Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) { return Constants::Ethernet::PPPOED; case PDU::MPLS: return Constants::Ethernet::MPLS; + case PDU::EAPOL: + case PDU::EAP: case PDU::RSNEAPOL: case PDU::RC4EAPOL: return Constants::Ethernet::EAPOL; @@ -295,4 +298,4 @@ PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag) { } } // Internals -} // Tins \ No newline at end of file +} // Tins diff --git a/src/dot11/dot11_action.cpp b/src/dot11/dot11_action.cpp new file mode 100644 index 00000000..1c656739 --- /dev/null +++ b/src/dot11/dot11_action.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 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 +#ifdef TINS_HAVE_DOT11 + +#include +#include +#include + +using Tins::Memory::InputMemoryStream; +using Tins::Memory::OutputMemoryStream; +using Tins::RawPDU; + +namespace Tins { + +// Dot11Action + +Dot11Action::Dot11Action(const address_type& dst_hw_addr, +const address_type& src_hw_addr, ActionCategories category) +: Dot11ManagementFrame(dst_hw_addr, src_hw_addr), body_() { + body_.category = category; + subtype(Dot11::ACTION); +} + +Dot11Action::Dot11Action(const uint8_t* buffer, uint32_t total_sz) +: Dot11ManagementFrame(buffer, total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(body_); + if(stream) { + inner_pdu(RawPDU(stream.pointer(), stream.size())); + } +} + +void Dot11Action::category(ActionCategories new_category) { + body_.category = static_cast(new_category); +} + +uint32_t Dot11Action::header_size() const { + return Dot11ManagementFrame::header_size() + sizeof(body_); +} + +void Dot11Action::write_fixed_parameters(OutputMemoryStream& stream) { + stream.write(body_); +} + +} // Tins + +#endif // TINS_HAVE_DOT11 diff --git a/src/dot11/dot11_base.cpp b/src/dot11/dot11_base.cpp index cc324442..d4a27291 100644 --- a/src/dot11/dot11_base.cpp +++ b/src/dot11/dot11_base.cpp @@ -252,7 +252,9 @@ Dot11* Dot11::from_bytes(const uint8_t* buffer, uint32_t total_sz) { case PROBE_REQ: return new Dot11ProbeRequest(buffer, total_sz); case PROBE_RESP: - return new Dot11ProbeResponse(buffer, total_sz); + return new Dot11ProbeResponse(buffer, total_sz); + case ACTION: + return new Dot11Action(buffer, total_sz); default: break; }; diff --git a/src/eapol.cpp b/src/eapol.cpp index 7d8aa05f..43fafa5c 100644 --- a/src/eapol.cpp +++ b/src/eapol.cpp @@ -51,11 +51,10 @@ PDU::metadata EAPOL::extract_metadata(const uint8_t *buffer, uint32_t total_sz) return metadata(actual_size, pdu_flag, PDU::UNKNOWN); } -EAPOL::EAPOL(uint8_t packet_type, EAPOLTYPE type) +EAPOL::EAPOL(PacketTypes packet_type) : header_() { header_.version = 1; header_.packet_type = packet_type; - header_.type = (uint8_t)type; } EAPOL::EAPOL(const uint8_t* buffer, uint32_t total_sz) { @@ -67,19 +66,32 @@ EAPOL* EAPOL::from_bytes(const uint8_t* buffer, uint32_t total_sz) { if (TINS_UNLIKELY(total_sz < sizeof(eapol_header))) { throw malformed_packet(); } - const eapol_header* ptr = (const eapol_header*)buffer; - uint32_t data_len = Endian::be_to_host(ptr->length); + const eapol_header* eapol_ptr = (const eapol_header*)buffer; + + uint32_t data_len = Endian::be_to_host(eapol_ptr->length); // at least 4 for fields always present data_len += 4; total_sz = (total_sz < data_len) ? total_sz : data_len; - switch(ptr->type) { - case RC4: - return new Tins::RC4EAPOL(buffer, total_sz); - break; - case RSN: - case EAPOL_WPA: - return new Tins::RSNEAPOL(buffer, total_sz); - break; + + switch(eapol_ptr->packet_type) { + case START: + case LOGOFF: + return new Tins::EAPOL(buffer, total_sz); + break; + case EAP_TYPE: + return new Tins::Eap(buffer, total_sz); + break; + case KEY: + const overlapping_eapol_header* ov_eapol_ptr = (const overlapping_eapol_header*)buffer; + switch(ov_eapol_ptr->subtype_code) { + case RC4: + return new Tins::RC4EAPOL(buffer, total_sz); + break; + case RSN: + case EAPOL_WPA: + return new Tins::RSNEAPOL(buffer, total_sz); + break; + } } return 0; } @@ -96,23 +108,126 @@ void EAPOL::length(uint16_t new_length) { header_.length = Endian::host_to_be(new_length); } -void EAPOL::type(uint8_t new_type) { - header_.type = new_type; +uint32_t EAPOL::header_size() const { + return static_cast(sizeof(eapol_header)); } void EAPOL::write_serialization(uint8_t* buffer, uint32_t total_sz) { OutputMemoryStream stream(buffer, total_sz); - length(total_sz - 4); + length(size() - 4); stream.write(header_); memcpy(buffer, &header_, sizeof(header_)); write_body(stream); } +void EAPOL::write_body(Memory::OutputMemoryStream& ) { + //write nothing +} + +/* EAP */ + +Eap::Eap() +: EAPOL(EAP_TYPE) { + memset(&eap_header_, 0, sizeof(eap_header_)); + eap_header_.code = SUCCESS; + length(size() - 4); +} + +Eap::Eap(Codes eap_code) +: EAPOL(EAP_TYPE) { + init(eap_code, 0 , invalid_type); +} +Eap::Eap(Codes eap_code, uint8_t id) +: EAPOL(EAP_TYPE) { + init(eap_code, id , invalid_type); +} + +Eap::Eap(Codes eap_code, uint8_t id, uint8_t eap_type) +: EAPOL(EAP_TYPE) { + init(eap_code, id , eap_type); +} + +Eap::Eap(const uint8_t* buffer, uint32_t total_sz) +: EAPOL(buffer, total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.skip(sizeof(eapol_header)); + eap_header eap_header_tmp; + stream.read(eap_header_tmp); + eap_header_.code = eap_header_tmp.code; + eap_header_.id = eap_header_tmp.id; + eap_header_.length = eap_header_tmp.length; + switch(eap_header_tmp.code) { + case SUCCESS: + case FAILURE: + eap_header_.type = invalid_type; + break; + case REQUEST: + case RESPONSE: + stream.read(eap_header_.type); + if (stream) { + inner_pdu(new RawPDU(stream.pointer(), stream.size())); + } + break; + } +} + +void Eap::length(uint16_t new_length) { + eap_header_.length = Endian::host_to_be(new_length); + this->EAPOL::length(new_length); +} + +void Eap::code(Codes new_code) { + eap_header_.code = static_cast(new_code); + switch(new_code) { + case SUCCESS: + case FAILURE: + type(invalid_type); + break; + case REQUEST: + case RESPONSE: + break; + } +} + +void Eap::id(uint8_t new_id) { + eap_header_.id = new_id; +} + +void Eap::type(uint8_t new_type) { + eap_header_.type = new_type; +} + +uint32_t Eap::header_size() const { + if(eap_header_.type == invalid_type) { + return static_cast(sizeof(eapol_header)) + sizeof(eap_header_) - 1; + } + else { + return static_cast(sizeof(eapol_header)) + sizeof(eap_header_); + } +} + +void Eap::write_body(OutputMemoryStream& stream) { + stream.write(eap_header_.code); + stream.write(eap_header_.id); + stream.write(eap_header_.length); + if(eap_header_.type != invalid_type) { + stream.write(eap_header_.type); + } +} + +void Eap::init(Codes eap_code, uint8_t id, uint8_t eap_type) { + eap_header_.code = eap_code; + eap_header_.type = eap_type; + eap_header_.id = id; + length(size() - 4); +} + /* RC4EAPOL */ RC4EAPOL::RC4EAPOL() -: EAPOL(0x03, RC4) { +: EAPOL(KEY) { memset(&header_, 0, sizeof(header_)); + header_.type = RC4; } RC4EAPOL::RC4EAPOL(const uint8_t* buffer, uint32_t total_sz) @@ -172,8 +287,9 @@ void RC4EAPOL::write_body(OutputMemoryStream& stream) { RSNEAPOL::RSNEAPOL() -: EAPOL(0x03, RSN) { +: EAPOL(KEY) { memset(&header_, 0, sizeof(header_)); + header_.type = RSN; } RSNEAPOL::RSNEAPOL(const uint8_t* buffer, uint32_t total_sz) From 7c5657bc9aafd51ccb4f33dd11273c62ce3badbb Mon Sep 17 00:00:00 2001 From: yair Date: Thu, 19 Jul 2018 18:18:53 +0300 Subject: [PATCH 2/2] added documentation and fixed type() --- include/tins/eapol.h | 55 +++++++++++++++++++++++++++++++++++++------- src/eapol.cpp | 8 +++++++ 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/include/tins/eapol.h b/include/tins/eapol.h index b7435047..1503f6d1 100644 --- a/include/tins/eapol.h +++ b/include/tins/eapol.h @@ -92,6 +92,8 @@ class TINS_API EAPOL : public PDU { /** * \brief constructor that sets the packet_type field. + * + * \param packet_type the eapol packet type */ EAPOL(PacketTypes packet_type); @@ -243,16 +245,25 @@ class TINS_API Eap : public EAPOL { /** * \brief constructor that sets the code field (id is 0, type is Eap::invalid_type) + * + * \param eap_code the eap type code */ Eap(Codes eap_code); /** * \brief constructor that sets the code and id fields. (type is Eap::invalid_type) + * + * \param eap_code the eap type code + * \param id the packet id */ Eap(Codes eap_code, uint8_t id); /** * \brief constructor that sets the code,id and and type fields. + * + * \param eap_code the eap type code + * \param id the packet id + * \param eap_type the type of the eap payload (if there is any) */ Eap(Codes eap_code, uint8_t id, uint8_t eap_type); @@ -294,8 +305,8 @@ class TINS_API Eap : public EAPOL { } /** - * \brief Getter for the code field. - * \return The code field. + * \brief Getter for the type field. + * \return The type field. */ uint8_t type() const { if(eap_header_.type == invalid_type) { @@ -307,25 +318,25 @@ class TINS_API Eap : public EAPOL { /** * \brief Sets the key length field. - * \param value The new key length to be set. + * \param new_length The new key length to be set. */ virtual void length(uint16_t new_length); /** * \brief Sets the code field. - * \param value The new code to be set. + * \param new_code The new code to be set. */ void code(Codes new_code); /** * \brief Sets the id field. - * \param value The new id to be set. + * \param new_id The new id to be set. */ void id(uint8_t new_id); /** * \brief Sets the type field. - * \param value The new type to be set. + * \param new_type The new type to be set. */ void type(uint8_t new_type); @@ -439,6 +450,14 @@ class TINS_API RC4EAPOL : public EAPOL { /* Getters */ + /** + * \brief Getter for the type field. + * \return The type field. + */ + uint8_t type() const { + return header_.type; + } + /** * \brief Getter for the key length field. * \return The key length field. @@ -497,6 +516,12 @@ class TINS_API RC4EAPOL : public EAPOL { /* Setters */ + /** + * \brief Sets the type field. + * \param value The new type to be set. + */ + void type(uint8_t value); + /** * \brief Sets the key length field. * \param value The new key length to be set. @@ -652,7 +677,15 @@ class TINS_API RSNEAPOL : public EAPOL { RSNEAPOL(const uint8_t* buffer, uint32_t total_sz); /* Getters */ - + + /** + * \brief Getter for the type field. + * \return The type field. + */ + uint8_t type() const { + return header_.type; + } + /** * \brief Getter for the key length field. * \return The key length field. @@ -817,7 +850,13 @@ class TINS_API RSNEAPOL : public EAPOL { uint32_t header_size() const; /* Setters */ - + + /** + * \brief Sets the type field. + * \param value The new type to be set. + */ + void type(uint8_t value); + /** * \brief Sets the key length field. * \param value The new key length to be set. diff --git a/src/eapol.cpp b/src/eapol.cpp index 43fafa5c..43e30f5c 100644 --- a/src/eapol.cpp +++ b/src/eapol.cpp @@ -243,6 +243,10 @@ RC4EAPOL::RC4EAPOL(const uint8_t* buffer, uint32_t total_sz) } } +void RC4EAPOL::type(const uint8_t value) { + header_.type = value; +} + void RC4EAPOL::key_length(uint16_t length) { header_.key_length = Endian::host_to_be(length); } @@ -305,6 +309,10 @@ RSNEAPOL::RSNEAPOL(const uint8_t* buffer, uint32_t total_sz) } } +void RSNEAPOL::type(const uint8_t value) { + header_.type = value; +} + void RSNEAPOL::nonce(const uint8_t* ptr) { memcpy(header_.nonce, ptr, nonce_size); }