source: trunk/src/network/ssl/qsslsocket_openssl.cpp@ 308

Last change on this file since 308 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 32.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtNetwork module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42//#define QSSLSOCKET_DEBUG
43
44#include "qsslsocket_openssl_p.h"
45#include "qsslsocket_openssl_symbols_p.h"
46#include "qsslsocket.h"
47#include "qsslcertificate_p.h"
48#include "qsslcipher_p.h"
49
50#include <QtCore/qdatetime.h>
51#include <QtCore/qdebug.h>
52#include <QtCore/qdir.h>
53#include <QtCore/qdiriterator.h>
54#include <QtCore/qfile.h>
55#include <QtCore/qfileinfo.h>
56#include <QtCore/qmutex.h>
57#include <QtCore/qthread.h>
58#include <QtCore/qurl.h>
59#include <QtCore/qvarlengtharray.h>
60
61static void initNetworkResources()
62{
63 // Initialize resources
64 Q_INIT_RESOURCE(network);
65}
66
67QT_BEGIN_NAMESPACE
68
69// Useful defines
70#define SSL_ERRORSTR() QString::fromLocal8Bit(q_ERR_error_string(q_ERR_get_error(), NULL))
71
72/* \internal
73
74 From OpenSSL's thread(3) manual page:
75
76 OpenSSL can safely be used in multi-threaded applications provided that at
77 least two callback functions are set.
78
79 locking_function(int mode, int n, const char *file, int line) is needed to
80 perform locking on shared data structures. (Note that OpenSSL uses a
81 number of global data structures that will be implicitly shared
82 when-whenever ever multiple threads use OpenSSL.) Multi-threaded
83 applications will crash at random if it is not set. ...
84 ...
85 id_function(void) is a function that returns a thread ID. It is not
86 needed on Windows nor on platforms where getpid() returns a different
87 ID for each thread (most notably Linux)
88*/
89class QOpenSslLocks
90{
91public:
92 inline QOpenSslLocks()
93 : initLocker(QMutex::Recursive),
94 locksLocker(QMutex::Recursive)
95 {
96 QMutexLocker locker(&locksLocker);
97 int numLocks = q_CRYPTO_num_locks();
98 locks = new QMutex *[numLocks];
99 memset(locks, 0, numLocks * sizeof(QMutex *));
100 }
101 inline ~QOpenSslLocks()
102 {
103 QMutexLocker locker(&locksLocker);
104 for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
105 delete locks[i];
106 delete [] locks;
107
108 QSslSocketPrivate::deinitialize();
109 }
110 inline QMutex *lock(int num)
111 {
112 QMutexLocker locker(&locksLocker);
113 QMutex *tmp = locks[num];
114 if (!tmp)
115 tmp = locks[num] = new QMutex(QMutex::Recursive);
116 return tmp;
117 }
118
119 QMutex *globalLock()
120 {
121 return &locksLocker;
122 }
123
124 QMutex *initLock()
125 {
126 return &initLocker;
127 }
128
129private:
130 QMutex initLocker;
131 QMutex locksLocker;
132 QMutex **locks;
133};
134Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
135
136extern "C" {
137static void locking_function(int mode, int lockNumber, const char *, int)
138{
139 QMutex *mutex = openssl_locks()->lock(lockNumber);
140
141 // Lock or unlock it
142 if (mode & CRYPTO_LOCK)
143 mutex->lock();
144 else
145 mutex->unlock();
146}
147static unsigned long id_function()
148{
149 return (unsigned long)QThread::currentThreadId();
150}
151} // extern "C"
152
153QSslSocketBackendPrivate::QSslSocketBackendPrivate()
154 : ssl(0),
155 ctx(0),
156 readBio(0),
157 writeBio(0),
158 session(0)
159{
160 // Calls SSL_library_init().
161 ensureInitialized();
162}
163
164QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
165{
166}
167
168QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
169{
170 QSslCipher ciph;
171
172 char buf [256];
173 QString descriptionOneLine = QString::fromLatin1(q_SSL_CIPHER_description(cipher, buf, sizeof(buf)));
174
175 QStringList descriptionList = descriptionOneLine.split(QLatin1String(" "), QString::SkipEmptyParts);
176 if (descriptionList.size() > 5) {
177 // ### crude code.
178 ciph.d->isNull = false;
179 ciph.d->name = descriptionList.at(0);
180
181 QString protoString = descriptionList.at(1);
182 ciph.d->protocolString = protoString;
183 ciph.d->protocol = QSsl::UnknownProtocol;
184 if (protoString == QLatin1String("SSLv3"))
185 ciph.d->protocol = QSsl::SslV3;
186 else if (protoString == QLatin1String("SSLv2"))
187 ciph.d->protocol = QSsl::SslV2;
188 else if (protoString == QLatin1String("TLSv1"))
189 ciph.d->protocol = QSsl::TlsV1;
190
191 if (descriptionList.at(2).startsWith(QLatin1String("Kx=")))
192 ciph.d->keyExchangeMethod = descriptionList.at(2).mid(3);
193 if (descriptionList.at(3).startsWith(QLatin1String("Au=")))
194 ciph.d->authenticationMethod = descriptionList.at(3).mid(3);
195 if (descriptionList.at(4).startsWith(QLatin1String("Enc=")))
196 ciph.d->encryptionMethod = descriptionList.at(4).mid(4);
197 ciph.d->exportable = (descriptionList.size() > 6 && descriptionList.at(6) == QLatin1String("export"));
198
199 ciph.d->bits = cipher->strength_bits;
200 ciph.d->supportedBits = cipher->alg_bits;
201
202 }
203 return ciph;
204}
205
206// ### This list is shared between all threads, and protected by a
207// mutex. Investigate using thread local storage instead.
208struct QSslErrorList
209{
210 QMutex mutex;
211 QList<QPair<int, int> > errors;
212};
213Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
214static int q_X509Callback(int ok, X509_STORE_CTX *ctx)
215{
216 if (!ok) {
217 // Store the error and at which depth the error was detected.
218 _q_sslErrorList()->errors << qMakePair<int, int>(ctx->error, ctx->error_depth);
219 }
220 // Always return OK to allow verification to continue. We're handle the
221 // errors gracefully after collecting all errors, after verification has
222 // completed.
223 return 1;
224}
225
226bool QSslSocketBackendPrivate::initSslContext()
227{
228 Q_Q(QSslSocket);
229
230 // Create and initialize SSL context. Accept SSLv2, SSLv3 and TLSv1.
231 bool client = (mode == QSslSocket::SslClientMode);
232
233 bool reinitialized = false;
234init_context:
235 switch (configuration.protocol) {
236 case QSsl::SslV2:
237 ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
238 break;
239 case QSsl::SslV3:
240 ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
241 break;
242 case QSsl::AnyProtocol:
243 default:
244 ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
245 break;
246 case QSsl::TlsV1:
247 ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
248 break;
249 }
250 if (!ctx) {
251 // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them
252 // by re-initializing the library.
253 if (!reinitialized) {
254 reinitialized = true;
255 if (q_SSL_library_init() == 1)
256 goto init_context;
257 }
258
259 // ### Bad error code
260 q->setErrorString(QSslSocket::tr("Error creating SSL context (%1)").arg(SSL_ERRORSTR()));
261 q->setSocketError(QAbstractSocket::UnknownSocketError);
262 emit q->error(QAbstractSocket::UnknownSocketError);
263 return false;
264 }
265
266 // Enable all bug workarounds.
267 q_SSL_CTX_set_options(ctx, SSL_OP_ALL);
268
269 // Initialize ciphers
270 QByteArray cipherString;
271 int first = true;
272 QList<QSslCipher> ciphers = configuration.ciphers;
273 if (ciphers.isEmpty())
274 ciphers = defaultCiphers();
275 foreach (const QSslCipher &cipher, ciphers) {
276 if (first)
277 first = false;
278 else
279 cipherString.append(":");
280 cipherString.append(cipher.name().toLatin1());
281 }
282
283 if (!q_SSL_CTX_set_cipher_list(ctx, cipherString.data())) {
284 // ### Bad error code
285 q->setErrorString(QSslSocket::tr("Invalid or empty cipher list (%1)").arg(SSL_ERRORSTR()));
286 q->setSocketError(QAbstractSocket::UnknownSocketError);
287 emit q->error(QAbstractSocket::UnknownSocketError);
288 return false;
289 }
290
291 // Add all our CAs to this store.
292 foreach (const QSslCertificate &caCertificate, q->caCertificates())
293 q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
294
295 // Register a custom callback to get all verification errors.
296 X509_STORE_set_verify_cb_func(ctx->cert_store, q_X509Callback);
297
298 if (!configuration.localCertificate.isNull()) {
299 // Require a private key as well.
300 if (configuration.privateKey.isNull()) {
301 q->setErrorString(QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(SSL_ERRORSTR()));
302 emit q->error(QAbstractSocket::UnknownSocketError);
303 return false;
304 }
305
306 // Load certificate
307 if (!q_SSL_CTX_use_certificate(ctx, (X509 *)configuration.localCertificate.handle())) {
308 q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(SSL_ERRORSTR()));
309 emit q->error(QAbstractSocket::UnknownSocketError);
310 return false;
311 }
312
313 // Load private key
314 EVP_PKEY *pkey = q_EVP_PKEY_new();
315 if (configuration.privateKey.algorithm() == QSsl::Rsa)
316 q_EVP_PKEY_assign_RSA(pkey, (RSA *)configuration.privateKey.handle());
317 else
318 q_EVP_PKEY_assign_DSA(pkey, (DSA *)configuration.privateKey.handle());
319 if (!q_SSL_CTX_use_PrivateKey(ctx, pkey)) {
320 q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(SSL_ERRORSTR()));
321 emit q->error(QAbstractSocket::UnknownSocketError);
322 return false;
323 }
324
325 // Check if the certificate matches the private key.
326 if (!q_SSL_CTX_check_private_key(ctx)) {
327 q->setErrorString(QSslSocket::tr("Private key does not certificate public key, %1").arg(SSL_ERRORSTR()));
328 emit q->error(QAbstractSocket::UnknownSocketError);
329 return false;
330 }
331 }
332
333 // Initialize peer verification.
334 if (configuration.peerVerifyMode == QSslSocket::VerifyNone) {
335 q_SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
336 } else {
337 q_SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, q_X509Callback);
338 }
339
340 // Set verification depth.
341 if (configuration.peerVerifyDepth != 0)
342 q_SSL_CTX_set_verify_depth(ctx, configuration.peerVerifyDepth);
343
344 // Create and initialize SSL session
345 if (!(ssl = q_SSL_new(ctx))) {
346 // ### Bad error code
347 q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(SSL_ERRORSTR()));
348 q->setSocketError(QAbstractSocket::UnknownSocketError);
349 emit q->error(QAbstractSocket::UnknownSocketError);
350 return false;
351 }
352
353 // Clear the session.
354 q_SSL_clear(ssl);
355 errorList.clear();
356
357 // Initialize memory BIOs for encryption and decryption.
358 readBio = q_BIO_new(q_BIO_s_mem());
359 writeBio = q_BIO_new(q_BIO_s_mem());
360 if (!readBio || !writeBio) {
361 // ### Bad error code
362 q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(SSL_ERRORSTR()));
363 q->setSocketError(QAbstractSocket::UnknownSocketError);
364 emit q->error(QAbstractSocket::UnknownSocketError);
365 return false;
366 }
367
368 // Assign the bios.
369 q_SSL_set_bio(ssl, readBio, writeBio);
370
371 if (mode == QSslSocket::SslClientMode)
372 q_SSL_set_connect_state(ssl);
373 else
374 q_SSL_set_accept_state(ssl);
375
376 return true;
377}
378
379/*!
380 \internal
381*/
382void QSslSocketPrivate::deinitialize()
383{
384 q_CRYPTO_set_id_callback(0);
385 q_CRYPTO_set_locking_callback(0);
386}
387
388/*!
389 \internal
390
391 Declared static in QSslSocketPrivate, makes sure the SSL libraries have
392 been initialized.
393*/
394bool QSslSocketPrivate::ensureInitialized()
395{
396 if (!q_resolveOpenSslSymbols())
397 return false;
398
399 // Check if the library itself needs to be initialized.
400 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();
407
408 // Initialize OpenSSL.
409 q_CRYPTO_set_id_callback(id_function);
410 q_CRYPTO_set_locking_callback(locking_function);
411 if (q_SSL_library_init() != 1)
412 return false;
413 q_SSL_load_error_strings();
414 q_OpenSSL_add_all_algorithms();
415
416 // Initialize OpenSSL's random seed.
417 if (!q_RAND_status()) {
418 struct {
419 int msec;
420 int sec;
421 void *stack;
422 } randomish;
423
424 int attempts = 500;
425 do {
426 if (attempts < 500) {
427#ifdef Q_OS_UNIX
428 struct timespec ts = {0, 33333333};
429 nanosleep(&ts, 0);
430#else
431 Sleep(3);
432#endif
433 randomish.msec = attempts;
434 }
435 randomish.stack = (void *)&randomish;
436 randomish.msec = QTime::currentTime().msec();
437 randomish.sec = QTime::currentTime().second();
438 q_RAND_seed((const char *)&randomish, sizeof(randomish));
439 } while (!q_RAND_status() && --attempts);
440 if (!attempts)
441 return false;
442 }
443
444 resetDefaultCiphers();
445 setDefaultCaCertificates(systemCaCertificates());
446 }
447 return true;
448}
449
450/*!
451 \internal
452
453 Declared static in QSslSocketPrivate, backend-dependent loading of
454 application-wide global ciphers.
455*/
456void QSslSocketPrivate::resetDefaultCiphers()
457{
458 SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method());
459 SSL *mySsl = q_SSL_new(myCtx);
460
461 QList<QSslCipher> ciphers;
462
463 STACK_OF(SSL_CIPHER) *supportedCiphers = q_SSL_get_ciphers(mySsl);
464 for (int i = 0; i < q_sk_SSL_CIPHER_num(supportedCiphers); ++i) {
465 if (SSL_CIPHER *cipher = q_sk_SSL_CIPHER_value(supportedCiphers, i)) {
466 if (cipher->valid) {
467 QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher);
468 if (!ciph.isNull()) {
469 if (!ciph.name().toLower().startsWith(QLatin1String("adh")))
470 ciphers << ciph;
471 }
472 }
473 }
474 }
475
476 q_SSL_CTX_free(myCtx);
477 q_SSL_free(mySsl);
478
479 setDefaultSupportedCiphers(ciphers);
480 setDefaultCiphers(ciphers);
481}
482
483QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
484{
485#ifdef QQ_OS_UNIX
486 // Check known locations for the system's default bundle. ### On Windows,
487 // we should use CAPI to find the bundle, and not rely on default unix
488 // locations.
489 const char *standardLocations[] = {"/etc/ssl/certs/",
490#if 0
491 // KDE uses KConfig for its SSL store,
492 // but it also stores the bundle at
493 // this location
494 "$HOME/.kde/share/apps/kssl/ca-bundle.crt",
495#endif
496 0};
497 const char **it = standardLocations;
498 QStringList nameFilter;
499 nameFilter << QLatin1String("*.pem") << QLatin1String("*.crt");
500 while (*it) {
501 if (QDirIterator(QLatin1String(*it), nameFilter).hasNext())
502 return certificatesFromPath(QLatin1String(*it));
503 ++it;
504 }
505#endif
506
507 // Qt provides a default bundle when we cannot detect the system's default
508 // bundle.
509 QFile caBundle(QLatin1String(":/trolltech/network/ssl/qt-ca-bundle.crt"));
510 if (caBundle.open(QIODevice::ReadOnly | QIODevice::Text))
511 return QSslCertificate::fromDevice(&caBundle);
512
513 // Unreachable; return no bundle.
514 return QList<QSslCertificate>();
515}
516
517void QSslSocketBackendPrivate::startClientEncryption()
518{
519 if (!initSslContext()) {
520 // ### report error: internal OpenSSL failure
521 return;
522 }
523
524 // Start connecting. This will place outgoing data in the BIO, so we
525 // follow up with calling transmit().
526 testConnection();
527 transmit();
528}
529
530void QSslSocketBackendPrivate::startServerEncryption()
531{
532 if (!initSslContext()) {
533 // ### report error: internal OpenSSL failure
534 return;
535 }
536
537 // Start connecting. This will place outgoing data in the BIO, so we
538 // follow up with calling transmit().
539 testConnection();
540 transmit();
541}
542
543/*!
544 \internal
545
546 Transmits encrypted data between the BIOs and the socket.
547*/
548void QSslSocketBackendPrivate::transmit()
549{
550 Q_Q(QSslSocket);
551
552 // If we don't have any SSL context, don't bother transmitting.
553 if (!ssl)
554 return;
555
556 bool transmitting;
557 do {
558 transmitting = false;
559
560 // If the connection is secure, we can transfer data from the write
561 // buffer (in plain text) to the write BIO through SSL_write.
562 if (connectionEncrypted && !writeBuffer.isEmpty()) {
563 qint64 totalBytesWritten = 0;
564 int nextDataBlockSize;
565 while ((nextDataBlockSize = writeBuffer.nextDataBlockSize()) > 0) {
566 int writtenBytes = q_SSL_write(ssl, writeBuffer.readPointer(), nextDataBlockSize);
567 if (writtenBytes <= 0) {
568 // ### Better error handling.
569 q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(SSL_ERRORSTR()));
570 q->setSocketError(QAbstractSocket::UnknownSocketError);
571 emit q->error(QAbstractSocket::UnknownSocketError);
572 return;
573 }
574#ifdef QSSLSOCKET_DEBUG
575 qDebug() << "QSslSocketBackendPrivate::transmit: encrypted" << writtenBytes << "bytes";
576#endif
577 writeBuffer.free(writtenBytes);
578 totalBytesWritten += writtenBytes;
579 }
580
581 if (totalBytesWritten > 0) {
582 // Don't emit bytesWritten() recursively.
583 if (!emittedBytesWritten) {
584 emittedBytesWritten = true;
585 emit q->bytesWritten(totalBytesWritten);
586 emittedBytesWritten = false;
587 }
588 }
589 }
590
591 // Check if we've got any data to be written to the socket.
592 QVarLengthArray<char, 4096> data;
593 int pendingBytes;
594 while (plainSocket->isValid() && (pendingBytes = q_BIO_pending(writeBio)) > 0) {
595 // Read encrypted data from the write BIO into a buffer.
596 data.resize(pendingBytes);
597 int encryptedBytesRead = q_BIO_read(writeBio, data.data(), pendingBytes);
598
599 // Write encrypted data from the buffer to the socket.
600 plainSocket->write(data.constData(), encryptedBytesRead);
601#ifdef QSSLSOCKET_DEBUG
602 qDebug() << "QSslSocketBackendPrivate::transmit: wrote" << encryptedBytesRead << "encrypted bytes to the socket";
603#endif
604 transmitting = true;
605 }
606
607 // Check if we've got any data to be read from the socket.
608 if (!connectionEncrypted || !readBufferMaxSize || readBuffer.size() < readBufferMaxSize)
609 while ((pendingBytes = plainSocket->bytesAvailable()) > 0) {
610 // Read encrypted data from the socket into a buffer.
611 data.resize(pendingBytes);
612 int decryptedBytesRead = plainSocket->read(data.data(), pendingBytes);
613#ifdef QSSLSOCKET_DEBUG
614 qDebug() << "QSslSocketBackendPrivate::transmit: read" << decryptedBytesRead << "encrypted bytes from the socket";
615#endif
616 // Write encrypted data from the buffer into the read BIO.
617 q_BIO_write(readBio, data.constData(), decryptedBytesRead);
618 transmitting = true;
619 }
620
621 // If the connection isn't secured yet, this is the time to retry the
622 // connect / accept.
623 if (!connectionEncrypted) {
624#ifdef QSSLSOCKET_DEBUG
625 qDebug() << "QSslSocketBackendPrivate::transmit: testing encryption";
626#endif
627 if (testConnection()) {
628#ifdef QSSLSOCKET_DEBUG
629 qDebug() << "QSslSocketBackendPrivate::transmit: encryption established";
630#endif
631 connectionEncrypted = true;
632 transmitting = true;
633 } else if (plainSocket->state() != QAbstractSocket::ConnectedState) {
634#ifdef QSSLSOCKET_DEBUG
635 qDebug() << "QSslSocketBackendPrivate::transmit: connection lost";
636#endif
637 break;
638 } else {
639#ifdef QSSLSOCKET_DEBUG
640 qDebug() << "QSslSocketBackendPrivate::transmit: encryption not done yet";
641#endif
642 }
643 }
644
645 // If the request is small and the remote host closes the transmission
646 // after sending, there's a chance that testConnection() will already
647 // have triggered a shutdown.
648 if (!ssl)
649 continue;
650
651 // We always read everything from the SSL decryption buffers, even if
652 // we have a readBufferMaxSize. There's no point in leaving data there
653 // just so that readBuffer.size() == readBufferMaxSize.
654 int readBytes = 0;
655 data.resize(4096);
656 ::memset(data.data(), 0, data.size());
657 do {
658 // Don't use SSL_pending(). It's very unreliable.
659 if ((readBytes = q_SSL_read(ssl, data.data(), data.size())) > 0) {
660#ifdef QSSLSOCKET_DEBUG
661 qDebug() << "QSslSocketBackendPrivate::transmit: decrypted" << readBytes << "bytes";
662#endif
663 char *ptr = readBuffer.reserve(readBytes);
664 ::memcpy(ptr, data.data(), readBytes);
665
666 if (readyReadEmittedPointer)
667 *readyReadEmittedPointer = true;
668 emit q->readyRead();
669 transmitting = true;
670 continue;
671 }
672
673 // Error.
674 switch (q_SSL_get_error(ssl, readBytes)) {
675 case SSL_ERROR_WANT_READ:
676 case SSL_ERROR_WANT_WRITE:
677 // Out of data.
678 break;
679 case SSL_ERROR_ZERO_RETURN:
680 // The remote host closed the connection.
681#ifdef QSSLSOCKET_DEBUG
682 qDebug() << "QSslSocketBackendPrivate::transmit: remote disconnect";
683#endif
684 plainSocket->disconnectFromHost();
685 break;
686 default:
687 // ### Handle errors better.
688 q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(SSL_ERRORSTR()));
689 q->setSocketError(QAbstractSocket::UnknownSocketError);
690 emit q->error(QAbstractSocket::UnknownSocketError);
691 break;
692 }
693 } while (ssl && readBytes > 0);
694 } while (ssl && ctx && transmitting);
695}
696
697static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &cert)
698{
699 QSslError error;
700 switch (errorCode) {
701 case X509_V_OK:
702 // X509_V_OK is also reported if the peer had no certificate.
703 break;
704 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
705 error = QSslError(QSslError::UnableToGetIssuerCertificate, cert); break;
706 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
707 error = QSslError(QSslError::UnableToDecryptCertificateSignature, cert); break;
708 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
709 error = QSslError(QSslError::UnableToDecodeIssuerPublicKey, cert); break;
710 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
711 error = QSslError(QSslError::CertificateSignatureFailed, cert); break;
712 case X509_V_ERR_CERT_NOT_YET_VALID:
713 error = QSslError(QSslError::CertificateNotYetValid, cert); break;
714 case X509_V_ERR_CERT_HAS_EXPIRED:
715 error = QSslError(QSslError::CertificateExpired, cert); break;
716 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
717 error = QSslError(QSslError::InvalidNotBeforeField, cert); break;
718 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
719 error = QSslError(QSslError::InvalidNotAfterField, cert); break;
720 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
721 error = QSslError(QSslError::SelfSignedCertificate, cert); break;
722 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
723 error = QSslError(QSslError::SelfSignedCertificateInChain, cert); break;
724 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
725 error = QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert); break;
726 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
727 error = QSslError(QSslError::UnableToVerifyFirstCertificate, cert); break;
728 case X509_V_ERR_CERT_REVOKED:
729 error = QSslError(QSslError::CertificateRevoked, cert); break;
730 case X509_V_ERR_INVALID_CA:
731 error = QSslError(QSslError::InvalidCaCertificate, cert); break;
732 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
733 error = QSslError(QSslError::PathLengthExceeded, cert); break;
734 case X509_V_ERR_INVALID_PURPOSE:
735 error = QSslError(QSslError::InvalidPurpose, cert); break;
736 case X509_V_ERR_CERT_UNTRUSTED:
737 error = QSslError(QSslError::CertificateUntrusted, cert); break;
738 case X509_V_ERR_CERT_REJECTED:
739 error = QSslError(QSslError::CertificateRejected, cert); break;
740 default:
741 error = QSslError(QSslError::UnspecifiedError, cert); break;
742 }
743 return error;
744}
745
746bool QSslSocketBackendPrivate::testConnection()
747{
748 Q_Q(QSslSocket);
749
750 // Check if the connection has been established. Get all errors from the
751 // verification stage.
752 _q_sslErrorList()->mutex.lock();
753 _q_sslErrorList()->errors.clear();
754 int result = (mode == QSslSocket::SslClientMode) ? q_SSL_connect(ssl) : q_SSL_accept(ssl);
755
756 const QList<QPair<int, int> > &lastErrors = _q_sslErrorList()->errors;
757 for (int i = 0; i < lastErrors.size(); ++i) {
758 const QPair<int, int> &currentError = lastErrors.at(i);
759 // Initialize the peer certificate chain in order to find which certificate caused this error
760 if (configuration.peerCertificateChain.isEmpty())
761 configuration.peerCertificateChain = STACKOFX509_to_QSslCertificates(q_SSL_get_peer_cert_chain(ssl));
762 emit q->peerVerifyError(_q_OpenSSL_to_QSslError(currentError.first,
763 configuration.peerCertificateChain.value(currentError.second)));
764 if (q->state() != QAbstractSocket::ConnectedState)
765 break;
766 }
767
768 errorList << lastErrors;
769 _q_sslErrorList()->mutex.unlock();
770
771 // Connection aborted during handshake phase.
772 if (q->state() != QAbstractSocket::ConnectedState)
773 return false;
774
775 // Check if we're encrypted or not.
776 if (result <= 0) {
777 switch (q_SSL_get_error(ssl, result)) {
778 case SSL_ERROR_WANT_READ:
779 case SSL_ERROR_WANT_WRITE:
780 // The handshake is not yet complete.
781 break;
782 default:
783 // ### Handle errors better
784 q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(SSL_ERRORSTR()));
785 q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
786#ifdef QSSLSOCKET_DEBUG
787 qDebug() << "QSslSocketBackendPrivate::testConnection: error!" << q->errorString();
788#endif
789 emit q->error(QAbstractSocket::SslHandshakeFailedError);
790 q->abort();
791 }
792 return false;
793 }
794
795 // Store the peer certificate and chain. For clients, the peer certificate
796 // chain includes the peer certificate; for servers, it doesn't. Both the
797 // peer certificate and the chain may be empty if the peer didn't present
798 // any certificate.
799 if (configuration.peerCertificateChain.isEmpty())
800 configuration.peerCertificateChain = STACKOFX509_to_QSslCertificates(q_SSL_get_peer_cert_chain(ssl));
801 X509 *x509 = q_SSL_get_peer_certificate(ssl);
802 configuration.peerCertificate = QSslCertificatePrivate::QSslCertificate_from_X509(x509);
803 q_X509_free(x509);
804
805 // Start translating errors.
806 QList<QSslError> errors;
807 bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
808 || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
809 && mode == QSslSocket::SslClientMode);
810
811 // Check the peer certificate itself. First try the subject's common name
812 // (CN) as a wildcard, then try all alternate subject name DNS entries the
813 // same way.
814 if (!configuration.peerCertificate.isNull()) {
815 // but only if we're a client connecting to a server
816 // if we're the server, don't check CN
817 if (mode == QSslSocket::SslClientMode) {
818 QString peerName = q->peerName();
819 QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName);
820
821 QRegExp regexp(commonName, Qt::CaseInsensitive, QRegExp::Wildcard);
822 if (!regexp.exactMatch(peerName)) {
823 bool matched = false;
824 foreach (QString altName, configuration.peerCertificate
825 .alternateSubjectNames().values(QSsl::DnsEntry)) {
826 regexp.setPattern(altName);
827 if (regexp.exactMatch(peerName)) {
828 matched = true;
829 break;
830 }
831 }
832 if (!matched) {
833 // No matches in common names or alternate names.
834 QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
835 errors << error;
836 emit q->peerVerifyError(error);
837 if (q->state() != QAbstractSocket::ConnectedState)
838 return false;
839 }
840 }
841 }
842 } else {
843 // No peer certificate presented. Report as error if the socket
844 // expected one.
845 if (doVerifyPeer) {
846 QSslError error(QSslError::NoPeerCertificate);
847 errors << error;
848 emit q->peerVerifyError(error);
849 if (q->state() != QAbstractSocket::ConnectedState)
850 return false;
851 }
852 }
853
854 // Translate errors from the error list into QSslErrors.
855 for (int i = 0; i < errorList.size(); ++i) {
856 const QPair<int, int> &errorAndDepth = errorList.at(i);
857 int err = errorAndDepth.first;
858 int depth = errorAndDepth.second;
859 errors << _q_OpenSSL_to_QSslError(err, configuration.peerCertificateChain.value(depth));
860 }
861
862 if (!errors.isEmpty()) {
863 sslErrors = errors;
864 emit q->sslErrors(errors);
865 if (doVerifyPeer && !ignoreSslErrors) {
866 q->setErrorString(sslErrors.first().errorString());
867 q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
868 emit q->error(QAbstractSocket::SslHandshakeFailedError);
869 plainSocket->disconnectFromHost();
870 return false;
871 }
872 } else {
873 sslErrors.clear();
874 }
875
876 // if we have a max read buffer size, reset the plain socket's to 1k
877 if (readBufferMaxSize)
878 plainSocket->setReadBufferSize(1024);
879
880 connectionEncrypted = true;
881 emit q->encrypted();
882 if (autoStartHandshake && pendingClose) {
883 pendingClose = false;
884 q->disconnectFromHost();
885 }
886 return true;
887}
888
889void QSslSocketBackendPrivate::disconnectFromHost()
890{
891 if (ssl) {
892 q_SSL_shutdown(ssl);
893 transmit();
894 }
895 plainSocket->disconnectFromHost();
896}
897
898void QSslSocketBackendPrivate::disconnected()
899{
900 if (ssl) {
901 q_SSL_free(ssl);
902 ssl = 0;
903 }
904 if (ctx) {
905 q_SSL_CTX_free(ctx);
906 ctx = 0;
907 }
908}
909
910QSslCipher QSslSocketBackendPrivate::sessionCipher() const
911{
912 if (!ssl || !ctx)
913 return QSslCipher();
914 SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
915 return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
916}
917
918QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
919{
920 ensureInitialized();
921 QList<QSslCertificate> certificates;
922 for (int i = 0; i < q_sk_X509_num(x509); ++i) {
923 if (X509 *entry = q_sk_X509_value(x509, i))
924 certificates << QSslCertificatePrivate::QSslCertificate_from_X509(entry);
925 }
926 return certificates;
927}
928
929QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.