pistache: std::runtime error at second curl request when using ssl
I might have found an issue with the Pistache https/ssl support. I used the following code:
#include <pistache/endpoint.h>
#include <iostream>
using namespace Pistache;
struct HelloHandler : public Http::Handler {
HTTP_PROTOTYPE(HelloHandler)
void onRequest(const Http::Request& request, Http::ResponseWriter writer) {
writer.send(Http::Code::Ok, "Hello, World!");
}
};
int main(void) {
std::cout << "Starting server\n";
Pistache::Address addr;
auto opts = Http::Endpoint::options().threads(1);
addr = Pistache::Address(Pistache::Ipv4::any(), Pistache::Port(9999));
Http::Endpoint server(addr);
server.init(opts);
server.setHandler(std::make_shared<HelloHandler>());
server.useSSL("./cas/server/server.crt", "./cas/server/server.key");
server.useSSLAuth("./cas/rootCA/rootCA.crt");
std::cout << "SSL enabled\n";
server.serve();
return 0;
}
The certificates where generated using the terminal script below. WARNING: The certificates generated by the terminal script might not be fully save. I am no expert in SSL and I chose to remove the password from the certificate generation. Make sure you check if the certificates are save before you use them.
#!/bin/bash
# This script was executed from inside the cas directory seen in the C++ code above
# Generate root CA
echo "Generating rootCA"
mkdir rootCA
cd rootCA
openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -subj "/C=NL/ST=UTRECHT/O=Some company/CN=rootca" -sha256 -days 1024 -out rootCA.crt
cd ..
# Generate server certificate
echo "\nGenerating server certificate"
mkdir server
cd server
openssl genrsa -out server.key 2048
openssl req -new -sha256 -key server.key -subj "/C=NL/ST=UTRECHT/O=Some company/CN=Some ip" -out server.csr
openssl x509 -req -in server.csr -CA ../rootCA/rootCA.crt -CAkey ../rootCA/rootCA.key -CAcreateserial -out server.crt -days 500 -sha256
cd ..
# Generate client certificate
echo "\nGenerating client certificate"
mkdir client
cd client
openssl genrsa -out client.key 2048
openssl req -new -sha256 -key client.key -subj "/C=NL/ST=UTRECHT/O=Some company/CN=Some ip" -out client.csr
openssl x509 -req -in client.csr -CA ../rootCA/rootCA.crt -CAkey ../rootCA/rootCA.key -CAcreateserial -out client.crt -days 500 -sha256
cd ..
And then I ran the command line curl request curl https://127.0.0.1:9999 --cacert rootCA/rootCA.crt --cert client/client.crt --key client/client.key -k -v
I performed two curl requests using the same line without restarting the server. The first provides me with status code OK and the hello world text. The second one gives me an error:
# CURL output
* Expire in 0 ms for 6 (transfer 0x564eefb7f5c0)
* Trying 127.0.0.1...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x564eefb7f5c0)
* Connected to 127.0.0.1 (127.0.0.1) port 9999 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: rootCA/rootCA.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Request CERT (13):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Certificate (11):
* TLSv1.3 (OUT), TLS handshake, CERT verify (15):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=NL; ST=UTRECHT; O=Some company; CN=Some ip
* start date: Jun 5 06:50:35 2019 GMT
* expire date: Oct 17 06:50:35 2020 GMT
* issuer: C=NL; ST=UTRECHT; O=Some company; CN=rootca
* SSL certificate verify ok.
> GET / HTTP/1.1
> Host: 127.0.0.1:9999
> User-Agent: curl/7.64.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* TLSv1.3 (OUT), TLS alert, bad record mac (532):
* OpenSSL SSL_read: error:1408F119:SSL routines:ssl3_get_record:decryption failed or bad record mac, errno 0
* Closing connection 0
curl: (56) OpenSSL SSL_read: error:1408F119:SSL routines:ssl3_get_record:decryption failed or bad record mac, errno 0
# Pistache output
Starting server
SSL enabled
terminate called after throwing an instance of 'std::runtime_error'
what(): Success
Aborted (core dumped)
Could someone either confirm this is an issue or tell me what I did wrong. Another bit of information is that the second request does not error in the handler. It errors before the handler is called.
Stack trace:
/lib/x86_64-linux-gnu/libc.so.6(+0x43f60) [0x7fe7eba08f60]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0xc7) [0x7fe7eba08ed7]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x121) [0x7fe7eb9ea535]
/lib/x86_64-linux-gnu/libstdc++.so.6(+0x99642) [0x7fe7ebdb3642]
/lib/x86_64-linux-gnu/libstdc++.so.6(+0xa5186) [0x7fe7ebdbf186]
/lib/x86_64-linux-gnu/libstdc++.so.6(+0xa51d1) [0x7fe7ebdbf1d1]
/lib/x86_64-linux-gnu/libstdc++.so.6(+0xa5405) [0x7fe7ebdbf405]
/usr/local/lib/libpistache.so.0(+0x5cfc4) [0x7fe7ec566fc4]
/usr/local/lib/libpistache.so.0(_ZN8Pistache3Tcp9Transport7onReadyERKNS_3Aio5FdSetE+0x151) [0x7fe7ec5b2ed1]
/usr/local/lib/libpistache.so.0(_ZN8Pistache3Aio8SyncImpl7runOnceEv+0x7f5) [0x7fe7ec5abd25]
/usr/local/lib/libpistache.so.0(_ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJZN8Pistache3Aio9AsyncImpl6Worker3runEvEUlvE_EEEEE6_M_runEv+0x10a) [0x7fe7ec5a9a3a]
/lib/x86_64-linux-gnu/libstdc++.so.6(+0xd0420) [0x7fe7ebdea420]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x9182) [0x7fe7ec4d9182]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x3f) [0x7fe7ebae2b1f]
About this issue
- Original URL
- State: open
- Created 5 years ago
- Comments: 18 (9 by maintainers)
Commits related to this issue
- Added basic_tls_request_with_servefile unit test to try and reproduce #549 and #566... — committed to kiplingw/pistache by kiplingw 5 years ago
I think on line 189 of transport.cc they are trying to remove it using the fd number of the peer. This might mean it is indeed a copying issue somewhere.
The copy constructor is explicitly deleted, but there is a clone function, which i assume does something similar. Although it seems to only clone the handler and nothing else.
Hey guys, I am new user of Pistache lib, so I am not much familiar with its code, but it seems to me that this issue was introduced by PR #462 . We try to close fd in putOnWire (http.cc) which would be fine, but ssl is being involved.
Transport itself handles peer disconnection (handlePeerDisconnection) that clears SSL connection and removes this peer from the map and also clears the buffers. But this is not available (no access to peers map, only to peer itself) from the thread where we try to close the fd leaving the peers map untouched with the same SSL connection for that fd. On second request we get new connection (most likely the same fd). Upon insert of this peer to map happens nothing because this peer with this fd exists in this list. IMHO this causes Transport::handleIncoming to throw the runtime_error: Success.
Did not find appropriate solution (only workaround) yet.
Perhaps I am wrong. I just wanted to let you know so it might help you.