curl NSS -12286 error in TLS handshake
Solution 1
The very first thing I notice, you're doing:
rv=curl_easy_setopt (ch, CURLOPT_CAPATH, "./cacert.pem" );
needs to specify a "string naming a directory holding multiple CA certificates to verify the peer with". From the man page. You'll probably want "/etc/tls/certs/"
In addition, it would appear the line:
rv=curl_easy_setopt(ch,CURLOPT_SSL_CTX_FUNCTION, *sslctx_function);
is doing nothing. I say this because, again, from the man page, "This option does only function for libcurl powered by OpenSSL". I say this because, your error log has "NSS error"
My experience with working with ssl is only with openssl. I found the command line function openssl s_client
to be helpful. That being said, it is very easy to miss configure your setup. Many functions and command line options will try to work with even the craziest input, leading to red herring errors.
Edit: My attempt at your program completes with success.
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL * ch;
CURLcode rv;
rv=curl_global_init(CURL_GLOBAL_ALL);
ch=curl_easy_init();
rv=curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
rv=curl_easy_setopt(ch, CURLOPT_CAPATH, "/etc/ssl/certs");
rv=curl_easy_setopt(ch, CURLOPT_URL, "https://");
rv=curl_easy_perform(ch);
if (rv==CURLE_OK) {
printf("*** transfer succeeded ***\n");
}
else {
printf("*** transfer failed ***\n");
}
curl_easy_cleanup(ch);
curl_global_cleanup();
return rv;
}
Solution 2
Ran into this in PHP. I ran curl on the command line with -v and found the NSS -12286 error.
Turns out that the remote server and curl did not have a common cypher (nss error codes). We added a cypher to the curl object like so:
curl_setopt($oCurl, CURLOPT_SSL_CIPHER_LIST, 'rsa_rc4_128_sha');
user1495372
Updated on June 04, 2022Comments
-
user1495372 almost 2 years
I am getting NSS -12286 error while trying to load the https page using the ca certificate using cacertinpem.c curl c code. i am using cacert.pem file in the code alog with path. but same thing is working when i try using curl -v "https://sampleserve.com:443",in this case ssl is taking default ca path as "/etc/tls/certs/ca.budle.crt"
But this c code is not working for both default ca location and external path selection of ca aswell.
What is the reason for this error(NSS -12286).
Error: * About to connect() to fiservices.sterlingbankng.com port 443 (#0) * Trying 1.1.1.1... * Connection timed out * Trying 1.1.1.2... * connected * Connected to fiservices.sterlingbankng.com (1.1.1.2) port 443 (#0) * Initializing NSS with certpath: /etc/pki/nssdb * CAfile: ./cacert.pem CApath: ./cacert.pem * NSS error -12286 * Error in TLS handshake, trying SSLv3... GET /CanFI/ HTTP/1.1 Host: sampleserver.com Accept: */* * Connection died, retrying a fresh connect * Closing connection #0 * Issue another request to this URL: 'https://sampleserver.com' * About to connect() to sampleserver.com port 443 (#0) * Trying 1.1.1.1... * Connection timed out * Trying 1.1.1.2... * connected * Connected to sampleserver.com (1.1.1.2) port 443 (#0) * TLS disabled due to previous handshake failure * CAfile: ./cacert.pem CApath: ./cacert.pem * NSS error -12286 * Closing connection #0 * SSL connect error
Sample code:
size_t writefunction( void *ptr, size_t size, size_t nmemb, void *stream) { fwrite(ptr,size,nmemb,stream); return(nmemb*size); } static CURLcode sslctx_function(CURL * curl, void * sslctx, void * parm) { X509_STORE * store; X509 * cert=NULL; BIO * bio; char * mypem = "-----BEGIN CERTIFICATE-----\n"\ "-----END CERTIFICATE-----\n"; //public certificate } int main(void) { CURL * ch; CURLcode rv; rv=curl_global_init(CURL_GLOBAL_ALL); ch=curl_easy_init(); rv=curl_easy_setopt(ch,CURLOPT_VERBOSE, 1L); rv=curl_easy_setopt(ch,CURLOPT_HEADER, 0L); rv=curl_easy_setopt(ch,CURLOPT_NOPROGRESS, 1L); rv=curl_easy_setopt(ch,CURLOPT_NOSIGNAL, 1L); rv=curl_easy_setopt(ch,CURLOPT_WRITEFUNCTION, *writefunction); rv=curl_easy_setopt(ch,CURLOPT_WRITEDATA, stdout); rv=curl_easy_setopt(ch,CURLOPT_HEADERFUNCTION, *writefunction); rv=curl_easy_setopt(ch,CURLOPT_WRITEHEADER, stderr); rv=curl_easy_setopt(ch,CURLOPT_SSLCERTTYPE,"PEM"); rv=curl_easy_setopt (ch, CURLOPT_CAPATH, "./cacert.pem" ); rv=curl_easy_setopt (ch, CURLOPT_CAINFO, "./cacert.pem" ); rv=curl_easy_setopt(ch,CURLOPT_SSL_VERIFYPEER,1L); rv=curl_easy_setopt(ch, CURLOPT_URL, "https://"); rv=curl_easy_perform(ch); if (rv==CURLE_OK) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); rv=curl_easy_setopt(ch,CURLOPT_SSL_CTX_FUNCTION, *sslctx_function); rv=curl_easy_perform(ch); if (rv==CURLE_OK) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); curl_easy_cleanup(ch); curl_global_cleanup(); return rv; }
Thanks
-
user1495372 almost 11 yearsThanks..As you have mentioned above i have tried giving complete path of CA certificate and removing ctx option aswell.But still error remains same.And also i have tried using "openssl s_client -verify 0 -connect ip:port" using command ,i could able to get server public certificate ,below are the some part of output log.openssl s_client -verify 0 -connect ip:port verify depth is 0 CONNECTED(00000003) depth=3 C = US, O = "VeriSign, Inc.", OU = Class 3 Public Primary Certification Authority verify return:1 3 s:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary C