24#include <QMutexLocker> 
   27#include <QSqlDatabase> 
   36#include <QDomDocument> 
   37#include <QRegularExpression> 
   38#include <QCoreApplication> 
   39#include <QRandomGenerator> 
   44#include <QSslConfiguration> 
   61const QString QgsAuthManager::AUTH_CONFIG_TABLE = QStringLiteral( 
"auth_configs" );
 
   62const QString QgsAuthManager::AUTH_PASS_TABLE = QStringLiteral( 
"auth_pass" );
 
   63const QString QgsAuthManager::AUTH_SETTINGS_TABLE = QStringLiteral( 
"auth_settings" );
 
   64const QString QgsAuthManager::AUTH_IDENTITIES_TABLE = QStringLiteral( 
"auth_identities" );
 
   65const QString QgsAuthManager::AUTH_SERVERS_TABLE = QStringLiteral( 
"auth_servers" );
 
   66const QString QgsAuthManager::AUTH_AUTHORITIES_TABLE = QStringLiteral( 
"auth_authorities" );
 
   67const QString QgsAuthManager::AUTH_TRUST_TABLE = QStringLiteral( 
"auth_trust" );
 
   69const QString QgsAuthManager::AUTH_CFG_REGEX = QStringLiteral( 
"authcfg=([a-z]|[A-Z]|[0-9]){7}" );
 
   72const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_KEY_NAME_BASE( 
"QGIS-Master-Password" );
 
   73const QLatin1String QgsAuthManager::AUTH_PASSWORD_HELPER_FOLDER_NAME( 
"QGIS" );
 
   79#elif defined(Q_OS_WIN) 
   81#elif defined(Q_OS_LINUX) 
   90  QMutexLocker locker( &sMutex );
 
 
  101  mMutex = std::make_unique<QRecursiveMutex>();
 
  102  mMasterPasswordMutex = std::make_unique<QRecursiveMutex>();
 
  104           this, &QgsAuthManager::writeToConsole );
 
 
  117  QMutexLocker locker( mMutex.get() );
 
  122  const QString connectionName = QStringLiteral( 
"authentication.configs:0x%1" ).arg( 
reinterpret_cast<quintptr
>( QThread::currentThread() ), 2 * QT_POINTER_SIZE, 16, QLatin1Char( 
'0' ) );
 
  123  QgsDebugMsgLevel( QStringLiteral( 
"Using auth db connection name: %1 " ).arg( connectionName ), 2 );
 
  124  if ( !QSqlDatabase::contains( connectionName ) )
 
  126    QgsDebugMsgLevel( QStringLiteral( 
"No existing connection, creating a new one" ), 2 );
 
  127    authdb = QSqlDatabase::addDatabase( QStringLiteral( 
"QSQLITE" ), connectionName );
 
  130    if ( QThread::currentThread() != QCoreApplication::instance()->thread() )
 
  132      QgsDebugMsgLevel( QStringLiteral( 
"Scheduled auth db remove on thread close" ), 2 );
 
  142      QMetaObject::Connection connection = connect( QThread::currentThread(), &QThread::finished, QThread::currentThread(), [connectionName, 
this ]
 
  144        QMutexLocker locker( mMutex.get() );
 
  145        QSqlDatabase::removeDatabase( connectionName );
 
  146        mConnectedThreads.remove( QThread::currentThread() );
 
  147      }, Qt::DirectConnection );
 
  149      mConnectedThreads.insert( QThread::currentThread(), connection );
 
  155    authdb = QSqlDatabase::database( connectionName );
 
  159  if ( !authdb.isOpen() )
 
  161    if ( !authdb.open() )
 
  163      QString err = tr( 
"Opening of authentication db FAILED : %1" ).arg( authdb.lastError().text() );
 
 
  174  return initPrivate( pluginPath, authDatabasePath );
 
 
  177bool QgsAuthManager::ensureInitialized()
 const 
  179  static QRecursiveMutex sInitializationMutex;
 
  180  static bool sInitialized = 
false;
 
  182  sInitializationMutex.lock();
 
  185    sInitializationMutex.unlock();
 
  186    return mLazyInitResult;
 
  189  mLazyInitResult = 
const_cast< QgsAuthManager * 
>( this )->initPrivate( mPluginPath, mAuthDatabasePath );
 
  191  sInitializationMutex.unlock();
 
  193  return mLazyInitResult;
 
  196bool QgsAuthManager::initPrivate( 
const QString &pluginPath, 
const QString &authDatabasePath )
 
  205  mQcaInitializer = std::make_unique<QCA::Initializer>( QCA::Practical, 256 );
 
  208  QCA::scanForPlugins();
 
  210  QgsDebugMsgLevel( QStringLiteral( 
"QCA Plugin Diagnostics Context: %1" ).arg( QCA::pluginDiagnosticText() ), 2 );
 
  211  QStringList capabilities;
 
  213  capabilities = QCA::supportedFeatures();
 
  214  QgsDebugMsgLevel( QStringLiteral( 
"QCA supports: %1" ).arg( capabilities.join( 
"," ) ), 2 );
 
  217  if ( !QCA::isSupported( 
"cert", QStringLiteral( 
"qca-ossl" ) ) )
 
  219    mAuthDisabled = 
true;
 
  220    mAuthDisabledMessage = tr( 
"QCA's OpenSSL plugin (qca-ossl) is missing" );
 
  224  QgsDebugMsgLevel( QStringLiteral( 
"Prioritizing qca-ossl over all other QCA providers..." ), 2 );
 
  225  const QCA::ProviderList provds = QCA::providers();
 
  227  for ( QCA::Provider *p : provds )
 
  229    QString pn = p->name();
 
  231    if ( pn != QLatin1String( 
"qca-ossl" ) )
 
  233      pr = QCA::providerPriority( pn ) + 1;
 
  235    QCA::setProviderPriority( pn, pr );
 
  236    prlist << QStringLiteral( 
"%1:%2" ).arg( pn ).arg( QCA::providerPriority( pn ) );
 
  238  QgsDebugMsgLevel( QStringLiteral( 
"QCA provider priorities: %1" ).arg( prlist.join( 
", " ) ), 2 );
 
  245  QgsDebugMsgLevel( QStringLiteral( 
"Authentication methods found: %1" ).arg( methods.join( 
", " ) ), 2 );
 
  247  if ( methods.isEmpty() )
 
  249    mAuthDisabled = 
true;
 
  250    mAuthDisabledMessage = tr( 
"No authentication method plugins found" );
 
  256    mAuthDisabled = 
true;
 
  257    mAuthDisabledMessage = tr( 
"No authentication method plugins could be loaded" );
 
  261  mAuthDbPath = QDir::cleanPath( authDatabasePath );
 
  265  QFileInfo dbdirinfo( dbinfo.path() );
 
  266  QgsDebugMsgLevel( QStringLiteral( 
"Auth db directory path: %1" ).arg( dbdirinfo.filePath() ), 2 );
 
  268  if ( !dbdirinfo.exists() )
 
  270    QgsDebugMsgLevel( QStringLiteral( 
"Auth db directory path does not exist, making path: %1" ).arg( dbdirinfo.filePath() ), 2 );
 
  271    if ( !QDir().mkpath( dbdirinfo.filePath() ) )
 
  273      const char *err = QT_TR_NOOP( 
"Auth db directory path could not be created" );
 
  280  if ( dbinfo.exists() )
 
  282    if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
 
  284      const char *err = QT_TR_NOOP( 
"Auth db is not readable or writable by user" );
 
  289    if ( dbinfo.size() > 0 )
 
  293      if ( !createCertTables() )
 
  303      const char *passenv = 
"QGIS_AUTH_PASSWORD_FILE";
 
  306        QString passpath( getenv( passenv ) );
 
  315        QFile passfile( passpath );
 
  316        if ( passfile.exists() && passfile.open( QIODevice::ReadOnly | QIODevice::Text ) )
 
  318          QTextStream passin( &passfile );
 
  319          while ( !passin.atEnd() )
 
  321            masterpass = passin.readLine();
 
  326        if ( !masterpass.isEmpty() )
 
  330            QgsDebugMsgLevel( QStringLiteral( 
"Authentication master password set from QGIS_AUTH_PASSWORD_FILE" ), 2 );
 
  334            QgsDebugError( 
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to set password using: " + passpath );
 
  340          QgsDebugError( 
"QGIS_AUTH_PASSWORD_FILE set, but FAILED to read password from: " + passpath );
 
  350    QgsDebugMsgLevel( QStringLiteral( 
"Auth db does not exist: creating through QSqlDatabase initial connection" ), 2 );
 
  352    if ( !createConfigTables() )
 
  355    if ( !createCertTables() )
 
  368  mPluginPath = pluginPath;
 
  369  mAuthDatabasePath = authDatabasePath;
 
 
  372bool QgsAuthManager::createConfigTables()
 
  374  QMutexLocker locker( mMutex.get() );
 
  378    const char *err = QT_TR_NOOP( 
"Auth db could not be created and opened" );
 
  389  qstr = QStringLiteral( 
"CREATE TABLE %1 (\n" 
  390                         "    'salt' TEXT NOT NULL,\n" 
  391                         "    'civ' TEXT NOT NULL\n" 
  392                         ", 'hash' TEXT  NOT NULL);" ).arg( authDbPassTable() );
 
  393  query.prepare( qstr );
 
  394  if ( !authDbQuery( &query ) )
 
  398  qstr = QStringLiteral( 
"CREATE TABLE %1 (\n" 
  399                         "    'id' TEXT NOT NULL,\n" 
  400                         "    'name' TEXT NOT NULL,\n" 
  402                         "    'type' TEXT NOT NULL,\n" 
  403                         "    'version' INTEGER NOT NULL\n" 
  405  query.prepare( qstr );
 
  406  if ( !authDbQuery( &query ) )
 
  411  query.prepare( qstr );
 
  412  if ( !authDbQuery( &query ) )
 
  417  query.prepare( qstr );
 
  418  if ( !authDbQuery( &query ) )
 
  425bool QgsAuthManager::createCertTables()
 
  427  QMutexLocker locker( mMutex.get() );
 
  436  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  437                         "    'setting' TEXT NOT NULL\n" 
  438                         ", 'value' TEXT);" ).arg( authDbSettingsTable() );
 
  439  query.prepare( qstr );
 
  440  if ( !authDbQuery( &query ) )
 
  445  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  446                         "    'id' TEXT NOT NULL,\n" 
  447                         "    'key' TEXT NOT NULL\n" 
  448                         ", 'cert' TEXT  NOT NULL);" ).arg( authDbIdentitiesTable() );
 
  449  query.prepare( qstr );
 
  450  if ( !authDbQuery( &query ) )
 
  454  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbIdentitiesTable() );
 
  455  query.prepare( qstr );
 
  456  if ( !authDbQuery( &query ) )
 
  461  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  462                         "    'id' TEXT NOT NULL,\n" 
  463                         "    'host' TEXT NOT NULL,\n" 
  466  query.prepare( qstr );
 
  467  if ( !authDbQuery( &query ) )
 
  471  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'host_index' on %1 (host ASC);" ).arg( 
authDatabaseServersTable() );
 
  472  query.prepare( qstr );
 
  473  if ( !authDbQuery( &query ) )
 
  478  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  479                         "    'id' TEXT NOT NULL\n" 
  480                         ", 'cert' TEXT  NOT NULL);" ).arg( authDbAuthoritiesTable() );
 
  481  query.prepare( qstr );
 
  482  if ( !authDbQuery( &query ) )
 
  486  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbAuthoritiesTable() );
 
  487  query.prepare( qstr );
 
  488  if ( !authDbQuery( &query ) )
 
  492  qstr = QStringLiteral( 
"CREATE TABLE IF NOT EXISTS %1 (\n" 
  493                         "    'id' TEXT NOT NULL\n" 
  494                         ", 'policy' TEXT  NOT NULL);" ).arg( authDbTrustTable() );
 
  495  query.prepare( qstr );
 
  496  if ( !authDbQuery( &query ) )
 
  500  qstr = QStringLiteral( 
"CREATE UNIQUE INDEX IF NOT EXISTS 'id_index' on %1 (id ASC);" ).arg( authDbTrustTable() );
 
  501  query.prepare( qstr );
 
  502  if ( !authDbQuery( &query ) )
 
  515    QgsDebugError( QStringLiteral( 
"Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" ) );
 
  517  return mAuthDisabled;
 
 
  524  return tr( 
"Authentication system is DISABLED:\n%1" ).arg( mAuthDisabledMessage );
 
 
  531  QMutexLocker locker( mMasterPasswordMutex.get() );
 
  535  if ( mScheduledDbErase )
 
  538  if ( mMasterPass.isEmpty() )
 
  540    QgsDebugMsgLevel( QStringLiteral( 
"Master password is not yet set by user" ), 2 );
 
  541    if ( !masterPasswordInput() )
 
  543      QgsDebugMsgLevel( QStringLiteral( 
"Master password input canceled by user" ), 2 );
 
  557  QgsDebugMsgLevel( QStringLiteral( 
"Master password is set and verified" ), 2 );
 
 
  565  QMutexLocker locker( mMutex.get() );
 
  569  if ( mScheduledDbErase )
 
  573  QString prevpass = QString( mMasterPass );
 
  577    mMasterPass = prevpass;
 
  578    const char *err = QT_TR_NOOP( 
"Master password set: FAILED to verify, reset to previous" );
 
  584  QgsDebugMsgLevel( QStringLiteral( 
"Master password set: SUCCESS%1" ).arg( verify ? 
" and verified" : 
"" ), 2 );
 
 
  596  if ( !masterPasswordRowsInDb( &rows ) )
 
  598    const char *err = QT_TR_NOOP( 
"Master password: FAILED to access database" );
 
  606  QgsDebugMsgLevel( QStringLiteral( 
"Master password: %1 rows in database" ).arg( rows ), 2 );
 
  610    const char *err = QT_TR_NOOP( 
"Master password: FAILED to find just one master password record in database" );
 
  617  else if ( rows == 1 )
 
  619    if ( !masterPasswordCheckAgainstDb( compare ) )
 
  621      if ( compare.isNull() ) 
 
  623        const char *err = QT_TR_NOOP( 
"Master password: FAILED to verify against hash in database" );
 
  632      if ( mPassTries >= 5 )
 
  634        mAuthDisabled = 
true;
 
  635        const char *err = QT_TR_NOOP( 
"Master password: failed 5 times authentication system DISABLED" );
 
  643      QgsDebugMsgLevel( QStringLiteral( 
"Master password: verified against hash in database" ), 2 );
 
  644      if ( compare.isNull() )
 
  648  else if ( compare.isNull() ) 
 
  650    if ( !masterPasswordStoreInDb() )
 
  652      const char *err = QT_TR_NOOP( 
"Master password: hash FAILED to be stored in database" );
 
  661      QgsDebugMsgLevel( QStringLiteral( 
"Master password: hash stored in database" ), 2 );
 
  664    if ( !masterPasswordCheckAgainstDb() )
 
  666      const char *err = QT_TR_NOOP( 
"Master password: FAILED to verify against hash in database" );
 
  676      QgsDebugMsgLevel( QStringLiteral( 
"Master password: verified against hash in database" ), 2 );
 
 
  688  return !mMasterPass.isEmpty();
 
 
  695  return mMasterPass == pass;
 
 
  699    bool keepbackup, QString *backuppath )
 
  715  QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: backed up current database" ), 2 );
 
  721  QString prevpass = QString( mMasterPass );
 
  722  QString prevciv = QString( masterPasswordCiv() );
 
  728  if ( ok && !masterPasswordClearDb() )
 
  731    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not clear current password from database" );
 
  737    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: cleared current password from database" ), 2 );
 
  744  if ( ok && !masterPasswordStoreInDb() )
 
  747    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not store new password in database" );
 
  753    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: stored new password in database" ), 2 );
 
  760    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not verify new password in database" );
 
  766  if ( ok && !reencryptAllAuthenticationConfigs( prevpass, prevciv ) )
 
  769    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt configs in database" );
 
  775    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: re-encrypted configs in database" ), 2 );
 
  779  if ( ok && !verifyPasswordCanDecryptConfigs() )
 
  782    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not verify password can decrypt re-encrypted configs" );
 
  787  if ( ok && !reencryptAllAuthenticationSettings( prevpass, prevciv ) )
 
  790    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt settings in database" );
 
  795  if ( ok && !reencryptAllAuthenticationIdentities( prevpass, prevciv ) )
 
  798    const char *err = QT_TR_NOOP( 
"Master password reset FAILED: could not re-encrypt identities in database" );
 
  808    QString errdbbackup( dbbackup );
 
  809    errdbbackup.replace( QLatin1String( 
".db" ), QLatin1String( 
"_ERROR.db" ) );
 
  811    QgsDebugError( QStringLiteral( 
"Master password reset FAILED: backed up failed db at %1" ).arg( errdbbackup ) );
 
  815    mMasterPass = prevpass;
 
  817    QgsDebugError( QStringLiteral( 
"Master password reset FAILED: reinstated previous password and database" ) );
 
  821      *backuppath = errdbbackup;
 
  827  if ( !keepbackup && !QFile::remove( dbbackup ) )
 
  829    const char *err = QT_TR_NOOP( 
"Master password reset: could not remove old database backup" );
 
  837    QgsDebugMsgLevel( QStringLiteral( 
"Master password reset: backed up previous db at %1" ).arg( dbbackup ), 2 );
 
  839      *backuppath = dbbackup;
 
 
  851  mScheduledDbErase = scheduleErase;
 
  853  mScheduledDbEraseRequestEmitted = 
false;
 
  854  mScheduledDbEraseRequestCount = 0;
 
  858    if ( !mScheduledDbEraseTimer )
 
  860      mScheduledDbEraseTimer = 
new QTimer( 
this );
 
  861      connect( mScheduledDbEraseTimer, &QTimer::timeout, 
this, &QgsAuthManager::tryToStartDbErase );
 
  862      mScheduledDbEraseTimer->start( mScheduledDbEraseRequestWait * 1000 );
 
  864    else if ( !mScheduledDbEraseTimer->isActive() )
 
  866      mScheduledDbEraseTimer->start();
 
  871    if ( mScheduledDbEraseTimer && mScheduledDbEraseTimer->isActive() )
 
  872      mScheduledDbEraseTimer->stop();
 
 
  881  qDeleteAll( mAuthMethods );
 
  882  mAuthMethods.clear();
 
  884  for ( 
const auto &authMethodKey : methods )
 
  889  return !mAuthMethods.isEmpty();
 
 
  901  QTimer::singleShot( 3, &loop, &QEventLoop::quit );
 
  907    for ( 
int i = 0; i < len; i++ )
 
  909      switch ( QRandomGenerator::system()->generate() % 2 )
 
  912          id += 
static_cast<char>( 
'0' + QRandomGenerator::system()->generate() % 10 );
 
  915          id += 
static_cast<char>( 
'a' + QRandomGenerator::system()->generate() % 26 );
 
  919    if ( !configids.contains( 
id ) )
 
  924  QgsDebugMsgLevel( QStringLiteral( 
"Generated unique ID: %1" ).arg( 
id ), 2 );
 
 
  937    const char *err = QT_TR_NOOP( 
"Config ID is empty" );
 
  943  return !configids.contains( 
id );
 
 
  948  const thread_local QRegularExpression authCfgRegExp( AUTH_CFG_REGEX );
 
  949  return txt.indexOf( authCfgRegExp ) != -1;
 
 
  956  QMutexLocker locker( mMutex.get() );
 
  957  QStringList providerAuthMethodsKeys;
 
  958  if ( !dataprovider.isEmpty() )
 
  969  query.prepare( QStringLiteral( 
"SELECT id, name, uri, type, version FROM %1" ).arg( 
authDatabaseConfigTable() ) );
 
  971  if ( !authDbQuery( &query ) )
 
  976  if ( query.isActive() && query.isSelect() )
 
  978    while ( query.next() )
 
  980      QString authcfg = query.value( 0 ).toString();
 
  982      config.
setId( authcfg );
 
  983      config.
setName( query.value( 1 ).toString() );
 
  984      config.
setUri( query.value( 2 ).toString() );
 
  985      config.
setMethod( query.value( 3 ).toString() );
 
  986      config.
setVersion( query.value( 4 ).toInt() );
 
  988      if ( !dataprovider.isEmpty() && !providerAuthMethodsKeys.contains( config.
method() ) )
 
  993      baseConfigs.insert( authcfg, config );
 
 
 1001  ensureInitialized();
 
 1003  QMutexLocker locker( mMutex.get() );
 
 1010  if ( !authDbQuery( &query ) )
 
 1015  if ( query.isActive() )
 
 1017    QgsDebugMsgLevel( QStringLiteral( 
"Syncing existing auth config and their auth methods" ), 2 );
 
 1018    mConfigAuthMethods.clear();
 
 1019    QStringList cfgmethods;
 
 1020    while ( query.next() )
 
 1022      mConfigAuthMethods.insert( query.value( 0 ).toString(),
 
 1023                                 query.value( 1 ).toString() );
 
 1024      cfgmethods << QStringLiteral( 
"%1=%2" ).arg( query.value( 0 ).toString(), query.value( 1 ).toString() );
 
 1026    QgsDebugMsgLevel( QStringLiteral( 
"Stored auth config/methods:\n%1" ).arg( cfgmethods.join( 
", " ) ), 2 );
 
 
 1032  ensureInitialized();
 
 1037  if ( !mConfigAuthMethods.contains( authcfg ) )
 
 1039    QgsDebugError( QStringLiteral( 
"No config auth method found in database for authcfg: %1" ).arg( authcfg ) );
 
 1043  QString authMethodKey = mConfigAuthMethods.value( authcfg );
 
 
 1050  ensureInitialized();
 
 1055  return mConfigAuthMethods.value( authcfg, QString() );
 
 
 1061  ensureInitialized();
 
 
 1068  ensureInitialized();
 
 1070  if ( !mAuthMethods.contains( authMethodKey ) )
 
 1072    QgsDebugError( QStringLiteral( 
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
 
 1076  return mAuthMethods.value( authMethodKey );
 
 
 1081  ensureInitialized();
 
 1083  if ( !mAuthMethods.contains( authMethodKey ) )
 
 1085    QgsDebugError( QStringLiteral( 
"No auth method registered for auth method key: %1" ).arg( authMethodKey ) );
 
 
 1095  ensureInitialized();
 
 1097  if ( dataprovider.isEmpty() )
 
 1099    return mAuthMethods;
 
 1103  QgsAuthMethodsMap::const_iterator i = mAuthMethods.constBegin();
 
 1104  while ( i != mAuthMethods.constEnd() )
 
 1107         && ( i.value()->supportedDataProviders().contains( QStringLiteral( 
"all" ) )
 
 1108              || i.value()->supportedDataProviders().contains( dataprovider ) ) )
 
 1110      filteredmap.insert( i.key(), i.value() );
 
 
 1118QWidget *QgsAuthManager::authMethodEditWidget( 
const QString &authMethodKey, QWidget *parent )
 
 1120  ensureInitialized();
 
 1124    return method->editWidget( parent );
 
 1132  ensureInitialized();
 
 1135    return QgsAuthMethod::Expansions();
 
 1142  return QgsAuthMethod::Expansions();
 
 
 1147  ensureInitialized();
 
 1149  QMutexLocker locker( mMutex.get() );
 
 1156    const char *err = QT_TR_NOOP( 
"Store config: FAILED because config is invalid" );
 
 1162  QString uid = mconfig.
id();
 
 1163  bool passedinID = !uid.isEmpty();
 
 1164  if ( uid.isEmpty() )
 
 1172      const char *err = QT_TR_NOOP( 
"Store config: FAILED because pre-defined config ID %1 is not unique" );
 
 1183  if ( configstring.isEmpty() )
 
 1185    const char *err = QT_TR_NOOP( 
"Store config: FAILED because config string is empty" );
 
 1191  QgsDebugMsgLevel( QStringLiteral( 
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ), 2 );
 
 1194  QgsDebugMsgLevel( QStringLiteral( 
"type: %1" ).arg( config.method() ), 2 );
 
 1195  QgsDebugMsgLevel( QStringLiteral( 
"version: %1" ).arg( config.version() ), 2 );
 
 1200  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, name, uri, type, version, config) " 
 1203  query.bindValue( QStringLiteral( 
":id" ), uid );
 
 1204  query.bindValue( QStringLiteral( 
":name" ), mconfig.
name() );
 
 1205  query.bindValue( QStringLiteral( 
":uri" ), mconfig.
uri() );
 
 1206  query.bindValue( QStringLiteral( 
":type" ), mconfig.
method() );
 
 1207  query.bindValue( QStringLiteral( 
":version" ), mconfig.
version() );
 
 1208  query.bindValue( QStringLiteral( 
":config" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
 
 1210  if ( !authDbStartTransaction() )
 
 1213  if ( !authDbQuery( &query ) )
 
 1216  if ( !authDbCommit() )
 
 1221    mconfig.
setId( uid );
 
 1225  QgsDebugMsgLevel( QStringLiteral( 
"Store config SUCCESS for authcfg: %1" ).arg( uid ), 2 );
 
 
 1231  ensureInitialized();
 
 1233  QMutexLocker locker( mMutex.get() );
 
 1238  if ( !config.
isValid( 
true ) )
 
 1240    const char *err = QT_TR_NOOP( 
"Update config: FAILED because config is invalid" );
 
 1247  if ( configstring.isEmpty() )
 
 1249    const char *err = QT_TR_NOOP( 
"Update config: FAILED because config is empty" );
 
 1256  QgsDebugMsgLevel( QStringLiteral( 
"authDbConfigTable(): %1" ).arg( authDbConfigTable() ), 2 );
 
 1266  if ( !query.prepare( QStringLiteral( 
"UPDATE %1 " 
 1267                                       "SET name = :name, uri = :uri, type = :type, version = :version, config = :config " 
 1270    const char *err = QT_TR_NOOP( 
"Update config: FAILED to prepare query" );
 
 1276  query.bindValue( QStringLiteral( 
":id" ), config.
id() );
 
 1277  query.bindValue( QStringLiteral( 
":name" ), config.
name() );
 
 1278  query.bindValue( QStringLiteral( 
":uri" ), config.
uri() );
 
 1279  query.bindValue( QStringLiteral( 
":type" ), config.
method() );
 
 1280  query.bindValue( QStringLiteral( 
":version" ), config.
version() );
 
 1281  query.bindValue( QStringLiteral( 
":config" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
 
 1283  if ( !authDbStartTransaction() )
 
 1286  if ( !authDbQuery( &query ) )
 
 1289  if ( !authDbCommit() )
 
 1297  QgsDebugMsgLevel( QStringLiteral( 
"Update config SUCCESS for authcfg: %1" ).arg( config.
id() ), 2 );
 
 
 1304  ensureInitialized();
 
 1312  QMutexLocker locker( mMutex.get() );
 
 1317    query.prepare( QStringLiteral( 
"SELECT id, name, uri, type, version, config FROM %1 " 
 1322    query.prepare( QStringLiteral( 
"SELECT id, name, uri, type, version FROM %1 " 
 1326  query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 1328  if ( !authDbQuery( &query ) )
 
 1333  if ( query.isActive() && query.isSelect() )
 
 1335    if ( query.first() )
 
 1337      mconfig.
setId( query.value( 0 ).toString() );
 
 1338      mconfig.
setName( query.value( 1 ).toString() );
 
 1339      mconfig.
setUri( query.value( 2 ).toString() );
 
 1340      mconfig.
setMethod( query.value( 3 ).toString() );
 
 1341      mconfig.
setVersion( query.value( 4 ).toInt() );
 
 1356        QgsDebugError( QStringLiteral( 
"Update of authcfg %1 FAILED for auth method %2" ).arg( authcfg, authMethodKey ) );
 
 1359      QgsDebugMsgLevel( QStringLiteral( 
"Load %1 config SUCCESS for authcfg: %2" ).arg( full ? 
"full" : 
"base", authcfg ), 2 );
 
 1364      QgsDebugError( QStringLiteral( 
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
 
 
 1374  ensureInitialized();
 
 1376  QMutexLocker locker( mMutex.get() );
 
 1380  if ( authcfg.isEmpty() )
 
 1387  query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 1389  if ( !authDbStartTransaction() )
 
 1392  if ( !authDbQuery( &query ) )
 
 1395  if ( !authDbCommit() )
 
 1402  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED config for authcfg: %1" ).arg( authcfg ), 2 );
 
 
 1409  ensureInitialized();
 
 1411  if ( filename.isEmpty() )
 
 1414  QDomDocument document( QStringLiteral( 
"qgis_authentication" ) );
 
 1415  QDomElement root = document.createElement( QStringLiteral( 
"qgis_authentication" ) );
 
 1416  document.appendChild( root );
 
 1419  if ( !password.isEmpty() )
 
 1424    root.setAttribute( QStringLiteral( 
"salt" ), salt );
 
 1425    root.setAttribute( QStringLiteral( 
"hash" ), hash );
 
 1426    root.setAttribute( QStringLiteral( 
"civ" ), civ );
 
 1429  QDomElement configurations = document.createElement( QStringLiteral( 
"configurations" ) );
 
 1430  for ( 
const QString &authcfg : authcfgs )
 
 1437      authMethodConfig.
writeXml( configurations, document );
 
 1440  if ( !password.isEmpty() )
 
 1442    QString configurationsString;
 
 1443    QTextStream ts( &configurationsString );
 
 1444#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
 1445    ts.setCodec( 
"UTF-8" );
 
 1447    configurations.save( ts, 2 );
 
 1448    root.appendChild( document.createTextNode( 
QgsAuthCrypto::encrypt( password, civ, configurationsString ) ) );
 
 1452    root.appendChild( configurations );
 
 1455  QFile file( filename );
 
 1456  if ( !file.open( QFile::WriteOnly | QIODevice::Truncate ) )
 
 1459  QTextStream ts( &file );
 
 1460#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
 1461  ts.setCodec( 
"UTF-8" );
 
 1463  document.save( ts, 2 );
 
 
 1470  ensureInitialized();
 
 1472  QFile file( filename );
 
 1473  if ( !file.open( QFile::ReadOnly ) )
 
 1478  QDomDocument document( QStringLiteral( 
"qgis_authentication" ) );
 
 1479  if ( !document.setContent( &file ) )
 
 1486  QDomElement root = document.documentElement();
 
 1487  if ( root.tagName() != QLatin1String( 
"qgis_authentication" ) )
 
 1492  QDomElement configurations;
 
 1493  if ( root.hasAttribute( QStringLiteral( 
"salt" ) ) )
 
 1495    QString salt = root.attribute( QStringLiteral( 
"salt" ) );
 
 1496    QString hash = root.attribute( QStringLiteral( 
"hash" ) );
 
 1497    QString civ = root.attribute( QStringLiteral( 
"civ" ) );
 
 1502    configurations = document.firstChild().toElement();
 
 1506    configurations = root.firstChildElement( QStringLiteral( 
"configurations" ) );
 
 1509  QDomElement configuration = configurations.firstChildElement();
 
 1510  while ( !configuration.isNull() )
 
 1513    authMethodConfig.
readXml( configuration );
 
 1516    configuration = configuration.nextSiblingElement();
 
 
 1523  ensureInitialized();
 
 1525  QMutexLocker locker( mMutex.get() );
 
 1531  bool res = authDbTransactionQuery( &query );
 
 1539  QgsDebugMsgLevel( QStringLiteral( 
"Remove configs from database: %1" ).arg( res ? 
"SUCCEEDED" : 
"FAILED" ), 2 );
 
 
 1546  ensureInitialized();
 
 1548  QMutexLocker locker( mMutex.get() );
 
 1551    const char *err = QT_TR_NOOP( 
"No authentication database found" );
 
 1559  if ( authConn.isValid() && authConn.isOpen() )
 
 1563  QString datestamp( QDateTime::currentDateTime().toString( QStringLiteral( 
"yyyy-MM-dd-hhmmss" ) ) );
 
 1565  dbbackup.replace( QLatin1String( 
".db" ), QStringLiteral( 
"_%1.db" ).arg( datestamp ) );
 
 1569    const char *err = QT_TR_NOOP( 
"Could not back up authentication database" );
 
 1576    *backuppath = dbbackup;
 
 1578  QgsDebugMsgLevel( QStringLiteral( 
"Backed up auth database at %1" ).arg( dbbackup ), 2 );
 
 
 1584  ensureInitialized();
 
 1586  QMutexLocker locker( mMutex.get() );
 
 1596  if ( backuppath && !dbbackup.isEmpty() )
 
 1597    *backuppath = dbbackup;
 
 1600  if ( dbinfo.exists() )
 
 1602    if ( !dbinfo.permission( QFile::ReadOwner | QFile::WriteOwner ) )
 
 1604      const char *err = QT_TR_NOOP( 
"Auth db is not readable or writable by user" );
 
 1612    const char *err = QT_TR_NOOP( 
"No authentication database found" );
 
 1620    const char *err = QT_TR_NOOP( 
"Authentication database could not be deleted" );
 
 1626  mMasterPass = QString();
 
 1628  QgsDebugMsgLevel( QStringLiteral( 
"Creating Auth db through QSqlDatabase initial connection" ), 2 );
 
 1631  if ( !authConn.isValid() || !authConn.isOpen() )
 
 1633    const char *err = QT_TR_NOOP( 
"Authentication database could not be initialized" );
 
 1639  if ( !createConfigTables() )
 
 1641    const char *err = QT_TR_NOOP( 
"FAILED to create auth database config tables" );
 
 1647  if ( !createCertTables() )
 
 1649    const char *err = QT_TR_NOOP( 
"FAILED to create auth database cert tables" );
 
 
 1668    const QString &dataprovider )
 
 1670  ensureInitialized();
 
 1680      QgsDebugError( QStringLiteral( 
"Network request updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 
 1695    const QString &dataprovider )
 
 1697  ensureInitialized();
 
 1707      QgsDebugError( QStringLiteral( 
"Network reply updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 
 1723    const QString &dataprovider )
 
 1725  ensureInitialized();
 
 1735      QgsDebugError( QStringLiteral( 
"Data source URI updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 
 1752  ensureInitialized();
 
 1762      QgsDebugError( QStringLiteral( 
"Proxy updating not supported by authcfg: %1" ).arg( authcfg ) );
 
 1771    QgsDebugMsgLevel( QStringLiteral( 
"Proxy updated successfully from authcfg: %1" ).arg( authcfg ), 2 );
 
 
 1780  ensureInitialized();
 
 1782  QMutexLocker locker( mMutex.get() );
 
 1783  if ( key.isEmpty() )
 
 1786  QString storeval( value.toString() );
 
 1802  query.prepare( QStringLiteral( 
"INSERT INTO %1 (setting, value) " 
 1803                                 "VALUES (:setting, :value)" ).arg( authDbSettingsTable() ) );
 
 1805  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1806  query.bindValue( QStringLiteral( 
":value" ), storeval );
 
 1808  if ( !authDbStartTransaction() )
 
 1811  if ( !authDbQuery( &query ) )
 
 1814  if ( !authDbCommit() )
 
 1817  QgsDebugMsgLevel( QStringLiteral( 
"Store setting SUCCESS for key: %1" ).arg( key ), 2 );
 
 
 1823  ensureInitialized();
 
 1825  QMutexLocker locker( mMutex.get() );
 
 1826  if ( key.isEmpty() )
 
 1832  QVariant value = defaultValue;
 
 1834  query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 1835                                 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 1837  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1839  if ( !authDbQuery( &query ) )
 
 1842  if ( query.isActive() && query.isSelect() )
 
 1844    if ( query.first() )
 
 1848        value = QVariant( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ) );
 
 1852        value = query.value( 0 );
 
 1854      QgsDebugMsgLevel( QStringLiteral( 
"Authentication setting retrieved for key: %1" ).arg( key ), 2 );
 
 1858      QgsDebugError( QStringLiteral( 
"Select contains more than one for setting key: %1" ).arg( key ) );
 
 
 1868  ensureInitialized();
 
 1870  QMutexLocker locker( mMutex.get() );
 
 1871  if ( key.isEmpty() )
 
 1875  query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 1876                                 "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 1878  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1880  if ( !authDbQuery( &query ) )
 
 1884  if ( query.isActive() && query.isSelect() )
 
 1886    if ( query.first() )
 
 1888      QgsDebugMsgLevel( QStringLiteral( 
"Authentication setting exists for key: %1" ).arg( key ), 2 );
 
 1893      QgsDebugError( QStringLiteral( 
"Select contains more than one for setting key: %1" ).arg( key ) );
 
 
 1903  ensureInitialized();
 
 1905  QMutexLocker locker( mMutex.get() );
 
 1906  if ( key.isEmpty() )
 
 1911  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 1913  query.bindValue( QStringLiteral( 
":setting" ), key );
 
 1915  if ( !authDbStartTransaction() )
 
 1918  if ( !authDbQuery( &query ) )
 
 1921  if ( !authDbCommit() )
 
 1924  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED setting for key: %1" ).arg( key ), 2 );
 
 
 1938  QMutexLocker locker( mMutex.get() );
 
 1944  mCustomConfigByHostCache.clear();
 
 1945  mHasCheckedIfCustomConfigByHostExists = 
false;
 
 1948    QgsDebugError( QStringLiteral( 
"Init of SSL caches FAILED" ) );
 
 
 1954  ensureInitialized();
 
 1956  QMutexLocker locker( mMutex.get() );
 
 1957  if ( cert.isNull() )
 
 1959    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 1964    QgsDebugError( QStringLiteral( 
"Passed private key is null" ) );
 
 1974  QString certpem( cert.toPem() );
 
 1978  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, key, cert) " 
 1979                                 "VALUES (:id, :key, :cert)" ).arg( authDbIdentitiesTable() ) );
 
 1981  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 1982  query.bindValue( QStringLiteral( 
":key" ), keypem );
 
 1983  query.bindValue( QStringLiteral( 
":cert" ), certpem );
 
 1985  if ( !authDbStartTransaction() )
 
 1988  if ( !authDbQuery( &query ) )
 
 1991  if ( !authDbCommit() )
 
 1994  QgsDebugMsgLevel( QStringLiteral( 
"Store certificate identity SUCCESS for id: %1" ).arg( 
id ), 2 );
 
 
 2000  ensureInitialized();
 
 2002  QMutexLocker locker( mMutex.get() );
 
 2003  QSslCertificate emptycert;
 
 2004  QSslCertificate cert;
 
 2009  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 2010                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 2012  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2014  if ( !authDbQuery( &query ) )
 
 2017  if ( query.isActive() && query.isSelect() )
 
 2019    if ( query.first() )
 
 2021      cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
 
 2022      QgsDebugMsgLevel( QStringLiteral( 
"Certificate identity retrieved for id: %1" ).arg( 
id ), 2 );
 
 2026      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate identity for id: %1" ).arg( 
id ) );
 
 
 2036  ensureInitialized();
 
 2038  QMutexLocker locker( mMutex.get() );
 
 2039  QPair<QSslCertificate, QSslKey> bundle;
 
 2047  query.prepare( QStringLiteral( 
"SELECT key, cert FROM %1 " 
 2048                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 2050  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2052  if ( !authDbQuery( &query ) )
 
 2055  if ( query.isActive() && query.isSelect() )
 
 2057    QSslCertificate cert;
 
 2059    if ( query.first() )
 
 2061      key = QSslKey( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 0 ).toString() ).toLatin1(),
 
 2062                     QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey );
 
 2065        const char *err = QT_TR_NOOP( 
"Retrieve certificate identity bundle: FAILED to create private key" );
 
 2070      cert = QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
 
 2071      if ( cert.isNull() )
 
 2073        const char *err = QT_TR_NOOP( 
"Retrieve certificate identity bundle: FAILED to create certificate" );
 
 2078      QgsDebugMsgLevel( QStringLiteral( 
"Certificate identity bundle retrieved for id: %1" ).arg( 
id ), 2 );
 
 2082      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate identity for id: %1" ).arg( 
id ) );
 
 2086    bundle = qMakePair( cert, key );
 
 
 2093  ensureInitialized();
 
 2095  QMutexLocker locker( mMutex.get() );
 
 2099    return QStringList() << QString( bundle.first.toPem() ) << QString( bundle.second.toPem() );
 
 2101  return QStringList();
 
 
 2106  ensureInitialized();
 
 2108  QMutexLocker locker( mMutex.get() );
 
 2109  QList<QSslCertificate> certs;
 
 2112  query.prepare( QStringLiteral( 
"SELECT id, cert FROM %1" ).arg( authDbIdentitiesTable() ) );
 
 2114  if ( !authDbQuery( &query ) )
 
 2117  if ( query.isActive() && query.isSelect() )
 
 2119    while ( query.next() )
 
 2121      certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
 
 
 2130  ensureInitialized();
 
 2132  QMutexLocker locker( mMutex.get() );
 
 2133  QStringList identityids = QStringList();
 
 2139  query.prepare( QStringLiteral( 
"SELECT id FROM %1" ).arg( authDbIdentitiesTable() ) );
 
 2141  if ( !authDbQuery( &query ) )
 
 2146  if ( query.isActive() )
 
 2148    while ( query.next() )
 
 2150      identityids << query.value( 0 ).toString();
 
 
 2158  ensureInitialized();
 
 2160  QMutexLocker locker( mMutex.get() );
 
 2165  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 2166                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 2168  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2170  if ( !authDbQuery( &query ) )
 
 2174  if ( query.isActive() && query.isSelect() )
 
 2176    if ( query.first() )
 
 2178      QgsDebugMsgLevel( QStringLiteral( 
"Certificate bundle exists for id: %1" ).arg( 
id ), 2 );
 
 2183      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate bundle for id: %1" ).arg( 
id ) );
 
 
 2193  ensureInitialized();
 
 2195  QMutexLocker locker( mMutex.get() );
 
 2198    QgsDebugError( QStringLiteral( 
"Passed bundle ID is empty" ) );
 
 2204  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 2206  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2208  if ( !authDbStartTransaction() )
 
 2211  if ( !authDbQuery( &query ) )
 
 2214  if ( !authDbCommit() )
 
 2217  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED certificate identity for id: %1" ).arg( 
id ), 2 );
 
 
 2223  ensureInitialized();
 
 2225  QMutexLocker locker( mMutex.get() );
 
 2237  QString certpem( cert.toPem() );
 
 2240  query.prepare( QStringLiteral( 
"INSERT OR REPLACE INTO %1 (id, host, cert, config) " 
 2243  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2244  query.bindValue( QStringLiteral( 
":host" ), config.
sslHostPort().trimmed() );
 
 2245  query.bindValue( QStringLiteral( 
":cert" ), certpem );
 
 2246  query.bindValue( QStringLiteral( 
":config" ), config.
configString() );
 
 2248  if ( !authDbStartTransaction() )
 
 2251  if ( !authDbQuery( &query ) )
 
 2254  if ( !authDbCommit() )
 
 2257  QgsDebugMsgLevel( QStringLiteral( 
"Store SSL cert custom config SUCCESS for host:port, id: %1, %2" )
 
 2261  mHasCheckedIfCustomConfigByHostExists = 
false;
 
 2262  mCustomConfigByHostCache.clear();
 
 
 2269  ensureInitialized();
 
 2271  QMutexLocker locker( mMutex.get() );
 
 2274  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2276    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2281  query.prepare( QStringLiteral( 
"SELECT id, host, cert, config FROM %1 " 
 2284  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2285  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2287  if ( !authDbQuery( &query ) )
 
 2290  if ( query.isActive() && query.isSelect() )
 
 2292    if ( query.first() )
 
 2294      config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
 
 2297      QgsDebugMsgLevel( QStringLiteral( 
"SSL cert custom config retrieved for host:port, id: %1, %2" ).arg( hostport, 
id ), 2 );
 
 2301      QgsDebugError( QStringLiteral( 
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport, 
id ) );
 
 2302      emit 
messageOut( tr( 
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
 
 
 2313  ensureInitialized();
 
 2316  if ( hostport.isEmpty() )
 
 2321  QMutexLocker locker( mMutex.get() );
 
 2322  if ( mHasCheckedIfCustomConfigByHostExists && !mHasCustomConfigByHost )
 
 2324  if ( mCustomConfigByHostCache.contains( hostport ) )
 
 2325    return mCustomConfigByHostCache.value( hostport );
 
 2330  if ( !mHasCheckedIfCustomConfigByHostExists )
 
 2332    mHasCheckedIfCustomConfigByHostExists = 
true;
 
 2334    if ( !authDbQuery( &query ) )
 
 2336      mHasCustomConfigByHost = 
false;
 
 2339    if ( query.isActive() && query.isSelect() && query.first() )
 
 2341      mHasCustomConfigByHost = query.value( 0 ).toInt() > 0;
 
 2342      if ( !mHasCustomConfigByHost )
 
 2347      mHasCustomConfigByHost = 
false;
 
 2352  query.prepare( QString( 
"SELECT id, host, cert, config FROM %1 " 
 2355  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2357  if ( !authDbQuery( &query ) )
 
 2359    mCustomConfigByHostCache.insert( hostport, config );
 
 2363  if ( query.isActive() && query.isSelect() )
 
 2365    if ( query.first() )
 
 2367      config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
 
 2370      QgsDebugMsgLevel( QStringLiteral( 
"SSL cert custom config retrieved for host:port: %1" ).arg( hostport ), 2 );
 
 2374      QgsDebugError( QStringLiteral( 
"Select contains more than one SSL cert custom config for host:port: %1" ).arg( hostport ) );
 
 2375      emit 
messageOut( tr( 
"Authentication database contains duplicate SSL cert custom configs for host:port: %1" )
 
 2378      mCustomConfigByHostCache.insert( hostport, emptyconfig );
 
 2383  mCustomConfigByHostCache.insert( hostport, config );
 
 
 2389  ensureInitialized();
 
 2391  QMutexLocker locker( mMutex.get() );
 
 2392  QList<QgsAuthConfigSslServer> configs;
 
 2397  if ( !authDbQuery( &query ) )
 
 2400  if ( query.isActive() && query.isSelect() )
 
 2402    while ( query.next() )
 
 2405      config.
setSslCertificate( QSslCertificate( query.value( 2 ).toByteArray(), QSsl::Pem ) );
 
 2409      configs.append( config );
 
 
 2418  ensureInitialized();
 
 2420  QMutexLocker locker( mMutex.get() );
 
 2421  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2423    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2428  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 2431  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2432  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2434  if ( !authDbQuery( &query ) )
 
 2438  if ( query.isActive() && query.isSelect() )
 
 2440    if ( query.first() )
 
 2442      QgsDebugMsgLevel( QStringLiteral( 
"SSL cert custom config exists for host:port, id: %1, %2" ).arg( hostport, 
id ), 2 );
 
 2447      QgsDebugError( QStringLiteral( 
"Select contains more than one SSL cert custom config for host:port, id: %1, %2" ).arg( hostport, 
id ) );
 
 2448      emit 
messageOut( tr( 
"Authentication database contains duplicate SSL cert custom configs for host:port, id: %1, %2" )
 
 
 2458  ensureInitialized();
 
 2460  QMutexLocker locker( mMutex.get() );
 
 2461  if ( 
id.isEmpty() || hostport.isEmpty() )
 
 2463    QgsDebugError( QStringLiteral( 
"Passed config ID or host:port is empty" ) );
 
 2467  mHasCheckedIfCustomConfigByHostExists = 
false;
 
 2468  mCustomConfigByHostCache.clear();
 
 2472  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id AND host = :host" ).arg( 
authDatabaseServersTable() ) );
 
 2474  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2475  query.bindValue( QStringLiteral( 
":host" ), hostport.trimmed() );
 
 2477  if ( !authDbStartTransaction() )
 
 2480  if ( !authDbQuery( &query ) )
 
 2483  if ( !authDbCommit() )
 
 2486  QString shahostport( QStringLiteral( 
"%1:%2" ).arg( 
id, hostport ) );
 
 2487  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2489    mIgnoredSslErrorsCache.remove( shahostport );
 
 2492  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED SSL cert custom config for host:port, id: %1, %2" ).arg( hostport, 
id ), 2 );
 
 
 2499  ensureInitialized();
 
 2501  QMutexLocker locker( mMutex.get() );
 
 2502  if ( !mIgnoredSslErrorsCache.isEmpty() )
 
 2504    QgsDebugMsgLevel( QStringLiteral( 
"Ignored SSL errors cache items:" ), 1 );
 
 2505    QHash<QString, QSet<QSslError::SslError> >::const_iterator i = mIgnoredSslErrorsCache.constBegin();
 
 2506    while ( i != mIgnoredSslErrorsCache.constEnd() )
 
 2509      for ( 
auto err : i.value() )
 
 2513      QgsDebugMsgLevel( QStringLiteral( 
"%1 = %2" ).arg( i.key(), errs.join( 
", " ) ), 1 );
 
 
 2525  ensureInitialized();
 
 2527  QMutexLocker locker( mMutex.get() );
 
 2534  QString shahostport( QStringLiteral( 
"%1:%2" )
 
 2537  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2539    mIgnoredSslErrorsCache.remove( shahostport );
 
 2542  if ( !errenums.isEmpty() )
 
 2544    mIgnoredSslErrorsCache.insert( shahostport, QSet<QSslError::SslError>( errenums.begin(), errenums.end() ) );
 
 2545    QgsDebugMsgLevel( QStringLiteral( 
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 2550  QgsDebugMsgLevel( QStringLiteral( 
"No ignored SSL errors to cache for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 
 2556  ensureInitialized();
 
 2558  QMutexLocker locker( mMutex.get() );
 
 2559  const thread_local QRegularExpression rx( QRegularExpression::anchoredPattern( 
"\\S+:\\S+:\\d+" ) );
 
 2560  if ( !rx.match( shahostport ).hasMatch() )
 
 2562    QgsDebugError( 
"Passed shahostport does not match \\S+:\\S+:\\d+, " 
 2563                   "e.g. 74a4ef5ea94512a43769b744cda0ca5049a72491:www.example.com:443" );
 
 2567  if ( mIgnoredSslErrorsCache.contains( shahostport ) )
 
 2569    mIgnoredSslErrorsCache.remove( shahostport );
 
 2572  if ( errors.isEmpty() )
 
 2574    QgsDebugError( QStringLiteral( 
"Passed errors list empty" ) );
 
 2578  QSet<QSslError::SslError> errs;
 
 2579  for ( 
const auto &error : errors )
 
 2581    if ( error.error() == QSslError::NoError )
 
 2584    errs.insert( error.error() );
 
 2587  if ( errs.isEmpty() )
 
 2589    QgsDebugError( QStringLiteral( 
"Passed errors list does not contain errors" ) );
 
 2593  mIgnoredSslErrorsCache.insert( shahostport, errs );
 
 2595  QgsDebugMsgLevel( QStringLiteral( 
"Update of ignored SSL errors cache SUCCEEDED for sha:host:port = %1" ).arg( shahostport ), 2 );
 
 
 2602  ensureInitialized();
 
 2604  QMutexLocker locker( mMutex.get() );
 
 2605  QHash<QString, QSet<QSslError::SslError> > prevcache( mIgnoredSslErrorsCache );
 
 2606  QHash<QString, QSet<QSslError::SslError> > nextcache;
 
 2611  if ( !authDbQuery( &query ) )
 
 2613    QgsDebugError( QStringLiteral( 
"Rebuild of ignored SSL errors cache FAILED" ) );
 
 2617  if ( query.isActive() && query.isSelect() )
 
 2619    while ( query.next() )
 
 2621      QString shahostport( QStringLiteral( 
"%1:%2" )
 
 2622                           .arg( query.value( 0 ).toString().trimmed(),
 
 2623                                 query.value( 1 ).toString().trimmed() ) );
 
 2627      if ( !errenums.isEmpty() )
 
 2629        nextcache.insert( shahostport, QSet<QSslError::SslError>( errenums.begin(), errenums.end() ) );
 
 2631      if ( prevcache.contains( shahostport ) )
 
 2633        prevcache.remove( shahostport );
 
 2638  if ( !prevcache.isEmpty() )
 
 2641    QHash<QString, QSet<QSslError::SslError> >::const_iterator i = prevcache.constBegin();
 
 2642    while ( i != prevcache.constEnd() )
 
 2644      nextcache.insert( i.key(), i.value() );
 
 2649  if ( nextcache != mIgnoredSslErrorsCache )
 
 2651    mIgnoredSslErrorsCache.clear();
 
 2652    mIgnoredSslErrorsCache = nextcache;
 
 2653    QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of ignored SSL errors cache SUCCEEDED" ), 2 );
 
 2658  QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of ignored SSL errors cache SAME AS BEFORE" ), 2 );
 
 
 2666  ensureInitialized();
 
 2668  QMutexLocker locker( mMutex.get() );
 
 2669  if ( certs.isEmpty() )
 
 2671    QgsDebugError( QStringLiteral( 
"Passed certificate list has no certs" ) );
 
 2675  for ( 
const auto &cert : certs )
 
 
 2685  ensureInitialized();
 
 2687  QMutexLocker locker( mMutex.get() );
 
 2690  if ( cert.isNull() )
 
 2692    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2699  QString pem( cert.toPem() );
 
 2702  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, cert) " 
 2703                                 "VALUES (:id, :cert)" ).arg( authDbAuthoritiesTable() ) );
 
 2705  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2706  query.bindValue( QStringLiteral( 
":cert" ), pem );
 
 2708  if ( !authDbStartTransaction() )
 
 2711  if ( !authDbQuery( &query ) )
 
 2714  if ( !authDbCommit() )
 
 2717  QgsDebugMsgLevel( QStringLiteral( 
"Store certificate authority SUCCESS for id: %1" ).arg( 
id ), 2 );
 
 
 2723  ensureInitialized();
 
 2725  QMutexLocker locker( mMutex.get() );
 
 2726  QSslCertificate emptycert;
 
 2727  QSslCertificate cert;
 
 2732  query.prepare( QStringLiteral( 
"SELECT cert FROM %1 " 
 2733                                 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
 
 2735  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2737  if ( !authDbQuery( &query ) )
 
 2740  if ( query.isActive() && query.isSelect() )
 
 2742    if ( query.first() )
 
 2744      cert = QSslCertificate( query.value( 0 ).toByteArray(), QSsl::Pem );
 
 2745      QgsDebugMsgLevel( QStringLiteral( 
"Certificate authority retrieved for id: %1" ).arg( 
id ), 2 );
 
 2749      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate authority for id: %1" ).arg( 
id ) );
 
 
 2759  ensureInitialized();
 
 2761  QMutexLocker locker( mMutex.get() );
 
 2762  if ( cert.isNull() )
 
 2764    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2771  query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 2772                                 "WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
 
 2774  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2776  if ( !authDbQuery( &query ) )
 
 2780  if ( query.isActive() && query.isSelect() )
 
 2782    if ( query.first() )
 
 2784      QgsDebugMsgLevel( QStringLiteral( 
"Certificate authority exists for id: %1" ).arg( 
id ), 2 );
 
 2789      QgsDebugError( QStringLiteral( 
"Select contains more than one certificate authority for id: %1" ).arg( 
id ) );
 
 
 2799  ensureInitialized();
 
 2801  QMutexLocker locker( mMutex.get() );
 
 2802  if ( cert.isNull() )
 
 2804    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2812  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id" ).arg( authDbAuthoritiesTable() ) );
 
 2814  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2816  if ( !authDbStartTransaction() )
 
 2819  if ( !authDbQuery( &query ) )
 
 2822  if ( !authDbCommit() )
 
 2825  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED authority for id: %1" ).arg( 
id ), 2 );
 
 
 2831  return QSslConfiguration::systemCaCertificates();
 
 
 2836  ensureInitialized();
 
 2838  QMutexLocker locker( mMutex.get() );
 
 2839  QList<QSslCertificate> certs;
 
 2840  QList<QSslCertificate> filecerts;
 
 2849  QString cafile( cafileval.toString() );
 
 2850  if ( !cafile.isEmpty() && QFile::exists( cafile ) )
 
 2855  for ( 
const auto &cert : std::as_const( filecerts ) )
 
 2857    if ( !allowinvalid.toBool() && ( cert.isBlacklisted()
 
 2859                                     || cert.expiryDate() <= QDateTime::currentDateTime()
 
 2860                                     || cert.effectiveDate() > QDateTime::currentDateTime() ) )
 
 
 2875  ensureInitialized();
 
 2877  QMutexLocker locker( mMutex.get() );
 
 2878  QList<QSslCertificate> certs;
 
 2881  query.prepare( QStringLiteral( 
"SELECT id, cert FROM %1" ).arg( authDbAuthoritiesTable() ) );
 
 2883  if ( !authDbQuery( &query ) )
 
 2886  if ( query.isActive() && query.isSelect() )
 
 2888    while ( query.next() )
 
 2890      certs << QSslCertificate( query.value( 1 ).toByteArray(), QSsl::Pem );
 
 
 2899  ensureInitialized();
 
 2901  QMutexLocker locker( mMutex.get() );
 
 
 2907  ensureInitialized();
 
 2909  QMutexLocker locker( mMutex.get() );
 
 2910  mCaCertsCache.clear();
 
 2916  bool res = !mCaCertsCache.isEmpty(); 
 
 2918    QgsDebugError( QStringLiteral( 
"Rebuild of CA certs cache FAILED" ) );
 
 
 2924  ensureInitialized();
 
 2926  QMutexLocker locker( mMutex.get() );
 
 2927  if ( cert.isNull() )
 
 2929    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2939    QgsDebugMsgLevel( QStringLiteral( 
"Passed policy was default, all cert records in database were removed for id: %1" ).arg( 
id ), 2 );
 
 2944  query.prepare( QStringLiteral( 
"INSERT INTO %1 (id, policy) " 
 2945                                 "VALUES (:id, :policy)" ).arg( authDbTrustTable() ) );
 
 2947  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2948  query.bindValue( QStringLiteral( 
":policy" ), 
static_cast< int >( policy ) );
 
 2950  if ( !authDbStartTransaction() )
 
 2953  if ( !authDbQuery( &query ) )
 
 2956  if ( !authDbCommit() )
 
 2959  QgsDebugMsgLevel( QStringLiteral( 
"Store certificate trust policy SUCCESS for id: %1" ).arg( 
id ), 2 );
 
 
 2965  ensureInitialized();
 
 2967  QMutexLocker locker( mMutex.get() );
 
 2968  if ( cert.isNull() )
 
 2970    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 2977  query.prepare( QStringLiteral( 
"SELECT policy FROM %1 " 
 2978                                 "WHERE id = :id" ).arg( authDbTrustTable() ) );
 
 2980  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 2982  if ( !authDbQuery( &query ) )
 
 2986  if ( query.isActive() && query.isSelect() )
 
 2988    if ( query.first() )
 
 2991      QgsDebugMsgLevel( QStringLiteral( 
"Authentication cert trust policy retrieved for id: %1" ).arg( 
id ), 2 );
 
 2995      QgsDebugError( QStringLiteral( 
"Select contains more than one cert trust policy for id: %1" ).arg( 
id ) );
 
 
 3005  ensureInitialized();
 
 3007  QMutexLocker locker( mMutex.get() );
 
 3008  if ( certs.empty() )
 
 3010    QgsDebugError( QStringLiteral( 
"Passed certificate list has no certs" ) );
 
 3014  for ( 
const auto &cert : certs )
 
 
 3024  ensureInitialized();
 
 3026  QMutexLocker locker( mMutex.get() );
 
 3027  if ( cert.isNull() )
 
 3029    QgsDebugError( QStringLiteral( 
"Passed certificate is null" ) );
 
 3037  query.prepare( QStringLiteral( 
"DELETE FROM %1 WHERE id = :id" ).arg( authDbTrustTable() ) );
 
 3039  query.bindValue( QStringLiteral( 
":id" ), 
id );
 
 3041  if ( !authDbStartTransaction() )
 
 3044  if ( !authDbQuery( &query ) )
 
 3047  if ( !authDbCommit() )
 
 3050  QgsDebugMsgLevel( QStringLiteral( 
"REMOVED cert trust policy for id: %1" ).arg( 
id ), 2 );
 
 
 3057  ensureInitialized();
 
 3059  QMutexLocker locker( mMutex.get() );
 
 3060  if ( cert.isNull() )
 
 3070  if ( trustedids.contains( 
id ) )
 
 3074  else if ( untrustedids.contains( 
id ) )
 
 
 3083  ensureInitialized();
 
 3090  return storeAuthSetting( QStringLiteral( 
"certdefaulttrust" ), 
static_cast< int >( policy ) );
 
 
 3095  ensureInitialized();
 
 3097  QMutexLocker locker( mMutex.get() );
 
 3098  QVariant policy( 
authSetting( QStringLiteral( 
"certdefaulttrust" ) ) );
 
 
 3108  ensureInitialized();
 
 3110  QMutexLocker locker( mMutex.get() );
 
 3111  mCertTrustCache.clear();
 
 3114  query.prepare( QStringLiteral( 
"SELECT id, policy FROM %1" ).arg( authDbTrustTable() ) );
 
 3116  if ( !authDbQuery( &query ) )
 
 3118    QgsDebugError( QStringLiteral( 
"Rebuild of cert trust policy cache FAILED" ) );
 
 3122  if ( query.isActive() && query.isSelect() )
 
 3124    while ( query.next() )
 
 3126      QString 
id = query.value( 0 ).toString();
 
 3130      if ( mCertTrustCache.contains( policy ) )
 
 3132        ids = mCertTrustCache.value( policy );
 
 3134      mCertTrustCache.insert( policy, ids << 
id );
 
 3138  QgsDebugMsgLevel( QStringLiteral( 
"Rebuild of cert trust policy cache SUCCEEDED" ), 2 );
 
 
 3144  ensureInitialized();
 
 3146  QMutexLocker locker( mMutex.get() );
 
 3150  const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
 
 3152  QList<QSslCertificate> trustedcerts;
 
 3153  for ( 
int i = 0; i < certpairs.size(); ++i )
 
 3155    QSslCertificate cert( certpairs.at( i ).second );
 
 3157    if ( trustedids.contains( certid ) )
 
 3160      trustedcerts.append( cert );
 
 3166      trustedcerts.append( cert );
 
 3171  QSslConfiguration sslconfig( QSslConfiguration::defaultConfiguration() );
 
 3172  sslconfig.setCaCertificates( trustedcerts );
 
 3173  QSslConfiguration::setDefaultConfiguration( sslconfig );
 
 3175  return trustedcerts;
 
 
 3180  ensureInitialized();
 
 3182  QMutexLocker locker( mMutex.get() );
 
 3183  if ( trustedCAs.isEmpty() )
 
 3185    if ( mTrustedCaCertsCache.isEmpty() )
 
 3192  const QList<QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > &certpairs( mCaCertsCache.values() );
 
 3194  QList<QSslCertificate> untrustedCAs;
 
 3195  for ( 
int i = 0; i < certpairs.size(); ++i )
 
 3197    QSslCertificate cert( certpairs.at( i ).second );
 
 3198    if ( !trustedCAs.contains( cert ) )
 
 3200      untrustedCAs.append( cert );
 
 3203  return untrustedCAs;
 
 
 3208  ensureInitialized();
 
 3210  QMutexLocker locker( mMutex.get() );
 
 3212  QgsDebugMsgLevel( QStringLiteral( 
"Rebuilt trusted cert authorities cache" ), 2 );
 
 
 3219  ensureInitialized();
 
 3221  QMutexLocker locker( mMutex.get() );
 
 
 3227  ensureInitialized();
 
 3229  QMutexLocker locker( mMutex.get() );
 
 3232    return passwordHelperWrite( mMasterPass );
 
 
 3244  ensureInitialized();
 
 3250  for ( 
const auto &authcfg : ids )
 
 
 3258  ensureInitialized();
 
 
 3270void QgsAuthManager::writeToConsole( 
const QString &message,
 
 3276  ensureInitialized();
 
 3286      msg += QLatin1String( 
"WARNING: " );
 
 3289      msg += QLatin1String( 
"ERROR: " );
 
 3296  QTextStream out( stdout, QIODevice::WriteOnly );
 
 3297  out << msg << Qt::endl;
 
 3300void QgsAuthManager::tryToStartDbErase()
 
 3302  ensureInitialized();
 
 3304  ++mScheduledDbEraseRequestCount;
 
 3306  int trycutoff = 90 / ( mScheduledDbEraseRequestWait ? mScheduledDbEraseRequestWait : 3 );
 
 3307  if ( mScheduledDbEraseRequestCount >= trycutoff )
 
 3310    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emitting/scheduling canceled" ), 2 );
 
 3315    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest attempt (%1 of %2)" )
 
 3316                      .arg( mScheduledDbEraseRequestCount ).arg( trycutoff ), 2 );
 
 3322    mScheduledDbEraseRequestEmitted = 
true;
 
 3327    QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emitted" ), 2 );
 
 3330  QgsDebugMsgLevel( QStringLiteral( 
"authDatabaseEraseRequest emit skipped" ), 2 );
 
 3336  QMutexLocker locker( mMutex.get() );
 
 3338  QMapIterator<QThread *, QMetaObject::Connection> iterator( mConnectedThreads );
 
 3339  while ( iterator.hasNext() )
 
 3342    QThread::disconnect( iterator.value() );
 
 3353    qDeleteAll( mAuthMethods );
 
 3356    if ( authConn.isValid() && authConn.isOpen() )
 
 3359  delete mScheduledDbEraseTimer;
 
 3360  mScheduledDbEraseTimer = 
nullptr;
 
 3361  QSqlDatabase::removeDatabase( QStringLiteral( 
"authentication.configs" ) );
 
 
 3365QString QgsAuthManager::passwordHelperName()
 const 
 3367  return tr( 
"Password Helper" );
 
 3371void QgsAuthManager::passwordHelperLog( 
const QString &msg )
 const 
 3373  ensureInitialized();
 
 3383  ensureInitialized();
 
 3387  QKeychain::DeletePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3390  job.setAutoDelete( 
false );
 
 3391  job.setKey( authPasswordHelperKeyName() );
 
 3393  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3398    mPasswordHelperErrorCode = job.error();
 
 3399    mPasswordHelperErrorMessage = tr( 
"Delete password failed: %1." ).arg( job.errorString() );
 
 3410  passwordHelperProcessError();
 
 
 3414QString QgsAuthManager::passwordHelperRead()
 
 3416  ensureInitialized();
 
 3421  QKeychain::ReadPasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3424  job.setAutoDelete( 
false );
 
 3425  job.setKey( authPasswordHelperKeyName() );
 
 3427  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3432    mPasswordHelperErrorCode = job.error();
 
 3439    password = job.textData();
 
 3441    if ( password.isEmpty() )
 
 3443      mPasswordHelperErrorCode = QKeychain::EntryNotFound;
 
 3454  passwordHelperProcessError();
 
 3458bool QgsAuthManager::passwordHelperWrite( 
const QString &password )
 
 3460  ensureInitialized();
 
 3462  Q_ASSERT( !password.isEmpty() );
 
 3465  QKeychain::WritePasswordJob job( AUTH_PASSWORD_HELPER_FOLDER_NAME );
 
 3468  job.setAutoDelete( 
false );
 
 3469  job.setKey( authPasswordHelperKeyName() );
 
 3470  job.setTextData( password );
 
 3472  connect( &job, &QKeychain::Job::finished, &loop, &QEventLoop::quit );
 
 3477    mPasswordHelperErrorCode = job.error();
 
 3485    passwordHelperClearErrors();
 
 3490  passwordHelperProcessError();
 
 3505  emit 
messageOut( enabled ? tr( 
"Your %1 will be <b>used from now</b> on to store and retrieve the master password." )
 
 3507                   tr( 
"Your %1 will <b>not be used anymore</b> to store and retrieve the master password." )
 
 
 3524void QgsAuthManager::passwordHelperClearErrors()
 
 3526  mPasswordHelperErrorCode = QKeychain::NoError;
 
 3527  mPasswordHelperErrorMessage.clear();
 
 3530void QgsAuthManager::passwordHelperProcessError()
 
 3532  ensureInitialized();
 
 3534  if ( mPasswordHelperErrorCode == QKeychain::AccessDenied ||
 
 3535       mPasswordHelperErrorCode == QKeychain::AccessDeniedByUser ||
 
 3536       mPasswordHelperErrorCode == QKeychain::NoBackendAvailable ||
 
 3537       mPasswordHelperErrorCode == QKeychain::NotImplemented )
 
 3543    mPasswordHelperErrorMessage = tr( 
"There was an error and integration with your %1 system has been disabled. " 
 3544                                      "You can re-enable it at any time through the \"Utilities\" menu " 
 3545                                      "in the Authentication pane of the options dialog. %2" )
 
 3548  if ( mPasswordHelperErrorCode != QKeychain::NoError )
 
 3554  passwordHelperClearErrors();
 
 3558bool QgsAuthManager::masterPasswordInput()
 
 3560  ensureInitialized();
 
 3566  bool storedPasswordIsValid = 
false;
 
 3572    pass = passwordHelperRead();
 
 3573    if ( ! pass.isEmpty() && ( mPasswordHelperErrorCode == QKeychain::NoError ) )
 
 3579        storedPasswordIsValid = 
true;
 
 3595  if ( ok && !pass.isEmpty() && mMasterPass != pass )
 
 3600      if ( passwordHelperWrite( pass ) )
 
 3614bool QgsAuthManager::masterPasswordRowsInDb( 
int *rows )
 const 
 3616  ensureInitialized();
 
 3622  query.prepare( QStringLiteral( 
"SELECT Count(*) FROM %1" ).arg( authDbPassTable() ) );
 
 3624  bool ok = authDbQuery( &query );
 
 3625  if ( query.first() )
 
 3627    *rows = query.value( 0 ).toInt();
 
 3635  ensureInitialized();
 
 3641  if ( !masterPasswordRowsInDb( &rows ) )
 
 3643    const char *err = QT_TR_NOOP( 
"Master password: FAILED to access database" );
 
 3649  return ( rows == 1 );
 
 
 3652bool QgsAuthManager::masterPasswordCheckAgainstDb( 
const QString &compare )
 const 
 3654  ensureInitialized();
 
 3662  query.prepare( QStringLiteral( 
"SELECT salt, hash FROM %1" ).arg( authDbPassTable() ) );
 
 3663  if ( !authDbQuery( &query ) )
 
 3666  if ( !query.first() )
 
 3669  QString salt = query.value( 0 ).toString();
 
 3670  QString hash = query.value( 1 ).toString();
 
 3675bool QgsAuthManager::masterPasswordStoreInDb()
 const 
 3677  ensureInitialized();
 
 3682  QString salt, hash, civ;
 
 3686  query.prepare( QStringLiteral( 
"INSERT INTO %1 (salt, hash, civ) VALUES (:salt, :hash, :civ)" ).arg( authDbPassTable() ) );
 
 3688  query.bindValue( QStringLiteral( 
":salt" ), salt );
 
 3689  query.bindValue( QStringLiteral( 
":hash" ), hash );
 
 3690  query.bindValue( QStringLiteral( 
":civ" ), civ );
 
 3692  if ( !authDbStartTransaction() )
 
 3695  if ( !authDbQuery( &query ) )
 
 3698  if ( !authDbCommit() )
 
 3704bool QgsAuthManager::masterPasswordClearDb()
 
 3706  ensureInitialized();
 
 3712  query.prepare( QStringLiteral( 
"DELETE FROM %1" ).arg( authDbPassTable() ) );
 
 3713  bool res = authDbTransactionQuery( &query );
 
 3719const QString QgsAuthManager::masterPasswordCiv()
 const 
 3721  ensureInitialized();
 
 3727  query.prepare( QStringLiteral( 
"SELECT civ FROM %1" ).arg( authDbPassTable() ) );
 
 3728  if ( !authDbQuery( &query ) )
 
 3731  if ( !query.first() )
 
 3734  return query.value( 0 ).toString();
 
 3739  ensureInitialized();
 
 3741  QStringList configids = QStringList();
 
 3749  if ( !authDbQuery( &query ) )
 
 3754  if ( query.isActive() )
 
 3756    while ( query.next() )
 
 3758      configids << query.value( 0 ).toString();
 
 
 3764bool QgsAuthManager::verifyPasswordCanDecryptConfigs()
 const 
 3766  ensureInitialized();
 
 3777  if ( !authDbQuery( &query ) )
 
 3780  if ( !query.isActive() || !query.isSelect() )
 
 3782    QgsDebugError( QStringLiteral( 
"Verify password can decrypt configs FAILED, query not active or a select operation" ) );
 
 3790  while ( query.next() )
 
 3795    QString configstring( 
QgsAuthCrypto::decrypt( mMasterPass, masterPasswordCiv(), query.value( 1 ).toString() ) );
 
 3796    if ( configstring.isEmpty() )
 
 3798      QgsDebugError( QStringLiteral( 
"Verify password can decrypt configs FAILED, could not decrypt a config (id: %1)" )
 
 3799                     .arg( query.value( 0 ).toString() ) );
 
 3804  QgsDebugMsgLevel( QStringLiteral( 
"Verify password can decrypt configs SUCCESS (checked %1 configs)" ).arg( checked ), 2 );
 
 3808bool QgsAuthManager::reencryptAllAuthenticationConfigs( 
const QString &prevpass, 
const QString &prevciv )
 
 3810  ensureInitialized();
 
 3817  for ( 
const auto &configid : ids )
 
 3819    res = res && reencryptAuthenticationConfig( configid, prevpass, prevciv );
 
 3824bool QgsAuthManager::reencryptAuthenticationConfig( 
const QString &authcfg, 
const QString &prevpass, 
const QString &prevciv )
 
 3826  ensureInitialized();
 
 3835  query.prepare( QStringLiteral( 
"SELECT config FROM %1 " 
 3838  query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 3840  if ( !authDbQuery( &query ) )
 
 3843  if ( !query.isActive() || !query.isSelect() )
 
 3845    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, query not active or a select operation for authcfg: %2" ).arg( authcfg ) );
 
 3849  if ( query.first() )
 
 3855      QgsDebugError( QStringLiteral( 
"Select contains more than one for authcfg: %1" ).arg( authcfg ) );
 
 3862    query.prepare( QStringLiteral( 
"UPDATE %1 " 
 3863                                   "SET config = :config " 
 3866    query.bindValue( QStringLiteral( 
":id" ), authcfg );
 
 3867    query.bindValue( QStringLiteral( 
":config" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), configstring ) );
 
 3869    if ( !authDbStartTransaction() )
 
 3872    if ( !authDbQuery( &query ) )
 
 3875    if ( !authDbCommit() )
 
 3878    QgsDebugMsgLevel( QStringLiteral( 
"Reencrypt SUCCESS for authcfg: %2" ).arg( authcfg ), 2 );
 
 3883    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find in db authcfg: %2" ).arg( authcfg ) );
 
 3888bool QgsAuthManager::reencryptAllAuthenticationSettings( 
const QString &prevpass, 
const QString &prevciv )
 
 3890  ensureInitialized();
 
 3893  Q_UNUSED( prevpass )
 
 3906  QStringList encryptedsettings;
 
 3907  encryptedsettings << 
"";
 
 3909  for ( 
const auto & sett, std::as_const( encryptedsettings ) )
 
 3916    QSqlQuery query( authDbConnection() );
 
 3918    query.prepare( QStringLiteral( 
"SELECT value FROM %1 " 
 3919                                   "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 3921    query.bindValue( 
":setting", sett );
 
 3923    if ( !authDbQuery( &query ) )
 
 3926    if ( !query.isActive() || !query.isSelect() )
 
 3928      QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, query not active or a select operation for setting: %2" ).arg( sett ) );
 
 3932    if ( query.first() )
 
 3938      query.prepare( QStringLiteral( 
"UPDATE %1 " 
 3939                                     "SET value = :value " 
 3940                                     "WHERE setting = :setting" ).arg( authDbSettingsTable() ) );
 
 3942      query.bindValue( 
":setting", sett );
 
 3945      if ( !authDbStartTransaction() )
 
 3948      if ( !authDbQuery( &query ) )
 
 3951      if ( !authDbCommit() )
 
 3954      QgsDebugMsgLevel( QStringLiteral( 
"Reencrypt SUCCESS for setting: %2" ).arg( sett ), 2 );
 
 3959      QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find in db setting: %2" ).arg( sett ) );
 
 3965      QgsDebugError( QStringLiteral( 
"Select contains more than one for setting: %1" ).arg( sett ) );
 
 3976bool QgsAuthManager::reencryptAllAuthenticationIdentities( 
const QString &prevpass, 
const QString &prevciv )
 
 3978  ensureInitialized();
 
 3985  for ( 
const auto &identid : ids )
 
 3987    res = res && reencryptAuthenticationIdentity( identid, prevpass, prevciv );
 
 3992bool QgsAuthManager::reencryptAuthenticationIdentity(
 
 3993  const QString &identid,
 
 3994  const QString &prevpass,
 
 3995  const QString &prevciv )
 
 3997  ensureInitialized();
 
 4006  query.prepare( QStringLiteral( 
"SELECT key FROM %1 " 
 4007                                 "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 4009  query.bindValue( QStringLiteral( 
":id" ), identid );
 
 4011  if ( !authDbQuery( &query ) )
 
 4014  if ( !query.isActive() || !query.isSelect() )
 
 4016    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, query not active or a select operation for identity id: %2" ).arg( identid ) );
 
 4020  if ( query.first() )
 
 4026      QgsDebugError( QStringLiteral( 
"Select contains more than one for identity id: %1" ).arg( identid ) );
 
 4033    query.prepare( QStringLiteral( 
"UPDATE %1 " 
 4035                                   "WHERE id = :id" ).arg( authDbIdentitiesTable() ) );
 
 4037    query.bindValue( QStringLiteral( 
":id" ), identid );
 
 4038    query.bindValue( QStringLiteral( 
":key" ), 
QgsAuthCrypto::encrypt( mMasterPass, masterPasswordCiv(), keystring ) );
 
 4040    if ( !authDbStartTransaction() )
 
 4043    if ( !authDbQuery( &query ) )
 
 4046    if ( !authDbCommit() )
 
 4049    QgsDebugMsgLevel( QStringLiteral( 
"Reencrypt SUCCESS for identity id: %2" ).arg( identid ), 2 );
 
 4054    QgsDebugError( QStringLiteral( 
"Reencrypt FAILED, could not find in db identity id: %2" ).arg( identid ) );
 
 4059bool QgsAuthManager::authDbOpen()
 const 
 4061  ensureInitialized();
 
 4067  if ( !authdb.isOpen() )
 
 4069    if ( !authdb.open() )
 
 4071      QgsDebugError( QStringLiteral( 
"Unable to establish database connection\nDatabase: %1\nDriver error: %2\nDatabase error: %3" )
 
 4073                           authdb.lastError().driverText(),
 
 4074                           authdb.lastError().databaseText() ) );
 
 4082bool QgsAuthManager::authDbQuery( QSqlQuery *query )
 const 
 4084  ensureInitialized();
 
 4089  query->setForwardOnly( 
true );
 
 4090  if ( !query->exec() )
 
 4092    const char *err = QT_TR_NOOP( 
"Auth db query exec() FAILED" );
 
 4098  if ( query->lastError().isValid() )
 
 4100    QgsDebugError( QStringLiteral( 
"Auth db query FAILED: %1\nError: %2" )
 
 4101                   .arg( query->executedQuery(),
 
 4102                         query->lastError().text() ) );
 
 4110bool QgsAuthManager::authDbStartTransaction()
 const 
 4112  ensureInitialized();
 
 4119    const char *err = QT_TR_NOOP( 
"Auth db FAILED to start transaction" );
 
 4128bool QgsAuthManager::authDbCommit()
 const 
 4130  ensureInitialized();
 
 4137    const char *err = QT_TR_NOOP( 
"Auth db FAILED to rollback changes" );
 
 4147bool QgsAuthManager::authDbTransactionQuery( QSqlQuery *query )
 const 
 4149  ensureInitialized();
 
 4156    const char *err = QT_TR_NOOP( 
"Auth db FAILED to start transaction" );
 
 4162  bool ok = authDbQuery( query );
 
 4166    const char *err = QT_TR_NOOP( 
"Auth db FAILED to rollback changes" );
 
 4178  ensureInitialized();
 
 4180  for ( 
const auto &cert : certs )
 
 4183                          QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>( source, cert ) );
 
 4187QString QgsAuthManager::authPasswordHelperKeyName()
 const 
 4189  ensureInitialized();
 
 4191  const QFileInfo info( mAuthDbPath );
 
 4192  const QString dbProfilePath = info.dir().dirName();
 
 4195  return AUTH_PASSWORD_HELPER_KEY_NAME_BASE + ( dbProfilePath.compare( QLatin1String( 
"default" ), Qt::CaseInsensitive ) == 0 ? QString() : dbProfilePath );
 
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.
static bool passwordHelperEnabled()
Password helper enabled getter.
bool exportAuthenticationConfigsToXml(const QString &filename, const QStringList &authcfgs, const QString &password=QString())
Export authentication configurations to an XML file.
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.
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
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.
bool rebuildCertTrustCache()
Rebuild certificate authority cache.
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.
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.
void setup(const QString &pluginPath=QString(), const QString &authDatabasePath=QString())
Sets up the authentication manager configuration.
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.
static 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.
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.
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.
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.
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, bool silenceNullWarnings=false)
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)