18 #include "ui_qgsauthauthoritieseditor.h" 24 #include <QFileDialog> 27 #include <QMessageBox> 29 #include <QPushButton> 30 #include <QSslConfiguration> 48 mAuthNotifyLayout =
new QVBoxLayout;
49 this->setLayout( mAuthNotifyLayout );
51 mAuthNotifyLayout->addWidget( mAuthNotify );
56 connect( btnAddCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnAddCa_clicked );
57 connect( btnRemoveCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnRemoveCa_clicked );
58 connect( btnInfoCa, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnInfoCa_clicked );
59 connect( btnGroupByOrg, &QToolButton::toggled,
this, &QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled );
60 connect( btnCaFile, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFile_clicked );
61 connect( btnCaFileClear, &QToolButton::clicked,
this, &QgsAuthAuthoritiesEditor::btnCaFileClear_clicked );
64 this, &QgsAuthAuthoritiesEditor::authMessageOut );
67 this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
71 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
72 this, &QgsAuthAuthoritiesEditor::selectionChanged );
74 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
75 this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
77 connect( btnViewRefresh, &QAbstractButton::clicked,
this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
80 if ( !cafileval.isNull() )
82 leCaFile->setText( cafileval.toString() );
85 btnGroupByOrg->setChecked(
false );
87 if ( !sortbyval.isNull() )
88 btnGroupByOrg->setChecked( sortbyval.toBool() );
91 populateCaCertsView();
94 populateUtilitiesMenu();
98 static void setItemBold_( QTreeWidgetItem *item )
100 item->setFirstColumnSpanned(
true );
101 QFont secf( item->font( 0 ) );
102 secf.setBold(
true );
103 item->setFont( 0, secf );
106 void QgsAuthAuthoritiesEditor::setupCaCertsTree()
108 treeWidgetCAs->setColumnCount( 4 );
109 treeWidgetCAs->setHeaderLabels(
110 QStringList() << tr(
"Common Name" )
112 << tr(
"Expiry Date" )
113 << tr(
"Trust Policy" ) );
114 treeWidgetCAs->setColumnWidth( 0, 300 );
115 treeWidgetCAs->setColumnWidth( 1, 75 );
116 treeWidgetCAs->setColumnWidth( 2, 200 );
119 mDbCaSecItem =
new QTreeWidgetItem(
122 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
123 setItemBold_( mDbCaSecItem );
124 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
125 mDbCaSecItem->setExpanded(
true );
126 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
128 mFileCaSecItem =
new QTreeWidgetItem(
131 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
132 setItemBold_( mFileCaSecItem );
133 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
134 mFileCaSecItem->setExpanded(
true );
135 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
137 mRootCaSecItem =
new QTreeWidgetItem(
140 static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
141 setItemBold_( mRootCaSecItem );
142 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
143 mRootCaSecItem->setExpanded(
false );
144 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
147 void QgsAuthAuthoritiesEditor::populateCaCertsView()
149 updateCertTrustPolicyCache();
150 populateDatabaseCaCerts();
151 populateFileCaCerts();
152 populateRootCaCerts();
155 void QgsAuthAuthoritiesEditor::refreshCaCertsView()
158 populateCaCertsView();
161 static void removeChildren_( QTreeWidgetItem *item )
163 const auto constTakeChildren = item->takeChildren();
164 for ( QTreeWidgetItem *child : constTakeChildren )
170 void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
172 removeChildren_( mDbCaSecItem );
174 bool expanded = mDbCaSecItem->isExpanded();
175 populateCaCertsSection( mDbCaSecItem,
177 QgsAuthAuthoritiesEditor::DbCaCert );
178 mDbCaSecItem->setExpanded( expanded );
181 void QgsAuthAuthoritiesEditor::populateFileCaCerts()
183 removeChildren_( mFileCaSecItem );
185 bool expanded = mFileCaSecItem->isExpanded();
186 populateCaCertsSection( mFileCaSecItem,
188 QgsAuthAuthoritiesEditor::FileCaCert );
189 mFileCaSecItem->setExpanded( expanded );
192 void QgsAuthAuthoritiesEditor::populateRootCaCerts()
194 removeChildren_( mRootCaSecItem );
196 bool expanded = mRootCaSecItem->isExpanded();
197 populateCaCertsSection( mRootCaSecItem,
199 QgsAuthAuthoritiesEditor::RootCaCert );
200 mRootCaSecItem->setExpanded( expanded );
203 void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item,
const QList<QSslCertificate> &certs,
204 QgsAuthAuthoritiesEditor::CaType catype )
206 if ( btnGroupByOrg->isChecked() )
208 appendCertsToGroup( certs, catype, item );
212 appendCertsToItem( certs, catype, item );
216 void QgsAuthAuthoritiesEditor::appendCertsToGroup(
const QList<QSslCertificate> &certs,
217 QgsAuthAuthoritiesEditor::CaType catype,
218 QTreeWidgetItem *parent )
225 parent = treeWidgetCAs->currentItem();
229 QMap< QString, QList<QSslCertificate> > orgcerts(
232 QMap< QString, QList<QSslCertificate> >::const_iterator it = orgcerts.constBegin();
233 for ( ; it != orgcerts.constEnd(); ++it )
235 QTreeWidgetItem *grpitem(
new QTreeWidgetItem( parent,
236 QStringList() << it.key(),
237 static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
238 grpitem->setFirstColumnSpanned(
true );
239 grpitem->setFlags( Qt::ItemIsEnabled );
240 grpitem->setExpanded(
true );
242 QBrush orgb( grpitem->foreground( 0 ) );
243 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
244 grpitem->setForeground( 0, orgb );
245 QFont grpf( grpitem->font( 0 ) );
246 grpf.setItalic(
true );
247 grpitem->setFont( 0, grpf );
249 appendCertsToItem( it.value(), catype, grpitem );
252 parent->sortChildren( 0, Qt::AscendingOrder );
255 void QgsAuthAuthoritiesEditor::appendCertsToItem(
const QList<QSslCertificate> &certs,
256 QgsAuthAuthoritiesEditor::CaType catype,
257 QTreeWidgetItem *parent )
264 parent = treeWidgetCAs->currentItem();
274 const auto constCerts = certs;
275 for (
const QSslCertificate &cert : constCerts )
281 coltxts << QString( cert.serialNumber() );
282 coltxts << cert.expiryDate().toString();
286 if ( trustedids.contains(
id ) )
290 else if ( untrustedids.contains(
id ) || !cert.isValid() )
296 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts, static_cast<int>( catype ) ) );
299 if ( !cert.isValid() )
301 item->setForeground( 2, redb );
305 if ( trustedids.contains(
id ) )
307 item->setForeground( 3, greenb );
308 if ( cert.isValid() )
313 else if ( untrustedids.contains(
id ) )
315 item->setForeground( 3, redb );
323 item->setData( 0, Qt::UserRole,
id );
326 parent->sortChildren( 0, Qt::AscendingOrder );
329 void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
334 void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
336 mActionDefaultTrustPolicy =
new QAction( QStringLiteral(
"Change default trust policy" ),
this );
337 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
339 mActionShowTrustedCAs =
new QAction( QStringLiteral(
"Show trusted authorities/issuers" ),
this );
340 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
342 mUtilitiesMenu =
new QMenu(
this );
343 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
344 mUtilitiesMenu->addSeparator();
345 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
347 btnUtilities->setMenu( mUtilitiesMenu );
350 void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
355 QString digest( item->data( 0, Qt::UserRole ).toString() );
357 QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
360 if ( !cacertscache.contains( digest ) )
362 QgsDebugMsg( QStringLiteral(
"Certificate Authority not in CA certs cache" ) );
366 QSslCertificate cert( cacertscache.value( digest ).second );
369 dlg->setWindowModality( Qt::WindowModal );
370 dlg->resize( 675, 500 );
372 if ( dlg->trustCacheRebuilt() )
375 populateCaCertsView();
380 void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
383 Q_UNUSED( deselected )
387 void QgsAuthAuthoritiesEditor::checkSelection()
390 bool isdbcert =
false;
391 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
393 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
395 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
397 case QgsAuthAuthoritiesEditor::RootCaCert:
400 case QgsAuthAuthoritiesEditor::FileCaCert:
403 case QgsAuthAuthoritiesEditor::DbCaCert:
412 btnRemoveCa->setEnabled( isdbcert );
413 btnInfoCa->setEnabled( iscert );
416 void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
421 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
423 case QgsAuthAuthoritiesEditor::Section:
426 case QgsAuthAuthoritiesEditor::OrgName:
435 showCertInfo( item );
439 void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
442 dlg->setWindowModality( Qt::WindowModal );
443 dlg->resize( 400, 450 );
449 messageBar()->
pushMessage( tr(
"ERROR storing CA(s) in authentication database" ),
457 const auto constCerts = certs;
458 for (
const QSslCertificate &cert : constCerts )
462 authMessageOut( QObject::tr(
"Could not set trust policy for imported certificates" ),
463 QObject::tr(
"Authorities Manager" ),
468 updateCertTrustPolicyCache();
472 populateDatabaseCaCerts();
473 mDbCaSecItem->setExpanded(
true );
478 void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
480 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
484 QgsDebugMsg( QStringLiteral(
"Current tree widget item not set" ) );
488 QString digest( item->data( 0, Qt::UserRole ).toString() );
490 if ( digest.isEmpty() )
492 messageBar()->
pushMessage( tr(
"Certificate id missing" ),
497 QMap<QString, QSslCertificate> mappedcerts(
500 if ( !mappedcerts.contains( digest ) )
502 QgsDebugMsg( QStringLiteral(
"Certificate Authority not in mapped database CAs" ) );
506 if ( QMessageBox::warning(
507 this, tr(
"Remove Certificate Authority" ),
508 tr(
"Are you sure you want to remove the selected " 509 "Certificate Authority from the database?\n\n" 510 "Operation can NOT be undone!" ),
511 QMessageBox::Ok | QMessageBox::Cancel,
512 QMessageBox::Cancel ) == QMessageBox::Cancel )
517 QSslCertificate cert( mappedcerts.value( digest ) );
521 messageBar()->
pushMessage( tr(
"Certificate could not be found in database for id %1:" ).arg( digest ),
528 messageBar()->
pushMessage( tr(
"ERROR removing CA from authentication database for id %1:" ).arg( digest ),
535 messageBar()->
pushMessage( tr(
"ERROR removing cert trust policy from authentication database for id %1:" ).arg( digest ),
542 updateCertTrustPolicyCache();
544 item->parent()->removeChild( item );
548 mDbCaSecItem->setExpanded(
true );
551 void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
553 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
555 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
556 handleDoubleClick( item, 0 );
560 void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
564 authMessageOut( QObject::tr(
"Could not store sort by preference" ),
565 QObject::tr(
"Authorities Manager" ),
568 populateCaCertsView();
571 void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
573 QDialog *dlg =
new QDialog(
this );
574 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
575 QVBoxLayout *layout =
new QVBoxLayout( dlg );
577 QHBoxLayout *hlayout =
new QHBoxLayout();
579 QLabel *lblwarn =
new QLabel( dlg );
580 QStyle *style = QApplication::style();
581 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
582 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
583 hlayout->addWidget( lblwarn );
585 QLabel *lbltxt =
new QLabel( dlg );
586 lbltxt->setText( tr(
"Changing the default certificate authority trust policy to 'Untrusted' " 587 "can cause unexpected SSL network connection results." ) );
588 lbltxt->setWordWrap(
true );
589 hlayout->addWidget( lbltxt );
591 layout->addLayout( hlayout );
593 QHBoxLayout *hlayout2 =
new QHBoxLayout();
595 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
596 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
597 hlayout2->addWidget( lblpolicy );
599 QComboBox *cmbpolicy =
new QComboBox( dlg );
600 QList < QPair<QgsAuthCertUtils::CertTrustPolicy, QString> > policies;
606 for (
int i = 0; i < policies.size(); i++ )
608 cmbpolicy->addItem( policies.at( i ).second, QVariant( static_cast<int>( policies.at( i ).first ) ) );
611 int idx = cmbpolicy->findData( QVariant( static_cast<int>( mDefaultTrustPolicy ) ) );
612 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
613 hlayout2->addWidget( cmbpolicy );
615 layout->addLayout( hlayout2 );
617 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok,
618 Qt::Horizontal, dlg );
619 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
621 layout->addWidget( buttonBox );
623 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
624 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
626 dlg->setLayout( layout );
627 dlg->setWindowModality( Qt::WindowModal );
628 dlg->resize( 400, 200 );
629 dlg->setMinimumSize( 400, 200 );
630 dlg->setMaximumSize( 500, 300 );
635 if ( mDefaultTrustPolicy != trustpolicy )
637 defaultTrustPolicyChanged( trustpolicy );
647 authMessageOut( QObject::tr(
"Could not store default trust policy." ),
648 QObject::tr(
"Authorities Manager" ),
651 mDefaultTrustPolicy = trustpolicy;
654 populateCaCertsView();
657 void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
662 dlg->setWindowModality( Qt::WindowModal );
663 dlg->resize( 400, 250 );
667 if ( !leCaFile->text().isEmpty() )
669 btnCaFileClear_clicked();
673 leCaFile->setText( fn );
677 authMessageOut( QObject::tr(
"Could not store 'CA file path' in authentication database." ),
678 QObject::tr(
"Authorities Manager" ),
684 authMessageOut( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication database." ),
685 QObject::tr(
"Authorities Manager" ),
694 const auto constCerts = certs;
695 for (
const QSslCertificate &cert : constCerts )
699 authMessageOut( QObject::tr(
"Could not set trust policy for imported certificates." ),
700 QObject::tr(
"Authorities Manager" ),
705 updateCertTrustPolicyCache();
710 populateFileCaCerts();
711 mFileCaSecItem->setExpanded(
true );
716 void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
720 authMessageOut( QObject::tr(
"Could not remove 'CA file path' from authentication database." ),
721 QObject::tr(
"Authorities Manager" ),
727 authMessageOut( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication database." ),
728 QObject::tr(
"Authorities Manager" ),
735 QString fn( leCaFile->text() );
736 if ( QFile::exists( fn ) )
740 if ( !certs.isEmpty() )
744 messageBar()->
pushMessage( tr(
"ERROR removing cert(s) trust policy from authentication database." ),
749 updateCertTrustPolicyCache();
756 populateFileCaCerts();
759 void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
762 dlg->setWindowModality( Qt::WindowModal );
763 dlg->resize( 675, 500 );
770 int levelint =
static_cast<int>( level );
778 treeWidgetCAs->setFocus();
780 QWidget::showEvent( e );
788 int QgsAuthAuthoritiesEditor::messageTimeout()
791 return settings.
value( QStringLiteral(
"qgis/messageTimeout" ), 5 ).toInt();
bool rebuildTrustedCaCertsCache()
Rebuild trusted certificate authorities cache.
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.
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 QList< QSslCertificate > certsFromFile(const QString &certspath)
Returns a list of concatenated certs from a PEM or DER formatted file.
A bar for displaying non-blocking messages to the user.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
bool allowInvalidCerts()
Whether to allow importation of invalid certificates (so trust policy can be overridden) ...
MessageLevel
Level for messages This will be used both for message log and message bar in application.
const QString certFileToImport()
Gets the file path to a certificate to import.
MessageLevel
Message log level (mirrors that of QgsMessageLog, so it can also output there)
bool rebuildCaCertsCache()
Rebuild certificate authority cache.
void showEvent(QShowEvent *e) override
Overridden show event of base widget.
QgsAuthCertUtils::CertTrustPolicy certTrustPolicy()
Defined trust policy for imported certificates.
static QColor redColor()
Red color representing invalid, untrusted, etc. certificate.
Dialog wrapper for widget displaying detailed info on a certificate and its hierarchical trust chain...
static QColor greenColor()
Green color representing valid, trusted, etc. certificate.
bool removeCertTrustPolicies(const QList< QSslCertificate > &certs)
Remove a group certificate authorities.
void authDatabaseChanged()
Emitted when the authentication db is significantly changed, e.g. large record removal, erased, etc.
void pushMessage(const QString &text, Qgis::MessageLevel level=Qgis::Info, int duration=5)
convenience method for pushing a message to the bar
QgsAuthAuthoritiesEditor(QWidget *parent=nullptr)
Widget for viewing and editing certificate authorities directly in database.
Widget for importing a certificate into the authentication database.
bool storeCertTrustPolicy(const QSslCertificate &cert, QgsAuthCertUtils::CertTrustPolicy policy)
Store user trust value for a certificate.
bool storeCertAuthorities(const QList< QSslCertificate > &certs)
Store multiple certificate authorities.
const QList< QSslCertificate > certificatesToImport()
Gets list of certificate objects to import.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
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 )) ...
const QMap< QgsAuthCertUtils::CertTrustPolicy, QStringList > certTrustCache()
certTrustCache get cache of certificate sha1s, per trust policy
static QMap< QString, QList< QSslCertificate > > certsGroupedByOrg(const QList< QSslCertificate > &certs)
Map certificates to their oraganization.
Widget for listing trusted Certificate (Intermediate) Authorities used in secure connections.
CertTrustPolicy
Type of certificate trust policy.
QgsAuthCertUtils::CertTrustPolicy defaultCertTrustPolicy()
Gets the default certificate trust policy preferred by user.
static QString getCertTrustName(QgsAuthCertUtils::CertTrustPolicy trust)
Gets the general name for certificate trust.
static QString getCaSourceName(QgsAuthCertUtils::CaCertSource source, bool single=false)
Gets the general name for CA source enum type.
static QString resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Gets the general name via RFC 5280 resolution.
bool rebuildCertTrustCache()
Rebuild certificate authority cache.