Doc: Modularize QtNetwork documentation.
[profile/ivi/qtbase.git] / src / network / ssl / qsslcertificate.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 /*!
44     \class QSslCertificate
45     \brief The QSslCertificate class provides a convenient API for an X509 certificate.
46     \since 4.3
47
48     \reentrant
49     \ingroup network
50     \ingroup ssl
51     \inmodule QtNetwork
52
53     QSslCertificate stores an X509 certificate, and is commonly used
54     to verify the identity and store information about the local host,
55     a remotely connected peer, or a trusted third party Certificate
56     Authority.
57
58     There are many ways to construct a QSslCertificate. The most
59     common way is to call QSslSocket::peerCertificate(), which returns
60     a QSslCertificate object, or QSslSocket::peerCertificateChain(),
61     which returns a list of them. You can also load certificates from
62     a DER (binary) or PEM (Base64) encoded bundle, typically stored as
63     one or more local files, or in a Qt Resource.
64
65     You can call isNull() to check if your certificate is null. By default,
66     QSslCertificate constructs a null certificate. A null certificate is
67     invalid, but an invalid certificate is not necessarily null. If you want
68     to reset all contents in a certificate, call clear().
69
70     After loading a certificate, you can find information about the
71     certificate, its subject, and its issuer, by calling one of the
72     many accessor functions, including version(), serialNumber(),
73     issuerInfo() and subjectInfo(). You can call effectiveDate() and
74     expiryDate() to check when the certificate starts being
75     effective and when it expires.
76     The publicKey() function returns the certificate
77     subject's public key as a QSslKey. You can call issuerInfo() or
78     subjectInfo() to get detailed information about the certificate
79     issuer and its subject.
80
81     Internally, QSslCertificate is stored as an X509 structure. You
82     can access this handle by calling handle(), but the results are
83     likely to not be portable.
84
85     \sa QSslSocket, QSslKey, QSslCipher, QSslError
86 */
87
88 /*!
89     \enum QSslCertificate::SubjectInfo
90
91     Describes keys that you can pass to QSslCertificate::issuerInfo() or
92     QSslCertificate::subjectInfo() to get information about the certificate
93     issuer or subject.
94
95     \value Organization "O" The name of the organization.
96
97     \value CommonName "CN" The common name; most often this is used to store
98     the host name.
99
100     \value LocalityName "L" The locality.
101
102     \value OrganizationalUnitName "OU" The organizational unit name.
103
104     \value CountryName "C" The country.
105
106     \value StateOrProvinceName "ST" The state or province.
107
108     \value DistinguishedNameQualifier The distinguished name qualifier
109
110     \value SerialNumber The certificate's serial number
111
112     \value EmailAddress The email address associated with the certificate
113 */
114
115 #include "qsslsocket_openssl_symbols_p.h"
116 #include "qsslcertificate.h"
117 #include "qsslcertificate_p.h"
118 #include "qsslkey.h"
119 #include "qsslkey_p.h"
120 #include "qsslcertificateextension.h"
121 #include "qsslcertificateextension_p.h"
122
123 #include <QtCore/qatomic.h>
124 #include <QtCore/qdatetime.h>
125 #include <QtCore/qdebug.h>
126 #include <QtCore/qdir.h>
127 #include <QtCore/qdiriterator.h>
128 #include <QtCore/qfile.h>
129 #include <QtCore/qfileinfo.h>
130 #include <QtCore/qmap.h>
131 #include <QtCore/qmutex.h>
132 #include <QtCore/private/qmutexpool_p.h>
133 #include <QtCore/qstring.h>
134 #include <QtCore/qstringlist.h>
135 #include <QtCore/qvarlengtharray.h>
136
137 QT_BEGIN_NAMESPACE
138
139 // forward declaration
140 static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name);
141
142 /*!
143     Constructs a QSslCertificate by reading \a format encoded data
144     from \a device and using the first certificate found. You can
145     later call isNull() to see if \a device contained a certificate,
146     and if this certificate was loaded successfully.
147 */
148 QSslCertificate::QSslCertificate(QIODevice *device, QSsl::EncodingFormat format)
149     : d(new QSslCertificatePrivate)
150 {
151     QSslSocketPrivate::ensureInitialized();
152     if (device)
153         d->init(device->readAll(), format);
154 }
155
156 /*!
157     Constructs a QSslCertificate by parsing the \a format encoded
158     \a data and using the first available certificate found. You can
159     later call isNull() to see if \a data contained a certificate,
160     and if this certificate was loaded successfully.
161 */
162 QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat format)
163     : d(new QSslCertificatePrivate)
164 {
165     QSslSocketPrivate::ensureInitialized();
166     d->init(data, format);
167 }
168
169 /*!
170     Constructs an identical copy of \a other.
171 */
172 QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d)
173 {
174 }
175
176 /*!
177     Destroys the QSslCertificate.
178 */
179 QSslCertificate::~QSslCertificate()
180 {
181 }
182
183 /*!
184     Copies the contents of \a other into this certificate, making the two
185     certificates identical.
186 */
187 QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other)
188 {
189     d = other.d;
190     return *this;
191 }
192
193 /*!
194     Returns true if this certificate is the same as \a other; otherwise
195     returns false.
196 */
197 bool QSslCertificate::operator==(const QSslCertificate &other) const
198 {
199     if (d == other.d)
200         return true;
201     if (d->null && other.d->null)
202         return true;
203     if (d->x509 && other.d->x509)
204         return q_X509_cmp(d->x509, other.d->x509) == 0;
205     return false;
206 }
207
208 /*!
209     \fn bool QSslCertificate::operator!=(const QSslCertificate &other) const
210
211     Returns true if this certificate is not the same as \a other; otherwise
212     returns false.
213 */
214
215 /*!
216     Returns true if this is a null certificate (i.e., a certificate
217     with no contents); otherwise returns false.
218
219     By default, QSslCertificate constructs a null certificate.
220
221     \sa clear()
222 */
223 bool QSslCertificate::isNull() const
224 {
225     return d->null;
226 }
227
228 #if QT_DEPRECATED_SINCE(5,0)
229 /*!
230     \fn bool QSslCertificate::isValid() const
231     \obsolete
232
233     To verify a certificate, use verify().
234     To check if a certificate is blacklisted, use isBlacklisted().
235     To check if a certificate has expired or is not yet valid, compare
236     expiryDate() and effectiveDate() with QDateTime::currentDateTime()
237
238     This function checks that the current
239     data-time is within the date-time range during which the
240     certificate is considered valid, and checks that the
241     certificate is not in a blacklist of fraudulent certificates.
242
243     \sa isNull(), verify(), isBlacklisted(), expiryDate(), effectiveDate()
244 */
245 #endif
246
247 /*!
248     Returns true if this certificate is blacklisted; otherwise
249     returns false.
250
251     \sa isNull()
252 */
253 bool QSslCertificate::isBlacklisted() const
254 {
255     return QSslCertificatePrivate::isBlacklisted(*this);
256 }
257
258 /*!
259     Clears the contents of this certificate, making it a null
260     certificate.
261
262     \sa isNull()
263 */
264 void QSslCertificate::clear()
265 {
266     if (isNull())
267         return;
268     d = new QSslCertificatePrivate;
269 }
270
271 /*!
272     Returns the certificate's version string.
273 */
274 QByteArray QSslCertificate::version() const
275 {
276     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
277     if (d->versionString.isEmpty() && d->x509)
278         d->versionString =
279             QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
280
281     return d->versionString;
282 }
283
284 /*!
285     Returns the certificate's serial number string in hexadecimal format.
286 */
287 QByteArray QSslCertificate::serialNumber() const
288 {
289     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
290     if (d->serialNumberString.isEmpty() && d->x509) {
291         ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
292         QByteArray hexString;
293         hexString.reserve(serialNumber->length * 3);
294         for (int a = 0; a < serialNumber->length; ++a) {
295             hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2, '0');
296             hexString += ':';
297         }
298         hexString.chop(1);
299         d->serialNumberString = hexString;
300     }
301     return d->serialNumberString;
302 }
303
304 /*!
305     Returns a cryptographic digest of this certificate. By default,
306     an MD5 digest will be generated, but you can also specify a
307     custom \a algorithm.
308 */
309 QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) const
310 {
311     return QCryptographicHash::hash(toDer(), algorithm);
312 }
313
314 static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info)
315 {
316     QByteArray str;
317     switch (info) {
318     case QSslCertificate::Organization: str = QByteArray("O"); break;
319     case QSslCertificate::CommonName: str = QByteArray("CN"); break;
320     case QSslCertificate::LocalityName: str = QByteArray("L"); break;
321     case QSslCertificate::OrganizationalUnitName: str = QByteArray("OU"); break;
322     case QSslCertificate::CountryName: str = QByteArray("C"); break;
323     case QSslCertificate::StateOrProvinceName: str = QByteArray("ST"); break;
324     case QSslCertificate::DistinguishedNameQualifier: str = QByteArray("dnQualifier"); break;
325     case QSslCertificate::SerialNumber: str = QByteArray("serialNumber"); break;
326     case QSslCertificate::EmailAddress: str = QByteArray("emailAddress"); break;
327     }
328     return str;
329 }
330
331 /*!
332   \fn QString QSslCertificate::issuerInfo(SubjectInfo subject) const
333
334   Returns the issuer information for the \a subject from the
335   certificate, or an empty string if there is no information for
336   \a subject in the certificate.
337
338   \sa subjectInfo()
339 */
340 QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
341 {
342     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
343     // lazy init
344     if (d->issuerInfo.isEmpty() && d->x509)
345         d->issuerInfo =
346                 _q_mapFromX509Name(q_X509_get_issuer_name(d->x509));
347
348     return d->issuerInfo.values(_q_SubjectInfoToString(info));
349 }
350
351 /*!
352   Returns the issuer information for \a attribute from the certificate,
353   or an empty string if there is no information for \a attribute in the
354   certificate.
355
356   \sa subjectInfo()
357 */
358 QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
359 {
360     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
361     // lazy init
362     if (d->issuerInfo.isEmpty() && d->x509)
363         d->issuerInfo =
364                 _q_mapFromX509Name(q_X509_get_issuer_name(d->x509));
365
366     return d->issuerInfo.values(attribute);
367 }
368
369 /*!
370
371   \fn QString QSslCertificate::subjectInfo(SubjectInfo subject) const
372
373   Returns the information for the \a subject, or an empty string if
374   there is no information for \a subject in the certificate.
375
376     \sa issuerInfo()
377 */
378 QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
379 {
380     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
381     // lazy init
382     if (d->subjectInfo.isEmpty() && d->x509)
383         d->subjectInfo =
384                 _q_mapFromX509Name(q_X509_get_subject_name(d->x509));
385
386     return d->subjectInfo.values(_q_SubjectInfoToString(info));
387 }
388
389 /*!
390     Returns the subject information for \a attribute, or an empty string if
391     there is no information for \a attribute in the certificate.
392
393     \sa issuerInfo()
394 */
395 QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
396 {
397     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
398     // lazy init
399     if (d->subjectInfo.isEmpty() && d->x509)
400         d->subjectInfo =
401                 _q_mapFromX509Name(q_X509_get_subject_name(d->x509));
402
403     return d->subjectInfo.values(attribute);
404 }
405
406 /*!
407     \since 5.0
408     Returns a list of the attributes that have values in the subject
409     information of this certificate. The information associated
410     with a given attribute can be accessed using the subjectInfo()
411     method. Note that this list may include the OIDs for any
412     elements that are not known by the SSL backend.
413
414     \sa subjectInfo()
415 */
416 QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
417 {
418     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
419     // lazy init
420     if (d->subjectInfo.isEmpty() && d->x509)
421         d->subjectInfo =
422                 _q_mapFromX509Name(q_X509_get_subject_name(d->x509));
423
424     return d->subjectInfo.uniqueKeys();
425 }
426
427 /*!
428     \since 5.0
429     Returns a list of the attributes that have values in the issuer
430     information of this certificate. The information associated
431     with a given attribute can be accessed using the issuerInfo()
432     method. Note that this list may include the OIDs for any
433     elements that are not known by the SSL backend.
434
435     \sa subjectInfo()
436 */
437 QList<QByteArray> QSslCertificate::issuerInfoAttributes() const
438 {
439     QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
440     // lazy init
441     if (d->issuerInfo.isEmpty() && d->x509)
442         d->issuerInfo =
443                 _q_mapFromX509Name(q_X509_get_issuer_name(d->x509));
444
445     return d->issuerInfo.uniqueKeys();
446 }
447
448 #if QT_DEPRECATED_SINCE(5,0)
449 /*!
450   \fn QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubjectNames() const
451   \obsolete
452
453   Use QSslCertificate::subjectAlternativeNames();
454 */
455 #endif
456
457 /*!
458   Returns the list of alternative subject names for this
459   certificate. The alternative names typically contain host
460   names, optionally with wildcards, that are valid for this
461   certificate.
462
463   These names are tested against the connected peer's host name, if
464   either the subject information for \l CommonName doesn't define a
465   valid host name, or the subject info name doesn't match the peer's
466   host name.
467
468   \sa subjectInfo()
469 */
470 QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlternativeNames() const
471 {
472     QMultiMap<QSsl::AlternativeNameEntryType, QString> result;
473
474     if (!d->x509)
475         return result;
476
477     STACK_OF(GENERAL_NAME) *altNames = (STACK_OF(GENERAL_NAME)*)q_X509_get_ext_d2i(d->x509, NID_subject_alt_name, 0, 0);
478
479     if (altNames) {
480         for (int i = 0; i < q_sk_GENERAL_NAME_num(altNames); ++i) {
481             const GENERAL_NAME *genName = q_sk_GENERAL_NAME_value(altNames, i);
482             if (genName->type != GEN_DNS && genName->type != GEN_EMAIL)
483                 continue;
484
485             int len = q_ASN1_STRING_length(genName->d.ia5);
486             if (len < 0 || len >= 8192) {
487                 // broken name
488                 continue;
489             }
490
491             const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(genName->d.ia5));
492             const QString altName = QString::fromLatin1(altNameStr, len);
493             if (genName->type == GEN_DNS)
494                 result.insert(QSsl::DnsEntry, altName);
495             else if (genName->type == GEN_EMAIL)
496                 result.insert(QSsl::EmailEntry, altName);
497         }
498         q_sk_pop_free((STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_sk_free));
499     }
500
501     return result;
502 }
503
504 /*!
505   Returns the date-time that the certificate becomes valid, or an
506   empty QDateTime if this is a null certificate.
507
508   \sa expiryDate()
509 */
510 QDateTime QSslCertificate::effectiveDate() const
511 {
512     return d->notValidBefore;
513 }
514
515 /*!
516   Returns the date-time that the certificate expires, or an empty
517   QDateTime if this is a null certificate.
518
519     \sa effectiveDate()
520 */
521 QDateTime QSslCertificate::expiryDate() const
522 {
523     return d->notValidAfter;
524 }
525
526 /*!
527     Returns a pointer to the native certificate handle, if there is
528     one, or a null pointer otherwise.
529
530     You can use this handle, together with the native API, to access
531     extended information about the certificate.
532
533     \warning Use of this function has a high probability of being
534     non-portable, and its return value may vary from platform to
535     platform or change from minor release to minor release.
536 */
537 Qt::HANDLE QSslCertificate::handle() const
538 {
539     return Qt::HANDLE(d->x509);
540 }
541
542 /*!
543     Returns the certificate subject's public key.
544 */
545 QSslKey QSslCertificate::publicKey() const
546 {
547     if (!d->x509)
548         return QSslKey();
549
550     QSslKey key;
551
552     key.d->type = QSsl::PublicKey;
553     X509_PUBKEY *xkey = d->x509->cert_info->key;
554     EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey);
555     Q_ASSERT(pkey);
556
557     if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) {
558         key.d->rsa = q_EVP_PKEY_get1_RSA(pkey);
559         key.d->algorithm = QSsl::Rsa;
560         key.d->isNull = false;
561     } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) {
562         key.d->dsa = q_EVP_PKEY_get1_DSA(pkey);
563         key.d->algorithm = QSsl::Dsa;
564         key.d->isNull = false;
565     } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) {
566         // DH unsupported
567     } else {
568         // error?
569     }
570
571     q_EVP_PKEY_free(pkey);
572     return key;
573 }
574
575 /*
576  * Convert unknown extensions to a QVariant.
577  */
578 static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
579 {
580     // Get the extension specific method object if available
581     // we cast away the const-ness here because some versions of openssl
582     // don't use const for the parameters in the functions pointers stored
583     // in the object.
584     X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext));
585     if (!meth) {
586         ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext);
587         QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_data(value)),
588                            q_ASN1_STRING_length(value));
589         return result;
590     }
591
592     //const unsigned char *data = ext->value->data;
593     void *ext_internal = q_X509V3_EXT_d2i(ext);
594
595     // If this extension can be converted
596     if (meth->i2v && ext_internal) {
597         STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal, 0);
598
599         QVariantMap map;
600         QVariantList list;
601         bool isMap = false;
602
603         for (int j = 0; j < q_SKM_sk_num(CONF_VALUE, val); j++) {
604             CONF_VALUE *nval = q_SKM_sk_value(CONF_VALUE, val, j);
605             if (nval->name && nval->value) {
606                 isMap = true;
607                 map[QString::fromUtf8(nval->name)] = QString::fromUtf8(nval->value);
608             } else if (nval->name) {
609                 list << QString::fromUtf8(nval->name);
610             } else if (nval->value) {
611                 list << QString::fromUtf8(nval->value);
612             }
613         }
614
615         if (isMap)
616             return map;
617         else
618             return list;
619     } else if (meth->i2s && ext_internal) {
620         //qDebug() << meth->i2s(meth, ext_internal);
621         QVariant result(QString::fromUtf8(meth->i2s(meth, ext_internal)));
622         return result;
623     } else if (meth->i2r && ext_internal) {
624         QByteArray result;
625
626         BIO *bio = q_BIO_new(q_BIO_s_mem());
627         if (!bio)
628             return result;
629
630         meth->i2r(meth, ext_internal, bio, 0);
631
632         char *bio_buffer;
633         long bio_size = q_BIO_get_mem_data(bio, &bio_buffer);
634         result = QByteArray(bio_buffer, bio_size);
635
636         q_BIO_free(bio);
637         return result;
638     }
639
640     return QVariant();
641 }
642
643 /*
644  * Convert extensions to a variant. The naming of the keys of the map are
645  * taken from RFC 5280, however we decided the capitalisation in the RFC
646  * was too silly for the real world.
647  */
648 static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
649 {
650     ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext);
651     int nid = q_OBJ_obj2nid(obj);
652
653     switch (nid) {
654     case NID_basic_constraints:
655         {
656             BASIC_CONSTRAINTS *basic = reinterpret_cast<BASIC_CONSTRAINTS *>(q_X509V3_EXT_d2i(ext));
657
658             QVariantMap result;
659             result[QLatin1String("ca")] = basic->ca ? true : false;
660             if (basic->pathlen)
661                 result[QLatin1String("pathLenConstraint")] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen);
662
663             q_BASIC_CONSTRAINTS_free(basic);
664             return result;
665         }
666         break;
667     case NID_info_access:
668         {
669             AUTHORITY_INFO_ACCESS *info = reinterpret_cast<AUTHORITY_INFO_ACCESS *>(q_X509V3_EXT_d2i(ext));
670
671             QVariantMap result;
672             for (int i=0; i < q_SKM_sk_num(ACCESS_DESCRIPTION, info); i++) {
673                 ACCESS_DESCRIPTION *ad = q_SKM_sk_value(ACCESS_DESCRIPTION, info, i);
674
675                 GENERAL_NAME *name = ad->location;
676                 if (name->type == GEN_URI) {
677                     int len = q_ASN1_STRING_length(name->d.uniformResourceIdentifier);
678                     if (len < 0 || len >= 8192) {
679                         // broken name
680                         continue;
681                     }
682
683                     const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(name->d.uniformResourceIdentifier));
684                     const QString uri = QString::fromUtf8(uriStr, len);
685
686                     result[QString::fromUtf8(QSslCertificatePrivate::asn1ObjectName(ad->method))] = uri;
687                 } else {
688                     qWarning() << "Strange location type" << name->type;
689                 }
690             }
691
692 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
693             q_sk_pop_free((_STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
694 #else
695             q_sk_pop_free((STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
696 #endif
697             return result;
698         }
699         break;
700     case NID_subject_key_identifier:
701         {
702             void *ext_internal = q_X509V3_EXT_d2i(ext);
703
704             // we cast away the const-ness here because some versions of openssl
705             // don't use const for the parameters in the functions pointers stored
706             // in the object.
707             X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext));
708
709             return QVariant(QString::fromUtf8(meth->i2s(meth, ext_internal)));
710         }
711         break;
712     case NID_authority_key_identifier:
713         {
714             AUTHORITY_KEYID *auth_key = reinterpret_cast<AUTHORITY_KEYID *>(q_X509V3_EXT_d2i(ext));
715
716             QVariantMap result;
717
718             // keyid
719             if (auth_key->keyid) {
720                 QByteArray keyid(reinterpret_cast<const char *>(auth_key->keyid->data),
721                                  auth_key->keyid->length);
722                 result[QLatin1String("keyid")] = keyid.toHex();
723             }
724
725             // issuer
726             // TODO: GENERAL_NAMES
727
728             // serial
729             if (auth_key->serial)
730                 result[QLatin1String("serial")] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial);
731
732             q_AUTHORITY_KEYID_free(auth_key);
733             return result;
734         }
735         break;
736     }
737
738     return QVariant();
739 }
740
741 QSslCertificateExtension QSslCertificatePrivate::convertExtension(X509_EXTENSION *ext)
742 {
743     QSslCertificateExtension result;
744
745     ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext);
746     QByteArray oid = QSslCertificatePrivate::asn1ObjectId(obj);
747     QByteArray name = QSslCertificatePrivate::asn1ObjectName(obj);
748
749     result.d->oid = QString::fromUtf8(oid);
750     result.d->name = QString::fromUtf8(name);
751
752     bool critical = q_X509_EXTENSION_get_critical(ext);
753     result.d->critical = critical;
754
755     // Lets see if we have custom support for this one
756     QVariant extensionValue = x509ExtensionToValue(ext);
757     if (extensionValue.isValid()) {
758         result.d->value = extensionValue;
759         result.d->supported = true;
760
761         return result;
762     }
763
764     extensionValue = x509UnknownExtensionToValue(ext);
765     if (extensionValue.isValid()) {
766         result.d->value = extensionValue;
767         result.d->supported = false;
768         return result;
769     }
770
771     return result;
772 }
773
774 /*!
775     Returns a list containing the X509 extensions of this certificate.
776     \since 5.0
777  */
778 QList<QSslCertificateExtension> QSslCertificate::extensions() const
779 {
780     QList<QSslCertificateExtension> result;
781
782     if (!d->x509)
783         return result;
784
785     int count = q_X509_get_ext_count(d->x509);
786
787     for (int i=0; i < count; i++) {
788         X509_EXTENSION *ext = q_X509_get_ext(d->x509, i);
789         result << QSslCertificatePrivate::convertExtension(ext);
790     }
791
792     return result;
793 }
794
795 /*!
796     Returns this certificate converted to a PEM (Base64) encoded
797     representation.
798 */
799 QByteArray QSslCertificate::toPem() const
800 {
801     if (!d->x509)
802         return QByteArray();
803     return d->QByteArray_from_X509(d->x509, QSsl::Pem);
804 }
805
806 /*!
807     Returns this certificate converted to a DER (binary) encoded
808     representation.
809 */
810 QByteArray QSslCertificate::toDer() const
811 {
812     if (!d->x509)
813         return QByteArray();
814     return d->QByteArray_from_X509(d->x509, QSsl::Der);
815 }
816
817 /*!
818     Returns this certificate converted to a human-readable text
819     representation.
820
821     \since 5.0
822 */
823 QByteArray QSslCertificate::toText() const
824 {
825     if (!d->x509)
826         return QByteArray();
827     return d->text_from_X509(d->x509);
828 }
829
830 /*!
831     Searches all files in the \a path for certificates encoded in the
832     specified \a format and returns them in a list. \e must be a file or a
833     pattern matching one or more files, as specified by \a syntax.
834
835     Example:
836
837     \snippet code/src_network_ssl_qsslcertificate.cpp 0
838
839     \sa fromData()
840 */
841 QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
842                                                  QSsl::EncodingFormat format,
843                                                  QRegExp::PatternSyntax syntax)
844 {
845     // $, (,), *, +, ., ?, [, ,], ^, {, | and }.
846     int pos = -1;
847     if (syntax == QRegExp::Wildcard)
848         pos = path.indexOf(QRegExp(QLatin1String("[^\\][\\*\\?\\[\\]]")));
849     else if (syntax != QRegExp::FixedString)
850         pos = path.indexOf(QRegExp(QLatin1String("[^\\][\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]")));
851     QString pathPrefix = path.left(pos); // == path if pos < 0
852     if (pos != -1)
853         pathPrefix = pathPrefix.left(pathPrefix.lastIndexOf(QLatin1Char('/')));
854
855     // Special case - if the prefix ends up being nothing, use "." instead and
856     // chop off the first two characters from the glob'ed paths.
857     int startIndex = 0;
858     if (pathPrefix.trimmed().isEmpty()) {
859         if(path.startsWith(QLatin1Char('/'))) {
860             pathPrefix = path.left(path.indexOf(QRegExp(QLatin1String("[\\*\\?\\[]"))));
861             pathPrefix = path.left(path.lastIndexOf(QLatin1Char('/')));
862         } else {
863             startIndex = 2;
864             pathPrefix = QLatin1String(".");
865         }
866     }
867
868     // The path is a file.
869     if (pos == -1 && QFileInfo(pathPrefix).isFile()) {
870         QFile file(pathPrefix);
871         if (file.open(QIODevice::ReadOnly | QIODevice::Text))
872             return QSslCertificate::fromData(file.readAll(),format);
873         return QList<QSslCertificate>();
874     }
875
876     // The path can be a file or directory.
877     QList<QSslCertificate> certs;
878     QRegExp pattern(path, Qt::CaseSensitive, syntax);
879     QDirIterator it(pathPrefix, QDir::Files, QDirIterator::FollowSymlinks | QDirIterator::Subdirectories);
880     while (it.hasNext()) {
881         QString filePath = startIndex == 0 ? it.next() : it.next().mid(startIndex);
882         if (!pattern.exactMatch(filePath))
883             continue;
884
885         QFile file(filePath);
886         if (file.open(QIODevice::ReadOnly | QIODevice::Text))
887             certs += QSslCertificate::fromData(file.readAll(),format);
888     }
889     return certs;
890 }
891
892 /*!
893     Searches for and parses all certificates in \a device that are
894     encoded in the specified \a format and returns them in a list of
895     certificates.
896
897     \sa fromData()
898 */
899 QList<QSslCertificate> QSslCertificate::fromDevice(QIODevice *device, QSsl::EncodingFormat format)
900 {
901     if (!device) {
902         qWarning("QSslCertificate::fromDevice: cannot read from a null device");
903         return QList<QSslCertificate>();
904     }
905     return fromData(device->readAll(), format);
906 }
907
908 /*!
909     Searches for and parses all certificates in \a data that are
910     encoded in the specified \a format and returns them in a list of
911     certificates.
912
913     \sa fromDevice()
914 */
915 QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::EncodingFormat format)
916 {
917     return (format == QSsl::Pem)
918         ? QSslCertificatePrivate::certificatesFromPem(data)
919         : QSslCertificatePrivate::certificatesFromDer(data);
920 }
921
922 /*!
923     Verifies a certificate chain. The chain to be verified is passed in the
924     \a certificateChain parameter. The first certificate in the list should
925     be the leaf certificate of the chain to be verified. If \a hostName is
926     specified then the certificate is also checked to see if it is valid for
927     the specified host name.
928
929     Note that the root (CA) certificate should not be included in the list to be verified,
930     this will be looked up automatically either using the CA list specified by
931     QSslSocket::defaultCaCertificates() or, if possible, it will be loaded on demand
932     on Unix.
933
934     \since 5.0
935  */
936 QList<QSslError> QSslCertificate::verify(QList<QSslCertificate> certificateChain, const QString &hostName)
937 {
938     return QSslSocketBackendPrivate::verify(certificateChain, hostName);
939 }
940
941 void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat format)
942 {
943     if (!data.isEmpty()) {
944         QList<QSslCertificate> certs = (format == QSsl::Pem)
945             ? certificatesFromPem(data, 1)
946             : certificatesFromDer(data, 1);
947         if (!certs.isEmpty()) {
948             *this = *certs.first().d;
949             if (x509)
950                 x509 = q_X509_dup(x509);
951         }
952     }
953 }
954
955 #define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
956 #define ENDCERTSTRING "-----END CERTIFICATE-----"
957
958 // ### refactor against QSsl::pemFromDer() etc. (to avoid redundant implementations)
959 QByteArray QSslCertificatePrivate::QByteArray_from_X509(X509 *x509, QSsl::EncodingFormat format)
960 {
961     if (!x509) {
962         qWarning("QSslSocketBackendPrivate::X509_to_QByteArray: null X509");
963         return QByteArray();
964     }
965
966     // Use i2d_X509 to convert the X509 to an array.
967     int length = q_i2d_X509(x509, 0);
968     QByteArray array;
969     array.resize(length);
970     char *data = array.data();
971     char **dataP = &data;
972     unsigned char **dataPu = (unsigned char **)dataP;
973     if (q_i2d_X509(x509, dataPu) < 0)
974         return QByteArray();
975
976     if (format == QSsl::Der)
977         return array;
978
979     // Convert to Base64 - wrap at 64 characters.
980     array = array.toBase64();
981     QByteArray tmp;
982     for (int i = 0; i <= array.size() - 64; i += 64) {
983         tmp += QByteArray::fromRawData(array.data() + i, 64);
984         tmp += '\n';
985     }
986     if (int remainder = array.size() % 64) {
987         tmp += QByteArray::fromRawData(array.data() + array.size() - remainder, remainder);
988         tmp += '\n';
989     }
990
991     return BEGINCERTSTRING "\n" + tmp + ENDCERTSTRING "\n";
992 }
993
994 QByteArray QSslCertificatePrivate::text_from_X509(X509 *x509)
995 {
996     if (!x509) {
997         qWarning("QSslSocketBackendPrivate::text_from_X509: null X509");
998         return QByteArray();
999     }
1000
1001     QByteArray result;
1002     BIO *bio = q_BIO_new(q_BIO_s_mem());
1003     if (!bio)
1004       return result;
1005
1006     q_X509_print(bio, x509);
1007
1008     QVarLengthArray<char, 16384> data;
1009     int count = q_BIO_read(bio, data.data(), 16384);
1010     if ( count > 0 ) {
1011         result = QByteArray( data.data(), count );
1012     }
1013
1014     q_BIO_free(bio);
1015
1016     return result;
1017 }
1018
1019 QByteArray QSslCertificatePrivate::asn1ObjectId(ASN1_OBJECT *object)
1020 {
1021     char buf[80]; // The openssl docs a buffer length of 80 should be more than enough
1022     q_OBJ_obj2txt(buf, sizeof(buf), object, 1); // the 1 says always use the oid not the long name
1023
1024     return QByteArray(buf);
1025 }
1026
1027
1028 QByteArray QSslCertificatePrivate::asn1ObjectName(ASN1_OBJECT *object)
1029 {
1030     int nid = q_OBJ_obj2nid(object);
1031     if (nid != NID_undef)
1032         return QByteArray(q_OBJ_nid2sn(nid));
1033
1034     return asn1ObjectId(object);
1035 }
1036
1037 static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
1038 {
1039     QMap<QByteArray, QString> info;
1040     for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) {
1041         X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i);
1042
1043         QByteArray name = QSslCertificatePrivate::asn1ObjectName(q_X509_NAME_ENTRY_get_object(e));
1044         unsigned char *data = 0;
1045         int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
1046         info.insertMulti(name, QString::fromUtf8((char*)data, size));
1047         q_CRYPTO_free(data);
1048     }
1049
1050     return info;
1051 }
1052
1053 QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509)
1054 {
1055     QSslCertificate certificate;
1056     if (!x509 || !QSslSocket::supportsSsl())
1057         return certificate;
1058
1059     ASN1_TIME *nbef = q_X509_get_notBefore(x509);
1060     ASN1_TIME *naft = q_X509_get_notAfter(x509);
1061     certificate.d->notValidBefore = q_getTimeFromASN1(nbef);
1062     certificate.d->notValidAfter = q_getTimeFromASN1(naft);
1063     certificate.d->null = false;
1064     certificate.d->x509 = q_X509_dup(x509);
1065
1066     return certificate;
1067 }
1068
1069 static bool matchLineFeed(const QByteArray &pem, int *offset)
1070 {
1071     char ch = 0;
1072
1073     // ignore extra whitespace at the end of the line
1074     while (*offset < pem.size() && (ch = pem.at(*offset)) == ' ')
1075         ++*offset;
1076
1077     if (ch == '\n') {
1078         *offset += 1;
1079         return true;
1080     }
1081     if (ch == '\r' && pem.size() > (*offset + 1) && pem.at(*offset + 1) == '\n') {
1082         *offset += 2;
1083         return true;
1084     }
1085     return false;
1086 }
1087
1088 QList<QSslCertificate> QSslCertificatePrivate::certificatesFromPem(const QByteArray &pem, int count)
1089 {
1090     QList<QSslCertificate> certificates;
1091     QSslSocketPrivate::ensureInitialized();
1092
1093     int offset = 0;
1094     while (count == -1 || certificates.size() < count) {
1095         int startPos = pem.indexOf(BEGINCERTSTRING, offset);
1096         if (startPos == -1)
1097             break;
1098         startPos += sizeof(BEGINCERTSTRING) - 1;
1099         if (!matchLineFeed(pem, &startPos))
1100             break;
1101
1102         int endPos = pem.indexOf(ENDCERTSTRING, startPos);
1103         if (endPos == -1)
1104             break;
1105
1106         offset = endPos + sizeof(ENDCERTSTRING) - 1;
1107         if (offset < pem.size() && !matchLineFeed(pem, &offset))
1108             break;
1109
1110         QByteArray decoded = QByteArray::fromBase64(
1111             QByteArray::fromRawData(pem.data() + startPos, endPos - startPos));
1112 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
1113         const unsigned char *data = (const unsigned char *)decoded.data();
1114 #else
1115         unsigned char *data = (unsigned char *)decoded.data();
1116 #endif
1117
1118         if (X509 *x509 = q_d2i_X509(0, &data, decoded.size())) {
1119             certificates << QSslCertificate_from_X509(x509);
1120             q_X509_free(x509);
1121         }
1122     }
1123
1124     return certificates;
1125 }
1126
1127 QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteArray &der, int count)
1128 {
1129     QList<QSslCertificate> certificates;
1130     QSslSocketPrivate::ensureInitialized();
1131
1132
1133 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
1134         const unsigned char *data = (const unsigned char *)der.data();
1135 #else
1136         unsigned char *data = (unsigned char *)der.data();
1137 #endif
1138     int size = der.size();
1139
1140     while (count == -1 || certificates.size() < count) {
1141         if (X509 *x509 = q_d2i_X509(0, &data, size)) {
1142             certificates << QSslCertificate_from_X509(x509);
1143             q_X509_free(x509);
1144         } else {
1145             break;
1146         }
1147         size -= ((char *)data - der.data());
1148     }
1149
1150     return certificates;
1151 }
1152
1153 // These certificates are known to be fraudulent and were created during the comodo
1154 // compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
1155 static const char *certificate_blacklist[] = {
1156     "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e", "mail.google.com", // Comodo
1157     "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06", "www.google.com", // Comodo
1158     "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3", "login.yahoo.com", // Comodo
1159     "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29", "login.yahoo.com", // Comodo
1160     "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71", "login.yahoo.com", // Comodo
1161     "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47", "login.skype.com", // Comodo
1162     "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43", "addons.mozilla.org", // Comodo
1163     "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0", "login.live.com", // Comodo
1164     "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0", "global trustee", // Comodo
1165
1166     "05:e2:e6:a4:cd:09:ea:54:d6:65:b0:75:fe:22:a2:56", "*.google.com", // leaf certificate issued by DigiNotar
1167     "0c:76:da:9c:91:0c:4e:2c:9e:fe:15:d0:58:93:3c:4c", "DigiNotar Root CA", // DigiNotar root
1168     "f1:4a:13:f4:87:2b:56:dc:39:df:84:ca:7a:a1:06:49", "DigiNotar Services CA", // DigiNotar intermediate signed by DigiNotar Root
1169     "36:16:71:55:43:42:1b:9d:e6:cb:a3:64:41:df:24:38", "DigiNotar Services 1024 CA", // DigiNotar intermediate signed by DigiNotar Root
1170     "0a:82:bd:1e:14:4e:88:14:d7:5b:1a:55:27:be:bf:3e", "DigiNotar Root CA G2", // other DigiNotar Root CA
1171     "a4:b6:ce:e3:2e:d3:35:46:26:3c:b3:55:3a:a8:92:21", "CertiID Enterprise Certificate Authority", // DigiNotar intermediate signed by "DigiNotar Root CA G2"
1172     "5b:d5:60:9c:64:17:68:cf:21:0e:35:fd:fb:05:ad:41", "DigiNotar Qualified CA", // DigiNotar intermediate signed by DigiNotar Root
1173
1174     "46:9c:2c:b0",                                     "DigiNotar Services 1024 CA", // DigiNotar intermediate cross-signed by Entrust
1175     "07:27:10:0d",                                     "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust
1176     "07:27:0f:f9",                                     "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust
1177     "07:27:10:03",                                     "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust
1178     "01:31:69:b0",                                     "DigiNotar PKIoverheid CA Overheid en Bedrijven", // DigiNotar intermediate cross-signed by the Dutch government
1179     "01:31:34:bf",                                     "DigiNotar PKIoverheid CA Organisatie - G2", // DigiNotar intermediate cross-signed by the Dutch government
1180     "d6:d0:29:77:f1:49:fd:1a:83:f2:b9:ea:94:8c:5c:b4", "DigiNotar Extended Validation CA", // DigiNotar intermediate signed by DigiNotar EV Root
1181     "1e:7d:7a:53:3d:45:30:41:96:40:0f:71:48:1f:45:04", "DigiNotar Public CA 2025", // DigiNotar intermediate
1182 //    "(has not been seen in the wild so far)", "DigiNotar Public CA - G2", // DigiNotar intermediate
1183 //    "(has not been seen in the wild so far)", "Koninklijke Notariele Beroepsorganisatie CA", // compromised during DigiNotar breach
1184 //    "(has not been seen in the wild so far)", "Stichting TTP Infos CA," // compromised during DigiNotar breach
1185     "46:9c:2c:af",                                     "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust
1186     "46:9c:3c:c9",                                     "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust
1187
1188     "07:27:14:a9",                                     "Digisign Server ID (Enrich)", // (Malaysian) Digicert Sdn. Bhd. cross-signed by Verizon CyberTrust
1189     "4c:0e:63:6a",                                     "Digisign Server ID - (Enrich)", // (Malaysian) Digicert Sdn. Bhd. cross-signed by Entrust
1190     "72:03:21:05:c5:0c:08:57:3d:8e:a5:30:4e:fe:e8:b0", "UTN-USERFirst-Hardware", // comodogate test certificate
1191     "41",                                              "MD5 Collisions Inc. (http://www.phreedom.org/md5)", // http://www.phreedom.org/research/rogue-ca/
1192     0
1193 };
1194
1195 bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
1196 {
1197     for (int a = 0; certificate_blacklist[a] != 0; a++) {
1198         QString blacklistedCommonName = QString::fromUtf8(certificate_blacklist[(a+1)]);
1199         if (certificate.serialNumber() == certificate_blacklist[a++] &&
1200             (certificate.subjectInfo(QSslCertificate::CommonName).contains(blacklistedCommonName) ||
1201              certificate.issuerInfo(QSslCertificate::CommonName).contains(blacklistedCommonName)))
1202             return true;
1203     }
1204     return false;
1205 }
1206
1207 #ifndef QT_NO_DEBUG_STREAM
1208 QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
1209 {
1210     debug << "QSslCertificate("
1211           << certificate.version()
1212           << ',' << certificate.serialNumber()
1213           << ',' << certificate.digest().toBase64()
1214           << ',' << certificate.issuerInfo(QSslCertificate::Organization)
1215           << ',' << certificate.subjectInfo(QSslCertificate::Organization)
1216           << ',' << certificate.subjectAlternativeNames()
1217 #ifndef QT_NO_DATESTRING
1218           << ',' << certificate.effectiveDate()
1219           << ',' << certificate.expiryDate()
1220 #endif
1221           << ')';
1222     return debug;
1223 }
1224 QDebug operator<<(QDebug debug, QSslCertificate::SubjectInfo info)
1225 {
1226     switch (info) {
1227     case QSslCertificate::Organization: debug << "Organization"; break;
1228     case QSslCertificate::CommonName: debug << "CommonName"; break;
1229     case QSslCertificate::CountryName: debug << "CountryName"; break;
1230     case QSslCertificate::LocalityName: debug << "LocalityName"; break;
1231     case QSslCertificate::OrganizationalUnitName: debug << "OrganizationalUnitName"; break;
1232     case QSslCertificate::StateOrProvinceName: debug << "StateOrProvinceName"; break;
1233     case QSslCertificate::DistinguishedNameQualifier: debug << "DistinguishedNameQualifier"; break;
1234     case QSslCertificate::SerialNumber: debug << "SerialNumber"; break;
1235     case QSslCertificate::EmailAddress: debug << "EmailAddress"; break;
1236     }
1237     return debug;
1238 }
1239 #endif
1240
1241 QT_END_NAMESPACE