24#include <QMutexLocker> 
   27#include <QSqlDatabase> 
   36#include <QDomDocument> 
   37#include <QRegularExpression> 
   39#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) 
   40#include <QRandomGenerator> 
   46#include <QSslConfiguration> 
   67const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral( 
"auth_configs" );
 
   68const QString QgsAuthManager::AUTH_PASS_TABLE = QStringLiteral( 
"auth_pass" );
 
   69const QString QgsAuthManager::AUTH_SETTINGS_TABLE = QStringLiteral( 
"auth_settings" );
 
   70const QString QgsAuthManager::AUTH_IDENTITIES_TABLE = QStringLiteral( 
"auth_identities" );
 
   71const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral( 
"auth_servers" );
 
   72const QString QgsAuthManager::AUTH_AUTHORITIES_TABLE = QStringLiteral( 
"auth_authorities" );
 
   73const QString QgsAuthManager::AUTH_TRUST_TABLE = QStringLiteral( 
"auth_trust" );
 
   75const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral( 
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
 
   78const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME( 
"QGIS-Master-Password" );
 
   79const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME( 
"QGIS" );
 
   85#elif defined(Q_OS_WIN) 
   87#elif defined(Q_OS_LINUX) 
   96  QMutexLocker locker( &sMutex );
 
  107  mMutex = std::make_unique<QRecursiveMutex>();
 
  108  mMasterPasswordMutex = std::make_unique<QRecursiveMutex>();
 
  110           this, &QgsAuthManager::writeToConsole );
 
  121  QMutexLocker locker( mMutex.get() );
 
  126  const QString connectionName = QStringLiteral( 
"authentication.configs:0x%1" ).arg( 
reinterpret_cast<quintptr
>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char( 
'0' ) );
 
  127  QgsDebugMsgLevel( QStringLiteral( 
"Using auth db connection name: %1 " ).arg( connectionName ), 2 );
 
  128  if ( !QSqlDatabase::contains( connectionName ) )
 
  130    QgsDebugMsgLevel( QStringLiteral( 
"No existing connection, creating a new one" ), 2 );
 
  131    authdb = QSqlDatabase::addDatabase( QStringLiteral( 
"QSQLITE" ), connectionName );
 
  134    if ( QThread::currentThread() != qApp->thread() )
 
  136      QgsDebugMsgLevel( QStringLiteral( 
"Scheduled auth db remove on thread close" ), 2 );
 
  146      QMetaObject::Connection connection = connect( QThread::currentThread(), &QThread::finished, QThread::currentThread(), [connectionName, 
this ]
 
  148        QMutexLocker locker( mMutex.get() );
 
  149        QSqlDatabase::removeDatabase( connectionName );
 
  150        mConnectedThreads.remove( QThread::currentThread() );
 
  151      }, Qt::DirectConnection );
 
  153      mConnectedThreads.insert( QThread::currentThread(), connection );
 
  159    authdb = QSqlDatabase::database( connectionName );
 
  163  if ( !authdb.isOpen() )
 
  165    if ( !authdb.open() )
 
  167      QString err = tr( 
"Opening of authentication db FAILED : %1" ).arg( authdb.lastError().text() );
 
  185  mQcaInitializer = std::make_unique<QCA::Initializer>( QCA::Practical, 256 );
 
  188  QCA::scanForPlugins();
 
  190  QgsDebugMsgLevel( QStringLiteral( 
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ), 2 );
 
  191  QStringList capabilities;
 
  193  capabilities = QCA::supportedFeatures();
 
  194  QgsDebugMsgLevel( QStringLiteral( 
"QCA supports: %1" ).arg( capabilities.join( 
"," ) ), 2 );
 
  197  if ( !QCA::isSupported( 
"cert", QStringLiteral( 
"qca-ossl" ) ) )
 
  199    mAuthDisabled = 
true;
 
  200    mAuthDisabledMessage = tr( 
"QCA's OpenSSL plugin (qca-ossl) is missing" );
 
  204  QgsDebugMsgLevel( QStringLiteral( 
"Prioritizing qca-ossl over all other QCA providers..." ), 2 );
 
  205  const QCA::ProviderList provds = QCA::providers();
 
  207  for ( QCA::Provider *p : provds )
 
  209    QString pn = p->name();
 
  211    if ( pn != QLatin1String( 
"qca-ossl" ) )
 
  213      pr = QCA::providerPriority( pn ) + 1;
 
  215    QCA::setProviderPriority( pn, pr );
 
  216    prlist << QStringLiteral( 
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
 
  218  QgsDebugMsgLevel( QStringLiteral( 
"QCA provider priorities: %1" ).arg( prlist.join( 
", " ) ), 2 );
 
  225  QgsDebugMsgLevel( QStringLiteral( 
"Authentication methods found: %1" ).arg( methods.join( 
", " ) ), 2 );
 
  227  if ( methods.isEmpty() )
 
  229    mAuthDisabled = 
true;
 
  230    mAuthDisabledMessage = tr( 
"No authentication method plugins found" );
 
  236    mAuthDisabled = 
true;
 
  237    mAuthDisabledMessage = tr( 
"No authentication method plugins could be loaded" );
 
  241  mAuthDbPath = QDir::cleanPath( authDatabasePath );
 
  245  QFileInfo dbdirinfo( dbinfo.path() );
 
  246  QgsDebugMsgLevel( QStringLiteral( 
"Auth db directory path: %1" ).arg( dbdirinfo.filePath() ), 2 );
 
  248  if ( !dbdirinfo.exists() )
 
  250    QgsDebugMsgLevel( QStringLiteral( 
"Auth db directory path does not exist, making path: %1" ).arg( dbdirinfo.filePath() ), 2 );
 
  251    if ( !QDir().mkpath( dbdirinfo.filePath() ) )
 
  253      const char *err = QT_TR_NOOP( 
"Auth db directory path could not be created" );
 
  260  if ( dbinfo.exists() )
 
  262    if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
 
  264      const char *err = QT_TR_NOOP( 
"Auth db is not readable or writable by user" );
 
  269    if ( dbinfo.size() > 0 )
 
  273      if ( !createCertTables() )
 
  283      const char *passenv = 
"QGIS_AUTH_PASSWORD_FILE";
 
  286        QString passpath( getenv( passenv ) );
 
  295        QFile passfile( passpath );
 
  296        if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
 
  298          QTextStream passin( &passfile );
 
  299          while ( !passin.atEnd() )
 
  301            masterpass = passin.readLine();
 
  306        if ( !masterpass.isEmpty() )
 
  310            QgsDebugMsgLevel( QStringLiteral( 
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" ), 2 );
 
  314            QgsDebugError( 
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
 
  320          QgsDebugError( 
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
 
  330    QgsDebugMsgLevel( QStringLiteral( 
"Auth db does not exist: creating through QSqlDatabase initial connection" ), 2 );
 
  332    if ( !createConfigTables() )
 
  335    if ( !createCertTables() )
 
  346bool QgsAuthManager::createConfigTables()
 
  348  QMutexLocker locker( mMutex.get() );
 
  352    const char *err = QT_TR_NOOP( 
"Auth db could not be created and opened" );
 
  363  qstr = QStringLiteral( 
"CREATE TABLE %1 (\n" 
  364                         "    'salt' TEXT NOT NULL,\n" 
  365                         "    'civ' TEXT NOT NULL\n" 
  366                         ", 'hash' TEXT  NOT NULL);" ).arg( authDbPassTable() );
 
  367  query.prepare( qstr );
 
  368  if ( !authDbQuery( &query ) )
 
  372  qstr = QStringLiteral( 
"CREATE TABLE %1 (\n" 
  373                         "    'id' TEXT NOT NULL,\n" 
  374                         "    'name' TEXT NOT NULL,\n" 
  376                         "    'type' TEXT NOT NULL,\n" 
  377                         "    'version' INTEGER NOT NULL\n" 
  379  query.prepare( qstr );
 
  380  if ( !authDbQuery( &query ) )
 
  385  query.prepare( qstr );
 
  386  if ( !authDbQuery( &query ) )
 
  391  query.prepare( qstr );
 
  392  if ( !authDbQuery( &query ) )
 
  399bool QgsAuthManager::createCertTables()
 
  401  QMutexLocker locker( mMutex.get() );
 
  410  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  411                         "    'setting' TEXT NOT NULL\n" 
  412                         ", 'value' TEXT);" ).arg( authDbSettingsTable() );
 
  413  query.prepare( qstr );
 
  414  if ( !authDbQuery( &query ) )
 
  419  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  420                         "    'id' TEXT NOT NULL,\n" 
  421                         "    'key' TEXT NOT NULL\n" 
  422                         ", 'cert' TEXT  NOT NULL);" ).arg( authDbIdentitiesTable() );
 
  423  query.prepare( qstr );
 
  424  if ( !authDbQuery( &query ) )
 
  428  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbIdentitiesTable() );
 
  429  query.prepare( qstr );
 
  430  if ( !authDbQuery( &query ) )
 
  435  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  436                         "    'id' TEXT NOT NULL,\n" 
  437                         "    'host' TEXT NOT NULL,\n" 
  440  query.prepare( qstr );
 
  441  if ( !authDbQuery( &query ) )
 
  445  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'host_index' on %1 (host ASC);" ).arg( 
authDatabaseServersTable() );
 
  446  query.prepare( qstr );
 
  447  if ( !authDbQuery( &query ) )
 
  452  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  453                         "    'id' TEXT NOT NULL\n" 
  454                         ", 'cert' TEXT  NOT NULL);" ).arg( authDbAuthoritiesTable() );
 
  455  query.prepare( qstr );
 
  456  if ( !authDbQuery( &query ) )
 
  460  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbAuthoritiesTable() );
 
  461  query.prepare( qstr );
 
  462  if ( !authDbQuery( &query ) )
 
  466  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  467                         "    'id' TEXT NOT NULL\n" 
  468                         ", 'policy' TEXT  NOT NULL);" ).arg( authDbTrustTable() );
 
  469  query.prepare( qstr );
 
  470  if ( !authDbQuery( &query ) )
 
  474  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbTrustTable() );
 
  475  query.prepare( qstr );
 
  476  if ( !authDbQuery( &query ) )
 
  487    QgsDebugError( QStringLiteral( 
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" ) );
 
  489  return mAuthDisabled;
 
  494  return tr( 
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
 
  499  QMutexLocker locker( mMasterPasswordMutex.get() );
 
  503  if ( mScheduledDbErase )
 
  506  if ( mMasterPass.isEmpty() )
 
  508    QgsDebugMsgLevel( QStringLiteral( 
"Master password is not yet set by user" ), 2 );
 
  509    if ( !masterPasswordInput() )
 
  511      QgsDebugMsgLevel( QStringLiteral( 
"Master password input canceled by user" ), 2 );
 
  525  QgsDebugMsgLevel( QStringLiteral( 
"Master password is set and verified" ), 2 );
 
  531  QMutexLocker locker( mMutex.get() );
 
  535  if ( mScheduledDbErase )
 
  539  QString prevpass = QString( mMasterPass );
 
  543    mMasterPass = prevpass;
 
  544    const char *err = QT_TR_NOOP( 
"Master password set: FAILED to verify, reset to previous" );
 
  550  QgsDebugMsgLevel( QStringLiteral( 
"Master password set: SUCCESS%1" ).arg( verify ? 
" and verified" : 
"" ), 2 );
 
  560  if ( !masterPasswordRowsInDb( &rows ) )
 
  562    const char *err = QT_TR_NOOP( 
"Master password: FAILED to access database" );
 
  570  QgsDebugMsgLevel( QStringLiteral( 
"Master password: %1 rows in database" ).arg( rows ), 2 );
 
  574    const char *err = QT_TR_NOOP( 
"Master password: FAILED to find just one master password record in database" );
 
  581  else if ( rows == 1 )
 
  583    if ( !masterPasswordCheckAgainstDb( compare ) )
 
  585      if ( compare.isNull() ) 
 
  587        const char *err = QT_TR_NOOP( 
"Master password: FAILED to verify against hash in database" );
 
  596      if ( mPassTries >= 5 )
 
  598        mAuthDisabled = 
true;
 
  599        const char *err = QT_TR_NOOP( 
"Master password: failed 5 times authentication system DISABLED" );
 
  607      QgsDebugMsgLevel( QStringLiteral( 
"Master password: verified against hash in database" ), 2 );
 
  608      if ( compare.isNull() )
 
  612  else if ( compare.isNull() ) 
 
  614    if ( !masterPasswordStoreInDb() )
 
  616      const char *err = QT_TR_NOOP( 
"Master password: hash FAILED to be stored in database" );
 
  625      QgsDebugMsgLevel( QStringLiteral( 
"Master password: hash stored in database" ), 2 );
 
  628    if ( !masterPasswordCheckAgainstDb() )
 
  630      const char *err = QT_TR_NOOP( 
"Master password: FAILED to verify against hash in database" );
 
  640      QgsDebugMsgLevel( QStringLiteral( 
"Master password: verified against hash in database" ), 2 );
 
  650  return !mMasterPass.isEmpty();
 
  655  return mMasterPass == pass;
 
  659    bool keepbackup, QString *backuppath )
 
  673  QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: backed up current database" ), 2 );
 
  679  QString prevpass = QString( mMasterPass );
 
  680  QString prevciv = QString( masterPasswordCiv() );
 
  686  if ( ok && !masterPasswordClearDb() )
 
  689    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not clear current password from database" );
 
  695    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: cleared current password from database" ), 2 );
 
  702  if ( ok && !masterPasswordStoreInDb() )
 
  705    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not store new password in database" );
 
  711    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: stored new password in database" ), 2 );
 
  718    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not verify new password in database" );
 
  724  if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
 
  727    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt configs in database" );
 
  733    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: re-encrypted configs in database" ), 2 );
 
  737  if ( ok && !verifyPasswordCanDecryptConfigs() )
 
  740    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
 
  745  if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
 
  748    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt settings in database" );
 
  753  if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
 
  756    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt identities in database" );
 
  766    QString errdbbackup( dbbackup );
 
  767    errdbbackup.replace( QLatin1String( 
".db" ), QLatin1String( 
"_ERROR.db" ) );
 
  769    QgsDebugError( QStringLiteral( 
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
 
  773    mMasterPass = prevpass;
 
  775    QgsDebugError( QStringLiteral( 
"Master password reset FAILED: reinstated previous password and database" ) );
 
  779      *backuppath = errdbbackup;
 
  785  if ( !keepbackup && !QFile::remove( dbbackup ) )
 
  787    const char *err = QT_TR_NOOP( 
"Master password reset: could not remove old database backup" );
 
  795    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: backed up previous db at %1" ).arg( dbbackup ), 2 );
 
  797      *backuppath = dbbackup;
 
  807  mScheduledDbErase = scheduleErase;
 
  809  mScheduledDbEraseRequestEmitted = 
false;
 
  810  mScheduledDbEraseRequestCount = 0;
 
  814    if ( !mScheduledDbEraseTimer )
 
  816      mScheduledDbEraseTimer = 
new QTimer( 
this );
 
  817      connect( mScheduledDbEraseTimer, &QTimer::timeout, 
this, &QgsAuthManager::tryToStartDbErase );
 
  818      mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
 
  820    else if ( !mScheduledDbEraseTimer->isActive() )
 
  822      mScheduledDbEraseTimer->start();
 
  827    if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
 
  828      mScheduledDbEraseTimer->stop();
 
  837  qDeleteAll( mAuthMethods );
 
  838  mAuthMethods.clear();
 
  840  for ( 
const auto &authMethodKey : methods )
 
  845  return !mAuthMethods.isEmpty();
 
  855  QTimer::singleShot( 3, &loop, &QEventLoop::quit );
 
  858#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  859  uint seed = 
static_cast< uint 
>( QTime::currentTime().msec() );
 
  866    for ( 
int i = 0; i < len; i++ )
 
  868#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  869      switch ( qrand() % 2 )
 
  871      switch ( QRandomGenerator::system()->generate() % 2 )
 
  875#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  876          id += ( 
'0' + qrand() % 10 );
 
  878          id += 
static_cast<char>( 
'0' + QRandomGenerator::system()->generate() % 10 );
 
  882#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  883          id += ( 
'a' + qrand() % 26 );
 
  885          id += 
static_cast<char>( 
'a' + QRandomGenerator::system()->generate() % 26 );
 
  890    if ( !configids.contains( 
id ) )
 
  895  QgsDebugMsgLevel( QStringLiteral( 
"Generated unique ID: %1" ).arg( 
id ), 2 );
 
  906    const char *err = QT_TR_NOOP( 
"Config ID is empty" );
 
  912  return !configids.contains( 
id );
 
  917  const thread_local QRegularExpression authCfgRegExp( AUTH_CFG_REGEX );
 
  918  return txt.indexOf( authCfgRegExp ) != -1;
 
  923  QMutexLocker locker( mMutex.get() );
 
  924  QStringList providerAuthMethodsKeys;
 
  925  if ( !dataprovider.isEmpty() )
 
  936  query.prepare( QStringLiteral( 
"SELECT id, name, uri, type, version FROM %1" ).arg( 
authDatabaseConfigTable() ) );
 
  938  if ( !authDbQuery( &query ) )
 
  943  if ( query.isActive() && query.isSelect() )
 
  945    while ( query.next() )
 
  947      QString authcfg = query.value( 0 ).toString();
 
  949      config.
setId( authcfg );
 
  950      config.
setName( query.value( 1 ).toString() );
 
  951      config.
setUri( query.value( 2 ).toString() );
 
  952      config.
setMethod( query.value( 3 ).toString() );
 
  953      config.
setVersion( query.value( 4 ).toInt() );
 
  955      if ( !dataprovider.isEmpty() && !providerAuthMethodsKeys.contains( config.
method() ) )
 
  960      baseConfigs.insert( authcfg, config );
 
  968  QMutexLocker locker( mMutex.get() );
 
  975  if ( !authDbQuery( &query ) )
 
  980  if ( query.isActive() )
 
  982    QgsDebugMsgLevel( QStringLiteral( 
"Syncing existing auth config and their auth methods" ), 2 );
 
  983    mConfigAuthMethods.clear();
 
  984    QStringList cfgmethods;
 
  985    while ( query.next() )
 
  987      mConfigAuthMethods.insert( query.value( 0 ).toString(),
 
  988                                 query.value( 1 ).toString() );
 
  989      cfgmethods << QStringLiteral( 
"%1=%2" ).arg( query.value( 0 ).toString(), query.value( 1 ).toString() );
 
  991    QgsDebugMsgLevel( QStringLiteral( 
"Stored auth config/methods:\n%1" ).arg( cfgmethods.join( 
", " ) ), 2 );
 
 1000  if ( !mConfigAuthMethods.contains( authcfg ) )
 
 1002    QgsDebugError( QStringLiteral( 
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
 
 1006  QString authMethodKey = mConfigAuthMethods.value( authcfg );
 
 1016  return mConfigAuthMethods.value( authcfg, QString() );
 
 1027  if ( !mAuthMethods.contains( authMethodKey ) )
 
 1029    QgsDebugError( QStringLiteral( 
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
 
 1033  return mAuthMethods.value( authMethodKey );
 
 1038  if ( !mAuthMethods.contains( authMethodKey ) )
 
 1040    QgsDebugError( QStringLiteral( 
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
 
 1050  if ( dataprovider.isEmpty() )
 
 1052    return mAuthMethods;
 
 1056  QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
 
 1057  while ( i != mAuthMethods.constEnd() )
 
 1060         && ( i.value()->supportedDataProviders().contains( QStringLiteral( 
"all" ) )
 
 1061              || i.value()->supportedDataProviders().contains( dataprovider ) ) )
 
 1063      filteredmap.insert( i.key(), i.value() );
 
 1071QWidget *QgsAuthManager::authMethodEditWidget( 
const QString &authMethodKey, QWidget *parent )
 
 1075    return method->editWidget( parent );
 
 1084    return QgsAuthMethod::Expansions();
 
 1091  return QgsAuthMethod::Expansions();
 
 1096  QMutexLocker locker( mMutex.get() );
 
 1103    const char *err = QT_TR_NOOP( 
"Store config: FAILED because config is invalid" );
 
 1109  QString uid = mconfig.
id();
 
 1110  bool passedinID = !uid.isEmpty();
 
 1111  if ( uid.isEmpty() )
 
 1119      const char *err = QT_TR_NOOP( 
"Store config: FAILED because pre-defined config ID %1 is not unique" );
 
 1130  if ( configstring.isEmpty() )
 
 1132    const char *err = QT_TR_NOOP( 
"Store config: FAILED because config string is empty" );
 
 1138  QgsDebugMsgLevel( QStringLiteral( 
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ), 2 );
 
 1141  QgsDebugMsgLevel( QStringLiteral( 
"type: %1" ).arg( config.method() ), 2 );
 
 1142  QgsDebugMsgLevel( QStringLiteral( 
"version: %1" ).arg( config.version() ), 2 );
 
 1147  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, name, uri, type, version, config) " 
 1150  query.bindValue( QStringLiteral( 
":id" ), uid );
 
 1151  query.bindValue( QStringLiteral( 
":name" ), mconfig.
name() );
 
 1152  query.bindValue( QStringLiteral( 
":uri" ), mconfig.
uri() );
 
 1153  query.bindValue( QStringLiteral( 
":type" ), mconfig.
method() );
 
 1154  query.bindValue( QStringLiteral( 
":version" ), mconfig.
version() );
 
 1155  query.bindValue( QStringLiteral( 
":config" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
 
 1157  if ( !authDbStartTransaction() )
 
 1160  if ( !authDbQuery( &query ) )
 
 1163  if ( !authDbCommit() )
 
 1168    mconfig.
setId( uid );
 
 1172  QgsDebugMsgLevel( QStringLiteral( 
"Store config SUCCESS for authcfg: %1" ).arg( uid ), 2 );
 
 1178  QMutexLocker locker( mMutex.get() );
 
 1183  if ( !config.
isValid( 
true ) )
 
 1185    const char *err = QT_TR_NOOP( 
"Update config: FAILED because config is invalid" );
 
 1192  if ( configstring.isEmpty() )
 
 1194    const char *err = QT_TR_NOOP( 
"Update config: FAILED because config is empty" );
 
 1201  QgsDebugMsgLevel( QStringLiteral( 
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ), 2 );
 
 1211  if ( !query.prepare( QStringLiteral( 
"UPDATE %1 " 
 1212                                       "SET name = :name, uri = :uri, type = :type, version = :version, config = :config " 
 1215    const char *err = QT_TR_NOOP( 
"Update config: FAILED to prepare query" );
 
 1221  query.bindValue( QStringLiteral( 
":id" ), config.
id() );
 
 1222  query.bindValue( QStringLiteral( 
":name" ), config.
name() );
 
 1223  query.bindValue( QStringLiteral( 
":uri" ), config.
uri() );
 
 1224  query.bindValue( QStringLiteral( 
":type" ), config.
method() );
 
 1225  query.bindValue( QStringLiteral( 
":version" ), config.
version() );
 
 1226  query.bindValue( QStringLiteral( 
":config" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
 
 1228  if ( !authDbStartTransaction() )
 
 1231  if ( !authDbQuery( &query ) )
 
 1234  if ( !authDbCommit() )
 
 1242  QgsDebugMsgLevel( QStringLiteral( 
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ), 2 );
 
 1255  QMutexLocker locker( mMutex.get() );
 
 1260    query.prepare( QStringLiteral( 
"SELECT id, name, uri, type, version, config FROM %1 " 
 1265    query.prepare( QStringLiteral( 
"SELECT id, name, uri, type, version FROM %1 " 
 1269  query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 1271  if ( !authDbQuery( &query ) )
 
 1276  if ( query.isActive() && query.isSelect() )
 
 1278    if ( query.first() )
 
 1280      mconfig.
setId( query.value( 0 ).toString() );
 
 1281      mconfig.
setName( query.value( 1 ).toString() );
 
 1282      mconfig.
setUri( query.value( 2 ).toString() );
 
 1283      mconfig.
setMethod( query.value( 3 ).toString() );
 
 1284      mconfig.
setVersion( query.value( 4 ).toInt() );
 
 1299        QgsDebugError( QStringLiteral( 
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
 
 1302      QgsDebugMsgLevel( QStringLiteral( 
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ? 
"full" : 
"base", authcfg ), 2 );
 
 1307      QgsDebugError( QStringLiteral( 
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
 
 1317  QMutexLocker locker( mMutex.get() );
 
 1321  if ( authcfg.isEmpty() )
 
 1328  query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 1330  if ( !authDbStartTransaction() )
 
 1333  if ( !authDbQuery( &query ) )
 
 1336  if ( !authDbCommit() )
 
 1343  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED config for authcfg: %1" ).arg( authcfg ), 2 );
 
 1350  if ( filename.isEmpty() )
 
 1353  QDomDocument document( QStringLiteral( 
"qgis_authentication" ) );
 
 1354  QDomElement root = document.createElement( QStringLiteral( 
"qgis_authentication" ) );
 
 1355  document.appendChild( root );
 
 1358  if ( !password.isEmpty() )
 
 1363    root.setAttribute( QStringLiteral( 
"salt" ), salt );
 
 1364    root.setAttribute( QStringLiteral( 
"hash" ), hash );
 
 1365    root.setAttribute( QStringLiteral( 
"civ" ), civ );
 
 1368  QDomElement configurations = document.createElement( QStringLiteral( 
"configurations" ) );
 
 1369  for ( 
const QString &authcfg : authcfgs )
 
 1376      authMethodConfig.
writeXml( configurations, document );
 
 1379  if ( !password.isEmpty() )
 
 1381    QString configurationsString;
 
 1382    QTextStream ts( &configurationsString );
 
 1383#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
 1384    ts.setCodec( 
"UTF-8" );
 
 1386    configurations.save( ts, 2 );
 
 1387    root.appendChild( document.createTextNode( 
QgsAuthCrypto::encrypt( password, civ, configurationsString ) ) );
 
 1391    root.appendChild( configurations );
 
 1394  QFile file( filename );
 
 1395  if ( !file.open( QFile::WriteOnly | QIODevice::Truncate ) )
 
 1398  QTextStream ts( &file );
 
 1399#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
 1400  ts.setCodec( 
"UTF-8" );
 
 1402  document.save( ts, 2 );
 
 1409  QFile file( filename );
 
 1410  if ( !file.open( QFile::ReadOnly ) )
 
 1415  QDomDocument document( QStringLiteral( 
"qgis_authentication" ) );
 
 1416  if ( !document.setContent( &file ) )
 
 1423  QDomElement root = document.documentElement();
 
 1424  if ( root.tagName() != QLatin1String( 
"qgis_authentication" ) )
 
 1429  QDomElement configurations;
 
 1430  if ( root.hasAttribute( QStringLiteral( 
"salt" ) ) )
 
 1432    QString salt = root.attribute( QStringLiteral( 
"salt" ) );
 
 1433    QString hash = root.attribute( QStringLiteral( 
"hash" ) );
 
 1434    QString civ = root.attribute( QStringLiteral( 
"civ" ) );
 
 1439    configurations = document.firstChild().toElement();
 
 1443    configurations = root.firstChildElement( QStringLiteral( 
"configurations" ) );
 
 1446  QDomElement configuration = configurations.firstChildElement();
 
 1447  while ( !configuration.isNull() )
 
 1450    authMethodConfig.
readXml( configuration );
 
 1453    configuration = configuration.nextSiblingElement();
 
 1460  QMutexLocker locker( mMutex.get() );
 
 1466  bool res = authDbTransactionQuery( &query );
 
 1474  QgsDebugMsgLevel( QStringLiteral( 
"Remove configs from database: %1" ).arg( res ? 
"SUCCEEDED" : 
"FAILED" ), 2 );
 
 1481  QMutexLocker locker( mMutex.get() );
 
 1484    const char *err = QT_TR_NOOP( 
"No authentication database found" );
 
 1492  if ( authConn.isValid() && authConn.isOpen() )
 
 1496  QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral( 
"yyyy-MM-dd-hhmmss" ) ) );
 
 1498  dbbackup.replace( QLatin1String( 
".db" ), QStringLiteral( 
"_%1.db" ).arg( datestamp ) );
 
 1502    const char *err = QT_TR_NOOP( 
"Could not back up authentication database" );
 
 1509    *backuppath = dbbackup;
 
 1511  QgsDebugMsgLevel( QStringLiteral( 
"Backed up auth database at %1" ).arg( dbbackup ), 2 );
 
 1517  QMutexLocker locker( mMutex.get() );
 
 1527  if ( backuppath && !dbbackup.isEmpty() )
 
 1528    *backuppath = dbbackup;
 
 1531  if ( dbinfo.exists() )
 
 1533    if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
 
 1535      const char *err = QT_TR_NOOP( 
"Auth db is not readable or writable by user" );
 
 1543    const char *err = QT_TR_NOOP( 
"No authentication database found" );
 
 1551    const char *err = QT_TR_NOOP( 
"Authentication database could not be deleted" );
 
 1557  mMasterPass = QString();
 
 1559  QgsDebugMsgLevel( QStringLiteral( 
"Creating Auth db through QSqlDatabase initial connection" ), 2 );
 
 1562  if ( !authConn.isValid() || !authConn.isOpen() )
 
 1564    const char *err = QT_TR_NOOP( 
"Authentication database could not be initialized" );
 
 1570  if ( !createConfigTables() )
 
 1572    const char *err = QT_TR_NOOP( 
"FAILED to create auth database config tables" );
 
 1578  if ( !createCertTables() )
 
 1580    const char *err = QT_TR_NOOP( 
"FAILED to create auth database cert tables" );
 
 1599    const QString &dataprovider )
 
 1609      QgsDebugError( QStringLiteral( 
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 1624    const QString &dataprovider )
 
 1634      QgsDebugError( QStringLiteral( 
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 1650    const QString &dataprovider )
 
 1660      QgsDebugError( QStringLiteral( 
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 1685      QgsDebugError( QStringLiteral( 
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 1694    QgsDebugMsgLevel( QStringLiteral( 
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ), 2 );
 
 1703  QMutexLocker locker( mMutex.get() );
 
 1704  if ( key.isEmpty() )
 
 1707  QString storeval( value.toString() );
 
 1723  query.prepare( QStringLiteral( 
"INSERT INTO %1 (setting, value) " 
 1724                                 "VALUES (:setting, :value)" ).arg( authDbSettingsTable() ) );
 
 1726  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1727  query.bindValue( QStringLiteral( 
":value" ), storeval );
 
 1729  if ( !authDbStartTransaction() )
 
 1732  if ( !authDbQuery( &query ) )
 
 1735  if ( !authDbCommit() )
 
 1738  QgsDebugMsgLevel( QStringLiteral( 
"Store setting SUCCESS for key: %1" ).arg( key ), 2 );
 
 1744  QMutexLocker locker( mMutex.get() );
 
 1745  if ( key.isEmpty() )
 
 1751  QVariant value = defaultValue;
 
 1753  query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 1754                                 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 1756  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1758  if ( !authDbQuery( &query ) )
 
 1761  if ( query.isActive() && query.isSelect() )
 
 1763    if ( query.first() )
 
 1767        value = QVariant( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ) );
 
 1771        value = query.value( 0 );
 
 1773      QgsDebugMsgLevel( QStringLiteral( 
"Authentication setting retrieved for key: %1" ).arg( key ), 2 );
 
 1777      QgsDebugError( QStringLiteral( 
"Select contains more than one for setting key: %1" ).arg( key ) );
 
 1787  QMutexLocker locker( mMutex.get() );
 
 1788  if ( key.isEmpty() )
 
 1792  query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 1793                                 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 1795  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1797  if ( !authDbQuery( &query ) )
 
 1801  if ( query.isActive() && query.isSelect() )
 
 1803    if ( query.first() )
 
 1805      QgsDebugMsgLevel( QStringLiteral( 
"Authentication setting exists for key: %1" ).arg( key ), 2 );
 
 1810      QgsDebugError( QStringLiteral( 
"Select contains more than one for setting key: %1" ).arg( key ) );
 
 1820  QMutexLocker locker( mMutex.get() );
 
 1821  if ( key.isEmpty() )
 
 1826  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 1828  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1830  if ( !authDbStartTransaction() )
 
 1833  if ( !authDbQuery( &query ) )
 
 1836  if ( !authDbCommit() )
 
 1839  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED setting for key: %1" ).arg( key ), 2 );
 
 1853  QMutexLocker locker( mMutex.get() );
 
 1859  mCustomConfigByHostCache.clear();
 
 1860  mHasCheckedIfCustomConfigByHostExists = 
false;
 
 1863    QgsDebugError( QStringLiteral( 
"Init of SSL caches FAILED" ) );
 
 1869  QMutexLocker locker( mMutex.get() );
 
 1870  if ( cert.isNull() )
 
 1872    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 1877    QgsDebugError( QStringLiteral( 
"Passed private key is null" ) );
 
 1887  QString certpem( cert.toPem() );
 
 1891  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, key, cert) " 
 1892                                 "VALUES (:id, :key, :cert)" ).arg( authDbIdentitiesTable() ) );
 
 1894  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 1895  query.bindValue( QStringLiteral( 
":key" ), keypem );
 
 1896  query.bindValue( QStringLiteral( 
":cert" ), certpem );
 
 1898  if ( !authDbStartTransaction() )
 
 1901  if ( !authDbQuery( &query ) )
 
 1904  if ( !authDbCommit() )
 
 1907  QgsDebugMsgLevel( QStringLiteral( 
"Store certificate identity SUCCESS for id: %1" ).arg( 
id ), 2 );
 
 1913  QMutexLocker locker( mMutex.get() );
 
 1914  QSslCertificate emptycert;
 
 1915  QSslCertificate cert;
 
 1920  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 1921                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 1923  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 1925  if ( !authDbQuery( &query ) )
 
 1928  if ( query.isActive() && query.isSelect() )
 
 1930    if ( query.first() )
 
 1932      cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
 
 1933      QgsDebugMsgLevel( QStringLiteral( 
"Certificate identity retrieved for id: %1" ).arg( 
id ), 2 );
 
 1937      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate identity for id: %1" ).arg( 
id ) );
 
 1947  QMutexLocker locker( mMutex.get() );
 
 1948  QPair<QSslCertificate, QSslKey> bundle;
 
 1956  query.prepare( QStringLiteral( 
"SELECT key, cert FROM %1 " 
 1957                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 1959  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 1961  if ( !authDbQuery( &query ) )
 
 1964  if ( query.isActive() && query.isSelect() )
 
 1966    QSslCertificate cert;
 
 1968    if ( query.first() )
 
 1970      key = QSslKey( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ).toLatin1(),
 
 1971                     QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
 
 1974        const char *err = QT_TR_NOOP( 
"Retrieve certificate identity bundle: FAILED to create private key" );
 
 1979      cert = QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
 
 1980      if ( cert.isNull() )
 
 1982        const char *err = QT_TR_NOOP( 
"Retrieve certificate identity bundle: FAILED to create certificate" );
 
 1987      QgsDebugMsgLevel( QStringLiteral( 
"Certificate identity bundle retrieved for id: %1" ).arg( 
id ), 2 );
 
 1991      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate identity for id: %1" ).arg( 
id ) );
 
 1995    bundle = qMakePair( cert, key );
 
 2002  QMutexLocker locker( mMutex.get() );
 
 2006    return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
 
 2008  return QStringList();
 
 2013  QMutexLocker locker( mMutex.get() );
 
 2014  QList<QSslCertificate> certs;
 
 2017  query.prepare( QStringLiteral( 
"SELECT id, cert FROM %1" ).arg( authDbIdentitiesTable() ) );
 
 2019  if ( !authDbQuery( &query ) )
 
 2022  if ( query.isActive() && query.isSelect() )
 
 2024    while ( query.next() )
 
 2026      certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
 
 2035  QMutexLocker locker( mMutex.get() );
 
 2036  QStringList identityids = QStringList();
 
 2042  query.prepare( QStringLiteral( 
"SELECT id FROM %1" ).arg( authDbIdentitiesTable() ) );
 
 2044  if ( !authDbQuery( &query ) )
 
 2049  if ( query.isActive() )
 
 2051    while ( query.next() )
 
 2053      identityids << query.value( 0 ).toString();
 
 2061  QMutexLocker locker( mMutex.get() );
 
 2066  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 2067                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 2069  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2071  if ( !authDbQuery( &query ) )
 
 2075  if ( query.isActive() && query.isSelect() )
 
 2077    if ( query.first() )
 
 2079      QgsDebugMsgLevel( QStringLiteral( 
"Certificate bundle exists for id: %1" ).arg( 
id ), 2 );
 
 2084      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate bundle for id: %1" ).arg( 
id ) );
 
 2094  QMutexLocker locker( mMutex.get() );
 
 2097    QgsDebugError( QStringLiteral( 
"Passed bundle ID is empty" ) );
 
 2103  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 2105  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2107  if ( !authDbStartTransaction() )
 
 2110  if ( !authDbQuery( &query ) )
 
 2113  if ( !authDbCommit() )
 
 2116  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED certificate identity for id: %1" ).arg( 
id ), 2 );
 
 2122  QMutexLocker locker( mMutex.get() );
 
 2134  QString certpem( cert.toPem() );
 
 2137  query.prepare( QStringLiteral( 
"INSERT OR REPLACE INTO %1 (id, host, cert, config) " 
 2140  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2141  query.bindValue( QStringLiteral( 
":host" ), config.
sslHostPort().trimmed() );
 
 2142  query.bindValue( QStringLiteral( 
":cert" ), certpem );
 
 2143  query.bindValue( QStringLiteral( 
":config" ), config.
configString() );
 
 2145  if ( !authDbStartTransaction() )
 
 2148  if ( !authDbQuery( &query ) )
 
 2151  if ( !authDbCommit() )
 
 2154  QgsDebugMsgLevel( QStringLiteral( 
"Store SSL cert custom config SUCCESS for host:port, id: %1, %2" )
 
 2158  mHasCheckedIfCustomConfigByHostExists = 
false;
 
 2159  mCustomConfigByHostCache.clear();
 
 2166  QMutexLocker locker( mMutex.get() );
 
 2169  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2171    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2176  query.prepare( QStringLiteral( 
"SELECT id, host, cert, config FROM %1 " 
 2179  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2180  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2182  if ( !authDbQuery( &query ) )
 
 2185  if ( query.isActive() && query.isSelect() )
 
 2187    if ( query.first() )
 
 2189      config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
 
 2192      QgsDebugMsgLevel( QStringLiteral( 
"SSL cert custom config retrieved for host:port, id: %1, %2" ).arg( hostport, 
id ), 2 );
 
 2196      QgsDebugError( QStringLiteral( 
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport, 
id ) );
 
 2197      emit 
messageOut( tr( 
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
 
 2209  if ( hostport.isEmpty() )
 
 2214  QMutexLocker locker( mMutex.get() );
 
 2215  if ( mHasCheckedIfCustomConfigByHostExists && !mHasCustomConfigByHost )
 
 2217  if ( mCustomConfigByHostCache.contains( hostport ) )
 
 2218    return mCustomConfigByHostCache.value( hostport );
 
 2223  if ( !mHasCheckedIfCustomConfigByHostExists )
 
 2225    mHasCheckedIfCustomConfigByHostExists = 
true;
 
 2227    if ( !authDbQuery( &query ) )
 
 2229      mHasCustomConfigByHost = 
false;
 
 2232    if ( query.isActive() && query.isSelect() && query.first() )
 
 2234      mHasCustomConfigByHost = query.value( 0 ).toInt() > 0;
 
 2235      if ( !mHasCustomConfigByHost )
 
 2240      mHasCustomConfigByHost = 
false;
 
 2245  query.prepare( QString( 
"SELECT id, host, cert, config FROM %1 " 
 2248  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2250  if ( !authDbQuery( &query ) )
 
 2252    mCustomConfigByHostCache.insert( hostport, config );
 
 2256  if ( query.isActive() && query.isSelect() )
 
 2258    if ( query.first() )
 
 2260      config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
 
 2263      QgsDebugMsgLevel( QStringLiteral( 
"SSL cert custom config retrieved for host:port: %1" ).arg( hostport ), 2 );
 
 2267      QgsDebugError( QStringLiteral( 
"Select contains more than one SSL cert custom config for host:port: %1" ).arg( hostport ) );
 
 2268      emit 
messageOut( tr( 
"Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
 
 2271      mCustomConfigByHostCache.insert( hostport, emptyconfig );
 
 2276  mCustomConfigByHostCache.insert( hostport, config );
 
 2282  QMutexLocker locker( mMutex.get() );
 
 2283  QList<QgsAuthConfigSslServer> configs;
 
 2288  if ( !authDbQuery( &query ) )
 
 2291  if ( query.isActive() && query.isSelect() )
 
 2293    while ( query.next() )
 
 2296      config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
 
 2300      configs.append( config );
 
 2309  QMutexLocker locker( mMutex.get() );
 
 2310  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2312    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2317  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 2320  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2321  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2323  if ( !authDbQuery( &query ) )
 
 2327  if ( query.isActive() && query.isSelect() )
 
 2329    if ( query.first() )
 
 2331      QgsDebugMsgLevel( QStringLiteral( 
"SSL cert custom config exists for host:port, id: %1, %2" ).arg( hostport, 
id ), 2 );
 
 2336      QgsDebugError( QStringLiteral( 
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport, 
id ) );
 
 2337      emit 
messageOut( tr( 
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
 
 2347  QMutexLocker locker( mMutex.get() );
 
 2348  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2350    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2354  mHasCheckedIfCustomConfigByHostExists = 
false;
 
 2355  mCustomConfigByHostCache.clear();
 
 2359  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id AND host = :host" ).arg( 
authDatabaseServersTable() ) );
 
 2361  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2362  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2364  if ( !authDbStartTransaction() )
 
 2367  if ( !authDbQuery( &query ) )
 
 2370  if ( !authDbCommit() )
 
 2373  QString shahostport( QStringLiteral( 
"%1:%2" ).arg( 
id, hostport ) );
 
 2374  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2376    mIgnoredSslErrorsCache.remove( shahostport );
 
 2379  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED SSL cert custom config for host:port, id: %1, %2" ).arg( hostport, 
id ), 2 );
 
 2386  QMutexLocker locker( mMutex.get() );
 
 2387  if ( !mIgnoredSslErrorsCache.isEmpty() )
 
 2389    QgsDebugMsgLevel( QStringLiteral( 
"Ignored SSL errors cache items:" ), 1 );
 
 2390    QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
 
 2391    while ( i != mIgnoredSslErrorsCache.constEnd() )
 
 2394      for ( 
auto err : i.value() )
 
 2398      QgsDebugMsgLevel( QStringLiteral( 
"%1 = %2" ).arg( i.key(), errs.join( 
", " ) ), 1 );
 
 2410  QMutexLocker locker( mMutex.get() );
 
 2417  QString shahostport( QStringLiteral( 
"%1:%2" )
 
 2420  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2422    mIgnoredSslErrorsCache.remove( shahostport );
 
 2425  if ( !errenums.isEmpty() )
 
 2427    mIgnoredSslErrorsCache.insert( shahostport, QSet<QSslError::SslError>( errenums.begin(), errenums.end() ) );
 
 2428    QgsDebugMsgLevel( QStringLiteral( 
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 2433  QgsDebugMsgLevel( QStringLiteral( 
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 2439  QMutexLocker locker( mMutex.get() );
 
 2440  const thread_local QRegularExpression rx( QRegularExpression::anchoredPattern( 
"\\S+:\\S+:\\d+" ) );
 
 2441  if ( !rx.match( shahostport ).hasMatch() )
 
 2443    QgsDebugError( 
"Passed shahostport does not match \\S+:\\S+:\\d+, " 
 2444                   "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
 
 2448  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2450    mIgnoredSslErrorsCache.remove( shahostport );
 
 2453  if ( errors.isEmpty() )
 
 2455    QgsDebugError( QStringLiteral( 
"Passed errors list empty" ) );
 
 2459  QSet<QSslError::SslError> errs;
 
 2460  for ( 
const auto &error : errors )
 
 2462    if ( error.error() == QSslError::NoError )
 
 2465    errs.insert( error.error() );
 
 2468  if ( errs.isEmpty() )
 
 2470    QgsDebugError( QStringLiteral( 
"Passed errors list does not contain errors" ) );
 
 2474  mIgnoredSslErrorsCache.insert( shahostport, errs );
 
 2476  QgsDebugMsgLevel( QStringLiteral( 
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 2483  QMutexLocker locker( mMutex.get() );
 
 2484  QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
 
 2485  QHash<QString, QSet<QSslError::SslError> > nextcache;
 
 2490  if ( !authDbQuery( &query ) )
 
 2492    QgsDebugError( QStringLiteral( 
"Rebuild of ignored SSL errors cache FAILED" ) );
 
 2496  if ( query.isActive() && query.isSelect() )
 
 2498    while ( query.next() )
 
 2500      QString shahostport( QStringLiteral( 
"%1:%2" )
 
 2501                           .arg( query.value( 0 ).toString().trimmed(),
 
 2502                                 query.value( 1 ).toString().trimmed() ) );
 
 2506      if ( !errenums.isEmpty() )
 
 2508        nextcache.insert( shahostport, QSet<QSslError::SslError>( errenums.begin(), errenums.end() ) );
 
 2510      if ( prevcache.contains( shahostport ) )
 
 2512        prevcache.remove( shahostport );
 
 2517  if ( !prevcache.isEmpty() )
 
 2520    QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
 
 2521    while ( i != prevcache.constEnd() )
 
 2523      nextcache.insert( i.key(), i.value() );
 
 2528  if ( nextcache != mIgnoredSslErrorsCache )
 
 2530    mIgnoredSslErrorsCache.clear();
 
 2531    mIgnoredSslErrorsCache = nextcache;
 
 2532    QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of ignored SSL errors cache SUCCEEDED" ), 2 );
 
 2537  QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of ignored SSL errors cache SAME AS BEFORE" ), 2 );
 
 2545  QMutexLocker locker( mMutex.get() );
 
 2546  if ( certs.isEmpty() )
 
 2548    QgsDebugError( QStringLiteral( 
"Passed certificate list has no certs" ) );
 
 2552  for ( 
const auto &cert : certs )
 
 2562  QMutexLocker locker( mMutex.get() );
 
 2565  if ( cert.isNull() )
 
 2567    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2574  QString pem( cert.toPem() );
 
 2577  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, cert) " 
 2578                                 "VALUES (:id, :cert)" ).arg( authDbAuthoritiesTable() ) );
 
 2580  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2581  query.bindValue( QStringLiteral( 
":cert" ), pem );
 
 2583  if ( !authDbStartTransaction() )
 
 2586  if ( !authDbQuery( &query ) )
 
 2589  if ( !authDbCommit() )
 
 2592  QgsDebugMsgLevel( QStringLiteral( 
"Store certificate authority SUCCESS for id: %1" ).arg( 
id ), 2 );
 
 2598  QMutexLocker locker( mMutex.get() );
 
 2599  QSslCertificate emptycert;
 
 2600  QSslCertificate cert;
 
 2605  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 2606                                 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
 
 2608  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2610  if ( !authDbQuery( &query ) )
 
 2613  if ( query.isActive() && query.isSelect() )
 
 2615    if ( query.first() )
 
 2617      cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
 
 2618      QgsDebugMsgLevel( QStringLiteral( 
"Certificate authority retrieved for id: %1" ).arg( 
id ), 2 );
 
 2622      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate authority for id: %1" ).arg( 
id ) );
 
 2632  QMutexLocker locker( mMutex.get() );
 
 2633  if ( cert.isNull() )
 
 2635    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2642  query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 2643                                 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
 
 2645  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2647  if ( !authDbQuery( &query ) )
 
 2651  if ( query.isActive() && query.isSelect() )
 
 2653    if ( query.first() )
 
 2655      QgsDebugMsgLevel( QStringLiteral( 
"Certificate authority exists for id: %1" ).arg( 
id ), 2 );
 
 2660      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate authority for id: %1" ).arg( 
id ) );
 
 2670  QMutexLocker locker( mMutex.get() );
 
 2671  if ( cert.isNull() )
 
 2673    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2681  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
 
 2683  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2685  if ( !authDbStartTransaction() )
 
 2688  if ( !authDbQuery( &query ) )
 
 2691  if ( !authDbCommit() )
 
 2694  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED authority for id: %1" ).arg( 
id ), 2 );
 
 2700  return QSslConfiguration::systemCaCertificates();
 
 2705  QMutexLocker locker( mMutex.get() );
 
 2706  QList<QSslCertificate> certs;
 
 2707  QList<QSslCertificate> filecerts;
 
 2716  QString cafile( cafileval.toString() );
 
 2717  if ( !cafile.isEmpty() && QFile::exists( cafile ) )
 
 2722  for ( 
const auto &cert : std::as_const( filecerts ) )
 
 2724    if ( !allowinvalid.toBool() && ( cert.isBlacklisted()
 
 2726                                     || cert.expiryDate() <= QDateTime::currentDateTime()
 
 2727                                     || cert.effectiveDate() > QDateTime::currentDateTime() ) )
 
 2742  QMutexLocker locker( mMutex.get() );
 
 2743  QList<QSslCertificate> certs;
 
 2746  query.prepare( QStringLiteral( 
"SELECT id, cert FROM %1" ).arg( authDbAuthoritiesTable() ) );
 
 2748  if ( !authDbQuery( &query ) )
 
 2751  if ( query.isActive() && query.isSelect() )
 
 2753    while ( query.next() )
 
 2755      certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
 
 2764  QMutexLocker locker( mMutex.get() );
 
 2770  QMutexLocker locker( mMutex.get() );
 
 2771  mCaCertsCache.clear();
 
 2777  bool res = !mCaCertsCache.isEmpty(); 
 
 2779    QgsDebugError( QStringLiteral( 
"Rebuild of CA certs cache FAILED" ) );
 
 2785  QMutexLocker locker( mMutex.get() );
 
 2786  if ( cert.isNull() )
 
 2788    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2798    QgsDebugMsgLevel( QStringLiteral( 
"Passed policy was default, all cert records in database were removed for id: %1" ).arg( 
id ), 2 );
 
 2803  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, policy) " 
 2804                                 "VALUES (:id, :policy)" ).arg( authDbTrustTable() ) );
 
 2806  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2807  query.bindValue( QStringLiteral( 
":policy" ), 
static_cast< int >( policy ) );
 
 2809  if ( !authDbStartTransaction() )
 
 2812  if ( !authDbQuery( &query ) )
 
 2815  if ( !authDbCommit() )
 
 2818  QgsDebugMsgLevel( QStringLiteral( 
"Store certificate trust policy SUCCESS for id: %1" ).arg( 
id ), 2 );
 
 2824  QMutexLocker locker( mMutex.get() );
 
 2825  if ( cert.isNull() )
 
 2827    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2834  query.prepare( QStringLiteral( 
"SELECT policy FROM %1 " 
 2835                                 "WHERE id = :id" ).arg( authDbTrustTable() ) );
 
 2837  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2839  if ( !authDbQuery( &query ) )
 
 2843  if ( query.isActive() && query.isSelect() )
 
 2845    if ( query.first() )
 
 2848      QgsDebugMsgLevel( QStringLiteral( 
"Authentication cert trust policy retrieved for id: %1" ).arg( 
id ), 2 );
 
 2852      QgsDebugError( QStringLiteral( 
"Select contains more than one cert trust policy for id: %1" ).arg( 
id ) );
 
 2862  QMutexLocker locker( mMutex.get() );
 
 2863  if ( certs.empty() )
 
 2865    QgsDebugError( QStringLiteral( 
"Passed certificate list has no certs" ) );
 
 2869  for ( 
const auto &cert : certs )
 
 2879  QMutexLocker locker( mMutex.get() );
 
 2880  if ( cert.isNull() )
 
 2882    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2890  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id" ).arg( authDbTrustTable() ) );
 
 2892  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2894  if ( !authDbStartTransaction() )
 
 2897  if ( !authDbQuery( &query ) )
 
 2900  if ( !authDbCommit() )
 
 2903  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED cert trust policy for id: %1" ).arg( 
id ), 2 );
 
 2910  QMutexLocker locker( mMutex.get() );
 
 2911  if ( cert.isNull() )
 
 2921  if ( trustedids.contains( 
id ) )
 
 2925  else if ( untrustedids.contains( 
id ) )
 
 2940  return storeAuthSetting( QStringLiteral( 
"certdefaulttrust" ), 
static_cast< int >( policy ) );
 
 2945  QMutexLocker locker( mMutex.get() );
 
 2946  QVariant policy( 
authSetting( QStringLiteral( 
"certdefaulttrust" ) ) );
 
 2956  QMutexLocker locker( mMutex.get() );
 
 2957  mCertTrustCache.clear();
 
 2960  query.prepare( QStringLiteral( 
"SELECT id, policy FROM %1" ).arg( authDbTrustTable() ) );
 
 2962  if ( !authDbQuery( &query ) )
 
 2964    QgsDebugError( QStringLiteral( 
"Rebuild of cert trust policy cache FAILED" ) );
 
 2968  if ( query.isActive() && query.isSelect() )
 
 2970    while ( query.next() )
 
 2972      QString 
id = query.value( 0 ).toString();
 
 2976      if ( mCertTrustCache.contains( policy ) )
 
 2978        ids = mCertTrustCache.value( policy );
 
 2980      mCertTrustCache.insert( policy, ids << 
id );
 
 2984  QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of cert trust policy cache SUCCEEDED" ), 2 );
 
 2990  QMutexLocker locker( mMutex.get() );
 
 2994  const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
 
 2996  QList<QSslCertificate> trustedcerts;
 
 2997  for ( 
int i = 0; i < certpairs.size(); ++i )
 
 2999    QSslCertificate cert( certpairs.at( i ).second );
 
 3001    if ( trustedids.contains( certid ) )
 
 3004      trustedcerts.append( cert );
 
 3010      trustedcerts.append( cert );
 
 3015  QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
 
 3016  sslconfig.setCaCertificates( trustedcerts );
 
 3017  QSslConfiguration::setDefaultConfiguration( sslconfig );
 
 3019  return trustedcerts;
 
 3024  QMutexLocker locker( mMutex.get() );
 
 3025  if ( trustedCAs.isEmpty() )
 
 3027    if ( mTrustedCaCertsCache.isEmpty() )
 
 3034  const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
 
 3036  QList<QSslCertificate> untrustedCAs;
 
 3037  for ( 
int i = 0; i < certpairs.size(); ++i )
 
 3039    QSslCertificate cert( certpairs.at( i ).second );
 
 3040    if ( !trustedCAs.contains( cert ) )
 
 3042      untrustedCAs.append( cert );
 
 3045  return untrustedCAs;
 
 3050  QMutexLocker locker( mMutex.get() );
 
 3052  QgsDebugMsgLevel( QStringLiteral( 
"Rebuilt trusted cert authorities cache" ), 2 );
 
 3059  QMutexLocker locker( mMutex.get() );
 
 3065  QMutexLocker locker( mMutex.get() );
 
 3068    return passwordHelperWrite( mMasterPass );
 
 3084  for ( 
const auto &authcfg : ids )
 
 3102void QgsAuthManager::writeToConsole( 
const QString &message,
 
 3116      msg += QLatin1String( 
"WARNING: " );
 
 3119      msg += QLatin1String( 
"ERROR: " );
 
 3126  QTextStream out( stdout, QIODevice::WriteOnly );
 
 3127  out << msg << Qt::endl;
 
 3130void QgsAuthManager::tryToStartDbErase()
 
 3132  ++mScheduledDbEraseRequestCount;
 
 3134  int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
 
 3135  if ( mScheduledDbEraseRequestCount >= trycutoff )
 
 3138    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emitting/scheduling canceled" ), 2 );
 
 3143    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest attempt (%1 of %2)" )
 
 3144                      .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ), 2 );
 
 3150    mScheduledDbEraseRequestEmitted = 
true;
 
 3155    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emitted" ), 2 );
 
 3158  QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emit skipped" ), 2 );
 
 3164  QMutexLocker locker( mMutex.get() );
 
 3165  QMapIterator<QThread *, QMetaObject::Connection> iterator( mConnectedThreads );
 
 3166  while ( iterator.hasNext() )
 
 3169    QThread::disconnect( iterator.value() );
 
 3176    qDeleteAll( mAuthMethods );
 
 3179    if ( authConn.isValid() && authConn.isOpen() )
 
 3182  delete mScheduledDbEraseTimer;
 
 3183  mScheduledDbEraseTimer = 
nullptr;
 
 3184  QSqlDatabase::removeDatabase( QStringLiteral( 
"authentication.configs" ) );
 
 3188QString QgsAuthManager::passwordHelperName()
 const 
 3190  return tr( 
"Password Helper" );
 
 3194void QgsAuthManager::passwordHelperLog( 
const QString &msg )
 const 
 3206  QKeychain::DeletePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3208  job.setInsecureFallback( settings.
value( QStringLiteral( 
"password_helper_insecure_fallback" ), 
false, QgsSettings::Section::Auth ).toBool() );
 
 3209  job.setAutoDelete( 
false );
 
 3210  job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
 
 3212  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3217    mPasswordHelperErrorCode = job.error();
 
 3218    mPasswordHelperErrorMessage = tr( 
"Delete password failed: %1." ).arg( job.errorString() );
 
 3229  passwordHelperProcessError();
 
 3233QString QgsAuthManager::passwordHelperRead()
 
 3238  QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3240  job.setInsecureFallback( settings.
value( QStringLiteral( 
"password_helper_insecure_fallback" ), 
false, QgsSettings::Section::Auth ).toBool() );
 
 3241  job.setAutoDelete( 
false );
 
 3242  job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
 
 3244  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3249    mPasswordHelperErrorCode = job.error();
 
 3256    password = job.textData();
 
 3258    if ( password.isEmpty() )
 
 3260      mPasswordHelperErrorCode = QKeychain::EntryNotFound;
 
 3271  passwordHelperProcessError();
 
 3275bool QgsAuthManager::passwordHelperWrite( 
const QString &password )
 
 3277  Q_ASSERT( !password.isEmpty() );
 
 3280  QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3282  job.setInsecureFallback( settings.
value( QStringLiteral( 
"password_helper_insecure_fallback" ), 
false, QgsSettings::Section::Auth ).toBool() );
 
 3283  job.setAutoDelete( 
false );
 
 3284  job.setKey( AUTH_PASSWORD_HELPER_KEY_NAME );
 
 3285  job.setTextData( password );
 
 3287  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3292    mPasswordHelperErrorCode = job.error();
 
 3300    passwordHelperClearErrors();
 
 3305  passwordHelperProcessError();
 
 3313  return settings.
value( QStringLiteral( 
"use_password_helper" ), 
true, QgsSettings::Section::Auth ).toBool();
 
 3319  settings.
setValue( QStringLiteral( 
"use_password_helper" ),  enabled, QgsSettings::Section::Auth );
 
 3320  emit 
messageOut( enabled ? tr( 
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
 
 3322                   tr( 
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
 
 3330  return settings.
value( QStringLiteral( 
"password_helper_logging" ), 
false, QgsSettings::Section::Auth ).toBool();
 
 3336  settings.
setValue( QStringLiteral( 
"password_helper_logging" ),  enabled, QgsSettings::Section::Auth );
 
 3339void QgsAuthManager::passwordHelperClearErrors()
 
 3341  mPasswordHelperErrorCode = QKeychain::NoError;
 
 3342  mPasswordHelperErrorMessage.clear();
 
 3345void QgsAuthManager::passwordHelperProcessError()
 
 3347  if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
 
 3348       mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
 
 3349       mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
 
 3350       mPasswordHelperErrorCode == QKeychain::NotImplemented )
 
 3356    mPasswordHelperErrorMessage = tr( 
"There was an error and integration with your %1 system has been disabled. " 
 3357                                      "You can re-enable it at any time through the \"Utilities\" menu " 
 3358                                      "in the Authentication pane of the options dialog. %2" )
 
 3361  if ( mPasswordHelperErrorCode != QKeychain::NoError )
 
 3367  passwordHelperClearErrors();
 
 3371bool QgsAuthManager::masterPasswordInput()
 
 3377  bool storedPasswordIsValid = 
false;
 
 3383    pass = passwordHelperRead();
 
 3384    if ( ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
 
 3390        storedPasswordIsValid = 
true;
 
 3406  if ( ok && !pass.isEmpty() && mMasterPass != pass )
 
 3411      if ( passwordHelperWrite( pass ) )
 
 3425bool QgsAuthManager::masterPasswordRowsInDb( 
int *rows )
 const 
 3431  query.prepare( QStringLiteral( 
"SELECT Count(*) FROM %1" ).arg( authDbPassTable() ) );
 
 3433  bool ok = authDbQuery( &query );
 
 3434  if ( query.first() )
 
 3436    *rows = query.value( 0 ).toInt();
 
 3448  if ( !masterPasswordRowsInDb( &rows ) )
 
 3450    const char *err = QT_TR_NOOP( 
"Master password: FAILED to access database" );
 
 3456  return ( rows == 1 );
 
 3459bool QgsAuthManager::masterPasswordCheckAgainstDb( 
const QString &compare )
 const 
 3467  query.prepare( QStringLiteral( 
"SELECT salt, hash FROM %1" ).arg( authDbPassTable() ) );
 
 3468  if ( !authDbQuery( &query ) )
 
 3471  if ( !query.first() )
 
 3474  QString salt = query.value( 0 ).toString();
 
 3475  QString hash = query.value( 1 ).toString();
 
 3480bool QgsAuthManager::masterPasswordStoreInDb()
 const 
 3485  QString salt, hash, civ;
 
 3489  query.prepare( QStringLiteral( 
"INSERT INTO %1 (salt, hash, civ) VALUES (:salt, :hash, :civ)" ).arg( authDbPassTable() ) );
 
 3491  query.bindValue( QStringLiteral( 
":salt" ), salt );
 
 3492  query.bindValue( QStringLiteral( 
":hash" ), hash );
 
 3493  query.bindValue( QStringLiteral( 
":civ" ), civ );
 
 3495  if ( !authDbStartTransaction() )
 
 3498  if ( !authDbQuery( &query ) )
 
 3501  if ( !authDbCommit() )
 
 3507bool QgsAuthManager::masterPasswordClearDb()
 
 3513  query.prepare( QStringLiteral( 
"DELETE FROM %1" ).arg( authDbPassTable() ) );
 
 3514  bool res = authDbTransactionQuery( &query );
 
 3520const QString QgsAuthManager::masterPasswordCiv()
 const 
 3526  query.prepare( QStringLiteral( 
"SELECT civ FROM %1" ).arg( authDbPassTable() ) );
 
 3527  if ( !authDbQuery( &query ) )
 
 3530  if ( !query.first() )
 
 3533  return query.value( 0 ).toString();
 
 3538  QStringList configids = QStringList();
 
 3546  if ( !authDbQuery( &query ) )
 
 3551  if ( query.isActive() )
 
 3553    while ( query.next() )
 
 3555      configids << query.value( 0 ).toString();
 
 3561bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
 const 
 3572  if ( !authDbQuery( &query ) )
 
 3575  if ( !query.isActive() || !query.isSelect() )
 
 3577    QgsDebugError( QStringLiteral( 
"Verify password can decrypt configs FAILED, query not active or a select operation" ) );
 
 3585  while ( query.next() )
 
 3590    QString configstring( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 1 ).toString() ) );
 
 3591    if ( configstring.isEmpty() )
 
 3593      QgsDebugError( QStringLiteral( 
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1)" )
 
 3594                     .arg( query.value( 0 ).toString() ) );
 
 3599  QgsDebugMsgLevel( QStringLiteral( 
"Verify password can decrypt configs SUCCESS (checked %1 configs)" ).arg( checked ), 2 );
 
 3603bool QgsAuthManager::reencryptAllAuthenticationConfigs( 
const QString &prevpass, 
const QString &prevciv )
 
 3610  for ( 
const auto &configid : ids )
 
 3612    res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
 
 3617bool QgsAuthManager::reencryptAuthenticationConfig( 
const QString &authcfg, 
const QString &prevpass, 
const QString &prevciv )
 
 3626  query.prepare( QStringLiteral( 
"SELECT config FROM %1 " 
 3629  query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 3631  if ( !authDbQuery( &query ) )
 
 3634  if ( !query.isActive() || !query.isSelect() )
 
 3636    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, query not active or a select operation for authcfg: %2" ).arg( authcfg ) );
 
 3640  if ( query.first() )
 
 3646      QgsDebugError( QStringLiteral( 
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
 
 3653    query.prepare( QStringLiteral( 
"UPDATE %1 " 
 3654                                   "SET config = :config " 
 3657    query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 3658    query.bindValue( QStringLiteral( 
":config" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
 
 3660    if ( !authDbStartTransaction() )
 
 3663    if ( !authDbQuery( &query ) )
 
 3666    if ( !authDbCommit() )
 
 3669    QgsDebugMsgLevel( QStringLiteral( 
"Reencrypt SUCCESS for authcfg: %2" ).arg( authcfg ), 2 );
 
 3674    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find in db authcfg: %2" ).arg( authcfg ) );
 
 3679bool QgsAuthManager::reencryptAllAuthenticationSettings( 
const QString &prevpass, 
const QString &prevciv )
 
 3682  Q_UNUSED( prevpass )
 
 3695  QStringList encryptedsettings;
 
 3696  encryptedsettings << 
"";
 
 3698  for ( 
const auto & sett, std::as_const( encryptedsettings ) )
 
 3705    QSqlQuery query( authDbConnection() );
 
 3707    query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 3708                                   "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 3710    query.bindValue( 
":setting", sett );
 
 3712    if ( !authDbQuery( &query ) )
 
 3715    if ( !query.isActive() || !query.isSelect() )
 
 3717      QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
 
 3721    if ( query.first() )
 
 3727      query.prepare( QStringLiteral( 
"UPDATE %1 " 
 3728                                     "SET value = :value " 
 3729                                     "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 3731      query.bindValue( 
":setting", sett );
 
 3734      if ( !authDbStartTransaction() )
 
 3737      if ( !authDbQuery( &query ) )
 
 3740      if ( !authDbCommit() )
 
 3743      QgsDebugMsgLevel( QStringLiteral( 
"Reencrypt SUCCESS for setting: %2" ).arg( sett ), 2 );
 
 3748      QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
 
 3754      QgsDebugError( QStringLiteral( 
"Select contains more than one for setting: %1" ).arg( sett ) );
 
 3765bool QgsAuthManager::reencryptAllAuthenticationIdentities( 
const QString &prevpass, 
const QString &prevciv )
 
 3772  for ( 
const auto &identid : ids )
 
 3774    res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
 
 3779bool QgsAuthManager::reencryptAuthenticationIdentity(
 
 3780  const QString &identid,
 
 3781  const QString &prevpass,
 
 3782  const QString &prevciv )
 
 3791  query.prepare( QStringLiteral( 
"SELECT key FROM %1 " 
 3792                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 3794  query.bindValue( QStringLiteral( 
":id" ), identid );
 
 3796  if ( !authDbQuery( &query ) )
 
 3799  if ( !query.isActive() || !query.isSelect() )
 
 3801    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, query not active or a select operation for identity id: %2" ).arg( identid ) );
 
 3805  if ( query.first() )
 
 3811      QgsDebugError( QStringLiteral( 
"Select contains more than one for identity id: %1" ).arg( identid ) );
 
 3818    query.prepare( QStringLiteral( 
"UPDATE %1 " 
 3820                                   "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 3822    query.bindValue( QStringLiteral( 
":id" ), identid );
 
 3823    query.bindValue( QStringLiteral( 
":key" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), keystring ) );
 
 3825    if ( !authDbStartTransaction() )
 
 3828    if ( !authDbQuery( &query ) )
 
 3831    if ( !authDbCommit() )
 
 3834    QgsDebugMsgLevel( QStringLiteral( 
"Reencrypt SUCCESS for identity id: %2" ).arg( identid ), 2 );
 
 3839    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find in db identity id: %2" ).arg( identid ) );
 
 3844bool QgsAuthManager::authDbOpen()
 const 
 3850  if ( !authdb.isOpen() )
 
 3852    if ( !authdb.open() )
 
 3854      QgsDebugError( QStringLiteral( 
"Unable to establish database connection\nDatabase: %1\nDriver error: %2\nDatabase error: %3" )
 
 3856                           authdb.lastError().driverText(),
 
 3857                           authdb.lastError().databaseText() ) );
 
 3865bool QgsAuthManager::authDbQuery( QSqlQuery *query )
 const 
 3870  query->setForwardOnly( 
true );
 
 3871  if ( !query->exec() )
 
 3873    const char *err = QT_TR_NOOP( 
"Auth db query exec() FAILED" );
 
 3879  if ( query->lastError().isValid() )
 
 3881    QgsDebugError( QStringLiteral( 
"Auth db query FAILED: %1\nError: %2" )
 
 3882                   .arg( query->executedQuery(),
 
 3883                         query->lastError().text() ) );
 
 3891bool QgsAuthManager::authDbStartTransaction()
 const 
 3898    const char *err = QT_TR_NOOP( 
"Auth db FAILED to start transaction" );
 
 3907bool QgsAuthManager::authDbCommit()
 const 
 3914    const char *err = QT_TR_NOOP( 
"Auth db FAILED to rollback changes" );
 
 3924bool QgsAuthManager::authDbTransactionQuery( QSqlQuery *query )
 const 
 3931    const char *err = QT_TR_NOOP( 
"Auth db FAILED to start transaction" );
 
 3937  bool ok = authDbQuery( query );
 
 3941    const char *err = QT_TR_NOOP( 
"Auth db FAILED to rollback changes" );
 
 3953  for ( 
const auto &cert : certs )
 
 3956                          QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>( source, cert ) );
 
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.
 
void setSslCertificate(const QSslCertificate &cert)
Sets server certificate object.
 
void setSslHostPort(const QString &hostport)
Sets server host:port string.
 
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.
 
const QString configString() const
Configuration as a concatenated string.
 
void loadConfigString(const QString &config=QString())
Load concatenated string into configuration, e.g. from auth database.
 
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 offering an interface to manage the authentication configuration database and to utilize co...
 
bool storeAuthSetting(const QString &key, const QVariant &value, bool encrypt=false)
Store an authentication setting (stored as string via QVariant( value ).toString() )
 
const QString authDatabaseServersTable() const
Name of the authentication database table that stores server exceptions/configs.
 
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.
 
MessageLevel
Message log level (mirrors that of QgsMessageLog, so it can also output there)
 
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.
 
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 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.
 
bool masterPasswordSame(const QString &pass) const
Check whether supplied password is the same as the one already set.
 
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.
 
bool exportAuthenticationConfigsToXml(const QString &filename, const QStringList &authcfgs, const QString &password=QString())
Export authentication configurations to an XML file.
 
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.
 
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.
 
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)
authSetting get an authentication setting (retrieved as string and returned as QVariant( QString ))
 
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
 
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
 
bool rebuildCertTrustCache()
Rebuild certificate authority cache.
 
const QString authenticationDatabasePath() const
The standard authentication database file in ~/.qgis3/ or defined location.
 
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.
 
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.
 
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
 
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.
 
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.
 
static QgsAuthManager * instance()
Enforce singleton pattern.
 
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.
 
void setPasswordHelperLoggingEnabled(bool enabled)
Password helper logging enabled setter.
 
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.
 
const QString authDatabaseConfigTable() const
Name of the authentication database table that stores configs.
 
bool existsCertIdentity(const QString &id)
Check if a certificate identity exists.
 
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,...
 
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.
 
bool passwordHelperEnabled() const
Password helper enabled getter.
 
bool passwordHelperLoggingEnabled() const
Password helper logging enabled getter.
 
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.
 
static const QString AUTH_PASSWORD_HELPER_DISPLAY_NAME
The display name of the password helper (platform dependent)
 
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.
 
bool hasConfigId(const QString &txt) const
Returns whether a string includes an authcfg ID token.
 
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 storeAuthenticationConfig(QgsAuthMethodConfig &mconfig, bool overwrite=false)
Store an authentication config in the database.
 
bool removeCertIdentity(const QString &id)
Remove a certificate identity.
 
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.
 
QString method() const
Textual key of the associated authentication method.
 
const QString uri() const
A URI to auto-select a config when connecting to a resource.
 
void setName(const QString &name)
Sets name of configuration.
 
void setVersion(int version)
Sets version of the configuration.
 
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 name() const
Gets name of configuration.
 
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.
 
int version() const
Gets version of the configuration.
 
void setMethod(const QString &method)
 
void setUri(const QString &uri)
 
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.
 
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.
 
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)
Adds a message to the log instance (and creates it if necessary).
 
Scoped object for logging of the runtime for a single operation or group of operations.
 
This class is a composition of two QSettings instances:
 
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)
Returns true if the specified variant should be considered a NULL value.
 
QHash< QString, QgsAuthMethodConfig > QgsAuthMethodConfigsMap
 
QHash< QString, QgsAuthMethod * > QgsAuthMethodsMap
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)