23 #include <QMutexLocker> 26 #include <QSqlDatabase> 29 #include <QTextStream> 38 #include <QSslConfiguration> 58 const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral(
"auth_configs" );
59 const QString QgsAuthManager::AUTH_PASS_TABLE = QStringLiteral(
"auth_pass" );
60 const QString QgsAuthManager::AUTH_SETTINGS_TABLE = QStringLiteral(
"auth_settings" );
61 const QString QgsAuthManager::AUTH_IDENTITIES_TABLE = QStringLiteral(
"auth_identities" );
62 const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral(
"auth_servers" );
63 const QString QgsAuthManager::AUTH_AUTHORITIES_TABLE = QStringLiteral(
"auth_authorities" );
64 const QString QgsAuthManager::AUTH_TRUST_TABLE = QStringLiteral(
"auth_trust" );
66 const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral(
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
69 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME(
"QGIS-Master-Password" );
70 const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME(
"QGIS" );
74 static const QString sDescription = QObject::tr(
"Master Password <-> KeyChain storage plugin. Store and retrieve your master password in your KeyChain" );
75 #elif defined(Q_OS_WIN) 77 static const QString sDescription = QObject::tr(
"Master Password <-> Password Manager storage plugin. Store and retrieve your master password in your Password Manager" );
78 #elif defined(Q_OS_LINUX) 80 static const QString sDescription = QObject::tr(
"Master Password <-> Wallet/KeyRing storage plugin. Store and retrieve your master password in your Wallet/KeyRing" );
83 static const QString sDescription = QObject::tr(
"Master Password <-> KeyChain storage plugin. Store and retrieve your master password in your Wallet/KeyChain/Password Manager" );
93 QMutexLocker locker( &sMutex );
105 mMutex =
new QMutex( QMutex::Recursive );
107 this, &QgsAuthManager::writeToConsole );
118 QMutexLocker locker( mMutex );
123 const QString connectionName = QStringLiteral(
"authentication.configs:0x%1" ).arg( reinterpret_cast<quintptr>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char(
'0' ) );
124 QgsDebugMsgLevel( QStringLiteral(
"Using auth db connection name: %1 " ).arg( connectionName ), 2 );
125 if ( !QSqlDatabase::contains( connectionName ) )
127 QgsDebugMsgLevel( QStringLiteral(
"No existing connection, creating a new one" ), 2 );
128 authdb = QSqlDatabase::addDatabase( QStringLiteral(
"QSQLITE" ), connectionName );
133 QgsDebugMsgLevel( QStringLiteral(
"Scheduled auth db remove on thread close" ), 2 );
143 connect( QThread::currentThread(), &QThread::finished, QThread::currentThread(), [connectionName,
this ]
145 QMutexLocker locker( mMutex );
146 QgsDebugMsgLevel( QStringLiteral(
"Removing outdated connection to %1 on thread exit" ).arg( connectionName ), 2 );
147 QSqlDatabase::removeDatabase( connectionName );
148 }, Qt::DirectConnection );
154 authdb = QSqlDatabase::database( connectionName );
158 if ( !authdb.isOpen() )
160 if ( !authdb.open() )
162 const char *err = QT_TR_NOOP(
"Opening of authentication db FAILED" );
177 QgsDebugMsg( QStringLiteral(
"Initializing QCA..." ) );
178 mQcaInitializer = qgis::make_unique<QCA::Initializer>( QCA::Practical, 256 );
180 QgsDebugMsg( QStringLiteral(
"QCA initialized." ) );
181 QCA::scanForPlugins();
183 QgsDebugMsg( QStringLiteral(
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ) );
184 QStringList capabilities;
186 capabilities = QCA::supportedFeatures();
187 QgsDebugMsg( QStringLiteral(
"QCA supports: %1" ).arg( capabilities.join(
"," ) ) );
190 if ( !QCA::isSupported(
"cert", QStringLiteral(
"qca-ossl" ) ) )
192 mAuthDisabled =
true;
193 mAuthDisabledMessage = tr(
"QCA's OpenSSL plugin (qca-ossl) is missing" );
197 QgsDebugMsg( QStringLiteral(
"Prioritizing qca-ossl over all other QCA providers..." ) );
198 const QCA::ProviderList provds = QCA::providers();
200 for ( QCA::Provider *p : provds )
202 QString pn = p->name();
204 if ( pn != QLatin1String(
"qca-ossl" ) )
206 pr = QCA::providerPriority( pn ) + 1;
208 QCA::setProviderPriority( pn, pr );
209 prlist << QStringLiteral(
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
211 QgsDebugMsg( QStringLiteral(
"QCA provider priorities: %1" ).arg( prlist.join(
", " ) ) );
213 QgsDebugMsg( QStringLiteral(
"Populating auth method registry" ) );
218 QgsDebugMsg( QStringLiteral(
"Authentication methods found: %1" ).arg( methods.join(
", " ) ) );
220 if ( methods.isEmpty() )
222 mAuthDisabled =
true;
223 mAuthDisabledMessage = tr(
"No authentication method plugins found" );
229 mAuthDisabled =
true;
230 mAuthDisabledMessage = tr(
"No authentication method plugins could be loaded" );
234 mAuthDbPath = QDir::cleanPath( authDatabasePath );
238 QFileInfo dbdirinfo( dbinfo.path() );
239 QgsDebugMsg( QStringLiteral(
"Auth db directory path: %1" ).arg( dbdirinfo.filePath() ) );
241 if ( !dbdirinfo.exists() )
243 QgsDebugMsg( QStringLiteral(
"Auth db directory path does not exist, making path: %1" ).arg( dbdirinfo.filePath() ) );
244 if ( !QDir().mkpath( dbdirinfo.filePath() ) )
246 const char *err = QT_TR_NOOP(
"Auth db directory path could not be created" );
253 if ( dbinfo.exists() )
255 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
257 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
262 if ( dbinfo.size() > 0 )
264 QgsDebugMsg( QStringLiteral(
"Auth db exists and has data" ) );
266 if ( !createCertTables() )
276 const char *passenv =
"QGIS_AUTH_PASSWORD_FILE";
279 QString passpath( getenv( passenv ) );
288 QFile passfile( passpath );
289 if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
291 QTextStream passin( &passfile );
292 while ( !passin.atEnd() )
294 masterpass = passin.readLine();
299 if ( !masterpass.isEmpty() )
303 QgsDebugMsg( QStringLiteral(
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" ) );
307 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
313 QgsDebugMsg(
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
323 QgsDebugMsg( QStringLiteral(
"Auth db does not exist: creating through QSqlDatabase initial connection" ) );
325 if ( !createConfigTables() )
328 if ( !createCertTables() )
339 bool QgsAuthManager::createConfigTables()
341 QMutexLocker locker( mMutex );
345 const char *err = QT_TR_NOOP(
"Auth db could not be created and opened" );
356 qstr = QString(
"CREATE TABLE %1 (\n" 357 " 'salt' TEXT NOT NULL,\n" 358 " 'civ' TEXT NOT NULL\n" 359 ", 'hash' TEXT NOT NULL);" ).arg( authDbPassTable() );
360 query.prepare( qstr );
361 if ( !authDbQuery( &query ) )
365 qstr = QString(
"CREATE TABLE %1 (\n" 366 " 'id' TEXT NOT NULL,\n" 367 " 'name' TEXT NOT NULL,\n" 369 " 'type' TEXT NOT NULL,\n" 370 " 'version' INTEGER NOT NULL\n" 372 query.prepare( qstr );
373 if ( !authDbQuery( &query ) )
378 query.prepare( qstr );
379 if ( !authDbQuery( &query ) )
384 query.prepare( qstr );
385 if ( !authDbQuery( &query ) )
392 bool QgsAuthManager::createCertTables()
394 QMutexLocker locker( mMutex );
396 QgsDebugMsg( QStringLiteral(
"Creating cert tables in auth db" ) );
403 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 404 " 'setting' TEXT NOT NULL\n" 405 ", 'value' TEXT);" ).arg( authDbSettingsTable() );
406 query.prepare( qstr );
407 if ( !authDbQuery( &query ) )
412 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 413 " 'id' TEXT NOT NULL,\n" 414 " 'key' TEXT NOT NULL\n" 415 ", 'cert' TEXT NOT NULL);" ).arg( authDbIdentitiesTable() );
416 query.prepare( qstr );
417 if ( !authDbQuery( &query ) )
421 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbIdentitiesTable() );
422 query.prepare( qstr );
423 if ( !authDbQuery( &query ) )
428 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 429 " 'id' TEXT NOT NULL,\n" 430 " 'host' TEXT NOT NULL,\n" 433 query.prepare( qstr );
434 if ( !authDbQuery( &query ) )
438 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'host_index' on %1 (host ASC);" ).arg(
authDatabaseServersTable() );
439 query.prepare( qstr );
440 if ( !authDbQuery( &query ) )
445 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 446 " 'id' TEXT NOT NULL\n" 447 ", 'cert' TEXT NOT NULL);" ).arg( authDbAuthoritiesTable() );
448 query.prepare( qstr );
449 if ( !authDbQuery( &query ) )
453 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbAuthoritiesTable() );
454 query.prepare( qstr );
455 if ( !authDbQuery( &query ) )
459 qstr = QString(
"CREATE TABLE IF NOT EXISTS %1 (\n" 460 " 'id' TEXT NOT NULL\n" 461 ", 'policy' TEXT NOT NULL);" ).arg( authDbTrustTable() );
462 query.prepare( qstr );
463 if ( !authDbQuery( &query ) )
467 qstr = QStringLiteral(
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbTrustTable() );
468 query.prepare( qstr );
469 if ( !authDbQuery( &query ) )
480 QgsDebugMsg( QStringLiteral(
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" ) );
482 return mAuthDisabled;
487 return tr(
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
492 QMutexLocker locker( mMutex );
496 if ( mScheduledDbErase )
499 if ( mMasterPass.isEmpty() )
501 QgsDebugMsg( QStringLiteral(
"Master password is not yet set by user" ) );
502 if ( !masterPasswordInput() )
504 QgsDebugMsg( QStringLiteral(
"Master password input canceled by user" ) );
510 QgsDebugMsg( QStringLiteral(
"Master password is set" ) );
518 QgsDebugMsg( QStringLiteral(
"Master password is set and verified" ) );
524 QMutexLocker locker( mMutex );
528 if ( mScheduledDbErase )
532 QString prevpass = QString( mMasterPass );
536 mMasterPass = prevpass;
537 const char *err = QT_TR_NOOP(
"Master password set: FAILED to verify, reset to previous" );
543 QgsDebugMsg( QStringLiteral(
"Master password set: SUCCESS%1" ).arg( verify ?
" and verified" :
"" ) );
553 if ( !masterPasswordRowsInDb( &rows ) )
555 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
563 QgsDebugMsg( QStringLiteral(
"Master password: %1 rows in database" ).arg( rows ) );
567 const char *err = QT_TR_NOOP(
"Master password: FAILED to find just one master password record in database" );
574 else if ( rows == 1 )
576 if ( !masterPasswordCheckAgainstDb( compare ) )
578 if ( compare.isNull() )
580 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
589 if ( mPassTries >= 5 )
591 mAuthDisabled =
true;
592 const char *err = QT_TR_NOOP(
"Master password: failed 5 times authentication system DISABLED" );
600 QgsDebugMsg( QStringLiteral(
"Master password: verified against hash in database" ) );
601 if ( compare.isNull() )
605 else if ( compare.isNull() )
607 if ( !masterPasswordStoreInDb() )
609 const char *err = QT_TR_NOOP(
"Master password: hash FAILED to be stored in database" );
618 QgsDebugMsg( QStringLiteral(
"Master password: hash stored in database" ) );
621 if ( !masterPasswordCheckAgainstDb() )
623 const char *err = QT_TR_NOOP(
"Master password: FAILED to verify against hash in database" );
633 QgsDebugMsg( QStringLiteral(
"Master password: verified against hash in database" ) );
643 return !mMasterPass.isEmpty();
648 return mMasterPass == pass;
652 bool keepbackup, QString *backuppath )
666 QgsDebugMsg( QStringLiteral(
"Master password reset: backed up current database" ) );
672 QString prevpass = QString( mMasterPass );
673 QString prevciv = QString( masterPasswordCiv() );
679 if ( ok && !masterPasswordClearDb() )
682 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not clear current password from database" );
688 QgsDebugMsg( QStringLiteral(
"Master password reset: cleared current password from database" ) );
695 if ( ok && !masterPasswordStoreInDb() )
698 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not store new password in database" );
704 QgsDebugMsg( QStringLiteral(
"Master password reset: stored new password in database" ) );
711 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify new password in database" );
717 if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
720 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt configs in database" );
726 QgsDebugMsg( QStringLiteral(
"Master password reset: re-encrypted configs in database" ) );
730 if ( ok && !verifyPasswordCanDecryptConfigs() )
733 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
738 if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
741 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt settings in database" );
746 if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
749 const char *err = QT_TR_NOOP(
"Master password reset FAILED: could not re-encrypt identities in database" );
759 QString errdbbackup( dbbackup );
760 errdbbackup.replace( QLatin1String(
".db" ), QLatin1String(
"_ERROR.db" ) );
762 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
766 mMasterPass = prevpass;
768 QgsDebugMsg( QStringLiteral(
"Master password reset FAILED: reinstated previous password and database" ) );
772 *backuppath = errdbbackup;
778 if ( !keepbackup && !QFile::remove( dbbackup ) )
780 const char *err = QT_TR_NOOP(
"Master password reset: could not remove old database backup" );
788 QgsDebugMsg( QStringLiteral(
"Master password reset: backed up previous db at %1" ).arg( dbbackup ) );
790 *backuppath = dbbackup;
793 QgsDebugMsg( QStringLiteral(
"Master password reset: SUCCESS" ) );
800 mScheduledDbErase = scheduleErase;
802 mScheduledDbEraseRequestEmitted =
false;
803 mScheduledDbEraseRequestCount = 0;
807 if ( !mScheduledDbEraseTimer )
809 mScheduledDbEraseTimer =
new QTimer(
this );
810 connect( mScheduledDbEraseTimer, &QTimer::timeout,
this, &QgsAuthManager::tryToStartDbErase );
811 mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
813 else if ( !mScheduledDbEraseTimer->isActive() )
815 mScheduledDbEraseTimer->start();
820 if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
821 mScheduledDbEraseTimer->stop();
830 qDeleteAll( mAuthMethods );
831 mAuthMethods.clear();
833 for (
const auto &authMethodKey : methods )
838 return !mAuthMethods.isEmpty();
848 QTimer::singleShot( 3, &loop, &QEventLoop::quit );
851 uint
seed =
static_cast< uint
>( QTime::currentTime().msec() );
857 for (
int i = 0; i < len; i++ )
859 switch ( qrand() % 2 )
862 id += (
'0' + qrand() % 10 );
865 id += (
'a' + qrand() % 26 );
869 if ( !configids.contains(
id ) )
874 QgsDebugMsg( QStringLiteral(
"Generated unique ID: %1" ).arg(
id ) );
885 const char *err = QT_TR_NOOP(
"Config ID is empty" );
891 return !configids.contains(
id );
896 QRegExp rx( AUTH_CFG_REGEX );
897 return rx.indexIn( txt ) != -1;
902 QMutexLocker locker( mMutex );
903 QStringList providerAuthMethodsKeys;
904 if ( !dataprovider.isEmpty() )
915 query.prepare( QStringLiteral(
"SELECT id, name, uri, type, version FROM %1" ).arg(
authDatabaseConfigTable() ) );
917 if ( !authDbQuery( &query ) )
922 if ( query.isActive() && query.isSelect() )
924 while ( query.next() )
926 QString authcfg = query.value( 0 ).toString();
928 config.
setId( authcfg );
929 config.
setName( query.value( 1 ).toString() );
930 config.
setUri( query.value( 2 ).toString() );
931 config.
setMethod( query.value( 3 ).toString() );
932 config.
setVersion( query.value( 4 ).toInt() );
934 if ( !dataprovider.isEmpty() && !providerAuthMethodsKeys.contains( config.
method() ) )
939 baseConfigs.insert( authcfg, config );
947 QMutexLocker locker( mMutex );
954 if ( !authDbQuery( &query ) )
959 if ( query.isActive() )
961 QgsDebugMsg( QStringLiteral(
"Synching existing auth config and their auth methods" ) );
962 mConfigAuthMethods.clear();
963 QStringList cfgmethods;
964 while ( query.next() )
966 mConfigAuthMethods.insert( query.value( 0 ).toString(),
967 query.value( 1 ).toString() );
968 cfgmethods << QStringLiteral(
"%1=%2" ).arg( query.value( 0 ).toString(), query.value( 1 ).toString() );
970 QgsDebugMsg( QStringLiteral(
"Stored auth config/methods:\n%1" ).arg( cfgmethods.join(
", " ) ) );
979 if ( !mConfigAuthMethods.contains( authcfg ) )
981 QgsDebugMsg( QStringLiteral(
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
985 QString authMethodKey = mConfigAuthMethods.value( authcfg );
995 return mConfigAuthMethods.value( authcfg, QString() );
1006 if ( !mAuthMethods.contains( authMethodKey ) )
1008 QgsDebugMsg( QStringLiteral(
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
1012 return mAuthMethods.value( authMethodKey );
1017 if ( dataprovider.isEmpty() )
1019 return mAuthMethods;
1023 QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
1024 while ( i != mAuthMethods.constEnd() )
1027 && ( i.value()->supportedDataProviders().contains( QStringLiteral(
"all" ) )
1028 || i.value()->supportedDataProviders().contains( dataprovider ) ) )
1030 filteredmap.insert( i.key(), i.value() );
1045 return QgsAuthMethod::Expansions(
nullptr );
1052 return QgsAuthMethod::Expansions(
nullptr );
1057 QMutexLocker locker( mMutex );
1064 const char *err = QT_TR_NOOP(
"Store config: FAILED because config is invalid" );
1070 QString uid = mconfig.
id();
1071 bool passedinID = !uid.isEmpty();
1072 if ( uid.isEmpty() )
1078 const char *err = QT_TR_NOOP(
"Store config: FAILED because pre-defined config ID is not unique" );
1085 if ( configstring.isEmpty() )
1087 const char *err = QT_TR_NOOP(
"Store config: FAILED because config string is empty" );
1093 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1094 QgsDebugMsg( QStringLiteral(
"name: %1" ).arg( config.name() ) );
1095 QgsDebugMsg( QStringLiteral(
"uri: %1" ).arg( config.uri() ) );
1096 QgsDebugMsg( QStringLiteral(
"type: %1" ).arg( config.method() ) );
1097 QgsDebugMsg( QStringLiteral(
"version: %1" ).arg( config.version() ) );
1098 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1102 query.prepare( QString(
"INSERT INTO %1 (id, name, uri, type, version, config) " 1105 query.bindValue( QStringLiteral(
":id" ), uid );
1106 query.bindValue( QStringLiteral(
":name" ), mconfig.
name() );
1107 query.bindValue( QStringLiteral(
":uri" ), mconfig.
uri() );
1108 query.bindValue( QStringLiteral(
":type" ), mconfig.
method() );
1109 query.bindValue( QStringLiteral(
":version" ), mconfig.
version() );
1110 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1112 if ( !authDbStartTransaction() )
1115 if ( !authDbQuery( &query ) )
1118 if ( !authDbCommit() )
1123 mconfig.
setId( uid );
1127 QgsDebugMsg( QStringLiteral(
"Store config SUCCESS for authcfg: %1" ).arg( uid ) );
1134 QMutexLocker locker( mMutex );
1139 if ( !config.
isValid(
true ) )
1141 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is invalid" );
1148 if ( configstring.isEmpty() )
1150 const char *err = QT_TR_NOOP(
"Update config: FAILED because config is empty" );
1157 QgsDebugMsg( QStringLiteral(
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ) );
1158 QgsDebugMsg( QStringLiteral(
"id: %1" ).arg( config.
id() ) );
1163 QgsDebugMsg( QStringLiteral(
"config: %1" ).arg( configstring ) );
1167 if ( !query.prepare( QString(
"UPDATE %1 " 1168 "SET name = :name, uri = :uri, type = :type, version = :version, config = :config " 1171 const char *err = QT_TR_NOOP(
"Update config: FAILED to prepare query" );
1177 query.bindValue( QStringLiteral(
":id" ), config.
id() );
1178 query.bindValue( QStringLiteral(
":name" ), config.
name() );
1179 query.bindValue( QStringLiteral(
":uri" ), config.
uri() );
1180 query.bindValue( QStringLiteral(
":type" ), config.
method() );
1181 query.bindValue( QStringLiteral(
":version" ), config.
version() );
1182 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
1184 if ( !authDbStartTransaction() )
1187 if ( !authDbQuery( &query ) )
1190 if ( !authDbCommit() )
1198 QgsDebugMsg( QStringLiteral(
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ) );
1205 QMutexLocker locker( mMutex );
1215 query.prepare( QString(
"SELECT id, name, uri, type, version, config FROM %1 " 1220 query.prepare( QString(
"SELECT id, name, uri, type, version FROM %1 " 1224 query.bindValue( QStringLiteral(
":id" ), authcfg );
1226 if ( !authDbQuery( &query ) )
1231 if ( query.isActive() && query.isSelect() )
1233 if ( query.first() )
1235 mconfig.
setId( query.value( 0 ).toString() );
1236 mconfig.
setName( query.value( 1 ).toString() );
1237 mconfig.
setUri( query.value( 2 ).toString() );
1238 mconfig.
setMethod( query.value( 3 ).toString() );
1239 mconfig.
setVersion( query.value( 4 ).toInt() );
1254 QgsDebugMsg( QStringLiteral(
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
1257 QgsDebugMsg( QStringLiteral(
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ?
"full" :
"base", authcfg ) );
1262 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
1272 QMutexLocker locker( mMutex );
1276 if ( authcfg.isEmpty() )
1283 query.bindValue( QStringLiteral(
":id" ), authcfg );
1285 if ( !authDbStartTransaction() )
1288 if ( !authDbQuery( &query ) )
1291 if ( !authDbCommit() )
1298 QgsDebugMsg( QStringLiteral(
"REMOVED config for authcfg: %1" ).arg( authcfg ) );
1305 QMutexLocker locker( mMutex );
1311 bool res = authDbTransactionQuery( &query );
1319 QgsDebugMsg( QStringLiteral(
"Remove configs from database: %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
1326 QMutexLocker locker( mMutex );
1329 const char *err = QT_TR_NOOP(
"No authentication database found" );
1337 if ( authConn.isValid() && authConn.isOpen() )
1341 QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral(
"yyyy-MM-dd-hhmmss" ) ) );
1343 dbbackup.replace( QLatin1String(
".db" ), QStringLiteral(
"_%1.db" ).arg( datestamp ) );
1347 const char *err = QT_TR_NOOP(
"Could not back up authentication database" );
1354 *backuppath = dbbackup;
1356 QgsDebugMsg( QStringLiteral(
"Backed up auth database at %1" ).arg( dbbackup ) );
1362 QMutexLocker locker( mMutex );
1372 if ( backuppath && !dbbackup.isEmpty() )
1373 *backuppath = dbbackup;
1376 if ( dbinfo.exists() )
1378 if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
1380 const char *err = QT_TR_NOOP(
"Auth db is not readable or writable by user" );
1388 const char *err = QT_TR_NOOP(
"No authentication database found" );
1396 const char *err = QT_TR_NOOP(
"Authentication database could not be deleted" );
1402 mMasterPass = QString();
1404 QgsDebugMsg( QStringLiteral(
"Creating Auth db through QSqlDatabase initial connection" ) );
1407 if ( !authConn.isValid() || !authConn.isOpen() )
1409 const char *err = QT_TR_NOOP(
"Authentication database could not be initialized" );
1415 if ( !createConfigTables() )
1417 const char *err = QT_TR_NOOP(
"FAILED to create auth database config tables" );
1423 if ( !createCertTables() )
1425 const char *err = QT_TR_NOOP(
"FAILED to create auth database cert tables" );
1441 const QString &dataprovider )
1451 QgsDebugMsg( QStringLiteral(
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
1466 const QString &dataprovider )
1476 QgsDebugMsg( QStringLiteral(
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ) );
1492 const QString &dataprovider )
1502 QgsDebugMsg( QStringLiteral(
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
1527 QgsDebugMsg( QStringLiteral(
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
1536 QgsDebugMsg( QStringLiteral(
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ) );
1545 QMutexLocker locker( mMutex );
1546 if ( key.isEmpty() )
1549 QString storeval( value.toString() );
1565 query.prepare( QString(
"INSERT INTO %1 (setting, value) " 1566 "VALUES (:setting, :value)" ).arg( authDbSettingsTable() ) );
1568 query.bindValue( QStringLiteral(
":setting" ), key );
1569 query.bindValue( QStringLiteral(
":value" ), storeval );
1571 if ( !authDbStartTransaction() )
1574 if ( !authDbQuery( &query ) )
1577 if ( !authDbCommit() )
1580 QgsDebugMsg( QStringLiteral(
"Store setting SUCCESS for key: %1" ).arg( key ) );
1586 QMutexLocker locker( mMutex );
1587 if ( key.isEmpty() )
1593 QVariant value = defaultValue;
1595 query.prepare( QString(
"SELECT value FROM %1 " 1596 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1598 query.bindValue( QStringLiteral(
":setting" ), key );
1600 if ( !authDbQuery( &query ) )
1603 if ( query.isActive() && query.isSelect() )
1605 if ( query.first() )
1609 value = QVariant(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ) );
1613 value = query.value( 0 );
1615 QgsDebugMsg( QStringLiteral(
"Authentication setting retrieved for key: %1" ).arg( key ) );
1619 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1629 QMutexLocker locker( mMutex );
1630 if ( key.isEmpty() )
1634 query.prepare( QString(
"SELECT value FROM %1 " 1635 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1637 query.bindValue( QStringLiteral(
":setting" ), key );
1639 if ( !authDbQuery( &query ) )
1643 if ( query.isActive() && query.isSelect() )
1645 if ( query.first() )
1647 QgsDebugMsg( QStringLiteral(
"Authentication setting exists for key: %1" ).arg( key ) );
1652 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting key: %1" ).arg( key ) );
1662 QMutexLocker locker( mMutex );
1663 if ( key.isEmpty() )
1668 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
1670 query.bindValue( QStringLiteral(
":setting" ), key );
1672 if ( !authDbStartTransaction() )
1675 if ( !authDbQuery( &query ) )
1678 if ( !authDbCommit() )
1681 QgsDebugMsg( QStringLiteral(
"REMOVED setting for key: %1" ).arg( key ) );
1693 QMutexLocker locker( mMutex );
1700 QgsDebugMsg( QStringLiteral(
"Init of SSL caches %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
1706 QMutexLocker locker( mMutex );
1707 if ( cert.isNull() )
1709 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
1714 QgsDebugMsg( QStringLiteral(
"Passed private key is null" ) );
1724 QString certpem( cert.toPem() );
1728 query.prepare( QString(
"INSERT INTO %1 (id, key, cert) " 1729 "VALUES (:id, :key, :cert)" ).arg( authDbIdentitiesTable() ) );
1731 query.bindValue( QStringLiteral(
":id" ),
id );
1732 query.bindValue( QStringLiteral(
":key" ), keypem );
1733 query.bindValue( QStringLiteral(
":cert" ), certpem );
1735 if ( !authDbStartTransaction() )
1738 if ( !authDbQuery( &query ) )
1741 if ( !authDbCommit() )
1744 QgsDebugMsg( QStringLiteral(
"Store certificate identity SUCCESS for id: %1" ).arg(
id ) );
1750 QMutexLocker locker( mMutex );
1751 QSslCertificate emptycert;
1752 QSslCertificate cert;
1757 query.prepare( QString(
"SELECT cert FROM %1 " 1758 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1760 query.bindValue( QStringLiteral(
":id" ),
id );
1762 if ( !authDbQuery( &query ) )
1765 if ( query.isActive() && query.isSelect() )
1767 if ( query.first() )
1769 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
1770 QgsDebugMsg( QStringLiteral(
"Certificate identity retrieved for id: %1" ).arg(
id ) );
1774 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1784 QMutexLocker locker( mMutex );
1785 QPair<QSslCertificate, QSslKey> bundle;
1793 query.prepare( QString(
"SELECT key, cert FROM %1 " 1794 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1796 query.bindValue( QStringLiteral(
":id" ),
id );
1798 if ( !authDbQuery( &query ) )
1801 if ( query.isActive() && query.isSelect() )
1803 QSslCertificate cert;
1805 if ( query.first() )
1807 key = QSslKey(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ).toLatin1(),
1808 QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
1811 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create private key" );
1816 cert = QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1817 if ( cert.isNull() )
1819 const char *err = QT_TR_NOOP(
"Retrieve certificate identity bundle: FAILED to create certificate" );
1824 QgsDebugMsg( QStringLiteral(
"Certificate identity bundle retrieved for id: %1" ).arg(
id ) );
1828 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate identity for id: %1" ).arg(
id ) );
1832 bundle = qMakePair( cert, key );
1839 QMutexLocker locker( mMutex );
1843 return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
1845 return QStringList();
1850 QMutexLocker locker( mMutex );
1851 QList<QSslCertificate> certs;
1854 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbIdentitiesTable() ) );
1856 if ( !authDbQuery( &query ) )
1859 if ( query.isActive() && query.isSelect() )
1861 while ( query.next() )
1863 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
1872 QMutexLocker locker( mMutex );
1873 QStringList identityids = QStringList();
1879 query.prepare( QStringLiteral(
"SELECT id FROM %1" ).arg( authDbIdentitiesTable() ) );
1881 if ( !authDbQuery( &query ) )
1886 if ( query.isActive() )
1888 while ( query.next() )
1890 identityids << query.value( 0 ).toString();
1898 QMutexLocker locker( mMutex );
1903 query.prepare( QString(
"SELECT cert FROM %1 " 1904 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1906 query.bindValue( QStringLiteral(
":id" ),
id );
1908 if ( !authDbQuery( &query ) )
1912 if ( query.isActive() && query.isSelect() )
1914 if ( query.first() )
1916 QgsDebugMsg( QStringLiteral(
"Certificate bundle exists for id: %1" ).arg(
id ) );
1921 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate bundle for id: %1" ).arg(
id ) );
1931 QMutexLocker locker( mMutex );
1934 QgsDebugMsg( QStringLiteral(
"Passed bundle ID is empty" ) );
1940 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
1942 query.bindValue( QStringLiteral(
":id" ),
id );
1944 if ( !authDbStartTransaction() )
1947 if ( !authDbQuery( &query ) )
1950 if ( !authDbCommit() )
1953 QgsDebugMsg( QStringLiteral(
"REMOVED certificate identity for id: %1" ).arg(
id ) );
1959 QMutexLocker locker( mMutex );
1962 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
1971 QString certpem( cert.toPem() );
1974 query.prepare( QString(
"INSERT OR REPLACE INTO %1 (id, host, cert, config) " 1977 query.bindValue( QStringLiteral(
":id" ),
id );
1978 query.bindValue( QStringLiteral(
":host" ), config.
sslHostPort().trimmed() );
1979 query.bindValue( QStringLiteral(
":cert" ), certpem );
1980 query.bindValue( QStringLiteral(
":config" ), config.
configString() );
1982 if ( !authDbStartTransaction() )
1985 if ( !authDbQuery( &query ) )
1988 if ( !authDbCommit() )
1991 QgsDebugMsg( QStringLiteral(
"Store SSL cert custom config SUCCESS for host:port, id: %1, %2" )
2001 QMutexLocker locker( mMutex );
2004 if (
id.isEmpty() || hostport.isEmpty() )
2006 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2011 query.prepare( QString(
"SELECT id, host, cert, config FROM %1 " 2014 query.bindValue( QStringLiteral(
":id" ),
id );
2015 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2017 if ( !authDbQuery( &query ) )
2020 if ( query.isActive() && query.isSelect() )
2022 if ( query.first() )
2024 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2027 QgsDebugMsg( QStringLiteral(
"SSL cert custom config retrieved for host:port, id: %1, %2" ).arg( hostport,
id ) );
2031 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2032 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2043 QMutexLocker locker( mMutex );
2046 if ( hostport.isEmpty() )
2048 QgsDebugMsg( QStringLiteral(
"Passed host:port is empty" ) );
2053 query.prepare( QString(
"SELECT id, host, cert, config FROM %1 " 2056 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2058 if ( !authDbQuery( &query ) )
2061 if ( query.isActive() && query.isSelect() )
2063 if ( query.first() )
2065 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2068 QgsDebugMsg( QStringLiteral(
"SSL cert custom config retrieved for host:port: %1" ).arg( hostport ) );
2072 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port: %1" ).arg( hostport ) );
2073 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
2084 QMutexLocker locker( mMutex );
2085 QList<QgsAuthConfigSslServer> configs;
2090 if ( !authDbQuery( &query ) )
2093 if ( query.isActive() && query.isSelect() )
2095 while ( query.next() )
2098 config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
2102 configs.append( config );
2111 QMutexLocker locker( mMutex );
2112 if (
id.isEmpty() || hostport.isEmpty() )
2114 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2119 query.prepare( QString(
"SELECT cert FROM %1 " 2122 query.bindValue( QStringLiteral(
":id" ),
id );
2123 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2125 if ( !authDbQuery( &query ) )
2129 if ( query.isActive() && query.isSelect() )
2131 if ( query.first() )
2133 QgsDebugMsg( QStringLiteral(
"SSL cert custom config exists for host:port, id: %1, %2" ).arg( hostport,
id ) );
2138 QgsDebugMsg( QStringLiteral(
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2139 emit
messageOut( tr(
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
2149 QMutexLocker locker( mMutex );
2150 if (
id.isEmpty() || hostport.isEmpty() )
2152 QgsDebugMsg( QStringLiteral(
"Passed config ID or host:port is empty" ) );
2158 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id AND host = :host" ).arg(
authDatabaseServersTable() ) );
2160 query.bindValue( QStringLiteral(
":id" ),
id );
2161 query.bindValue( QStringLiteral(
":host" ), hostport.trimmed() );
2163 if ( !authDbStartTransaction() )
2166 if ( !authDbQuery( &query ) )
2169 if ( !authDbCommit() )
2172 QString shahostport( QStringLiteral(
"%1:%2" ).arg(
id, hostport ) );
2173 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2175 mIgnoredSslErrorsCache.remove( shahostport );
2178 QgsDebugMsg( QStringLiteral(
"REMOVED SSL cert custom config for host:port, id: %1, %2" ).arg( hostport,
id ) );
2185 QMutexLocker locker( mMutex );
2186 if ( !mIgnoredSslErrorsCache.isEmpty() )
2188 QgsDebugMsg( QStringLiteral(
"Ignored SSL errors cache items:" ) );
2189 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
2190 while ( i != mIgnoredSslErrorsCache.constEnd() )
2193 for (
auto err : i.value() )
2197 QgsDebugMsg( QStringLiteral(
"%1 = %2" ).arg( i.key(), errs.join(
", " ) ) );
2203 QgsDebugMsg( QStringLiteral(
"Ignored SSL errors cache EMPTY" ) );
2209 QMutexLocker locker( mMutex );
2212 QgsDebugMsg( QStringLiteral(
"Passed config is null" ) );
2216 QString shahostport( QStringLiteral(
"%1:%2" )
2219 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2221 mIgnoredSslErrorsCache.remove( shahostport );
2224 if ( !errenums.isEmpty() )
2226 mIgnoredSslErrorsCache.insert( shahostport, QSet<QSslError::SslError>::fromList( errenums ) );
2227 QgsDebugMsg( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2232 QgsDebugMsg( QStringLiteral(
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ) );
2238 QMutexLocker locker( mMutex );
2239 QRegExp rx(
"\\S+:\\S+:\\d+" );
2240 if ( !rx.exactMatch( shahostport ) )
2242 QgsDebugMsg(
"Passed shahostport does not match \\S+:\\S+:\\d+, " 2243 "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
2247 if ( mIgnoredSslErrorsCache.contains( shahostport ) )
2249 mIgnoredSslErrorsCache.remove( shahostport );
2252 if ( errors.isEmpty() )
2254 QgsDebugMsg( QStringLiteral(
"Passed errors list empty" ) );
2258 QSet<QSslError::SslError> errs;
2259 for (
const auto &error : errors )
2261 if ( error.error() == QSslError::NoError )
2264 errs.insert( error.error() );
2267 if ( errs.isEmpty() )
2269 QgsDebugMsg( QStringLiteral(
"Passed errors list does not contain errors" ) );
2273 mIgnoredSslErrorsCache.insert( shahostport, errs );
2275 QgsDebugMsg( QStringLiteral(
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ) );
2282 QMutexLocker locker( mMutex );
2283 QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
2284 QHash<QString, QSet<QSslError::SslError> > nextcache;
2289 if ( !authDbQuery( &query ) )
2291 QgsDebugMsg( QStringLiteral(
"Rebuild of ignored SSL errors cache FAILED" ) );
2295 if ( query.isActive() && query.isSelect() )
2297 while ( query.next() )
2299 QString shahostport( QStringLiteral(
"%1:%2" )
2300 .arg( query.value( 0 ).toString().trimmed(),
2301 query.value( 1 ).toString().trimmed() ) );
2305 if ( !errenums.isEmpty() )
2307 nextcache.insert( shahostport, QSet<QSslError::SslError>::fromList( errenums ) );
2309 if ( prevcache.contains( shahostport ) )
2311 prevcache.remove( shahostport );
2316 if ( !prevcache.isEmpty() )
2319 QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
2320 while ( i != prevcache.constEnd() )
2322 nextcache.insert( i.key(), i.value() );
2327 if ( nextcache != mIgnoredSslErrorsCache )
2329 mIgnoredSslErrorsCache.clear();
2330 mIgnoredSslErrorsCache = nextcache;
2331 QgsDebugMsg( QStringLiteral(
"Rebuild of ignored SSL errors cache SUCCEEDED" ) );
2336 QgsDebugMsg( QStringLiteral(
"Rebuild of ignored SSL errors cache SAME AS BEFORE" ) );
2344 QMutexLocker locker( mMutex );
2345 if ( certs.isEmpty() )
2347 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2351 for (
const auto &cert : certs )
2361 QMutexLocker locker( mMutex );
2364 if ( cert.isNull() )
2366 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2373 QString pem( cert.toPem() );
2376 query.prepare( QString(
"INSERT INTO %1 (id, cert) " 2377 "VALUES (:id, :cert)" ).arg( authDbAuthoritiesTable() ) );
2379 query.bindValue( QStringLiteral(
":id" ),
id );
2380 query.bindValue( QStringLiteral(
":cert" ), pem );
2382 if ( !authDbStartTransaction() )
2385 if ( !authDbQuery( &query ) )
2388 if ( !authDbCommit() )
2391 QgsDebugMsg( QStringLiteral(
"Store certificate authority SUCCESS for id: %1" ).arg(
id ) );
2397 QMutexLocker locker( mMutex );
2398 QSslCertificate emptycert;
2399 QSslCertificate cert;
2404 query.prepare( QString(
"SELECT cert FROM %1 " 2405 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2407 query.bindValue( QStringLiteral(
":id" ),
id );
2409 if ( !authDbQuery( &query ) )
2412 if ( query.isActive() && query.isSelect() )
2414 if ( query.first() )
2416 cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
2417 QgsDebugMsg( QStringLiteral(
"Certificate authority retrieved for id: %1" ).arg(
id ) );
2421 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2431 QMutexLocker locker( mMutex );
2432 if ( cert.isNull() )
2434 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2441 query.prepare( QString(
"SELECT value FROM %1 " 2442 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2444 query.bindValue( QStringLiteral(
":id" ),
id );
2446 if ( !authDbQuery( &query ) )
2450 if ( query.isActive() && query.isSelect() )
2452 if ( query.first() )
2454 QgsDebugMsg( QStringLiteral(
"Certificate authority exists for id: %1" ).arg(
id ) );
2459 QgsDebugMsg( QStringLiteral(
"Select contains more than one certificate authority for id: %1" ).arg(
id ) );
2469 QMutexLocker locker( mMutex );
2470 if ( cert.isNull() )
2472 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2480 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
2482 query.bindValue( QStringLiteral(
":id" ),
id );
2484 if ( !authDbStartTransaction() )
2487 if ( !authDbQuery( &query ) )
2490 if ( !authDbCommit() )
2493 QgsDebugMsg( QStringLiteral(
"REMOVED authority for id: %1" ).arg(
id ) );
2500 return QSslSocket::systemCaCertificates();
2502 QNetworkRequest req;
2503 return req.sslConfiguration().caCertificates();
2509 QMutexLocker locker( mMutex );
2510 QList<QSslCertificate> certs;
2511 QList<QSslCertificate> filecerts;
2513 if ( cafileval.isNull() )
2517 if ( allowinvalid.isNull() )
2520 QString cafile( cafileval.toString() );
2521 if ( !cafile.isEmpty() && QFile::exists( cafile ) )
2526 for (
const auto &cert : qgis::as_const( filecerts ) )
2528 if ( !allowinvalid.toBool() && !cert.isValid() )
2543 QMutexLocker locker( mMutex );
2544 QList<QSslCertificate> certs;
2547 query.prepare( QStringLiteral(
"SELECT id, cert FROM %1" ).arg( authDbAuthoritiesTable() ) );
2549 if ( !authDbQuery( &query ) )
2552 if ( query.isActive() && query.isSelect() )
2554 while ( query.next() )
2556 certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
2565 QMutexLocker locker( mMutex );
2571 QMutexLocker locker( mMutex );
2572 mCaCertsCache.clear();
2578 bool res = !mCaCertsCache.isEmpty();
2579 QgsDebugMsg( QStringLiteral(
"Rebuild of CA certs cache %1" ).arg( res ?
"SUCCEEDED" :
"FAILED" ) );
2585 QMutexLocker locker( mMutex );
2586 if ( cert.isNull() )
2588 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2598 QgsDebugMsg( QStringLiteral(
"Passed policy was default, all cert records in database were removed for id: %1" ).arg(
id ) );
2603 query.prepare( QString(
"INSERT INTO %1 (id, policy) " 2604 "VALUES (:id, :policy)" ).arg( authDbTrustTable() ) );
2606 query.bindValue( QStringLiteral(
":id" ),
id );
2607 query.bindValue( QStringLiteral(
":policy" ), static_cast< int >( policy ) );
2609 if ( !authDbStartTransaction() )
2612 if ( !authDbQuery( &query ) )
2615 if ( !authDbCommit() )
2618 QgsDebugMsg( QStringLiteral(
"Store certificate trust policy SUCCESS for id: %1" ).arg(
id ) );
2624 QMutexLocker locker( mMutex );
2625 if ( cert.isNull() )
2627 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2634 query.prepare( QString(
"SELECT policy FROM %1 " 2635 "WHERE id = :id" ).arg( authDbTrustTable() ) );
2637 query.bindValue( QStringLiteral(
":id" ),
id );
2639 if ( !authDbQuery( &query ) )
2643 if ( query.isActive() && query.isSelect() )
2645 if ( query.first() )
2648 QgsDebugMsg( QStringLiteral(
"Authentication cert trust policy retrieved for id: %1" ).arg(
id ) );
2652 QgsDebugMsg( QStringLiteral(
"Select contains more than one cert trust policy for id: %1" ).arg(
id ) );
2662 QMutexLocker locker( mMutex );
2663 if ( certs.empty() )
2665 QgsDebugMsg( QStringLiteral(
"Passed certificate list has no certs" ) );
2669 for (
const auto &cert : certs )
2679 QMutexLocker locker( mMutex );
2680 if ( cert.isNull() )
2682 QgsDebugMsg( QStringLiteral(
"Passed certificate is null" ) );
2690 query.prepare( QStringLiteral(
"DELETE FROM %1 WHERE id = :id" ).arg( authDbTrustTable() ) );
2692 query.bindValue( QStringLiteral(
":id" ),
id );
2694 if ( !authDbStartTransaction() )
2697 if ( !authDbQuery( &query ) )
2700 if ( !authDbCommit() )
2703 QgsDebugMsg( QStringLiteral(
"REMOVED cert trust policy for id: %1" ).arg(
id ) );
2710 QMutexLocker locker( mMutex );
2711 if ( cert.isNull() )
2721 if ( trustedids.contains(
id ) )
2725 else if ( untrustedids.contains(
id ) )
2740 return storeAuthSetting( QStringLiteral(
"certdefaulttrust" ), static_cast< int >( policy ) );
2745 QMutexLocker locker( mMutex );
2746 QVariant policy(
authSetting( QStringLiteral(
"certdefaulttrust" ) ) );
2747 if ( policy.isNull() )
2756 QMutexLocker locker( mMutex );
2757 mCertTrustCache.clear();
2760 query.prepare( QStringLiteral(
"SELECT id, policy FROM %1" ).arg( authDbTrustTable() ) );
2762 if ( !authDbQuery( &query ) )
2764 QgsDebugMsg( QStringLiteral(
"Rebuild of cert trust policy cache FAILED" ) );
2768 if ( query.isActive() && query.isSelect() )
2770 while ( query.next() )
2772 QString
id = query.value( 0 ).toString();
2776 if ( mCertTrustCache.contains( policy ) )
2778 ids = mCertTrustCache.value( policy );
2780 mCertTrustCache.insert( policy, ids <<
id );
2784 QgsDebugMsg( QStringLiteral(
"Rebuild of cert trust policy cache SUCCEEDED" ) );
2790 QMutexLocker locker( mMutex );
2794 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2796 QList<QSslCertificate> trustedcerts;
2797 for (
int i = 0; i < certpairs.size(); ++i )
2799 QSslCertificate cert( certpairs.at( i ).second );
2801 if ( trustedids.contains( certid ) )
2804 trustedcerts.append( cert );
2810 trustedcerts.append( cert );
2815 QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
2816 sslconfig.setCaCertificates( trustedcerts );
2817 QSslConfiguration::setDefaultConfiguration( sslconfig );
2819 return trustedcerts;
2824 QMutexLocker locker( mMutex );
2825 if ( trustedCAs.isEmpty() )
2827 if ( mTrustedCaCertsCache.isEmpty() )
2834 const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
2836 QList<QSslCertificate> untrustedCAs;
2837 for (
int i = 0; i < certpairs.size(); ++i )
2839 QSslCertificate cert( certpairs.at( i ).second );
2840 if ( !trustedCAs.contains( cert ) )
2842 untrustedCAs.append( cert );
2845 return untrustedCAs;
2850 QMutexLocker locker( mMutex );
2852 QgsDebugMsg( QStringLiteral(
"Rebuilt trusted cert authorities cache" ) );
2859 QMutexLocker locker( mMutex );
2865 QMutexLocker locker( mMutex );
2868 return passwordHelperWrite( mMasterPass );
2884 for (
const auto &authcfg : ids )
2902 void QgsAuthManager::writeToConsole(
const QString &message,
2916 msg += QLatin1String(
"WARNING: " );
2919 msg += QLatin1String(
"ERROR: " );
2926 QTextStream out( stdout, QIODevice::WriteOnly );
2930 void QgsAuthManager::tryToStartDbErase()
2932 ++mScheduledDbEraseRequestCount;
2934 int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
2935 if ( mScheduledDbEraseRequestCount >= trycutoff )
2938 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emitting/scheduling canceled" ) );
2943 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest attempt (%1 of %2)" )
2944 .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ) );
2950 mScheduledDbEraseRequestEmitted =
true;
2955 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emitted" ) );
2958 QgsDebugMsg( QStringLiteral(
"authDatabaseEraseRequest emit skipped" ) );
2967 qDeleteAll( mAuthMethods );
2970 if ( authConn.isValid() && authConn.isOpen() )
2975 delete mScheduledDbEraseTimer;
2976 mScheduledDbEraseTimer =
nullptr;
2977 QSqlDatabase::removeDatabase( QStringLiteral(
"authentication.configs" ) );
2981 QString QgsAuthManager::passwordHelperName()
const 2983 return tr(
"Password Helper" );
2987 void QgsAuthManager::passwordHelperLog(
const QString &msg )
const 2999 QKeychain::DeletePasswordJob 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();
3011 mPasswordHelperErrorMessage = tr(
"Delete password failed: %1." ).arg( job.errorString() );
3022 passwordHelperProcessError();
3026 QString QgsAuthManager::passwordHelperRead()
3031 QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3033 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3034 job.setAutoDelete(
false );
3035 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3037 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3042 mPasswordHelperErrorCode = job.error();
3049 password = job.textData();
3051 if ( password.isEmpty() )
3053 mPasswordHelperErrorCode = QKeychain::EntryNotFound;
3064 passwordHelperProcessError();
3068 bool QgsAuthManager::passwordHelperWrite(
const QString &password )
3070 Q_ASSERT( !password.isEmpty() );
3073 QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
3075 job.setInsecureFallback( settings.
value( QStringLiteral(
"password_helper_insecure_fallback" ),
false, QgsSettings::Section::Auth ).toBool() );
3076 job.setAutoDelete(
false );
3077 job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
3078 job.setTextData( password );
3080 connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
3085 mPasswordHelperErrorCode = job.error();
3093 passwordHelperClearErrors();
3098 passwordHelperProcessError();
3106 return settings.
value( QStringLiteral(
"use_password_helper" ),
true, QgsSettings::Section::Auth ).toBool();
3112 settings.
setValue( QStringLiteral(
"use_password_helper" ), enabled, QgsSettings::Section::Auth );
3113 emit
messageOut( enabled ? tr(
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
3115 tr(
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
3123 return settings.
value( QStringLiteral(
"password_helper_logging" ),
false, QgsSettings::Section::Auth ).toBool();
3129 settings.
setValue( QStringLiteral(
"password_helper_logging" ), enabled, QgsSettings::Section::Auth );
3132 void QgsAuthManager::passwordHelperClearErrors()
3134 mPasswordHelperErrorCode = QKeychain::NoError;
3135 mPasswordHelperErrorMessage.clear();
3138 void QgsAuthManager::passwordHelperProcessError()
3140 if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
3141 mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
3142 mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
3143 mPasswordHelperErrorCode == QKeychain::NotImplemented )
3149 mPasswordHelperErrorMessage = tr(
"There was an error and integration with your %1 system has been disabled. " 3150 "You can re-enable it at any time through the \"Utilities\" menu " 3151 "in the Authentication pane of the options dialog. %2" )
3154 if ( mPasswordHelperErrorCode != QKeychain::NoError )
3160 passwordHelperClearErrors();
3164 bool QgsAuthManager::masterPasswordInput()
3170 bool storedPasswordIsValid =
false;
3176 pass = passwordHelperRead();
3177 if ( ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
3183 storedPasswordIsValid =
true;
3200 if ( ok && !pass.isEmpty() && mMasterPass != pass )
3205 if ( passwordHelperWrite( pass ) )
3219 bool QgsAuthManager::masterPasswordRowsInDb(
int *rows )
const 3225 query.prepare( QStringLiteral(
"SELECT Count(*) FROM %1" ).arg( authDbPassTable() ) );
3227 bool ok = authDbQuery( &query );
3228 if ( query.first() )
3230 *rows = query.value( 0 ).toInt();
3242 if ( !masterPasswordRowsInDb( &rows ) )
3244 const char *err = QT_TR_NOOP(
"Master password: FAILED to access database" );
3250 return ( rows == 1 );
3253 bool QgsAuthManager::masterPasswordCheckAgainstDb(
const QString &compare )
const 3261 query.prepare( QStringLiteral(
"SELECT salt, hash FROM %1" ).arg( authDbPassTable() ) );
3262 if ( !authDbQuery( &query ) )
3265 if ( !query.first() )
3268 QString salt = query.value( 0 ).toString();
3269 QString hash = query.value( 1 ).toString();
3274 bool QgsAuthManager::masterPasswordStoreInDb()
const 3279 QString salt, hash, civ;
3283 query.prepare( QStringLiteral(
"INSERT INTO %1 (salt, hash, civ) VALUES (:salt, :hash, :civ)" ).arg( authDbPassTable() ) );
3285 query.bindValue( QStringLiteral(
":salt" ), salt );
3286 query.bindValue( QStringLiteral(
":hash" ), hash );
3287 query.bindValue( QStringLiteral(
":civ" ), civ );
3289 if ( !authDbStartTransaction() )
3292 if ( !authDbQuery( &query ) )
3295 if ( !authDbCommit() )
3301 bool QgsAuthManager::masterPasswordClearDb()
3307 query.prepare( QStringLiteral(
"DELETE FROM %1" ).arg( authDbPassTable() ) );
3308 bool res = authDbTransactionQuery( &query );
3314 const QString QgsAuthManager::masterPasswordCiv()
const 3320 query.prepare( QStringLiteral(
"SELECT civ FROM %1" ).arg( authDbPassTable() ) );
3321 if ( !authDbQuery( &query ) )
3324 if ( !query.first() )
3327 return query.value( 0 ).toString();
3332 QStringList configids = QStringList();
3340 if ( !authDbQuery( &query ) )
3345 if ( query.isActive() )
3347 while ( query.next() )
3349 configids << query.value( 0 ).toString();
3355 bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
const 3366 if ( !authDbQuery( &query ) )
3369 if ( !query.isActive() || !query.isSelect() )
3371 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, query not active or a select operation" ) );
3376 while ( query.next() )
3379 QString configstring(
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 1 ).toString() ) );
3380 if ( configstring.isEmpty() )
3382 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1)" )
3383 .arg( query.value( 0 ).toString() ) );
3388 QgsDebugMsg( QStringLiteral(
"Verify password can decrypt configs SUCCESS (checked %1 configs)" ).arg( checked ) );
3392 bool QgsAuthManager::reencryptAllAuthenticationConfigs(
const QString &prevpass,
const QString &prevciv )
3399 for (
const auto &configid : ids )
3401 res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
3406 bool QgsAuthManager::reencryptAuthenticationConfig(
const QString &authcfg,
const QString &prevpass,
const QString &prevciv )
3415 query.prepare( QString(
"SELECT config FROM %1 " 3418 query.bindValue( QStringLiteral(
":id" ), authcfg );
3420 if ( !authDbQuery( &query ) )
3423 if ( !query.isActive() || !query.isSelect() )
3425 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for authcfg: %2" ).arg( authcfg ) );
3429 if ( query.first() )
3435 QgsDebugMsg( QStringLiteral(
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
3442 query.prepare( QString(
"UPDATE %1 " 3443 "SET config = :config " 3446 query.bindValue( QStringLiteral(
":id" ), authcfg );
3447 query.bindValue( QStringLiteral(
":config" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
3449 if ( !authDbStartTransaction() )
3452 if ( !authDbQuery( &query ) )
3455 if ( !authDbCommit() )
3458 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for authcfg: %2" ).arg( authcfg ) );
3463 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db authcfg: %2" ).arg( authcfg ) );
3468 bool QgsAuthManager::reencryptAllAuthenticationSettings(
const QString &prevpass,
const QString &prevciv )
3471 Q_UNUSED( prevpass );
3472 Q_UNUSED( prevciv );
3484 QStringList encryptedsettings;
3485 encryptedsettings <<
"";
3487 for (
const auto & sett, qgis::as_const( encryptedsettings ) )
3494 QSqlQuery query( authDbConnection() );
3496 query.prepare( QString(
"SELECT value FROM %1 " 3497 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3499 query.bindValue(
":setting", sett );
3501 if ( !authDbQuery( &query ) )
3504 if ( !query.isActive() || !query.isSelect() )
3506 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
3510 if ( query.first() )
3516 query.prepare( QString(
"UPDATE %1 " 3517 "SET value = :value " 3518 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
3520 query.bindValue(
":setting", sett );
3523 if ( !authDbStartTransaction() )
3526 if ( !authDbQuery( &query ) )
3529 if ( !authDbCommit() )
3532 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for setting: %2" ).arg( sett ) );
3537 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
3543 QgsDebugMsg( QStringLiteral(
"Select contains more than one for setting: %1" ).arg( sett ) );
3554 bool QgsAuthManager::reencryptAllAuthenticationIdentities(
const QString &prevpass,
const QString &prevciv )
3561 for (
const auto &identid : ids )
3563 res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
3568 bool QgsAuthManager::reencryptAuthenticationIdentity(
3569 const QString &identid,
3570 const QString &prevpass,
3571 const QString &prevciv )
3580 query.prepare( QString(
"SELECT key FROM %1 " 3581 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3583 query.bindValue( QStringLiteral(
":id" ), identid );
3585 if ( !authDbQuery( &query ) )
3588 if ( !query.isActive() || !query.isSelect() )
3590 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, query not active or a select operation for identity id: %2" ).arg( identid ) );
3594 if ( query.first() )
3600 QgsDebugMsg( QStringLiteral(
"Select contains more than one for identity id: %1" ).arg( identid ) );
3607 query.prepare( QString(
"UPDATE %1 " 3609 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
3611 query.bindValue( QStringLiteral(
":id" ), identid );
3612 query.bindValue( QStringLiteral(
":key" ),
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), keystring ) );
3614 if ( !authDbStartTransaction() )
3617 if ( !authDbQuery( &query ) )
3620 if ( !authDbCommit() )
3623 QgsDebugMsg( QStringLiteral(
"Reencrypt SUCCESS for identity id: %2" ).arg( identid ) );
3628 QgsDebugMsg( QStringLiteral(
"Reencrypt FAILED, could not find in db identity id: %2" ).arg( identid ) );
3633 bool QgsAuthManager::authDbOpen()
const 3639 if ( !authdb.isOpen() )
3641 if ( !authdb.open() )
3643 QgsDebugMsg( QStringLiteral(
"Unable to establish database connection\nDatabase: %1\nDriver error: %2\nDatabase error: %3" )
3645 authdb.lastError().driverText(),
3646 authdb.lastError().databaseText() ) );
3654 bool QgsAuthManager::authDbQuery( QSqlQuery *query )
const 3659 query->setForwardOnly(
true );
3660 if ( !query->exec() )
3662 const char *err = QT_TR_NOOP(
"Auth db query exec() FAILED" );
3668 if ( query->lastError().isValid() )
3670 QgsDebugMsg( QStringLiteral(
"Auth db query FAILED: %1\nError: %2" )
3671 .arg( query->executedQuery(),
3672 query->lastError().text() ) );
3680 bool QgsAuthManager::authDbStartTransaction()
const 3687 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3696 bool QgsAuthManager::authDbCommit()
const 3703 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3713 bool QgsAuthManager::authDbTransactionQuery( QSqlQuery *query )
const 3720 const char *err = QT_TR_NOOP(
"Auth db FAILED to start transaction" );
3726 bool ok = authDbQuery( query );
3730 const char *err = QT_TR_NOOP(
"Auth db FAILED to rollback changes" );
3742 for (
const auto &cert : certs )
3745 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.
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
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.
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) ...
#define QgsDebugMsgLevel(str, level)
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...
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