Require server verification when SSL is enabled.

If SSL is "enabled" via command line without specifying a fingerprint or
certificate, the system CA list is checked for server verification and
_now_ fails the handshake if that check fails. This change was made to
remain consistent with standard SSL/TLS client behavior. This can still
be overridden by using the allow any certificate flag.

If the SSL behavior is autodetect, the system CA list is still checked
but a warning is logged if this fails. The stream is not rejected
because a re-connect will be attempted - its better to have an
unverified encrypted stream than an unverified + unencrypted stream.
This commit is contained in:
Lee Clagett 2019-03-17 22:06:36 -04:00
parent 96d602ac84
commit 0416764cae
2 changed files with 16 additions and 11 deletions

View file

@ -104,6 +104,12 @@ namespace net_utils
boost::asio::ssl::context create_context() const; boost::asio::ssl::context create_context() const;
/*! \note If `this->support == autodetect && this->verification != none`,
then the handshake will not fail when peer verification fails. The
assumption is that a re-connect will be attempted, so a warning is
logged instead of failure.
\return True if the SSL handshake completes with peer verification
settings. */
bool handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type) const; bool handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type) const;
}; };

View file

@ -313,7 +313,6 @@ bool ssl_options_t::has_fingerprint(boost::asio::ssl::verify_context &ctx) const
bool ssl_options_t::handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type) const bool ssl_options_t::handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type) const
{ {
bool verified = false;
socket.next_layer().set_option(boost::asio::ip::tcp::no_delay(true)); socket.next_layer().set_option(boost::asio::ip::tcp::no_delay(true));
/* Using system-wide CA store for client verification is funky - there is /* Using system-wide CA store for client verification is funky - there is
@ -335,11 +334,16 @@ bool ssl_options_t::handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::soc
{ {
// preverified means it passed system or user CA check. System CA is never loaded // preverified means it passed system or user CA check. System CA is never loaded
// when fingerprints are whitelisted. // when fingerprints are whitelisted.
if (!preverified && verification == ssl_verification_t::user_certificates && !has_fingerprint(ctx)) { if (!preverified && !has_fingerprint(ctx))
MERROR("Certificate is not in the allowed list, connection droppped"); {
// autodetect will reconnect without SSL - warn and keep connection encrypted
if (support != ssl_support_t::e_ssl_support_autodetect)
{
MERROR("SSL certificate is not in the allowed list, connection droppped");
return false; return false;
} }
verified = true; MWARNING("SSL peer has not been verified");
}
return true; return true;
}); });
} }
@ -348,12 +352,7 @@ bool ssl_options_t::handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::soc
socket.handshake(type, ec); socket.handshake(type, ec);
if (ec) if (ec)
{ {
MERROR("handshake failed, connection dropped: " << ec.message()); MERROR("SSL handshake failed, connection dropped: " << ec.message());
return false;
}
if (verification == ssl_verification_t::none && !verified)
{
MERROR("Peer did not provide a certificate in the allowed list, connection dropped");
return false; return false;
} }
MDEBUG("SSL handshake success"); MDEBUG("SSL handshake success");