17#include "ui_qgsauthauthoritieseditor.h"
41#include <QSslConfiguration>
43#include "moc_qgsauthauthoritieseditor.cpp"
51 mAuthNotifyLayout =
new QVBoxLayout;
52 this->setLayout( mAuthNotifyLayout );
54 mAuthNotifyLayout->addWidget( mAuthNotify );
59 connect( btnAddCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnAddCa_clicked );
60 connect( btnRemoveCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnRemoveCa_clicked );
61 connect( btnInfoCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnInfoCa_clicked );
62 connect( btnGroupByOrg, &QToolButton::toggled,
this, &QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled );
63 connect( btnCaFile, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFile_clicked );
64 connect( btnCaFileClear, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFileClear_clicked );
72 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAuthAuthoritiesEditor::selectionChanged );
74 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
76 connect( btnViewRefresh, &QAbstractButton::clicked,
this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
81 leCaFile->setText( cafileval.toString() );
84 btnGroupByOrg->setChecked(
false );
87 btnGroupByOrg->setChecked( sortbyval.toBool() );
90 populateCaCertsView();
93 populateUtilitiesMenu();
97void QgsAuthAuthoritiesEditor::setupCaCertsTree()
99 treeWidgetCAs->setColumnCount( 4 );
100 treeWidgetCAs->setHeaderLabels(
101 QStringList() << tr(
"Common Name" )
103 << tr(
"Expiry Date" )
104 << tr(
"Trust Policy" )
106 treeWidgetCAs->setColumnWidth( 0, 300 );
107 treeWidgetCAs->setColumnWidth( 1, 75 );
108 treeWidgetCAs->setColumnWidth( 2, 200 );
111 mDbCaSecItem =
new QTreeWidgetItem(
114 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
117 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
118 mDbCaSecItem->setExpanded(
true );
119 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
121 mFileCaSecItem =
new QTreeWidgetItem(
124 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
127 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
128 mFileCaSecItem->setExpanded(
true );
129 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
131 mRootCaSecItem =
new QTreeWidgetItem(
134 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
137 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
138 mRootCaSecItem->setExpanded(
false );
139 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
142void QgsAuthAuthoritiesEditor::populateCaCertsView()
144 updateCertTrustPolicyCache();
145 populateDatabaseCaCerts();
146 populateFileCaCerts();
147 populateRootCaCerts();
150void QgsAuthAuthoritiesEditor::refreshCaCertsView()
153 populateCaCertsView();
156void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
160 const bool expanded = mDbCaSecItem->isExpanded();
162 mDbCaSecItem->setExpanded( expanded );
165void QgsAuthAuthoritiesEditor::populateFileCaCerts()
169 const bool expanded = mFileCaSecItem->isExpanded();
171 mFileCaSecItem->setExpanded( expanded );
174void QgsAuthAuthoritiesEditor::populateRootCaCerts()
178 const bool expanded = mRootCaSecItem->isExpanded();
180 mRootCaSecItem->setExpanded( expanded );
183void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype )
185 if ( btnGroupByOrg->isChecked() )
187 appendCertsToGroup( certs, catype, item );
191 appendCertsToItem( certs, catype, item );
195void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
202 parent = treeWidgetCAs->currentItem();
206 const QMap<QString, QList<QSslCertificate>> orgcerts(
210 QMap<QString, QList<QSslCertificate>>::const_iterator it = orgcerts.constBegin();
211 for ( ; it != orgcerts.constEnd(); ++it )
213 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent, QStringList() << it.key(),
static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
214 grpitem->setFirstColumnSpanned(
true );
215 grpitem->setFlags( Qt::ItemIsEnabled );
216 grpitem->setExpanded(
true );
218 QBrush orgb( grpitem->foreground( 0 ) );
219 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
220 grpitem->setForeground( 0, orgb );
221 QFont grpf( grpitem->font( 0 ) );
222 grpf.setItalic(
true );
223 grpitem->setFont( 0, grpf );
225 appendCertsToItem( it.value(), catype, grpitem );
228 parent->sortChildren( 0, Qt::AscendingOrder );
231void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
238 parent = treeWidgetCAs->currentItem();
248 const auto constCerts = certs;
249 for (
const QSslCertificate &cert : constCerts )
255 coltxts << QString( cert.serialNumber() );
256 coltxts << cert.expiryDate().toString();
260 if ( trustedids.contains(
id ) )
264 else if ( untrustedids.contains(
id )
265 || cert.isBlacklisted()
267 || cert.expiryDate() <= QDateTime::currentDateTime()
268 || cert.effectiveDate() > QDateTime::currentDateTime() )
274 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
277 if ( cert.isBlacklisted()
279 || cert.expiryDate() <= QDateTime::currentDateTime()
280 || cert.effectiveDate() > QDateTime::currentDateTime() )
282 item->setForeground( 2, redb );
286 if ( trustedids.contains(
id ) )
288 item->setForeground( 3, greenb );
289 if ( !cert.isBlacklisted()
291 && cert.expiryDate() > QDateTime::currentDateTime()
292 && cert.effectiveDate() <= QDateTime::currentDateTime() )
297 else if ( untrustedids.contains(
id ) )
299 item->setForeground( 3, redb );
307 item->setData( 0, Qt::UserRole,
id );
310 parent->sortChildren( 0, Qt::AscendingOrder );
313void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
318void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
320 mActionDefaultTrustPolicy =
new QAction( QStringLiteral(
"Change default trust policy" ),
this );
321 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
323 mActionShowTrustedCAs =
new QAction( QStringLiteral(
"Show trusted authorities/issuers" ),
this );
324 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
326 mUtilitiesMenu =
new QMenu(
this );
327 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
328 mUtilitiesMenu->addSeparator();
329 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
331 btnUtilities->setMenu( mUtilitiesMenu );
334void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
339 const QString digest( item->data( 0, Qt::UserRole ).toString() );
341 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>> cacertscache(
345 if ( !cacertscache.contains( digest ) )
347 QgsDebugError( QStringLiteral(
"Certificate Authority not in CA certs cache" ) );
351 const QSslCertificate cert( cacertscache.value( digest ).second );
353 QgsAuthCertInfoDialog *dlg =
new QgsAuthCertInfoDialog( cert,
true,
this );
354 dlg->setWindowModality( Qt::WindowModal );
355 dlg->resize( 675, 500 );
360 populateCaCertsView();
365void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
368 Q_UNUSED( deselected )
372void QgsAuthAuthoritiesEditor::checkSelection()
375 bool isdbcert =
false;
376 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
378 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
380 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
382 case QgsAuthAuthoritiesEditor::RootCaCert:
385 case QgsAuthAuthoritiesEditor::FileCaCert:
388 case QgsAuthAuthoritiesEditor::DbCaCert:
397 btnRemoveCa->setEnabled( isdbcert );
398 btnInfoCa->setEnabled( iscert );
401void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
406 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
408 case QgsAuthAuthoritiesEditor::Section:
411 case QgsAuthAuthoritiesEditor::OrgName:
420 showCertInfo( item );
424void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
427 dlg->setWindowModality( Qt::WindowModal );
428 dlg->resize( 400, 450 );
441 const auto constCerts = certs;
442 for (
const QSslCertificate &cert : constCerts )
446 logMessage( QObject::tr(
"Could not set trust policy for imported certificates" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
450 updateCertTrustPolicyCache();
454 populateDatabaseCaCerts();
455 mDbCaSecItem->setExpanded(
true );
460void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
462 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
466 QgsDebugMsgLevel( QStringLiteral(
"Current tree widget item not set" ), 2 );
470 const QString digest( item->data( 0, Qt::UserRole ).toString() );
472 if ( digest.isEmpty() )
478 const QMap<QString, QSslCertificate> mappedcerts(
482 if ( !mappedcerts.contains( digest ) )
484 QgsDebugError( QStringLiteral(
"Certificate Authority not in mapped database CAs" ) );
488 if ( QMessageBox::warning(
489 this, tr(
"Remove Certificate Authority" ),
490 tr(
"Are you sure you want to remove the selected "
491 "Certificate Authority from the database?\n\n"
492 "Operation can NOT be undone!" ),
493 QMessageBox::Ok | QMessageBox::Cancel,
496 == QMessageBox::Cancel )
501 const QSslCertificate cert( mappedcerts.value( digest ) );
505 messageBar()->pushMessage( tr(
"Certificate could not be found in the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Warning );
511 messageBar()->pushMessage( tr(
"ERROR removing CA from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
517 messageBar()->pushMessage( tr(
"ERROR removing cert trust policy from the authentication storage for id %1:" ).arg( digest ),
Qgis::MessageLevel::Critical );
523 updateCertTrustPolicyCache();
525 item->parent()->removeChild( item );
529 mDbCaSecItem->setExpanded(
true );
532void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
534 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
536 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
537 handleDoubleClick( item, 0 );
541void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
545 logMessage( QObject::tr(
"Could not store sort by preference" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
547 populateCaCertsView();
550void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
552 QDialog *dlg =
new QDialog(
this );
553 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
554 QVBoxLayout *layout =
new QVBoxLayout( dlg );
556 QHBoxLayout *hlayout =
new QHBoxLayout();
558 QLabel *lblwarn =
new QLabel( dlg );
559 QStyle *style = QApplication::style();
560 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
561 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
562 hlayout->addWidget( lblwarn );
564 QLabel *lbltxt =
new QLabel( dlg );
565 lbltxt->setText( tr(
"Changing the default certificate authority trust policy to 'Untrusted' "
566 "can cause unexpected SSL network connection results." ) );
567 lbltxt->setWordWrap(
true );
568 hlayout->addWidget( lbltxt );
570 layout->addLayout( hlayout );
572 QHBoxLayout *hlayout2 =
new QHBoxLayout();
574 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
575 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
576 hlayout2->addWidget( lblpolicy );
578 QComboBox *cmbpolicy =
new QComboBox( dlg );
579 QList<QPair<QgsAuthCertUtils::CertTrustPolicy, QString>> policies;
583 for (
int i = 0; i < policies.size(); i++ )
585 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
588 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
589 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
590 hlayout2->addWidget( cmbpolicy );
592 layout->addLayout( hlayout2 );
594 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok, Qt::Horizontal, dlg );
595 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
597 layout->addWidget( buttonBox );
599 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
600 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
602 dlg->setLayout( layout );
603 dlg->setWindowModality( Qt::WindowModal );
604 dlg->resize( 400, 200 );
605 dlg->setMinimumSize( 400, 200 );
606 dlg->setMaximumSize( 500, 300 );
612 if ( mDefaultTrustPolicy != trustpolicy )
614 defaultTrustPolicyChanged( trustpolicy );
624 logMessage( QObject::tr(
"Could not store default trust policy." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Critical );
626 mDefaultTrustPolicy = trustpolicy;
629 populateCaCertsView();
632void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
635 dlg->setWindowModality( Qt::WindowModal );
636 dlg->resize( 400, 250 );
640 if ( !leCaFile->text().isEmpty() )
642 btnCaFileClear_clicked();
646 leCaFile->setText( fn );
650 logMessage( QObject::tr(
"Could not store 'CA file path' in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
654 logMessage( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
662 const auto constCerts = certs;
663 for (
const QSslCertificate &cert : constCerts )
667 logMessage( QObject::tr(
"Could not set trust policy for imported certificates." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
671 updateCertTrustPolicyCache();
676 populateFileCaCerts();
677 mFileCaSecItem->setExpanded(
true );
682void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
686 logMessage( QObject::tr(
"Could not remove 'CA file path' from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
691 logMessage( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication storage." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
697 const QString fn( leCaFile->text() );
698 if ( QFile::exists( fn ) )
702 if ( !certs.isEmpty() )
710 updateCertTrustPolicyCache();
717 populateFileCaCerts();
720void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
722 QgsAuthTrustedCAsDialog *dlg =
new QgsAuthTrustedCAsDialog(
this );
723 dlg->setWindowModality( Qt::WindowModal );
724 dlg->resize( 675, 500 );
729void QgsAuthAuthoritiesEditor::logMessage(
const QString &message,
const QString &authtag,
Qgis::MessageLevel level )
731 messageBar()->pushMessage( authtag, message, level, 7 );
738 treeWidgetCAs->setFocus();
740 QWidget::showEvent( e );
748int QgsAuthAuthoritiesEditor::messageTimeout()
750 const QgsSettings settings;
751 return settings.
value( QStringLiteral(
"qgis/messageTimeout" ), 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.
static QString resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Gets the general name via RFC 5280 resolution.
static QMap< QString, QList< QSslCertificate > > certsGroupedByOrg(const QList< QSslCertificate > &certs)
Map certificates to their oraganization.
static QString getCertTrustName(QgsAuthCertUtils::CertTrustPolicy trust)
Gets the general name for certificate trust.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
CertTrustPolicy
Type of certificate trust policy.
static QList< QSslCertificate > certsFromFile(const QString &certspath)
Returns a list of concatenated certs from a PEM or DER formatted file.
static QString getCaSourceName(QgsAuthCertUtils::CaCertSource source, bool single=false)
Gets the general name for CA source enum type.
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)