63#include "ui_qgsauthsslimporterrors.h"
84#include "moc_qgsauthsslimportdialog.cpp"
86using namespace Qt::StringLiterals;
93 mAuthNotifyLayout =
new QVBoxLayout;
94 this->setLayout( mAuthNotifyLayout );
96 mAuthNotifyLayout->addWidget( mAuthNotify );
101 connect( btnCertPath, &QToolButton::clicked,
this, &QgsAuthSslImportDialog::btnCertPath_clicked );
102 QStyle *style = QApplication::style();
103 lblWarningIcon->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
104 lblWarningIcon->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
106 closeButton()->setDefault(
false );
107 saveButton()->setEnabled(
false );
109 leServer->setSelection( 0, leServer->text().size() );
110 pteSessionStatus->setReadOnly(
true );
111 spinbxTimeout->setClearValue( 15 );
112 spinbxTimeout->setValue( 15 );
113 spinbxPort->setClearValue( 443 );
115 grpbxServer->setCollapsed(
false );
116 radioServerImport->setChecked(
true );
117 frameServerImport->setEnabled(
true );
118 radioFileImport->setChecked(
false );
119 frameFileImport->setEnabled(
false );
121 connect( radioServerImport, &QAbstractButton::toggled,
this, &QgsAuthSslImportDialog::radioServerImportToggled );
122 connect( radioFileImport, &QAbstractButton::toggled,
this, &QgsAuthSslImportDialog::radioFileImportToggled );
124 connect( leServer, &QLineEdit::textChanged,
this, &QgsAuthSslImportDialog::updateEnabledState );
125 connect( btnConnect, &QAbstractButton::clicked,
this, &QgsAuthSslImportDialog::secureConnect );
126 connect( leServer, &QLineEdit::returnPressed, btnConnect, &QAbstractButton::click );
129 connect( buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
132 wdgtSslConfig->setEnabled(
false );
140 wdgtSslConfig->saveSslCertConfig();
144void QgsAuthSslImportDialog::updateEnabledState()
146 leServer->setStyleSheet( QString() );
148 const bool unconnected = !mSocket || mSocket->state() == QAbstractSocket::UnconnectedState;
150 leServer->setReadOnly( !unconnected );
151 spinbxPort->setReadOnly( !unconnected );
152 spinbxTimeout->setReadOnly( !unconnected );
154 leServer->setFocusPolicy( unconnected ? Qt::StrongFocus : Qt::NoFocus );
155 btnConnect->setEnabled( unconnected && !leServer->text().isEmpty() );
157 const bool connected = mSocket && mSocket->state() == QAbstractSocket::ConnectedState;
158 if ( connected && !mSocket->peerName().isEmpty() )
160 appendString( tr(
"Connected to %1: %2" ).arg( mSocket->peerName() ).arg( mSocket->peerPort() ) );
164void QgsAuthSslImportDialog::secureConnect()
166 if ( leServer->text().isEmpty() )
171 leServer->setStyleSheet( QString() );
172 clearStatusCertificateConfig();
176 mSocket =
new QSslSocket(
this );
177 connect( mSocket, &QAbstractSocket::stateChanged,
this, &QgsAuthSslImportDialog::socketStateChanged );
178 connect( mSocket, &QAbstractSocket::connected,
this, &QgsAuthSslImportDialog::socketConnected );
179 connect( mSocket, &QAbstractSocket::disconnected,
this, &QgsAuthSslImportDialog::socketDisconnected );
180 connect( mSocket, &QSslSocket::encrypted,
this, &QgsAuthSslImportDialog::socketEncrypted );
181 connect( mSocket, &QAbstractSocket::errorOccurred,
this, &QgsAuthSslImportDialog::socketError );
182 connect( mSocket,
static_cast<void ( QSslSocket::* )(
const QList<QSslError> & )
>( &QSslSocket::sslErrors ),
this, &QgsAuthSslImportDialog::sslErrors );
183 connect( mSocket, &QIODevice::readyRead,
this, &QgsAuthSslImportDialog::socketReadyRead );
186 QSslConfiguration sslConfig = mSocket->sslConfiguration();
187 sslConfig.setCaCertificates( mTrustedCAs );
188 mSocket->setSslConfiguration( sslConfig );
192 mTimer =
new QTimer(
this );
193 connect( mTimer, &QTimer::timeout,
this, &QgsAuthSslImportDialog::destroySocket );
195 mTimer->start( spinbxTimeout->value() * 1000 );
197 mSocket->connectToHost( leServer->text(), spinbxPort->value() );
198 updateEnabledState();
201void QgsAuthSslImportDialog::socketStateChanged( QAbstractSocket::SocketState state )
203 if ( mExecErrorsDialog )
208 updateEnabledState();
209 if ( state == QAbstractSocket::UnconnectedState )
211 leServer->setFocus();
216void QgsAuthSslImportDialog::socketConnected()
218 appendString( tr(
"Socket CONNECTED" ) );
219 mSocket->startClientEncryption();
222void QgsAuthSslImportDialog::socketDisconnected()
224 appendString( tr(
"Socket DISCONNECTED" ) );
227void QgsAuthSslImportDialog::socketEncrypted()
233 appendString( tr(
"Socket ENCRYPTED" ) );
235 appendString( u
"%1: %2"_s.arg( tr(
"Protocol" ), QgsAuthCertUtils::getSslProtocolName( mSocket->protocol() ) ) );
237 const QSslCipher ciph = mSocket->sessionCipher();
238 const QString cipher = u
"%1: %2, %3 (%4/%5)"_s
239 .arg( tr(
"Session cipher" ), ciph.authenticationMethod(), ciph.name() )
240 .arg( ciph.usedBits() )
241 .arg( ciph.supportedBits() );
242 appendString( cipher );
245 wdgtSslConfig->setEnabled(
true );
246 const QString hostport( u
"%1:%2"_s.arg( mSocket->peerName() ).arg( mSocket->peerPort() ) );
247 wdgtSslConfig->setSslCertificate( mSocket->peerCertificate(), hostport.trimmed() );
248 if ( !mSslErrors.isEmpty() )
250 wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
262void QgsAuthSslImportDialog::socketError( QAbstractSocket::SocketError err )
267 appendString( u
"%1: %2"_s.arg( tr(
"Socket ERROR" ), mSocket->errorString() ) );
271void QgsAuthSslImportDialog::socketReadyRead()
273 appendString( QString::fromUtf8( mSocket->readAll() ) );
276void QgsAuthSslImportDialog::destroySocket()
282 if ( !mSocket->isEncrypted() )
284 appendString( tr(
"Socket unavailable or not encrypted" ) );
286 mSocket->disconnectFromHost();
287 mSocket->deleteLater();
291void QgsAuthSslImportDialog::sslErrors(
const QList<QSslError> &errors )
293 if ( !mTimer->isActive() )
299 QDialog errorDialog(
this );
301 ui.setupUi( &errorDialog );
302 const auto constErrors = errors;
303 for (
const QSslError &error : constErrors )
305 ui.sslErrorList->addItem( error.errorString() );
308 mExecErrorsDialog =
true;
309 if ( errorDialog.exec() == QDialog::Accepted )
311 mSocket->ignoreSslErrors();
314 mExecErrorsDialog =
false;
319 if ( mSocket->state() != QAbstractSocket::ConnectedState )
320 socketStateChanged( mSocket->state() );
323void QgsAuthSslImportDialog::showCertificateInfo()
325 QList<QSslCertificate> peerchain( mSocket->peerCertificateChain() );
327 if ( !peerchain.isEmpty() )
329 const QSslCertificate cert = peerchain.takeFirst();
330 if ( !cert.isNull() )
332 QgsAuthCertInfoDialog *info =
new QgsAuthCertInfoDialog( cert,
false,
this, peerchain );
339void QgsAuthSslImportDialog::widgetReadyToSaveChanged(
bool cansave )
341 saveButton()->setEnabled( cansave );
344void QgsAuthSslImportDialog::checkCanSave()
346 saveButton()->setEnabled( wdgtSslConfig->readyToSave() );
347 saveButton()->setDefault(
false );
348 closeButton()->setDefault(
false );
351void QgsAuthSslImportDialog::radioServerImportToggled(
bool checked )
353 frameServerImport->setEnabled( checked );
354 clearStatusCertificateConfig();
357void QgsAuthSslImportDialog::radioFileImportToggled(
bool checked )
359 frameFileImport->setEnabled( checked );
360 clearStatusCertificateConfig();
363void QgsAuthSslImportDialog::btnCertPath_clicked()
365 const QString &fn = getOpenFileName( tr(
"Open Server Certificate File" ), tr(
"All files (*.*);;PEM (*.pem);;DER (*.der)" ) );
368 leCertPath->setText( fn );
373void QgsAuthSslImportDialog::clearCertificateConfig()
375 wdgtSslConfig->resetSslCertConfig();
376 wdgtSslConfig->setEnabled(
false );
379void QgsAuthSslImportDialog::clearStatusCertificateConfig()
382 pteSessionStatus->clear();
383 saveButton()->setEnabled(
false );
384 clearCertificateConfig();
387void QgsAuthSslImportDialog::loadCertFromFile()
389 clearStatusCertificateConfig();
390 QList<QSslCertificate> certs( QgsAuthCertUtils::certsFromFile( leCertPath->text() ) );
392 if ( certs.isEmpty() )
394 appendString( tr(
"Could not load any certs from file" ) );
398 const QSslCertificate cert( certs.first() );
401 appendString( tr(
"Could not load server cert from file" ) );
405 if ( !QgsAuthCertUtils::certificateIsSslServer( cert ) )
407 appendString( tr(
"Certificate does not appear for be for an SSL server. "
408 "You can still add a configuration, if you know it is the correct certificate." ) );
411 wdgtSslConfig->setEnabled(
true );
412 wdgtSslConfig->setSslHost( QString() );
413 wdgtSslConfig->setSslCertificate( cert );
414 if ( !mSslErrors.isEmpty() )
416 wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
422void QgsAuthSslImportDialog::appendString(
const QString &line )
424 QTextCursor cursor( pteSessionStatus->textCursor() );
425 cursor.movePosition( QTextCursor::End );
426 cursor.insertText( line +
'\n' );
430QPushButton *QgsAuthSslImportDialog::saveButton()
432 return buttonBox->button( QDialogButtonBox::Save );
435QPushButton *QgsAuthSslImportDialog::closeButton()
437 return buttonBox->button( QDialogButtonBox::Close );
440QString QgsAuthSslImportDialog::getOpenFileName(
const QString &title,
const QString &extfilter )
442 QgsSettings settings;
443 const QString recentdir = settings.
value( u
"UI/lastAuthImportSslOpenFileDir"_s, QDir::homePath() ).toString();
444 QString f = QFileDialog::getOpenFileName(
this, title, recentdir, extfilter );
448 this->activateWindow();
452 settings.
setValue( u
"UI/lastAuthImportSslOpenFileDir"_s, QFileInfo( f ).absoluteDir().path() );
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static QString greenTextStyleSheet(const QString &selector="*")
Green text stylesheet representing valid, trusted, etc. certificate.
const QList< QSslCertificate > trustedCaCertsCache()
trustedCaCertsCache cache of trusted certificate authorities, ready for network connections
QgsAuthSslImportDialog(QWidget *parent=nullptr)
Construct dialog for importing certificates.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define QgsDebugMsgLevel(str, level)