1 | // Copyright (C) 2023 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include <QtCore/qfile.h> |
5 | #include <QtNetwork/qsslcipher.h> |
6 | #include "qqmlsslconfiguration_p.h" |
7 | #include <array> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | static constexpr std::array<QSsl::SslOption, 8> SslOptions = { |
11 | QSsl::SslOptionDisableEmptyFragments, |
12 | QSsl::SslOptionDisableSessionTickets, |
13 | QSsl::SslOptionDisableCompression, |
14 | QSsl::SslOptionDisableServerNameIndication, |
15 | QSsl::SslOptionDisableLegacyRenegotiation, |
16 | QSsl::SslOptionDisableSessionSharing, |
17 | QSsl::SslOptionDisableSessionPersistence, |
18 | QSsl::SslOptionDisableServerCipherPreference |
19 | }; |
20 | |
21 | QString QQmlSslConfiguration::ciphers() const |
22 | { |
23 | return m_ciphers; |
24 | } |
25 | |
26 | QList<QSsl::SslOption> QQmlSslConfiguration::sslOptions() const |
27 | { |
28 | return m_sslOptions; |
29 | } |
30 | |
31 | QSsl::SslProtocol QQmlSslConfiguration::protocol() const |
32 | { |
33 | return m_configuration.protocol(); |
34 | } |
35 | |
36 | QSslSocket::PeerVerifyMode QQmlSslConfiguration::peerVerifyMode() const |
37 | { |
38 | return m_configuration.peerVerifyMode(); |
39 | } |
40 | |
41 | int QQmlSslConfiguration::peerVerifyDepth() const |
42 | { |
43 | return m_configuration.peerVerifyDepth(); |
44 | } |
45 | |
46 | QByteArray QQmlSslConfiguration::sessionTicket() const |
47 | { |
48 | return m_configuration.sessionTicket(); |
49 | } |
50 | |
51 | QSslConfiguration const QQmlSslConfiguration::configuration() |
52 | { |
53 | return m_configuration; |
54 | } |
55 | |
56 | void QQmlSslConfiguration::setCertificateFiles(const QStringList &certificateFiles) |
57 | { |
58 | if (m_certificateFiles == certificateFiles) |
59 | return; |
60 | |
61 | m_certificateFiles = certificateFiles; |
62 | QList<QSslCertificate> certificates; |
63 | for (const QString &fileName: m_certificateFiles) { |
64 | QFile certificateFile(fileName); |
65 | if (certificateFile.open(flags: QIODevice::ReadOnly)) { |
66 | QByteArray cert = certificateFile.readAll(); |
67 | certificates.append(t: QSslCertificate(cert)); |
68 | } else { |
69 | qWarning() << "File: " << fileName << "is not found. It will be skipped." ; |
70 | } |
71 | } |
72 | |
73 | if (!certificates.isEmpty()) |
74 | m_configuration.setCaCertificates(certificates); |
75 | else |
76 | qWarning() << "No certificates loaded." ; |
77 | } |
78 | |
79 | void QQmlSslConfiguration::setProtocol(QSsl::SslProtocol protocol) |
80 | { |
81 | if (m_configuration.protocol() == protocol) |
82 | return; |
83 | |
84 | m_configuration.setProtocol(protocol); |
85 | } |
86 | |
87 | void QQmlSslConfiguration::setPeerVerifyMode(QSslSocket::PeerVerifyMode mode) |
88 | { |
89 | if (m_configuration.peerVerifyMode() == mode) |
90 | return; |
91 | |
92 | m_configuration.setPeerVerifyMode(mode); |
93 | } |
94 | |
95 | void QQmlSslConfiguration::setPeerVerifyDepth(int depth) |
96 | { |
97 | if (m_configuration.peerVerifyDepth() == depth) |
98 | return; |
99 | |
100 | m_configuration.setPeerVerifyDepth(depth); |
101 | } |
102 | |
103 | void QQmlSslConfiguration::setCiphers(const QString &ciphers) |
104 | { |
105 | if (ciphers == m_ciphers) |
106 | return; |
107 | |
108 | m_ciphers = ciphers; |
109 | m_configuration.setCiphers(ciphers); // split(":") is used inside |
110 | } |
111 | |
112 | void QQmlSslConfiguration::setSslOptions(const QList<QSsl::SslOption> &options) |
113 | { |
114 | if (m_sslOptions == options) |
115 | return; |
116 | |
117 | m_sslOptions = options; |
118 | for (QSsl::SslOption option: m_sslOptions) |
119 | m_configuration.setSslOption(option, on: true); |
120 | } |
121 | |
122 | void QQmlSslConfiguration::setSessionTicket(const QByteArray &sessionTicket) |
123 | { |
124 | if (m_configuration.sessionTicket() == sessionTicket) |
125 | return; |
126 | |
127 | m_configuration.setSessionTicket(sessionTicket); |
128 | } |
129 | |
130 | void QQmlSslConfiguration::setPrivateKey(const QQmlSslKey &privateKey) |
131 | { |
132 | m_configuration.setPrivateKey(privateKey.getSslKey()); |
133 | } |
134 | |
135 | void QQmlSslConfiguration::setSslOptionsList(const QSslConfiguration &configuration) |
136 | { |
137 | for (QSsl::SslOption option: SslOptions) { |
138 | if (configuration.testSslOption(option)) |
139 | m_sslOptions.append(t: option); |
140 | } |
141 | } |
142 | |
143 | void QQmlSslConfiguration::setCiphersList(const QSslConfiguration &configuration) |
144 | { |
145 | QList<QSslCipher> ciphers = configuration.ciphers(); |
146 | for (int i = 0; i < ciphers.size(); ++i) { |
147 | if (i != 0) { |
148 | m_ciphers += QString::fromUtf8(utf8: ":" ); |
149 | } |
150 | m_ciphers += ciphers[i].name(); |
151 | } |
152 | } |
153 | |
154 | QQmlSslDefaultConfiguration::QQmlSslDefaultConfiguration() |
155 | : QQmlSslConfiguration() |
156 | { |
157 | m_configuration = QSslConfiguration::defaultConfiguration(); |
158 | setSslOptionsList(m_configuration); |
159 | setCiphersList(m_configuration); |
160 | } |
161 | |
162 | QQmlSslDefaultDtlsConfiguration::QQmlSslDefaultDtlsConfiguration() |
163 | : QQmlSslConfiguration() |
164 | { |
165 | #if QT_CONFIG(dtls) |
166 | m_configuration = QSslConfiguration::defaultDtlsConfiguration(); |
167 | #else |
168 | qWarning() << "No dtls support enabled" ; |
169 | m_configuration = QSslConfiguration::defaultConfiguration(); |
170 | #endif // QT_CONFIG(dtls) |
171 | setSslOptionsList(m_configuration); |
172 | setCiphersList(m_configuration); |
173 | } |
174 | |
175 | QT_END_NAMESPACE |
176 | |