QGIS API Documentation 3.41.0-Master (45a0abf3bec)
Loading...
Searching...
No Matches
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
19#include "moc_qgsauthsslerrorsdialog.cpp"
21
22#include <QDialogButtonBox>
23#include <QFont>
24#include <QPushButton>
25#include <QStyle>
26#include <QToolButton>
27
28#include "qgsauthmanager.h"
30#include "qgsauthcertutils.h"
33#include "qgslogger.h"
34#include "qgsapplication.h"
35
36
38 const QList<QSslError> &sslErrors,
39 QWidget *parent,
40 const QString &digest,
41 const QString &hostport )
42 : QDialog( parent )
43 , mSslConfiguration( reply->sslConfiguration() )
44 , mSslErrors( sslErrors )
45 , mDigest( digest )
46 , mHostPort( hostport )
47{
48 if ( mDigest.isEmpty() )
49 {
50 mDigest = QgsAuthCertUtils::shaHexForCert( mSslConfiguration.peerCertificate() );
51 }
52 if ( mHostPort.isEmpty() )
53 {
54 mHostPort = QStringLiteral( "%1:%2" )
55 .arg( reply->url().host() )
56 .arg( reply->url().port() != -1 ? reply->url().port() : 443 )
57 .trimmed();
58 }
59
60 setupUi( this );
61 connect( buttonBox, &QDialogButtonBox::clicked, this, &QgsAuthSslErrorsDialog::buttonBox_clicked );
62 connect( btnChainInfo, &QToolButton::clicked, this, &QgsAuthSslErrorsDialog::btnChainInfo_clicked );
63 connect( btnChainCAs, &QToolButton::clicked, this, &QgsAuthSslErrorsDialog::btnChainCAs_clicked );
64 connect( grpbxSslErrors, &QgsCollapsibleGroupBoxBasic::collapsedStateChanged, this, &QgsAuthSslErrorsDialog::grpbxSslErrors_collapsedStateChanged );
65 QStyle *style = QApplication::style();
66 lblWarningIcon->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
67 lblWarningIcon->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
68
69 lblErrorsText->setStyleSheet( QStringLiteral( "QLabel{ font-weight: bold; }" ) );
70 leUrl->setText( reply->request().url().toString() );
71
72 ignoreButton()->setDefault( false );
73 abortButton()->setDefault( true );
74
75 if ( !QgsApplication::authManager()->isDisabled() )
76 {
77 saveButton()->setEnabled( false );
78
79 saveButton()->setText( QStringLiteral( "%1 && %2" ).arg( saveButton()->text(),
80 ignoreButton()->text() ) );
81
82 grpbxSslConfig->setChecked( false );
83 grpbxSslConfig->setCollapsed( true );
84 connect( grpbxSslConfig, &QGroupBox::toggled,
85 this, &QgsAuthSslErrorsDialog::loadUnloadCertificate );
86
87 connect( wdgtSslConfig, &QgsAuthSslConfigWidget::readyToSaveChanged,
88 this, &QgsAuthSslErrorsDialog::widgetReadyToSaveChanged );
89 wdgtSslConfig->setConfigCheckable( false );
90 wdgtSslConfig->certificateGroupBox()->setFlat( true );
91 }
92 else
93 {
94 btnChainInfo->setVisible( false );
95 btnChainCAs->setVisible( false );
96 grpbxSslConfig->setVisible( false );
97 saveButton()->setVisible( false );
98 }
99
100 populateErrorsList();
101}
102
103void QgsAuthSslErrorsDialog::loadUnloadCertificate( bool load )
104{
105 grpbxSslErrors->setCollapsed( load );
106 if ( !load )
107 {
108 QgsDebugMsgLevel( QStringLiteral( "Unloading certificate and host:port" ), 2 );
109 clearCertificateConfig();
110 return;
111 }
112 wdgtSslConfig->setEnabled( true );
113 QgsDebugMsgLevel( QStringLiteral( "Loading certificate for host:port = %1" ).arg( mHostPort ), 2 );
114 wdgtSslConfig->setSslCertificate( mSslConfiguration.peerCertificate(), mHostPort );
115 if ( !mSslErrors.isEmpty() )
116 {
117 wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
118 }
119}
120
121void QgsAuthSslErrorsDialog::showCertificateChainInfo()
122{
123 QList<QSslCertificate> peerchain( mSslConfiguration.peerCertificateChain() );
124
125 if ( !peerchain.isEmpty() )
126 {
127 const QSslCertificate cert = peerchain.takeFirst();
128 if ( !cert.isNull() )
129 {
130 QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this, peerchain );
131 dlg->setWindowModality( Qt::WindowModal );
132 dlg->resize( 675, 500 );
133 dlg->exec();
134 dlg->deleteLater();
135 }
136 }
137}
138
139void QgsAuthSslErrorsDialog::showCertificateChainCAsInfo()
140{
141 const QList< QSslCertificate > certificates = mSslConfiguration.caCertificates();
142 for ( const auto &cert : certificates )
143 {
144 qDebug() << cert.subjectInfo( QSslCertificate::SubjectInfo::CommonName );
145 }
146
147 QgsAuthTrustedCAsDialog *dlg = new QgsAuthTrustedCAsDialog( this, mSslConfiguration.caCertificates() );
148 dlg->setWindowModality( Qt::WindowModal );
149 dlg->resize( 675, 500 );
150 dlg->exec();
151 dlg->deleteLater();
152}
153
154void QgsAuthSslErrorsDialog::widgetReadyToSaveChanged( bool cansave )
155{
156 ignoreButton()->setDefault( false );
157 abortButton()->setDefault( !cansave );
158 saveButton()->setEnabled( cansave );
159 saveButton()->setDefault( cansave );
160}
161
162void QgsAuthSslErrorsDialog::checkCanSave()
163{
164 widgetReadyToSaveChanged( wdgtSslConfig->readyToSave() );
165}
166
167void QgsAuthSslErrorsDialog::clearCertificateConfig()
168{
169 wdgtSslConfig->resetSslCertConfig();
170 wdgtSslConfig->setEnabled( false );
171 checkCanSave();
172}
173
174void QgsAuthSslErrorsDialog::buttonBox_clicked( QAbstractButton *button )
175{
176 const QDialogButtonBox::StandardButton btnenum( buttonBox->standardButton( button ) );
177 switch ( btnenum )
178 {
179 case QDialogButtonBox::Ignore:
181 QStringLiteral( "%1:%2" ).arg( mDigest, mHostPort ),
182 mSslErrors );
183 accept();
184 break;
185 case QDialogButtonBox::Save:
186 // save config and ignore errors
187 wdgtSslConfig->saveSslCertConfig();
188 accept();
189 break;
190 case QDialogButtonBox::Abort:
191 default:
192 reject();
193 break;
194 }
195 // Clear access cache if the user choose abort and the
196 // setting allows it
197 if ( btnenum == QDialogButtonBox::Abort &&
198 QgsSettings().value( QStringLiteral( "clear_auth_cache_on_errors" ),
199 true,
200 QgsSettings::Section::Auth ).toBool( ) )
201 {
202 QgsNetworkAccessManager::instance()->clearAccessCache();
203 }
204}
205
206void QgsAuthSslErrorsDialog::populateErrorsList()
207{
208 QStringList errs;
209 errs.reserve( mSslErrors.size() );
210 const auto constMSslErrors = mSslErrors;
211 for ( const QSslError &err : constMSslErrors )
212 {
213 errs << QStringLiteral( "* %1: %2" )
214 .arg( QgsAuthCertUtils::sslErrorEnumString( err.error() ),
215 err.errorString() );
216 }
217 teSslErrors->setPlainText( errs.join( QLatin1Char( '\n' ) ) );
218}
219
220QPushButton *QgsAuthSslErrorsDialog::ignoreButton()
221{
222 return buttonBox->button( QDialogButtonBox::Ignore );
223}
224
225QPushButton *QgsAuthSslErrorsDialog::saveButton()
226{
227 return buttonBox->button( QDialogButtonBox::Save );
228}
229
230QPushButton *QgsAuthSslErrorsDialog::abortButton()
231{
232 return buttonBox->button( QDialogButtonBox::Abort );
233}
234
235void QgsAuthSslErrorsDialog::btnChainInfo_clicked()
236{
237 showCertificateChainInfo();
238}
239
240void QgsAuthSslErrorsDialog::btnChainCAs_clicked()
241{
242 showCertificateChainCAsInfo();
243}
244
245void QgsAuthSslErrorsDialog::grpbxSslErrors_collapsedStateChanged( bool collapsed )
246{
247 if ( !collapsed && QgsApplication::authManager()->isDisabled() )
248 {
249 btnChainInfo->setVisible( false );
250 btnChainCAs->setVisible( false );
251 }
252}
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:64
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39