17#include "ui_qgsauthauthoritieseditor.h"
42#include <QSslConfiguration>
45#include "moc_qgsauthauthoritieseditor.cpp"
47using namespace Qt::StringLiterals;
55 mAuthNotifyLayout =
new QVBoxLayout;
56 this->setLayout( mAuthNotifyLayout );
58 mAuthNotifyLayout->addWidget( mAuthNotify );
63 connect( btnAddCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnAddCa_clicked );
64 connect( btnRemoveCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnRemoveCa_clicked );
65 connect( btnInfoCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnInfoCa_clicked );
66 connect( btnGroupByOrg, &QToolButton::toggled,
this, &QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled );
67 connect( btnCaFile, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFile_clicked );
68 connect( btnCaFileClear, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFileClear_clicked );
76 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAuthAuthoritiesEditor::selectionChanged );
78 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
80 connect( btnViewRefresh, &QAbstractButton::clicked,
this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
85 leCaFile->setText( cafileval.toString() );
88 btnGroupByOrg->setChecked(
false );
91 btnGroupByOrg->setChecked( sortbyval.toBool() );
94 populateCaCertsView();
97 populateUtilitiesMenu();
101void QgsAuthAuthoritiesEditor::setupCaCertsTree()
103 treeWidgetCAs->setColumnCount( 4 );
104 treeWidgetCAs->setHeaderLabels( QStringList() << tr(
"Common Name" ) << tr(
"Serial #" ) << tr(
"Expiry Date" ) << tr(
"Trust Policy" ) );
105 treeWidgetCAs->setColumnWidth( 0, 300 );
106 treeWidgetCAs->setColumnWidth( 1, 75 );
107 treeWidgetCAs->setColumnWidth( 2, 200 );
110 mDbCaSecItem =
new QTreeWidgetItem( treeWidgetCAs, QStringList( QgsAuthCertUtils::getCaSourceName(
QgsAuthCertUtils::InDatabase ) ),
static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
112 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
113 mDbCaSecItem->setExpanded(
true );
114 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
116 mFileCaSecItem =
new QTreeWidgetItem( treeWidgetCAs, QStringList( QgsAuthCertUtils::getCaSourceName(
QgsAuthCertUtils::FromFile ) ),
static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
118 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
119 mFileCaSecItem->setExpanded(
true );
120 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
122 mRootCaSecItem =
new QTreeWidgetItem( treeWidgetCAs, QStringList( QgsAuthCertUtils::getCaSourceName(
QgsAuthCertUtils::SystemRoot ) ),
static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
124 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
125 mRootCaSecItem->setExpanded(
false );
126 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
129void QgsAuthAuthoritiesEditor::populateCaCertsView()
131 updateCertTrustPolicyCache();
132 populateDatabaseCaCerts();
133 populateFileCaCerts();
134 populateRootCaCerts();
137void QgsAuthAuthoritiesEditor::refreshCaCertsView()
140 populateCaCertsView();
143void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
147 const bool expanded = mDbCaSecItem->isExpanded();
149 mDbCaSecItem->setExpanded( expanded );
152void QgsAuthAuthoritiesEditor::populateFileCaCerts()
156 const bool expanded = mFileCaSecItem->isExpanded();
158 mFileCaSecItem->setExpanded( expanded );
161void QgsAuthAuthoritiesEditor::populateRootCaCerts()
165 const bool expanded = mRootCaSecItem->isExpanded();
167 mRootCaSecItem->setExpanded( expanded );
170void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype )
172 if ( btnGroupByOrg->isChecked() )
174 appendCertsToGroup( certs, catype, item );
178 appendCertsToItem( certs, catype, item );
182void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
189 parent = treeWidgetCAs->currentItem();
193 const QMap<QString, QList<QSslCertificate>> orgcerts( QgsAuthCertUtils::certsGroupedByOrg( certs ) );
195 QMap<QString, QList<QSslCertificate>>::const_iterator it = orgcerts.constBegin();
196 for ( ; it != orgcerts.constEnd(); ++it )
198 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent, QStringList() << it.key(),
static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
199 grpitem->setFirstColumnSpanned(
true );
200 grpitem->setFlags( Qt::ItemIsEnabled );
201 grpitem->setExpanded(
true );
203 QBrush orgb( grpitem->foreground( 0 ) );
204 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
205 grpitem->setForeground( 0, orgb );
206 QFont grpf( grpitem->font( 0 ) );
207 grpf.setItalic(
true );
208 grpitem->setFont( 0, grpf );
210 appendCertsToItem( it.value(), catype, grpitem );
213 parent->sortChildren( 0, Qt::AscendingOrder );
216void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
223 parent = treeWidgetCAs->currentItem();
233 const auto constCerts = certs;
234 for (
const QSslCertificate &cert : constCerts )
236 const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
239 coltxts << QgsAuthCertUtils::resolvedCertName( cert );
240 coltxts << QString( cert.serialNumber() );
241 coltxts << cert.expiryDate().toString();
244 QString policy( QgsAuthCertUtils::getCertTrustName( mDefaultTrustPolicy ) );
245 if ( trustedids.contains(
id ) )
249 else if ( untrustedids.contains(
id ) || cert.isBlacklisted() || cert.isNull() || cert.expiryDate() <= QDateTime::currentDateTime() || cert.effectiveDate() > QDateTime::currentDateTime() )
255 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
258 if ( cert.isBlacklisted() || cert.isNull() || cert.expiryDate() <= QDateTime::currentDateTime() || cert.effectiveDate() > QDateTime::currentDateTime() )
260 item->setForeground( 2, redb );
264 if ( trustedids.contains(
id ) )
266 item->setForeground( 3, greenb );
267 if ( !cert.isBlacklisted() && !cert.isNull() && cert.expiryDate() > QDateTime::currentDateTime() && cert.effectiveDate() <= QDateTime::currentDateTime() )
272 else if ( untrustedids.contains(
id ) )
274 item->setForeground( 3, redb );
282 item->setData( 0, Qt::UserRole,
id );
285 parent->sortChildren( 0, Qt::AscendingOrder );
288void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
293void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
295 mActionDefaultTrustPolicy =
new QAction( u
"Change default trust policy"_s,
this );
296 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
298 mActionShowTrustedCAs =
new QAction( u
"Show trusted authorities/issuers"_s,
this );
299 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
301 mUtilitiesMenu =
new QMenu(
this );
302 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
303 mUtilitiesMenu->addSeparator();
304 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
306 btnUtilities->setMenu( mUtilitiesMenu );
309void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
314 const QString digest( item->data( 0, Qt::UserRole ).toString() );
316 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>> cacertscache(
QgsApplication::authManager()->caCertsCache() );
318 if ( !cacertscache.contains( digest ) )
320 QgsDebugError( u
"Certificate Authority not in CA certs cache"_s );
324 const QSslCertificate cert( cacertscache.value( digest ).second );
326 QgsAuthCertInfoDialog *dlg =
new QgsAuthCertInfoDialog( cert,
true,
this );
327 dlg->setWindowModality( Qt::WindowModal );
328 dlg->resize( 675, 500 );
333 populateCaCertsView();
338void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
341 Q_UNUSED( deselected )
345void QgsAuthAuthoritiesEditor::checkSelection()
348 bool isdbcert =
false;
349 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
351 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
353 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
355 case QgsAuthAuthoritiesEditor::RootCaCert:
358 case QgsAuthAuthoritiesEditor::FileCaCert:
361 case QgsAuthAuthoritiesEditor::DbCaCert:
370 btnRemoveCa->setEnabled( isdbcert );
371 btnInfoCa->setEnabled( iscert );
374void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
379 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
381 case QgsAuthAuthoritiesEditor::Section:
384 case QgsAuthAuthoritiesEditor::OrgName:
393 showCertInfo( item );
397void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
400 dlg->setWindowModality( Qt::WindowModal );
401 dlg->resize( 400, 450 );
414 const auto constCerts = certs;
415 for (
const QSslCertificate &cert : constCerts )
419 logMessage( QObject::tr(
"Could not set trust policy for imported certificates" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
423 updateCertTrustPolicyCache();
427 populateDatabaseCaCerts();
428 mDbCaSecItem->setExpanded(
true );
433void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
435 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
443 const QString digest( item->data( 0, Qt::UserRole ).toString() );
445 if ( digest.isEmpty() )
453 if ( !mappedcerts.contains( digest ) )
455 QgsDebugError( u
"Certificate Authority not in mapped database CAs"_s );
459 if ( QMessageBox::warning(
461 tr(
"Remove Certificate Authority" ),
463 "Are you sure you want to remove the selected "
464 "Certificate Authority from the database?\n\n"
465 "Operation can NOT be undone!"
467 QMessageBox::Ok | QMessageBox::Cancel,
470 == QMessageBox::Cancel )
475 const QSslCertificate cert( mappedcerts.value( digest ) );
479 messageBar()->pushMessage( tr(
"Certificate could not be found in the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Warning );
485 messageBar()->pushMessage( tr(
"ERROR removing CA from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
491 messageBar()->pushMessage( tr(
"ERROR removing cert trust policy from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
497 updateCertTrustPolicyCache();
499 item->parent()->removeChild( item );
503 mDbCaSecItem->setExpanded(
true );
506void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
508 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
510 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
511 handleDoubleClick( item, 0 );
515void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
519 logMessage( QObject::tr(
"Could not store sort by preference" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
521 populateCaCertsView();
524void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
526 QDialog *dlg =
new QDialog(
this );
527 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
528 QVBoxLayout *layout =
new QVBoxLayout( dlg );
530 QHBoxLayout *hlayout =
new QHBoxLayout();
532 QLabel *lblwarn =
new QLabel( dlg );
533 QStyle *style = QApplication::style();
534 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
535 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
536 hlayout->addWidget( lblwarn );
538 QLabel *lbltxt =
new QLabel( dlg );
540 "Changing the default certificate authority trust policy to 'Untrusted' "
541 "can cause unexpected SSL network connection results."
543 lbltxt->setWordWrap(
true );
544 hlayout->addWidget( lbltxt );
546 layout->addLayout( hlayout );
548 QHBoxLayout *hlayout2 =
new QHBoxLayout();
550 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
551 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
552 hlayout2->addWidget( lblpolicy );
554 QComboBox *cmbpolicy =
new QComboBox( dlg );
555 QList<QPair<QgsAuthCertUtils::CertTrustPolicy, QString>> policies;
560 for (
int i = 0; i < policies.size(); i++ )
562 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
565 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
566 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
567 hlayout2->addWidget( cmbpolicy );
569 layout->addLayout( hlayout2 );
571 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok, Qt::Horizontal, dlg );
572 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
574 layout->addWidget( buttonBox );
576 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
577 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
579 dlg->setLayout( layout );
580 dlg->setWindowModality( Qt::WindowModal );
581 dlg->resize( 400, 200 );
582 dlg->setMinimumSize( 400, 200 );
583 dlg->setMaximumSize( 500, 300 );
587 if ( mDefaultTrustPolicy != trustpolicy )
589 defaultTrustPolicyChanged( trustpolicy );
599 logMessage( QObject::tr(
"Could not store default trust policy." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Critical );
601 mDefaultTrustPolicy = trustpolicy;
604 populateCaCertsView();
607void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
610 dlg->setWindowModality( Qt::WindowModal );
611 dlg->resize( 400, 250 );
615 if ( !leCaFile->text().isEmpty() )
617 btnCaFileClear_clicked();
621 leCaFile->setText( fn );
625 logMessage( QObject::tr(
"Could not store 'CA file path' in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
629 logMessage( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
637 const auto constCerts = certs;
638 for (
const QSslCertificate &cert : constCerts )
642 logMessage( QObject::tr(
"Could not set trust policy for imported certificates." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
646 updateCertTrustPolicyCache();
651 populateFileCaCerts();
652 mFileCaSecItem->setExpanded(
true );
657void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
661 logMessage( QObject::tr(
"Could not remove 'CA file path' from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
666 logMessage( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
672 const QString fn( leCaFile->text() );
673 if ( QFile::exists( fn ) )
675 const QList<QSslCertificate> certs( QgsAuthCertUtils::certsFromFile( fn ) );
677 if ( !certs.isEmpty() )
685 updateCertTrustPolicyCache();
692 populateFileCaCerts();
695void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
697 QgsAuthTrustedCAsDialog *dlg =
new QgsAuthTrustedCAsDialog(
this );
698 dlg->setWindowModality( Qt::WindowModal );
699 dlg->resize( 675, 500 );
704void QgsAuthAuthoritiesEditor::logMessage(
const QString &message,
const QString &authtag,
Qgis::MessageLevel level )
706 messageBar()->pushMessage( authtag, message, level, 7 );
713 treeWidgetCAs->setFocus();
715 QWidget::showEvent( e );
723int QgsAuthAuthoritiesEditor::messageTimeout()
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.
T value(const QString &dynamicKeyPart=QString()) const
Returns settings value.
static const QgsSettingsEntryInteger * settingsMessageTimeout
Settings entry message timeout in seconds.
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)