23 #include <QMutexLocker>
26 #include <QSqlDatabase>
29 #include <QTextStream>
34 #include <QDomElement>
35 #include <QDomDocument>
36 #include <QRegularExpression>
38 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
39 #include <QRandomGenerator>
45 #include <QSslConfiguration>
66 const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral(
"auth_configs" );
67 const QString QgsAuthManager::AUTH_PASS_TABLE = QStringLiteral(
"auth_pass" );
68 const QString QgsAuthManager::AUTH_SETTINGS_TABLE = QStringLiteral(
"auth_settings" );
69 const QString QgsAuthManager::AUTH_IDENTITIES_TABLE = QStringLiteral(
"auth_identities" );
70 const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral(
"auth_servers" );
71 const QString QgsAuthManager::AUTH_AUTHORITIES_TABLE = QStringLiteral(
"auth_authorities" );
72 const QString QgsAuthManager::AUTH_TRUST_TABLE = QStringLiteral(
"auth_trust" );
74 const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral(
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
77 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME(
"QGIS-Master-Password" );
78 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME(
"QGIS" );
84 #elif defined(Q_OS_WIN)
86 #elif defined(Q_OS_LINUX)
95 QMutexLocker locker( &sMutex );
106 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
107 mMutex.reset(
new QMutex( QMutex::Recursive ) );
108 mMasterPasswordMutex.reset(
new QMutex( QMutex::Recursive ) );
110 mMutex = std::make_unique<QRecursiveMutex>();
111 mMasterPasswordMutex = std::make_unique<QRecursiveMutex>();
114 this, &QgsAuthManager::writeToConsole );
125 QMutexLocker locker( mMutex.get() );
130 const QString connectionName = QStringLiteral(
"authentication.configs:0x%1" ).arg(
reinterpret_cast<quintptr
>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char(
'0' ) );
131 QgsDebugMsgLevel( QStringLiteral(
"Using auth db connection name: %1 " ).arg( connectionName ), 2 );
132 if ( !QSqlDatabase::contains( connectionName ) )
134 QgsDebugMsgLevel( QStringLiteral(
"No existing connection, creating a new one" ), 2 );
135 authdb = QSqlDatabase::addDatabase( QStringLiteral(
"QSQLITE" ), connectionName );
138 if ( QThread::currentThread() != qApp->thread() )
140 QgsDebugMsgLevel( QStringLiteral(
"Scheduled auth db remove on thread close" ), 2 );
150 QMetaObject::Connection connection = connect( QThread::currentThread(), &QThread::finished, QThread::currentThread(), [connectionName,
this ]
152 QMutexLocker locker( mMutex.get() );
153 QSqlDatabase::removeDatabase( connectionName );
154 mConnectedThreads.remove( QThread::currentThread() );
155 }, Qt::DirectConnection );
157 mConnectedThreads.insert( QThread::currentThread(), connection );
163 authdb = QSqlDatabase::database( connectionName );
167 if ( !authdb.isOpen() )
169 if ( !authdb.open() )
171 QString err = tr(
"Opening of authentication db FAILED : %1" ).arg( authdb.lastError().text() );
189 mQcaInitializer = std::make_unique<QCA::Initializer>( QCA::Practical, 256 );
192 QCA::scanForPlugins();
194 QgsDebugMsgLevel( QStringLiteral(
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ), 2 );
195 QStringList capabilities;
197 capabilities = QCA::supportedFeatures();
198 QgsDebugMsgLevel( QStringLiteral(
"QCA supports: %1" ).arg( capabilities.join(
"," ) ), 2 );
201 if ( !QCA::isSupported(
"cert", QStringLiteral(
"qca-ossl" ) ) )
203 mAuthDisabled =
true;
204 mAuthDisabledMessage = tr(
"QCA's OpenSSL plugin (qca-ossl) is missing" );
208 QgsDebugMsgLevel( QStringLiteral(
"Prioritizing qca-ossl over all other QCA providers..." ), 2 );
209 const QCA::ProviderList provds = QCA::providers();
211 for ( QCA::Provider *p : provds )
213 QString pn = p->name();
215 if ( pn != QLatin1String(
"qca-ossl" ) )
217 pr = QCA::providerPriority( pn ) + 1;
219 QCA::setProviderPriority( pn, pr );
220 prlist << QStringLiteral(
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
222 QgsDebugMsgLevel( QStringLiteral(
"QCA provider priorities: %1" ).arg( prlist.join(
", " ) ), 2 );
229 QgsDebugMsgLevel( QStringLiteral(
"Authentication methods found: %1" ).arg( methods.join(
", " ) ), 2 );
231 if ( methods.isEmpty() )
233 mAuthDisabled =
true;
234 mAuthDisabledMessage = tr(
"No authentication method plugins found" );
240 mAuthDisabled =
true;
241 mAuthDisabledMessage = tr(
"No authentication method plugins could be loaded" );
245 mAuthDbPath = QDir::cleanPath( authDatabasePath );
249 QFileInfo dbdirinfo( dbinfo.path() );
250 QgsDebugMsgLevel( QStringLiteral(
"Auth db directory path: %1" ).arg( dbdirinfo.filePath() ), 2 );
252 if ( !dbdirinfo.exists() )
254 QgsDebugMsgLevel( QStringLiteral(
"Auth db directory path does not exist, making path: %1" ).arg( dbdirinfo.filePath() ), 2 );
255 if ( !QDir().mkpath( dbdirinfo.filePath() ) )
257 const char *err = QT_TR_NOOP(
"Auth db directory path could not be created" );
264 if ( dbinfo.exists() )
266 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
268 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
273 if ( dbinfo.size() > 0 )
277 if ( !createCertTables() )
287 const char *passenv =
"QGIS_AUTH_PASSWORD_FILE";
290 QString passpath( getenv( passenv ) );
299 QFile passfile( passpath );
300 if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
302 QTextStream passin( &passfile );
303 while ( !passin.atEnd() )
305 masterpass = passin.readLine();
310 if ( !masterpass.isEmpty() )
314 QgsDebugMsgLevel( QStringLiteral(
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" ), 2 );
318 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
324 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
334 QgsDebugMsgLevel( QStringLiteral(
"Auth db does not exist: creating through QSqlDatabase initial connection" ), 2 );
336 if ( !createConfigTables() )
339 if ( !createCertTables() )
350 bool QgsAuthManager::createConfigTables()
352 QMutexLocker locker( mMutex.get() );
356 const char *err = QT_TR_NOOP(
"Auth db could not be created and opened" );
367 qstr = QStringLiteral(
"CREATE TABLE %1 (\n"
368 " 'salt' TEXT NOT NULL,\n"
369 " 'civ' TEXT NOT NULL\n"
370 ", 'hash' TEXT NOT NULL);" ).arg( authDbPassTable() );
371 query.prepare( qstr );
372 if ( !authDbQuery( &query ) )
376 qstr = QStringLiteral(
"CREATE TABLE %1 (\n"
377 " 'id' TEXT NOT NULL,\n"
378 " 'name' TEXT NOT NULL,\n"
380 " 'type' TEXT NOT NULL,\n"
381 " 'version' INTEGER NOT NULL\n"
383 query.prepare( qstr );
384 if ( !authDbQuery( &query ) )
389 query.prepare( qstr );
390 if ( !authDbQuery( &query ) )
395 query.prepare( qstr );
396 if ( !authDbQuery( &query ) )
403 bool QgsAuthManager::createCertTables()
405 QMutexLocker locker( mMutex.get() );
414 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
415 " 'setting' TEXT NOT NULL\n"
416 ", 'value' TEXT);" ).arg( authDbSettingsTable() );
417 query.prepare( qstr );
418 if ( !authDbQuery( &query ) )
423 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
424 " 'id' TEXT NOT NULL,\n"
425 " 'key' TEXT NOT NULL\n"
426 ", 'cert' TEXT NOT NULL);" ).arg( authDbIdentitiesTable() );
427 query.prepare( qstr );
428 if ( !authDbQuery( &query ) )
432 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbIdentitiesTable() );
433 query.prepare( qstr );
434 if ( !authDbQuery( &query ) )
439 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
440 " 'id' TEXT NOT NULL,\n"
441 " 'host' TEXT NOT NULL,\n"
444 query.prepare( qstr );
445 if ( !authDbQuery( &query ) )
449 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'host_index' on %1 (host ASC);" ).arg(
authDatabaseServersTable() );
450 query.prepare( qstr );
451 if ( !authDbQuery( &query ) )
456 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
457 " 'id' TEXT NOT NULL\n"
458 ", 'cert' TEXT NOT NULL);" ).arg( authDbAuthoritiesTable() );
459 query.prepare( qstr );
460 if ( !authDbQuery( &query ) )
464 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbAuthoritiesTable() );
465 query.prepare( qstr );
466 if ( !authDbQuery( &query ) )
470 qstr = QStringLiteral(
"CREATE TABLE IF NOT EXISTS %1 (\n"
471 " 'id' TEXT NOT NULL\n"
472 ", 'policy' TEXT NOT NULL);" ).arg( authDbTrustTable() );
473 query.prepare( qstr );
474 if ( !authDbQuery( &query ) )
478 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbTrustTable() );
479 query.prepare( qstr );
480 if ( !authDbQuery( &query ) )
491 QgsDebugMsg( QStringLiteral(
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" ) );
493 return mAuthDisabled;
498 return tr(
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
503 QMutexLocker locker( mMasterPasswordMutex.get() );
507 if ( mScheduledDbErase )
510 if ( mMasterPass.isEmpty() )
512 QgsDebugMsgLevel( QStringLiteral(
"Master password is not yet set by user" ), 2 );
513 if ( !masterPasswordInput() )
515 QgsDebugMsgLevel( QStringLiteral(
"Master password input canceled by user" ), 2 );
529 QgsDebugMsgLevel( QStringLiteral(
"Master password is set and verified" ), 2 );
535 QMutexLocker locker( mMutex.get() );
539 if ( mScheduledDbErase )
543 QString prevpass = QString( mMasterPass );
547 mMasterPass = prevpass;
548 const char *err = QT_TR_NOOP(
"Master password set: FAILED to verify, reset to previous" );
554 QgsDebugMsgLevel( QStringLiteral(
"Master password set: SUCCESS%1" ).arg( verify ?
" and verified" :
"" ), 2 );
564 if ( !masterPasswordRowsInDb( &rows ) )
566 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
574 QgsDebugMsgLevel( QStringLiteral(
"Master password: %1 rows in database" ).arg( rows ), 2 );
578 const char *err = QT_TR_NOOP(
"Master password: FAILED to find just one master password record in database" );
585 else if ( rows == 1 )
587 if ( !masterPasswordCheckAgainstDb( compare ) )
589 if ( compare.isNull() )
591 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
600 if ( mPassTries >= 5 )
602 mAuthDisabled =
true;
603 const char *err = QT_TR_NOOP(
"Master password: failed 5 times authentication system DISABLED" );
611 QgsDebugMsgLevel( QStringLiteral(
"Master password: verified against hash in database" ), 2 );
612 if ( compare.isNull() )
616 else if ( compare.isNull() )
618 if ( !masterPasswordStoreInDb() )
620 const char *err = QT_TR_NOOP(
"Master password: hash FAILED to be stored in database" );
629 QgsDebugMsgLevel( QStringLiteral(
"Master password: hash stored in database" ), 2 );
632 if ( !masterPasswordCheckAgainstDb() )
634 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
644 QgsDebugMsgLevel( QStringLiteral(
"Master password: verified against hash in database" ), 2 );
654 return !mMasterPass.isEmpty();
659 return mMasterPass == pass;
663 bool keepbackup, QString *backuppath )
677 QgsDebugMsgLevel( QStringLiteral(
"Master password reset: backed up current database" ), 2 );
683 QString prevpass = QString( mMasterPass );
684 QString prevciv = QString( masterPasswordCiv() );
690 if ( ok && !masterPasswordClearDb() )
693 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not clear current password from database" );
699 QgsDebugMsgLevel( QStringLiteral(
"Master password reset: cleared current password from database" ), 2 );
706 if ( ok && !masterPasswordStoreInDb() )
709 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not store new password in database" );
715 QgsDebugMsgLevel( QStringLiteral(
"Master password reset: stored new password in database" ), 2 );
722 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify new password in database" );
728 if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
731 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt configs in database" );
737 QgsDebugMsgLevel( QStringLiteral(
"Master password reset: re-encrypted configs in database" ), 2 );
741 if ( ok && !verifyPasswordCanDecryptConfigs() )
744 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
749 if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
752 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt settings in database" );
757 if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
760 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt identities in database" );
770 QString errdbbackup( dbbackup );
771 errdbbackup.replace( QLatin1String(
".db" ), QLatin1String(
"_ERROR.db" ) );
773 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
777 mMasterPass = prevpass;
779 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: reinstated previous password and database" ) );
783 *backuppath = errdbbackup;
789 if ( !keepbackup && !QFile::remove( dbbackup ) )
791 const char *err = QT_TR_NOOP(
"Master password reset: could not remove old database backup" );
799 QgsDebugMsgLevel( QStringLiteral(
"Master password reset: backed up previous db at %1" ).arg( dbbackup ), 2 );
801 *backuppath = dbbackup;
811 mScheduledDbErase = scheduleErase;
813 mScheduledDbEraseRequestEmitted =
false;
814 mScheduledDbEraseRequestCount = 0;
818 if ( !mScheduledDbEraseTimer )
820 mScheduledDbEraseTimer =
new QTimer(
this );
821 connect( mScheduledDbEraseTimer, &QTimer::timeout,
this, &QgsAuthManager::tryToStartDbErase );
822 mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
824 else if ( !mScheduledDbEraseTimer->isActive() )
826 mScheduledDbEraseTimer->start();
831 if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
832 mScheduledDbEraseTimer->stop();
841 qDeleteAll( mAuthMethods );
842 mAuthMethods.clear();
844 for (
const auto &authMethodKey : methods )
849 return !mAuthMethods.isEmpty();
859 QTimer::singleShot( 3, &loop, &QEventLoop::quit );
862 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
863 uint seed =
static_cast< uint
>( QTime::currentTime().msec() );
870 for (
int i = 0; i < len; i++ )
872 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
873 switch ( qrand() % 2 )
875 switch ( QRandomGenerator::system()->generate() % 2 )
879 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
880 id += (
'0' + qrand() % 10 );
882 id +=
static_cast<char>(
'0' + QRandomGenerator::system()->generate() % 10 );
886 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
887 id += (
'a' + qrand() % 26 );
889 id +=
static_cast<char>(
'a' + QRandomGenerator::system()->generate() % 26 );
894 if ( !configids.contains(
id ) )
899 QgsDebugMsgLevel( QStringLiteral(
"Generated unique ID: %1" ).arg(
id ), 2 );
910 const char *err = QT_TR_NOOP(
"Config ID is empty" );
916 return !configids.contains(
id );
921 const thread_local QRegularExpression authCfgRegExp( AUTH_CFG_REGEX );
922 return txt.indexOf( authCfgRegExp ) != -1;
927 QMutexLocker locker( mMutex.get() );
928 QStringList providerAuthMethodsKeys;
929 if ( !dataprovider.isEmpty() )
940 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1" ).arg(
authDatabaseConfigTable() ) );
942 if ( !authDbQuery( &query ) )
947 if ( query.isActive() && query.isSelect() )
949 while ( query.next() )
951 QString authcfg = query.value( 0 ).toString();
953 config.
setId( authcfg );
954 config.
setName( query.value( 1 ).toString() );
955 config.
setUri( query.value( 2 ).toString() );
956 config.
setMethod( query.value( 3 ).toString() );
957 config.
setVersion( query.value( 4 ).toInt() );
959 if ( !dataprovider.isEmpty() && !providerAuthMethodsKeys.contains( config.
method() ) )
964 baseConfigs.insert( authcfg, config );
972 QMutexLocker locker( mMutex.get() );
979 if ( !authDbQuery( &query ) )
984 if ( query.isActive() )
986 QgsDebugMsgLevel( QStringLiteral(
"Syncing existing auth config and their auth methods" ), 2 );
987 mConfigAuthMethods.clear();
988 QStringList cfgmethods;
989 while ( query.next() )
991 mConfigAuthMethods.insert( query.value( 0 ).toString(),
992 query.value( 1 ).toString() );
993 cfgmethods << QStringLiteral(
"%1=%2" ).arg( query.value( 0 ).toString(), query.value( 1 ).toString() );
995 QgsDebugMsgLevel( QStringLiteral(
"Stored auth config/methods:\n%1" ).arg( cfgmethods.join(
", " ) ), 2 );
1004 if ( !mConfigAuthMethods.contains( authcfg ) )
1006 QgsDebugMsg( QStringLiteral(
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
1010 QString authMethodKey = mConfigAuthMethods.value( authcfg );
1020 return mConfigAuthMethods.value( authcfg, QString() );
1031 if ( !mAuthMethods.contains( authMethodKey ) )
1033 QgsDebugMsg( QStringLiteral(
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
1037 return mAuthMethods.value( authMethodKey );
1042 if ( !mAuthMethods.contains( authMethodKey ) )
1044 QgsDebugMsg( QStringLiteral(
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
1054 if ( dataprovider.isEmpty() )
1056 return mAuthMethods;
1060 QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
1061 while ( i != mAuthMethods.constEnd() )
1064 && ( i.value()->supportedDataProviders().contains( QStringLiteral(
"all" ) )
1065 || i.value()->supportedDataProviders().contains( dataprovider ) ) )
1067 filteredmap.insert( i.key(), i.value() );
1075 QWidget *QgsAuthManager::authMethodEditWidget(
const QString &authMethodKey, QWidget *parent )
1079 return method->editWidget( parent );
1088 return QgsAuthMethod::Expansions();
1095 return QgsAuthMethod::Expansions();
1100 QMutexLocker locker( mMutex.get() );
1107 const char *err = QT_TR_NOOP(
"Store config: FAILED because config is invalid" );
1113 QString uid = mconfig.
id();
1114 bool passedinID = !uid.isEmpty();
1115 if ( uid.isEmpty() )
1123 const char *err = QT_TR_NOOP(
"Store config: FAILED because pre-defined config ID %1 is not unique" );
1134 if ( configstring.isEmpty() )
1136 const char *err = QT_TR_NOOP(
"Store config: FAILED because config string is empty" );
1142 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1143 QgsDebugMsg( QStringLiteral(
"name: %1" ).arg( config.name() ) );
1144 QgsDebugMsg( QStringLiteral(
"uri: %1" ).arg( config.uri() ) );
1145 QgsDebugMsg( QStringLiteral(
"type: %1" ).arg( config.method() ) );
1146 QgsDebugMsg( QStringLiteral(
"version: %1" ).arg( config.version() ) );
1147 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1151 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, name, uri, type, version, config) "
1154 query.bindValue( QStringLiteral(
":id" ), uid );
1155 query.bindValue( QStringLiteral(
":name" ), mconfig.
name() );
1156 query.bindValue( QStringLiteral(
":uri" ), mconfig.
uri() );
1157 query.bindValue( QStringLiteral(
":type" ), mconfig.
method() );
1158 query.bindValue( QStringLiteral(
":version" ), mconfig.
version() );
1159 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1161 if ( !authDbStartTransaction() )
1164 if ( !authDbQuery( &query ) )
1167 if ( !authDbCommit() )
1172 mconfig.
setId( uid );
1176 QgsDebugMsgLevel( QStringLiteral(
"Store config SUCCESS for authcfg: %1" ).arg( uid ), 2 );
1182 QMutexLocker locker( mMutex.get() );
1187 if ( !config.
isValid(
true ) )
1189 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is invalid" );
1196 if ( configstring.isEmpty() )
1198 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is empty" );
1205 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1206 QgsDebugMsg( QStringLiteral(
"id: %1" ).arg( config.
id() ) );
1211 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1215 if ( !query.prepare( QStringLiteral(
"UPDATE %1 "
1216 "SET name = :name, uri = :uri, type = :type, version = :version, config = :config "
1219 const char *err = QT_TR_NOOP(
"Update config: FAILED to prepare query" );
1225 query.bindValue( QStringLiteral(
":id" ), config.
id() );
1226 query.bindValue( QStringLiteral(
":name" ), config.
name() );
1227 query.bindValue( QStringLiteral(
":uri" ), config.
uri() );
1228 query.bindValue( QStringLiteral(
":type" ), config.
method() );
1229 query.bindValue( QStringLiteral(
":version" ), config.
version() );
1230 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1232 if ( !authDbStartTransaction() )
1235 if ( !authDbQuery( &query ) )
1238 if ( !authDbCommit() )
1246 QgsDebugMsgLevel( QStringLiteral(
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ), 2 );
1259 QMutexLocker locker( mMutex.get() );
1264 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version, config FROM %1 "
1269 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1 "
1273 query.bindValue( QStringLiteral(
":id" ), authcfg );
1275 if ( !authDbQuery( &query ) )
1280 if ( query.isActive() && query.isSelect() )
1282 if ( query.first() )
1284 mconfig.
setId( query.value( 0 ).toString() );
1285 mconfig.
setName( query.value( 1 ).toString() );
1286 mconfig.
setUri( query.value( 2 ).toString() );
1287 mconfig.
setMethod( query.value( 3 ).toString() );
1288 mconfig.
setVersion( query.value( 4 ).toInt() );
1303 QgsDebugMsg( QStringLiteral(
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
1306 QgsDebugMsgLevel( QStringLiteral(
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ?
"full" :
"base", authcfg ), 2 );
1311 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
1321 QMutexLocker locker( mMutex.get() );
1325 if ( authcfg.isEmpty() )
1332 query.bindValue( QStringLiteral(
":id" ), authcfg );
1334 if ( !authDbStartTransaction() )
1337 if ( !authDbQuery( &query ) )
1340 if ( !authDbCommit() )
1347 QgsDebugMsgLevel( QStringLiteral(
"REMOVED config for authcfg: %1" ).arg( authcfg ), 2 );
1354 if ( filename.isEmpty() )
1357 QDomDocument document( QStringLiteral(
"qgis_authentication" ) );
1358 QDomElement root = document.createElement( QStringLiteral(
"qgis_authentication" ) );
1359 document.appendChild( root );
1362 if ( !password.isEmpty() )
1367 root.setAttribute( QStringLiteral(
"salt" ), salt );
1368 root.setAttribute( QStringLiteral(
"hash" ), hash );
1369 root.setAttribute( QStringLiteral(
"civ" ), civ );
1372 QDomElement configurations = document.createElement( QStringLiteral(
"configurations" ) );
1373 for (
const QString &authcfg : authcfgs )
1380 authMethodConfig.
writeXml( configurations, document );
1383 if ( !password.isEmpty() )
1385 QString configurationsString;
1386 QTextStream ts( &configurationsString );
1387 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1388 ts.setCodec(
"UTF-8" );
1390 configurations.save( ts, 2 );
1391 root.appendChild( document.createTextNode(
QgsAuthCrypto::encrypt( password, civ, configurationsString ) ) );
1395 root.appendChild( configurations );
1398 QFile file( filename );
1399 if ( !file.open( QFile::WriteOnly | QIODevice::Truncate ) )
1402 QTextStream ts( &file );
1403 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1404 ts.setCodec(
"UTF-8" );
1406 document.save( ts, 2 );
1413 QFile file( filename );
1414 if ( !file.open( QFile::ReadOnly ) )
1419 QDomDocument document( QStringLiteral(
"qgis_authentication" ) );
1420 if ( !document.setContent( &file ) )
1427 QDomElement root = document.documentElement();
1428 if ( root.tagName() != QLatin1String(
"qgis_authentication" ) )
1433 QDomElement configurations;
1434 if ( root.hasAttribute( QStringLiteral(
"salt" ) ) )
1436 QString salt = root.attribute( QStringLiteral(
"salt" ) );
1437 QString hash = root.attribute( QStringLiteral(
"hash" ) );
1438 QString civ = root.attribute( QStringLiteral(
"civ" ) );
1443 configurations = document.firstChild().toElement();
1447 configurations = root.firstChildElement( QStringLiteral(
"configurations" ) );
1450 QDomElement configuration = configurations.firstChildElement();
1451 while ( !configuration.isNull() )
1454 authMethodConfig.
readXml( configuration );
1457 configuration = configuration.nextSiblingElement();
1464 QMutexLocker locker( mMutex.get() );
1470 bool res = authDbTransactionQuery( &query );
1478 QgsDebugMsgLevel( QStringLiteral(
"Remove configs from database: %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ), 2 );
1485 QMutexLocker locker( mMutex.get() );
1488 const char *err = QT_TR_NOOP(
"No authentication database found" );
1496 if ( authConn.isValid() && authConn.isOpen() )
1500 QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral(
"yyyy-MM-dd-hhmmss" ) ) );
1502 dbbackup.replace( QLatin1String(
".db" ), QStringLiteral(
"_%1.db" ).arg( datestamp ) );
1506 const char *err = QT_TR_NOOP(
"Could not back up authentication database" );
1513 *backuppath = dbbackup;
1515 QgsDebugMsgLevel( QStringLiteral(
"Backed up auth database at %1" ).arg( dbbackup ), 2 );
1521 QMutexLocker locker( mMutex.get() );
1531 if ( backuppath && !dbbackup.isEmpty() )
1532 *backuppath = dbbackup;
1535 if ( dbinfo.exists() )
1537 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
1539 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
1547 const char *err = QT_TR_NOOP(
"No authentication database found" );
1555 const char *err = QT_TR_NOOP(
"Authentication database could not be deleted" );
1561 mMasterPass = QString();
1563 QgsDebugMsgLevel( QStringLiteral(
"Creating Auth db through QSqlDatabase initial connection" ), 2 );
1566 if ( !authConn.isValid() || !authConn.isOpen() )
1568 const char *err = QT_TR_NOOP(
"Authentication database could not be initialized" );
1574 if ( !createConfigTables() )
1576 const char *err = QT_TR_NOOP(
"FAILED to create auth database config tables" );
1582 if ( !createCertTables() )
1584 const char *err = QT_TR_NOOP(
"FAILED to create auth database cert tables" );
1600 const QString &dataprovider )
1610 QgsDebugMsg( QStringLiteral(
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
1625 const QString &dataprovider )
1635 QgsDebugMsg( QStringLiteral(
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ) );
1651 const QString &dataprovider )
1661 QgsDebugMsg( QStringLiteral(
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
1686 QgsDebugMsg( QStringLiteral(
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
1695 QgsDebugMsgLevel( QStringLiteral(
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ), 2 );
1704 QMutexLocker locker( mMutex.get() );
1705 if ( key.isEmpty() )
1708 QString storeval( value.toString() );
1724 query.prepare( QStringLiteral(
"INSERT INTO %1 (setting, value) "
1725 "VALUES (:setting, :value)" ).arg( authDbSettingsTable() ) );
1727 query.bindValue( QStringLiteral(
":setting" ), key );
1728 query.bindValue( QStringLiteral(
":value" ), storeval );
1730 if ( !authDbStartTransaction() )
1733 if ( !authDbQuery( &query ) )
1736 if ( !authDbCommit() )
1739 QgsDebugMsgLevel( QStringLiteral(
"Store setting SUCCESS for key: %1" ).arg( key ), 2 );
1745 QMutexLocker locker( mMutex.get() );
1746 if ( key.isEmpty() )
1752 QVariant value = defaultValue;
1754 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
1755 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1757 query.bindValue( QStringLiteral(
":setting" ), key );
1759 if ( !authDbQuery( &query ) )
1762 if ( query.isActive() && query.isSelect() )
1764 if ( query.first() )
1768 value = QVariant(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ) );
1772 value = query.value( 0 );
1774 QgsDebugMsgLevel( QStringLiteral(
"Authentication setting retrieved for key: %1" ).arg( key ), 2 );
1778 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1788 QMutexLocker locker( mMutex.get() );
1789 if ( key.isEmpty() )
1793 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
1794 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1796 query.bindValue( QStringLiteral(
":setting" ), key );
1798 if ( !authDbQuery( &query ) )
1802 if ( query.isActive() && query.isSelect() )
1804 if ( query.first() )
1806 QgsDebugMsgLevel( QStringLiteral(
"Authentication setting exists for key: %1" ).arg( key ), 2 );
1811 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1821 QMutexLocker locker( mMutex.get() );
1822 if ( key.isEmpty() )
1827 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1829 query.bindValue( QStringLiteral(
":setting" ), key );
1831 if ( !authDbStartTransaction() )
1834 if ( !authDbQuery( &query ) )
1837 if ( !authDbCommit() )
1840 QgsDebugMsgLevel( QStringLiteral(
"REMOVED setting for key: %1" ).arg( key ), 2 );
1854 QMutexLocker locker( mMutex.get() );
1860 mCustomConfigByHostCache.clear();
1861 mHasCheckedIfCustomConfigByHostExists =
false;
1864 QgsDebugMsg( QStringLiteral(
"Init of SSL caches FAILED" ) );
1870 QMutexLocker locker( mMutex.get() );
1871 if ( cert.isNull() )
1873 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
1878 QgsDebugMsg( QStringLiteral(
"Passed private key is null" ) );
1888 QString certpem( cert.toPem() );
1892 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, key, cert) "
1893 "VALUES (:id, :key, :cert)" ).arg( authDbIdentitiesTable() ) );
1895 query.bindValue( QStringLiteral(
":id" ),
id );
1896 query.bindValue( QStringLiteral(
":key" ), keypem );
1897 query.bindValue( QStringLiteral(
":cert" ), certpem );
1899 if ( !authDbStartTransaction() )
1902 if ( !authDbQuery( &query ) )
1905 if ( !authDbCommit() )
1908 QgsDebugMsgLevel( QStringLiteral(
"Store certificate identity SUCCESS for id: %1" ).arg(
id ), 2 );
1914 QMutexLocker locker( mMutex.get() );
1915 QSslCertificate emptycert;
1916 QSslCertificate cert;
1921 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
1922 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1924 query.bindValue( QStringLiteral(
":id" ),
id );
1926 if ( !authDbQuery( &query ) )
1929 if ( query.isActive() && query.isSelect() )
1931 if ( query.first() )
1933 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
1934 QgsDebugMsgLevel( QStringLiteral(
"Certificate identity retrieved for id: %1" ).arg(
id ), 2 );
1938 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1948 QMutexLocker locker( mMutex.get() );
1949 QPair<QSslCertificate, QSslKey> bundle;
1957 query.prepare( QStringLiteral(
"SELECT key, cert FROM %1 "
1958 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1960 query.bindValue( QStringLiteral(
":id" ),
id );
1962 if ( !authDbQuery( &query ) )
1965 if ( query.isActive() && query.isSelect() )
1967 QSslCertificate cert;
1969 if ( query.first() )
1971 key = QSslKey(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ).toLatin1(),
1972 QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
1975 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create private key" );
1980 cert = QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1981 if ( cert.isNull() )
1983 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create certificate" );
1988 QgsDebugMsgLevel( QStringLiteral(
"Certificate identity bundle retrieved for id: %1" ).arg(
id ), 2 );
1992 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1996 bundle = qMakePair( cert, key );
2003 QMutexLocker locker( mMutex.get() );
2007 return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
2009 return QStringList();
2014 QMutexLocker locker( mMutex.get() );
2015 QList<QSslCertificate> certs;
2018 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbIdentitiesTable() ) );
2020 if ( !authDbQuery( &query ) )
2023 if ( query.isActive() && query.isSelect() )
2025 while ( query.next() )
2027 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
2036 QMutexLocker locker( mMutex.get() );
2037 QStringList identityids = QStringList();
2043 query.prepare( QStringLiteral(
"SELECT id FROM %1" ).arg( authDbIdentitiesTable() ) );
2045 if ( !authDbQuery( &query ) )
2050 if ( query.isActive() )
2052 while ( query.next() )
2054 identityids << query.value( 0 ).toString();
2062 QMutexLocker locker( mMutex.get() );
2067 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
2068 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
2070 query.bindValue( QStringLiteral(
":id" ),
id );
2072 if ( !authDbQuery( &query ) )
2076 if ( query.isActive() && query.isSelect() )
2078 if ( query.first() )
2080 QgsDebugMsgLevel( QStringLiteral(
"Certificate bundle exists for id: %1" ).arg(
id ), 2 );
2085 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate bundle for id: %1" ).arg(
id ) );
2095 QMutexLocker locker( mMutex.get() );
2098 QgsDebugMsg( QStringLiteral(
"Passed bundle ID is empty" ) );
2104 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
2106 query.bindValue( QStringLiteral(
":id" ),
id );
2108 if ( !authDbStartTransaction() )
2111 if ( !authDbQuery( &query ) )
2114 if ( !authDbCommit() )
2117 QgsDebugMsgLevel( QStringLiteral(
"REMOVED certificate identity for id: %1" ).arg(
id ), 2 );
2123 QMutexLocker locker( mMutex.get() );
2126 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
2135 QString certpem( cert.toPem() );
2138 query.prepare( QStringLiteral(
"INSERT OR REPLACE INTO %1 (id, host, cert, config) "
2141 query.bindValue( QStringLiteral(
":id" ),
id );
2142 query.bindValue( QStringLiteral(
":host" ), config.
sslHostPort().trimmed() );
2143 query.bindValue( QStringLiteral(
":cert" ), certpem );
2144 query.bindValue( QStringLiteral(
":config" ), config.
configString() );
2146 if ( !authDbStartTransaction() )
2149 if ( !authDbQuery( &query ) )
2152 if ( !authDbCommit() )
2155 QgsDebugMsgLevel( QStringLiteral(
"Store SSL cert custom config SUCCESS for host:port, id: %1, %2" )
2159 mHasCheckedIfCustomConfigByHostExists =
false;
2160 mCustomConfigByHostCache.clear();
2167 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 id, host, cert, config FROM %1 "
2180 query.bindValue( QStringLiteral(
":id" ),
id );
2181 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2183 if ( !authDbQuery( &query ) )
2186 if ( query.isActive() && query.isSelect() )
2188 if ( query.first() )
2190 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2193 QgsDebugMsgLevel( QStringLiteral(
"SSL cert custom config retrieved for host:port, id: %1, %2" ).arg( hostport,
id ), 2 );
2197 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2198 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2210 if ( hostport.isEmpty() )
2215 QMutexLocker locker( mMutex.get() );
2216 if ( mHasCheckedIfCustomConfigByHostExists && !mHasCustomConfigByHost )
2218 if ( mCustomConfigByHostCache.contains( hostport ) )
2219 return mCustomConfigByHostCache.value( hostport );
2224 if ( !mHasCheckedIfCustomConfigByHostExists )
2226 mHasCheckedIfCustomConfigByHostExists =
true;
2228 if ( !authDbQuery( &query ) )
2230 mHasCustomConfigByHost =
false;
2233 if ( query.isActive() && query.isSelect() && query.first() )
2235 mHasCustomConfigByHost = query.value( 0 ).toInt() > 0;
2236 if ( !mHasCustomConfigByHost )
2241 mHasCustomConfigByHost =
false;
2246 query.prepare( QString(
"SELECT id, host, cert, config FROM %1 "
2249 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2251 if ( !authDbQuery( &query ) )
2253 mCustomConfigByHostCache.insert( hostport, config );
2257 if ( query.isActive() && query.isSelect() )
2259 if ( query.first() )
2261 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2264 QgsDebugMsgLevel( QStringLiteral(
"SSL cert custom config retrieved for host:port: %1" ).arg( hostport ), 2 );
2268 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port: %1" ).arg( hostport ) );
2269 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
2272 mCustomConfigByHostCache.insert( hostport, emptyconfig );
2277 mCustomConfigByHostCache.insert( hostport, config );
2283 QMutexLocker locker( mMutex.get() );
2284 QList<QgsAuthConfigSslServer> configs;
2289 if ( !authDbQuery( &query ) )
2292 if ( query.isActive() && query.isSelect() )
2294 while ( query.next() )
2297 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2301 configs.append( config );
2310 QMutexLocker locker( mMutex.get() );
2311 if (
id.isEmpty() || hostport.isEmpty() )
2313 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2318 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
2321 query.bindValue( QStringLiteral(
":id" ),
id );
2322 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2324 if ( !authDbQuery( &query ) )
2328 if ( query.isActive() && query.isSelect() )
2330 if ( query.first() )
2332 QgsDebugMsgLevel( QStringLiteral(
"SSL cert custom config exists for host:port, id: %1, %2" ).arg( hostport,
id ), 2 );
2337 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2338 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2348 QMutexLocker locker( mMutex.get() );
2349 if (
id.isEmpty() || hostport.isEmpty() )
2351 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2355 mHasCheckedIfCustomConfigByHostExists =
false;
2356 mCustomConfigByHostCache.clear();
2360 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id AND host = :host" ).arg(
authDatabaseServersTable() ) );
2362 query.bindValue( QStringLiteral(
":id" ),
id );
2363 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2365 if ( !authDbStartTransaction() )
2368 if ( !authDbQuery( &query ) )
2371 if ( !authDbCommit() )
2374 QString shahostport( QStringLiteral(
"%1:%2" ).arg(
id, hostport ) );
2375 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2377 mIgnoredSslErrorsCache.remove( shahostport );
2380 QgsDebugMsgLevel( QStringLiteral(
"REMOVED SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ), 2 );
2387 QMutexLocker locker( mMutex.get() );
2388 if ( !mIgnoredSslErrorsCache.isEmpty() )
2390 QgsDebugMsg( QStringLiteral(
"Ignored SSL errors cache items:" ) );
2391 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
2392 while ( i != mIgnoredSslErrorsCache.constEnd() )
2395 for (
auto err : i.value() )
2399 QgsDebugMsg( QStringLiteral(
"%1 = %2" ).arg( i.key(), errs.join(
", " ) ) );
2411 QMutexLocker locker( mMutex.get() );
2414 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
2418 QString shahostport( QStringLiteral(
"%1:%2" )
2421 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2423 mIgnoredSslErrorsCache.remove( shahostport );
2426 if ( !errenums.isEmpty() )
2428 mIgnoredSslErrorsCache.insert( shahostport, qgis::listToSet( errenums ) );
2429 QgsDebugMsgLevel( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
2434 QgsDebugMsgLevel( QStringLiteral(
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ), 2 );
2440 QMutexLocker locker( mMutex.get() );
2441 const thread_local QRegularExpression rx( QRegularExpression::anchoredPattern(
"\\S+:\\S+:\\d+" ) );
2442 if ( !rx.match( shahostport ).hasMatch() )
2444 QgsDebugMsg(
"Passed shahostport does not match \\S+:\\S+:\\d+, "
2445 "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
2449 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2451 mIgnoredSslErrorsCache.remove( shahostport );
2454 if ( errors.isEmpty() )
2456 QgsDebugMsg( QStringLiteral(
"Passed errors list empty" ) );
2460 QSet<QSslError::SslError> errs;
2461 for (
const auto &error : errors )
2463 if ( error.error() == QSslError::NoError )
2466 errs.insert( error.error() );
2469 if ( errs.isEmpty() )
2471 QgsDebugMsg( QStringLiteral(
"Passed errors list does not contain errors" ) );
2475 mIgnoredSslErrorsCache.insert( shahostport, errs );
2477 QgsDebugMsgLevel( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
2484 QMutexLocker locker( mMutex.get() );
2485 QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
2486 QHash<QString, QSet<QSslError::SslError> > nextcache;
2491 if ( !authDbQuery( &query ) )
2493 QgsDebugMsg( QStringLiteral(
"Rebuild of ignored SSL errors cache FAILED" ) );
2497 if ( query.isActive() && query.isSelect() )
2499 while ( query.next() )
2501 QString shahostport( QStringLiteral(
"%1:%2" )
2502 .arg( query.value( 0 ).toString().trimmed(),
2503 query.value( 1 ).toString().trimmed() ) );
2507 if ( !errenums.isEmpty() )
2509 nextcache.insert( shahostport, qgis::listToSet( errenums ) );
2511 if ( prevcache.contains( shahostport ) )
2513 prevcache.remove( shahostport );
2518 if ( !prevcache.isEmpty() )
2521 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
2522 while ( i != prevcache.constEnd() )
2524 nextcache.insert( i.key(), i.value() );
2529 if ( nextcache != mIgnoredSslErrorsCache )
2531 mIgnoredSslErrorsCache.clear();
2532 mIgnoredSslErrorsCache = nextcache;
2533 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of ignored SSL errors cache SUCCEEDED" ), 2 );
2538 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of ignored SSL errors cache SAME AS BEFORE" ), 2 );
2546 QMutexLocker locker( mMutex.get() );
2547 if ( certs.isEmpty() )
2549 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2553 for (
const auto &cert : certs )
2563 QMutexLocker locker( mMutex.get() );
2566 if ( cert.isNull() )
2568 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2575 QString pem( cert.toPem() );
2578 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, cert) "
2579 "VALUES (:id, :cert)" ).arg( authDbAuthoritiesTable() ) );
2581 query.bindValue( QStringLiteral(
":id" ),
id );
2582 query.bindValue( QStringLiteral(
":cert" ), pem );
2584 if ( !authDbStartTransaction() )
2587 if ( !authDbQuery( &query ) )
2590 if ( !authDbCommit() )
2593 QgsDebugMsgLevel( QStringLiteral(
"Store certificate authority SUCCESS for id: %1" ).arg(
id ), 2 );
2599 QMutexLocker locker( mMutex.get() );
2600 QSslCertificate emptycert;
2601 QSslCertificate cert;
2606 query.prepare( QStringLiteral(
"SELECT cert FROM %1 "
2607 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2609 query.bindValue( QStringLiteral(
":id" ),
id );
2611 if ( !authDbQuery( &query ) )
2614 if ( query.isActive() && query.isSelect() )
2616 if ( query.first() )
2618 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
2619 QgsDebugMsgLevel( QStringLiteral(
"Certificate authority retrieved for id: %1" ).arg(
id ), 2 );
2623 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2633 QMutexLocker locker( mMutex.get() );
2634 if ( cert.isNull() )
2636 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2643 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
2644 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2646 query.bindValue( QStringLiteral(
":id" ),
id );
2648 if ( !authDbQuery( &query ) )
2652 if ( query.isActive() && query.isSelect() )
2654 if ( query.first() )
2656 QgsDebugMsgLevel( QStringLiteral(
"Certificate authority exists for id: %1" ).arg(
id ), 2 );
2661 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2671 QMutexLocker locker( mMutex.get() );
2672 if ( cert.isNull() )
2674 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2682 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2684 query.bindValue( QStringLiteral(
":id" ),
id );
2686 if ( !authDbStartTransaction() )
2689 if ( !authDbQuery( &query ) )
2692 if ( !authDbCommit() )
2695 QgsDebugMsgLevel( QStringLiteral(
"REMOVED authority for id: %1" ).arg(
id ), 2 );
2701 return QSslConfiguration::systemCaCertificates();
2706 QMutexLocker locker( mMutex.get() );
2707 QList<QSslCertificate> certs;
2708 QList<QSslCertificate> filecerts;
2710 if ( cafileval.isNull() )
2714 if ( allowinvalid.isNull() )
2717 QString cafile( cafileval.toString() );
2718 if ( !cafile.isEmpty() && QFile::exists( cafile ) )
2723 for (
const auto &cert : std::as_const( filecerts ) )
2725 if ( !allowinvalid.toBool() && ( cert.isBlacklisted()
2727 || cert.expiryDate() <= QDateTime::currentDateTime()
2728 || cert.effectiveDate() > QDateTime::currentDateTime() ) )
2743 QMutexLocker locker( mMutex.get() );
2744 QList<QSslCertificate> certs;
2747 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbAuthoritiesTable() ) );
2749 if ( !authDbQuery( &query ) )
2752 if ( query.isActive() && query.isSelect() )
2754 while ( query.next() )
2756 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
2765 QMutexLocker locker( mMutex.get() );
2771 QMutexLocker locker( mMutex.get() );
2772 mCaCertsCache.clear();
2778 bool res = !mCaCertsCache.isEmpty();
2780 QgsDebugMsg( QStringLiteral(
"Rebuild of CA certs cache FAILED" ) );
2786 QMutexLocker locker( mMutex.get() );
2787 if ( cert.isNull() )
2789 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2799 QgsDebugMsg( QStringLiteral(
"Passed policy was default, all cert records in database were removed for id: %1" ).arg(
id ) );
2804 query.prepare( QStringLiteral(
"INSERT INTO %1 (id, policy) "
2805 "VALUES (:id, :policy)" ).arg( authDbTrustTable() ) );
2807 query.bindValue( QStringLiteral(
":id" ),
id );
2808 query.bindValue( QStringLiteral(
":policy" ),
static_cast< int >( policy ) );
2810 if ( !authDbStartTransaction() )
2813 if ( !authDbQuery( &query ) )
2816 if ( !authDbCommit() )
2819 QgsDebugMsgLevel( QStringLiteral(
"Store certificate trust policy SUCCESS for id: %1" ).arg(
id ), 2 );
2825 QMutexLocker locker( mMutex.get() );
2826 if ( cert.isNull() )
2828 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2835 query.prepare( QStringLiteral(
"SELECT policy FROM %1 "
2836 "WHERE id = :id" ).arg( authDbTrustTable() ) );
2838 query.bindValue( QStringLiteral(
":id" ),
id );
2840 if ( !authDbQuery( &query ) )
2844 if ( query.isActive() && query.isSelect() )
2846 if ( query.first() )
2849 QgsDebugMsgLevel( QStringLiteral(
"Authentication cert trust policy retrieved for id: %1" ).arg(
id ), 2 );
2853 QgsDebugMsg( QStringLiteral(
"Select contains more than one cert trust policy for id: %1" ).arg(
id ) );
2863 QMutexLocker locker( mMutex.get() );
2864 if ( certs.empty() )
2866 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2870 for (
const auto &cert : certs )
2880 QMutexLocker locker( mMutex.get() );
2881 if ( cert.isNull() )
2883 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2891 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbTrustTable() ) );
2893 query.bindValue( QStringLiteral(
":id" ),
id );
2895 if ( !authDbStartTransaction() )
2898 if ( !authDbQuery( &query ) )
2901 if ( !authDbCommit() )
2904 QgsDebugMsgLevel( QStringLiteral(
"REMOVED cert trust policy for id: %1" ).arg(
id ), 2 );
2911 QMutexLocker locker( mMutex.get() );
2912 if ( cert.isNull() )
2922 if ( trustedids.contains(
id ) )
2926 else if ( untrustedids.contains(
id ) )
2941 return storeAuthSetting( QStringLiteral(
"certdefaulttrust" ),
static_cast< int >( policy ) );
2946 QMutexLocker locker( mMutex.get() );
2947 QVariant policy(
authSetting( QStringLiteral(
"certdefaulttrust" ) ) );
2948 if ( policy.isNull() )
2957 QMutexLocker locker( mMutex.get() );
2958 mCertTrustCache.clear();
2961 query.prepare( QStringLiteral(
"SELECT id, policy FROM %1" ).arg( authDbTrustTable() ) );
2963 if ( !authDbQuery( &query ) )
2965 QgsDebugMsg( QStringLiteral(
"Rebuild of cert trust policy cache FAILED" ) );
2969 if ( query.isActive() && query.isSelect() )
2971 while ( query.next() )
2973 QString
id = query.value( 0 ).toString();
2977 if ( mCertTrustCache.contains( policy ) )
2979 ids = mCertTrustCache.value( policy );
2981 mCertTrustCache.insert( policy, ids <<
id );
2985 QgsDebugMsgLevel( QStringLiteral(
"Rebuild of cert trust policy cache SUCCEEDED" ), 2 );
2991 QMutexLocker locker( mMutex.get() );
2995 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2997 QList<QSslCertificate> trustedcerts;
2998 for (
int i = 0; i < certpairs.size(); ++i )
3000 QSslCertificate cert( certpairs.at( i ).second );
3002 if ( trustedids.contains( certid ) )
3005 trustedcerts.append( cert );
3011 trustedcerts.append( cert );
3016 QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
3017 sslconfig.setCaCertificates( trustedcerts );
3018 QSslConfiguration::setDefaultConfiguration( sslconfig );
3020 return trustedcerts;
3025 QMutexLocker locker( mMutex.get() );
3026 if ( trustedCAs.isEmpty() )
3028 if ( mTrustedCaCertsCache.isEmpty() )
3035 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
3037 QList<QSslCertificate> untrustedCAs;
3038 for (
int i = 0; i < certpairs.size(); ++i )
3040 QSslCertificate cert( certpairs.at( i ).second );
3041 if ( !trustedCAs.contains( cert ) )
3043 untrustedCAs.append( cert );
3046 return untrustedCAs;
3051 QMutexLocker locker( mMutex.get() );
3053 QgsDebugMsgLevel( QStringLiteral(
"Rebuilt trusted cert authorities cache" ), 2 );
3060 QMutexLocker locker( mMutex.get() );
3066 QMutexLocker locker( mMutex.get() );
3069 return passwordHelperWrite( mMasterPass );
3085 for (
const auto &authcfg : ids )
3103 void QgsAuthManager::writeToConsole(
const QString &message,
3117 msg += QLatin1String(
"WARNING: " );
3120 msg += QLatin1String(
"ERROR: " );
3127 QTextStream out( stdout, QIODevice::WriteOnly );
3128 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
3131 out << msg << Qt::endl;
3135 void QgsAuthManager::tryToStartDbErase()
3137 ++mScheduledDbEraseRequestCount;
3139 int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
3140 if ( mScheduledDbEraseRequestCount >= trycutoff )
3143 QgsDebugMsgLevel( QStringLiteral(
"authDatabaseEraseRequest emitting/scheduling canceled" ), 2 );
3148 QgsDebugMsgLevel( QStringLiteral(
"authDatabaseEraseRequest attempt (%1 of %2)" )
3149 .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ), 2 );
3155 mScheduledDbEraseRequestEmitted =
true;
3160 QgsDebugMsgLevel( QStringLiteral(
"authDatabaseEraseRequest emitted" ), 2 );
3163 QgsDebugMsgLevel( QStringLiteral(
"authDatabaseEraseRequest emit skipped" ), 2 );
3169 QMutexLocker locker( mMutex.get() );
3170 QMapIterator<QThread *, QMetaObject::Connection> iterator( mConnectedThreads );
3171 while ( iterator.hasNext() )
3174 QThread::disconnect( iterator.value() );
3181 qDeleteAll( mAuthMethods );
3184 if ( authConn.isValid() && authConn.isOpen() )
3187 delete mScheduledDbEraseTimer;
3188 mScheduledDbEraseTimer =
nullptr;
3189 QSqlDatabase::removeDatabase( QStringLiteral(
"authentication.configs" ) );
3193 QString QgsAuthManager::passwordHelperName()
const
3195 return tr(
"Password Helper" );
3199 void QgsAuthManager::passwordHelperLog(
const QString &msg )
const
3211 QKeychain::DeletePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3213 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3214 job.setAutoDelete(
false );
3215 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3217 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3222 mPasswordHelperErrorCode = job.error();
3223 mPasswordHelperErrorMessage = tr(
"Delete password failed: %1." ).arg( job.errorString() );
3234 passwordHelperProcessError();
3238 QString QgsAuthManager::passwordHelperRead()
3243 QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3245 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3246 job.setAutoDelete(
false );
3247 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3249 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3254 mPasswordHelperErrorCode = job.error();
3261 password = job.textData();
3263 if ( password.isEmpty() )
3265 mPasswordHelperErrorCode = QKeychain::EntryNotFound;
3276 passwordHelperProcessError();
3280 bool QgsAuthManager::passwordHelperWrite(
const QString &password )
3282 Q_ASSERT( !password.isEmpty() );
3285 QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3287 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3288 job.setAutoDelete(
false );
3289 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3290 job.setTextData( password );
3292 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3297 mPasswordHelperErrorCode = job.error();
3305 passwordHelperClearErrors();
3310 passwordHelperProcessError();
3318 return settings.
value( QStringLiteral(
"use_password_helper" ),
true, QgsSettings::Section::Auth ).toBool();
3324 settings.
setValue( QStringLiteral(
"use_password_helper" ), enabled, QgsSettings::Section::Auth );
3325 emit
messageOut( enabled ? tr(
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
3327 tr(
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
3335 return settings.
value( QStringLiteral(
"password_helper_logging" ),
false, QgsSettings::Section::Auth ).toBool();
3341 settings.
setValue( QStringLiteral(
"password_helper_logging" ), enabled, QgsSettings::Section::Auth );
3344 void QgsAuthManager::passwordHelperClearErrors()
3346 mPasswordHelperErrorCode = QKeychain::NoError;
3347 mPasswordHelperErrorMessage.clear();
3350 void QgsAuthManager::passwordHelperProcessError()
3352 if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
3353 mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
3354 mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
3355 mPasswordHelperErrorCode == QKeychain::NotImplemented )
3361 mPasswordHelperErrorMessage = tr(
"There was an error and integration with your %1 system has been disabled. "
3362 "You can re-enable it at any time through the \"Utilities\" menu "
3363 "in the Authentication pane of the options dialog. %2" )
3366 if ( mPasswordHelperErrorCode != QKeychain::NoError )
3372 passwordHelperClearErrors();
3376 bool QgsAuthManager::masterPasswordInput()
3382 bool storedPasswordIsValid =
false;
3388 pass = passwordHelperRead();
3389 if ( ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
3395 storedPasswordIsValid =
true;
3411 if ( ok && !pass.isEmpty() && mMasterPass != pass )
3416 if ( passwordHelperWrite( pass ) )
3430 bool QgsAuthManager::masterPasswordRowsInDb(
int *rows )
const
3436 query.prepare( QStringLiteral(
"SELECT Count(*) FROM %1" ).arg( authDbPassTable() ) );
3438 bool ok = authDbQuery( &query );
3439 if ( query.first() )
3441 *rows = query.value( 0 ).toInt();
3453 if ( !masterPasswordRowsInDb( &rows ) )
3455 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
3461 return ( rows == 1 );
3464 bool QgsAuthManager::masterPasswordCheckAgainstDb(
const QString &compare )
const
3472 query.prepare( QStringLiteral(
"SELECT salt, hash FROM %1" ).arg( authDbPassTable() ) );
3473 if ( !authDbQuery( &query ) )
3476 if ( !query.first() )
3479 QString salt = query.value( 0 ).toString();
3480 QString hash = query.value( 1 ).toString();
3485 bool QgsAuthManager::masterPasswordStoreInDb()
const
3490 QString salt, hash, civ;
3494 query.prepare( QStringLiteral(
"INSERT INTO %1 (salt, hash, civ) VALUES (:salt, :hash, :civ)" ).arg( authDbPassTable() ) );
3496 query.bindValue( QStringLiteral(
":salt" ), salt );
3497 query.bindValue( QStringLiteral(
":hash" ), hash );
3498 query.bindValue( QStringLiteral(
":civ" ), civ );
3500 if ( !authDbStartTransaction() )
3503 if ( !authDbQuery( &query ) )
3506 if ( !authDbCommit() )
3512 bool QgsAuthManager::masterPasswordClearDb()
3518 query.prepare( QStringLiteral(
"DELETE FROM %1" ).arg( authDbPassTable() ) );
3519 bool res = authDbTransactionQuery( &query );
3525 const QString QgsAuthManager::masterPasswordCiv()
const
3531 query.prepare( QStringLiteral(
"SELECT civ FROM %1" ).arg( authDbPassTable() ) );
3532 if ( !authDbQuery( &query ) )
3535 if ( !query.first() )
3538 return query.value( 0 ).toString();
3543 QStringList configids = QStringList();
3551 if ( !authDbQuery( &query ) )
3556 if ( query.isActive() )
3558 while ( query.next() )
3560 configids << query.value( 0 ).toString();
3566 bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
const
3577 if ( !authDbQuery( &query ) )
3580 if ( !query.isActive() || !query.isSelect() )
3582 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, query not active or a select operation" ) );
3587 while ( query.next() )
3590 QString configstring(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 1 ).toString() ) );
3591 if ( configstring.isEmpty() )
3593 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1)" )
3594 .arg( query.value( 0 ).toString() ) );
3599 QgsDebugMsgLevel( QStringLiteral(
"Verify password can decrypt configs SUCCESS (checked %1 configs)" ).arg( checked ), 2 );
3603 bool QgsAuthManager::reencryptAllAuthenticationConfigs(
const QString &prevpass,
const QString &prevciv )
3610 for (
const auto &configid : ids )
3612 res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
3617 bool QgsAuthManager::reencryptAuthenticationConfig(
const QString &authcfg,
const QString &prevpass,
const QString &prevciv )
3626 query.prepare( QStringLiteral(
"SELECT config FROM %1 "
3629 query.bindValue( QStringLiteral(
":id" ), authcfg );
3631 if ( !authDbQuery( &query ) )
3634 if ( !query.isActive() || !query.isSelect() )
3636 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for authcfg: %2" ).arg( authcfg ) );
3640 if ( query.first() )
3646 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
3653 query.prepare( QStringLiteral(
"UPDATE %1 "
3654 "SET config = :config "
3657 query.bindValue( QStringLiteral(
":id" ), authcfg );
3658 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
3660 if ( !authDbStartTransaction() )
3663 if ( !authDbQuery( &query ) )
3666 if ( !authDbCommit() )
3669 QgsDebugMsgLevel( QStringLiteral(
"Reencrypt SUCCESS for authcfg: %2" ).arg( authcfg ), 2 );
3674 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db authcfg: %2" ).arg( authcfg ) );
3679 bool QgsAuthManager::reencryptAllAuthenticationSettings(
const QString &prevpass,
const QString &prevciv )
3682 Q_UNUSED( prevpass )
3695 QStringList encryptedsettings;
3696 encryptedsettings <<
"";
3698 for (
const auto & sett, std::as_const( encryptedsettings ) )
3705 QSqlQuery query( authDbConnection() );
3707 query.prepare( QStringLiteral(
"SELECT value FROM %1 "
3708 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3710 query.bindValue(
":setting", sett );
3712 if ( !authDbQuery( &query ) )
3715 if ( !query.isActive() || !query.isSelect() )
3717 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
3721 if ( query.first() )
3727 query.prepare( QStringLiteral(
"UPDATE %1 "
3728 "SET value = :value "
3729 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3731 query.bindValue(
":setting", sett );
3734 if ( !authDbStartTransaction() )
3737 if ( !authDbQuery( &query ) )
3740 if ( !authDbCommit() )
3743 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for setting: %2" ).arg( sett ) );
3748 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
3754 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting: %1" ).arg( sett ) );
3765 bool QgsAuthManager::reencryptAllAuthenticationIdentities(
const QString &prevpass,
const QString &prevciv )
3772 for (
const auto &identid : ids )
3774 res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
3779 bool QgsAuthManager::reencryptAuthenticationIdentity(
3780 const QString &identid,
3781 const QString &prevpass,
3782 const QString &prevciv )
3791 query.prepare( QStringLiteral(
"SELECT key FROM %1 "
3792 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3794 query.bindValue( QStringLiteral(
":id" ), identid );
3796 if ( !authDbQuery( &query ) )
3799 if ( !query.isActive() || !query.isSelect() )
3801 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for identity id: %2" ).arg( identid ) );
3805 if ( query.first() )
3811 QgsDebugMsg( QStringLiteral(
"Select contains more than one for identity id: %1" ).arg( identid ) );
3818 query.prepare( QStringLiteral(
"UPDATE %1 "
3820 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3822 query.bindValue( QStringLiteral(
":id" ), identid );
3823 query.bindValue( QStringLiteral(
":key" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), keystring ) );
3825 if ( !authDbStartTransaction() )
3828 if ( !authDbQuery( &query ) )
3831 if ( !authDbCommit() )
3834 QgsDebugMsgLevel( QStringLiteral(
"Reencrypt SUCCESS for identity id: %2" ).arg( identid ), 2 );
3839 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db identity id: %2" ).arg( identid ) );
3844 bool QgsAuthManager::authDbOpen()
const
3850 if ( !authdb.isOpen() )
3852 if ( !authdb.open() )
3854 QgsDebugMsg( QStringLiteral(
"Unable to establish database connection\nDatabase: %1\nDriver error: %2\nDatabase error: %3" )
3856 authdb.lastError().driverText(),
3857 authdb.lastError().databaseText() ) );
3865 bool QgsAuthManager::authDbQuery( QSqlQuery *query )
const
3870 query->setForwardOnly(
true );
3871 if ( !query->exec() )
3873 const char *err = QT_TR_NOOP(
"Auth db query exec() FAILED" );
3879 if ( query->lastError().isValid() )
3881 QgsDebugMsg( QStringLiteral(
"Auth db query FAILED: %1\nError: %2" )
3882 .arg( query->executedQuery(),
3883 query->lastError().text() ) );
3891 bool QgsAuthManager::authDbStartTransaction()
const
3898 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3907 bool QgsAuthManager::authDbCommit()
const
3914 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3924 bool QgsAuthManager::authDbTransactionQuery( QSqlQuery *query )
const
3931 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3937 bool ok = authDbQuery( query );
3941 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3953 for (
const auto &cert : certs )
3956 QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>( source, cert ) );