26#include <QCryptographicHash> 
   34const QString QgsAuthMethodConfig::CONFIG_SEP = QStringLiteral( 
"|||" );
 
   35const QString QgsAuthMethodConfig::CONFIG_KEY_SEP = QStringLiteral( 
":::" );
 
   36const QString QgsAuthMethodConfig::CONFIG_LIST_SEP = QStringLiteral( 
"```" );
 
   38const int QgsAuthMethodConfig::CONFIG_VERSION = 1;
 
   53  return ( other.
id() == 
id()
 
 
   63  return  !( *
this == other );
 
 
   68  const bool idvalid = validateid ? !mId.isEmpty() : 
true;
 
 
   80  QgsStringMap::const_iterator i = mConfigMap.constBegin();
 
   81  while ( i != mConfigMap.constEnd() )
 
   83    confstrs << i.key() + CONFIG_KEY_SEP + i.value();
 
   86  return confstrs.join( CONFIG_SEP );
 
 
   92  if ( configstr.isEmpty() )
 
   97  const QStringList confs( configstr.split( CONFIG_SEP ) );
 
   99  for ( 
const auto &conf : confs )
 
  101    if ( conf.contains( CONFIG_KEY_SEP ) )
 
  103      const QStringList keyval( conf.split( CONFIG_KEY_SEP ) );
 
  104      setConfig( keyval.at( 0 ), keyval.at( 1 ) );
 
  110    setConfig( QStringLiteral( 
"oldconfigstyle" ), configstr );
 
 
  116  mConfigMap.insert( key, value );
 
 
  121  setConfig( key, value.join( CONFIG_LIST_SEP ) );
 
 
  126  return mConfigMap.remove( key );
 
 
  131  return mConfigMap.value( key, defaultvalue );
 
 
  136  return config( key ).split( CONFIG_LIST_SEP );
 
 
  141  return mConfigMap.contains( key );
 
 
  146  QString res = QString();
 
  147  if ( !accessurl.isEmpty() )
 
  149    const QUrl url( accessurl );
 
  152      res = QStringLiteral( 
"%1://%2:%3%4" ).arg( url.scheme(), url.host() )
 
  153            .arg( url.port() ).arg( withpath ? url.path() : QString() );
 
  157  return ( !res.isEmpty() );
 
 
  163  QDomElement element = document.createElement( QStringLiteral( 
"AuthMethodConfig" ) );
 
  164  element.setAttribute( QStringLiteral( 
"method" ), mMethod );
 
  165  element.setAttribute( QStringLiteral( 
"id" ), mId );
 
  166  element.setAttribute( QStringLiteral( 
"name" ), mName );
 
  167  element.setAttribute( QStringLiteral( 
"version" ), QString::number( mVersion ) );
 
  168  element.setAttribute( QStringLiteral( 
"uri" ), mUri );
 
  170  QDomElement configElements = document.createElement( QStringLiteral( 
"Config" ) );
 
  171  QgsStringMap::const_iterator i = mConfigMap.constBegin();
 
  172  while ( i != mConfigMap.constEnd() )
 
  174    configElements.setAttribute( i.key(), i.value() );
 
  177  element.appendChild( configElements );
 
  179  parentElement.appendChild( element );
 
 
  185  if ( element.nodeName() != QLatin1String( 
"AuthMethodConfig" ) )
 
  188  mMethod = element.attribute( QStringLiteral( 
"method" ) );
 
  189  mId = element.attribute( QStringLiteral( 
"id" ) );
 
  190  mName = element.attribute( QStringLiteral( 
"name" ) );
 
  191  mVersion = element.attribute( QStringLiteral( 
"version" ) ).toInt();
 
  192  mUri = element.attribute( QStringLiteral( 
"uri" ) );
 
  195  const QDomNamedNodeMap configAttributes = element.firstChildElement().attributes();
 
  196  for ( 
int i = 0; i < configAttributes.length(); i++ )
 
  198    const QDomAttr configAttribute = configAttributes.item( i ).toAttr();
 
  199    setConfig( configAttribute.name(), configAttribute.value() );
 
 
  212                            const QSslKey &clientKey,
 
  213                            const QList<QSslCertificate> &caChain )
 
  214  : mCert( QSslCertificate() )
 
  215  , mCertKey( QSslKey() )
 
  216  , mCaChain( caChain )
 
 
  223    const QString &keyPath,
 
  224    const QString &keyPass,
 
  225    const QList<QSslCertificate> &caChain )
 
  228  if ( !certPath.isEmpty() && !keyPath.isEmpty()
 
  229       && ( certPath.endsWith( QLatin1String( 
".pem" ), Qt::CaseInsensitive )
 
  230            || certPath.endsWith( QLatin1String( 
".der" ), Qt::CaseInsensitive ) )
 
  231       && QFile::exists( certPath ) && QFile::exists( keyPath )
 
  235    const bool pem = certPath.endsWith( QLatin1String( 
".pem" ), Qt::CaseInsensitive );
 
 
  251    const QString &bundlepass )
 
  254  if ( QCA::isSupported( 
"pkcs12" )
 
  255       && !bundlepath.isEmpty()
 
  256       && ( bundlepath.endsWith( QLatin1String( 
".p12" ), Qt::CaseInsensitive )
 
  257            || bundlepath.endsWith( QLatin1String( 
".pfx" ), Qt::CaseInsensitive ) )
 
  258       && QFile::exists( bundlepath ) )
 
  260    QCA::SecureArray passarray;
 
  261    if ( !bundlepass.isNull() )
 
  262      passarray = QCA::SecureArray( bundlepass.toUtf8() );
 
  263    QCA::ConvertResult res;
 
  264    const QCA::KeyBundle bundle( QCA::KeyBundle::fromFile( bundlepath, passarray, &res, QStringLiteral( 
"qca-ossl" ) ) );
 
  265    if ( res == QCA::ConvertGood && !bundle.isNull() )
 
  267      const QCA::CertificateChain cert_chain( bundle.certificateChain() );
 
  268      const QSslCertificate cert( cert_chain.primary().toPEM().toLatin1() );
 
  269      if ( !cert.isNull() )
 
  273      const QSslKey cert_key( bundle.privateKey().toPEM().toLatin1(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, QByteArray() );
 
  274      if ( !cert_key.isNull() )
 
  279      if ( cert_chain.size() > 1 )
 
  281        QList<QSslCertificate> ca_chain;
 
  282        for ( 
const auto &ca_cert : cert_chain )
 
  284          if ( ca_cert != cert_chain.primary() )
 
  286            ca_chain << QSslCertificate( ca_cert.toPEM().toLatin1() );
 
 
  299  return ( mCert.isNull() || mCertKey.isNull() );
 
 
  309  if ( mCert.isNull() )
 
  313  return QString( mCert.digest( QCryptographicHash::Sha1 ).toHex() );
 
 
  319  if ( !cert.isNull() )
 
 
  328  if ( !certkey.isNull() && certkey.type() == QSsl::PrivateKey )
 
 
  340                                        const QSslCertificate &cert,
 
  341                                        const QSslKey &certkey,
 
  342                                        const QList<QSslCertificate> &cachain )
 
  345  , mCertKey( certkey )
 
  346  , mCaChain( cachain )
 
 
  352  return ( !mCert.isNull() && !mCertKey.isNull() );
 
 
  360const QString QgsAuthConfigSslServer::CONF_SEP = QStringLiteral( 
"|||" );
 
  363  : mSslHostPort( QString() )
 
  364  , mSslCert( QSslCertificate() )
 
  365  , mSslIgnoredErrors( QList<QSslError::SslError>() )
 
  371  mSslProtocol = QSsl::SecureProtocols;
 
 
  376  QList<QSslError> errors;
 
  378  for ( 
const QSslError::SslError errenum : ignoredErrors )
 
  380    errors << QSslError( errenum );
 
 
  387  QStringList configlist
 
  389    QString::number( mVersion ),
 
  390    QString::number( mQtVersion ),
 
  391    encodeSslProtocol( mSslProtocol )
 
  395  for ( 
const auto err : mSslIgnoredErrors )
 
  397    errs << QString::number( static_cast< int >( err ) );
 
  399  configlist << errs.join( QLatin1String( 
"~~" ) );
 
  401  configlist << QStringLiteral( 
"%1~~%2" ).arg( 
static_cast< int >( mSslPeerVerifyMode ) ).arg( mSslPeerVerifyDepth );
 
  403  return configlist.join( CONF_SEP );
 
 
  408  if ( config.isEmpty() )
 
  412  const QStringList configlist( config.split( CONF_SEP ) );
 
  414  mVersion = configlist.at( 0 ).toInt();
 
  415  mQtVersion = configlist.at( 1 ).toInt();
 
  416  mSslProtocol = decodeSslProtocol( configlist.at( 2 ) );
 
  418  mSslIgnoredErrors.clear();
 
  419  const QStringList errs( configlist.at( 3 ).split( QStringLiteral( 
"~~" ) ) );
 
  420  for ( 
const auto &err : errs )
 
  422    mSslIgnoredErrors.append( 
static_cast< QSslError::SslError 
>( err.toInt() ) );
 
  425  const QStringList peerverify( configlist.at( 4 ).split( QStringLiteral( 
"~~" ) ) );
 
  426  mSslPeerVerifyMode = 
static_cast< QSslSocket::PeerVerifyMode 
>( peerverify.at( 0 ).toInt() );
 
  427  mSslPeerVerifyDepth = peerverify.at( 1 ).toInt();
 
 
  432  return mSslCert.isNull() && mSslHostPort.isEmpty();
 
 
  435QSsl::SslProtocol QgsAuthConfigSslServer::decodeSslProtocol( 
const QString &protocol )
 
  438  const int qt5EnumInt = protocol.toInt( &ok );
 
  443    switch ( qt5EnumInt )
 
  446#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  447        return QSsl::SslProtocol::SslV3;
 
  449        return QSsl::SslProtocol::UnknownProtocol;
 
  453#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  454        return QSsl::SslProtocol::SslV2;
 
  459        return QSsl::SslProtocol::TlsV1_0;
 
  461        return QSsl::SslProtocol::TlsV1_1;
 
  463        return QSsl::SslProtocol::TlsV1_2;
 
  465        return QSsl::SslProtocol::AnyProtocol;
 
  467#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  468        return QSsl::SslProtocol::TlsV1SslV3;
 
  470        return QSsl::SslProtocol::TlsV1_3;
 
  473        return QSsl::SslProtocol::SecureProtocols;
 
  475        return QSsl::SslProtocol::TlsV1_0OrLater;
 
  477        return QSsl::SslProtocol::TlsV1_1OrLater;
 
  479        return QSsl::SslProtocol::TlsV1_2OrLater;
 
  481        return QSsl::SslProtocol::DtlsV1_0;
 
  483        return QSsl::SslProtocol::DtlsV1_0OrLater;
 
  485        return QSsl::SslProtocol::DtlsV1_2;
 
  487        return QSsl::SslProtocol::DtlsV1_2OrLater;
 
  489        return QSsl::SslProtocol::TlsV1_3;
 
  491        return QSsl::SslProtocol::TlsV1_3OrLater;
 
  493        return QSsl::SslProtocol::UnknownProtocol;
 
  497#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  498  if ( protocol == QLatin1String( 
"SslV3" ) )
 
  499    return QSsl::SslProtocol::SslV3;
 
  500  else if ( protocol == QLatin1String( 
"SslV2" ) )
 
  501    return QSsl::SslProtocol::SslV2;
 
  503  if ( protocol == QLatin1String( 
"TlsV1_0" ) )
 
  504    return QSsl::SslProtocol::TlsV1_0;
 
  505  else if ( protocol == QLatin1String( 
"TlsV1_1" ) )
 
  506    return QSsl::SslProtocol::TlsV1_1;
 
  507  else if ( protocol == QLatin1String( 
"TlsV1_2" ) )
 
  508    return QSsl::SslProtocol::TlsV1_2;
 
  509  else if ( protocol == QLatin1String( 
"AnyProtocol" ) )
 
  510    return QSsl::SslProtocol::AnyProtocol;
 
  511#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  512  else if ( protocol == QLatin1String( 
"TlsV1SslV3" ) )
 
  513    return QSsl::SslProtocol::TlsV1SslV3;
 
  515  else if ( protocol == QLatin1String( 
"SecureProtocols" ) )
 
  516    return QSsl::SslProtocol::SecureProtocols;
 
  517  else if ( protocol == QLatin1String( 
"TlsV1_0OrLater" ) )
 
  518    return QSsl::SslProtocol::TlsV1_0OrLater;
 
  519  else if ( protocol == QLatin1String( 
"TlsV1_1OrLater" ) )
 
  520    return QSsl::SslProtocol::TlsV1_1OrLater;
 
  521  else if ( protocol == QLatin1String( 
"TlsV1_2OrLater" ) )
 
  522    return QSsl::SslProtocol::TlsV1_2OrLater;
 
  523  else if ( protocol == QLatin1String( 
"DtlsV1_0" ) )
 
  524    return QSsl::SslProtocol::DtlsV1_0;
 
  525  else if ( protocol == QLatin1String( 
"DtlsV1_0OrLater" ) )
 
  526    return QSsl::SslProtocol::DtlsV1_0OrLater;
 
  527  else if ( protocol == QLatin1String( 
"DtlsV1_2" ) )
 
  528    return QSsl::SslProtocol::DtlsV1_2;
 
  529  else if ( protocol == QLatin1String( 
"DtlsV1_2OrLater" ) )
 
  530    return QSsl::SslProtocol::DtlsV1_2OrLater;
 
  531  else if ( protocol == QLatin1String( 
"TlsV1_3" ) )
 
  532    return QSsl::SslProtocol::TlsV1_3;
 
  533  else if ( protocol == QLatin1String( 
"TlsV1_3OrLater" ) )
 
  534    return QSsl::SslProtocol::TlsV1_3OrLater;
 
  536  QgsDebugError( QStringLiteral( 
"Can't decode protocol \"%1\"" ).arg( protocol ) );
 
  538  return QSsl::SslProtocol::UnknownProtocol;
 
  541QString QgsAuthConfigSslServer::encodeSslProtocol( QSsl::SslProtocol protocol )
 
  545#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  547      return QStringLiteral( 
"SslV3" );
 
  549      return QStringLiteral( 
"SslV2" );
 
  552      return QStringLiteral( 
"TlsV1_0" );
 
  554      return QStringLiteral( 
"TlsV1_1" );
 
  556      return QStringLiteral( 
"TlsV1_2" );
 
  557    case QSsl::AnyProtocol:
 
  558      return QStringLiteral( 
"AnyProtocol" );
 
  559#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 
  560    case QSsl::TlsV1SslV3:
 
  561      return QStringLiteral( 
"TlsV1SslV3" );
 
  563    case QSsl::SecureProtocols:
 
  564      return QStringLiteral( 
"SecureProtocols" );
 
  565    case QSsl::TlsV1_0OrLater:
 
  566      return QStringLiteral( 
"TlsV1_0OrLater" );
 
  567    case QSsl::TlsV1_1OrLater:
 
  568      return QStringLiteral( 
"TlsV1_1OrLater" );
 
  569    case QSsl::TlsV1_2OrLater:
 
  570      return QStringLiteral( 
"TlsV1_2OrLater" );
 
  572      return QStringLiteral( 
"DtlsV1_0" );
 
  573    case QSsl::DtlsV1_0OrLater:
 
  574      return QStringLiteral( 
"DtlsV1_0OrLater" );
 
  576      return QStringLiteral( 
"DtlsV1_2" );
 
  577    case QSsl::DtlsV1_2OrLater:
 
  578      return QStringLiteral( 
"DtlsV1_2OrLater" );
 
  580      return QStringLiteral( 
"TlsV1_3" );
 
  581    case QSsl::TlsV1_3OrLater:
 
  582      return QStringLiteral( 
"TlsV1_3OrLater" );
 
  583    case QSsl::UnknownProtocol:
 
  584      return QStringLiteral( 
"UnknownProtocol" );
 
  587  QgsDebugError( QStringLiteral( 
"Can't encode protocol: %1" ).arg( protocol ) );
 
  589  return QStringLiteral( 
"UnknownProtocol" );
 
static QByteArray fileData(const QString &path)
Returns data from a local file via a read-only operation.
 
static bool certIsViable(const QSslCertificate &cert)
certIsViable checks for viability errors of cert and whether it is NULL
 
static QSslKey keyFromFile(const QString &keypath, const QString &keypass=QString(), QString *algtype=nullptr)
Returns non-encrypted key from a PEM or DER formatted file.
 
const QList< QSslError > sslIgnoredErrors() const
SSL server errors to ignore in connections.
 
bool isNull() const
Whether configuration is null (missing components)
 
const QList< QSslError::SslError > sslIgnoredErrorEnums() const
SSL server errors (as enum list) to ignore in connections.
 
const QString configString() const
Configuration as a concatenated string.
 
QgsAuthConfigSslServer()
Construct a default SSL server configuration.
 
void loadConfigString(const QString &config=QString())
Load concatenated string into configuration, e.g. from auth database.
 
Configuration storage class for authentication method configurations.
 
QString config(const QString &key, const QString &defaultvalue=QString()) const
Returns a config's value.
 
bool isValid(bool validateid=false) const
Whether the configuration is valid.
 
QString method() const
Textual key of the associated authentication method.
 
const QString uri() const
A URI to auto-select a config when connecting to a resource.
 
int removeConfig(const QString &key)
Remove a config from map.
 
bool readXml(const QDomElement &element)
from a DOM element.
 
const QString configString() const
The extended configuration, as stored and retrieved from the authentication database.
 
const QString name() const
Gets name of configuration.
 
bool operator==(const QgsAuthMethodConfig &other) const
 
const QString id() const
Gets 'authcfg' 7-character alphanumeric ID of the config.
 
void loadConfigString(const QString &configstr)
Load existing extended configuration.
 
void clearConfigMap()
Clear all configs.
 
bool writeXml(QDomElement &parentElement, QDomDocument &document)
Stores the configuration in a DOM.
 
void setConfig(const QString &key, const QString &value)
Set a single config value per key in the map.
 
QStringList configList(const QString &key) const
Returns a config's list of values.
 
int version() const
Gets version of the configuration.
 
QgsStringMap configMap() const
Gets extended configuration, mapped to key/value pairs of QStrings.
 
bool operator!=(const QgsAuthMethodConfig &other) const
 
bool hasConfig(const QString &key) const
Whether a config key exists in config map.
 
QgsAuthMethodConfig(const QString &method=QString(), int version=0)
Construct a configuration for an authentication method.
 
void setConfigList(const QString &key, const QStringList &value)
Set a multiple config values per key in the map.
 
static bool uriToResource(const QString &accessurl, QString *resource, bool withpath=false)
A utility function for generating a resource from a URL to be compared against the config's uri() for...
 
Storage set for PKI bundle: SSL certificate, key, optional CA cert chain.
 
const QString certId() const
The sha hash of the client certificate.
 
bool isNull() const
Whether the bundle, either its certificate or private key, is null.
 
QgsPkiBundle(const QSslCertificate &clientCert=QSslCertificate(), const QSslKey &clientKey=QSslKey(), const QList< QSslCertificate > &caChain=QList< QSslCertificate >())
Construct a bundle from existing PKI components.
 
void setClientKey(const QSslKey &certkey)
Sets private key object.
 
void setClientCert(const QSslCertificate &cert)
Sets client certificate object.
 
static const QgsPkiBundle fromPkcs12Paths(const QString &bundlepath, const QString &bundlepass=QString())
Construct a bundle of PKI components from a PKCS#12 file path.
 
const QSslKey clientKey() const
Private key object.
 
void setCaChain(const QList< QSslCertificate > &cachain)
Sets chain of Certificate Authorities for client certificate.
 
const QList< QSslCertificate > caChain() const
Chain of Certificate Authorities for client certificate.
 
static const QgsPkiBundle fromPemPaths(const QString &certPath, const QString &keyPath, const QString &keyPass=QString(), const QList< QSslCertificate > &caChain=QList< QSslCertificate >())
Construct a bundle of PKI components from PEM-formatted file paths.
 
const QSslCertificate clientCert() const
Client certificate object.
 
bool isValid() const
Whether the bundle is valid.
 
QgsPkiConfigBundle(const QgsAuthMethodConfig &config, const QSslCertificate &cert, const QSslKey &certkey, const QList< QSslCertificate > &cachain=QList< QSslCertificate >())
Construct a bundle from existing PKI components and authentication method configuration.
 
bool isValid()
Whether the bundle is valid.
 
QMap< QString, QString > QgsStringMap
 
#define QgsDebugError(str)