18#include "moc_qgsauthauthoritieseditor.cpp"
19#include "ui_qgsauthauthoritieseditor.h"
31#include <QSslConfiguration>
50 mAuthNotifyLayout =
new QVBoxLayout;
51 this->setLayout( mAuthNotifyLayout );
53 mAuthNotifyLayout->addWidget( mAuthNotify );
58 connect( btnAddCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnAddCa_clicked );
59 connect( btnRemoveCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnRemoveCa_clicked );
60 connect( btnInfoCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnInfoCa_clicked );
61 connect( btnGroupByOrg, &QToolButton::toggled,
this, &QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled );
62 connect( btnCaFile, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFile_clicked );
63 connect( btnCaFileClear, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFileClear_clicked );
71 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsAuthAuthoritiesEditor::selectionChanged );
73 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
75 connect( btnViewRefresh, &QAbstractButton::clicked,
this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
80 leCaFile->setText( cafileval.toString() );
83 btnGroupByOrg->setChecked(
false );
86 btnGroupByOrg->setChecked( sortbyval.toBool() );
89 populateCaCertsView();
92 populateUtilitiesMenu();
96void QgsAuthAuthoritiesEditor::setupCaCertsTree()
98 treeWidgetCAs->setColumnCount( 4 );
99 treeWidgetCAs->setHeaderLabels(
100 QStringList() << tr(
"Common Name" )
102 << tr(
"Expiry Date" )
103 << tr(
"Trust Policy" )
105 treeWidgetCAs->setColumnWidth( 0, 300 );
106 treeWidgetCAs->setColumnWidth( 1, 75 );
107 treeWidgetCAs->setColumnWidth( 2, 200 );
110 mDbCaSecItem =
new QTreeWidgetItem(
113 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
116 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
117 mDbCaSecItem->setExpanded(
true );
118 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
120 mFileCaSecItem =
new QTreeWidgetItem(
123 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
126 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
127 mFileCaSecItem->setExpanded(
true );
128 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
130 mRootCaSecItem =
new QTreeWidgetItem(
133 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
136 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
137 mRootCaSecItem->setExpanded(
false );
138 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
141void QgsAuthAuthoritiesEditor::populateCaCertsView()
143 updateCertTrustPolicyCache();
144 populateDatabaseCaCerts();
145 populateFileCaCerts();
146 populateRootCaCerts();
149void QgsAuthAuthoritiesEditor::refreshCaCertsView()
152 populateCaCertsView();
155void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
159 const bool expanded = mDbCaSecItem->isExpanded();
161 mDbCaSecItem->setExpanded( expanded );
164void QgsAuthAuthoritiesEditor::populateFileCaCerts()
168 const bool expanded = mFileCaSecItem->isExpanded();
170 mFileCaSecItem->setExpanded( expanded );
173void QgsAuthAuthoritiesEditor::populateRootCaCerts()
177 const bool expanded = mRootCaSecItem->isExpanded();
179 mRootCaSecItem->setExpanded( expanded );
182void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype )
184 if ( btnGroupByOrg->isChecked() )
186 appendCertsToGroup( certs, catype, item );
190 appendCertsToItem( certs, catype, item );
194void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
201 parent = treeWidgetCAs->currentItem();
205 const QMap<QString, QList<QSslCertificate>> orgcerts(
209 QMap<QString, QList<QSslCertificate>>::const_iterator it = orgcerts.constBegin();
210 for ( ; it != orgcerts.constEnd(); ++it )
212 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent, QStringList() << it.key(),
static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
213 grpitem->setFirstColumnSpanned(
true );
214 grpitem->setFlags( Qt::ItemIsEnabled );
215 grpitem->setExpanded(
true );
217 QBrush orgb( grpitem->foreground( 0 ) );
218 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
219 grpitem->setForeground( 0, orgb );
220 QFont grpf( grpitem->font( 0 ) );
221 grpf.setItalic(
true );
222 grpitem->setFont( 0, grpf );
224 appendCertsToItem( it.value(), catype, grpitem );
227 parent->sortChildren( 0, Qt::AscendingOrder );
230void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
237 parent = treeWidgetCAs->currentItem();
247 const auto constCerts = certs;
248 for (
const QSslCertificate &cert : constCerts )
254 coltxts << QString( cert.serialNumber() );
255 coltxts << cert.expiryDate().toString();
259 if ( trustedids.contains(
id ) )
263 else if ( untrustedids.contains(
id )
264 || cert.isBlacklisted()
266 || cert.expiryDate() <= QDateTime::currentDateTime()
267 || cert.effectiveDate() > QDateTime::currentDateTime() )
273 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
276 if ( cert.isBlacklisted()
278 || cert.expiryDate() <= QDateTime::currentDateTime()
279 || cert.effectiveDate() > QDateTime::currentDateTime() )
281 item->setForeground( 2, redb );
285 if ( trustedids.contains(
id ) )
287 item->setForeground( 3, greenb );
288 if ( !cert.isBlacklisted()
290 && cert.expiryDate() > QDateTime::currentDateTime()
291 && cert.effectiveDate() <= QDateTime::currentDateTime() )
296 else if ( untrustedids.contains(
id ) )
298 item->setForeground( 3, redb );
306 item->setData( 0, Qt::UserRole,
id );
309 parent->sortChildren( 0, Qt::AscendingOrder );
312void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
317void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
319 mActionDefaultTrustPolicy =
new QAction( QStringLiteral(
"Change default trust policy" ),
this );
320 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
322 mActionShowTrustedCAs =
new QAction( QStringLiteral(
"Show trusted authorities/issuers" ),
this );
323 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
325 mUtilitiesMenu =
new QMenu(
this );
326 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
327 mUtilitiesMenu->addSeparator();
328 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
330 btnUtilities->setMenu( mUtilitiesMenu );
333void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
338 const QString digest( item->data( 0, Qt::UserRole ).toString() );
340 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>> cacertscache(
344 if ( !cacertscache.contains( digest ) )
346 QgsDebugError( QStringLiteral(
"Certificate Authority not in CA certs cache" ) );
350 const QSslCertificate cert( cacertscache.value( digest ).second );
353 dlg->setWindowModality( Qt::WindowModal );
354 dlg->resize( 675, 500 );
359 populateCaCertsView();
364void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
367 Q_UNUSED( deselected )
371void QgsAuthAuthoritiesEditor::checkSelection()
374 bool isdbcert =
false;
375 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
377 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
379 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
381 case QgsAuthAuthoritiesEditor::RootCaCert:
384 case QgsAuthAuthoritiesEditor::FileCaCert:
387 case QgsAuthAuthoritiesEditor::DbCaCert:
396 btnRemoveCa->setEnabled( isdbcert );
397 btnInfoCa->setEnabled( iscert );
400void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
405 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
407 case QgsAuthAuthoritiesEditor::Section:
410 case QgsAuthAuthoritiesEditor::OrgName:
419 showCertInfo( item );
423void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
426 dlg->setWindowModality( Qt::WindowModal );
427 dlg->resize( 400, 450 );
440 const auto constCerts = certs;
441 for (
const QSslCertificate &cert : constCerts )
445 logMessage( QObject::tr(
"Could not set trust policy for imported certificates" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
449 updateCertTrustPolicyCache();
453 populateDatabaseCaCerts();
454 mDbCaSecItem->setExpanded(
true );
459void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
461 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
465 QgsDebugMsgLevel( QStringLiteral(
"Current tree widget item not set" ), 2 );
469 const QString digest( item->data( 0, Qt::UserRole ).toString() );
471 if ( digest.isEmpty() )
477 const QMap<QString, QSslCertificate> mappedcerts(
481 if ( !mappedcerts.contains( digest ) )
483 QgsDebugError( QStringLiteral(
"Certificate Authority not in mapped database CAs" ) );
487 if ( QMessageBox::warning(
488 this, tr(
"Remove Certificate Authority" ),
489 tr(
"Are you sure you want to remove the selected "
490 "Certificate Authority from the database?\n\n"
491 "Operation can NOT be undone!" ),
492 QMessageBox::Ok | QMessageBox::Cancel,
495 == QMessageBox::Cancel )
500 const QSslCertificate cert( mappedcerts.value( digest ) );
522 updateCertTrustPolicyCache();
524 item->parent()->removeChild( item );
528 mDbCaSecItem->setExpanded(
true );
531void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
533 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
535 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
536 handleDoubleClick( item, 0 );
540void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
544 logMessage( QObject::tr(
"Could not store sort by preference" ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
546 populateCaCertsView();
549void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
551 QDialog *dlg =
new QDialog(
this );
552 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
553 QVBoxLayout *layout =
new QVBoxLayout( dlg );
555 QHBoxLayout *hlayout =
new QHBoxLayout();
557 QLabel *lblwarn =
new QLabel( dlg );
558 QStyle *style = QApplication::style();
559 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
560 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
561 hlayout->addWidget( lblwarn );
563 QLabel *lbltxt =
new QLabel( dlg );
564 lbltxt->setText( tr(
"Changing the default certificate authority trust policy to 'Untrusted' "
565 "can cause unexpected SSL network connection results." ) );
566 lbltxt->setWordWrap(
true );
567 hlayout->addWidget( lbltxt );
569 layout->addLayout( hlayout );
571 QHBoxLayout *hlayout2 =
new QHBoxLayout();
573 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
574 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
575 hlayout2->addWidget( lblpolicy );
577 QComboBox *cmbpolicy =
new QComboBox( dlg );
578 QList<QPair<QgsAuthCertUtils::CertTrustPolicy, QString>> policies;
582 for (
int i = 0; i < policies.size(); i++ )
584 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
587 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
588 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
589 hlayout2->addWidget( cmbpolicy );
591 layout->addLayout( hlayout2 );
593 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok, Qt::Horizontal, dlg );
594 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
596 layout->addWidget( buttonBox );
598 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
599 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
601 dlg->setLayout( layout );
602 dlg->setWindowModality( Qt::WindowModal );
603 dlg->resize( 400, 200 );
604 dlg->setMinimumSize( 400, 200 );
605 dlg->setMaximumSize( 500, 300 );
611 if ( mDefaultTrustPolicy != trustpolicy )
613 defaultTrustPolicyChanged( trustpolicy );
623 logMessage( QObject::tr(
"Could not store default trust policy." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Critical );
625 mDefaultTrustPolicy = trustpolicy;
628 populateCaCertsView();
631void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
634 dlg->setWindowModality( Qt::WindowModal );
635 dlg->resize( 400, 250 );
639 if ( !leCaFile->text().isEmpty() )
641 btnCaFileClear_clicked();
645 leCaFile->setText( fn );
649 logMessage( QObject::tr(
"Could not store 'CA file path' in authentication database." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
653 logMessage( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication database." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
661 const auto constCerts = certs;
662 for (
const QSslCertificate &cert : constCerts )
666 logMessage( QObject::tr(
"Could not set trust policy for imported certificates." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
670 updateCertTrustPolicyCache();
675 populateFileCaCerts();
676 mFileCaSecItem->setExpanded(
true );
681void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
685 logMessage( QObject::tr(
"Could not remove 'CA file path' from authentication database." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
690 logMessage( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication database." ), QObject::tr(
"Authorities Manager" ),
Qgis::MessageLevel::Warning );
696 const QString fn( leCaFile->text() );
697 if ( QFile::exists( fn ) )
701 if ( !certs.isEmpty() )
709 updateCertTrustPolicyCache();
716 populateFileCaCerts();
719void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
722 dlg->setWindowModality( Qt::WindowModal );
723 dlg->resize( 675, 500 );
728void QgsAuthAuthoritiesEditor::logMessage(
const QString &message,
const QString &authtag,
Qgis::MessageLevel level )
730 messageBar()->
pushMessage( authtag, message, level, 7 );
737 treeWidgetCAs->setFocus();
739 QWidget::showEvent( e );
747int QgsAuthAuthoritiesEditor::messageTimeout()
750 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.
Dialog wrapper for widget displaying detailed info on a certificate and its hierarchical trust chain.
bool trustCacheRebuilt()
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.
Widget for importing a certificate into the authentication database.
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)
authSetting get an authentication setting (retrieved as string and returned as QVariant( QString ))
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.
Widget for listing trusted Certificate (Intermediate) Authorities used in secure connections.
A bar for displaying non-blocking messages to the user.
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::MessageLevel::Info, int duration=-1)
A convenience method for pushing a message with the specified text to the bar.
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.
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)