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