20#include <QDialogButtonBox>
31static void setItemBold_( QTreeWidgetItem *item )
33 item->setFirstColumnSpanned(
true );
34 QFont secf( item->font( 0 ) );
36 item->setFont( 0, secf );
39static const QString configFoundText_() {
return QObject::tr(
"Configuration loaded from database" ); }
40static const QString configNotFoundText_() {
return QObject::tr(
"Configuration not found in database" ); }
43 const QSslCertificate &cert,
44 const QString &hostport,
45 const QList<QSslCertificate> &connectionCAs )
48 , mConnectionCAs( connectionCAs )
53 mAuthNotifyLayout =
new QVBoxLayout;
54 this->setLayout( mAuthNotifyLayout );
56 mAuthNotifyLayout->addWidget( mAuthNotify );
61 connect( btnCertInfo, &QToolButton::clicked,
this, &QgsAuthSslConfigWidget::btnCertInfo_clicked );
69 lblLoadedConfig->setVisible(
false );
70 lblLoadedConfig->clear();
72 connect( leHost, &QLineEdit::textChanged,
97 return grpbxSslConfig;
101QTreeWidgetItem *QgsAuthSslConfigWidget::addRootItem(
const QString &label )
103 QTreeWidgetItem *item =
new QTreeWidgetItem(
104 QStringList() << label,
105 static_cast<int>( ConfigParent ) );
106 setItemBold_( item );
107 item->setTextAlignment( 0, Qt::AlignVCenter );
108 item->setFlags( item->flags() & ~Qt::ItemIsSelectable );
109 treeSslConfig->insertTopLevelItem( treeSslConfig->topLevelItemCount(), item );
114void QgsAuthSslConfigWidget::setUpSslConfigTree()
116 treeSslConfig->setColumnCount( 1 );
119 mProtocolItem = addRootItem( tr(
"Protocol" ) );
120 mProtocolCmbBx =
new QComboBox( treeSslConfig );
122 static_cast<int>( QSsl::SecureProtocols ) );
123#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
125 static_cast<int>( QSsl::TlsV1SslV3 ) );
128 static_cast<int>( QSsl::TlsV1_0 ) );
129#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
131 static_cast<int>( QSsl::SslV3 ) );
133 static_cast<int>( QSsl::SslV2 ) );
135 mProtocolCmbBx->setMaximumWidth( 300 );
136 mProtocolCmbBx->setCurrentIndex( 0 );
137 QTreeWidgetItem *protocolitem =
new QTreeWidgetItem(
139 QStringList() << QString(),
140 static_cast<int>( ConfigItem ) );
141 protocolitem->setFlags( protocolitem->flags() & ~Qt::ItemIsSelectable );
142 treeSslConfig->setItemWidget( protocolitem, 0, mProtocolCmbBx );
143 mProtocolItem->setExpanded(
true );
145 mVerifyModeItem = addRootItem( tr(
"Peer verification" ) );
146 mVerifyPeerCmbBx =
new QComboBox( treeSslConfig );
147 mVerifyPeerCmbBx->addItem( tr(
"Verify Peer Certs" ),
148 static_cast<int>( QSslSocket::VerifyPeer ) );
149 mVerifyPeerCmbBx->addItem( tr(
"Do Not Verify Peer Certs" ),
150 static_cast<int>( QSslSocket::VerifyNone ) );
151 mVerifyPeerCmbBx->setMaximumWidth( 300 );
152 mVerifyPeerCmbBx->setCurrentIndex( 0 );
153 QTreeWidgetItem *peerverifycmbxitem =
new QTreeWidgetItem(
155 QStringList() << QString(),
156 static_cast<int>( ConfigItem ) );
157 peerverifycmbxitem->setFlags( peerverifycmbxitem->flags() & ~Qt::ItemIsSelectable );
158 treeSslConfig->setItemWidget( peerverifycmbxitem, 0, mVerifyPeerCmbBx );
159 mVerifyModeItem->setExpanded(
true );
161 mVerifyDepthItem = addRootItem( tr(
"Peer verification depth (0 = complete cert chain)" ) );
162 mVerifyDepthSpnBx =
new QSpinBox( treeSslConfig );
163 mVerifyDepthSpnBx->setMinimum( 0 );
164 mVerifyDepthSpnBx->setMaximum( 10 );
165 mVerifyDepthSpnBx->setMaximumWidth( 200 );
166 mVerifyDepthSpnBx->setAlignment( Qt::AlignHCenter );
167 QTreeWidgetItem *peerverifyspnbxitem =
new QTreeWidgetItem(
169 QStringList() << QString(),
170 static_cast<int>( ConfigItem ) );
171 peerverifyspnbxitem->setFlags( peerverifyspnbxitem->flags() & ~Qt::ItemIsSelectable );
172 treeSslConfig->setItemWidget( peerverifyspnbxitem, 0, mVerifyDepthSpnBx );
173 mVerifyDepthItem->setExpanded(
true );
175 mIgnoreErrorsItem = addRootItem( tr(
"Ignore errors" ) );
178 for (
int i = 0; i < errenums.size(); i++ )
180 QTreeWidgetItem *item =
new QTreeWidgetItem(
182 QStringList() << errenums.at( i ).second,
183 static_cast<int>( ConfigItem ) );
184 item->setCheckState( 0, Qt::Unchecked );
185 item->setTextAlignment( 0, Qt::AlignVCenter );
186 item->setFlags( item->flags() & ~Qt::ItemIsSelectable );
187 item->setData( 0, Qt::UserRole, errenums.at( i ).first );
189 mIgnoreErrorsItem->setExpanded(
true );
212 return QSslCertificate();
223 return leHost->text();
232 if ( grpbxSslConfig->isCheckable() )
234 grpbxSslConfig->setChecked( enable );
250 if ( !hostport.isEmpty() )
261 lblLoadedConfig->setVisible(
true );
269 lblLoadedConfig->setText( configNotFoundText_() );
285 QgsDebugError( QStringLiteral(
"Passed-in SSL custom config is null" ) );
292 QgsDebugError( QStringLiteral(
"SSL custom config's cert is null" ) );
304 lblLoadedConfig->setVisible(
true );
305 lblLoadedConfig->setText( configFoundText_() );
316 QgsDebugError( QStringLiteral(
"SSL custom config FAILED to store in authentication database" ) );
327 mConnectionCAs.clear();
328 leCommonName->clear();
329 leCommonName->setStyleSheet( QString() );
332 lblLoadedConfig->setVisible(
false );
333 lblLoadedConfig->clear();
344 return QSsl::UnknownProtocol;
346 return ( QSsl::SslProtocol )mProtocolCmbBx->currentData().toInt();
355 const int indx( mProtocolCmbBx->findData(
static_cast<int>( protocol ) ) );
356 mProtocolCmbBx->setCurrentIndex( indx );
365 mProtocolCmbBx->setCurrentIndex( 0 );
376 QList<QSslError::SslError> errenums;
377 const auto constErrors = errors;
378 for (
const QSslError &err : constErrors )
380 errenums << err.error();
383 for (
int i = 0; i < mIgnoreErrorsItem->childCount(); i++ )
385 QTreeWidgetItem *item( mIgnoreErrorsItem->child( i ) );
386 if ( errenums.contains( ( QSslError::SslError )item->data( 0, Qt::UserRole ).toInt() ) )
388 item->setCheckState( 0, Qt::Checked );
399 QList<QSslError> errors;
400 const auto constErrorenums = errorenums;
401 for (
const QSslError::SslError errorenum : constErrorenums )
403 errors << QSslError( errorenum );
414 if ( errors.isEmpty() )
421 QList<QSslError::SslError> errenums;
422 const auto constErrors = errors;
423 for (
const QSslError &err : constErrors )
425 errenums << err.error();
428 for (
int i = 0; i < mIgnoreErrorsItem->childCount(); i++ )
430 QTreeWidgetItem *item( mIgnoreErrorsItem->child( i ) );
431 const bool enable( errenums.contains( ( QSslError::SslError )item->data( 0, Qt::UserRole ).toInt() ) );
432 item->setCheckState( 0, enable ? Qt::Checked : Qt::Unchecked );
442 for (
int i = 0; i < mIgnoreErrorsItem->childCount(); i++ )
444 mIgnoreErrorsItem->child( i )->setCheckState( 0, Qt::Unchecked );
450 QList<QSslError::SslError> errs;
455 for (
int i = 0; i < mIgnoreErrorsItem->childCount(); i++ )
457 QTreeWidgetItem *item( mIgnoreErrorsItem->child( i ) );
458 if ( item->checkState( 0 ) == Qt::Checked )
460 errs.append( ( QSslError::SslError )item->data( 0, Qt::UserRole ).toInt() );
470 return QSslSocket::AutoVerifyPeer;
472 return ( QSslSocket::PeerVerifyMode )mVerifyPeerCmbBx->currentData().toInt();
481 return mVerifyDepthSpnBx->value();
492 const int indx( mVerifyPeerCmbBx->findData(
static_cast<int>( mode ) ) );
493 mVerifyPeerCmbBx->setCurrentIndex( indx );
495 mVerifyDepthSpnBx->setValue( modedepth );
504 mVerifyPeerCmbBx->setCurrentIndex( 0 );
505 mVerifyDepthSpnBx->setValue( 0 );
514 const bool cansave = ( isEnabled()
515 && ( grpbxSslConfig->isCheckable() ? grpbxSslConfig->isChecked() : true )
516 && validateHostPort( leHost->text() ) );
517 if ( mCanSave != cansave )
531 leHost->setText( host );
534bool QgsAuthSslConfigWidget::validateHostPort(
const QString &txt )
536 const QString hostport( txt );
537 if ( hostport.isEmpty() )
544 const QString urlbase( QStringLiteral(
"https://%1" ).arg( hostport ) );
545 const QUrl url( urlbase );
546 return ( !url.host().isEmpty() && QString::number( url.port() ).size() > 0
547 && QStringLiteral(
"https://%1:%2" ).arg( url.host() ).arg( url.port() ) == urlbase );
556 const bool valid = validateHostPort( txt );
568 grpbxSslConfig->setCheckable( checkable );
571 grpbxSslConfig->setEnabled(
true );
575void QgsAuthSslConfigWidget::btnCertInfo_clicked()
577 if ( mCert.isNull() )
583 dlg->setWindowModality( Qt::WindowModal );
584 dlg->resize( 675, 500 );
596 setWindowTitle( tr(
"Custom Certificate Configuration" ) );
597 QVBoxLayout *layout =
new QVBoxLayout(
this );
598 layout->setContentsMargins( 6, 6, 6, 6 );
602 this, &QgsAuthSslConfigDialog::checkCanSave );
603 layout->addWidget( mSslConfigWdgt );
605 QDialogButtonBox *buttonBox =
new QDialogButtonBox(
606 QDialogButtonBox::Close | QDialogButtonBox::Save, Qt::Horizontal,
this );
608 buttonBox->button( QDialogButtonBox::Close )->setDefault(
true );
609 mSaveButton = buttonBox->button( QDialogButtonBox::Save );
610 connect( buttonBox, &QDialogButtonBox::rejected,
this, &QWidget::close );
612 layout->addWidget( buttonBox );
615 mSaveButton->setEnabled( mSslConfigWdgt->
readyToSave() );
624void QgsAuthSslConfigDialog::checkCanSave(
bool cansave )
626 mSaveButton->setEnabled( cansave );
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 resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Gets the general name via RFC 5280 resolution.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
static QString getSslProtocolName(QSsl::SslProtocol protocol)
SSL Protocol name strings per enum.
static QList< QPair< QSslError::SslError, QString > > sslErrorEnumStrings()
Gets short strings describing SSL errors.
Configuration container for SSL server connection exceptions or overrides.
void setSslProtocol(QSsl::SslProtocol protocol)
Sets SSL server protocol to use in connections.
void setSslCertificate(const QSslCertificate &cert)
Sets server certificate object.
void setSslHostPort(const QString &hostport)
Sets server host:port string.
QSsl::SslProtocol sslProtocol() const
SSL server protocol to use in connections.
void setSslPeerVerifyMode(QSslSocket::PeerVerifyMode mode)
Sets SSL client's peer verify mode to use in connections.
void setSslPeerVerifyDepth(int depth)
Set number or SSL client's peer to verify in connections.
int sslPeerVerifyDepth() const
Number or SSL client's peer to verify in connections.
bool isNull() const
Whether configuration is null (missing components)
void setSslIgnoredErrorEnums(const QList< QSslError::SslError > &errors)
Sets SSL server errors (as enum list) to ignore in connections.
const QList< QSslError::SslError > sslIgnoredErrorEnums() const
SSL server errors (as enum list) to ignore in connections.
QSslSocket::PeerVerifyMode sslPeerVerifyMode() const
SSL client's peer verify mode to use in connections.
const QSslCertificate sslCertificate() const
Server certificate object.
const QString sslHostPort() const
Server host:port string.
static QString greenTextStyleSheet(const QString &selector="*")
Green text stylesheet representing valid, trusted, etc. certificate.
static QString redTextStyleSheet(const QString &selector="*")
Red text stylesheet representing invalid, untrusted, etc. certificate.
static QString orangeTextStyleSheet(const QString &selector="*")
Orange text stylesheet representing loaded component, but not stored in database.
QgsAuthSslConfigDialog(QWidget *parent=nullptr, const QSslCertificate &cert=QSslCertificate(), const QString &hostport=QString())
Construct wrapper dialog for the SSL config widget.
#define QgsDebugError(str)