Skip to content

Commit e0d85f5

Browse files
Zainullin DamirZainullin Damir
authored andcommitted
Process plugins - Introduce TLS parser
1 parent 5965c54 commit e0d85f5

File tree

11 files changed

+846
-858
lines changed

11 files changed

+846
-858
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @file
3+
* @brief Provides a reader for parsing TLS extensions.
4+
* @author Damir Zainullin <[email protected]>
5+
* @date 2025
6+
*
7+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
8+
*/
9+
10+
#include "../tlsExtension.hpp"
11+
12+
#include <optional>
13+
#include <ranges>
14+
#include <span>
15+
16+
#include <arpa/inet.h>
17+
#include <readers/rangeReader/generator.hpp>
18+
#include <readers/rangeReader/rangeReader.hpp>
19+
20+
namespace ipxp::process {
21+
22+
/**
23+
* @class ExtensionReader
24+
* @brief A reader for parsing TLS extensions from a byte span.
25+
*
26+
* This class provides functionality to parse TLS extensions from a given payload.
27+
* It uses a generator to yield each parsed extension as a `TLSExtension` struct.
28+
*/
29+
class ExtensionReader : public RangeReader {
30+
public:
31+
auto getRange(std::span<const std::byte> payload) noexcept
32+
{
33+
return Generator::generate([this, payload]() mutable -> std::optional<TLSExtension> {
34+
if (payload.empty()) {
35+
setSuccess();
36+
return std::nullopt;
37+
}
38+
if (payload.size() < sizeof(uint16_t)) {
39+
return std::nullopt;
40+
}
41+
42+
const uint16_t length
43+
= ntohs(*reinterpret_cast<const uint16_t*>(payload.data()));
44+
if (length > payload.size() || length < sizeof(uint16_t)) {
45+
return std::nullopt;
46+
}
47+
48+
const auto type = static_cast<TLSExtensionType>(
49+
ntohs(*reinterpret_cast<const uint16_t*>(payload.data() + sizeof(length))));
50+
51+
const auto extensionBegin = payload.data() + sizeof(type) + sizeof(length);
52+
53+
payload = payload.subspan(sizeof(type) + sizeof(length) + length);
54+
55+
return TLSExtension {type, {extensionBegin, length}};
56+
})
57+
| std::views::take_while(
58+
[](const std::optional<TLSExtension>& v) { return v.has_value(); })
59+
| std::views::transform([](const std::optional<TLSExtension>& v) { return *v; });
60+
}
61+
};
62+
63+
/*class ExtensionReader : public RangeReader<ExtensionReaderFactory> {
64+
public:
65+
ExtensionReader(std::span<const std::byte> payload)
66+
: RangeReader(payload, ExtensionReaderFactory{this}) {}
67+
};*/
68+
69+
} // namespace ipxp
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* @file
3+
* @brief Provides a reader for parsing User-Agent extensions in TLS.
4+
* @author Damir Zainullin <[email protected]>
5+
* @date 2025
6+
*
7+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
8+
*/
9+
10+
#include "../../../quic/src/quicVariableInt.hpp"
11+
12+
#include <optional>
13+
#include <ranges>
14+
#include <span>
15+
16+
#include <readers/rangeReader/generator.hpp>
17+
#include <readers/rangeReader/rangeReader.hpp>
18+
19+
namespace ipxp::process {
20+
21+
/**
22+
* @struct UserAgent
23+
* @brief Represents a User-Agent with an ID and value.
24+
*/
25+
struct UserAgent {
26+
uint64_t id;
27+
std::string_view value;
28+
};
29+
30+
/**
31+
* @class UserAgentReader
32+
* @brief A reader for parsing User-Agent extensions from a byte span.
33+
*
34+
* This class provides functionality to parse User-Agent extensions from a given payload.
35+
* It uses a generator to yield each parsed User-Agent as a `UserAgent` struct.
36+
*/
37+
struct UserAgentReader : public RangeReader {
38+
auto getRange(std::span<const std::byte> userAgentExtension) noexcept
39+
{
40+
return Generator::generate(
41+
[this, userAgentExtension]() mutable -> std::optional<UserAgent> {
42+
if (userAgentExtension.empty()) {
43+
setSuccess();
44+
return std::nullopt;
45+
}
46+
const std::optional<quic::VariableLengthInt> id
47+
= quic::readQUICVariableLengthInt(userAgentExtension);
48+
if (!id.has_value()) {
49+
return std::nullopt;
50+
}
51+
52+
const std::size_t lengthOffset = id->length;
53+
const std::optional<quic::VariableLengthInt> userAgentLength
54+
= quic::readQUICVariableLengthInt(
55+
userAgentExtension.subspan(lengthOffset));
56+
if (!userAgentLength.has_value()) {
57+
return std::nullopt;
58+
}
59+
if (id->length + userAgentLength->length + userAgentLength->value
60+
> userAgentExtension.size()) {
61+
return std::nullopt;
62+
}
63+
64+
const std::size_t userAgentOffset = lengthOffset + userAgentLength->length;
65+
const auto userAgent = reinterpret_cast<const char*>(
66+
userAgentExtension.data() + userAgentOffset);
67+
68+
userAgentExtension
69+
= userAgentExtension.subspan(userAgentOffset + userAgentLength->length);
70+
71+
return UserAgent {id->value, {userAgent, userAgentLength->value}};
72+
})
73+
| std::views::take_while(
74+
[](const std::optional<UserAgent>& v) { return v.has_value(); })
75+
| std::views::transform([](const std::optional<UserAgent>& v) { return *v; });
76+
}
77+
};
78+
79+
/*
80+
class TLSUserAgentReader : public RangeReader<UserAgentReaderFactory> {
81+
public:
82+
TLSUserAgentReader(std::span<const std::byte> userAgentExtension)
83+
: RangeReader(userAgentExtension, UserAgentReaderFactory{this}) {}
84+
};*/
85+
86+
} // namespace ipxp::process
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @file
3+
* @brief Defines the TLSExtension struct for representing TLS extensions.
4+
* @author Damir Zainullin <[email protected]>
5+
* @date 2025
6+
*
7+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
8+
*/
9+
10+
#pragma once
11+
12+
#include "tlsExtensionType.hpp"
13+
14+
#include <cstdint>
15+
#include <span>
16+
17+
namespace ipxp::process {
18+
19+
/**
20+
* @struct TLSExtension
21+
* @brief Represents a TLS extension with its type and payload.
22+
*/
23+
struct TLSExtension {
24+
TLSExtensionType type;
25+
std::span<const std::byte> payload;
26+
};
27+
28+
} // namespace ipxp::process
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @file
3+
* @brief Defines the TLSExtensionType enum for identifying TLS extension types.
4+
* @author Damir Zainullin <[email protected]>
5+
* @date 2025
6+
*
7+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
8+
*/
9+
10+
#pragma once
11+
12+
#include <cstdint>
13+
14+
namespace ipxp::process {
15+
16+
/**
17+
* @enum TLSExtensionType
18+
* @brief Enumerates the types of TLS extensions.
19+
*
20+
* This enum defines various TLS extension types identified by their respective type codes.
21+
*/
22+
enum class TLSExtensionType : uint16_t {
23+
SERVER_NAME = 0,
24+
SUPPORTED_GROUPS = 10, // AKA supported_groups, ECLIPTIC_CURVES
25+
ELLIPTIC_CURVE_POINT_FORMATS = 11,
26+
SIGNATURE_ALGORITHMS = 13,
27+
ALPN = 16,
28+
SUPPORTED_VERSION = 43,
29+
QUIC_TRANSPORT_PARAMETERS = 0xffa5,
30+
QUIC_TRANSPORT_PARAMETERS_V1 = 0x39,
31+
QUIC_TRANSPORT_PARAMETERS_V2 = 0x26
32+
};
33+
34+
} // namespace ipxp::process
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @file
3+
* @brief Defines the TLSHandshake struct for representing TLS handshake messages.
4+
* @author Damir Zainullin <[email protected]>
5+
* @date 2025
6+
*
7+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
8+
*/
9+
10+
#pragma once
11+
12+
#include "tlsVersion.hpp"
13+
14+
#include <cstdint>
15+
16+
namespace ipxp::process {
17+
18+
/**
19+
* @struct TLSHandshake
20+
* @brief Represents a TLS handshake message with its type, length, and version.
21+
*
22+
* This structure is used to parse and represent the initial handshake messages
23+
* in the TLS protocol, such as ClientHello and ServerHello.
24+
*/
25+
struct TLSHandshake {
26+
enum class Type : uint8_t { CLIENT_HELLO = 1, SERVER_HELLO = 2 };
27+
28+
Type type;
29+
uint8_t length1; // length field is 3 bytes long...
30+
uint16_t length2;
31+
TLSVersion version;
32+
33+
/* Handshake data... */
34+
} __attribute__((packed));
35+
36+
} // namespace ipxp::process
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* @file
3+
* @brief Defines the TLSHeader struct for representing TLS record headers.
4+
* @author Damir Zainullin <[email protected]>
5+
* @date 2025
6+
*
7+
* @copyright Copyright (c) 2025 CESNET, z.s.p.o.
8+
*/
9+
10+
#pragma once
11+
12+
#include <cstdint>
13+
14+
namespace ipxp::process {
15+
16+
/**
17+
* @struct TLSVersion
18+
* @brief Represents the version of the TLS protocol.
19+
*
20+
* This structure holds the major and minor version numbers of the TLS protocol.
21+
*/
22+
struct TLSHeader {
23+
enum class Type : uint8_t { HANDSHAKE = 22 };
24+
25+
Type type;
26+
TLSVersion version;
27+
uint16_t length;
28+
/* Record data... */
29+
30+
} __attribute__((packed));
31+
32+
} // namespace ipxp::process

0 commit comments

Comments
 (0)