QGIS API Documentation 3.99.0-Master (e9821da5c6b)
Loading...
Searching...
No Matches
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
17#include "ui_qgsauthauthoritieseditor.h"
19
20#include "qgsapplication.h"
22#include "qgsauthcertutils.h"
23#include "qgsauthguiutils.h"
25#include "qgsauthmanager.h"
27#include "qgslogger.h"
28#include "qgssettings.h"
29#include "qgsvariantutils.h"
30
31#include <QAction>
32#include <QComboBox>
33#include <QDateTime>
34#include <QDir>
35#include <QFileDialog>
36#include <QFileInfo>
37#include <QMenu>
38#include <QMessageBox>
39#include <QPair>
40#include <QPushButton>
41#include <QSslConfiguration>
42#include <QString>
43
44#include "moc_qgsauthauthoritieseditor.cpp"
45
46using namespace Qt::StringLiterals;
47
49 : QWidget( parent )
50{
51 if ( QgsApplication::authManager()->isDisabled() )
52 {
53 mDisabled = true;
54 mAuthNotifyLayout = new QVBoxLayout;
55 this->setLayout( mAuthNotifyLayout );
56 mAuthNotify = new QLabel( QgsApplication::authManager()->disabledMessage(), this );
57 mAuthNotifyLayout->addWidget( mAuthNotify );
58 }
59 else
60 {
61 setupUi( this );
62 connect( btnAddCa, &QToolButton::clicked, this, &QgsAuthAuthoritiesEditor::btnAddCa_clicked );
63 connect( btnRemoveCa, &QToolButton::clicked, this, &QgsAuthAuthoritiesEditor::btnRemoveCa_clicked );
64 connect( btnInfoCa, &QToolButton::clicked, this, &QgsAuthAuthoritiesEditor::btnInfoCa_clicked );
65 connect( btnGroupByOrg, &QToolButton::toggled, this, &QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled );
66 connect( btnCaFile, &QToolButton::clicked, this, &QgsAuthAuthoritiesEditor::btnCaFile_clicked );
67 connect( btnCaFileClear, &QToolButton::clicked, this, &QgsAuthAuthoritiesEditor::btnCaFileClear_clicked );
68
69 connect( QgsApplication::authManager(), &QgsAuthManager::messageLog, this, &QgsAuthAuthoritiesEditor::logMessage );
70
71 connect( QgsApplication::authManager(), &QgsAuthManager::authDatabaseChanged, this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
72
73 setupCaCertsTree();
74
75 connect( treeWidgetCAs->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAuthAuthoritiesEditor::selectionChanged );
76
77 connect( treeWidgetCAs, &QTreeWidget::itemDoubleClicked, this, &QgsAuthAuthoritiesEditor::handleDoubleClick );
78
79 connect( btnViewRefresh, &QAbstractButton::clicked, this, &QgsAuthAuthoritiesEditor::refreshCaCertsView );
80
81 const QVariant cafileval = QgsApplication::authManager()->authSetting( u"cafile"_s );
82 if ( !QgsVariantUtils::isNull( cafileval ) )
83 {
84 leCaFile->setText( cafileval.toString() );
85 }
86
87 btnGroupByOrg->setChecked( false );
88 const QVariant sortbyval = QgsApplication::authManager()->authSetting( u"casortby"_s, QVariant( false ) );
89 if ( !QgsVariantUtils::isNull( sortbyval ) )
90 btnGroupByOrg->setChecked( sortbyval.toBool() );
91
92 mDefaultTrustPolicy = QgsApplication::authManager()->defaultCertTrustPolicy();
93 populateCaCertsView();
94 checkSelection();
95
96 populateUtilitiesMenu();
97 }
98}
99
100void QgsAuthAuthoritiesEditor::setupCaCertsTree()
101{
102 treeWidgetCAs->setColumnCount( 4 );
103 treeWidgetCAs->setHeaderLabels(
104 QStringList() << tr( "Common Name" )
105 << tr( "Serial #" )
106 << tr( "Expiry Date" )
107 << tr( "Trust Policy" )
108 );
109 treeWidgetCAs->setColumnWidth( 0, 300 );
110 treeWidgetCAs->setColumnWidth( 1, 75 );
111 treeWidgetCAs->setColumnWidth( 2, 200 );
112
113 // add root sections
114 mDbCaSecItem = new QTreeWidgetItem(
115 treeWidgetCAs,
116 QStringList( QgsAuthCertUtils::getCaSourceName( QgsAuthCertUtils::InDatabase ) ),
117 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
118 );
119 QgsAuthGuiUtils::setItemBold( mDbCaSecItem );
120 mDbCaSecItem->setFlags( Qt::ItemIsEnabled );
121 mDbCaSecItem->setExpanded( true );
122 treeWidgetCAs->insertTopLevelItem( 0, mDbCaSecItem );
123
124 mFileCaSecItem = new QTreeWidgetItem(
125 treeWidgetCAs,
126 QStringList( QgsAuthCertUtils::getCaSourceName( QgsAuthCertUtils::FromFile ) ),
127 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
128 );
129 QgsAuthGuiUtils::setItemBold( mFileCaSecItem );
130 mFileCaSecItem->setFlags( Qt::ItemIsEnabled );
131 mFileCaSecItem->setExpanded( true );
132 treeWidgetCAs->insertTopLevelItem( 0, mFileCaSecItem );
133
134 mRootCaSecItem = new QTreeWidgetItem(
135 treeWidgetCAs,
136 QStringList( QgsAuthCertUtils::getCaSourceName( QgsAuthCertUtils::SystemRoot ) ),
137 static_cast<int>( QgsAuthAuthoritiesEditor::Section )
138 );
139 QgsAuthGuiUtils::setItemBold( mRootCaSecItem );
140 mRootCaSecItem->setFlags( Qt::ItemIsEnabled );
141 mRootCaSecItem->setExpanded( false );
142 treeWidgetCAs->insertTopLevelItem( 0, mRootCaSecItem );
143}
144
145void QgsAuthAuthoritiesEditor::populateCaCertsView()
146{
147 updateCertTrustPolicyCache();
148 populateDatabaseCaCerts();
149 populateFileCaCerts();
150 populateRootCaCerts();
151}
152
153void QgsAuthAuthoritiesEditor::refreshCaCertsView()
154{
155 // QgsApplication::authManager()->rebuildCaCertsCache();
156 populateCaCertsView();
157}
158
159void QgsAuthAuthoritiesEditor::populateDatabaseCaCerts()
160{
161 QgsAuthGuiUtils::removeChildren( mDbCaSecItem );
162
163 const bool expanded = mDbCaSecItem->isExpanded();
164 populateCaCertsSection( mDbCaSecItem, QgsApplication::authManager()->databaseCAs(), QgsAuthAuthoritiesEditor::DbCaCert );
165 mDbCaSecItem->setExpanded( expanded );
166}
167
168void QgsAuthAuthoritiesEditor::populateFileCaCerts()
169{
170 QgsAuthGuiUtils::removeChildren( mFileCaSecItem );
171
172 const bool expanded = mFileCaSecItem->isExpanded();
173 populateCaCertsSection( mFileCaSecItem, QgsApplication::authManager()->extraFileCAs(), QgsAuthAuthoritiesEditor::FileCaCert );
174 mFileCaSecItem->setExpanded( expanded );
175}
176
177void QgsAuthAuthoritiesEditor::populateRootCaCerts()
178{
179 QgsAuthGuiUtils::removeChildren( mRootCaSecItem );
180
181 const bool expanded = mRootCaSecItem->isExpanded();
182 populateCaCertsSection( mRootCaSecItem, QgsApplication::authManager()->systemRootCAs(), QgsAuthAuthoritiesEditor::RootCaCert );
183 mRootCaSecItem->setExpanded( expanded );
184}
185
186void QgsAuthAuthoritiesEditor::populateCaCertsSection( QTreeWidgetItem *item, const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype )
187{
188 if ( btnGroupByOrg->isChecked() )
189 {
190 appendCertsToGroup( certs, catype, item );
191 }
192 else
193 {
194 appendCertsToItem( certs, catype, item );
195 }
196}
197
198void QgsAuthAuthoritiesEditor::appendCertsToGroup( const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
199{
200 if ( certs.empty() )
201 return;
202
203 if ( !parent )
204 {
205 parent = treeWidgetCAs->currentItem();
206 }
207
208 // TODO: find all organizational name, sort and make subsections
209 const QMap<QString, QList<QSslCertificate>> orgcerts(
210 QgsAuthCertUtils::certsGroupedByOrg( certs )
211 );
212
213 QMap<QString, QList<QSslCertificate>>::const_iterator it = orgcerts.constBegin();
214 for ( ; it != orgcerts.constEnd(); ++it )
215 {
216 QTreeWidgetItem *grpitem( new QTreeWidgetItem( parent, QStringList() << it.key(), static_cast<int>( QgsAuthAuthoritiesEditor::OrgName ) ) );
217 grpitem->setFirstColumnSpanned( true );
218 grpitem->setFlags( Qt::ItemIsEnabled );
219 grpitem->setExpanded( true );
220
221 QBrush orgb( grpitem->foreground( 0 ) );
222 orgb.setColor( QColor::fromRgb( 90, 90, 90 ) );
223 grpitem->setForeground( 0, orgb );
224 QFont grpf( grpitem->font( 0 ) );
225 grpf.setItalic( true );
226 grpitem->setFont( 0, grpf );
227
228 appendCertsToItem( it.value(), catype, grpitem );
229 }
230
231 parent->sortChildren( 0, Qt::AscendingOrder );
232}
233
234void QgsAuthAuthoritiesEditor::appendCertsToItem( const QList<QSslCertificate> &certs, QgsAuthAuthoritiesEditor::CaType catype, QTreeWidgetItem *parent )
235{
236 if ( certs.empty() )
237 return;
238
239 if ( !parent )
240 {
241 parent = treeWidgetCAs->currentItem();
242 }
243
244 const QBrush greenb( QgsAuthGuiUtils::greenColor() );
245 const QBrush redb( QgsAuthGuiUtils::redColor() );
246
247 const QStringList trustedids = mCertTrustCache.value( QgsAuthCertUtils::Trusted );
248 const QStringList untrustedids = mCertTrustCache.value( QgsAuthCertUtils::Untrusted );
249
250 // Columns: Common Name, Serial #, Expiry Date
251 const auto constCerts = certs;
252 for ( const QSslCertificate &cert : constCerts )
253 {
254 const QString id( QgsAuthCertUtils::shaHexForCert( cert ) );
255
256 QStringList coltxts;
257 coltxts << QgsAuthCertUtils::resolvedCertName( cert );
258 coltxts << QString( cert.serialNumber() );
259 coltxts << cert.expiryDate().toString();
260
261 // trust policy
262 QString policy( QgsAuthCertUtils::getCertTrustName( mDefaultTrustPolicy ) );
263 if ( trustedids.contains( id ) )
264 {
265 policy = QgsAuthCertUtils::getCertTrustName( QgsAuthCertUtils::Trusted );
266 }
267 else if ( untrustedids.contains( id )
268 || cert.isBlacklisted()
269 || cert.isNull()
270 || cert.expiryDate() <= QDateTime::currentDateTime()
271 || cert.effectiveDate() > QDateTime::currentDateTime() )
272 {
273 policy = QgsAuthCertUtils::getCertTrustName( QgsAuthCertUtils::Untrusted );
274 }
275 coltxts << policy;
276
277 QTreeWidgetItem *item( new QTreeWidgetItem( parent, coltxts, static_cast<int>( catype ) ) );
278
279 item->setIcon( 0, QgsApplication::getThemeIcon( u"/mIconCertificate.svg"_s ) );
280 if ( cert.isBlacklisted()
281 || cert.isNull()
282 || cert.expiryDate() <= QDateTime::currentDateTime()
283 || cert.effectiveDate() > QDateTime::currentDateTime() )
284 {
285 item->setForeground( 2, redb );
286 item->setIcon( 0, QgsApplication::getThemeIcon( u"/mIconCertificateUntrusted.svg"_s ) );
287 }
288
289 if ( trustedids.contains( id ) )
290 {
291 item->setForeground( 3, greenb );
292 if ( !cert.isBlacklisted()
293 && !cert.isNull()
294 && cert.expiryDate() > QDateTime::currentDateTime()
295 && cert.effectiveDate() <= QDateTime::currentDateTime() )
296 {
297 item->setIcon( 0, QgsApplication::getThemeIcon( u"/mIconCertificateTrusted.svg"_s ) );
298 }
299 }
300 else if ( untrustedids.contains( id ) )
301 {
302 item->setForeground( 3, redb );
303 item->setIcon( 0, QgsApplication::getThemeIcon( u"/mIconCertificateUntrusted.svg"_s ) );
304 }
305 else if ( mDefaultTrustPolicy == QgsAuthCertUtils::Untrusted )
306 {
307 item->setIcon( 0, QgsApplication::getThemeIcon( u"/mIconCertificateUntrusted.svg"_s ) );
308 }
309
310 item->setData( 0, Qt::UserRole, id );
311 }
312
313 parent->sortChildren( 0, Qt::AscendingOrder );
314}
315
316void QgsAuthAuthoritiesEditor::updateCertTrustPolicyCache()
317{
318 mCertTrustCache = QgsApplication::authManager()->certTrustCache();
319}
320
321void QgsAuthAuthoritiesEditor::populateUtilitiesMenu()
322{
323 mActionDefaultTrustPolicy = new QAction( u"Change default trust policy"_s, this );
324 connect( mActionDefaultTrustPolicy, &QAction::triggered, this, &QgsAuthAuthoritiesEditor::editDefaultTrustPolicy );
325
326 mActionShowTrustedCAs = new QAction( u"Show trusted authorities/issuers"_s, this );
327 connect( mActionShowTrustedCAs, &QAction::triggered, this, &QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities );
328
329 mUtilitiesMenu = new QMenu( this );
330 mUtilitiesMenu->addAction( mActionDefaultTrustPolicy );
331 mUtilitiesMenu->addSeparator();
332 mUtilitiesMenu->addAction( mActionShowTrustedCAs );
333
334 btnUtilities->setMenu( mUtilitiesMenu );
335}
336
337void QgsAuthAuthoritiesEditor::showCertInfo( QTreeWidgetItem *item )
338{
339 if ( !item )
340 return;
341
342 const QString digest( item->data( 0, Qt::UserRole ).toString() );
343
344 const QMap<QString, QPair<QgsAuthCertUtils::CaCertSource, QSslCertificate>> cacertscache(
345 QgsApplication::authManager()->caCertsCache()
346 );
347
348 if ( !cacertscache.contains( digest ) )
349 {
350 QgsDebugError( u"Certificate Authority not in CA certs cache"_s );
351 return;
352 }
353
354 const QSslCertificate cert( cacertscache.value( digest ).second );
355
356 QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, true, this );
357 dlg->setWindowModality( Qt::WindowModal );
358 dlg->resize( 675, 500 );
359 dlg->exec();
360 if ( dlg->trustCacheRebuilt() )
361 {
362 // QgsApplication::authManager()->rebuildTrustedCaCertsCache() already called in dlg
363 populateCaCertsView();
364 }
365 dlg->deleteLater();
366}
367
368void QgsAuthAuthoritiesEditor::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
369{
370 Q_UNUSED( selected )
371 Q_UNUSED( deselected )
372 checkSelection();
373}
374
375void QgsAuthAuthoritiesEditor::checkSelection()
376{
377 bool iscert = false;
378 bool isdbcert = false;
379 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
380 {
381 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
382
383 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
384 {
385 case QgsAuthAuthoritiesEditor::RootCaCert:
386 iscert = true;
387 break;
388 case QgsAuthAuthoritiesEditor::FileCaCert:
389 iscert = true;
390 break;
391 case QgsAuthAuthoritiesEditor::DbCaCert:
392 iscert = true;
393 isdbcert = true;
394 break;
395 default:
396 break;
397 }
398 }
399
400 btnRemoveCa->setEnabled( isdbcert );
401 btnInfoCa->setEnabled( iscert );
402}
403
404void QgsAuthAuthoritiesEditor::handleDoubleClick( QTreeWidgetItem *item, int col )
405{
406 Q_UNUSED( col )
407 bool iscert = true;
408
409 switch ( ( QgsAuthAuthoritiesEditor::CaType ) item->type() )
410 {
411 case QgsAuthAuthoritiesEditor::Section:
412 iscert = false;
413 break;
414 case QgsAuthAuthoritiesEditor::OrgName:
415 iscert = false;
416 break;
417 default:
418 break;
419 }
420
421 if ( iscert )
422 {
423 showCertInfo( item );
424 }
425}
426
427void QgsAuthAuthoritiesEditor::btnAddCa_clicked()
428{
429 QgsAuthImportCertDialog *dlg = new QgsAuthImportCertDialog( this, QgsAuthImportCertDialog::CaFilter );
430 dlg->setWindowModality( Qt::WindowModal );
431 dlg->resize( 400, 450 );
432 if ( dlg->exec() )
433 {
434 const QList<QSslCertificate> &certs( dlg->certificatesToImport() );
435 if ( !QgsApplication::authManager()->storeCertAuthorities( certs ) )
436 {
437 messageBar()->pushMessage( tr( "ERROR storing CA(s) in authentication storage" ), Qgis::MessageLevel::Critical );
438 }
439
441
443 {
444 const auto constCerts = certs;
445 for ( const QSslCertificate &cert : constCerts )
446 {
447 if ( !QgsApplication::authManager()->storeCertTrustPolicy( cert, dlg->certTrustPolicy() ) )
448 {
449 logMessage( QObject::tr( "Could not set trust policy for imported certificates" ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Warning );
450 }
451 }
453 updateCertTrustPolicyCache();
454 }
455
457 populateDatabaseCaCerts();
458 mDbCaSecItem->setExpanded( true );
459 }
460 dlg->deleteLater();
461}
462
463void QgsAuthAuthoritiesEditor::btnRemoveCa_clicked()
464{
465 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
466
467 if ( !item )
468 {
469 QgsDebugMsgLevel( u"Current tree widget item not set"_s, 2 );
470 return;
471 }
472
473 const QString digest( item->data( 0, Qt::UserRole ).toString() );
474
475 if ( digest.isEmpty() )
476 {
477 messageBar()->pushMessage( tr( "Certificate id missing" ), Qgis::MessageLevel::Warning );
478 return;
479 }
480
481 const QMap<QString, QSslCertificate> mappedcerts(
482 QgsApplication::authManager()->mappedDatabaseCAs()
483 );
484
485 if ( !mappedcerts.contains( digest ) )
486 {
487 QgsDebugError( u"Certificate Authority not in mapped database CAs"_s );
488 return;
489 }
490
491 if ( QMessageBox::warning(
492 this, tr( "Remove Certificate Authority" ),
493 tr( "Are you sure you want to remove the selected "
494 "Certificate Authority from the database?\n\n"
495 "Operation can NOT be undone!" ),
496 QMessageBox::Ok | QMessageBox::Cancel,
497 QMessageBox::Cancel
498 )
499 == QMessageBox::Cancel )
500 {
501 return;
502 }
503
504 const QSslCertificate cert( mappedcerts.value( digest ) );
505
506 if ( cert.isNull() )
507 {
508 messageBar()->pushMessage( tr( "Certificate could not be found in the authentication storage for id %1:" ).arg( digest ), Qgis::MessageLevel::Warning );
509 return;
510 }
511
512 if ( !QgsApplication::authManager()->removeCertAuthority( cert ) )
513 {
514 messageBar()->pushMessage( tr( "ERROR removing CA from the authentication storage for id %1:" ).arg( digest ), Qgis::MessageLevel::Critical );
515 return;
516 }
517
518 if ( !QgsApplication::authManager()->removeCertTrustPolicy( cert ) )
519 {
520 messageBar()->pushMessage( tr( "ERROR removing cert trust policy from the authentication storage for id %1:" ).arg( digest ), Qgis::MessageLevel::Critical );
521 return;
522 }
523
526 updateCertTrustPolicyCache();
527
528 item->parent()->removeChild( item );
529 delete item;
530
531 // populateDatabaseCaCerts();
532 mDbCaSecItem->setExpanded( true );
533}
534
535void QgsAuthAuthoritiesEditor::btnInfoCa_clicked()
536{
537 if ( treeWidgetCAs->selectionModel()->selection().length() > 0 )
538 {
539 QTreeWidgetItem *item( treeWidgetCAs->currentItem() );
540 handleDoubleClick( item, 0 );
541 }
542}
543
544void QgsAuthAuthoritiesEditor::btnGroupByOrg_toggled( bool checked )
545{
546 if ( !QgsApplication::authManager()->storeAuthSetting( u"casortby"_s, QVariant( checked ) ) )
547 {
548 logMessage( QObject::tr( "Could not store sort by preference" ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Warning );
549 }
550 populateCaCertsView();
551}
552
553void QgsAuthAuthoritiesEditor::editDefaultTrustPolicy()
554{
555 QDialog *dlg = new QDialog( this );
556 dlg->setWindowTitle( tr( "Default Trust Policy" ) );
557 QVBoxLayout *layout = new QVBoxLayout( dlg );
558
559 QHBoxLayout *hlayout = new QHBoxLayout();
560
561 QLabel *lblwarn = new QLabel( dlg );
562 QStyle *style = QApplication::style();
563 lblwarn->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
564 lblwarn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
565 hlayout->addWidget( lblwarn );
566
567 QLabel *lbltxt = new QLabel( dlg );
568 lbltxt->setText( tr( "Changing the default certificate authority trust policy to 'Untrusted' "
569 "can cause unexpected SSL network connection results." ) );
570 lbltxt->setWordWrap( true );
571 hlayout->addWidget( lbltxt );
572
573 layout->addLayout( hlayout );
574
575 QHBoxLayout *hlayout2 = new QHBoxLayout();
576
577 QLabel *lblpolicy = new QLabel( tr( "Default policy" ), dlg );
578 lblpolicy->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );
579 hlayout2->addWidget( lblpolicy );
580
581 QComboBox *cmbpolicy = new QComboBox( dlg );
582 QList<QPair<QgsAuthCertUtils::CertTrustPolicy, QString>> policies;
583 policies << qMakePair( QgsAuthCertUtils::Trusted, QgsAuthCertUtils::getCertTrustName( QgsAuthCertUtils::Trusted ) )
584 << qMakePair( QgsAuthCertUtils::Untrusted, QgsAuthCertUtils::getCertTrustName( QgsAuthCertUtils::Untrusted ) );
585
586 for ( int i = 0; i < policies.size(); i++ )
587 {
588 cmbpolicy->addItem( policies.at( i ).second, QVariant( static_cast<int>( policies.at( i ).first ) ) );
589 }
590
591 const int idx = cmbpolicy->findData( QVariant( static_cast<int>( mDefaultTrustPolicy ) ) );
592 cmbpolicy->setCurrentIndex( idx == -1 ? 0 : idx );
593 hlayout2->addWidget( cmbpolicy );
594
595 layout->addLayout( hlayout2 );
596
597 QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Close | QDialogButtonBox::Ok, Qt::Horizontal, dlg );
598 buttonBox->button( QDialogButtonBox::Close )->setDefault( true );
599
600 layout->addWidget( buttonBox );
601
602 connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
603 connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QWidget::close );
604
605 dlg->setLayout( layout );
606 dlg->setWindowModality( Qt::WindowModal );
607 dlg->resize( 400, 200 );
608 dlg->setMinimumSize( 400, 200 );
609 dlg->setMaximumSize( 500, 300 );
610 if ( dlg->exec() )
611 {
612 const QgsAuthCertUtils::CertTrustPolicy trustpolicy(
613 ( QgsAuthCertUtils::CertTrustPolicy ) cmbpolicy->currentData().toInt()
614 );
615 if ( mDefaultTrustPolicy != trustpolicy )
616 {
617 defaultTrustPolicyChanged( trustpolicy );
618 }
619 }
620 dlg->deleteLater();
621}
622
623void QgsAuthAuthoritiesEditor::defaultTrustPolicyChanged( QgsAuthCertUtils::CertTrustPolicy trustpolicy )
624{
625 if ( !QgsApplication::authManager()->setDefaultCertTrustPolicy( trustpolicy ) )
626 {
627 logMessage( QObject::tr( "Could not store default trust policy." ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Critical );
628 }
629 mDefaultTrustPolicy = trustpolicy;
632 populateCaCertsView();
633}
634
635void QgsAuthAuthoritiesEditor::btnCaFile_clicked()
636{
637 QgsAuthImportCertDialog *dlg = new QgsAuthImportCertDialog( this, QgsAuthImportCertDialog::CaFilter, QgsAuthImportCertDialog::FileInput );
638 dlg->setWindowModality( Qt::WindowModal );
639 dlg->resize( 400, 250 );
640 if ( dlg->exec() )
641 {
642 // clear out any currently defined file certs and their trust settings
643 if ( !leCaFile->text().isEmpty() )
644 {
645 btnCaFileClear_clicked();
646 }
647
648 const QString &fn = dlg->certFileToImport();
649 leCaFile->setText( fn );
650
651 if ( !QgsApplication::authManager()->storeAuthSetting( u"cafile"_s, QVariant( fn ) ) )
652 {
653 logMessage( QObject::tr( "Could not store 'CA file path' in authentication storage." ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Warning );
654 }
655 if ( !QgsApplication::authManager()->storeAuthSetting( u"cafileallowinvalid"_s, QVariant( dlg->allowInvalidCerts() ) ) )
656 {
657 logMessage( QObject::tr( "Could not store 'CA file allow invalids' setting in authentication storage." ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Warning );
658 }
659
661
663 {
664 const QList<QSslCertificate> certs( QgsApplication::authManager()->extraFileCAs() );
665 const auto constCerts = certs;
666 for ( const QSslCertificate &cert : constCerts )
667 {
668 if ( !QgsApplication::authManager()->storeCertTrustPolicy( cert, dlg->certTrustPolicy() ) )
669 {
670 logMessage( QObject::tr( "Could not set trust policy for imported certificates." ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Warning );
671 }
672 }
674 updateCertTrustPolicyCache();
675 }
676
678
679 populateFileCaCerts();
680 mFileCaSecItem->setExpanded( true );
681 }
682 dlg->deleteLater();
683}
684
685void QgsAuthAuthoritiesEditor::btnCaFileClear_clicked()
686{
687 if ( !QgsApplication::authManager()->removeAuthSetting( u"cafile"_s ) )
688 {
689 logMessage( QObject::tr( "Could not remove 'CA file path' from authentication storage." ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Warning );
690 return;
691 }
692 if ( !QgsApplication::authManager()->removeAuthSetting( u"cafileallowinvalid"_s ) )
693 {
694 logMessage( QObject::tr( "Could not remove 'CA file allow invalids' setting from authentication storage." ), QObject::tr( "Authorities Manager" ), Qgis::MessageLevel::Warning );
695 return;
696 }
697
699
700 const QString fn( leCaFile->text() );
701 if ( QFile::exists( fn ) )
702 {
703 const QList<QSslCertificate> certs( QgsAuthCertUtils::certsFromFile( fn ) );
704
705 if ( !certs.isEmpty() )
706 {
707 if ( !QgsApplication::authManager()->removeCertTrustPolicies( certs ) )
708 {
709 messageBar()->pushMessage( tr( "ERROR removing cert(s) trust policy from authentication storage." ), Qgis::MessageLevel::Critical );
710 return;
711 }
713 updateCertTrustPolicyCache();
714 }
715 }
716
718
719 leCaFile->clear();
720 populateFileCaCerts();
721}
722
723void QgsAuthAuthoritiesEditor::showTrustedCertificateAuthorities()
724{
725 QgsAuthTrustedCAsDialog *dlg = new QgsAuthTrustedCAsDialog( this );
726 dlg->setWindowModality( Qt::WindowModal );
727 dlg->resize( 675, 500 );
728 dlg->exec();
729 dlg->deleteLater();
730}
731
732void QgsAuthAuthoritiesEditor::logMessage( const QString &message, const QString &authtag, Qgis::MessageLevel level )
733{
734 messageBar()->pushMessage( authtag, message, level, 7 );
735}
736
738{
739 if ( !mDisabled )
740 {
741 treeWidgetCAs->setFocus();
742 }
743 QWidget::showEvent( e );
744}
745
746QgsMessageBar *QgsAuthAuthoritiesEditor::messageBar()
747{
748 return msgBar;
749}
750
751int QgsAuthAuthoritiesEditor::messageTimeout()
752{
753 const QgsSettings settings;
754 return settings.value( u"qgis/messageTimeout"_s, 5 ).toInt();
755}
MessageLevel
Level for messages This will be used both for message log and message bar in application.
Definition qgis.h:159
@ Warning
Warning message.
Definition qgis.h:161
@ Critical
Critical/error message.
Definition qgis.h:162
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.
bool trustCacheRebuilt() const
Whether the trust cache has been rebuilt.
CertTrustPolicy
Type of certificate trust policy.
static QColor greenColor()
Green color representing valid, trusted, etc. certificate.
static void setItemBold(QTreeWidgetItem *item)
Call setFirstColumnSpanned(true) on the item and make its font bold.
static void removeChildren(QTreeWidgetItem *item)
Remove the children of the passed item.
static QColor redColor()
Red color representing invalid, untrusted, etc. certificate.
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)
Returns a previously set authentication setting.
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.
A bar for displaying non-blocking messages to the user.
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)
Definition qgslogger.h:63
#define QgsDebugError(str)
Definition qgslogger.h:59