25
25
#pragma clang diagnostic ignored "-Wunused-local-typedef"
26
26
#pragma clang diagnostic ignored "-Winfinite-recursion"
27
27
#endif
28
+
28
29
#include < boost/algorithm/string.hpp>
30
+ #include < boost/asio/steady_timer.hpp>
31
+ #include < boost/bind.hpp>
32
+
33
+ #if defined(CPPREST_BOTAN_SSL)
34
+ #include < botan/asio_stream.h>
35
+ #else
29
36
#include < boost/asio.hpp>
30
37
#include < boost/asio/ssl.hpp>
31
38
#include < boost/asio/ssl/error.hpp>
32
- #include < boost/asio/steady_timer.hpp >
33
- # include < boost/bind.hpp >
39
+ #endif
40
+
34
41
#if defined(__clang__)
35
42
#pragma clang diagnostic pop
36
43
#endif
@@ -87,8 +94,7 @@ namespace
87
94
{
88
95
const std::string CRLF (" \r\n " );
89
96
90
- std::string calc_cn_host (const web::http::uri& baseUri,
91
- const web::http::http_headers& requestHeaders)
97
+ std::string calc_cn_host (const web::http::uri& baseUri, const web::http::http_headers& requestHeaders)
92
98
{
93
99
std::string result;
94
100
if (baseUri.scheme () == U (" https" ))
@@ -142,9 +148,18 @@ static std::string generate_base64_userpass(const ::web::credentials& creds)
142
148
143
149
class asio_connection_pool ;
144
150
151
+ #if defined(CPPREST_BOTAN_SSL)
152
+ using ssl_stream_t = Botan::TLS::Stream<tcp::socket&, Botan::TLS::Client>;
153
+ using ssl_handshake_type_t = Botan::TLS::handshake_type;
154
+ #else
155
+ using ssl_stream_t = boost::asio::ssl::stream<tcp::socket&>;
156
+ using ssl_handshake_type_t = boost::asio::ssl::stream_base::handshake_type;
157
+ #endif
158
+
145
159
class asio_connection
146
160
{
147
161
friend class asio_client ;
162
+ using ssl_context_t = http_client::ssl_context;
148
163
149
164
public:
150
165
asio_connection (boost::asio::io_service& io_service)
@@ -161,20 +176,24 @@ class asio_connection
161
176
~asio_connection () { close (); }
162
177
163
178
// This simply instantiates the internal state to support ssl. It does not perform the handshake.
164
- void upgrade_to_ssl (std::string&& cn_hostname,
165
- const std::function<void (boost::asio::ssl::context&)>& ssl_context_callback)
179
+ void upgrade_to_ssl (std::string&& cn_hostname, const std::function<void (ssl_context_t &)>& ssl_context_callback)
166
180
{
167
181
std::lock_guard<std::mutex> lock (m_socket_lock);
168
182
assert (!is_ssl ());
183
+ #if defined(CPPREST_BOTAN_SSL)
184
+ Botan::TLS::Context ssl_context;
185
+ ssl_context_callback (ssl_context);
186
+ ssl_context.serverInfo = Botan::TLS::Server_Information (m_cn_hostname);
187
+ #else
169
188
boost::asio::ssl::context ssl_context (boost::asio::ssl::context::sslv23);
170
189
ssl_context.set_default_verify_paths ();
171
190
ssl_context.set_options (boost::asio::ssl::context::default_workarounds);
172
191
if (ssl_context_callback)
173
192
{
174
193
ssl_context_callback (ssl_context);
175
194
}
176
- m_ssl_stream = utility::details::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket&>>(
177
- m_socket, ssl_context);
195
+ # endif
196
+ m_ssl_stream = utility::details::make_unique< ssl_stream_t >( m_socket, ssl_context);
178
197
m_cn_hostname = std::move (cn_hostname);
179
198
}
180
199
@@ -232,6 +251,7 @@ class asio_connection
232
251
// server due to inactivity. Unfortunately, the exact error we get
233
252
// in this case depends on the Boost.Asio version used.
234
253
#if BOOST_ASIO_VERSION >= 101008
254
+ // TODO
235
255
if (boost::asio::ssl::error::stream_truncated == ec) return true ;
236
256
#else // Asio < 1.10.8 didn't have ssl::error::stream_truncated
237
257
if (boost::system::error_code (ERR_PACK (ERR_LIB_SSL, 0 , SSL_R_SHORT_READ),
@@ -259,14 +279,17 @@ class asio_connection
259
279
}
260
280
261
281
template <typename HandshakeHandler, typename CertificateHandler>
262
- void async_handshake (boost::asio::ssl::stream_base::handshake_type type,
282
+ void async_handshake (ssl_handshake_type_t type,
263
283
const http_client_config& config,
264
284
const HandshakeHandler& handshake_handler,
265
285
const CertificateHandler& cert_handler)
266
286
{
267
287
std::lock_guard<std::mutex> lock (m_socket_lock);
268
288
assert (is_ssl ());
269
289
290
+ #if !defined(CPPREST_BOTAN_SSL)
291
+ // This is configured via the Botan::TLS::Context callback in the Botan case
292
+
270
293
// Check to turn on/off server certificate verification.
271
294
if (config.validate_certificates ())
272
295
{
@@ -283,7 +306,7 @@ class asio_connection
283
306
{
284
307
SSL_set_tlsext_host_name (m_ssl_stream->native_handle (), &m_cn_hostname[0 ]);
285
308
}
286
-
309
+ # endif
287
310
m_ssl_stream->async_handshake (type, handshake_handler);
288
311
}
289
312
@@ -337,7 +360,7 @@ class asio_connection
337
360
// as normal message processing.
338
361
std::mutex m_socket_lock;
339
362
tcp::socket m_socket;
340
- std::unique_ptr<boost::asio::ssl::stream<tcp::socket&> > m_ssl_stream;
363
+ std::unique_ptr<ssl_stream_t > m_ssl_stream;
341
364
std::string m_cn_hostname;
342
365
343
366
bool m_is_reused;
@@ -1062,10 +1085,13 @@ class asio_context final : public request_context, public std::enable_shared_fro
1062
1085
{
1063
1086
const auto weakCtx = std::weak_ptr<asio_context>(shared_from_this ());
1064
1087
m_connection->async_handshake (
1065
- boost::asio::ssl::stream_base ::client,
1088
+ ssl_handshake_type_t ::client,
1066
1089
m_http_client->client_config (),
1067
1090
boost::bind (&asio_context::handle_handshake, shared_from_this (), boost::asio::placeholders::error),
1068
1091
1092
+ #if defined(CPPREST_BOTAN_SSL)
1093
+ false // unused
1094
+ #else
1069
1095
// Use a weak_ptr since the verify_callback is stored until the connection is
1070
1096
// destroyed. This avoids creating a circular reference since we pool connection
1071
1097
// objects.
@@ -1076,7 +1102,9 @@ class asio_context final : public request_context, public std::enable_shared_fro
1076
1102
return this_request->handle_cert_verification (preverified, verify_context);
1077
1103
}
1078
1104
return false ;
1079
- });
1105
+ }
1106
+ #endif
1107
+ );
1080
1108
}
1081
1109
else
1082
1110
{
@@ -1096,7 +1124,7 @@ class asio_context final : public request_context, public std::enable_shared_fro
1096
1124
}
1097
1125
else
1098
1126
{
1099
- report_error (" Error in SSL handshake" , ec, httpclient_errorcode_context::handshake);
1127
+ report_error (" Error in SSL handshake: " + ec. message () , ec, httpclient_errorcode_context::handshake);
1100
1128
}
1101
1129
}
1102
1130
0 commit comments