diff --git a/python/core/auth/qgsauthcertutils.sip b/python/core/auth/qgsauthcertutils.sip index 06cc2975702..239f1203a2f 100644 --- a/python/core/auth/qgsauthcertutils.sip +++ b/python/core/auth/qgsauthcertutils.sip @@ -87,12 +87,29 @@ Return list of concatenated certs from a PEM or DER formatted file :rtype: list of QSslCertificate %End + static QList casFromFile( const QString &certspath ); +%Docstring +Return list of concatenated CAs from a PEM or DER formatted file + :rtype: list of QSslCertificate +%End + static QSslCertificate certFromFile( const QString &certpath ); %Docstring Return first cert from a PEM or DER formatted file :rtype: QSslCertificate %End + static QList casMerge( const QList &bundle1, + const QList &bundle2 ); +%Docstring + casMerge merges two certificate bundles in a single one removing duplicates, the certificates + from the ``bundle2`` are appended to ``bundle1`` if not already there + \param bundle1 first bundle + \param bundle2 second bundle + :return: a list of unique certificates + :rtype: list of QSslCertificate +%End + static QSslKey keyFromFile( const QString &keypath, const QString &keypass = QString(), QString *algtype = 0 ); @@ -136,6 +153,25 @@ Return list of concatenated certs from a PEM Base64 text block :rtype: list of str %End + static QList pkcs12BundleCas( const QString &bundlepath, + const QString &bundlepass = QString() ); +%Docstring + Return list of CA certificates (as QSslCertificate) for a PKCS#12 bundle + \param bundlepath File path to the PKCS bundle + \param bundlepass Passphrase for bundle + :return: list of certificate + :rtype: list of QSslCertificate +%End + + + static QByteArray certsToPemText( const QList &certs ); +%Docstring + certsToPemText dump a list of QSslCertificates to PEM text + \param certs list of certs + :return: a byte array of concatenated certificates as PEM text + :rtype: QByteArray +%End + static QString pemTextToTempFile( const QString &name, const QByteArray &pemtext ); %Docstring Write a temporary file for a PEM text of cert/key/CAs bundle component diff --git a/src/core/auth/qgsauthcertutils.cpp b/src/core/auth/qgsauthcertutils.cpp index d9ec3168e07..f36c7f24566 100644 --- a/src/core/auth/qgsauthcertutils.cpp +++ b/src/core/auth/qgsauthcertutils.cpp @@ -125,6 +125,42 @@ QList QgsAuthCertUtils::certsFromFile( const QString &certspath return certs; } +QList QgsAuthCertUtils::casFromFile( const QString &certspath ) +{ + QList cas; + const QList certs( certsFromFile( certspath ) ); + for ( const auto &cert : certs ) + { + if ( certificateIsAuthority( cert ) ) + { + cas.append( cert ); + } + } + return cas; +} + +QList QgsAuthCertUtils::casMerge( const QList &bundle1, const QList &bundle2 ) +{ + QStringList shas; + QList result( bundle1 ); + const QList c_bundle1( bundle1 ); + for ( const auto &cert : c_bundle1 ) + { + shas.append( shaHexForCert( cert ) ); + } + const QList c_bundle2( bundle2 ); + for ( const auto &cert : c_bundle2 ) + { + if ( ! shas.contains( shaHexForCert( cert ) ) ) + { + result.append( cert ); + } + } + return result; +} + + + QSslCertificate QgsAuthCertUtils::certFromFile( const QString &certpath ) { QSslCertificate cert; @@ -246,6 +282,42 @@ QStringList QgsAuthCertUtils::pkcs12BundleToPem( const QString &bundlepath, return QStringList() << bundle.certificateChain().primary().toPEM() << bundle.privateKey().toPEM( passarray ) << algtype; } +QList QgsAuthCertUtils::pkcs12BundleCas( const QString &bundlepath, const QString &bundlepass ) +{ + QList result; + if ( !QCA::isSupported( "pkcs12" ) ) + return result; + + QCA::KeyBundle bundle( QgsAuthCertUtils::qcaKeyBundle( bundlepath, bundlepass ) ); + if ( bundle.isNull() ) + return result; + + const QCA::CertificateChain chain( bundle.certificateChain() ); + for ( const auto &cert : chain ) + { + if ( cert.isCA( ) ) + { + result.append( QSslCertificate::fromData( cert.toPEM().toAscii() ) ); + } + } + return result; +} + +QByteArray QgsAuthCertUtils::certsToPemText( const QList &certs ) +{ + QByteArray capem; + if ( !certs.isEmpty() ) + { + QStringList certslist; + for ( const auto &cert : certs ) + { + certslist << cert.toPem(); + } + capem = certslist.join( QStringLiteral( "\n" ) ).toLatin1(); //+ "\n"; + } + return capem; +} + QString QgsAuthCertUtils::pemTextToTempFile( const QString &name, const QByteArray &pemtext ) { QFile pemFile( QDir::tempPath() + QDir::separator() + name ); diff --git a/src/core/auth/qgsauthcertutils.h b/src/core/auth/qgsauthcertutils.h index f6738713a55..c62ccf1e927 100644 --- a/src/core/auth/qgsauthcertutils.h +++ b/src/core/auth/qgsauthcertutils.h @@ -107,9 +107,22 @@ class CORE_EXPORT QgsAuthCertUtils //! Return list of concatenated certs from a PEM or DER formatted file static QList certsFromFile( const QString &certspath ); + //! Return list of concatenated CAs from a PEM or DER formatted file + static QList casFromFile( const QString &certspath ); + //! Return first cert from a PEM or DER formatted file static QSslCertificate certFromFile( const QString &certpath ); + /** + * \brief casMerge merges two certificate bundles in a single one removing duplicates, the certificates + * from the \a bundle2 are appended to \a bundle1 if not already there + * \param bundle1 first bundle + * \param bundle2 second bundle + * \return a list of unique certificates + */ + static QList casMerge( const QList &bundle1, + const QList &bundle2 ); + /** * Return non-encrypted key from a PEM or DER formatted file * \param keypath File path to private key @@ -147,6 +160,23 @@ class CORE_EXPORT QgsAuthCertUtils const QString &bundlepass = QString(), bool reencrypt = true ); + /** + * Return list of CA certificates (as QSslCertificate) for a PKCS#12 bundle + * \param bundlepath File path to the PKCS bundle + * \param bundlepass Passphrase for bundle + * \returns list of certificate + */ + static QList pkcs12BundleCas( const QString &bundlepath, + const QString &bundlepass = QString() ); + + + /** + * \brief certsToPemText dump a list of QSslCertificates to PEM text + * \param certs list of certs + * \return a byte array of concatenated certificates as PEM text + */ + static QByteArray certsToPemText( const QList &certs ); + /** * Write a temporary file for a PEM text of cert/key/CAs bundle component * \param pemtext Component content as PEM text