Botan 3.4.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.h>
14#include <botan/types.h>
15
16#if defined(BOTAN_HAS_TLS_13)
17 #include <botan/tls_psk_identity_13.h>
18#endif
19
20#include <chrono>
21#include <map>
22#include <utility>
23#include <variant>
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 public:
47 Session_Manager(const std::shared_ptr<RandomNumberGenerator>& rng);
48
49 /**
50 * @brief Save a new Session and assign a Session_Handle (TLS Server)
51 *
52 * Save a new session on a best effort basis; the manager may not in fact
53 * be able to save the session for whatever reason; this is not an error.
54 * Callers cannot assume that calling establish() followed immediately by
55 * retrieve() or choose_from_offered_tickets() will result in a successful
56 * lookup. In case no session was stored, std::nullopt is returned.
57 *
58 * This method is only called on TLS servers.
59 *
60 * Note that implementations will silently refrain from sending session
61 * tickets to the client when this method returns std::nullopt.
62 *
63 * @param session to save
64 * @param id to use (instead of an ID chosen by the manager)
65 * @param tls12_no_ticket disable tickets for this establishment
66 * (set when TLS 1.2 client does not support them)
67 * @return a Session_Handle containing either an ID or a ticket
68 * if the session was saved, otherwise std::nullopt
69 */
70 virtual std::optional<Session_Handle> establish(const Session& session,
71 const std::optional<Session_ID>& id = std::nullopt,
72 bool tls12_no_ticket = false);
73
74 /**
75 * @brief Save a Session under a Session_Handle (TLS Client)
76 *
77 * Save a session on a best effort basis; the manager may not in fact be
78 * able to save the session for whatever reason; this is not an error.
79 * Callers cannot assume that calling store() followed immediately by
80 * find() will result in a successful lookup.
81 *
82 * In contrast to establish(), this stores sessions that were created by
83 * the server along with a Session_Handle also coined by the server.
84 *
85 * This method is only called on TLS clients.
86 *
87 * @param session to save
88 * @param handle a Session_Handle on which this session shoud by stored
89 */
90 virtual void store(const Session& session, const Session_Handle& handle) = 0;
91
92#if defined(BOTAN_HAS_TLS_13)
93 /**
94 * Lets the server application choose a PSK to use for a new TLS
95 * connection. Implementers must make sure that the PSK's associated
96 * hash function is equal to the passed @p hash_function.
97 *
98 * RFC 8446 4.2.11
99 * The server MUST ensure that it selects a compatible PSK (if any)
100 * and cipher suite.
101 *
102 * The default implementation simply tries to retrieve all tickets in
103 * the order offered by the peer and picks the first that is found and
104 * features a matching hash algorithm.
105 *
106 * This method is called only by TLS 1.3 servers.
107 *
108 * @param tickets a list of tickets that were offered by the client
109 * @param hash_function the hash algorithm name we are going to use for
110 * the to-be-negotiated connection
111 * @param callbacks callbacks to be used for session policy decisions
112 * @param policy policy to be used for session policy decisions
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>> choose_from_offered_tickets(
121 const std::vector<PskIdentity>& 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, Callbacks& callbacks, const Policy& policy);
151
152 /**
153 * @brief Find all sessions that match a given server @p info
154 *
155 * TLS clients use this to obtain session resumption information for a
156 * server they are wishing to handshake with. Typically, session info will
157 * have been received in prior connections to that same server and stored
158 * using Session_Manager::store().
159 *
160 * The default implementation will invoke Session_Manager::find_some() and
161 * filter the result against a policy. Most notably an expiry check.
162 * Expired sessions will be removed via Session_Manager::remove().
163 *
164 * The TLS client implementations will query the session manager exactly
165 * once per handshake attempt. If no reuse is desired, the session manager
166 * may remove the sessions internally when handing them out to the client.
167 * The default implementation adheres to Policy::reuse_session_tickets().
168 *
169 * For TLS 1.2 the client implementation will attempt a resumption with
170 * the first session in the returned list. For TLS 1.3, it will offer all
171 * found sessions to the server.
172 *
173 * Applications that wish to implement their own Session_Manager may
174 * override the default implementation to add further policy checks.
175 * Though, typically implementing Session_Manager::find_some() and
176 * relying on the default implementation is enough.
177 *
178 * @param info the info about the server we want to handshake with
179 * @param callbacks callbacks to be used for session policy decisions
180 * @param policy policy to be used for session policy decisions
181 * @return a list of usable sessions that might be empty if no
182 * such session exists or passed the policy validation
183 */
184 virtual std::vector<Session_with_Handle> find(const Server_Information& info,
185 Callbacks& callbacks,
186 const Policy& policy);
187
188 /**
189 * Remove a specific session from the cache, if it exists.
190 * The handle might contain either a session ID or a ticket.
191 *
192 * @param handle a Session_Handle of the session to be removed
193 * @return the number of sessions that were removed
194 */
195 virtual size_t remove(const Session_Handle& handle) = 0;
196
197 /**
198 * Remove all sessions from the cache
199 * @return the number of sessions that were removed
200 */
201 virtual size_t remove_all() = 0;
202
203 /**
204 * Declares whether the given Session_Manager implementation may emit
205 * session tickets. Note that this _does not_ mean that the implementation
206 * must always emit tickets.
207 *
208 * Concrete implementations should declare this, to allow the TLS
209 * implementations to act accordingly. E.g. to advertise support for
210 * session tickets in their Server Hello.
211 *
212 * @return true if the Session_Manager produces session tickets
213 */
214 virtual bool emits_session_tickets() { return false; }
215
216 virtual ~Session_Manager() = default;
217
218 protected:
219 /**
220 * @brief Internal retrieval function for a single session
221 *
222 * Try to obtain a Session from a Session_Handle that contains either
223 * a session ID or a session ticket. This method should not apply any
224 * policy decision (such as ticket expiry) but simply be a storage
225 * interface.
226 *
227 * Applications that wish to implement their own Session_Manager will
228 * have to provide an implementation for it.
229 *
230 * This method is called only by servers.
231 *
232 * @param handle a Session_Handle containing either an ID or a ticket
233 * @return the obtained session or std::nullopt if none can be obtained
234 */
235 virtual std::optional<Session> retrieve_one(const Session_Handle& handle) = 0;
236
237 /**
238 * @brief Internal retrieval function to find sessions to resume
239 *
240 * Try to find saved sessions using info about the server we're planning
241 * to connect to. It should return a list of sessions in preference order
242 * of the session manager.
243 *
244 * Applications that wish to implement their own Session_Manager will
245 * have to provide an implementation for it.
246 *
247 * Note that the TLS client implementations do not perform any checks on
248 * the validity of the session for a given @p info. Particularly, it is
249 * the Session_Manager's responsibility to ensure the restrictions posed
250 * in RFC 8446 4.6.1 regarding server certificate validity for the given
251 * @p info.
252 *
253 * This is called for TLS clients only.
254 *
255 * @param info the information about the server
256 * @param max_sessions_hint a non-binding guideline for an upper bound of
257 * sessions to return from this method
258 * (will be at least 1 but potentially more)
259 * @return the found sessions along with their handles (containing either a
260 * session ID or a ticket)
261 */
262 virtual std::vector<Session_with_Handle> find_some(const Server_Information& info, size_t max_sessions_hint) = 0;
263
264 /**
265 * Returns the base class' recursive mutex for reuse in derived classes
266 */
267 recursive_mutex_type& mutex() { return m_mutex; }
268
269 private:
270 std::vector<Session_with_Handle> find_and_filter(const Server_Information& info,
271 Callbacks& callbacks,
272 const Policy& policy);
273
274 protected:
275 std::shared_ptr<RandomNumberGenerator> m_rng;
276
277 private:
278 recursive_mutex_type m_mutex;
279};
280
281} // namespace Botan::TLS
282
283#endif
Helper class to embody a session handle in all protocol versions.
Definition tls_session.h:64
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()
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.
std::shared_ptr< RandomNumberGenerator > m_rng
virtual size_t remove_all()=0
#define BOTAN_PUBLIC_API(maj, min)
Definition compiler.h:31