OpenSSL Certificate "unable to get local issuer certificate" - c++

I just started using Poco C++ libraries and i just compiled the NetSSL-OpenSSL download example.
When using it with an http site, everything works, but when i use it with an https site, following error occurs:
>download.exe https://api.github.com
WARNING: Certificate verification failed
----------------------------------------
Issuer Name: C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert High Assurance EV Root CA
Subject Name: C=US,O=DigiCert Inc,OU=www.digicert.com,CN=DigiCert SHA2 High Assurance Server CA
The certificate yielded the error: unable to get local issuer certificate
The error occurred in the certificate chain at position 1
Accept the certificate (y,n)?
weirdly the content is still loaded fine after saying yes, but i would really like my program to be clean and also safe regarding internet security.
Here is my code in its current state, but i really don't know what i'm doing, so please point me in the right direction:
// POCO C++ Libraries used
SharedPtr<InvalidCertificateHandler> ptrCert = new ConsoleCertificateHandler(false);
Context::Ptr ptrContext = new Context(Context::CLIENT_USE, "", "cert.pem", "", Context::VerificationMode::VERIFY_NONE);
SSLManager::instance().initializeClient(0, ptrCert, ptrContext);
URI uri(argv[1]);
std::unique_ptr<std::istream> pStr(URIStreamOpener::defaultOpener().open(uri));
StreamCopier::copyStream(*pStr.get(), std::cout);
I generated the cert.pem file with openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes, hoping this would generate a certificate, but i don't know what certificates i need and where to specify them in my c++ program.
My aim is to connect to a Github API page and read a GET Request, any help appreciated...

I just managed to do it, for anyone interested:
Since i only need to access the Github API, i only need to verify the certificate used by github, which is DigiCert.
I visited this page https://www.digicert.com/kb/digicert-root-certificates.htm and downloaded the file DigiCertHighAssuranceEVRootCA.crt.pem, copied it next to my exe and then specified it in my c++ program as such:
SharedPtr<InvalidCertificateHandler> ptrCert = new ConsoleCertificateHandler(false);
Context::Ptr ptrContext = new Context(Context::CLIENT_USE, "", "", "DigiCertHighAssuranceEVRootCA.crt.pem", Context::VerificationMode::VERIFY_RELAXED);
SSLManager::instance().initializeClient(0, ptrCert, ptrContext);
Now i get the answer immediately, without any errors or warnings

Related

CFHTTP unable to find valid certification path to requested target

I'm looking to scrape data off a website, other https sites work and this was working last week but now fails
<cfhttp url="https://www.cliftoncameras.co.uk/all-brands-and-types-of-used-cameras/"></cfhttp>
If I run a dump of cfhttp
Exception: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
I have tried running with the latest JRE version 12 - no change
https://helpx.adobe.com/coldfusion/kb/import-certificates-certificate-stores-coldfusion.html
Reverted back to CF original JRE, downloaded the target SSL certificate and installed it using the keytool - no change
c:\ColdFusion2018\jre\bin\keytool -import -keystore cacerts -alias
cliftoncameras -file
c:\ColdFusion2018\jre\lib\security\cliftoncameras.cer
I changed the websocket in the CFAdmin to proxy - no change
I did restart the CF Application Server each time.
What else can I do?
I have also seen this java.security.cert.CertPathBuilderException error before from Java and Coldfusion on sites that load ok in a regular browser, but which still error from cfhttp even after adding the certificate to the CF keystore and restarting.
This happens when the target site server certificate configuration has a trust chain issue - when one or more trust chain paths requires the browser to perform an "extra download" of a certificate. This can be because of a missing intermediate certificate in a single trust chain path, or because there are multiple branches in the trust chain with different fingerprints and one or more certificates from one or more of those branches is not being served.
If you run the target site through an SSL Analyzer like ssllabs.com - eg
https://globalsign.ssllabs.com/analyze.html?d=www.cliftoncameras.co.uk&hideResults=on - you'll see that their intermediate certificate Starfield Secure Certificate Authority - G2 is not being served by their server, which forces the client to do an "extra download" - which won't be a problem for most proper browsers, but the Java client used by cfhttp needs the server to provide pretty much every intermediate and root cert directly. It used to be the same for most mobile OSs up until a few years ago.
So the ideal solution is to contact cliftoncameras and have their server admin install the correct Starfield Intermediate certificate so that it is served correctly.
A possible workaround on your side is to install the Starfield Secure Certificate Authority - G2 intermediate certificate in your CF keystore.
On my development platform I added
-Dcom.sun.security.enableAIAcaIssuers=true
To the java.args in the file in ColdFusion2018\cfusion\bin\jvm.config
Then restarted the CF Application Server, and now my CFHTTP call is successful.
Thanks to #agreax for this solution
Thanks to #sevroberts who's answer was probably the correct one, even though I couldn't get it to work. The production host installed the SSL certificate to the keystore and successfully resolved it this way. They said:
If you use FireFox browser and click on the lock icon when browsing the URL you are wanting to have the cfhttp request access you can then get the more info and click the View Certificate option.
You will need to download the PEM (cert) not the Chain. Once downloaded, you need to run the keytool in order to import it to the keystore.
If you are using the default JRE within your JVM for ColdFusion you will need to install a JDK to your development machine.
You can see the details and steps we have listed on our wiki regarding the commands from the command prompt to import the SSL into the store.
https://wiki.hostek.com/ColdFusion_Tips_%26_Tricks#Fixing_cfhttp_Connection_Failures_with_Keytool
Thanks to #alexbaban his workaround, whilst it worked, it was a solution I could not implement due to requiring the use of the tag cfexecute.
If you can not get the keystore thing working maybe you'll want to try this.
Create a dedicated command line executable (.exe) which will read the web page and save the source to a text file. You can then use ColdFusion to read the file and work with the data.
Here is the ColdFusion code:
<cfscript>
_execPath = "c:/bin/clifton.exe";
_filePath = "c:/bin/clifton.txt";
// run your command-line app (clifton.exe)
cfexecute(name="#_execPath#");
// wait for the file
do {
sleep(100);
} while ( not fileExists(_filePath) )
// wait for write to finish
do {
sleep(100);
_fileInfo = getFileInfo(_filePath);
writeOutput(" ## ");
cfflush();
} while ( _fileInfo.size eq 0 || dateDiff("s", _fileInfo.lastmodified, now()) lte 3 )
writeOutput("<hr />")
_result = fileRead(_filePath);
writeDump(_result);
</cfscript>
As you can see it depends on clifton.exe and reads clifton.txt (clifton.txt is the result of executing clifton.exe).
How to make clifton.exe
You will use the Dart SDK and the dart2native tool to create the executable on your development computer. You can deploy the executable on your production server as a standalone (You don't need the Dart SDK installed on production).
Create a bin folder on your C drive.
From https://ssl-ccp.secureserver.net/repository/?origin=CALLISTO download the certificate sfig2.crt.pem (PEM) and save it inside c:\bin.
Inside c:\bin create a text file clifton.dart with the following code:
// clifton.dart
import 'dart:convert';
import 'dart:io';
main() {
//
const String _certFilePath = 'c:/bin/sfig2.crt.pem';
const String _responseFilePath = 'c:/bin/clifton.txt';
const String _uri =
'https://www.cliftoncameras.co.uk/all-brands-and-types-of-used-cameras/';
final File _file = new File(_responseFilePath);
final IOSink _sink = _file.openWrite();
final SecurityContext _context = new SecurityContext();
_context.setTrustedCertificates(_certFilePath);
final HttpClient _client = new HttpClient(context: _context);
saveSourceToFile(_client, _uri, _sink);
_client.close();
//
}
// get web page source then write it to file
void saveSourceToFile(HttpClient _client, String _uri, IOSink _sink) {
//
_client
.getUrl(Uri.parse(_uri))
.then((req) => req.close())
.then((res) => res.transform(Utf8Decoder()).listen((data) {
// as data is received write to file
_sink.write(data);
}, onDone: () {
_sink.close();
}));
//
}
Download and install the Dart SDK from https://dart.dev/
Open a terminal window and test the installation of Dart with dart --version (you should be able to run dart from any folder, if needed add dart to your PATH)
In a terminal window, change directory to c:\bin with cd c:\bin
Next, run dart2native clifton.dart -o clifton.exe
If compilation goes well you should have inside c:\bin the three files: clifton.dart, clifton.exe and the certificate sfig2.crt.pem.
If you wish you can test run clifton.exe in the terminal window, which should create the clifton.txt file.
Test the ColdFusion page which calls clifton.exe, waits for clifton.txt then outputs the content.
If you deploy in production you need both files clifton.exe and sfig2.crt.pem (the certificate).
Good luck!

Python requests [SSL] PEM lib (_ssl.c:2603)

while trying to do a requests call on a in-house web-service, I am getting the following error message, whereas I have put in the PEM certificate file and have specified it
r = requests.get(url, cert=cert)
and the error response I get is
raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL] PEM lib (_ssl.c:2603)
I dont have access to export the private key for personal certificate which might help in resolving this issue. Is there any other way to bypass it or point it to the certificate and provide authentication?
The url opens up in browser from my computer totally fine without asking for user credentials or anything for authorization.

using self-signed certificates with requests in python

Situation :
The target site (a pre-prod URL, say https://my-pre-prod-site.com/login, for example) is using a self-signed certificate.
From the browser, the site is accessible over https without any issues (the self-signed certificate warning is suppressed by adding the certificate to the trust store in the browser)
Problem Statement :
A simple python script that makes a get call to the target site using requests fails with either of the below errors in different situations :
requests.exceptions.SSLError: [Errno 0] _ssl.c:344: error:00000000:lib(0):func(0):reason(0)
or
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
The simple script used (on the python prompt) is :
import requests
res = requests.get('https://my-pre-prod-site.com/login')
**Things already tried **
I do NOT want to skip the ssl verification. Hence, verify = false is not an option for me.
I have already used the below with the same error
res = requests.get('https://my-pre-prod-site.com/login', verify = os.path.join(os.getcwd(),'test.pem') where test.pem is a pem file created by concatenating the output of the below commands in that order :
openssl rsa -in ~/Desktop/CertPath/private.key -check
and
openssl x509 -pubkey -noout -in ~/Desktop/CertPath/certificate.pem
The script is run from ~/Desktop/CertPath so getcwd() gives the right path to the certificate.
I tried another test.pem file as well where the order of concatenation was reversed. It still throws the same error.
Have tried passing the .pem file holding the public key and the .key file holding the private key, separately (individually) as well, with the same error as the outcome.
Environment details if it helps
OS - ElCapitan Mac
Requests - 2.9.0
Python - 2.7.10
OpenSSL being used by Python - 'OpenSSL 0.9.8zg 14 July 2015'
Note - The openssl version does not seem to be an issue. Because even with an updated version of openssl, the errors are the same - tested on Ubuntu
with Python 2.6 that uses the Openssl 1.x
This question is old but In case someone wonders off here.
You are putting the private key and public key in you test.pem. This is wrong. What verify param requires is certs which it can trust.
res = requests.get('https://my-pre-prod-site.com/login', verify = os.path.join(os.getcwd(),'test.pem')
The test.pem is supposed to contain the list of all the Trusted Certificates. But what you're providing in your test.pem is your public and private key. You're ~/Desktop/CertPath/certificate.pem file itself should go into it.
Try this:
res = requests.get('https://my-pre-prod-site.com/login', verify = '~/Desktop/CertPath/certificate.pem')
In order to specify certificate for SSL verification you can use :
requests.get('https://my-pre-prod-site.com/login', cert=os.path.join(os.getcwd(),'test.pem'))

classic asp, MSXML2.ServerXMLHTTP.6.0 web service call with certificate iussue

after days of failed attempts and research i need your help.
i'm trying tocall a web service to get a Token, the webservice it's protected by a certificate.
I have the .pem file with password and I converted it into .p12 using the mmc command to import it on IIS
If i call the https page by browser i can access easly, so the certificate it's ok.
If i try to connect with "curl" command on dos all work correctly
The problem is when i try to use the classic asp
I receive this error message:
msxml6.dll error '80072f7d'
An error occurred in the secure channel support
this is the code
Dim oRequest
Set oRequest = Server.CreateObject("MSXML2.ServerXMLHTTP.6.0")
oRequest.setOption(2) = 13056
oRequest.setOption(3) = "LOCAL_MACHINE\My\" & CERIFICATE_NAME
oRequest.setTimeouts 10000, 10000, 10000, 10000
msURL = WEBSERVICE_HTTPS_URL
oRequest.Open "GET", msURL, False,USERNAME,PASSWORD
oRequest.setRequestHeader "Authorization", "Basic " & Base64Encode("USERNAME:PASSWORD")
oRequest.setRequestHeader "User-Agent", Request.ServerVariables("HTTP_User-Agent")
oRequest.setRequestHeader "Content-Type", "text/html;charset=ISO-8859-1"
oRequest.send
any advice is appreciated,
Salvatore

OpenSSL Ignore Self-signed certificate error

I'm writing a small program with the OpenSSL library that is suppose to establish a connection with an SSLv3 server. This server dispenses a self-signed certificate, which causes the handshake to fail with this message: "sslv3 alert handshake failure, self signed certificate in certificate chain."
Is there a way I can force the connection to proceed? I've tried calling SSL_CTX_set_verify like so:
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
But it does not seem to change anything.
Any suggestions?
By default OpenSSL walks the certificate chain and tries to verify on each step, SSL_set_verify() does not change that, see tha man page. Quoting it:
The actual verification procedure is performed either using the
built-in verification procedure or using another application provided
verification function set with SSL_CTX_set_cert_verify_callback(3).
So the solution is to create a simple callback and set that one, so that you override all certificate-chain walking:
static int always_true_callback(X509_STORE_CTX *ctx, void *arg)
{
return 1;
}
SSL_CTX_set_cert_verify_callback(CTX, always_true_callback);
Have you tried giving your app the server's CA certificate so that your app can verify the certificate chain?
Check these OpenSSL Examples: http://www.rtfm.com/openssl-examples/
The wclient.c connects to any https page, for example:
wclient -h www.yahoo.com -p 443
If you run that with the default installation, you'll get a certificate error (you can use the -i flag to bypass the certificate check though).
To verify the certificate, you'll need to download the CA certificates (Verisign, Thawte, Equifax, etc), so google this file cacert.pem, download and rename it to root.pem and you'll be able to connect to a web server and validate its certificate.
Have you tried setting SSL_set_verify?
SSL_set_verify(s, SSL_VERIFY_NONE, NULL);
You could try passing your own callback to SSL_set_verify() and then doing your own verification. It's less than ideal as I think you then need to do all of the verification and then allow the self signed error to be ignored, but you should be able to work out what the standard verify code does from the OpenSSL source and then simply pull it into your own verification callback and allow the specific error code...
My sample client code (link) works fine with self signed server cert. I have the below code after SSL_connect and have full control over self signed certificates acceptability in my client
SSL_CTX* ctx = SSL_CTX_new(SSLv3_method());
// TCP connection and SSL handshake ...
/* Check the certificate */
rc = SSL_get_verify_result(ssl);
if(rc != X509_V_OK) {
if (rc == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || rc == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
fprintf(stderr, "self signed certificate\n");
}
else {
fprintf(stderr, "Certificate verification error: %ld\n", SSL_get_verify_result(ssl));
SSL_CTX_free(ctx);
return 0;
}
}