QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsauthsslerrorsdialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsauthsslerrorsdialog.cpp
3 ---------------------
4 begin : May 22, 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
20
21#include <QDialogButtonBox>
22#include <QFont>
23#include <QPushButton>
24#include <QStyle>
25#include <QToolButton>
26
27#include "qgsauthmanager.h"
29#include "qgsauthcertutils.h"
32#include "qgslogger.h"
33#include "qgsapplication.h"
34
35
37 const QList<QSslError> &sslErrors,
38 QWidget *parent,
39 const QString &digest,
40 const QString &hostport )
41 : QDialog( parent )
42 , mSslConfiguration( reply->sslConfiguration() )
43 , mSslErrors( sslErrors )
44 , mDigest( digest )
45 , mHostPort( hostport )
46{
47 if ( mDigest.isEmpty() )
48 {
49 mDigest = QgsAuthCertUtils::shaHexForCert( mSslConfiguration.peerCertificate() );
50 }
51 if ( mHostPort.isEmpty() )
52 {
53 mHostPort = QStringLiteral( "%1:%2" )
54 .arg( reply->url().host() )
55 .arg( reply->url().port() != -1 ? reply->url().port() : 443 )
56 .trimmed();
57 }
58
59 setupUi( this );
60 connect( buttonBox, &QDialogButtonBox::clicked, this, &QgsAuthSslErrorsDialog::buttonBox_clicked );
61 connect( btnChainInfo, &QToolButton::clicked, this, &QgsAuthSslErrorsDialog::btnChainInfo_clicked );
62 connect( btnChainCAs, &QToolButton::clicked, this, &QgsAuthSslErrorsDialog::btnChainCAs_clicked );
63 connect( grpbxSslErrors, &QgsCollapsibleGroupBoxBasic::collapsedStateChanged, this, &QgsAuthSslErrorsDialog::grpbxSslErrors_collapsedStateChanged );
64 QStyle *style = QApplication::style();
65 lblWarningIcon->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
66 lblWarningIcon->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
67
68 lblErrorsText->setStyleSheet( QStringLiteral( "QLabel{ font-weight: bold; }" ) );
69 leUrl->setText( reply->request().url().toString() );
70
71 ignoreButton()->setDefault( false );
72 abortButton()->setDefault( true );
73
74 if ( !QgsApplication::authManager()->isDisabled() )
75 {
76 saveButton()->setEnabled( false );
77
78 saveButton()->setText( QStringLiteral( "%1 && %2" ).arg( saveButton()->text(),
79 ignoreButton()->text() ) );
80
81 grpbxSslConfig->setChecked( false );
82 grpbxSslConfig->setCollapsed( true );
83 connect( grpbxSslConfig, &QGroupBox::toggled,
84 this, &QgsAuthSslErrorsDialog::loadUnloadCertificate );
85
86 connect( wdgtSslConfig, &QgsAuthSslConfigWidget::readyToSaveChanged,
87 this, &QgsAuthSslErrorsDialog::widgetReadyToSaveChanged );
88 wdgtSslConfig->setConfigCheckable( false );
89 wdgtSslConfig->certificateGroupBox()->setFlat( true );
90 }
91 else
92 {
93 btnChainInfo->setVisible( false );
94 btnChainCAs->setVisible( false );
95 grpbxSslConfig->setVisible( false );
96 saveButton()->setVisible( false );
97 }
98
99 populateErrorsList();
100}
101
102void QgsAuthSslErrorsDialog::loadUnloadCertificate( bool load )
103{
104 grpbxSslErrors->setCollapsed( load );
105 if ( !load )
106 {
107 QgsDebugMsg( QStringLiteral( "Unloading certificate and host:port" ) );
108 clearCertificateConfig();
109 return;
110 }
111 wdgtSslConfig->setEnabled( true );
112 QgsDebugMsg( QStringLiteral( "Loading certificate for host:port = %1" ).arg( mHostPort ) );
113 wdgtSslConfig->setSslCertificate( mSslConfiguration.peerCertificate(), mHostPort );
114 if ( !mSslErrors.isEmpty() )
115 {
116 wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
117 }
118}
119
120void QgsAuthSslErrorsDialog::showCertificateChainInfo()
121{
122 QList<QSslCertificate> peerchain( mSslConfiguration.peerCertificateChain() );
123
124 if ( !peerchain.isEmpty() )
125 {
126 const QSslCertificate cert = peerchain.takeFirst();
127 if ( !cert.isNull() )
128 {
129 QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this, peerchain );
130 dlg->setWindowModality( Qt::WindowModal );
131 dlg->resize( 675, 500 );
132 dlg->exec();
133 dlg->deleteLater();
134 }
135 }
136}
137
138void QgsAuthSslErrorsDialog::showCertificateChainCAsInfo()
139{
140 const QList< QSslCertificate > certificates = mSslConfiguration.caCertificates();
141 for ( const auto &cert : certificates )
142 {
143 qDebug() << cert.subjectInfo( QSslCertificate::SubjectInfo::CommonName );
144 }
145
146 QgsAuthTrustedCAsDialog *dlg = new QgsAuthTrustedCAsDialog( this, mSslConfiguration.caCertificates() );
147 dlg->setWindowModality( Qt::WindowModal );
148 dlg->resize( 675, 500 );
149 dlg->exec();
150 dlg->deleteLater();
151}
152
153void QgsAuthSslErrorsDialog::widgetReadyToSaveChanged( bool cansave )
154{
155 ignoreButton()->setDefault( false );
156 abortButton()->setDefault( !cansave );
157 saveButton()->setEnabled( cansave );
158 saveButton()->setDefault( cansave );
159}
160
161void QgsAuthSslErrorsDialog::checkCanSave()
162{
163 widgetReadyToSaveChanged( wdgtSslConfig->readyToSave() );
164}
165
166void QgsAuthSslErrorsDialog::clearCertificateConfig()
167{
168 wdgtSslConfig->resetSslCertConfig();
169 wdgtSslConfig->setEnabled( false );
170 checkCanSave();
171}
172
173void QgsAuthSslErrorsDialog::buttonBox_clicked( QAbstractButton *button )
174{
175 const QDialogButtonBox::StandardButton btnenum( buttonBox->standardButton( button ) );
176 switch ( btnenum )
177 {
178 case QDialogButtonBox::Ignore:
180 QStringLiteral( "%1:%2" ).arg( mDigest, mHostPort ),
181 mSslErrors );
182 accept();
183 break;
184 case QDialogButtonBox::Save:
185 // save config and ignore errors
186 wdgtSslConfig->saveSslCertConfig();
187 accept();
188 break;
189 case QDialogButtonBox::Abort:
190 default:
191 reject();
192 break;
193 }
194 // Clear access cache if the user choose abort and the
195 // setting allows it
196 if ( btnenum == QDialogButtonBox::Abort &&
197 QgsSettings().value( QStringLiteral( "clear_auth_cache_on_errors" ),
198 true,
199 QgsSettings::Section::Auth ).toBool( ) )
200 {
201 QgsNetworkAccessManager::instance()->clearAccessCache();
202 }
203}
204
205void QgsAuthSslErrorsDialog::populateErrorsList()
206{
207 QStringList errs;
208 errs.reserve( mSslErrors.size() );
209 const auto constMSslErrors = mSslErrors;
210 for ( const QSslError &err : constMSslErrors )
211 {
212 errs << QStringLiteral( "* %1: %2" )
213 .arg( QgsAuthCertUtils::sslErrorEnumString( err.error() ),
214 err.errorString() );
215 }
216 teSslErrors->setPlainText( errs.join( QLatin1Char( '\n' ) ) );
217}
218
219QPushButton *QgsAuthSslErrorsDialog::ignoreButton()
220{
221 return buttonBox->button( QDialogButtonBox::Ignore );
222}
223
224QPushButton *QgsAuthSslErrorsDialog::saveButton()
225{
226 return buttonBox->button( QDialogButtonBox::Save );
227}
228
229QPushButton *QgsAuthSslErrorsDialog::abortButton()
230{
231 return buttonBox->button( QDialogButtonBox::Abort );
232}
233
234void QgsAuthSslErrorsDialog::btnChainInfo_clicked()
235{
236 showCertificateChainInfo();
237}
238
239void QgsAuthSslErrorsDialog::btnChainCAs_clicked()
240{
241 showCertificateChainCAsInfo();
242}
243
244void QgsAuthSslErrorsDialog::grpbxSslErrors_collapsedStateChanged( bool collapsed )
245{
246 if ( !collapsed && QgsApplication::authManager()->isDisabled() )
247 {
248 btnChainInfo->setVisible( false );
249 btnChainCAs->setVisible( false );
250 }
251}
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
Dialog wrapper for widget displaying detailed info on a certificate and its hierarchical trust chain.
static QString sslErrorEnumString(QSslError::SslError errenum)
Gets short strings describing an SSL error.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
bool updateIgnoredSslErrorsCache(const QString &shahostport, const QList< QSslError > &errors)
Update ignored SSL error cache with possible ignored SSL errors, using sha:host:port key.
void readyToSaveChanged(bool cansave)
Emitted when the configuration can be saved changes.
QgsAuthSslErrorsDialog(QNetworkReply *reply, const QList< QSslError > &sslErrors, QWidget *parent=nullptr, const QString &digest=QString(), const QString &hostport=QString())
Construct a dialog to handle SSL errors and saving SSL server certificate exceptions.
Widget for listing trusted Certificate (Intermediate) Authorities used in secure connections.
void collapsedStateChanged(bool collapsed)
Signal emitted when groupbox collapsed/expanded state is changed, and when first shown.
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
#define QgsDebugMsg(str)
Definition: qgslogger.h:38