Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rudimentary eap packet parsing and dot11_action #303

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

AntiMatterDynamite
Copy link

this is addressing the problem described in this issue of libtins not handling eapol packets that are not rsn\rc4 key exchanges.

for eapol added:

  • ability to create EAPOL packets without a body (for eapol start and logoff)
  • more correct handling and parsing of EAPOL packets (checking the packet type)
  • new EAP class for handling EAPOL with packet_type 0

so now it can parse 100% of the pcap file posted in the original issue. (anything past the normal header is passed as RawPDU but parsing every single type of identifier is a MUCH bigger project)

also added new action pdu to dot11 packets so it won't just throw those out.
its very basic parsing (just one extra byte) but at least it won't throw them out

@christophert
Copy link
Contributor

I think that the 802.11 Action definition is missing the one-byte action code and dialog token fields but that should be a simple addition.

@AntiMatterDynamite
Copy link
Author

those are not always present in all action packets iirc (for reference scapy only parses the one byte too) , maybe you can subclass it and add those in, but thats just a slippery slope of dozens of different types of actions to implement and my goal was mainly to just make sure action packets weren't dropped.

@christophert
Copy link
Contributor

christophert commented Jul 23, 2018

After looking at 802.11-2016 (9.3.3.14/Table 9-38)and 802.11u-2011, it looks the one-byte action code field is defined for all action frames in order to specify the type of action frame it is. Other than that it looks good.

EDIT: I stand corrected, it seems that it applies for all EXCEPT for vendor-specific (126/127). It looks like we will have to subclass it as you said.

Copy link
Owner

@mfontanini mfontanini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it took me this long to get here!

void write_serialization(uint8_t* buffer, uint32_t total_sz);

eapol_header header_;
};

class TINS_API Eap : public EAPOL {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to call this EAP? That would make it consistent with the rest of the class names.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i was going by the dot11 classes but i see the rest are all uppercase

* \brief Enum for the different action categories.
*
*/
enum ActionCategories {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call this ActionCategory rather than the plural form of it.

InputMemoryStream stream(buffer, total_sz);
stream.skip(management_frame_size());
stream.read(body_);
if(stream) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[style] space after if

*/
enum EAPOLTYPE {
enum PacketTypes
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd call this PacketType. Also, can you move the brace up to this line so it looks like enum name {?

/**
* EAPOL key types enum.
*/
enum KeyTypes {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, KeyType.

*/
TINS_BEGIN_PACK
struct extended_eap_header {
uint8_t code, id;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's probably better to define extended_eap_header as something like (not necessarily with these names):

TINS_BEGIN_PACK
struct extended_eap_header {
    eap_header base;
    uint8_t type;
} TINS_END_PACK;

This way you can make the code simpler below. e.g. when you read, you don't need a temporary eap_header, you can just read straight into eap_hader_.base


extended_eap_header eap_header_;

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[style] this extra line here

/**
* EAP types enum.
*/
enum Codes {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about using singular names for enums, use Code here

/**
* A number to signify 'no value' for type
*/
static const uint8_t invalid_type = 255;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this value is never exposed to a user, is it? If that's the case, it should be private and there should be no mention of it in the API docs, this is an implementation detail.

Skimming through the RFC, it seems like 255 is actually a valid type? It seems like it's an experimental type but it's still valid. This should be handled in a different way. If we could use boost here, I'd use a boost::optional but I'd rather not pull that dependency in here.

*/
uint8_t type() const {
if(eap_header_.type == invalid_type) {
throw option_not_found();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably throw another exception here. Maybe field_not_present which already exists could fit here? Also, the docs on this method should say something about this throwing if the PDU doesn't have a type.

There should probably be a bool has_type() const; to check if the frame has a type and not have to rely on a try-catch around calling this method.

joy4eg pushed a commit to SonarWireless/libtins that referenced this pull request Apr 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants