Skip to content

Commit

Permalink
core: implement ftp::ssl::create_context() function
Browse files Browse the repository at this point in the history
It provides a more convenient way to create the ftp::ssl::context_ptr object and allows to configure the SSL session resumption behavior.
  • Loading branch information
deniskovalchuk committed Jul 28, 2024
1 parent 94fcd20 commit bbeabba
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 16 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ set(sources
src/replies.cpp
src/reply.cpp
src/socket.cpp
src/ssl.cpp
src/ssl_socket.cpp
src/utils.cpp)

Expand Down
5 changes: 1 addition & 4 deletions example/ftps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,10 @@ int main(int argc, char *argv[])
/* Learn more about ssl_context in the Boost.Asio documentation.
* https://live.boost.org/doc/libs/1_85_0/doc/html/boost_asio/overview/ssl.html
*/
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tlsv13_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tlsv13_client, true);
ssl_context->set_default_verify_paths();
ssl_context->set_verify_mode(ftp::ssl::verify_peer);

/* Set SSL_SESS_CACHE_CLIENT to support SSL session resumption for data connections. */
SSL_CTX_set_session_cache_mode(ssl_context->native_handle(), SSL_SESS_CACHE_CLIENT);

ftp::client client(std::move(ssl_context));

handle_reply(client.connect("test.rebex.net", 21, "demo", "password"));
Expand Down
5 changes: 5 additions & 0 deletions include/ftp/ssl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,10 @@ namespace ftp::ssl
using namespace boost::asio::ssl;
using context_ptr = std::unique_ptr<boost::asio::ssl::context>;

/* ssl_session_resumption - Configures SSL session resumption. The SSL session
* of control connection will be reused for data connections.
*/
context_ptr create_context(context::method method, bool ssl_session_resumption = false);

} // namespace ftp::ssl
#endif //LIBFTP_SSL_HPP
42 changes: 42 additions & 0 deletions src/ssl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* MIT License
*
* Copyright (c) 2024 Denis Kovalchuk
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include <ftp/ssl.hpp>

namespace ftp::ssl
{

context_ptr create_context(context::method method, bool ssl_session_resumption)
{
context_ptr ssl_context = std::make_unique<context>(method);

if (ssl_session_resumption)
{
SSL_CTX_set_session_cache_mode(ssl_context->native_handle(), SSL_SESS_CACHE_CLIENT);
}

return ssl_context;
}

} // namespace ftp::ssl
22 changes: 10 additions & 12 deletions test/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ TEST_F(client, upload_unique_file)

TEST_F(client, open_ssl_connection)
{
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);

ftp::client client(std::move(ssl_context));

Expand Down Expand Up @@ -1103,7 +1103,7 @@ class ssl_client : public client_base<2142, true>

TEST_F(ssl_client, open_connection)
{
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);
ssl_context->load_verify_file(ftp::test::server::get_root_ca_cert_path().string());
ssl_context->load_verify_file(ftp::test::server::get_ca_cert_path().string());
ssl_context->set_verify_mode(ftp::ssl::verify_peer);
Expand Down Expand Up @@ -1153,7 +1153,7 @@ TEST_F(ssl_client, login)
GTEST_SKIP() << "pyftpdlib doesn't handle the 'REIN' command properly. "
"The control connection is not switched to non-SSL mode.";

ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);
ssl_context->load_verify_file(ftp::test::server::get_root_ca_cert_path().string());
ssl_context->load_verify_file(ftp::test::server::get_ca_cert_path().string());
ssl_context->set_verify_mode(ftp::ssl::verify_peer);
Expand Down Expand Up @@ -1181,7 +1181,7 @@ TEST_F(ssl_client, login)

TEST_F(ssl_client, unknown_certificate_authority)
{
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);

/* Do not specify certificate authorities. */
ssl_context->set_verify_mode(ftp::ssl::verify_peer);
Expand All @@ -1203,7 +1203,7 @@ TEST_F(ssl_client, unknown_certificate_authority)

TEST_F(ssl_client, short_verification_depth)
{
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);
ssl_context->load_verify_file(ftp::test::server::get_root_ca_cert_path().string());
ssl_context->load_verify_file(ftp::test::server::get_ca_cert_path().string());
ssl_context->set_verify_mode(ftp::ssl::verify_peer);
Expand All @@ -1226,7 +1226,7 @@ TEST_F(ssl_client, short_verification_depth)

TEST_F(ssl_client, no_certificate_verification)
{
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);

/* Do not specify certificate authorities, but use the "none" verification mode. */
ssl_context->set_verify_mode(ftp::ssl::verify_none);
Expand Down Expand Up @@ -1283,7 +1283,7 @@ INSTANTIATE_TEST_SUITE_P(all_params, ssl_client_parameterized,
TEST_P(ssl_client_parameterized, get_file_list)
{
auto [ mode, type, rfc2428_support ] = GetParam();
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);
ssl_context->load_verify_file(ftp::test::server::get_root_ca_cert_path().string());
ssl_context->load_verify_file(ftp::test::server::get_ca_cert_path().string());
ssl_context->set_verify_mode(ftp::ssl::verify_peer);
Expand Down Expand Up @@ -1326,7 +1326,7 @@ TEST_P(ssl_client_parameterized, get_file_list)
TEST_P(ssl_client_parameterized, upload_download_file)
{
auto [ mode, type, rfc2428_support ] = GetParam();
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tls_client);
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tls_client);
ssl_context->load_verify_file(ftp::test::server::get_root_ca_cert_path().string());
ssl_context->load_verify_file(ftp::test::server::get_ca_cert_path().string());
ssl_context->set_verify_mode(ftp::ssl::verify_peer);
Expand Down Expand Up @@ -1397,14 +1397,12 @@ INSTANTIATE_TEST_SUITE_P(all_modes, ssl_client_with_transfer_mode, testing::Valu
TEST_P(ssl_client_with_transfer_mode, ssl_session_resumption)
{
ftp::transfer_mode mode = GetParam();
ftp::ssl::context_ptr ssl_context = std::make_unique<ftp::ssl::context>(ftp::ssl::context::tlsv13_client);
/* Configure the SSL session resumption. */
ftp::ssl::context_ptr ssl_context = ftp::ssl::create_context(ftp::ssl::context::tlsv13_client, true);
ssl_context->load_verify_file(ftp::test::server::get_root_ca_cert_path().string());
ssl_context->load_verify_file(ftp::test::server::get_ca_cert_path().string());
ssl_context->set_verify_mode(ftp::ssl::verify_peer);

/* Set SSL_SESS_CACHE_CLIENT to use a single SSL session for control and data connections. */
SSL_CTX_set_session_cache_mode(ssl_context->native_handle(), SSL_SESS_CACHE_CLIENT);

ftp::client client(mode, ftp::transfer_type::ascii, std::move(ssl_context));

for (int i = 0; i < 3; i++)
Expand Down

0 comments on commit bbeabba

Please sign in to comment.