66 #include "ui_qgsauthsslimporterrors.h" 
   69 #include <QFileDialog> 
   71 #include <QPushButton> 
   75 #include <QToolButton> 
   89     mAuthNotifyLayout = 
new QVBoxLayout;
 
   90     this->setLayout( mAuthNotifyLayout );
 
   92     mAuthNotifyLayout->addWidget( mAuthNotify );
 
   97     connect( btnCertPath, &QToolButton::clicked, 
this, &QgsAuthSslImportDialog::btnCertPath_clicked );
 
   98     QStyle *style = QApplication::style();
 
   99     lblWarningIcon->setPixmap( style->standardIcon( QStyle::SP_MessageBoxWarning ).pixmap( 48, 48 ) );
 
  100     lblWarningIcon->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
 
  102     closeButton()->setDefault( 
false );
 
  103     saveButton()->setEnabled( 
false );
 
  105     leServer->setSelection( 0, leServer->text().size() );
 
  106     pteSessionStatus->setReadOnly( 
true );
 
  107     spinbxTimeout->setClearValue( 15 );
 
  108     spinbxTimeout->setValue( 15 );
 
  109     spinbxPort->setClearValue( 443 );
 
  111     grpbxServer->setCollapsed( 
false );
 
  112     radioServerImport->setChecked( 
true );
 
  113     frameServerImport->setEnabled( 
true );
 
  114     radioFileImport->setChecked( 
false );
 
  115     frameFileImport->setEnabled( 
false );
 
  117     connect( radioServerImport, &QAbstractButton::toggled,
 
  118              this, &QgsAuthSslImportDialog::radioServerImportToggled );
 
  119     connect( radioFileImport, &QAbstractButton::toggled,
 
  120              this, &QgsAuthSslImportDialog::radioFileImportToggled );
 
  122     connect( leServer, &QLineEdit::textChanged,
 
  123              this, &QgsAuthSslImportDialog::updateEnabledState );
 
  124     connect( btnConnect, &QAbstractButton::clicked,
 
  125              this, &QgsAuthSslImportDialog::secureConnect );
 
  126     connect( leServer, &QLineEdit::returnPressed,
 
  127              btnConnect, &QAbstractButton::click );
 
  129     connect( buttonBox, &QDialogButtonBox::accepted,
 
  131     connect( buttonBox, &QDialogButtonBox::rejected,
 
  132              this, &QDialog::reject );
 
  135              this, &QgsAuthSslImportDialog::widgetReadyToSaveChanged );
 
  136     wdgtSslConfig->setEnabled( 
false );
 
  144   wdgtSslConfig->saveSslCertConfig();
 
  148 void QgsAuthSslImportDialog::updateEnabledState()
 
  150   leServer->setStyleSheet( QString() );
 
  152   const bool unconnected = !mSocket || mSocket->state() == QAbstractSocket::UnconnectedState;
 
  154   leServer->setReadOnly( !unconnected );
 
  155   spinbxPort->setReadOnly( !unconnected );
 
  156   spinbxTimeout->setReadOnly( !unconnected );
 
  158   leServer->setFocusPolicy( unconnected ? Qt::StrongFocus : Qt::NoFocus );
 
  159   btnConnect->setEnabled( unconnected && !leServer->text().isEmpty() );
 
  161   const bool connected = mSocket && mSocket->state() == QAbstractSocket::ConnectedState;
 
  162   if ( connected && !mSocket->peerName().isEmpty() )
 
  164     appendString( tr( 
"Connected to %1: %2" ).arg( mSocket->peerName() ).arg( mSocket->peerPort() ) );
 
  168 void QgsAuthSslImportDialog::secureConnect()
 
  170   if ( leServer->text().isEmpty() )
 
  175   leServer->setStyleSheet( QString() );
 
  176   clearStatusCertificateConfig();
 
  180     mSocket = 
new QSslSocket( 
this );
 
  181     connect( mSocket, &QAbstractSocket::stateChanged,
 
  182              this, &QgsAuthSslImportDialog::socketStateChanged );
 
  183     connect( mSocket, &QAbstractSocket::connected,
 
  184              this, &QgsAuthSslImportDialog::socketConnected );
 
  185     connect( mSocket, &QAbstractSocket::disconnected,
 
  186              this, &QgsAuthSslImportDialog::socketDisconnected );
 
  187     connect( mSocket, &QSslSocket::encrypted,
 
  188              this, &QgsAuthSslImportDialog::socketEncrypted );
 
  189 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  190     connect( mSocket, 
static_cast<void ( QAbstractSocket::* )( QAbstractSocket::SocketError )
>( &QAbstractSocket::error ),
 
  191              this, &QgsAuthSslImportDialog::socketError );
 
  193     connect( mSocket, &QAbstractSocket::errorOccurred, 
this, &QgsAuthSslImportDialog::socketError );
 
  195     connect( mSocket, 
static_cast<void ( QSslSocket::* )( 
const QList<QSslError> & )
>( &QSslSocket::sslErrors ),
 
  196              this, &QgsAuthSslImportDialog::sslErrors );
 
  197     connect( mSocket, &QIODevice::readyRead,
 
  198              this, &QgsAuthSslImportDialog::socketReadyRead );
 
  201   QSslConfiguration sslConfig = mSocket->sslConfiguration();
 
  202   sslConfig.setCaCertificates( mTrustedCAs );
 
  203   mSocket->setSslConfiguration( sslConfig );
 
  207     mTimer = 
new QTimer( 
this );
 
  208     connect( mTimer, &QTimer::timeout, 
this, &QgsAuthSslImportDialog::destroySocket );
 
  210   mTimer->start( spinbxTimeout->value() * 1000 );
 
  212   mSocket->connectToHost( leServer->text(), spinbxPort->value() );
 
  213   updateEnabledState();
 
  216 void QgsAuthSslImportDialog::socketStateChanged( QAbstractSocket::SocketState state )
 
  218   if ( mExecErrorsDialog )
 
  223   updateEnabledState();
 
  224   if ( state == QAbstractSocket::UnconnectedState )
 
  226     leServer->setFocus();
 
  231 void QgsAuthSslImportDialog::socketConnected()
 
  233   appendString( tr( 
"Socket CONNECTED" ) );
 
  234   mSocket->startClientEncryption();
 
  237 void QgsAuthSslImportDialog::socketDisconnected()
 
  239   appendString( tr( 
"Socket DISCONNECTED" ) );
 
  242 void QgsAuthSslImportDialog::socketEncrypted()
 
  244   QgsDebugMsg( QStringLiteral( 
"socketEncrypted entered" ) );
 
  248   appendString( tr( 
"Socket ENCRYPTED" ) );
 
  250   appendString( QStringLiteral( 
"%1: %2" ).arg( tr( 
"Protocol" ),
 
  253   const QSslCipher ciph = mSocket->sessionCipher();
 
  254   const QString cipher = QStringLiteral( 
"%1: %2, %3 (%4/%5)" )
 
  255                          .arg( tr( 
"Session cipher" ), ciph.authenticationMethod(), ciph.name() )
 
  256                          .arg( ciph.usedBits() ).arg( ciph.supportedBits() );
 
  257   appendString( cipher );
 
  261   wdgtSslConfig->setEnabled( 
true );
 
  262   const QString hostport( QStringLiteral( 
"%1:%2" ).arg( mSocket->peerName() ).arg( mSocket->peerPort() ) );
 
  263   wdgtSslConfig->setSslCertificate( mSocket->peerCertificate(), hostport.trimmed() );
 
  264   if ( !mSslErrors.isEmpty() )
 
  266     wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
 
  278 void QgsAuthSslImportDialog::socketError( QAbstractSocket::SocketError err )
 
  283     appendString( QStringLiteral( 
"%1: %2" ).arg( tr( 
"Socket ERROR" ), mSocket->errorString() ) );
 
  287 void QgsAuthSslImportDialog::socketReadyRead()
 
  289   appendString( QString::fromUtf8( mSocket->readAll() ) );
 
  292 void QgsAuthSslImportDialog::destroySocket()
 
  298   if ( !mSocket->isEncrypted() )
 
  300     appendString( tr( 
"Socket unavailable or not encrypted" ) );
 
  302   mSocket->disconnectFromHost();
 
  303   mSocket->deleteLater();
 
  307 void QgsAuthSslImportDialog::sslErrors( 
const QList<QSslError> &errors )
 
  309   if ( !mTimer->isActive() )
 
  315   QDialog errorDialog( 
this );
 
  317   ui.setupUi( &errorDialog );
 
  318   const auto constErrors = errors;
 
  319   for ( 
const QSslError &error : constErrors )
 
  321     ui.sslErrorList->addItem( error.errorString() );
 
  324   mExecErrorsDialog = 
true;
 
  325   if ( errorDialog.exec() == QDialog::Accepted )
 
  327     mSocket->ignoreSslErrors();
 
  330   mExecErrorsDialog = 
false;
 
  335   if ( mSocket->state() != QAbstractSocket::ConnectedState )
 
  336     socketStateChanged( mSocket->state() );
 
  339 void QgsAuthSslImportDialog::showCertificateInfo()
 
  341   QList<QSslCertificate> peerchain( mSocket->peerCertificateChain() );
 
  343   if ( !peerchain.isEmpty() )
 
  345     const QSslCertificate cert = peerchain.takeFirst();
 
  346     if ( !cert.isNull() )
 
  355 void QgsAuthSslImportDialog::widgetReadyToSaveChanged( 
bool cansave )
 
  357   saveButton()->setEnabled( cansave );
 
  360 void QgsAuthSslImportDialog::checkCanSave()
 
  362   saveButton()->setEnabled( wdgtSslConfig->readyToSave() );
 
  363   saveButton()->setDefault( 
false );
 
  364   closeButton()->setDefault( 
false );
 
  367 void QgsAuthSslImportDialog::radioServerImportToggled( 
bool checked )
 
  369   frameServerImport->setEnabled( checked );
 
  370   clearStatusCertificateConfig();
 
  373 void QgsAuthSslImportDialog::radioFileImportToggled( 
bool checked )
 
  375   frameFileImport->setEnabled( checked );
 
  376   clearStatusCertificateConfig();
 
  379 void QgsAuthSslImportDialog::btnCertPath_clicked()
 
  381   const QString &fn = getOpenFileName( tr( 
"Open Server Certificate File" ),  tr( 
"All files (*.*);;PEM (*.pem);;DER (*.der)" ) );
 
  384     leCertPath->setText( fn );
 
  389 void QgsAuthSslImportDialog::clearCertificateConfig()
 
  391   wdgtSslConfig->resetSslCertConfig();
 
  392   wdgtSslConfig->setEnabled( 
false );
 
  395 void QgsAuthSslImportDialog::clearStatusCertificateConfig()
 
  398   pteSessionStatus->clear();
 
  399   saveButton()->setEnabled( 
false );
 
  400   clearCertificateConfig();
 
  403 void QgsAuthSslImportDialog::loadCertFromFile()
 
  405   clearStatusCertificateConfig();
 
  408   if ( certs.isEmpty() )
 
  410     appendString( tr( 
"Could not load any certs from file" ) );
 
  414   const QSslCertificate cert( certs.first() );
 
  417     appendString( tr( 
"Could not load server cert from file" ) );
 
  423     appendString( tr( 
"Certificate does not appear for be for an SSL server. " 
  424                       "You can still add a configuration, if you know it is the correct certificate." ) );
 
  427   wdgtSslConfig->setEnabled( 
true );
 
  428   wdgtSslConfig->setSslHost( QString() );
 
  429   wdgtSslConfig->setSslCertificate( cert );
 
  430   if ( !mSslErrors.isEmpty() )
 
  432     wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
 
  438 void QgsAuthSslImportDialog::appendString( 
const QString &line )
 
  440   QTextCursor cursor( pteSessionStatus->textCursor() );
 
  441   cursor.movePosition( QTextCursor::End );
 
  442   cursor.insertText( line + 
'\n' );
 
  446 QPushButton *QgsAuthSslImportDialog::saveButton()
 
  448   return buttonBox->button( QDialogButtonBox::Save );
 
  451 QPushButton *QgsAuthSslImportDialog::closeButton()
 
  453   return buttonBox->button( QDialogButtonBox::Close );
 
  456 QString QgsAuthSslImportDialog::getOpenFileName( 
const QString &title, 
const QString &extfilter )
 
  459   const QString recentdir = settings.
value( QStringLiteral( 
"UI/lastAuthImportSslOpenFileDir" ), QDir::homePath() ).toString();
 
  460   QString f = QFileDialog::getOpenFileName( 
this, title, recentdir, extfilter );
 
  464   this->activateWindow();
 
  468     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.