Changeset 846 for trunk/src/network/ssl


Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
1 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/network/ssl/qssl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qssl.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcertificate.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    260260/*!
    261261    Returns the certificate's serial number string in decimal format.
     262    In case the serial number cannot be converted to decimal format
     263    (i.e. if it is bigger than 4294967295, which means it does not fit into 4 bytes),
     264    its hexadecimal version is returned.
    262265*/
    263266QByteArray QSslCertificate::serialNumber() const
    264267{
    265     if (d->serialNumberString.isEmpty() && d->x509)
    266         d->serialNumberString =
    267             QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->serialNumber)));
    268 
     268    if (d->serialNumberString.isEmpty() && d->x509) {
     269        ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
     270        // if we cannot convert to a long, just output the hexadecimal number
     271        if (serialNumber->length > 4) {
     272            QByteArray hexString;
     273            hexString.reserve(serialNumber->length * 3);
     274            for (int a = 0; a < serialNumber->length; ++a) {
     275                hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2, '0');
     276                hexString += ':';
     277            }
     278            hexString.chop(1);
     279            d->serialNumberString = hexString;
     280        } else {
     281            d->serialNumberString = QByteArray::number(qlonglong(q_ASN1_INTEGER_get(serialNumber)));
     282        }
     283    }
    269284    return d->serialNumberString;
    270285}
     
    534549    int startIndex = 0;
    535550    if (pathPrefix.trimmed().isEmpty()) {
    536         startIndex = 2;
    537         pathPrefix = QLatin1String(".");
     551        if(path.startsWith(QLatin1Char('/'))) {
     552            pathPrefix = path.left(path.indexOf(QRegExp(QLatin1String("[\\*\\?\\[]"))));
     553            pathPrefix = path.left(path.lastIndexOf(QLatin1Char('/')));
     554        } else {
     555            startIndex = 2;
     556            pathPrefix = QLatin1String(".");
     557        }
    538558    }
    539559
     
    697717static bool matchLineFeed(const QByteArray &pem, int *offset)
    698718{
    699     char ch;
     719    char ch = 0;
    700720
    701721    // ignore extra whitespace at the end of the line
  • trunk/src/network/ssl/qsslcertificate.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcertificate_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcipher.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcipher.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcipher_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslconfiguration.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    486486  Returns this connection's CA certificate database. The CA certificate
    487487  database is used by the socket during the handshake phase to
    488   validate the peer's certificate. It can be moodified prior to the
    489   handshake with addCaCertificate(), addCaCertificates(), and
    490   setCaCertificates().
     488  validate the peer's certificate. It can be modified prior to the
     489  handshake with setCaCertificates(), or with \l{QSslSocket}'s
     490  \l{QSslSocket::}{addCaCertificate()} and
     491  \l{QSslSocket::}{addCaCertificates()}.
    491492
    492493  \sa setCaCertificates()
  • trunk/src/network/ssl/qsslconfiguration.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslconfiguration_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslerror.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslerror.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslkey.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslkey.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslkey_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslsocket.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    211211    signal. This mode is the default for clients.
    212212
    213     \value AutoVerifyPeer QSslSocket will automaticaly use QueryPeer for
     213    \value AutoVerifyPeer QSslSocket will automatically use QueryPeer for
    214214    server sockets and VerifyPeer for client sockets.
    215215
     
    297297#include <QtCore/qdebug.h>
    298298#include <QtCore/qdir.h>
    299 #include <QtCore/qdatetime.h>
    300299#include <QtCore/qmutex.h>
     300#include <QtCore/qelapsedtimer.h>
    301301#include <QtNetwork/qhostaddress.h>
    302302#include <QtNetwork/qhostinfo.h>
     
    575575
    576576    The default mode is AutoVerifyPeer, which tells QSslSocket to use
    577     VerifyPeer for clients, QueryPeer for clients.
     577    VerifyPeer for clients and QueryPeer for servers.
    578578
    579579    \sa setPeerVerifyMode(), peerVerifyDepth(), mode()
     
    595595
    596596    The default mode is AutoVerifyPeer, which tells QSslSocket to use
    597     VerifyPeer for clients, QueryPeer for clients.
     597    VerifyPeer for clients and QueryPeer for servers.
    598598
    599599    Setting this mode after encryption has started has no effect on the
     
    13301330    Returns the current default CA certificate database. This database
    13311331    is originally set to your system's default CA certificate database.
    1332     If no system default database is found, Qt will provide its own
    1333     default database. You can override the default CA certificate database
     1332    If no system default database is found, an empty database will be
     1333    returned. You can override the default CA certificate database
    13341334    with your own CA certificate database using setDefaultCaCertificates().
    13351335
     
    13451345
    13461346/*!
    1347     This function provides a default CA certificate database
    1348     shipped together with Qt. The CA certificate database
     1347    This function provides the CA certificate database
     1348    provided by the operating system. The CA certificate database
    13491349    returned by this function is used to initialize the database
    13501350    returned by defaultCaCertificates(). You can replace that database
     
    13551355QList<QSslCertificate> QSslSocket::systemCaCertificates()
    13561356{
    1357     QSslSocketPrivate::ensureInitialized();
     1357    // we are calling ensureInitialized() in the method below
    13581358    return QSslSocketPrivate::systemCaCertificates();
    13591359}
     
    14041404        return false;
    14051405
    1406     QTime stopWatch;
     1406    QElapsedTimer stopWatch;
    14071407    stopWatch.start();
    14081408
     
    14441444    d->readyReadEmittedPointer = &readyReadEmitted;
    14451445
    1446     QTime stopWatch;
     1446    QElapsedTimer stopWatch;
    14471447    stopWatch.start();
    14481448
     
    14811481        return d->plainSocket->waitForBytesWritten(msecs);
    14821482
    1483     QTime stopWatch;
     1483    QElapsedTimer stopWatch;
    14841484    stopWatch.start();
    14851485
     
    15191519        return d->plainSocket->waitForDisconnected(msecs);
    15201520
    1521     QTime stopWatch;
     1521    QElapsedTimer stopWatch;
    15221522    stopWatch.start();
    15231523
     
    15571557bool QSslSocket::supportsSsl()
    15581558{
    1559     return QSslSocketPrivate::ensureInitialized();
     1559    return QSslSocketPrivate::supportsSsl();
    15601560}
    15611561
     
    19661966    QMutexLocker locker(&globalData()->mutex);
    19671967    const QSslConfigurationPrivate *global = globalData()->config.constData();
     1968
     1969    if (!global) {
     1970        ptr = 0;
     1971        return;
     1972    }
    19681973
    19691974    ptr->ref = 1;
     
    20312036}
    20322037
     2038void QSslSocketPrivate::pauseSocketNotifiers(QSslSocket *socket)
     2039{
     2040    if (!socket->d_func()->plainSocket)
     2041        return;
     2042    QAbstractSocketPrivate::pauseSocketNotifiers(socket->d_func()->plainSocket);
     2043}
     2044
     2045void QSslSocketPrivate::resumeSocketNotifiers(QSslSocket *socket)
     2046{
     2047    if (!socket->d_func()->plainSocket)
     2048        return;
     2049    QAbstractSocketPrivate::resumeSocketNotifiers(socket->d_func()->plainSocket);
     2050}
     2051
    20332052/*!
    20342053    \internal
  • trunk/src/network/ssl/qsslsocket.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslsocket_openssl.cpp

    r788 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5252#include <QtCore/qdir.h>
    5353#include <QtCore/qdiriterator.h>
     54#include <QtCore/qelapsedtimer.h>
    5455#include <QtCore/qfile.h>
    5556#include <QtCore/qfileinfo.h>
     
    5859#include <QtCore/qurl.h>
    5960#include <QtCore/qvarlengtharray.h>
    60 
    61 static void initNetworkResources()
    62 {
    63     // Initialize resources
    64     Q_INIT_RESOURCE(network);
    65 }
     61#include <QLibrary> // for loading the security lib for the CA store
    6662
    6763QT_BEGIN_NAMESPACE
    6864
    69 // Useful defines
    70 #define SSL_ERRORSTR() QString::fromLocal8Bit(q_ERR_error_string(q_ERR_get_error(), NULL))
     65#if defined(Q_OS_MAC)
     66#define kSecTrustSettingsDomainSystem 2 // so we do not need to include the header file
     67    PtrSecCertificateGetData QSslSocketPrivate::ptrSecCertificateGetData = 0;
     68    PtrSecTrustSettingsCopyCertificates QSslSocketPrivate::ptrSecTrustSettingsCopyCertificates = 0;
     69    PtrSecTrustCopyAnchorCertificates QSslSocketPrivate::ptrSecTrustCopyAnchorCertificates = 0;
     70#elif defined(Q_OS_WIN)
     71    PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0;
     72    PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0;
     73    PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0;
     74#elif defined(Q_OS_SYMBIAN)
     75#include <e32base.h>
     76#include <e32std.h>
     77#include <e32debug.h>
     78#include <QtCore/private/qcore_symbian_p.h>
     79#endif
     80
     81bool QSslSocketPrivate::s_libraryLoaded = false;
     82bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
    7183
    7284/* \internal
     
    147159static unsigned long id_function()
    148160{
    149     return (unsigned long)QThread::currentThreadId();
     161    return (quintptr)QThread::currentThreadId();
    150162}
    151163} // extern "C"
     
    154166    : ssl(0),
    155167      ctx(0),
     168      pkey(0),
    156169      readBio(0),
    157170      writeBio(0),
     
    258271
    259272        // ### Bad error code
    260         q->setErrorString(QSslSocket::tr("Error creating SSL context (%1)").arg(SSL_ERRORSTR()));
     273        q->setErrorString(QSslSocket::tr("Error creating SSL context (%1)").arg(getErrorsFromOpenSsl()));
    261274        q->setSocketError(QAbstractSocket::UnknownSocketError);
    262275        emit q->error(QAbstractSocket::UnknownSocketError);
     
    283296    if (!q_SSL_CTX_set_cipher_list(ctx, cipherString.data())) {
    284297        // ### Bad error code
    285         q->setErrorString(QSslSocket::tr("Invalid or empty cipher list (%1)").arg(SSL_ERRORSTR()));
     298        q->setErrorString(QSslSocket::tr("Invalid or empty cipher list (%1)").arg(getErrorsFromOpenSsl()));
    286299        q->setSocketError(QAbstractSocket::UnknownSocketError);
    287300        emit q->error(QAbstractSocket::UnknownSocketError);
     
    290303
    291304    // Add all our CAs to this store.
    292     foreach (const QSslCertificate &caCertificate, q->caCertificates())
     305    QList<QSslCertificate> expiredCerts;
     306    foreach (const QSslCertificate &caCertificate, q->caCertificates()) {
     307        // add expired certs later, so that the
     308        // valid ones are used before the expired ones
     309        if (! caCertificate.isValid()) {
     310            expiredCerts.append(caCertificate);
     311        } else {
     312            q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
     313        }
     314    }
     315    // now add the expired certs
     316    foreach (const QSslCertificate &caCertificate, expiredCerts) {
    293317        q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
     318    }
    294319
    295320    // Register a custom callback to get all verification errors.
     
    299324        // Require a private key as well.
    300325        if (configuration.privateKey.isNull()) {
    301             q->setErrorString(QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(SSL_ERRORSTR()));
     326            q->setErrorString(QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(getErrorsFromOpenSsl()));
    302327            emit q->error(QAbstractSocket::UnknownSocketError);
    303328            return false;
     
    306331        // Load certificate
    307332        if (!q_SSL_CTX_use_certificate(ctx, (X509 *)configuration.localCertificate.handle())) {
    308             q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(SSL_ERRORSTR()));
     333            q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(getErrorsFromOpenSsl()));
    309334            emit q->error(QAbstractSocket::UnknownSocketError);
    310335            return false;
     
    312337
    313338        // Load private key
    314         EVP_PKEY *pkey = q_EVP_PKEY_new();
     339        pkey = q_EVP_PKEY_new();
     340        // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
     341        // this lead to a memory leak. Now we use the *_set1_* functions which do not
     342        // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
    315343        if (configuration.privateKey.algorithm() == QSsl::Rsa)
    316             q_EVP_PKEY_assign_RSA(pkey, (RSA *)configuration.privateKey.handle());
     344            q_EVP_PKEY_set1_RSA(pkey, (RSA *)configuration.privateKey.handle());
    317345        else
    318             q_EVP_PKEY_assign_DSA(pkey, (DSA *)configuration.privateKey.handle());
     346            q_EVP_PKEY_set1_DSA(pkey, (DSA *)configuration.privateKey.handle());
    319347        if (!q_SSL_CTX_use_PrivateKey(ctx, pkey)) {
    320             q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(SSL_ERRORSTR()));
     348            q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(getErrorsFromOpenSsl()));
    321349            emit q->error(QAbstractSocket::UnknownSocketError);
    322350            return false;
     
    325353        // Check if the certificate matches the private key.
    326354        if (!q_SSL_CTX_check_private_key(ctx)) {
    327             q->setErrorString(QSslSocket::tr("Private key does not certify public key, %1").arg(SSL_ERRORSTR()));
     355            q->setErrorString(QSslSocket::tr("Private key does not certify public key, %1").arg(getErrorsFromOpenSsl()));
    328356            emit q->error(QAbstractSocket::UnknownSocketError);
    329357            return false;
     
    345373    if (!(ssl = q_SSL_new(ctx))) {
    346374        // ### Bad error code
    347         q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(SSL_ERRORSTR()));
     375        q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl()));
    348376        q->setSocketError(QAbstractSocket::UnknownSocketError);
    349377        emit q->error(QAbstractSocket::UnknownSocketError);
     
    360388    if (!readBio || !writeBio) {
    361389        // ### Bad error code
    362         q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(SSL_ERRORSTR()));
     390        q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl()));
    363391        q->setSocketError(QAbstractSocket::UnknownSocketError);
    364392        emit q->error(QAbstractSocket::UnknownSocketError);
     
    389417    \internal
    390418
    391     Declared static in QSslSocketPrivate, makes sure the SSL libraries have
    392     been initialized.
     419    Does the minimum amount of initialization to determine whether SSL
     420    is supported or not.
    393421*/
    394 bool QSslSocketPrivate::ensureInitialized()
     422
     423bool QSslSocketPrivate::supportsSsl()
     424{
     425    return ensureLibraryLoaded();
     426}
     427
     428bool QSslSocketPrivate::ensureLibraryLoaded()
    395429{
    396430    if (!q_resolveOpenSslSymbols())
     
    399433    // Check if the library itself needs to be initialized.
    400434    QMutexLocker locker(openssl_locks()->initLock());
    401     static int q_initialized = false;
    402     if (!q_initialized) {
    403         q_initialized = true;
    404 
    405         // Initialize resources
    406         initNetworkResources();
     435    if (!s_libraryLoaded) {
     436        s_libraryLoaded = true;
    407437
    408438        // Initialize OpenSSL.
     
    441471                return false;
    442472        }
    443 
    444         resetDefaultCiphers();
    445         setDefaultCaCertificates(systemCaCertificates());
    446473    }
    447474    return true;
     475}
     476
     477void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
     478{
     479    QMutexLocker locker(openssl_locks()->initLock());
     480    if (s_loadedCiphersAndCerts)
     481        return;
     482    s_loadedCiphersAndCerts = true;
     483
     484    resetDefaultCiphers();
     485
     486    //load symbols needed to receive certificates from system store
     487#if defined(Q_OS_MAC)
     488    QLibrary securityLib("/System/Library/Frameworks/Security.framework/Versions/Current/Security");
     489    if (securityLib.load()) {
     490        ptrSecCertificateGetData = (PtrSecCertificateGetData) securityLib.resolve("SecCertificateGetData");
     491        if (!ptrSecCertificateGetData)
     492            qWarning("could not resolve symbols in security library"); // should never happen
     493
     494        ptrSecTrustSettingsCopyCertificates = (PtrSecTrustSettingsCopyCertificates) securityLib.resolve("SecTrustSettingsCopyCertificates");
     495        if (!ptrSecTrustSettingsCopyCertificates) { // method was introduced in Leopard, use legacy method if it's not there
     496            ptrSecTrustCopyAnchorCertificates = (PtrSecTrustCopyAnchorCertificates) securityLib.resolve("SecTrustCopyAnchorCertificates");
     497            if (!ptrSecTrustCopyAnchorCertificates)
     498                qWarning("could not resolve symbols in security library"); // should never happen
     499        }
     500    } else {
     501        qWarning("could not load security library");
     502    }
     503#elif defined(Q_OS_WIN)
     504    HINSTANCE hLib = LoadLibraryW(L"Crypt32");
     505    if (hLib) {
     506#if defined(Q_OS_WINCE)
     507        ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, L"CertOpenStore");
     508        ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, L"CertFindCertificateInStore");
     509        ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, L"CertCloseStore");
     510#else
     511        ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
     512        ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
     513        ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
     514#endif
     515        if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
     516            qWarning("could not resolve symbols in crypt32 library"); // should never happen
     517    } else {
     518        qWarning("could not load crypt32 library"); // should never happen
     519    }
     520#endif
     521    setDefaultCaCertificates(systemCaCertificates());
     522}
     523
     524/*!
     525    \internal
     526
     527    Declared static in QSslSocketPrivate, makes sure the SSL libraries have
     528    been initialized.
     529*/
     530
     531void QSslSocketPrivate::ensureInitialized()
     532{
     533    if (!supportsSsl())
     534        return;
     535
     536    ensureCiphersAndCertsLoaded();
    448537}
    449538
     
    481570}
    482571
     572#if defined(Q_OS_SYMBIAN)
     573
     574CSymbianCertificateRetriever::CSymbianCertificateRetriever() : CActive(CActive::EPriorityStandard),
     575    iCertificatePtr(0,0,0), iSequenceError(KErrNone)
     576{
     577}
     578
     579CSymbianCertificateRetriever::~CSymbianCertificateRetriever()
     580{
     581    iThread.Close();
     582}
     583
     584CSymbianCertificateRetriever* CSymbianCertificateRetriever::NewL()
     585{
     586    CSymbianCertificateRetriever* self = new (ELeave) CSymbianCertificateRetriever();
     587    CleanupStack::PushL(self);
     588    self->ConstructL();
     589    CleanupStack::Pop();
     590    return self;
     591}
     592
     593int CSymbianCertificateRetriever::GetCertificates(QList<QByteArray> &certificates)
     594{
     595    iCertificates = &certificates;
     596
     597    TRequestStatus status;
     598    iThread.Logon(status);
     599    iThread.Resume();
     600    User::WaitForRequest(status);
     601    if (iThread.ExitType() == EExitKill)
     602        return KErrDied;
     603    else
     604        return status.Int();    // Logon() completes with the thread's exit value
     605}
     606
     607void CSymbianCertificateRetriever::doThreadEntryL()
     608{
     609    CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
     610    CleanupStack::PushL(activeScheduler);
     611    CActiveScheduler::Install(activeScheduler);
     612
     613    CActiveScheduler::Add(this);
     614
     615    // These aren't deleted in the destructor so leaving the to CS is ok
     616    iCertStore = CUnifiedCertStore::NewLC(qt_s60GetRFs(), EFalse);
     617    iCertFilter = CCertAttributeFilter::NewLC();
     618
     619    // only interested in CA certs
     620    iCertFilter->SetOwnerType(ECACertificate);
     621    // only interested in X.509 format (we don't support WAP formats)
     622    iCertFilter->SetFormat(EX509Certificate);
     623
     624    // Kick off the sequence by initializing the cert store
     625    iState = Initializing;
     626    iCertStore->Initialize(iStatus);
     627    SetActive();
     628
     629    CActiveScheduler::Start();
     630
     631    // Sequence complete, clean up
     632
     633    // These MUST be cleaned up before the installed CActiveScheduler is destroyed and can't be left to the
     634    // destructor of CSymbianCertificateRetriever. Otherwise the destructor of CActiveScheduler will get
     635    // stuck.
     636    iCertInfos.Close();
     637    CleanupStack::PopAndDestroy(3);     // activeScheduler, iCertStore, iCertFilter
     638}
     639
     640
     641TInt CSymbianCertificateRetriever::ThreadEntryPoint(TAny* aParams)
     642{
     643    User::SetCritical(User::EProcessCritical);
     644    CTrapCleanup* cleanupStack = CTrapCleanup::New();
     645
     646    CSymbianCertificateRetriever* self = (CSymbianCertificateRetriever*) aParams;
     647    TRAPD(err, self->doThreadEntryL());
     648    delete cleanupStack;
     649
     650    // doThreadEntryL() can leave only before the retrieval sequence is started
     651    if (err)
     652        return err;
     653    else
     654        return self->iSequenceError;    // return any error that occurred during the retrieval
     655}
     656
     657void CSymbianCertificateRetriever::ConstructL()
     658{
     659    TInt err;
     660    int i=0;
     661    QString name(QLatin1String("CertWorkerThread-%1"));
     662    //recently closed thread names remain in use for a while until all handles have been closed
     663    //including users of RUndertaker
     664    do {
     665        err = iThread.Create(qt_QString2TPtrC(name.arg(i++)),
     666            CSymbianCertificateRetriever::ThreadEntryPoint, 16384, NULL, this);
     667    } while (err == KErrAlreadyExists);
     668    User::LeaveIfError(err);
     669}
     670
     671void CSymbianCertificateRetriever::DoCancel()
     672{
     673    switch(iState) {
     674    case Initializing:
     675        iCertStore->CancelInitialize();
     676        break;
     677    case Listing:
     678        iCertStore->CancelList();
     679        break;
     680    case RetrievingCertificates:
     681        iCertStore->CancelGetCert();
     682        break;
     683    }
     684}
     685
     686TInt CSymbianCertificateRetriever::RunError(TInt aError)
     687{
     688    // If something goes wrong in the sequence, abort the sequence
     689    iSequenceError = aError;    // this gets reported to the client in the TRequestStatus
     690    CActiveScheduler::Stop();
     691    return KErrNone;
     692}
     693
     694void CSymbianCertificateRetriever::GetCertificateL()
     695{
     696    if (iCurrentCertIndex < iCertInfos.Count()) {
     697        CCTCertInfo* certInfo = iCertInfos[iCurrentCertIndex++];
     698        iCertificateData = QByteArray();
     699        QT_TRYCATCH_LEAVING(iCertificateData.resize(certInfo->Size()));
     700        iCertificatePtr.Set((TUint8*)iCertificateData.data(), 0, iCertificateData.size());
     701#ifdef QSSLSOCKET_DEBUG
     702        qDebug() << "getting " << qt_TDesC2QString(certInfo->Label()) << " size=" << certInfo->Size();
     703        qDebug() << "format=" << certInfo->CertificateFormat();
     704        qDebug() << "ownertype=" << certInfo->CertificateOwnerType();
     705        qDebug() << "type=" << hex << certInfo->Type().iUid;
     706#endif
     707        iCertStore->Retrieve(*certInfo, iCertificatePtr, iStatus);
     708        iState = RetrievingCertificates;
     709        SetActive();
     710    } else {
     711        //reached end of list
     712        CActiveScheduler::Stop();
     713    }
     714}
     715
     716void CSymbianCertificateRetriever::RunL()
     717{
     718#ifdef QSSLSOCKET_DEBUG
     719    qDebug() << "CSymbianCertificateRetriever::RunL status " << iStatus.Int() << " count " << iCertInfos.Count() << " index " << iCurrentCertIndex;
     720#endif
     721    switch (iState) {
     722    case Initializing:
     723        User::LeaveIfError(iStatus.Int()); // initialise fail means pointless to continue
     724        iState = Listing;
     725        iCertStore->List(iCertInfos, *iCertFilter, iStatus);
     726        SetActive();
     727        break;
     728
     729    case Listing:
     730        User::LeaveIfError(iStatus.Int()); // listing fail means pointless to continue
     731        iCurrentCertIndex = 0;
     732        GetCertificateL();
     733        break;
     734
     735    case RetrievingCertificates:
     736        if (iStatus.Int() == KErrNone)
     737            iCertificates->append(iCertificateData);
     738        else
     739            qWarning() << "CSymbianCertificateRetriever: failed to retrieve a certificate, error " << iStatus.Int();
     740        GetCertificateL();
     741        break;
     742    }
     743}
     744#endif // defined(Q_OS_SYMBIAN)
     745
    483746QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
    484747{
    485     // Qt provides a default bundle of certificates
    486     QFile caBundle(QLatin1String(":/trolltech/network/ssl/qt-ca-bundle.crt"));
    487     if (caBundle.open(QIODevice::ReadOnly | QIODevice::Text))
    488         return QSslCertificate::fromDevice(&caBundle);
    489 
    490     // Unreachable; return no bundle.
    491     return QList<QSslCertificate>();
     748    ensureInitialized();
     749#ifdef QSSLSOCKET_DEBUG
     750    QElapsedTimer timer;
     751    timer.start();
     752#endif
     753    QList<QSslCertificate> systemCerts;
     754#if defined(Q_OS_MAC)
     755    CFArrayRef cfCerts;
     756    OSStatus status = 1;
     757
     758    OSStatus SecCertificateGetData (
     759       SecCertificateRef certificate,
     760       CSSM_DATA_PTR data
     761    );
     762
     763    if (ptrSecCertificateGetData) {
     764        if (ptrSecTrustSettingsCopyCertificates)
     765            status = ptrSecTrustSettingsCopyCertificates(kSecTrustSettingsDomainSystem, &cfCerts);
     766        else if (ptrSecTrustCopyAnchorCertificates)
     767            status = ptrSecTrustCopyAnchorCertificates(&cfCerts);
     768        if (!status) {
     769            CFIndex size = CFArrayGetCount(cfCerts);
     770            for (CFIndex i = 0; i < size; ++i) {
     771                SecCertificateRef cfCert = (SecCertificateRef)CFArrayGetValueAtIndex(cfCerts, i);
     772                CSSM_DATA data;
     773                CSSM_DATA_PTR dataPtr = &data;
     774                if (ptrSecCertificateGetData(cfCert, dataPtr)) {
     775                    qWarning("error retrieving a CA certificate from the system store");
     776                } else {
     777                    int len = data.Length;
     778                    char *rawData = reinterpret_cast<char *>(data.Data);
     779                    QByteArray rawCert(rawData, len);
     780                    systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der));
     781                }
     782            }
     783        }
     784        else {
     785           // no detailed error handling here
     786           qWarning("could not retrieve system CA certificates");
     787        }
     788    }
     789#elif defined(Q_OS_WIN)
     790    if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
     791        HCERTSTORE hSystemStore;
     792#if defined(Q_OS_WINCE)
     793        hSystemStore = ptrCertOpenSystemStoreW(CERT_STORE_PROV_SYSTEM_W,
     794                                               0,
     795                                               0,
     796                                               CERT_STORE_NO_CRYPT_RELEASE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,
     797                                               L"ROOT");
     798#else
     799        hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
     800#endif
     801        if(hSystemStore) {
     802            PCCERT_CONTEXT pc = NULL;
     803            while(1) {
     804                pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
     805                if(!pc)
     806                    break;
     807                QByteArray der((const char *)(pc->pbCertEncoded), static_cast<int>(pc->cbCertEncoded));
     808                QSslCertificate cert(der, QSsl::Der);
     809                systemCerts.append(cert);
     810            }
     811            ptrCertCloseStore(hSystemStore, 0);
     812        }
     813    }
     814#elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
     815    QSet<QString> certFiles;
     816    QList<QByteArray> directories;
     817    directories << "/etc/ssl/certs/"; // (K)ubuntu, OpenSUSE, Mandriva, MeeGo ...
     818    directories << "/usr/lib/ssl/certs/"; // Gentoo, Mandrake
     819    directories << "/usr/share/ssl/"; // Centos, Redhat, SuSE
     820    directories << "/usr/local/ssl/"; // Normal OpenSSL Tarball
     821    directories << "/var/ssl/certs/"; // AIX
     822    directories << "/usr/local/ssl/certs/"; // Solaris
     823    directories << "/opt/openssl/certs/"; // HP-UX
     824
     825    QDir currentDir;
     826    QStringList nameFilters;
     827    nameFilters << QLatin1String("*.pem") << QLatin1String("*.crt");
     828    currentDir.setNameFilters(nameFilters);
     829    for (int a = 0; a < directories.count(); a++) {
     830        currentDir.setPath(QLatin1String(directories.at(a)));
     831        QDirIterator it(currentDir);
     832        while(it.hasNext()) {
     833            it.next();
     834            // use canonical path here to not load the same certificate twice if symlinked
     835            certFiles.insert(it.fileInfo().canonicalFilePath());
     836        }
     837    }
     838    QSetIterator<QString> it(certFiles);
     839    while(it.hasNext()) {
     840        systemCerts.append(QSslCertificate::fromPath(it.next()));
     841    }
     842    systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva
     843    systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss
     844
     845#elif defined(Q_OS_SYMBIAN)
     846    QList<QByteArray> certs;
     847    QScopedPointer<CSymbianCertificateRetriever> retriever(CSymbianCertificateRetriever::NewL());
     848
     849    retriever->GetCertificates(certs);
     850    foreach (const QByteArray &encodedCert, certs) {
     851        QSslCertificate cert(encodedCert, QSsl::Der);
     852        if (!cert.isNull()) {
     853#ifdef QSSLSOCKET_DEBUG
     854            qDebug() << "imported certificate: " << cert.issuerInfo(QSslCertificate::CommonName);
     855#endif
     856            systemCerts.append(cert);
     857        }
     858    }
     859#endif
     860#ifdef QSSLSOCKET_DEBUG
     861    qDebug() << "systemCaCertificates retrieval time " << timer.elapsed() << "ms";
     862    qDebug() << "imported " << systemCerts.count() << " certificates";
     863#endif
     864
     865    return systemCerts;
    492866}
    493867
     
    544918                if (writtenBytes <= 0) {
    545919                    // ### Better error handling.
    546                     q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(SSL_ERRORSTR()));
     920                    q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(getErrorsFromOpenSsl()));
    547921                    q->setSocketError(QAbstractSocket::UnknownSocketError);
    548922                    emit q->error(QAbstractSocket::UnknownSocketError);
     
    607981                } else {
    608982                    // ### Better error handling.
    609                     q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(SSL_ERRORSTR()));
     983                    q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(getErrorsFromOpenSsl()));
    610984                    q->setSocketError(QAbstractSocket::UnknownSocketError);
    611985                    emit q->error(QAbstractSocket::UnknownSocketError);
     
    6811055                plainSocket->disconnectFromHost();
    6821056                break;
     1057            case SSL_ERROR_SYSCALL: // some IO error
     1058            case SSL_ERROR_SSL: // error in the SSL library
     1059                // we do not know exactly what the error is, nor whether we can recover from it,
     1060                // so just return to prevent an endless loop in the outer "while" statement
     1061                q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
     1062                q->setSocketError(QAbstractSocket::UnknownSocketError);
     1063                emit q->error(QAbstractSocket::UnknownSocketError);
     1064                return;
    6831065            default:
    684                 // ### Handle errors better.
    685                 q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(SSL_ERRORSTR()));
     1066                // SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a
     1067                // BIO_s_connect() or BIO_s_accept(), which we do not call.
     1068                // SSL_ERROR_WANT_X509_LOOKUP: can only happen with a
     1069                // SSL_CTX_set_client_cert_cb(), which we do not call.
     1070                // So this default case should never be triggered.
     1071                q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
    6861072                q->setSocketError(QAbstractSocket::UnknownSocketError);
    6871073                emit q->error(QAbstractSocket::UnknownSocketError);
     
    7781164            break;
    7791165        default:
    780             // ### Handle errors better
    781             q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(SSL_ERRORSTR()));
     1166            q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl()));
    7821167            q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
    7831168#ifdef QSSLSOCKET_DEBUG
     
    8161201            QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName);
    8171202
    818             QRegExp regexp(commonName, Qt::CaseInsensitive, QRegExp::Wildcard);
    819             if (!regexp.exactMatch(peerName)) {
     1203            if (!isMatchingHostname(commonName.toLower(), peerName.toLower())) {
    8201204                bool matched = false;
    8211205                foreach (const QString &altName, configuration.peerCertificate
    8221206                         .alternateSubjectNames().values(QSsl::DnsEntry)) {
    823                     regexp.setPattern(altName);
    824                     if (regexp.exactMatch(peerName)) {
     1207                    if (isMatchingHostname(altName.toLower(), peerName.toLower())) {
    8251208                        matched = true;
    8261209                        break;
    8271210                    }
    8281211                }
     1212
    8291213                if (!matched) {
    8301214                    // No matches in common names or alternate names.
     
    9231307        ctx = 0;
    9241308    }
     1309    if (pkey) {
     1310        q_EVP_PKEY_free(pkey);
     1311        pkey = 0;
     1312    }
     1313
    9251314}
    9261315
     
    9511340}
    9521341
     1342QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
     1343{
     1344    QString errorString;
     1345    unsigned long errNum;
     1346    while((errNum = q_ERR_get_error())) {
     1347        if (! errorString.isEmpty())
     1348            errorString.append(QLatin1String(", "));
     1349        const char *error = q_ERR_error_string(errNum, NULL);
     1350        errorString.append(QString::fromAscii(error)); // error is ascii according to man ERR_error_string
     1351    }
     1352    return errorString;
     1353}
     1354
     1355bool QSslSocketBackendPrivate::isMatchingHostname(const QString &cn, const QString &hostname)
     1356{
     1357    int wildcard = cn.indexOf(QLatin1Char('*'));
     1358
     1359    // Check this is a wildcard cert, if not then just compare the strings
     1360    if (wildcard < 0)
     1361        return cn == hostname;
     1362
     1363    int firstCnDot = cn.indexOf(QLatin1Char('.'));
     1364    int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1);
     1365
     1366    // Check at least 3 components
     1367    if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length()))
     1368        return false;
     1369
     1370    // Check * is last character of 1st component (ie. there's a following .)
     1371    if (wildcard+1 != firstCnDot)
     1372        return false;
     1373
     1374    // Check only one star
     1375    if (cn.lastIndexOf(QLatin1Char('*')) != wildcard)
     1376        return false;
     1377
     1378    // Check characters preceding * (if any) match
     1379    if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard)))
     1380        return false;
     1381
     1382    // Check characters following first . match
     1383    if (hostname.midRef(hostname.indexOf(QLatin1Char('.'))) != cn.midRef(firstCnDot))
     1384        return false;
     1385
     1386    // Check if the hostname is an IP address, if so then wildcards are not allowed
     1387    QHostAddress addr(hostname);
     1388    if (!addr.isNull())
     1389        return false;
     1390
     1391    // Ok, I guess this was a wildcard CN and the hostname matches.
     1392    return true;
     1393}
     1394
    9531395QT_END_NAMESPACE
  • trunk/src/network/ssl/qsslsocket_openssl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9898    SSL *ssl;
    9999    SSL_CTX *ctx;
     100    EVP_PKEY *pkey;
    100101    BIO *readBio;
    101102    BIO *writeBio;
     
    116117    static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
    117118    static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
     119    Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
     120    static QString getErrorsFromOpenSsl();
    118121};
     122
     123#if defined(Q_OS_SYMBIAN)
     124
     125#include <QByteArray>
     126#include <e32base.h>
     127#include <f32file.h>
     128#include <unifiedcertstore.h>     // link against certstore.lib
     129#include <ccertattributefilter.h> // link against ctframework.lib
     130
     131// The purpose of this class is to wrap the asynchronous API of Symbian certificate store to one
     132// synchronizable call. The user of this class needs to provide a TRequestStatus object which can
     133// be used with User::WaitForRequest() unlike with the calls of the certificate store API.
     134// A thread is used instead of a CActiveSchedulerWait scheme, because that would make the call
     135// asynchronous (other events might be processed during the call even though the call would be seemingly
     136// synchronous).
     137
     138class CSymbianCertificateRetriever : public CActive
     139{
     140public:
     141    static CSymbianCertificateRetriever* NewL();
     142    ~CSymbianCertificateRetriever();
     143
     144    int GetCertificates(QList<QByteArray> &aCertificates);
     145
     146private:
     147    void ConstructL();
     148    CSymbianCertificateRetriever();
     149    static TInt ThreadEntryPoint(TAny* aParams);
     150    void doThreadEntryL();
     151    void GetCertificateL();
     152    void DoCancel();
     153    void RunL();
     154    TInt RunError(TInt aError);
     155
     156private:
     157    enum {
     158        Initializing,
     159        Listing,
     160        RetrievingCertificates
     161    } iState;
     162
     163    RThread iThread;
     164    CUnifiedCertStore* iCertStore;
     165    RMPointerArray<CCTCertInfo> iCertInfos;
     166    CCertAttributeFilter* iCertFilter;
     167    TInt iCurrentCertIndex;
     168    QByteArray iCertificateData;
     169    TPtr8 iCertificatePtr;
     170    QList<QByteArray>* iCertificates;
     171    TInt iSequenceError;
     172};
     173
     174
     175#endif
     176
    119177
    120178QT_END_NAMESPACE
  • trunk/src/network/ssl/qsslsocket_openssl_symbols.cpp

    r788 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include "qsslsocket_openssl_symbols_p.h"
    4444
    45 #include <QtCore/qlibrary.h>
     45#ifdef Q_OS_WIN
     46# include <private/qsystemlibrary_p.h>
     47#else
     48# include <QtCore/qlibrary.h>
     49#endif
    4650#include <QtCore/qmutex.h>
    4751#include <private/qmutexpool_p.h>
     
    120124DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
    121125DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
     126DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
     127DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
    122128DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG)
    123129DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return)
     
    333339            .split(QLatin1Char(':'), QString::SkipEmptyParts);
    334340#  endif
    335     paths << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
     341    paths << QLatin1String("/lib") << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
    336342
    337343    QStringList foundSsls;
     
    348354}
    349355# endif
     356
     357#ifdef Q_OS_WIN
     358static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32()
     359{
     360    QPair<QSystemLibrary*,QSystemLibrary*> pair;
     361    pair.first = 0;
     362    pair.second = 0;
     363
     364    QSystemLibrary *ssleay32 = new QSystemLibrary(QLatin1String("ssleay32"));
     365    if (!ssleay32->load(false)) {
     366        // Cannot find ssleay32.dll
     367        delete ssleay32;
     368        return pair;
     369    }
     370
     371    QSystemLibrary *libeay32 = new QSystemLibrary(QLatin1String("libeay32"));
     372    if (!libeay32->load(false)) {
     373        delete ssleay32;
     374        delete libeay32;
     375        return pair;
     376    }
     377
     378    pair.first = ssleay32;
     379    pair.second = libeay32;
     380    return pair;
     381}
     382#else
    350383
    351384static QPair<QLibrary*, QLibrary*> loadOpenSsl()
     
    355388    pair.second = 0;
    356389
    357 # ifdef Q_OS_WIN
    358     QLibrary *ssleay32 = new QLibrary(QLatin1String("ssleay32"));
    359     if (!ssleay32->load()) {
    360         // Cannot find ssleay32.dll
    361         delete ssleay32;
    362         return pair;
    363     }
    364 
    365     QLibrary *libeay32 = new QLibrary(QLatin1String("libeay32"));
    366     if (!libeay32->load()) {
    367         delete ssleay32;
    368         delete libeay32;
    369         return pair;
    370     }
    371 
    372     pair.first = ssleay32;
    373     pair.second = libeay32;
    374     return pair;
    375 # elif defined(Q_OS_SYMBIAN)
     390# if defined(Q_OS_SYMBIAN)
    376391     QLibrary *libssl = new QLibrary(QLatin1String("libssl"));
    377392    if (!libssl->load()) {
     
    506521# endif
    507522}
     523#endif
    508524
    509525bool q_resolveOpenSslSymbols()
     
    520536    triedToResolveSymbols = true;
    521537
     538#ifdef Q_OS_WIN
     539    QPair<QSystemLibrary *, QSystemLibrary *> libs = loadOpenSslWin32();
     540#else
    522541    QPair<QLibrary *, QLibrary *> libs = loadOpenSsl();
     542#endif
    523543    if (!libs.first || !libs.second)
    524544        // failed to load them
     
    549569    RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second )
    550570    RESOLVEFUNC(EVP_PKEY_assign, 859, libs.second )
     571    RESOLVEFUNC(EVP_PKEY_set1_RSA, 880, libs.second )
     572    RESOLVEFUNC(EVP_PKEY_set1_DSA, 879, libs.second )
    551573    RESOLVEFUNC(EVP_PKEY_free, 867, libs.second )
    552574    RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second )
     
    671693    RESOLVEFUNC(EVP_des_ede3_cbc)
    672694    RESOLVEFUNC(EVP_PKEY_assign)
     695    RESOLVEFUNC(EVP_PKEY_set1_RSA)
     696    RESOLVEFUNC(EVP_PKEY_set1_DSA)
    673697    RESOLVEFUNC(EVP_PKEY_free)
    674698    RESOLVEFUNC(EVP_PKEY_get1_DSA)
     
    794818QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime)
    795819{
    796     char lBuffer[24];
    797     char *pBuffer = lBuffer;
    798 
    799820    size_t lTimeLength = aTime->length;
    800821    char *pString = (char *) aTime->data;
    801822
    802823    if (aTime->type == V_ASN1_UTCTIME) {
     824
     825        char lBuffer[24];
     826        char *pBuffer = lBuffer;
     827
    803828        if ((lTimeLength < 11) || (lTimeLength > 17))
    804829            return QDateTime();
     
    807832        pBuffer += 10;
    808833        pString += 10;
     834
     835        if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) {
     836            *pBuffer++ = '0';
     837            *pBuffer++ = '0';
     838        } else {
     839            *pBuffer++ = *pString++;
     840            *pBuffer++ = *pString++;
     841            // Skip any fractional seconds...
     842            if (*pString == '.') {
     843                pString++;
     844                while ((*pString >= '0') && (*pString <= '9'))
     845                    pString++;
     846            }
     847        }
     848
     849        *pBuffer++ = 'Z';
     850        *pBuffer++ = '\0';
     851
     852        time_t lSecondsFromUCT;
     853        if (*pString == 'Z') {
     854            lSecondsFromUCT = 0;
     855        } else {
     856            if ((*pString != '+') && (*pString != '-'))
     857                return QDateTime();
     858
     859            lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
     860            lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0');
     861            lSecondsFromUCT *= 60;
     862            if (*pString == '-')
     863                lSecondsFromUCT = -lSecondsFromUCT;
     864        }
     865
     866        tm lTime;
     867        lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
     868        lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
     869        lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
     870        lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0');
     871        lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1;
     872        lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0');
     873        if (lTime.tm_year < 50)
     874            lTime.tm_year += 100; // RFC 2459
     875
     876        QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
     877        QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
     878
     879        QDateTime result(resDate, resTime, Qt::UTC);
     880        result = result.addSecs(lSecondsFromUCT);
     881        return result;
     882
     883    } else if (aTime->type == V_ASN1_GENERALIZEDTIME) {
     884
     885        if (lTimeLength < 15)
     886            return QDateTime(); // hopefully never triggered
     887
     888        // generalized time is always YYYYMMDDHHMMSSZ (RFC 2459, section 4.1.2.5.2)
     889        tm lTime;
     890        lTime.tm_sec = ((pString[12] - '0') * 10) + (pString[13] - '0');
     891        lTime.tm_min = ((pString[10] - '0') * 10) + (pString[11] - '0');
     892        lTime.tm_hour = ((pString[8] - '0') * 10) + (pString[9] - '0');
     893        lTime.tm_mday = ((pString[6] - '0') * 10) + (pString[7] - '0');
     894        lTime.tm_mon = (((pString[4] - '0') * 10) + (pString[5] - '0'));
     895        lTime.tm_year = ((pString[0] - '0') * 1000) + ((pString[1] - '0') * 100) +
     896                        ((pString[2] - '0') * 10) + (pString[3] - '0');
     897
     898        QDate resDate(lTime.tm_year, lTime.tm_mon, lTime.tm_mday);
     899        QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
     900
     901        QDateTime result(resDate, resTime, Qt::UTC);
     902        return result;
     903
    809904    } else {
    810         if (lTimeLength < 13)
    811             return QDateTime();
    812 
    813         memcpy(pBuffer, pString, 12);
    814         pBuffer += 12;
    815         pString += 12;
    816     }
    817 
    818     if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) {
    819         *pBuffer++ = '0';
    820         *pBuffer++ = '0';
    821     } else {
    822         *pBuffer++ = *pString++;
    823         *pBuffer++ = *pString++;
    824         // Skip any fractional seconds...
    825         if (*pString == '.') {
    826             pString++;
    827             while ((*pString >= '0') && (*pString <= '9'))
    828                 pString++;
    829         }
    830     }
    831 
    832     *pBuffer++ = 'Z';
    833     *pBuffer++ = '\0';
    834 
    835     time_t lSecondsFromUCT;
    836     if (*pString == 'Z') {
    837         lSecondsFromUCT = 0;
    838     } else {
    839         if ((*pString != '+') && (*pString != '-'))
    840             return QDateTime();
    841 
    842         lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
    843         lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0');
    844         lSecondsFromUCT *= 60;
    845         if (*pString == '-')
    846             lSecondsFromUCT = -lSecondsFromUCT;
    847     }
    848 
    849     tm lTime;
    850     lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
    851     lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
    852     lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
    853     lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0');
    854     lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1;
    855     lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0');
    856     if (lTime.tm_year < 50)
    857         lTime.tm_year += 100; // RFC 2459
    858 
    859     QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
    860     QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
    861     QDateTime result(resDate, resTime, Qt::UTC);
    862     result = result.addSecs(lSecondsFromUCT);
    863     return result;
     905        qWarning("unsupported date format detected");
     906        return QDateTime();
     907    }
     908
    864909}
    865910
  • trunk/src/network/ssl/qsslsocket_openssl_symbols_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    228228const EVP_CIPHER *q_EVP_des_ede3_cbc();
    229229int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
     230int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
     231int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
    230232void q_EVP_PKEY_free(EVP_PKEY *a);
    231233RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a);
  • trunk/src/network/ssl/qsslsocket_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6767QT_BEGIN_NAMESPACE
    6868
     69#if defined(Q_OS_MAC)
     70#include <Security/SecCertificate.h>
     71#include <CoreFoundation/CFArray.h>
     72    typedef OSStatus (*PtrSecCertificateGetData)(SecCertificateRef, CSSM_DATA_PTR);
     73    typedef OSStatus (*PtrSecTrustSettingsCopyCertificates)(int, CFArrayRef*);
     74    typedef OSStatus (*PtrSecTrustCopyAnchorCertificates)(CFArrayRef*);
     75#elif defined(Q_OS_WIN)
     76#include <wincrypt.h>
     77#ifndef HCRYPTPROV_LEGACY
     78#define HCRYPTPROV_LEGACY HCRYPTPROV
     79#endif
     80#if defined(Q_OS_WINCE)
     81    typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, const void*);
     82#else
     83    typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(HCRYPTPROV_LEGACY, LPCWSTR);
     84#endif
     85    typedef PCCERT_CONTEXT (WINAPI *PtrCertFindCertificateInStore)(HCERTSTORE, DWORD, DWORD, DWORD, const void*, PCCERT_CONTEXT);
     86    typedef BOOL (WINAPI *PtrCertCloseStore)(HCERTSTORE, DWORD);
     87#endif
     88
     89
     90
    6991class QSslSocketPrivate : public QTcpSocketPrivate
    7092{
     
    91113    QString verificationPeerName;
    92114
    93     static bool ensureInitialized();
     115    static bool supportsSsl();
     116    static void ensureInitialized();
    94117    static void deinitialize();
    95118    static QList<QSslCipher> defaultCiphers();
     
    107130    static void addDefaultCaCertificates(const QList<QSslCertificate> &certs);
    108131
     132#if defined(Q_OS_MAC)
     133    static PtrSecCertificateGetData ptrSecCertificateGetData;
     134    static PtrSecTrustSettingsCopyCertificates ptrSecTrustSettingsCopyCertificates;
     135    static PtrSecTrustCopyAnchorCertificates ptrSecTrustCopyAnchorCertificates;
     136#elif defined(Q_OS_WIN)
     137    static PtrCertOpenSystemStoreW ptrCertOpenSystemStoreW;
     138    static PtrCertFindCertificateInStore ptrCertFindCertificateInStore;
     139    static PtrCertCloseStore ptrCertCloseStore;
     140#endif
     141
    109142    // The socket itself, including private slots.
    110143    QTcpSocket *plainSocket;
    111144    void createPlainSocket(QIODevice::OpenMode openMode);
     145    static void pauseSocketNotifiers(QSslSocket*);
     146    static void resumeSocketNotifiers(QSslSocket*);
    112147    void _q_connectedSlot();
    113148    void _q_hostFoundSlot();
     
    127162    virtual void disconnected() = 0;
    128163    virtual QSslCipher sessionCipher() const = 0;
     164
     165private:
     166    static bool ensureLibraryLoaded();
     167    static void ensureCiphersAndCertsLoaded();
     168
     169    static bool s_libraryLoaded;
     170    static bool s_loadedCiphersAndCerts;
    129171};
    130172
  • trunk/src/network/ssl/ssl.pri

    r788 r846  
    3232               ssl/qsslsocket_openssl_symbols.cpp
    3333
    34     # Include Qt's default CA bundle
    35     RESOURCES += network.qrc
    36 
    3734    # Add optional SSL libs
    3835    LIBS_PRIVATE += $$OPENSSL_LIBS
Note: See TracChangeset for help on using the changeset viewer.