Boost asio GET with client certificate sslv3 hand shake failed - ssl

I want to do a simple C++ web get similar to what is done by this curl command. I can use asio from boost. I must use boost 1.49
curl https://mysite.dev/api/v1/search?q=test -k --cert
C:\work\testCert.pem
The server is requiring the client certificate.
I started by using this as an example http://www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/example/ssl/client.cpp
and I added modifications by adding calls to the context like
ctx.set_options(boost::asio::ssl::context::default_workarounds);
ctx.use_certificate_file("C:\\work\\testCert.pem", boost::asio::ssl::context_base::pem);
ctx.use_private_key_file("C:\\work\\testKey.pem", boost::asio::ssl::context_base::pem);
My Request Looks like this:
GET /api/v1/search?q=test HTTP/1.0
Host: mysite.dev
Accept: */*
but I keep getting messages like this
Error: sslv3 alert handshake failure
clearly there is a step I am missing in the handshake process

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);

Related

WebSocketpp handshake issue with TLS

I have been learning with WebSocket++ and built some of the server examples (Windows 10 Visual Studio 2019). The non-TLS examples work without issues, however, the TLS-enabled examples (echo_server_both.cpp and echo_server_tls.cpp) can't do the handshake. I am very new to web development in general so I know I must be doing something wrong with regards to the certificate and keys.
I am testing the servers with WebSocket King client, an extension of Google Chrome that connects correctly to other websocket servers like wss://echo.websocket.org and to my own localhost when I don't use TLS.
The echo_server_both example comes with a server.pem file, and the echo_server_tls example comes with server.pem and dh.pem. I have used the same files that come with the samples, and I have also tried generating and registering my own .pem files using openSSL. In both cases I get this when the client tries to connect:
[2021-06-29 20:51:21] [error] handle_transport_init received error: sslv3 alert certificate unknown
[2021-06-29 20:51:21] [fail] WebSocket Connection [::1]:63346 - "" - 0 asio.ssl:336151574 sslv3 alert certificate unknown
[2021-06-29 20:51:21] [info] asio async_shutdown error: asio.ssl:336462231 (shutdown while in init)
I discovered these errors after I edited handle_init() in tls.hpp, following a suggestion in another site, to look like this:
void handle_init(init_handler callback,lib::asio::error_code const & ec) {
if (ec) {
//m_ec = socket::make_error_code(socket::error::tls_handshake_failed);
m_ec = ec;
} else {
m_ec = lib::error_code();
}
callback(m_ec);
}
This change let the actual openSSL error to show in the console, otherwise it would show a generic "handshake failed" error.
I know I'm not doing what I should with the certificates, but I have no idea where else to look or what to do next. Can anyone here help please? Should I use the .pem files that come with the examples, or should I generate my own? in case I should generate my own, what would be the openSSL command to do that correctly and how do I tell my PC to recognize these as valid so that the server works?
Found the problem: WebSocket++ will not accept a self-signed certificate (the ones you can create directly in your own PC using OpenSSL or the Windows utilities). There is no way around it. You must have a valid, authority-validated and endorsed certificate. You can get such a certificate for free (valid only for 90 days) from https://zerossl.com/. The site has detailed instructions on how to request, obtain and install a certificate. After getting a valid certificate and installing it on my server, everything worked as it should.

Tls 1.3 client does not report failed handshake when client certificate verification by server failed

I have a C client using OpenSSL that is failing a test when using a certificate that fails validation on the server side during the SSL_do_handshake() call on the server. When the application was using TLS 1.2 The SSL_do_handshake() failure on the server would be reported back to the client when it called SSL_do_handshake() as a failure return value.
When upgrading my application to OpenSSL 1.1.1 and TLS 1.3 I noted that while the validation error is still occurring on the server, it was no longer being reported back to the client.
I'm aware that the handshake protocol got completely re-written as part of TLS 1.3 however it seems like with all of the various callbacks available I should be able somehow on the client side to determine that authentication has failed without having to attempt to write data to the server.
Has anyone else encountered this and can they recommend a path forward?
The server and client in both TLSv1.2 and TLSv1.3 consider the handshake to be complete when they have both written a "Finished" message, and received one from the peer. This is what the handshake looks like in TLSv1.2 (taken from RFC5246):
Client Server
ClientHello -------->
ServerHello
Certificate*
ServerKeyExchange*
CertificateRequest*
<-------- ServerHelloDone
Certificate*
ClientKeyExchange
CertificateVerify*
[ChangeCipherSpec]
Finished -------->
[ChangeCipherSpec]
<-------- Finished
Application Data <-------> Application Data
So here you can see that the client sends its Certificate and Finished messages in its second flight of communication with the server. It then waits to receive the ChangeCipherSpec and Finished messages back from the server before it considers the handshake "complete" and it can start sending application data.
This is the equivalent flow for TLSv1.3 taken from RFC8446:
Client Server
Key ^ ClientHello
Exch | + key_share*
| + signature_algorithms*
| + psk_key_exchange_modes*
v + pre_shared_key* -------->
ServerHello ^ Key
+ key_share* | Exch
+ pre_shared_key* v
{EncryptedExtensions} ^ Server
{CertificateRequest*} v Params
{Certificate*} ^
{CertificateVerify*} | Auth
{Finished} v
<-------- [Application Data*]
^ {Certificate*}
Auth | {CertificateVerify*}
v {Finished} -------->
[Application Data] <-------> [Application Data]
One of the advantages of TLSv1.3 is that it speeds up the time taken to complete a handshake. In TLSv1.3 the client receives the "Finished" message from the server before it sends its Certificate and Finished messages back. By the time the client sends its "Finished" message, it has already received the "Finished" and so the handshake has completed and it can immediately start sending application data.
This of course means that the client won't know whether the server has accepted the certificate or not until it next reads data from the server. If it has been rejected then the next thing the client will read will be a failure alert (otherwise it will be normal application data).
I'm aware that the handshake protocol got completely re-written as part of TLS 1.3 however it seems like with all of the various callbacks available I should be able somehow on the client side to determine that authentication has failed without having to attempt to write data to the server.
It's not writing data to the server that is important - it is reading data. Only then will you know whether the server has sent an alert or just normal application data. Until that data has been read there are no callbacks available in OpenSSL that will tell you this - because OpenSSL itself does not know due to the underlying protocol.

HTTPS requests to paypal sandbox fail

I can't currently use the PayPal Sandbox to test my shopping-cart integrations. When i access the sandbox in a browser or via curl, all i get is connection errors.
Here's an example curl-session:
curl -v "https://api-3t.sandbox.paypal.com/nvp?user=test"
* Trying 173.0.82.83...
* TCP_NODELAY set
* Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_AES_256_CBC_SHA256
* Server certificate: api-3t.sandbox.paypal.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> GET /nvp?user=test HTTP/1.1
> Host: api-3t.sandbox.paypal.com
> User-Agent: curl/7.51.0
> Accept: */*
>
* SSLRead() return error -9806
* Curl_http_done: called premature == 1
* Closing connection 0
curl: (56) SSLRead() return error -9806
Any hints if this is a serverside issue or something i can work around?
Thanks!
Looks like the NVP/SOAP integration method of Paypal Express Checkout is deprecated as of January 1, 2017. The live URL (https://api-3t.paypal.com/nvp) seems to work for now, but this might be why the sandbox doesn't work anymore.
I don't exactly understand why, but using POST instead of GET when submitting data to the PayPal Sandbox solves the problem nicely. No more weird SSL-errors.
Found below answer to curl 56 error . Hope that could help work out of the problem.
curl (56) Recv failure
PHP CURL Error - curl: (56) Recv failure: Connection reset by peer

ERROR: Fetching the page failed because other errors. Twitter Cards Issue

When I go to https://cards-dev.twitter.com/validator and enter https://piktoria.com/blog/instagram-to-drive-sales/ and adlatch.com
Validator says - Unable to render Card preview
ERROR: Fetching the page failed because other errors.
So because of that when i share anything on twitter, don't get any snippets, tried twitter support they say:
"There's something wrong with your SSL setup - I am seeing SslHandshakeException: handshake alert: unrecognized_name at remote address in my debug log which I suspect means that your server name does not match the certificate, or something similar."
Can anyone help in solving this issue
This problem happened with me also But i managed to Fix It when twiiter told me to check SSL Settings
I got the point The problem was From AES256 and AES128 (For NgiNx Web Server) You need to enable AES128
Here is Snippet
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384!AES128:!3DES';
As you see in the Snippet the AES128 is Disabled(!)
you need to remove the ! From AES128 So the Code will be:
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:!3DES';
This might be a post a bit old, but you can get this error due to a different TLS configuration.
When I looked into my webserver error logs, I encountered the following error:
2021/05/12 19:41:31 [crit] 16585#16585: *44673 SSL_do_handshake() failed (SSL: error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol) while SSL handshaking, client: X.X.X.X, server: X.X.X.X:443
It looks like twitter, as of now, does not support TLSv1.3 for getting the cards, and the solution is to also enable TLSv1.2. If you use the intermediate configuration from Mozilla's ssl-config tool that is good enough.
See https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1d&guideline=5.6

Websocket and Safari 6.0

I am using Safari 6 and websockets. My server is receiving the following handshake from the browser:
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: nomad.local:1299
Origin: file://
Sec-WebSocket-Key: WhZTuybN4i2ZshDBxco42w==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
There is no Protocol included. My server can deal with that, but when it tries to complete the handshake with the browser client I get the following message:
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
Is there an implied Protocol in the message sent to server that I need to return in the handshake to the client?
This worked before I upgraded to latest Safari
If the client does not send any sub-protocols in the handshake (Sec-WebSocket-Protocol) then the server must not send back a sub-protocol header (Sec-WebSocket-Protocol). If the server sends back the common default of "Sec-WebSocket-Protocol: chat" even though the client did not include a sub-protocol header, the client must refuse the connection. Some browsers were sloppy about this and have recently begun to tighten up their compliance.
If the client does send a sub-protocol list, then the server must select a single sub-protocol that it supports and send this back to the client as the chosen sub-protocol.
Well the protocol is WebSockets ;-) See the RFC for further explanations on Sec-WebSocket-Protocol: http://datatracker.ietf.org/doc/rfc6455/?include_text=1
The handshake from the client looks as follows:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
The handshake from the server looks as follows:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Don't know wether the Safari 6 implemenation differs, but protocols from RFC are usually a nightmare... There might be a standard implied?