23 #include <QMutexLocker>
26 #include <QSqlDatabase>
29 #include <QTextStream>
38 #include <QSslConfiguration>
59 const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral(
"auth_configs" );
60 const QString QgsAuthManager::AUTH_PASS_TABLE = QStringLiteral(
"auth_pass" );
61 const QString QgsAuthManager::AUTH_SETTINGS_TABLE = QStringLiteral(
"auth_settings" );
62 const QString QgsAuthManager::AUTH_IDENTITIES_TABLE = QStringLiteral(
"auth_identities" );
63 const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral(
"auth_servers" );
64 const QString QgsAuthManager::AUTH_AUTHORITIES_TABLE = QStringLiteral(
"auth_authorities" );
65 const QString QgsAuthManager::AUTH_TRUST_TABLE = QStringLiteral(
"auth_trust" );
67 const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral(
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
70 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME(
"QGIS-Master-Password" );
71 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME(
"QGIS" );
77 #elif defined(Q_OS_WIN)
79 #elif defined(Q_OS_LINUX)
88 QMutexLocker locker( &sMutex );
99 mMutex.reset(
new QMutex( QMutex::Recursive ) );
100 mMasterPasswordMutex.reset(
new QMutex( QMutex::Recursive ) );
102 this, &QgsAuthManager::writeToConsole );
113 QMutexLocker locker( mMutex.get() );
118 const QString connectionName = QStringLiteral(
"authentication.configs:0x%1" ).arg(
reinterpret_cast<quintptr
>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char(
'0' ) );
119 QgsDebugMsgLevel( QStringLiteral(
"Using auth db connection name: %1 " ).arg( connectionName ), 2 );
120 if ( !QSqlDatabase::contains( connectionName ) )
122 QgsDebugMsgLevel( QStringLiteral(
"No existing connection, creating a new one" ), 2 );
123 authdb = QSqlDatabase::addDatabase( QStringLiteral(
"QSQLITE" ), connectionName );
126 if ( QThread::currentThread() != qApp->thread() )
128 QgsDebugMsgLevel( QStringLiteral(
"Scheduled auth db remove on thread close" ), 2 );
138 QMetaObject::Connection connection = connect( QThread::currentThread(), &QThread::finished, QThread::currentThread(), [connectionName,
this ]
140 QMutexLocker locker( mMutex.get() );
141 QSqlDatabase::removeDatabase( connectionName );
142 mConnectedThreads.remove( QThread::currentThread() );
143 }, Qt::DirectConnection );
145 mConnectedThreads.insert( QThread::currentThread(), connection );
151 authdb = QSqlDatabase::database( connectionName );
155 if ( !authdb.isOpen() )
157 if ( !authdb.open() )
159 const char *err = QT_TR_NOOP(
"Opening of authentication db FAILED" );
177 mQcaInitializer = qgis::make_unique<QCA::Initializer>( QCA::Practical, 256 );
180 QCA::scanForPlugins();
182 QgsDebugMsgLevel( QStringLiteral(
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ), 2 );
183 QStringList capabilities;
185 capabilities = QCA::supportedFeatures();
186 QgsDebugMsgLevel( QStringLiteral(
"QCA supports: %1" ).arg( capabilities.join(
"," ) ), 2 );
189 if ( !QCA::isSupported(
"cert", QStringLiteral(
"qca-ossl" ) ) )
191 mAuthDisabled =
true;
192 mAuthDisabledMessage = tr(
"QCA's OpenSSL plugin (qca-ossl) is missing" );
196 QgsDebugMsgLevel( QStringLiteral(
"Prioritizing qca-ossl over all other QCA providers..." ), 2 );
197 const QCA::ProviderList provds = QCA::providers();
199 for ( QCA::Provider *p : provds )
201 QString pn = p->name();
203 if ( pn != QLatin1String(
"qca-ossl" ) )
205 pr = QCA::providerPriority( pn ) + 1;
207 QCA::setProviderPriority( pn, pr );
208 prlist << QStringLiteral(
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
210 QgsDebugMsgLevel( QStringLiteral(
"QCA provider priorities: %1" ).arg( prlist.join(
", " ) ), 2 );
217 QgsDebugMsgLevel( QStringLiteral(
"Authentication methods found: %1" ).arg( methods.join(
", " ) ), 2 );
219 if ( methods.isEmpty() )
221 mAuthDisabled =
true;
222 mAuthDisabledMessage = tr(
"No authentication method plugins found" );
228 mAuthDisabled =
true;
229 mAuthDisabledMessage = tr(
"No authentication method plugins could be loaded" );
233 mAuthDbPath = QDir::cleanPath( authDatabasePath );
237 QFileInfo dbdirinfo( dbinfo.path() );
238 QgsDebugMsgLevel( QStringLiteral(
"Auth db directory path: %1" ).arg( dbdirinfo.filePath() ), 2 );
240 if ( !dbdirinfo.exists() )
242 QgsDebugMsgLevel( QStringLiteral(
"Auth db directory path does not exist, making path: %1" ).arg( dbdirinfo.filePath() ), 2 );
243 if ( !QDir().mkpath( dbdirinfo.filePath() ) )
245 const char *err = QT_TR_NOOP(
"Auth db directory path could not be created" );
252 if ( dbinfo.exists() )
254 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
256 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
261 if ( dbinfo.size() > 0 )
265 if ( !createCertTables() )
275 const char *passenv =
"QGIS_AUTH_PASSWORD_FILE";
278 QString passpath( getenv( passenv ) );
287 QFile passfile( passpath );
288 if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
290 QTextStream passin( &passfile );
291 while ( !passin.atEnd() )
293 masterpass = passin.readLine();
298 if ( !masterpass.isEmpty() )
302 QgsDebugMsgLevel( QStringLiteral(
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" ), 2 );
306 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
312 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
322 QgsDebugMsgLevel( QStringLiteral(
"Auth db does not exist: creating through QSqlDatabase initial connection" ), 2 );
324 if ( !createConfigTables() )
327 if ( !createCertTables() )
338 bool QgsAuthManager::createConfigTables()
340 QMutexLocker locker( mMutex.get() );
344 const char *err = QT_TR_NOOP(
"Auth db could not be created and opened" );
355 qstr = QStringLiteral(
"CREATE TABLE %1 (\n"
356 " 'salt' TEXT NOT NULL,\n"
357 " 'civ' TEXT NOT NULL\n"
358 ", 'hash' TEXT NOT NULL);" ).arg( authDbPassTable() );
359 query.prepare( qstr );
360 if ( !authDbQuery( &query ) )
364 qstr = QStringLiteral(
"CREATE TABLE %1 (\n"
365 " 'id' TEXT NOT NULL,\n"
366 " 'name' TEXT NOT NULL,\n"
368 " 'type' TEXT NOT NULL,\n"
369 " 'version' INTEGER NOT NULL\n"
371 query.prepare( qstr );
372 if ( !authDbQuery( &query ) )
377 query.prepare( qstr );
378 if ( !authDbQuery( &query ) )
383 query.prepare( qstr );
384 if ( !authDbQuery( &query ) )
391 bool QgsAuthManager::createCertTables()
393 QMutexLocker locker( mMutex.get() );
402 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
403 " 'setting' TEXT NOT NULL\n"
404 ", 'value' TEXT);" ).arg( authDbSettingsTable() );
405 query.prepare( qstr );
406 if ( !authDbQuery( &query ) )
411 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
412 " 'id' TEXT NOT NULL,\n"
413 " 'key' TEXT NOT NULL\n"
414 ", 'cert' TEXT NOT NULL);" ).arg( authDbIdentitiesTable() );
415 query.prepare( qstr );
416 if ( !authDbQuery( &query ) )
420 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbIdentitiesTable() );
421 query.prepare( qstr );
422 if ( !authDbQuery( &query ) )
427 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
428 " 'id' TEXT NOT NULL,\n"
429 " 'host' TEXT NOT NULL,\n"
432 query.prepare( qstr );
433 if ( !authDbQuery( &query ) )
437 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'host_index' on %1 (host ASC);" ).arg(
authDatabaseServersTable() );
438 query.prepare( qstr );
439 if ( !authDbQuery( &query ) )
444 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
445 " 'id' TEXT NOT NULL\n"
446 ", 'cert' TEXT NOT NULL);" ).arg( authDbAuthoritiesTable() );
447 query.prepare( qstr );
448 if ( !authDbQuery( &query ) )
452 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbAuthoritiesTable() );
453 query.prepare( qstr );
454 if ( !authDbQuery( &query ) )
458 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
459 " 'id' TEXT NOT NULL\n"
460 ", 'policy' TEXT NOT NULL);" ).arg( authDbTrustTable() );
461 query.prepare( qstr );
462 if ( !authDbQuery( &query ) )
466 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbTrustTable() );
467 query.prepare( qstr );
468 if ( !authDbQuery( &query ) )
479 QgsDebugMsg( QStringLiteral(
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" ) );
481 return mAuthDisabled;
486 return tr(
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
491 QMutexLocker locker( mMasterPasswordMutex.get() );
495 if ( mScheduledDbErase )
498 if ( mMasterPass.isEmpty() )
500 QgsDebugMsg( QStringLiteral(
"Master password is not yet set by user" ) );
501 if ( !masterPasswordInput() )
503 QgsDebugMsg( QStringLiteral(
"Master password input canceled by user" ) );
509 QgsDebugMsg( QStringLiteral(
"Master password is set" ) );
517 QgsDebugMsg( QStringLiteral(
"Master password is set and verified" ) );
523 QMutexLocker locker( mMutex.get() );
527 if ( mScheduledDbErase )
531 QString prevpass = QString( mMasterPass );
535 mMasterPass = prevpass;
536 const char *err = QT_TR_NOOP(
"Master password set: FAILED to verify, reset to previous" );
542 QgsDebugMsg( QStringLiteral(
"Master password set: SUCCESS%1" ).arg( verify ?
" and verified" :
"" ) );
552 if ( !masterPasswordRowsInDb( &rows ) )
554 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
562 QgsDebugMsg( QStringLiteral(
"Master password: %1 rows in database" ).arg( rows ) );
566 const char *err = QT_TR_NOOP(
"Master password: FAILED to find just one master password record in database" );
573 else if ( rows == 1 )
575 if ( !masterPasswordCheckAgainstDb( compare ) )
577 if ( compare.isNull() )
579 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
588 if ( mPassTries >= 5 )
590 mAuthDisabled =
true;
591 const char *err = QT_TR_NOOP(
"Master password: failed 5 times authentication system DISABLED" );
599 QgsDebugMsg( QStringLiteral(
"Master password: verified against hash in database" ) );
600 if ( compare.isNull() )
604 else if ( compare.isNull() )
606 if ( !masterPasswordStoreInDb() )
608 const char *err = QT_TR_NOOP(
"Master password: hash FAILED to be stored in database" );
617 QgsDebugMsg( QStringLiteral(
"Master password: hash stored in database" ) );
620 if ( !masterPasswordCheckAgainstDb() )
622 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
632 QgsDebugMsg( QStringLiteral(
"Master password: verified against hash in database" ) );
642 return !mMasterPass.isEmpty();
647 return mMasterPass == pass;
651 bool keepbackup, QString *backuppath )
665 QgsDebugMsg( QStringLiteral(
"Master password reset: backed up current database" ) );
671 QString prevpass = QString( mMasterPass );
672 QString prevciv = QString( masterPasswordCiv() );
678 if ( ok && !masterPasswordClearDb() )
681 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not clear current password from database" );
687 QgsDebugMsg( QStringLiteral(
"Master password reset: cleared current password from database" ) );
694 if ( ok && !masterPasswordStoreInDb() )
697 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not store new password in database" );
703 QgsDebugMsg( QStringLiteral(
"Master password reset: stored new password in database" ) );
710 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify new password in database" );
716 if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
719 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt configs in database" );
725 QgsDebugMsg( QStringLiteral(
"Master password reset: re-encrypted configs in database" ) );
729 if ( ok && !verifyPasswordCanDecryptConfigs() )
732 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
737 if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
740 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt settings in database" );
745 if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
748 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt identities in database" );
758 QString errdbbackup( dbbackup );
759 errdbbackup.replace( QLatin1String(
".db" ), QLatin1String(
"_ERROR.db" ) );
761 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
765 mMasterPass = prevpass;
767 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: reinstated previous password and database" ) );
771 *backuppath = errdbbackup;
777 if ( !keepbackup && !QFile::remove( dbbackup ) )
779 const char *err = QT_TR_NOOP(
"Master password reset: could not remove old database backup" );
787 QgsDebugMsg( QStringLiteral(
"Master password reset: backed up previous db at %1" ).arg( dbbackup ) );
789 *backuppath = dbbackup;
792 QgsDebugMsg( QStringLiteral(
"Master password reset: SUCCESS" ) );
799 mScheduledDbErase = scheduleErase;
801 mScheduledDbEraseRequestEmitted =
false;
802 mScheduledDbEraseRequestCount = 0;
806 if ( !mScheduledDbEraseTimer )
808 mScheduledDbEraseTimer =
new QTimer(
this );
809 connect( mScheduledDbEraseTimer, &QTimer::timeout,
this, &QgsAuthManager::tryToStartDbErase );
810 mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
812 else if ( !mScheduledDbEraseTimer->isActive() )
814 mScheduledDbEraseTimer->start();
819 if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
820 mScheduledDbEraseTimer->stop();
829 qDeleteAll( mAuthMethods );
830 mAuthMethods.clear();
832 for (
const auto &authMethodKey : methods )
837 return !mAuthMethods.isEmpty();
847 QTimer::singleShot( 3, &loop, &QEventLoop::quit );
850 uint seed =
static_cast< uint
>( QTime::currentTime().msec() );
856 for (
int i = 0; i < len; i++ )
858 switch ( qrand() % 2 )
861 id += (
'0' + qrand() % 10 );
864 id += (
'a' + qrand() % 26 );
868 if ( !configids.contains(
id ) )
873 QgsDebugMsg( QStringLiteral(
"Generated unique ID: %1" ).arg(
id ) );
884 const char *err = QT_TR_NOOP(
"Config ID is empty" );
890 return !configids.contains(
id );
895 QRegExp rx( AUTH_CFG_REGEX );
896 return rx.indexIn( txt ) != -1;
901 QMutexLocker locker( mMutex.get() );
902 QStringList providerAuthMethodsKeys;
903 if ( !dataprovider.isEmpty() )
914 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1" ).arg(
authDatabaseConfigTable() ) );
916 if ( !authDbQuery( &query ) )
921 if ( query.isActive() && query.isSelect() )
923 while ( query.next() )
925 QString authcfg = query.value( 0 ).toString();
927 config.
setId( authcfg );
928 config.
setName( query.value( 1 ).toString() );
929 config.
setUri( query.value( 2 ).toString() );
930 config.
setMethod( query.value( 3 ).toString() );
931 config.
setVersion( query.value( 4 ).toInt() );
933 if ( !dataprovider.isEmpty() && !providerAuthMethodsKeys.contains( config.
method() ) )
938 baseConfigs.insert( authcfg, config );
946 QMutexLocker locker( mMutex.get() );
953 if ( !authDbQuery( &query ) )
958 if ( query.isActive() )
960 QgsDebugMsgLevel( QStringLiteral(
"Syncing existing auth config and their auth methods" ), 2 );
961 mConfigAuthMethods.clear();
962 QStringList cfgmethods;
963 while ( query.next() )
965 mConfigAuthMethods.insert( query.value( 0 ).toString(),
966 query.value( 1 ).toString() );
967 cfgmethods << QStringLiteral(
"%1=%2" ).arg( query.value( 0 ).toString(), query.value( 1 ).toString() );
969 QgsDebugMsgLevel( QStringLiteral(
"Stored auth config/methods:\n%1" ).arg( cfgmethods.join(
", " ) ), 2 );
978 if ( !mConfigAuthMethods.contains( authcfg ) )
980 QgsDebugMsg( QStringLiteral(
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
984 QString authMethodKey = mConfigAuthMethods.value( authcfg );
994 return mConfigAuthMethods.value( authcfg, QString() );
1005 if ( !mAuthMethods.contains( authMethodKey ) )
1007 QgsDebugMsg( QStringLiteral(
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
1011 return mAuthMethods.value( authMethodKey );
1016 if ( dataprovider.isEmpty() )
1018 return mAuthMethods;
1022 QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
1023 while ( i != mAuthMethods.constEnd() )
1026 && ( i.value()->supportedDataProviders().contains( QStringLiteral(
"all" ) )
1027 || i.value()->supportedDataProviders().contains( dataprovider ) ) )
1029 filteredmap.insert( i.key(), i.value() );
1044 return QgsAuthMethod::Expansions(
nullptr );
1051 return QgsAuthMethod::Expansions(
nullptr );
1056 QMutexLocker locker( mMutex.get() );
1063 const char *err = QT_TR_NOOP(
"Store config: FAILED because config is invalid" );
1069 QString uid = mconfig.
id();
1070 bool passedinID = !uid.isEmpty();
1071 if ( uid.isEmpty() )
1077 const char *err = QT_TR_NOOP(
"Store config: FAILED because pre-defined config ID is not unique" );
1084 if ( configstring.isEmpty() )
1086 const char *err = QT_TR_NOOP(
"Store config: FAILED because config string is empty" );
1092 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1093 QgsDebugMsg( QStringLiteral(
"name: %1" ).arg( config.name() ) );
1094 QgsDebugMsg( QStringLiteral(
"uri: %1" ).arg( config.uri() ) );
1095 QgsDebugMsg( QStringLiteral(
"type: %1" ).arg( config.method() ) );
1096 QgsDebugMsg( QStringLiteral(
"version: %1" ).arg( config.version() ) );
1097 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1101 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, name, uri, type, version, config) "
1104 query.bindValue( QStringLiteral(
":id" ), uid );
1105 query.bindValue( QStringLiteral(
":name" ), mconfig.
name() );
1106 query.bindValue( QStringLiteral(
":uri" ), mconfig.
uri() );
1107 query.bindValue( QStringLiteral(
":type" ), mconfig.
method() );
1108 query.bindValue( QStringLiteral(
":version" ), mconfig.
version() );
1109 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1111 if ( !authDbStartTransaction() )
1114 if ( !authDbQuery( &query ) )
1117 if ( !authDbCommit() )
1122 mconfig.
setId( uid );
1126 QgsDebugMsg( QStringLiteral(
"Store config SUCCESS for authcfg: %1" ).arg( uid ) );
1133 QMutexLocker locker( mMutex.get() );
1138 if ( !config.
isValid(
true ) )
1140 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is invalid" );
1147 if ( configstring.isEmpty() )
1149 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is empty" );
1156 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1157 QgsDebugMsg( QStringLiteral(
"id: %1" ).arg( config.
id() ) );
1162 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1166 if ( !query.prepare( QStringLiteral(
"UPDATE %1 "
1167 "SET name = :name, uri = :uri, type = :type, version = :version, config = :config "
1170 const char *err = QT_TR_NOOP(
"Update config: FAILED to prepare query" );
1176 query.bindValue( QStringLiteral(
":id" ), config.
id() );
1177 query.bindValue( QStringLiteral(
":name" ), config.
name() );
1178 query.bindValue( QStringLiteral(
":uri" ), config.
uri() );
1179 query.bindValue( QStringLiteral(
":type" ), config.
method() );
1180 query.bindValue( QStringLiteral(
":version" ), config.
version() );
1181 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1183 if ( !authDbStartTransaction() )
1186 if ( !authDbQuery( &query ) )
1189 if ( !authDbCommit() )
1197 QgsDebugMsg( QStringLiteral(
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ) );
1210 QMutexLocker locker( mMutex.get() );
1215 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version, config FROM %1 "
1220 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1 "
1224 query.bindValue( QStringLiteral(
":id" ), authcfg );
1226 if ( !authDbQuery( &query ) )
1231 if ( query.isActive() && query.isSelect() )
1233 if ( query.first() )
1235 mconfig.
setId( query.value( 0 ).toString() );
1236 mconfig.
setName( query.value( 1 ).toString() );
1237 mconfig.
setUri( query.value( 2 ).toString() );
1238 mconfig.
setMethod( query.value( 3 ).toString() );
1239 mconfig.
setVersion( query.value( 4 ).toInt() );
1254 QgsDebugMsg( QStringLiteral(
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
1257 QgsDebugMsg( QStringLiteral(
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ?
"full" :
"base", authcfg ) );
1262 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
1272 QMutexLocker locker( mMutex.get() );
1276 if ( authcfg.isEmpty() )
1283 query.bindValue( QStringLiteral(
":id" ), authcfg );
1285 if ( !authDbStartTransaction() )
1288 if ( !authDbQuery( &query ) )
1291 if ( !authDbCommit() )
1298 QgsDebugMsg( QStringLiteral(
"REMOVED config for authcfg: %1" ).arg( authcfg ) );
1305 QMutexLocker locker( mMutex.get() );
1311 bool res = authDbTransactionQuery( &query );
1319 QgsDebugMsg( QStringLiteral(
"Remove configs from database: %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
1326 QMutexLocker locker( mMutex.get() );
1329 const char *err = QT_TR_NOOP(
"No authentication database found" );
1337 if ( authConn.isValid() && authConn.isOpen() )
1341 QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral(
"yyyy-MM-dd-hhmmss" ) ) );
1343 dbbackup.replace( QLatin1String(
".db" ), QStringLiteral(
"_%1.db" ).arg( datestamp ) );
1347 const char *err = QT_TR_NOOP(
"Could not back up authentication database" );
1354 *backuppath = dbbackup;
1356 QgsDebugMsg( QStringLiteral(
"Backed up auth database at %1" ).arg( dbbackup ) );
1362 QMutexLocker locker( mMutex.get() );
1372 if ( backuppath && !dbbackup.isEmpty() )
1373 *backuppath = dbbackup;
1376 if ( dbinfo.exists() )
1378 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
1380 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
1388 const char *err = QT_TR_NOOP(
"No authentication database found" );
1396 const char *err = QT_TR_NOOP(
"Authentication database could not be deleted" );
1402 mMasterPass = QString();
1404 QgsDebugMsg( QStringLiteral(
"Creating Auth db through QSqlDatabase initial connection" ) );
1407 if ( !authConn.isValid() || !authConn.isOpen() )
1409 const char *err = QT_TR_NOOP(
"Authentication database could not be initialized" );
1415 if ( !createConfigTables() )
1417 const char *err = QT_TR_NOOP(
"FAILED to create auth database config tables" );
1423 if ( !createCertTables() )
1425 const char *err = QT_TR_NOOP(
"FAILED to create auth database cert tables" );
1441 const QString &dataprovider )
1451 QgsDebugMsg( QStringLiteral(
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
1466 const QString &dataprovider )
1476 QgsDebugMsg( QStringLiteral(
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ) );
1492 const QString &dataprovider )
1502 QgsDebugMsg( QStringLiteral(
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
1527 QgsDebugMsg( QStringLiteral(
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
1536 QgsDebugMsg( QStringLiteral(
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ) );
1545 QMutexLocker locker( mMutex.get() );
1546 if ( key.isEmpty() )
1549 QString storeval( value.toString() );
1565 query.prepare( QStringLiteral(
"INSERT INTO %1 (setting, value) "
1566 "VALUES (:setting, :value)" ).arg( authDbSettingsTable() ) );
1568 query.bindValue( QStringLiteral(
":setting" ), key );
1569 query.bindValue( QStringLiteral(
":value" ), storeval );
1571 if ( !authDbStartTransaction() )
1574 if ( !authDbQuery( &query ) )
1577 if ( !authDbCommit() )
1580 QgsDebugMsg( QStringLiteral(
"Store setting SUCCESS for key: %1" ).arg( key ) );
1586 QMutexLocker locker( mMutex.get() );
1587 if ( key.isEmpty() )
1593 QVariant value = defaultValue;
1595 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
1596 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1598 query.bindValue( QStringLiteral(
":setting" ), key );
1600 if ( !authDbQuery( &query ) )
1603 if ( query.isActive() && query.isSelect() )
1605 if ( query.first() )
1609 value = QVariant(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ) );
1613 value = query.value( 0 );
1615 QgsDebugMsg( QStringLiteral(
"Authentication setting retrieved for key: %1" ).arg( key ) );
1619 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1629 QMutexLocker locker( mMutex.get() );
1630 if ( key.isEmpty() )
1634 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
1635 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1637 query.bindValue( QStringLiteral(
":setting" ), key );
1639 if ( !authDbQuery( &query ) )
1643 if ( query.isActive() && query.isSelect() )
1645 if ( query.first() )
1647 QgsDebugMsg( QStringLiteral(
"Authentication setting exists for key: %1" ).arg( key ) );
1652 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1662 QMutexLocker locker( mMutex.get() );
1663 if ( key.isEmpty() )
1668 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1670 query.bindValue( QStringLiteral(
":setting" ), key );
1672 if ( !authDbStartTransaction() )
1675 if ( !authDbQuery( &query ) )
1678 if ( !authDbCommit() )
1681 QgsDebugMsg( QStringLiteral(
"REMOVED setting for key: %1" ).arg( key ) );
1695 QMutexLocker locker( mMutex.get() );
1701 mCustomConfigByHostCache.clear();
1702 mHasCheckedIfCustomConfigByHostExists =
false;
1705 QgsDebugMsg( QStringLiteral(
"Init of SSL caches FAILED" ) );
1711 QMutexLocker locker( mMutex.get() );
1712 if ( cert.isNull() )
1714 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
1719 QgsDebugMsg( QStringLiteral(
"Passed private key is null" ) );
1729 QString certpem( cert.toPem() );
1733 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, key, cert) "
1734 "VALUES (:id, :key, :cert)" ).arg( authDbIdentitiesTable() ) );
1736 query.bindValue( QStringLiteral(
":id" ),
id );
1737 query.bindValue( QStringLiteral(
":key" ), keypem );
1738 query.bindValue( QStringLiteral(
":cert" ), certpem );
1740 if ( !authDbStartTransaction() )
1743 if ( !authDbQuery( &query ) )
1746 if ( !authDbCommit() )
1749 QgsDebugMsgLevel( QStringLiteral(
"Store certificate identity SUCCESS for id: %1" ).arg(
id ), 2 );
1755 QMutexLocker locker( mMutex.get() );
1756 QSslCertificate emptycert;
1757 QSslCertificate cert;
1762 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
1763 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1765 query.bindValue( QStringLiteral(
":id" ),
id );
1767 if ( !authDbQuery( &query ) )
1770 if ( query.isActive() && query.isSelect() )
1772 if ( query.first() )
1774 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
1775 QgsDebugMsg( QStringLiteral(
"Certificate identity retrieved for id: %1" ).arg(
id ) );
1779 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1789 QMutexLocker locker( mMutex.get() );
1790 QPair<QSslCertificate, QSslKey> bundle;
1798 query.prepare( QStringLiteral(
"SELECT key, cert FROM %1 "
1799 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1801 query.bindValue( QStringLiteral(
":id" ),
id );
1803 if ( !authDbQuery( &query ) )
1806 if ( query.isActive() && query.isSelect() )
1808 QSslCertificate cert;
1810 if ( query.first() )
1812 key = QSslKey(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ).toLatin1(),
1813 QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
1816 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create private key" );
1821 cert = QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1822 if ( cert.isNull() )
1824 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create certificate" );
1829 QgsDebugMsg( QStringLiteral(
"Certificate identity bundle retrieved for id: %1" ).arg(
id ) );
1833 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1837 bundle = qMakePair( cert, key );
1844 QMutexLocker locker( mMutex.get() );
1848 return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
1850 return QStringList();
1855 QMutexLocker locker( mMutex.get() );
1856 QList<QSslCertificate> certs;
1859 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbIdentitiesTable() ) );
1861 if ( !authDbQuery( &query ) )
1864 if ( query.isActive() && query.isSelect() )
1866 while ( query.next() )
1868 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1877 QMutexLocker locker( mMutex.get() );
1878 QStringList identityids = QStringList();
1884 query.prepare( QStringLiteral(
"SELECT id FROM %1" ).arg( authDbIdentitiesTable() ) );
1886 if ( !authDbQuery( &query ) )
1891 if ( query.isActive() )
1893 while ( query.next() )
1895 identityids << query.value( 0 ).toString();
1903 QMutexLocker locker( mMutex.get() );
1908 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
1909 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1911 query.bindValue( QStringLiteral(
":id" ),
id );
1913 if ( !authDbQuery( &query ) )
1917 if ( query.isActive() && query.isSelect() )
1919 if ( query.first() )
1921 QgsDebugMsg( QStringLiteral(
"Certificate bundle exists for id: %1" ).arg(
id ) );
1926 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate bundle for id: %1" ).arg(
id ) );
1936 QMutexLocker locker( mMutex.get() );
1939 QgsDebugMsg( QStringLiteral(
"Passed bundle ID is empty" ) );
1945 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1947 query.bindValue( QStringLiteral(
":id" ),
id );
1949 if ( !authDbStartTransaction() )
1952 if ( !authDbQuery( &query ) )
1955 if ( !authDbCommit() )
1958 QgsDebugMsg( QStringLiteral(
"REMOVED certificate identity for id: %1" ).arg(
id ) );
1964 QMutexLocker locker( mMutex.get() );
1967 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
1976 QString certpem( cert.toPem() );
1979 query.prepare( QStringLiteral(
"INSERT OR REPLACE INTO %1 (id, host, cert, config) "
1982 query.bindValue( QStringLiteral(
":id" ),
id );
1983 query.bindValue( QStringLiteral(
":host" ), config.
sslHostPort().trimmed() );
1984 query.bindValue( QStringLiteral(
":cert" ), certpem );
1985 query.bindValue( QStringLiteral(
":config" ), config.
configString() );
1987 if ( !authDbStartTransaction() )
1990 if ( !authDbQuery( &query ) )
1993 if ( !authDbCommit() )
1996 QgsDebugMsg( QStringLiteral(
"Store SSL cert custom config SUCCESS for host:port, id: %1, %2" )
2000 mHasCheckedIfCustomConfigByHostExists =
false;
2001 mCustomConfigByHostCache.clear();
2008 QMutexLocker locker( mMutex.get() );
2011 if (
id.isEmpty() || hostport.isEmpty() )
2013 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2018 query.prepare( QStringLiteral(
"SELECT id, host, cert, config FROM %1 "
2021 query.bindValue( QStringLiteral(
":id" ),
id );
2022 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2024 if ( !authDbQuery( &query ) )
2027 if ( query.isActive() && query.isSelect() )
2029 if ( query.first() )
2031 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2034 QgsDebugMsg( QStringLiteral(
"SSL cert custom config retrieved for host:port, id: %1, %2" ).arg( hostport,
id ) );
2038 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2039 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2051 if ( hostport.isEmpty() )
2056 QMutexLocker locker( mMutex.get() );
2057 if ( mHasCheckedIfCustomConfigByHostExists && !mHasCustomConfigByHost )
2059 if ( mCustomConfigByHostCache.contains( hostport ) )
2060 return mCustomConfigByHostCache.value( hostport );
2065 if ( !mHasCheckedIfCustomConfigByHostExists )
2067 mHasCheckedIfCustomConfigByHostExists =
true;
2069 if ( !authDbQuery( &query ) )
2071 mHasCustomConfigByHost =
false;
2074 if ( query.isActive() && query.isSelect() && query.first() )
2076 mHasCustomConfigByHost = query.value( 0 ).toInt() > 0;
2077 if ( !mHasCustomConfigByHost )
2082 mHasCustomConfigByHost =
false;
2087 query.prepare( QString(
"SELECT id, host, cert, config FROM %1 "
2090 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2092 if ( !authDbQuery( &query ) )
2094 mCustomConfigByHostCache.insert( hostport, config );
2098 if ( query.isActive() && query.isSelect() )
2100 if ( query.first() )
2102 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2105 QgsDebugMsg( QStringLiteral(
"SSL cert custom config retrieved for host:port: %1" ).arg( hostport ) );
2109 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port: %1" ).arg( hostport ) );
2110 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
2113 mCustomConfigByHostCache.insert( hostport, emptyconfig );
2118 mCustomConfigByHostCache.insert( hostport, config );
2124 QMutexLocker locker( mMutex.get() );
2125 QList<QgsAuthConfigSslServer> configs;
2130 if ( !authDbQuery( &query ) )
2133 if ( query.isActive() && query.isSelect() )
2135 while ( query.next() )
2138 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2142 configs.append( config );
2151 QMutexLocker locker( mMutex.get() );
2152 if (
id.isEmpty() || hostport.isEmpty() )
2154 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2159 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
2162 query.bindValue( QStringLiteral(
":id" ),
id );
2163 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2165 if ( !authDbQuery( &query ) )
2169 if ( query.isActive() && query.isSelect() )
2171 if ( query.first() )
2173 QgsDebugMsg( QStringLiteral(
"SSL cert custom config exists for host:port, id: %1, %2" ).arg( hostport,
id ) );
2178 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2179 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2189 QMutexLocker locker( mMutex.get() );
2190 if (
id.isEmpty() || hostport.isEmpty() )
2192 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2196 mHasCheckedIfCustomConfigByHostExists =
false;
2197 mCustomConfigByHostCache.clear();
2201 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id AND host = :host" ).arg(
authDatabaseServersTable() ) );
2203 query.bindValue( QStringLiteral(
":id" ),
id );
2204 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2206 if ( !authDbStartTransaction() )
2209 if ( !authDbQuery( &query ) )
2212 if ( !authDbCommit() )
2215 QString shahostport( QStringLiteral(
"%1:%2" ).arg(
id, hostport ) );
2216 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2218 mIgnoredSslErrorsCache.remove( shahostport );
2221 QgsDebugMsg( QStringLiteral(
"REMOVED SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2228 QMutexLocker locker( mMutex.get() );
2229 if ( !mIgnoredSslErrorsCache.isEmpty() )
2231 QgsDebugMsg( QStringLiteral(
"Ignored SSL errors cache items:" ) );
2232 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
2233 while ( i != mIgnoredSslErrorsCache.constEnd() )
2236 for (
auto err : i.value() )
2240 QgsDebugMsg( QStringLiteral(
"%1 = %2" ).arg( i.key(), errs.join(
", " ) ) );
2252 QMutexLocker locker( mMutex.get() );
2255 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
2259 QString shahostport( QStringLiteral(
"%1:%2" )
2262 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2264 mIgnoredSslErrorsCache.remove( shahostport );
2267 if ( !errenums.isEmpty() )
2269 mIgnoredSslErrorsCache.insert( shahostport, qgis::listToSet( errenums ) );
2270 QgsDebugMsg( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2275 QgsDebugMsg( QStringLiteral(
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ) );
2281 QMutexLocker locker( mMutex.get() );
2282 QRegExp rx(
"\\S+:\\S+:\\d+" );
2283 if ( !rx.exactMatch( shahostport ) )
2285 QgsDebugMsg(
"Passed shahostport does not match \\S+:\\S+:\\d+, "
2286 "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
2290 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2292 mIgnoredSslErrorsCache.remove( shahostport );
2295 if ( errors.isEmpty() )
2297 QgsDebugMsg( QStringLiteral(
"Passed errors list empty" ) );
2301 QSet<QSslError::SslError> errs;
2302 for (
const auto &error : errors )
2304 if ( error.error() == QSslError::NoError )
2307 errs.insert( error.error() );
2310 if ( errs.isEmpty() )
2312 QgsDebugMsg( QStringLiteral(
"Passed errors list does not contain errors" ) );
2316 mIgnoredSslErrorsCache.insert( shahostport, errs );
2318 QgsDebugMsg( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2325 QMutexLocker locker( mMutex.get() );
2326 QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
2327 QHash<QString, QSet<QSslError::SslError> > nextcache;
2332 if ( !authDbQuery( &query ) )
2334 QgsDebugMsg( QStringLiteral(
"Rebuild of ignored SSL errors cache FAILED" ) );
2338 if ( query.isActive() && query.isSelect() )
2340 while ( query.next() )
2342 QString shahostport( QStringLiteral(
"%1:%2" )
2343 .arg( query.value( 0 ).toString().trimmed(),
2344 query.value( 1 ).toString().trimmed() ) );
2348 if ( !errenums.isEmpty() )
2350 nextcache.insert( shahostport, qgis::listToSet( errenums ) );
2352 if ( prevcache.contains( shahostport ) )
2354 prevcache.remove( shahostport );
2359 if ( !prevcache.isEmpty() )
2362 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
2363 while ( i != prevcache.constEnd() )
2365 nextcache.insert( i.key(), i.value() );
2370 if ( nextcache != mIgnoredSslErrorsCache )
2372 mIgnoredSslErrorsCache.clear();
2373 mIgnoredSslErrorsCache = nextcache;
2374 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of ignored SSL errors cache SUCCEEDED" ), 2 );
2379 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of ignored SSL errors cache SAME AS BEFORE" ), 2 );
2387 QMutexLocker locker( mMutex.get() );
2388 if ( certs.isEmpty() )
2390 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2394 for (
const auto &cert : certs )
2404 QMutexLocker locker( mMutex.get() );
2407 if ( cert.isNull() )
2409 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2416 QString pem( cert.toPem() );
2419 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, cert) "
2420 "VALUES (:id, :cert)" ).arg( authDbAuthoritiesTable() ) );
2422 query.bindValue( QStringLiteral(
":id" ),
id );
2423 query.bindValue( QStringLiteral(
":cert" ), pem );
2425 if ( !authDbStartTransaction() )
2428 if ( !authDbQuery( &query ) )
2431 if ( !authDbCommit() )
2434 QgsDebugMsg( QStringLiteral(
"Store certificate authority SUCCESS for id: %1" ).arg(
id ) );
2440 QMutexLocker locker( mMutex.get() );
2441 QSslCertificate emptycert;
2442 QSslCertificate cert;
2447 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
2448 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2450 query.bindValue( QStringLiteral(
":id" ),
id );
2452 if ( !authDbQuery( &query ) )
2455 if ( query.isActive() && query.isSelect() )
2457 if ( query.first() )
2459 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
2460 QgsDebugMsg( QStringLiteral(
"Certificate authority retrieved for id: %1" ).arg(
id ) );
2464 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2474 QMutexLocker locker( mMutex.get() );
2475 if ( cert.isNull() )
2477 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2484 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
2485 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2487 query.bindValue( QStringLiteral(
":id" ),
id );
2489 if ( !authDbQuery( &query ) )
2493 if ( query.isActive() && query.isSelect() )
2495 if ( query.first() )
2497 QgsDebugMsg( QStringLiteral(
"Certificate authority exists for id: %1" ).arg(
id ) );
2502 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2512 QMutexLocker locker( mMutex.get() );
2513 if ( cert.isNull() )
2515 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2523 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2525 query.bindValue( QStringLiteral(
":id" ),
id );
2527 if ( !authDbStartTransaction() )
2530 if ( !authDbQuery( &query ) )
2533 if ( !authDbCommit() )
2536 QgsDebugMsg( QStringLiteral(
"REMOVED authority for id: %1" ).arg(
id ) );
2542 return QSslConfiguration::systemCaCertificates();
2547 QMutexLocker locker( mMutex.get() );
2548 QList<QSslCertificate> certs;
2549 QList<QSslCertificate> filecerts;
2551 if ( cafileval.isNull() )
2555 if ( allowinvalid.isNull() )
2558 QString cafile( cafileval.toString() );
2559 if ( !cafile.isEmpty() && QFile::exists( cafile ) )
2564 for (
const auto &cert : qgis::as_const( filecerts ) )
2566 if ( !allowinvalid.toBool() && ( cert.isBlacklisted()
2568 || cert.expiryDate() <= QDateTime::currentDateTime()
2569 || cert.effectiveDate() > QDateTime::currentDateTime() ) )
2584 QMutexLocker locker( mMutex.get() );
2585 QList<QSslCertificate> certs;
2588 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbAuthoritiesTable() ) );
2590 if ( !authDbQuery( &query ) )
2593 if ( query.isActive() && query.isSelect() )
2595 while ( query.next() )
2597 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
2606 QMutexLocker locker( mMutex.get() );
2612 QMutexLocker locker( mMutex.get() );
2613 mCaCertsCache.clear();
2619 bool res = !mCaCertsCache.isEmpty();
2621 QgsDebugMsg( QStringLiteral(
"Rebuild of CA certs cache FAILED" ) );
2627 QMutexLocker locker( mMutex.get() );
2628 if ( cert.isNull() )
2630 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2640 QgsDebugMsg( QStringLiteral(
"Passed policy was default, all cert records in database were removed for id: %1" ).arg(
id ) );
2645 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, policy) "
2646 "VALUES (:id, :policy)" ).arg( authDbTrustTable() ) );
2648 query.bindValue( QStringLiteral(
":id" ),
id );
2649 query.bindValue( QStringLiteral(
":policy" ),
static_cast< int >( policy ) );
2651 if ( !authDbStartTransaction() )
2654 if ( !authDbQuery( &query ) )
2657 if ( !authDbCommit() )
2660 QgsDebugMsg( QStringLiteral(
"Store certificate trust policy SUCCESS for id: %1" ).arg(
id ) );
2666 QMutexLocker locker( mMutex.get() );
2667 if ( cert.isNull() )
2669 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2676 query.prepare( QStringLiteral(
"SELECT policy FROM %1 "
2677 "WHERE id = :id" ).arg( authDbTrustTable() ) );
2679 query.bindValue( QStringLiteral(
":id" ),
id );
2681 if ( !authDbQuery( &query ) )
2685 if ( query.isActive() && query.isSelect() )
2687 if ( query.first() )
2690 QgsDebugMsg( QStringLiteral(
"Authentication cert trust policy retrieved for id: %1" ).arg(
id ) );
2694 QgsDebugMsg( QStringLiteral(
"Select contains more than one cert trust policy for id: %1" ).arg(
id ) );
2704 QMutexLocker locker( mMutex.get() );
2705 if ( certs.empty() )
2707 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2711 for (
const auto &cert : certs )
2721 QMutexLocker locker( mMutex.get() );
2722 if ( cert.isNull() )
2724 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2732 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbTrustTable() ) );
2734 query.bindValue( QStringLiteral(
":id" ),
id );
2736 if ( !authDbStartTransaction() )
2739 if ( !authDbQuery( &query ) )
2742 if ( !authDbCommit() )
2745 QgsDebugMsg( QStringLiteral(
"REMOVED cert trust policy for id: %1" ).arg(
id ) );
2752 QMutexLocker locker( mMutex.get() );
2753 if ( cert.isNull() )
2763 if ( trustedids.contains(
id ) )
2767 else if ( untrustedids.contains(
id ) )
2782 return storeAuthSetting( QStringLiteral(
"certdefaulttrust" ),
static_cast< int >( policy ) );
2787 QMutexLocker locker( mMutex.get() );
2788 QVariant policy(
authSetting( QStringLiteral(
"certdefaulttrust" ) ) );
2789 if ( policy.isNull() )
2798 QMutexLocker locker( mMutex.get() );
2799 mCertTrustCache.clear();
2802 query.prepare( QStringLiteral(
"SELECT id, policy FROM %1" ).arg( authDbTrustTable() ) );
2804 if ( !authDbQuery( &query ) )
2806 QgsDebugMsg( QStringLiteral(
"Rebuild of cert trust policy cache FAILED" ) );
2810 if ( query.isActive() && query.isSelect() )
2812 while ( query.next() )
2814 QString
id = query.value( 0 ).toString();
2818 if ( mCertTrustCache.contains( policy ) )
2820 ids = mCertTrustCache.value( policy );
2822 mCertTrustCache.insert( policy, ids <<
id );
2826 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of cert trust policy cache SUCCEEDED" ), 2 );
2832 QMutexLocker locker( mMutex.get() );
2836 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2838 QList<QSslCertificate> trustedcerts;
2839 for (
int i = 0; i < certpairs.size(); ++i )
2841 QSslCertificate cert( certpairs.at( i ).second );
2843 if ( trustedids.contains( certid ) )
2846 trustedcerts.append( cert );
2852 trustedcerts.append( cert );
2857 QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
2858 sslconfig.setCaCertificates( trustedcerts );
2859 QSslConfiguration::setDefaultConfiguration( sslconfig );
2861 return trustedcerts;
2866 QMutexLocker locker( mMutex.get() );
2867 if ( trustedCAs.isEmpty() )
2869 if ( mTrustedCaCertsCache.isEmpty() )
2876 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2878 QList<QSslCertificate> untrustedCAs;
2879 for (
int i = 0; i < certpairs.size(); ++i )
2881 QSslCertificate cert( certpairs.at( i ).second );
2882 if ( !trustedCAs.contains( cert ) )
2884 untrustedCAs.append( cert );
2887 return untrustedCAs;
2892 QMutexLocker locker( mMutex.get() );
2894 QgsDebugMsgLevel( QStringLiteral(
"Rebuilt trusted cert authorities cache" ), 2 );
2901 QMutexLocker locker( mMutex.get() );
2907 QMutexLocker locker( mMutex.get() );
2910 return passwordHelperWrite( mMasterPass );
2926 for (
const auto &authcfg : ids )
2944 void QgsAuthManager::writeToConsole(
const QString &message,
2958 msg += QLatin1String(
"WARNING: " );
2961 msg += QLatin1String(
"ERROR: " );
2968 QTextStream out( stdout, QIODevice::WriteOnly );
2972 void QgsAuthManager::tryToStartDbErase()
2974 ++mScheduledDbEraseRequestCount;
2976 int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
2977 if ( mScheduledDbEraseRequestCount >= trycutoff )
2980 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emitting/scheduling canceled" ) );
2985 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest attempt (%1 of %2)" )
2986 .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ) );
2992 mScheduledDbEraseRequestEmitted =
true;
2997 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emitted" ) );
3000 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emit skipped" ) );
3006 QMutexLocker locker( mMutex.get() );
3007 QMapIterator<QThread *, QMetaObject::Connection> iterator( mConnectedThreads );
3008 while ( iterator.hasNext() )
3011 iterator.key()->disconnect( iterator.value() );
3018 qDeleteAll( mAuthMethods );
3021 if ( authConn.isValid() && authConn.isOpen() )
3024 delete mScheduledDbEraseTimer;
3025 mScheduledDbEraseTimer =
nullptr;
3026 QSqlDatabase::removeDatabase( QStringLiteral(
"authentication.configs" ) );
3030 QString QgsAuthManager::passwordHelperName()
const
3032 return tr(
"Password Helper" );
3036 void QgsAuthManager::passwordHelperLog(
const QString &msg )
const
3048 QKeychain::DeletePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3050 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3051 job.setAutoDelete(
false );
3052 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3054 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3059 mPasswordHelperErrorCode = job.error();
3060 mPasswordHelperErrorMessage = tr(
"Delete password failed: %1." ).arg( job.errorString() );
3071 passwordHelperProcessError();
3075 QString QgsAuthManager::passwordHelperRead()
3080 QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3082 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3083 job.setAutoDelete(
false );
3084 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3086 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3091 mPasswordHelperErrorCode = job.error();
3098 password = job.textData();
3100 if ( password.isEmpty() )
3102 mPasswordHelperErrorCode = QKeychain::EntryNotFound;
3113 passwordHelperProcessError();
3117 bool QgsAuthManager::passwordHelperWrite(
const QString &password )
3119 Q_ASSERT( !password.isEmpty() );
3122 QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3124 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3125 job.setAutoDelete(
false );
3126 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3127 job.setTextData( password );
3129 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3134 mPasswordHelperErrorCode = job.error();
3142 passwordHelperClearErrors();
3147 passwordHelperProcessError();
3155 return settings.
value( QStringLiteral(
"use_password_helper" ),
true, QgsSettings::Section::Auth ).toBool();
3161 settings.
setValue( QStringLiteral(
"use_password_helper" ), enabled, QgsSettings::Section::Auth );
3162 emit
messageOut( enabled ? tr(
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
3164 tr(
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
3172 return settings.
value( QStringLiteral(
"password_helper_logging" ),
false, QgsSettings::Section::Auth ).toBool();
3178 settings.
setValue( QStringLiteral(
"password_helper_logging" ), enabled, QgsSettings::Section::Auth );
3181 void QgsAuthManager::passwordHelperClearErrors()
3183 mPasswordHelperErrorCode = QKeychain::NoError;
3184 mPasswordHelperErrorMessage.clear();
3187 void QgsAuthManager::passwordHelperProcessError()
3189 if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
3190 mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
3191 mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
3192 mPasswordHelperErrorCode == QKeychain::NotImplemented )
3198 mPasswordHelperErrorMessage = tr(
"There was an error and integration with your %1 system has been disabled. "
3199 "You can re-enable it at any time through the \"Utilities\" menu "
3200 "in the Authentication pane of the options dialog. %2" )
3203 if ( mPasswordHelperErrorCode != QKeychain::NoError )
3209 passwordHelperClearErrors();
3213 bool QgsAuthManager::masterPasswordInput()
3219 bool storedPasswordIsValid =
false;
3225 pass = passwordHelperRead();
3226 if ( ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
3232 storedPasswordIsValid =
true;
3248 if ( ok && !pass.isEmpty() && mMasterPass != pass )
3253 if ( passwordHelperWrite( pass ) )
3267 bool QgsAuthManager::masterPasswordRowsInDb(
int *rows )
const
3273 query.prepare( QStringLiteral(
"SELECT Count(*) FROM %1" ).arg( authDbPassTable() ) );
3275 bool ok = authDbQuery( &query );
3276 if ( query.first() )
3278 *rows = query.value( 0 ).toInt();
3290 if ( !masterPasswordRowsInDb( &rows ) )
3292 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
3298 return ( rows == 1 );
3301 bool QgsAuthManager::masterPasswordCheckAgainstDb(
const QString &compare )
const
3309 query.prepare( QStringLiteral(
"SELECT salt, hash FROM %1" ).arg( authDbPassTable() ) );
3310 if ( !authDbQuery( &query ) )
3313 if ( !query.first() )
3316 QString salt = query.value( 0 ).toString();
3317 QString hash = query.value( 1 ).toString();
3322 bool QgsAuthManager::masterPasswordStoreInDb()
const
3327 QString salt, hash, civ;
3331 query.prepare( QStringLiteral(
"INSERT INTO %1 (salt, hash, civ) VALUES (:salt, :hash, :civ)" ).arg( authDbPassTable() ) );
3333 query.bindValue( QStringLiteral(
":salt" ), salt );
3334 query.bindValue( QStringLiteral(
":hash" ), hash );
3335 query.bindValue( QStringLiteral(
":civ" ), civ );
3337 if ( !authDbStartTransaction() )
3340 if ( !authDbQuery( &query ) )
3343 if ( !authDbCommit() )
3349 bool QgsAuthManager::masterPasswordClearDb()
3355 query.prepare( QStringLiteral(
"DELETE FROM %1" ).arg( authDbPassTable() ) );
3356 bool res = authDbTransactionQuery( &query );
3362 const QString QgsAuthManager::masterPasswordCiv()
const
3368 query.prepare( QStringLiteral(
"SELECT civ FROM %1" ).arg( authDbPassTable() ) );
3369 if ( !authDbQuery( &query ) )
3372 if ( !query.first() )
3375 return query.value( 0 ).toString();
3380 QStringList configids = QStringList();
3388 if ( !authDbQuery( &query ) )
3393 if ( query.isActive() )
3395 while ( query.next() )
3397 configids << query.value( 0 ).toString();
3403 bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
const
3414 if ( !authDbQuery( &query ) )
3417 if ( !query.isActive() || !query.isSelect() )
3419 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, query not active or a select operation" ) );
3424 while ( query.next() )
3427 QString configstring(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 1 ).toString() ) );
3428 if ( configstring.isEmpty() )
3430 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1)" )
3431 .arg( query.value( 0 ).toString() ) );
3436 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs SUCCESS (checked %1 configs)" ).arg( checked ) );
3440 bool QgsAuthManager::reencryptAllAuthenticationConfigs(
const QString &prevpass,
const QString &prevciv )
3447 for (
const auto &configid : ids )
3449 res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
3454 bool QgsAuthManager::reencryptAuthenticationConfig(
const QString &authcfg,
const QString &prevpass,
const QString &prevciv )
3463 query.prepare( QStringLiteral(
"SELECT config FROM %1 "
3466 query.bindValue( QStringLiteral(
":id" ), authcfg );
3468 if ( !authDbQuery( &query ) )
3471 if ( !query.isActive() || !query.isSelect() )
3473 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for authcfg: %2" ).arg( authcfg ) );
3477 if ( query.first() )
3483 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
3490 query.prepare( QStringLiteral(
"UPDATE %1 "
3491 "SET config = :config "
3494 query.bindValue( QStringLiteral(
":id" ), authcfg );
3495 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
3497 if ( !authDbStartTransaction() )
3500 if ( !authDbQuery( &query ) )
3503 if ( !authDbCommit() )
3506 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for authcfg: %2" ).arg( authcfg ) );
3511 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db authcfg: %2" ).arg( authcfg ) );
3516 bool QgsAuthManager::reencryptAllAuthenticationSettings(
const QString &prevpass,
const QString &prevciv )
3519 Q_UNUSED( prevpass )
3532 QStringList encryptedsettings;
3533 encryptedsettings <<
"";
3535 for (
const auto & sett, qgis::as_const( encryptedsettings ) )
3542 QSqlQuery query( authDbConnection() );
3544 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
3545 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3547 query.bindValue(
":setting", sett );
3549 if ( !authDbQuery( &query ) )
3552 if ( !query.isActive() || !query.isSelect() )
3554 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
3558 if ( query.first() )
3564 query.prepare( QStringLiteral(
"UPDATE %1 "
3565 "SET value = :value "
3566 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3568 query.bindValue(
":setting", sett );
3571 if ( !authDbStartTransaction() )
3574 if ( !authDbQuery( &query ) )
3577 if ( !authDbCommit() )
3580 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for setting: %2" ).arg( sett ) );
3585 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
3591 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting: %1" ).arg( sett ) );
3602 bool QgsAuthManager::reencryptAllAuthenticationIdentities(
const QString &prevpass,
const QString &prevciv )
3609 for (
const auto &identid : ids )
3611 res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
3616 bool QgsAuthManager::reencryptAuthenticationIdentity(
3617 const QString &identid,
3618 const QString &prevpass,
3619 const QString &prevciv )
3628 query.prepare( QStringLiteral(
"SELECT key FROM %1 "
3629 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3631 query.bindValue( QStringLiteral(
":id" ), identid );
3633 if ( !authDbQuery( &query ) )
3636 if ( !query.isActive() || !query.isSelect() )
3638 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for identity id: %2" ).arg( identid ) );
3642 if ( query.first() )
3648 QgsDebugMsg( QStringLiteral(
"Select contains more than one for identity id: %1" ).arg( identid ) );
3655 query.prepare( QStringLiteral(
"UPDATE %1 "
3657 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3659 query.bindValue( QStringLiteral(
":id" ), identid );
3660 query.bindValue( QStringLiteral(
":key" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), keystring ) );
3662 if ( !authDbStartTransaction() )
3665 if ( !authDbQuery( &query ) )
3668 if ( !authDbCommit() )
3671 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for identity id: %2" ).arg( identid ) );
3676 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db identity id: %2" ).arg( identid ) );
3681 bool QgsAuthManager::authDbOpen()
const
3687 if ( !authdb.isOpen() )
3689 if ( !authdb.open() )
3691 QgsDebugMsg( QStringLiteral(
"Unable to establish database connection\nDatabase: %1\nDriver error: %2\nDatabase error: %3" )
3693 authdb.lastError().driverText(),
3694 authdb.lastError().databaseText() ) );
3702 bool QgsAuthManager::authDbQuery( QSqlQuery *query )
const
3707 query->setForwardOnly(
true );
3708 if ( !query->exec() )
3710 const char *err = QT_TR_NOOP(
"Auth db query exec() FAILED" );
3716 if ( query->lastError().isValid() )
3718 QgsDebugMsg( QStringLiteral(
"Auth db query FAILED: %1\nError: %2" )
3719 .arg( query->executedQuery(),
3720 query->lastError().text() ) );
3728 bool QgsAuthManager::authDbStartTransaction()
const
3735 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3744 bool QgsAuthManager::authDbCommit()
const
3751 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3761 bool QgsAuthManager::authDbTransactionQuery( QSqlQuery *query )
const
3768 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3774 bool ok = authDbQuery( query );
3778 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3790 for (
const auto &cert : certs )
3793 QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>( source, cert ) );