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.
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
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)
In order to install Virtuoso on my MacOS X environment, i used the brew port, that is:
brew install virtuoso
By doing so, it automatically installed some ODBC/iODBC drivers, that could not be overwritte by any other unixodbc setup. In particular if I try to link such library:
$ brew link unixodbc
Linking /usr/local/Cellar/unixodbc/2.3.4...
Error: Could not symlink bin/isql
Target /usr/local/bin/isql
is a symlink belonging to virtuoso. You can unlink it:
brew unlink virtuoso
To force the link and overwrite all conflicting files:
brew link --overwrite unixodbc
To list all files that would be deleted:
brew link --overwrite --dry-run unixodbc
By the way, I do not want to unlink this version. So I tried to compile Redland from scratch and download it from GitHub. In particular, I used two possible configurations:
env PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --with-virtuoso --with-odbc=/usr/local/Cellar/virtuoso/7.2.4.2
env PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure --with-virtuoso --with-iodbc=/usr/local/Cellar/virtuoso/7.2.4.2
After adding rdf_hash_internal.h and rdf_heuristics.h in my project manually, everything just goes smoothly and everything gets both compiled and linked. In my C++ app, I'm trying to access the database with the following code:
world = librdf_new_world();
librdf_world_open(world);
storage = librdf_new_storage(world,"virtuoso",graphName.c_str(),"dsn='Local Virtuoso',user='dba',password='dba'");
model = librdf_new_model(world,storage,NULL);
context_node = librdf_new_node_from_uri_string(world,(const unsigned char*)defaultContext.c_str());
/* librdf_model_transaction_commit(this->super->model) */
librdf_model_size(super->model)
If either I disable the transaction or not, anyway I got the following error at line 941 of "rdf_storage_virtuoso.c":
rc = SQLDriverConnect(connection->hdbc, 0,(UCHAR *) context->conn_str,
SQL_NTS, context->outdsn,
LIBRDF_VIRTUOSO_CONTEXT_DSN_SIZE,
&buflen, SQL_DRIVER_COMPLETE);
Hence, I suppose there is a connection error at the ODBC/iODBC level. By the way, I could connect to virtuoso with the following command:
$ isql localhost:1111 dba dba
Connected to OpenLink Virtuoso
Driver: 07.20.3217 OpenLink Virtuoso ODBC Driver
OpenLink Interactive SQL (Virtuoso), version 0.9849b.
Type HELP; for help and EXIT; to exit.
SQL>
Is there any way to connect the Redland library with ODBC library by Virtuoso? Thanks in advance.
All those troubles were due to a configuration issue that AFIK was described in no guide (Correct me if I'm wrong, I'd like to find more details on both Virtuoso and Redland/librdf). Hereby, as I told in the comments, the problem was in ODBC, but the reason was that there is no mention in no Virtuoso guide how to configure their driver. This is the way to go:
/Library/ODBC/odbc.ini
[ODBC Data Sources]
VOS = virtuoso-odbc
[VOS]
Driver = /usr/local/Cellar/virtuoso/7.2.4.2/lib/virtodbc.so
Description = Virtuoso Open-Source Edition
Address = localhost:1111
UserName = dba
User = dba
/Library/ODBC/odbcinst.ini
[ODBC Drivers]
virtuoso-odbc = Installed
[virtuoso-odbc]
Driver = /usr/local/Cellar/virtuoso/7.2.4.2/lib/virtodbc.so
Consequently, even the configuration parameters required to access through Redland has to change.
storage=librdf_new_storage(world, "virtuoso","db1","dsn='VOS',user='dba',password='dba'");
Where VOS is the configuration definition within ODBC.
Moreover, the specific ContextNode specifies which is the Named Graph to be used.
I don't know much about brew, but is it possible to modify its package-definition so that it renames our isql binary, e.g. to isql-vt instead?
We already do this in our Debian/Ubuntu packaging by calling
./configure --program-transform-name='s/isql$$/isql-vt/;s/isqlw/isqlw-vt/'
See https://github.com/openlink/virtuoso-opensource/blob/develop/7/debian/rules#L31
I don't see the error you get from line 941, but two things concerning ODBC connections:
1) your --with-iodbc= must point to a copy of iodbc, not to virtuoso (you can get it from http://iodbc.org/ or your distribution probably has a package e.g. libiodbc2-dev on debian/ubuntu)
2) Virtuoso's isql tests a direct connection to virtuoso; to check that the driver manager is configured properly, use iodbctest (or unixODBC's isql that caused the conflict above in the first place).
First thing, iODBC is the ODBC driver manager Apple builds into OS X, and users are usually better off sticking with it -- though we (OpenLink Software, maintainers of iODBC) do recommend updating to the curent version, as Apple is typically many updates behind.
Related to that, Apple doesn't bundle the full iODBC SDK. They leave out the Frameworks, among other things.
Generally speaking, UnixODBC doesn't fully integrate with GUI-space OS X apps nor drivers, and there are various other issues that surface over time. Current iODBC doesn't care whether you're working in GUI or command-line, Carbon or Cocoa, 32-bit or 64-bit... It all just works (and if it doesn't work, we want to know, so we can fix it).
MacPorts and other packagers I've used have had ways to switch between UnixODBC and iODBC (e.g., variants); I can't quickly find such for Homebrew, but maybe you can?
I am attempting to get MySQL++ to work correctly on Debian 6 with SSL support. I have tested everything on Windows 7 and it works great. Everything is encrypted. I am having a little bit of trouble porting it to Debian though.
This is my error:
terminate called after throwing an instance of 'mysqlpp::BadOption'
what(): Option not supported by database driver v5.1.49
This is my call for setting the certificate files:
connection->set_option(new mysqlpp::SslOption("/root/certs/client-key.pem", "/root/certs/client-cert.pem", "/root/certs/ca-cert.pem", "/root/certs", "DHE-RSA-AES256-SHA"));
I have noticed that when configuring MySQL++ it looks for mysql_ssl_set() in libmysqlclient. It does not find that function.
checking for mysql_ssl_set in -l... no
This bug is fixed in MySQL++ 3.2.0, released today.
In older versions, there's a bug in the test for mysql_ssl_set(). If you cannot use the current version but can patch your version's source code, this will fix it:
Index: config/mysql_ssl.m4
===================================================================
--- config/mysql_ssl.m4 (revision 2696)
+++ config/mysql_ssl.m4 (working copy)
## -10,7 +10,7 ##
#
# Check for mysql_ssl_set() in libmysqlclient(_r)
#
- AC_CHECK_LIB($MYSQL_C_LIB, mysql_ssl_set, [
+ AC_CHECK_LIB($MYSQL_C_LIB_NAME, mysql_ssl_set, [
AC_DEFINE(HAVE_MYSQL_SSL_SET,, Define if your MySQL library has SSL functions)
]) dnl AC_CHECK_LIB(mysqlclient, mysql_ssl_set)
]) dnl MYSQL_WITH_SSL
You will then need to re-bootstrap the source tree, and rebuild.