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]
|
||||
...
|
||||
// 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()) {
|
||||
db.setConnectOptions(); // clears the connect option string
|
||||
...
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <qstringlist.h>
|
||||
#include <qtextcodec.h>
|
||||
#include <qvector.h>
|
||||
#include <qfile.h>
|
||||
|
||||
#include <qdebug.h>
|
||||
|
||||
@ -1211,7 +1212,7 @@ static void setOptionFlag(uint &optionFlags, const QString &opt)
|
||||
else if (opt == QLatin1String("CLIENT_ODBC"))
|
||||
optionFlags |= CLIENT_ODBC;
|
||||
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
|
||||
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;
|
||||
const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
|
||||
QString unixSocket;
|
||||
QString sslCert;
|
||||
QString sslCA;
|
||||
QString sslKey;
|
||||
QString sslCAPath;
|
||||
QString sslCipher;
|
||||
#if MYSQL_VERSION_ID >= 50000
|
||||
my_bool reconnect=false;
|
||||
uint connectTimeout = 0;
|
||||
@ -1263,6 +1269,16 @@ bool QMYSQLDriver::open(const QString& db,
|
||||
writeTimeout = val.toInt();
|
||||
}
|
||||
#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"))
|
||||
setOptionFlag(optionFlags, tmp.left(idx).simplified());
|
||||
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 (connectTimeout != 0)
|
||||
mysql_options(d->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &connectTimeout);
|
||||
if (readTimeout != 0)
|
||||
mysql_options(d->mysql, MYSQL_OPT_READ_TIMEOUT, &readTimeout);
|
||||
if (writeTimeout != 0)
|
||||
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);
|
||||
if (connectTimeout != 0)
|
||||
mysql_options(d->mysql, MYSQL_OPT_CONNECT_TIMEOUT, &connectTimeout);
|
||||
if (readTimeout != 0)
|
||||
mysql_options(d->mysql, MYSQL_OPT_READ_TIMEOUT, &readTimeout);
|
||||
if (writeTimeout != 0)
|
||||
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
|
||||
} else {
|
||||
setLastError(qMakeError(tr("Unable to connect"),
|
||||
QSqlError::ConnectionError, d));
|
||||
|
@ -1218,7 +1218,6 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const
|
||||
\li CLIENT_COMPRESS
|
||||
\li CLIENT_FOUND_ROWS
|
||||
\li CLIENT_IGNORE_SPACE
|
||||
\li CLIENT_SSL
|
||||
\li CLIENT_ODBC
|
||||
\li CLIENT_NO_SCHEMA
|
||||
\li CLIENT_INTERACTIVE
|
||||
@ -1227,6 +1226,11 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const
|
||||
\li MYSQL_OPT_CONNECT_TIMEOUT
|
||||
\li MYSQL_OPT_READ_TIMEOUT
|
||||
\li MYSQL_OPT_WRITE_TIMEOUT
|
||||
\li SSL_KEY
|
||||
\li SSL_CERT
|
||||
\li SSL_CA
|
||||
\li SSL_CAPATH
|
||||
\li SSL_CIPHER
|
||||
\endlist
|
||||
|
||||
\li
|
||||
|
@ -261,8 +261,8 @@ public:
|
||||
|
||||
// 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", 3308, "CLIENT_COMPRESS=1;CLIENT_SSL=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", 3308, "CLIENT_COMPRESS=1" ); // MySQL 4.1.1
|
||||
// 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", "testuser", "Ee4Gabf6_", "bq-mysql41.qt-project.org" ); // MySQL 4.1.22-2.el4 linux
|
||||
|
Loading…
Reference in New Issue
Block a user