23 #include <QMutexLocker> 26 #include <QSqlDatabase> 29 #include <QTextStream> 37 #include <QSslConfiguration> 56 const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral(
"auth_configs" );
57 const QString QgsAuthManager::AUTH_PASS_TABLE = QStringLiteral(
"auth_pass" );
58 const QString QgsAuthManager::AUTH_SETTINGS_TABLE = QStringLiteral(
"auth_settings" );
59 const QString QgsAuthManager::AUTH_IDENTITIES_TABLE = QStringLiteral(
"auth_identities" );
60 const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral(
"auth_servers" );
61 const QString QgsAuthManager::AUTH_AUTHORITIES_TABLE = QStringLiteral(
"auth_authorities" );
62 const QString QgsAuthManager::AUTH_TRUST_TABLE = QStringLiteral(
"auth_trust" );
64 const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral(
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
67 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME(
"QGIS-Master-Password" );
68 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME(
"QGIS" );
72 static const QString sDescription = QObject::tr(
"Master Password <-> KeyChain storage plugin. Store and retrieve your master password in your KeyChain" );
73 #elif defined(Q_OS_WIN) 75 static const QString sDescription = QObject::tr(
"Master Password <-> Password Manager storage plugin. Store and retrieve your master password in your Password Manager" );
76 #elif defined(Q_OS_LINUX) 78 static const QString sDescription = QObject::tr(
"Master Password <-> Wallet/KeyRing storage plugin. Store and retrieve your master password in your Wallet/KeyRing" );
81 static const QString sDescription = QObject::tr(
"Master Password <-> KeyChain storage plugin. Store and retrieve your master password in your Wallet/KeyChain/Password Manager" );
91 QMutexLocker locker( &sMutex );
103 mMutex =
new QMutex( QMutex::Recursive );
105 this, &QgsAuthManager::writeToConsole );
114 QString connectionname = QStringLiteral(
"authentication.configs" );
115 if ( !QSqlDatabase::contains( connectionname ) )
117 authdb = QSqlDatabase::addDatabase( QStringLiteral(
"QSQLITE" ), connectionname );
122 authdb = QSqlDatabase::database( connectionname );
124 if ( !authdb.isOpen() )
126 if ( !authdb.open() )
128 const char *err = QT_TR_NOOP(
"Opening of authentication db FAILED" );
144 mQcaInitializer =
new QCA::Initializer( QCA::Practical, 256 );
147 QCA::scanForPlugins();
149 QgsDebugMsg( QString(
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ) );
150 QStringList capabilities;
152 capabilities = QCA::supportedFeatures();
153 QgsDebugMsg( QString(
"QCA supports: %1" ).arg( capabilities.join(
"," ) ) );
156 if ( !QCA::isSupported(
"cert", QStringLiteral(
"qca-ossl" ) ) )
158 mAuthDisabled =
true;
159 mAuthDisabledMessage = tr(
"QCA's OpenSSL plugin (qca-ossl) is missing" );
163 QgsDebugMsg(
"Prioritizing qca-ossl over all other QCA providers..." );
164 const QCA::ProviderList provds = QCA::providers();
166 for ( QCA::Provider *p : provds )
168 QString pn = p->name();
170 if ( pn != QLatin1String(
"qca-ossl" ) )
172 pr = QCA::providerPriority( pn ) + 1;
174 QCA::setProviderPriority( pn, pr );
175 prlist << QStringLiteral(
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
177 QgsDebugMsg( QString(
"QCA provider priorities: %1" ).arg( prlist.join(
", " ) ) );
184 QgsDebugMsg( QString(
"Authentication methods found: %1" ).arg( methods.join(
", " ) ) );
186 if ( methods.isEmpty() )
188 mAuthDisabled =
true;
189 mAuthDisabledMessage = tr(
"No authentication method plugins found" );
195 mAuthDisabled =
true;
196 mAuthDisabledMessage = tr(
"No authentication method plugins could be loaded" );
200 mAuthDbPath = QDir::cleanPath( authDatabasePath );
204 QFileInfo dbdirinfo( dbinfo.path() );
205 QgsDebugMsg( QString(
"Auth db directory path: %1" ).arg( dbdirinfo.filePath() ) );
207 if ( !dbdirinfo.exists() )
209 QgsDebugMsg( QString(
"Auth db directory path does not exist, making path: %1" ).arg( dbdirinfo.filePath() ) );
210 if ( !QDir().mkpath( dbdirinfo.filePath() ) )
212 const char *err = QT_TR_NOOP(
"Auth db directory path could not be created" );
219 if ( dbinfo.exists() )
221 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
223 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
228 if ( dbinfo.size() > 0 )
232 if ( !createCertTables() )
242 const char *passenv =
"QGIS_AUTH_PASSWORD_FILE";
245 QString passpath( getenv( passenv ) );
254 QFile passfile( passpath );
255 if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
257 QTextStream passin( &passfile );
258 while ( !passin.atEnd() )
260 masterpass = passin.readLine();
265 if ( !masterpass.isEmpty() )
269 QgsDebugMsg(
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" );
273 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
279 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
289 QgsDebugMsg(
"Auth db does not exist: creating through QSqlDatabase initial connection" );
291 if ( !createConfigTables() )
294 if ( !createCertTables() )
305 bool QgsAuthManager::createConfigTables()
307 QMutexLocker locker( mMutex );
311 const char *err = QT_TR_NOOP(
"Auth db could not be created and opened" );
322 qstr = QString(
"CREATE TABLE %1 (\n" 323 " 'salt' TEXT NOT NULL,\n" 324 " 'civ' TEXT NOT NULL\n" 325 ", 'hash' TEXT NOT NULL);" ).arg( authDbPassTable() );
326 query.prepare( qstr );
327 if ( !authDbQuery( &query ) )
331 qstr = QString(
"CREATE TABLE %1 (\n" 332 " 'id' TEXT NOT NULL,\n" 333 " 'name' TEXT NOT NULL,\n" 335 " 'type' TEXT NOT NULL,\n" 336 " 'version' INTEGER NOT NULL\n" 338 query.prepare( qstr );
339 if ( !authDbQuery( &query ) )
344 query.prepare( qstr );
345 if ( !authDbQuery( &query ) )
350 query.prepare( qstr );
351 if ( !authDbQuery( &query ) )
358 bool QgsAuthManager::createCertTables()
360 QMutexLocker locker( mMutex );
369 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 370 " 'setting' TEXT NOT NULL\n" 371 ", 'value' TEXT);" ).arg( authDbSettingsTable() );
372 query.prepare( qstr );
373 if ( !authDbQuery( &query ) )
378 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 379 " 'id' TEXT NOT NULL,\n" 380 " 'key' TEXT NOT NULL\n" 381 ", 'cert' TEXT NOT NULL);" ).arg( authDbIdentitiesTable() );
382 query.prepare( qstr );
383 if ( !authDbQuery( &query ) )
387 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbIdentitiesTable() );
388 query.prepare( qstr );
389 if ( !authDbQuery( &query ) )
394 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 395 " 'id' TEXT NOT NULL,\n" 396 " 'host' TEXT NOT NULL,\n" 399 query.prepare( qstr );
400 if ( !authDbQuery( &query ) )
404 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'host_index' on %1 (host ASC);" ).arg(
authDatabaseServersTable() );
405 query.prepare( qstr );
406 if ( !authDbQuery( &query ) )
411 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 412 " 'id' TEXT NOT NULL\n" 413 ", 'cert' TEXT NOT NULL);" ).arg( authDbAuthoritiesTable() );
414 query.prepare( qstr );
415 if ( !authDbQuery( &query ) )
419 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbAuthoritiesTable() );
420 query.prepare( qstr );
421 if ( !authDbQuery( &query ) )
425 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 426 " 'id' TEXT NOT NULL\n" 427 ", 'policy' TEXT NOT NULL);" ).arg( authDbTrustTable() );
428 query.prepare( qstr );
429 if ( !authDbQuery( &query ) )
433 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbTrustTable() );
434 query.prepare( qstr );
435 if ( !authDbQuery( &query ) )
446 QgsDebugMsg(
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" );
448 return mAuthDisabled;
453 return tr(
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
458 QMutexLocker locker( mMutex );
462 if ( mScheduledDbErase )
465 if ( mMasterPass.isEmpty() )
467 QgsDebugMsg(
"Master password is not yet set by user" );
468 if ( !masterPasswordInput() )
470 QgsDebugMsg(
"Master password input canceled by user" );
484 QgsDebugMsg(
"Master password is set and verified" );
490 QMutexLocker locker( mMutex );
494 if ( mScheduledDbErase )
498 QString prevpass = QString( mMasterPass );
502 mMasterPass = prevpass;
503 const char *err = QT_TR_NOOP(
"Master password set: FAILED to verify, reset to previous" );
509 QgsDebugMsg( QString(
"Master password set: SUCCESS%1" ).arg( verify ?
" and verified" :
"" ) );
519 if ( !masterPasswordRowsInDb( &rows ) )
521 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
529 QgsDebugMsg( QString(
"Master password: %1 rows in database" ).arg( rows ) );
533 const char *err = QT_TR_NOOP(
"Master password: FAILED to find just one master password record in database" );
540 else if ( rows == 1 )
542 if ( !masterPasswordCheckAgainstDb( compare ) )
544 if ( compare.isNull() )
546 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
555 if ( mPassTries >= 5 )
557 mAuthDisabled =
true;
558 const char *err = QT_TR_NOOP(
"Master password: failed 5 times authentication system DISABLED" );
566 QgsDebugMsg(
"Master password: verified against hash in database" );
567 if ( compare.isNull() )
571 else if ( compare.isNull() )
573 if ( !masterPasswordStoreInDb() )
575 const char *err = QT_TR_NOOP(
"Master password: hash FAILED to be stored in database" );
584 QgsDebugMsg(
"Master password: hash stored in database" );
587 if ( !masterPasswordCheckAgainstDb() )
589 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
599 QgsDebugMsg(
"Master password: verified against hash in database" );
609 return !mMasterPass.isEmpty();
614 return mMasterPass == pass;
618 bool keepbackup, QString *backuppath )
632 QgsDebugMsg(
"Master password reset: backed up current database" );
638 QString prevpass = QString( mMasterPass );
639 QString prevciv = QString( masterPasswordCiv() );
645 if ( ok && !masterPasswordClearDb() )
648 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not clear current password from database" );
654 QgsDebugMsg(
"Master password reset: cleared current password from database" );
661 if ( ok && !masterPasswordStoreInDb() )
664 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not store new password in database" );
670 QgsDebugMsg(
"Master password reset: stored new password in database" );
677 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify new password in database" );
683 if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
686 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt configs in database" );
692 QgsDebugMsg(
"Master password reset: re-encrypted configs in database" );
696 if ( ok && !verifyPasswordCanDecryptConfigs() )
699 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
704 if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
707 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt settings in database" );
712 if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
715 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt identities in database" );
725 QString errdbbackup( dbbackup );
726 errdbbackup.replace( QLatin1String(
".db" ), QLatin1String(
"_ERROR.db" ) );
728 QgsDebugMsg( QString(
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
732 mMasterPass = prevpass;
734 QgsDebugMsg(
"Master password reset FAILED: reinstated previous password and database" );
738 *backuppath = errdbbackup;
744 if ( !keepbackup && !QFile::remove( dbbackup ) )
746 const char *err = QT_TR_NOOP(
"Master password reset: could not remove old database backup" );
754 QgsDebugMsg( QString(
"Master password reset: backed up previous db at %1" ).arg( dbbackup ) );
756 *backuppath = dbbackup;
766 mScheduledDbErase = scheduleErase;
768 mScheduledDbEraseRequestEmitted =
false;
769 mScheduledDbEraseRequestCount = 0;
773 if ( !mScheduledDbEraseTimer )
775 mScheduledDbEraseTimer =
new QTimer(
this );
776 connect( mScheduledDbEraseTimer, &QTimer::timeout,
this, &QgsAuthManager::tryToStartDbErase );
777 mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
779 else if ( !mScheduledDbEraseTimer->isActive() )
781 mScheduledDbEraseTimer->start();
786 if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
787 mScheduledDbEraseTimer->stop();
796 qDeleteAll( mAuthMethods );
797 mAuthMethods.clear();
799 for (
const auto &authMethodKey : methods )
804 return !mAuthMethods.isEmpty();
814 QTimer::singleShot( 3, &loop, SLOT( quit() ) );
817 uint
seed =
static_cast< uint
>( QTime::currentTime().msec() );
823 for (
int i = 0; i < len; i++ )
825 switch ( qrand() % 2 )
828 id += (
'0' + qrand() % 10 );
831 id += (
'a' + qrand() % 26 );
835 if ( !configids.contains(
id ) )
840 QgsDebugMsg( QString(
"Generated unique ID: %1" ).arg(
id ) );
851 const char *err = QT_TR_NOOP(
"Config ID is empty" );
857 return !configids.contains(
id );
862 QRegExp rx( AUTH_CFG_REGEX );
863 return rx.indexIn( txt ) != -1;
868 QMutexLocker locker( mMutex );
869 QStringList providerAuthMethodsKeys;
870 if ( !dataprovider.isEmpty() )
881 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1" ).arg(
authDatabaseConfigTable() ) );
883 if ( !authDbQuery( &query ) )
888 if ( query.isActive() && query.isSelect() )
890 while ( query.next() )
892 QString authcfg = query.value( 0 ).toString();
894 config.
setId( authcfg );
895 config.
setName( query.value( 1 ).toString() );
896 config.
setUri( query.value( 2 ).toString() );
897 config.
setMethod( query.value( 3 ).toString() );
898 config.
setVersion( query.value( 4 ).toInt() );
900 if ( !dataprovider.isEmpty() && !providerAuthMethodsKeys.contains( config.
method() ) )
905 baseConfigs.insert( authcfg, config );
913 QMutexLocker locker( mMutex );
920 if ( !authDbQuery( &query ) )
925 if ( query.isActive() )
927 QgsDebugMsg(
"Synching existing auth config and their auth methods" );
928 mConfigAuthMethods.clear();
929 QStringList cfgmethods;
930 while ( query.next() )
932 mConfigAuthMethods.insert( query.value( 0 ).toString(),
933 query.value( 1 ).toString() );
934 cfgmethods << QStringLiteral(
"%1=%2" ).arg( query.value( 0 ).toString(), query.value( 1 ).toString() );
936 QgsDebugMsg( QString(
"Stored auth config/methods:\n%1" ).arg( cfgmethods.join(
", " ) ) );
945 if ( !mConfigAuthMethods.contains( authcfg ) )
947 QgsDebugMsg( QString(
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
951 QString authMethodKey = mConfigAuthMethods.value( authcfg );
961 return mConfigAuthMethods.value( authcfg, QString() );
972 if ( !mAuthMethods.contains( authMethodKey ) )
974 QgsDebugMsg( QString(
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
978 return mAuthMethods.value( authMethodKey );
983 if ( dataprovider.isEmpty() )
989 QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
990 while ( i != mAuthMethods.constEnd() )
993 && ( i.value()->supportedDataProviders().contains( QStringLiteral(
"all" ) )
994 || i.value()->supportedDataProviders().contains( dataprovider ) ) )
996 filteredmap.insert( i.key(), i.value() );
1011 return QgsAuthMethod::Expansions(
nullptr );
1018 return QgsAuthMethod::Expansions(
nullptr );
1023 QMutexLocker locker( mMutex );
1030 const char *err = QT_TR_NOOP(
"Store config: FAILED because config is invalid" );
1036 QString uid = mconfig.
id();
1037 bool passedinID = !uid.isEmpty();
1038 if ( uid.isEmpty() )
1044 const char *err = QT_TR_NOOP(
"Store config: FAILED because pre-defined config ID is not unique" );
1051 if ( configstring.isEmpty() )
1053 const char *err = QT_TR_NOOP(
"Store config: FAILED because config string is empty" );
1059 QgsDebugMsg( QString(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1060 QgsDebugMsg( QString(
"name: %1" ).arg( config.name() ) );
1061 QgsDebugMsg( QString(
"uri: %1" ).arg( config.uri() ) );
1062 QgsDebugMsg( QString(
"type: %1" ).arg( config.method() ) );
1063 QgsDebugMsg( QString(
"version: %1" ).arg( config.version() ) );
1064 QgsDebugMsg( QString(
"config: %1" ).arg( configstring ) );
1068 query.prepare( QString(
"INSERT INTO %1 (id, name, uri, type, version, config) " 1071 query.bindValue( QStringLiteral(
":id" ), uid );
1072 query.bindValue( QStringLiteral(
":name" ), mconfig.
name() );
1073 query.bindValue( QStringLiteral(
":uri" ), mconfig.
uri() );
1074 query.bindValue( QStringLiteral(
":type" ), mconfig.
method() );
1075 query.bindValue( QStringLiteral(
":version" ), mconfig.
version() );
1076 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1078 if ( !authDbStartTransaction() )
1081 if ( !authDbQuery( &query ) )
1084 if ( !authDbCommit() )
1089 mconfig.
setId( uid );
1093 QgsDebugMsg( QString(
"Store config SUCCESS for authcfg: %1" ).arg( uid ) );
1100 QMutexLocker locker( mMutex );
1105 if ( !config.
isValid(
true ) )
1107 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is invalid" );
1114 if ( configstring.isEmpty() )
1116 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is empty" );
1123 QgsDebugMsg( QString(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1129 QgsDebugMsg( QString(
"config: %1" ).arg( configstring ) );
1133 if ( !query.prepare( QString(
"UPDATE %1 " 1134 "SET name = :name, uri = :uri, type = :type, version = :version, config = :config " 1137 const char *err = QT_TR_NOOP(
"Update config: FAILED to prepare query" );
1143 query.bindValue( QStringLiteral(
":id" ), config.
id() );
1144 query.bindValue( QStringLiteral(
":name" ), config.
name() );
1145 query.bindValue( QStringLiteral(
":uri" ), config.
uri() );
1146 query.bindValue( QStringLiteral(
":type" ), config.
method() );
1147 query.bindValue( QStringLiteral(
":version" ), config.
version() );
1148 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1150 if ( !authDbStartTransaction() )
1153 if ( !authDbQuery( &query ) )
1156 if ( !authDbCommit() )
1164 QgsDebugMsg( QString(
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ) );
1171 QMutexLocker locker( mMutex );
1181 query.prepare( QString(
"SELECT id, name, uri, type, version, config FROM %1 " 1186 query.prepare( QString(
"SELECT id, name, uri, type, version FROM %1 " 1190 query.bindValue( QStringLiteral(
":id" ), authcfg );
1192 if ( !authDbQuery( &query ) )
1197 if ( query.isActive() && query.isSelect() )
1199 if ( query.first() )
1201 mconfig.
setId( query.value( 0 ).toString() );
1202 mconfig.
setName( query.value( 1 ).toString() );
1203 mconfig.
setUri( query.value( 2 ).toString() );
1204 mconfig.
setMethod( query.value( 3 ).toString() );
1205 mconfig.
setVersion( query.value( 4 ).toInt() );
1220 QgsDebugMsg( QString(
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
1223 QgsDebugMsg( QString(
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ?
"full" :
"base", authcfg ) );
1228 QgsDebugMsg( QString(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
1238 QMutexLocker locker( mMutex );
1242 if ( authcfg.isEmpty() )
1249 query.bindValue( QStringLiteral(
":id" ), authcfg );
1251 if ( !authDbStartTransaction() )
1254 if ( !authDbQuery( &query ) )
1257 if ( !authDbCommit() )
1264 QgsDebugMsg( QString(
"REMOVED config for authcfg: %1" ).arg( authcfg ) );
1271 QMutexLocker locker( mMutex );
1277 bool res = authDbTransactionQuery( &query );
1285 QgsDebugMsg( QString(
"Remove configs from database: %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
1292 QMutexLocker locker( mMutex );
1295 const char *err = QT_TR_NOOP(
"No authentication database found" );
1303 if ( authConn.isValid() && authConn.isOpen() )
1307 QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral(
"yyyy-MM-dd-hhmmss" ) ) );
1309 dbbackup.replace( QLatin1String(
".db" ), QStringLiteral(
"_%1.db" ).arg( datestamp ) );
1313 const char *err = QT_TR_NOOP(
"Could not back up authentication database" );
1320 *backuppath = dbbackup;
1322 QgsDebugMsg( QString(
"Backed up auth database at %1" ).arg( dbbackup ) );
1328 QMutexLocker locker( mMutex );
1338 if ( backuppath && !dbbackup.isEmpty() )
1339 *backuppath = dbbackup;
1342 if ( dbinfo.exists() )
1344 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
1346 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
1354 const char *err = QT_TR_NOOP(
"No authentication database found" );
1362 const char *err = QT_TR_NOOP(
"Authentication database could not be deleted" );
1368 mMasterPass = QString();
1370 QgsDebugMsg(
"Creating Auth db through QSqlDatabase initial connection" );
1373 if ( !authConn.isValid() || !authConn.isOpen() )
1375 const char *err = QT_TR_NOOP(
"Authentication database could not be initialized" );
1381 if ( !createConfigTables() )
1383 const char *err = QT_TR_NOOP(
"FAILED to create auth database config tables" );
1389 if ( !createCertTables() )
1391 const char *err = QT_TR_NOOP(
"FAILED to create auth database cert tables" );
1407 const QString &dataprovider )
1417 QgsDebugMsg( QString(
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
1432 const QString &dataprovider )
1442 QgsDebugMsg( QString(
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ) );
1458 const QString &dataprovider )
1468 QgsDebugMsg( QString(
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
1493 QgsDebugMsg( QStringLiteral(
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
1502 QgsDebugMsg( QStringLiteral(
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ) );
1511 QMutexLocker locker( mMutex );
1512 if ( key.isEmpty() )
1515 QString storeval( value.toString() );
1531 query.prepare( QString(
"INSERT INTO %1 (setting, value) " 1532 "VALUES (:setting, :value)" ).arg( authDbSettingsTable() ) );
1534 query.bindValue( QStringLiteral(
":setting" ), key );
1535 query.bindValue( QStringLiteral(
":value" ), storeval );
1537 if ( !authDbStartTransaction() )
1540 if ( !authDbQuery( &query ) )
1543 if ( !authDbCommit() )
1546 QgsDebugMsg( QString(
"Store setting SUCCESS for key: %1" ).arg( key ) );
1552 QMutexLocker locker( mMutex );
1553 if ( key.isEmpty() )
1559 QVariant value = defaultValue;
1561 query.prepare( QString(
"SELECT value FROM %1 " 1562 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1564 query.bindValue( QStringLiteral(
":setting" ), key );
1566 if ( !authDbQuery( &query ) )
1569 if ( query.isActive() && query.isSelect() )
1571 if ( query.first() )
1575 value = QVariant(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ) );
1579 value = query.value( 0 );
1581 QgsDebugMsg( QString(
"Authentication setting retrieved for key: %1" ).arg( key ) );
1585 QgsDebugMsg( QString(
"Select contains more than one for setting key: %1" ).arg( key ) );
1595 QMutexLocker locker( mMutex );
1596 if ( key.isEmpty() )
1600 query.prepare( QString(
"SELECT value FROM %1 " 1601 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1603 query.bindValue( QStringLiteral(
":setting" ), key );
1605 if ( !authDbQuery( &query ) )
1609 if ( query.isActive() && query.isSelect() )
1611 if ( query.first() )
1613 QgsDebugMsg( QString(
"Authentication setting exists for key: %1" ).arg( key ) );
1618 QgsDebugMsg( QString(
"Select contains more than one for setting key: %1" ).arg( key ) );
1628 QMutexLocker locker( mMutex );
1629 if ( key.isEmpty() )
1634 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1636 query.bindValue( QStringLiteral(
":setting" ), key );
1638 if ( !authDbStartTransaction() )
1641 if ( !authDbQuery( &query ) )
1644 if ( !authDbCommit() )
1647 QgsDebugMsg( QString(
"REMOVED setting for key: %1" ).arg( key ) );
1659 QMutexLocker locker( mMutex );
1666 QgsDebugMsg( QString(
"Init of SSL caches %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
1672 QMutexLocker locker( mMutex );
1673 if ( cert.isNull() )
1690 QString certpem( cert.toPem() );
1694 query.prepare( QString(
"INSERT INTO %1 (id, key, cert) " 1695 "VALUES (:id, :key, :cert)" ).arg( authDbIdentitiesTable() ) );
1697 query.bindValue( QStringLiteral(
":id" ),
id );
1698 query.bindValue( QStringLiteral(
":key" ), keypem );
1699 query.bindValue( QStringLiteral(
":cert" ), certpem );
1701 if ( !authDbStartTransaction() )
1704 if ( !authDbQuery( &query ) )
1707 if ( !authDbCommit() )
1710 QgsDebugMsg( QString(
"Store certificate identity SUCCESS for id: %1" ).arg(
id ) );
1716 QMutexLocker locker( mMutex );
1717 QSslCertificate emptycert;
1718 QSslCertificate cert;
1723 query.prepare( QString(
"SELECT cert FROM %1 " 1724 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1726 query.bindValue( QStringLiteral(
":id" ),
id );
1728 if ( !authDbQuery( &query ) )
1731 if ( query.isActive() && query.isSelect() )
1733 if ( query.first() )
1735 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
1736 QgsDebugMsg( QString(
"Certificate identity retrieved for id: %1" ).arg(
id ) );
1740 QgsDebugMsg( QString(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1750 QMutexLocker locker( mMutex );
1751 QPair<QSslCertificate, QSslKey> bundle;
1759 query.prepare( QString(
"SELECT key, cert FROM %1 " 1760 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1762 query.bindValue( QStringLiteral(
":id" ),
id );
1764 if ( !authDbQuery( &query ) )
1767 if ( query.isActive() && query.isSelect() )
1769 QSslCertificate cert;
1771 if ( query.first() )
1773 key = QSslKey(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ).toLatin1(),
1774 QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
1777 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create private key" );
1782 cert = QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1783 if ( cert.isNull() )
1785 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create certificate" );
1790 QgsDebugMsg( QString(
"Certificate identity bundle retrieved for id: %1" ).arg(
id ) );
1794 QgsDebugMsg( QString(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1798 bundle = qMakePair( cert, key );
1805 QMutexLocker locker( mMutex );
1809 return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
1811 return QStringList();
1816 QMutexLocker locker( mMutex );
1817 QList<QSslCertificate> certs;
1820 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbIdentitiesTable() ) );
1822 if ( !authDbQuery( &query ) )
1825 if ( query.isActive() && query.isSelect() )
1827 while ( query.next() )
1829 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1838 QMutexLocker locker( mMutex );
1839 QStringList identityids = QStringList();
1845 query.prepare( QStringLiteral(
"SELECT id FROM %1" ).arg( authDbIdentitiesTable() ) );
1847 if ( !authDbQuery( &query ) )
1852 if ( query.isActive() )
1854 while ( query.next() )
1856 identityids << query.value( 0 ).toString();
1864 QMutexLocker locker( mMutex );
1869 query.prepare( QString(
"SELECT cert FROM %1 " 1870 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1872 query.bindValue( QStringLiteral(
":id" ),
id );
1874 if ( !authDbQuery( &query ) )
1878 if ( query.isActive() && query.isSelect() )
1880 if ( query.first() )
1882 QgsDebugMsg( QString(
"Certificate bundle exists for id: %1" ).arg(
id ) );
1887 QgsDebugMsg( QString(
"Select contains more than one certificate bundle for id: %1" ).arg(
id ) );
1897 QMutexLocker locker( mMutex );
1906 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1908 query.bindValue( QStringLiteral(
":id" ),
id );
1910 if ( !authDbStartTransaction() )
1913 if ( !authDbQuery( &query ) )
1916 if ( !authDbCommit() )
1919 QgsDebugMsg( QString(
"REMOVED certificate identity for id: %1" ).arg(
id ) );
1925 QMutexLocker locker( mMutex );
1937 QString certpem( cert.toPem() );
1940 query.prepare( QString(
"INSERT INTO %1 (id, host, cert, config) " 1943 query.bindValue( QStringLiteral(
":id" ),
id );
1944 query.bindValue( QStringLiteral(
":host" ), config.
sslHostPort().trimmed() );
1945 query.bindValue( QStringLiteral(
":cert" ), certpem );
1946 query.bindValue( QStringLiteral(
":config" ), config.
configString() );
1948 if ( !authDbStartTransaction() )
1951 if ( !authDbQuery( &query ) )
1954 if ( !authDbCommit() )
1957 QgsDebugMsg( QString(
"Store SSL cert custom config SUCCESS for host:port, id: %1, %2" )
1967 QMutexLocker locker( mMutex );
1970 if (
id.isEmpty() || hostport.isEmpty() )
1972 QgsDebugMsg(
"Passed config ID or host:port is empty" );
1977 query.prepare( QString(
"SELECT id, host, cert, config FROM %1 " 1980 query.bindValue( QStringLiteral(
":id" ),
id );
1981 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
1983 if ( !authDbQuery( &query ) )
1986 if ( query.isActive() && query.isSelect() )
1988 if ( query.first() )
1990 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
1993 QgsDebugMsg( QString(
"SSL cert custom config retrieved for host:port, id: %1, %2" ).arg( hostport,
id ) );
1997 QgsDebugMsg( QString(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
1998 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2009 QMutexLocker locker( mMutex );
2012 if ( hostport.isEmpty() )
2019 query.prepare( QString(
"SELECT id, host, cert, config FROM %1 " 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( QString(
"SSL cert custom config retrieved for host:port: %1" ).arg( hostport ) );
2038 QgsDebugMsg( QString(
"Select contains more than one SSL cert custom config for host:port: %1" ).arg( hostport ) );
2039 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
2050 QMutexLocker locker( mMutex );
2051 QList<QgsAuthConfigSslServer> configs;
2056 if ( !authDbQuery( &query ) )
2059 if ( query.isActive() && query.isSelect() )
2061 while ( query.next() )
2064 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2068 configs.append( config );
2077 QMutexLocker locker( mMutex );
2078 if (
id.isEmpty() || hostport.isEmpty() )
2080 QgsDebugMsg(
"Passed config ID or host:port is empty" );
2085 query.prepare( QString(
"SELECT cert FROM %1 " 2088 query.bindValue( QStringLiteral(
":id" ),
id );
2089 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2091 if ( !authDbQuery( &query ) )
2095 if ( query.isActive() && query.isSelect() )
2097 if ( query.first() )
2099 QgsDebugMsg( QString(
"SSL cert custom config exists for host:port, id: %1, %2" ).arg( hostport,
id ) );
2104 QgsDebugMsg( QString(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2105 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2115 QMutexLocker locker( mMutex );
2116 if (
id.isEmpty() || hostport.isEmpty() )
2118 QgsDebugMsg(
"Passed config ID or host:port is empty" );
2124 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id AND host = :host" ).arg(
authDatabaseServersTable() ) );
2126 query.bindValue( QStringLiteral(
":id" ),
id );
2127 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2129 if ( !authDbStartTransaction() )
2132 if ( !authDbQuery( &query ) )
2135 if ( !authDbCommit() )
2138 QString shahostport( QStringLiteral(
"%1:%2" ).arg(
id, hostport ) );
2139 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2141 mIgnoredSslErrorsCache.remove( shahostport );
2144 QgsDebugMsg( QString(
"REMOVED SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2151 QMutexLocker locker( mMutex );
2152 if ( !mIgnoredSslErrorsCache.isEmpty() )
2155 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
2156 while ( i != mIgnoredSslErrorsCache.constEnd() )
2159 for (
auto err : i.value() )
2163 QgsDebugMsg( QString(
"%1 = %2" ).arg( i.key(), errs.join(
", " ) ) );
2175 QMutexLocker locker( mMutex );
2182 QString shahostport( QStringLiteral(
"%1:%2" )
2185 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2187 mIgnoredSslErrorsCache.remove( shahostport );
2190 if ( !errenums.isEmpty() )
2192 mIgnoredSslErrorsCache.insert( shahostport, QSet<QSslError::SslError>::fromList( errenums ) );
2193 QgsDebugMsg( QString(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2198 QgsDebugMsg( QString(
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ) );
2204 QMutexLocker locker( mMutex );
2205 QRegExp rx(
"\\S+:\\S+:\\d+" );
2206 if ( !rx.exactMatch( shahostport ) )
2208 QgsDebugMsg(
"Passed shahostport does not match \\S+:\\S+:\\d+, " 2209 "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
2213 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2215 mIgnoredSslErrorsCache.remove( shahostport );
2218 if ( errors.isEmpty() )
2224 QSet<QSslError::SslError> errs;
2225 for (
const auto &error : errors )
2227 if ( error.error() == QSslError::NoError )
2230 errs.insert( error.error() );
2233 if ( errs.isEmpty() )
2235 QgsDebugMsg(
"Passed errors list does not contain errors" );
2239 mIgnoredSslErrorsCache.insert( shahostport, errs );
2241 QgsDebugMsg( QString(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2248 QMutexLocker locker( mMutex );
2249 QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
2250 QHash<QString, QSet<QSslError::SslError> > nextcache;
2255 if ( !authDbQuery( &query ) )
2257 QgsDebugMsg(
"Rebuild of ignored SSL errors cache FAILED" );
2261 if ( query.isActive() && query.isSelect() )
2263 while ( query.next() )
2265 QString shahostport( QStringLiteral(
"%1:%2" )
2266 .arg( query.value( 0 ).toString().trimmed(),
2267 query.value( 1 ).toString().trimmed() ) );
2271 if ( !errenums.isEmpty() )
2273 nextcache.insert( shahostport, QSet<QSslError::SslError>::fromList( errenums ) );
2275 if ( prevcache.contains( shahostport ) )
2277 prevcache.remove( shahostport );
2282 if ( !prevcache.isEmpty() )
2285 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
2286 while ( i != prevcache.constEnd() )
2288 nextcache.insert( i.key(), i.value() );
2293 if ( nextcache != mIgnoredSslErrorsCache )
2295 mIgnoredSslErrorsCache.clear();
2296 mIgnoredSslErrorsCache = nextcache;
2297 QgsDebugMsg(
"Rebuild of ignored SSL errors cache SUCCEEDED" );
2302 QgsDebugMsg(
"Rebuild of ignored SSL errors cache SAME AS BEFORE" );
2310 QMutexLocker locker( mMutex );
2311 if ( certs.isEmpty() )
2313 QgsDebugMsg(
"Passed certificate list has no certs" );
2317 for (
const auto &cert : certs )
2327 QMutexLocker locker( mMutex );
2330 if ( cert.isNull() )
2339 QString pem( cert.toPem() );
2342 query.prepare( QString(
"INSERT INTO %1 (id, cert) " 2343 "VALUES (:id, :cert)" ).arg( authDbAuthoritiesTable() ) );
2345 query.bindValue( QStringLiteral(
":id" ),
id );
2346 query.bindValue( QStringLiteral(
":cert" ), pem );
2348 if ( !authDbStartTransaction() )
2351 if ( !authDbQuery( &query ) )
2354 if ( !authDbCommit() )
2357 QgsDebugMsg( QString(
"Store certificate authority SUCCESS for id: %1" ).arg(
id ) );
2363 QMutexLocker locker( mMutex );
2364 QSslCertificate emptycert;
2365 QSslCertificate cert;
2370 query.prepare( QString(
"SELECT cert FROM %1 " 2371 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2373 query.bindValue( QStringLiteral(
":id" ),
id );
2375 if ( !authDbQuery( &query ) )
2378 if ( query.isActive() && query.isSelect() )
2380 if ( query.first() )
2382 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
2383 QgsDebugMsg( QString(
"Certificate authority retrieved for id: %1" ).arg(
id ) );
2387 QgsDebugMsg( QString(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2397 QMutexLocker locker( mMutex );
2398 if ( cert.isNull() )
2407 query.prepare( QString(
"SELECT value FROM %1 " 2408 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2410 query.bindValue( QStringLiteral(
":id" ),
id );
2412 if ( !authDbQuery( &query ) )
2416 if ( query.isActive() && query.isSelect() )
2418 if ( query.first() )
2420 QgsDebugMsg( QString(
"Certificate authority exists for id: %1" ).arg(
id ) );
2425 QgsDebugMsg( QString(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2435 QMutexLocker locker( mMutex );
2436 if ( cert.isNull() )
2446 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2448 query.bindValue( QStringLiteral(
":id" ),
id );
2450 if ( !authDbStartTransaction() )
2453 if ( !authDbQuery( &query ) )
2456 if ( !authDbCommit() )
2459 QgsDebugMsg( QString(
"REMOVED authority for id: %1" ).arg(
id ) );
2466 return QSslSocket::systemCaCertificates();
2468 QNetworkRequest req;
2469 return req.sslConfiguration().caCertificates();
2475 QMutexLocker locker( mMutex );
2476 QList<QSslCertificate> certs;
2477 QList<QSslCertificate> filecerts;
2479 if ( cafileval.isNull() )
2483 if ( allowinvalid.isNull() )
2486 QString cafile( cafileval.toString() );
2487 if ( !cafile.isEmpty() && QFile::exists( cafile ) )
2492 for (
const auto &cert : qgis::as_const( filecerts ) )
2494 if ( !allowinvalid.toBool() && !cert.isValid() )
2509 QMutexLocker locker( mMutex );
2510 QList<QSslCertificate> certs;
2513 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbAuthoritiesTable() ) );
2515 if ( !authDbQuery( &query ) )
2518 if ( query.isActive() && query.isSelect() )
2520 while ( query.next() )
2522 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
2531 QMutexLocker locker( mMutex );
2537 QMutexLocker locker( mMutex );
2538 mCaCertsCache.clear();
2544 bool res = !mCaCertsCache.isEmpty();
2545 QgsDebugMsg( QString(
"Rebuild of CA certs cache %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
2551 QMutexLocker locker( mMutex );
2552 if ( cert.isNull() )
2564 QgsDebugMsg( QString(
"Passed policy was default, all cert records in database were removed for id: %1" ).arg(
id ) );
2569 query.prepare( QString(
"INSERT INTO %1 (id, policy) " 2570 "VALUES (:id, :policy)" ).arg( authDbTrustTable() ) );
2572 query.bindValue( QStringLiteral(
":id" ),
id );
2573 query.bindValue( QStringLiteral(
":policy" ), static_cast< int >( policy ) );
2575 if ( !authDbStartTransaction() )
2578 if ( !authDbQuery( &query ) )
2581 if ( !authDbCommit() )
2584 QgsDebugMsg( QString(
"Store certificate trust policy SUCCESS for id: %1" ).arg(
id ) );
2590 QMutexLocker locker( mMutex );
2591 if ( cert.isNull() )
2600 query.prepare( QString(
"SELECT policy FROM %1 " 2601 "WHERE id = :id" ).arg( authDbTrustTable() ) );
2603 query.bindValue( QStringLiteral(
":id" ),
id );
2605 if ( !authDbQuery( &query ) )
2609 if ( query.isActive() && query.isSelect() )
2611 if ( query.first() )
2614 QgsDebugMsg( QString(
"Authentication cert trust policy retrieved for id: %1" ).arg(
id ) );
2618 QgsDebugMsg( QString(
"Select contains more than one cert trust policy for id: %1" ).arg(
id ) );
2628 QMutexLocker locker( mMutex );
2629 if ( certs.empty() )
2631 QgsDebugMsg(
"Passed certificate list has no certs" );
2635 for (
const auto &cert : certs )
2645 QMutexLocker locker( mMutex );
2646 if ( cert.isNull() )
2656 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbTrustTable() ) );
2658 query.bindValue( QStringLiteral(
":id" ),
id );
2660 if ( !authDbStartTransaction() )
2663 if ( !authDbQuery( &query ) )
2666 if ( !authDbCommit() )
2669 QgsDebugMsg( QString(
"REMOVED cert trust policy for id: %1" ).arg(
id ) );
2676 QMutexLocker locker( mMutex );
2677 if ( cert.isNull() )
2687 if ( trustedids.contains(
id ) )
2691 else if ( untrustedids.contains(
id ) )
2706 return storeAuthSetting( QStringLiteral(
"certdefaulttrust" ), static_cast< int >( policy ) );
2711 QMutexLocker locker( mMutex );
2712 QVariant policy(
authSetting( QStringLiteral(
"certdefaulttrust" ) ) );
2713 if ( policy.isNull() )
2722 QMutexLocker locker( mMutex );
2723 mCertTrustCache.clear();
2726 query.prepare( QStringLiteral(
"SELECT id, policy FROM %1" ).arg( authDbTrustTable() ) );
2728 if ( !authDbQuery( &query ) )
2730 QgsDebugMsg(
"Rebuild of cert trust policy cache FAILED" );
2734 if ( query.isActive() && query.isSelect() )
2736 while ( query.next() )
2738 QString
id = query.value( 0 ).toString();
2742 if ( mCertTrustCache.contains( policy ) )
2744 ids = mCertTrustCache.value( policy );
2746 mCertTrustCache.insert( policy, ids <<
id );
2750 QgsDebugMsg(
"Rebuild of cert trust policy cache SUCCEEDED" );
2756 QMutexLocker locker( mMutex );
2760 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2762 QList<QSslCertificate> trustedcerts;
2763 for (
int i = 0; i < certpairs.size(); ++i )
2765 QSslCertificate cert( certpairs.at( i ).second );
2767 if ( trustedids.contains( certid ) )
2770 trustedcerts.append( cert );
2776 trustedcerts.append( cert );
2781 QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
2782 sslconfig.setCaCertificates( trustedcerts );
2783 QSslConfiguration::setDefaultConfiguration( sslconfig );
2785 return trustedcerts;
2790 QMutexLocker locker( mMutex );
2791 if ( trustedCAs.isEmpty() )
2793 if ( mTrustedCaCertsCache.isEmpty() )
2800 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2802 QList<QSslCertificate> untrustedCAs;
2803 for (
int i = 0; i < certpairs.size(); ++i )
2805 QSslCertificate cert( certpairs.at( i ).second );
2806 if ( !trustedCAs.contains( cert ) )
2808 untrustedCAs.append( cert );
2811 return untrustedCAs;
2816 QMutexLocker locker( mMutex );
2818 QgsDebugMsg(
"Rebuilt trusted cert authorities cache" );
2825 QMutexLocker locker( mMutex );
2831 QMutexLocker locker( mMutex );
2834 return passwordHelperWrite( mMasterPass );
2850 for (
const auto &authcfg : ids )
2868 void QgsAuthManager::writeToConsole(
const QString &message,
2882 msg += QLatin1String(
"WARNING: " );
2885 msg += QLatin1String(
"ERROR: " );
2892 QTextStream out( stdout, QIODevice::WriteOnly );
2896 void QgsAuthManager::tryToStartDbErase()
2898 ++mScheduledDbEraseRequestCount;
2900 int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
2901 if ( mScheduledDbEraseRequestCount >= trycutoff )
2904 QgsDebugMsg(
"authDatabaseEraseRequest emitting/scheduling canceled" );
2909 QgsDebugMsg( QString(
"authDatabaseEraseRequest attempt (%1 of %2)" )
2910 .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ) );
2916 mScheduledDbEraseRequestEmitted =
true;
2921 QgsDebugMsg(
"authDatabaseEraseRequest emitted" );
2924 QgsDebugMsg(
"authDatabaseEraseRequest emit skipped" );
2933 qDeleteAll( mAuthMethods );
2936 if ( authConn.isValid() && authConn.isOpen() )
2941 delete mScheduledDbEraseTimer;
2942 mScheduledDbEraseTimer =
nullptr;
2943 delete mQcaInitializer;
2944 mQcaInitializer =
nullptr;
2945 QSqlDatabase::removeDatabase( QStringLiteral(
"authentication.configs" ) );
2949 QString QgsAuthManager::passwordHelperName()
const 2951 return tr(
"Password Helper" );
2955 void QgsAuthManager::passwordHelperLog(
const QString &msg )
const 2967 QKeychain::DeletePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
2969 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
2970 job.setAutoDelete(
false );
2971 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
2973 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
2978 mPasswordHelperErrorCode = job.error();
2979 mPasswordHelperErrorMessage = tr(
"Delete password failed: %1." ).arg( job.errorString() );
2990 passwordHelperProcessError();
2994 QString QgsAuthManager::passwordHelperRead()
2997 QString password( QLatin1String(
"" ) );
2999 QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3001 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3002 job.setAutoDelete(
false );
3003 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3005 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3010 mPasswordHelperErrorCode = job.error();
3017 password = job.textData();
3019 if ( password.isEmpty() )
3021 mPasswordHelperErrorCode = QKeychain::EntryNotFound;
3032 passwordHelperProcessError();
3036 bool QgsAuthManager::passwordHelperWrite(
const QString &password )
3038 Q_ASSERT( !password.isEmpty() );
3041 QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3043 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3044 job.setAutoDelete(
false );
3045 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3046 job.setTextData( password );
3048 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3053 mPasswordHelperErrorCode = job.error();
3061 passwordHelperClearErrors();
3066 passwordHelperProcessError();
3074 return settings.
value( QStringLiteral(
"use_password_helper" ),
true, QgsSettings::Section::Auth ).toBool();
3080 settings.
setValue( QStringLiteral(
"use_password_helper" ), enabled, QgsSettings::Section::Auth );
3081 emit
messageOut( enabled ? tr(
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
3083 tr(
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
3091 return settings.
value( QStringLiteral(
"password_helper_logging" ),
false, QgsSettings::Section::Auth ).toBool();
3097 settings.
setValue( QStringLiteral(
"password_helper_logging" ), enabled, QgsSettings::Section::Auth );
3100 void QgsAuthManager::passwordHelperClearErrors()
3102 mPasswordHelperErrorCode = QKeychain::NoError;
3103 mPasswordHelperErrorMessage.clear();
3106 void QgsAuthManager::passwordHelperProcessError()
3108 if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
3109 mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
3110 mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
3111 mPasswordHelperErrorCode == QKeychain::NotImplemented )
3117 mPasswordHelperErrorMessage = tr(
"There was an error and integration with your %1 system has been disabled. " 3118 "You can re-enable it at any time through the \"Utilities\" menu " 3119 "in the Authentication pane of the options dialog. %2" )
3122 if ( mPasswordHelperErrorCode != QKeychain::NoError )
3128 passwordHelperClearErrors();
3132 bool QgsAuthManager::masterPasswordInput()
3138 bool storedPasswordIsValid =
false;
3144 pass = passwordHelperRead();
3145 if ( ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
3151 storedPasswordIsValid =
true;
3170 if ( ok && !pass.isEmpty() && mMasterPass != pass )
3175 if ( passwordHelperWrite( pass ) )
3189 bool QgsAuthManager::masterPasswordRowsInDb(
int *rows )
const 3195 query.prepare( QStringLiteral(
"SELECT Count(*) FROM %1" ).arg( authDbPassTable() ) );
3197 bool ok = authDbQuery( &query );
3198 if ( query.first() )
3200 *rows = query.value( 0 ).toInt();
3212 if ( !masterPasswordRowsInDb( &rows ) )
3214 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
3220 return ( rows == 1 );
3223 bool QgsAuthManager::masterPasswordCheckAgainstDb(
const QString &compare )
const 3231 query.prepare( QStringLiteral(
"SELECT salt, hash FROM %1" ).arg( authDbPassTable() ) );
3232 if ( !authDbQuery( &query ) )
3235 if ( !query.first() )
3238 QString salt = query.value( 0 ).toString();
3239 QString hash = query.value( 1 ).toString();
3244 bool QgsAuthManager::masterPasswordStoreInDb()
const 3249 QString salt, hash, civ;
3253 query.prepare( QStringLiteral(
"INSERT INTO %1 (salt, hash, civ) VALUES (:salt, :hash, :civ)" ).arg( authDbPassTable() ) );
3255 query.bindValue( QStringLiteral(
":salt" ), salt );
3256 query.bindValue( QStringLiteral(
":hash" ), hash );
3257 query.bindValue( QStringLiteral(
":civ" ), civ );
3259 if ( !authDbStartTransaction() )
3262 if ( !authDbQuery( &query ) )
3265 if ( !authDbCommit() )
3271 bool QgsAuthManager::masterPasswordClearDb()
3277 query.prepare( QStringLiteral(
"DELETE FROM %1" ).arg( authDbPassTable() ) );
3278 bool res = authDbTransactionQuery( &query );
3284 const QString QgsAuthManager::masterPasswordCiv()
const 3290 query.prepare( QStringLiteral(
"SELECT civ FROM %1" ).arg( authDbPassTable() ) );
3291 if ( !authDbQuery( &query ) )
3294 if ( !query.first() )
3297 return query.value( 0 ).toString();
3302 QStringList configids = QStringList();
3310 if ( !authDbQuery( &query ) )
3315 if ( query.isActive() )
3317 while ( query.next() )
3319 configids << query.value( 0 ).toString();
3325 bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
const 3336 if ( !authDbQuery( &query ) )
3339 if ( !query.isActive() || !query.isSelect() )
3341 QgsDebugMsg( QString(
"Verify password can decrypt configs FAILED, query not active or a select operation" ) );
3346 while ( query.next() )
3349 QString configstring(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 1 ).toString() ) );
3350 if ( configstring.isEmpty() )
3352 QgsDebugMsg( QString(
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1)" )
3353 .arg( query.value( 0 ).toString() ) );
3358 QgsDebugMsg( QString(
"Verify password can decrypt configs SUCCESS (checked %1 configs)" ).arg( checked ) );
3362 bool QgsAuthManager::reencryptAllAuthenticationConfigs(
const QString &prevpass,
const QString &prevciv )
3369 for (
const auto &configid : ids )
3371 res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
3376 bool QgsAuthManager::reencryptAuthenticationConfig(
const QString &authcfg,
const QString &prevpass,
const QString &prevciv )
3385 query.prepare( QString(
"SELECT config FROM %1 " 3388 query.bindValue( QStringLiteral(
":id" ), authcfg );
3390 if ( !authDbQuery( &query ) )
3393 if ( !query.isActive() || !query.isSelect() )
3395 QgsDebugMsg( QString(
"Reencrypt FAILED, query not active or a select operation for authcfg: %2" ).arg( authcfg ) );
3399 if ( query.first() )
3405 QgsDebugMsg( QString(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
3412 query.prepare( QString(
"UPDATE %1 " 3413 "SET config = :config " 3416 query.bindValue( QStringLiteral(
":id" ), authcfg );
3417 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
3419 if ( !authDbStartTransaction() )
3422 if ( !authDbQuery( &query ) )
3425 if ( !authDbCommit() )
3428 QgsDebugMsg( QString(
"Reencrypt SUCCESS for authcfg: %2" ).arg( authcfg ) );
3433 QgsDebugMsg( QString(
"Reencrypt FAILED, could not find in db authcfg: %2" ).arg( authcfg ) );
3438 bool QgsAuthManager::reencryptAllAuthenticationSettings(
const QString &prevpass,
const QString &prevciv )
3441 Q_UNUSED( prevpass );
3442 Q_UNUSED( prevciv );
3454 QStringList encryptedsettings;
3455 encryptedsettings <<
"";
3457 for (
const auto & sett, qgis::as_const( encryptedsettings ) )
3464 QSqlQuery query( authDbConnection() );
3466 query.prepare( QString(
"SELECT value FROM %1 " 3467 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3469 query.bindValue(
":setting", sett );
3471 if ( !authDbQuery( &query ) )
3474 if ( !query.isActive() || !query.isSelect() )
3476 QgsDebugMsg( QString(
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
3480 if ( query.first() )
3486 query.prepare( QString(
"UPDATE %1 " 3487 "SET value = :value " 3488 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3490 query.bindValue(
":setting", sett );
3493 if ( !authDbStartTransaction() )
3496 if ( !authDbQuery( &query ) )
3499 if ( !authDbCommit() )
3502 QgsDebugMsg( QString(
"Reencrypt SUCCESS for setting: %2" ).arg( sett ) );
3507 QgsDebugMsg( QString(
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
3513 QgsDebugMsg( QString(
"Select contains more than one for setting: %1" ).arg( sett ) );
3524 bool QgsAuthManager::reencryptAllAuthenticationIdentities(
const QString &prevpass,
const QString &prevciv )
3531 for (
const auto &identid : ids )
3533 res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
3538 bool QgsAuthManager::reencryptAuthenticationIdentity(
3539 const QString &identid,
3540 const QString &prevpass,
3541 const QString &prevciv )
3550 query.prepare( QString(
"SELECT key FROM %1 " 3551 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3553 query.bindValue( QStringLiteral(
":id" ), identid );
3555 if ( !authDbQuery( &query ) )
3558 if ( !query.isActive() || !query.isSelect() )
3560 QgsDebugMsg( QString(
"Reencrypt FAILED, query not active or a select operation for identity id: %2" ).arg( identid ) );
3564 if ( query.first() )
3570 QgsDebugMsg( QString(
"Select contains more than one for identity id: %1" ).arg( identid ) );
3577 query.prepare( QString(
"UPDATE %1 " 3579 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3581 query.bindValue( QStringLiteral(
":id" ), identid );
3582 query.bindValue( QStringLiteral(
":key" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), keystring ) );
3584 if ( !authDbStartTransaction() )
3587 if ( !authDbQuery( &query ) )
3590 if ( !authDbCommit() )
3593 QgsDebugMsg( QString(
"Reencrypt SUCCESS for identity id: %2" ).arg( identid ) );
3598 QgsDebugMsg( QString(
"Reencrypt FAILED, could not find in db identity id: %2" ).arg( identid ) );
3603 bool QgsAuthManager::authDbOpen()
const 3609 if ( !authdb.isOpen() )
3611 if ( !authdb.open() )
3613 QgsDebugMsg( QString(
"Unable to establish database connection\nDatabase: %1\nDriver error: %2\nDatabase error: %3" )
3615 authdb.lastError().driverText(),
3616 authdb.lastError().databaseText() ) );
3624 bool QgsAuthManager::authDbQuery( QSqlQuery *query )
const 3629 query->setForwardOnly(
true );
3630 if ( !query->exec() )
3632 const char *err = QT_TR_NOOP(
"Auth db query exec() FAILED" );
3638 if ( query->lastError().isValid() )
3640 QgsDebugMsg( QString(
"Auth db query FAILED: %1\nError: %2" )
3641 .arg( query->executedQuery(),
3642 query->lastError().text() ) );
3650 bool QgsAuthManager::authDbStartTransaction()
const 3657 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3666 bool QgsAuthManager::authDbCommit()
const 3673 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3683 bool QgsAuthManager::authDbTransactionQuery( QSqlQuery *query )
const 3690 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3696 bool ok = authDbQuery( query );
3700 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3712 for (
const auto &cert : certs )
3715 QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>( source, cert ) );
Singleton offering an interface to manage the authentication configuration database and to utilize co...
bool rebuildTrustedCaCertsCache()
Rebuild trusted certificate authorities cache.
bool getMasterPassword(QString &password, bool stored=false)
bool isNull() const
Whether configuration is null (missing components)
void setUri(const QString &uri)
const QString authDatabaseConfigTable() const
Name of the authentication database table that stores configs.
void messageOut(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, QgsAuthManager::MessageLevel level=QgsAuthManager::INFO) const
Custom logging signal to relay to console output and QgsMessageLog.
bool isValid(bool validateid=false) const
Whether the configuration is valid.
static bool verifyPasswordKeyHash(const QString &pass, const QString &salt, const QString &hash, QString *hashderived=nullptr)
Verify existing master password hash to a re-generated one.
bool passwordHelperEnabled() const
Password helper enabled getter.
void setId(const QString &id)
Sets auth config ID.
static QgsAuthManager * instance()
Enforce singleton pattern.
QgsAuthMethod::Expansions supportedAuthMethodExpansions(const QString &authcfg)
Gets supported authentication method expansion(s), e.g.
void setScheduledAuthDatabaseErase(bool scheduleErase)
Schedule an optional erase of authentication database, starting when mutex is lockable.
Interface for requesting credentials in QGIS in GUI independent way.
bool storeSslCertCustomConfig(const QgsAuthConfigSslServer &config)
Store an SSL certificate custom config.
This class is a composition of two QSettings instances:
bool existsAuthSetting(const QString &key)
Check if an authentication setting exists.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QStringList authMethodList() const
Returns list of available auth methods by their keys.
bool storeAuthSetting(const QString &key, const QVariant &value, bool encrypt=false)
Store an authentication setting (stored as string via QVariant( value ).toString() ) ...
bool removeCertAuthority(const QSslCertificate &cert)
Remove a certificate authority.
bool updateNetworkProxy(QNetworkProxy &proxy, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkProxy with an authentication config.
bool masterPasswordSame(const QString &pass) const
Check whether supplied password is the same as the one already set.
static QString sslErrorEnumString(QSslError::SslError errenum)
Gets short strings describing an SSL error.
bool initSslCaches()
Initialize various SSL authentication caches.
static QList< QSslCertificate > certsFromFile(const QString &certspath)
Returns a list of concatenated certs from a PEM or DER formatted file.
void passwordHelperFailure()
Signals emitted on password helper failure, mainly used in the tests to exit main application loop...
static QMap< QString, QSslCertificate > mapDigestToCerts(const QList< QSslCertificate > &certs)
Map certificate sha1 to certificate as simple cache.
Configuration container for SSL server connection exceptions or overrides.
virtual bool updateDataSourceUriItems(QStringList &connectionItems, const QString &authcfg, const QString &dataprovider=QString())
Update data source connection items with authentication components.
void passwordHelperMessageOut(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, QgsAuthManager::MessageLevel level=QgsAuthManager::INFO)
Custom logging signal to inform the user about master password <-> password manager interactions...
static QgsCredentials * instance()
retrieves instance
static bool certificateIsAuthorityOrIssuer(const QSslCertificate &cert)
Gets whether a certificate is an Authority or can at least sign other certificates.
const QString disabledMessage() const
Standard message for when QCA's qca-ossl plugin is missing and system is disabled.
bool removeCertTrustPolicy(const QSslCertificate &cert)
Remove a certificate authority.
const QList< QgsAuthConfigSslServer > sslCertCustomConfigs()
sslCertCustomConfigs get SSL certificate custom configs
QStringList authMethodsKeys(const QString &dataprovider=QString())
Gets keys of supported authentication methods.
QgsAuthMethod * authMethod(const QString &authMethodKey)
Gets authentication method from the config/provider cache via its key.
bool storeCertAuthority(const QSslCertificate &cert)
Store a certificate authority.
const QList< QSslCertificate > extraFileCAs()
extraFileCAs extra file-based certificate authorities
static void passwordKeyHash(const QString &pass, QString *salt, QString *hash, QString *cipheriv=nullptr)
Generate SHA256 hash for master password, with iterations and salt.
MessageLevel
Message log level (mirrors that of QgsMessageLog, so it can also output there)
bool rebuildCaCertsCache()
Rebuild certificate authority cache.
QgsAuthCertUtils::CertTrustPolicy certificateTrustPolicy(const QSslCertificate &cert)
certificateTrustPolicy get trust policy for a particular certificate cert
A registry / canonical manager of authentication methods.
const QPair< QSslCertificate, QSslKey > certIdentityBundle(const QString &id)
Gets a certificate identity bundle by id (sha hash).
const QString uniqueConfigId() const
Gets a unique generated 7-character string to assign to as config id.
static const QString AUTH_PASSWORD_HELPER_DISPLAY_NAME
The display name of the password helper (platform dependent)
bool updateAuthenticationConfig(const QgsAuthMethodConfig &config)
Update an authentication config in the database.
void lock()
Lock the instance against access from multiple threads.
bool eraseAuthenticationDatabase(bool backup, QString *backuppath=nullptr)
Erase all rows from all tables in authentication database.
const QList< QSslCertificate > trustedCaCerts(bool includeinvalid=false)
trustedCaCerts get list of all trusted CA certificates
virtual bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Update a network request with authentication components.
void clearCachedConfig(const QString &authcfg)
Clear an authentication config from its associated authentication method cache.
void masterPasswordVerified(bool verified)
Emitted when a password has been verify (or not)
static bool certIsViable(const QSslCertificate &cert)
certIsViable checks for viability errors of cert and whether it is NULL
bool setDefaultCertTrustPolicy(QgsAuthCertUtils::CertTrustPolicy policy)
Sets the default certificate trust policy preferred by user.
bool removeAllAuthenticationConfigs()
Clear all authentication configs from table in database and from provider caches. ...
bool hasConfigId(const QString &txt) const
Returns whether a string includes an authcfg ID token.
const QList< QSslCertificate > untrustedCaCerts(QList< QSslCertificate > trustedCAs=QList< QSslCertificate >())
untrustedCaCerts get list of untrusted certificate authorities
bool passwordHelperLoggingEnabled() const
Password helper logging enabled getter.
QWidget * editWidget(const QString &authMethodKey, QWidget *parent=nullptr)
Returns the auth method capabilities.
QHash< QString, QgsAuthMethodConfig > QgsAuthMethodConfigsMap
const QMap< QString, QSslCertificate > mappedDatabaseCAs()
mappedDatabaseCAs get sha1-mapped database-stored certificate authorities
QgsAuthMethodConfigsMap availableAuthMethodConfigs(const QString &dataprovider=QString())
Gets mapping of authentication config ids and their base configs (not decrypted data) ...
QString authManTag() const
Simple text tag describing authentication system for message logs.
void setMethod(const QString &method)
~QgsAuthManager() override
Configuration storage class for authentication method configurations.
const QString configString() const
Configuration as a concatenated string.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
void seed(uint32_t value)
const QString authenticationDatabasePath() const
The standard authentication database file in ~/.qgis3/ or defined location.
bool storeCertIdentity(const QSslCertificate &cert, const QSslKey &key)
Store a certificate identity.
bool updateDataSourceUriItems(QStringList &connectionItems, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QgsDataSourceUri with an authentication config.
bool removeCertTrustPolicies(const QList< QSslCertificate > &certs)
Remove a group certificate authorities.
bool removeSslCertCustomConfig(const QString &id, const QString &hostport)
Remove an SSL certificate custom config.
const QStringList certIdentityBundleToPem(const QString &id)
certIdentityBundleToPem get a certificate identity bundle by id (sha hash) returned as PEM text ...
bool passwordHelperSync()
Store the password manager into the wallet.
void authDatabaseChanged()
Emitted when the authentication db is significantly changed, e.g. large record removal, erased, etc.
void loadConfigString(const QString &configstr)
Load existing extended configuration.
const QString name() const
Gets name of configuration.
const QString sslHostPort() const
Server host:port string.
void passwordHelperSuccess()
Signals emitted on password helper success, mainly used in the tests to exit main application loop...
QStringList configIds() const
Gets list of authentication ids from database.
QWidget * authMethodEditWidget(const QString &authMethodKey, QWidget *parent)
Gets authentication method edit widget via its key.
const QgsAuthConfigSslServer sslCertCustomConfigByHost(const QString &hostport)
sslCertCustomConfigByHost get an SSL certificate custom config by hostport (host:port) ...
void authDatabaseEraseRequested()
Emitted when a user has indicated they may want to erase the authentication db.
const QList< QSslError::SslError > sslIgnoredErrorEnums() const
SSL server errors (as enum list) to ignore in connections.
void setSslHostPort(const QString &hostport)
Sets server host:port string.
void updateConfigAuthMethods()
Sync the confg/authentication method cache with what is in database.
QSqlDatabase authDatabaseConnection() const
Sets up the application instance of the authentication database connection.
bool storeCertTrustPolicy(const QSslCertificate &cert, QgsAuthCertUtils::CertTrustPolicy policy)
Store user trust value for a certificate.
int version() const
Gets version of the configuration.
virtual void clearCachedConfig(const QString &authcfg)=0
Clear any cached configuration.
bool masterPasswordHashInDatabase() const
Verify a password hash existing in authentication database.
bool passwordHelperDelete()
Delete master password from wallet.
bool storeCertAuthorities(const QList< QSslCertificate > &certs)
Store multiple certificate authorities.
bool existsCertAuthority(const QSslCertificate &cert)
Check if a certificate authority exists.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
QString configAuthMethodKey(const QString &authcfg) const
Gets key of authentication method associated with config ID.
const QList< QSslCertificate > certIdentities()
certIdentities get certificate identities
virtual bool updateNetworkProxy(QNetworkProxy &proxy, const QString &authcfg, const QString &dataprovider=QString())
Update proxy settings with authentication components.
bool updateIgnoredSslErrorsCacheFromConfig(const QgsAuthConfigSslServer &config)
Update ignored SSL error cache with possible ignored SSL errors, using server config.
QgsAuthMethod * configAuthMethod(const QString &authcfg)
Gets authentication method from the config/provider cache.
const QSslCertificate sslCertificate() const
Server certificate object.
const QSslCertificate certIdentity(const QString &id)
certIdentity get a certificate identity by id (sha hash)
Abstract base class for authentication method plugins.
static const QString encrypt(const QString &pass, const QString &cipheriv, const QString &text)
Encrypt data using master password.
CaCertSource
Type of CA certificate source.
QVariant authSetting(const QString &key, const QVariant &defaultValue=QVariant(), bool decrypt=false)
authSetting get an authentication setting (retrieved as string and returned as QVariant( QString )) ...
bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkRequest with an authentication config.
bool removeCertIdentity(const QString &id)
Remove a certificate identity.
const QByteArray trustedCaCertsPemText()
trustedCaCertsPemText get concatenated string of all trusted CA certificates
void clearMasterPassword()
Clear supplied master password.
const QgsAuthConfigSslServer sslCertCustomConfig(const QString &id, const QString &hostport)
sslCertCustomConfig get an SSL certificate custom config by id (sha hash) and hostport (host:port) ...
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
bool updateIgnoredSslErrorsCache(const QString &shahostport, const QList< QSslError > &errors)
Update ignored SSL error cache with possible ignored SSL errors, using sha:host:port key...
bool setMasterPassword(bool verify=false)
Main call to initially set or continually check master password is set.
bool resetMasterPassword(const QString &newpass, const QString &oldpass, bool keepbackup, QString *backuppath=nullptr)
Reset the master password to a new one, then re-encrypt all previous configs in a new database file...
bool storeAuthenticationConfig(QgsAuthMethodConfig &mconfig)
Store an authentication config in the database.
const QList< QSslCertificate > trustedCaCertsCache()
trustedCaCertsCache cache of trusted certificate authorities, ready for network connections ...
void setVersion(int version)
Sets version of the configuration.
bool loadAuthenticationConfig(const QString &authcfg, QgsAuthMethodConfig &mconfig, bool full=false)
Load an authentication config from the database into subclass.
const QSslCertificate certAuthority(const QString &id)
Gets a certificate authority by id (sha hash)
bool existsSslCertCustomConfig(const QString &id, const QString &hostport)
Check if SSL certificate custom config exists.
bool isDisabled() const
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
static const QString decrypt(const QString &pass, const QString &cipheriv, const QString &text)
Decrypt data using master password.
virtual bool updateNetworkReply(QNetworkReply *reply, const QString &authcfg, const QString &dataprovider=QString())
Update a network reply with authentication components.
bool configIdUnique(const QString &id) const
Verify if provided authentication id is unique.
QString method() const
Textual key of the associated authentication method.
bool init(const QString &pluginPath=QString(), const QString &authDatabasePath=QString())
init initialize QCA, prioritize qca-ossl plugin and optionally set up the authentication database ...
void loadConfigString(const QString &config=QString())
Load concatenated string into configuration, e.g. from auth database.
void setPasswordHelperEnabled(bool enabled)
Password helper enabled setter.
static const QString AUTH_MAN_TAG
The display name of the Authentication Manager.
const QString uri() const
A URI to auto-select a config when connecting to a resource.
bool existsCertIdentity(const QString &id)
Check if a certificate identity exists.
bool masterPasswordIsSet() const
Whether master password has be input and verified, i.e. authentication database is accessible...
const QList< QSslCertificate > databaseCAs()
databaseCAs get database-stored certificate authorities
CertTrustPolicy
Type of certificate trust policy.
QgsAuthMethodsMap authMethodsMap(const QString &dataprovider=QString())
Gets available authentication methods mapped to their key.
bool scheduledAuthDatabaseErase()
Whether there is a scheduled opitonal erase of authentication database.
bool updateNetworkReply(QNetworkReply *reply, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkReply with an authentication config (used to skip known SSL errors...
void unlock()
Unlock the instance after being locked.
bool removeAuthenticationConfig(const QString &authcfg)
Remove an authentication config in the database.
QgsAuthCertUtils::CertTrustPolicy certTrustPolicy(const QSslCertificate &cert)
certTrustPolicy get whether certificate cert is trusted by user
void dumpIgnoredSslErrorsCache_()
Utility function to dump the cache for debug purposes.
const QList< QSslCertificate > systemRootCAs()
systemRootCAs get root system certificate authorities
QgsAuthCertUtils::CertTrustPolicy defaultCertTrustPolicy()
Gets the default certificate trust policy preferred by user.
const QString authDatabaseServersTable() const
Name of the authentication database table that stores server exceptions/configs.
QgsAuthMethod::Expansions supportedExpansions() const
Flags that represent the update points (where authentication configurations are expanded) supported b...
bool removeAuthSetting(const QString &key)
Remove an authentication setting.
static QgsAuthMethodRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
void setName(const QString &name)
Sets name of configuration.
const QString configString() const
The extended configuration, as stored and retrieved from the authentication database.
bool rebuildIgnoredSslErrorCache()
Rebuild ignoredSSL error cache.
void setSslCertificate(const QSslCertificate &cert)
Sets server certificate object.
bool backupAuthenticationDatabase(QString *backuppath=nullptr)
Close connection to current authentication database and back it up.
virtual void updateMethodConfig(QgsAuthMethodConfig &mconfig)=0
Update an authentication configuration in place.
bool registerCoreAuthMethods()
Instantiate and register existing C++ core authentication methods from plugins.
QStringList certIdentityIds() const
certIdentityIds get list of certificate identity ids from database
void setPasswordHelperLoggingEnabled(bool enabled)
Password helper logging enabled setter.
const QString id() const
Gets 'authcfg' 7-character alphanumeric ID of the config.
static QByteArray certsToPemText(const QList< QSslCertificate > &certs)
certsToPemText dump a list of QSslCertificates to PEM text
bool verifyMasterPassword(const QString &compare=QString())
Verify the supplied master password against any existing hash in authentication database.
void clearAllCachedConfigs()
Clear all authentication configs from authentication method caches.
bool rebuildCertTrustCache()
Rebuild certificate authority cache.
QHash< QString, QgsAuthMethod * > QgsAuthMethodsMap