Changeset 846 for trunk/src/network/ssl
- Timestamp:
- May 5, 2011, 5:36:53 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 1 deleted
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.7.2 (added) merged: 845 /branches/vendor/nokia/qt/current merged: 844 /branches/vendor/nokia/qt/4.6.3 removed
- Property svn:mergeinfo changed
-
trunk/src/network/ssl/qssl.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qssl.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslcertificate.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 260 260 /*! 261 261 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. 262 265 */ 263 266 QByteArray QSslCertificate::serialNumber() const 264 267 { 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 } 269 284 return d->serialNumberString; 270 285 } … … 534 549 int startIndex = 0; 535 550 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 } 538 558 } 539 559 … … 697 717 static bool matchLineFeed(const QByteArray &pem, int *offset) 698 718 { 699 char ch ;719 char ch = 0; 700 720 701 721 // ignore extra whitespace at the end of the line -
trunk/src/network/ssl/qsslcertificate.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslcertificate_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslcipher.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslcipher.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslcipher_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslconfiguration.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 486 486 Returns this connection's CA certificate database. The CA certificate 487 487 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()}. 491 492 492 493 \sa setCaCertificates() -
trunk/src/network/ssl/qsslconfiguration.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslconfiguration_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslerror.cpp
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslerror.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslkey.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslkey.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslkey_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslsocket.cpp
r769 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 211 211 signal. This mode is the default for clients. 212 212 213 \value AutoVerifyPeer QSslSocket will automatical y use QueryPeer for213 \value AutoVerifyPeer QSslSocket will automatically use QueryPeer for 214 214 server sockets and VerifyPeer for client sockets. 215 215 … … 297 297 #include <QtCore/qdebug.h> 298 298 #include <QtCore/qdir.h> 299 #include <QtCore/qdatetime.h>300 299 #include <QtCore/qmutex.h> 300 #include <QtCore/qelapsedtimer.h> 301 301 #include <QtNetwork/qhostaddress.h> 302 302 #include <QtNetwork/qhostinfo.h> … … 575 575 576 576 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. 578 578 579 579 \sa setPeerVerifyMode(), peerVerifyDepth(), mode() … … 595 595 596 596 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. 598 598 599 599 Setting this mode after encryption has started has no effect on the … … 1330 1330 Returns the current default CA certificate database. This database 1331 1331 is originally set to your system's default CA certificate database. 1332 If no system default database is found, Qt will provide its own1333 default database. You can override the default CA certificate database1332 If no system default database is found, an empty database will be 1333 returned. You can override the default CA certificate database 1334 1334 with your own CA certificate database using setDefaultCaCertificates(). 1335 1335 … … 1345 1345 1346 1346 /*! 1347 This function provides a defaultCA certificate database1348 shipped together with Qt. The CA certificate database1347 This function provides the CA certificate database 1348 provided by the operating system. The CA certificate database 1349 1349 returned by this function is used to initialize the database 1350 1350 returned by defaultCaCertificates(). You can replace that database … … 1355 1355 QList<QSslCertificate> QSslSocket::systemCaCertificates() 1356 1356 { 1357 QSslSocketPrivate::ensureInitialized();1357 // we are calling ensureInitialized() in the method below 1358 1358 return QSslSocketPrivate::systemCaCertificates(); 1359 1359 } … … 1404 1404 return false; 1405 1405 1406 Q TimestopWatch;1406 QElapsedTimer stopWatch; 1407 1407 stopWatch.start(); 1408 1408 … … 1444 1444 d->readyReadEmittedPointer = &readyReadEmitted; 1445 1445 1446 Q TimestopWatch;1446 QElapsedTimer stopWatch; 1447 1447 stopWatch.start(); 1448 1448 … … 1481 1481 return d->plainSocket->waitForBytesWritten(msecs); 1482 1482 1483 Q TimestopWatch;1483 QElapsedTimer stopWatch; 1484 1484 stopWatch.start(); 1485 1485 … … 1519 1519 return d->plainSocket->waitForDisconnected(msecs); 1520 1520 1521 Q TimestopWatch;1521 QElapsedTimer stopWatch; 1522 1522 stopWatch.start(); 1523 1523 … … 1557 1557 bool QSslSocket::supportsSsl() 1558 1558 { 1559 return QSslSocketPrivate:: ensureInitialized();1559 return QSslSocketPrivate::supportsSsl(); 1560 1560 } 1561 1561 … … 1966 1966 QMutexLocker locker(&globalData()->mutex); 1967 1967 const QSslConfigurationPrivate *global = globalData()->config.constData(); 1968 1969 if (!global) { 1970 ptr = 0; 1971 return; 1972 } 1968 1973 1969 1974 ptr->ref = 1; … … 2031 2036 } 2032 2037 2038 void QSslSocketPrivate::pauseSocketNotifiers(QSslSocket *socket) 2039 { 2040 if (!socket->d_func()->plainSocket) 2041 return; 2042 QAbstractSocketPrivate::pauseSocketNotifiers(socket->d_func()->plainSocket); 2043 } 2044 2045 void QSslSocketPrivate::resumeSocketNotifiers(QSslSocket *socket) 2046 { 2047 if (!socket->d_func()->plainSocket) 2048 return; 2049 QAbstractSocketPrivate::resumeSocketNotifiers(socket->d_func()->plainSocket); 2050 } 2051 2033 2052 /*! 2034 2053 \internal -
trunk/src/network/ssl/qsslsocket.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) -
trunk/src/network/ssl/qsslsocket_openssl.cpp
r788 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 52 52 #include <QtCore/qdir.h> 53 53 #include <QtCore/qdiriterator.h> 54 #include <QtCore/qelapsedtimer.h> 54 55 #include <QtCore/qfile.h> 55 56 #include <QtCore/qfileinfo.h> … … 58 59 #include <QtCore/qurl.h> 59 60 #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 66 62 67 63 QT_BEGIN_NAMESPACE 68 64 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 81 bool QSslSocketPrivate::s_libraryLoaded = false; 82 bool QSslSocketPrivate::s_loadedCiphersAndCerts = false; 71 83 72 84 /* \internal … … 147 159 static unsigned long id_function() 148 160 { 149 return ( unsigned long)QThread::currentThreadId();161 return (quintptr)QThread::currentThreadId(); 150 162 } 151 163 } // extern "C" … … 154 166 : ssl(0), 155 167 ctx(0), 168 pkey(0), 156 169 readBio(0), 157 170 writeBio(0), … … 258 271 259 272 // ### 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())); 261 274 q->setSocketError(QAbstractSocket::UnknownSocketError); 262 275 emit q->error(QAbstractSocket::UnknownSocketError); … … 283 296 if (!q_SSL_CTX_set_cipher_list(ctx, cipherString.data())) { 284 297 // ### 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())); 286 299 q->setSocketError(QAbstractSocket::UnknownSocketError); 287 300 emit q->error(QAbstractSocket::UnknownSocketError); … … 290 303 291 304 // 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) { 293 317 q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle()); 318 } 294 319 295 320 // Register a custom callback to get all verification errors. … … 299 324 // Require a private key as well. 300 325 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())); 302 327 emit q->error(QAbstractSocket::UnknownSocketError); 303 328 return false; … … 306 331 // Load certificate 307 332 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())); 309 334 emit q->error(QAbstractSocket::UnknownSocketError); 310 335 return false; … … 312 337 313 338 // 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. 315 343 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()); 317 345 else 318 q_EVP_PKEY_ assign_DSA(pkey, (DSA *)configuration.privateKey.handle());346 q_EVP_PKEY_set1_DSA(pkey, (DSA *)configuration.privateKey.handle()); 319 347 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())); 321 349 emit q->error(QAbstractSocket::UnknownSocketError); 322 350 return false; … … 325 353 // Check if the certificate matches the private key. 326 354 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())); 328 356 emit q->error(QAbstractSocket::UnknownSocketError); 329 357 return false; … … 345 373 if (!(ssl = q_SSL_new(ctx))) { 346 374 // ### 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())); 348 376 q->setSocketError(QAbstractSocket::UnknownSocketError); 349 377 emit q->error(QAbstractSocket::UnknownSocketError); … … 360 388 if (!readBio || !writeBio) { 361 389 // ### 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())); 363 391 q->setSocketError(QAbstractSocket::UnknownSocketError); 364 392 emit q->error(QAbstractSocket::UnknownSocketError); … … 389 417 \internal 390 418 391 D eclared static in QSslSocketPrivate, makes sure the SSL libraries have392 been initialized.419 Does the minimum amount of initialization to determine whether SSL 420 is supported or not. 393 421 */ 394 bool QSslSocketPrivate::ensureInitialized() 422 423 bool QSslSocketPrivate::supportsSsl() 424 { 425 return ensureLibraryLoaded(); 426 } 427 428 bool QSslSocketPrivate::ensureLibraryLoaded() 395 429 { 396 430 if (!q_resolveOpenSslSymbols()) … … 399 433 // Check if the library itself needs to be initialized. 400 434 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; 407 437 408 438 // Initialize OpenSSL. … … 441 471 return false; 442 472 } 443 444 resetDefaultCiphers();445 setDefaultCaCertificates(systemCaCertificates());446 473 } 447 474 return true; 475 } 476 477 void 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 531 void QSslSocketPrivate::ensureInitialized() 532 { 533 if (!supportsSsl()) 534 return; 535 536 ensureCiphersAndCertsLoaded(); 448 537 } 449 538 … … 481 570 } 482 571 572 #if defined(Q_OS_SYMBIAN) 573 574 CSymbianCertificateRetriever::CSymbianCertificateRetriever() : CActive(CActive::EPriorityStandard), 575 iCertificatePtr(0,0,0), iSequenceError(KErrNone) 576 { 577 } 578 579 CSymbianCertificateRetriever::~CSymbianCertificateRetriever() 580 { 581 iThread.Close(); 582 } 583 584 CSymbianCertificateRetriever* CSymbianCertificateRetriever::NewL() 585 { 586 CSymbianCertificateRetriever* self = new (ELeave) CSymbianCertificateRetriever(); 587 CleanupStack::PushL(self); 588 self->ConstructL(); 589 CleanupStack::Pop(); 590 return self; 591 } 592 593 int 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 607 void 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 641 TInt 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 657 void 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 671 void 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 686 TInt 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 694 void 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 716 void 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 483 746 QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates() 484 747 { 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; 492 866 } 493 867 … … 544 918 if (writtenBytes <= 0) { 545 919 // ### 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())); 547 921 q->setSocketError(QAbstractSocket::UnknownSocketError); 548 922 emit q->error(QAbstractSocket::UnknownSocketError); … … 607 981 } else { 608 982 // ### 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())); 610 984 q->setSocketError(QAbstractSocket::UnknownSocketError); 611 985 emit q->error(QAbstractSocket::UnknownSocketError); … … 681 1055 plainSocket->disconnectFromHost(); 682 1056 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; 683 1065 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())); 686 1072 q->setSocketError(QAbstractSocket::UnknownSocketError); 687 1073 emit q->error(QAbstractSocket::UnknownSocketError); … … 778 1164 break; 779 1165 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())); 782 1167 q->setSocketError(QAbstractSocket::SslHandshakeFailedError); 783 1168 #ifdef QSSLSOCKET_DEBUG … … 816 1201 QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName); 817 1202 818 QRegExp regexp(commonName, Qt::CaseInsensitive, QRegExp::Wildcard); 819 if (!regexp.exactMatch(peerName)) { 1203 if (!isMatchingHostname(commonName.toLower(), peerName.toLower())) { 820 1204 bool matched = false; 821 1205 foreach (const QString &altName, configuration.peerCertificate 822 1206 .alternateSubjectNames().values(QSsl::DnsEntry)) { 823 regexp.setPattern(altName); 824 if (regexp.exactMatch(peerName)) { 1207 if (isMatchingHostname(altName.toLower(), peerName.toLower())) { 825 1208 matched = true; 826 1209 break; 827 1210 } 828 1211 } 1212 829 1213 if (!matched) { 830 1214 // No matches in common names or alternate names. … … 923 1307 ctx = 0; 924 1308 } 1309 if (pkey) { 1310 q_EVP_PKEY_free(pkey); 1311 pkey = 0; 1312 } 1313 925 1314 } 926 1315 … … 951 1340 } 952 1341 1342 QString 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 1355 bool 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 953 1395 QT_END_NAMESPACE -
trunk/src/network/ssl/qsslsocket_openssl_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 98 98 SSL *ssl; 99 99 SSL_CTX *ctx; 100 EVP_PKEY *pkey; 100 101 BIO *readBio; 101 102 BIO *writeBio; … … 116 117 static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher); 117 118 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(); 118 121 }; 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 138 class CSymbianCertificateRetriever : public CActive 139 { 140 public: 141 static CSymbianCertificateRetriever* NewL(); 142 ~CSymbianCertificateRetriever(); 143 144 int GetCertificates(QList<QByteArray> &aCertificates); 145 146 private: 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 156 private: 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 119 177 120 178 QT_END_NAMESPACE -
trunk/src/network/ssl/qsslsocket_openssl_symbols.cpp
r788 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 43 43 #include "qsslsocket_openssl_symbols_p.h" 44 44 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 46 50 #include <QtCore/qmutex.h> 47 51 #include <private/qmutexpool_p.h> … … 120 124 DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return) 121 125 DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return) 126 DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) 127 DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) 122 128 DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG) 123 129 DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return) … … 333 339 .split(QLatin1Char(':'), QString::SkipEmptyParts); 334 340 # endif 335 paths << QLatin1String("/ usr/lib") << QLatin1String("/usr/local/lib");341 paths << QLatin1String("/lib") << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib"); 336 342 337 343 QStringList foundSsls; … … 348 354 } 349 355 # endif 356 357 #ifdef Q_OS_WIN 358 static 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 350 383 351 384 static QPair<QLibrary*, QLibrary*> loadOpenSsl() … … 355 388 pair.second = 0; 356 389 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) 376 391 QLibrary *libssl = new QLibrary(QLatin1String("libssl")); 377 392 if (!libssl->load()) { … … 506 521 # endif 507 522 } 523 #endif 508 524 509 525 bool q_resolveOpenSslSymbols() … … 520 536 triedToResolveSymbols = true; 521 537 538 #ifdef Q_OS_WIN 539 QPair<QSystemLibrary *, QSystemLibrary *> libs = loadOpenSslWin32(); 540 #else 522 541 QPair<QLibrary *, QLibrary *> libs = loadOpenSsl(); 542 #endif 523 543 if (!libs.first || !libs.second) 524 544 // failed to load them … … 549 569 RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second ) 550 570 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 ) 551 573 RESOLVEFUNC(EVP_PKEY_free, 867, libs.second ) 552 574 RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second ) … … 671 693 RESOLVEFUNC(EVP_des_ede3_cbc) 672 694 RESOLVEFUNC(EVP_PKEY_assign) 695 RESOLVEFUNC(EVP_PKEY_set1_RSA) 696 RESOLVEFUNC(EVP_PKEY_set1_DSA) 673 697 RESOLVEFUNC(EVP_PKEY_free) 674 698 RESOLVEFUNC(EVP_PKEY_get1_DSA) … … 794 818 QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) 795 819 { 796 char lBuffer[24];797 char *pBuffer = lBuffer;798 799 820 size_t lTimeLength = aTime->length; 800 821 char *pString = (char *) aTime->data; 801 822 802 823 if (aTime->type == V_ASN1_UTCTIME) { 824 825 char lBuffer[24]; 826 char *pBuffer = lBuffer; 827 803 828 if ((lTimeLength < 11) || (lTimeLength > 17)) 804 829 return QDateTime(); … … 807 832 pBuffer += 10; 808 833 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 809 904 } 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 864 909 } 865 910 -
trunk/src/network/ssl/qsslsocket_openssl_symbols_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 228 228 const EVP_CIPHER *q_EVP_des_ede3_cbc(); 229 229 int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c); 230 int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); 231 int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); 230 232 void q_EVP_PKEY_free(EVP_PKEY *a); 231 233 RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); -
trunk/src/network/ssl/qsslsocket_p.h
r651 r846 1 1 /**************************************************************************** 2 2 ** 3 ** Copyright (C) 201 0Nokia Corporation and/or its subsidiary(-ies).3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** All rights reserved. 5 5 ** Contact: Nokia Corporation (qt-info@nokia.com) … … 67 67 QT_BEGIN_NAMESPACE 68 68 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 69 91 class QSslSocketPrivate : public QTcpSocketPrivate 70 92 { … … 91 113 QString verificationPeerName; 92 114 93 static bool ensureInitialized(); 115 static bool supportsSsl(); 116 static void ensureInitialized(); 94 117 static void deinitialize(); 95 118 static QList<QSslCipher> defaultCiphers(); … … 107 130 static void addDefaultCaCertificates(const QList<QSslCertificate> &certs); 108 131 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 109 142 // The socket itself, including private slots. 110 143 QTcpSocket *plainSocket; 111 144 void createPlainSocket(QIODevice::OpenMode openMode); 145 static void pauseSocketNotifiers(QSslSocket*); 146 static void resumeSocketNotifiers(QSslSocket*); 112 147 void _q_connectedSlot(); 113 148 void _q_hostFoundSlot(); … … 127 162 virtual void disconnected() = 0; 128 163 virtual QSslCipher sessionCipher() const = 0; 164 165 private: 166 static bool ensureLibraryLoaded(); 167 static void ensureCiphersAndCertsLoaded(); 168 169 static bool s_libraryLoaded; 170 static bool s_loadedCiphersAndCerts; 129 171 }; 130 172 -
trunk/src/network/ssl/ssl.pri
r788 r846 32 32 ssl/qsslsocket_openssl_symbols.cpp 33 33 34 # Include Qt's default CA bundle35 RESOURCES += network.qrc36 37 34 # Add optional SSL libs 38 35 LIBS_PRIVATE += $$OPENSSL_LIBS
Note:
See TracChangeset
for help on using the changeset viewer.