Added SSL support for MySQL database connections
Addition of new options SSL_KEY, SSL_CERT, SSL_CA, SSL_CAPATH and SSL_CIPHER to allow SSL-encrypted connections to MySQL databases. When needed, these options must be specified in the function call QSqlDatabase::setConnectOptions() before the call to QSqlDatabase::open(). SSL_KEY = the path name to the key file SSL_CERT = the path name to the certificate file SSL_CA = the path name to the certificate authority file SSL_CAPATH = the path name to a directory that contains trusted SSL CA certificates in PEM format. SSL_CIPHER = a list of permissible ciphers to use for SSL encryption. These options replace CLIENT_SSL (which should not be used any more). Example: db.setConnectOptions("SSL_KEY=client-key.pem;" \ "SSL_CERT=client-cert.pem;" \ "SSL_CA=server-ca.pem"); [ChangeLog][QtSql] SSL support for MySQL database connections has been added. Option CLIENT_SSL replaced by SSL_KEY, SSL_CERT, SSL_CA, SSL_CAPATH and SSL_CIPHER, so that the keys, certificates and cipher can be specified. Task-number: QtBUG-3500 Change-Id: I8197234b169a818658678d6fcc953c90e83db23e Reviewed-by: Mark Brand <mabrand@mabrand.nl>
This commit is contained in:
parent
bca41b1b85
commit
28ceb2ea5e
@ -80,7 +80,7 @@ if (db.open()) {
|
|||||||
//! [4]
|
//! [4]
|
||||||
...
|
...
|
||||||
// MySQL connection
|
// MySQL connection
|
||||||
db.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1"); // use an SSL connection to the server
|
db.setConnectOptions("SSL_KEY=client-key.pem;SSL_CERT=client-cert.pem;SSL_CA=ca-cert.pem;CLIENT_IGNORE_SPACE=1"); // use an SSL connection to the server
|
||||||
if (!db.open()) {
|
if (!db.open()) {
|
||||||
db.setConnectOptions(); // clears the connect option string
|
db.setConnectOptions(); // clears the connect option string
|
||||||
...
|
...
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include <qstringlist.h>
|
#include <qstringlist.h>
|
||||||
#include <qtextcodec.h>
|
#include <qtextcodec.h>
|
||||||
#include <qvector.h>
|
#include <qvector.h>
|
||||||
|
#include <qfile.h>
|
||||||
|
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
|
|
||||||
@ -1211,7 +1212,7 @@ static void setOptionFlag(uint &optionFlags, const QString &opt)
|
|||||||
else if (opt == QLatin1String("CLIENT_ODBC"))
|
else if (opt == QLatin1String("CLIENT_ODBC"))
|
||||||
optionFlags |= CLIENT_ODBC;
|
optionFlags |= CLIENT_ODBC;
|
||||||
else if (opt == QLatin1String("CLIENT_SSL"))
|
else if (opt == QLatin1String("CLIENT_SSL"))
|
||||||
optionFlags |= CLIENT_SSL;
|
qWarning("QMYSQLDriver: SSL_KEY, SSL_CERT and SSL_CA should be used instead of CLIENT_SSL.");
|
||||||
else
|
else
|
||||||
qWarning("QMYSQLDriver::open: Unknown connect option '%s'", opt.toLocal8Bit().constData());
|
qWarning("QMYSQLDriver::open: Unknown connect option '%s'", opt.toLocal8Bit().constData());
|
||||||
}
|
}
|
||||||
@ -1235,6 +1236,11 @@ bool QMYSQLDriver::open(const QString& db,
|
|||||||
unsigned int optionFlags = Q_CLIENT_MULTI_STATEMENTS;
|
unsigned int optionFlags = Q_CLIENT_MULTI_STATEMENTS;
|
||||||
const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
|
const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
|
||||||
QString unixSocket;
|
QString unixSocket;
|
||||||
|
QString sslCert;
|
||||||
|
QString sslCA;
|
||||||
|
QString sslKey;
|
||||||
|
QString sslCAPath;
|
||||||
|
QString sslCipher;
|
||||||
#if MYSQL_VERSION_ID >= 50000
|
#if MYSQL_VERSION_ID >= 50000
|
||||||
my_bool reconnect=false;
|
my_bool reconnect=false;
|
||||||
uint connectTimeout = 0;
|
uint connectTimeout = 0;
|
||||||
@ -1263,6 +1269,16 @@ bool QMYSQLDriver::open(const QString& db,
|
|||||||
writeTimeout = val.toInt();
|
writeTimeout = val.toInt();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
else if (opt == QLatin1String("SSL_KEY"))
|
||||||
|
sslKey = val;
|
||||||
|
else if (opt == QLatin1String("SSL_CERT"))
|
||||||
|
sslCert = val;
|
||||||
|
else if (opt == QLatin1String("SSL_CA"))
|
||||||
|
sslCA = val;
|
||||||
|
else if (opt == QLatin1String("SSL_CAPATH"))
|
||||||
|
sslCAPath = val;
|
||||||
|
else if (opt == QLatin1String("SSL_CIPHER"))
|
||||||
|
sslCipher = val;
|
||||||
else if (val == QLatin1String("TRUE") || val == QLatin1String("1"))
|
else if (val == QLatin1String("TRUE") || val == QLatin1String("1"))
|
||||||
setOptionFlag(optionFlags, tmp.left(idx).simplified());
|
setOptionFlag(optionFlags, tmp.left(idx).simplified());
|
||||||
else
|
else
|
||||||
@ -1273,39 +1289,60 @@ bool QMYSQLDriver::open(const QString& db,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((d->mysql = mysql_init((MYSQL*) 0))) {
|
if (!(d->mysql = mysql_init((MYSQL*) 0))) {
|
||||||
|
setLastError(qMakeError(tr("Unable to allocate a MYSQL object"),
|
||||||
|
QSqlError::ConnectionError, d));
|
||||||
|
setOpenError(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sslKey.isNull() || !sslCert.isNull() || !sslCA.isNull() ||
|
||||||
|
!sslCAPath.isNull() || !sslCipher.isNull()) {
|
||||||
|
mysql_ssl_set(d->mysql,
|
||||||
|
sslKey.isNull() ? static_cast<const char *>(0)
|
||||||
|
: QFile::encodeName(sslKey).constData(),
|
||||||
|
sslCert.isNull() ? static_cast<const char *>(0)
|
||||||
|
: QFile::encodeName(sslCert).constData(),
|
||||||
|
sslCA.isNull() ? static_cast<const char *>(0)
|
||||||
|
: QFile::encodeName(sslCA).constData(),
|
||||||
|
sslCAPath.isNull() ? static_cast<const char *>(0)
|
||||||
|
: QFile::encodeName(sslCAPath).constData(),
|
||||||
|
sslCipher.isNull() ? static_cast<const char *>(0)
|
||||||
|
: sslCipher.toLocal8Bit().constData());
|
||||||
|
}
|
||||||
|
|
||||||
#if MYSQL_VERSION_ID >= 50000
|
#if MYSQL_VERSION_ID >= 50000
|
||||||
if (connectTimeout != 0)
|
if (connectTimeout != 0)
|
||||||
mysql_options(d->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &connectTimeout);
|
mysql_options(d->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &connectTimeout);
|
||||||
if (readTimeout != 0)
|
if (readTimeout != 0)
|
||||||
mysql_options(d->mysql, MYSQL_OPT_READ_TIMEOUT, &readTimeout);
|
mysql_options(d->mysql, MYSQL_OPT_READ_TIMEOUT, &readTimeout);
|
||||||
if (writeTimeout != 0)
|
if (writeTimeout != 0)
|
||||||
mysql_options(d->mysql, MYSQL_OPT_WRITE_TIMEOUT, &writeTimeout);
|
mysql_options(d->mysql, MYSQL_OPT_WRITE_TIMEOUT, &writeTimeout);
|
||||||
#endif
|
|
||||||
if (mysql_real_connect(d->mysql,
|
|
||||||
host.isNull() ? static_cast<const char *>(0)
|
|
||||||
: host.toLocal8Bit().constData(),
|
|
||||||
user.isNull() ? static_cast<const char *>(0)
|
|
||||||
: user.toLocal8Bit().constData(),
|
|
||||||
password.isNull() ? static_cast<const char *>(0)
|
|
||||||
: password.toLocal8Bit().constData(),
|
|
||||||
db.isNull() ? static_cast<const char *>(0)
|
|
||||||
: db.toLocal8Bit().constData(),
|
|
||||||
(port > -1) ? port : 0,
|
|
||||||
unixSocket.isNull() ? static_cast<const char *>(0)
|
|
||||||
: unixSocket.toLocal8Bit().constData(),
|
|
||||||
optionFlags)) {
|
|
||||||
if (!db.isEmpty() && mysql_select_db(d->mysql, db.toLocal8Bit().constData())) {
|
|
||||||
setLastError(qMakeError(tr("Unable to open database '%1'").arg(db), QSqlError::ConnectionError, d));
|
|
||||||
mysql_close(d->mysql);
|
|
||||||
setOpenError(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#if MYSQL_VERSION_ID >= 50000
|
|
||||||
if (reconnect)
|
|
||||||
mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect);
|
|
||||||
#endif
|
#endif
|
||||||
|
if (mysql_real_connect(d->mysql,
|
||||||
|
host.isNull() ? static_cast<const char *>(0)
|
||||||
|
: host.toLocal8Bit().constData(),
|
||||||
|
user.isNull() ? static_cast<const char *>(0)
|
||||||
|
: user.toLocal8Bit().constData(),
|
||||||
|
password.isNull() ? static_cast<const char *>(0)
|
||||||
|
: password.toLocal8Bit().constData(),
|
||||||
|
db.isNull() ? static_cast<const char *>(0)
|
||||||
|
: db.toLocal8Bit().constData(),
|
||||||
|
(port > -1) ? port : 0,
|
||||||
|
unixSocket.isNull() ? static_cast<const char *>(0)
|
||||||
|
: unixSocket.toLocal8Bit().constData(),
|
||||||
|
optionFlags))
|
||||||
|
{
|
||||||
|
if (!db.isEmpty() && mysql_select_db(d->mysql, db.toLocal8Bit().constData())) {
|
||||||
|
setLastError(qMakeError(tr("Unable to open database '%1'").arg(db), QSqlError::ConnectionError, d));
|
||||||
|
mysql_close(d->mysql);
|
||||||
|
setOpenError(true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
#if MYSQL_VERSION_ID >= 50000
|
||||||
|
if (reconnect)
|
||||||
|
mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
setLastError(qMakeError(tr("Unable to connect"),
|
setLastError(qMakeError(tr("Unable to connect"),
|
||||||
QSqlError::ConnectionError, d));
|
QSqlError::ConnectionError, d));
|
||||||
|
@ -1218,7 +1218,6 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const
|
|||||||
\li CLIENT_COMPRESS
|
\li CLIENT_COMPRESS
|
||||||
\li CLIENT_FOUND_ROWS
|
\li CLIENT_FOUND_ROWS
|
||||||
\li CLIENT_IGNORE_SPACE
|
\li CLIENT_IGNORE_SPACE
|
||||||
\li CLIENT_SSL
|
|
||||||
\li CLIENT_ODBC
|
\li CLIENT_ODBC
|
||||||
\li CLIENT_NO_SCHEMA
|
\li CLIENT_NO_SCHEMA
|
||||||
\li CLIENT_INTERACTIVE
|
\li CLIENT_INTERACTIVE
|
||||||
@ -1227,6 +1226,11 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const
|
|||||||
\li MYSQL_OPT_CONNECT_TIMEOUT
|
\li MYSQL_OPT_CONNECT_TIMEOUT
|
||||||
\li MYSQL_OPT_READ_TIMEOUT
|
\li MYSQL_OPT_READ_TIMEOUT
|
||||||
\li MYSQL_OPT_WRITE_TIMEOUT
|
\li MYSQL_OPT_WRITE_TIMEOUT
|
||||||
|
\li SSL_KEY
|
||||||
|
\li SSL_CERT
|
||||||
|
\li SSL_CA
|
||||||
|
\li SSL_CAPATH
|
||||||
|
\li SSL_CIPHER
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\li
|
\li
|
||||||
|
@ -261,8 +261,8 @@ public:
|
|||||||
|
|
||||||
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org" );
|
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org" );
|
||||||
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org", 3307 );
|
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org", 3307 );
|
||||||
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org", 3308, "CLIENT_COMPRESS=1;CLIENT_SSL=1" ); // MySQL 4.1.1
|
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org", 3308, "CLIENT_COMPRESS=1" ); // MySQL 4.1.1
|
||||||
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org", 3309, "CLIENT_COMPRESS=1;CLIENT_SSL=1" ); // MySQL 5.0.18 Linux
|
// addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.qt-project.org", 3309, "CLIENT_COMPRESS=1" ); // MySQL 5.0.18 Linux
|
||||||
// addDb( "QMYSQL3", "testdb", "troll", "trond", "silence.qt-project.org" ); // MySQL 5.1.36 Windows
|
// addDb( "QMYSQL3", "testdb", "troll", "trond", "silence.qt-project.org" ); // MySQL 5.1.36 Windows
|
||||||
|
|
||||||
// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "bq-mysql41.qt-project.org" ); // MySQL 4.1.22-2.el4 linux
|
// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "bq-mysql41.qt-project.org" ); // MySQL 4.1.22-2.el4 linux
|
||||||
|
Loading…
x
Reference in New Issue
Block a user