22 #include <QSslCertificate>
31 #if QT_VERSION >= 0x040800
32 case QSsl::SecureProtocols:
34 case QSsl::TlsV1SslV3:
65 org =
"(Organization not defined)";
67 orgcerts.
insert( org, valist << cert );
92 orgconfigs.
insert( org, valist << config );
105 openflags |= QIODevice::Text;
106 bool ret = file.
open( openflags );
119 bool pem = certspath.
endsWith(
".pem", Qt::CaseInsensitive );
132 if ( certs.
size() > 0 )
134 cert = certs.
first();
147 bool pem = keypath.
endsWith(
".pem", Qt::CaseInsensitive );
153 pem ? QSsl::Pem : QSsl::Der,
161 pem ? QSsl::Pem : QSsl::Der,
198 if ( !clientcert.
isNull() )
208 if ( !clientkey.
isNull() )
213 return QStringList() << certpem << keypem << algtype;
221 if ( !QCA::isSupported(
"pkcs12" ) )
225 if ( bundle.isNull() )
228 QCA::SecureArray passarray;
229 if ( reencrypt && !bundlepass.
isEmpty() )
230 passarray = QCA::SecureArray( bundlepass.
toUtf8() );
233 if ( bundle.privateKey().isRSA() )
237 else if ( bundle.privateKey().isDSA() )
241 else if ( bundle.privateKey().isDH() )
246 return QStringList() << bundle.certificateChain().primary().toPEM() << bundle.privateKey().toPEM( passarray ) << algtype;
272 name = issuer ?
SSL_ISSUER_INFO( cert, QSslCertificate::OrganizationalUnitName )
284 name = issuer ?
SSL_ISSUER_INFO( cert, QSslCertificate::StateOrProvinceName )
295 void QgsAuthCertUtils::appendDirSegment_(
QStringList &dirname,
300 dirname.
append( segment +
"=" + value.
replace(
",",
"\\," ) );
305 const QCA::Certificate &acert ,
311 if ( acert.isNull() )
313 QCA::ConvertResult res;
314 QCA::Certificate acert( QCA::Certificate::fromPEM( qcert.
toPem(), &res,
QString(
"qca-ossl" ) ) );
315 if ( res != QCA::ConvertGood || acert.isNull() )
317 QgsDebugMsg(
"Certificate could not be converted to QCA cert" );
329 QgsAuthCertUtils::appendDirSegment_(
330 dirname,
"E", issuer ? acert.issuerInfo().
value( QCA::Email )
331 : acert.subjectInfo().value( QCA::Email ) );
332 QgsAuthCertUtils::appendDirSegment_(
333 dirname,
"CN", issuer ?
SSL_ISSUER_INFO( qcert, QSslCertificate::CommonName )
335 QgsAuthCertUtils::appendDirSegment_(
336 dirname,
"OU", issuer ?
SSL_ISSUER_INFO( qcert, QSslCertificate::OrganizationalUnitName )
338 QgsAuthCertUtils::appendDirSegment_(
339 dirname,
"O", issuer ?
SSL_ISSUER_INFO( qcert, QSslCertificate::Organization )
341 QgsAuthCertUtils::appendDirSegment_(
342 dirname,
"L", issuer ?
SSL_ISSUER_INFO( qcert, QSslCertificate::LocalityName )
344 QgsAuthCertUtils::appendDirSegment_(
345 dirname,
"ST", issuer ?
SSL_ISSUER_INFO( qcert, QSslCertificate::StateOrProvinceName )
347 QgsAuthCertUtils::appendDirSegment_(
348 dirname,
"C", issuer ?
SSL_ISSUER_INFO( qcert, QSslCertificate::CountryName )
351 return dirname.
join(
"," );
375 for (
int i = 0; i < txt.
size(); i += 2 )
377 sl << txt.
mid( i, ( i + 2 > txt.
size() ) ? -1 : 2 );
379 return sl.
join(
":" );
395 return QCA::Certificate();
397 QCA::ConvertResult res;
398 QCA::Certificate qcacert( QCA::Certificate::fromPEM( cert.
toPem(), &res,
QString(
"qca-ossl" ) ) );
399 if ( res != QCA::ConvertGood || qcacert.isNull() )
401 QgsDebugMsg(
"Certificate could not be converted to QCA cert" );
402 qcacert = QCA::Certificate();
409 QCA::CertificateCollection qcacoll;
416 if ( !qcacert.isNull() )
418 qcacoll.addCertificate( qcacert );
426 QCA::SecureArray passarray;
428 passarray = QCA::SecureArray( pass.
toUtf8() );
430 QCA::ConvertResult res;
431 QCA::KeyBundle bundle( QCA::KeyBundle::fromFile( path, passarray, &res,
QString(
"qca-ossl" ) ) );
433 return ( res == QCA::ConvertGood ? bundle : QCA::KeyBundle() );
440 case QCA::ValidityGood:
442 case QCA::ErrorRejected:
443 return QObject::tr(
"Root CA rejected the certificate purpose." );
444 case QCA::ErrorUntrusted:
445 return QObject::tr(
"Certificate is not trusted." );
446 case QCA::ErrorSignatureFailed:
448 case QCA::ErrorInvalidCA:
449 return QObject::tr(
"Certificate Authority is invalid or not found." );
450 case QCA::ErrorInvalidPurpose:
451 return QObject::tr(
"Purpose does not match the intended usage." );
452 case QCA::ErrorSelfSigned:
453 return QObject::tr(
"Certificate is self-signed, and is not found in the list of trusted certificates." );
454 case QCA::ErrorRevoked:
455 return QObject::tr(
"Certificate has been revoked." );
456 case QCA::ErrorPathLengthExceeded:
457 return QObject::tr(
"Path length from the root CA to this certificate is too long." );
458 case QCA::ErrorExpired:
459 return QObject::tr(
"Certificate has expired or is not yet valid." );
460 case QCA::ErrorExpiredCA:
461 return QObject::tr(
"Certificate Authority has expired." );
462 case QCA::ErrorValidityUnknown:
473 case QCA::EMSA1_SHA1:
475 case QCA::EMSA3_SHA1:
481 case QCA::EMSA3_RIPEMD160:
485 #if QCA_VERSION >= 0x020100
486 case QCA::EMSA3_SHA224:
488 case QCA::EMSA3_SHA256:
490 case QCA::EMSA3_SHA384:
492 case QCA::EMSA3_SHA512:
496 return QObject::tr(
"Unknown (possibly Elliptic Curve)" );
502 switch ( constraint )
504 case QCA::DigitalSignature:
506 case QCA::NonRepudiation:
508 case QCA::KeyEncipherment:
510 case QCA::DataEncipherment:
512 case QCA::KeyAgreement:
514 case QCA::KeyCertificateSign:
518 case QCA::EncipherOnly:
520 case QCA::DecipherOnly:
522 case QCA::ServerAuth:
524 case QCA::ClientAuth:
526 case QCA::CodeSigning:
528 case QCA::EmailProtection:
530 case QCA::IPSecEndSystem:
532 case QCA::IPSecTunnel:
536 case QCA::TimeStamping:
538 case QCA::OCSPSigning:
582 QCA::ConvertResult res;
583 QCA::Certificate qcacert( QCA::Certificate::fromPEM( cert.
toPem(), &res,
QString(
"qca-ossl" ) ) );
584 if ( res != QCA::ConvertGood || qcacert.isNull() )
586 QgsDebugMsg(
"Certificate could not be converted to QCA cert" );
590 if ( qcacert.isCA() )
592 QgsDebugMsg(
"Certificate has 'CA:TRUE' basic constraint" );
597 Q_FOREACH (
const QCA::ConstraintType& certconst, certconsts )
599 if ( certconst.known() == QCA::KeyCertificateSign )
601 QgsDebugMsg(
"Certificate has 'Certificate Sign' key usage" );
604 else if ( certconst.known() == QCA::ServerAuth )
606 QgsDebugMsg(
"Certificate has 'server authentication' extended key usage" );
612 QCA::CertificateCollection trustedCAs(
614 QCA::CertificateCollection untrustedCAs(
618 v_any = qcacert.validate( trustedCAs, untrustedCAs, QCA::UsageAny, QCA::ValidateAll );
619 if ( v_any == QCA::ValidityGood )
624 QCA::Validity v_tlsserver;
625 v_tlsserver = qcacert.validate( trustedCAs, untrustedCAs, QCA::UsageTLSServer, QCA::ValidateAll );
626 if ( v_tlsserver == QCA::ValidityGood )
636 QCA::Validity v_tlsclient;
637 v_tlsclient = qcacert.validate( trustedCAs, untrustedCAs, QCA::UsageTLSClient, QCA::ValidateAll );
639 if ( v_tlsclient == QCA::ValidityGood )
682 QCA::ConvertResult res;
683 QCA::Certificate qcacert( QCA::Certificate::fromPEM( cert.
toPem(), &res,
QString(
"qca-ossl" ) ) );
684 if ( res != QCA::ConvertGood || qcacert.isNull() )
686 QgsDebugMsg(
"Certificate could not be converted to QCA cert" );
690 if ( qcacert.isCA() )
692 QgsDebugMsg(
"SSL server certificate has 'CA:TRUE' basic constraint (and should not)" );
697 Q_FOREACH ( QCA::ConstraintType certconst, certconsts )
699 if ( certconst.known() == QCA::KeyCertificateSign )
701 QgsDebugMsg(
"SSL server certificate has 'Certificate Sign' key usage (and should not)" );
708 bool serverauth =
false;
709 bool dsignature =
false;
710 bool keyencrypt =
false;
711 Q_FOREACH ( QCA::ConstraintType certconst, certconsts )
713 if ( certconst.known() == QCA::DigitalSignature )
715 QgsDebugMsg(
"SSL server certificate has 'digital signature' key usage" );
718 else if ( certconst.known() == QCA::KeyEncipherment )
720 QgsDebugMsg(
"SSL server certificate has 'key encipherment' key usage" );
723 else if ( certconst.known() == QCA::KeyAgreement )
725 QgsDebugMsg(
"SSL server certificate has 'key agreement' key usage" );
728 else if ( certconst.known() == QCA::ServerAuth )
730 QgsDebugMsg(
"SSL server certificate has 'server authentication' extended key usage" );
742 if ( serverauth && dsignature && keyencrypt )
746 if ( dsignature && keyencrypt )
752 bool keyagree =
false;
753 bool encipheronly =
false;
754 bool decipheronly =
false;
756 QCA::PublicKey pubkey( qcacert.subjectPublicKey() );
758 if ( pubkey.bitSize() > 0 && pubkey.isDH() )
760 keyagree = pubkey.canKeyAgree();
765 Q_FOREACH ( QCA::ConstraintType certconst, certconsts )
767 if ( certconst.known() == QCA::EncipherOnly )
769 QgsDebugMsg(
"SSL server public key has 'encipher only' key usage" );
772 else if ( certconst.known() == QCA::DecipherOnly )
774 QgsDebugMsg(
"SSL server public key has 'decipher only' key usage" );
778 if ( !encipheronly && !decipheronly )
796 case QSslError::UnableToGetIssuerCertificate:
797 return QObject::tr(
"Unable To Get Issuer Certificate" );
798 case QSslError::UnableToDecryptCertificateSignature:
799 return QObject::tr(
"Unable To Decrypt Certificate Signature" );
800 case QSslError::UnableToDecodeIssuerPublicKey:
801 return QObject::tr(
"Unable To Decode Issuer Public Key" );
802 case QSslError::CertificateSignatureFailed:
803 return QObject::tr(
"Certificate Signature Failed" );
804 case QSslError::CertificateNotYetValid:
806 case QSslError::CertificateExpired:
808 case QSslError::InvalidNotBeforeField:
810 case QSslError::InvalidNotAfterField:
812 case QSslError::SelfSignedCertificate:
814 case QSslError::SelfSignedCertificateInChain:
815 return QObject::tr(
"Self-signed Certificate In Chain" );
816 case QSslError::UnableToGetLocalIssuerCertificate:
817 return QObject::tr(
"Unable To Get Local Issuer Certificate" );
818 case QSslError::UnableToVerifyFirstCertificate:
819 return QObject::tr(
"Unable To Verify First Certificate" );
820 case QSslError::CertificateRevoked:
822 case QSslError::InvalidCaCertificate:
824 case QSslError::PathLengthExceeded:
826 case QSslError::InvalidPurpose:
828 case QSslError::CertificateUntrusted:
830 case QSslError::CertificateRejected:
832 case QSslError::SubjectIssuerMismatch:
834 case QSslError::AuthorityIssuerSerialNumberMismatch:
835 return QObject::tr(
"Authority Issuer Serial Number Mismatch" );
836 case QSslError::NoPeerCertificate:
838 case QSslError::HostNameMismatch:
840 case QSslError::UnspecifiedError:
842 case QSslError::CertificateBlacklisted:
844 case QSslError::NoError:
846 case QSslError::NoSslSupport:
856 errenums << qMakePair( QSslError::UnableToGetIssuerCertificate,
858 errenums << qMakePair( QSslError::UnableToDecryptCertificateSignature,
860 errenums << qMakePair( QSslError::UnableToDecodeIssuerPublicKey,
862 errenums << qMakePair( QSslError::CertificateSignatureFailed,
864 errenums << qMakePair( QSslError::CertificateNotYetValid,
866 errenums << qMakePair( QSslError::CertificateExpired,
868 errenums << qMakePair( QSslError::InvalidNotBeforeField,
870 errenums << qMakePair( QSslError::InvalidNotAfterField,
872 errenums << qMakePair( QSslError::SelfSignedCertificate,
874 errenums << qMakePair( QSslError::SelfSignedCertificateInChain,
876 errenums << qMakePair( QSslError::UnableToGetLocalIssuerCertificate,
878 errenums << qMakePair( QSslError::UnableToVerifyFirstCertificate,
880 errenums << qMakePair( QSslError::CertificateRevoked,
882 errenums << qMakePair( QSslError::InvalidCaCertificate,
884 errenums << qMakePair( QSslError::PathLengthExceeded,
886 errenums << qMakePair( QSslError::InvalidPurpose,
888 errenums << qMakePair( QSslError::CertificateUntrusted,
890 errenums << qMakePair( QSslError::CertificateRejected,
892 errenums << qMakePair( QSslError::SubjectIssuerMismatch,
894 errenums << qMakePair( QSslError::AuthorityIssuerSerialNumberMismatch,
896 errenums << qMakePair( QSslError::NoPeerCertificate,
898 errenums << qMakePair( QSslError::HostNameMismatch,
900 errenums << qMakePair( QSslError::UnspecifiedError,
902 errenums << qMakePair( QSslError::CertificateBlacklisted,
static QString certificateUsageTypeString(QgsAuthCertUtils::CertUsageType usagetype)
Certificate usage type strings per enum.
bool contains(const Key &key) const
static QMap< QString, QgsAuthConfigSslServer > mapDigestToSslConfigs(const QList< QgsAuthConfigSslServer > &configs)
Map SSL custom configs' certificate sha1 to custom config as simple cache.
static QgsAuthManager * instance()
Enforce singleton pattern.
static bool certificateIsIssuer(const QSslCertificate &cert)
Get whether a certificate can sign other certificates.
static QString qcaKnownConstraint(QCA::ConstraintTypeKnown constraint)
Certificate well-known constraint strings per enum.
CertTrustPolicy
Type of certificate trust policy.
static QString sslErrorEnumString(QSslError::SslError errenum)
Get short strings describing an SSL error.
static QList< QSslCertificate > certsFromFile(const QString &certspath)
Return list of concatenated certs from a PEM or DER formatted file.
static QMap< QString, QSslCertificate > mapDigestToCerts(const QList< QSslCertificate > &certs)
Map certificate sha1 to certificate as simple cache.
Configuration container for SSL server connection exceptions or overrides.
static bool certificateIsAuthorityOrIssuer(const QSslCertificate &cert)
Get whether a certificate is an Authority or can at least sign other certificates.
static QCA::CertificateCollection qtCertsToQcaCollection(const QList< QSslCertificate > &certs)
Convert a QList of QSslCertificate to a QCA::CertificateCollection.
QString join(const QString &separator) const
static QCA::Certificate qtCertToQcaCert(const QSslCertificate &cert)
Convert a QSslCertificate to a QCA::Certificate.
static QList< QgsAuthCertUtils::CertUsageType > certificateUsageTypes(const QSslCertificate &cert)
Try to determine the certificates usage types.
QString tr(const char *sourceText, const char *disambiguation, int n)
static QByteArray fileData_(const QString &path, bool astext=false)
CertUsageType
Type of certificate usage.
static QStringList pkcs12BundleToPem(const QString &bundlepath, const QString &bundlepass=QString(), bool reencrypt=true)
Return list of certificate, private key and algorithm (as PEM text) for a PKCS#12 bundle...
static bool certificateIsAuthority(const QSslCertificate &cert)
Get whether a certificate is an Authority.
void append(const T &value)
static QStringList certKeyBundleToPem(const QString &certpath, const QString &keypath, const QString &keypass=QString(), bool reencrypt=true)
Return list of certificate, private key and algorithm (as PEM text) from file path components...
CaCertSource
Type of CA certificate source.
static QString getCertDistinguishedName(const QSslCertificate &qcert, const QCA::Certificate &acert=QCA::Certificate(), bool issuer=false)
Get combined distinguished name for certificate.
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
static QMap< QString, QList< QgsAuthConfigSslServer > > sslConfigsGroupedByOrg(const QList< QgsAuthConfigSslServer > &configs)
Map SSL custom configs' certificates to their oraganization.
const QSslCertificate sslCertificate() const
Server certificate object.
QList< QSslCertificate > fromData(const QByteArray &data, QSsl::EncodingFormat format)
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
static bool certificateIsSslServer(const QSslCertificate &cert)
Get whether a certificate is probably used for a SSL server.
static QList< QSslCertificate > certsFromString(const QString &pemtext)
Return list of concatenated certs from a PEM Base64 text block.
static QString getSslProtocolName(QSsl::SslProtocol protocol)
SSL Protocol name strings per enum.
bool contains(const T &value) const
QByteArray digest(QCryptographicHash::Algorithm algorithm) const
static bool certificateIsSslClient(const QSslCertificate &cert)
Get whether a certificate is probably used for a client identity.
static QString shaHexForCert(const QSslCertificate &cert, bool formatted=false)
Get the sha1 hash for certificate.
QString & replace(int position, int n, QChar after)
QString mid(int position, int n) const
#define SSL_SUBJECT_INFO(var, prop)
static QString qcaSignatureAlgorithm(QCA::SignatureAlgorithm algorithm)
Certificate signature algorithm strings per enum.
static QSslKey keyFromFile(const QString &keypath, const QString &keypass=QString(), QString *algtype=0)
Return non-encrypted key from a PEM or DER formatted file.
QByteArray toPem(const QByteArray &passPhrase) const
static QMap< QString, QList< QSslCertificate > > certsGroupedByOrg(const QList< QSslCertificate > &certs)
Map certificates to their oraganization.
iterator insert(const Key &key, const T &value)
static QString getColonDelimited(const QString &txt)
Get string with colon delimeters every 2 characters.
static QCA::KeyBundle qcaKeyBundle(const QString &path, const QString &pass)
PKI key/cert bundle from file path, e.g.
static QList< QPair< QSslError::SslError, QString > > sslErrorEnumStrings()
Get short strings describing SSL errors.
static QString getCertTrustName(QgsAuthCertUtils::CertTrustPolicy trust)
Get the general name for certificate trust.
static QSslCertificate certFromFile(const QString &certpath)
Return first cert from a PEM or DER formatted file.
#define SSL_ISSUER_INFO(var, prop)
static QString getCaSourceName(QgsAuthCertUtils::CaCertSource source, bool single=false)
Get the general name for CA source enum type.
static QString resolvedCertName(const QSslCertificate &cert, bool issuer=false)
Get the general name via RFC 5280 resolution.
QByteArray toAscii() const
static QString qcaValidityMessage(QCA::Validity validity)
Certificate validity check messages per enum.
const T value(const Key &key) const
QByteArray toUtf8() const