util/src/network/ssl/qsslcertificate.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtNetwork module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    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
       
    66     default, QSslCertificate constructs a null certificate. To check
       
    67     if the certificate is valid, call isValid(). A null certificate is
       
    68     invalid, but an invalid certificate is not necessarily null. If
       
    69     you want to reset all contents in a certificate, call clear().
       
    70 
       
    71     After loading a certificate, you can find information about the
       
    72     certificate, its subject, and its issuer, by calling one of the
       
    73     many accessor functions, including version(), serialNumber(),
       
    74     issuerInfo() and subjectInfo(). You can call effectiveDate() and
       
    75     expiryDate() to check when the certificate starts being
       
    76     effective and when it expires.
       
    77     The publicKey() function returns the certificate
       
    78     subject's public key as a QSslKey. You can call issuerInfo() or
       
    79     subjectInfo() to get detailed information about the certificate
       
    80     issuer and its subject.
       
    81 
       
    82     Internally, QSslCertificate is stored as an X509 structure. You
       
    83     can access this handle by calling handle(), but the results are
       
    84     likely to not be portable.
       
    85 
       
    86     \sa QSslSocket, QSslKey, QSslCipher, QSslError
       
    87 */
       
    88 
       
    89 /*!
       
    90     \enum QSslCertificate::SubjectInfo
       
    91 
       
    92     Describes keys that you can pass to QSslCertificate::issuerInfo() or
       
    93     QSslCertificate::subjectInfo() to get information about the certificate
       
    94     issuer or subject.
       
    95 
       
    96     \value Organization "O" The name of the organization.
       
    97 
       
    98     \value CommonName "CN" The common name; most often this is used to store
       
    99     the host name.
       
   100 
       
   101     \value LocalityName "L" The locality.
       
   102 
       
   103     \value OrganizationalUnitName "OU" The organizational unit name.
       
   104 
       
   105     \value CountryName "C" The country.
       
   106 
       
   107     \value StateOrProvinceName "ST" The state or province.
       
   108 */
       
   109 
       
   110 #include "qsslsocket_openssl_symbols_p.h"
       
   111 #include "qsslcertificate.h"
       
   112 #include "qsslcertificate_p.h"
       
   113 #include "qsslkey.h"
       
   114 #include "qsslkey_p.h"
       
   115 
       
   116 #include <QtCore/qatomic.h>
       
   117 #include <QtCore/qdatetime.h>
       
   118 #include <QtCore/qdebug.h>
       
   119 #include <QtCore/qdir.h>
       
   120 #include <QtCore/qdiriterator.h>
       
   121 #include <QtCore/qfile.h>
       
   122 #include <QtCore/qfileinfo.h>
       
   123 #include <QtCore/qmap.h>
       
   124 #include <QtCore/qstring.h>
       
   125 #include <QtCore/qstringlist.h>
       
   126 
       
   127 QT_BEGIN_NAMESPACE
       
   128 
       
   129 // forward declaration
       
   130 static QMap<QString, QString> _q_mapFromOnelineName(char *name);
       
   131 
       
   132 /*!
       
   133     Constructs a QSslCertificate by reading \a format encoded data
       
   134     from \a device and using the first certificate found. You can
       
   135     later call isNull() to see if \a device contained a certificate,
       
   136     and if this certificate was loaded successfully.
       
   137 */
       
   138 QSslCertificate::QSslCertificate(QIODevice *device, QSsl::EncodingFormat format)
       
   139     : d(new QSslCertificatePrivate)
       
   140 {
       
   141     QSslSocketPrivate::ensureInitialized();
       
   142     if (device)
       
   143         d->init(device->readAll(), format);
       
   144 }
       
   145 
       
   146 /*!
       
   147     Constructs a QSslCertificate by parsing the \a format encoded
       
   148     \a data and using the first available certificate found. You can
       
   149     later call isNull() to see if \a data contained a certificate,
       
   150     and if this certificate was loaded successfully.
       
   151 */
       
   152 QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat format)
       
   153     : d(new QSslCertificatePrivate)
       
   154 {
       
   155     QSslSocketPrivate::ensureInitialized();
       
   156     d->init(data, format);
       
   157 }
       
   158 
       
   159 /*!
       
   160     Constructs an identical copy of \a other.
       
   161 */
       
   162 QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d)
       
   163 {
       
   164 }
       
   165 
       
   166 /*!
       
   167     Destroys the QSslCertificate.
       
   168 */
       
   169 QSslCertificate::~QSslCertificate()
       
   170 {
       
   171 }
       
   172 
       
   173 /*!
       
   174     Copies the contents of \a other into this certificate, making the two
       
   175     certificates identical.
       
   176 */
       
   177 QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other)
       
   178 {
       
   179     d = other.d;
       
   180     return *this;
       
   181 }
       
   182 
       
   183 /*!
       
   184     Returns true if this certificate is the same as \a other; otherwise
       
   185     returns false.
       
   186 */
       
   187 bool QSslCertificate::operator==(const QSslCertificate &other) const
       
   188 {
       
   189     if (d == other.d)
       
   190         return true;
       
   191     if (d->null && other.d->null)
       
   192         return true;
       
   193     if (d->x509 && other.d->x509)
       
   194         return q_X509_cmp(d->x509, other.d->x509) == 0;
       
   195     return false;
       
   196 }
       
   197 
       
   198 /*!
       
   199     \fn bool QSslCertificate::operator!=(const QSslCertificate &other) const
       
   200 
       
   201     Returns true if this certificate is not the same as \a other; otherwise
       
   202     returns false.
       
   203 */
       
   204 
       
   205 /*!
       
   206     Returns true if this is a null certificate (i.e., a certificate
       
   207     with no contents); otherwise returns false.
       
   208 
       
   209     By default, QSslCertificate constructs a null certificate.
       
   210 
       
   211     \sa isValid(), clear()
       
   212 */
       
   213 bool QSslCertificate::isNull() const
       
   214 {
       
   215     return d->null;
       
   216 }
       
   217 
       
   218 /*!
       
   219     Returns true if this certificate is valid; otherwise returns
       
   220     false.
       
   221 
       
   222     Note: Currently, this function only checks that the current
       
   223     data-time is within the date-time range during which the
       
   224     certificate is considered valid. No other checks are
       
   225     currently performed.
       
   226 
       
   227     \sa isNull()
       
   228 */
       
   229 bool QSslCertificate::isValid() const
       
   230 {
       
   231     const QDateTime currentTime = QDateTime::currentDateTime();
       
   232     return currentTime >= d->notValidBefore && currentTime <= d->notValidAfter;
       
   233 }
       
   234 
       
   235 /*!
       
   236     Clears the contents of this certificate, making it a null
       
   237     certificate.
       
   238 
       
   239     \sa isNull()
       
   240 */
       
   241 void QSslCertificate::clear()
       
   242 {
       
   243     if (isNull())
       
   244         return;
       
   245     d = new QSslCertificatePrivate;
       
   246 }
       
   247 
       
   248 /*!
       
   249     Returns the certificate's version string.
       
   250 */
       
   251 QByteArray QSslCertificate::version() const
       
   252 {
       
   253     if (d->versionString.isEmpty() && d->x509)
       
   254         d->versionString =
       
   255             QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
       
   256 
       
   257     return d->versionString;
       
   258 }
       
   259 
       
   260 /*!
       
   261     Returns the certificate's serial number string in decimal format.
       
   262 */
       
   263 QByteArray QSslCertificate::serialNumber() const
       
   264 {
       
   265     if (d->serialNumberString.isEmpty() && d->x509)
       
   266         d->serialNumberString =
       
   267             QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->serialNumber)));
       
   268 
       
   269     return d->serialNumberString;
       
   270 }
       
   271 
       
   272 /*!
       
   273     Returns a cryptographic digest of this certificate. By default,
       
   274     an MD5 digest will be generated, but you can also specify a
       
   275     custom \a algorithm.
       
   276 */
       
   277 QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) const
       
   278 {
       
   279     return QCryptographicHash::hash(toDer(), algorithm);
       
   280 }
       
   281 
       
   282 static QString _q_SubjectInfoToString(QSslCertificate::SubjectInfo info)
       
   283 {
       
   284     QString str;
       
   285     switch (info) {
       
   286     case QSslCertificate::Organization: str = QLatin1String("O"); break;
       
   287     case QSslCertificate::CommonName: str = QLatin1String("CN"); break;
       
   288     case QSslCertificate::LocalityName: str = QLatin1String("L"); break;
       
   289     case QSslCertificate::OrganizationalUnitName: str = QLatin1String("OU"); break;
       
   290     case QSslCertificate::CountryName: str = QLatin1String("C"); break;
       
   291     case QSslCertificate::StateOrProvinceName: str = QLatin1String("ST"); break;
       
   292     }
       
   293     return str;
       
   294 }
       
   295 
       
   296 /*!
       
   297   \fn QString QSslCertificate::issuerInfo(SubjectInfo subject) const
       
   298   
       
   299   Returns the issuer information for the \a subject from the
       
   300   certificate, or an empty string if there is no information for
       
   301   \a subject in the certificate.
       
   302 
       
   303   \sa subjectInfo()
       
   304 */
       
   305 QString QSslCertificate::issuerInfo(SubjectInfo info) const
       
   306 {
       
   307     // lazy init
       
   308     if (d->issuerInfo.isEmpty() && d->x509)
       
   309         d->issuerInfo =
       
   310                 _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(d->x509), 0, 0));
       
   311 
       
   312     return d->issuerInfo.value(_q_SubjectInfoToString(info));
       
   313 }
       
   314 
       
   315 /*!
       
   316   Returns the issuer information for \a tag from the certificate,
       
   317   or an empty string if there is no information for \a tag in the
       
   318   certificate.
       
   319 
       
   320   \sa subjectInfo()
       
   321 */
       
   322 QString QSslCertificate::issuerInfo(const QByteArray &tag) const
       
   323 {
       
   324     // lazy init
       
   325     if (d->issuerInfo.isEmpty() && d->x509)
       
   326         d->issuerInfo =
       
   327                 _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_issuer_name(d->x509), 0, 0));
       
   328 
       
   329     return d->issuerInfo.value(QString::fromLatin1(tag));
       
   330 }
       
   331 
       
   332 /*!
       
   333 
       
   334   \fn QString QSslCertificate::subjectInfo(SubjectInfo subject) const
       
   335 
       
   336   Returns the information for the \a subject, or an empty string if
       
   337   there is no information for \a subject in the certificate.
       
   338 
       
   339     \sa issuerInfo()
       
   340 */
       
   341 QString QSslCertificate::subjectInfo(SubjectInfo info) const
       
   342 {
       
   343     // lazy init
       
   344     if (d->subjectInfo.isEmpty() && d->x509)
       
   345         d->subjectInfo =
       
   346                 _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(d->x509), 0, 0));
       
   347 
       
   348     return d->subjectInfo.value(_q_SubjectInfoToString(info));
       
   349 }
       
   350 
       
   351 /*!
       
   352     Returns the subject information for \a tag, or an empty string if
       
   353     there is no information for \a tag in the certificate.
       
   354 
       
   355     \sa issuerInfo()
       
   356 */
       
   357 QString QSslCertificate::subjectInfo(const QByteArray &tag) const
       
   358 {
       
   359     // lazy init
       
   360     if (d->subjectInfo.isEmpty() && d->x509)
       
   361         d->subjectInfo =
       
   362                 _q_mapFromOnelineName(q_X509_NAME_oneline(q_X509_get_subject_name(d->x509), 0, 0));
       
   363 
       
   364     return d->subjectInfo.value(QString::fromLatin1(tag));
       
   365 }
       
   366 
       
   367 /*!
       
   368   Returns the list of alternative subject names for this
       
   369   certificate. The alternate subject names typically contain host
       
   370   names, optionally with wildcards, that are valid for this
       
   371   certificate.
       
   372   
       
   373   These names are tested against the connected peer's host name, if
       
   374   either the subject information for \l CommonName doesn't define a
       
   375   valid host name, or the subject info name doesn't match the peer's
       
   376   host name.
       
   377   
       
   378   \sa subjectInfo()
       
   379 */
       
   380 QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubjectNames() const
       
   381 {
       
   382     QMultiMap<QSsl::AlternateNameEntryType, QString> result;
       
   383 
       
   384     if (!d->x509)
       
   385         return result;
       
   386 
       
   387     STACK_OF(GENERAL_NAME) *altNames = (STACK_OF(GENERAL_NAME)*)q_X509_get_ext_d2i(d->x509, NID_subject_alt_name, 0, 0);
       
   388 
       
   389     if (altNames) {
       
   390         for (int i = 0; i < q_sk_GENERAL_NAME_num(altNames); ++i) {
       
   391             const GENERAL_NAME *genName = q_sk_GENERAL_NAME_value(altNames, i);
       
   392             if (genName->type != GEN_DNS && genName->type != GEN_EMAIL)
       
   393                 continue;
       
   394 
       
   395             int len = q_ASN1_STRING_length(genName->d.ia5);
       
   396             if (len < 0 || len >= 8192) {
       
   397                 // broken name
       
   398                 continue;
       
   399             }
       
   400 
       
   401             const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(genName->d.ia5));
       
   402             const QString altName = QString::fromLatin1(altNameStr, len);
       
   403             if (genName->type == GEN_DNS)
       
   404                 result.insert(QSsl::DnsEntry, altName);
       
   405             else if (genName->type == GEN_EMAIL)
       
   406                 result.insert(QSsl::EmailEntry, altName);
       
   407         }
       
   408         q_sk_pop_free((STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_sk_free));
       
   409     }
       
   410 
       
   411     return result;
       
   412 }
       
   413 
       
   414 /*!
       
   415   Returns the date-time that the certificate becomes valid, or an
       
   416   empty QDateTime if this is a null certificate.
       
   417 
       
   418   \sa expiryDate()
       
   419 */
       
   420 QDateTime QSslCertificate::effectiveDate() const
       
   421 {
       
   422     return d->notValidBefore;
       
   423 }
       
   424 
       
   425 /*!
       
   426   Returns the date-time that the certificate expires, or an empty
       
   427   QDateTime if this is a null certificate.
       
   428 
       
   429     \sa effectiveDate()
       
   430 */
       
   431 QDateTime QSslCertificate::expiryDate() const
       
   432 {
       
   433     return d->notValidAfter;
       
   434 }
       
   435 
       
   436 /*!
       
   437     Returns a pointer to the native certificate handle, if there is
       
   438     one, or a null pointer otherwise.
       
   439 
       
   440     You can use this handle, together with the native API, to access
       
   441     extended information about the certificate.
       
   442 
       
   443     \warning Use of this function has a high probability of being
       
   444     non-portable, and its return value may vary from platform to
       
   445     platform or change from minor release to minor release.
       
   446 */
       
   447 Qt::HANDLE QSslCertificate::handle() const
       
   448 {
       
   449     return Qt::HANDLE(d->x509);
       
   450 }
       
   451 
       
   452 /*!
       
   453     Returns the certificate subject's public key.
       
   454 */
       
   455 QSslKey QSslCertificate::publicKey() const
       
   456 {
       
   457     if (!d->x509)
       
   458         return QSslKey();
       
   459 
       
   460     QSslKey key;
       
   461 
       
   462     key.d->type = QSsl::PublicKey;
       
   463     X509_PUBKEY *xkey = d->x509->cert_info->key;
       
   464     EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey);
       
   465     Q_ASSERT(pkey);
       
   466 
       
   467     if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) {
       
   468         key.d->rsa = q_EVP_PKEY_get1_RSA(pkey);
       
   469         key.d->algorithm = QSsl::Rsa;
       
   470         key.d->isNull = false;
       
   471     } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) {
       
   472         key.d->dsa = q_EVP_PKEY_get1_DSA(pkey);
       
   473         key.d->algorithm = QSsl::Dsa;
       
   474         key.d->isNull = false;
       
   475     } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) {
       
   476         // DH unsupported
       
   477     } else {
       
   478         // error?
       
   479     }
       
   480 
       
   481     q_EVP_PKEY_free(pkey);
       
   482     return key;
       
   483 }
       
   484 
       
   485 /*!
       
   486     Returns this certificate converted to a PEM (Base64) encoded
       
   487     representation.
       
   488 */
       
   489 QByteArray QSslCertificate::toPem() const
       
   490 {
       
   491     if (!d->x509)
       
   492         return QByteArray();
       
   493     return d->QByteArray_from_X509(d->x509, QSsl::Pem);
       
   494 }
       
   495 
       
   496 /*!
       
   497     Returns this certificate converted to a DER (binary) encoded
       
   498     representation.
       
   499 */
       
   500 QByteArray QSslCertificate::toDer() const
       
   501 {
       
   502     if (!d->x509)
       
   503         return QByteArray();
       
   504     return d->QByteArray_from_X509(d->x509, QSsl::Der);
       
   505 }
       
   506 
       
   507 /*!
       
   508     Searches all files in the \a path for certificates encoded in the
       
   509     specified \a format and returns them in a list. \e must be a file or a
       
   510     pattern matching one or more files, as specified by \a syntax.
       
   511 
       
   512     Example:
       
   513     
       
   514     \snippet doc/src/snippets/code/src_network_ssl_qsslcertificate.cpp 0
       
   515 
       
   516     \sa fromData()
       
   517 */
       
   518 QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
       
   519                                                  QSsl::EncodingFormat format,
       
   520                                                  QRegExp::PatternSyntax syntax)
       
   521 {
       
   522     // $, (,), *, +, ., ?, [, ,], ^, {, | and }.
       
   523     int pos = -1;
       
   524     if (syntax == QRegExp::Wildcard)
       
   525         pos = path.indexOf(QRegExp(QLatin1String("[^\\][\\*\\?\\[\\]]")));
       
   526     else if (syntax != QRegExp::FixedString)
       
   527         pos = path.indexOf(QRegExp(QLatin1String("[^\\][\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]")));
       
   528     QString pathPrefix = path.left(pos); // == path if pos < 0
       
   529     if (pos != -1)
       
   530         pathPrefix = pathPrefix.left(pathPrefix.lastIndexOf(QLatin1Char('/')));
       
   531 
       
   532     // Special case - if the prefix ends up being nothing, use "." instead and
       
   533     // chop off the first two characters from the glob'ed paths.
       
   534     int startIndex = 0;
       
   535     if (pathPrefix.trimmed().isEmpty()) {
       
   536         startIndex = 2;
       
   537         pathPrefix = QLatin1String(".");
       
   538     }
       
   539 
       
   540     // The path is a file.
       
   541     if (pos == -1 && QFileInfo(pathPrefix).isFile()) {
       
   542         QFile file(pathPrefix);
       
   543         if (file.open(QIODevice::ReadOnly | QIODevice::Text))
       
   544             return QSslCertificate::fromData(file.readAll(),format);
       
   545         return QList<QSslCertificate>();
       
   546     }
       
   547 
       
   548     // The path can be a file or directory.
       
   549     QList<QSslCertificate> certs;
       
   550     QRegExp pattern(path, Qt::CaseSensitive, syntax);
       
   551     QDirIterator it(pathPrefix, QDir::Files, QDirIterator::FollowSymlinks | QDirIterator::Subdirectories);
       
   552     while (it.hasNext()) {
       
   553         QString filePath = startIndex == 0 ? it.next() : it.next().mid(startIndex);
       
   554         if (!pattern.exactMatch(filePath))
       
   555             continue;
       
   556 
       
   557         QFile file(filePath);
       
   558         if (file.open(QIODevice::ReadOnly | QIODevice::Text))
       
   559             certs += QSslCertificate::fromData(file.readAll(),format);
       
   560     }
       
   561     return certs;
       
   562 }
       
   563 
       
   564 /*!
       
   565     Searches for and parses all certificates in \a device that are
       
   566     encoded in the specified \a format and returns them in a list of
       
   567     certificates.
       
   568 
       
   569     \sa fromData()
       
   570 */
       
   571 QList<QSslCertificate> QSslCertificate::fromDevice(QIODevice *device, QSsl::EncodingFormat format)
       
   572 {
       
   573     if (!device) {
       
   574         qWarning("QSslCertificate::fromDevice: cannot read from a null device");
       
   575         return QList<QSslCertificate>();
       
   576     }
       
   577     return fromData(device->readAll(), format);
       
   578 }
       
   579 
       
   580 /*!
       
   581     Searches for and parses all certificates in \a data that are
       
   582     encoded in the specified \a format and returns them in a list of
       
   583     certificates.
       
   584 
       
   585     \sa fromDevice()
       
   586 */
       
   587 QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::EncodingFormat format)
       
   588 {
       
   589     return (format == QSsl::Pem)
       
   590         ? QSslCertificatePrivate::certificatesFromPem(data)
       
   591         : QSslCertificatePrivate::certificatesFromDer(data);
       
   592 }
       
   593 
       
   594 void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat format)
       
   595 {
       
   596     if (!data.isEmpty()) {
       
   597         QList<QSslCertificate> certs = (format == QSsl::Pem)
       
   598             ? certificatesFromPem(data, 1)
       
   599             : certificatesFromDer(data, 1);
       
   600         if (!certs.isEmpty()) {
       
   601             *this = *certs.first().d;
       
   602             if (x509)
       
   603                 x509 = q_X509_dup(x509);
       
   604         }
       
   605     }
       
   606 }
       
   607 
       
   608 #define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
       
   609 #define ENDCERTSTRING "-----END CERTIFICATE-----"
       
   610 
       
   611 // ### refactor against QSsl::pemFromDer() etc. (to avoid redundant implementations)
       
   612 QByteArray QSslCertificatePrivate::QByteArray_from_X509(X509 *x509, QSsl::EncodingFormat format)
       
   613 {
       
   614     if (!x509) {
       
   615         qWarning("QSslSocketBackendPrivate::X509_to_QByteArray: null X509");
       
   616         return QByteArray();
       
   617     }
       
   618 
       
   619     // Use i2d_X509 to convert the X509 to an array.
       
   620     int length = q_i2d_X509(x509, 0);
       
   621     QByteArray array;
       
   622     array.resize(length);
       
   623     char *data = array.data();
       
   624     char **dataP = &data;
       
   625     unsigned char **dataPu = (unsigned char **)dataP;
       
   626     if (q_i2d_X509(x509, dataPu) < 0)
       
   627         return QByteArray();
       
   628 
       
   629     if (format == QSsl::Der)
       
   630         return array;
       
   631 
       
   632     // Convert to Base64 - wrap at 64 characters.
       
   633     array = array.toBase64();
       
   634     QByteArray tmp;
       
   635     for (int i = 0; i <= array.size() - 64; i += 64) {
       
   636         tmp += QByteArray::fromRawData(array.data() + i, 64);
       
   637         tmp += '\n';
       
   638     }
       
   639     if (int remainder = array.size() % 64) {
       
   640         tmp += QByteArray::fromRawData(array.data() + array.size() - remainder, remainder);
       
   641         tmp += '\n';
       
   642     }
       
   643 
       
   644     return BEGINCERTSTRING "\n" + tmp + ENDCERTSTRING "\n";
       
   645 }
       
   646 
       
   647 static QMap<QString, QString> _q_mapFromOnelineName(char *name)
       
   648 {
       
   649     QMap<QString, QString> info;
       
   650     QString infoStr = QString::fromLocal8Bit(name);
       
   651     q_CRYPTO_free(name);
       
   652 
       
   653     // ### The right-hand encoding seems to allow hex (Regulierungsbeh\xC8orde)
       
   654     //entry.replace(QLatin1String("\\x"), QLatin1String("%"));
       
   655     //entry = QUrl::fromPercentEncoding(entry.toLatin1());
       
   656     // ### See RFC-4630 for more details!
       
   657 
       
   658     QRegExp rx(QLatin1String("/([A-Za-z]+)=(.+)"));
       
   659 
       
   660     int pos = 0;
       
   661     while ((pos = rx.indexIn(infoStr, pos)) != -1) {
       
   662         const QString name = rx.cap(1);
       
   663 
       
   664         QString value = rx.cap(2);
       
   665         const int valuePos = rx.pos(2);
       
   666 
       
   667         const int next = rx.indexIn(value);
       
   668         if (next == -1) {
       
   669             info.insert(name, value);
       
   670             break;
       
   671         }
       
   672 
       
   673         value = value.left(next);
       
   674         info.insert(name, value);
       
   675         pos = valuePos + value.length();
       
   676     }
       
   677 
       
   678     return info;
       
   679 }
       
   680 
       
   681 QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509)
       
   682 {
       
   683     QSslCertificate certificate;
       
   684     if (!x509 || !QSslSocket::supportsSsl())
       
   685         return certificate;
       
   686 
       
   687     ASN1_TIME *nbef = q_X509_get_notBefore(x509);
       
   688     ASN1_TIME *naft = q_X509_get_notAfter(x509);
       
   689     certificate.d->notValidBefore = q_getTimeFromASN1(nbef);
       
   690     certificate.d->notValidAfter = q_getTimeFromASN1(naft);
       
   691     certificate.d->null = false;
       
   692     certificate.d->x509 = q_X509_dup(x509);
       
   693 
       
   694     return certificate;
       
   695 }
       
   696 
       
   697 static bool matchLineFeed(const QByteArray &pem, int *offset)
       
   698 {
       
   699     char ch;
       
   700 
       
   701     // ignore extra whitespace at the end of the line
       
   702     while (*offset < pem.size() && (ch = pem.at(*offset)) == ' ')
       
   703         ++*offset;
       
   704 
       
   705     if (ch == '\n') {
       
   706         *offset += 1;
       
   707         return true;
       
   708     }
       
   709     if (ch == '\r' && pem.size() > (*offset + 1) && pem.at(*offset + 1) == '\n') {
       
   710         *offset += 2;
       
   711         return true;
       
   712     }
       
   713     return false;
       
   714 }
       
   715 
       
   716 QList<QSslCertificate> QSslCertificatePrivate::certificatesFromPem(const QByteArray &pem, int count)
       
   717 {
       
   718     QList<QSslCertificate> certificates;
       
   719     QSslSocketPrivate::ensureInitialized();
       
   720 
       
   721     int offset = 0;
       
   722     while (count == -1 || certificates.size() < count) {
       
   723         int startPos = pem.indexOf(BEGINCERTSTRING, offset);
       
   724         if (startPos == -1)
       
   725             break;
       
   726         startPos += sizeof(BEGINCERTSTRING) - 1;
       
   727         if (!matchLineFeed(pem, &startPos))
       
   728             break;
       
   729 
       
   730         int endPos = pem.indexOf(ENDCERTSTRING, startPos);
       
   731         if (endPos == -1)
       
   732             break;
       
   733 
       
   734         offset = endPos + sizeof(ENDCERTSTRING) - 1;
       
   735         if (offset < pem.size() && !matchLineFeed(pem, &offset))
       
   736             break;
       
   737 
       
   738         QByteArray decoded = QByteArray::fromBase64(
       
   739             QByteArray::fromRawData(pem.data() + startPos, endPos - startPos));
       
   740 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
       
   741         const unsigned char *data = (const unsigned char *)decoded.data();
       
   742 #else
       
   743         unsigned char *data = (unsigned char *)decoded.data();
       
   744 #endif
       
   745 
       
   746         if (X509 *x509 = q_d2i_X509(0, &data, decoded.size())) {
       
   747             certificates << QSslCertificate_from_X509(x509);
       
   748             q_X509_free(x509);
       
   749         }
       
   750     }
       
   751 
       
   752     return certificates;
       
   753 }
       
   754 
       
   755 QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteArray &der, int count)
       
   756 {
       
   757     QList<QSslCertificate> certificates;
       
   758     QSslSocketPrivate::ensureInitialized();
       
   759 
       
   760 
       
   761 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
       
   762         const unsigned char *data = (const unsigned char *)der.data();
       
   763 #else
       
   764         unsigned char *data = (unsigned char *)der.data();
       
   765 #endif
       
   766     int size = der.size();
       
   767 
       
   768     while (count == -1 || certificates.size() < count) {
       
   769         if (X509 *x509 = q_d2i_X509(0, &data, size)) {
       
   770             certificates << QSslCertificate_from_X509(x509);
       
   771             q_X509_free(x509);
       
   772         } else {
       
   773             break;
       
   774         }
       
   775         size -= ((char *)data - der.data());
       
   776     }
       
   777 
       
   778     return certificates;
       
   779 }
       
   780 
       
   781 #ifndef QT_NO_DEBUG_STREAM
       
   782 QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
       
   783 {
       
   784     debug << "QSslCertificate("
       
   785           << certificate.version()
       
   786           << ',' << certificate.serialNumber()
       
   787           << ',' << certificate.digest().toBase64()
       
   788           << ',' << certificate.issuerInfo(QSslCertificate::Organization)
       
   789           << ',' << certificate.subjectInfo(QSslCertificate::Organization)
       
   790           << ',' << certificate.alternateSubjectNames()
       
   791 #ifndef QT_NO_TEXTSTREAM
       
   792           << ',' << certificate.effectiveDate()
       
   793           << ',' << certificate.expiryDate()
       
   794 #endif
       
   795           << ')';
       
   796     return debug;
       
   797 }
       
   798 QDebug operator<<(QDebug debug, QSslCertificate::SubjectInfo info)
       
   799 {
       
   800     switch (info) {
       
   801     case QSslCertificate::Organization: debug << "Organization"; break;
       
   802     case QSslCertificate::CommonName: debug << "CommonName"; break;
       
   803     case QSslCertificate::CountryName: debug << "CountryName"; break;
       
   804     case QSslCertificate::LocalityName: debug << "LocalityName"; break;
       
   805     case QSslCertificate::OrganizationalUnitName: debug << "OrganizationalUnitName"; break;
       
   806     case QSslCertificate::StateOrProvinceName: debug << "StateOrProvinceName"; break;
       
   807     }
       
   808     return debug;
       
   809 }
       
   810 #endif
       
   811 
       
   812 QT_END_NAMESPACE