I applied ssl but the result is not satisfactory. There is no key change between the server and the client when viewed with wireshark.
Communication is possible, but not satisfactory. The server is Linux and the client is using Chrome. I know that the normal ssl communication message is
"client key exchange, password change specification, encrypted handshake message"
and
"server hello, certificate, server key exchange, server hello done". but it is invisible to me.
code
#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
int main(){
http_listener_config listen_config;
listen_config.set_ssl_context_callback([](boost::asio::ssl::context &ctx)
{
ctx.set_options(
boost::asio::ssl::context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::no_tlsv1
| boost::asio::ssl::context::no_tlsv1_1
| boost::asio::ssl::context::single_dh_use);
ctx.set_password_callback([](std::size_t max_length, boost::asio::ssl::context::password_purpose purpose)
{
return "password";
});
ctx.use_certificate_chain_file("rootca.crt");
ctx.use_private_key_file("rootca.key", boost::asio::ssl::context::pem);
ctx.use_tmp_dh_file("dh2048.pem");
});
listen_config.set_timeout(utility::seconds(10));
http_listener listener(U("https://0.0.0.0:10022"), listen_config); //Server URL, Port .
listener.support(methods::GET, [](http_request req){
auto j = json::value::object();
auto path = req.request_uri().path();
std::cout << path << std::endl;
j[U("one")] = json::value::string(U("asdfasefasdfaefasdfasefasdfefasefasefaqf3wfsefasdfasefasdfzsfzdfaesfzsefzsdfzsef"));
req.reply(status_codes::OK, j);
});
listener.open().then([&listener](){std::cout << (U("\n start!!\n"));}).wait(); //Server open
while(true);
listener.close();
return 0;
}
Packet when client connects to server.
Is there a problem with this code? or is this normal?
No this is not ok:
Doing a
openssl s_client -connect :10022 -debug -showcerts -state
Shows
CONNECTED(00000005)
write to 0x5614f8b23690 [0x5614f8b33620] (311 bytes => 311 (0x137))
0000 - 16 03 01 01 32 01 00 01-2e 03 03 79 fe 76 37 2b ....2......y.v7+
0010 - 9f bf e7 62 51 34 7d 4a-00 5e 1f ed 55 64 61 e1 ...bQ4}J.^..Uda.
0020 - 44 ce a0 c0 31 eb 3a b0-80 78 87 20 70 c4 1f 56 D...1.:..x. p..V
0030 - 62 da 74 b7 d7 6a 31 50-0c 8c 90 46 23 c6 59 13 b.t..j1P...F#.Y.
0040 - 17 6c 67 8f e3 9a 85 77-ab 6e c2 a3 00 3e 13 02 .lg....w.n...>..
0050 - 13 03 13 01 c0 2c c0 30-00 9f cc a9 cc a8 cc aa .....,.0........
0060 - c0 2b c0 2f 00 9e c0 24-c0 28 00 6b c0 23 c0 27 .+./...$.(.k.#.'
0070 - 00 67 c0 0a c0 14 00 39-c0 09 c0 13 00 33 00 9d .g.....9.....3..
0080 - 00 9c 00 3d 00 3c 00 35-00 2f 00 ff 01 00 00 a7 ...=.<.5./......
0090 - 00 00 00 0e 00 0c 00 00-09 6c 6f 63 61 6c 68 6f .........localho
00a0 - 73 74 00 0b 00 04 03 00-01 02 00 0a 00 0c 00 0a st..............
00b0 - 00 1d 00 17 00 1e 00 19-00 18 00 23 00 00 00 16 ...........#....
00c0 - 00 00 00 17 00 00 00 0d-00 30 00 2e 04 03 05 03 .........0......
00d0 - 06 03 08 07 08 08 08 09-08 0a 08 0b 08 04 08 05 ................
00e0 - 08 06 04 01 05 01 06 01-03 03 02 03 03 01 02 01 ................
00f0 - 03 02 02 02 04 02 05 02-06 02 00 2b 00 09 08 03 ...........+....
0100 - 04 03 03 03 02 03 01 00-2d 00 02 01 01 00 33 00 ........-.....3.
0110 - 26 00 24 00 1d 00 20 a1-ab 9c 0d 7e e9 80 84 ba &.$... ....~....
0120 - 0a 5a 71 20 7d 59 cd d9-24 9c de 9a 05 9d a2 78 .Zq }Y..$......x
0130 - 0d 0d 79 a1 3b 65 58 ..y.;eX
read from 0x5614f8b23690 [0x5614f8b2a313] (5 bytes => 0 (0x0))
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 311 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
read from 0x5614f8b23690 [0x5614f8b18d80] (8192 bytes => 0 (0x0))
So I was getting none-secure fallback. Turns out unhandled exceptions cause really degenerate behaviour. Adding some exception handling reveals:
ERROR: use_certificate_chain_file: No such file or directory
Well, of course. Adding those:
NOTE: It seems unlikely that you'd actually use a rootca for the sever. Maybe change the name of the file to reflect what it contains, or reconsider the cert you use for a server purpose.
ctx.set_password_callback(
[](std::size_t /*max_length*/,
ssl::context::password_purpose /*purpose*/) {
return "test";
});
ctx.use_certificate_chain_file("server.pem");
ctx.use_private_key_file("server.pem", ssl::context::pem);
ctx.use_tmp_dh_file("dh2048.pem");
Note, I used the key/dh params from the boost SSL samples, so the passphrase is test
Now, a simple GET request works, either with s_client
again or using something like wget
:
wget --no-check-certificate https://localhost:10022/ -O - -q
{"one":"asdfasefasdfaefasdfasefasdfefasefasefaqf3wfsefasdfasefasdfzsfzdfaesfzsefzsdfzsef"}
My assumption is that you, too, fell into the trap of not handling errors. I consider the "fail open" mode of the library a potential security issue - though all those parameters to the ssl::context
might have been effectively asking for that.
For reference, the full code I tested with in the end:
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <iostream>
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
namespace net = boost::asio;
namespace ssl = net::ssl;
int main() {
http_listener_config listen_config;
listen_config.set_ssl_context_callback([](ssl::context& ctx) {
try {
std::clog << "set_ssl_context_callback" << std::endl;
ctx.set_options(ssl::context::default_workarounds |
ssl::context::no_sslv2 | ssl::context::no_tlsv1 |
ssl::context::no_tlsv1_1 |
ssl::context::single_dh_use);
ctx.set_password_callback(
[](std::size_t /*max_length*/,
ssl::context::password_purpose /*purpose*/) {
return "test";
});
ctx.use_certificate_chain_file("server.pem");
ctx.use_private_key_file("server.pem", ssl::context::pem);
ctx.use_tmp_dh_file("dh2048.pem");
std::clog << "leave set_ssl_context_callback" << std::endl;
} catch (std::exception const& e) {
std::clog << "ERROR: " << e.what() << "\n";
}
});
listen_config.set_timeout(utility::seconds(10));
http_listener listener(U("https://localhost:10022"),
listen_config); // Server URL, Port .
listener.support(methods::GET, [](http_request req) {
std::clog << "enter handler" << std::endl;
auto j = json::value::object();
auto path = req.request_uri().path();
std::clog << path << std::endl;
j[U("one")] =
json::value::string(U("asdfasefasdfaefasdfasefasdfefasefasefaqf3wfs"
"efasdfasefasdfzsfzdfaesfzsefzsdfzsef"));
req.reply(status_codes::OK, j).wait();
std::clog << "leave handler" << std::endl;
});
listener.open()
.then([&listener] { std::clog << (U("\n start!!\n")); })
.wait(); // Server open
while (true)
;
listener.close(); // huh
}