23 #include <QSslCertificate> 
   40     case QSsl::SecureProtocols:
 
   41       return QObject::tr( 
"SecureProtocols" );
 
   42 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
   43     case QSsl::TlsV1SslV3:
 
   44       return QObject::tr( 
"TlsV1SslV3" );
 
   47       return QObject::tr( 
"TlsV1" );
 
   48 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
   51       return QObject::tr( 
"SslV3" );
 
   53       return QObject::tr( 
"SslV2" );
 
   62   QMap<QString, QSslCertificate> digestmap;
 
   63   for ( 
const auto &cert : certs )
 
   72   QMap< QString, QList<QSslCertificate> > orgcerts;
 
   73   for ( 
const auto &cert : certs )
 
   77       org = QStringLiteral( 
"(Organization not defined)" );
 
   78     QList<QSslCertificate> valist = orgcerts.contains( org ) ? orgcerts.value( org ) : QList<QSslCertificate>();
 
   79     orgcerts.insert( org, valist << cert );
 
   86   QMap<QString, QgsAuthConfigSslServer> digestmap;
 
   87   for ( 
const auto &config : configs )
 
   89     digestmap.insert( 
shaHexForCert( config.sslCertificate() ), config );
 
   96   QMap< QString, QList<QgsAuthConfigSslServer> > orgconfigs;
 
   97   for ( 
const auto &config : configs )
 
   99     QString org( 
SSL_SUBJECT_INFO( config.sslCertificate(), QSslCertificate::Organization ) );
 
  102       org = QObject::tr( 
"(Organization not defined)" );
 
  103     QList<QgsAuthConfigSslServer> valist = orgconfigs.contains( org ) ? orgconfigs.value( org ) : QList<QgsAuthConfigSslServer>();
 
  104     orgconfigs.insert( org, valist << config );
 
  113   if ( !file.exists() )
 
  115     QgsDebugMsg( QStringLiteral( 
"Read file error, file not found: %1" ).arg( path ) );
 
  119   const QFile::OpenMode openflags( QIODevice::ReadOnly );
 
  120   const bool ret = file.open( openflags );
 
  123     data = file.readAll();
 
  132   QList<QSslCertificate> certs;
 
  134   certs = QSslCertificate::fromData( payload, sniffEncoding( payload ) );
 
  135   if ( certs.isEmpty() )
 
  137     QgsDebugMsg( QStringLiteral( 
"Parsed cert(s) EMPTY for path: %1" ).arg( certspath ) );
 
  144   QList<QSslCertificate> cas;
 
  145   const QList<QSslCertificate> certs( 
certsFromFile( certspath ) );
 
  146   for ( 
const auto &cert : certs )
 
  159   QList<QSslCertificate> result( bundle1 );
 
  160   const QList<QSslCertificate> c_bundle1( bundle1 );
 
  161   for ( 
const auto &cert : c_bundle1 )
 
  165   const QList<QSslCertificate> c_bundle2( bundle2 );
 
  166   for ( 
const auto &cert : c_bundle2 )
 
  170       result.append( cert );
 
  180   QSslCertificate cert;
 
  182   if ( !certs.isEmpty() )
 
  184     cert = certs.first();
 
  188     QgsDebugMsg( QStringLiteral( 
"Parsed cert is NULL for path: %1" ).arg( certpath ) );
 
  194                                        const QString &keypass,
 
  201   const QSsl::EncodingFormat keyEncoding( sniffEncoding( keydata ) );
 
  203   const std::vector<QSsl::KeyAlgorithm> algs
 
  205     QSsl::KeyAlgorithm::Rsa,
 
  206     QSsl::KeyAlgorithm::Dsa,
 
  207     QSsl::KeyAlgorithm::Ec,
 
  208     QSsl::KeyAlgorithm::Opaque
 
  211   for ( 
const auto &alg : algs )
 
  213     clientkey = QSslKey( keydata,
 
  217                          !keypass.isEmpty() ? keypass.toUtf8() : QByteArray() );
 
  218     if ( ! clientkey.isNull() )
 
  224           case QSsl::KeyAlgorithm::Rsa:
 
  225             *algtype = QStringLiteral( 
"rsa" );
 
  227           case QSsl::KeyAlgorithm::Dsa:
 
  228             *algtype = QStringLiteral( 
"dsa" );
 
  230           case QSsl::KeyAlgorithm::Ec:
 
  231             *algtype = QStringLiteral( 
"ec" );
 
  233           case QSsl::KeyAlgorithm::Opaque:
 
  234             *algtype = QStringLiteral( 
"opaque" );
 
  236 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) 
  237           case QSsl::KeyAlgorithm::Dh:
 
  238             *algtype = QStringLiteral( 
"dh" );
 
  251   QList<QSslCertificate> certs;
 
  252   certs = QSslCertificate::fromData( pemtext.toLatin1(), QSsl::Pem );
 
  253   if ( certs.isEmpty() )
 
  255     QgsDebugMsg( QStringLiteral( 
"Parsed cert(s) EMPTY" ) );
 
  262   QList<QSslCertificate> certs;
 
  263   for ( 
const auto &cert : caList )
 
  265     if ( ! cert.isSelfSigned( ) )
 
  267       certs.append( cert );
 
  274     const QString &keypath,
 
  275     const QString &keypass,
 
  280   if ( !clientcert.isNull() )
 
  282     certpem = QString( clientcert.toPem() );
 
  290   if ( !clientkey.isNull() )
 
  292     keypem = QString( clientkey.toPem( ( reencrypt && !keypass.isEmpty() ) ? keypass.toUtf8() : QByteArray() ) );
 
  295   return QStringList() << certpem << keypem << algtype;
 
  300   const QString pkcs8Header = QStringLiteral( 
"-----BEGIN PRIVATE KEY-----" );
 
  301   const QString pkcs8Footer = QStringLiteral( 
"-----END PRIVATE KEY-----" );
 
  302   return keyPemTxt.contains( pkcs8Header ) && keyPemTxt.contains( pkcs8Footer );
 
  306 QByteArray QgsAuthCertUtils::pkcs8PrivateKey( QByteArray &pkcs8Der )
 
  310   if ( pkcs8Der.isEmpty() )
 
  312     QgsDebugMsg( QStringLiteral( 
"ERROR, passed DER is empty" ) );
 
  319   if ( ! asnDefsRsrc.exists() )
 
  321     QgsDebugMsg( QStringLiteral( 
"ERROR, pkcs.asn resource file not found: %1" ).arg( asnDefsRsrc.filePath() ) );
 
  324   const char *asnDefsFile = asnDefsRsrc.absoluteFilePath().toLocal8Bit().constData();
 
  326   int asn1_result = ASN1_SUCCESS, der_len = 0, oct_len = 0;
 
  327   asn1_node definitions = NULL, structure = NULL;
 
  328   char errorDescription[ASN1_MAX_ERROR_DESCRIPTION_SIZE], oct_data[1024];
 
  329   unsigned char *der = NULL;
 
  330   unsigned int flags = 0; 
 
  334   QString 
typeName( QStringLiteral( 
"PKCS-8.PrivateKeyInfo" ) );
 
  336   asn1_result = asn1_parser2tree( asnDefsFile, &definitions, errorDescription );
 
  338   switch ( asn1_result )
 
  343     case ASN1_FILE_NOT_FOUND:
 
  344       QgsDebugMsg( QStringLiteral( 
"ERROR, file not found: %1" ).arg( asnDefsFile ) );
 
  346     case ASN1_SYNTAX_ERROR:
 
  347     case ASN1_IDENTIFIER_NOT_FOUND:
 
  348     case ASN1_NAME_TOO_LONG:
 
  349       QgsDebugMsg( QStringLiteral( 
"ERROR, asn1 parsing: %1" ).arg( errorDescription ) );
 
  352       QgsDebugMsg( QStringLiteral( 
"ERROR, libtasn1: %1" ).arg( asn1_strerror( asn1_result ) ) );
 
  357   asn1_result = asn1_create_element( definitions, 
typeName.toLatin1().constData(), &structure );
 
  361   if ( asn1_result != ASN1_SUCCESS )
 
  363     QgsDebugMsg( QStringLiteral( 
"ERROR, structure creation: %1" ).arg( asn1_strerror( asn1_result ) ) );
 
  368   der = 
reinterpret_cast<unsigned char *
>( pkcs8Der.data() );
 
  369   der_len = pkcs8Der.size();
 
  373     asn1_result = asn1_der_decoding2( &structure, der, &der_len, flags, errorDescription );
 
  377     asn1_result = asn1_der_decoding( &structure, der, der_len, errorDescription );
 
  380   if ( asn1_result != ASN1_SUCCESS )
 
  382     QgsDebugMsg( QStringLiteral( 
"ERROR, decoding: %1" ).arg( errorDescription ) );
 
  387     QgsDebugMsgLevel( QStringLiteral( 
"Decoding: %1" ).arg( asn1_strerror( asn1_result ) ), 4 );
 
  392     QgsDebugMsg( QStringLiteral( 
"DECODING RESULT:" ) );
 
  393     asn1_print_structure( stdout, structure, 
"", ASN1_PRINT_NAME_TYPE_VALUE );
 
  398   typeName.append( QStringLiteral( 
".privateKey" ) );
 
  401   asn1_result = asn1_read_value_type( structure, 
"privateKey", NULL, &oct_len, &oct_etype );
 
  403   if ( asn1_result != ASN1_MEM_ERROR ) 
 
  405     QgsDebugMsg( QStringLiteral( 
"ERROR, asn1 read privateKey value type: %1" ).arg( asn1_strerror( asn1_result ) ) );
 
  409   if ( oct_etype != ASN1_ETYPE_OCTET_STRING )
 
  411     QgsDebugMsg( QStringLiteral( 
"ERROR, asn1 privateKey value not octet string, but type: %1" ).arg( 
static_cast<int>( oct_etype ) ) );
 
  417     QgsDebugMsg( QStringLiteral( 
"ERROR, asn1 privateKey octet string empty" ) );
 
  422   asn1_result = asn1_read_value( structure, 
"privateKey", oct_data, &oct_len );
 
  424   if ( asn1_result != ASN1_SUCCESS )
 
  426     QgsDebugMsg( QStringLiteral( 
"ERROR, asn1 read privateKey value: %1" ).arg( asn1_strerror( asn1_result ) ) );
 
  432     QgsDebugMsg( QStringLiteral( 
"ERROR, asn1 privateKey value octet string empty" ) );
 
  436   pkcs1 = QByteArray( oct_data, oct_len );
 
  443   asn1_delete_structure( &structure );
 
  449     const QString &bundlepass,
 
  453   if ( !QCA::isSupported( 
"pkcs12" ) )
 
  455     QgsDebugMsg( QStringLiteral( 
"QCA does not support PKCS#12" ) );
 
  460   if ( bundle.isNull() )
 
  462     QgsDebugMsg( QStringLiteral( 
"FAILED to convert PKCS#12 file to QCA key bundle: %1" ).arg( bundlepath ) );
 
  466   QCA::SecureArray passarray;
 
  467   if ( reencrypt && !bundlepass.isEmpty() )
 
  469     passarray = QCA::SecureArray( bundlepass.toUtf8() );
 
  473   QSsl::KeyAlgorithm keyalg = QSsl::Opaque;
 
  474   if ( bundle.privateKey().isRSA() )
 
  476     algtype = QStringLiteral( 
"rsa" );
 
  479   else if ( bundle.privateKey().isDSA() )
 
  481     algtype = QStringLiteral( 
"dsa" );
 
  484   else if ( bundle.privateKey().isDH() )
 
  486     algtype = QStringLiteral( 
"dh" );
 
  491   if ( keyalg == QSsl::Opaque )
 
  493     QgsDebugMsg( QStringLiteral( 
"FAILED to read PKCS#12 key (only RSA and DSA algorithms supported): %1" ).arg( bundlepath ) );
 
  501     QgsDebugMsgLevel( QStringLiteral( 
"Private key is PKCS#8: attempting conversion to PKCS#1..." ), 4 );
 
  506     QByteArray pkcs8Der = bundle.privateKey().toDER().toByteArray();
 
  507     if ( pkcs8Der.isEmpty() )
 
  509       QgsDebugMsg( QStringLiteral( 
"FAILED to convert PKCS#12 key to DER-encoded format: %1" ).arg( bundlepath ) );
 
  513     QByteArray pkcs1Der = QgsAuthCertUtils::pkcs8PrivateKey( pkcs8Der );
 
  514     if ( pkcs1Der.isEmpty() )
 
  516       QgsDebugMsg( QStringLiteral( 
"FAILED to convert PKCS#12 key from PKCS#8 to PKCS#1: %1" ).arg( bundlepath ) );
 
  520     QSslKey pkcs1Key( pkcs1Der, QSsl::Rsa, QSsl::Der, QSsl::PrivateKey );
 
  521     if ( pkcs1Key.isNull() )
 
  523       QgsDebugMsg( QStringLiteral( 
"FAILED to convert PKCS#12 key from PKCS#8 to PKCS#1 QSslKey: %1" ).arg( bundlepath ) );
 
  526     keyPem = QString( pkcs1Key.toPem( passarray.toByteArray() ) );
 
  530     keyPem = bundle.privateKey().toPEM( passarray );
 
  533   keyPem = bundle.privateKey().toPEM( passarray );
 
  536   QgsDebugMsgLevel( QStringLiteral( 
"PKCS#12 cert as PEM:\n%1" ).arg( QString( bundle.certificateChain().primary().toPEM() ) ), 4 );
 
  540   return QStringList() << bundle.certificateChain().primary().toPEM() << keyPem << algtype;
 
  545   QList<QSslCertificate> result;
 
  546   if ( !QCA::isSupported( 
"pkcs12" ) )
 
  550   if ( bundle.isNull() )
 
  553   const QCA::CertificateChain chain( bundle.certificateChain() );
 
  554   for ( 
const auto &cert : chain )
 
  558       result.append( QSslCertificate::fromData( cert.toPEM().toLatin1() ) );
 
  567   if ( !certs.isEmpty() )
 
  569     QStringList certslist;
 
  570     for ( 
const auto &cert : certs )
 
  572       certslist << cert.toPem();
 
  574     capem = certslist.join( QLatin1Char( 
'\n' ) ).toLatin1(); 
 
  581   QFile pemFile( QDir::tempPath() + QDir::separator() + name );
 
  582   QString pemFilePath( pemFile.fileName() );
 
  584   if ( pemFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
 
  586     const qint64 bytesWritten = pemFile.write( pemtext );
 
  587     if ( bytesWritten == -1 )
 
  589       QgsDebugMsg( QStringLiteral( 
"FAILED to write to temp PEM file: %1" ).arg( pemFilePath ) );
 
  595     QgsDebugMsg( QStringLiteral( 
"FAILED to open writing for temp PEM file: %1" ).arg( pemFilePath ) );
 
  599   if ( !pemFile.setPermissions( QFile::ReadUser ) )
 
  601     QgsDebugMsg( QStringLiteral( 
"FAILED to set permissions on temp PEM file: %1" ).arg( pemFilePath ) );
 
  613       return single ? QObject::tr( 
"System Root CA" ) : QObject::tr( 
"System Root Authorities" );
 
  615       return single ? QObject::tr( 
"File CA" ) : QObject::tr( 
"Authorities from File" );
 
  617       return single ? QObject::tr( 
"Database CA" ) : QObject::tr( 
"Authorities in Database" );
 
  619       return single ? QObject::tr( 
"Connection CA" ) : QObject::tr( 
"Authorities from connection" );
 
  627   QString name( issuer ? 
SSL_ISSUER_INFO( cert, QSslCertificate::CommonName )
 
  630   if ( name.isEmpty() )
 
  631     name = issuer ? 
SSL_ISSUER_INFO( cert, QSslCertificate::OrganizationalUnitName )
 
  634   if ( name.isEmpty() )
 
  638   if ( name.isEmpty() )
 
  642   if ( name.isEmpty() )
 
  643     name = issuer ? 
SSL_ISSUER_INFO( cert, QSslCertificate::StateOrProvinceName )
 
  646   if ( name.isEmpty() )
 
  654 void QgsAuthCertUtils::appendDirSegment_( QStringList &dirname,
 
  655     const QString &
segment, QString value )
 
  657   if ( !value.isEmpty() )
 
  659     dirname.append( 
segment + 
'=' + value.replace( 
',', QLatin1String( 
"\\," ) ) );
 
  663 QSsl::EncodingFormat QgsAuthCertUtils::sniffEncoding( 
const QByteArray &payload )
 
  665   return payload.contains( QByteArrayLiteral( 
"-----BEGIN " ) ) ?
 
  671     const QCA::Certificate &acert,
 
  677   if ( acert.isNull() )
 
  679     QCA::ConvertResult res;
 
  680     const QCA::Certificate acert( QCA::Certificate::fromPEM( qcert.toPem(), &res, QStringLiteral( 
"qca-ossl" ) ) );
 
  681     if ( res != QCA::ConvertGood || acert.isNull() )
 
  683       QgsDebugMsg( QStringLiteral( 
"Certificate could not be converted to QCA cert" ) );
 
  695   QgsAuthCertUtils::appendDirSegment_(
 
  696     dirname, QStringLiteral( 
"E" ), issuer ? acert.issuerInfo().value( QCA::Email )
 
  697     : acert.subjectInfo().value( QCA::Email ) );
 
  698   QgsAuthCertUtils::appendDirSegment_(
 
  699     dirname, QStringLiteral( 
"CN" ), issuer ? 
SSL_ISSUER_INFO( qcert, QSslCertificate::CommonName )
 
  701   QgsAuthCertUtils::appendDirSegment_(
 
  702     dirname, QStringLiteral( 
"OU" ), issuer ? 
SSL_ISSUER_INFO( qcert, QSslCertificate::OrganizationalUnitName )
 
  704   QgsAuthCertUtils::appendDirSegment_(
 
  705     dirname, QStringLiteral( 
"O" ), issuer ? 
SSL_ISSUER_INFO( qcert, QSslCertificate::Organization )
 
  707   QgsAuthCertUtils::appendDirSegment_(
 
  708     dirname, QStringLiteral( 
"L" ), issuer ? 
SSL_ISSUER_INFO( qcert, QSslCertificate::LocalityName )
 
  710   QgsAuthCertUtils::appendDirSegment_(
 
  711     dirname, QStringLiteral( 
"ST" ), issuer ? 
SSL_ISSUER_INFO( qcert, QSslCertificate::StateOrProvinceName )
 
  713   QgsAuthCertUtils::appendDirSegment_(
 
  714     dirname, QStringLiteral( 
"C" ), issuer ? 
SSL_ISSUER_INFO( qcert, QSslCertificate::CountryName )
 
  717   return dirname.join( QLatin1Char( 
',' ) );
 
  725       return QObject::tr( 
"Default" );
 
  727       return QObject::tr( 
"Trusted" );
 
  729       return QObject::tr( 
"Untrusted" );
 
  740   sl.reserve( txt.size() );
 
  741   for ( 
int i = 0; i < txt.size(); i += 2 )
 
  743     sl << txt.mid( i, ( i + 2 > txt.size() ) ? -1 : 2 );
 
  745   return sl.join( QLatin1Char( 
':' ) );
 
  750   QString sha( cert.digest( QCryptographicHash::Sha1 ).toHex() );
 
  761     return QCA::Certificate();
 
  763   QCA::ConvertResult res;
 
  764   QCA::Certificate qcacert( QCA::Certificate::fromPEM( cert.toPem(), &res, QStringLiteral( 
"qca-ossl" ) ) );
 
  765   if ( res != QCA::ConvertGood || qcacert.isNull() )
 
  767     QgsDebugMsg( QStringLiteral( 
"Certificate could not be converted to QCA cert" ) );
 
  768     qcacert = QCA::Certificate();
 
  775   QCA::CertificateCollection qcacoll;
 
  779   for ( 
const auto &cert : certs )
 
  782     if ( !qcacert.isNull() )
 
  784       qcacoll.addCertificate( qcacert );
 
  792   QCA::SecureArray passarray;
 
  793   if ( !pass.isEmpty() )
 
  794     passarray = QCA::SecureArray( pass.toUtf8() );
 
  796   QCA::ConvertResult res;
 
  797   const QCA::KeyBundle bundle( QCA::KeyBundle::fromFile( path, passarray, &res, QStringLiteral( 
"qca-ossl" ) ) );
 
  799   return ( res == QCA::ConvertGood ? bundle : QCA::KeyBundle() );
 
  806     case QCA::ValidityGood:
 
  807       return QObject::tr( 
"Certificate is valid." );
 
  808     case QCA::ErrorRejected:
 
  809       return QObject::tr( 
"Root CA rejected the certificate purpose." );
 
  810     case QCA::ErrorUntrusted:
 
  811       return QObject::tr( 
"Certificate is not trusted." );
 
  812     case QCA::ErrorSignatureFailed:
 
  813       return QObject::tr( 
"Signature does not match." );
 
  814     case QCA::ErrorInvalidCA:
 
  815       return QObject::tr( 
"Certificate Authority is invalid or not found." );
 
  816     case QCA::ErrorInvalidPurpose:
 
  817       return QObject::tr( 
"Purpose does not match the intended usage." );
 
  818     case QCA::ErrorSelfSigned:
 
  819       return QObject::tr( 
"Certificate is self-signed, and is not found in the list of trusted certificates." );
 
  820     case QCA::ErrorRevoked:
 
  821       return QObject::tr( 
"Certificate has been revoked." );
 
  822     case QCA::ErrorPathLengthExceeded:
 
  823       return QObject::tr( 
"Path length from the root CA to this certificate is too long." );
 
  824     case QCA::ErrorExpired:
 
  825       return QObject::tr( 
"Certificate has expired or is not yet valid." );
 
  826     case QCA::ErrorExpiredCA:
 
  827       return QObject::tr( 
"Certificate Authority has expired." );
 
  828     case QCA::ErrorValidityUnknown:
 
  829       return QObject::tr( 
"Validity is unknown." );
 
  839     case QCA::EMSA1_SHA1:
 
  840       return QObject::tr( 
"SHA1, with EMSA1" );
 
  841     case QCA::EMSA3_SHA1:
 
  842       return QObject::tr( 
"SHA1, with EMSA3" );
 
  844       return QObject::tr( 
"MD5, with EMSA3" );
 
  846       return QObject::tr( 
"MD2, with EMSA3" );
 
  847     case QCA::EMSA3_RIPEMD160:
 
  848       return QObject::tr( 
"RIPEMD160, with EMSA3" );
 
  850       return QObject::tr( 
"EMSA3, without digest" );
 
  851 #if QCA_VERSION >= 0x020100 
  852     case QCA::EMSA3_SHA224:
 
  853       return QObject::tr( 
"SHA224, with EMSA3" );
 
  854     case QCA::EMSA3_SHA256:
 
  855       return QObject::tr( 
"SHA256, with EMSA3" );
 
  856     case QCA::EMSA3_SHA384:
 
  857       return QObject::tr( 
"SHA384, with EMSA3" );
 
  858     case QCA::EMSA3_SHA512:
 
  859       return QObject::tr( 
"SHA512, with EMSA3" );
 
  862       return QObject::tr( 
"Unknown (possibly Elliptic Curve)" );
 
  868   switch ( constraint )
 
  870     case QCA::DigitalSignature:
 
  871       return QObject::tr( 
"Digital Signature" );
 
  872     case QCA::NonRepudiation:
 
  873       return QObject::tr( 
"Non-repudiation" );
 
  874     case QCA::KeyEncipherment:
 
  875       return QObject::tr( 
"Key Encipherment" );
 
  876     case QCA::DataEncipherment:
 
  877       return QObject::tr( 
"Data Encipherment" );
 
  878     case QCA::KeyAgreement:
 
  879       return QObject::tr( 
"Key Agreement" );
 
  880     case QCA::KeyCertificateSign:
 
  881       return QObject::tr( 
"Key Certificate Sign" );
 
  883       return QObject::tr( 
"CRL Sign" );
 
  884     case QCA::EncipherOnly:
 
  885       return QObject::tr( 
"Encipher Only" );
 
  886     case QCA::DecipherOnly:
 
  887       return QObject::tr( 
"Decipher Only" );
 
  888     case QCA::ServerAuth:
 
  889       return QObject::tr( 
"Server Authentication" );
 
  890     case QCA::ClientAuth:
 
  891       return QObject::tr( 
"Client Authentication" );
 
  892     case QCA::CodeSigning:
 
  893       return QObject::tr( 
"Code Signing" );
 
  894     case QCA::EmailProtection:
 
  895       return QObject::tr( 
"Email Protection" );
 
  896     case QCA::IPSecEndSystem:
 
  897       return QObject::tr( 
"IPSec Endpoint" );
 
  898     case QCA::IPSecTunnel:
 
  899       return QObject::tr( 
"IPSec Tunnel" );
 
  901       return QObject::tr( 
"IPSec User" );
 
  902     case QCA::TimeStamping:
 
  903       return QObject::tr( 
"Time Stamping" );
 
  904     case QCA::OCSPSigning:
 
  905       return QObject::tr( 
"OCSP Signing" );
 
  916       return QObject::tr( 
"Any or unspecified" );
 
  918       return QObject::tr( 
"Certificate Authority" );
 
  920       return QObject::tr( 
"Certificate Issuer" );
 
  922       return QObject::tr( 
"TLS/SSL Server" );
 
  924       return QObject::tr( 
"TLS/SSL Server EV" );
 
  926       return QObject::tr( 
"TLS/SSL Client" );
 
  928       return QObject::tr( 
"Code Signing" );
 
  930       return QObject::tr( 
"Email Protection" );
 
  932       return QObject::tr( 
"Time Stamping" );
 
  934       return QObject::tr( 
"CRL Signing" );
 
  937       return QObject::tr( 
"Undetermined usage" );
 
  943   QList<QgsAuthCertUtils::CertUsageType> usages;
 
  948   QCA::ConvertResult res;
 
  949   const QCA::Certificate qcacert( QCA::Certificate::fromPEM( cert.toPem(), &res, QStringLiteral( 
"qca-ossl" ) ) );
 
  950   if ( res != QCA::ConvertGood || qcacert.isNull() )
 
  952     QgsDebugMsg( QStringLiteral( 
"Certificate could not be converted to QCA cert" ) );
 
  956   if ( qcacert.isCA() )
 
  958     QgsDebugMsg( QStringLiteral( 
"Certificate has 'CA:TRUE' basic constraint" ) );
 
  962   const QList<QCA::ConstraintType> certconsts = qcacert.constraints();
 
  963   for ( 
const auto &certconst : certconsts )
 
  965     if ( certconst.known() == QCA::KeyCertificateSign )
 
  967       QgsDebugMsg( QStringLiteral( 
"Certificate has 'Certificate Sign' key usage" ) );
 
  970     else if ( certconst.known() == QCA::ServerAuth )
 
  972       QgsDebugMsg( QStringLiteral( 
"Certificate has 'server authentication' extended key usage" ) );
 
  978   const QCA::CertificateCollection trustedCAs(
 
  980   const QCA::CertificateCollection untrustedCAs(
 
  984   v_any = qcacert.validate( trustedCAs, untrustedCAs, QCA::UsageAny, QCA::ValidateAll );
 
  985   if ( v_any == QCA::ValidityGood )
 
  990   QCA::Validity v_tlsserver;
 
  991   v_tlsserver = qcacert.validate( trustedCAs, untrustedCAs, QCA::UsageTLSServer, QCA::ValidateAll );
 
  992   if ( v_tlsserver == QCA::ValidityGood )
 
 1002   QCA::Validity v_tlsclient;
 
 1003   v_tlsclient = qcacert.validate( trustedCAs, untrustedCAs, QCA::UsageTLSClient, QCA::ValidateAll );
 
 1005   if ( v_tlsclient == QCA::ValidityGood )
 
 1048   QCA::ConvertResult res;
 
 1049   QCA::Certificate qcacert( QCA::Certificate::fromPEM( cert.toPem(), &res, QString( 
"qca-ossl" ) ) );
 
 1050   if ( res != QCA::ConvertGood || qcacert.isNull() )
 
 1052     QgsDebugMsg( QStringLiteral( 
"Certificate could not be converted to QCA cert" ) );
 
 1056   if ( qcacert.isCA() )
 
 1058     QgsDebugMsg( QStringLiteral( 
"SSL server certificate has 'CA:TRUE' basic constraint (and should not)" ) );
 
 1062   const QList<QCA::ConstraintType> certconsts = qcacert.constraints();
 
 1063   for ( 
const auto & certconst, certconsts )
 
 1065     if ( certconst.known() == QCA::KeyCertificateSign )
 
 1067       QgsDebugMsg( QStringLiteral( 
"SSL server certificate has 'Certificate Sign' key usage (and should not)" ) );
 
 1074   bool serverauth = 
false;
 
 1075   bool dsignature = 
false;
 
 1076   bool keyencrypt = 
false;
 
 1077   for ( 
const auto &certconst : certconsts )
 
 1079     if ( certconst.known() == QCA::DigitalSignature )
 
 1081       QgsDebugMsg( QStringLiteral( 
"SSL server certificate has 'digital signature' key usage" ) );
 
 1084     else if ( certconst.known() == QCA::KeyEncipherment )
 
 1086       QgsDebugMsg( QStringLiteral( 
"SSL server certificate has 'key encipherment' key usage" ) );
 
 1089     else if ( certconst.known() == QCA::KeyAgreement )
 
 1091       QgsDebugMsg( QStringLiteral( 
"SSL server certificate has 'key agreement' key usage" ) );
 
 1094     else if ( certconst.known() == QCA::ServerAuth )
 
 1096       QgsDebugMsg( QStringLiteral( 
"SSL server certificate has 'server authentication' extended key usage" ) );
 
 1108   if ( serverauth && dsignature && keyencrypt )
 
 1112   if ( dsignature && keyencrypt )
 
 1118   bool keyagree = 
false;
 
 1119   bool encipheronly = 
false;
 
 1120   bool decipheronly = 
false;
 
 1122   QCA::PublicKey pubkey( qcacert.subjectPublicKey() );
 
 1124   if ( pubkey.bitSize() > 0 && pubkey.isDH() )
 
 1126     keyagree = pubkey.canKeyAgree();
 
 1131     for ( 
const auto &certconst : certconsts )
 
 1133       if ( certconst.known() == QCA::EncipherOnly )
 
 1135         QgsDebugMsg( QStringLiteral( 
"SSL server public key has 'encipher only' key usage" ) );
 
 1136         encipheronly = 
true;
 
 1138       else if ( certconst.known() == QCA::DecipherOnly )
 
 1140         QgsDebugMsg( QStringLiteral( 
"SSL server public key has 'decipher only' key usage" ) );
 
 1141         decipheronly = 
true;
 
 1144     if ( !encipheronly && !decipheronly )
 
 1162     case QSslError::UnableToGetIssuerCertificate:
 
 1163       return QObject::tr( 
"Unable to Get Issuer Certificate" );
 
 1164     case QSslError::UnableToDecryptCertificateSignature:
 
 1165       return QObject::tr( 
"Unable to Decrypt Certificate Signature" );
 
 1166     case QSslError::UnableToDecodeIssuerPublicKey:
 
 1167       return QObject::tr( 
"Unable to Decode Issuer Public Key" );
 
 1168     case QSslError::CertificateSignatureFailed:
 
 1169       return QObject::tr( 
"Certificate Signature Failed" );
 
 1170     case QSslError::CertificateNotYetValid:
 
 1171       return QObject::tr( 
"Certificate Not Yet Valid" );
 
 1172     case QSslError::CertificateExpired:
 
 1173       return QObject::tr( 
"Certificate Expired" );
 
 1174     case QSslError::InvalidNotBeforeField:
 
 1175       return QObject::tr( 
"Invalid Not Before Field" );
 
 1176     case QSslError::InvalidNotAfterField:
 
 1177       return QObject::tr( 
"Invalid Not After Field" );
 
 1178     case QSslError::SelfSignedCertificate:
 
 1179       return QObject::tr( 
"Self-signed Certificate" );
 
 1180     case QSslError::SelfSignedCertificateInChain:
 
 1181       return QObject::tr( 
"Self-signed Certificate In Chain" );
 
 1182     case QSslError::UnableToGetLocalIssuerCertificate:
 
 1183       return QObject::tr( 
"Unable to Get Local Issuer Certificate" );
 
 1184     case QSslError::UnableToVerifyFirstCertificate:
 
 1185       return QObject::tr( 
"Unable to Verify First Certificate" );
 
 1186     case QSslError::CertificateRevoked:
 
 1187       return QObject::tr( 
"Certificate Revoked" );
 
 1188     case QSslError::InvalidCaCertificate:
 
 1189       return QObject::tr( 
"Invalid CA Certificate" );
 
 1190     case QSslError::PathLengthExceeded:
 
 1191       return QObject::tr( 
"Path Length Exceeded" );
 
 1192     case QSslError::InvalidPurpose:
 
 1193       return QObject::tr( 
"Invalid Purpose" );
 
 1194     case QSslError::CertificateUntrusted:
 
 1195       return QObject::tr( 
"Certificate Untrusted" );
 
 1196     case QSslError::CertificateRejected:
 
 1197       return QObject::tr( 
"Certificate Rejected" );
 
 1198     case QSslError::SubjectIssuerMismatch:
 
 1199       return QObject::tr( 
"Subject Issuer Mismatch" );
 
 1200     case QSslError::AuthorityIssuerSerialNumberMismatch:
 
 1201       return QObject::tr( 
"Authority Issuer Serial Number Mismatch" );
 
 1202     case QSslError::NoPeerCertificate:
 
 1203       return QObject::tr( 
"No Peer Certificate" );
 
 1204     case QSslError::HostNameMismatch:
 
 1205       return QObject::tr( 
"Host Name Mismatch" );
 
 1206     case QSslError::UnspecifiedError:
 
 1207       return QObject::tr( 
"Unspecified Error" );
 
 1208     case QSslError::CertificateBlacklisted:
 
 1209       return QObject::tr( 
"Certificate Blacklisted" );
 
 1210     case QSslError::NoError:
 
 1211       return QObject::tr( 
"No Error" );
 
 1212     case QSslError::NoSslSupport:
 
 1213       return QObject::tr( 
"No SSL Support" );
 
 1221   QList<QPair<QSslError::SslError, QString> > errenums;
 
 1222   errenums << qMakePair( QSslError::UnableToGetIssuerCertificate,
 
 1224   errenums << qMakePair( QSslError::UnableToDecryptCertificateSignature,
 
 1226   errenums << qMakePair( QSslError::UnableToDecodeIssuerPublicKey,
 
 1228   errenums << qMakePair( QSslError::CertificateSignatureFailed,
 
 1230   errenums << qMakePair( QSslError::CertificateNotYetValid,
 
 1232   errenums << qMakePair( QSslError::CertificateExpired,
 
 1234   errenums << qMakePair( QSslError::InvalidNotBeforeField,
 
 1236   errenums << qMakePair( QSslError::InvalidNotAfterField,
 
 1238   errenums << qMakePair( QSslError::SelfSignedCertificate,
 
 1240   errenums << qMakePair( QSslError::SelfSignedCertificateInChain,
 
 1242   errenums << qMakePair( QSslError::UnableToGetLocalIssuerCertificate,
 
 1244   errenums << qMakePair( QSslError::UnableToVerifyFirstCertificate,
 
 1246   errenums << qMakePair( QSslError::CertificateRevoked,
 
 1248   errenums << qMakePair( QSslError::InvalidCaCertificate,
 
 1250   errenums << qMakePair( QSslError::PathLengthExceeded,
 
 1252   errenums << qMakePair( QSslError::InvalidPurpose,
 
 1254   errenums << qMakePair( QSslError::CertificateUntrusted,
 
 1256   errenums << qMakePair( QSslError::CertificateRejected,
 
 1258   errenums << qMakePair( QSslError::SubjectIssuerMismatch,
 
 1260   errenums << qMakePair( QSslError::AuthorityIssuerSerialNumberMismatch,
 
 1262   errenums << qMakePair( QSslError::NoPeerCertificate,
 
 1264   errenums << qMakePair( QSslError::HostNameMismatch,
 
 1266   errenums << qMakePair( QSslError::UnspecifiedError,
 
 1268   errenums << qMakePair( QSslError::CertificateBlacklisted,
 
 1275   if ( cert.isNull() )
 
 1277   const QDateTime currentTime = QDateTime::currentDateTime();
 
 1278   return cert.effectiveDate() <= currentTime && cert.expiryDate() >= currentTime;
 
 1283   QList<QSslError> sslErrors;
 
 1285   if ( cert.isNull() )
 
 1288   const QDateTime currentTime = QDateTime::currentDateTime();
 
 1289   if ( cert.expiryDate() <= currentTime )
 
 1291     sslErrors << QSslError( QSslError::SslError::CertificateExpired, cert );
 
 1293   if ( cert.effectiveDate() >= QDateTime::currentDateTime() )
 
 1295     sslErrors << QSslError( QSslError::SslError::CertificateNotYetValid, cert );
 
 1297   if ( cert.isBlacklisted() )
 
 1299     sslErrors << QSslError( QSslError::SslError::CertificateBlacklisted, cert );
 
 1311     const QString &hostName,
 
 1314   QList<QSslError> sslErrors;
 
 1315   QList<QSslCertificate> trustedChain;
 
 1317   for ( 
const auto &cert : certificateChain )
 
 1319     bool untrusted = 
false;
 
 1322       if ( cert.digest( ) == untrustedCert.digest( ) )
 
 1330       trustedChain << cert;
 
 1335   const QList<QSslCertificate> constTrustedChain( trustedChain );
 
 1336   for ( 
const auto &cert : constTrustedChain )
 
 1342   if ( trustRootCa && trustedChain.count() > 1 && trustedChain.last().isSelfSigned() )
 
 1344     static QMutex sMutex;
 
 1345     const QMutexLocker lock( &sMutex );
 
 1346     const QSslConfiguration oldSslConfig( QSslConfiguration::defaultConfiguration() );
 
 1347     QSslConfiguration sslConfig( oldSslConfig );
 
 1348     sslConfig.setCaCertificates( 
casMerge( sslConfig.caCertificates(), QList<QSslCertificate>() << trustedChain.last() ) );
 
 1349     QSslConfiguration::setDefaultConfiguration( sslConfig );
 
 1350     sslErrors = QSslCertificate::verify( trustedChain, hostName );
 
 1351     QSslConfiguration::setDefaultConfiguration( oldSslConfig );
 
 1355     sslErrors = QSslCertificate::verify( trustedChain, hostName );
 
 1364     errors << QObject::tr( 
"Client certificate is NULL." );
 
 1367     errors << QObject::tr( 
"Client certificate key is NULL." );
 
 1370   if ( !errors.isEmpty() )
 
 1373   QList<QSslError> sslErrors;
 
 1374   if ( useIntermediates )
 
 1376     QList<QSslCertificate> certsList( bundle.
caChain() );
 
 1382     sslErrors = QSslCertificate::verify( QList<QSslCertificate>() << bundle.
clientCert() );
 
 1384   const QList<QSslError> constSslErrors( sslErrors );
 
 1385   for ( 
const auto &sslError : constSslErrors )
 
 1387     if ( sslError.error() != QSslError::NoError )
 
 1389       errors << sslError.errorString();
 
 1393   const QCA::PrivateKey pvtKey( QCA::PrivateKey::fromPEM( bundle.
clientKey().toPem() ) );
 
 1394   const QCA::PublicKey pubKey( QCA::PublicKey::fromPEM( bundle.
clientCert().publicKey().toPem( ) ) );
 
 1395   bool keyValid( ! pvtKey.isNull() );
 
 1396   if ( keyValid && !( pubKey.toRSA().isNull( ) || pvtKey.toRSA().isNull( ) ) )
 
 1398     keyValid = pubKey.toRSA().n() == pvtKey.toRSA().n();
 
 1400   else if ( keyValid && !( pubKey.toDSA().isNull( ) || pvtKey.toDSA().isNull( ) ) )
 
 1402     keyValid = pubKey == QCA::DSAPublicKey( pvtKey.toDSA() );
 
 1406     QgsDebugMsg( QStringLiteral( 
"Key is not DSA, RSA: validation is not supported by QCA" ) );
 
 1410     errors << QObject::tr( 
"Private key does not match client certificate public key." );
 
static QString pkgDataPath()
Returns the common root path of all application data directories.
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
static QString sslErrorEnumString(QSslError::SslError errenum)
Gets short strings describing an SSL error.
static QString qcaValidityMessage(QCA::Validity validity)
Certificate validity check messages per enum.
static QByteArray fileData(const QString &path)
Returns data from a local file via a read-only operation.
static QList< QgsAuthCertUtils::CertUsageType > certificateUsageTypes(const QSslCertificate &cert)
Try to determine the certificates usage types.
static QString qcaSignatureAlgorithm(QCA::SignatureAlgorithm algorithm)
Certificate signature algorithm strings per enum.
static QString resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Gets the general name via RFC 5280 resolution.
static QCA::Certificate qtCertToQcaCert(const QSslCertificate &cert)
Convert a QSslCertificate to a QCA::Certificate.
static QMap< QString, QList< QSslCertificate > > certsGroupedByOrg(const QList< QSslCertificate > &certs)
Map certificates to their oraganization.
static QString certificateUsageTypeString(QgsAuthCertUtils::CertUsageType usagetype)
Certificate usage type strings per enum.
static QString getCertTrustName(QgsAuthCertUtils::CertTrustPolicy trust)
Gets the general name for certificate trust.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Gets the sha1 hash for certificate.
static QCA::CertificateCollection qtCertsToQcaCollection(const QList< QSslCertificate > &certs)
Convert a QList of QSslCertificate to a QCA::CertificateCollection.
CertTrustPolicy
Type of certificate trust policy.
static QSslCertificate certFromFile(const QString &certpath)
Returns the first cert from a PEM or DER formatted file.
static QString qcaKnownConstraint(QCA::ConstraintTypeKnown constraint)
Certificate well-known constraint strings per enum.
static QMap< QString, QSslCertificate > mapDigestToCerts(const QList< QSslCertificate > &certs)
Map certificate sha1 to certificate as simple cache.
static QList< QSslCertificate > casMerge(const QList< QSslCertificate > &bundle1, const QList< QSslCertificate > &bundle2)
casMerge merges two certificate bundles in a single one removing duplicates, the certificates from th...
static QByteArray certsToPemText(const QList< QSslCertificate > &certs)
certsToPemText dump a list of QSslCertificates to PEM text
static QString getSslProtocolName(QSsl::SslProtocol protocol)
SSL Protocol name strings per enum.
static bool certIsViable(const QSslCertificate &cert)
certIsViable checks for viability errors of cert and whether it is NULL
static QStringList certKeyBundleToPem(const QString &certpath, const QString &keypath, const QString &keypass=QString(), bool reencrypt=true)
Returns list of certificate, private key and algorithm (as PEM text) from file path components.
static QString getColonDelimited(const QString &txt)
Gets string with colon delimiters every 2 characters.
static bool certificateIsAuthority(const QSslCertificate &cert)
Gets whether a certificate is an Authority.
static QStringList pkcs12BundleToPem(const QString &bundlepath, const QString &bundlepass=QString(), bool reencrypt=true)
Returns list of certificate, private key and algorithm (as PEM text) for a PKCS#12 bundle.
static QMap< QString, QList< QgsAuthConfigSslServer > > sslConfigsGroupedByOrg(const QList< QgsAuthConfigSslServer > &configs)
Map SSL custom configs' certificates to their oraganization.
static QList< QSslCertificate > certsFromFile(const QString &certspath)
Returns a list of concatenated certs from a PEM or DER formatted file.
static bool certificateIsAuthorityOrIssuer(const QSslCertificate &cert)
Gets whether a certificate is an Authority or can at least sign other certificates.
static QList< QSslCertificate > casRemoveSelfSigned(const QList< QSslCertificate > &caList)
casRemoveSelfSigned remove self-signed CA certificates from caList
static bool certificateIsIssuer(const QSslCertificate &cert)
Gets whether a certificate can sign other certificates.
static bool certificateIsSslClient(const QSslCertificate &cert)
Gets whether a certificate is probably used for a client identity.
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 bool certificateIsSslServer(const QSslCertificate &cert)
Gets whether a certificate is probably used for a SSL server.
static QList< QSslCertificate > casFromFile(const QString &certspath)
Returns a list of concatenated CAs 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
CertUsageType
Type of certificate usage.
CaCertSource
Type of CA certificate source.
static QList< QSslCertificate > pkcs12BundleCas(const QString &bundlepath, const QString &bundlepass=QString())
Returns list of CA certificates (as QSslCertificate) for a PKCS#12 bundle.
static QCA::KeyBundle qcaKeyBundle(const QString &path, const QString &pass)
PKI key/cert bundle from file path, e.g.
static QString getCaSourceName(QgsAuthCertUtils::CaCertSource source, bool single=false)
Gets the general name for CA source enum type.
static QString pemTextToTempFile(const QString &name, const QByteArray &pemtext)
Write a temporary file for a PEM text of cert/key/CAs bundle component.
static bool pemIsPkcs8(const QString &keyPemTxt)
Determine if the PEM-encoded text of a key is PKCS#8 format.
static QMap< QString, QgsAuthConfigSslServer > mapDigestToSslConfigs(const QList< QgsAuthConfigSslServer > &configs)
Map SSL custom configs' certificate sha1 to custom config as simple cache.
static QList< QSslError > validateCertChain(const QList< QSslCertificate > &certificateChain, const QString &hostName=QString(), bool trustRootCa=false)
validateCertChain validates the given certificateChain
static QList< QPair< QSslError::SslError, QString > > sslErrorEnumStrings()
Gets short strings describing SSL errors.
static QString getCertDistinguishedName(const QSslCertificate &qcert, const QCA::Certificate &acert=QCA::Certificate(), bool issuer=false)
Gets combined distinguished name for certificate.
static QStringList validatePKIBundle(QgsPkiBundle &bundle, bool useIntermediates=true, bool trustRootCa=false)
validatePKIBundle validate the PKI bundle by checking the certificate chain, the expiration and effec...
static QList< QSslError > certViabilityErrors(const QSslCertificate &cert)
certViabilityErrors checks basic characteristics (validity dates, blocklisting, etc....
static int debugLevel()
Reads the environment variable QGIS_DEBUG and converts it to int.
Storage set for PKI bundle: SSL certificate, key, optional CA cert chain.
const QSslKey clientKey() const
Private key object.
const QList< QSslCertificate > caChain() const
Chain of Certificate Authorities for client certificate.
const QSslCertificate clientCert() const
Client certificate object.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
#define SSL_SUBJECT_INFO(var, prop)
#define SSL_ISSUER_INFO(var, prop)
#define QgsDebugMsgLevel(str, level)
QLineF segment(int index, QRectF rect, double radius)