Skip to content

Commit 44bd07c

Browse files
Zainullin DamirZainullin Damir
authored andcommitted
Bugfixes - TLS and QUIC parsers
1 parent fa98343 commit 44bd07c

File tree

5 files changed

+63
-25
lines changed

5 files changed

+63
-25
lines changed

src/plugins/process/common/tlsParser/extensionReaders/extensionReader.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#include "../tlsExtension.hpp"
1111

12-
#include <iostream>
1312
#include <optional>
1413
#include <ranges>
1514
#include <span>
@@ -31,7 +30,7 @@ class ExtensionReader : public RangeReader {
3130
public:
3231
auto getRange(std::span<const std::byte> payload) noexcept
3332
{
34-
return Generator([&]() -> std::optional<TLSExtension> {
33+
return Generator([payload, this]() mutable -> std::optional<TLSExtension> {
3534
if (payload.empty()) {
3635
setSuccess();
3736
return std::nullopt;
@@ -42,7 +41,6 @@ class ExtensionReader : public RangeReader {
4241

4342
const auto type = static_cast<TLSExtensionType>(
4443
ntohs(*reinterpret_cast<const uint16_t*>(payload.data())));
45-
std::cout << "Extension type raw: " << std::hex << static_cast<uint16_t>(type) << "\n";
4644
const uint16_t length
4745
= ntohs(*reinterpret_cast<const uint16_t*>(payload.data() + sizeof(type)));
4846
if (length > payload.size()) {

src/plugins/process/common/tlsParser/extensionReaders/userAgentReader.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct UserAgentReader : public RangeReader {
4242
setSuccess();
4343
return std::nullopt;
4444
}
45+
4546
const std::optional<quic::VariableLengthInt> id
4647
= quic::readQUICVariableLengthInt(userAgentExtension);
4748
if (!id.has_value()) {
@@ -64,7 +65,7 @@ struct UserAgentReader : public RangeReader {
6465
= reinterpret_cast<const char*>(userAgentExtension.data() + userAgentOffset);
6566

6667
userAgentExtension
67-
= userAgentExtension.subspan(userAgentOffset + userAgentLength->length);
68+
= userAgentExtension.subspan(userAgentOffset + userAgentLength->value);
6869

6970
return UserAgent {id->value, {userAgent, userAgentLength->value}};
7071
});

src/plugins/process/common/tlsParser/tlsParser.cpp

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "tlsParser.hpp"
1313

1414
#include "extensionReaders/extensionReader.hpp"
15+
#include "extensionReaders/serverNameReader.hpp"
1516
#include "extensionReaders/userAgentReader.hpp"
1617
#include "tlsHandshake.hpp"
1718
#include "tlsHeader.hpp"
@@ -84,11 +85,11 @@ parseHeader(std::span<const std::byte> payload, const bool isQUIC) noexcept
8485
if (isQUIC) {
8586
return 0;
8687
}
87-
const auto* tlsHeader = reinterpret_cast<const TLSHeader*>(payload.data());
8888

8989
if (sizeof(TLSHeader) > payload.size()) {
9090
return std::nullopt;
9191
}
92+
const auto* tlsHeader = reinterpret_cast<const TLSHeader*>(payload.data());
9293

9394
if (tlsHeader->type != TLSHeader::Type::HANDSHAKE) {
9495
return std::nullopt;
@@ -103,6 +104,10 @@ parseHeader(std::span<const std::byte> payload, const bool isQUIC) noexcept
103104

104105
bool TLSParser::parseExtensions(const std::function<bool(const TLSExtension&)>& callable) noexcept
105106
{
107+
if (!m_extensions.has_value()) {
108+
return false;
109+
}
110+
106111
ExtensionReader reader;
107112
return std::ranges::all_of(reader.getRange(*m_extensions), callable)
108113
&& reader.parsedSuccessfully();
@@ -152,15 +157,26 @@ static std::optional<TLSHandshake> parseHandshake(std::span<const std::byte> pay
152157
return *handshake;
153158
}
154159

155-
constexpr static std::optional<TLSParser::CipherSuites>
156-
parseClientCipherSuites(std::span<const std::byte> payload) noexcept
160+
struct ParsedCipherSuitesSection {
161+
TLSParser::CipherSuites cipherSuites;
162+
std::size_t sectionLength;
163+
};
164+
165+
constexpr static std::optional<ParsedCipherSuitesSection> parseClientCipherSuites(
166+
std::span<const std::byte> payload,
167+
const TLSHandshake::Type handshakeType) noexcept
157168
{
158-
auto res = std::make_optional<TLSParser::CipherSuites>();
169+
auto res = std::make_optional<ParsedCipherSuitesSection>();
159170

160171
if (payload.size() < sizeof(uint16_t)) {
161172
return std::nullopt;
162173
}
163174

175+
if (handshakeType == TLSHandshake::Type::SERVER_HELLO) {
176+
res->sectionLength = sizeof(uint16_t);
177+
return res;
178+
}
179+
164180
const uint16_t clientCipherSuitesLength
165181
= ntohs(*reinterpret_cast<const uint16_t*>(payload.data()));
166182
if (sizeof(clientCipherSuitesLength) + clientCipherSuitesLength > payload.size()) {
@@ -173,8 +189,10 @@ parseClientCipherSuites(std::span<const std::byte> payload) noexcept
173189
clientCipherSuitesLength / sizeof(uint16_t))
174190
| std::views::transform(ntohs)
175191
| std::views::filter(std::not_fn(TLSParser::isGreaseValue))
176-
| std::views::take(res->capacity()),
177-
std::back_inserter(*res));
192+
| std::views::take(res->cipherSuites.capacity()),
193+
std::back_inserter(res->cipherSuites));
194+
195+
res->sectionLength = sizeof(clientCipherSuitesLength) + clientCipherSuitesLength;
178196

179197
return res;
180198
}
@@ -195,22 +213,26 @@ bool TLSParser::parse(std::span<const std::byte> payload, const bool isQUIC) noe
195213
constexpr std::size_t randomBytesLength = 32;
196214
const std::size_t sessionIdLengthOffset
197215
= handshakeOffset + sizeof(TLSHandshake) + randomBytesLength;
216+
if (payload.size() < sessionIdLengthOffset) {
217+
return false;
218+
}
219+
198220
const std::optional<uint8_t> sessionIdSectionLength
199221
= getSessionIdSectionLength(payload.subspan(sessionIdLengthOffset));
200222
if (!sessionIdSectionLength) {
201223
return false;
202224
}
203225

204226
const std::size_t cipherSuitesOffset = sessionIdLengthOffset + *sessionIdSectionLength;
205-
if (handshake->type == TLSHandshake::Type::CLIENT_HELLO) {
206-
cipherSuites = parseClientCipherSuites(payload.subspan(cipherSuitesOffset));
207-
if (!cipherSuites.has_value()) {
208-
return false;
209-
}
227+
const std::optional<ParsedCipherSuitesSection> parsedCipherSuitesSection
228+
= parseClientCipherSuites(payload.subspan(cipherSuitesOffset), handshake->type);
229+
if (!parsedCipherSuitesSection.has_value()) {
230+
return false;
210231
}
232+
cipherSuites = parsedCipherSuitesSection->cipherSuites;
211233

212-
const std::size_t compressionMethodsOffset = cipherSuitesOffset + sizeof(uint16_t)
213-
+ (cipherSuites.has_value() ? cipherSuites->size() * sizeof(uint16_t) : 0);
234+
const std::size_t compressionMethodsOffset
235+
= cipherSuitesOffset + parsedCipherSuitesSection->sectionLength;
214236
const std::optional<std::size_t> compressionMethodsLength
215237
= getCompressionMethodsLength(payload.subspan(compressionMethodsOffset), *handshake);
216238
if (!compressionMethodsLength.has_value()) {
@@ -241,7 +263,7 @@ TLSParser::parseServerNames(std::span<const std::byte> extension) noexcept
241263
return std::nullopt;
242264
}
243265

244-
PrefixedLengthStringReader<uint16_t> reader;
266+
ServerNameReader reader;
245267
std::ranges::copy(
246268
reader.getRange(extension.subspan(sizeof(servernameListLength), servernameListLength))
247269
| std::views::take(res->capacity()),
@@ -259,10 +281,13 @@ TLSParser::parseUserAgent(std::span<const std::byte> extension) noexcept
259281
auto res = std::make_optional<UserAgents>();
260282

261283
UserAgentReader reader;
284+
285+
constexpr static std::size_t GOOGLE_USER_AGENT_ID = 12585;
262286
std::ranges::copy(
263-
reader.getRange(extension) | std::views::transform([](const UserAgent& userAgent) {
264-
return userAgent.value;
265-
}) | std::views::take(res->capacity()),
287+
reader.getRange(extension) | std::views::filter([](const UserAgent& userAgent) {
288+
return userAgent.id == GOOGLE_USER_AGENT_ID;
289+
}) | std::views::transform([](const UserAgent& userAgent) { return userAgent.value; })
290+
| std::views::take(res->capacity()),
266291
std::back_inserter(*res));
267292
if (!reader.parsedSuccessfully()) {
268293
return std::nullopt;
@@ -386,7 +411,8 @@ std::optional<TLSParser::SupportedVersions> TLSParser::parseSupportedVersions(
386411
toSpan<const uint16_t>(
387412
extension.data() + sizeof(versionsLength),
388413
versionsLength / sizeof(uint16_t))
389-
| std::views::transform(std::not_fn(isGreaseValue)),
414+
| std::views::filter(std::not_fn(isGreaseValue)) | std::views::transform(ntohs)
415+
| std::views::take(res->capacity()),
390416
std::back_inserter(*res));
391417

392418
return res;

src/plugins/process/quic/src/quicInitialHeaderView.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ encryptSample(const QUICInitialSecrets& initialSecrets, std::span<const std::byt
276276
return std::nullopt;
277277
}
278278

279+
if (updateLength + finalLength > plaintext.size()) {
280+
return std::nullopt;
281+
}
282+
279283
return toSpan<const std::byte>(plaintext.data(), updateLength + finalLength);
280284
}
281285

@@ -321,6 +325,15 @@ static std::optional<QUICInitialHeaderView::DeobfuscatedHeader> decryptInitialHe
321325
// = payload.subspan(-primaryHeaderLength, payload.size() + primaryHeaderLength);
322326
const std::byte deobfuscatedFormHeader = payload[0] ^ (mask[0] & std::byte {0x0f});
323327
const uint8_t packetNumberLength = (static_cast<uint8_t>(deobfuscatedFormHeader) & 0x03) + 1;
328+
329+
if (encryptedPacketNumber + packetNumberLength - payload.data() > payload.size()) {
330+
return std::nullopt;
331+
}
332+
if (encryptedPacketNumber + packetNumberLength - payload.data()
333+
> deobfuscatedHeader->capacity()) {
334+
return std::nullopt;
335+
}
336+
324337
deobfuscatedHeader->insert(
325338
deobfuscatedHeader->end(),
326339
payload.data(),
@@ -688,8 +701,6 @@ reassembleCryptoFrames(std::span<const std::byte> decryptedPayload) noexcept
688701
bool QUICInitialHeaderView::parseTLSExtensions(TLSParser& parser) noexcept
689702
{
690703
const bool extensionsParsed = parser.parseExtensions([&](const TLSExtension& extension) {
691-
std::cout << "Parsing extension type: " << std::hex << static_cast<uint16_t>(extension.type)
692-
<< "\n";
693704
if (extension.type == TLSExtensionType::SERVER_NAME && !extension.payload.empty()) {
694705
const std::optional<TLSParser::ServerNames> parsedServerNames
695706
= parser.parseServerNames(extension.payload);
@@ -820,6 +831,9 @@ std::optional<QUICInitialHeaderView> QUICInitialHeaderView::createFrom(
820831
return std::nullopt;
821832
}
822833
res->tokenLength = tokenLength->value;
834+
if (tokenLength->length + tokenLength->value > payload.size()) {
835+
return std::nullopt;
836+
}
823837

824838
const std::optional<VariableLengthInt> restPayloadLength
825839
= readQUICVariableLengthInt(payload.subspan(tokenLength->length + tokenLength->value));

src/plugins/process/quic/src/quicParser.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ bool QUICParser::parse(
135135
for (std::optional<std::size_t> secondaryHeaderSize = std::nullopt;
136136
payload.size() >= MIN_PACKET_SIZE;
137137
payload = payload.subspan(*secondaryHeaderSize)) {
138-
// TODO CHECK IF SUBSPAN NOT STARTS AFTER SPAN END
139138
const std::optional<QUICHeaderView> headerView
140139
= QUICHeaderView::createFrom(payload, l4Protocol);
141140
if (!headerView.has_value()) {

0 commit comments

Comments
 (0)