Botan 3.0.0
Crypto and TLS for C&
tls_session_manager.h
Go to the documentation of this file.
1/*
2* TLS Session Manager
3* (C) 2011-2023 Jack Lloyd
4* 2022-2023 René Meusel - Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#ifndef BOTAN_TLS_SESSION_MANAGER_H_
10#define BOTAN_TLS_SESSION_MANAGER_H_
11
12#include <botan/build.h>
13#include <botan/tls_session.h>
14#include <botan/mutex.h>
15
16#if defined(BOTAN_HAS_TLS_13)
17 #include <botan/tls_ticket_13.h>
18#endif
19
20#include <chrono>
21#include <map>
22#include <variant>
23#include <utility>
24
25namespace Botan {
26class RandomNumberGenerator;
27}
28
29namespace Botan::TLS {
30
31class Callbacks;
32class Policy;
33
34/**
35* Session_Manager is an interface to systems which can save session parameters
36* for supporting session resumption.
37*
38* Saving sessions is done on a best-effort basis; an implementation is
39* allowed to drop sessions due to space constraints or other issues.
40*
41* Implementations should strive to be thread safe. This base class provides a
42* recursive mutex (via Session_Manager::mutex()). Derived classes may simply
43* reuse this for their own locking.
44*/
46 {
47 public:
48 Session_Manager(const std::shared_ptr<RandomNumberGenerator>& rng);
49
50 /**
51 * @brief Save a new Session and assign a Session_Handle (TLS Server)
52 *
53 * Save a new session on a best effort basis; the manager may not in fact
54 * be able to save the session for whatever reason; this is not an error.
55 * Callers cannot assume that calling establish() followed immediately by
56 * retrieve() or choose_from_offered_tickets() will result in a successful
57 * lookup. In case no session was stored, std::nullopt is returned.
58 *
59 * This method is only called on TLS servers.
60 *
61 * Note that implementations will silently refrain from sending session
62 * tickets to the client when this method returns std::nullopt.
63 *
64 * @param session to save
65 * @param id to use (instead of an ID chosen by the manager)
66 * @param tls12_no_ticket disable tickets for this establishment
67 * (set when TLS 1.2 client does not support them)
68 * @return a Session_Handle containing either an ID or a ticket
69 * if the session was saved, otherwise std::nullopt
70 */
71 virtual std::optional<Session_Handle> establish(
72 const Session& session,
73 const std::optional<Session_ID>& id = std::nullopt,
74 bool tls12_no_ticket = false);
75
76 /**
77 * @brief Save a Session under a Session_Handle (TLS Client)
78 *
79 * Save a session on a best effort basis; the manager may not in fact be
80 * able to save the session for whatever reason; this is not an error.
81 * Callers cannot assume that calling store() followed immediately by
82 * find() will result in a successful lookup.
83 *
84 * In contrast to establish(), this stores sessions that were created by
85 * the server along with a Session_Handle also coined by the server.
86 *
87 * This method is only called on TLS clients.
88 *
89 * @param session to save
90 * @param handle a Session_Handle on which this session shoud by stored
91 */
92 virtual void store(const Session& session, const Session_Handle& handle) = 0;
93
94#if defined(BOTAN_HAS_TLS_13)
95 /**
96 * Lets the server application choose a PSK to use for a new TLS
97 * connection. Implementers must make sure that the PSK's associated
98 * hash function is equal to the passed @p hash_function.
99 *
100 * RFC 8446 4.2.11
101 * The server MUST ensure that it selects a compatible PSK (if any)
102 * and cipher suite.
103 *
104 * The default implementation simply tries to retrieve all tickets in
105 * the order offered by the peer and picks the first that is found and
106 * features a matching hash algorithm.
107 *
108 * This method is called only by TLS 1.3 servers.
109 *
110 * @param tickets a list of tickets that were offered by the client
111 * @param hash_function the hash algorithm name we are going to use for
112 * the to-be-negotiated connection
113 *
114 * @return a std::pair of the Session associated to the choosen PSK and
115 * the index of the selected ticket; std::nullopt if no PSK was
116 * chosen for usage (will result in a full handshake)
117 *
118 * @note if no PSK is chosen, the server will attempt a regular handshake.
119 */
120 virtual std::optional<std::pair<Session, uint16_t>>
121 choose_from_offered_tickets(const std::vector<Ticket>& tickets,
122 std::string_view hash_function,
123 Callbacks& callbacks,
124 const Policy& policy);
125#endif
126
127 /**
128 * @brief Retrieves a specific session given a @p handle
129 *
130 * This is typically used by TLS servers to obtain resumption information
131 * for a previous call to Session_Manager::establish() when a client
132 * requested resumption using the @p handle.
133 *
134 * Even if the session is found successfully, it is returned only if it
135 * passes policy validations. Most notably an expiry check. If the expiry
136 * check fails, the default implementation calls Session_Manager::remove()
137 * for the provided @p handle.
138 *
139 * Applications that wish to implement their own Session_Manager may
140 * override the default implementation to add further policy checks.
141 * Though, typically implementing Session_Manager::retrieve_one() and
142 * relying on the default implementation is enough.
143 *
144 * @param handle the Session_Handle to be retrieved
145 * @param callbacks callbacks to be used for session policy decisions
146 * @param policy policy to be used for session policy decisions
147 * @return the obtained session or std::nullopt if no session
148 * was found or the policy checks failed
149 */
150 virtual std::optional<Session> retrieve(const Session_Handle& handle,
151 Callbacks& callbacks,
152 const Policy& policy);
153
154 /**
155 * @brief Find all sessions that match a given server @p info
156 *
157 * TLS clients use this to obtain session resumption information for a
158 * server they are wishing to handshake with. Typically, session info will
159 * have been received in prior connections to that same server and stored
160 * using Session_Manager::store().
161 *
162 * The default implementation will invoke Session_Manager::find_some() and
163 * filter the result against a policy. Most notably an expiry check.
164 * Expired sessions will be removed via Session_Manager::remove().
165 *
166 * The TLS client implementations will query the session manager exactly
167 * once per handshake attempt. If no reuse is desired, the session manager
168 * may remove the sessions internally when handing them out to the client.
169 * The default implementation adheres to Policy::reuse_session_tickets().
170 *
171 * For TLS 1.2 the client implementation will attempt a resumption with
172 * the first session in the returned list. For TLS 1.3, it will offer all
173 * found sessions to the server.
174 *
175 * Applications that wish to implement their own Session_Manager may
176 * override the default implementation to add further policy checks.
177 * Though, typically implementing Session_Manager::find_some() and
178 * relying on the default implementation is enough.
179 *
180 * @param info the info about the server we want to handshake with
181 * @param callbacks callbacks to be used for session policy decisions
182 * @param policy policy to be used for session policy decisions
183 * @return a list of usable sessions that might be empty if no
184 * such session exists or passed the policy validation
185 */
186 virtual std::vector<Session_with_Handle> find(const Server_Information& info,
187 Callbacks& callbacks,
188 const Policy& policy);
189
190 /**
191 * Remove a specific session from the cache, if it exists.
192 * The handle might contain either a session ID or a ticket.
193 *
194 * @param handle a Session_Handle of the session to be removed
195 * @return the number of sessions that were removed
196 */
197 virtual size_t remove(const Session_Handle& handle) = 0;
198
199 /**
200 * Remove all sessions from the cache
201 * @return the number of sessions that were removed
202 */
203 virtual size_t remove_all() = 0;
204
205 /**
206 * Declares whether the given Session_Manager implementation may emit
207 * session tickets. Note that this _does not_ mean that the implementation
208 * must always emit tickets.
209 *
210 * Concrete implementations should declare this, to allow the TLS
211 * implementations to act accordingly. E.g. to advertise support for
212 * session tickets in their Server Hello.
213 *
214 * @return true if the Session_Manager produces session tickets
215 */
216 virtual bool emits_session_tickets() { return false; }
217
218 virtual ~Session_Manager() = default;
219
220 protected:
221 /**
222 * @brief Internal retrieval function for a single session
223 *
224 * Try to obtain a Session from a Session_Handle that contains either
225 * a session ID or a session ticket. This method should not apply any
226 * policy decision (such as ticket expiry) but simply be a storage
227 * interface.
228 *
229 * Applications that wish to implement their own Session_Manager will
230 * have to provide an implementation for it.
231 *
232 * This method is called only by servers.
233 *
234 * @param handle a Session_Handle containing either an ID or a ticket
235 * @return the obtained session or std::nullopt if none can be obtained
236 */
237 virtual std::optional<Session> retrieve_one(const Session_Handle& handle) = 0;
238
239 /**
240 * @brief Internal retrieval function to find sessions to resume
241 *
242 * Try to find saved sessions using info about the server we're planning
243 * to connect to. It should return a list of sessions in preference order
244 * of the session manager.
245 *
246 * Applications that wish to implement their own Session_Manager will
247 * have to provide an implementation for it.
248 *
249 * Note that the TLS client implementations do not perform any checks on
250 * the validity of the session for a given @p info. Particularly, it is
251 * the Session_Manager's responsibility to ensure the restrictions posed
252 * in RFC 8446 4.6.1 regarding server certificate validity for the given
253 * @p info.
254 *
255 * This is called for TLS clients only.
256 *
257 * @param info the information about the server
258 * @param max_sessions_hint a non-binding guideline for an upper bound of
259 * sessions to return from this method
260 * (will be at least 1 but potentially more)
261 * @return the found sessions along with their handles (containing either a
262 * session ID or a ticket)
263 */
264 virtual std::vector<Session_with_Handle> find_some(const Server_Information& info,
265 const size_t max_sessions_hint) = 0;
266
267 /**
268 * Returns the base class' recursive mutex for reuse in derived classes
269 */
270 recursive_mutex_type& mutex() { return m_mutex; }
271
272 private:
273 std::vector<Session_with_Handle> find_and_filter(const Server_Information& info,
274 Callbacks& callbacks,
275 const Policy& policy);
276
277 protected:
278 std::shared_ptr<RandomNumberGenerator> m_rng;
279
280 private:
281 recursive_mutex_type m_mutex;
282 };
283
284}
285
286#endif
Helper class to embody a session handle in all protocol versions.
Definition: tls_session.h:69
virtual ~Session_Manager()=default
virtual size_t remove(const Session_Handle &handle)=0
virtual std::vector< Session_with_Handle > find_some(const Server_Information &info, const size_t max_sessions_hint)=0
Internal retrieval function to find sessions to resume.
virtual std::optional< Session > retrieve_one(const Session_Handle &handle)=0
Internal retrieval function for a single session.
virtual void store(const Session &session, const Session_Handle &handle)=0
Save a Session under a Session_Handle (TLS Client)
recursive_mutex_type & mutex()
std::shared_ptr< RandomNumberGenerator > m_rng
virtual size_t remove_all()=0
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:31
Definition: alg_id.cpp:12