@@ -282,6 +282,10 @@ namespace web { namespace http
282
282
boost::asio::deadline_timer m_timeout_timer;
283
283
std::shared_ptr<linux_connection> m_connection;
284
284
285
+ #if defined(__APPLE__) || defined(ANDROID)
286
+ bool m_openssl_failed;
287
+ #endif
288
+
285
289
virtual ~linux_client_request_context ();
286
290
287
291
void handle_timeout_timer (const boost::system::error_code& ec)
@@ -334,9 +338,7 @@ namespace web { namespace http
334
338
335
339
if (m_uri.scheme () == " https" )
336
340
{
337
- boost::asio::ssl::context context (boost::asio::ssl::context::sslv23);
338
- context.set_default_verify_paths ();
339
- ctx->m_ssl_stream .reset (new boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>(ctx->m_connection ->socket (), context));
341
+ reset_ssl_stream (ctx);
340
342
}
341
343
342
344
auto encoded_resource = uri_builder (m_uri).append (ctx->m_request .relative_uri ()).to_uri ().resource ().to_string ();
@@ -398,8 +400,6 @@ namespace web { namespace http
398
400
else
399
401
{
400
402
has_body = false ;
401
- extra_headers.append (header_names::content_length);
402
- extra_headers.append (" :0" + CRLF);
403
403
}
404
404
}
405
405
@@ -453,9 +453,6 @@ namespace web { namespace http
453
453
454
454
private:
455
455
tcp::resolver m_resolver;
456
- #if defined(__APPLE__) || defined(ANDROID)
457
- bool m_openssl_failed;
458
- #endif
459
456
460
457
static bool _check_streambuf (std::shared_ptr<linux_client_request_context> ctx, concurrency::streams::streambuf<uint8_t > rdbuf, const utility::char_t * msg)
461
458
{
@@ -474,6 +471,29 @@ namespace web { namespace http
474
471
return rdbuf.is_open ();
475
472
}
476
473
474
+ // Helper function to create ssl stream and set verification options.
475
+ void reset_ssl_stream (const std::shared_ptr<linux_client_request_context> &ctx)
476
+ {
477
+ boost::asio::ssl::context sslContext (boost::asio::ssl::context::sslv23);
478
+ sslContext.set_default_verify_paths ();
479
+ sslContext.set_options (boost::asio::ssl::context::default_workarounds);
480
+ ctx->m_ssl_stream .reset (new boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>(ctx->m_connection ->socket (), sslContext));
481
+
482
+ // Check to turn off server certificate verification.
483
+ if (client_config ().validate_certificates ())
484
+ {
485
+ ctx->m_ssl_stream ->set_verify_mode (boost::asio::ssl::context::verify_peer);
486
+ ctx->m_ssl_stream ->set_verify_callback (boost::bind (&linux_client::handle_cert_verification, shared_from_this (), _1, _2, ctx));
487
+ #if defined(__APPLE__) || defined(ANDROID)
488
+ ctx->m_openssl_failed = false ;
489
+ #endif
490
+ }
491
+ else
492
+ {
493
+ ctx->m_ssl_stream ->set_verify_mode (boost::asio::ssl::context::verify_none);
494
+ }
495
+ }
496
+
477
497
void handle_resolve (const boost::system::error_code& ec, tcp::resolver::iterator endpoints, std::shared_ptr<linux_client_request_context> ctx)
478
498
{
479
499
if (ec)
@@ -483,22 +503,6 @@ namespace web { namespace http
483
503
else
484
504
{
485
505
auto endpoint = *endpoints;
486
- if (ctx->m_ssl_stream )
487
- {
488
- // Check to turn off server certificate verification.
489
- if (client_config ().validate_certificates ())
490
- {
491
- ctx->m_ssl_stream ->set_verify_mode (boost::asio::ssl::context::verify_peer);
492
- ctx->m_ssl_stream ->set_verify_callback (boost::bind (&linux_client::handle_cert_verification, shared_from_this (), _1, _2));
493
- #if defined(__APPLE__) || defined(ANDROID)
494
- m_openssl_failed = false ;
495
- #endif
496
- }
497
- else
498
- {
499
- ctx->m_ssl_stream ->set_verify_mode (boost::asio::ssl::context::verify_none);
500
- }
501
- }
502
506
ctx->m_connection ->socket ().async_connect (endpoint, boost::bind (&linux_client::handle_connect, shared_from_this (), boost::asio::placeholders::error, ++endpoints, ctx));
503
507
}
504
508
}
@@ -515,7 +519,7 @@ namespace web { namespace http
515
519
}
516
520
}
517
521
518
- void handle_connect (const boost::system::error_code& ec, tcp::resolver::iterator endpoints, std::shared_ptr<linux_client_request_context> ctx)
522
+ void handle_connect (const boost::system::error_code& ec, tcp::resolver::iterator endpoints, const std::shared_ptr<linux_client_request_context> & ctx)
519
523
{
520
524
if (!ec)
521
525
{
@@ -531,35 +535,21 @@ namespace web { namespace http
531
535
532
536
// Replace the connection. This causes old connection object to go out of scope.
533
537
ctx->m_connection = m_pool.obtain ();
534
-
535
- auto endpoint = *endpoints;
538
+
536
539
if (ctx->m_ssl_stream )
537
540
{
538
- boost::asio::ssl::context context (boost::asio::ssl::context::sslv23);
539
- context.set_default_verify_paths ();
540
- ctx->m_ssl_stream .reset (new boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>(ctx->m_connection ->socket (), context));
541
-
542
- // Check to turn off server certificate verification.
543
- if (client_config ().validate_certificates ())
544
- {
545
- ctx->m_ssl_stream ->set_verify_mode (boost::asio::ssl::context::verify_peer);
546
- ctx->m_ssl_stream ->set_verify_callback (boost::bind (&linux_client::handle_cert_verification, shared_from_this (), _1, _2));
547
- #if defined(__APPLE__) || defined(ANDROID)
548
- m_openssl_failed = false ;
549
- #endif
550
- }
551
- else
552
- {
553
- ctx->m_ssl_stream ->set_verify_mode (boost::asio::ssl::context::verify_none);
554
- }
541
+ reset_ssl_stream (ctx);
555
542
}
556
-
543
+ auto endpoint = *endpoints;
557
544
ctx->m_connection ->socket ().async_connect (endpoint, boost::bind (&linux_client::handle_connect, shared_from_this (), boost::asio::placeholders::error, ++endpoints, ctx));
558
545
}
559
546
}
560
547
561
- bool handle_cert_verification (bool preverified, boost::asio::ssl::verify_context &ctx )
548
+ bool handle_cert_verification (bool preverified, boost::asio::ssl::verify_context &verifyCtx, const std::shared_ptr<linux_client_request_context> &requestCtx )
562
549
{
550
+ // Unreferenced parameter on some platforms.
551
+ requestCtx;
552
+
563
553
// OpenSSL calls the verification callback once per certificate in the chain,
564
554
// starting with the root CA certificate. The 'leaf', non-Certificate Authority (CA)
565
555
// certificate, i.e. actual server certificate is at the '0' position in the
@@ -569,15 +559,15 @@ namespace web { namespace http
569
559
#if defined(__APPLE__) || defined(ANDROID)
570
560
if (!preverified)
571
561
{
572
- m_openssl_failed = true ;
562
+ requestCtx-> m_openssl_failed = true ;
573
563
}
574
- if (m_openssl_failed)
564
+ if (requestCtx-> m_openssl_failed )
575
565
{
576
566
// On OS X, iOS, and Android, OpenSSL doesn't have access to where the OS
577
567
// stores keychains. If OpenSSL fails we will doing verification at the
578
568
// end using the whole certificate chain so wait until the 'leaf' cert.
579
569
// For now return true so OpenSSL continues down the certificate chain.
580
- X509_STORE_CTX *storeContext = ctx .native_handle ();
570
+ X509_STORE_CTX *storeContext = verifyCtx .native_handle ();
581
571
int currentDepth = X509_STORE_CTX_get_error_depth (storeContext);
582
572
if (currentDepth != 0 )
583
573
{
@@ -621,7 +611,7 @@ namespace web { namespace http
621
611
#endif
622
612
623
613
boost::asio::ssl::rfc2818_verification rfc2818 (m_uri.host ());
624
- return rfc2818 (preverified, ctx );
614
+ return rfc2818 (preverified, verifyCtx );
625
615
}
626
616
627
617
void handle_handshake (const boost::system::error_code& ec, std::shared_ptr<linux_client_request_context> ctx)
@@ -1184,6 +1174,9 @@ namespace web { namespace http
1184
1174
, m_timedout(false )
1185
1175
, m_timeout_timer(crossplat::threadpool::shared_instance().service())
1186
1176
, m_connection(std::move(connection))
1177
+ #if defined(__APPLE__) || defined(ANDROID)
1178
+ , m_openssl_failed(false )
1179
+ #endif
1187
1180
{}
1188
1181
1189
1182
std::shared_ptr<request_context> linux_client_request_context::create_request_context (
0 commit comments