ircd::net::socket: Support non-SSL sockets.

This commit is contained in:
Jason Volk 2023-03-18 11:20:57 -07:00
parent 3fcfaddc3e
commit 4e16f1849b
5 changed files with 99 additions and 35 deletions

View File

@ -65,6 +65,9 @@ struct ircd::net::open_opts
/// if given. Defaults to null; no application is made.
const sock_opts *sopts { nullptr };
/// Option to disable SSL. Use false for plaintext socket.
bool secure { true };
/// Option to toggle whether to perform the SSL handshake; you want true.
bool handshake { true };

View File

@ -28,7 +28,7 @@ namespace ircd::net
}
/// Internal socket interface
///
/// Socket cannot be copied or moved; must be constructed as shared ptr.
struct [[gnu::visibility("protected")]]
ircd::net::socket
:std::enable_shared_from_this<ircd::net::socket>
@ -40,6 +40,7 @@ ircd::net::socket
using endpoint = ip::tcp::endpoint;
using wait_type = ip::tcp::socket::wait_type;
using message_flags = asio::socket_base::message_flags;
using ssl_stream = asio::ssl::stream<ip::tcp::socket &>;
using handshake_type = asio::ssl::stream<ip::tcp::socket>::handshake_type;
using ec_handler = std::function<void (const error_code &)>;
using eptr_handler = std::function<void (std::exception_ptr)>;
@ -64,7 +65,7 @@ ircd::net::socket
uint64_t id {++count};
ip::tcp::socket sd;
asio::ssl::stream<ip::tcp::socket &> ssl;
std::optional<ssl_stream> ssl;
endpoint local, remote;
stat in, out;
deadline_timer timer;
@ -120,9 +121,8 @@ ircd::net::socket
void connect(const endpoint &, const open_opts &, eptr_handler);
bool cancel() noexcept;
socket(asio::ssl::context & = sslv23_client);
// Socket cannot be copied or moved; must be constructed as shared ptr
socket(asio::ssl::context &);
socket();
socket(socket &&) = delete;
socket(const socket &) = delete;
socket &operator=(socket &&) = delete;

View File

@ -759,7 +759,13 @@ ircd::net::open(const open_opts &opts)
{
ctx::promise<std::shared_ptr<socket>> p;
ctx::future<std::shared_ptr<socket>> f(p);
auto s{std::make_shared<socket>()};
auto s
{
opts.secure?
std::make_shared<socket>(sslv23_client):
std::make_shared<socket>()
};
open(*s, opts, [s, p(std::move(p))]
(std::exception_ptr eptr)
mutable
@ -779,7 +785,13 @@ std::shared_ptr<ircd::net::socket>
ircd::net::open(const open_opts &opts,
open_callback handler)
{
auto s{std::make_shared<socket>()};
auto s
{
opts.secure?
std::make_shared<socket>(sslv23_client):
std::make_shared<socket>()
};
open(*s, opts, std::move(handler));
return s;
}
@ -1475,9 +1487,22 @@ ircd::net::socket::total_calls_out
};
//
// socket
// socket::socket
//
ircd::net::socket::socket()
:sd
{
ios::get()
}
,timer
{
ios::get()
}
{
++instances;
}
ircd::net::socket::socket(asio::ssl::context &ssl)
:sd
{
@ -1485,7 +1510,7 @@ ircd::net::socket::socket(asio::ssl::context &ssl)
}
,ssl
{
this->sd, ssl
std::in_place, this->sd, ssl
}
,timer
{
@ -1568,6 +1593,7 @@ ircd::net::socket::handshake(const open_opts &opts,
{
assert(!fini);
assert(sd.is_open());
assert(ssl);
log::debug
{
@ -1596,8 +1622,8 @@ ircd::net::socket::handshake(const open_opts &opts,
if(opts.send_sni && server_name(opts))
openssl::server_name(*this, server_name(opts));
ssl.set_verify_callback(std::move(verify_handler));
ssl.async_handshake(handshake_type::client, ios::handle(desc_handshake, std::move(handshake_handler)));
ssl->set_verify_callback(std::move(verify_handler));
ssl->async_handshake(handshake_type::client, ios::handle(desc_handshake, std::move(handshake_handler)));
}
void
@ -1648,13 +1674,21 @@ try
case dc::SSL_NOTIFY:
{
if(!ssl)
{
// Redirect SSL_NOTIFY to another strategy for non-SSL sockets.
sd.shutdown(ip::tcp::socket::shutdown_both);
sd.close();
break;
}
auto disconnect_handler
{
std::bind(&socket::handle_disconnect, this, shared_from(*this), std::move(callback), ph::_1)
};
set_timeout(opts.timeout);
ssl.async_shutdown(ios::handle(desc_disconnect, std::move(disconnect_handler)));
ssl->async_shutdown(ios::handle(desc_disconnect, std::move(disconnect_handler)));
return;
}
}
@ -1796,7 +1830,7 @@ try
// real socket wait.
static char buf[64];
static const ilist<mutable_buffer> bufs{buf};
if(SSL_peek(ssl.native_handle(), buf, sizeof(buf)) > 0)
if(ssl && SSL_peek(ssl->native_handle(), buf, sizeof(buf)) > 0)
{
ircd::dispatch{desc_wait[1], ios::defer, [handle(std::move(handle))]
{
@ -1868,7 +1902,7 @@ noexcept
return make_error_code(std::errc::not_connected);
std::error_code ret;
if(SSL_peek(ssl.native_handle(), buf, sizeof(buf)) > 0)
if(ssl && SSL_peek(ssl->native_handle(), buf, sizeof(buf)) > 0)
return ret;
assert(!blocking(*this));
@ -1914,7 +1948,9 @@ try
continuation::asio_predicate, interruption, [this, &ret, &bufs]
(auto &yield)
{
ret = asio::async_read(ssl, bufs, completion, yield);
ret = ssl?
asio::async_read(*ssl, bufs, completion, yield):
asio::async_read(sd, bufs, completion, yield);
}
};
@ -1954,7 +1990,9 @@ try
continuation::asio_predicate, interruption, [this, &ret, &bufs]
(auto &yield)
{
ret = ssl.async_read_some(bufs, yield);
ret = ssl?
ssl->async_read_some(bufs, yield):
sd.async_read_some(bufs, yield);
}
};
@ -1990,7 +2028,9 @@ ircd::net::socket::read_any(const mutable_buffers &bufs)
boost::system::error_code ec;
const size_t ret
{
asio::read(ssl, bufs, completion, ec)
ssl?
asio::read(*ssl, bufs, completion, ec):
asio::read(sd, bufs, completion, ec)
};
++in.calls;
@ -2018,7 +2058,9 @@ ircd::net::socket::read_one(const mutable_buffers &bufs)
boost::system::error_code ec;
const size_t ret
{
ssl.read_some(bufs, ec)
ssl?
ssl->read_some(bufs, ec):
sd.read_some(bufs, ec)
};
++in.calls;
@ -2061,7 +2103,9 @@ try
continuation::asio_predicate, interruption, [this, &ret, &bufs]
(auto &yield)
{
ret = asio::async_write(ssl, bufs, completion, yield);
ret = ssl?
asio::async_write(*ssl, bufs, completion, yield):
asio::async_write(sd, bufs, completion, yield);
}
};
@ -2096,7 +2140,9 @@ try
continuation::asio_predicate, interruption, [this, &ret, &bufs]
(auto &yield)
{
ret = ssl.async_write_some(bufs, yield);
ret = ssl?
ssl->async_write_some(bufs, yield):
sd.async_write_some(bufs, yield);
}
};
@ -2126,7 +2172,9 @@ try
assert(!blocking(*this));
const size_t ret
{
asio::write(ssl, bufs, completion)
ssl?
asio::write(*ssl, bufs, completion):
asio::write(sd, bufs, completion)
};
++out.calls;
@ -2150,7 +2198,9 @@ try
assert(!blocking(*this));
const size_t ret
{
ssl.write_some(bufs)
ssl?
ssl->write_some(bufs):
sd.write_some(bufs)
};
++out.calls;
@ -2192,8 +2242,10 @@ noexcept try
{
const auto has_pending
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
SSL_has_pending(ssl.native_handle())
#if OPENSSL_VERSION_NUMBER >= 0x1010000L
ssl?
SSL_has_pending(ssl->native_handle()):
0
#else
0
#endif
@ -2209,7 +2261,7 @@ noexcept try
type == ready::READ? bytes : 0UL,
type == ready::READ? available(*this) : 0UL,
has_pending,
SSL_pending(ssl.native_handle()),
ssl? SSL_pending(ssl->native_handle()): 0,
};
}
@ -2385,8 +2437,11 @@ noexcept try
set(*this, *opts.sopts);
// The user can opt out of performing the handshake here.
if(!opts.handshake)
if(!ssl || !opts.handshake)
{
blocking(*this, false);
return call_user(callback, ec);
}
assert(!fini);
handshake(opts, std::move(callback));
@ -2809,18 +2864,20 @@ ircd::net::socket::set_timeout(const milliseconds &t,
ircd::net::socket::operator
SSL &()
{
assert(ssl.native_handle());
return *ssl.native_handle();
assert(ssl);
assert(ssl->native_handle());
return *ssl->native_handle();
}
ircd::net::socket::operator
const SSL &()
const
{
using type = typename std::remove_const<decltype(socket::ssl)>::type;
auto &ssl(const_cast<type &>(this->ssl));
assert(ssl.native_handle());
return *ssl.native_handle();
auto &ssl(mutable_cast(this)->ssl);
assert(ssl);
assert(ssl->native_handle());
return *ssl->native_handle();
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -580,7 +580,7 @@ noexcept try
};
sock->set_timeout(milliseconds(timeout));
sock->ssl.async_handshake(handshake_type, ios::handle(handshake_desc, std::move(handshake)));
sock->ssl->async_handshake(handshake_type, ios::handle(handshake_desc, std::move(handshake)));
assert(!openssl::get_app_data(*sock));
openssl::set_app_data(*sock, sock.get());
}

View File

@ -2910,7 +2910,9 @@ ircd::server::link::discard_read()
const ssize_t has_pending
{
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
SSL_has_pending(socket->ssl.native_handle())
socket->ssl?
SSL_has_pending(socket->ssl->native_handle()):
-2L
#else
-2L
#endif
@ -2918,7 +2920,9 @@ ircd::server::link::discard_read()
const ssize_t pending
{
SSL_pending(socket->ssl.native_handle())
socket->ssl?
SSL_pending(socket->ssl->native_handle()):
0L
};
const size_t discarded