Linking two libraries that uses openssl - c++

platform: GNU/Linux Debian Etch 32b
libcurl 7.37.1
qt 4.8.1
openssl 0.9.8
Above is a schema with the dependencies of my app (only the one involved in this question)
+-----------------+
| application |
+-----------------+
| libcurl | libqt |
+-----------------+
| libssl |
+-----------------+
My c++ application is based on qt 4.8.1 but for some http/network operation we use libcurl
Both libs are compiled with the ssl support
Im facing a really strange error scenario:
Object1 runs a curl_easy_perform() to an https site. The call reports an error. The curl_error_buffer contains:
error setting certificate verify locations: CAfile:
/etc/ssl/certs/ca-certificates.crt CApath: none
Later on Object2 calls QSslSocket.write()
This second call generates a QTcpError.
The error string reported by the QSslSocket is:
TCP Error: Error while reading: error:02001002:system library:fopen:No such file or directory, error:2006D080:BIO routines:BIO_new_file:no such file, error:0B084002:x509 certificate routines X509_load_cert_crl_file:system lib
Both objects live in the same application thread.
Tracing the application behavior with gdb it seems like:
The X509_load_cert_crl_file call is performed inside the curl_easy_perform()
When the method QSslSocket.write() is called, the function: X509_load_cert_crl_file is not called netherless the SSL stack returns to the qt network stack the above error.
My idea is that the SSL lib state is somehow global (i.e. errno) and/or shared between two library (qt and libcurl) and performing the QSslSocket.write() we got the error state previously set by the libcurl call.
Does it make any sense?
I'm I using the libcurl the wrong way, so that it is leaving the ssl connection in some inconsistent state?
Please note that the qt write method actually perform internally a write AND a read from the socket. After that the state of ssl is checked with SSL_get_error
(Qt code here: https://github.com/qt/qt/blob/v4.8.1/src/network/ssl/qsslsocket_openssl.cpp#L1140)

Related

Self-Compiled OpenSSL package gives certificate error on CentOS 7

I am developing a C++ HTTP/HTTPS client application inside environment of CentOS/Redhat 7.7, which the OS comes with OpenSSL 1.0.2k-fips. But I need at least OpenSSL 1.1.1 for my application. So I compiled OpenSSL 1.1.1f from source.
My compilation configuration.
./Configure linux-x86_64 enable-ec_nistp_64_gcc_128 -Wl,-rpath=/usr/local/lib64 --prefix=/usr/local --openssldir=/usr/local
The problem starts here.
Any requests I make with the new OpenSSL results with Verify return code: 20 (unable to get local issuer certificate). I spent some time switching HTTP clients for C++, which was a very tiring process, only to find out that the issue is with OpenSSL itself.
After a long research, the HTTP client I currently use, shared a ca-bundle inside it's repo. Including it into my project resolved the issue.
https://github.com/yhirose/cpp-httplib/blob/master/example/ca-bundle.crt
cli.set_ca_cert_path(./ca-bundle.crt);
Or with command line,
openssl s_client -connect example.com:443 -CAfile ./ca-bundle.crt
This all seems absurd, I never had to do anything like this before in my experience with developing HTTP clients. Therefore my questions:
Is this a problem with CentOS 7 ?
Did I make a mistake while compiling OpenSSL ? (Followed)
Note: Using cli.set_ca_cert_path("/etc/ssl/certs/ca-bundle.crt"); also works (took me a long time to realize), but I never had to do this manually before, hence forgive my ignorance.
Thanks for your time.
Edit: With the help of some code,
const char* dir = getenv(X509_get_default_cert_dir_env());
if (!dir)
dir = X509_get_default_cert_dir();
cout << dir << endl;
It would seem dir is /usr/local/certs which does not exist. But I also tried this with the default installed OpenSSL inside the OS. Which I would guess should point to the real certificates ?
Edit2: Using /etc/pki/tls/cert.pem also works.

Error connecting mongocxx to mongodb server: SSL support not available

Using mongocxx 3.3 or mongo cxx 3.4 stable versions, I´m trying to connect to a mongo atlas instance. This is my basic code:
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
mongocxx::instance inst{};
mongocxx::uri uri = mongocxx::uri("mongodb+srv://...");
mongocxx::client conn(uri);
mongocxx::database db = conn["test"];
And I have tested several alternatives, like using client options (like explained here: http://mongocxx.org/mongocxx-v3/configuration/), and also setting a pem file path like explained here: Mongocxx fails to connect to mongoDB with SSL.
I always have the following error:
terminate called after throwing an instance of 'mongocxx::v_noabi::exception'
what(): SSL support not available
Aborted (core dumped)
You got this error because one or both of the C and C++ drivers was configured without SSL support. The C++ driver build defaults to SSL support (look for the MONGOCXX_ENABLE_SSL CMake option). So the most likely explanation is that the underlying C driver was built without SSL, and the second most likely explanation is that the C driver does have SSL support built in, but it was explicitly set to off when building the C++ driver. You can verify the state of the C driver by looking for the value of MONGOC_ENABLE_SSL in the C driver headers. If it is enabled, it should look like this:
$ find /usr/local/Cellar/mongo-c-driver/1.14.0/include -type f -name "*.h" | xargs grep 'MONGOC_ENABLE_SSL '
/usr/local/Cellar/mongo-c-driver/1.14.0/include/libmongoc-1.0/mongoc/mongoc-config.h: * MONGOC_ENABLE_SSL is set from configure to determine if we are
/usr/local/Cellar/mongo-c-driver/1.14.0/include/libmongoc-1.0/mongoc/mongoc-config.h:#define MONGOC_ENABLE_SSL 1
/usr/local/Cellar/mongo-c-driver/1.14.0/include/libmongoc-1.0/mongoc/mongoc-config.h:#if MONGOC_ENABLE_SSL != 1
Of course, you should replace the path to the include directory above with the actual location where you have the C driver installed.
If you see anything other than #define MONGOC_ENABLE_SSL 1 in there, then your C driver doesn't have SSL support enabled and you will need to rebuild it to have it.

Call to mongocxx::instance returns "mongoc: Failed to initialize OpenSSL"

I have a very simple MongoDB application that connects to a MongoDB database and works fine.
I've then added the connectivity calls to a large, complex, legacy application and when I call:
mongocxx::instance (i.e. the first MongoDB library call)
I get the following response:
2018/08/16 10:20:59.0499: [16856]: ERROR: mongoc: Failed to initialize OpenSSL.
It appears that the low-level call to SSL_CTX_new within the MongoDB C library is returning a null pointer.
I'm not too sure why this is happening. I've even gone so far as recompiling and linking my simple MongoDB app against all of the libraries that the large legacy app uses (calls to ldd are now identical) but the simple app is still working fine.
This is using the following MongoDB drivers:
mongo-c-driver-1.11.0
mongo-cxx-driver-r3.3.0
Compiled and run on RHEL7 box (7.4) using OpenSSL 1.1.0.
Any suggestions?
I was just in trouble with the same error.
It solved it by changing the option of cmake.
In this way, setting an option, it will work.
cmake -DENABLE_SSL=OFF ..
In the following method, OpenSSL initialization error occurs.
cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP = NO
I'd like to know how to prevent initialization errors with "ENABLE_AUTOMATIC_INIT_AND_CLEANUP".
https://github.com/mongodb/mongo-c-driver/blob/r1.10/NEWS#L935
https://github.com/mongodb/mongo-c-driver/blob/2edd3b2a91171a5da88e9282ffb6a3efbbc2bd91/src/libmongoc/CMakeLists.txt#L225
This problem was solved by make of OpenSSL.
Why 'apt-get install openssl' did not install last version of OpenSSL?
I used the following.
openssl-1.1.0f
mongo-c-driver-1.10.1
mongo-cxx-driver-r3.3.0

qtdbus under windows 7

CONFIGURATION
I have this configuration:
QT Community 5.4.1
dbus-daemon.exe downloaded from http://sourceforge.net/projects/windbus/
link
I have copied in my local directory these qt example:
c:\Qt\Qt5.4.1\Examples\Qt-5.4\dbus\remotecontrolledcar\car
c:\Qt\Qt5.4.1\Examples\Qt-5.4\dbus\remotecontrolledcar\controller
I use Windows 7 and NOT Linux!!!!!!
Procedure:
I compiled both examples in debug mode in my local directory
I launched dbus-daemon.exe with these parameters:
DBUS_SESSION_BUS_ADDRESS sets to tcp; host sets to localhost,port sets to 12434.
set DBUS_SYSTEM_BUS_DEFAULT_ADDRESS=tcp:host=localhost,port=12434
dbus-daemon.exe --session --system --config-file=.\etc\session.conf
I execute car.exe
I execute controller.exe
PROBLEM
The dbus connection fails in particular the method sessionBus form DBusConnection class fails. Infact when i call the isConnected method, it returns false.
Someone can explain why? Is it wrong the way I call the daemon executable?
Or Qt Comunity 5.4.1 have problem with qtdbus? can someone pass me a correct configuration file (session.conf)?
Thank you very much for for the support.
Fausto

Initializing SSL and libcurl and getting "out of memory"

I intend to do https requests with libcurl and openssl with a C++ program.
I initialized libcurl with curl_global_init(CURL_GLOBAL_ALL) as described in the documentation. Then I use an curl_easy handle that I initialize, populate with headers and a body, and send everything out to ´https://example.com:443/foo´. It works for non-https connections.
Looking around I find that there may be other libraries that are already getting an SSL context which is what causes libcurl to fail in doing precisely that. I get the following error message:
curl_easy_perform failed: Out of memory
In my case I am using libmicrohttpd which I initialize with
mhdDaemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL,
htons(port),
NULL,
NULL,
connectionTreat, NULL,
MHD_OPTION_HTTPS_MEM_KEY, httpsKey,
MHD_OPTION_HTTPS_MEM_CERT, httpsCertificate,
MHD_OPTION_CONNECTION_MEMORY_LIMIT, memoryLimit,
MHD_OPTION_SOCK_ADDR, (struct sockaddr*) &sad,
MHD_OPTION_NOTIFY_COMPLETED, requestCompleted, NULL,
MHD_OPTION_END);
So I am indeed using openSSL somewhere else. The thing is, if I take out the MHD_USE_SSL part it does not fix the problem.
This is the list of libraries that are linked to the application (I'm using cmake):
-lmicrohttpd
-lmongoclient
-lboost_thread
-lboost_filesystem
-lboost_system
-lpthread
Is there any of the others that could be loading SSL? Is microhttpd loading it anyways even if I comment out the MHD_USE_SSL flag (plus all other related flags)? Could there be any other reason for this error?
I'm not aware of any problem in libcurl that would cause this error code to get returned if indeed a memory allocation function doesn't fail. Using OpenSSL in multiple modules does not cause such a failure. (I am the lead developer of libcurl.)
So, run your app with VERBOSE set to libcurl, or even strace to see which syscall that fails and it should give you more clues.
As the descibed in this answer, you might need to disable SSLv3 if you are on Ubuntu 16.04 like so
curl_easy_setopt(curl_, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2));
It was disabled on Ubuntu 16.04 for security reasons, see more here.