QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsauthauthoritieseditor.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsauthauthoritieseditor.cpp
3  ---------------------
4  begin : April 26, 2015
5  copyright : (C) 2015 by Boundless Spatial, Inc. USA
6  author : Larry Shaffer
7  email : lshaffer at boundlessgeo dot com
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
18 #include "ui_qgsauthauthoritieseditor.h"
19 
20 #include <QAction>
21 #include <QComboBox>
22 #include <QDateTime>
23 #include <QDir>
24 #include <QFileDialog>
25 #include <QFileInfo>
26 #include <QMenu>
27 #include <QMessageBox>
28 #include <QPair>
29 #include <QPushButton>
30 #include <QSslConfiguration>
31 
32 #include "qgssettings.h"
33 #include "qgsapplication.h"
34 #include "qgsauthcertificateinfo.h"
35 #include "qgsauthcertutils.h"
36 #include "qgsauthguiutils.h"
38 #include "qgsauthmanager.h"
40 #include "qgslogger.h"
41 
43  : QWidget( parent )
44 {
45  if ( QgsApplication::authManager()->isDisabled() )
46  {
47  mDisabled = true;
48  mAuthNotifyLayout = new QVBoxLayout;
49  this->setLayout( mAuthNotifyLayout );
50  mAuthNotify = new QLabel( QgsApplication::authManager()->disabledMessage(), this );
51  mAuthNotifyLayout->addWidget( mAuthNotify );
52  }
53  else
54  {
55  setupUi( this );
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 );
62 
64  this, &QgsAuthAuthoritiesEditor::authMessageOut );
65 
67  this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
68 
69  setupCaCertsTree();
70 
71  connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged,
72  this, &QgsAuthAuthoritiesEditor::selectionChanged );
73 
74  connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked,
75  this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
76 
77  connect( btnViewRefresh, &QAbstractButton::clicked, this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
78 
79  const QVariant cafileval = QgsApplication::authManager()->authSetting( QStringLiteral( "cafile" ) );
80  if ( !cafileval.isNull() )
81  {
82  leCaFile->setText( cafileval.toString() );
83  }
84 
85  btnGroupByOrg->setChecked( false );
86  const QVariant sortbyval = QgsApplication::authManager()->authSetting( QStringLiteral( "casortby" ), QVariant( false ) );
87  if ( !sortbyval.isNull() )
88  btnGroupByOrg->setChecked( sortbyval.toBool() );
89 
90  mDefaultTrustPolicy = QgsApplication::authManager()->defaultCertTrustPolicy();
91  populateCaCertsView();
92  checkSelection();
93 
94  populateUtilitiesMenu();
95  }
96 }
97 
98 static void setItemBold_( QTreeWidgetItem *item )
99 {
100  item->setFirstColumnSpanned( true );
101  QFont secf( item->font( 0 ) );
102  secf.setBold( true );
103  item->setFont( 0, secf );
104 }
105 
106 void QgsAuthAuthoritiesEditor::setupCaCertsTree()
107 {
108  treeWidgetCAs->setColumnCount( 4 );
109  treeWidgetCAs->setHeaderLabels(
110  QStringList() << tr( "Common Name" )
111  << tr( "Serial #" )
112  << tr( "Expiry Date" )
113  << tr( "Trust Policy" ) );
114  treeWidgetCAs->setColumnWidth( 0, 300 );
115  treeWidgetCAs->setColumnWidth( 1, 75 );
116  treeWidgetCAs->setColumnWidth( 2, 200 );
117 
118  // add root sections
119  mDbCaSecItem = new QTreeWidgetItem(
120  treeWidgetCAs,
122  static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
123  setItemBold_( mDbCaSecItem );
124  mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
125  mDbCaSecItem->setExpanded( true );
126  treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
127 
128  mFileCaSecItem = new QTreeWidgetItem(
129  treeWidgetCAs,
131  static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
132  setItemBold_( mFileCaSecItem );
133  mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
134  mFileCaSecItem->setExpanded( true );
135  treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
136 
137  mRootCaSecItem = new QTreeWidgetItem(
138  treeWidgetCAs,
140  static_cast<int>( QgsAuthAuthoritiesEditor::Section ) );
141  setItemBold_( mRootCaSecItem );
142  mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
143  mRootCaSecItem->setExpanded( false );
144  treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
145 }
146 
147 void QgsAuthAuthoritiesEditor::populateCaCertsView()
148 {
149  updateCertTrustPolicyCache();
150  populateDatabaseCaCerts();
151  populateFileCaCerts();
152  populateRootCaCerts();
153 }
154 
155 void QgsAuthAuthoritiesEditor::refreshCaCertsView()
156 {
157 // QgsApplication::authManager()->rebuildCaCertsCache();
158  populateCaCertsView();
159 }
160 
161 static void removeChildren_( QTreeWidgetItem *item )
162 {
163  const auto constTakeChildren = item->takeChildren();
164  for ( QTreeWidgetItem *child : constTakeChildren )
165  {
166  delete child;
167  }
168 }
169 
170 void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
171 {
172  removeChildren_( mDbCaSecItem );
173 
174  const bool expanded = mDbCaSecItem->isExpanded();
175  populateCaCertsSection( mDbCaSecItem,
176  QgsApplication::authManager()->databaseCAs(),
177  QgsAuthAuthoritiesEditor::DbCaCert );
178  mDbCaSecItem->setExpanded( expanded );
179 }
180 
181 void QgsAuthAuthoritiesEditor::populateFileCaCerts()
182 {
183  removeChildren_( mFileCaSecItem );
184 
185  const bool expanded = mFileCaSecItem->isExpanded();
186  populateCaCertsSection( mFileCaSecItem,
187  QgsApplication::authManager()->extraFileCAs(),
188  QgsAuthAuthoritiesEditor::FileCaCert );
189  mFileCaSecItem->setExpanded( expanded );
190 }
191 
192 void QgsAuthAuthoritiesEditor::populateRootCaCerts()
193 {
194  removeChildren_( mRootCaSecItem );
195 
196  const bool expanded = mRootCaSecItem->isExpanded();
197  populateCaCertsSection( mRootCaSecItem,
198  QgsApplication::authManager()->systemRootCAs(),
199  QgsAuthAuthoritiesEditor::RootCaCert );
200  mRootCaSecItem->setExpanded( expanded );
201 }
202 
203 void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item, const QList<QSslCertificate> &certs,
204  QgsAuthAuthoritiesEditor::CaType catype )
205 {
206  if ( btnGroupByOrg->isChecked() )
207  {
208  appendCertsToGroup( certs, catype, item );
209  }
210  else
211  {
212  appendCertsToItem( certs, catype, item );
213  }
214 }
215 
216 void QgsAuthAuthoritiesEditor::appendCertsToGroup( const QList<QSslCertificate> &certs,
217  QgsAuthAuthoritiesEditor::CaType catype,
218  QTreeWidgetItem *parent )
219 {
220  if ( certs.empty() )
221  return;
222 
223  if ( !parent )
224  {
225  parent = treeWidgetCAs->currentItem();
226  }
227 
228  // TODO: find all organizational name, sort and make subsections
229  const QMap< QString, QList<QSslCertificate> > orgcerts(
231 
232  QMap< QString, QList<QSslCertificate> >::const_iterator it = orgcerts.constBegin();
233  for ( ; it != orgcerts.constEnd(); ++it )
234  {
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 );
241 
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 );
248 
249  appendCertsToItem( it.value(), catype, grpitem );
250  }
251 
252  parent->sortChildren( 0, Qt::AscendingOrder );
253 }
254 
255 void QgsAuthAuthoritiesEditor::appendCertsToItem( const QList<QSslCertificate> &certs,
256  QgsAuthAuthoritiesEditor::CaType catype,
257  QTreeWidgetItem *parent )
258 {
259  if ( certs.empty() )
260  return;
261 
262  if ( !parent )
263  {
264  parent = treeWidgetCAs->currentItem();
265  }
266 
267  const QBrush greenb( QgsAuthGuiUtils::greenColor() );
268  const QBrush redb( QgsAuthGuiUtils::redColor() );
269 
270  const QStringList trustedids = mCertTrustCache.value( QgsAuthCertUtils::Trusted );
271  const QStringList untrustedids = mCertTrustCache.value( QgsAuthCertUtils::Untrusted );
272 
273  // Columns: Common Name, Serial #, Expiry Date
274  const auto constCerts = certs;
275  for ( const QSslCertificate &cert : constCerts )
276  {
277  const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
278 
279  QStringList coltxts;
280  coltxts << QgsAuthCertUtils::resolvedCertName( cert );
281  coltxts << QString( cert.serialNumber() );
282  coltxts << cert.expiryDate().toString();
283 
284  // trust policy
285  QString policy( QgsAuthCertUtils::getCertTrustName( mDefaultTrustPolicy ) );
286  if ( trustedids.contains( id ) )
287  {
289  }
290  else if ( untrustedids.contains( id )
291  || cert.isBlacklisted()
292  || cert.isNull()
293  || cert.expiryDate() <= QDateTime::currentDateTime()
294  || cert.effectiveDate() > QDateTime::currentDateTime() )
295  {
297  }
298  coltxts << policy;
299 
300  QTreeWidgetItem *item( new QTreeWidgetItem( parent, coltxts, static_cast<int>( catype ) ) );
301 
302  item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificate.svg" ) ) );
303  if ( cert.isBlacklisted()
304  || cert.isNull()
305  || cert.expiryDate() <= QDateTime::currentDateTime()
306  || cert.effectiveDate() > QDateTime::currentDateTime() )
307  {
308  item->setForeground( 2, redb );
309  item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateUntrusted.svg" ) ) );
310  }
311 
312  if ( trustedids.contains( id ) )
313  {
314  item->setForeground( 3, greenb );
315  if ( !cert.isBlacklisted()
316  && !cert.isNull()
317  && cert.expiryDate() > QDateTime::currentDateTime()
318  && cert.effectiveDate() <= QDateTime::currentDateTime() )
319  {
320  item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateTrusted.svg" ) ) );
321  }
322  }
323  else if ( untrustedids.contains( id ) )
324  {
325  item->setForeground( 3, redb );
326  item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateUntrusted.svg" ) ) );
327  }
328  else if ( mDefaultTrustPolicy == QgsAuthCertUtils::Untrusted )
329  {
330  item->setIcon( 0, QgsApplication::getThemeIcon( QStringLiteral( "/mIconCertificateUntrusted.svg" ) ) );
331  }
332 
333  item->setData( 0, Qt::UserRole, id );
334  }
335 
336  parent->sortChildren( 0, Qt::AscendingOrder );
337 }
338 
339 void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
340 {
341  mCertTrustCache = QgsApplication::authManager()->certTrustCache();
342 }
343 
344 void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
345 {
346  mActionDefaultTrustPolicy = new QAction( QStringLiteral( "Change default trust policy" ), this );
347  connect( mActionDefaultTrustPolicy, &QAction::triggered, this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
348 
349  mActionShowTrustedCAs = new QAction( QStringLiteral( "Show trusted authorities/issuers" ), this );
350  connect( mActionShowTrustedCAs, &QAction::triggered, this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
351 
352  mUtilitiesMenu = new QMenu( this );
353  mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
354  mUtilitiesMenu->addSeparator();
355  mUtilitiesMenu->addAction( mActionShowTrustedCAs );
356 
357  btnUtilities->setMenu( mUtilitiesMenu );
358 }
359 
360 void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
361 {
362  if ( !item )
363  return;
364 
365  const QString digest( item->data( 0, Qt::UserRole ).toString() );
366 
367  const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate> > cacertscache(
368  QgsApplication::authManager()->caCertsCache() );
369 
370  if ( !cacertscache.contains( digest ) )
371  {
372  QgsDebugMsg( QStringLiteral( "Certificate Authority not in CA certs cache" ) );
373  return;
374  }
375 
376  const QSslCertificate cert( cacertscache.value( digest ).second );
377 
378  QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, true, this );
379  dlg->setWindowModality( Qt::WindowModal );
380  dlg->resize( 675, 500 );
381  dlg->exec();
382  if ( dlg->trustCacheRebuilt() )
383  {
384  // QgsApplication::authManager()->rebuildTrustedCaCertsCache() already called in dlg
385  populateCaCertsView();
386  }
387  dlg->deleteLater();
388 }
389 
390 void QgsAuthAuthoritiesEditor::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
391 {
392  Q_UNUSED( selected )
393  Q_UNUSED( deselected )
394  checkSelection();
395 }
396 
397 void QgsAuthAuthoritiesEditor::checkSelection()
398 {
399  bool iscert = false;
400  bool isdbcert = false;
401  if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
402  {
403  QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
404 
405  switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
406  {
407  case QgsAuthAuthoritiesEditor::RootCaCert:
408  iscert = true;
409  break;
410  case QgsAuthAuthoritiesEditor::FileCaCert:
411  iscert = true;
412  break;
413  case QgsAuthAuthoritiesEditor::DbCaCert:
414  iscert = true;
415  isdbcert = true;
416  break;
417  default:
418  break;
419  }
420  }
421 
422  btnRemoveCa->setEnabled( isdbcert );
423  btnInfoCa->setEnabled( iscert );
424 }
425 
426 void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item, int col )
427 {
428  Q_UNUSED( col )
429  bool iscert = true;
430 
431  switch ( ( QgsAuthAuthoritiesEditor::CaType )item->type() )
432  {
433  case QgsAuthAuthoritiesEditor::Section:
434  iscert = false;
435  break;
436  case QgsAuthAuthoritiesEditor::OrgName:
437  iscert = false;
438  break;
439  default:
440  break;
441  }
442 
443  if ( iscert )
444  {
445  showCertInfo( item );
446  }
447 }
448 
449 void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
450 {
452  dlg->setWindowModality( Qt::WindowModal );
453  dlg->resize( 400, 450 );
454  if ( dlg->exec() )
455  {
456  const QList<QSslCertificate> &certs( dlg->certificatesToImport() );
457  if ( !QgsApplication::authManager()->storeCertAuthorities( certs ) )
458  {
459  messageBar()->pushMessage( tr( "ERROR storing CA(s) in authentication database" ),
460  Qgis::MessageLevel::Critical );
461  }
462 
464 
466  {
467  const auto constCerts = certs;
468  for ( const QSslCertificate &cert : constCerts )
469  {
470  if ( !QgsApplication::authManager()->storeCertTrustPolicy( cert, dlg->certTrustPolicy() ) )
471  {
472  authMessageOut( QObject::tr( "Could not set trust policy for imported certificates" ),
473  QObject::tr( "Authorities Manager" ),
475  }
476  }
478  updateCertTrustPolicyCache();
479  }
480 
482  populateDatabaseCaCerts();
483  mDbCaSecItem->setExpanded( true );
484  }
485  dlg->deleteLater();
486 }
487 
488 void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
489 {
490  QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
491 
492  if ( !item )
493  {
494  QgsDebugMsg( QStringLiteral( "Current tree widget item not set" ) );
495  return;
496  }
497 
498  const QString digest( item->data( 0, Qt::UserRole ).toString() );
499 
500  if ( digest.isEmpty() )
501  {
502  messageBar()->pushMessage( tr( "Certificate id missing" ),
503  Qgis::MessageLevel::Warning );
504  return;
505  }
506 
507  const QMap<QString, QSslCertificate> mappedcerts(
508  QgsApplication::authManager()->mappedDatabaseCAs() );
509 
510  if ( !mappedcerts.contains( digest ) )
511  {
512  QgsDebugMsg( QStringLiteral( "Certificate Authority not in mapped database CAs" ) );
513  return;
514  }
515 
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 )
523  {
524  return;
525  }
526 
527  const QSslCertificate cert( mappedcerts.value( digest ) );
528 
529  if ( cert.isNull() )
530  {
531  messageBar()->pushMessage( tr( "Certificate could not be found in database for id %1:" ).arg( digest ),
532  Qgis::MessageLevel::Warning );
533  return;
534  }
535 
536  if ( !QgsApplication::authManager()->removeCertAuthority( cert ) )
537  {
538  messageBar()->pushMessage( tr( "ERROR removing CA from authentication database for id %1:" ).arg( digest ),
539  Qgis::MessageLevel::Critical );
540  return;
541  }
542 
543  if ( !QgsApplication::authManager()->removeCertTrustPolicy( cert ) )
544  {
545  messageBar()->pushMessage( tr( "ERROR removing cert trust policy from authentication database for id %1:" ).arg( digest ),
546  Qgis::MessageLevel::Critical );
547  return;
548  }
549 
552  updateCertTrustPolicyCache();
553 
554  item->parent()->removeChild( item );
555  delete item;
556 
557 // populateDatabaseCaCerts();
558  mDbCaSecItem->setExpanded( true );
559 }
560 
561 void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
562 {
563  if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
564  {
565  QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
566  handleDoubleClick( item, 0 );
567  }
568 }
569 
570 void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled( bool checked )
571 {
572  if ( !QgsApplication::authManager()->storeAuthSetting( QStringLiteral( "casortby" ), QVariant( checked ) ) )
573  {
574  authMessageOut( QObject::tr( "Could not store sort by preference" ),
575  QObject::tr( "Authorities Manager" ),
577  }
578  populateCaCertsView();
579 }
580 
581 void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
582 {
583  QDialog *dlg = new QDialog( this );
584  dlg->setWindowTitle( tr( "Default Trust Policy" ) );
585  QVBoxLayout *layout = new QVBoxLayout( dlg );
586 
587  QHBoxLayout *hlayout = new QHBoxLayout();
588 
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 );
594 
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 );
600 
601  layout->addLayout( hlayout );
602 
603  QHBoxLayout *hlayout2 = new QHBoxLayout();
604 
605  QLabel *lblpolicy = new QLabel( tr( "Default policy" ), dlg );
606  lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
607  hlayout2->addWidget( lblpolicy );
608 
609  QComboBox *cmbpolicy = new QComboBox( dlg );
610  QList < QPair<QgsAuthCertUtils::CertTrustPolicy, QString> > policies;
611  policies << qMakePair( QgsAuthCertUtils::Trusted,
613  << qMakePair( QgsAuthCertUtils::Untrusted,
615 
616  for ( int i = 0; i < policies.size(); i++ )
617  {
618  cmbpolicy->addItem( policies.at( i ).second, QVariant( static_cast<int>( policies.at( i ).first ) ) );
619  }
620 
621  const int idx = cmbpolicy->findData( QVariant( static_cast<int>( mDefaultTrustPolicy ) ) );
622  cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
623  hlayout2->addWidget( cmbpolicy );
624 
625  layout->addLayout( hlayout2 );
626 
627  QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok,
628  Qt::Horizontal, dlg );
629  buttonBox->button( QDialogButtonBox::Close )->setDefault( true );
630 
631  layout->addWidget( buttonBox );
632 
633  connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
634  connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
635 
636  dlg->setLayout( layout );
637  dlg->setWindowModality( Qt::WindowModal );
638  dlg->resize( 400, 200 );
639  dlg->setMinimumSize( 400, 200 );
640  dlg->setMaximumSize( 500, 300 );
641  if ( dlg->exec() )
642  {
643  const QgsAuthCertUtils::CertTrustPolicy trustpolicy(
644  ( QgsAuthCertUtils::CertTrustPolicy )cmbpolicy->currentData().toInt() );
645  if ( mDefaultTrustPolicy != trustpolicy )
646  {
647  defaultTrustPolicyChanged( trustpolicy );
648  }
649  }
650  dlg->deleteLater();
651 }
652 
653 void QgsAuthAuthoritiesEditor::defaultTrustPolicyChanged( QgsAuthCertUtils::CertTrustPolicy trustpolicy )
654 {
655  if ( !QgsApplication::authManager()->setDefaultCertTrustPolicy( trustpolicy ) )
656  {
657  authMessageOut( QObject::tr( "Could not store default trust policy." ),
658  QObject::tr( "Authorities Manager" ),
660  }
661  mDefaultTrustPolicy = trustpolicy;
664  populateCaCertsView();
665 }
666 
667 void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
668 {
672  dlg->setWindowModality( Qt::WindowModal );
673  dlg->resize( 400, 250 );
674  if ( dlg->exec() )
675  {
676  // clear out any currently defined file certs and their trust settings
677  if ( !leCaFile->text().isEmpty() )
678  {
679  btnCaFileClear_clicked();
680  }
681 
682  const QString &fn = dlg->certFileToImport();
683  leCaFile->setText( fn );
684 
685  if ( !QgsApplication::authManager()->storeAuthSetting( QStringLiteral( "cafile" ), QVariant( fn ) ) )
686  {
687  authMessageOut( QObject::tr( "Could not store 'CA file path' in authentication database." ),
688  QObject::tr( "Authorities Manager" ),
690  }
691  if ( !QgsApplication::authManager()->storeAuthSetting( QStringLiteral( "cafileallowinvalid" ),
692  QVariant( dlg->allowInvalidCerts() ) ) )
693  {
694  authMessageOut( QObject::tr( "Could not store 'CA file allow invalids' setting in authentication database." ),
695  QObject::tr( "Authorities Manager" ),
697  }
698 
700 
702  {
703  const QList<QSslCertificate> certs( QgsApplication::authManager()->extraFileCAs() );
704  const auto constCerts = certs;
705  for ( const QSslCertificate &cert : constCerts )
706  {
707  if ( !QgsApplication::authManager()->storeCertTrustPolicy( cert, dlg->certTrustPolicy() ) )
708  {
709  authMessageOut( QObject::tr( "Could not set trust policy for imported certificates." ),
710  QObject::tr( "Authorities Manager" ),
712  }
713  }
715  updateCertTrustPolicyCache();
716  }
717 
719 
720  populateFileCaCerts();
721  mFileCaSecItem->setExpanded( true );
722  }
723  dlg->deleteLater();
724 }
725 
726 void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
727 {
728  if ( !QgsApplication::authManager()->removeAuthSetting( QStringLiteral( "cafile" ) ) )
729  {
730  authMessageOut( QObject::tr( "Could not remove 'CA file path' from authentication database." ),
731  QObject::tr( "Authorities Manager" ),
733  return;
734  }
735  if ( !QgsApplication::authManager()->removeAuthSetting( QStringLiteral( "cafileallowinvalid" ) ) )
736  {
737  authMessageOut( QObject::tr( "Could not remove 'CA file allow invalids' setting from authentication database." ),
738  QObject::tr( "Authorities Manager" ),
740  return;
741  }
742 
744 
745  const QString fn( leCaFile->text() );
746  if ( QFile::exists( fn ) )
747  {
748  const QList<QSslCertificate> certs( QgsAuthCertUtils::certsFromFile( fn ) );
749 
750  if ( !certs.isEmpty() )
751  {
752  if ( !QgsApplication::authManager()->removeCertTrustPolicies( certs ) )
753  {
754  messageBar()->pushMessage( tr( "ERROR removing cert(s) trust policy from authentication database." ),
755  Qgis::MessageLevel::Critical );
756  return;
757  }
759  updateCertTrustPolicyCache();
760  }
761  }
762 
764 
765  leCaFile->clear();
766  populateFileCaCerts();
767 }
768 
769 void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
770 {
772  dlg->setWindowModality( Qt::WindowModal );
773  dlg->resize( 675, 500 );
774  dlg->exec();
775  dlg->deleteLater();
776 }
777 
778 void QgsAuthAuthoritiesEditor::authMessageOut( const QString &message, const QString &authtag, QgsAuthManager::MessageLevel level )
779 {
780  const int levelint = static_cast<int>( level );
781  messageBar()->pushMessage( authtag, message, ( Qgis::MessageLevel )levelint, 7 );
782 }
783 
785 {
786  if ( !mDisabled )
787  {
788  treeWidgetCAs->setFocus();
789  }
790  QWidget::showEvent( e );
791 }
792 
793 QgsMessageBar *QgsAuthAuthoritiesEditor::messageBar()
794 {
795  return msgBar;
796 }
797 
798 int QgsAuthAuthoritiesEditor::messageTimeout()
799 {
800  const QgsSettings settings;
801  return settings.value( QStringLiteral( "qgis/messageTimeout" ), 5 ).toInt();
802 }
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition: qgis.h:106
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
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.
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.
Definition: qgsmessagebar.h:61
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:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38