diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qnetworkreply.cpp | 5 | ||||
-rw-r--r-- | src/network/access/qnetworkreply.h | 6 | ||||
-rw-r--r-- | src/network/configure.json | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate_openssl.cpp | 27 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate_qt.cpp | 4 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 23 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl11_symbols_p.h | 7 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_symbols.cpp | 34 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_opensslpre11_symbols_p.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_p.h | 1 |
11 files changed, 93 insertions, 20 deletions
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index aca9cb1c08..fb30bfd4f1 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -687,7 +687,7 @@ QVariant QNetworkReply::attribute(QNetworkRequest::Attribute code) const return d_func()->attributes.value(code); } -#ifndef QT_NO_SSL +#if QT_CONFIG(ssl) /*! Returns the SSL configuration and state associated with this reply, if SSL was used. It will contain the remote server's @@ -742,7 +742,6 @@ void QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors) { ignoreSslErrorsImplementation(errors); } -#endif /*! \fn void QNetworkReply::sslConfigurationImplementation(QSslConfiguration &configuration) const @@ -786,6 +785,8 @@ void QNetworkReply::ignoreSslErrorsImplementation(const QList<QSslError> &) { } +#endif // QT_CONFIG(ssl) + /*! If this function is called, SSL errors related to network connection will be ignored, including certificate validation diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 63c2752caf..4a402daa91 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -143,7 +143,7 @@ public: // attributes QVariant attribute(QNetworkRequest::Attribute code) const; -#ifndef QT_NO_SSL +#if QT_CONFIG(ssl) QSslConfiguration sslConfiguration() const; void setSslConfiguration(const QSslConfiguration &configuration); void ignoreSslErrors(const QList<QSslError> &errors); @@ -157,7 +157,7 @@ Q_SIGNALS: void metaDataChanged(); void finished(); void error(QNetworkReply::NetworkError); -#ifndef QT_NO_SSL +#if QT_CONFIG(ssl) void encrypted(); void sslErrors(const QList<QSslError> &errors); void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator); @@ -182,9 +182,11 @@ protected: void setRawHeader(const QByteArray &headerName, const QByteArray &value); void setAttribute(QNetworkRequest::Attribute code, const QVariant &value); +#if QT_CONFIG(ssl) virtual void sslConfigurationImplementation(QSslConfiguration &) const; virtual void setSslConfigurationImplementation(const QSslConfiguration &); virtual void ignoreSslErrorsImplementation(const QList<QSslError> &); +#endif private: Q_DECLARE_PRIVATE(QNetworkReply) diff --git a/src/network/configure.json b/src/network/configure.json index 47a4ec12f2..dd3b5c295c 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -212,7 +212,7 @@ }, "linux-netlink": { "label": "Linux AF_NETLINK", - "condition": "config.linux && tests.linux-netlink", + "condition": "config.linux && !config.android && tests.linux-netlink", "output": [ "privateFeature" ] }, "openssl": { diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp index fa87cfeaaf..baf3e4accf 100644 --- a/src/network/ssl/qsslcertificate_openssl.cpp +++ b/src/network/ssl/qsslcertificate_openssl.cpp @@ -294,9 +294,12 @@ static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) // we cast away the const-ness here because some versions of openssl // don't use const for the parameters in the functions pointers stored // in the object. + Q_ASSERT(ext); + X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext)); if (!meth) { ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext); + Q_ASSERT(value); QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(value)), q_ASN1_STRING_length(value)); return result; @@ -330,7 +333,6 @@ static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) else return list; } else if (meth->i2s && ext_internal) { - //qCDebug(lcSsl) << meth->i2s(meth, ext_internal); QVariant result(QString::fromUtf8(meth->i2s(meth, ext_internal))); return result; } else if (meth->i2r && ext_internal) { @@ -367,6 +369,8 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext) case NID_basic_constraints: { BASIC_CONSTRAINTS *basic = reinterpret_cast<BASIC_CONSTRAINTS *>(q_X509V3_EXT_d2i(ext)); + if (!basic) + return QVariant(); QVariantMap result; result[QLatin1String("ca")] = basic->ca ? true : false; @@ -380,6 +384,8 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext) case NID_info_access: { AUTHORITY_INFO_ACCESS *info = reinterpret_cast<AUTHORITY_INFO_ACCESS *>(q_X509V3_EXT_d2i(ext)); + if (!info) + return QVariant(); QVariantMap result; for (int i=0; i < q_SKM_sk_num(ACCESS_DESCRIPTION, info); i++) { @@ -409,7 +415,8 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext) case NID_subject_key_identifier: { void *ext_internal = q_X509V3_EXT_d2i(ext); - + if (!ext_internal) + return QVariant(); // we cast away the const-ness here because some versions of openssl // don't use const for the parameters in the functions pointers stored // in the object. @@ -421,6 +428,8 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext) case NID_authority_key_identifier: { AUTHORITY_KEYID *auth_key = reinterpret_cast<AUTHORITY_KEYID *>(q_X509V3_EXT_d2i(ext)); + if (!auth_key) + return QVariant(); QVariantMap result; @@ -449,9 +458,16 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext) QSslCertificateExtension QSslCertificatePrivate::convertExtension(X509_EXTENSION *ext) { + Q_ASSERT(ext); + QSslCertificateExtension result; ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext); + if (!obj) { + qCWarning(lcSsl, "Invalid (nullptr) ASN1_OBJECT"); + return result; + } + QByteArray oid = QSslCertificatePrivate::asn1ObjectId(obj); QByteArray name = QSslCertificatePrivate::asn1ObjectName(obj); @@ -488,10 +504,17 @@ QList<QSslCertificateExtension> QSslCertificate::extensions() const return result; int count = q_X509_get_ext_count(d->x509); + if (count <= 0) + return result; + result.reserve(count); for (int i = 0; i < count; i++) { X509_EXTENSION *ext = q_X509_get_ext(d->x509, i); + if (!ext) { + qCWarning(lcSsl) << "Invalid (nullptr) extension at index" << i; + continue; + } result << QSslCertificatePrivate::convertExtension(ext); } diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp index dfdfd529e5..66c54bfab9 100644 --- a/src/network/ssl/qsslcertificate_qt.cpp +++ b/src/network/ssl/qsslcertificate_qt.cpp @@ -305,7 +305,9 @@ bool QSslCertificatePrivate::parse(const QByteArray &data) if (elem.type() == QAsn1Element::Context0Type) { QDataStream versionStream(elem.value()); - if (!elem.read(versionStream) || elem.type() != QAsn1Element::IntegerType) + if (!elem.read(versionStream) + || elem.type() != QAsn1Element::IntegerType + || elem.value().isEmpty()) return false; versionString = QByteArray::number(elem.value().at(0) + 1); diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 4f49a71e8a..9f9eaf3d36 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2108,7 +2108,7 @@ void QSslSocketPrivate::init() shutdown = false; pendingClose = false; flushTriggered = false; - + systemOrSslErrorDetected = false; // we don't want to clear the ignoreErrorsList, so // that it is possible setting it before connecting // ignoreErrorsList.clear(); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index ec772ddb45..c4abc1eef0 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -471,10 +471,16 @@ bool QSslSocketBackendPrivate::initSslContext() void QSslSocketBackendPrivate::destroySslContext() { if (ssl) { - // We do not send a shutdown alert here. Just mark the session as - // resumable for qhttpnetworkconnection's "optimization", otherwise - // OpenSSL won't start a session resumption. - q_SSL_shutdown(ssl); + if (!q_SSL_in_init(ssl) && !systemOrSslErrorDetected) { + // We do not send a shutdown alert here. Just mark the session as + // resumable for qhttpnetworkconnection's "optimization", otherwise + // OpenSSL won't start a session resumption. + if (q_SSL_shutdown(ssl) != 1) { + // Some error may be queued, clear it. + const auto errors = getErrorsFromOpenSsl(); + Q_UNUSED(errors); + } + } q_SSL_free(ssl); ssl = nullptr; } @@ -909,6 +915,7 @@ void QSslSocketBackendPrivate::transmit() case SSL_ERROR_SSL: // error in the SSL library // we do not know exactly what the error is, nor whether we can recover from it, // so just return to prevent an endless loop in the outer "while" statement + systemOrSslErrorDetected = true; { const ScopedBool bg(inSetAndEmitError, true); setErrorAndEmit(QAbstractSocket::SslInternalError, @@ -1309,8 +1316,12 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi void QSslSocketBackendPrivate::disconnectFromHost() { if (ssl) { - if (!shutdown) { - q_SSL_shutdown(ssl); + if (!shutdown && !q_SSL_in_init(ssl) && !systemOrSslErrorDetected) { + if (q_SSL_shutdown(ssl) != 1) { + // Some error may be queued, clear it. + const auto errors = getErrorsFromOpenSsl(); + Q_UNUSED(errors); + } shutdown = true; transmit(); } diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h index 0c32b0a934..c80baa20aa 100644 --- a/src/network/ssl/qsslsocket_openssl11_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h @@ -186,4 +186,11 @@ typedef int (*q_SSL_psk_use_session_cb_func_t)(SSL *, const EVP_MD *, const unsi } void q_SSL_set_psk_use_session_callback(SSL *s, q_SSL_psk_use_session_cb_func_t); +#if OPENSSL_VERSION_NUMBER < 0x10101000L +// What a mess! +int q_SSL_in_init(SSL *s); +#else +int q_SSL_in_init(const SSL *s); +#endif // 1.1.1 or 1.1.0 + #endif diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index c303e266ba..60ba3a0958 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -161,6 +161,11 @@ DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return) DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return) DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return) +#if OPENSSL_VERSION_NUMBER < 0x10101000L +DEFINEFUNC(int, SSL_in_init, SSL *a, a, return 0, return) +#else +DEFINEFUNC(int, SSL_in_init, const SSL *a, a, return 0, return) +#endif #ifdef TLS1_3_VERSION DEFINEFUNC2(int, SSL_CTX_set_ciphersuites, SSL_CTX *ctx, ctx, const char *str, str, return 0, return) DEFINEFUNC2(void, SSL_set_psk_use_session_callback, SSL *ssl, ssl, q_SSL_psk_use_session_cb_func_t callback, callback, return, DUMMYARG) @@ -213,6 +218,7 @@ DEFINEFUNC2(void, BIO_set_shutdown, BIO *a, a, int shut, shut, return, DUMMYARG) // Functions below are either deprecated or removed in OpenSSL >= 1.1: DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return nullptr, return) +DEFINEFUNC(int, SSL_state, const SSL *a, a, return 0, return) #ifdef SSLEAY_MACROS DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return nullptr, return) @@ -988,6 +994,7 @@ bool q_resolveOpenSslSymbols() #if QT_CONFIG(opensslv11) RESOLVEFUNC(OPENSSL_init_ssl) + RESOLVEFUNC(SSL_in_init) RESOLVEFUNC(OPENSSL_init_crypto) RESOLVEFUNC(ASN1_STRING_get0_data) RESOLVEFUNC(EVP_CIPHER_CTX_reset) @@ -1060,6 +1067,7 @@ bool q_resolveOpenSslSymbols() #else // !opensslv11 RESOLVEFUNC(ASN1_STRING_data) + RESOLVEFUNC(SSL_state) #ifdef SSLEAY_MACROS RESOLVEFUNC(ASN1_dup) @@ -1367,12 +1375,12 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_select_next_proto) RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb) RESOLVEFUNC(SSL_get0_next_proto_negotiated) -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... #if OPENSSL_VERSION_NUMBER >= 0x10002000L - RESOLVEFUNC(SSL_set_alpn_protos) - RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) - RESOLVEFUNC(SSL_get0_alpn_selected) + RESOLVEFUNC(SSL_set_alpn_protos) + RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) + RESOLVEFUNC(SSL_get0_alpn_selected) #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... +#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... #if QT_CONFIG(dtls) RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb) RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb) @@ -1421,6 +1429,9 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) { size_t lTimeLength = aTime->length; char *pString = (char *) aTime->data; + auto isValidPointer = [pString, lTimeLength](const char *const probe){ + return size_t(probe - pString) < lTimeLength; + }; if (aTime->type == V_ASN1_UTCTIME) { @@ -1439,12 +1450,21 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) *pBuffer++ = '0'; } else { *pBuffer++ = *pString++; + if (!isValidPointer(pString)) // Nah. + return {}; *pBuffer++ = *pString++; + if (!isValidPointer(pString)) // Nah. + return {}; // Skip any fractional seconds... if (*pString == '.') { pString++; - while ((*pString >= '0') && (*pString <= '9')) + if (!isValidPointer(pString)) // Oh no, cannot dereference (see below). + return {}; + while ((*pString >= '0') && (*pString <= '9')) { pString++; + if (!isValidPointer(pString)) // No and no. + return {}; + } } } @@ -1458,6 +1478,10 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) if ((*pString != '+') && (*pString != '-')) return QDateTime(); + if (!isValidPointer(pString + 4)) { + // What kind of input parameters we were provided with? To hell with them! + return {}; + } lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60; lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0'); lSecondsFromUCT *= 60; diff --git a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h index 48364ceb1d..c139ecb32e 100644 --- a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h +++ b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h @@ -132,6 +132,8 @@ SSL_CTX *q_SSL_CTX_new(SSL_METHOD *a); int q_SSL_library_init(); void q_SSL_load_error_strings(); +int q_SSL_state(const SSL *a); +#define q_SSL_in_init(a) (q_SSL_state(a) & SSL_ST_INIT) #if OPENSSL_VERSION_NUMBER >= 0x10001000L int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 6f34c6c888..e657987769 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -220,6 +220,7 @@ protected: bool verifyErrorsHaveBeenIgnored(); bool paused; bool flushTriggered; + bool systemOrSslErrorDetected = false; }; QT_END_NAMESPACE |