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 );
66 this, &QgsAuthAuthoritiesEditor::logMessage );
69 this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
73 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
74 this, &QgsAuthAuthoritiesEditor::selectionChanged );
76 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
77 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();
100static void setItemBold_( QTreeWidgetItem *item )
102 item->setFirstColumnSpanned(
true );
103 QFont secf( item->font( 0 ) );
104 secf.setBold(
true );
105 item->setFont( 0, secf );
108void QgsAuthAuthoritiesEditor::setupCaCertsTree()
110 treeWidgetCAs->setColumnCount( 4 );
111 treeWidgetCAs->setHeaderLabels(
112 QStringList() << tr(
"Common Name" )
114 << tr(
"Expiry Date" )
115 << tr(
"Trust Policy" ) );
116 treeWidgetCAs->setColumnWidth( 0, 300 );
117 treeWidgetCAs->setColumnWidth( 1, 75 );
118 treeWidgetCAs->setColumnWidth( 2, 200 );
121 mDbCaSecItem =
new QTreeWidgetItem(
124 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
125 setItemBold_( mDbCaSecItem );
126 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
127 mDbCaSecItem->setExpanded(
true );
128 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
130 mFileCaSecItem =
new QTreeWidgetItem(
133 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
134 setItemBold_( mFileCaSecItem );
135 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
136 mFileCaSecItem->setExpanded(
true );
137 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
139 mRootCaSecItem =
new QTreeWidgetItem(
142 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
143 setItemBold_( mRootCaSecItem );
144 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
145 mRootCaSecItem->setExpanded(
false );
146 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
149void QgsAuthAuthoritiesEditor::populateCaCertsView()
151 updateCertTrustPolicyCache();
152 populateDatabaseCaCerts();
153 populateFileCaCerts();
154 populateRootCaCerts();
157void QgsAuthAuthoritiesEditor::refreshCaCertsView()
160 populateCaCertsView();
163static void removeChildren_( QTreeWidgetItem *item )
165 const auto constTakeChildren = item->takeChildren();
166 for ( QTreeWidgetItem *child : constTakeChildren )
172void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
174 removeChildren_( mDbCaSecItem );
176 const bool expanded = mDbCaSecItem->isExpanded();
177 populateCaCertsSection( mDbCaSecItem,
179 QgsAuthAuthoritiesEditor::DbCaCert );
180 mDbCaSecItem->setExpanded( expanded );
183void QgsAuthAuthoritiesEditor::populateFileCaCerts()
185 removeChildren_( mFileCaSecItem );
187 const bool expanded = mFileCaSecItem->isExpanded();
188 populateCaCertsSection( mFileCaSecItem,
190 QgsAuthAuthoritiesEditor::FileCaCert );
191 mFileCaSecItem->setExpanded( expanded );
194void QgsAuthAuthoritiesEditor::populateRootCaCerts()
196 removeChildren_( mRootCaSecItem );
198 const bool expanded = mRootCaSecItem->isExpanded();
199 populateCaCertsSection( mRootCaSecItem,
201 QgsAuthAuthoritiesEditor::RootCaCert );
202 mRootCaSecItem->setExpanded( expanded );
205void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs,
206 QgsAuthAuthoritiesEditor::CaType catype )
208 if ( btnGroupByOrg->isChecked() )
210 appendCertsToGroup( certs, catype, item );
214 appendCertsToItem( certs, catype, item );
218void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs,
219 QgsAuthAuthoritiesEditor::CaType catype,
220 QTreeWidgetItem *parent )
227 parent = treeWidgetCAs->currentItem();
231 const QMap< QString, QList<QSslCertificate> > orgcerts(
234 QMap< QString, QList<QSslCertificate> >::const_iterator it = orgcerts.constBegin();
235 for ( ; it != orgcerts.constEnd(); ++it )
237 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent,
238 QStringList() << it.key(),
239 static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
240 grpitem->setFirstColumnSpanned(
true );
241 grpitem->setFlags( Qt::ItemIsEnabled );
242 grpitem->setExpanded(
true );
244 QBrush orgb( grpitem->foreground( 0 ) );
245 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
246 grpitem->setForeground( 0, orgb );
247 QFont grpf( grpitem->font( 0 ) );
248 grpf.setItalic(
true );
249 grpitem->setFont( 0, grpf );
251 appendCertsToItem( it.value(), catype, grpitem );
254 parent->sortChildren( 0, Qt::AscendingOrder );
257void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs,
258 QgsAuthAuthoritiesEditor::CaType catype,
259 QTreeWidgetItem *parent )
266 parent = treeWidgetCAs->currentItem();
276 const auto constCerts = certs;
277 for (
const QSslCertificate &cert : constCerts )
283 coltxts << QString( cert.serialNumber() );
284 coltxts << cert.expiryDate().toString();
288 if ( trustedids.contains(
id ) )
292 else if ( untrustedids.contains(
id )
293 || cert.isBlacklisted()
295 || cert.expiryDate() <= QDateTime::currentDateTime()
296 || cert.effectiveDate() > QDateTime::currentDateTime() )
302 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
305 if ( cert.isBlacklisted()
307 || cert.expiryDate() <= QDateTime::currentDateTime()
308 || cert.effectiveDate() > QDateTime::currentDateTime() )
310 item->setForeground( 2, redb );
314 if ( trustedids.contains(
id ) )
316 item->setForeground( 3, greenb );
317 if ( !cert.isBlacklisted()
319 && cert.expiryDate() > QDateTime::currentDateTime()
320 && cert.effectiveDate() <= QDateTime::currentDateTime() )
325 else if ( untrustedids.contains(
id ) )
327 item->setForeground( 3, redb );
335 item->setData( 0, Qt::UserRole,
id );
338 parent->sortChildren( 0, Qt::AscendingOrder );
341void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
346void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
348 mActionDefaultTrustPolicy =
new QAction( QStringLiteral(
"Change default trust policy" ),
this );
349 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
351 mActionShowTrustedCAs =
new QAction( QStringLiteral(
"Show trusted authorities/issuers" ),
this );
352 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
354 mUtilitiesMenu =
new QMenu(
this );
355 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
356 mUtilitiesMenu->addSeparator();
357 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
359 btnUtilities->setMenu( mUtilitiesMenu );
362void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
367 const QString digest( item->data( 0, Qt::UserRole ).toString() );
369 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
372 if ( !cacertscache.contains( digest ) )
374 QgsDebugError( QStringLiteral(
"Certificate Authority not in CA certs cache" ) );
378 const QSslCertificate cert( cacertscache.value( digest ).second );
381 dlg->setWindowModality( Qt::WindowModal );
382 dlg->resize( 675, 500 );
387 populateCaCertsView();
392void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
395 Q_UNUSED( deselected )
399void QgsAuthAuthoritiesEditor::checkSelection()
402 bool isdbcert =
false;
403 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
405 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
407 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
409 case QgsAuthAuthoritiesEditor::RootCaCert:
412 case QgsAuthAuthoritiesEditor::FileCaCert:
415 case QgsAuthAuthoritiesEditor::DbCaCert:
424 btnRemoveCa->setEnabled( isdbcert );
425 btnInfoCa->setEnabled( iscert );
428void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
433 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
435 case QgsAuthAuthoritiesEditor::Section:
438 case QgsAuthAuthoritiesEditor::OrgName:
447 showCertInfo( item );
451void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
454 dlg->setWindowModality( Qt::WindowModal );
455 dlg->resize( 400, 450 );
461 messageBar()->
pushMessage( tr(
"ERROR storing CA(s) in authentication database" ),
469 const auto constCerts = certs;
470 for (
const QSslCertificate &cert : constCerts )
474 logMessage( QObject::tr(
"Could not set trust policy for imported certificates" ),
475 QObject::tr(
"Authorities Manager" ),
480 updateCertTrustPolicyCache();
484 populateDatabaseCaCerts();
485 mDbCaSecItem->setExpanded(
true );
490void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
492 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
496 QgsDebugMsgLevel( QStringLiteral(
"Current tree widget item not set" ), 2 );
500 const QString digest( item->data( 0, Qt::UserRole ).toString() );
502 if ( digest.isEmpty() )
504 messageBar()->
pushMessage( tr(
"Certificate id missing" ),
509 const QMap<QString, QSslCertificate> mappedcerts(
512 if ( !mappedcerts.contains( digest ) )
514 QgsDebugError( QStringLiteral(
"Certificate Authority not in mapped database CAs" ) );
518 if ( QMessageBox::warning(
519 this, tr(
"Remove Certificate Authority" ),
520 tr(
"Are you sure you want to remove the selected "
521 "Certificate Authority from the database?\n\n"
522 "Operation can NOT be undone!" ),
523 QMessageBox::Ok | QMessageBox::Cancel,
524 QMessageBox::Cancel ) == QMessageBox::Cancel )
529 const QSslCertificate cert( mappedcerts.value( digest ) );
533 messageBar()->
pushMessage( tr(
"Certificate could not be found in database for id %1:" ).arg( digest ),
540 messageBar()->
pushMessage( tr(
"ERROR removing CA from authentication database for id %1:" ).arg( digest ),
547 messageBar()->
pushMessage( tr(
"ERROR removing cert trust policy from authentication database for id %1:" ).arg( digest ),
554 updateCertTrustPolicyCache();
556 item->parent()->removeChild( item );
560 mDbCaSecItem->setExpanded(
true );
563void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
565 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
567 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
568 handleDoubleClick( item, 0 );
572void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
576 logMessage( QObject::tr(
"Could not store sort by preference" ),
577 QObject::tr(
"Authorities Manager" ),
580 populateCaCertsView();
583void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
585 QDialog *dlg =
new QDialog(
this );
586 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
587 QVBoxLayout *layout =
new QVBoxLayout( dlg );
589 QHBoxLayout *hlayout =
new QHBoxLayout();
591 QLabel *lblwarn =
new QLabel( dlg );
592 QStyle *style = QApplication::style();
593 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
594 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
595 hlayout->addWidget( lblwarn );
597 QLabel *lbltxt =
new QLabel( dlg );
598 lbltxt->setText( tr(
"Changing the default certificate authority trust policy to 'Untrusted' "
599 "can cause unexpected SSL network connection results." ) );
600 lbltxt->setWordWrap(
true );
601 hlayout->addWidget( lbltxt );
603 layout->addLayout( hlayout );
605 QHBoxLayout *hlayout2 =
new QHBoxLayout();
607 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
608 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
609 hlayout2->addWidget( lblpolicy );
611 QComboBox *cmbpolicy =
new QComboBox( dlg );
612 QList < QPair<QgsAuthCertUtils::CertTrustPolicy, QString> > policies;
618 for (
int i = 0; i < policies.size(); i++ )
620 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
623 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
624 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
625 hlayout2->addWidget( cmbpolicy );
627 layout->addLayout( hlayout2 );
629 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok,
630 Qt::Horizontal, dlg );
631 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
633 layout->addWidget( buttonBox );
635 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
636 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
638 dlg->setLayout( layout );
639 dlg->setWindowModality( Qt::WindowModal );
640 dlg->resize( 400, 200 );
641 dlg->setMinimumSize( 400, 200 );
642 dlg->setMaximumSize( 500, 300 );
647 if ( mDefaultTrustPolicy != trustpolicy )
649 defaultTrustPolicyChanged( trustpolicy );
659 logMessage( QObject::tr(
"Could not store default trust policy." ),
660 QObject::tr(
"Authorities Manager" ),
663 mDefaultTrustPolicy = trustpolicy;
666 populateCaCertsView();
669void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
674 dlg->setWindowModality( Qt::WindowModal );
675 dlg->resize( 400, 250 );
679 if ( !leCaFile->text().isEmpty() )
681 btnCaFileClear_clicked();
685 leCaFile->setText( fn );
689 logMessage( QObject::tr(
"Could not store 'CA file path' in authentication database." ),
690 QObject::tr(
"Authorities Manager" ),
696 logMessage( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication database." ),
697 QObject::tr(
"Authorities Manager" ),
706 const auto constCerts = certs;
707 for (
const QSslCertificate &cert : constCerts )
711 logMessage( QObject::tr(
"Could not set trust policy for imported certificates." ),
712 QObject::tr(
"Authorities Manager" ),
717 updateCertTrustPolicyCache();
722 populateFileCaCerts();
723 mFileCaSecItem->setExpanded(
true );
728void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
732 logMessage( QObject::tr(
"Could not remove 'CA file path' from authentication database." ),
733 QObject::tr(
"Authorities Manager" ),
739 logMessage( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication database." ),
740 QObject::tr(
"Authorities Manager" ),
747 const QString fn( leCaFile->text() );
748 if ( QFile::exists( fn ) )
752 if ( !certs.isEmpty() )
756 messageBar()->
pushMessage( tr(
"ERROR removing cert(s) trust policy from authentication database." ),
761 updateCertTrustPolicyCache();
768 populateFileCaCerts();
771void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
774 dlg->setWindowModality( Qt::WindowModal );
775 dlg->resize( 675, 500 );
780void QgsAuthAuthoritiesEditor::logMessage(
const QString &message,
const QString &authtag,
Qgis::MessageLevel level )
782 messageBar()->
pushMessage( authtag, message, level, 7 );
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)
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)