2017-05-02 19:32:48 -07:00
|
|
|
//
|
|
|
|
|
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
|
|
|
//
|
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "websocket_async_ssl_echo_server.hpp"
|
|
|
|
|
|
|
|
|
|
#include <beast/websocket/stream.hpp>
|
2017-05-04 05:01:50 -07:00
|
|
|
#include <beast/core/ostream.hpp>
|
2017-05-02 19:32:48 -07:00
|
|
|
#include <beast/unit_test/suite.hpp>
|
|
|
|
|
#include <beast/test/yield_to.hpp>
|
|
|
|
|
#include <boost/asio.hpp>
|
|
|
|
|
#include <boost/asio/ssl.hpp>
|
|
|
|
|
|
|
|
|
|
namespace beast {
|
|
|
|
|
namespace websocket {
|
|
|
|
|
|
|
|
|
|
class ssl_server_test
|
|
|
|
|
: public beast::unit_test::suite
|
|
|
|
|
, public test::enable_yield_to
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
using self = ssl_server_test;
|
|
|
|
|
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
|
|
|
|
using address_type = boost::asio::ip::address;
|
|
|
|
|
using socket_type = boost::asio::ip::tcp::socket;
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
run() override
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
The certificate was generated from CMD.EXE on Windows 10 using:
|
|
|
|
|
|
|
|
|
|
winpty openssl dhparam -out dh.pem 2048
|
|
|
|
|
winpty openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 10000 -out cert.pem -subj "//C=US\ST=CA\L=Los Angeles\O=Beast\CN=www.example.com"
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
std::string const cert =
|
|
|
|
|
"-----BEGIN CERTIFICATE-----\n"
|
|
|
|
|
"MIIDaDCCAlCgAwIBAgIJAO8vBu8i8exWMA0GCSqGSIb3DQEBCwUAMEkxCzAJBgNV\n"
|
|
|
|
|
"BAYTAlVTMQswCQYDVQQIDAJDQTEtMCsGA1UEBwwkTG9zIEFuZ2VsZXNPPUJlYXN0\n"
|
|
|
|
|
"Q049d3d3LmV4YW1wbGUuY29tMB4XDTE3MDUwMzE4MzkxMloXDTQ0MDkxODE4Mzkx\n"
|
|
|
|
|
"MlowSTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMS0wKwYDVQQHDCRMb3MgQW5n\n"
|
|
|
|
|
"ZWxlc089QmVhc3RDTj13d3cuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n"
|
|
|
|
|
"A4IBDwAwggEKAoIBAQDJ7BRKFO8fqmsEXw8v9YOVXyrQVsVbjSSGEs4Vzs4cJgcF\n"
|
|
|
|
|
"xqGitbnLIrOgiJpRAPLy5MNcAXE1strVGfdEf7xMYSZ/4wOrxUyVw/Ltgsft8m7b\n"
|
|
|
|
|
"Fu8TsCzO6XrxpnVtWk506YZ7ToTa5UjHfBi2+pWTxbpN12UhiZNUcrRsqTFW+6fO\n"
|
|
|
|
|
"9d7xm5wlaZG8cMdg0cO1bhkz45JSl3wWKIES7t3EfKePZbNlQ5hPy7Pd5JTmdGBp\n"
|
|
|
|
|
"yY8anC8u4LPbmgW0/U31PH0rRVfGcBbZsAoQw5Tc5dnb6N2GEIbq3ehSfdDHGnrv\n"
|
|
|
|
|
"enu2tOK9Qx6GEzXh3sekZkxcgh+NlIxCNxu//Dk9AgMBAAGjUzBRMB0GA1UdDgQW\n"
|
|
|
|
|
"BBTZh0N9Ne1OD7GBGJYz4PNESHuXezAfBgNVHSMEGDAWgBTZh0N9Ne1OD7GBGJYz\n"
|
|
|
|
|
"4PNESHuXezAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCmTJVT\n"
|
|
|
|
|
"LH5Cru1vXtzb3N9dyolcVH82xFVwPewArchgq+CEkajOU9bnzCqvhM4CryBb4cUs\n"
|
|
|
|
|
"gqXWp85hAh55uBOqXb2yyESEleMCJEiVTwm/m26FdONvEGptsiCmF5Gxi0YRtn8N\n"
|
|
|
|
|
"V+KhrQaAyLrLdPYI7TrwAOisq2I1cD0mt+xgwuv/654Rl3IhOMx+fKWKJ9qLAiaE\n"
|
|
|
|
|
"fQyshjlPP9mYVxWOxqctUdQ8UnsUKKGEUcVrA08i1OAnVKlPFjKBvk+r7jpsTPcr\n"
|
|
|
|
|
"9pWXTO9JrYMML7d+XRSZA1n3856OqZDX4403+9FnXCvfcLZLLKTBvwwFgEFGpzjK\n"
|
|
|
|
|
"UEVbkhd5qstF6qWK\n"
|
|
|
|
|
"-----END CERTIFICATE-----\n";
|
|
|
|
|
|
|
|
|
|
std::string const key =
|
|
|
|
|
"-----BEGIN PRIVATE KEY-----\n"
|
|
|
|
|
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJ7BRKFO8fqmsE\n"
|
|
|
|
|
"Xw8v9YOVXyrQVsVbjSSGEs4Vzs4cJgcFxqGitbnLIrOgiJpRAPLy5MNcAXE1strV\n"
|
|
|
|
|
"GfdEf7xMYSZ/4wOrxUyVw/Ltgsft8m7bFu8TsCzO6XrxpnVtWk506YZ7ToTa5UjH\n"
|
|
|
|
|
"fBi2+pWTxbpN12UhiZNUcrRsqTFW+6fO9d7xm5wlaZG8cMdg0cO1bhkz45JSl3wW\n"
|
|
|
|
|
"KIES7t3EfKePZbNlQ5hPy7Pd5JTmdGBpyY8anC8u4LPbmgW0/U31PH0rRVfGcBbZ\n"
|
|
|
|
|
"sAoQw5Tc5dnb6N2GEIbq3ehSfdDHGnrvenu2tOK9Qx6GEzXh3sekZkxcgh+NlIxC\n"
|
|
|
|
|
"Nxu//Dk9AgMBAAECggEBAK1gV8uETg4SdfE67f9v/5uyK0DYQH1ro4C7hNiUycTB\n"
|
|
|
|
|
"oiYDd6YOA4m4MiQVJuuGtRR5+IR3eI1zFRMFSJs4UqYChNwqQGys7CVsKpplQOW+\n"
|
|
|
|
|
"1BCqkH2HN/Ix5662Dv3mHJemLCKUON77IJKoq0/xuZ04mc9csykox6grFWB3pjXY\n"
|
|
|
|
|
"OEn9U8pt5KNldWfpfAZ7xu9WfyvthGXlhfwKEetOuHfAQv7FF6s25UIEU6Hmnwp9\n"
|
|
|
|
|
"VmYp2twfMGdztz/gfFjKOGxf92RG+FMSkyAPq/vhyB7oQWxa+vdBn6BSdsfn27Qs\n"
|
|
|
|
|
"bTvXrGe4FYcbuw4WkAKTljZX7TUegkXiwFoSps0jegECgYEA7o5AcRTZVUmmSs8W\n"
|
|
|
|
|
"PUHn89UEuDAMFVk7grG1bg8exLQSpugCykcqXt1WNrqB7x6nB+dbVANWNhSmhgCg\n"
|
|
|
|
|
"VrV941vbx8ketqZ9YInSbGPWIU/tss3r8Yx2Ct3mQpvpGC6iGHzEc/NHJP8Efvh/\n"
|
|
|
|
|
"CcUWmLjLGJYYeP5oNu5cncC3fXUCgYEA2LANATm0A6sFVGe3sSLO9un1brA4zlZE\n"
|
|
|
|
|
"Hjd3KOZnMPt73B426qUOcw5B2wIS8GJsUES0P94pKg83oyzmoUV9vJpJLjHA4qmL\n"
|
|
|
|
|
"CDAd6CjAmE5ea4dFdZwDDS8F9FntJMdPQJA9vq+JaeS+k7ds3+7oiNe+RUIHR1Sz\n"
|
|
|
|
|
"VEAKh3Xw66kCgYB7KO/2Mchesu5qku2tZJhHF4QfP5cNcos511uO3bmJ3ln+16uR\n"
|
|
|
|
|
"GRqz7Vu0V6f7dvzPJM/O2QYqV5D9f9dHzN2YgvU9+QSlUeFK9PyxPv3vJt/WP1//\n"
|
|
|
|
|
"zf+nbpaRbwLxnCnNsKSQJFpnrE166/pSZfFbmZQpNlyeIuJU8czZGQTifQKBgHXe\n"
|
|
|
|
|
"/pQGEZhVNab+bHwdFTxXdDzr+1qyrodJYLaM7uFES9InVXQ6qSuJO+WosSi2QXlA\n"
|
|
|
|
|
"hlSfwwCwGnHXAPYFWSp5Owm34tbpp0mi8wHQ+UNgjhgsE2qwnTBUvgZ3zHpPORtD\n"
|
|
|
|
|
"23KZBkTmO40bIEyIJ1IZGdWO32q79nkEBTY+v/lRAoGBAI1rbouFYPBrTYQ9kcjt\n"
|
|
|
|
|
"1yfu4JF5MvO9JrHQ9tOwkqDmNCWx9xWXbgydsn/eFtuUMULWsG3lNjfst/Esb8ch\n"
|
|
|
|
|
"k5cZd6pdJZa4/vhEwrYYSuEjMCnRb0lUsm7TsHxQrUd6Fi/mUuFU/haC0o0chLq7\n"
|
|
|
|
|
"pVOUFq5mW8p0zbtfHbjkgxyF\n"
|
|
|
|
|
"-----END PRIVATE KEY-----\n";
|
|
|
|
|
|
|
|
|
|
std::string const dh =
|
|
|
|
|
"-----BEGIN DH PARAMETERS-----\n"
|
|
|
|
|
"MIIBCAKCAQEArzQc5mpm0Fs8yahDeySj31JZlwEphUdZ9StM2D8+Fo7TMduGtSi+\n"
|
|
|
|
|
"/HRWVwHcTFAgrxVdm+dl474mOUqqaz4MpzIb6+6OVfWHbQJmXPepZKyu4LgUPvY/\n"
|
|
|
|
|
"4q3/iDMjIS0fLOu/bLuObwU5ccZmDgfhmz1GanRlTQOiYRty3FiOATWZBRh6uv4u\n"
|
|
|
|
|
"tff4A9Bm3V9tLx9S6djq31w31Gl7OQhryodW28kc16t9TvO1BzcV3HjRPwpe701X\n"
|
|
|
|
|
"oEEZdnZWANkkpR/m/pfgdmGPU66S2sXMHgsliViQWpDCYeehrvFRHEdR9NV+XJfC\n"
|
|
|
|
|
"QMUk26jPTIVTLfXmmwU0u8vUkpR7LQKkwwIBAg==\n"
|
|
|
|
|
"-----END DH PARAMETERS-----\n";
|
|
|
|
|
|
|
|
|
|
using endpoint_type = boost::asio::ip::tcp::endpoint;
|
|
|
|
|
using address_type = boost::asio::ip::address;
|
|
|
|
|
::websocket::async_ssl_echo_server server{
|
|
|
|
|
&log, 1, cert, key, dh};
|
|
|
|
|
error_code ec;
|
|
|
|
|
server.open(endpoint_type{
|
|
|
|
|
address_type::from_string("127.0.0.1"), 6000 }, ec);
|
|
|
|
|
auto const ep = server.local_endpoint();
|
|
|
|
|
|
|
|
|
|
using boost::asio::connect;
|
|
|
|
|
using socket = boost::asio::ip::tcp::socket;
|
|
|
|
|
using io_service = boost::asio::io_service;
|
|
|
|
|
namespace ssl = boost::asio::ssl;
|
|
|
|
|
|
|
|
|
|
// Perform SSL handshaking
|
|
|
|
|
io_service ios;
|
|
|
|
|
using stream_type = ssl::stream<socket>;
|
|
|
|
|
ssl::context ctx{ssl::context::sslv23};
|
|
|
|
|
stream_type stream{ios_, ctx};
|
|
|
|
|
stream.next_layer().connect(ep);
|
|
|
|
|
stream.set_verify_mode(ssl::verify_none);
|
|
|
|
|
stream.handshake(ssl::stream_base::client);
|
|
|
|
|
|
|
|
|
|
// Secure WebSocket connect and send message using Beast
|
|
|
|
|
beast::websocket::stream<stream_type&> ws{stream};
|
|
|
|
|
ws.handshake("localhost", "/");
|
2017-05-04 05:01:50 -07:00
|
|
|
ws.write(boost::asio::buffer("Hello, world!", 13));
|
2017-05-02 19:32:48 -07:00
|
|
|
|
|
|
|
|
// Receive Secure WebSocket message, print and close using Beast
|
2017-05-04 15:40:07 -07:00
|
|
|
beast::multi_buffer b;
|
2017-06-08 19:55:42 -07:00
|
|
|
ws.read(b);
|
2017-05-02 19:32:48 -07:00
|
|
|
ws.close(beast::websocket::close_code::normal);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
for(;;)
|
|
|
|
|
{
|
2017-06-08 19:55:42 -07:00
|
|
|
ws.read(b);
|
2017-05-04 15:40:07 -07:00
|
|
|
b.consume(b.size());
|
2017-05-02 19:32:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch(system_error const& se)
|
|
|
|
|
{
|
|
|
|
|
if(se.code() != beast::websocket::error::closed)
|
|
|
|
|
throw;
|
|
|
|
|
}
|
2017-05-04 05:01:50 -07:00
|
|
|
BEAST_EXPECT(boost::lexical_cast<std::string>(
|
2017-05-04 15:40:07 -07:00
|
|
|
buffers(b.data())) == "Hello, world!");
|
2017-05-02 19:32:48 -07:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
BEAST_DEFINE_TESTSUITE(ssl_server,websocket,beast);
|
|
|
|
|
|
|
|
|
|
} // websocket
|
|
|
|
|
} // beast
|