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(
104 QStringList() << tr(
"Common Name" )
106 << tr(
"Expiry Date" )
107 << tr(
"Trust Policy" )
109 treeWidgetCAs->setColumnWidth( 0, 300 );
110 treeWidgetCAs->setColumnWidth( 1, 75 );
111 treeWidgetCAs->setColumnWidth( 2, 200 );
114 mDbCaSecItem =
new QTreeWidgetItem(
117 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
120 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
121 mDbCaSecItem->setExpanded(
true );
122 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
124 mFileCaSecItem =
new QTreeWidgetItem(
127 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
130 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
131 mFileCaSecItem->setExpanded(
true );
132 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
134 mRootCaSecItem =
new QTreeWidgetItem(
137 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
140 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
141 mRootCaSecItem->setExpanded(
false );
142 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
145void QgsAuthAuthoritiesEditor::populateCaCertsView()
147 updateCertTrustPolicyCache();
148 populateDatabaseCaCerts();
149 populateFileCaCerts();
150 populateRootCaCerts();
153void QgsAuthAuthoritiesEditor::refreshCaCertsView()
156 populateCaCertsView();
159void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
163 const bool expanded = mDbCaSecItem->isExpanded();
165 mDbCaSecItem->setExpanded( expanded );
168void QgsAuthAuthoritiesEditor::populateFileCaCerts()
172 const bool expanded = mFileCaSecItem->isExpanded();
174 mFileCaSecItem->setExpanded( expanded );
177void QgsAuthAuthoritiesEditor::populateRootCaCerts()
181 const bool expanded = mRootCaSecItem->isExpanded();
183 mRootCaSecItem->setExpanded( expanded );
186void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype )
188 if ( btnGroupByOrg->isChecked() )
190 appendCertsToGroup( certs, catype, item );
194 appendCertsToItem( certs, catype, item );
198void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
205 parent = treeWidgetCAs->currentItem();
209 const QMap<QString, QList<QSslCertificate>> orgcerts(
210 QgsAuthCertUtils::certsGroupedByOrg( certs )
213 QMap<QString, QList<QSslCertificate>>::const_iterator it = orgcerts.constBegin();
214 for ( ; it != orgcerts.constEnd(); ++it )
216 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent, QStringList() << it.key(),
static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
217 grpitem->setFirstColumnSpanned(
true );
218 grpitem->setFlags( Qt::ItemIsEnabled );
219 grpitem->setExpanded(
true );
221 QBrush orgb( grpitem->foreground( 0 ) );
222 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
223 grpitem->setForeground( 0, orgb );
224 QFont grpf( grpitem->font( 0 ) );
225 grpf.setItalic(
true );
226 grpitem->setFont( 0, grpf );
228 appendCertsToItem( it.value(), catype, grpitem );
231 parent->sortChildren( 0, Qt::AscendingOrder );
234void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
241 parent = treeWidgetCAs->currentItem();
251 const auto constCerts = certs;
252 for (
const QSslCertificate &cert : constCerts )
254 const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
257 coltxts << QgsAuthCertUtils::resolvedCertName( cert );
258 coltxts << QString( cert.serialNumber() );
259 coltxts << cert.expiryDate().toString();
262 QString policy( QgsAuthCertUtils::getCertTrustName( mDefaultTrustPolicy ) );
263 if ( trustedids.contains(
id ) )
267 else if ( untrustedids.contains(
id )
268 || cert.isBlacklisted()
270 || cert.expiryDate() <= QDateTime::currentDateTime()
271 || cert.effectiveDate() > QDateTime::currentDateTime() )
277 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
280 if ( cert.isBlacklisted()
282 || cert.expiryDate() <= QDateTime::currentDateTime()
283 || cert.effectiveDate() > QDateTime::currentDateTime() )
285 item->setForeground( 2, redb );
289 if ( trustedids.contains(
id ) )
291 item->setForeground( 3, greenb );
292 if ( !cert.isBlacklisted()
294 && cert.expiryDate() > QDateTime::currentDateTime()
295 && cert.effectiveDate() <= QDateTime::currentDateTime() )
300 else if ( untrustedids.contains(
id ) )
302 item->setForeground( 3, redb );
310 item->setData( 0, Qt::UserRole,
id );
313 parent->sortChildren( 0, Qt::AscendingOrder );
316void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
321void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
323 mActionDefaultTrustPolicy =
new QAction( u
"Change default trust policy"_s,
this );
324 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
326 mActionShowTrustedCAs =
new QAction( u
"Show trusted authorities/issuers"_s,
this );
327 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
329 mUtilitiesMenu =
new QMenu(
this );
330 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
331 mUtilitiesMenu->addSeparator();
332 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
334 btnUtilities->setMenu( mUtilitiesMenu );
337void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
342 const QString digest( item->data( 0, Qt::UserRole ).toString() );
344 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>> cacertscache(
348 if ( !cacertscache.contains( digest ) )
350 QgsDebugError( u
"Certificate Authority not in CA certs cache"_s );
354 const QSslCertificate cert( cacertscache.value( digest ).second );
356 QgsAuthCertInfoDialog *dlg =
new QgsAuthCertInfoDialog( cert,
true,
this );
357 dlg->setWindowModality( Qt::WindowModal );
358 dlg->resize( 675, 500 );
363 populateCaCertsView();
368void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
371 Q_UNUSED( deselected )
375void QgsAuthAuthoritiesEditor::checkSelection()
378 bool isdbcert =
false;
379 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
381 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
383 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
385 case QgsAuthAuthoritiesEditor::RootCaCert:
388 case QgsAuthAuthoritiesEditor::FileCaCert:
391 case QgsAuthAuthoritiesEditor::DbCaCert:
400 btnRemoveCa->setEnabled( isdbcert );
401 btnInfoCa->setEnabled( iscert );
404void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
409 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
411 case QgsAuthAuthoritiesEditor::Section:
414 case QgsAuthAuthoritiesEditor::OrgName:
423 showCertInfo( item );
427void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
430 dlg->setWindowModality( Qt::WindowModal );
431 dlg->resize( 400, 450 );
444 const auto constCerts = certs;
445 for (
const QSslCertificate &cert : constCerts )
449 logMessage( QObject::tr(
"Could not set trust policy for imported certificates" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
453 updateCertTrustPolicyCache();
457 populateDatabaseCaCerts();
458 mDbCaSecItem->setExpanded(
true );
463void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
465 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
473 const QString digest( item->data( 0, Qt::UserRole ).toString() );
475 if ( digest.isEmpty() )
481 const QMap<QString, QSslCertificate> mappedcerts(
485 if ( !mappedcerts.contains( digest ) )
487 QgsDebugError( u
"Certificate Authority not in mapped database CAs"_s );
491 if ( QMessageBox::warning(
492 this, tr(
"Remove Certificate Authority" ),
493 tr(
"Are you sure you want to remove the selected "
494 "Certificate Authority from the database?\n\n"
495 "Operation can NOT be undone!" ),
496 QMessageBox::Ok | QMessageBox::Cancel,
499 == QMessageBox::Cancel )
504 const QSslCertificate cert( mappedcerts.value( digest ) );
508 messageBar()->pushMessage( tr(
"Certificate could not be found in the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Warning );
514 messageBar()->pushMessage( tr(
"ERROR removing CA from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
520 messageBar()->pushMessage( tr(
"ERROR removing cert trust policy from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
526 updateCertTrustPolicyCache();
528 item->parent()->removeChild( item );
532 mDbCaSecItem->setExpanded(
true );
535void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
537 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
539 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
540 handleDoubleClick( item, 0 );
544void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
548 logMessage( QObject::tr(
"Could not store sort by preference" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
550 populateCaCertsView();
553void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
555 QDialog *dlg =
new QDialog(
this );
556 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
557 QVBoxLayout *layout =
new QVBoxLayout( dlg );
559 QHBoxLayout *hlayout =
new QHBoxLayout();
561 QLabel *lblwarn =
new QLabel( dlg );
562 QStyle *style = QApplication::style();
563 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
564 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
565 hlayout->addWidget( lblwarn );
567 QLabel *lbltxt =
new QLabel( dlg );
568 lbltxt->setText( tr(
"Changing the default certificate authority trust policy to 'Untrusted' "
569 "can cause unexpected SSL network connection results." ) );
570 lbltxt->setWordWrap(
true );
571 hlayout->addWidget( lbltxt );
573 layout->addLayout( hlayout );
575 QHBoxLayout *hlayout2 =
new QHBoxLayout();
577 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
578 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
579 hlayout2->addWidget( lblpolicy );
581 QComboBox *cmbpolicy =
new QComboBox( dlg );
582 QList<QPair<QgsAuthCertUtils::CertTrustPolicy, QString>> policies;
586 for (
int i = 0; i < policies.size(); i++ )
588 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
591 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
592 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
593 hlayout2->addWidget( cmbpolicy );
595 layout->addLayout( hlayout2 );
597 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok, Qt::Horizontal, dlg );
598 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
600 layout->addWidget( buttonBox );
602 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
603 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
605 dlg->setLayout( layout );
606 dlg->setWindowModality( Qt::WindowModal );
607 dlg->resize( 400, 200 );
608 dlg->setMinimumSize( 400, 200 );
609 dlg->setMaximumSize( 500, 300 );
615 if ( mDefaultTrustPolicy != trustpolicy )
617 defaultTrustPolicyChanged( trustpolicy );
627 logMessage( QObject::tr(
"Could not store default trust policy." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Critical );
629 mDefaultTrustPolicy = trustpolicy;
632 populateCaCertsView();
635void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
638 dlg->setWindowModality( Qt::WindowModal );
639 dlg->resize( 400, 250 );
643 if ( !leCaFile->text().isEmpty() )
645 btnCaFileClear_clicked();
649 leCaFile->setText( fn );
653 logMessage( QObject::tr(
"Could not store 'CA file path' in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
657 logMessage( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
665 const auto constCerts = certs;
666 for (
const QSslCertificate &cert : constCerts )
670 logMessage( QObject::tr(
"Could not set trust policy for imported certificates." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
674 updateCertTrustPolicyCache();
679 populateFileCaCerts();
680 mFileCaSecItem->setExpanded(
true );
685void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
689 logMessage( QObject::tr(
"Could not remove 'CA file path' from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
694 logMessage( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
700 const QString fn( leCaFile->text() );
701 if ( QFile::exists( fn ) )
703 const QList<QSslCertificate> certs( QgsAuthCertUtils::certsFromFile( fn ) );
705 if ( !certs.isEmpty() )
713 updateCertTrustPolicyCache();
720 populateFileCaCerts();
723void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
725 QgsAuthTrustedCAsDialog *dlg =
new QgsAuthTrustedCAsDialog(
this );
726 dlg->setWindowModality( Qt::WindowModal );
727 dlg->resize( 675, 500 );
732void QgsAuthAuthoritiesEditor::logMessage(
const QString &message,
const QString &authtag,
Qgis::MessageLevel level )
734 messageBar()->pushMessage( authtag, message, level, 7 );
741 treeWidgetCAs->setFocus();
743 QWidget::showEvent( e );
751int QgsAuthAuthoritiesEditor::messageTimeout()
753 const QgsSettings settings;
754 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)