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)