Adding self-signed SSL certificate for libcurl - c

I am using libcurl in my C application to communicate with an HTTPS server that I have set up. I generated a self-signed certificate on that server that I wish to use with curl.
I am aware of setting CURLOPT_SSL_VERIFYPEER to 0 to bypass the SSL verification, but I wish to add the generated certificate to curl's "valid" CA certificates.
I have tried setting CURLOPT_CAPATH and CURLOPT_SSLCERT to the location of the server SSL public key, but it fails to pass the verification.
How can I add my own CA/Self-signed certificate so that libcurl will successfully validate it?

To add a self-signed certificate, use CURLOPT_CAINFO
To retrieve the SSL public certificate of a site, use
openssl s_client -connect www.site.com:443 | tee logfile
The certificate is the portion marked by ----BEGIN CERTIFICATE---- and
---END CERTIFICATE----.
Save that certificate into a file, and use curl in a manner like so:
CURL* c = curl_easy_init();
curl_easy_setopt(c, CURLOPT_URL, "https://www.site.com");
curl_easy_setopt(c, CURLOPT_CAINFO, "/path/to/the/certificate.crt");
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 1);
curl_easy_perform(c);
curl_easy_cleanup(c);

First, you kind of mix "Certificate Authority" files and "Certificate" files which confuses me.
How can I add my own CA/Self-signed certificate so that libcurl will
successfully validate it?
This might be seen as a complementary answer to the one above.
In the case you want to add a self-signed CA (every root-CA is self-signed) so that libcurl will successfully validate a website's certificate, which has been generated by the CA, then continue reading.
With CURLOPT_CAINFO you need to pass the "Certificate Authority" file (CA) that was used when generating the (non-CA) certificate of the site you want to verify.
(I do not know if this option works by passing it a non-CA certificate, the documentation is not really clear on this, and the previous answer has 2 up-votes, so if anyone has tested it please comment)
You can also pass a Certificate Authority chain file that contains the CA that was used, in case it was not a root-CA.
Here's a little tutorial I've found that can help you test your solution:
Creating a private root CA:
http://www.flatmtn.com/article/setting-openssl-create-certificates
Creating a site certificate:
http://www.flatmtn.com/article/setting-ssl-certificates-apache

Related

Getting access token with client credentials and X509 certificate (Identity Server 4)

i'm looking for a solution for 4 days but i have found nothing.
What i want is to get an access token from my Identity Server with a client_credentials grant_type. I found that you can do this but nowhere is explained how to make the certificates, how the request is made etc.
I tried a lot of ways but with no success.
From the documentation:Our default private key JWT secret validator expects the full (leaf) certificate as base64 on the secret definition. This certificate will then be used to validate the signature on the self-signed JWT . That base64 is the content of the .cert file i believe. On the request should i put the .pfx file in base64 too?
Are there any changes that i need to make on the program.cs file for the Kestrel? I found this too, but all are outdated and doesn't work.
Now i'm trying with postman, after this everything should be called from an Azure Logic App.
I followed this example : but doesn't work.
The error:
Postman:
Program.cs
And the Config.cs from Identity
I will be very glad if you can help. Thanks in advance
As said you can use a client secret instead of a client certificate which is more common/easier. If you really need certificate authentication: I found more information on http://docs.identityserver.io/en/latest/topics/mtls.html

Sending pfx certificate in angular $http call

I have an external API that I'm using: https://example.com/. When browsing to this, I get a popup that asks for a certificate, which I have as a .pfx file (or in my keychain as a .cer). I accept that they access the certificate and sign it with my private key and voilà - I can access the page.
Now what I want to be able to do is do this in AngularJS. What I have tried so far is:
$http.get("https://example.com/");
Response:
Failed to load resource: The server ”...” did not accept the certificate. - I translated this from another language, just so you know.
What I want to do is to somehow send the .pfx file in the $http request. How do I do this?
I solved this by doing it in node.js instead, where there are options for certificates. I used pfx and passphrase and that was it. I however don't know if this is possible to do in AngularJS.

How to test client certificate

I'm building a web service to allow salesforce to call to it, the two way SSL is used for security, and salesforce has provided its client certificate: sfdc-client.cert.
In order to test whether salesforce client certificate work or not, I have setup a very simple web on MAC apache and enable SSL and client authentication on ssl config file /etc/apache2/extra/httpd-ssl.conf as below (use self-signed):
SSLCertificateFile "/private/etc/apache2/ssl/server.crt"
SSLCertificateKeyFile "/private/etc/apache2/ssl/server.key"
SSLCACertificateFile "/private/etc/apache2/ssl/sfdc-client.cert"
SSLVerifyClient require
SSLVerifyDepth 10
The first browsing by Chrome, I got "SSL Connection Error", I supposed it's correct in this case.
Then, I have tried to import sfdc-client.cert to key chain access, but it does not work at all because it just supports p12/pfx format.
I also tried to use CURL:
curl https://test.com --cert-type der --cert sfdc-client.cert
but got the error:
curl: (58) unable to use client certificate (no key found or wrong pass phrase?)
I'm totally newbie on this stuff, does anyone know how to test client certificate to make sure it works as above?
First you need to have both the client's certificate and certificate private key to be able to test 2-way SSL authentication.
To test with web browser, follow instructions here: Is there a way to test 2 way ssl through browser?

Authenticate server (peer) with SSL

I would want my C/C++ client to authenticate the server via SSL.
I first downloaded the certificate file from the server with
openssl s_client -showcerts -connect www.openssl.org:443 </dev/null 2>/dev/null | openssl x509 -outform PEM > mycertfile.pem
Then in my application I do the following API invocations (pseudo code):
// Register the error strings for libcrypto & libssl
SSL_load_error_strings();
// Register the available ciphers and digests
SSL_library_init();
// New context saying we are a client, and using SSL 2 or 3
ctx = SSL_CTX_new(SSLv23_client_method());
// load the certificate
if(!SSL_CTX_load_verify_locations(ctx, "mycertfile.pem", 0))
...
// Create an SSL struct for the connection
ssl = SSL_new(ctx);
// Connect the SSL struct to our pre-existing TCP/IP socket connection
if (!SSL_set_fd(ssl, sd))
...
// Initiate SSL handshake
if(SSL_connect(ssl) != 1)
...
// form this point onwards the SSL connection is established and works
// perfectly, I would be able to send and receive encrypted data
// **Crucial point now**
// Get certificate (it works)
X509 *cert = SSL_get_peer_certificate(ssl);
if(cert) {
// the below API returns code 19
const long cert_res = SSL_get_verify_result(ssl);
if(cert_res == X509_V_OK) {
printf("Certificate verified!\n");
}
X509_free(cert);
}
Above code works fine if I don't mind checking the certificate and I'm just interested in an encrypted connection.
Problem with it is that when I try to verify the authenticity of the server, I do get the certificate from SSL_get_peer_certificate but then the verification of results doesn't work even if I've just downloaded the certificate 5 minutes before.
What am I doing wrong?
All this is on Ubuntu 12.04.03 x86-64 with gcc and openssl.
Thanks,
Ema
You should only call SSL_CTX_load_verify_locations() if you have a more complete set of CA certificates than what OpenSSL already provides, or if you are connecting to a server that has used a non-standard CA to sign its cert, and for which you have the CA certificate to verify the server cert. Otherwise, you should call SSL_CTX_set_default_verify_paths() instead.
// load the certificate^H^H^H^H^H^H^H^H^H^H^H^H CA trust-store
if(!SSL_CTX_set_default_verify_paths(ctx))
...
On a side note, your program had another error. You passed the wrong pointer to SSL_get_verify_result(). Instead of passing in a SSL_CTX *, you should pass in the SSL *. The compiler should have warned you about this error.
const long cert_res = SSL_get_verify_result(ssl);
The certificate you just downloaded should have been signed by a certificate authority (CA). You need to load the certificate of the CA (or the root CA) and not the certificate itself. Since you loaded the server's certificate directly into the SSL_CTX_load_verify_locations, the verification routine SSL_get_verify_result returned with a failure code. Most likely the verification code must have been 19 (X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN).
That said, OpenSSL comes with a built-in set of CAs (and root CAs) that you can use in your client application. The path to these certificates, on a Linux distribution, is typically /etc/ssl/certs. So, you can try changing your SSL_CTX_load_verify_locations as below:
if (!SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ssl/certs"))
...
Of course, this assumes that /etc/ssl/certs exists and has the relevant certificates (one of which signed the server certificate). If you are authenticating a well known host, you will most likely find the CA in /etc/ssl/certs.

Sending and Verifying SSL certificate using c/c++

I am actually working on a protocol security. I need to send the certificate and verify it on the other side.
Now here is what I have planned:
1 Send the certificate chain just like a normal stream of data
2.Capture it on the other side and store it in a char[] buffer
Now, how to verify the certificate from this char[]buffer and extract the needed parameters?
I need it in c/c++.
This blog post about Verifying Using a Certificate Store using OpenSSL shows how to verify certificate against CA.

Resources