QGIS API Documentation 3.99.0-Master (e9821da5c6b)
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
18
19#include "qgsapplication.h"
21#include "qgsauthcertutils.h"
22#include "qgsauthmanager.h"
26#include "qgslogger.h"
28
29#include <QDialogButtonBox>
30#include <QFont>
31#include <QPushButton>
32#include <QString>
33#include <QStyle>
34#include <QToolButton>
35
36#include "moc_qgsauthsslerrorsdialog.cpp"
37
38using namespace Qt::StringLiterals;
39
40QgsAuthSslErrorsDialog::QgsAuthSslErrorsDialog( QNetworkReply *reply, const QList<QSslError> &sslErrors, QWidget *parent, const QString &digest, 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 = u"%1:%2"_s
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( u"QLabel{ font-weight: bold; }"_s );
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( u"%1 && %2"_s.arg( saveButton()->text(), ignoreButton()->text() ) );
79
80 grpbxSslConfig->setChecked( false );
81 grpbxSslConfig->setCollapsed( true );
82 connect( grpbxSslConfig, &QGroupBox::toggled, this, &QgsAuthSslErrorsDialog::loadUnloadCertificate );
83
84 connect( wdgtSslConfig, &QgsAuthSslConfigWidget::readyToSaveChanged, this, &QgsAuthSslErrorsDialog::widgetReadyToSaveChanged );
85 wdgtSslConfig->setConfigCheckable( false );
86 wdgtSslConfig->certificateGroupBox()->setFlat( true );
87 }
88 else
89 {
90 btnChainInfo->setVisible( false );
91 btnChainCAs->setVisible( false );
92 grpbxSslConfig->setVisible( false );
93 saveButton()->setVisible( false );
94 }
95
96 populateErrorsList();
97}
98
99void QgsAuthSslErrorsDialog::loadUnloadCertificate( bool load )
100{
101 grpbxSslErrors->setCollapsed( load );
102 if ( !load )
103 {
104 QgsDebugMsgLevel( u"Unloading certificate and host:port"_s, 2 );
105 clearCertificateConfig();
106 return;
107 }
108 wdgtSslConfig->setEnabled( true );
109 QgsDebugMsgLevel( u"Loading certificate for host:port = %1"_s.arg( mHostPort ), 2 );
110 wdgtSslConfig->setSslCertificate( mSslConfiguration.peerCertificate(), mHostPort );
111 if ( !mSslErrors.isEmpty() )
112 {
113 wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
114 }
115}
116
117void QgsAuthSslErrorsDialog::showCertificateChainInfo()
118{
119 QList<QSslCertificate> peerchain( mSslConfiguration.peerCertificateChain() );
120
121 if ( !peerchain.isEmpty() )
122 {
123 const QSslCertificate cert = peerchain.takeFirst();
124 if ( !cert.isNull() )
125 {
126 QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this, peerchain );
127 dlg->setWindowModality( Qt::WindowModal );
128 dlg->resize( 675, 500 );
129 dlg->exec();
130 dlg->deleteLater();
131 }
132 }
133}
134
135void QgsAuthSslErrorsDialog::showCertificateChainCAsInfo()
136{
137 const QList<QSslCertificate> certificates = mSslConfiguration.caCertificates();
138 for ( const auto &cert : certificates )
139 {
140 qDebug() << cert.subjectInfo( QSslCertificate::SubjectInfo::CommonName );
141 }
142
143 QgsAuthTrustedCAsDialog *dlg = new QgsAuthTrustedCAsDialog( this, mSslConfiguration.caCertificates() );
144 dlg->setWindowModality( Qt::WindowModal );
145 dlg->resize( 675, 500 );
146 dlg->exec();
147 dlg->deleteLater();
148}
149
150void QgsAuthSslErrorsDialog::widgetReadyToSaveChanged( bool cansave )
151{
152 ignoreButton()->setDefault( false );
153 abortButton()->setDefault( !cansave );
154 saveButton()->setEnabled( cansave );
155 saveButton()->setDefault( cansave );
156}
157
158void QgsAuthSslErrorsDialog::checkCanSave()
159{
160 widgetReadyToSaveChanged( wdgtSslConfig->readyToSave() );
161}
162
163void QgsAuthSslErrorsDialog::clearCertificateConfig()
164{
165 wdgtSslConfig->resetSslCertConfig();
166 wdgtSslConfig->setEnabled( false );
167 checkCanSave();
168}
169
170void QgsAuthSslErrorsDialog::buttonBox_clicked( QAbstractButton *button )
171{
172 const QDialogButtonBox::StandardButton btnenum( buttonBox->standardButton( button ) );
173 switch ( btnenum )
174 {
175 case QDialogButtonBox::Ignore:
177 u"%1:%2"_s.arg( mDigest, mHostPort ),
178 mSslErrors
179 );
180 accept();
181 break;
182 case QDialogButtonBox::Save:
183 // save config and ignore errors
184 wdgtSslConfig->saveSslCertConfig();
185 accept();
186 break;
187 case QDialogButtonBox::Abort:
188 default:
189 reject();
190 break;
191 }
192 // Clear access cache if the user choose abort and the
193 // setting allows it
194 if ( btnenum == QDialogButtonBox::Abort && QgsSettings().value( u"clear_auth_cache_on_errors"_s, true, QgsSettings::Section::Auth ).toBool() )
195 {
196 QgsNetworkAccessManager::instance()->clearAccessCache();
197 }
198}
199
200void QgsAuthSslErrorsDialog::populateErrorsList()
201{
202 QStringList errs;
203 errs.reserve( mSslErrors.size() );
204 const auto constMSslErrors = mSslErrors;
205 for ( const QSslError &err : constMSslErrors )
206 {
207 errs << u"* %1: %2"_s
208 .arg( QgsAuthCertUtils::sslErrorEnumString( err.error() ), err.errorString() );
209 }
210 teSslErrors->setPlainText( errs.join( QLatin1Char( '\n' ) ) );
211}
212
213QPushButton *QgsAuthSslErrorsDialog::ignoreButton()
214{
215 return buttonBox->button( QDialogButtonBox::Ignore );
216}
217
218QPushButton *QgsAuthSslErrorsDialog::saveButton()
219{
220 return buttonBox->button( QDialogButtonBox::Save );
221}
222
223QPushButton *QgsAuthSslErrorsDialog::abortButton()
224{
225 return buttonBox->button( QDialogButtonBox::Abort );
226}
227
228void QgsAuthSslErrorsDialog::btnChainInfo_clicked()
229{
230 showCertificateChainInfo();
231}
232
233void QgsAuthSslErrorsDialog::btnChainCAs_clicked()
234{
235 showCertificateChainCAsInfo();
236}
237
238void QgsAuthSslErrorsDialog::grpbxSslErrors_collapsedStateChanged( bool collapsed )
239{
240 if ( !collapsed && QgsApplication::authManager()->isDisabled() )
241 {
242 btnChainInfo->setVisible( false );
243 btnChainCAs->setVisible( false );
244 }
245}
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
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.
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.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63