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();