1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtNetwork module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | |
41 | /*! |
42 | \class QSslError |
43 | \brief The QSslError class provides an SSL error. |
44 | \since 4.3 |
45 | |
46 | \reentrant |
47 | \ingroup network |
48 | \ingroup ssl |
49 | \ingroup shared |
50 | \inmodule QtNetwork |
51 | |
52 | QSslError provides a simple API for managing errors during QSslSocket's |
53 | SSL handshake. |
54 | |
55 | \sa QSslSocket, QSslCertificate, QSslCipher |
56 | */ |
57 | |
58 | /*! |
59 | \enum QSslError::SslError |
60 | |
61 | Describes all recognized errors that can occur during an SSL handshake. |
62 | |
63 | \value NoError |
64 | \value UnableToGetIssuerCertificate |
65 | \value UnableToDecryptCertificateSignature |
66 | \value UnableToDecodeIssuerPublicKey |
67 | \value CertificateSignatureFailed |
68 | \value CertificateNotYetValid |
69 | \value CertificateExpired |
70 | \value InvalidNotBeforeField |
71 | \value InvalidNotAfterField |
72 | \value SelfSignedCertificate |
73 | \value SelfSignedCertificateInChain |
74 | \value UnableToGetLocalIssuerCertificate |
75 | \value UnableToVerifyFirstCertificate |
76 | \value CertificateRevoked |
77 | \value InvalidCaCertificate |
78 | \value PathLengthExceeded |
79 | \value InvalidPurpose |
80 | \value CertificateUntrusted |
81 | \value CertificateRejected |
82 | \value SubjectIssuerMismatch |
83 | \value AuthorityIssuerSerialNumberMismatch |
84 | \value NoPeerCertificate |
85 | \value HostNameMismatch |
86 | \value UnspecifiedError |
87 | \value NoSslSupport |
88 | \value CertificateBlacklisted |
89 | \value CertificateStatusUnknown |
90 | \value OcspNoResponseFound |
91 | \value OcspMalformedRequest |
92 | \value OcspMalformedResponse |
93 | \value OcspInternalError |
94 | \value OcspTryLater |
95 | \value OcspSigRequred |
96 | \value OcspUnauthorized |
97 | \value OcspResponseCannotBeTrusted |
98 | \value OcspResponseCertIdUnknown |
99 | \value OcspResponseExpired |
100 | \value OcspStatusUnknown |
101 | |
102 | |
103 | \sa QSslError::errorString() |
104 | */ |
105 | |
106 | #include "qsslerror.h" |
107 | #include "qsslsocket.h" |
108 | #ifndef QT_NO_DEBUG_STREAM |
109 | #include <QtCore/qdebug.h> |
110 | #endif |
111 | |
112 | QT_BEGIN_NAMESPACE |
113 | |
114 | class QSslErrorPrivate |
115 | { |
116 | public: |
117 | QSslError::SslError error; |
118 | QSslCertificate certificate; |
119 | }; |
120 | |
121 | // RVCT compiler in debug build does not like about default values in const- |
122 | // So as an workaround we define all constructor overloads here explicitly |
123 | /*! |
124 | Constructs a QSslError object with no error and default certificate. |
125 | |
126 | */ |
127 | |
128 | QSslError::QSslError() |
129 | : d(new QSslErrorPrivate) |
130 | { |
131 | d->error = QSslError::NoError; |
132 | d->certificate = QSslCertificate(); |
133 | } |
134 | |
135 | /*! |
136 | Constructs a QSslError object. The argument specifies the \a |
137 | error that occurred. |
138 | |
139 | */ |
140 | QSslError::QSslError(SslError error) |
141 | : d(new QSslErrorPrivate) |
142 | { |
143 | d->error = error; |
144 | d->certificate = QSslCertificate(); |
145 | } |
146 | |
147 | /*! |
148 | Constructs a QSslError object. The two arguments specify the \a |
149 | error that occurred, and which \a certificate the error relates to. |
150 | |
151 | \sa QSslCertificate |
152 | */ |
153 | QSslError::QSslError(SslError error, const QSslCertificate &certificate) |
154 | : d(new QSslErrorPrivate) |
155 | { |
156 | d->error = error; |
157 | d->certificate = certificate; |
158 | } |
159 | |
160 | /*! |
161 | Constructs an identical copy of \a other. |
162 | */ |
163 | QSslError::QSslError(const QSslError &other) |
164 | : d(new QSslErrorPrivate) |
165 | { |
166 | *d.data() = *other.d.data(); |
167 | } |
168 | |
169 | /*! |
170 | Destroys the QSslError object. |
171 | */ |
172 | QSslError::~QSslError() |
173 | { |
174 | } |
175 | |
176 | /*! |
177 | \since 4.4 |
178 | |
179 | Assigns the contents of \a other to this error. |
180 | */ |
181 | QSslError &QSslError::operator=(const QSslError &other) |
182 | { |
183 | *d.data() = *other.d.data(); |
184 | return *this; |
185 | } |
186 | |
187 | /*! |
188 | \fn void QSslError::swap(QSslError &other) |
189 | \since 5.0 |
190 | |
191 | Swaps this error instance with \a other. This function is very |
192 | fast and never fails. |
193 | */ |
194 | |
195 | /*! |
196 | \since 4.4 |
197 | |
198 | Returns \c true if this error is equal to \a other; otherwise returns \c false. |
199 | */ |
200 | bool QSslError::operator==(const QSslError &other) const |
201 | { |
202 | return d->error == other.d->error |
203 | && d->certificate == other.d->certificate; |
204 | } |
205 | |
206 | /*! |
207 | \fn bool QSslError::operator!=(const QSslError &other) const |
208 | \since 4.4 |
209 | |
210 | Returns \c true if this error is not equal to \a other; otherwise returns |
211 | false. |
212 | */ |
213 | |
214 | /*! |
215 | Returns the type of the error. |
216 | |
217 | \sa errorString(), certificate() |
218 | */ |
219 | QSslError::SslError QSslError::error() const |
220 | { |
221 | return d->error; |
222 | } |
223 | |
224 | /*! |
225 | Returns a short localized human-readable description of the error. |
226 | |
227 | \sa error(), certificate() |
228 | */ |
229 | QString QSslError::errorString() const |
230 | { |
231 | QString errStr; |
232 | switch (d->error) { |
233 | case NoError: |
234 | errStr = QSslSocket::tr(s: "No error" ); |
235 | break; |
236 | case UnableToGetIssuerCertificate: |
237 | errStr = QSslSocket::tr(s: "The issuer certificate could not be found" ); |
238 | break; |
239 | case UnableToDecryptCertificateSignature: |
240 | errStr = QSslSocket::tr(s: "The certificate signature could not be decrypted" ); |
241 | break; |
242 | case UnableToDecodeIssuerPublicKey: |
243 | errStr = QSslSocket::tr(s: "The public key in the certificate could not be read" ); |
244 | break; |
245 | case CertificateSignatureFailed: |
246 | errStr = QSslSocket::tr(s: "The signature of the certificate is invalid" ); |
247 | break; |
248 | case CertificateNotYetValid: |
249 | errStr = QSslSocket::tr(s: "The certificate is not yet valid" ); |
250 | break; |
251 | case CertificateExpired: |
252 | errStr = QSslSocket::tr(s: "The certificate has expired" ); |
253 | break; |
254 | case InvalidNotBeforeField: |
255 | errStr = QSslSocket::tr(s: "The certificate's notBefore field contains an invalid time" ); |
256 | break; |
257 | case InvalidNotAfterField: |
258 | errStr = QSslSocket::tr(s: "The certificate's notAfter field contains an invalid time" ); |
259 | break; |
260 | case SelfSignedCertificate: |
261 | errStr = QSslSocket::tr(s: "The certificate is self-signed, and untrusted" ); |
262 | break; |
263 | case SelfSignedCertificateInChain: |
264 | errStr = QSslSocket::tr(s: "The root certificate of the certificate chain is self-signed, and untrusted" ); |
265 | break; |
266 | case UnableToGetLocalIssuerCertificate: |
267 | errStr = QSslSocket::tr(s: "The issuer certificate of a locally looked up certificate could not be found" ); |
268 | break; |
269 | case UnableToVerifyFirstCertificate: |
270 | errStr = QSslSocket::tr(s: "No certificates could be verified" ); |
271 | break; |
272 | case InvalidCaCertificate: |
273 | errStr = QSslSocket::tr(s: "One of the CA certificates is invalid" ); |
274 | break; |
275 | case PathLengthExceeded: |
276 | errStr = QSslSocket::tr(s: "The basicConstraints path length parameter has been exceeded" ); |
277 | break; |
278 | case InvalidPurpose: |
279 | errStr = QSslSocket::tr(s: "The supplied certificate is unsuitable for this purpose" ); |
280 | break; |
281 | case CertificateUntrusted: |
282 | errStr = QSslSocket::tr(s: "The root CA certificate is not trusted for this purpose" ); |
283 | break; |
284 | case CertificateRejected: |
285 | errStr = QSslSocket::tr(s: "The root CA certificate is marked to reject the specified purpose" ); |
286 | break; |
287 | case SubjectIssuerMismatch: // hostname mismatch |
288 | errStr = QSslSocket::tr(s: "The current candidate issuer certificate was rejected because its" |
289 | " subject name did not match the issuer name of the current certificate" ); |
290 | break; |
291 | case AuthorityIssuerSerialNumberMismatch: |
292 | errStr = QSslSocket::tr(s: "The current candidate issuer certificate was rejected because" |
293 | " its issuer name and serial number was present and did not match the" |
294 | " authority key identifier of the current certificate" ); |
295 | break; |
296 | case NoPeerCertificate: |
297 | errStr = QSslSocket::tr(s: "The peer did not present any certificate" ); |
298 | break; |
299 | case HostNameMismatch: |
300 | errStr = QSslSocket::tr(s: "The host name did not match any of the valid hosts" |
301 | " for this certificate" ); |
302 | break; |
303 | case NoSslSupport: |
304 | break; |
305 | case CertificateBlacklisted: |
306 | errStr = QSslSocket::tr(s: "The peer certificate is blacklisted" ); |
307 | break; |
308 | case OcspNoResponseFound: |
309 | errStr = QSslSocket::tr(s: "No OCSP status response found" ); |
310 | break; |
311 | case OcspMalformedRequest: |
312 | errStr = QSslSocket::tr(s: "The OCSP status request had invalid syntax" ); |
313 | break; |
314 | case OcspMalformedResponse: |
315 | errStr = QSslSocket::tr(s: "OCSP response contains an unexpected number of SingleResponse structures" ); |
316 | break; |
317 | case OcspInternalError: |
318 | errStr = QSslSocket::tr(s: "OCSP responder reached an inconsistent internal state" ); |
319 | break; |
320 | case OcspTryLater: |
321 | errStr = QSslSocket::tr(s: "OCSP responder was unable to return a status for the requested certificate" ); |
322 | break; |
323 | case OcspSigRequred: |
324 | errStr = QSslSocket::tr(s: "The server requires the client to sign the OCSP request in order to construct a response" ); |
325 | break; |
326 | case OcspUnauthorized: |
327 | errStr = QSslSocket::tr(s: "The client is not authorized to request OCSP status from this server" ); |
328 | break; |
329 | case OcspResponseCannotBeTrusted: |
330 | errStr = QSslSocket::tr(s: "OCSP responder's identity cannot be verified" ); |
331 | break; |
332 | case OcspResponseCertIdUnknown: |
333 | errStr = QSslSocket::tr(s: "The identity of a certificate in an OCSP response cannot be established" ); |
334 | break; |
335 | case OcspResponseExpired: |
336 | errStr = QSslSocket::tr(s: "The certificate status response has expired" ); |
337 | break; |
338 | case OcspStatusUnknown: |
339 | errStr = QSslSocket::tr(s: "The certificate's status is unknown" ); |
340 | break; |
341 | default: |
342 | errStr = QSslSocket::tr(s: "Unknown error" ); |
343 | break; |
344 | } |
345 | |
346 | return errStr; |
347 | } |
348 | |
349 | /*! |
350 | Returns the certificate associated with this error, or a null certificate |
351 | if the error does not relate to any certificate. |
352 | |
353 | \sa error(), errorString() |
354 | */ |
355 | QSslCertificate QSslError::certificate() const |
356 | { |
357 | return d->certificate; |
358 | } |
359 | |
360 | /*! |
361 | Returns the hash value for the \a key, using \a seed to seed the calculation. |
362 | \since 5.4 |
363 | \relates QHash |
364 | */ |
365 | uint qHash(const QSslError &key, uint seed) noexcept |
366 | { |
367 | QtPrivate::QHashCombine hash; |
368 | seed = hash(seed, key.error()); |
369 | seed = hash(seed, key.certificate()); |
370 | return seed; |
371 | } |
372 | |
373 | #ifndef QT_NO_DEBUG_STREAM |
374 | //class QDebug; |
375 | QDebug operator<<(QDebug debug, const QSslError &error) |
376 | { |
377 | debug << error.errorString(); |
378 | return debug; |
379 | } |
380 | QDebug operator<<(QDebug debug, const QSslError::SslError &error) |
381 | { |
382 | debug << QSslError(error).errorString(); |
383 | return debug; |
384 | } |
385 | #endif |
386 | |
387 | QT_END_NAMESPACE |
388 | |