5 // Copyright (c) 2003-2014 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
13 #include <boost/bind.hpp>
14 #include <boost/asio.hpp>
15 #include <boost/asio/ssl.hpp>
17 enum { max_length = 1024 };
22 client(boost::asio::io_service& io_service,
23 boost::asio::ssl::context& context,
24 boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
25 : socket_(io_service, context)
27 socket_.set_verify_mode(boost::asio::ssl::verify_peer);
28 socket_.set_verify_callback(
29 boost::bind(&client::verify_certificate, this, _1, _2));
31 boost::asio::async_connect(socket_.lowest_layer(), endpoint_iterator,
32 boost::bind(&client::handle_connect, this,
33 boost::asio::placeholders::error));
36 bool verify_certificate(bool preverified,
37 boost::asio::ssl::verify_context& ctx)
39 // The verify callback can be used to check whether the certificate that is
40 // being presented is valid for the peer. For example, RFC 2818 describes
41 // the steps involved in doing this for HTTPS. Consult the OpenSSL
42 // documentation for more details. Note that the callback is called once
43 // for each certificate in the certificate chain, starting from the root
44 // certificate authority.
46 // In this example we will simply print the certificate's subject name.
47 char subject_name[256];
48 X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
49 X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
50 std::cout << "Verifying " << subject_name << "\n";
55 void handle_connect(const boost::system::error_code& error)
59 socket_.async_handshake(boost::asio::ssl::stream_base::client,
60 boost::bind(&client::handle_handshake, this,
61 boost::asio::placeholders::error));
65 std::cout << "Connect failed: " << error.message() << "\n";
69 void handle_handshake(const boost::system::error_code& error)
73 std::cout << "Enter message: ";
74 std::cin.getline(request_, max_length);
75 size_t request_length = strlen(request_);
77 boost::asio::async_write(socket_,
78 boost::asio::buffer(request_, request_length),
79 boost::bind(&client::handle_write, this,
80 boost::asio::placeholders::error,
81 boost::asio::placeholders::bytes_transferred));
85 std::cout << "Handshake failed: " << error.message() << "\n";
89 void handle_write(const boost::system::error_code& error,
90 size_t bytes_transferred)
94 boost::asio::async_read(socket_,
95 boost::asio::buffer(reply_, bytes_transferred),
96 boost::bind(&client::handle_read, this,
97 boost::asio::placeholders::error,
98 boost::asio::placeholders::bytes_transferred));
102 std::cout << "Write failed: " << error.message() << "\n";
106 void handle_read(const boost::system::error_code& error,
107 size_t bytes_transferred)
111 std::cout << "Reply: ";
112 std::cout.write(reply_, bytes_transferred);
117 std::cout << "Read failed: " << error.message() << "\n";
122 boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
123 char request_[max_length];
124 char reply_[max_length];
127 int main(int argc, char* argv[])
133 std::cerr << "Usage: client <host> <port>\n";
137 boost::asio::io_service io_service;
139 boost::asio::ip::tcp::resolver resolver(io_service);
140 boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
141 boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
143 boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
144 ctx.load_verify_file("ca.pem");
146 client c(io_service, ctx, iterator);
150 catch (std::exception& e)
152 std::cerr << "Exception: " << e.what() << "\n";