18#include "moc_qgsauthimportidentitydialog.cpp" 
   19#include "ui_qgsauthimportidentitydialog.h" 
   36  , mIdentityType( CertIdentity )
 
   44    mAuthNotifyLayout = 
new QVBoxLayout;
 
   45    this->setLayout( mAuthNotifyLayout );
 
   47    mAuthNotifyLayout->addWidget( mAuthNotify );
 
   52    connect( lePkiPathsKeyPass, &QLineEdit::textChanged, 
this, &QgsAuthImportIdentityDialog::lePkiPathsKeyPass_textChanged );
 
   53    connect( chkPkiPathsPassShow, &QCheckBox::stateChanged, 
this, &QgsAuthImportIdentityDialog::chkPkiPathsPassShow_stateChanged );
 
   54    connect( btnPkiPathsCert, &QToolButton::clicked, 
this, &QgsAuthImportIdentityDialog::btnPkiPathsCert_clicked );
 
   55    connect( btnPkiPathsKey, &QToolButton::clicked, 
this, &QgsAuthImportIdentityDialog::btnPkiPathsKey_clicked );
 
   56    connect( lePkiPkcs12KeyPass, &QLineEdit::textChanged, 
this, &QgsAuthImportIdentityDialog::lePkiPkcs12KeyPass_textChanged );
 
   57    connect( chkPkiPkcs12PassShow, &QCheckBox::stateChanged, 
this, &QgsAuthImportIdentityDialog::chkPkiPkcs12PassShow_stateChanged );
 
   58    connect( btnPkiPkcs12Bundle, &QToolButton::clicked, 
this, &QgsAuthImportIdentityDialog::btnPkiPkcs12Bundle_clicked );
 
   59    connect( buttonBox, &QDialogButtonBox::rejected, 
this, &QWidget::close );
 
   60    connect( buttonBox, &QDialogButtonBox::accepted, 
this, &QDialog::accept );
 
   62    mIdentityType = identitytype;
 
   64    populateIdentityType();
 
 
   81    return qMakePair( QSslCertificate(), QSslKey() );
 
 
   86void QgsAuthImportIdentityDialog::populateIdentityType()
 
   90    stkwBundleType->setVisible( 
true );
 
   95    connect( cmbIdentityTypes, 
static_cast<void ( QComboBox::* )( 
int )
>( &QComboBox::currentIndexChanged ), stkwBundleType, &QStackedWidget::setCurrentIndex );
 
   96    connect( stkwBundleType, &QStackedWidget::currentChanged, cmbIdentityTypes, &QComboBox::setCurrentIndex );
 
   98    connect( cmbIdentityTypes, 
static_cast<void ( QComboBox::* )( 
int )
>( &QComboBox::currentIndexChanged ), 
this, [
this] { validateIdentity(); } );
 
   99    connect( stkwBundleType, &QStackedWidget::currentChanged, 
this, &QgsAuthImportIdentityDialog::validateIdentity );
 
  101    cmbIdentityTypes->setCurrentIndex( 0 );
 
  102    stkwBundleType->setCurrentIndex( 0 );
 
  107void QgsAuthImportIdentityDialog::validateIdentity()
 
  112    ok = validateBundle();
 
  114  okButton()->setEnabled( ok );
 
  117bool QgsAuthImportIdentityDialog::validateBundle()
 
  120  const QSslCertificate emptycert;
 
  121  const QSslKey emptykey;
 
  122  mCertBundle = qMakePair( emptycert, emptykey );
 
  125  QWidget *curpage = stkwBundleType->currentWidget();
 
  126  if ( curpage == pagePkiPaths )
 
  128    return validatePkiPaths();
 
  130  else if ( curpage == pagePkiPkcs12 )
 
  132    return validatePkiPkcs12();
 
  138void QgsAuthImportIdentityDialog::clearValidation()
 
  140  teValidation->clear();
 
  141  teValidation->setStyleSheet( QString() );
 
  152      txt = tr( 
"Valid: %1" ).arg( msg );
 
  156      txt = tr( 
"Invalid: %1" ).arg( msg );
 
  161  teValidation->setStyleSheet( ss );
 
  164    teValidation->append( txt );
 
  168    teValidation->setText( txt );
 
  170  teValidation->moveCursor( QTextCursor::Start );
 
  173void QgsAuthImportIdentityDialog::lePkiPathsKeyPass_textChanged( 
const QString &pass )
 
  179void QgsAuthImportIdentityDialog::chkPkiPathsPassShow_stateChanged( 
int state )
 
  181  lePkiPathsKeyPass->setEchoMode( ( state > 0 ) ? QLineEdit::Normal : QLineEdit::Password );
 
  184void QgsAuthImportIdentityDialog::btnPkiPathsCert_clicked()
 
  186  const QString &fn = getOpenFileName( tr( 
"Open Client Certificate File" ), tr( 
"All files (*.*);;PEM (*.pem);;DER (*.der)" ) );
 
  189    lePkiPathsCert->setText( fn );
 
  194void QgsAuthImportIdentityDialog::btnPkiPathsKey_clicked()
 
  196  const QString &fn = getOpenFileName( tr( 
"Open Private Key File" ), tr( 
"All files (*.*);;PEM (*.pem);;DER (*.der)" ) );
 
  199    lePkiPathsKey->setText( fn );
 
  204void QgsAuthImportIdentityDialog::lePkiPkcs12KeyPass_textChanged( 
const QString &pass )
 
  210void QgsAuthImportIdentityDialog::chkPkiPkcs12PassShow_stateChanged( 
int state )
 
  212  lePkiPkcs12KeyPass->setEchoMode( ( state > 0 ) ? QLineEdit::Normal : QLineEdit::Password );
 
  215void QgsAuthImportIdentityDialog::btnPkiPkcs12Bundle_clicked()
 
  217  const QString &fn = getOpenFileName( tr( 
"Open PKCS#12 Certificate Bundle" ), tr( 
"PKCS#12 (*.p12 *.pfx)" ) );
 
  220    lePkiPkcs12Bundle->setText( fn );
 
  225bool QgsAuthImportIdentityDialog::validatePkiPaths()
 
  227  bool isvalid = 
false;
 
  230  const QString certpath( lePkiPathsCert->text() );
 
  231  const QString keypath( lePkiPathsKey->text() );
 
  233  const bool certfound = QFile::exists( certpath );
 
  234  const bool keyfound = QFile::exists( keypath );
 
  236  fileFound( certpath.isEmpty() || certfound, lePkiPathsCert );
 
  237  fileFound( keypath.isEmpty() || keyfound, lePkiPathsKey );
 
  239  if ( !certfound || !keyfound )
 
  241    writeValidation( tr( 
"Missing components" ), 
Invalid );
 
  246  QSslCertificate clientcert;
 
  248  QList<QSslCertificate> ca_certs;
 
  249  if ( !certs.isEmpty() )
 
  251    clientcert = certs.takeFirst();
 
  255    writeValidation( tr( 
"Failed to read client certificate from file" ), 
Invalid );
 
  259  if ( clientcert.isNull() )
 
  261    writeValidation( tr( 
"Failed to load client certificate from file" ), 
Invalid );
 
  265  if ( !certs.isEmpty() ) 
 
  267    teValidation->append( tr( 
"Extra certificates found with identity" ) );
 
  273  const QDateTime startdate( clientcert.effectiveDate() );
 
  274  const QDateTime enddate( clientcert.expiryDate() );
 
  280  const QString keypass( lePkiPathsKeyPass->text() );
 
  282  if ( clientkey.isNull() )
 
  284    writeValidation( tr( 
"Failed to load client private key from file" ), 
Invalid, 
true );
 
  285    if ( !keypass.isEmpty() )
 
  287      writeValidation( tr( 
"Private key password may not match" ), 
Invalid, 
true );
 
  294    mCertBundle = qMakePair( clientcert, clientkey );
 
  295    mPkiBundle = 
QgsPkiBundle( clientcert, clientkey, ca_certs );
 
  301bool QgsAuthImportIdentityDialog::validatePkiPkcs12()
 
  304  const QString bundlepath( lePkiPkcs12Bundle->text() );
 
  305  const bool bundlefound = QFile::exists( bundlepath );
 
  306  fileFound( bundlepath.isEmpty() || bundlefound, lePkiPkcs12Bundle );
 
  310    writeValidation( tr( 
"Missing components" ), 
Invalid );
 
  314  if ( !QCA::isSupported( 
"pkcs12" ) )
 
  316    writeValidation( tr( 
"QCA library has no PKCS#12 support" ), 
Invalid );
 
  321  QCA::SecureArray passarray;
 
  322  QString keypass = QString();
 
  323  if ( !lePkiPkcs12KeyPass->text().isEmpty() )
 
  325    passarray = QCA::SecureArray( lePkiPkcs12KeyPass->text().toUtf8() );
 
  326    keypass = lePkiPkcs12KeyPass->text();
 
  329  QCA::ConvertResult res;
 
  330  const QCA::KeyBundle bundle( QCA::KeyBundle::fromFile( bundlepath, passarray, &res, QStringLiteral( 
"qca-ossl" ) ) );
 
  332  if ( res == QCA::ErrorFile )
 
  334    writeValidation( tr( 
"Failed to read bundle file" ), 
Invalid );
 
  337  else if ( res == QCA::ErrorPassphrase )
 
  339    writeValidation( tr( 
"Incorrect bundle password" ), 
Invalid );
 
  340    lePkiPkcs12KeyPass->setPlaceholderText( QStringLiteral( 
"Required passphrase" ) );
 
  343  else if ( res == QCA::ErrorDecode )
 
  345    writeValidation( tr( 
"Failed to decode (try entering password)" ), 
Invalid );
 
  349  if ( bundle.isNull() )
 
  351    writeValidation( tr( 
"Bundle empty or can not be loaded" ), 
Invalid );
 
  356  const QCA::Certificate cert( bundle.certificateChain().primary() );
 
  359    writeValidation( tr( 
"Bundle client cert can not be loaded" ), 
Invalid );
 
  364  const QDateTime startdate( cert.notValidBefore() );
 
  365  const QDateTime enddate( cert.notValidAfter() );
 
  366  const QDateTime now( QDateTime::currentDateTime() );
 
  367  const bool bundlevalid = ( now >= startdate && now <= enddate );
 
  369  writeValidation( tr( 
"%1 thru %2" ).arg( startdate.toString(), enddate.toString() ), ( bundlevalid ? 
Valid : 
Invalid ) );
 
  373    QSslCertificate clientcert;
 
  375    if ( !certs.isEmpty() )
 
  377      clientcert = certs.first();
 
  379    if ( clientcert.isNull() )
 
  381      writeValidation( tr( 
"Qt cert could not be created from QCA cert" ), 
Invalid, 
true );
 
  385    clientkey = QSslKey( bundle.privateKey().toRSA().toPEM().toLatin1(), QSsl::Rsa );
 
  386    if ( clientkey.isNull() )
 
  388      writeValidation( tr( 
"Qt private key could not be created from QCA key" ), 
Invalid, 
true );
 
  392    const QCA::CertificateChain cert_chain( bundle.certificateChain() );
 
  393    QList<QSslCertificate> ca_certs;
 
  394    if ( cert_chain.size() > 1 )
 
  396      const auto constCert_chain = cert_chain;
 
  397      for ( 
const QCA::Certificate &ca_cert : constCert_chain )
 
  399        if ( ca_cert != cert_chain.primary() )
 
  401          ca_certs << QSslCertificate( ca_cert.toPEM().toLatin1() );
 
  406    mCertBundle = qMakePair( clientcert, clientkey );
 
  407    mPkiBundle = 
QgsPkiBundle( clientcert, clientkey, ca_certs );
 
  413void QgsAuthImportIdentityDialog::fileFound( 
bool found, QWidget *widget )
 
  418    widget->setToolTip( tr( 
"File not found" ) );
 
  422    widget->setStyleSheet( QString() );
 
  423    widget->setToolTip( QString() );
 
  427QString QgsAuthImportIdentityDialog::getOpenFileName( 
const QString &title, 
const QString &extfilter )
 
  430  const QString recentdir = settings.
value( QStringLiteral( 
"UI/lastAuthImportBundleOpenFileDir" ), QDir::homePath() ).toString();
 
  431  QString f = QFileDialog::getOpenFileName( 
this, title, recentdir, extfilter );
 
  435  this->activateWindow();
 
  439    settings.
setValue( QStringLiteral( 
"UI/lastAuthImportBundleOpenFileDir" ), QFileInfo( f ).absoluteDir().path() );
 
  444QPushButton *QgsAuthImportIdentityDialog::okButton()
 
  446  return buttonBox->button( QDialogButtonBox::Ok );
 
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
 
static bool certIsViable(const QSslCertificate &cert)
certIsViable checks for viability errors of cert and whether it is NULL
 
static QList< QSslCertificate > certsFromFile(const QString &certspath)
Returns a list of concatenated certs from a PEM or DER formatted file.
 
static QSslKey keyFromFile(const QString &keypath, const QString &keypass=QString(), QString *algtype=nullptr)
Returns non-encrypted key from a PEM or DER formatted file.
 
static QList< QSslCertificate > certsFromString(const QString &pemtext)
Returns a list of concatenated certs from a PEM Base64 text block.
 
static bool certIsCurrent(const QSslCertificate &cert)
certIsCurrent checks if cert is viable for its not before and not after dates
 
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.
 
QgsAuthImportIdentityDialog::IdentityType identityType()
Gets identity type.
 
const QPair< QSslCertificate, QSslKey > certBundleToImport()
Gets certificate/key bundle to be imported.
 
Validity
Type of certificate/bundle validity output.
 
IdentityType
Type of identity being imported.
 
QgsAuthImportIdentityDialog(QgsAuthImportIdentityDialog::IdentityType identitytype, QWidget *parent=nullptr)
Construct a dialog for importing identities.
 
Storage set for PKI bundle: SSL certificate, key, optional CA cert chain.
 
Stores settings for use within QGIS.
 
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.