Skip to content

Commit 490921c

Browse files
committed
TCP input TLS - Add TlsDecoder.
1 parent ba746de commit 490921c

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

src/plugins/input/tcp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_library(tcp-input MODULE
1414
src/Plugin.cpp
1515
src/IpxPlugin.cpp
1616
src/tls/Ssl.cpp
17+
src/tls/TlsDecoder.cpp
1718
)
1819

1920
find_package(LibLz4 REQUIRED)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* \file
3+
* \author Jakub Antonín Štigler <[email protected]>
4+
* \brief TLS decoder for IPFIX plugin. (source file)
5+
* \date 2025
6+
*
7+
* Copyright: (C) 2023 CESNET, z.s.p.o.
8+
* SPDX-License-Identifier: BSD-3-Clause
9+
*/
10+
11+
#include "TlsDecoder.hpp"
12+
13+
namespace tcp_in {
14+
namespace tls {
15+
16+
// Size of buffer for copying data from OpenSSL to DecodeBuffer.
17+
constexpr std::size_t BUFFER_SIZE = 4096;
18+
19+
TlsDecoder::TlsDecoder(SslCtx &ctx, int fd) :
20+
m_ssl(ctx.create_ssl()),
21+
m_buffer(BUFFER_SIZE)
22+
{
23+
SslBio bio(BIO_s_socket());
24+
bio.set_fd(fd);
25+
m_ssl.set_bio(std::move(bio));
26+
27+
m_handshake_complete = m_ssl.accept();
28+
}
29+
30+
DecodeBuffer &TlsDecoder::decode() {
31+
if (!m_handshake_complete) {
32+
m_handshake_complete = m_ssl.accept();
33+
if (!m_handshake_complete) {
34+
return m_decoded;
35+
}
36+
}
37+
38+
// XXX: The copy to intermidiate `m_buffer` can be avoided by extending `DecodeBuffer` to be
39+
// able to read with generic read function.
40+
41+
while (!m_decoded.enough_data()) {
42+
auto res = m_ssl.read_ex(m_buffer);
43+
m_decoded.read_from(m_buffer.data(), m_buffer.size());
44+
switch (res) {
45+
case ReadResult::READ:
46+
break;
47+
case ReadResult::WAIT:
48+
return m_decoded;
49+
case ReadResult::FINISHED:
50+
// FIXME: properly check that the shutdown is complete.
51+
m_ssl.shutdown();
52+
// Intentional falltrough
53+
case ReadResult::CLOSED:
54+
m_decoded.signal_eof();
55+
return m_decoded;
56+
}
57+
}
58+
59+
return m_decoded;
60+
}
61+
62+
} // namespace tls
63+
} // namespace tcp_in
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* \file
3+
* \author Jakub Antonín Štigler <[email protected]>
4+
* \brief TLS decoder for IPFIX plugin. (header file)
5+
* \date 2025
6+
*
7+
* Copyright: (C) 2023 CESNET, z.s.p.o.
8+
* SPDX-License-Identifier: BSD-3-Clause
9+
*/
10+
11+
#pragma once
12+
13+
#include <vector>
14+
15+
#include "../Decoder.hpp"
16+
#include "../UniqueFd.hpp"
17+
#include "SslCtx.hpp"
18+
#include "Ssl.hpp"
19+
20+
namespace tcp_in {
21+
namespace tls {
22+
23+
// TLS content type handshake
24+
/** Identifies data for which `TlsDecoder` should be used. */
25+
constexpr std::uint8_t TLS_MAGIC = 22;
26+
27+
/** Decoder for TLS connections. */
28+
class TlsDecoder : public Decoder {
29+
public:
30+
/**
31+
* @brief Create new TLS decoder with shared context.
32+
* @param ctx Initialized shared context. Its configuration is not modified.
33+
* @param fd Stream for TLS communication (Usually TCP).
34+
*/
35+
TlsDecoder(SslCtx &ctx, int fd);
36+
37+
/**
38+
* @brief Reads all available data from TLS stream and returns buffer with decoded messages.
39+
* @returns Buffer with decoded messages.
40+
*/
41+
virtual DecodeBuffer &decode() override;
42+
43+
/**
44+
* @brief Gets the name of the decoder.
45+
* @return returns `"TLS"`.
46+
*/
47+
virtual const char *get_name() const override { return "TLS"; }
48+
49+
private:
50+
Ssl m_ssl;
51+
bool m_handshake_complete = false;
52+
DecodeBuffer m_decoded;
53+
std::vector<std::uint8_t> m_buffer;
54+
};
55+
56+
} // namespace tls
57+
} // namespace tcp_in

0 commit comments

Comments
 (0)