Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Avoid sqlite database lookup on EVERY https network request
Whenever a https network request is created, QgsAuthManager::sslCertCustomConfigByHost
is used to alter the ssl configuration according to config
stored within the sqlite authentication database. This results
in a database query being created for EVERY request, regardless
of whether a user actually has any ssl configuration set.

Instead, use a cache to avoid firing off this db query
for every request
  • Loading branch information
nyalldawson committed Jun 9, 2019
1 parent d106406 commit 2e0d67a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
46 changes: 43 additions & 3 deletions src/core/auth/qgsauthmanager.cpp
Expand Up @@ -1698,6 +1698,8 @@ bool QgsAuthManager::initSslCaches()
res = res && rebuildCertTrustCache();
res = res && rebuildTrustedCaCertsCache();
res = res && rebuildIgnoredSslErrorCache();
mCustomConfigByHostCache.clear();
mHasCheckedIfCustomConfigByHostExists = false;

QgsDebugMsg( QStringLiteral( "Init of SSL caches %1" ).arg( res ? "SUCCEEDED" : "FAILED" ) );
return res;
Expand Down Expand Up @@ -1994,6 +1996,8 @@ bool QgsAuthManager::storeSslCertCustomConfig( const QgsAuthConfigSslServer &con
.arg( config.sslHostPort().trimmed(), id ) );

updateIgnoredSslErrorsCacheFromConfig( config );
mHasCheckedIfCustomConfigByHostExists = false;
mCustomConfigByHostCache.clear();

return true;
}
Expand Down Expand Up @@ -2042,23 +2046,53 @@ const QgsAuthConfigSslServer QgsAuthManager::sslCertCustomConfig( const QString

const QgsAuthConfigSslServer QgsAuthManager::sslCertCustomConfigByHost( const QString &hostport )
{
QMutexLocker locker( mMutex );
QgsAuthConfigSslServer config;

if ( hostport.isEmpty() )
{
QgsDebugMsg( QStringLiteral( "Passed host:port is empty" ) );
return config;
}

QMutexLocker locker( mMutex );
if ( mHasCheckedIfCustomConfigByHostExists && !mHasCustomConfigByHost )
return config;
if ( mCustomConfigByHostCache.contains( hostport ) )
return mCustomConfigByHostCache.value( hostport );

QSqlQuery query( authDatabaseConnection() );

// first run -- see if we have ANY custom config by host. If not, we can skip all future checks for any host
if ( !mHasCheckedIfCustomConfigByHostExists )
{
mHasCheckedIfCustomConfigByHostExists = true;
query.prepare( QString( "SELECT count(*) FROM %1" ).arg( authDatabaseServersTable() ) );
if ( !authDbQuery( &query ) )
{
mHasCustomConfigByHost = false;
return config;
}
if ( query.isActive() && query.isSelect() && query.first() )
{
mHasCustomConfigByHost = query.value( 0 ).toInt() > 0;
if ( !mHasCustomConfigByHost )
return config;
}
else
{
mHasCustomConfigByHost = false;
return config;
}
}

query.prepare( QString( "SELECT id, host, cert, config FROM %1 "
"WHERE host = :host" ).arg( authDatabaseServersTable() ) );

query.bindValue( QStringLiteral( ":host" ), hostport.trimmed() );

if ( !authDbQuery( &query ) )
{
mCustomConfigByHostCache.insert( hostport, config );
return config;
}

if ( query.isActive() && query.isSelect() )
{
Expand All @@ -2075,9 +2109,12 @@ const QgsAuthConfigSslServer QgsAuthManager::sslCertCustomConfigByHost( const QS
emit messageOut( tr( "Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
.arg( hostport ), authManTag(), WARNING );
QgsAuthConfigSslServer emptyconfig;
mCustomConfigByHostCache.insert( hostport, emptyconfig );
return emptyconfig;
}
}

mCustomConfigByHostCache.insert( hostport, config );
return config;
}

Expand Down Expand Up @@ -2155,6 +2192,9 @@ bool QgsAuthManager::removeSslCertCustomConfig( const QString &id, const QString
return false;
}

mHasCheckedIfCustomConfigByHostExists = false;
mCustomConfigByHostCache.clear();

QSqlQuery query( authDatabaseConnection() );

query.prepare( QStringLiteral( "DELETE FROM %1 WHERE id = :id AND host = :host" ).arg( authDatabaseServersTable() ) );
Expand Down
4 changes: 4 additions & 0 deletions src/core/auth/qgsauthmanager.h
Expand Up @@ -874,6 +874,10 @@ class CORE_EXPORT QgsAuthManager : public QObject
QList<QSslCertificate> mTrustedCaCertsCache;
// cache of SSL errors to be ignored in network connections, per sha-hostport
QHash<QString, QSet<QSslError::SslError> > mIgnoredSslErrorsCache;

bool mHasCustomConfigByHost = false;
bool mHasCheckedIfCustomConfigByHostExists = false;
QMap< QString, QgsAuthConfigSslServer > mCustomConfigByHostCache;
#endif

//////////////////////////////////////////////////////////////////////////////
Expand Down

0 comments on commit 2e0d67a

Please sign in to comment.