QGIS API Documentation  2.14.0-Essen
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 
17 #include "qgsauthcertificateinfo.h"
18 #include "qgsauthsslerrorsdialog.h"
19 #include "qgsauthsslconfigwidget.h"
20 
21 #include <QDialogButtonBox>
22 #include <QFont>
23 #include <QPushButton>
24 #include <QStyle>
25 #include <QToolButton>
26 
27 #include "qgsauthmanager.h"
28 #include "qgsauthcertutils.h"
30 #include "qgscollapsiblegroupbox.h"
31 #include "qgslogger.h"
32 
33 
35  const QList<QSslError> &sslErrors,
36  QWidget *parent,
37  const QString &digest,
38  const QString &hostport )
39  : QDialog( parent )
40  , mSslConfiguration( reply->sslConfiguration() )
41  , mSslErrors( sslErrors )
42  , mDigest( digest )
43  , mHostPort( hostport )
44 {
45  if ( mDigest.isEmpty() )
46  {
47  mDigest = QgsAuthCertUtils::shaHexForCert( mSslConfiguration.peerCertificate() );
48  }
49  if ( mHostPort.isEmpty() )
50  {
51  mHostPort = QString( "%1:%2" )
52  .arg( reply->url().host() )
53  .arg( reply->url().port() != -1 ? reply->url().port() : 443 )
54  .trimmed();
55  }
56 
57  setupUi( this );
59  lblWarningIcon->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
60  lblWarningIcon->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
61 
62  lblErrorsText->setStyleSheet( "QLabel{ font-weight: bold; }" );
63  leUrl->setText( reply->request().url().toString() );
64 
65  ignoreButton()->setDefault( false );
66  abortButton()->setDefault( true );
67 
68  if ( !QgsAuthManager::instance()->isDisabled() )
69  {
70  saveButton()->setEnabled( false );
71 
72  saveButton()->setText( QString( "%1 && %2" ).arg( saveButton()->text(),
73  ignoreButton()->text() ) );
74 
75  grpbxSslConfig->setChecked( false );
76  grpbxSslConfig->setCollapsed( true );
77  connect( grpbxSslConfig, SIGNAL( toggled( bool ) ),
78  this, SLOT( loadUnloadCertificate( bool ) ) );
79 
80  connect( wdgtSslConfig, SIGNAL( readyToSaveChanged( bool ) ),
81  this, SLOT( widgetReadyToSaveChanged( bool ) ) );
82  wdgtSslConfig->setConfigCheckable( false );
83  wdgtSslConfig->certificateGroupBox()->setFlat( true );
84  }
85  else
86  {
87  btnChainInfo->setVisible( false );
88  btnChainCAs->setVisible( false );
89  grpbxSslConfig->setVisible( false );
90  saveButton()->setVisible( false );
91  }
92 
93  populateErrorsList();
94 }
95 
97 {
98 }
99 
100 void QgsAuthSslErrorsDialog::loadUnloadCertificate( bool load )
101 {
102  grpbxSslErrors->setCollapsed( load );
103  if ( !load )
104  {
105  QgsDebugMsg( "Unloading certificate and host:port" );
106  clearCertificateConfig();
107  return;
108  }
109  wdgtSslConfig->setEnabled( true );
110  QgsDebugMsg( QString( "Loading certificate for host:port = %1" ).arg( mHostPort ) );
111  wdgtSslConfig->setSslCertificate( mSslConfiguration.peerCertificate(), mHostPort );
112  if ( !mSslErrors.isEmpty() )
113  {
114  wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
115  }
116 }
117 
118 void QgsAuthSslErrorsDialog::showCertificateChainInfo()
119 {
120  QList<QSslCertificate> peerchain( mSslConfiguration.peerCertificateChain() );
121 
122  if ( !peerchain.isEmpty() )
123  {
124  QSslCertificate cert = peerchain.takeFirst();
125  if ( !cert.isNull() )
126  {
127  QgsAuthCertInfoDialog *dlg = new QgsAuthCertInfoDialog( cert, false, this, peerchain );
128  dlg->setWindowModality( Qt::WindowModal );
129  dlg->resize( 675, 500 );
130  dlg->exec();
131  dlg->deleteLater();
132  }
133  }
134 }
135 
136 void QgsAuthSslErrorsDialog::showCertificateChainCAsInfo()
137 {
138  QgsAuthTrustedCAsDialog *dlg = new QgsAuthTrustedCAsDialog( this, mSslConfiguration.caCertificates() );
139  dlg->setWindowModality( Qt::WindowModal );
140  dlg->resize( 675, 500 );
141  dlg->exec();
142  dlg->deleteLater();
143 }
144 
145 void QgsAuthSslErrorsDialog::widgetReadyToSaveChanged( bool cansave )
146 {
147  ignoreButton()->setDefault( false );
148  abortButton()->setDefault( !cansave );
149  saveButton()->setEnabled( cansave );
150  saveButton()->setDefault( cansave );
151 }
152 
153 void QgsAuthSslErrorsDialog::checkCanSave()
154 {
155  widgetReadyToSaveChanged( wdgtSslConfig->readyToSave() );
156 }
157 
158 void QgsAuthSslErrorsDialog::clearCertificateConfig()
159 {
160  wdgtSslConfig->resetSslCertConfig();
161  wdgtSslConfig->setEnabled( false );
162  checkCanSave();
163 }
164 
165 void QgsAuthSslErrorsDialog::on_buttonBox_clicked( QAbstractButton *button )
166 {
167  QDialogButtonBox::StandardButton btnenum( buttonBox->standardButton( button ) );
168  switch ( btnenum )
169  {
170  case QDialogButtonBox::Ignore:
172  QString( "%1:%2" ).arg( mDigest, mHostPort ),
173  mSslErrors );
174  accept();
175  break;
176  case QDialogButtonBox::Save:
177  // save config and ignore errors
178  wdgtSslConfig->saveSslCertConfig();
179  accept();
180  break;
181  case QDialogButtonBox::Abort:
182  default:
183  reject();
184  break;
185  }
186 }
187 
188 void QgsAuthSslErrorsDialog::populateErrorsList()
189 {
190  QStringList errs;
191  errs.reserve( mSslErrors.size() );
192  Q_FOREACH ( const QSslError &err, mSslErrors )
193  {
194  errs << QString( "* %1: %2" )
196  err.errorString() );
197  }
198  teSslErrors->setPlainText( errs.join( "\n" ) );
199 }
200 
201 QPushButton *QgsAuthSslErrorsDialog::ignoreButton()
202 {
203  return buttonBox->button( QDialogButtonBox::Ignore );
204 }
205 
206 QPushButton *QgsAuthSslErrorsDialog::saveButton()
207 {
208  return buttonBox->button( QDialogButtonBox::Save );
209 }
210 
211 QPushButton *QgsAuthSslErrorsDialog::abortButton()
212 {
213  return buttonBox->button( QDialogButtonBox::Abort );
214 }
215 
216 void QgsAuthSslErrorsDialog::on_btnChainInfo_clicked()
217 {
218  showCertificateChainInfo();
219 }
220 
221 void QgsAuthSslErrorsDialog::on_btnChainCAs_clicked()
222 {
223  showCertificateChainCAsInfo();
224 }
225 
226 void QgsAuthSslErrorsDialog::on_grpbxSslErrors_collapsedStateChanged( bool collapsed )
227 {
228  if ( !collapsed && QgsAuthManager::instance()->isDisabled() )
229  {
230  btnChainInfo->setVisible( false );
231  btnChainCAs->setVisible( false );
232  }
233 }
void setupUi(QWidget *widget)
virtual void reject()
static QgsAuthManager * instance()
Enforce singleton pattern.
bool isNull() const
void setWindowModality(Qt::WindowModality windowModality)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void reserve(int alloc)
QStyle * style() const
static QString sslErrorEnumString(QSslError::SslError errenum)
Get short strings describing an SSL error.
QString host() const
virtual void setVisible(bool visible)
QNetworkRequest request() const
int exec()
QString join(const QString &separator) const
int port() const
QString toString(QFlags< QUrl::FormattingOption > options) const
QSslCertificate peerCertificate() const
QPixmap pixmap(const QSize &size, Mode mode, State state) const
int size() const
void resize(int w, int h)
QList< QSslCertificate > peerCertificateChain() const
void setEnabled(bool)
Dialog wrapper for widget displaying detailed info on a certificate and its hierarchical trust chain...
bool isEmpty() const
bool isEmpty() const
void deleteLater()
virtual void accept()
QString errorString() const
QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
QUrl url() const
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Get the sha1 hash for certificate.
QStyle * style()
bool updateIgnoredSslErrorsCache(const QString &shahostport, const QList< QSslError > &errors)
Update ignored SSL error cache with possible ignored SSL errors, using sha:host:port key...
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.
QUrl url() const
SslError error() const
void setText(const QString &text)
Widget for listing trusted Certificate (Intermediate) Authorities used in secure connections.
QList< QSslCertificate > caCertificates() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setDefault(bool)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const