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 const bool expanded = mDbCaSecItem->isExpanded();
175 populateCaCertsSection( mDbCaSecItem,
177 QgsAuthAuthoritiesEditor::DbCaCert );
178 mDbCaSecItem->setExpanded( expanded );
181 void QgsAuthAuthoritiesEditor::populateFileCaCerts()
183 removeChildren_( mFileCaSecItem );
185 const bool expanded = mFileCaSecItem->isExpanded();
186 populateCaCertsSection( mFileCaSecItem,
188 QgsAuthAuthoritiesEditor::FileCaCert );
189 mFileCaSecItem->setExpanded( expanded );
192 void QgsAuthAuthoritiesEditor::populateRootCaCerts()
194 removeChildren_( mRootCaSecItem );
196 const 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 const 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 )
291 || cert.isBlacklisted()
293 || cert.expiryDate() <= QDateTime::currentDateTime()
294 || cert.effectiveDate() > QDateTime::currentDateTime() )
300 QTreeWidgetItem *item(
new QTreeWidgetItem( parent, coltxts,
static_cast<int>( catype ) ) );
303 if ( cert.isBlacklisted()
305 || cert.expiryDate() <= QDateTime::currentDateTime()
306 || cert.effectiveDate() > QDateTime::currentDateTime() )
308 item->setForeground( 2, redb );
312 if ( trustedids.contains(
id ) )
314 item->setForeground( 3, greenb );
315 if ( !cert.isBlacklisted()
317 && cert.expiryDate() > QDateTime::currentDateTime()
318 && cert.effectiveDate() <= QDateTime::currentDateTime() )
323 else if ( untrustedids.contains(
id ) )
325 item->setForeground( 3, redb );
333 item->setData( 0, Qt::UserRole,
id );
336 parent->sortChildren( 0, Qt::AscendingOrder );
339 void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
344 void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
346 mActionDefaultTrustPolicy =
new QAction( QStringLiteral(
"Change default trust policy" ),
this );
347 connect( mActionDefaultTrustPolicy, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
349 mActionShowTrustedCAs =
new QAction( QStringLiteral(
"Show trusted authorities/issuers" ),
this );
350 connect( mActionShowTrustedCAs, &QAction::triggered,
this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
352 mUtilitiesMenu =
new QMenu(
this );
353 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
354 mUtilitiesMenu->addSeparator();
355 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
357 btnUtilities->setMenu( mUtilitiesMenu );
360 void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
365 const QString digest( item->data( 0, Qt::UserRole ).toString() );
367 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
370 if ( !cacertscache.contains( digest ) )
372 QgsDebugMsg( QStringLiteral(
"Certificate Authority not in CA certs cache" ) );
376 const QSslCertificate cert( cacertscache.value( digest ).second );
379 dlg->setWindowModality( Qt::WindowModal );
380 dlg->resize( 675, 500 );
385 populateCaCertsView();
390 void QgsAuthAuthoritiesEditor::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
393 Q_UNUSED( deselected )
397 void QgsAuthAuthoritiesEditor::checkSelection()
400 bool isdbcert =
false;
401 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
403 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
405 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
407 case QgsAuthAuthoritiesEditor::RootCaCert:
410 case QgsAuthAuthoritiesEditor::FileCaCert:
413 case QgsAuthAuthoritiesEditor::DbCaCert:
422 btnRemoveCa->setEnabled( isdbcert );
423 btnInfoCa->setEnabled( iscert );
426 void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item,
int col )
431 switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
433 case QgsAuthAuthoritiesEditor::Section:
436 case QgsAuthAuthoritiesEditor::OrgName:
445 showCertInfo( item );
449 void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
452 dlg->setWindowModality( Qt::WindowModal );
453 dlg->resize( 400, 450 );
459 messageBar()->
pushMessage( tr(
"ERROR storing CA(s) in authentication database" ),
460 Qgis::MessageLevel::Critical );
467 const auto constCerts = certs;
468 for (
const QSslCertificate &cert : constCerts )
472 authMessageOut( QObject::tr(
"Could not set trust policy for imported certificates" ),
473 QObject::tr(
"Authorities Manager" ),
478 updateCertTrustPolicyCache();
482 populateDatabaseCaCerts();
483 mDbCaSecItem->setExpanded(
true );
488 void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
490 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
494 QgsDebugMsg( QStringLiteral(
"Current tree widget item not set" ) );
498 const QString digest( item->data( 0, Qt::UserRole ).toString() );
500 if ( digest.isEmpty() )
502 messageBar()->
pushMessage( tr(
"Certificate id missing" ),
503 Qgis::MessageLevel::Warning );
507 const QMap<QString, QSslCertificate> mappedcerts(
510 if ( !mappedcerts.contains( digest ) )
512 QgsDebugMsg( QStringLiteral(
"Certificate Authority not in mapped database CAs" ) );
516 if ( QMessageBox::warning(
517 this, tr(
"Remove Certificate Authority" ),
518 tr(
"Are you sure you want to remove the selected "
519 "Certificate Authority from the database?\n\n"
520 "Operation can NOT be undone!" ),
521 QMessageBox::Ok | QMessageBox::Cancel,
522 QMessageBox::Cancel ) == QMessageBox::Cancel )
527 const QSslCertificate cert( mappedcerts.value( digest ) );
531 messageBar()->
pushMessage( tr(
"Certificate could not be found in database for id %1:" ).arg( digest ),
532 Qgis::MessageLevel::Warning );
538 messageBar()->
pushMessage( tr(
"ERROR removing CA from authentication database for id %1:" ).arg( digest ),
539 Qgis::MessageLevel::Critical );
545 messageBar()->
pushMessage( tr(
"ERROR removing cert trust policy from authentication database for id %1:" ).arg( digest ),
546 Qgis::MessageLevel::Critical );
552 updateCertTrustPolicyCache();
554 item->parent()->removeChild( item );
558 mDbCaSecItem->setExpanded(
true );
561 void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
563 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
565 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
566 handleDoubleClick( item, 0 );
570 void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled(
bool checked )
574 authMessageOut( QObject::tr(
"Could not store sort by preference" ),
575 QObject::tr(
"Authorities Manager" ),
578 populateCaCertsView();
581 void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
583 QDialog *dlg =
new QDialog(
this );
584 dlg->setWindowTitle( tr(
"Default Trust Policy" ) );
585 QVBoxLayout *layout =
new QVBoxLayout( dlg );
587 QHBoxLayout *hlayout =
new QHBoxLayout();
589 QLabel *lblwarn =
new QLabel( dlg );
590 QStyle *style = QApplication::style();
591 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
592 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
593 hlayout->addWidget( lblwarn );
595 QLabel *lbltxt =
new QLabel( dlg );
596 lbltxt->setText( tr(
"Changing the default certificate authority trust policy to 'Untrusted' "
597 "can cause unexpected SSL network connection results." ) );
598 lbltxt->setWordWrap(
true );
599 hlayout->addWidget( lbltxt );
601 layout->addLayout( hlayout );
603 QHBoxLayout *hlayout2 =
new QHBoxLayout();
605 QLabel *lblpolicy =
new QLabel( tr(
"Default policy" ), dlg );
606 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
607 hlayout2->addWidget( lblpolicy );
609 QComboBox *cmbpolicy =
new QComboBox( dlg );
610 QList < QPair<QgsAuthCertUtils::CertTrustPolicy, QString> > policies;
616 for (
int i = 0; i < policies.size(); i++ )
618 cmbpolicy->addItem( policies.at( i ).second, QVariant(
static_cast<int>( policies.at( i ).first ) ) );
621 const int idx = cmbpolicy->findData( QVariant(
static_cast<int>( mDefaultTrustPolicy ) ) );
622 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
623 hlayout2->addWidget( cmbpolicy );
625 layout->addLayout( hlayout2 );
627 QDialogButtonBox *buttonBox =
new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok,
628 Qt::Horizontal, dlg );
629 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
631 layout->addWidget( buttonBox );
633 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
634 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
636 dlg->setLayout( layout );
637 dlg->setWindowModality( Qt::WindowModal );
638 dlg->resize( 400, 200 );
639 dlg->setMinimumSize( 400, 200 );
640 dlg->setMaximumSize( 500, 300 );
645 if ( mDefaultTrustPolicy != trustpolicy )
647 defaultTrustPolicyChanged( trustpolicy );
657 authMessageOut( QObject::tr(
"Could not store default trust policy." ),
658 QObject::tr(
"Authorities Manager" ),
661 mDefaultTrustPolicy = trustpolicy;
664 populateCaCertsView();
667 void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
672 dlg->setWindowModality( Qt::WindowModal );
673 dlg->resize( 400, 250 );
677 if ( !leCaFile->text().isEmpty() )
679 btnCaFileClear_clicked();
683 leCaFile->setText( fn );
687 authMessageOut( QObject::tr(
"Could not store 'CA file path' in authentication database." ),
688 QObject::tr(
"Authorities Manager" ),
694 authMessageOut( QObject::tr(
"Could not store 'CA file allow invalids' setting in authentication database." ),
695 QObject::tr(
"Authorities Manager" ),
704 const auto constCerts = certs;
705 for (
const QSslCertificate &cert : constCerts )
709 authMessageOut( QObject::tr(
"Could not set trust policy for imported certificates." ),
710 QObject::tr(
"Authorities Manager" ),
715 updateCertTrustPolicyCache();
720 populateFileCaCerts();
721 mFileCaSecItem->setExpanded(
true );
726 void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
730 authMessageOut( QObject::tr(
"Could not remove 'CA file path' from authentication database." ),
731 QObject::tr(
"Authorities Manager" ),
737 authMessageOut( QObject::tr(
"Could not remove 'CA file allow invalids' setting from authentication database." ),
738 QObject::tr(
"Authorities Manager" ),
745 const QString fn( leCaFile->text() );
746 if ( QFile::exists( fn ) )
750 if ( !certs.isEmpty() )
754 messageBar()->
pushMessage( tr(
"ERROR removing cert(s) trust policy from authentication database." ),
755 Qgis::MessageLevel::Critical );
759 updateCertTrustPolicyCache();
766 populateFileCaCerts();
769 void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
772 dlg->setWindowModality( Qt::WindowModal );
773 dlg->resize( 675, 500 );
780 const int levelint =
static_cast<int>( level );
788 treeWidgetCAs->setFocus();
790 QWidget::showEvent( e );
798 int QgsAuthAuthoritiesEditor::messageTimeout()
801 return settings.
value( QStringLiteral(
"qgis/messageTimeout" ), 5 ).toInt();