Skip to content

Commit

Permalink
Incoming packet validation and header data.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ohjurot committed Jul 9, 2023
1 parent 7f87284 commit d8cbf50
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 7 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# Python virtual env
/venv

# VSOutput
**/.vs/**
**/out/**
8 changes: 8 additions & 0 deletions docs/libaaa/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# LibAAA a Bare-Bone C radius packet library

The following pages will explain the usage of the libaaa library. The lib is composed out of the following components:

- `libaaa_pg`: C-API for packet generation
- `libaaa_pr`: C-API for packet reading/parsing
- `libaaa::packet_generator`: C++ OOP wrapper for packet generation
- `libaaa::packet_reader`: C++ OOP wrapper for packet reading/parsing
3 changes: 0 additions & 3 deletions docs/libaaa/reference.md

This file was deleted.

35 changes: 35 additions & 0 deletions libaaa/include/libaaa/libaaa.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
//
#define LIBAAA_OK 0
#define LIBAAA_ERROR -1
#define LIBAAA_PACKET_INVALID_LENGTH -2
#define LIBAAA_PACKET_VALIDATION_FAILED -3
#define LIBAAA_PACKET_INVALID_BODY -4

#define LIBAAA_PACKET_MAX_SIZE 4096
#define LIBAAA_PG_CONTEXT_SIZE 64
Expand Down Expand Up @@ -334,6 +337,38 @@ LIBAAA_API int libaaa_pg_write_integer64(libaaa_pg_context_t context, uint64_t v
// === API "pr" (Packet Reader) ===
//

/*!
* @brief Generic packet validation (before parsing it). This will NOT catch all possible issues!
*
* - Validates input_size
* - Validates packet header (size)
* - Validates packet header values
* - Validates all packets attributes size (in attribute and across packet)
* @param input_buffer Received network packet data
* @param input_size Size of the packet
* @return status code
* - LIBAAA_OK: Packet validated successfully
* - LIBAAA_PACKET_INVALID_LENGTH: Packet does not contain a radius header / is invalid in it's length
* - LIBAAA_PACKET_VALIDATION_FAILED: Packet is not a valid radius packet
* - LIBAAA_PACKET_INVALID_BODY: Packet's body is not valid in itself or with the header
*/
LIBAAA_API int libaaa_pr_validate_packet(const void* input_buffer, int input_size);

/*!
* @brief Retrieves non attribute detail from the packet.
*
* Only unse this function when the packet has been validated by the "libaaa_pr_validate_packet" function.
* This function can be called on the following return values from "libaaa_pr_validate_packet":
* LIBAAA_OK, LIBAAA_PACKET_VALIDATION_FAILED, LIBAAA_PACKET_INVALID_BODY
*
* @param input_buffer Input buffer to read header from
* @param code Output radius code
* @param identifier Output radius identifier
* @param authenticator Output radius authenticator (16-Bytes)
* @return
*/
LIBAAA_API void libaaa_pr_get_packet_details(const void* input_buffer, libaaa_radius_code_t* code, uint8_t* identifier, char* authenticator);

#ifdef __cplusplus
}
#endif // __cplusplus
Expand Down
64 changes: 61 additions & 3 deletions libaaa/src/libaaa.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ LIBAAA_API int libaaa_pg_finalize(libaaa_pg_context_t context)
__libaaa_ats_finish(ctx);

// Write packet length and return it
__libaaa_hton(&ctx->buffer_head, &ctx->buffer[__LIBAAA_PO_HEADER_LENGTH], 2);
__libaaa_hton((char*)&ctx->buffer_head, (char*)&ctx->buffer[__LIBAAA_PO_HEADER_LENGTH], 2);
return ctx->buffer_head;
}

Expand Down Expand Up @@ -364,7 +364,7 @@ LIBAAA_API int libaaa_pg_attribute_begin_extended_vendor_specific(libaaa_pg_cont
LIBAAA_API int libaaa_pg_write_integer(libaaa_pg_context_t context, uint32_t value)
{
uint32_t swap;
__libaaa_hton(&value, &swap, sizeof(uint32_t));
__libaaa_hton((char*)&value, (char*)&swap, sizeof(uint32_t));
return __libaaa_ats_write(context, &swap, sizeof(uint32_t));
}

Expand Down Expand Up @@ -489,6 +489,64 @@ LIBAAA_API int libaaa_pg_write_ipv4prefix(libaaa_pg_context_t context, uint8_t p
LIBAAA_API int libaaa_pg_write_integer64(libaaa_pg_context_t context, uint64_t value)
{
uint64_t swap;
__libaaa_hton(&value, &swap, sizeof(uint64_t));
__libaaa_hton((char*)&value, (char*)&swap, sizeof(uint64_t));
return __libaaa_ats_write(context, &swap, sizeof(uint64_t));
}

LIBAAA_API int libaaa_pr_validate_packet(const void* input_buffer, int input_size)
{
// (1) Network size
if(input_size < 20 || input_size > LIBAAA_PACKET_MAX_SIZE)
{
return LIBAAA_PACKET_INVALID_LENGTH;
}

// (2) Packet size
uint16_t packet_size = 0;
__libaaa_ntoh(&((const char*)input_buffer)[__LIBAAA_PO_HEADER_LENGTH], (char*)&packet_size, sizeof(uint16_t));
if (packet_size > input_size)
{
return LIBAAA_PACKET_VALIDATION_FAILED;
}

// (3) Packet header
uint8_t radius_code = ((const char*)input_buffer)[__LIBAAA_PO_HEADER_CODE];
if (radius_code == 0 || (radius_code > 5 && radius_code < 11) || radius_code > 13)
{
return LIBAAA_PACKET_VALIDATION_FAILED;
}

// (4) Attributes
uint64_t offset = 20;
while (offset < packet_size)
{
// THIS
const char* attribute = &((const char*)input_buffer)[offset];
uint8_t attribute_len = attribute[__LIBAAA_PO_ATTRIBUTE_LENGTH];

// Attribute bounds
if (offset + attribute_len > packet_size)
{
return LIBAAA_PACKET_INVALID_BODY;
}
// Attribute size
if (attribute_len < 2)
{
return LIBAAA_PACKET_INVALID_BODY;
}

// NEXT
offset += attribute_len;
}

// Passed
return LIBAAA_OK;
}

LIBAAA_API void libaaa_pr_get_packet_details(const void* input_buffer, libaaa_radius_code_t* code, uint8_t* identifier, char* authenticator)
{
*code = ((const char*)input_buffer)[__LIBAAA_PO_HEADER_CODE];
*identifier = ((const char*)input_buffer)[__LIBAAA_PO_HEADER_IDENTIFIER];
memcpy(authenticator, &((const char*)input_buffer)[__LIBAAA_PO_HEADER_AUTHENTICATOR], 16);
}

2 changes: 2 additions & 0 deletions libaaa/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ add_executable(libaaa_test
./tests/pg_empty.cpp
./tests/pg_attribute.cpp
./tests/pg_x_attribute.cpp
./tests/pr_validation.cpp
./tests/pr_header_data.cpp
)

target_link_libraries(libaaa_test PUBLIC GTest::gtest GTest::gtest_main GTest::gmock)
Expand Down
9 changes: 9 additions & 0 deletions libaaa/test/tests/pr_facade.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "libaaa_test.h"

class libaaa_pr_test : public ::testing::Test
{
protected:
virtual void SetUp() override
{
}
};
34 changes: 34 additions & 0 deletions libaaa/test/tests/pr_header_data.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "pr_facade.h"

class pr_header_data : public libaaa_pr_test {};

TEST_F(pr_header_data, extract)
{
// Expected values
uint8_t expected_code = 22;
uint8_t expected_id = 111;
uint8_t expected_authenticator[] = {
0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x8A,
0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0x8B,
};

// Target values
uint8_t code = 0;
uint8_t id = 0;
uint8_t authenticator[16];
memset(authenticator, 0x0, 16);

// Retrieve packet
uint8_t packet[] = {
22, 111, // Code, ID
0, 20, // Length
0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, 0x8A, // Authenticator
0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, 0x8B, // ...
};

libaaa_pr_get_packet_details(packet, &code, &id, (char*)authenticator);

EXPECT_EQ(code, expected_code);
EXPECT_EQ(id, expected_id);
ASSERT_THAT(authenticator, PacketCheck(expected_authenticator, 16));
}
96 changes: 96 additions & 0 deletions libaaa/test/tests/pr_validation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "pr_facade.h"

class pr_validation : public libaaa_pr_test {};

TEST_F(pr_validation, size_invalid)
{
// Retrieve packet
uint8_t packet[] = {
0, 0, 0, 0,
};

EXPECT_EQ(libaaa_pr_validate_packet(packet, 4), LIBAAA_PACKET_INVALID_LENGTH);
}

TEST_F(pr_validation, header_valid)
{
// Retrieve packet
uint8_t packet[] = {
1, 2, // Code, ID
0, 20, // Length
0, 0, 0, 0, 0, 0, 0, 0, // Authenticator
0, 0, 0, 0, 0, 0, 0, 0, // ...
};

EXPECT_EQ(libaaa_pr_validate_packet(packet, 20), LIBAAA_OK);
}

TEST_F(pr_validation, header_valid_padding)
{
// Retrieve packet
uint8_t packet[] = {
1, 2, // Code, ID
0, 20, // Length
0, 0, 0, 0, 0, 0, 0, 0, // Authenticator
0, 0, 0, 0, 0, 0, 0, 0, // ...
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
};

EXPECT_EQ(libaaa_pr_validate_packet(packet, 32), LIBAAA_OK);
}

TEST_F(pr_validation, header_invalid)
{
// Retrieve packet
uint8_t packet[] = {
160, 2, // Code, ID
0, 20, // Length
0, 0, 0, 0, 0, 0, 0, 0, // Authenticator
0, 0, 0, 0, 0, 0, 0, 0, // ...
};

EXPECT_EQ(libaaa_pr_validate_packet(packet, 20), LIBAAA_PACKET_VALIDATION_FAILED);
}

TEST_F(pr_validation, attribute_valid)
{
// Retrieve packet
uint8_t packet[] = {
1, 2, // Code, ID
0, 22, // Length
0, 0, 0, 0, 0, 0, 0, 0, // Authenticator
0, 0, 0, 0, 0, 0, 0, 0, // ...
5, 2,
};

EXPECT_EQ(libaaa_pr_validate_packet(packet, 22), LIBAAA_OK);
}

TEST_F(pr_validation, attribute_invalid)
{
// Retrieve packet
uint8_t packet[] = {
1, 2, // Code, ID
0, 22, // Length
0, 0, 0, 0, 0, 0, 0, 0, // Authenticator
0, 0, 0, 0, 0, 0, 0, 0, // ...
5, 0,
};

EXPECT_EQ(libaaa_pr_validate_packet(packet, 22), LIBAAA_PACKET_INVALID_BODY);
}

TEST_F(pr_validation, attribute_header_missmatch)
{
// Retrieve packet
uint8_t packet[] = {
1, 2, // Code, ID
0, 22, // Length
0, 0, 0, 0, 0, 0, 0, 0, // Authenticator
0, 0, 0, 0, 0, 0, 0, 0, // ...
5, 5, 0, 0, 0, // <-- Valid attributes but invalid header size
};

EXPECT_EQ(libaaa_pr_validate_packet(packet, 25), LIBAAA_PACKET_INVALID_BODY);
}
17 changes: 16 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,22 @@ nav:
- About: "index.md"
- LibAAA:
- About: "libaaa/index.md"
- Reference: "libaaa/reference.md"
- libaaa_pg:
- Reference: "libaaa/libaaa_pg/reference.md"
- User Guide: "libaaa/libaaa_pg/guide.md"
- Example: "libaaa/libaaa_pg/example.md"
- libaaa_pr:
- Reference: "libaaa/libaaa_pr/reference.md"
- User Guide: "libaaa/libaaa_pr/guide.md"
- Example: "libaaa/libaaa_pr/example.md"
- "libaaa::packet_generator":
- Reference: "libaaa/packet_generator/reference.md"
- User Guide: "libaaa/packet_generator/guide.md"
- Example: "libaaa/packet_generator/example.md"
- "libaaa::packet_reader":
- Reference: "libaaa/packet_reader/reference.md"
- User Guide: "libaaa/packet_reader/guide.md"
- Example: "libaaa/packet_reader/example.md"
- LibAAA-Server: "libaaa-server/index.md"
- LibAAA-Client: "libaaa-client/index.md"

Expand Down

0 comments on commit d8cbf50

Please sign in to comment.