Exception Running Boost Asio Ssl Example

Exception running boost asio ssl example

OK, for anyone finding this in the future, you need to create your certificates and sign them appropriately.
Here are the commands for linux:

//Generate a private key

openssl genrsa -des3 -out server.key 1024

//Generate Certificate signing request

openssl req -new -key server.key -out server.csr

//Sign certificate with private key

openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt

//Remove password requirement (needed for example)

cp server.key server.key.secure
openssl rsa -in server.key.secure -out server.key

//Generate dhparam file

openssl dhparam -out dh512.pem 512

Once you've done that, you need to change the filenames in server.cpp and client.cpp.

server.cpp

context_.use_certificate_chain_file("server.crt"); 
context_.use_private_key_file("server.key", boost::asio::ssl::context::pem);
context_.use_tmp_dh_file("dh512.pem");

client.cpp

ctx.load_verify_file("server.crt");

Then it should all work!

Boost::Asio, SSL Connection Problems

Hah!

I've found more time and looked at it again. My code here (http://coliru.stacked-crooked.com/a/2042c3d24a16c6ac) was already almost correct. Except for one really simple bug:

size_t request_length = strlen(request_);

Looks innocuous, no? Except... request_ was uninitialized at this point. It needed to be (in context):

  static char const raw[] = "GET / HTTP/1.1\r\nHost: www.google.de\r\nConnection: close\r\n\r\n";

static_assert(sizeof(raw)<=sizeof(request_), "too large");

size_t request_length = strlen(raw);
std::copy(raw, raw+request_length, request_);

Of course, this problem did not exist in the official Boost sample you linked to (as it reads directly into the request buffer with std::cin.getline). However, like me, you might have made the same beginner's mistake.

Hope this helps.

Attached is a fully working demo that you van even switch to use HTTPS or not using preprocessor directive:

#define SEHE_USE_SSL

Note also, I used

ctx.set_default_verify_paths();

so you can use the default root authority certificates registered on your machine (if your openssl installation has it).

Full Code

#define SEHE_USE_SSL
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

class client
{
public:
client(boost::asio::io_service& io_service,
boost::asio::ssl::context& context,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
: socket_(io_service
#ifdef SEHE_USE_SSL
, context)
{
socket_.set_verify_mode(boost::asio::ssl::verify_peer);
socket_.set_verify_callback(
boost::bind(&client::verify_certificate, this, _1, _2));
#else
)
{
(void) context;
#endif

boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
boost::bind(&client::handle_connect, this,
boost::asio::placeholders::error));
}

bool verify_certificate(bool preverified,
boost::asio::ssl::verify_context& ctx)
{
// The verify callback can be used to check whether the certificate that is
// being presented is valid for the peer. For example, RFC 2818 describes
// the steps involved in doing this for HTTPS. Consult the OpenSSL
// documentation for more details. Note that the callback is called once
// for each certificate in the certificate chain, starting from the root
// certificate authority.

// In this example we will simply print the certificate's subject name.
char subject_name[256];
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
std::cout << "Verifying " << subject_name << "\n";

return true || preverified;
}

void handle_connect(const boost::system::error_code& error)
{
#ifdef SEHE_USE_SSL
if (!error)
{
socket_.async_handshake(boost::asio::ssl::stream_base::client,
boost::bind(&client::handle_handshake, this,
boost::asio::placeholders::error));
}
else
{
std::cout << "Connect failed: " << error.message() << "\n";
}
#else
handle_handshake(error);
#endif
}

void handle_handshake(const boost::system::error_code& error)
{
if (!error)
{
std::cout << "Enter message: ";
static char const raw[] = "GET / HTTP/1.1\r\nHost: www.google.de\r\nConnection: close\r\n\r\n";

static_assert(sizeof(raw)<=sizeof(request_), "too large");

size_t request_length = strlen(raw);
std::copy(raw, raw+request_length, request_);

{
// used this for debugging:
std::ostream hexos(std::cout.rdbuf());
for(auto it = raw; it != raw+request_length; ++it)
hexos << std::hex << std::setw(2) << std::setfill('0') << std::showbase << ((short unsigned) *it) << " ";
std::cout << "\n";
}

boost::asio::async_write(socket_,
boost::asio::buffer(request_, request_length),
boost::bind(&client::handle_write, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Handshake failed: " << error.message() << "\n";
}
}

void handle_write(const boost::system::error_code& error,
size_t /*bytes_transferred*/)
{
if (!error)
{
std::cout << "starting read loop\n";
boost::asio::async_read_until(socket_,
//boost::asio::buffer(reply_, sizeof(reply_)),
reply_, '\n',
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else
{
std::cout << "Write failed: " << error.message() << "\n";
}
}

void handle_read(const boost::system::error_code& error, size_t /*bytes_transferred*/)
{
if (!error)
{
std::cout << "Reply: " << &reply_ << "\n";
}
else
{
std::cout << "Read failed: " << error.message() << "\n";
}
}

private:
#ifdef SEHE_USE_SSL
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
#else
boost::asio::ip::tcp::socket socket_;
#endif
char request_[1024];
//char reply_ [1024];
boost::asio::streambuf reply_;
};

int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cerr << "Usage: client <host> <port>\n";
return 1;
}

boost::asio::io_service io_service;

boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);

boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
ctx.set_default_verify_paths();

client c(io_service, ctx, iterator);

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

return 0;
}

Boost asio GET with client certificate sslv3 hand shake failed

The solution was to disable SSLv3 support, appartently most servers disable this because of design flaws.

ctx.set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3);

Aid in building boost asio ssl example

I think you've misunderstood how the -L option works. -L specifies a path in which to search for libraries. To specify an individual library to link to, use the -l option and omit the "lib" prefix, as follows:

LIBS = -L/usr/local/boost_1_41_0/lib -L/opt/local/lib \
-lboost_system -lcrypto -lssl

Also, there is usually no space between the -I include path option and the actual path. I'm not sure if a space in there causes problems, but you might try this to be on the safe side:

INCLUDES = -I/usr/local/boost_1_41_0/ -I/opt/local/include/

Also, as noted in my comment, you defined the LIBS variable but then used the LIB variable. The call to g++ should be as follows:

$(CPP) $(LIBS) $(INCLUDES) ssl-client.cpp

boost asio SSL server error: called a function you should not call

Seems that the following line triggers the problem:

context_(io_service, boost::asio::ssl::context::tlsv12_client)

I should have paid more attention to my code (copy-paste is the root of all evil):
The offending line was in the context constructor:

ctx_(io_service, boost::asio::ssl::context::tlsv12_client)

I've replaced with the server version:

context_(io_service, boost::asio::ssl::context::tlsv12_server)

The full list is hidden in the implementation header of boost.
Insert big facepalm here :-)

boost::asio::ssl::context crash during construction

The openssl cygwin package I installed is not a stable one, so the include and lib files are missing and I'm using the wrong ones (incompatible with the x86_64-w64-mingw32-g++ compiler). I've installed another stable version and the desired files are available now.



Related Topics



Leave a reply



Submit