10#include <QtNetwork/private/qsslcertificate_p.h>
12#include <QtNetwork/qsslsocket.h>
13#include <QtNetwork/qhostaddress.h>
15#include <QtCore/qendian.h>
16#include <QtCore/qdatetime.h>
17#include <QtCore/qhash.h>
18#include <QtCore/qiodevice.h>
19#include <QtCore/qscopeguard.h>
20#include <QtCore/qtimezone.h>
21#include <QtCore/qvarlengtharray.h>
51 return asn1ObjectId(
object);
64 unsigned char *
data =
nullptr;
73QDateTime dateTimeFromASN1(
const ASN1_TIME *aTime)
79 QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
80 QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
88#define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
89#define ENDCERTSTRING "-----END CERTIFICATE-----"
106 char **dataP = &
data;
107 unsigned char **dataPu = (
unsigned char **)dataP;
117 for (
int i = 0;
i <=
array.size() - 64;
i += 64) {
121 if (
int remainder =
array.size() % 64) {
149QVariant x509UnknownExtensionToValue(X509_EXTENSION *
ext)
170 const auto extCleaner =
qScopeGuard([meth, ext_internal]{
174 q_ASN1_item_free(
static_cast<ASN1_VALUE *
>(ext_internal), ASN1_ITEM_ptr(meth->it));
175 else if (meth->ext_free)
176 meth->ext_free(ext_internal);
178 qCWarning(lcTlsBackend,
"No method to free an unknown extension, a potential memory leak?");
183 STACK_OF(CONF_VALUE) *
val = meth->i2v(meth, ext_internal,
nullptr);
195 if (nval->name && nval->value) {
198 }
else if (nval->name) {
200 }
else if (nval->value) {
209 }
else if (meth->i2s) {
210 const char *hexString = meth->i2s(meth, ext_internal);
214 }
else if (meth->i2r) {
221 meth->i2r(meth, ext_internal, bio, 0);
249 void *ext_internal =
nullptr;
250 const auto extCleaner =
qScopeGuard([meth, &ext_internal]() {
251 if (!meth || !ext_internal)
255 q_ASN1_item_free(
static_cast<ASN1_VALUE *
>(ext_internal), ASN1_ITEM_ptr(meth->it));
256 else if (meth->ext_free)
257 meth->ext_free(ext_internal);
259 qWarning(lcTlsBackend,
"Cannot free an extension, a potential memory leak?");
262 const char * hexString =
nullptr;
263 const auto hexStringCleaner =
qScopeGuard([&hexString](){
269 case NID_basic_constraints:
275 result[
"ca"_L1] = basic->ca ? true :
false;
283 case NID_info_access:
292 GENERAL_NAME *
name = ad->location;
293 if (
name->type == GEN_URI) {
295 if (len < 0 || len >= 8192) {
305 qCWarning(lcTlsBackend) <<
"Strange location type" <<
name->type;
313 case NID_subject_key_identifier:
319 hexString = meth->i2s(meth, ext_internal);
323 case NID_authority_key_identifier:
331 if (auth_key->keyid) {
332 QByteArray keyid(
reinterpret_cast<const char *
>(auth_key->keyid->data),
333 auth_key->keyid->length);
334 result[
"keyid"_L1] = keyid.toHex();
341 if (auth_key->serial)
360 ErrorListPtr errors =
nullptr;
385 qCWarning(lcTlsBackend,
"Neither X509_STORE, nor SSL contains error list, verification failed");
409 if (x509 &&
other.x509) {
411 if (
ret >= -1 &&
ret <= 1)
440 auto altName = [](ASN1_IA5STRING *ia5,
int len) {
447 if (genName->type != GEN_DNS && genName->type != GEN_EMAIL && genName->type != GEN_IPADD)
451 if (len < 0 || len >= 8192) {
456 switch (genName->type) {
502 return x509ToQByteArray(x509,
QSsl::Pem);
510 return x509ToQByteArray(x509,
QSsl::Der);
518 return x509ToText(x509);
530 unsigned int len = 0;
531 unsigned char md[EVP_MAX_MD_SIZE];
543 auto *backend = QTlsBackend::backend<X509CertificateOpenSSL>(certificate);
544 if (!backend || !x509)
549 backend->notValidBefore = dateTimeFromASN1(nbef);
553 backend->notValidAfter = dateTimeFromASN1(naft);
555 backend->null =
false;
570 backend->serialNumberString = hexString;
573 backend->parseExtensions();
612 return verify(roots, chain, hostName);
620 if (certificateChain.
size() <= 0)
626 qCWarning(lcTlsBackend) <<
"Unable to create certificate store";
645 if (caCertificate.expiryDate() >=
now) {
652 qCWarning(lcTlsBackend) <<
"Unable to attach external data (error list) to a store";
661 STACK_OF(X509) *intermediates =
nullptr;
662 if (certificateChain.
size() > 1) {
665 if (!intermediates) {
702 if (certificateChain[0].isBlacklisted())
706 if (!hostName.
isEmpty() && !TlsCryptograph::isMatchingHostname(certificateChain[0], hostName)) {
714 for (
const auto &
error : std::as_const(lastErrors))
743 const unsigned char *
data = (
const unsigned char *)decoded.
data();
758 const unsigned char *
data = (
const unsigned char *)der.
data();
785 if (pkcs12data.
size() == 0)
790 qCWarning(lcTlsBackend,
"BIO_new_mem_buf returned null");
798 qCWarning(lcTlsBackend,
"Unable to read PKCS#12 structure, %s",
805 EVP_PKEY *pkey =
nullptr;
806 X509 *x509 =
nullptr;
810 qCWarning(lcTlsBackend,
"Unable to parse PKCS#12 structure, %s",
823 auto *tlsKey = QTlsBackend::backend<TlsKeyOpenSSL>(*
key);
824 if (!tlsKey || !tlsKey->fromEVP_PKEY(pkey)) {
825 qCWarning(lcTlsBackend,
"Unable to convert private key");
844 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
846 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
848 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
850 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
852 case X509_V_ERR_CERT_NOT_YET_VALID:
854 case X509_V_ERR_CERT_HAS_EXPIRED:
856 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
858 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
860 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
862 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
864 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
866 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
868 case X509_V_ERR_CERT_REVOKED:
870 case X509_V_ERR_INVALID_CA:
872 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
874 case X509_V_ERR_INVALID_PURPOSE:
876 case X509_V_ERR_CERT_UNTRUSTED:
878 case X509_V_ERR_CERT_REJECTED:
886void X509CertificateOpenSSL::parseExtensions()
902 qCWarning(lcTlsBackend) <<
"Invalid (nullptr) extension at index" <<
i;
913X509CertificateBase::X509CertificateExtension X509CertificateOpenSSL::convertExtension(X509_EXTENSION *
ext)
917 X509CertificateExtension
result;
929 QVariant extensionValue = x509ExtensionToValue(
ext);
930 if (extensionValue.
isValid()) {
931 result.value = extensionValue;
936 extensionValue = x509UnknownExtensionToValue(
ext);
938 result.value = extensionValue;
IOBluetoothDevice * device
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
qsizetype indexOf(char c, qsizetype from=0) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void chop(qsizetype n)
Removes n bytes from the end of the byte array.
qsizetype length() const noexcept
Same as size().
static QByteArray fromBase64(const QByteArray &base64, Base64Options options=Base64Encoding)
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QByteArray rightJustified(qsizetype width, char fill=' ', bool truncate=false) const
Returns a byte array of size width that contains the fill byte followed by this byte array.
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
\inmodule QtCore\reentrant
static QDateTime currentDateTimeUtc()
\inmodule QtCore \reentrant
The QHostAddress class provides an IP address.
bool isNull() const
Returns true if this host address is not valid for any host or interface.
QString toString() const
Returns the address as a string.
\inmodule QtCore \reentrant
qsizetype size() const noexcept
T value(qsizetype i) const
void reserve(qsizetype size)
void append(parameter_type t)
The QSslCertificate class provides a convenient API for an X509 certificate.
QList< QSslCertificate > caCertificates() const
Returns this connection's CA certificate database.
static QSslConfiguration defaultConfiguration()
Returns the default SSL configuration to be used in new SSL connections.
The QSslError class provides an SSL error.
@ UnableToVerifyFirstCertificate
@ UnableToDecodeIssuerPublicKey
@ UnableToDecryptCertificateSignature
@ UnableToGetLocalIssuerCertificate
@ UnableToGetIssuerCertificate
@ SelfSignedCertificateInChain
@ CertificateSignatureFailed
The QSslKey class provides an interface for private and public keys.
static bool rootCertOnDemandLoadingSupported()
static QList< QSslCertificate > systemCaCertificates()
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
\inmodule QtCore \reentrant
static void logAndClearErrorQueue()
static void clearErrorQueue()
static int s_indexForSSLExtraData
static TlsKeyOpenSSL * publicKeyFromX509(X509 *x)
TlsKey is an abstract class, that allows a TLS plugin to provide an underlying implementation for the...
QList< X509CertificateExtension > extensions
QByteArray serialNumber() const override
static bool matchLineFeed(const QByteArray &pem, int *offset)
static QSslErrorEntry errorEntryFromStoreContext(X509_STORE_CTX *ctx)
static QSslCertificate certificateFromX509(X509 *x)
QByteArray toPem() const override
static bool importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert, QList< QSslCertificate > *caCertificates, const QByteArray &passPhrase)
static QList< QSslCertificate > certificatesFromDer(const QByteArray &der, int count)
QByteArray toDer() const override
QString toText() const override
static QSslError openSSLErrorToQSslError(int errorCode, const QSslCertificate &cert)
static QList< QSslCertificate > certificatesFromPem(const QByteArray &pem, int count)
bool isSelfSigned() const override
TlsKey * publicKey() const override
size_t hash(size_t seed) const noexcept override
~X509CertificateOpenSSL()
bool isEqual(const X509Certificate &rhs) const override
Qt::HANDLE handle() const override
static QList< QSslError > verify(const QList< QSslCertificate > &chain, const QString &hostName)
static QList< QSslCertificate > stackOfX509ToQSslCertificates(STACK_OF(X509) *x509)
QMultiMap< QSsl::AlternativeNameEntryType, QString > subjectAlternativeNames() const override
X509Certificate is an abstract class that allows a TLS backend to provide an implementation of the QS...
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
QMap< QString, QString > map
[6]
EncodingFormat
Describes supported encoding formats for certificates and keys.
Combined button and popup list for selecting options.
Namespace containing onternal types that TLS backends implement.
int qt_X509Callback(int ok, X509_STORE_CTX *ctx)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
constexpr T qFromBigEndian(T source)
size_t qHashBits(const void *p, size_t size, size_t seed) noexcept
#define qCWarning(category,...)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
X509_STORE_CTX * q_X509_STORE_CTX_new()
int q_OBJ_obj2nid(const ASN1_OBJECT *a)
int q_ASN1_STRING_length(ASN1_STRING *a)
void * q_X509_STORE_get_ex_data(X509_STORE *r, int idx)
OPENSSL_STACK * q_OPENSSL_sk_new_null()
int q_SSL_get_ex_data_X509_STORE_CTX_idx()
const char * q_OBJ_nid2sn(int a)
int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
int q_X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain)
void q_BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a)
unsigned long q_ERR_get_error()
int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len)
#define q_sk_GENERAL_NAME_value(st, i)
const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x)
void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data)
#define q_sk_X509_num(st)
const EVP_MD * q_EVP_sha1()
X509 * q_X509_dup(X509 *a)
PKCS12 * q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12)
int q_X509_EXTENSION_get_critical(X509_EXTENSION *a)
X509_NAME * q_X509_get_issuer_name(X509 *a)
#define q_BIO_get_mem_data(b, pp)
void * q_X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb)
int q_X509_cmp(X509 *a, X509 *b)
void q_X509V3_conf_free(CONF_VALUE *val)
void * q_X509V3_EXT_d2i(X509_EXTENSION *a)
STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx)
void q_OPENSSL_sk_free(OPENSSL_STACK *a)
void q_CRYPTO_free(void *str, const char *file, int line)
void q_EVP_PKEY_free(EVP_PKEY *a)
void q_AUTHORITY_KEYID_free(AUTHORITY_KEYID *a)
void q_X509_STORE_free(X509_STORE *store)
ASN1_STRING * q_X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *a)
BIO * q_BIO_new(const BIO_METHOD *a)
long q_X509_get_version(X509 *a)
int q_i2d_X509(X509 *a, unsigned char **b)
ASN1_TIME * q_X509_getm_notAfter(X509 *a)
X509_STORE * q_X509_STORE_new()
ASN1_OBJECT * q_X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *a)
void q_PKCS12_free(PKCS12 *pkcs12)
void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void(*b)(void *))
void * q_SSL_get_ex_data(const SSL *ssl, int idx)
void q_AUTHORITY_INFO_ACCESS_free(AUTHORITY_INFO_ACCESS *a)
ASN1_INTEGER * q_X509_get_serialNumber(X509 *a)
void q_ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
long q_ASN1_INTEGER_get(ASN1_INTEGER *a)
int q_X509_check_issued(X509 *a, X509 *b)
const BIO_METHOD * q_BIO_s_mem()
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b)
int q_BIO_read(BIO *a, void *b, int c)
char * q_ERR_error_string(unsigned long a, char *b)
ASN1_OCTET_STRING * q_X509_EXTENSION_get_data(X509_EXTENSION *a)
int q_OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *obj, int no_name)
X509_NAME_ENTRY * q_X509_NAME_get_entry(X509_NAME *a, int b)
void q_X509_print(BIO *a, X509 *b)
void q_X509_free(X509 *a)
X509_NAME * q_X509_get_subject_name(X509 *a)
int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
void * q_X509_get_ext_d2i(X509 *a, int b, int *c, int *d)
void q_X509_STORE_CTX_free(X509_STORE_CTX *storeCtx)
const X509V3_EXT_METHOD * q_X509V3_EXT_get(X509_EXTENSION *a)
int q_X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
BIO * q_BIO_new_mem_buf(void *a, int b)
#define q_sk_X509_value(st, i)
int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data)
int q_X509_get_ext_count(X509 *a)
void q_GENERAL_NAME_free(GENERAL_NAME *a)
int q_X509_verify_cert(X509_STORE_CTX *ctx)
X509_STORE * q_X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
X509 * q_d2i_X509(X509 **a, const unsigned char **b, long c)
X509_EXTENSION * q_X509_get_ext(X509 *a, int b)
int q_ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
int q_X509_NAME_entry_count(X509_NAME *a)
#define q_SKM_sk_value(type, st, i)
ASN1_OBJECT * q_X509_EXTENSION_get_object(X509_EXTENSION *a)
#define q_OPENSSL_free(addr)
ASN1_TIME * q_X509_getm_notBefore(X509 *a)
#define q_sk_GENERAL_NAME_num(st)
int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
QFileInfo info(fileName)
[8]
QList< QSslCertificate > cert
[0]