Skip to content

Commit 112bba7

Browse files
authored
Merge pull request #174 from boostorg/168-no-way-to-specify-caclient-certificate-for-ssl-connections
Provides a way of passing a custom ssl context to the connection.
2 parents 4f86b4b + 1160347 commit 112bba7

File tree

6 files changed

+62
-40
lines changed

6 files changed

+62
-40
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -686,12 +686,12 @@ https://lists.boost.org/Archives/boost/2023/01/253944.php.
686686
not.
687687

688688
* ([Issue 168](https://github.com/boostorg/redis/issues/168)).
689-
Provides SSL context getters. The user wants to be able to pass the
690-
`ssl::context` in the connection constructor as is done in Boost.Beast
691-
and Boost.MySql. However, doing so would penalize users on plain
692-
connections, which would have to start passing a dummy context on
693-
every instantiation. If there is more convincing argument I will
694-
change this in the future.
689+
Provides a way of passing a custom SSL context to the connection.
690+
The design here differs from that of Boost.Beast and Boost.MySql
691+
since in Boost.Redis the connection owns the context instead of only
692+
storing a reference to a user provided one. This is ok so because
693+
apps need only one connection for their entire application, which
694+
makes the overhead of one ssl-context per connection negligible.
695695

696696
### Boost 1.84 (First release in Boost)
697697

example/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ macro(make_example EXAMPLE_NAME STANDARD)
1010
if (${STANDARD} STREQUAL "20")
1111
target_link_libraries(${EXAMPLE_NAME} PRIVATE examples_main)
1212
endif()
13-
if (${STANDARD} STREQUAL "20")
14-
target_link_libraries(${EXAMPLE_NAME} PRIVATE Boost::json)
13+
if (${EXAMPLE_NAME} STREQUAL "cpp20_json")
14+
target_link_libraries(${EXAMPLE_NAME} PRIVATE Boost::json Boost::container_hash)
1515
endif()
1616
endmacro()
1717

include/boost/redis/connection.hpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,29 @@ class basic_connection {
8686
using other = basic_connection<Executor1>;
8787
};
8888

89-
/// Contructs from an executor.
89+
/** @brief Constructor
90+
*
91+
* @param ex Executor on which connection operation will run.
92+
* @param ctx SSL context.
93+
* @param max_read_size Maximum read size that is passed to
94+
* the internal `asio::dynamic_buffer` constructor.
95+
*/
9096
explicit
9197
basic_connection(
9298
executor_type ex,
93-
asio::ssl::context::method method = asio::ssl::context::tls_client,
99+
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
94100
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)())
95-
: impl_{ex, method, max_read_size}
101+
: impl_{ex, std::move(ctx), max_read_size}
96102
, timer_{ex}
97103
{ }
98104

99105
/// Contructs from a context.
100106
explicit
101107
basic_connection(
102108
asio::io_context& ioc,
103-
asio::ssl::context::method method = asio::ssl::context::tls_client,
109+
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
104110
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)())
105-
: basic_connection(ioc.get_executor(), method, max_read_size)
111+
: basic_connection(ioc.get_executor(), std::move(ctx), max_read_size)
106112
{ }
107113

108114
/** @brief Starts underlying connection operations.
@@ -286,10 +292,6 @@ class basic_connection {
286292
auto const& get_ssl_context() const noexcept
287293
{ return impl_.get_ssl_context();}
288294

289-
/// Returns the ssl context.
290-
auto& get_ssl_context() noexcept
291-
{ return impl_.get_ssl_context();}
292-
293295
/// Resets the underlying stream.
294296
void reset_stream()
295297
{ impl_.reset_stream(); }
@@ -343,14 +345,14 @@ class connection {
343345
explicit
344346
connection(
345347
executor_type ex,
346-
asio::ssl::context::method method = asio::ssl::context::tls_client,
348+
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
347349
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)());
348350

349351
/// Contructs from a context.
350352
explicit
351353
connection(
352354
asio::io_context& ioc,
353-
asio::ssl::context::method method = asio::ssl::context::tls_client,
355+
asio::ssl::context ctx = asio::ssl::context{asio::ssl::context::tlsv12_client},
354356
std::size_t max_read_size = (std::numeric_limits<std::size_t>::max)());
355357

356358
/// Returns the underlying executor.
@@ -427,10 +429,6 @@ class connection {
427429
auto const& get_ssl_context() const noexcept
428430
{ return impl_.get_ssl_context();}
429431

430-
/// Returns the ssl context.
431-
auto& get_ssl_context() noexcept
432-
{ return impl_.get_ssl_context();}
433-
434432
private:
435433
void
436434
async_run_impl(

include/boost/redis/detail/connection_base.hpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,9 @@ class connection_base {
394394
/// Constructs from an executor.
395395
connection_base(
396396
executor_type ex,
397-
asio::ssl::context::method method,
397+
asio::ssl::context ctx,
398398
std::size_t max_read_size)
399-
: ctx_{method}
399+
: ctx_{std::move(ctx)}
400400
, stream_{std::make_unique<next_layer_type>(ex, ctx_)}
401401
, writer_timer_{ex}
402402
, receive_channel_{ex, 256}
@@ -411,10 +411,6 @@ class connection_base {
411411
auto const& get_ssl_context() const noexcept
412412
{ return ctx_;}
413413

414-
/// Returns the ssl context.
415-
auto& get_ssl_context() noexcept
416-
{ return ctx_;}
417-
418414
/// Resets the underlying stream.
419415
void reset_stream()
420416
{

include/boost/redis/impl/connection.ipp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ namespace boost::redis {
1010

1111
connection::connection(
1212
executor_type ex,
13-
asio::ssl::context::method method,
13+
asio::ssl::context ctx,
1414
std::size_t max_read_size)
15-
: impl_{ex, method, max_read_size}
15+
: impl_{ex, std::move(ctx), max_read_size}
1616
{ }
1717

1818
connection::connection(
1919
asio::io_context& ioc,
20-
asio::ssl::context::method method,
20+
asio::ssl::context ctx,
2121
std::size_t max_read_size)
22-
: impl_{ioc.get_executor(), method, max_read_size}
22+
: impl_{ioc.get_executor(), std::move(ctx), max_read_size}
2323
{ }
2424

2525
void

test/test_conn_tls.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ bool verify_certificate(bool, net::ssl::verify_context&)
2525
return true;
2626
}
2727

28-
BOOST_AUTO_TEST_CASE(ping)
28+
config make_tls_config()
2929
{
3030
config cfg;
3131
cfg.use_ssl = true;
@@ -34,7 +34,12 @@ BOOST_AUTO_TEST_CASE(ping)
3434
cfg.addr.host = "db.occase.de";
3535
cfg.addr.port = "6380";
3636
//cfg.health_check_interval = std::chrono::seconds{0};
37+
return cfg;
38+
}
3739

40+
BOOST_AUTO_TEST_CASE(ping_internal_ssl_context)
41+
{
42+
auto const cfg = make_tls_config();
3843
std::string const in = "Kabuf";
3944

4045
request req;
@@ -59,14 +64,37 @@ BOOST_AUTO_TEST_CASE(ping)
5964
BOOST_CHECK_EQUAL(in, std::get<0>(resp).value());
6065
}
6166

67+
BOOST_AUTO_TEST_CASE(ping_custom_ssl_context)
68+
{
69+
auto const cfg = make_tls_config();
70+
std::string const in = "Kabuf";
71+
72+
request req;
73+
req.push("PING", in);
74+
75+
response<std::string> resp;
76+
77+
net::io_context ioc;
78+
net::ssl::context ctx{boost::asio::ssl::context::tls_client};
79+
connection conn{ioc, std::move(ctx)};
80+
conn.next_layer().set_verify_mode(net::ssl::verify_peer);
81+
conn.next_layer().set_verify_callback(verify_certificate);
82+
83+
conn.async_exec(req, resp, [&](auto ec, auto) {
84+
BOOST_TEST(!ec);
85+
conn.cancel();
86+
});
87+
88+
conn.async_run(cfg, {}, [](auto) { });
89+
90+
ioc.run();
91+
92+
BOOST_CHECK_EQUAL(in, std::get<0>(resp).value());
93+
}
94+
6295
BOOST_AUTO_TEST_CASE(acl_does_not_allow_select)
6396
{
64-
config cfg;
65-
cfg.use_ssl = true;
66-
cfg.username = "aedis";
67-
cfg.password = "aedis";
68-
cfg.addr.host = "db.occase.de";
69-
cfg.addr.port = "6380";
97+
auto cfg = make_tls_config();
7098
cfg.database_index = 22;
7199
cfg.reconnect_wait_interval = std::chrono::seconds::zero();
72100

0 commit comments

Comments
 (0)