23 #include <QMutexLocker>
26 #include <QSqlDatabase>
29 #include <QTextStream>
35 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
36 #include <QRandomGenerator>
42 #include <QSslConfiguration>
63 const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral(
"auth_configs" );
64 const QString QgsAuthManager::AUTH_PASS_TABLE = QStringLiteral(
"auth_pass" );
65 const QString QgsAuthManager::AUTH_SETTINGS_TABLE = QStringLiteral(
"auth_settings" );
66 const QString QgsAuthManager::AUTH_IDENTITIES_TABLE = QStringLiteral(
"auth_identities" );
67 const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral(
"auth_servers" );
68 const QString QgsAuthManager::AUTH_AUTHORITIES_TABLE = QStringLiteral(
"auth_authorities" );
69 const QString QgsAuthManager::AUTH_TRUST_TABLE = QStringLiteral(
"auth_trust" );
71 const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral(
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
74 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME(
"QGIS-Master-Password" );
75 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME(
"QGIS" );
81 #elif defined(Q_OS_WIN)
83 #elif defined(Q_OS_LINUX)
92 QMutexLocker locker( &sMutex );
103 mMutex.reset(
new QMutex( QMutex::Recursive ) );
104 mMasterPasswordMutex.reset(
new QMutex( QMutex::Recursive ) );
106 this, &QgsAuthManager::writeToConsole );
117 QMutexLocker locker( mMutex.get() );
122 const QString connectionName = QStringLiteral(
"authentication.configs:0x%1" ).arg(
reinterpret_cast<quintptr
>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char(
'0' ) );
123 QgsDebugMsgLevel( QStringLiteral(
"Using auth db connection name: %1 " ).arg( connectionName ), 2 );
124 if ( !QSqlDatabase::contains( connectionName ) )
126 QgsDebugMsgLevel( QStringLiteral(
"No existing connection, creating a new one" ), 2 );
127 authdb = QSqlDatabase::addDatabase( QStringLiteral(
"QSQLITE" ), connectionName );
130 if ( QThread::currentThread() != qApp->thread() )
132 QgsDebugMsgLevel( QStringLiteral(
"Scheduled auth db remove on thread close" ), 2 );
142 QMetaObject::Connection connection = connect( QThread::currentThread(), &QThread::finished, QThread::currentThread(), [connectionName,
this ]
144 QMutexLocker locker( mMutex.get() );
145 QSqlDatabase::removeDatabase( connectionName );
146 mConnectedThreads.remove( QThread::currentThread() );
147 }, Qt::DirectConnection );
149 mConnectedThreads.insert( QThread::currentThread(), connection );
155 authdb = QSqlDatabase::database( connectionName );
159 if ( !authdb.isOpen() )
161 if ( !authdb.open() )
163 const char *err = QT_TR_NOOP(
"Opening of authentication db FAILED" );
181 mQcaInitializer = qgis::make_unique<QCA::Initializer>( QCA::Practical, 256 );
184 QCA::scanForPlugins();
186 QgsDebugMsgLevel( QStringLiteral(
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ), 2 );
187 QStringList capabilities;
189 capabilities = QCA::supportedFeatures();
190 QgsDebugMsgLevel( QStringLiteral(
"QCA supports: %1" ).arg( capabilities.join(
"," ) ), 2 );
193 if ( !QCA::isSupported(
"cert", QStringLiteral(
"qca-ossl" ) ) )
195 mAuthDisabled =
true;
196 mAuthDisabledMessage = tr(
"QCA's OpenSSL plugin (qca-ossl) is missing" );
200 QgsDebugMsgLevel( QStringLiteral(
"Prioritizing qca-ossl over all other QCA providers..." ), 2 );
201 const QCA::ProviderList provds = QCA::providers();
203 for ( QCA::Provider *p : provds )
205 QString pn = p->name();
207 if ( pn != QLatin1String(
"qca-ossl" ) )
209 pr = QCA::providerPriority( pn ) + 1;
211 QCA::setProviderPriority( pn, pr );
212 prlist << QStringLiteral(
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
214 QgsDebugMsgLevel( QStringLiteral(
"QCA provider priorities: %1" ).arg( prlist.join(
", " ) ), 2 );
221 QgsDebugMsgLevel( QStringLiteral(
"Authentication methods found: %1" ).arg( methods.join(
", " ) ), 2 );
223 if ( methods.isEmpty() )
225 mAuthDisabled =
true;
226 mAuthDisabledMessage = tr(
"No authentication method plugins found" );
232 mAuthDisabled =
true;
233 mAuthDisabledMessage = tr(
"No authentication method plugins could be loaded" );
237 mAuthDbPath = QDir::cleanPath( authDatabasePath );
241 QFileInfo dbdirinfo( dbinfo.path() );
242 QgsDebugMsgLevel( QStringLiteral(
"Auth db directory path: %1" ).arg( dbdirinfo.filePath() ), 2 );
244 if ( !dbdirinfo.exists() )
246 QgsDebugMsgLevel( QStringLiteral(
"Auth db directory path does not exist, making path: %1" ).arg( dbdirinfo.filePath() ), 2 );
247 if ( !QDir().mkpath( dbdirinfo.filePath() ) )
249 const char *err = QT_TR_NOOP(
"Auth db directory path could not be created" );
256 if ( dbinfo.exists() )
258 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
260 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
265 if ( dbinfo.size() > 0 )
269 if ( !createCertTables() )
279 const char *passenv =
"QGIS_AUTH_PASSWORD_FILE";
282 QString passpath( getenv( passenv ) );
291 QFile passfile( passpath );
292 if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
294 QTextStream passin( &passfile );
295 while ( !passin.atEnd() )
297 masterpass = passin.readLine();
302 if ( !masterpass.isEmpty() )
306 QgsDebugMsgLevel( QStringLiteral(
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" ), 2 );
310 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
316 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
326 QgsDebugMsgLevel( QStringLiteral(
"Auth db does not exist: creating through QSqlDatabase initial connection" ), 2 );
328 if ( !createConfigTables() )
331 if ( !createCertTables() )
342 bool QgsAuthManager::createConfigTables()
344 QMutexLocker locker( mMutex.get() );
348 const char *err = QT_TR_NOOP(
"Auth db could not be created and opened" );
359 qstr = QStringLiteral(
"CREATE TABLE %1 (\n"
360 " 'salt' TEXT NOT NULL,\n"
361 " 'civ' TEXT NOT NULL\n"
362 ", 'hash' TEXT NOT NULL);" ).arg( authDbPassTable() );
363 query.prepare( qstr );
364 if ( !authDbQuery( &query ) )
368 qstr = QStringLiteral(
"CREATE TABLE %1 (\n"
369 " 'id' TEXT NOT NULL,\n"
370 " 'name' TEXT NOT NULL,\n"
372 " 'type' TEXT NOT NULL,\n"
373 " 'version' INTEGER NOT NULL\n"
375 query.prepare( qstr );
376 if ( !authDbQuery( &query ) )
381 query.prepare( qstr );
382 if ( !authDbQuery( &query ) )
387 query.prepare( qstr );
388 if ( !authDbQuery( &query ) )
395 bool QgsAuthManager::createCertTables()
397 QMutexLocker locker( mMutex.get() );
406 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
407 " 'setting' TEXT NOT NULL\n"
408 ", 'value' TEXT);" ).arg( authDbSettingsTable() );
409 query.prepare( qstr );
410 if ( !authDbQuery( &query ) )
415 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
416 " 'id' TEXT NOT NULL,\n"
417 " 'key' TEXT NOT NULL\n"
418 ", 'cert' TEXT NOT NULL);" ).arg( authDbIdentitiesTable() );
419 query.prepare( qstr );
420 if ( !authDbQuery( &query ) )
424 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbIdentitiesTable() );
425 query.prepare( qstr );
426 if ( !authDbQuery( &query ) )
431 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
432 " 'id' TEXT NOT NULL,\n"
433 " 'host' TEXT NOT NULL,\n"
436 query.prepare( qstr );
437 if ( !authDbQuery( &query ) )
441 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'host_index' on %1 (host ASC);" ).arg(
authDatabaseServersTable() );
442 query.prepare( qstr );
443 if ( !authDbQuery( &query ) )
448 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
449 " 'id' TEXT NOT NULL\n"
450 ", 'cert' TEXT NOT NULL);" ).arg( authDbAuthoritiesTable() );
451 query.prepare( qstr );
452 if ( !authDbQuery( &query ) )
456 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbAuthoritiesTable() );
457 query.prepare( qstr );
458 if ( !authDbQuery( &query ) )
462 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
463 " 'id' TEXT NOT NULL\n"
464 ", 'policy' TEXT NOT NULL);" ).arg( authDbTrustTable() );
465 query.prepare( qstr );
466 if ( !authDbQuery( &query ) )
470 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbTrustTable() );
471 query.prepare( qstr );
472 if ( !authDbQuery( &query ) )
483 QgsDebugMsg( QStringLiteral(
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" ) );
485 return mAuthDisabled;
490 return tr(
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
495 QMutexLocker locker( mMasterPasswordMutex.get() );
499 if ( mScheduledDbErase )
502 if ( mMasterPass.isEmpty() )
504 QgsDebugMsg( QStringLiteral(
"Master password is not yet set by user" ) );
505 if ( !masterPasswordInput() )
507 QgsDebugMsg( QStringLiteral(
"Master password input canceled by user" ) );
513 QgsDebugMsg( QStringLiteral(
"Master password is set" ) );
521 QgsDebugMsg( QStringLiteral(
"Master password is set and verified" ) );
527 QMutexLocker locker( mMutex.get() );
531 if ( mScheduledDbErase )
535 QString prevpass = QString( mMasterPass );
539 mMasterPass = prevpass;
540 const char *err = QT_TR_NOOP(
"Master password set: FAILED to verify, reset to previous" );
546 QgsDebugMsg( QStringLiteral(
"Master password set: SUCCESS%1" ).arg( verify ?
" and verified" :
"" ) );
556 if ( !masterPasswordRowsInDb( &rows ) )
558 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
566 QgsDebugMsg( QStringLiteral(
"Master password: %1 rows in database" ).arg( rows ) );
570 const char *err = QT_TR_NOOP(
"Master password: FAILED to find just one master password record in database" );
577 else if ( rows == 1 )
579 if ( !masterPasswordCheckAgainstDb( compare ) )
581 if ( compare.isNull() )
583 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
592 if ( mPassTries >= 5 )
594 mAuthDisabled =
true;
595 const char *err = QT_TR_NOOP(
"Master password: failed 5 times authentication system DISABLED" );
603 QgsDebugMsg( QStringLiteral(
"Master password: verified against hash in database" ) );
604 if ( compare.isNull() )
608 else if ( compare.isNull() )
610 if ( !masterPasswordStoreInDb() )
612 const char *err = QT_TR_NOOP(
"Master password: hash FAILED to be stored in database" );
621 QgsDebugMsg( QStringLiteral(
"Master password: hash stored in database" ) );
624 if ( !masterPasswordCheckAgainstDb() )
626 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
636 QgsDebugMsg( QStringLiteral(
"Master password: verified against hash in database" ) );
646 return !mMasterPass.isEmpty();
651 return mMasterPass == pass;
655 bool keepbackup, QString *backuppath )
669 QgsDebugMsg( QStringLiteral(
"Master password reset: backed up current database" ) );
675 QString prevpass = QString( mMasterPass );
676 QString prevciv = QString( masterPasswordCiv() );
682 if ( ok && !masterPasswordClearDb() )
685 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not clear current password from database" );
691 QgsDebugMsg( QStringLiteral(
"Master password reset: cleared current password from database" ) );
698 if ( ok && !masterPasswordStoreInDb() )
701 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not store new password in database" );
707 QgsDebugMsg( QStringLiteral(
"Master password reset: stored new password in database" ) );
714 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify new password in database" );
720 if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
723 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt configs in database" );
729 QgsDebugMsg( QStringLiteral(
"Master password reset: re-encrypted configs in database" ) );
733 if ( ok && !verifyPasswordCanDecryptConfigs() )
736 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
741 if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
744 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt settings in database" );
749 if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
752 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt identities in database" );
762 QString errdbbackup( dbbackup );
763 errdbbackup.replace( QLatin1String(
".db" ), QLatin1String(
"_ERROR.db" ) );
765 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
769 mMasterPass = prevpass;
771 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: reinstated previous password and database" ) );
775 *backuppath = errdbbackup;
781 if ( !keepbackup && !QFile::remove( dbbackup ) )
783 const char *err = QT_TR_NOOP(
"Master password reset: could not remove old database backup" );
791 QgsDebugMsg( QStringLiteral(
"Master password reset: backed up previous db at %1" ).arg( dbbackup ) );
793 *backuppath = dbbackup;
796 QgsDebugMsg( QStringLiteral(
"Master password reset: SUCCESS" ) );
803 mScheduledDbErase = scheduleErase;
805 mScheduledDbEraseRequestEmitted =
false;
806 mScheduledDbEraseRequestCount = 0;
810 if ( !mScheduledDbEraseTimer )
812 mScheduledDbEraseTimer =
new QTimer(
this );
813 connect( mScheduledDbEraseTimer, &QTimer::timeout,
this, &QgsAuthManager::tryToStartDbErase );
814 mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
816 else if ( !mScheduledDbEraseTimer->isActive() )
818 mScheduledDbEraseTimer->start();
823 if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
824 mScheduledDbEraseTimer->stop();
833 qDeleteAll( mAuthMethods );
834 mAuthMethods.clear();
836 for (
const auto &authMethodKey : methods )
841 return !mAuthMethods.isEmpty();
851 QTimer::singleShot( 3, &loop, &QEventLoop::quit );
854 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
855 uint seed =
static_cast< uint
>( QTime::currentTime().msec() );
862 for (
int i = 0; i < len; i++ )
864 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
865 switch ( qrand() % 2 )
867 switch ( QRandomGenerator::system()->generate() % 2 )
871 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
872 id += (
'0' + qrand() % 10 );
874 id += (
'0' + QRandomGenerator::system()->generate() % 10 );
878 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
879 id += (
'a' + qrand() % 26 );
881 id += (
'a' + QRandomGenerator::system()->generate() % 26 );
886 if ( !configids.contains(
id ) )
891 QgsDebugMsg( QStringLiteral(
"Generated unique ID: %1" ).arg(
id ) );
902 const char *err = QT_TR_NOOP(
"Config ID is empty" );
908 return !configids.contains(
id );
913 QRegExp rx( AUTH_CFG_REGEX );
914 return rx.indexIn( txt ) != -1;
919 QMutexLocker locker( mMutex.get() );
920 QStringList providerAuthMethodsKeys;
921 if ( !dataprovider.isEmpty() )
932 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1" ).arg(
authDatabaseConfigTable() ) );
934 if ( !authDbQuery( &query ) )
939 if ( query.isActive() && query.isSelect() )
941 while ( query.next() )
943 QString authcfg = query.value( 0 ).toString();
945 config.
setId( authcfg );
946 config.
setName( query.value( 1 ).toString() );
947 config.
setUri( query.value( 2 ).toString() );
948 config.
setMethod( query.value( 3 ).toString() );
949 config.
setVersion( query.value( 4 ).toInt() );
951 if ( !dataprovider.isEmpty() && !providerAuthMethodsKeys.contains( config.
method() ) )
956 baseConfigs.insert( authcfg, config );
964 QMutexLocker locker( mMutex.get() );
971 if ( !authDbQuery( &query ) )
976 if ( query.isActive() )
978 QgsDebugMsgLevel( QStringLiteral(
"Syncing existing auth config and their auth methods" ), 2 );
979 mConfigAuthMethods.clear();
980 QStringList cfgmethods;
981 while ( query.next() )
983 mConfigAuthMethods.insert( query.value( 0 ).toString(),
984 query.value( 1 ).toString() );
985 cfgmethods << QStringLiteral(
"%1=%2" ).arg( query.value( 0 ).toString(), query.value( 1 ).toString() );
987 QgsDebugMsgLevel( QStringLiteral(
"Stored auth config/methods:\n%1" ).arg( cfgmethods.join(
", " ) ), 2 );
996 if ( !mConfigAuthMethods.contains( authcfg ) )
998 QgsDebugMsg( QStringLiteral(
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
1002 QString authMethodKey = mConfigAuthMethods.value( authcfg );
1012 return mConfigAuthMethods.value( authcfg, QString() );
1023 if ( !mAuthMethods.contains( authMethodKey ) )
1025 QgsDebugMsg( QStringLiteral(
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
1029 return mAuthMethods.value( authMethodKey );
1034 if ( dataprovider.isEmpty() )
1036 return mAuthMethods;
1040 QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
1041 while ( i != mAuthMethods.constEnd() )
1044 && ( i.value()->supportedDataProviders().contains( QStringLiteral(
"all" ) )
1045 || i.value()->supportedDataProviders().contains( dataprovider ) ) )
1047 filteredmap.insert( i.key(), i.value() );
1062 return QgsAuthMethod::Expansions();
1069 return QgsAuthMethod::Expansions();
1074 QMutexLocker locker( mMutex.get() );
1081 const char *err = QT_TR_NOOP(
"Store config: FAILED because config is invalid" );
1087 QString uid = mconfig.
id();
1088 bool passedinID = !uid.isEmpty();
1089 if ( uid.isEmpty() )
1095 const char *err = QT_TR_NOOP(
"Store config: FAILED because pre-defined config ID is not unique" );
1102 if ( configstring.isEmpty() )
1104 const char *err = QT_TR_NOOP(
"Store config: FAILED because config string is empty" );
1110 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1111 QgsDebugMsg( QStringLiteral(
"name: %1" ).arg( config.name() ) );
1112 QgsDebugMsg( QStringLiteral(
"uri: %1" ).arg( config.uri() ) );
1113 QgsDebugMsg( QStringLiteral(
"type: %1" ).arg( config.method() ) );
1114 QgsDebugMsg( QStringLiteral(
"version: %1" ).arg( config.version() ) );
1115 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1119 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, name, uri, type, version, config) "
1122 query.bindValue( QStringLiteral(
":id" ), uid );
1123 query.bindValue( QStringLiteral(
":name" ), mconfig.
name() );
1124 query.bindValue( QStringLiteral(
":uri" ), mconfig.
uri() );
1125 query.bindValue( QStringLiteral(
":type" ), mconfig.
method() );
1126 query.bindValue( QStringLiteral(
":version" ), mconfig.
version() );
1127 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1129 if ( !authDbStartTransaction() )
1132 if ( !authDbQuery( &query ) )
1135 if ( !authDbCommit() )
1140 mconfig.
setId( uid );
1144 QgsDebugMsg( QStringLiteral(
"Store config SUCCESS for authcfg: %1" ).arg( uid ) );
1151 QMutexLocker locker( mMutex.get() );
1156 if ( !config.
isValid(
true ) )
1158 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is invalid" );
1165 if ( configstring.isEmpty() )
1167 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is empty" );
1174 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1175 QgsDebugMsg( QStringLiteral(
"id: %1" ).arg( config.
id() ) );
1180 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1184 if ( !query.prepare( QStringLiteral(
"UPDATE %1 "
1185 "SET name = :name, uri = :uri, type = :type, version = :version, config = :config "
1188 const char *err = QT_TR_NOOP(
"Update config: FAILED to prepare query" );
1194 query.bindValue( QStringLiteral(
":id" ), config.
id() );
1195 query.bindValue( QStringLiteral(
":name" ), config.
name() );
1196 query.bindValue( QStringLiteral(
":uri" ), config.
uri() );
1197 query.bindValue( QStringLiteral(
":type" ), config.
method() );
1198 query.bindValue( QStringLiteral(
":version" ), config.
version() );
1199 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1201 if ( !authDbStartTransaction() )
1204 if ( !authDbQuery( &query ) )
1207 if ( !authDbCommit() )
1215 QgsDebugMsg( QStringLiteral(
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ) );
1228 QMutexLocker locker( mMutex.get() );
1233 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version, config FROM %1 "
1238 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1 "
1242 query.bindValue( QStringLiteral(
":id" ), authcfg );
1244 if ( !authDbQuery( &query ) )
1249 if ( query.isActive() && query.isSelect() )
1251 if ( query.first() )
1253 mconfig.
setId( query.value( 0 ).toString() );
1254 mconfig.
setName( query.value( 1 ).toString() );
1255 mconfig.
setUri( query.value( 2 ).toString() );
1256 mconfig.
setMethod( query.value( 3 ).toString() );
1257 mconfig.
setVersion( query.value( 4 ).toInt() );
1272 QgsDebugMsg( QStringLiteral(
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
1275 QgsDebugMsg( QStringLiteral(
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ?
"full" :
"base", authcfg ) );
1280 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
1290 QMutexLocker locker( mMutex.get() );
1294 if ( authcfg.isEmpty() )
1301 query.bindValue( QStringLiteral(
":id" ), authcfg );
1303 if ( !authDbStartTransaction() )
1306 if ( !authDbQuery( &query ) )
1309 if ( !authDbCommit() )
1316 QgsDebugMsg( QStringLiteral(
"REMOVED config for authcfg: %1" ).arg( authcfg ) );
1323 QMutexLocker locker( mMutex.get() );
1329 bool res = authDbTransactionQuery( &query );
1337 QgsDebugMsg( QStringLiteral(
"Remove configs from database: %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
1344 QMutexLocker locker( mMutex.get() );
1347 const char *err = QT_TR_NOOP(
"No authentication database found" );
1355 if ( authConn.isValid() && authConn.isOpen() )
1359 QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral(
"yyyy-MM-dd-hhmmss" ) ) );
1361 dbbackup.replace( QLatin1String(
".db" ), QStringLiteral(
"_%1.db" ).arg( datestamp ) );
1365 const char *err = QT_TR_NOOP(
"Could not back up authentication database" );
1372 *backuppath = dbbackup;
1374 QgsDebugMsg( QStringLiteral(
"Backed up auth database at %1" ).arg( dbbackup ) );
1380 QMutexLocker locker( mMutex.get() );
1390 if ( backuppath && !dbbackup.isEmpty() )
1391 *backuppath = dbbackup;
1394 if ( dbinfo.exists() )
1396 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
1398 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
1406 const char *err = QT_TR_NOOP(
"No authentication database found" );
1414 const char *err = QT_TR_NOOP(
"Authentication database could not be deleted" );
1420 mMasterPass = QString();
1422 QgsDebugMsg( QStringLiteral(
"Creating Auth db through QSqlDatabase initial connection" ) );
1425 if ( !authConn.isValid() || !authConn.isOpen() )
1427 const char *err = QT_TR_NOOP(
"Authentication database could not be initialized" );
1433 if ( !createConfigTables() )
1435 const char *err = QT_TR_NOOP(
"FAILED to create auth database config tables" );
1441 if ( !createCertTables() )
1443 const char *err = QT_TR_NOOP(
"FAILED to create auth database cert tables" );
1459 const QString &dataprovider )
1469 QgsDebugMsg( QStringLiteral(
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
1484 const QString &dataprovider )
1494 QgsDebugMsg( QStringLiteral(
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ) );
1510 const QString &dataprovider )
1520 QgsDebugMsg( QStringLiteral(
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
1545 QgsDebugMsg( QStringLiteral(
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
1554 QgsDebugMsg( QStringLiteral(
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ) );
1563 QMutexLocker locker( mMutex.get() );
1564 if ( key.isEmpty() )
1567 QString storeval( value.toString() );
1583 query.prepare( QStringLiteral(
"INSERT INTO %1 (setting, value) "
1584 "VALUES (:setting, :value)" ).arg( authDbSettingsTable() ) );
1586 query.bindValue( QStringLiteral(
":setting" ), key );
1587 query.bindValue( QStringLiteral(
":value" ), storeval );
1589 if ( !authDbStartTransaction() )
1592 if ( !authDbQuery( &query ) )
1595 if ( !authDbCommit() )
1598 QgsDebugMsg( QStringLiteral(
"Store setting SUCCESS for key: %1" ).arg( key ) );
1604 QMutexLocker locker( mMutex.get() );
1605 if ( key.isEmpty() )
1611 QVariant value = defaultValue;
1613 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
1614 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1616 query.bindValue( QStringLiteral(
":setting" ), key );
1618 if ( !authDbQuery( &query ) )
1621 if ( query.isActive() && query.isSelect() )
1623 if ( query.first() )
1627 value = QVariant(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ) );
1631 value = query.value( 0 );
1633 QgsDebugMsg( QStringLiteral(
"Authentication setting retrieved for key: %1" ).arg( key ) );
1637 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1647 QMutexLocker locker( mMutex.get() );
1648 if ( key.isEmpty() )
1652 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
1653 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1655 query.bindValue( QStringLiteral(
":setting" ), key );
1657 if ( !authDbQuery( &query ) )
1661 if ( query.isActive() && query.isSelect() )
1663 if ( query.first() )
1665 QgsDebugMsg( QStringLiteral(
"Authentication setting exists for key: %1" ).arg( key ) );
1670 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1680 QMutexLocker locker( mMutex.get() );
1681 if ( key.isEmpty() )
1686 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1688 query.bindValue( QStringLiteral(
":setting" ), key );
1690 if ( !authDbStartTransaction() )
1693 if ( !authDbQuery( &query ) )
1696 if ( !authDbCommit() )
1699 QgsDebugMsg( QStringLiteral(
"REMOVED setting for key: %1" ).arg( key ) );
1713 QMutexLocker locker( mMutex.get() );
1719 mCustomConfigByHostCache.clear();
1720 mHasCheckedIfCustomConfigByHostExists =
false;
1723 QgsDebugMsg( QStringLiteral(
"Init of SSL caches FAILED" ) );
1729 QMutexLocker locker( mMutex.get() );
1730 if ( cert.isNull() )
1732 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
1737 QgsDebugMsg( QStringLiteral(
"Passed private key is null" ) );
1747 QString certpem( cert.toPem() );
1751 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, key, cert) "
1752 "VALUES (:id, :key, :cert)" ).arg( authDbIdentitiesTable() ) );
1754 query.bindValue( QStringLiteral(
":id" ),
id );
1755 query.bindValue( QStringLiteral(
":key" ), keypem );
1756 query.bindValue( QStringLiteral(
":cert" ), certpem );
1758 if ( !authDbStartTransaction() )
1761 if ( !authDbQuery( &query ) )
1764 if ( !authDbCommit() )
1767 QgsDebugMsgLevel( QStringLiteral(
"Store certificate identity SUCCESS for id: %1" ).arg(
id ), 2 );
1773 QMutexLocker locker( mMutex.get() );
1774 QSslCertificate emptycert;
1775 QSslCertificate cert;
1780 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
1781 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1783 query.bindValue( QStringLiteral(
":id" ),
id );
1785 if ( !authDbQuery( &query ) )
1788 if ( query.isActive() && query.isSelect() )
1790 if ( query.first() )
1792 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
1793 QgsDebugMsg( QStringLiteral(
"Certificate identity retrieved for id: %1" ).arg(
id ) );
1797 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1807 QMutexLocker locker( mMutex.get() );
1808 QPair<QSslCertificate, QSslKey> bundle;
1816 query.prepare( QStringLiteral(
"SELECT key, cert FROM %1 "
1817 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1819 query.bindValue( QStringLiteral(
":id" ),
id );
1821 if ( !authDbQuery( &query ) )
1824 if ( query.isActive() && query.isSelect() )
1826 QSslCertificate cert;
1828 if ( query.first() )
1830 key = QSslKey(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ).toLatin1(),
1831 QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
1834 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create private key" );
1839 cert = QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1840 if ( cert.isNull() )
1842 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create certificate" );
1847 QgsDebugMsg( QStringLiteral(
"Certificate identity bundle retrieved for id: %1" ).arg(
id ) );
1851 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1855 bundle = qMakePair( cert, key );
1862 QMutexLocker locker( mMutex.get() );
1866 return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
1868 return QStringList();
1873 QMutexLocker locker( mMutex.get() );
1874 QList<QSslCertificate> certs;
1877 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbIdentitiesTable() ) );
1879 if ( !authDbQuery( &query ) )
1882 if ( query.isActive() && query.isSelect() )
1884 while ( query.next() )
1886 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1895 QMutexLocker locker( mMutex.get() );
1896 QStringList identityids = QStringList();
1902 query.prepare( QStringLiteral(
"SELECT id FROM %1" ).arg( authDbIdentitiesTable() ) );
1904 if ( !authDbQuery( &query ) )
1909 if ( query.isActive() )
1911 while ( query.next() )
1913 identityids << query.value( 0 ).toString();
1921 QMutexLocker locker( mMutex.get() );
1926 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
1927 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1929 query.bindValue( QStringLiteral(
":id" ),
id );
1931 if ( !authDbQuery( &query ) )
1935 if ( query.isActive() && query.isSelect() )
1937 if ( query.first() )
1939 QgsDebugMsg( QStringLiteral(
"Certificate bundle exists for id: %1" ).arg(
id ) );
1944 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate bundle for id: %1" ).arg(
id ) );
1954 QMutexLocker locker( mMutex.get() );
1957 QgsDebugMsg( QStringLiteral(
"Passed bundle ID is empty" ) );
1963 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1965 query.bindValue( QStringLiteral(
":id" ),
id );
1967 if ( !authDbStartTransaction() )
1970 if ( !authDbQuery( &query ) )
1973 if ( !authDbCommit() )
1976 QgsDebugMsg( QStringLiteral(
"REMOVED certificate identity for id: %1" ).arg(
id ) );
1982 QMutexLocker locker( mMutex.get() );
1985 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
1994 QString certpem( cert.toPem() );
1997 query.prepare( QStringLiteral(
"INSERT OR REPLACE INTO %1 (id, host, cert, config) "
2000 query.bindValue( QStringLiteral(
":id" ),
id );
2001 query.bindValue( QStringLiteral(
":host" ), config.
sslHostPort().trimmed() );
2002 query.bindValue( QStringLiteral(
":cert" ), certpem );
2003 query.bindValue( QStringLiteral(
":config" ), config.
configString() );
2005 if ( !authDbStartTransaction() )
2008 if ( !authDbQuery( &query ) )
2011 if ( !authDbCommit() )
2014 QgsDebugMsg( QStringLiteral(
"Store SSL cert custom config SUCCESS for host:port, id: %1, %2" )
2018 mHasCheckedIfCustomConfigByHostExists =
false;
2019 mCustomConfigByHostCache.clear();
2026 QMutexLocker locker( mMutex.get() );
2029 if (
id.isEmpty() || hostport.isEmpty() )
2031 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2036 query.prepare( QStringLiteral(
"SELECT id, host, cert, config FROM %1 "
2039 query.bindValue( QStringLiteral(
":id" ),
id );
2040 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2042 if ( !authDbQuery( &query ) )
2045 if ( query.isActive() && query.isSelect() )
2047 if ( query.first() )
2049 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2052 QgsDebugMsg( QStringLiteral(
"SSL cert custom config retrieved for host:port, id: %1, %2" ).arg( hostport,
id ) );
2056 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2057 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2069 if ( hostport.isEmpty() )
2074 QMutexLocker locker( mMutex.get() );
2075 if ( mHasCheckedIfCustomConfigByHostExists && !mHasCustomConfigByHost )
2077 if ( mCustomConfigByHostCache.contains( hostport ) )
2078 return mCustomConfigByHostCache.value( hostport );
2083 if ( !mHasCheckedIfCustomConfigByHostExists )
2085 mHasCheckedIfCustomConfigByHostExists =
true;
2087 if ( !authDbQuery( &query ) )
2089 mHasCustomConfigByHost =
false;
2092 if ( query.isActive() && query.isSelect() && query.first() )
2094 mHasCustomConfigByHost = query.value( 0 ).toInt() > 0;
2095 if ( !mHasCustomConfigByHost )
2100 mHasCustomConfigByHost =
false;
2105 query.prepare( QString(
"SELECT id, host, cert, config FROM %1 "
2108 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2110 if ( !authDbQuery( &query ) )
2112 mCustomConfigByHostCache.insert( hostport, config );
2116 if ( query.isActive() && query.isSelect() )
2118 if ( query.first() )
2120 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2123 QgsDebugMsg( QStringLiteral(
"SSL cert custom config retrieved for host:port: %1" ).arg( hostport ) );
2127 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port: %1" ).arg( hostport ) );
2128 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
2131 mCustomConfigByHostCache.insert( hostport, emptyconfig );
2136 mCustomConfigByHostCache.insert( hostport, config );
2142 QMutexLocker locker( mMutex.get() );
2143 QList<QgsAuthConfigSslServer> configs;
2148 if ( !authDbQuery( &query ) )
2151 if ( query.isActive() && query.isSelect() )
2153 while ( query.next() )
2156 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2160 configs.append( config );
2169 QMutexLocker locker( mMutex.get() );
2170 if (
id.isEmpty() || hostport.isEmpty() )
2172 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2177 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
2180 query.bindValue( QStringLiteral(
":id" ),
id );
2181 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2183 if ( !authDbQuery( &query ) )
2187 if ( query.isActive() && query.isSelect() )
2189 if ( query.first() )
2191 QgsDebugMsg( QStringLiteral(
"SSL cert custom config exists for host:port, id: %1, %2" ).arg( hostport,
id ) );
2196 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2197 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2207 QMutexLocker locker( mMutex.get() );
2208 if (
id.isEmpty() || hostport.isEmpty() )
2210 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2214 mHasCheckedIfCustomConfigByHostExists =
false;
2215 mCustomConfigByHostCache.clear();
2219 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id AND host = :host" ).arg(
authDatabaseServersTable() ) );
2221 query.bindValue( QStringLiteral(
":id" ),
id );
2222 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2224 if ( !authDbStartTransaction() )
2227 if ( !authDbQuery( &query ) )
2230 if ( !authDbCommit() )
2233 QString shahostport( QStringLiteral(
"%1:%2" ).arg(
id, hostport ) );
2234 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2236 mIgnoredSslErrorsCache.remove( shahostport );
2239 QgsDebugMsg( QStringLiteral(
"REMOVED SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2246 QMutexLocker locker( mMutex.get() );
2247 if ( !mIgnoredSslErrorsCache.isEmpty() )
2249 QgsDebugMsg( QStringLiteral(
"Ignored SSL errors cache items:" ) );
2250 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
2251 while ( i != mIgnoredSslErrorsCache.constEnd() )
2254 for (
auto err : i.value() )
2258 QgsDebugMsg( QStringLiteral(
"%1 = %2" ).arg( i.key(), errs.join(
", " ) ) );
2270 QMutexLocker locker( mMutex.get() );
2273 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
2277 QString shahostport( QStringLiteral(
"%1:%2" )
2280 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2282 mIgnoredSslErrorsCache.remove( shahostport );
2285 if ( !errenums.isEmpty() )
2287 mIgnoredSslErrorsCache.insert( shahostport, qgis::listToSet( errenums ) );
2288 QgsDebugMsg( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2293 QgsDebugMsg( QStringLiteral(
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ) );
2299 QMutexLocker locker( mMutex.get() );
2300 QRegExp rx(
"\\S+:\\S+:\\d+" );
2301 if ( !rx.exactMatch( shahostport ) )
2303 QgsDebugMsg(
"Passed shahostport does not match \\S+:\\S+:\\d+, "
2304 "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
2308 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2310 mIgnoredSslErrorsCache.remove( shahostport );
2313 if ( errors.isEmpty() )
2315 QgsDebugMsg( QStringLiteral(
"Passed errors list empty" ) );
2319 QSet<QSslError::SslError> errs;
2320 for (
const auto &error : errors )
2322 if ( error.error() == QSslError::NoError )
2325 errs.insert( error.error() );
2328 if ( errs.isEmpty() )
2330 QgsDebugMsg( QStringLiteral(
"Passed errors list does not contain errors" ) );
2334 mIgnoredSslErrorsCache.insert( shahostport, errs );
2336 QgsDebugMsg( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2343 QMutexLocker locker( mMutex.get() );
2344 QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
2345 QHash<QString, QSet<QSslError::SslError> > nextcache;
2350 if ( !authDbQuery( &query ) )
2352 QgsDebugMsg( QStringLiteral(
"Rebuild of ignored SSL errors cache FAILED" ) );
2356 if ( query.isActive() && query.isSelect() )
2358 while ( query.next() )
2360 QString shahostport( QStringLiteral(
"%1:%2" )
2361 .arg( query.value( 0 ).toString().trimmed(),
2362 query.value( 1 ).toString().trimmed() ) );
2366 if ( !errenums.isEmpty() )
2368 nextcache.insert( shahostport, qgis::listToSet( errenums ) );
2370 if ( prevcache.contains( shahostport ) )
2372 prevcache.remove( shahostport );
2377 if ( !prevcache.isEmpty() )
2380 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
2381 while ( i != prevcache.constEnd() )
2383 nextcache.insert( i.key(), i.value() );
2388 if ( nextcache != mIgnoredSslErrorsCache )
2390 mIgnoredSslErrorsCache.clear();
2391 mIgnoredSslErrorsCache = nextcache;
2392 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of ignored SSL errors cache SUCCEEDED" ), 2 );
2397 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of ignored SSL errors cache SAME AS BEFORE" ), 2 );
2405 QMutexLocker locker( mMutex.get() );
2406 if ( certs.isEmpty() )
2408 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2412 for (
const auto &cert : certs )
2422 QMutexLocker locker( mMutex.get() );
2425 if ( cert.isNull() )
2427 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2434 QString pem( cert.toPem() );
2437 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, cert) "
2438 "VALUES (:id, :cert)" ).arg( authDbAuthoritiesTable() ) );
2440 query.bindValue( QStringLiteral(
":id" ),
id );
2441 query.bindValue( QStringLiteral(
":cert" ), pem );
2443 if ( !authDbStartTransaction() )
2446 if ( !authDbQuery( &query ) )
2449 if ( !authDbCommit() )
2452 QgsDebugMsg( QStringLiteral(
"Store certificate authority SUCCESS for id: %1" ).arg(
id ) );
2458 QMutexLocker locker( mMutex.get() );
2459 QSslCertificate emptycert;
2460 QSslCertificate cert;
2465 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
2466 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2468 query.bindValue( QStringLiteral(
":id" ),
id );
2470 if ( !authDbQuery( &query ) )
2473 if ( query.isActive() && query.isSelect() )
2475 if ( query.first() )
2477 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
2478 QgsDebugMsg( QStringLiteral(
"Certificate authority retrieved for id: %1" ).arg(
id ) );
2482 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2492 QMutexLocker locker( mMutex.get() );
2493 if ( cert.isNull() )
2495 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2502 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
2503 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2505 query.bindValue( QStringLiteral(
":id" ),
id );
2507 if ( !authDbQuery( &query ) )
2511 if ( query.isActive() && query.isSelect() )
2513 if ( query.first() )
2515 QgsDebugMsg( QStringLiteral(
"Certificate authority exists for id: %1" ).arg(
id ) );
2520 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2530 QMutexLocker locker( mMutex.get() );
2531 if ( cert.isNull() )
2533 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2541 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2543 query.bindValue( QStringLiteral(
":id" ),
id );
2545 if ( !authDbStartTransaction() )
2548 if ( !authDbQuery( &query ) )
2551 if ( !authDbCommit() )
2554 QgsDebugMsg( QStringLiteral(
"REMOVED authority for id: %1" ).arg(
id ) );
2560 return QSslConfiguration::systemCaCertificates();
2565 QMutexLocker locker( mMutex.get() );
2566 QList<QSslCertificate> certs;
2567 QList<QSslCertificate> filecerts;
2569 if ( cafileval.isNull() )
2573 if ( allowinvalid.isNull() )
2576 QString cafile( cafileval.toString() );
2577 if ( !cafile.isEmpty() && QFile::exists( cafile ) )
2582 for (
const auto &cert : qgis::as_const( filecerts ) )
2584 if ( !allowinvalid.toBool() && ( cert.isBlacklisted()
2586 || cert.expiryDate() <= QDateTime::currentDateTime()
2587 || cert.effectiveDate() > QDateTime::currentDateTime() ) )
2602 QMutexLocker locker( mMutex.get() );
2603 QList<QSslCertificate> certs;
2606 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbAuthoritiesTable() ) );
2608 if ( !authDbQuery( &query ) )
2611 if ( query.isActive() && query.isSelect() )
2613 while ( query.next() )
2615 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
2624 QMutexLocker locker( mMutex.get() );
2630 QMutexLocker locker( mMutex.get() );
2631 mCaCertsCache.clear();
2637 bool res = !mCaCertsCache.isEmpty();
2639 QgsDebugMsg( QStringLiteral(
"Rebuild of CA certs cache FAILED" ) );
2645 QMutexLocker locker( mMutex.get() );
2646 if ( cert.isNull() )
2648 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2658 QgsDebugMsg( QStringLiteral(
"Passed policy was default, all cert records in database were removed for id: %1" ).arg(
id ) );
2663 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, policy) "
2664 "VALUES (:id, :policy)" ).arg( authDbTrustTable() ) );
2666 query.bindValue( QStringLiteral(
":id" ),
id );
2667 query.bindValue( QStringLiteral(
":policy" ),
static_cast< int >( policy ) );
2669 if ( !authDbStartTransaction() )
2672 if ( !authDbQuery( &query ) )
2675 if ( !authDbCommit() )
2678 QgsDebugMsg( QStringLiteral(
"Store certificate trust policy SUCCESS for id: %1" ).arg(
id ) );
2684 QMutexLocker locker( mMutex.get() );
2685 if ( cert.isNull() )
2687 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2694 query.prepare( QStringLiteral(
"SELECT policy FROM %1 "
2695 "WHERE id = :id" ).arg( authDbTrustTable() ) );
2697 query.bindValue( QStringLiteral(
":id" ),
id );
2699 if ( !authDbQuery( &query ) )
2703 if ( query.isActive() && query.isSelect() )
2705 if ( query.first() )
2708 QgsDebugMsg( QStringLiteral(
"Authentication cert trust policy retrieved for id: %1" ).arg(
id ) );
2712 QgsDebugMsg( QStringLiteral(
"Select contains more than one cert trust policy for id: %1" ).arg(
id ) );
2722 QMutexLocker locker( mMutex.get() );
2723 if ( certs.empty() )
2725 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2729 for (
const auto &cert : certs )
2739 QMutexLocker locker( mMutex.get() );
2740 if ( cert.isNull() )
2742 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2750 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbTrustTable() ) );
2752 query.bindValue( QStringLiteral(
":id" ),
id );
2754 if ( !authDbStartTransaction() )
2757 if ( !authDbQuery( &query ) )
2760 if ( !authDbCommit() )
2763 QgsDebugMsg( QStringLiteral(
"REMOVED cert trust policy for id: %1" ).arg(
id ) );
2770 QMutexLocker locker( mMutex.get() );
2771 if ( cert.isNull() )
2781 if ( trustedids.contains(
id ) )
2785 else if ( untrustedids.contains(
id ) )
2800 return storeAuthSetting( QStringLiteral(
"certdefaulttrust" ),
static_cast< int >( policy ) );
2805 QMutexLocker locker( mMutex.get() );
2806 QVariant policy(
authSetting( QStringLiteral(
"certdefaulttrust" ) ) );
2807 if ( policy.isNull() )
2816 QMutexLocker locker( mMutex.get() );
2817 mCertTrustCache.clear();
2820 query.prepare( QStringLiteral(
"SELECT id, policy FROM %1" ).arg( authDbTrustTable() ) );
2822 if ( !authDbQuery( &query ) )
2824 QgsDebugMsg( QStringLiteral(
"Rebuild of cert trust policy cache FAILED" ) );
2828 if ( query.isActive() && query.isSelect() )
2830 while ( query.next() )
2832 QString
id = query.value( 0 ).toString();
2836 if ( mCertTrustCache.contains( policy ) )
2838 ids = mCertTrustCache.value( policy );
2840 mCertTrustCache.insert( policy, ids <<
id );
2844 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of cert trust policy cache SUCCEEDED" ), 2 );
2850 QMutexLocker locker( mMutex.get() );
2854 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2856 QList<QSslCertificate> trustedcerts;
2857 for (
int i = 0; i < certpairs.size(); ++i )
2859 QSslCertificate cert( certpairs.at( i ).second );
2861 if ( trustedids.contains( certid ) )
2864 trustedcerts.append( cert );
2870 trustedcerts.append( cert );
2875 QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
2876 sslconfig.setCaCertificates( trustedcerts );
2877 QSslConfiguration::setDefaultConfiguration( sslconfig );
2879 return trustedcerts;
2884 QMutexLocker locker( mMutex.get() );
2885 if ( trustedCAs.isEmpty() )
2887 if ( mTrustedCaCertsCache.isEmpty() )
2894 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2896 QList<QSslCertificate> untrustedCAs;
2897 for (
int i = 0; i < certpairs.size(); ++i )
2899 QSslCertificate cert( certpairs.at( i ).second );
2900 if ( !trustedCAs.contains( cert ) )
2902 untrustedCAs.append( cert );
2905 return untrustedCAs;
2910 QMutexLocker locker( mMutex.get() );
2912 QgsDebugMsgLevel( QStringLiteral(
"Rebuilt trusted cert authorities cache" ), 2 );
2919 QMutexLocker locker( mMutex.get() );
2925 QMutexLocker locker( mMutex.get() );
2928 return passwordHelperWrite( mMasterPass );
2944 for (
const auto &authcfg : ids )
2962 void QgsAuthManager::writeToConsole(
const QString &message,
2976 msg += QLatin1String(
"WARNING: " );
2979 msg += QLatin1String(
"ERROR: " );
2986 QTextStream out( stdout, QIODevice::WriteOnly );
2987 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
2990 out << msg << Qt::endl;
2994 void QgsAuthManager::tryToStartDbErase()
2996 ++mScheduledDbEraseRequestCount;
2998 int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
2999 if ( mScheduledDbEraseRequestCount >= trycutoff )
3002 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emitting/scheduling canceled" ) );
3007 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest attempt (%1 of %2)" )
3008 .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ) );
3014 mScheduledDbEraseRequestEmitted =
true;
3019 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emitted" ) );
3022 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emit skipped" ) );
3028 QMutexLocker locker( mMutex.get() );
3029 QMapIterator<QThread *, QMetaObject::Connection> iterator( mConnectedThreads );
3030 while ( iterator.hasNext() )
3033 iterator.key()->disconnect( iterator.value() );
3040 qDeleteAll( mAuthMethods );
3043 if ( authConn.isValid() && authConn.isOpen() )
3046 delete mScheduledDbEraseTimer;
3047 mScheduledDbEraseTimer =
nullptr;
3048 QSqlDatabase::removeDatabase( QStringLiteral(
"authentication.configs" ) );
3052 QString QgsAuthManager::passwordHelperName()
const
3054 return tr(
"Password Helper" );
3058 void QgsAuthManager::passwordHelperLog(
const QString &msg )
const
3070 QKeychain::DeletePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3072 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3073 job.setAutoDelete(
false );
3074 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3076 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3081 mPasswordHelperErrorCode = job.error();
3082 mPasswordHelperErrorMessage = tr(
"Delete password failed: %1." ).arg( job.errorString() );
3093 passwordHelperProcessError();
3097 QString QgsAuthManager::passwordHelperRead()
3102 QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3104 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3105 job.setAutoDelete(
false );
3106 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3108 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3113 mPasswordHelperErrorCode = job.error();
3120 password = job.textData();
3122 if ( password.isEmpty() )
3124 mPasswordHelperErrorCode = QKeychain::EntryNotFound;
3135 passwordHelperProcessError();
3139 bool QgsAuthManager::passwordHelperWrite(
const QString &password )
3141 Q_ASSERT( !password.isEmpty() );
3144 QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3146 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3147 job.setAutoDelete(
false );
3148 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3149 job.setTextData( password );
3151 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3156 mPasswordHelperErrorCode = job.error();
3164 passwordHelperClearErrors();
3169 passwordHelperProcessError();
3177 return settings.
value( QStringLiteral(
"use_password_helper" ),
true, QgsSettings::Section::Auth ).toBool();
3183 settings.
setValue( QStringLiteral(
"use_password_helper" ), enabled, QgsSettings::Section::Auth );
3184 emit
messageOut( enabled ? tr(
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
3186 tr(
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
3194 return settings.
value( QStringLiteral(
"password_helper_logging" ),
false, QgsSettings::Section::Auth ).toBool();
3200 settings.
setValue( QStringLiteral(
"password_helper_logging" ), enabled, QgsSettings::Section::Auth );
3203 void QgsAuthManager::passwordHelperClearErrors()
3205 mPasswordHelperErrorCode = QKeychain::NoError;
3206 mPasswordHelperErrorMessage.clear();
3209 void QgsAuthManager::passwordHelperProcessError()
3211 if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
3212 mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
3213 mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
3214 mPasswordHelperErrorCode == QKeychain::NotImplemented )
3220 mPasswordHelperErrorMessage = tr(
"There was an error and integration with your %1 system has been disabled. "
3221 "You can re-enable it at any time through the \"Utilities\" menu "
3222 "in the Authentication pane of the options dialog. %2" )
3225 if ( mPasswordHelperErrorCode != QKeychain::NoError )
3231 passwordHelperClearErrors();
3235 bool QgsAuthManager::masterPasswordInput()
3241 bool storedPasswordIsValid =
false;
3247 pass = passwordHelperRead();
3248 if ( ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
3254 storedPasswordIsValid =
true;
3270 if ( ok && !pass.isEmpty() && mMasterPass != pass )
3275 if ( passwordHelperWrite( pass ) )
3289 bool QgsAuthManager::masterPasswordRowsInDb(
int *rows )
const
3295 query.prepare( QStringLiteral(
"SELECT Count(*) FROM %1" ).arg( authDbPassTable() ) );
3297 bool ok = authDbQuery( &query );
3298 if ( query.first() )
3300 *rows = query.value( 0 ).toInt();
3312 if ( !masterPasswordRowsInDb( &rows ) )
3314 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
3320 return ( rows == 1 );
3323 bool QgsAuthManager::masterPasswordCheckAgainstDb(
const QString &compare )
const
3331 query.prepare( QStringLiteral(
"SELECT salt, hash FROM %1" ).arg( authDbPassTable() ) );
3332 if ( !authDbQuery( &query ) )
3335 if ( !query.first() )
3338 QString salt = query.value( 0 ).toString();
3339 QString hash = query.value( 1 ).toString();
3344 bool QgsAuthManager::masterPasswordStoreInDb()
const
3349 QString salt, hash, civ;
3353 query.prepare( QStringLiteral(
"INSERT INTO %1 (salt, hash, civ) VALUES (:salt, :hash, :civ)" ).arg( authDbPassTable() ) );
3355 query.bindValue( QStringLiteral(
":salt" ), salt );
3356 query.bindValue( QStringLiteral(
":hash" ), hash );
3357 query.bindValue( QStringLiteral(
":civ" ), civ );
3359 if ( !authDbStartTransaction() )
3362 if ( !authDbQuery( &query ) )
3365 if ( !authDbCommit() )
3371 bool QgsAuthManager::masterPasswordClearDb()
3377 query.prepare( QStringLiteral(
"DELETE FROM %1" ).arg( authDbPassTable() ) );
3378 bool res = authDbTransactionQuery( &query );
3384 const QString QgsAuthManager::masterPasswordCiv()
const
3390 query.prepare( QStringLiteral(
"SELECT civ FROM %1" ).arg( authDbPassTable() ) );
3391 if ( !authDbQuery( &query ) )
3394 if ( !query.first() )
3397 return query.value( 0 ).toString();
3402 QStringList configids = QStringList();
3410 if ( !authDbQuery( &query ) )
3415 if ( query.isActive() )
3417 while ( query.next() )
3419 configids << query.value( 0 ).toString();
3425 bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
const
3436 if ( !authDbQuery( &query ) )
3439 if ( !query.isActive() || !query.isSelect() )
3441 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, query not active or a select operation" ) );
3446 while ( query.next() )
3449 QString configstring(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 1 ).toString() ) );
3450 if ( configstring.isEmpty() )
3452 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1)" )
3453 .arg( query.value( 0 ).toString() ) );
3458 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs SUCCESS (checked %1 configs)" ).arg( checked ) );
3462 bool QgsAuthManager::reencryptAllAuthenticationConfigs(
const QString &prevpass,
const QString &prevciv )
3469 for (
const auto &configid : ids )
3471 res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
3476 bool QgsAuthManager::reencryptAuthenticationConfig(
const QString &authcfg,
const QString &prevpass,
const QString &prevciv )
3485 query.prepare( QStringLiteral(
"SELECT config FROM %1 "
3488 query.bindValue( QStringLiteral(
":id" ), authcfg );
3490 if ( !authDbQuery( &query ) )
3493 if ( !query.isActive() || !query.isSelect() )
3495 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for authcfg: %2" ).arg( authcfg ) );
3499 if ( query.first() )
3505 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
3512 query.prepare( QStringLiteral(
"UPDATE %1 "
3513 "SET config = :config "
3516 query.bindValue( QStringLiteral(
":id" ), authcfg );
3517 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
3519 if ( !authDbStartTransaction() )
3522 if ( !authDbQuery( &query ) )
3525 if ( !authDbCommit() )
3528 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for authcfg: %2" ).arg( authcfg ) );
3533 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db authcfg: %2" ).arg( authcfg ) );
3538 bool QgsAuthManager::reencryptAllAuthenticationSettings(
const QString &prevpass,
const QString &prevciv )
3541 Q_UNUSED( prevpass )
3554 QStringList encryptedsettings;
3555 encryptedsettings <<
"";
3557 for (
const auto & sett, qgis::as_const( encryptedsettings ) )
3564 QSqlQuery query( authDbConnection() );
3566 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
3567 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3569 query.bindValue(
":setting", sett );
3571 if ( !authDbQuery( &query ) )
3574 if ( !query.isActive() || !query.isSelect() )
3576 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
3580 if ( query.first() )
3586 query.prepare( QStringLiteral(
"UPDATE %1 "
3587 "SET value = :value "
3588 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3590 query.bindValue(
":setting", sett );
3593 if ( !authDbStartTransaction() )
3596 if ( !authDbQuery( &query ) )
3599 if ( !authDbCommit() )
3602 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for setting: %2" ).arg( sett ) );
3607 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
3613 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting: %1" ).arg( sett ) );
3624 bool QgsAuthManager::reencryptAllAuthenticationIdentities(
const QString &prevpass,
const QString &prevciv )
3631 for (
const auto &identid : ids )
3633 res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
3638 bool QgsAuthManager::reencryptAuthenticationIdentity(
3639 const QString &identid,
3640 const QString &prevpass,
3641 const QString &prevciv )
3650 query.prepare( QStringLiteral(
"SELECT key FROM %1 "
3651 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3653 query.bindValue( QStringLiteral(
":id" ), identid );
3655 if ( !authDbQuery( &query ) )
3658 if ( !query.isActive() || !query.isSelect() )
3660 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for identity id: %2" ).arg( identid ) );
3664 if ( query.first() )
3670 QgsDebugMsg( QStringLiteral(
"Select contains more than one for identity id: %1" ).arg( identid ) );
3677 query.prepare( QStringLiteral(
"UPDATE %1 "
3679 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3681 query.bindValue( QStringLiteral(
":id" ), identid );
3682 query.bindValue( QStringLiteral(
":key" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), keystring ) );
3684 if ( !authDbStartTransaction() )
3687 if ( !authDbQuery( &query ) )
3690 if ( !authDbCommit() )
3693 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for identity id: %2" ).arg( identid ) );
3698 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db identity id: %2" ).arg( identid ) );
3703 bool QgsAuthManager::authDbOpen()
const
3709 if ( !authdb.isOpen() )
3711 if ( !authdb.open() )
3713 QgsDebugMsg( QStringLiteral(
"Unable to establish database connection\nDatabase: %1\nDriver error: %2\nDatabase error: %3" )
3715 authdb.lastError().driverText(),
3716 authdb.lastError().databaseText() ) );
3724 bool QgsAuthManager::authDbQuery( QSqlQuery *query )
const
3729 query->setForwardOnly(
true );
3730 if ( !query->exec() )
3732 const char *err = QT_TR_NOOP(
"Auth db query exec() FAILED" );
3738 if ( query->lastError().isValid() )
3740 QgsDebugMsg( QStringLiteral(
"Auth db query FAILED: %1\nError: %2" )
3741 .arg( query->executedQuery(),
3742 query->lastError().text() ) );
3750 bool QgsAuthManager::authDbStartTransaction()
const
3757 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3766 bool QgsAuthManager::authDbCommit()
const
3773 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3783 bool QgsAuthManager::authDbTransactionQuery( QSqlQuery *query )
const
3790 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3796 bool ok = authDbQuery( query );
3800 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3812 for (
const auto &cert : certs )
3815 QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>( source, cert ) );