Botan 3.10.0
Crypto and TLS for C&
tls_session_manager_memory.cpp
Go to the documentation of this file.
1/**
2 * TLS Session Management
3 * (C) 2011,2012 Jack Lloyd
4 * 2023 René Meusel - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#include <botan/tls_session_manager_memory.h>
10
11#include <botan/rng.h>
12#include <botan/internal/stl_util.h>
13
14namespace Botan::TLS {
15
16Session_Manager_In_Memory::Session_Manager_In_Memory(const std::shared_ptr<RandomNumberGenerator>& rng,
17 size_t max_sessions) :
18 Session_Manager(rng), m_max_sessions(max_sessions) {
19 if(max_sessions > 0) {
20 m_fifo.emplace();
21 }
22}
23
24void Session_Manager_In_Memory::store(const Session& session, const Session_Handle& handle) {
25 // TODO: C++20 allows CTAD for template aliases (read: lock_guard_type), so
26 // technically we should be able to omit the explicit mutex type.
27 // Unfortunately clang does not agree, yet.
29
30 if(m_fifo.has_value()) {
31 while(m_sessions.size() >= capacity()) {
32 BOTAN_ASSERT_NOMSG(m_sessions.size() <= m_fifo->size());
33 m_sessions.erase(m_fifo->front());
34 m_fifo->pop_front();
35 }
36 }
37
38 // Generate a random session ID if the peer did not provide one. Note that
39 // this ID is just for internal use and won't be returned on ::find().
40 auto id = handle.id().value_or(m_rng->random_vec<Session_ID>(32));
41 m_sessions.emplace(id, Session_with_Handle{session, handle});
42
43 if(m_fifo.has_value()) {
44 m_fifo->emplace_back(std::move(id));
45 }
46}
47
48std::optional<Session> Session_Manager_In_Memory::retrieve_one(const Session_Handle& handle) {
50
51 if(auto id = handle.id()) {
52 const auto session = m_sessions.find(id.value());
53 if(session != m_sessions.end()) {
54 return session->second.session;
55 }
56 }
57
58 return std::nullopt;
59}
60
61std::vector<Session_with_Handle> Session_Manager_In_Memory::find_some(const Server_Information& info,
62 const size_t max_sessions_hint) {
63 BOTAN_UNUSED(max_sessions_hint);
64
66
67 std::vector<Session_with_Handle> found_sessions;
68 // TODO: std::copy_if?
69 for(const auto& [_, session_and_handle] : m_sessions) {
70 if(session_and_handle.session.server_info() == info) {
71 found_sessions.emplace_back(session_and_handle);
72 }
73 }
74
75 return found_sessions;
76}
77
80 return remove_internal(handle);
81}
82
83size_t Session_Manager_In_Memory::remove_internal(const Session_Handle& handle) {
84 return std::visit(overloaded{
85 // We deliberately leave the deleted session in m_fifo. Finding it would be
86 // another O(n) operation. Instead, purging will run in a loop and skip m_fifo
87 // entries that were not found anymore.
88 [&](const Session_Ticket& ticket) -> size_t {
89 // TODO: This is an O(n) operation. Typically, the Session_Manager will
90 // not contain a plethora of sessions and this should be fine. If
91 // it's not, we'll need to consider another index on tickets.
92 return std::erase_if(m_sessions, [&](const auto& item) {
93 const auto& [_unused1, session_and_handle] = item;
94 const auto& [_unused2, this_handle] = session_and_handle;
95 return this_handle.is_ticket() && this_handle.ticket().value() == ticket;
96 });
97 },
98 [&](const Session_ID& id) -> size_t { return m_sessions.erase(id); },
99 [&](const Opaque_Session_Handle&) -> size_t {
100 if(auto id = handle.id()) {
101 auto removed = remove_internal(Session_Handle(id.value()));
102 if(removed > 0) {
103 return removed;
104 }
105 }
106
107 if(auto ticket = handle.ticket()) {
108 return remove_internal(Session_Handle(ticket.value()));
109 }
110
111 return 0;
112 },
113 },
114 handle.get());
115}
116
119
120 const auto sessions = m_sessions.size();
121 m_sessions.clear();
122 if(m_fifo.has_value()) {
123 m_fifo->clear();
124 }
125
126 return sessions;
127}
128
129} // namespace Botan::TLS
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
Helper class to embody a session handle in all protocol versions.
Definition tls_session.h:63
std::optional< Session_Ticket > ticket() const
decltype(auto) get() const
std::optional< Session_ID > id() const
void store(const Session &session, const Session_Handle &handle) override
Save a Session under a Session_Handle (TLS Client).
BOTAN_FUTURE_EXPLICIT Session_Manager_In_Memory(const std::shared_ptr< RandomNumberGenerator > &rng, size_t max_sessions=1000)
std::vector< Session_with_Handle > find_some(const Server_Information &info, size_t max_sessions_hint) override
Internal retrieval function to find sessions to resume.
size_t remove(const Session_Handle &handle) override
std::optional< Session > retrieve_one(const Session_Handle &handle) override
Internal retrieval function for a single session.
recursive_mutex_type & mutex()
BOTAN_FUTURE_EXPLICIT Session_Manager(const std::shared_ptr< RandomNumberGenerator > &rng)
std::shared_ptr< RandomNumberGenerator > m_rng
Strong< std::vector< uint8_t >, struct Session_ID_ > Session_ID
holds a TLS 1.2 session ID for stateful resumption
Definition tls_session.h:31
Strong< std::vector< uint8_t >, struct Session_Ticket_ > Session_Ticket
holds a TLS 1.2 session ticket for stateless resumption
Definition tls_session.h:34
Strong< std::vector< uint8_t >, struct Opaque_Session_Handle_ > Opaque_Session_Handle
holds an opaque session handle as used in TLS 1.3 that could be either a ticket for stateless resumpt...
Definition tls_session.h:38
lock_guard< T > lock_guard_type
Definition mutex.h:55