17#include "ui_qgsauthauthoritieseditor.h"
41#include <QSslConfiguration>
44#include "moc_qgsauthauthoritieseditor.cpp"
46using namespace Qt::StringLiterals;
54 mAuthNotifyLayout =
new QVBoxLayout;
55 this->setLayout( mAuthNotifyLayout );
57 mAuthNotifyLayout->addWidget( mAuthNotify );
62 connect( btnAddCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnAddCa_clicked );
63 connect( btnRemoveCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnRemoveCa_clicked );
64 connect( btnInfoCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnInfoCa_clicked );
65 connect( btnGroupByOrg, &QToolButton::toggled,
this, &QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled );
66 connect( btnCaFile, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFile_clicked );
67 connect( btnCaFileClear, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFileClear_clicked );
75 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAuthAuthoritiesEditor::selectionChanged );
77 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
79 connect( btnViewRefresh, &QAbstractButton::clicked,
this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
84 leCaFile->setText( cafileval.toString() );
87 btnGroupByOrg->setChecked(
false );
90 btnGroupByOrg->setChecked( sortbyval.toBool() );
93 populateCaCertsView();
96 populateUtilitiesMenu();
100void QgsAuthAuthoritiesEditor::setupCaCertsTree()
102 treeWidgetCAs->setColumnCount( 4 );
103 treeWidgetCAs->setHeaderLabels( QStringList() << tr(
"Common Name" ) << tr(
"Serial #" ) << tr(
"Expiry Date" ) << tr(
"Trust Policy" ) );
104 treeWidgetCAs->setColumnWidth( 0, 300 );
105 treeWidgetCAs->setColumnWidth( 1, 75 );
106 treeWidgetCAs->setColumnWidth( 2, 200 );
109 mDbCaSecItem =
new QTreeWidgetItem( treeWidgetCAs, QStringList( QgsAuthCertUtils::getCaSourceName(
QgsAuthCertUtils::InDatabase ) ),
static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
111 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
112 mDbCaSecItem->setExpanded(
true );
113 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
115 mFileCaSecItem =
new QTreeWidgetItem( treeWidgetCAs, QStringList( QgsAuthCertUtils::getCaSourceName(
QgsAuthCertUtils::FromFile ) ),
static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
117 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
118 mFileCaSecItem->setExpanded(
true );
119 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
121 mRootCaSecItem =
new QTreeWidgetItem( treeWidgetCAs, QStringList( QgsAuthCertUtils::getCaSourceName(
QgsAuthCertUtils::SystemRoot ) ),
static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
123 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
124 mRootCaSecItem->setExpanded(
false );
125 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
128void QgsAuthAuthoritiesEditor::populateCaCertsView()
130 updateCertTrustPolicyCache();
131 populateDatabaseCaCerts();
132 populateFileCaCerts();
133 populateRootCaCerts();
136void QgsAuthAuthoritiesEditor::refreshCaCertsView()
139 populateCaCertsView();
142void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
146 const bool expanded = mDbCaSecItem->isExpanded();
148 mDbCaSecItem->setExpanded( expanded );
151void QgsAuthAuthoritiesEditor::populateFileCaCerts()
155 const bool expanded = mFileCaSecItem->isExpanded();
157 mFileCaSecItem->setExpanded( expanded );
160void QgsAuthAuthoritiesEditor::populateRootCaCerts()
164 const bool expanded = mRootCaSecItem->isExpanded();
166 mRootCaSecItem->setExpanded( expanded );
169void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype )
171 if ( btnGroupByOrg->isChecked() )
173 appendCertsToGroup( certs, catype, item );
177 appendCertsToItem( certs, catype, item );
181void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
188 parent = treeWidgetCAs->currentItem();
192 const QMap<QString, QList<QSslCertificate>> orgcerts( QgsAuthCertUtils::certsGroupedByOrg( certs ) );
194 QMap<QString, QList<QSslCertificate>>::const_iterator it = orgcerts.constBegin();
195 for ( ; it != orgcerts.constEnd(); ++it )
197 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent, QStringList() << it.key(),
static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
198 grpitem->setFirstColumnSpanned(
true );
199 grpitem->setFlags( Qt::ItemIsEnabled );
200 grpitem->setExpanded(
true );
202 QBrush orgb( grpitem->foreground( 0 ) );
203 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
204 grpitem->setForeground( 0, orgb );
205 QFont grpf( grpitem->font( 0 ) );
206 grpf.setItalic(
true );
207 grpitem->setFont( 0, grpf );
209 appendCertsToItem( it.value(), catype, grpitem );
212 parent->sortChildren( 0, Qt::AscendingOrder );
215void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
222 parent = treeWidgetCAs->currentItem();
232 const auto constCerts = certs;
233 for (
const QSslCertificate &cert : constCerts )
235 const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
238 coltxts << QgsAuthCertUtils::resolvedCertName( cert );
239 coltxts << QString( cert.serialNumber() );
240 coltxts << cert.expiryDate().toString();
243 QString policy( QgsAuthCertUtils::getCertTrustName( mDefaultTrustPolicy ) );
244 if ( trustedids.contains(
id ) )
248 else if ( untrustedids.contains(
id ) || cert.isBlacklisted() || cert.isNull() || cert.expiryDate() <= QDateTime::currentDateTime() || cert.effectiveDate() > QDateTime::currentDateTime() )
254 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
257 if ( cert.isBlacklisted() || cert.isNull() || cert.expiryDate() <= QDateTime::currentDateTime() || cert.effectiveDate() > QDateTime::currentDateTime() )
259 item->setForeground( 2, redb );
263 if ( trustedids.contains(
id ) )
265 item->setForeground( 3, greenb );
266 if ( !cert.isBlacklisted() && !cert.isNull() && cert.expiryDate() > QDateTime::currentDateTime() && cert.effectiveDate() <= QDateTime::currentDateTime() )
271 else if ( untrustedids.contains(
id ) )
273 item->setForeground( 3, redb );
281 item->setData( 0, Qt::UserRole,
id );
284 parent->sortChildren( 0, Qt::AscendingOrder );
287void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
292void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
294 mActionDefaultTrustPolicy =
new QAction( u
"Change default trust policy"_s,
this );
295 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
297 mActionShowTrustedCAs =
new QAction( u
"Show trusted authorities/issuers"_s,
this );
298 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
300 mUtilitiesMenu =
new QMenu(
this );
301 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
302 mUtilitiesMenu->addSeparator();
303 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
305 btnUtilities->setMenu( mUtilitiesMenu );
308void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
313 const QString digest( item->data( 0, Qt::UserRole ).toString() );
315 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>> cacertscache(
QgsApplication::authManager()->caCertsCache() );
317 if ( !cacertscache.contains( digest ) )
319 QgsDebugError( u
"Certificate Authority not in CA certs cache"_s );
323 const QSslCertificate cert( cacertscache.value( digest ).second );
325 QgsAuthCertInfoDialog *dlg =
new QgsAuthCertInfoDialog( cert,
true,
this );
326 dlg->setWindowModality( Qt::WindowModal );
327 dlg->resize( 675, 500 );
332 populateCaCertsView();
337void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
340 Q_UNUSED( deselected )
344void QgsAuthAuthoritiesEditor::checkSelection()
347 bool isdbcert =
false;
348 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
350 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
352 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
354 case QgsAuthAuthoritiesEditor::RootCaCert:
357 case QgsAuthAuthoritiesEditor::FileCaCert:
360 case QgsAuthAuthoritiesEditor::DbCaCert:
369 btnRemoveCa->setEnabled( isdbcert );
370 btnInfoCa->setEnabled( iscert );
373void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
378 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
380 case QgsAuthAuthoritiesEditor::Section:
383 case QgsAuthAuthoritiesEditor::OrgName:
392 showCertInfo( item );
396void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
399 dlg->setWindowModality( Qt::WindowModal );
400 dlg->resize( 400, 450 );
413 const auto constCerts = certs;
414 for (
const QSslCertificate &cert : constCerts )
418 logMessage( QObject::tr(
"Could not set trust policy for imported certificates" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
422 updateCertTrustPolicyCache();
426 populateDatabaseCaCerts();
427 mDbCaSecItem->setExpanded(
true );
432void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
434 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
442 const QString digest( item->data( 0, Qt::UserRole ).toString() );
444 if ( digest.isEmpty() )
452 if ( !mappedcerts.contains( digest ) )
454 QgsDebugError( u
"Certificate Authority not in mapped database CAs"_s );
458 if ( QMessageBox::warning(
460 tr(
"Remove Certificate Authority" ),
462 "Are you sure you want to remove the selected "
463 "Certificate Authority from the database?\n\n"
464 "Operation can NOT be undone!"
466 QMessageBox::Ok | QMessageBox::Cancel,
469 == QMessageBox::Cancel )
474 const QSslCertificate cert( mappedcerts.value( digest ) );
478 messageBar()->pushMessage( tr(
"Certificate could not be found in the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Warning );
484 messageBar()->pushMessage( tr(
"ERROR removing CA from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
490 messageBar()->pushMessage( tr(
"ERROR removing cert trust policy from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
496 updateCertTrustPolicyCache();
498 item->parent()->removeChild( item );
502 mDbCaSecItem->setExpanded(
true );
505void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
507 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
509 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
510 handleDoubleClick( item, 0 );
514void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
518 logMessage( QObject::tr(
"Could not store sort by preference" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
520 populateCaCertsView();
523void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
525 QDialog *dlg =
new QDialog(
this );
526 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
527 QVBoxLayout *layout =
new QVBoxLayout( dlg );
529 QHBoxLayout *hlayout =
new QHBoxLayout();
531 QLabel *lblwarn =
new QLabel( dlg );
532 QStyle *style = QApplication::style();
533 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
534 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
535 hlayout->addWidget( lblwarn );
537 QLabel *lbltxt =
new QLabel( dlg );
539 "Changing the default certificate authority trust policy to 'Untrusted' "
540 "can cause unexpected SSL network connection results."
542 lbltxt->setWordWrap(
true );
543 hlayout->addWidget( lbltxt );
545 layout->addLayout( hlayout );
547 QHBoxLayout *hlayout2 =
new QHBoxLayout();
549 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
550 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
551 hlayout2->addWidget( lblpolicy );
553 QComboBox *cmbpolicy =
new QComboBox( dlg );
554 QList<QPair<QgsAuthCertUtils::CertTrustPolicy, QString>> policies;
559 for (
int i = 0; i < policies.size(); i++ )
561 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
564 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
565 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
566 hlayout2->addWidget( cmbpolicy );
568 layout->addLayout( hlayout2 );
570 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok, Qt::Horizontal, dlg );
571 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
573 layout->addWidget( buttonBox );
575 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
576 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
578 dlg->setLayout( layout );
579 dlg->setWindowModality( Qt::WindowModal );
580 dlg->resize( 400, 200 );
581 dlg->setMinimumSize( 400, 200 );
582 dlg->setMaximumSize( 500, 300 );
586 if ( mDefaultTrustPolicy != trustpolicy )
588 defaultTrustPolicyChanged( trustpolicy );
598 logMessage( QObject::tr(
"Could not store default trust policy." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Critical );
600 mDefaultTrustPolicy = trustpolicy;
603 populateCaCertsView();
606void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
609 dlg->setWindowModality( Qt::WindowModal );
610 dlg->resize( 400, 250 );
614 if ( !leCaFile->text().isEmpty() )
616 btnCaFileClear_clicked();
620 leCaFile->setText( fn );
624 logMessage( QObject::tr(
"Could not store 'CA file path' in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
628 logMessage( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
636 const auto constCerts = certs;
637 for (
const QSslCertificate &cert : constCerts )
641 logMessage( QObject::tr(
"Could not set trust policy for imported certificates." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
645 updateCertTrustPolicyCache();
650 populateFileCaCerts();
651 mFileCaSecItem->setExpanded(
true );
656void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
660 logMessage( QObject::tr(
"Could not remove 'CA file path' from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
665 logMessage( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
671 const QString fn( leCaFile->text() );
672 if ( QFile::exists( fn ) )
674 const QList<QSslCertificate> certs( QgsAuthCertUtils::certsFromFile( fn ) );
676 if ( !certs.isEmpty() )
684 updateCertTrustPolicyCache();
691 populateFileCaCerts();
694void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
696 QgsAuthTrustedCAsDialog *dlg =
new QgsAuthTrustedCAsDialog(
this );
697 dlg->setWindowModality( Qt::WindowModal );
698 dlg->resize( 675, 500 );
703void QgsAuthAuthoritiesEditor::logMessage(
const QString &message,
const QString &authtag,
Qgis::MessageLevel level )
705 messageBar()->pushMessage( authtag, message, level, 7 );
712 treeWidgetCAs->setFocus();
714 QWidget::showEvent( e );
722int QgsAuthAuthoritiesEditor::messageTimeout()
724 const QgsSettings settings;
725 return settings.
value( u
"qgis/messageTimeout"_s, 5 ).toInt();
MessageLevel
Level for messages This will be used both for message log and message bar in application.
@ Warning
Warning message.
@ Critical
Critical/error message.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
void showEvent(QShowEvent *e) override
Overridden show event of base widget.
QgsAuthAuthoritiesEditor(QWidget *parent=nullptr)
Widget for viewing and editing certificate authorities directly in database.
bool trustCacheRebuilt() const
Whether the trust cache has been rebuilt.
CertTrustPolicy
Type of certificate trust policy.
static QColor greenColor()
Green color representing valid, trusted, etc. certificate.
static void setItemBold(QTreeWidgetItem *item)
Call setFirstColumnSpanned(true) on the item and make its font bold.
static void removeChildren(QTreeWidgetItem *item)
Remove the children of the passed item.
static QColor redColor()
Red color representing invalid, untrusted, etc. certificate.
QgsAuthCertUtils::CertTrustPolicy certTrustPolicy()
Defined trust policy for imported certificates.
const QString certFileToImport()
Gets the file path to a certificate to import.
const QList< QSslCertificate > certificatesToImport()
Gets list of certificate objects to import.
bool allowInvalidCerts()
Whether to allow importation of invalid certificates (so trust policy can be overridden).
const QMap< QgsAuthCertUtils::CertTrustPolicy, QStringList > certTrustCache()
certTrustCache get cache of certificate sha1s, per trust policy
bool rebuildCaCertsCache()
Rebuild certificate authority cache.
void authDatabaseChanged()
Emitted when the authentication db is significantly changed, e.g. large record removal,...
QVariant authSetting(const QString &key, const QVariant &defaultValue=QVariant(), bool decrypt=false)
Returns a previously set authentication setting.
QgsAuthCertUtils::CertTrustPolicy defaultCertTrustPolicy()
Gets the default certificate trust policy preferred by user.
bool rebuildCertTrustCache()
Rebuild certificate authority cache.
void messageLog(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, Qgis::MessageLevel level=Qgis::MessageLevel::Info) const
Custom logging signal to relay to console output and QgsMessageLog.
bool rebuildTrustedCaCertsCache()
Rebuild trusted certificate authorities cache.
A bar for displaying non-blocking messages to the user.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)