65#include "moc_qgsauthsslimportdialog.cpp"
67#include "ui_qgsauthsslimporterrors.h"
90 mAuthNotifyLayout =
new QVBoxLayout;
91 this->setLayout( mAuthNotifyLayout );
93 mAuthNotifyLayout->addWidget( mAuthNotify );
98 connect( btnCertPath, &QToolButton::clicked,
this, &QgsAuthSslImportDialog::btnCertPath_clicked );
99 QStyle *style = QApplication::style();
100 lblWarningIcon->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
101 lblWarningIcon->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
103 closeButton()->setDefault(
false );
104 saveButton()->setEnabled(
false );
106 leServer->setSelection( 0, leServer->text().size() );
107 pteSessionStatus->setReadOnly(
true );
108 spinbxTimeout->setClearValue( 15 );
109 spinbxTimeout->setValue( 15 );
110 spinbxPort->setClearValue( 443 );
112 grpbxServer->setCollapsed(
false );
113 radioServerImport->setChecked(
true );
114 frameServerImport->setEnabled(
true );
115 radioFileImport->setChecked(
false );
116 frameFileImport->setEnabled(
false );
118 connect( radioServerImport, &QAbstractButton::toggled,
119 this, &QgsAuthSslImportDialog::radioServerImportToggled );
120 connect( radioFileImport, &QAbstractButton::toggled,
121 this, &QgsAuthSslImportDialog::radioFileImportToggled );
123 connect( leServer, &QLineEdit::textChanged,
124 this, &QgsAuthSslImportDialog::updateEnabledState );
125 connect( btnConnect, &QAbstractButton::clicked,
126 this, &QgsAuthSslImportDialog::secureConnect );
127 connect( leServer, &QLineEdit::returnPressed,
128 btnConnect, &QAbstractButton::click );
130 connect( buttonBox, &QDialogButtonBox::accepted,
132 connect( buttonBox, &QDialogButtonBox::rejected,
133 this, &QDialog::reject );
136 this, &QgsAuthSslImportDialog::widgetReadyToSaveChanged );
137 wdgtSslConfig->setEnabled(
false );
145 wdgtSslConfig->saveSslCertConfig();
149void QgsAuthSslImportDialog::updateEnabledState()
151 leServer->setStyleSheet( QString() );
153 const bool unconnected = !mSocket || mSocket->state() == QAbstractSocket::UnconnectedState;
155 leServer->setReadOnly( !unconnected );
156 spinbxPort->setReadOnly( !unconnected );
157 spinbxTimeout->setReadOnly( !unconnected );
159 leServer->setFocusPolicy( unconnected ? Qt::StrongFocus : Qt::NoFocus );
160 btnConnect->setEnabled( unconnected && !leServer->text().isEmpty() );
162 const bool connected = mSocket && mSocket->state() == QAbstractSocket::ConnectedState;
163 if ( connected && !mSocket->peerName().isEmpty() )
165 appendString( tr(
"Connected to %1: %2" ).arg( mSocket->peerName() ).arg( mSocket->peerPort() ) );
169void QgsAuthSslImportDialog::secureConnect()
171 if ( leServer->text().isEmpty() )
176 leServer->setStyleSheet( QString() );
177 clearStatusCertificateConfig();
181 mSocket =
new QSslSocket(
this );
182 connect( mSocket, &QAbstractSocket::stateChanged,
183 this, &QgsAuthSslImportDialog::socketStateChanged );
184 connect( mSocket, &QAbstractSocket::connected,
185 this, &QgsAuthSslImportDialog::socketConnected );
186 connect( mSocket, &QAbstractSocket::disconnected,
187 this, &QgsAuthSslImportDialog::socketDisconnected );
188 connect( mSocket, &QSslSocket::encrypted,
189 this, &QgsAuthSslImportDialog::socketEncrypted );
190#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
191 connect( mSocket,
static_cast<void ( QAbstractSocket::* )( QAbstractSocket::SocketError )
>( &QAbstractSocket::error ),
192 this, &QgsAuthSslImportDialog::socketError );
194 connect( mSocket, &QAbstractSocket::errorOccurred,
this, &QgsAuthSslImportDialog::socketError );
196 connect( mSocket,
static_cast<void ( QSslSocket::* )(
const QList<QSslError> & )
>( &QSslSocket::sslErrors ),
197 this, &QgsAuthSslImportDialog::sslErrors );
198 connect( mSocket, &QIODevice::readyRead,
199 this, &QgsAuthSslImportDialog::socketReadyRead );
202 QSslConfiguration sslConfig = mSocket->sslConfiguration();
203 sslConfig.setCaCertificates( mTrustedCAs );
204 mSocket->setSslConfiguration( sslConfig );
208 mTimer =
new QTimer(
this );
209 connect( mTimer, &QTimer::timeout,
this, &QgsAuthSslImportDialog::destroySocket );
211 mTimer->start( spinbxTimeout->value() * 1000 );
213 mSocket->connectToHost( leServer->text(), spinbxPort->value() );
214 updateEnabledState();
217void QgsAuthSslImportDialog::socketStateChanged( QAbstractSocket::SocketState state )
219 if ( mExecErrorsDialog )
224 updateEnabledState();
225 if ( state == QAbstractSocket::UnconnectedState )
227 leServer->setFocus();
232void QgsAuthSslImportDialog::socketConnected()
234 appendString( tr(
"Socket CONNECTED" ) );
235 mSocket->startClientEncryption();
238void QgsAuthSslImportDialog::socketDisconnected()
240 appendString( tr(
"Socket DISCONNECTED" ) );
243void QgsAuthSslImportDialog::socketEncrypted()
249 appendString( tr(
"Socket ENCRYPTED" ) );
251 appendString( QStringLiteral(
"%1: %2" ).arg( tr(
"Protocol" ),
254 const QSslCipher ciph = mSocket->sessionCipher();
255 const QString cipher = QStringLiteral(
"%1: %2, %3 (%4/%5)" )
256 .arg( tr(
"Session cipher" ), ciph.authenticationMethod(), ciph.name() )
257 .arg( ciph.usedBits() ).arg( ciph.supportedBits() );
258 appendString( cipher );
262 wdgtSslConfig->setEnabled(
true );
263 const QString hostport( QStringLiteral(
"%1:%2" ).arg( mSocket->peerName() ).arg( mSocket->peerPort() ) );
264 wdgtSslConfig->setSslCertificate( mSocket->peerCertificate(), hostport.trimmed() );
265 if ( !mSslErrors.isEmpty() )
267 wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
279void QgsAuthSslImportDialog::socketError( QAbstractSocket::SocketError err )
284 appendString( QStringLiteral(
"%1: %2" ).arg( tr(
"Socket ERROR" ), mSocket->errorString() ) );
288void QgsAuthSslImportDialog::socketReadyRead()
290 appendString( QString::fromUtf8( mSocket->readAll() ) );
293void QgsAuthSslImportDialog::destroySocket()
299 if ( !mSocket->isEncrypted() )
301 appendString( tr(
"Socket unavailable or not encrypted" ) );
303 mSocket->disconnectFromHost();
304 mSocket->deleteLater();
308void QgsAuthSslImportDialog::sslErrors(
const QList<QSslError> &errors )
310 if ( !mTimer->isActive() )
316 QDialog errorDialog(
this );
318 ui.setupUi( &errorDialog );
319 const auto constErrors = errors;
320 for (
const QSslError &error : constErrors )
322 ui.sslErrorList->addItem( error.errorString() );
325 mExecErrorsDialog =
true;
326 if ( errorDialog.exec() == QDialog::Accepted )
328 mSocket->ignoreSslErrors();
331 mExecErrorsDialog =
false;
336 if ( mSocket->state() != QAbstractSocket::ConnectedState )
337 socketStateChanged( mSocket->state() );
340void QgsAuthSslImportDialog::showCertificateInfo()
342 QList<QSslCertificate> peerchain( mSocket->peerCertificateChain() );
344 if ( !peerchain.isEmpty() )
346 const QSslCertificate cert = peerchain.takeFirst();
347 if ( !cert.isNull() )
356void QgsAuthSslImportDialog::widgetReadyToSaveChanged(
bool cansave )
358 saveButton()->setEnabled( cansave );
361void QgsAuthSslImportDialog::checkCanSave()
363 saveButton()->setEnabled( wdgtSslConfig->readyToSave() );
364 saveButton()->setDefault(
false );
365 closeButton()->setDefault(
false );
368void QgsAuthSslImportDialog::radioServerImportToggled(
bool checked )
370 frameServerImport->setEnabled( checked );
371 clearStatusCertificateConfig();
374void QgsAuthSslImportDialog::radioFileImportToggled(
bool checked )
376 frameFileImport->setEnabled( checked );
377 clearStatusCertificateConfig();
380void QgsAuthSslImportDialog::btnCertPath_clicked()
382 const QString &fn = getOpenFileName( tr(
"Open Server Certificate File" ), tr(
"All files (*.*);;PEM (*.pem);;DER (*.der)" ) );
385 leCertPath->setText( fn );
390void QgsAuthSslImportDialog::clearCertificateConfig()
392 wdgtSslConfig->resetSslCertConfig();
393 wdgtSslConfig->setEnabled(
false );
396void QgsAuthSslImportDialog::clearStatusCertificateConfig()
399 pteSessionStatus->clear();
400 saveButton()->setEnabled(
false );
401 clearCertificateConfig();
404void QgsAuthSslImportDialog::loadCertFromFile()
406 clearStatusCertificateConfig();
409 if ( certs.isEmpty() )
411 appendString( tr(
"Could not load any certs from file" ) );
415 const QSslCertificate cert( certs.first() );
418 appendString( tr(
"Could not load server cert from file" ) );
424 appendString( tr(
"Certificate does not appear for be for an SSL server. "
425 "You can still add a configuration, if you know it is the correct certificate." ) );
428 wdgtSslConfig->setEnabled(
true );
429 wdgtSslConfig->setSslHost( QString() );
430 wdgtSslConfig->setSslCertificate( cert );
431 if ( !mSslErrors.isEmpty() )
433 wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
439void QgsAuthSslImportDialog::appendString(
const QString &line )
441 QTextCursor cursor( pteSessionStatus->textCursor() );
442 cursor.movePosition( QTextCursor::End );
443 cursor.insertText( line +
'\n' );
447QPushButton *QgsAuthSslImportDialog::saveButton()
449 return buttonBox->button( QDialogButtonBox::Save );
452QPushButton *QgsAuthSslImportDialog::closeButton()
454 return buttonBox->button( QDialogButtonBox::Close );
457QString QgsAuthSslImportDialog::getOpenFileName(
const QString &title,
const QString &extfilter )
460 const QString recentdir = settings.
value( QStringLiteral(
"UI/lastAuthImportSslOpenFileDir" ), QDir::homePath() ).toString();
461 QString f = QFileDialog::getOpenFileName(
this, title, recentdir, extfilter );
465 this->activateWindow();
469 settings.
setValue( QStringLiteral(
"UI/lastAuthImportSslOpenFileDir" ), QFileInfo( f ).absoluteDir().path() );
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 getSslProtocolName(QSsl::SslProtocol protocol)
SSL Protocol name strings per enum.
static QList< QSslCertificate > certsFromFile(const QString &certspath)
Returns a list of concatenated certs from a PEM or DER formatted file.
static bool certificateIsSslServer(const QSslCertificate &cert)
Gets whether a certificate is probably used for a SSL server.
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.
This class is a composition of two QSettings instances:
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)