Revision control
++ // Copyright (C) 2023 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include <QtCore/qfile.h>
++ #include <QtNetwork/qsslcipher.h>
++ #include "qqmlsslconfiguration_p.h"
++ #include <array>
++
++ QT_BEGIN_NAMESPACE
++
++ // Keep in sync with QSsl::SslOption!
++ static constexpr std::array<QSsl::SslOption, 8> SslOptions = {
++ QSsl::SslOptionDisableEmptyFragments,
++ QSsl::SslOptionDisableSessionTickets,
++ QSsl::SslOptionDisableCompression,
++ QSsl::SslOptionDisableServerNameIndication,
++ QSsl::SslOptionDisableLegacyRenegotiation,
++ QSsl::SslOptionDisableSessionSharing,
++ QSsl::SslOptionDisableSessionPersistence,
++ QSsl::SslOptionDisableServerCipherPreference
++ };
++
++ QString QQmlSslConfiguration::ciphers() const
++ {
++ return m_ciphers;
++ }
++
++ #if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 11)
++ QList<QSsl::SslOption> QQmlSslConfiguration::sslOptions() const
++ {
++ return m_sslOptions;
++ }
++ #endif // QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 11)
++
++ QSsl::SslProtocol QQmlSslConfiguration::protocol() const
++ {
++ return m_configuration.protocol();
++ }
++
++ QSslSocket::PeerVerifyMode QQmlSslConfiguration::peerVerifyMode() const
++ {
++ return m_configuration.peerVerifyMode();
++ }
++
++ int QQmlSslConfiguration::peerVerifyDepth() const
++ {
++ return m_configuration.peerVerifyDepth();
++ }
++
++ QByteArray QQmlSslConfiguration::sessionTicket() const
++ {
++ return m_configuration.sessionTicket();
++ }
++
++ QSsl::SslOptions QQmlSslConfiguration::sslOptionFlags() const
++ {
++ QSsl::SslOptions options{};
++ for (auto opt : SslOptions) {
++ if (m_configuration.testSslOption(opt))
++ options |= opt;
++ }
++ return options;
++ }
++
++ QSslConfiguration const QQmlSslConfiguration::configuration()
++ {
++ return m_configuration;
++ }
++
++ void QQmlSslConfiguration::setCertificateFiles(const QStringList &certificateFiles)
++ {
++ if (m_certificateFiles == certificateFiles)
++ return;
++
++ m_certificateFiles = certificateFiles;
++ QList<QSslCertificate> certificates;
++ for (const QString &fileName: m_certificateFiles) {
++ QFile certificateFile(fileName);
++ if (certificateFile.open(QIODevice::ReadOnly)) {
++ QByteArray cert = certificateFile.readAll();
++ certificates.append(QSslCertificate(cert));
++ } else {
++ qWarning() << "File: " << fileName << "is not found. It will be skipped.";
++ }
++ }
++
++ if (!certificates.isEmpty())
++ m_configuration.setCaCertificates(certificates);
++ else
++ qWarning() << "No certificates loaded.";
++ }
++
++ void QQmlSslConfiguration::setProtocol(QSsl::SslProtocol protocol)
++ {
++ if (m_configuration.protocol() == protocol)
++ return;
++
++ m_configuration.setProtocol(protocol);
++ }
++
++ void QQmlSslConfiguration::setPeerVerifyMode(QSslSocket::PeerVerifyMode mode)
++ {
++ if (m_configuration.peerVerifyMode() == mode)
++ return;
++
++ m_configuration.setPeerVerifyMode(mode);
++ }
++
++ void QQmlSslConfiguration::setPeerVerifyDepth(int depth)
++ {
++ if (m_configuration.peerVerifyDepth() == depth)
++ return;
++
++ m_configuration.setPeerVerifyDepth(depth);
++ }
++
++ void QQmlSslConfiguration::setCiphers(const QString &ciphers)
++ {
++ if (ciphers == m_ciphers)
++ return;
++
++ m_ciphers = ciphers;
++ m_configuration.setCiphers(ciphers); // split(":") is used inside
++ }
++
++ #if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 11)
++ void QQmlSslConfiguration::setSslOptions(const QList<QSsl::SslOption> &options)
++ {
++ if (m_sslOptions == options)
++ return;
++
++ m_sslOptions = options;
++ for (QSsl::SslOption option: m_sslOptions)
++ m_configuration.setSslOption(option, true);
++ }
++ #endif // QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 11)
++
++ void QQmlSslConfiguration::setSessionTicket(const QByteArray &sessionTicket)
++ {
++ if (m_configuration.sessionTicket() == sessionTicket)
++ return;
++
++ m_configuration.setSessionTicket(sessionTicket);
++ }
++
++ void QQmlSslConfiguration::setSslOptionFlags(QSsl::SslOptions options)
++ {
++ for (auto opt : SslOptions)
++ m_configuration.setSslOption(opt, options & opt);
++ }
++
++ void QQmlSslConfiguration::setPrivateKey(const QQmlSslKey &privateKey)
++ {
++ m_configuration.setPrivateKey(privateKey.getSslKey());
++ }
++
++ #if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 11)
++ void QQmlSslConfiguration::setSslOptionsList(const QSslConfiguration &configuration)
++ {
++ Q_ASSERT(m_sslOptions.isEmpty());
++ for (QSsl::SslOption option: SslOptions) {
++ if (configuration.testSslOption(option))
++ m_sslOptions.append(option);
++ }
++ }
++ #endif
++
++ void QQmlSslConfiguration::setCiphersList(const QSslConfiguration &configuration)
++ {
++ Q_ASSERT(m_ciphers.isEmpty());
++ QList<QSslCipher> ciphers = configuration.ciphers();
++ for (int i = 0; i < ciphers.size(); ++i) {
++ if (i != 0) {
++ m_ciphers += QString::fromUtf8(":");
++ }
++ m_ciphers += ciphers[i].name();
++ }
++ }
++
++ QQmlSslDefaultConfiguration::QQmlSslDefaultConfiguration()
++ : QQmlSslConfiguration()
++ {
++ m_configuration = QSslConfiguration::defaultConfiguration();
++ #if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 11)
++ setSslOptionsList(m_configuration);
++ #endif
++ setCiphersList(m_configuration);
++ }
++
++ QQmlSslDefaultDtlsConfiguration::QQmlSslDefaultDtlsConfiguration()
++ : QQmlSslConfiguration()
++ {
++ #if QT_CONFIG(dtls)
++ m_configuration = QSslConfiguration::defaultDtlsConfiguration();
++ #else
++ qWarning() << "No dtls support enabled";
++ m_configuration = QSslConfiguration::defaultConfiguration();
++ #endif // QT_CONFIG(dtls)
++ #if QT_REMOVAL_QT7_DEPRECATED_SINCE(6, 11)
++ setSslOptionsList(m_configuration);
++ #endif
++ setCiphersList(m_configuration);
++ }
++
++ QT_END_NAMESPACE