17
17
#include < botan/pkix_types.h>
18
18
#include < botan/certstor_flatfile.h>
19
19
#include < botan/x509path.h>
20
+ #include < botan/tls_session_manager_memory.h>
20
21
21
22
using namespace trantor ;
22
23
using namespace std ::placeholders;
23
24
24
- static Botan::System_RNG sessionManagerRng;
25
- // Is this Ok? C++ technically doesn't guarantee static object initialization
26
- // order.
27
- static Botan::TLS::Session_Manager_In_Memory sessionManager (sessionManagerRng);
28
- static thread_local Botan::System_RNG rng;
25
+ static std::once_flag sessionManagerInitFlag;
26
+ static std::shared_ptr<Botan::AutoSeeded_RNG> sessionManagerRng;
27
+ static std::shared_ptr<Botan::TLS::Session_Manager_In_Memory> sessionManager;
28
+ static thread_local std::shared_ptr<Botan::AutoSeeded_RNG> rng;
29
29
static Botan::System_Certificate_Store certStore;
30
30
31
31
using namespace trantor ;
32
32
33
33
class Credentials : public Botan ::Credentials_Manager
34
34
{
35
35
public:
36
- Credentials (Botan::Private_Key * key,
36
+ Credentials (std::shared_ptr< Botan::Private_Key> key,
37
37
Botan::X509_Certificate *cert,
38
38
Botan::Certificate_Store *certStore)
39
39
: certStore_(certStore), cert_(cert), key_(key)
@@ -50,28 +50,33 @@ class Credentials : public Botan::Credentials_Manager
50
50
return {certStore_};
51
51
}
52
52
53
- std::vector<Botan::X509_Certificate> cert_chain (
53
+ std::vector<Botan::X509_Certificate> find_cert_chain (
54
54
const std::vector<std::string> &cert_key_types,
55
+ const std::vector<Botan::AlgorithmIdentifier> &cert_signature_schemes,
56
+ const std::vector<Botan::X509_DN> &acceptable_CAs,
55
57
const std::string &type,
56
58
const std::string &context) override
57
59
{
58
60
(void )type;
59
61
(void )context;
62
+ (void )cert_signature_schemes;
63
+ (void )acceptable_CAs;
60
64
if (cert_ == nullptr )
61
65
return {};
62
66
63
67
auto key_algo =
64
- cert_->subject_public_key_algo ().get_oid ().to_formatted_string ();
68
+ cert_->subject_public_key_algo ().oid ().to_formatted_string ();
65
69
auto it =
66
70
std::find (cert_key_types.begin (), cert_key_types.end (), key_algo);
67
71
if (it == cert_key_types.end ())
68
72
return {};
69
73
return {*cert_};
70
74
}
71
75
72
- Botan::Private_Key *private_key_for (const Botan::X509_Certificate &cert,
73
- const std::string &type,
74
- const std::string &context) override
76
+ std::shared_ptr<Botan::Private_Key> private_key_for (
77
+ const Botan::X509_Certificate &cert,
78
+ const std::string &type,
79
+ const std::string &context) override
75
80
{
76
81
(void )cert;
77
82
(void )type;
@@ -80,7 +85,7 @@ class Credentials : public Botan::Credentials_Manager
80
85
}
81
86
Botan::Certificate_Store *certStore_ = nullptr ;
82
87
Botan::X509_Certificate *cert_ = nullptr ;
83
- Botan::Private_Key * key_ = nullptr ;
88
+ std::shared_ptr< Botan::Private_Key> key_ = nullptr ;
84
89
};
85
90
86
91
struct BotanCertificate : public Certificate
@@ -110,7 +115,7 @@ namespace trantor
110
115
{
111
116
struct SSLContext
112
117
{
113
- std::unique_ptr <Botan::Private_Key> key;
118
+ std::shared_ptr <Botan::Private_Key> key;
114
119
std::unique_ptr<Botan::X509_Certificate> cert;
115
120
std::shared_ptr<Botan::Certificate_Store> certStore;
116
121
bool isServer = false ;
@@ -136,14 +141,16 @@ class TrantorPolicy : public Botan::TLS::Policy
136
141
137
142
struct BotanTLSProvider : public TLSProvider ,
138
143
public NonCopyable,
139
- public Botan::TLS::Callbacks
144
+ public Botan::TLS::Callbacks,
145
+ public std::enable_shared_from_this<BotanTLSProvider>
140
146
{
141
147
public:
142
148
BotanTLSProvider (TcpConnection *conn,
143
149
TLSPolicyPtr policy,
144
150
SSLContextPtr ctx)
145
151
: TLSProvider(conn, std::move(policy), std::move(ctx))
146
152
{
153
+ validationPolicy_ = std::make_shared<TrantorPolicy>();
147
154
}
148
155
149
156
virtual void recvData (MsgBuffer *buffer) override
@@ -163,7 +170,7 @@ struct BotanTLSProvider : public TLSProvider,
163
170
164
171
if (tlsConnected_ == false )
165
172
{
166
- if (e.type () == Botan::TLS::Alert::BAD_CERTIFICATE )
173
+ if (e.type () == Botan::TLS::Alert::BadCertificate )
167
174
handleSSLError (SSLError::kSSLInvalidCertificate );
168
175
else
169
176
handleSSLError (SSLError::kSSLHandshakeError );
@@ -226,31 +233,44 @@ struct BotanTLSProvider : public TLSProvider,
226
233
227
234
virtual void startEncryption () override
228
235
{
229
- credsPtr_ = std::make_unique <Credentials>(contextPtr_->key . get () ,
236
+ credsPtr_ = std::make_shared <Credentials>(contextPtr_->key ,
230
237
contextPtr_->cert .get (),
231
238
contextPtr_->certStore .get ());
232
239
if (policyPtr_->getConfCmds ().empty () == false )
233
240
LOG_WARN << " BotanTLSConnectionImpl does not support sslConfCmds." ;
241
+
242
+ // initialize rng and session manager if we haven't already
243
+ std::call_once (sessionManagerInitFlag, []() {
244
+ sessionManagerRng = std::make_shared<Botan::AutoSeeded_RNG>();
245
+ sessionManager =
246
+ std::make_shared<Botan::TLS::Session_Manager_In_Memory>(
247
+ sessionManagerRng);
248
+ });
249
+ if (rng == nullptr )
250
+ rng = std::make_shared<Botan::AutoSeeded_RNG>();
234
251
if (contextPtr_->isServer )
235
252
{
236
253
// TODO: Need a more scalable way to manage session validation rules
237
- validationPolicy_. requireClientCert_ =
254
+ validationPolicy_-> requireClientCert_ =
238
255
contextPtr_->requireClientCert ;
239
- channel_ = std::make_unique<Botan::TLS::Server>(
240
- *this , sessionManager, *credsPtr_, validationPolicy_, rng);
256
+ channel_ = std::make_unique<Botan::TLS::Server>(shared_from_this (),
257
+ sessionManager,
258
+ credsPtr_,
259
+ validationPolicy_,
260
+ rng);
241
261
}
242
262
else
243
263
{
244
- validationPolicy_. requireClientCert_ =
264
+ validationPolicy_-> requireClientCert_ =
245
265
contextPtr_->requireClientCert ;
246
266
// technically Botan2 does support TLS 1.0 and 1.1, but Botan3 does
247
267
// not. So we just disable them to keep compatibility.
248
268
if (policyPtr_->getUseOldTLS ())
249
269
LOG_WARN << " Old TLS not supported by Botan (only >= TLS 1.2)" ;
250
270
channel_ = std::make_unique<Botan::TLS::Client>(
251
- * this ,
271
+ shared_from_this () ,
252
272
sessionManager,
253
- * credsPtr_,
273
+ credsPtr_,
254
274
validationPolicy_,
255
275
rng,
256
276
Botan::TLS::Server_Information (policyPtr_->getHostname (),
@@ -270,32 +290,32 @@ struct BotanTLSProvider : public TLSProvider,
270
290
271
291
virtual ~BotanTLSProvider () override = default ;
272
292
273
- void tls_emit_data (const uint8_t data[], size_t size ) override
293
+ void tls_emit_data (std::span< const uint8_t > data) override
274
294
{
275
- auto n = writeCallback_ (conn_, data, size );
295
+ auto n = writeCallback_ (conn_, data. data (), data. size_bytes () );
276
296
lastWriteSize_ = n;
277
297
278
298
// store the unsent data and send it later
279
- if (n == ssize_t (size ))
299
+ if (n == ssize_t (data. size_bytes () ))
280
300
return ;
281
301
if (n == -1 )
282
302
n = 0 ;
283
- appendToWriteBuffer ((const char *)data + n, size - n);
303
+ appendToWriteBuffer ((const char *)data.data () + n,
304
+ data.size_bytes () - n);
284
305
}
285
306
286
307
void tls_record_received (uint64_t seq_no,
287
- const uint8_t data[],
288
- size_t size) override
308
+ std::span<const uint8_t > data) override
289
309
{
290
310
(void )seq_no;
291
- recvBuffer_.append ((const char *)data, size );
311
+ recvBuffer_.append ((const char *)data. data (), data. size_bytes () );
292
312
if (messageCallback_)
293
313
messageCallback_ (conn_, &recvBuffer_);
294
314
}
295
315
296
316
void tls_alert (Botan::TLS::Alert alert) override
297
317
{
298
- if (alert.type () == Botan::TLS::Alert::CLOSE_NOTIFY )
318
+ if (alert.type () == Botan::TLS::Alert::CloseNotify )
299
319
{
300
320
LOG_TRACE << " TLS close notify received" ;
301
321
if (closeCallback_)
@@ -324,7 +344,7 @@ struct BotanTLSProvider : public TLSProvider,
324
344
325
345
void tls_verify_cert_chain (
326
346
const std::vector<Botan::X509_Certificate> &certs,
327
- const std::vector<std::shared_ptr< const Botan::OCSP::Response>> &ocsp,
347
+ const std::vector<std::optional< Botan::OCSP::Response>> &ocsp,
328
348
const std::vector<Botan::Certificate_Store *> &trusted_roots,
329
349
Botan::Usage_Type usage,
330
350
const std::string &hostname,
@@ -338,38 +358,31 @@ struct BotanTLSProvider : public TLSProvider,
338
358
{
339
359
if (certs.size () == 0 )
340
360
throw Botan::TLS::TLS_Exception (
341
- Botan::TLS::Alert::NO_CERTIFICATE ,
361
+ Botan::TLS::Alert::NoCertificate ,
342
362
" Certificate validation failed: no certificate" );
343
363
// handle self-signed certificate
344
- std::vector<std::shared_ptr<const Botan::X509_Certificate>>
345
- selfSigned = {
346
- std::make_shared<Botan::X509_Certificate>(certs[0 ])};
364
+ std::vector<Botan::X509_Certificate> selfSigned = {certs[0 ]};
347
365
348
366
Botan::Path_Validation_Restrictions restrictions (
349
367
false , // require revocation
350
- validationPolicy_. minimum_signature_strength ());
368
+ validationPolicy_-> minimum_signature_strength ());
351
369
352
370
auto now = std::chrono::system_clock::now ();
353
- const auto status =
354
- Botan::PKIX::check_chain (selfSigned,
355
- now,
356
- hostname,
357
- usage,
358
- restrictions.minimum_key_strength (),
359
- restrictions.trusted_hashes ());
371
+ const auto status = Botan::PKIX::check_chain (
372
+ selfSigned, now, hostname, usage, restrictions);
360
373
361
374
const auto result = Botan::PKIX::overall_status (status);
362
375
363
376
if (result != Botan::Certificate_Status_Code::OK)
364
377
throw Botan::TLS::TLS_Exception (
365
- Botan::TLS::Alert::BAD_CERTIFICATE ,
378
+ Botan::TLS::Alert::BadCertificate ,
366
379
std::string (" Certificate validation failed: " ) +
367
380
Botan::to_string (result));
368
381
}
369
382
}
370
383
371
- TrantorPolicy validationPolicy_;
372
- std::unique_ptr <Botan::Credentials_Manager> credsPtr_;
384
+ std::shared_ptr< TrantorPolicy> validationPolicy_;
385
+ std::shared_ptr <Botan::Credentials_Manager> credsPtr_;
373
386
std::unique_ptr<Botan::TLS::Channel> channel_;
374
387
bool tlsConnected_ = false ;
375
388
ssize_t lastWriteSize_ = 0 ;
0 commit comments