diff --git a/include/eapol.h b/include/eapol.h index 3f4c1b6..9c24278 100644 --- a/include/eapol.h +++ b/include/eapol.h @@ -3,6 +3,7 @@ #include "pdu.h" +#include "utils.h" namespace Tins { @@ -10,11 +11,30 @@ namespace Tins { * \brief Class that represents the EAP encapsulation over LAN. */ class EAPOL : public PDU { + public: + enum EAPOLTYPE { + RC4 = 1 + }; protected: /** * \brief Protected constructor that sets the packet_type and type fields. */ - EAPOL(uint8_t packet_type, uint8_t type); + 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. + */ + EAPOL(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Static method to instantiate the correct EAPOL subclass + * based on a raw buffer. + * \param buffer The buffer from which the data will be taken. + * \param total_sz The total size of the buffer. + */ + static EAPOL *from_bytes(const uint8_t *buffer, uint32_t total_sz); /* Getters */ @@ -34,7 +54,7 @@ namespace Tins { * \brief Getter for the length field. * \return The length field. */ - uint16_t length() const { return _header.length; } + uint16_t length() const { return Utils::net_to_host_s(_header.length); } /** * \brief Getter for the type field. @@ -112,6 +132,13 @@ namespace Tins { */ RC4EAPOL(); + /** + * \brief Constructor which creates an RC4EAPOL object from a buffer. + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + RC4EAPOL(const uint8_t *buffer, uint32_t total_sz); + /** * \brief RC4EAPOL destructor * @@ -125,7 +152,7 @@ namespace Tins { * \brief Getter for the key length field. * \return The key length field. */ - uint16_t key_length() const { return _header.key_length; } + uint16_t key_length() const { return Utils::net_to_host_s(_header.key_length); } /** * \brief Getter for the replay counter field. diff --git a/src/eapol.cpp b/src/eapol.cpp index 15ec801..fba59ec 100644 --- a/src/eapol.cpp +++ b/src/eapol.cpp @@ -1,14 +1,32 @@ #include #include +#include #include "eapol.h" -#include "utils.h" -Tins::EAPOL::EAPOL(uint8_t packet_type, uint8_t type) : PDU(0xff) { +Tins::EAPOL::EAPOL(uint8_t packet_type, EAPOLTYPE type) : PDU(0xff) { std::memset(&_header, 0, sizeof(_header)); _header.version = 1; _header.packet_type = packet_type; - _header.type = type; + _header.type = (uint8_t)type; +} + +Tins::EAPOL::EAPOL(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { + if(total_sz < sizeof(_header)) + throw std::runtime_error("Not enough size for an EAPOL header in the buffer."); + std::memcpy(&_header, buffer, sizeof(_header)); +} + +Tins::EAPOL *Tins::EAPOL::from_bytes(const uint8_t *buffer, uint32_t total_sz) { + if(total_sz < sizeof(eapolhdr)) + throw std::runtime_error("Not enough size for an EAPOL header in the buffer."); + const eapolhdr *ptr = (const eapolhdr*)buffer; + switch(ptr->type) { + case RC4: + return new RC4EAPOL(buffer, total_sz); + break; + } + return 0; } void Tins::EAPOL::version(uint8_t new_version) { @@ -38,10 +56,27 @@ void Tins::EAPOL::write_serialization(uint8_t *buffer, uint32_t total_sz, const /* RC4EAPOL */ -Tins::RC4EAPOL::RC4EAPOL() : EAPOL(0x03, 0x01), _key(0), _key_size(0) { +Tins::RC4EAPOL::RC4EAPOL() : EAPOL(0x03, RC4), _key(0), _key_size(0) { std::memset(&_header, 0, sizeof(_header)); } +Tins::RC4EAPOL::RC4EAPOL(const uint8_t *buffer, uint32_t total_sz) : EAPOL(buffer, total_sz) { + buffer += sizeof(eapolhdr); + total_sz -= sizeof(eapolhdr); + if(total_sz < sizeof(_header)) + throw std::runtime_error("Not enough size for an EAPOL header in the buffer."); + std::memcpy(&_header, buffer, sizeof(_header)); + buffer += sizeof(_header); + total_sz -= sizeof(_header); + if(total_sz == key_length()) { + _key = new uint8_t[total_sz]; + _key_size = total_sz; + std::memcpy(_key, buffer, total_sz); + } + else + _key = 0; +} + Tins::RC4EAPOL::~RC4EAPOL() { delete[] _key; }