2 years ago

#61007

test-img

Fabio

Is it possible to use an asio ssl stream class to alternate between encrypted and clear traffic?

I am writing a client server application using the standalone version of asio.

I would like to use the same tcp socket for ssl and non ssl traffic.

Say I have a variable m_socket of type asio::ssl::stream<tcp::socket>, where I have already successfully completed the handshake. I want to use it to send/receive messages in clear, e.g.

// send in clear
asio::async_write(m_socket.next_layer(), buffer, handler);

or encrypted, e.g.

// send encrypted
asio::async_write(m_socket, buffer, handler);

To test if it is even possible to use the raw socket embedded in an ssl stream to send and receive traffic in clear, I wrote the following mini client-server programs. It works correctly when I use the ssl stream in read/write operations. If instead I replace socket with socket.next_layer() (i.e. if I change the #if 1 to #if 0 in both programs) then the text received by the client is garbled.

//////////////////
// CLIENT
//

#include <cstdlib>
#include <iostream>
#include <asio.hpp>
#include <asio/ssl.hpp>

#if 1 // change this to zero to send/recv in clear
#define SOCKET socket
#else
#define SOCKET socket.next_layer()
#endif

using asio::ip::tcp;

int main(int argc, char* argv[])
{
    char message[4] = {};

    try
    {
        asio::io_context io_context;
        asio::ssl::context sslctx(asio::ssl::context::sslv23);
        sslctx.use_certificate_chain_file("certificate.pem");
        sslctx.use_private_key_file("key.pem", asio::ssl::context::pem);
        sslctx.use_tmp_dh_file("dh2048.pem");
        sslctx.set_options(
            asio::ssl::context::default_workarounds
            | asio::ssl::context::no_sslv2
            | asio::ssl::context::single_dh_use);
        asio::ssl::stream<tcp::socket> socket(io_context, sslctx);
        tcp::acceptor(io_context, tcp::endpoint(tcp::v4(), 15000)).accept(socket.next_layer());
        socket.handshake(asio::ssl::stream_base::server);

        for (int i = 0; i < 10; ++i) {
            asio::read(SOCKET, asio::buffer(message, 3));
            std::cout << "read: " << message << "\n";
            snprintf(message, sizeof(message), "%03d", 1 + atoi(message));
            asio::write(SOCKET, asio::buffer(message, 3));
            std::cout << "sent: " << message << "\n";
        }
    }
    catch (std::exception& e)  {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

and

//////////////////
// SERVER
//

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <asio.hpp>
#include <asio/ssl.hpp>

#if 1 // change this to 0 to send/receive in clear
#define SOCKET socket
#else
#define SOCKET socket.next_layer()
#endif

using asio::ip::tcp;

int main(int argc, char* argv[])
{
    char message[4] = {};

    try
    {
        asio::io_context io_context;
        asio::ssl::context sslctx(asio::ssl::context::sslv23);
        sslctx.load_verify_file("certificate.pem");
        asio::ssl::stream<tcp::socket> socket(io_context, sslctx);
        socket.set_verify_mode(asio::ssl::verify_peer);
        
        auto endpoints = tcp::resolver(io_context).resolve(tcp::v4(), "localhost", "15000");
        asio::connect(socket.lowest_layer(), endpoints);
        socket.handshake(asio::ssl::stream_base::client);
    
        for (int i = 0; i < 10; ++i) {
            snprintf(message, sizeof(message), "%03d", 2*i);
            asio::write(SOCKET, asio::buffer(message, 3));
            std::cout << "sent: " << message << "\n";
            asio::read(SOCKET, asio::buffer(message, 3));
            std::cout << "read: " << message << "\n";
        }

    }
    catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << "\n";
    }

    return 0;
}

Does somebody know if what I am trying to do is even possible using an asio ssl stream?

c++

sockets

boost-asio

asio

tls1.3

0 Answers

Your Answer

Accepted video resources