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   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   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     connect( mSocket, 
static_cast<void ( QAbstractSocket::* )( QAbstractSocket::SocketError )
>( &QAbstractSocket::error ),
 
  190              this, &QgsAuthSslImportDialog::socketError );
 
  191     connect( mSocket, 
static_cast<void ( QSslSocket::* )( 
const QList<QSslError> & )
>( &QSslSocket::sslErrors ),
 
  192              this, &QgsAuthSslImportDialog::sslErrors );
 
  193     connect( mSocket, &QIODevice::readyRead,
 
  194              this, &QgsAuthSslImportDialog::socketReadyRead );
 
  197   QSslConfiguration sslConfig = mSocket->sslConfiguration();
 
  198   sslConfig.setCaCertificates( mTrustedCAs );
 
  199   mSocket->setSslConfiguration( sslConfig );
 
  203     mTimer = 
new QTimer( 
this );
 
  204     connect( mTimer, &QTimer::timeout, 
this, &QgsAuthSslImportDialog::destroySocket );
 
  206   mTimer->start( spinbxTimeout->value() * 1000 );
 
  208   mSocket->connectToHost( leServer->text(), spinbxPort->value() );
 
  209   updateEnabledState();
 
  212 void QgsAuthSslImportDialog::socketStateChanged( QAbstractSocket::SocketState state )
 
  214   if ( mExecErrorsDialog )
 
  219   updateEnabledState();
 
  220   if ( state == QAbstractSocket::UnconnectedState )
 
  222     leServer->setFocus();
 
  227 void QgsAuthSslImportDialog::socketConnected()
 
  229   appendString( tr( 
"Socket CONNECTED" ) );
 
  230   mSocket->startClientEncryption();
 
  233 void QgsAuthSslImportDialog::socketDisconnected()
 
  235   appendString( tr( 
"Socket DISCONNECTED" ) );
 
  238 void QgsAuthSslImportDialog::socketEncrypted()
 
  240   QgsDebugMsg( QStringLiteral( 
"socketEncrypted entered" ) );
 
  244   appendString( tr( 
"Socket ENCRYPTED" ) );
 
  246   appendString( QStringLiteral( 
"%1: %2" ).arg( tr( 
"Protocol" ),
 
  249   QSslCipher ciph = mSocket->sessionCipher();
 
  250   QString cipher = QStringLiteral( 
"%1: %2, %3 (%4/%5)" )
 
  251                    .arg( tr( 
"Session cipher" ), ciph.authenticationMethod(), ciph.name() )
 
  252                    .arg( ciph.usedBits() ).arg( ciph.supportedBits() );
 
  253   appendString( cipher );
 
  257   wdgtSslConfig->setEnabled( 
true );
 
  258   QString hostport( QStringLiteral( 
"%1:%2" ).arg( mSocket->peerName() ).arg( mSocket->peerPort() ) );
 
  259   wdgtSslConfig->setSslCertificate( mSocket->peerCertificate(), hostport.trimmed() );
 
  260   if ( !mSslErrors.isEmpty() )
 
  262     wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
 
  274 void QgsAuthSslImportDialog::socketError( QAbstractSocket::SocketError err )
 
  279     appendString( QStringLiteral( 
"%1: %2" ).arg( tr( 
"Socket ERROR" ), mSocket->errorString() ) );
 
  283 void QgsAuthSslImportDialog::socketReadyRead()
 
  285   appendString( QString::fromUtf8( mSocket->readAll() ) );
 
  288 void QgsAuthSslImportDialog::destroySocket()
 
  294   if ( !mSocket->isEncrypted() )
 
  296     appendString( tr( 
"Socket unavailable or not encrypted" ) );
 
  298   mSocket->disconnectFromHost();
 
  299   mSocket->deleteLater();
 
  303 void QgsAuthSslImportDialog::sslErrors( 
const QList<QSslError> &errors )
 
  305   if ( !mTimer->isActive() )
 
  311   QDialog errorDialog( 
this );
 
  313   ui.setupUi( &errorDialog );
 
  314   const auto constErrors = errors;
 
  315   for ( 
const QSslError &error : constErrors )
 
  317     ui.sslErrorList->addItem( error.errorString() );
 
  320   mExecErrorsDialog = 
true;
 
  321   if ( errorDialog.exec() == QDialog::Accepted )
 
  323     mSocket->ignoreSslErrors();
 
  326   mExecErrorsDialog = 
false;
 
  331   if ( mSocket->state() != QAbstractSocket::ConnectedState )
 
  332     socketStateChanged( mSocket->state() );
 
  335 void QgsAuthSslImportDialog::showCertificateInfo()
 
  337   QList<QSslCertificate> peerchain( mSocket->peerCertificateChain() );
 
  339   if ( !peerchain.isEmpty() )
 
  341     QSslCertificate cert = peerchain.takeFirst();
 
  342     if ( !cert.isNull() )
 
  351 void QgsAuthSslImportDialog::widgetReadyToSaveChanged( 
bool cansave )
 
  353   saveButton()->setEnabled( cansave );
 
  356 void QgsAuthSslImportDialog::checkCanSave()
 
  358   saveButton()->setEnabled( wdgtSslConfig->readyToSave() );
 
  359   saveButton()->setDefault( 
false );
 
  360   closeButton()->setDefault( 
false );
 
  363 void QgsAuthSslImportDialog::radioServerImportToggled( 
bool checked )
 
  365   frameServerImport->setEnabled( checked );
 
  366   clearStatusCertificateConfig();
 
  369 void QgsAuthSslImportDialog::radioFileImportToggled( 
bool checked )
 
  371   frameFileImport->setEnabled( checked );
 
  372   clearStatusCertificateConfig();
 
  375 void QgsAuthSslImportDialog::btnCertPath_clicked()
 
  377   const QString &fn = getOpenFileName( tr( 
"Open Server Certificate File" ),  tr( 
"All files (*.*);;PEM (*.pem);;DER (*.der)" ) );
 
  380     leCertPath->setText( fn );
 
  385 void QgsAuthSslImportDialog::clearCertificateConfig()
 
  387   wdgtSslConfig->resetSslCertConfig();
 
  388   wdgtSslConfig->setEnabled( 
false );
 
  391 void QgsAuthSslImportDialog::clearStatusCertificateConfig()
 
  394   pteSessionStatus->clear();
 
  395   saveButton()->setEnabled( 
false );
 
  396   clearCertificateConfig();
 
  399 void QgsAuthSslImportDialog::loadCertFromFile()
 
  401   clearStatusCertificateConfig();
 
  404   if ( certs.isEmpty() )
 
  406     appendString( tr( 
"Could not load any certs from file" ) );
 
  410   QSslCertificate cert( certs.first() );
 
  413     appendString( tr( 
"Could not load server cert from file" ) );
 
  419     appendString( tr( 
"Certificate does not appear for be for an SSL server. " 
  420                       "You can still add a configuration, if you know it is the correct certificate." ) );
 
  423   wdgtSslConfig->setEnabled( 
true );
 
  424   wdgtSslConfig->setSslHost( QString() );
 
  425   wdgtSslConfig->setSslCertificate( cert );
 
  426   if ( !mSslErrors.isEmpty() )
 
  428     wdgtSslConfig->appendSslIgnoreErrors( mSslErrors );
 
  434 void QgsAuthSslImportDialog::appendString( 
const QString &line )
 
  436   QTextCursor cursor( pteSessionStatus->textCursor() );
 
  437   cursor.movePosition( QTextCursor::End );
 
  438   cursor.insertText( line + 
'\n' );
 
  442 QPushButton *QgsAuthSslImportDialog::saveButton()
 
  444   return buttonBox->button( QDialogButtonBox::Save );
 
  447 QPushButton *QgsAuthSslImportDialog::closeButton()
 
  449   return buttonBox->button( QDialogButtonBox::Close );
 
  452 QString QgsAuthSslImportDialog::getOpenFileName( 
const QString &title, 
const QString &extfilter )
 
  454   QgsSettings settings;
 
  455   QString recentdir = settings.value( QStringLiteral( 
"UI/lastAuthImportSslOpenFileDir" ), QDir::homePath() ).toString();
 
  456   QString f = QFileDialog::getOpenFileName( 
this, title, recentdir, extfilter );
 
  460   this->activateWindow();
 
  464     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.