21#include <QMutexLocker> 
   24#include <QSqlDatabase> 
   33#include <QDomDocument> 
   34#include <QRegularExpression> 
   35#include <QCoreApplication> 
   36#include <QRandomGenerator> 
   41#include <QSslConfiguration> 
   54#include "moc_qgsauthmanager.cpp" 
   65const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral( 
"auth_configs" );
 
   66const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral( 
"auth_servers" );
 
   68const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral( 
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
 
   71const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME_BASE( 
"QGIS-Master-Password" );
 
   72const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME( 
"QGIS" );
 
   80#elif defined(Q_OS_WIN) 
   82#elif defined(Q_OS_LINUX) 
   92  QMutexLocker locker( &sMutex );
 
 
  103  mMutex = std::make_unique<QRecursiveMutex>();
 
  104  mMasterPasswordMutex = std::make_unique<QRecursiveMutex>();
 
  106           this, &QgsAuthManager::writeToConsole );
 
 
  120  QMutexLocker locker( mMutex.get() );
 
  125    return storage->authDatabaseConnection();
 
 
  139    const QList<QgsAuthConfigurationStorage *> storages { storageRegistry->
readyStorages() };
 
  142      if ( 
auto dbStorage = qobject_cast<QgsAuthConfigurationStorageDb *>( storage ) )
 
  146          return dbStorage->quotedQualifiedIdentifier( dbStorage->methodConfigTableName() );
 
 
  159  const auto drivers { QSqlDatabase::drivers() };
 
  160  for ( 
const QString &driver : std::as_const( drivers ) )
 
  162    if ( driver != ( QStringLiteral( 
"QSQLITE" ) ) && driver != ( QStringLiteral( 
"QSPATIALITE" ) ) && uri.startsWith( driver ) )
 
 
  172  return mAuthDatabaseConnectionUri;
 
 
  177  QRegularExpression re( QStringLiteral( 
"password=(.*)" ) );
 
  178  QString uri = mAuthDatabaseConnectionUri;
 
  179  return uri.replace( re, QStringLiteral( 
"password=*****" ) );
 
 
  185  mAuthDatabaseConnectionUri = authDatabasePath.startsWith( QLatin1String( 
"QSQLITE://" ) ) ? authDatabasePath : QStringLiteral( 
"QSQLITE://" ) + authDatabasePath;
 
  186  return initPrivate( pluginPath );
 
 
  191  static QRecursiveMutex sInitializationMutex;
 
  192  static bool sInitialized = 
false;
 
  194  sInitializationMutex.lock();
 
  197    sInitializationMutex.unlock();
 
  198    return mLazyInitResult;
 
  201  mLazyInitResult = 
const_cast< QgsAuthManager * 
>( this )->initPrivate( mPluginPath );
 
  203  sInitializationMutex.unlock();
 
  205  return mLazyInitResult;
 
 
  208static char *sPassFileEnv = 
nullptr;
 
  210bool QgsAuthManager::initPrivate( 
const QString &pluginPath )
 
  219  mQcaInitializer = std::make_unique<QCA::Initializer>( QCA::Practical, 256 );
 
  222  QCA::scanForPlugins();
 
  224  QgsDebugMsgLevel( QStringLiteral( 
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ), 2 );
 
  225  QStringList capabilities;
 
  227  capabilities = QCA::supportedFeatures();
 
  228  QgsDebugMsgLevel( QStringLiteral( 
"QCA supports: %1" ).arg( capabilities.join( 
"," ) ), 2 );
 
  231  if ( !QCA::isSupported( 
"cert", QStringLiteral( 
"qca-ossl" ) ) )
 
  233    mAuthDisabled = 
true;
 
  234    mAuthDisabledMessage = tr( 
"QCA's OpenSSL plugin (qca-ossl) is missing" );
 
  238  QgsDebugMsgLevel( QStringLiteral( 
"Prioritizing qca-ossl over all other QCA providers..." ), 2 );
 
  239  const QCA::ProviderList provds = QCA::providers();
 
  241  for ( QCA::Provider *p : provds )
 
  243    QString pn = p->name();
 
  245    if ( pn != QLatin1String( 
"qca-ossl" ) )
 
  247      pr = QCA::providerPriority( pn ) + 1;
 
  249    QCA::setProviderPriority( pn, pr );
 
  250    prlist << QStringLiteral( 
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
 
  252  QgsDebugMsgLevel( QStringLiteral( 
"QCA provider priorities: %1" ).arg( prlist.join( 
", " ) ), 2 );
 
  259  QgsDebugMsgLevel( QStringLiteral( 
"Authentication methods found: %1" ).arg( methods.join( 
", " ) ), 2 );
 
  261  if ( methods.isEmpty() )
 
  263    mAuthDisabled = 
true;
 
  264    mAuthDisabledMessage = tr( 
"No authentication method plugins found" );
 
  270    mAuthDisabled = 
true;
 
  271    mAuthDisabledMessage = tr( 
"No authentication method plugins could be loaded" );
 
  275  QgsDebugMsgLevel( QStringLiteral( 
"Auth database URI: %1" ).arg( mAuthDatabaseConnectionUri ), 2 );
 
  279  if ( ! sqliteDbPath.isEmpty() )
 
  283  else if ( ! mAuthDatabaseConnectionUri.isEmpty() )
 
  306      const QString err = tr( 
"Failed to initialize storage %1: %2" ).arg( storage->
name(), storage->
lastError() );
 
  326    QString passpath( sPassFileEnv );
 
  327    free( sPassFileEnv );
 
  328    sPassFileEnv = 
nullptr;
 
  331    QFile passfile( passpath );
 
  332    if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
 
  334      QTextStream passin( &passfile );
 
  335      while ( !passin.atEnd() )
 
  337        masterpass = passin.readLine();
 
  342    if ( !masterpass.isEmpty() )
 
  346        QgsDebugMsgLevel( QStringLiteral( 
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" ), 2 );
 
  350        QgsDebugError( 
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
 
  356      QgsDebugError( 
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
 
  370  mPluginPath = pluginPath;
 
  371  mAuthDatabaseConnectionUri = authDatabasePath;
 
  373  const char *p = getenv( 
"QGIS_AUTH_PASSWORD_FILE" );
 
  376    sPassFileEnv = qstrdup( p );
 
  381    putenv( 
"QGIS_AUTH_PASSWORD_FILE" );
 
  383    unsetenv( 
"QGIS_AUTH_PASSWORD_FILE" );
 
 
  388QString QgsAuthManager::generatePassword()
 
  390  QRandomGenerator generator = QRandomGenerator::securelySeeded();
 
  393  static const QString sPwChars = QStringLiteral( 
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-{}[]" );
 
  394  for ( 
int i = 0; i < pw.size(); ++i )
 
  396    pw[i] = sPwChars.at( generator.bounded( 0, sPwChars.length() ) );
 
  407    QgsDebugError( QStringLiteral( 
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" ) );
 
  409  return mAuthDisabled;
 
 
  416  return tr( 
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
 
 
  421  QMutexLocker locker( mMasterPasswordMutex.get() );
 
  425  if ( mScheduledDbErase )
 
  431  if ( !mMasterPass.isEmpty() )
 
  433    QgsDebugError( QStringLiteral( 
"Master password is already set!" ) );
 
  437  const QString newPassword = generatePassword();
 
  438  if ( passwordHelperWrite( newPassword ) )
 
  440    mMasterPass = newPassword;
 
  454  QgsDebugMsgLevel( QStringLiteral( 
"Master password is set and verified" ), 2 );
 
 
  468  QString path = mAuthDatabaseConnectionUri;
 
  469  if ( path.startsWith( QStringLiteral( 
"QSQLITE://" ), Qt::CaseSensitivity::CaseInsensitive ) )
 
  471    path = path.mid( 10 );
 
  473  else if ( path.startsWith( QStringLiteral( 
"QSPATIALITE://" ), Qt::CaseSensitivity::CaseInsensitive ) )
 
  475    path = path.mid( 14 );
 
  478  return QDir::cleanPath( path );
 
 
  490  QMutexLocker locker( mMasterPasswordMutex.get() );
 
  494  if ( mScheduledDbErase )
 
  497  if ( mMasterPass.isEmpty() )
 
  499    QgsDebugMsgLevel( QStringLiteral( 
"Master password is not yet set by user" ), 2 );
 
  500    if ( !masterPasswordInput() )
 
  502      QgsDebugMsgLevel( QStringLiteral( 
"Master password input canceled by user" ), 2 );
 
  516  QgsDebugMsgLevel( QStringLiteral( 
"Master password is set and verified" ), 2 );
 
 
  524  QMutexLocker locker( mMutex.get() );
 
  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  QgsDebugMsgLevel( QStringLiteral( 
"Master password set: SUCCESS%1" ).arg( verify ? 
" and verified" : 
"" ), 2 );
 
 
  555  if ( !masterPasswordRowsInDb( &rows ) )
 
  557    const char *err = QT_TR_NOOP( 
"Master password: FAILED to access database" );
 
  565  QgsDebugMsgLevel( QStringLiteral( 
"Master password: %1 rows in database" ).arg( rows ), 2 );
 
  569    const char *err = QT_TR_NOOP( 
"Master password: FAILED to find just one master password record in database" );
 
  576  else if ( rows == 1 )
 
  578    if ( !masterPasswordCheckAgainstDb( compare ) )
 
  580      if ( compare.isNull() ) 
 
  582        const char *err = QT_TR_NOOP( 
"Master password: FAILED to verify against hash in database" );
 
  591      if ( mPassTries >= 5 )
 
  593        mAuthDisabled = 
true;
 
  594        const char *err = QT_TR_NOOP( 
"Master password: failed 5 times authentication system DISABLED" );
 
  602      QgsDebugMsgLevel( QStringLiteral( 
"Master password: verified against hash in database" ), 2 );
 
  603      if ( compare.isNull() )
 
  607  else if ( compare.isNull() ) 
 
  609    if ( !masterPasswordStoreInDb() )
 
  611      const char *err = QT_TR_NOOP( 
"Master password: hash FAILED to be stored in database" );
 
  620      QgsDebugMsgLevel( QStringLiteral( 
"Master password: hash stored in database" ), 2 );
 
  623    if ( !masterPasswordCheckAgainstDb() )
 
  625      const char *err = QT_TR_NOOP( 
"Master password: FAILED to verify against hash in database" );
 
  635      QgsDebugMsgLevel( QStringLiteral( 
"Master password: verified against hash in database" ), 2 );
 
 
  647  return !mMasterPass.isEmpty();
 
 
  654  return mMasterPass == pass;
 
 
  658    bool keepbackup, QString *backuppath )
 
  674  QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: backed up current database" ), 2 );
 
  677  QString prevpass = QString( mMasterPass );
 
  678  QString prevciv = QString( masterPasswordCiv() );
 
  684  if ( ok && !masterPasswordClearDb() )
 
  687    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not clear current password from database" );
 
  693    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: cleared current password from database" ), 2 );
 
  700  if ( ok && !masterPasswordStoreInDb() )
 
  703    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not store new password in database" );
 
  709    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: stored new password in database" ), 2 );
 
  716    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not verify new password in database" );
 
  722  if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
 
  725    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt configs in database" );
 
  731    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: re-encrypted configs in database" ), 2 );
 
  735  if ( ok && !verifyPasswordCanDecryptConfigs() )
 
  738    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
 
  743  if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
 
  746    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt settings in database" );
 
  751  if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
 
  754    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt identities in database" );
 
  762    const QString err = tr( 
"Master password reset FAILED: could not sync password helper: %1" ).arg( 
passwordHelperErrorMessage() );
 
  771    QString errdbbackup( dbbackup );
 
  772    errdbbackup.replace( QLatin1String( 
".db" ), QLatin1String( 
"_ERROR.db" ) );
 
  774    QgsDebugError( QStringLiteral( 
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
 
  777    mMasterPass = prevpass;
 
  778    QgsDebugError( QStringLiteral( 
"Master password reset FAILED: reinstated previous password and database" ) );
 
  782      *backuppath = errdbbackup;
 
  787  if ( !keepbackup && !QFile::remove( dbbackup ) )
 
  789    const char *err = QT_TR_NOOP( 
"Master password reset: could not remove old database backup" );
 
  797    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: backed up previous db at %1" ).arg( dbbackup ), 2 );
 
  799      *backuppath = dbbackup;
 
 
  818  const QString existingPassword = passwordHelperRead( readOk );
 
 
  832  mScheduledDbErase = scheduleErase;
 
  834  mScheduledDbEraseRequestEmitted = 
false;
 
  835  mScheduledDbEraseRequestCount = 0;
 
  839    if ( !mScheduledDbEraseTimer )
 
  841      mScheduledDbEraseTimer = std::make_unique<QTimer>( 
this );
 
  842      connect( mScheduledDbEraseTimer.get(), &QTimer::timeout, 
this, &QgsAuthManager::tryToStartDbErase );
 
  843      mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
 
  845    else if ( !mScheduledDbEraseTimer->isActive() )
 
  847      mScheduledDbEraseTimer->start();
 
  852    if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
 
  853      mScheduledDbEraseTimer->stop();
 
 
  862  qDeleteAll( mAuthMethods );
 
  863  mAuthMethods.clear();
 
  865  for ( 
const auto &authMethodKey : methods )
 
  870  return !mAuthMethods.isEmpty();
 
 
  882#ifndef __clang_analyzer__ 
  885  QTimer::singleShot( 3, &loop, &QEventLoop::quit );
 
  892    for ( 
int i = 0; i < len; i++ )
 
  894      switch ( QRandomGenerator::system()->generate() % 2 )
 
  897          id += 
static_cast<char>( 
'0' + QRandomGenerator::system()->generate() % 10 );
 
  900          id += 
static_cast<char>( 
'a' + QRandomGenerator::system()->generate() % 26 );
 
  904    if ( !configids.contains( 
id ) )
 
  909  QgsDebugMsgLevel( QStringLiteral( 
"Generated unique ID: %1" ).arg( 
id ), 2 );
 
 
  922    const char *err = QT_TR_NOOP( 
"Config ID is empty" );
 
  928  return !configids.contains( 
id );
 
 
  933  const thread_local QRegularExpression authCfgRegExp( AUTH_CFG_REGEX );
 
  934  return txt.indexOf( authCfgRegExp ) != -1;
 
 
  941  QMutexLocker locker( mMutex.get() );
 
  942  QStringList providerAuthMethodsKeys;
 
  943  if ( !dataprovider.isEmpty() )
 
  960      if ( providerAuthMethodsKeys.isEmpty() || providerAuthMethodsKeys.contains( config.method() ) )
 
  963        if ( baseConfigs.contains( config.id() ) )
 
  970          baseConfigs.insert( config.id(), config );
 
  976  if ( storages.empty() )
 
  979    QgsDebugError( QStringLiteral( 
"No credentials storages found" ) );
 
 
  998      if ( ! 
configIds.contains( config.id() ) )
 
 1000        mConfigAuthMethods.insert( config.id(), config.method() );
 
 1001        QgsDebugMsgLevel( QStringLiteral( 
"Stored auth config/methods:\n%1 %2" ).arg( config.id(), config.method() ), 2 );
 
 1007        QgsDebugMsgLevel( QStringLiteral( 
"A config with same id %1 was already added, skipping from %2" ).arg( config.id(), storage->
name() ), 2 );
 
 
 1020  if ( !mConfigAuthMethods.contains( authcfg ) )
 
 1022    QgsDebugError( QStringLiteral( 
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
 
 1026  QString authMethodKey = mConfigAuthMethods.value( authcfg );
 
 
 1038  return mConfigAuthMethods.value( authcfg, QString() );
 
 
 1053  if ( !mAuthMethods.contains( authMethodKey ) )
 
 1055    QgsDebugError( QStringLiteral( 
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
 
 1059  return mAuthMethods.value( authMethodKey );
 
 
 1066  if ( !mAuthMethods.contains( authMethodKey ) )
 
 1068    QgsDebugError( QStringLiteral( 
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
 
 
 1080  if ( dataprovider.isEmpty() )
 
 1082    return mAuthMethods;
 
 1086  QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
 
 1087  while ( i != mAuthMethods.constEnd() )
 
 1090         && ( i.value()->supportedDataProviders().contains( QStringLiteral( 
"all" ) )
 
 1091              || i.value()->supportedDataProviders().contains( dataprovider ) ) )
 
 1093      filteredmap.insert( i.key(), i.value() );
 
 
 1101QWidget *QgsAuthManager::authMethodEditWidget( 
const QString &authMethodKey, QWidget *parent )
 
 1107    return method->editWidget( parent );
 
 1132  QMutexLocker locker( mMutex.get() );
 
 1139    const char *err = QT_TR_NOOP( 
"Store config: FAILED because config is invalid" );
 
 1145  QString uid = config.
id();
 
 1146  bool passedinID = !uid.isEmpty();
 
 1147  if ( uid.isEmpty() )
 
 1155      const char *err = QT_TR_NOOP( 
"Store config: FAILED because pre-defined config ID %1 is not unique" );
 
 1163      const char *err = QT_TR_NOOP( 
"Store config: FAILED because pre-defined config ID %1 could not be removed" );
 
 1172  if ( configstring.isEmpty() )
 
 1174    const char *err = QT_TR_NOOP( 
"Store config: FAILED because config string is empty" );
 
 1182    if ( defaultStorage->isEncrypted() )
 
 1189    configCopy.
setId( uid );
 
 1190    if ( !defaultStorage->storeMethodConfig( configCopy, configstring ) )
 
 1204    config.
setId( uid );
 
 1208  QgsDebugMsgLevel( QStringLiteral( 
"Store config SUCCESS for authcfg: %1" ).arg( uid ), 2 );
 
 
 1216  QMutexLocker locker( mMutex.get() );
 
 1221  if ( !config.
isValid( 
true ) )
 
 1223    const char *err = QT_TR_NOOP( 
"Update config: FAILED because config is invalid" );
 
 1230  if ( configstring.isEmpty() )
 
 1232    const char *err = QT_TR_NOOP( 
"Update config: FAILED because config is empty" );
 
 1263  if ( storages.empty() )
 
 1274  QgsDebugMsgLevel( QStringLiteral( 
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ), 2 );
 
 
 1289  QMutexLocker locker( mMutex.get() );
 
 1301      if ( ! config.
isValid( 
true ) || ( full && payload.isEmpty() ) )
 
 1324        QgsDebugError( QStringLiteral( 
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
 
 1327      QgsDebugMsgLevel( QStringLiteral( 
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ? 
"full" : 
"base", authcfg ), 2 );
 
 1332  if ( storages.empty() )
 
 
 1348  QMutexLocker locker( mMutex.get() );
 
 1352  if ( authcfg.isEmpty() )
 
 1371        QgsDebugMsgLevel( QStringLiteral( 
"REMOVED config for authcfg: %1" ).arg( authcfg ), 2 );
 
 1378  if ( storages.empty() )
 
 
 1395  if ( filename.isEmpty() )
 
 1398  QDomDocument document( QStringLiteral( 
"qgis_authentication" ) );
 
 1399  QDomElement root = document.createElement( QStringLiteral( 
"qgis_authentication" ) );
 
 1400  document.appendChild( root );
 
 1403  if ( !password.isEmpty() )
 
 1408    root.setAttribute( QStringLiteral( 
"salt" ), salt );
 
 1409    root.setAttribute( QStringLiteral( 
"hash" ), hash );
 
 1410    root.setAttribute( QStringLiteral( 
"civ" ), civ );
 
 1413  QDomElement configurations = document.createElement( QStringLiteral( 
"configurations" ) );
 
 1414  for ( 
const QString &authcfg : authcfgs )
 
 1421      authMethodConfig.
writeXml( configurations, document );
 
 1424  if ( !password.isEmpty() )
 
 1426    QString configurationsString;
 
 1427    QTextStream ts( &configurationsString );
 
 1428#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
 1429    ts.setCodec( 
"UTF-8" );
 
 1431    configurations.save( ts, 2 );
 
 1432    root.appendChild( document.createTextNode( 
QgsAuthCrypto::encrypt( password, civ, configurationsString ) ) );
 
 1436    root.appendChild( configurations );
 
 1439  QFile file( filename );
 
 1440  if ( !file.open( QFile::WriteOnly | QIODevice::Truncate ) )
 
 1443  QTextStream ts( &file );
 
 1444#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
 1445  ts.setCodec( 
"UTF-8" );
 
 1447  document.save( ts, 2 );
 
 
 1456  QFile file( filename );
 
 1457  if ( !file.open( QFile::ReadOnly ) )
 
 1462  QDomDocument document( QStringLiteral( 
"qgis_authentication" ) );
 
 1463  if ( !document.setContent( &file ) )
 
 1470  QDomElement root = document.documentElement();
 
 1471  if ( root.tagName() != QLatin1String( 
"qgis_authentication" ) )
 
 1476  QDomElement configurations;
 
 1477  if ( root.hasAttribute( QStringLiteral( 
"salt" ) ) )
 
 1479    QString salt = root.attribute( QStringLiteral( 
"salt" ) );
 
 1480    QString hash = root.attribute( QStringLiteral( 
"hash" ) );
 
 1481    QString civ = root.attribute( QStringLiteral( 
"civ" ) );
 
 1486    configurations = document.firstChild().toElement();
 
 1490    configurations = root.firstChildElement( QStringLiteral( 
"configurations" ) );
 
 1493  QDomElement configuration = configurations.firstChildElement();
 
 1494  while ( !configuration.isNull() )
 
 1497    authMethodConfig.
readXml( configuration );
 
 1500    configuration = configuration.nextSiblingElement();
 
 
 1509  QMutexLocker locker( mMutex.get() );
 
 1515    if ( defaultStorage->clearMethodConfigs() )
 
 1519      QgsDebugMsgLevel( QStringLiteral( 
"REMOVED all configs from the default storage" ), 2 );
 
 1524      QgsDebugMsgLevel( QStringLiteral( 
"FAILED to remove all configs from the default storage" ), 2 );
 
 
 1540  QMutexLocker locker( mMutex.get() );
 
 1544    const char *err = QT_TR_NOOP( 
"The authentication storage is not filesystem-based" );
 
 1552    const char *err = QT_TR_NOOP( 
"No authentication database file found" );
 
 1562  if ( authConn.isValid() && authConn.isOpen() )
 
 1566  QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral( 
"yyyy-MM-dd-hhmmss" ) ) );
 
 1568  dbbackup.replace( QLatin1String( 
".db" ), QStringLiteral( 
"_%1.db" ).arg( datestamp ) );
 
 1572    const char *err = QT_TR_NOOP( 
"Could not back up authentication database" );
 
 1579    *backuppath = dbbackup;
 
 1581  QgsDebugMsgLevel( QStringLiteral( 
"Backed up auth database at %1" ).arg( dbbackup ), 2 );
 
 
 1589  QMutexLocker locker( mMutex.get() );
 
 1600  if ( backuppath && !dbbackup.isEmpty() )
 
 1601    *backuppath = dbbackup;
 
 1605    if ( defaultStorage->erase() )
 
 1607      mMasterPass = QString();
 
 
 1635    const QString &dataprovider )
 
 1647      QgsDebugError( QStringLiteral( 
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 
 1662    const QString &dataprovider )
 
 1674      QgsDebugMsgLevel( QStringLiteral( 
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ), 3 );
 
 
 1690    const QString &dataprovider )
 
 1702      QgsDebugError( QStringLiteral( 
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 
 1729      QgsDebugError( QStringLiteral( 
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 1738    QgsDebugMsgLevel( QStringLiteral( 
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ), 2 );
 
 
 1749  QMutexLocker locker( mMutex.get() );
 
 1750  if ( key.isEmpty() )
 
 1753  QString storeval( value.toString() );
 
 1776    if ( !defaultStorage->storeAuthSetting( key, storeval ) )
 
 
 1794  QMutexLocker locker( mMutex.get() );
 
 1795  if ( key.isEmpty() )
 
 1801  QVariant value = defaultValue;
 
 1809    if ( !storeval.isEmpty() )
 
 1820  if ( storages.empty() )
 
 
 1832  QMutexLocker locker( mMutex.get() );
 
 1833  if ( key.isEmpty() )
 
 1847  if ( storages.empty() )
 
 
 1859  QMutexLocker locker( mMutex.get() );
 
 1860  if ( key.isEmpty() )
 
 1887  if ( storages.empty() )
 
 
 1902  QMutexLocker locker( mMutex.get() );
 
 1908  mCustomConfigByHostCache.clear();
 
 1909  mHasCheckedIfCustomConfigByHostExists = 
false;
 
 1912    QgsDebugError( QStringLiteral( 
"Init of SSL caches FAILED" ) );
 
 
 1920  QMutexLocker locker( mMutex.get() );
 
 1921  if ( cert.isNull() )
 
 1923    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 1928    QgsDebugError( QStringLiteral( 
"Passed private key is null" ) );
 
 1940    QgsDebugError( QStringLiteral( 
"Store certificate identity: FAILED to remove pre-existing certificate identity %1" ).arg( 
id ) );
 
 1948    if ( !defaultStorage->storeCertIdentity( cert, keypem ) )
 
 
 1966  QMutexLocker locker( mMutex.get() );
 
 1968  QSslCertificate cert;
 
 1979    if ( !cert.isNull() )
 
 1985  if ( storages.empty() )
 
 
 1997  QMutexLocker locker( mMutex.get() );
 
 1998  QPair<QSslCertificate, QSslKey> bundle;
 
 2013      if ( encryptedBundle.first.isNull() )
 
 2015        QgsDebugError( QStringLiteral( 
"Certificate identity bundle is null for id: %1" ).arg( 
id ) );
 
 2018      QSslKey key( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), encryptedBundle.second ).toLatin1(),
 
 2019                   QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
 
 2022        QgsDebugError( QStringLiteral( 
"Certificate identity bundle: FAILED to create private key" ) );
 
 2025      bundle = qMakePair( encryptedBundle.first, key );
 
 2030  if ( storages.empty() )
 
 
 2043  QMutexLocker locker( mMutex.get() );
 
 2047    return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
 
 2049  return QStringList();
 
 
 2056  QMutexLocker locker( mMutex.get() );
 
 2057  QList<QSslCertificate> certs;
 
 2064    const QList<QSslCertificate> storageCerts = storage->
certIdentities();
 
 2066    for ( 
const QSslCertificate &cert : std::as_const( storageCerts ) )
 
 2068      if ( !certs.contains( cert ) )
 
 2070        certs.append( cert );
 
 2079  if ( storages.empty() )
 
 
 2091  QMutexLocker locker( mMutex.get() );
 
 2105    for ( 
const QString &
id : std::as_const( storageIds ) )
 
 2107      if ( !ids.contains( 
id ) )
 
 
 2125  QMutexLocker locker( mMutex.get() );
 
 2140  if ( storages.empty() )
 
 
 2152  QMutexLocker locker( mMutex.get() );
 
 2155    QgsDebugError( QStringLiteral( 
"Passed bundle ID is empty" ) );
 
 2175  if ( storages.empty() )
 
 
 2188  QMutexLocker locker( mMutex.get() );
 
 2200    QgsDebugError( QStringLiteral( 
"Store SSL certificate custom config: FAILED to remove pre-existing config %1" ).arg( 
id ) );
 
 2206    if ( !defaultStorage->storeSslCertCustomConfig( config ) )
 
 2219  mCustomConfigByHostCache.clear();
 
 
 2228  QMutexLocker locker( mMutex.get() );
 
 2231  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2233    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2257  if ( storages.empty() )
 
 
 2271  if ( hostport.isEmpty() )
 
 2276  QMutexLocker locker( mMutex.get() );
 
 2278  if ( mCustomConfigByHostCache.contains( hostport ) )
 
 2279    return mCustomConfigByHostCache.value( hostport );
 
 2289      mCustomConfigByHostCache.insert( hostport, config );
 
 2294  if ( storages.empty() )
 
 
 2306  QMutexLocker locker( mMutex.get() );
 
 2307  QList<QgsAuthConfigSslServer> configs;
 
 2318    for ( 
const auto &config : std::as_const( storageConfigs ) )
 
 2321      const QString hostPort = config.sslHostPort();
 
 2322      const QString shaHostPort( QStringLiteral( 
"%1:%2" ).arg( 
id, hostPort ) );
 
 2323      if ( ! ids.contains( shaHostPort ) )
 
 2325        ids.append( shaHostPort );
 
 2326        configs.append( config );
 
 2335  if ( storages.empty() )
 
 
 2347  QMutexLocker locker( mMutex.get() );
 
 2348  if ( 
id.isEmpty() || hostPort.isEmpty() )
 
 2350    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2365  if ( storages.empty() )
 
 
 2377  QMutexLocker locker( mMutex.get() );
 
 2378  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2380    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2384  mCustomConfigByHostCache.clear();
 
 2398      const QString shaHostPort( QStringLiteral( 
"%1:%2" ).arg( 
id, hostport ) );
 
 2399      if ( mIgnoredSslErrorsCache.contains( shaHostPort ) )
 
 2401        mIgnoredSslErrorsCache.remove( shaHostPort );
 
 2407  if ( storages.empty() )
 
 
 2420  QMutexLocker locker( mMutex.get() );
 
 2421  if ( !mIgnoredSslErrorsCache.isEmpty() )
 
 2423    QgsDebugMsgLevel( QStringLiteral( 
"Ignored SSL errors cache items:" ), 1 );
 
 2424    QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
 
 2425    while ( i != mIgnoredSslErrorsCache.constEnd() )
 
 2428      for ( 
auto err : i.value() )
 
 2432      QgsDebugMsgLevel( QStringLiteral( 
"%1 = %2" ).arg( i.key(), errs.join( 
", " ) ), 1 );
 
 
 2446  QMutexLocker locker( mMutex.get() );
 
 2453  QString shahostport( QStringLiteral( 
"%1:%2" )
 
 2456  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2458    mIgnoredSslErrorsCache.remove( shahostport );
 
 2461  if ( !errenums.isEmpty() )
 
 2463    mIgnoredSslErrorsCache.insert( shahostport, QSet<QSslError::SslError>( errenums.begin(), errenums.end() ) );
 
 2464    QgsDebugMsgLevel( QStringLiteral( 
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 2469  QgsDebugMsgLevel( QStringLiteral( 
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 
 2477  QMutexLocker locker( mMutex.get() );
 
 2478  const thread_local QRegularExpression rx( QRegularExpression::anchoredPattern( 
"\\S+:\\S+:\\d+" ) );
 
 2479  if ( !rx.match( shahostport ).hasMatch() )
 
 2481    QgsDebugError( 
"Passed shahostport does not match \\S+:\\S+:\\d+, " 
 2482                   "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
 
 2486  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2488    mIgnoredSslErrorsCache.remove( shahostport );
 
 2491  if ( errors.isEmpty() )
 
 2493    QgsDebugError( QStringLiteral( 
"Passed errors list empty" ) );
 
 2497  QSet<QSslError::SslError> errs;
 
 2498  for ( 
const auto &error : errors )
 
 2500    if ( error.error() == QSslError::NoError )
 
 2503    errs.insert( error.error() );
 
 2506  if ( errs.isEmpty() )
 
 2508    QgsDebugError( QStringLiteral( 
"Passed errors list does not contain errors" ) );
 
 2512  mIgnoredSslErrorsCache.insert( shahostport, errs );
 
 2514  QgsDebugMsgLevel( QStringLiteral( 
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 
 2523  QMutexLocker locker( mMutex.get() );
 
 2524  QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
 
 2525  QHash<QString, QSet<QSslError::SslError> > nextcache;
 
 2535    for ( 
const auto &config : std::as_const( customConfigs ) )
 
 2538      if ( ! ids.contains( shaHostPort ) )
 
 2540        ids.append( shaHostPort );
 
 2541        if ( !config.sslIgnoredErrorEnums().isEmpty() )
 
 2543          nextcache.insert( shaHostPort, QSet<QSslError::SslError>( config.sslIgnoredErrorEnums().cbegin(), config.sslIgnoredErrorEnums().cend() ) );
 
 2545        if ( prevcache.contains( shaHostPort ) )
 
 2547          prevcache.remove( shaHostPort );
 
 2557  if ( !prevcache.isEmpty() )
 
 2560    QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
 
 2561    while ( i != prevcache.constEnd() )
 
 2563      nextcache.insert( i.key(), i.value() );
 
 2568  if ( nextcache != mIgnoredSslErrorsCache )
 
 2570    mIgnoredSslErrorsCache.clear();
 
 2571    mIgnoredSslErrorsCache = nextcache;
 
 2572    QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of ignored SSL errors cache SUCCEEDED" ), 2 );
 
 2577  QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of ignored SSL errors cache SAME AS BEFORE" ), 2 );
 
 
 2586  QMutexLocker locker( mMutex.get() );
 
 2587  if ( certs.isEmpty() )
 
 2589    QgsDebugError( QStringLiteral( 
"Passed certificate list has no certs" ) );
 
 2593  for ( 
const auto &cert : certs )
 
 
 2605  QMutexLocker locker( mMutex.get() );
 
 2608  if ( cert.isNull() )
 
 2610    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2616    QgsDebugError( QStringLiteral( 
"Store certificate authority: FAILED to remove pre-existing certificate authority" ) );
 
 2622    return defaultStorage->storeCertAuthority( cert );
 
 
 2637  QMutexLocker locker( mMutex.get() );
 
 2638  QSslCertificate emptycert;
 
 2639  QSslCertificate cert;
 
 2649    if ( !cert.isNull() )
 
 2655  if ( storages.empty() )
 
 
 2668  QMutexLocker locker( mMutex.get() );
 
 2669  if ( cert.isNull() )
 
 2671    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2686  if ( storages.empty() )
 
 
 2698  QMutexLocker locker( mMutex.get() );
 
 2699  if ( cert.isNull() )
 
 2701    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2728  if ( storages.empty() )
 
 
 2738  return QSslConfiguration::systemCaCertificates();
 
 
 2745  QMutexLocker locker( mMutex.get() );
 
 2746  QList<QSslCertificate> certs;
 
 2747  QList<QSslCertificate> filecerts;
 
 2756  QString cafile( cafileval.toString() );
 
 2757  if ( !cafile.isEmpty() && QFile::exists( cafile ) )
 
 2762  for ( 
const auto &cert : std::as_const( filecerts ) )
 
 2764    if ( !allowinvalid.toBool() && ( cert.isBlacklisted()
 
 2766                                     || cert.expiryDate() <= QDateTime::currentDateTime()
 
 2767                                     || cert.effectiveDate() > QDateTime::currentDateTime() ) )
 
 
 2784  QMutexLocker locker( mMutex.get() );
 
 2789  QList<QSslCertificate> certs;
 
 2793    const QList<QSslCertificate> storageCerts = storage->
caCerts();
 
 2795    for ( 
const QSslCertificate &cert : std::as_const( storageCerts ) )
 
 2797      if ( !certs.contains( cert ) )
 
 2799        certs.append( cert );
 
 2808  if ( storages.empty() )
 
 
 2820  QMutexLocker locker( mMutex.get() );
 
 
 2828  QMutexLocker locker( mMutex.get() );
 
 2829  mCaCertsCache.clear();
 
 2835  bool res = !mCaCertsCache.isEmpty(); 
 
 2837    QgsDebugError( QStringLiteral( 
"Rebuild of CA certs cache FAILED" ) );
 
 
 2845  QMutexLocker locker( mMutex.get() );
 
 2846  if ( cert.isNull() )
 
 2848    QgsDebugError( QStringLiteral( 
"Passed certificate is null." ) );
 
 2865    return defaultStorage->storeCertTrustPolicy( cert, policy );
 
 
 2878  QMutexLocker locker( mMutex.get() );
 
 2879  if ( cert.isNull() )
 
 2881    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2897  if ( storages.empty() )
 
 
 2909  QMutexLocker locker( mMutex.get() );
 
 2910  if ( certs.empty() )
 
 2912    QgsDebugError( QStringLiteral( 
"Passed certificate list has no certs" ) );
 
 2916  for ( 
const auto &cert : certs )
 
 
 2928  QMutexLocker locker( mMutex.get() );
 
 2929  if ( cert.isNull() )
 
 2931    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2957  if ( storages.empty() )
 
 
 2969  QMutexLocker locker( mMutex.get() );
 
 2970  if ( cert.isNull() )
 
 2980  if ( trustedids.contains( 
id ) )
 
 2984  else if ( untrustedids.contains( 
id ) )
 
 
 3000  return storeAuthSetting( QStringLiteral( 
"certdefaulttrust" ), 
static_cast< int >( policy ) );
 
 
 3007  QMutexLocker locker( mMutex.get() );
 
 3008  QVariant policy( 
authSetting( QStringLiteral( 
"certdefaulttrust" ) ) );
 
 
 3020  QMutexLocker locker( mMutex.get() );
 
 3021  mCertTrustCache.clear();
 
 3032    for ( 
auto it = trustedCerts.cbegin(); it != trustedCerts.cend(); ++it )
 
 3034      const QString 
id { it.key( )};
 
 3035      if ( ! ids.contains( 
id ) )
 
 3056  if ( ! storages.empty() )
 
 3058    QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of cert trust policy cache SUCCEEDED" ), 2 );
 
 
 3072  QMutexLocker locker( mMutex.get() );
 
 3076  const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
 
 3078  QList<QSslCertificate> trustedcerts;
 
 3079  for ( 
int i = 0; i < certpairs.size(); ++i )
 
 3081    QSslCertificate cert( certpairs.at( i ).second );
 
 3083    if ( trustedids.contains( certid ) )
 
 3086      trustedcerts.append( cert );
 
 3092      trustedcerts.append( cert );
 
 3097  QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
 
 3098  sslconfig.setCaCertificates( trustedcerts );
 
 3099  QSslConfiguration::setDefaultConfiguration( sslconfig );
 
 3101  return trustedcerts;
 
 
 3108  QMutexLocker locker( mMutex.get() );
 
 3109  if ( trustedCAs.isEmpty() )
 
 3111    if ( mTrustedCaCertsCache.isEmpty() )
 
 3118  const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
 
 3120  QList<QSslCertificate> untrustedCAs;
 
 3121  for ( 
int i = 0; i < certpairs.size(); ++i )
 
 3123    QSslCertificate cert( certpairs.at( i ).second );
 
 3124    if ( !trustedCAs.contains( cert ) )
 
 3126      untrustedCAs.append( cert );
 
 3129  return untrustedCAs;
 
 
 3136  QMutexLocker locker( mMutex.get() );
 
 3138  QgsDebugMsgLevel( QStringLiteral( 
"Rebuilt trusted cert authorities cache" ), 2 );
 
 
 3147  QMutexLocker locker( mMutex.get() );
 
 
 3155  QMutexLocker locker( mMutex.get() );
 
 3158    return passwordHelperWrite( mMasterPass );
 
 
 3168  bool readOk = 
false;
 
 3169  const QString currentPass = passwordHelperRead( readOk );
 
 3173  if ( !currentPass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
 
 
 3182#if defined(Q_OS_MAC) 
 3183  return titleCase ? QObject::tr( 
"Keychain" ) : QObject::tr( 
"keychain" );
 
 3184#elif defined(Q_OS_WIN) 
 3185  return titleCase ? QObject::tr( 
"Password Manager" ) : QObject::tr( 
"password manager" );
 
 3186#elif defined(Q_OS_LINUX) 
 3188  const QString desktopSession = qgetenv( 
"DESKTOP_SESSION" );
 
 3189  const QString currentDesktop = qgetenv( 
"XDG_CURRENT_DESKTOP" );
 
 3190  const QString gdmSession = qgetenv( 
"GDMSESSION" );
 
 3192  if ( desktopSession.contains( QLatin1String( 
"kde" ), Qt::CaseInsensitive ) || currentDesktop.contains( QLatin1String( 
"kde" ), Qt::CaseInsensitive ) || gdmSession.contains( QLatin1String( 
"kde" ), Qt::CaseInsensitive ) )
 
 3194    return titleCase ? QObject::tr( 
"Wallet" ) : QObject::tr( 
"wallet" );
 
 3197  return titleCase ? QObject::tr( 
"Wallet/Key Ring" ) : QObject::tr( 
"wallet/key ring" );
 
 3199  return titleCase ? QObject::tr( 
"Password Manager" ) : QObject::tr( 
"password manager" );
 
 
 3216  for ( 
const auto &authcfg : ids )
 
 
 3236void QgsAuthManager::writeToConsole( 
const QString &message,
 
 3252      msg += QLatin1String( 
"WARNING: " );
 
 3255      msg += QLatin1String( 
"ERROR: " );
 
 3262  QTextStream out( stdout, QIODevice::WriteOnly );
 
 3263  out << msg << Qt::endl;
 
 3266void QgsAuthManager::tryToStartDbErase()
 
 3270  ++mScheduledDbEraseRequestCount;
 
 3272  int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
 
 3273  if ( mScheduledDbEraseRequestCount >= trycutoff )
 
 3276    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emitting/scheduling canceled" ), 2 );
 
 3281    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest attempt (%1 of %2)" )
 
 3282                      .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ), 2 );
 
 3288    mScheduledDbEraseRequestEmitted = 
true;
 
 3293    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emitted" ), 2 );
 
 3296  QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emit skipped" ), 2 );
 
 3302  QMutexLocker locker( mMutex.get() );
 
 3304  QMapIterator<QThread *, QMetaObject::Connection> iterator( mConnectedThreads );
 
 3305  while ( iterator.hasNext() )
 
 3308    QThread::disconnect( iterator.value() );
 
 3319    qDeleteAll( mAuthMethods );
 
 3324    if ( authConn.isValid() && authConn.isOpen() )
 
 3328  QSqlDatabase::removeDatabase( QStringLiteral( 
"authentication.configs" ) );
 
 
 3333  QMutexLocker locker( mMutex.get() );
 
 3334  if ( ! mAuthConfigurationStorageRegistry )
 
 3336    mAuthConfigurationStorageRegistry = std::make_unique<QgsAuthConfigurationStorageRegistry>();
 
 3338  return mAuthConfigurationStorageRegistry.get();
 
 
 3342QString QgsAuthManager::passwordHelperName()
 const 
 3344  return tr( 
"Password Helper" );
 
 3348void QgsAuthManager::passwordHelperLog( 
const QString &msg )
 const 
 3364  QKeychain::DeletePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3367  job.setAutoDelete( 
false );
 
 3368  job.setKey( authPasswordHelperKeyName() );
 
 3370  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3375    mPasswordHelperErrorCode = job.error();
 
 3376    mPasswordHelperErrorMessage = tr( 
"Delete password failed: %1." ).arg( job.errorString() );
 
 3387  passwordHelperProcessError();
 
 
 3391QString QgsAuthManager::passwordHelperRead( 
bool &ok )
 
 3399  QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3402  job.setAutoDelete( 
false );
 
 3403  job.setKey( authPasswordHelperKeyName() );
 
 3405  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3410    mPasswordHelperErrorCode = job.error();
 
 3411    mPasswordHelperErrorMessage = tr( 
"Retrieving password from the %1 failed: %2." ).arg( 
passwordHelperDisplayName(), job.errorString() );
 
 3417    password = job.textData();
 
 3419    if ( password.isEmpty() )
 
 3421      mPasswordHelperErrorCode = QKeychain::EntryNotFound;
 
 3433  passwordHelperProcessError();
 
 3437bool QgsAuthManager::passwordHelperWrite( 
const QString &password )
 
 3441  Q_ASSERT( !password.isEmpty() );
 
 3444  QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3447  job.setAutoDelete( 
false );
 
 3448  job.setKey( authPasswordHelperKeyName() );
 
 3449  job.setTextData( password );
 
 3451  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3456    mPasswordHelperErrorCode = job.error();
 
 3457    mPasswordHelperErrorMessage = tr( 
"Storing password in the %1 failed: %2." ).arg( 
passwordHelperDisplayName(), job.errorString() );
 
 3464    passwordHelperClearErrors();
 
 3469  passwordHelperProcessError();
 
 3484  emit 
messageLog( enabled ? tr( 
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
 
 3486                   tr( 
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
 
 
 3503void QgsAuthManager::passwordHelperClearErrors()
 
 3505  mPasswordHelperErrorCode = QKeychain::NoError;
 
 3506  mPasswordHelperErrorMessage.clear();
 
 3509void QgsAuthManager::passwordHelperProcessError()
 
 3513  if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
 
 3514       mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
 
 3515       mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
 
 3516       mPasswordHelperErrorCode == QKeychain::NotImplemented )
 
 3522    mPasswordHelperErrorMessage = tr( 
"There was an error and integration with your %1 has been disabled. " 
 3523                                      "You can re-enable it at any time through the \"Utilities\" menu " 
 3524                                      "in the Authentication pane of the options dialog. %2" )
 
 3527  if ( mPasswordHelperErrorCode != QKeychain::NoError )
 
 3533  passwordHelperClearErrors();
 
 3537bool QgsAuthManager::masterPasswordInput()
 
 3545  bool storedPasswordIsValid = 
false;
 
 3551    bool readOk = 
false;
 
 3552    pass = passwordHelperRead( readOk );
 
 3553    if ( readOk && ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
 
 3559        storedPasswordIsValid = 
true;
 
 3574  if ( ok && !pass.isEmpty() && mMasterPass != pass )
 
 3579      if ( !passwordHelperWrite( pass ) )
 
 3589bool QgsAuthManager::masterPasswordRowsInDb( 
int *rows )
 const 
 3598  QMutexLocker locker( mMutex.get() );
 
 3616  if ( storages.empty() )
 
 3633  if ( !masterPasswordRowsInDb( &rows ) )
 
 3635    const char *err = QT_TR_NOOP( 
"Master password: FAILED to access database" );
 
 3641  return ( rows == 1 );
 
 
 3644bool QgsAuthManager::masterPasswordCheckAgainstDb( 
const QString &compare )
 const 
 3656      const QList<QgsAuthConfigurationStorage::MasterPasswordConfig> passwords { defaultStorage->masterPasswords( ) };
 
 3657      if ( passwords.size() == 0 )
 
 3680bool QgsAuthManager::masterPasswordStoreInDb()
 const 
 3687  QString salt, hash, civ;
 
 3695      return defaultStorage->storeMasterPassword( { salt, civ, hash } );
 
 3711bool QgsAuthManager::masterPasswordClearDb()
 
 3723      return defaultStorage->clearMasterPasswords();
 
 3740const QString QgsAuthManager::masterPasswordCiv()
 const 
 3751      const QList<QgsAuthConfigurationStorage::MasterPasswordConfig> passwords { defaultStorage->masterPasswords( ) };
 
 3752      if ( passwords.size() == 0 )
 
 3757      return passwords.first().civ;
 
 3777  QStringList configKeys = QStringList();
 
 3791      for ( 
auto it = configs.cbegin(); it != configs.cend(); ++it )
 
 3793        if ( !configKeys.contains( it.key() ) )
 
 3795          configKeys.append( it.key() );
 
 
 3813bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
 const 
 3836      for ( 
auto it = configs.cbegin(); it != configs.cend(); ++it )
 
 3838        QString configstring( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), it.value().config( QStringLiteral( 
"encrypted_payload" ) ) ) );
 
 3839        if ( configstring.isEmpty() )
 
 3841          QgsDebugError( QStringLiteral( 
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1) from storage %2" )
 
 3842                         .arg( it.key(), storage->
name() ) );
 
 3856  if ( storages.empty() )
 
 3865bool QgsAuthManager::reencryptAllAuthenticationConfigs( 
const QString &prevpass, 
const QString &prevciv )
 
 3874  for ( 
const auto &configid : ids )
 
 3876    res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
 
 3881bool QgsAuthManager::reencryptAuthenticationConfig( 
const QString &authcfg, 
const QString &prevpass, 
const QString &prevciv )
 
 3906        if ( payload.isEmpty() || ! config.
isValid( 
true ) )
 
 3908          QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find config (id: %1)" ).arg( authcfg ) );
 
 3913        if ( configstring.isEmpty() )
 
 3915          QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not decrypt config (id: %1)" ).arg( authcfg ) );
 
 3937  if ( storages.empty() )
 
 3949bool QgsAuthManager::reencryptAllAuthenticationSettings( 
const QString &prevpass, 
const QString &prevciv )
 
 3954  Q_UNUSED( prevpass )
 
 3967  QStringList encryptedsettings;
 
 3968  encryptedsettings << 
"";
 
 3970  for ( 
const auto & sett, std::as_const( encryptedsettings ) )
 
 3977    QSqlQuery query( authDbConnection() );
 
 3979    query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 3980                                   "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 3982    query.bindValue( 
":setting", sett );
 
 3984    if ( !authDbQuery( &query ) )
 
 3987    if ( !query.isActive() || !query.isSelect() )
 
 3989      QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
 
 3993    if ( query.first() )
 
 3999      query.prepare( QStringLiteral( 
"UPDATE %1 " 
 4000                                     "SET value = :value " 
 4001                                     "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 4003      query.bindValue( 
":setting", sett );
 
 4006      if ( !authDbStartTransaction() )
 
 4009      if ( !authDbQuery( &query ) )
 
 4012      if ( !authDbCommit() )
 
 4015      QgsDebugMsgLevel( QStringLiteral( 
"Reencrypt SUCCESS for setting: %2" ).arg( sett ), 2 );
 
 4020      QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
 
 4026      QgsDebugError( QStringLiteral( 
"Select contains more than one for setting: %1" ).arg( sett ) );
 
 4037bool QgsAuthManager::reencryptAllAuthenticationIdentities( 
const QString &prevpass, 
const QString &prevciv )
 
 4046  for ( 
const auto &identid : ids )
 
 4048    res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
 
 4053bool QgsAuthManager::reencryptAuthenticationIdentity(
 
 4054  const QString &identid,
 
 4055  const QString &prevpass,
 
 4056  const QString &prevciv )
 
 4084        if ( keystring.isEmpty() )
 
 4086          QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not decrypt identity id: %1" ).arg( identid ) );
 
 4102  if ( storages.empty() )
 
 4118  for ( 
const auto &cert : certs )
 
 4121                          QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>( source, cert ) );
 
 4125QString QgsAuthManager::authPasswordHelperKeyName()
 const 
 4129  QString dbProfilePath;
 
 4135    const QFileInfo info( mAuthDatabaseConnectionUri );
 
 4136    dbProfilePath = info.dir().dirName();
 
 4140    dbProfilePath = QCryptographicHash::hash( ( mAuthDatabaseConnectionUri.toUtf8() ), QCryptographicHash::Md5 ).toHex();
 
 4144  return AUTH_PASSWORD_HELPER_KEY_NAME_BASE + ( dbProfilePath.compare( QLatin1String( 
"default" ), Qt::CaseInsensitive ) == 0 ? QString() : dbProfilePath );
 
 4153    if ( qobject_cast<QgsAuthConfigurationStorageDb *>( storage ) )
 
 
MessageLevel
Level for messages This will be used both for message log and message bar in application.
 
@ Warning
Warning message.
 
@ Critical
Critical/error message.
 
@ Info
Information message.
 
AuthConfigurationStorageCapability
Authentication configuration storage capabilities.
 
@ CreateSetting
Can create a new authentication setting.
 
@ CreateConfiguration
Can create a new authentication configuration.
 
@ ClearStorage
Can clear all configurations from storage.
 
@ DeleteCertificateAuthority
Can delete a certificate authority.
 
@ DeleteSslCertificateCustomConfig
Can delete a SSL certificate custom config.
 
@ DeleteSetting
Can delete the authentication setting.
 
@ ReadSslCertificateCustomConfig
Can read a SSL certificate custom config.
 
@ DeleteMasterPassword
Can delete the master password.
 
@ CreateSslCertificateCustomConfig
Can create a new SSL certificate custom config.
 
@ ReadCertificateTrustPolicy
Can read a certificate trust policy.
 
@ ReadConfiguration
Can read an authentication configuration.
 
@ UpdateConfiguration
Can update an authentication configuration.
 
@ ReadCertificateAuthority
Can read a certificate authority.
 
@ CreateCertificateAuthority
Can create a new certificate authority.
 
@ DeleteConfiguration
Can deleet an authentication configuration.
 
@ ReadSetting
Can read the authentication settings.
 
@ CreateCertificateIdentity
Can create a new certificate identity.
 
@ ReadCertificateIdentity
Can read a certificate identity.
 
@ CreateCertificateTrustPolicy
Can create a new certificate trust policy.
 
@ ReadMasterPassword
Can read the master password.
 
@ CreateMasterPassword
Can create a new master password.
 
@ DeleteCertificateTrustPolicy
Can delete a certificate trust policy.
 
static QString sslErrorEnumString(QSslError::SslError errenum)
Gets short strings describing an SSL error.
 
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
 
CertTrustPolicy
Type of certificate trust policy.
 
static QMap< QString, QSslCertificate > mapDigestToCerts(const QList< QSslCertificate > &certs)
Map certificate sha1 to certificate as simple cache.
 
static QByteArray certsToPemText(const QList< QSslCertificate > &certs)
certsToPemText dump a list of QSslCertificates to PEM text
 
static bool certIsViable(const QSslCertificate &cert)
certIsViable checks for viability errors of cert and whether it is NULL
 
static QList< QSslCertificate > certsFromFile(const QString &certspath)
Returns a list of concatenated certs from a PEM or DER formatted file.
 
static bool certificateIsAuthorityOrIssuer(const QSslCertificate &cert)
Gets whether a certificate is an Authority or can at least sign other certificates.
 
CaCertSource
Type of CA certificate source.
 
Configuration container for SSL server connection exceptions or overrides.
 
bool isNull() const
Whether configuration is null (missing components)
 
const QList< QSslError::SslError > sslIgnoredErrorEnums() const
SSL server errors (as enum list) to ignore in connections.
 
const QSslCertificate sslCertificate() const
Server certificate object.
 
const QString sslHostPort() const
Server host:port string.
 
QSqlDatabase based implementation of QgsAuthConfigurationStorage.
 
bool removeCertTrustPolicy(const QSslCertificate &cert) override
Remove certificate trust policy.
 
const QgsAuthConfigSslServer loadSslCertCustomConfigByHost(const QString &hostport) const override
Loads an SSL certificate custom config by hostport (host:port)
 
QString loadAuthSetting(const QString &key) const override
Load an authentication setting from the storage.
 
bool removeAuthSetting(const QString &key) override
Remove an authentication setting from the storage.
 
const QMap< QString, QgsAuthCertUtils::CertTrustPolicy > caCertsPolicy() const override
Returns the map of CA certificates hashes in the storages and their trust policy.
 
QgsAuthCertUtils::CertTrustPolicy loadCertTrustPolicy(const QSslCertificate &cert) const override
Load certificate trust policy.
 
bool sslCertCustomConfigExists(const QString &id, const QString &hostport) override
Check if SSL certificate custom config exists.
 
bool removeCertIdentity(const QSslCertificate &cert) override
Remove a certificate identity from the storage.
 
const QPair< QSslCertificate, QString > loadCertIdentityBundle(const QString &id) const override
Returns a certificate identity bundle by id (sha hash).
 
const QList< QgsAuthConfigurationStorage::MasterPasswordConfig > masterPasswords() const override
Returns the list of (encrypted) master passwords stored in the database.
 
bool methodConfigExists(const QString &id) const override
Check if an authentication configuration exists in the storage.
 
QStringList certIdentityIds() const override
certIdentityIds get list of certificate identity ids from database
 
bool initialize() override
Initializes the storage.
 
bool storeMethodConfig(const QgsAuthMethodConfig &mconfig, const QString &payload) override
Store an authentication config in the database.
 
bool removeCertAuthority(const QSslCertificate &cert) override
Remove a certificate authority.
 
const QSslCertificate loadCertIdentity(const QString &id) const override
certIdentity get a certificate identity by id (sha hash)
 
const QList< QgsAuthConfigSslServer > sslCertCustomConfigs() const override
sslCertCustomConfigs get SSL certificate custom configs
 
QgsAuthMethodConfigsMap authMethodConfigs(const QStringList &allowedMethods=QStringList()) const override
Returns a mapping of authentication configurations available from this storage.
 
const QList< QSslCertificate > caCerts() const override
Returns the list of CA certificates in the storage.
 
bool certTrustPolicyExists(const QSslCertificate &cert) const override
Check if certificate trust policy exists.
 
const QSslCertificate loadCertAuthority(const QString &id) const override
certAuthority get a certificate authority by id (sha hash)
 
bool removeMethodConfig(const QString &id) override
Removes the authentication configuration with the specified id.
 
QgsAuthMethodConfigsMap authMethodConfigsWithPayload() const override
Returns a mapping of authentication configurations available from this storage.
 
bool certIdentityExists(const QString &id) const override
Check if the certificate identity exists.
 
bool certAuthorityExists(const QSslCertificate &cert) const override
Check if a certificate authority exists.
 
QgsAuthMethodConfig loadMethodConfig(const QString &id, QString &payload, bool full=false) const override
Load an authentication configuration from the database.
 
bool storeCertIdentity(const QSslCertificate &cert, const QString &keyPem) override
Store a certificate identity in the storage.
 
bool removeSslCertCustomConfig(const QString &id, const QString &hostport) override
Remove an SSL certificate custom config.
 
const QList< QSslCertificate > certIdentities() const override
certIdentities get certificate identities
 
QString name() const override
Returns a human readable localized short name of the storage implementation (e.g "SQLite").
 
bool authSettingExists(const QString &key) const override
Check if an authentication setting exists in the storage.
 
const QgsAuthConfigSslServer loadSslCertCustomConfig(const QString &id, const QString &hostport) const override
Loads an SSL certificate custom config by id (sha hash) and hostport (host:port)
 
Registry for authentication configuration storages.
 
QgsAuthConfigurationStorage * firstReadyStorageWithCapability(Qgis::AuthConfigurationStorageCapability capability) const
Returns the first ready (and enabled) authentication configuration storage which has the required cap...
 
QList< QgsAuthConfigurationStorage * > storages() const
Returns the list of all registered authentication configuration storages.
 
QList< QgsAuthConfigurationStorage * > readyStoragesWithCapability(Qgis::AuthConfigurationStorageCapability capability) const
Returns the list of all ready (and enabled) authentication configuration storage with the required ca...
 
QList< QgsAuthConfigurationStorage * > readyStorages() const
Returns the list of all ready (and enabled) authentication configuration storage.
 
bool addStorage(QgsAuthConfigurationStorage *storage)
Add an authentication configuration storage to the registry.
 
Abstract class that defines the interface for all authentication configuration storage implementation...
 
virtual void setReadOnly(bool readOnly)
Utility method to unset all editing capabilities.
 
void methodConfigChanged()
Emitted when the storage method config table was changed.
 
Qgis::AuthConfigurationStorageCapabilities capabilities() const
Returns the capabilities of the storage.
 
bool isEnabled() const
Returns true if the storage is enabled.
 
bool isEncrypted() const
Returns true if the storage is encrypted.
 
void messageLog(const QString &message, const QString &tag=QStringLiteral("Authentication"), Qgis::MessageLevel level=Qgis::MessageLevel::Info)
Custom logging signal to relay to console output and QgsMessageLog.
 
virtual QString lastError() const
Returns the last error message.
 
static void passwordKeyHash(const QString &pass, QString *salt, QString *hash, QString *cipheriv=nullptr)
Generate SHA256 hash for master password, with iterations and salt.
 
static const QString encrypt(const QString &pass, const QString &cipheriv, const QString &text)
Encrypt data using master password.
 
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.
 
static const QString decrypt(const QString &pass, const QString &cipheriv, const QString &text)
Decrypt data using master password.
 
Singleton which offers an interface to manage the authentication configuration database and to utiliz...
 
bool storeAuthSetting(const QString &key, const QVariant &value, bool encrypt=false)
Stores an authentication setting.
 
bool setDefaultCertTrustPolicy(QgsAuthCertUtils::CertTrustPolicy policy)
Sets the default certificate trust policy preferred by user.
 
void clearAllCachedConfigs()
Clear all authentication configs from authentication method caches.
 
const QSslCertificate certIdentity(const QString &id)
certIdentity get a certificate identity by id (sha hash)
 
const QStringList certIdentityBundleToPem(const QString &id)
certIdentityBundleToPem get a certificate identity bundle by id (sha hash) returned as PEM text
 
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 verifyMasterPassword(const QString &compare=QString())
Verify the supplied master password against any existing hash in authentication database.
 
bool updateIgnoredSslErrorsCacheFromConfig(const QgsAuthConfigSslServer &config)
Update ignored SSL error cache with possible ignored SSL errors, using server config.
 
const QString disabledMessage() const
Standard message for when QCA's qca-ossl plugin is missing and system is disabled.
 
const QList< QSslCertificate > trustedCaCertsCache()
trustedCaCertsCache cache of trusted certificate authorities, ready for network connections
 
QgsAuthMethod * configAuthMethod(const QString &authcfg)
Gets authentication method from the config/provider cache.
 
static bool isFilesystemBasedDatabase(const QString &uri)
Returns the true if the uri is a filesystem-based database (SQLite).
 
bool storeCertIdentity(const QSslCertificate &cert, const QSslKey &key)
Store a certificate identity.
 
QgsAuthMethodsMap authMethodsMap(const QString &dataprovider=QString())
Gets available authentication methods mapped to their key.
 
bool rebuildIgnoredSslErrorCache()
Rebuild ignoredSSL error cache.
 
bool initSslCaches()
Initialize various SSL authentication caches.
 
const QList< QSslCertificate > extraFileCAs()
extraFileCAs extra file-based certificate authorities
 
bool removeAuthSetting(const QString &key)
Remove an authentication setting.
 
bool storeCertTrustPolicy(const QSslCertificate &cert, QgsAuthCertUtils::CertTrustPolicy policy)
Store user trust value for a certificate.
 
bool rebuildCaCertsCache()
Rebuild certificate authority cache.
 
bool scheduledAuthDatabaseErase()
Whether there is a scheduled opitonal erase of authentication database.
 
bool eraseAuthenticationDatabase(bool backup, QString *backuppath=nullptr)
Erase all rows from all tables in authentication database.
 
static bool passwordHelperEnabled()
Password helper enabled getter.
 
void passwordHelperMessageLog(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, Qgis::MessageLevel level=Qgis::MessageLevel::Info)
Custom logging signal to inform the user about master password <-> password manager interactions.
 
bool exportAuthenticationConfigsToXml(const QString &filename, const QStringList &authcfgs, const QString &password=QString())
Export authentication configurations to an XML file.
 
QString sqliteDatabasePath() const
Returns the path to the authentication database file or an empty string if the database is not SQLite...
 
Q_DECL_DEPRECATED 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 authDatabaseChanged()
Emitted when the authentication db is significantly changed, e.g. large record removal,...
 
void setPasswordHelperEnabled(bool enabled)
Password helper enabled setter.
 
void setScheduledAuthDatabaseErase(bool scheduleErase)
Schedule an optional erase of authentication database, starting when mutex is lockable.
 
const QList< QgsAuthConfigSslServer > sslCertCustomConfigs()
sslCertCustomConfigs get SSL certificate custom configs
 
const QList< QSslCertificate > untrustedCaCerts(QList< QSslCertificate > trustedCAs=QList< QSslCertificate >())
untrustedCaCerts get list of untrusted certificate authorities
 
const QString uniqueConfigId() const
Gets a unique generated 7-character string to assign to as config id.
 
const QPair< QSslCertificate, QSslKey > certIdentityBundle(const QString &id)
Gets a certificate identity bundle by id (sha hash).
 
bool isDisabled() const
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
 
QVariant authSetting(const QString &key, const QVariant &defaultValue=QVariant(), bool decrypt=false)
Returns a previously set authentication setting.
 
static const QString AUTH_MAN_TAG
The display name of the Authentication Manager.
 
QgsAuthCertUtils::CertTrustPolicy defaultCertTrustPolicy()
Gets the default certificate trust policy preferred by user.
 
const QByteArray trustedCaCertsPemText()
trustedCaCertsPemText get concatenated string of all trusted CA certificates
 
static bool hasConfigId(const QString &txt)
Returns whether a string includes an authcfg ID token.
 
bool removeAllAuthenticationConfigs()
Clear all authentication configs from table in database and from provider caches.
 
QgsAuthCertUtils::CertTrustPolicy certificateTrustPolicy(const QSslCertificate &cert)
certificateTrustPolicy get trust policy for a particular certificate cert
 
static bool passwordHelperLoggingEnabled()
Password helper logging enabled getter.
 
QgsAuthConfigurationStorageRegistry * authConfigurationStorageRegistry() const
Returns the authentication configuration storage registry.
 
bool rebuildCertTrustCache()
Rebuild certificate authority cache.
 
Q_DECL_DEPRECATED const QString authenticationDatabasePath() const
The standard authentication database file in ~/.qgis3/ or defined location.
 
static const QList< QSslCertificate > systemRootCAs()
systemRootCAs get root system certificate authorities
 
bool removeCertAuthority(const QSslCertificate &cert)
Remove a certificate authority.
 
const QList< QSslCertificate > trustedCaCerts(bool includeinvalid=false)
trustedCaCerts get list of all trusted CA certificates
 
bool existsCertAuthority(const QSslCertificate &cert)
Check if a certificate authority exists.
 
const QMap< QString, QSslCertificate > mappedDatabaseCAs()
mappedDatabaseCAs get sha1-mapped database-stored certificate authorities
 
bool importAuthenticationConfigsFromXml(const QString &filename, const QString &password=QString(), bool overwrite=false)
Import authentication configurations from an XML file.
 
bool configIdUnique(const QString &id) const
Verify if provided authentication id is unique.
 
static const QgsSettingsEntryBool * settingsGenerateRandomPasswordForPasswordHelper
 
QStringList configIds() const
Gets list of authentication ids from database.
 
QString authManTag() const
Simple text tag describing authentication system for message logs.
 
bool loadAuthenticationConfig(const QString &authcfg, QgsAuthMethodConfig &mconfig, bool full=false)
Load an authentication config from the database into subclass.
 
QgsAuthCertUtils::CertTrustPolicy certTrustPolicy(const QSslCertificate &cert)
certTrustPolicy get whether certificate cert is trusted by user
 
bool masterPasswordHashInDatabase() const
Verify a password hash existing in authentication database.
 
Q_DECL_DEPRECATED 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.
 
QgsAuthConfigurationStorageDb * defaultDbStorage() const
Transitional proxy to the first ready storage of database type.
 
bool updateNetworkProxy(QNetworkProxy &proxy, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkProxy with an authentication config.
 
const QSslCertificate certAuthority(const QString &id)
Gets a certificate authority by id (sha hash)
 
void passwordHelperSuccess()
Signals emitted on password helper success, mainly used in the tests to exit main application loop.
 
bool registerCoreAuthMethods()
Instantiate and register existing C++ core authentication methods from plugins.
 
bool passwordHelperDelete()
Delete master password from wallet.
 
~QgsAuthManager() override
 
void dumpIgnoredSslErrorsCache_()
Utility function to dump the cache for debug purposes.
 
const QList< QSslCertificate > databaseCAs()
databaseCAs get database-stored certificate authorities
 
void messageLog(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, Qgis::MessageLevel level=Qgis::MessageLevel::Info) const
Custom logging signal to relay to console output and QgsMessageLog.
 
bool backupAuthenticationDatabase(QString *backuppath=nullptr)
Close connection to current authentication database and back it up.
 
void authDatabaseEraseRequested()
Emitted when a user has indicated they may want to erase the authentication db.
 
void passwordHelperFailure()
Signals emitted on password helper failure, mainly used in the tests to exit main application loop.
 
bool existsSslCertCustomConfig(const QString &id, const QString &hostport)
Check if SSL certificate custom config exists.
 
bool existsAuthSetting(const QString &key)
Check if an authentication setting exists.
 
void clearCachedConfig(const QString &authcfg)
Clear an authentication config from its associated authentication method cache.
 
void clearMasterPassword()
Clear supplied master password.
 
bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkRequest with an authentication config.
 
bool createAndStoreRandomMasterPasswordInKeyChain()
Creates a new securely seeded random password and stores it in the system keychain as the new master ...
 
const QList< QSslCertificate > certIdentities()
certIdentities get certificate identities
 
bool storeCertAuthority(const QSslCertificate &cert)
Store a certificate authority.
 
QStringList certIdentityIds() const
certIdentityIds get list of certificate identity ids from database
 
bool removeCertTrustPolicies(const QList< QSslCertificate > &certs)
Remove a group certificate authorities.
 
QgsAuthMethod * authMethod(const QString &authMethodKey)
Gets authentication method from the config/provider cache via its key.
 
bool updateDataSourceUriItems(QStringList &connectionItems, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QgsDataSourceUri with an authentication config.
 
void setup(const QString &pluginPath=QString(), const QString &authDatabasePath=QString())
Sets up the authentication manager configuration.
 
const QString passwordHelperErrorMessage()
Error message getter.
 
Q_DECL_DEPRECATED QSqlDatabase authDatabaseConnection() const
Sets up the application instance of the authentication database connection.
 
void updateConfigAuthMethods()
Sync the confg/authentication method cache with what is in database.
 
bool storeSslCertCustomConfig(const QgsAuthConfigSslServer &config)
Store an SSL certificate custom config.
 
static void setPasswordHelperLoggingEnabled(bool enabled)
Password helper logging enabled setter.
 
bool ensureInitialized() const
Performs lazy initialization of the authentication framework, if it has not already been done.
 
const QgsAuthConfigSslServer sslCertCustomConfigByHost(const QString &hostport)
sslCertCustomConfigByHost get an SSL certificate custom config by hostport (host:port)
 
bool updateAuthenticationConfig(const QgsAuthMethodConfig &config)
Update an authentication config in the database.
 
bool existsCertIdentity(const QString &id)
Check if a certificate identity exists.
 
const QString authenticationDatabaseUri() const
Returns the authentication database connection URI.
 
static const QgsSettingsEntryBool * settingsUsingGeneratedRandomPassword
 
bool resetMasterPassword(const QString &newpass, const QString &oldpass, bool keepbackup, QString *backuppath=nullptr)
Reset the master password to a new one, then re-encrypts all previous configs with the new password.
 
QStringList authMethodsKeys(const QString &dataprovider=QString())
Gets keys of supported authentication methods.
 
bool passwordHelperSync()
Store the password manager into the wallet.
 
bool masterPasswordIsSet() const
Whether master password has be input and verified, i.e. authentication database is accessible.
 
const QString methodConfigTableName() const
Returns the database table from the first ready storage that stores authentication configs,...
 
static QgsAuthManager * instance()
Enforce singleton pattern.
 
void masterPasswordVerified(bool verified)
Emitted when a password has been verify (or not)
 
bool setMasterPassword(bool verify=false)
Main call to initially set or continually check master password is set.
 
bool storeCertAuthorities(const QList< QSslCertificate > &certs)
Store multiple certificate authorities.
 
bool removeSslCertCustomConfig(const QString &id, const QString &hostport)
Remove an SSL certificate custom config.
 
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 rebuildTrustedCaCertsCache()
Rebuild trusted certificate authorities cache.
 
const QgsAuthMethodMetadata * authMethodMetadata(const QString &authMethodKey)
Gets authentication method metadata via its key.
 
bool removeAuthenticationConfig(const QString &authcfg)
Remove an authentication config in the database.
 
bool removeCertTrustPolicy(const QSslCertificate &cert)
Remove a certificate authority.
 
const QString authenticationDatabaseUriStripped() const
Returns the authentication database connection URI with the password stripped.
 
QgsAuthMethod::Expansions supportedAuthMethodExpansions(const QString &authcfg)
Gets supported authentication method expansion(s), e.g.
 
const QgsAuthConfigSslServer sslCertCustomConfig(const QString &id, const QString &hostport)
sslCertCustomConfig get an SSL certificate custom config by id (sha hash) and hostport (host:port)
 
QgsAuthMethodConfigsMap availableAuthMethodConfigs(const QString &dataprovider=QString())
Gets mapping of authentication config ids and their base configs (not decrypted data)
 
bool masterPasswordSame(const QString &password) const
Check whether supplied password is the same as the one already set.
 
static const QString AUTH_PASSWORD_HELPER_DISPLAY_NAME
The display name of the password helper (platform dependent).
 
bool storeAuthenticationConfig(QgsAuthMethodConfig &mconfig, bool overwrite=false)
Store an authentication config in the database.
 
bool verifyStoredPasswordHelperPassword()
Verify the password stored in the password helper.
 
bool removeCertIdentity(const QString &id)
Remove a certificate identity.
 
static QString passwordHelperDisplayName(bool titleCase=false)
Returns a translated display name of the password helper (platform dependent).
 
bool resetMasterPasswordUsingStoredPasswordHelper(const QString &newPassword, bool keepBackup, QString *backupPath=nullptr)
Reset the master password to a new one, hen re-encrypts all previous configs with the new password.
 
QString configAuthMethodKey(const QString &authcfg) const
Gets key of authentication method associated with config ID.
 
Configuration storage class for authentication method configurations.
 
bool isValid(bool validateid=false) const
Whether the configuration is valid.
 
bool readXml(const QDomElement &element)
from a DOM element.
 
const QString configString() const
The extended configuration, as stored and retrieved from the authentication database.
 
const QString id() const
Gets 'authcfg' 7-character alphanumeric ID of the config.
 
void loadConfigString(const QString &configstr)
Load existing extended configuration.
 
bool writeXml(QDomElement &parentElement, QDomDocument &document)
Stores the configuration in a DOM.
 
void setId(const QString &id)
Sets auth config ID.
 
A registry / canonical manager of authentication methods.
 
const QgsAuthMethodMetadata * authMethodMetadata(const QString &authMethodKey) const
Returns metadata of the auth method or nullptr if not found.
 
static QgsAuthMethodRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
 
QStringList authMethodList() const
Returns list of available auth methods by their keys.
 
QgsAuthMethod * createAuthMethod(const QString &authMethodKey)
Create an instance of the auth method.
 
Abstract base class for authentication method plugins.
 
virtual bool updateNetworkProxy(QNetworkProxy &proxy, const QString &authcfg, const QString &dataprovider=QString())
Update proxy settings with authentication components.
 
virtual bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Update a network request with authentication components.
 
QgsAuthMethod::Expansions supportedExpansions() const
Flags that represent the update points (where authentication configurations are expanded) supported b...
 
virtual void clearCachedConfig(const QString &authcfg)=0
Clear any cached configuration.
 
virtual void updateMethodConfig(QgsAuthMethodConfig &mconfig)=0
Update an authentication configuration in place.
 
virtual bool updateNetworkReply(QNetworkReply *reply, const QString &authcfg, const QString &dataprovider=QString())
Update a network reply with authentication components.
 
virtual bool updateDataSourceUriItems(QStringList &connectionItems, const QString &authcfg, const QString &dataprovider=QString())
Update data source connection items with authentication components.
 
QFlags< Expansion > Expansions
 
static QgsCredentials * instance()
retrieves instance
 
bool getMasterPassword(QString &password, bool stored=false)
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
Custom exception class which is raised when an operation is not supported.
 
Scoped object for logging of the runtime for a single operation or group of operations.
 
bool setValue(const T &value, const QString &dynamicKeyPart=QString()) const
Set settings value.
 
A boolean settings entry.
 
static QgsSettingsTreeNode * sTreeAuthentication
 
Stores settings for use within QGIS.
 
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
 
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
 
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
 
#define Q_NOWARN_DEPRECATED_POP
 
#define Q_NOWARN_DEPRECATED_PUSH
 
QHash< QString, QgsAuthMethodConfig > QgsAuthMethodConfigsMap
 
QHash< QString, QgsAuthMethod * > QgsAuthMethodsMap
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)
 
Structure that holds the (encrypted) master password elements.