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 
QSslError()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 */
QSslError(SslError error)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 */
QSslError(SslError error,const QSslCertificate & certificate)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 */
QSslError(const QSslError & other)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 */
~QSslError()172 QSslError::~QSslError()
173 {
174 }
175 
176 /*!
177     \since 4.4
178 
179     Assigns the contents of \a other to this error.
180 */
operator =(const QSslError & other)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 */
operator ==(const QSslError & other) const200 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 */
error() const219 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 */
errorString() const229 QString QSslError::errorString() const
230 {
231     QString errStr;
232     switch (d->error) {
233     case NoError:
234         errStr = QSslSocket::tr("No error");
235         break;
236     case UnableToGetIssuerCertificate:
237         errStr = QSslSocket::tr("The issuer certificate could not be found");
238         break;
239     case UnableToDecryptCertificateSignature:
240         errStr = QSslSocket::tr("The certificate signature could not be decrypted");
241         break;
242     case UnableToDecodeIssuerPublicKey:
243         errStr = QSslSocket::tr("The public key in the certificate could not be read");
244         break;
245     case CertificateSignatureFailed:
246         errStr = QSslSocket::tr("The signature of the certificate is invalid");
247         break;
248     case CertificateNotYetValid:
249         errStr = QSslSocket::tr("The certificate is not yet valid");
250         break;
251     case CertificateExpired:
252         errStr = QSslSocket::tr("The certificate has expired");
253         break;
254     case InvalidNotBeforeField:
255         errStr = QSslSocket::tr("The certificate's notBefore field contains an invalid time");
256         break;
257     case InvalidNotAfterField:
258         errStr = QSslSocket::tr("The certificate's notAfter field contains an invalid time");
259         break;
260     case SelfSignedCertificate:
261         errStr = QSslSocket::tr("The certificate is self-signed, and untrusted");
262         break;
263     case SelfSignedCertificateInChain:
264         errStr = QSslSocket::tr("The root certificate of the certificate chain is self-signed, and untrusted");
265         break;
266     case UnableToGetLocalIssuerCertificate:
267         errStr = QSslSocket::tr("The issuer certificate of a locally looked up certificate could not be found");
268         break;
269     case UnableToVerifyFirstCertificate:
270         errStr = QSslSocket::tr("No certificates could be verified");
271         break;
272     case InvalidCaCertificate:
273         errStr = QSslSocket::tr("One of the CA certificates is invalid");
274         break;
275     case PathLengthExceeded:
276         errStr = QSslSocket::tr("The basicConstraints path length parameter has been exceeded");
277         break;
278     case InvalidPurpose:
279         errStr = QSslSocket::tr("The supplied certificate is unsuitable for this purpose");
280         break;
281     case CertificateUntrusted:
282         errStr = QSslSocket::tr("The root CA certificate is not trusted for this purpose");
283         break;
284     case CertificateRejected:
285         errStr = QSslSocket::tr("The root CA certificate is marked to reject the specified purpose");
286         break;
287     case SubjectIssuerMismatch: // hostname mismatch
288         errStr = QSslSocket::tr("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("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("The peer did not present any certificate");
298         break;
299     case HostNameMismatch:
300         errStr = QSslSocket::tr("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("The peer certificate is blacklisted");
307         break;
308     case OcspNoResponseFound:
309         errStr = QSslSocket::tr("No OCSP status response found");
310         break;
311     case OcspMalformedRequest:
312         errStr = QSslSocket::tr("The OCSP status request had invalid syntax");
313         break;
314     case OcspMalformedResponse:
315         errStr = QSslSocket::tr("OCSP response contains an unexpected number of SingleResponse structures");
316         break;
317     case OcspInternalError:
318         errStr = QSslSocket::tr("OCSP responder reached an inconsistent internal state");
319         break;
320     case OcspTryLater:
321         errStr = QSslSocket::tr("OCSP responder was unable to return a status for the requested certificate");
322         break;
323     case OcspSigRequred:
324         errStr = QSslSocket::tr("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("The client is not authorized to request OCSP status from this server");
328         break;
329     case OcspResponseCannotBeTrusted:
330         errStr = QSslSocket::tr("OCSP responder's identity cannot be verified");
331         break;
332     case OcspResponseCertIdUnknown:
333         errStr = QSslSocket::tr("The identity of a certificate in an OCSP response cannot be established");
334         break;
335     case OcspResponseExpired:
336         errStr = QSslSocket::tr("The certificate status response has expired");
337         break;
338     case OcspStatusUnknown:
339         errStr = QSslSocket::tr("The certificate's status is unknown");
340         break;
341     default:
342         errStr = QSslSocket::tr("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 */
certificate() const355 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 */
qHash(const QSslError & key,uint seed)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;
operator <<(QDebug debug,const QSslError & error)375 QDebug operator<<(QDebug debug, const QSslError &error)
376 {
377     debug << error.errorString();
378     return debug;
379 }
operator <<(QDebug debug,const QSslError::SslError & error)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