Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt MySQL connect to Azure via SSL

I am trying to connect to a Azure MySQL 5.7 with SSL, but I have run into an error that I cannot seem to resolve.

Connecting works fine for

  • mysql.exe
  • MySQL Workbench 8.0

Connecting doesn't work for

  • Qt
  • MySQL Connector/C 8.0.18

I call mysql.exe with the following working command

mysql.exe -h server.mysql.database.azure.com -u user@server -p --ssl

This connects and doesn't present any issues. MySQL Workbench 8.0 works fine too.

But then using the Qt MySQL plugin to connect yields this error.

SSL connection error: socket layer receive error

This is the Qt code I'm using to connect

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");

db.setHostName("server.mysql.database.azure.com");
db.setPort(3306);
db.setDatabaseName("databasename");
db.setUserName("user@server");
db.setPassword("password");
db.setConnectOptions("SSL_CA=C:/Users/User/Downloads/BaltimoreCyberTrustRoot.crt.pem");
if (!db.open()) {
    std::cout << db.lastError().text().toStdString() << "\n";   
}

Next I tried using the MySQL Connector/C (which Qt uses underneath) to directly connect to the Azure database.

MYSQL* mysql = mysql_init(nullptr);

char* t = "C:/Users/User/Downloads/BaltimoreCyberTrustRoot.crt.pem";

mysql_ssl_set(mysql, nullptr, nullptr, t, nullptr, nullptr);

if (!mysql_real_connect(mysql, "server.mysql.database.azure.com", "user@server", "password", "databasename", 3306, nullptr, 0)) {
    fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(mysql));
}
mysql_close(mysql);

Which both produce the socket layer error.

Disabling SSL in Azure allows me to connect with both Qt and MySQL Connector/C. This means that the connection data (username, password, hostname) are correct, but that there is possibly an issue with setting SSL options.

Qt version 5.13.1
MySQL Connector/C 8.0.18
MySQL DB 5.7

like image 760
Eejin Avatar asked Oct 19 '19 14:10

Eejin


1 Answers

I don't have any exposure to Qt, but I do MySQL and SSL, so after reading your question was intrigued.

I'm afraid to tell you that it would appear Qt have inadvertently coded out the transport security capabilities with this update:

https://codereview.qt-project.org/c/qt/qtbase/+/96849/11/src/sql/drivers/mysql/qsql_mysql.cpp

I say inadvertently because I can't believe that they intended on replacing CLIENT_SSL with client certificate authentication. CLIENT_SSL is still a valid option for the mysql_real_connect interface, but options validation is ignoring it. Without reaching out I can only assume that a developer was tasked with updating the code to support client certificates and confused client certs with transport encryption, swapping the functionality instead of adding to it.

This breaking change was introduced in version 5.5. If you're feeling daring enough, you could pull the codebase and change:

    else if (opt == QLatin1String("CLIENT_SSL"))
        qWarning("QMYSQLDriver: SSL_KEY, SSL_CERT and SSL_CA should be used instead of CLIENT_SSL.");

To:

    else if (opt == QLatin1String("CLIENT_SSL"))
        optionFlags |= CLIENT_SSL;

Compile & much luck...or you have these options.

  1. Downgrade to Qt 5.2 (Yeah I know but...)
  2. If you have the CA private key, generate a client certificate signed by the CA and add the SSL_CERT and SSL_KEY connection options and hope that this is sufficient (I haven't looked deeper in to the code)
like image 122
Architect Jamie Avatar answered Oct 08 '22 04:10

Architect Jamie