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
104105bool 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;
0 commit comments