18#include "ui_qgsauthauthoritieseditor.h"
30#include <QSslConfiguration>
49 mAuthNotifyLayout =
new QVBoxLayout;
50 this->setLayout( mAuthNotifyLayout );
52 mAuthNotifyLayout->addWidget( mAuthNotify );
57 connect( btnAddCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnAddCa_clicked );
58 connect( btnRemoveCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnRemoveCa_clicked );
59 connect( btnInfoCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnInfoCa_clicked );
60 connect( btnGroupByOrg, &QToolButton::toggled,
this, &QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled );
61 connect( btnCaFile, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFile_clicked );
62 connect( btnCaFileClear, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFileClear_clicked );
65 this, &QgsAuthAuthoritiesEditor::authMessageOut );
68 this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
72 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
73 this, &QgsAuthAuthoritiesEditor::selectionChanged );
75 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
76 this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
78 connect( btnViewRefresh, &QAbstractButton::clicked,
this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
83 leCaFile->setText( cafileval.toString() );
86 btnGroupByOrg->setChecked(
false );
89 btnGroupByOrg->setChecked( sortbyval.toBool() );
92 populateCaCertsView();
95 populateUtilitiesMenu();
99static void setItemBold_( QTreeWidgetItem *item )
101 item->setFirstColumnSpanned(
true );
102 QFont secf( item->font( 0 ) );
103 secf.setBold(
true );
104 item->setFont( 0, secf );
107void QgsAuthAuthoritiesEditor::setupCaCertsTree()
109 treeWidgetCAs->setColumnCount( 4 );
110 treeWidgetCAs->setHeaderLabels(
111 QStringList() << tr(
"Common Name" )
113 << tr(
"Expiry Date" )
114 << tr(
"Trust Policy" ) );
115 treeWidgetCAs->setColumnWidth( 0, 300 );
116 treeWidgetCAs->setColumnWidth( 1, 75 );
117 treeWidgetCAs->setColumnWidth( 2, 200 );
120 mDbCaSecItem =
new QTreeWidgetItem(
123 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
124 setItemBold_( mDbCaSecItem );
125 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
126 mDbCaSecItem->setExpanded(
true );
127 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
129 mFileCaSecItem =
new QTreeWidgetItem(
132 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
133 setItemBold_( mFileCaSecItem );
134 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
135 mFileCaSecItem->setExpanded(
true );
136 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
138 mRootCaSecItem =
new QTreeWidgetItem(
141 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
142 setItemBold_( mRootCaSecItem );
143 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
144 mRootCaSecItem->setExpanded(
false );
145 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
148void QgsAuthAuthoritiesEditor::populateCaCertsView()
150 updateCertTrustPolicyCache();
151 populateDatabaseCaCerts();
152 populateFileCaCerts();
153 populateRootCaCerts();
156void QgsAuthAuthoritiesEditor::refreshCaCertsView()
159 populateCaCertsView();
162static void removeChildren_( QTreeWidgetItem *item )
164 const auto constTakeChildren = item->takeChildren();
165 for ( QTreeWidgetItem *child : constTakeChildren )
171void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
173 removeChildren_( mDbCaSecItem );
175 const bool expanded = mDbCaSecItem->isExpanded();
176 populateCaCertsSection( mDbCaSecItem,
178 QgsAuthAuthoritiesEditor::DbCaCert );
179 mDbCaSecItem->setExpanded( expanded );
182void QgsAuthAuthoritiesEditor::populateFileCaCerts()
184 removeChildren_( mFileCaSecItem );
186 const bool expanded = mFileCaSecItem->isExpanded();
187 populateCaCertsSection( mFileCaSecItem,
189 QgsAuthAuthoritiesEditor::FileCaCert );
190 mFileCaSecItem->setExpanded( expanded );
193void QgsAuthAuthoritiesEditor::populateRootCaCerts()
195 removeChildren_( mRootCaSecItem );
197 const bool expanded = mRootCaSecItem->isExpanded();
198 populateCaCertsSection( mRootCaSecItem,
200 QgsAuthAuthoritiesEditor::RootCaCert );
201 mRootCaSecItem->setExpanded( expanded );
204void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs,
205 QgsAuthAuthoritiesEditor::CaType catype )
207 if ( btnGroupByOrg->isChecked() )
209 appendCertsToGroup( certs, catype, item );
213 appendCertsToItem( certs, catype, item );
217void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs,
218 QgsAuthAuthoritiesEditor::CaType catype,
219 QTreeWidgetItem *parent )
226 parent = treeWidgetCAs->currentItem();
230 const QMap< QString, QList<QSslCertificate> > orgcerts(
233 QMap< QString, QList<QSslCertificate> >::const_iterator it = orgcerts.constBegin();
234 for ( ; it != orgcerts.constEnd(); ++it )
236 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent,
237 QStringList() << it.key(),
238 static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
239 grpitem->setFirstColumnSpanned(
true );
240 grpitem->setFlags( Qt::ItemIsEnabled );
241 grpitem->setExpanded(
true );
243 QBrush orgb( grpitem->foreground( 0 ) );
244 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
245 grpitem->setForeground( 0, orgb );
246 QFont grpf( grpitem->font( 0 ) );
247 grpf.setItalic(
true );
248 grpitem->setFont( 0, grpf );
250 appendCertsToItem( it.value(), catype, grpitem );
253 parent->sortChildren( 0, Qt::AscendingOrder );
256void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs,
257 QgsAuthAuthoritiesEditor::CaType catype,
258 QTreeWidgetItem *parent )
265 parent = treeWidgetCAs->currentItem();
275 const auto constCerts = certs;
276 for (
const QSslCertificate &cert : constCerts )
282 coltxts << QString( cert.serialNumber() );
283 coltxts << cert.expiryDate().toString();
287 if ( trustedids.contains(
id ) )
291 else if ( untrustedids.contains(
id )
292 || cert.isBlacklisted()
294 || cert.expiryDate() <= QDateTime::currentDateTime()
295 || cert.effectiveDate() > QDateTime::currentDateTime() )
301 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
304 if ( cert.isBlacklisted()
306 || cert.expiryDate() <= QDateTime::currentDateTime()
307 || cert.effectiveDate() > QDateTime::currentDateTime() )
309 item->setForeground( 2, redb );
313 if ( trustedids.contains(
id ) )
315 item->setForeground( 3, greenb );
316 if ( !cert.isBlacklisted()
318 && cert.expiryDate() > QDateTime::currentDateTime()
319 && cert.effectiveDate() <= QDateTime::currentDateTime() )
324 else if ( untrustedids.contains(
id ) )
326 item->setForeground( 3, redb );
334 item->setData( 0, Qt::UserRole,
id );
337 parent->sortChildren( 0, Qt::AscendingOrder );
340void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
345void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
347 mActionDefaultTrustPolicy =
new QAction( QStringLiteral(
"Change default trust policy" ),
this );
348 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
350 mActionShowTrustedCAs =
new QAction( QStringLiteral(
"Show trusted authorities/issuers" ),
this );
351 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
353 mUtilitiesMenu =
new QMenu(
this );
354 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
355 mUtilitiesMenu->addSeparator();
356 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
358 btnUtilities->setMenu( mUtilitiesMenu );
361void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
366 const QString digest( item->data( 0, Qt::UserRole ).toString() );
368 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
371 if ( !cacertscache.contains( digest ) )
373 QgsDebugError( QStringLiteral(
"Certificate Authority not in CA certs cache" ) );
377 const QSslCertificate cert( cacertscache.value( digest ).second );
380 dlg->setWindowModality( Qt::WindowModal );
381 dlg->resize( 675, 500 );
386 populateCaCertsView();
391void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
394 Q_UNUSED( deselected )
398void QgsAuthAuthoritiesEditor::checkSelection()
401 bool isdbcert =
false;
402 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
404 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
406 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
408 case QgsAuthAuthoritiesEditor::RootCaCert:
411 case QgsAuthAuthoritiesEditor::FileCaCert:
414 case QgsAuthAuthoritiesEditor::DbCaCert:
423 btnRemoveCa->setEnabled( isdbcert );
424 btnInfoCa->setEnabled( iscert );
427void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
432 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
434 case QgsAuthAuthoritiesEditor::Section:
437 case QgsAuthAuthoritiesEditor::OrgName:
446 showCertInfo( item );
450void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
453 dlg->setWindowModality( Qt::WindowModal );
454 dlg->resize( 400, 450 );
460 messageBar()->
pushMessage( tr(
"ERROR storing CA(s) in authentication database" ),
468 const auto constCerts = certs;
469 for (
const QSslCertificate &cert : constCerts )
473 authMessageOut( QObject::tr(
"Could not set trust policy for imported certificates" ),
474 QObject::tr(
"Authorities Manager" ),
479 updateCertTrustPolicyCache();
483 populateDatabaseCaCerts();
484 mDbCaSecItem->setExpanded(
true );
489void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
491 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
495 QgsDebugMsgLevel( QStringLiteral(
"Current tree widget item not set" ), 2 );
499 const QString digest( item->data( 0, Qt::UserRole ).toString() );
501 if ( digest.isEmpty() )
503 messageBar()->
pushMessage( tr(
"Certificate id missing" ),
508 const QMap<QString, QSslCertificate> mappedcerts(
511 if ( !mappedcerts.contains( digest ) )
513 QgsDebugError( QStringLiteral(
"Certificate Authority not in mapped database CAs" ) );
517 if ( QMessageBox::warning(
518 this, tr(
"Remove Certificate Authority" ),
519 tr(
"Are you sure you want to remove the selected "
520 "Certificate Authority from the database?\n\n"
521 "Operation can NOT be undone!" ),
522 QMessageBox::Ok | QMessageBox::Cancel,
523 QMessageBox::Cancel ) == QMessageBox::Cancel )
528 const QSslCertificate cert( mappedcerts.value( digest ) );
532 messageBar()->
pushMessage( tr(
"Certificate could not be found in database for id %1:" ).arg( digest ),
539 messageBar()->
pushMessage( tr(
"ERROR removing CA from authentication database for id %1:" ).arg( digest ),
546 messageBar()->
pushMessage( tr(
"ERROR removing cert trust policy from authentication database for id %1:" ).arg( digest ),
553 updateCertTrustPolicyCache();
555 item->parent()->removeChild( item );
559 mDbCaSecItem->setExpanded(
true );
562void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
564 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
566 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
567 handleDoubleClick( item, 0 );
571void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
575 authMessageOut( QObject::tr(
"Could not store sort by preference" ),
576 QObject::tr(
"Authorities Manager" ),
579 populateCaCertsView();
582void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
584 QDialog *dlg =
new QDialog(
this );
585 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
586 QVBoxLayout *layout =
new QVBoxLayout( dlg );
588 QHBoxLayout *hlayout =
new QHBoxLayout();
590 QLabel *lblwarn =
new QLabel( dlg );
591 QStyle *style = QApplication::style();
592 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
593 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
594 hlayout->addWidget( lblwarn );
596 QLabel *lbltxt =
new QLabel( dlg );
597 lbltxt->setText( tr(
"Changing the default certificate authority trust policy to 'Untrusted' "
598 "can cause unexpected SSL network connection results." ) );
599 lbltxt->setWordWrap(
true );
600 hlayout->addWidget( lbltxt );
602 layout->addLayout( hlayout );
604 QHBoxLayout *hlayout2 =
new QHBoxLayout();
606 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
607 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
608 hlayout2->addWidget( lblpolicy );
610 QComboBox *cmbpolicy =
new QComboBox( dlg );
611 QList < QPair<QgsAuthCertUtils::CertTrustPolicy, QString> > policies;
617 for (
int i = 0; i < policies.size(); i++ )
619 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
622 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
623 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
624 hlayout2->addWidget( cmbpolicy );
626 layout->addLayout( hlayout2 );
628 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok,
629 Qt::Horizontal, dlg );
630 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
632 layout->addWidget( buttonBox );
634 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
635 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
637 dlg->setLayout( layout );
638 dlg->setWindowModality( Qt::WindowModal );
639 dlg->resize( 400, 200 );
640 dlg->setMinimumSize( 400, 200 );
641 dlg->setMaximumSize( 500, 300 );
646 if ( mDefaultTrustPolicy != trustpolicy )
648 defaultTrustPolicyChanged( trustpolicy );
658 authMessageOut( QObject::tr(
"Could not store default trust policy." ),
659 QObject::tr(
"Authorities Manager" ),
662 mDefaultTrustPolicy = trustpolicy;
665 populateCaCertsView();
668void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
673 dlg->setWindowModality( Qt::WindowModal );
674 dlg->resize( 400, 250 );
678 if ( !leCaFile->text().isEmpty() )
680 btnCaFileClear_clicked();
684 leCaFile->setText( fn );
688 authMessageOut( QObject::tr(
"Could not store 'CA file path' in authentication database." ),
689 QObject::tr(
"Authorities Manager" ),
695 authMessageOut( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication database." ),
696 QObject::tr(
"Authorities Manager" ),
705 const auto constCerts = certs;
706 for (
const QSslCertificate &cert : constCerts )
710 authMessageOut( QObject::tr(
"Could not set trust policy for imported certificates." ),
711 QObject::tr(
"Authorities Manager" ),
716 updateCertTrustPolicyCache();
721 populateFileCaCerts();
722 mFileCaSecItem->setExpanded(
true );
727void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
731 authMessageOut( QObject::tr(
"Could not remove 'CA file path' from authentication database." ),
732 QObject::tr(
"Authorities Manager" ),
738 authMessageOut( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication database." ),
739 QObject::tr(
"Authorities Manager" ),
746 const QString fn( leCaFile->text() );
747 if ( QFile::exists( fn ) )
751 if ( !certs.isEmpty() )
755 messageBar()->
pushMessage( tr(
"ERROR removing cert(s) trust policy from authentication database." ),
760 updateCertTrustPolicyCache();
767 populateFileCaCerts();
770void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
773 dlg->setWindowModality( Qt::WindowModal );
774 dlg->resize( 675, 500 );
781 const int levelint =
static_cast<int>( level );
789 treeWidgetCAs->setFocus();
791 QWidget::showEvent( e );
799int QgsAuthAuthoritiesEditor::messageTimeout()
802 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 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)
MessageLevel
Message log level (mirrors that of QgsMessageLog, so it can also output there)
void messageOut(const QString &message, const QString &tag=QgsAuthManager::AUTH_MAN_TAG, QgsAuthManager::MessageLevel level=QgsAuthManager::INFO) const
Custom logging signal to relay to console output and QgsMessageLog.
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.
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)
Returns true if the specified variant should be considered a NULL value.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)