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