SSL certificate expiration date on Windows - c++

Can anybody provide me a C++ implementation rather simple to get SSL certificate expiration date. I have been looking online for past many hours, couldn't find anything so far. Currently I am using libcpr, and it doesn't seem to have any way to get it. I tried using the "curl" command, but that also doesn't seem to have that particular information in the output on Windows OS. The same command give the "expire date" in the output if I run it in GitBash, but not in the windows command prompt. I am new to C++.
The command below and output is from GitBash.
$ curl --insecure -vvI https://www.example.com
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
* Server certificate:
* subject: C=US; ST=California; L=Los Angeles;
O=Internet▒Corporation▒for▒Assigned▒Names▒and▒Numbers; CN=www.example.org
* start date: Mar 14 00:00:00 2022 GMT
* expire date: Mar 14 23:59:59 2023 GMT <-------- **********
* issuer: C=US; O=DigiCert Inc; CN=DigiCert TLS RSA SHA256 2020 CA1
* SSL certificate verify result: unable to get local issuer certificate (20),
continuing anyway.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* h2h3 [:method: HEAD]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: www.example.com]
* h2h3 [user-agent: curl/7.83.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x16d9a46c1d0)
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection #0 to host www.example.com left intact
Any help would be appriciated!!
Thanks

I suggest you to refer to the code in this issue:
ASN1_TIME *expires = X509_get_notAfter(cert.get());
// Construct another ASN1_TIME for the unix epoch, get the difference
// between them and use that to calculate a unix timestamp representing
// when the cert expires
ASN1_TIME_ptr epoch(ASN1_TIME_new(), ASN1_STRING_free);
ASN1_TIME_set_string(epoch.get(), "700101000000");
int days, seconds;
ASN1_TIME_diff(&days, &seconds, epoch.get(), expires);
time_t expire_timestamp = (days * 24 * 60 * 60) + seconds;
std::cout << "Expiration timestamp:" << std::endl;
std::cout << expire_timestamp << std::endl;
std::cout << std::endl;

Related

public cert is not picked from keystore provided in wso2 micro integrator

I have created a MI project using Hello World Docker template using Integration Studio 7.2.0. I want to setup mTLS for the service. I have configured the keystore like below.
deployment.toml
[keystore.tls]
file_name = "interceptor.jks"
password = "wso2carbon"
alias = "interceptor"
key_password = "wso2carbon"
[truststore]
file_name = "interceptor.jks"
password = "wso2carbon"
alias = "mg"
algorithm="AES"
interceptor.jks contains client cert with alias mg and privateKey with alias interceptor. This service is invoked using cURL as below.
curl --cacert interceptor.pem --cert mg.pem --key mg.key "https://xml-interceptor:8253/api/v1/handle-request" -H "content-type: application/json" -H "accept: application/json" -d '{"requestBody": "eyJuYW1lIjoiVGhlIFByaXNvbmVyIn0="}' -v
And it fails. While it is successful with -k option I noticed that the cert received to the client is below and not the one I configured in deployment.toml
* Server certificate:
* subject: C=US; ST=CA; L=Mountain View; O=WSO2; OU=WSO2; CN=localhost
* start date: Oct 23 07:30:43 2019 GMT
* expire date: Jan 25 07:30:43 2022 GMT
* issuer: C=US; ST=CA; L=Mountain View; O=WSO2; OU=WSO2; CN=localhost
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
> POST /api/v1/handle-request HTTP/1.1
I get this in Micro Integrator logs,
[2022-06-15 13:38:29,417] WARN {SourceHandler} - I/O error: Received fatal alert: unknown_ca
Seems it is unable to read the cert I configured. Any idea how to sort out this issue?
I have already tried importing the privateKey to wso2carbon.jks as well.
In your case, it seems the keystore is not getting updated.
You can build the docker image from the Integration Studio as specified in here[1].
Then you can mount the new keystore to the MI container [2].
[1] - https://apim.docs.wso2.com/en/latest/integrate/develop/create-docker-project/#build-and-push-docker-images
[2] - https://docs.docker.com/storage/volumes/#start-a-container-with-a-volume

Different server/IP - no more connection?

I'm using Mailgun through my local installation of Mautic. It used to connect correctly. Today however I got this error message: Unable to connect with TLS encryption Log data: ++ Starting Swift_SmtpTransport << 220-node6237.myfcloud.com ESMTP Exim 4.95 #2 Tue, 12 Apr 2022 13:38:14 +0000 220-We do not authorize the use of this system to transport unsolicited, 220 and/or bulk e-mail. >> EHLO dashboard.nsking.ee << 250-node6237.myfcloud.com Hello dashboard.nsking.ee [194.233.160.33] 250-SIZE 52428800 250-8BITMIME 250-PIPELINING 250-PIPE_CONNECT 250-AUTH PLAIN LOGIN 250-STARTTLS 250 HELP >> STARTTLS << 220 TLS go ahead !! Unable to connect with TLS encryption (code: 0) ++ Starting Swift_SmtpTransport << 220-node6237.myfcloud.com ESMTP Exim 4.95 #2 Tue, 12 Apr 2022 13:38:14 +0000 220-We do not authorize the use of this system to transport unsolicited, 220 and/or bulk e-mail. >> EHLO dashboard.nsking.ee << 250-node6237.myfcloud.com Hello dashboard.nsking.ee [194.233.160.33] 250-SIZE 52428800 250-8BITMIME 250-PIPELINING 250-PIPE_CONNECT 250-AUTH PLAIN LOGIN 250-STARTTLS 250 HELP >> STARTTLS << 220 TLS go ahead !! Unable to connect with TLS encryption (code: 0)
What is the cause of it? Keep in mind, nothing has changed in our installation except the server name and the IP.
I tried to change to SSL and I got this error:
Connection could not be established with host smtp.mailgun.org :stream_socket_client(): Peer certificate CN=node6237.myfcloud.com' did not match expected CN=smtp.mailgun.org' Log data: ++ Starting Swift_SmtpTransport !! Connection could not be established with host smtp.mailgun.org :stream_socket_client(): Peer certificate CN=node6237.myfcloud.com' did not match expected CN=smtp.mailgun.org' (code: 0)
++ Starting Swift_SmtpTransport !! Connection could not be established with host smtp.mailgun.org :stream_socket_client(): Peer certificate CN=node6237.myfcloud.com' did not match expected CN=smtp.mailgun.org' (code: 0)

How to send JSON data to a REST API?

I'm sending data to a Wordpress site with the WooCommerce plugin installed using libcurl in C++ and the WooCommerce REST API. The data seems to get sent but the expected result is not shown on the website. The purpose of it is to update (modify) the product. My code is based on the WooCommerce documentation, found here.
I have managed to get the CURLOPT_VERBOSE text from the program in a separate txt file.
Here is my C++ code using cURL :
std::string URL = main_domain + "wp-json/wc/v3/products/" + product_id + "?consumer_key=" + consumer_key + "&consumer_secret=" + consumer_secret;
curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
headers = curl_slist_append(headers, "Accept:application/json");
headers = curl_slist_append(headers, "Content-Type:application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
// log file
FILE* filep = fopen("logfichier.txt", "w");
std::string toUpdate = "{\"id\":\"" + product_id + ",\"name\":\"" + product_name + "\",\"description\":\"" + product_description + "\",\"price\":\"" + product_price + "\"}";
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl) {
readBuffer = "";
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, toUpdate.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, toUpdate.length());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_STDERR, filep);
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK) {
// error handling and cleanup
}
else {
// code and cleanup
}
}
else {
// error handling and cleanup
}
I've literally put every header found on the internet that seemed relevant to what i'm trying to acomplish in my code.
Here is the returned debug text :
* STATE: INIT => CONNECT handle 0x10870278; line 1428 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x10870278; line 1464 (connection #0)
* Trying 192.XX.XX.XX...
* TCP_NODELAY set
* STATE: WAITRESOLVE => WAITCONNECT handle 0x10870278; line 1545 (connection #0)
* Connected to mywebsite.com (192.XX.XX.XX) port 443 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x10870278; line 1599 (connection #0)
* Marked for [keep alive]: HTTP default
* schannel: SSL/TLS connection with mywebsite.com port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 176 bytes...
// (here was just a bunch of connexion attemps log text...)
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with mywebsite.com port 443 (step 3/3)
* schannel: stored credential handle in session cache
* STATE: PROTOCONNECT => DO handle 0x10870278; line 1634 (connection #0)
> PUT /wp-json/wc/v3/products/111867?consumer_key=(the actual key)&consumer_secret=(the actual secret) HTTP/1.1
Host: mywebsite.com
Transfer-Encoding: chunked
Accept:application/json
Content-Type:application/json
charsets: utf-8
4b
* upload completely sent off: 82 out of 75 bytes
* STATE: DO => DO_DONE handle 0x10870278; line 1696 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x10870278; line 1823 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x10870278; line 1838 (connection #0)
* schannel: client wants to read 16384 bytes
* schannel: encdata_buffer resized 17408
* schannel: encrypted data buffer: offset 0 length 17408
// (a few decrypting data attempts...)
* schannel: decrypted data returned 536
* schannel: decrypted data buffer: offset 0 length 16384
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
< Date: Tue, 18 Jun 2019 15:27:42 GMT
* Server Apache is not blacklisted
< Server: Apache
< X-Robots-Tag: noindex
< Link: <https://mywebsite.com/wp-json/>; rel="https://api.w.org/"
< X-Content-Type-Options: nosniff
< Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages
< Access-Control-Allow-Headers: Authorization, Content-Type
< Expires: Wed, 11 Jan 1984 05:00:00 GMT
< Cache-Control: no-transform, no-cache, must-revalidate, max-age=0
< Allow: GET, POST, PUT, PATCH, DELETE
< Transfer-Encoding: chunked
< Content-Type: application/json; charset=UTF-8
<
* schannel: client wants to read 16384 bytes
* schannel: encrypted data buffer: offset 835 length 17408
// (a few decrypting data attempts...)
* schannel: decrypted data returned 1986
* schannel: decrypted data buffer: offset 0 length 16384
* STATE: PERFORM => DONE handle 0x10870278; line 2011 (connection #0)
* multi_done
* Connection #0 to host axanti.info left intact
I took out a few redundant part from the original text and kept what I think is the main piece of information. It seems that my JSON data is actually sent to the server but the intended result doesn't show up on my website (a product should be modified but it's actually not).
Is there any way this code could be wrong ? Or is the problem on the server side ? Because I litteraly apply the same stuff that is mentioned in the official documentation.
Looks like your payload if off. The id portion is redundant, as you're already specifying the product to update via the URL, so you can drop that. Additionally, you're attempting to set the price incorrectly. Per the REST docs, you need to use the regular_price attribute instead of price (price is read only). The proper payload should look like this:
{
name: 'My product name',
description: 'my product description',
regular_price' : '3.50',
}

Betfair API'ing Certificate login using C++ boost SSL Sockets

Firstly, thanks for coming here. I'm trying to login with betfair using a certificate login using boost's ssl sockets however, once I send my http login POST, I receive the message CERT_AUTH_REQUIRED. On the betfair website it says this means "Certificate required or certificate present but could not authenticate with it".
I am able to connect, handshake and send/receive data. However, I just can't seem to login with my code. I've tested the exact certificates using curl without any problems.
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: C=IE; ST=Leinster; L=Dublin; O=Paddy Power Betfair Public Limi
ted Company; OU=IT Networks; CN=betfair.com
* start date: Sep 11 05:50:38 2018 GMT
* expire date: Sep 11 05:59:00 2020 GMT
* issuer: C=US; O=HydrantID (Avalanche Cloud Corporation); CN=HydrantID S
SL ICA G2
* SSL certificate verify result: self signed certificate in certificate c
hain (19), continuing anyway.
> POST /api/certlogin HTTP/1.1
> Host: identitysso-cert.betfair.com
> User-Agent: curl/7.46.0
> Accept: */*
> X-Application: AOxcQMZwVN3jOsLZ4
> Content-Length: 41
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 41 out of 41 bytes
< HTTP/1.1 200 OK
< Content-Type: text/plain;charset=ISO-8859-1
< Content-Length: 87
< Date: Wed, 06 Mar 2019 11:09:35 GMT
<
{"sessionToken":"ZFbyo3HeAh07UFTHzhhGjOyQFeX2MKdHHHHtAm2S7FXw=","loginStatus":"SU
CCESS"}* Connection #0 to host identitysso-cert.betfair.com left intact
I have further tested these certificates with python code that also works.
My C++ code is below. I've tried sending incorrect passwords which result in the status from server INVALID_USERNAME_OR_PASSWORD instead.
boost::asio::ssl::context ctx(boost::asio::ssl::context::tlsv12);
// load certificates
ctx.load_verify_file(cert_filename.c_str());
// ctx.use_private_key_file(private_filename.c_str(), boost::asio::ssl::context::pem);
ctx.use_rsa_private_key_file(private_filename.c_str(), boost::asio::ssl::context::pem);
mSocket.reset(new boost::asio::ssl::stream<tcp::socket>(mIoService, ctx));
mSocket->set_verify_mode(boost::asio::ssl::verify_peer);
mSocket->set_verify_callback(
boost::bind(&BetfairSession::VerifyCertificate, this, _1, _2));
tcp::resolver resolver(mIoService);
tcp::resolver::query query("identitysso-cert.betfair.com", port);
tcp::resolver::iterator endpointIter = resolver.resolve(query);
Many thanks in advance :)
I think you are confusing the client certificate and the CA List.
This:
ctx.load_verify_file(cert_filename.c_str());
Is loading a list of CA certificates to verify the server certificate against.
You can find a example of this list here:
http://curl.haxx.se/ca/cacert.pem
You also need to setup the certificate to use for the SSL connection, you do this with the "use_certificate_chain_file" method.
e.g.
ctx.use_certificate_chain_file(cert_filename.c_str());

C++/MFC fail to login websit using HTTPS

i use fiddler capture the POST message ,the different between normal login(firefox)
and mine is only the content-length:
(fireFox)Content-Length: 164
(mine) Content-Length: 165
i dont think it's the problem.
Then,i find that HTTPS connection to(Tunnel to Packet) server is more different.
i just show the difference.
Here is the message:
1. fireFox:
- Headers: ;
* CONNECT account.xiaomi.com:443 HTTP/1.1;
* Host: account.xiaomi.com ;
- CONTENT:
* Version: 3.2 (TLS/1.1)
* Ciphers: have more than 30 items;
2. mine):
- Headers:;
* CONNECT account.xiaomi.com:443 HTTP/1.0;
* Host: account.xiaomi.com:443;
- CONTENT:
* Version: 3.1 (TLS/1.0)
* Ciphers: have 12 items
i use CHttpFile to post