Qt 4.8
qsslsocket_openssl.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 //#define QSSLSOCKET_DEBUG
43 //#define QT_DECRYPT_SSL_TRAFFIC
44 
45 #include "qsslsocket_openssl_p.h"
47 #include "qsslsocket.h"
48 #include "qsslcertificate_p.h"
49 #include "qsslcipher_p.h"
50 
51 #include <QtCore/qdatetime.h>
52 #include <QtCore/qdebug.h>
53 #include <QtCore/qdir.h>
54 #include <QtCore/qdiriterator.h>
55 #include <QtCore/qelapsedtimer.h>
56 #include <QtCore/qfile.h>
57 #include <QtCore/qfileinfo.h>
58 #include <QtCore/qmutex.h>
59 #include <QtCore/qthread.h>
60 #include <QtCore/qurl.h>
61 #include <QtCore/qvarlengtharray.h>
62 #include <QLibrary> // for loading the security lib for the CA store
63 
64 #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
65 // Symbian does not seem to have the symbol for SNI defined
66 #ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
67 #define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
68 #endif
69 #endif
71 
72 #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
73 #define kSecTrustSettingsDomainSystem 2 // so we do not need to include the header file
77 #elif defined(Q_OS_WIN)
78  PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0;
79  PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0;
80  PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0;
81 #elif defined(Q_OS_SYMBIAN)
82 #include <e32base.h>
83 #include <e32std.h>
84 #include <e32debug.h>
85 #include <QtCore/private/qcore_symbian_p.h>
86 #endif
87 
91 
92 /* \internal
93 
94  From OpenSSL's thread(3) manual page:
95 
96  OpenSSL can safely be used in multi-threaded applications provided that at
97  least two callback functions are set.
98 
99  locking_function(int mode, int n, const char *file, int line) is needed to
100  perform locking on shared data structures. (Note that OpenSSL uses a
101  number of global data structures that will be implicitly shared
102  when-whenever ever multiple threads use OpenSSL.) Multi-threaded
103  applications will crash at random if it is not set. ...
104  ...
105  id_function(void) is a function that returns a thread ID. It is not
106  needed on Windows nor on platforms where getpid() returns a different
107  ID for each thread (most notably Linux)
108 */
110 {
111 public:
112  inline QOpenSslLocks()
113  : initLocker(QMutex::Recursive),
114  locksLocker(QMutex::Recursive)
115  {
116  QMutexLocker locker(&locksLocker);
117  int numLocks = q_CRYPTO_num_locks();
118  locks = new QMutex *[numLocks];
119  memset(locks, 0, numLocks * sizeof(QMutex *));
120  }
121  inline ~QOpenSslLocks()
122  {
123  QMutexLocker locker(&locksLocker);
124  for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
125  delete locks[i];
126  delete [] locks;
127 
129  }
130  inline QMutex *lock(int num)
131  {
132  QMutexLocker locker(&locksLocker);
133  QMutex *tmp = locks[num];
134  if (!tmp)
135  tmp = locks[num] = new QMutex(QMutex::Recursive);
136  return tmp;
137  }
138 
140  {
141  return &locksLocker;
142  }
143 
145  {
146  return &initLocker;
147  }
148 
149 private:
153 };
154 Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
155 
156 extern "C" {
157 static void locking_function(int mode, int lockNumber, const char *, int)
158 {
159  QMutex *mutex = openssl_locks()->lock(lockNumber);
160 
161  // Lock or unlock it
162  if (mode & CRYPTO_LOCK)
163  mutex->lock();
164  else
165  mutex->unlock();
166 }
167 static unsigned long id_function()
168 {
170 }
171 } // extern "C"
172 
174  : ssl(0),
175  ctx(0),
176  pkey(0),
177  readBio(0),
178  writeBio(0),
179  session(0)
180 {
181  // Calls SSL_library_init().
183 }
184 
186 {
188 }
189 
191 {
192  QSslCipher ciph;
193 
194  char buf [256];
195  QString descriptionOneLine = QString::fromLatin1(q_SSL_CIPHER_description(cipher, buf, sizeof(buf)));
196 
197  QStringList descriptionList = descriptionOneLine.split(QLatin1String(" "), QString::SkipEmptyParts);
198  if (descriptionList.size() > 5) {
199  // ### crude code.
200  ciph.d->isNull = false;
201  ciph.d->name = descriptionList.at(0);
202 
203  QString protoString = descriptionList.at(1);
204  ciph.d->protocolString = protoString;
206  if (protoString == QLatin1String("SSLv3"))
207  ciph.d->protocol = QSsl::SslV3;
208  else if (protoString == QLatin1String("SSLv2"))
209  ciph.d->protocol = QSsl::SslV2;
210  else if (protoString == QLatin1String("TLSv1"))
211  ciph.d->protocol = QSsl::TlsV1;
212 
213  if (descriptionList.at(2).startsWith(QLatin1String("Kx=")))
214  ciph.d->keyExchangeMethod = descriptionList.at(2).mid(3);
215  if (descriptionList.at(3).startsWith(QLatin1String("Au=")))
216  ciph.d->authenticationMethod = descriptionList.at(3).mid(3);
217  if (descriptionList.at(4).startsWith(QLatin1String("Enc=")))
218  ciph.d->encryptionMethod = descriptionList.at(4).mid(4);
219  ciph.d->exportable = (descriptionList.size() > 6 && descriptionList.at(6) == QLatin1String("export"));
220 
221  ciph.d->bits = cipher->strength_bits;
222  ciph.d->supportedBits = cipher->alg_bits;
223 
224  }
225  return ciph;
226 }
227 
228 // ### This list is shared between all threads, and protected by a
229 // mutex. Investigate using thread local storage instead.
231 {
234 };
235 Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
236 static int q_X509Callback(int ok, X509_STORE_CTX *ctx)
237 {
238  if (!ok) {
239  // Store the error and at which depth the error was detected.
240  _q_sslErrorList()->errors << qMakePair<int, int>(q_X509_STORE_CTX_get_error(ctx), q_X509_STORE_CTX_get_error_depth(ctx));
241  }
242  // Always return OK to allow verification to continue. We're handle the
243  // errors gracefully after collecting all errors, after verification has
244  // completed.
245  return 1;
246 }
247 
249 {
250  Q_Q(QSslSocket);
251 
252  // Create and initialize SSL context. Accept SSLv2, SSLv3 and TLSv1.
253  bool client = (mode == QSslSocket::SslClientMode);
254 
255  bool reinitialized = false;
256 init_context:
257  switch (configuration.protocol) {
258  case QSsl::SslV2:
259 #ifndef OPENSSL_NO_SSL2
261 #else
262  ctx = 0; // SSL 2 not supported by the system, but chosen deliberately -> error
263 #endif
264  break;
265  case QSsl::SslV3:
267  break;
268  case QSsl::SecureProtocols: // SslV2 will be disabled below
269  case QSsl::TlsV1SslV3: // SslV2 will be disabled below
270  case QSsl::AnyProtocol:
271  default:
273  break;
274  case QSsl::TlsV1:
276  break;
277  }
278  if (!ctx) {
279  // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them
280  // by re-initializing the library.
281  if (!reinitialized) {
282  reinitialized = true;
283  if (q_SSL_library_init() == 1)
284  goto init_context;
285  }
286 
287  // ### Bad error code
288  q->setErrorString(QSslSocket::tr("Error creating SSL context (%1)").arg(getErrorsFromOpenSsl()));
289  q->setSocketError(QAbstractSocket::UnknownSocketError);
291  return false;
292  }
293 
294  // Enable bug workarounds.
295  long options;
297  options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
298  else
299  options = SSL_OP_ALL;
300 
301  // This option is disabled by default, so we need to be able to clear it
303  options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
304  else
305  options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
306 
307 #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
308  // This option is disabled by default, so we need to be able to clear it
310  options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
311  else
312  options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
313 #endif
314 
315 #ifdef SSL_OP_NO_TICKET
317  options |= SSL_OP_NO_TICKET;
318 #endif
319 #ifdef SSL_OP_NO_COMPRESSION
321  options |= SSL_OP_NO_COMPRESSION;
322 #endif
323 
324  q_SSL_CTX_set_options(ctx, options);
325 
326  // Initialize ciphers
327  QByteArray cipherString;
328  int first = true;
330  if (ciphers.isEmpty())
331  ciphers = defaultCiphers();
332  foreach (const QSslCipher &cipher, ciphers) {
333  if (first)
334  first = false;
335  else
336  cipherString.append(':');
337  cipherString.append(cipher.name().toLatin1());
338  }
339 
340  if (!q_SSL_CTX_set_cipher_list(ctx, cipherString.data())) {
341  // ### Bad error code
342  q->setErrorString(QSslSocket::tr("Invalid or empty cipher list (%1)").arg(getErrorsFromOpenSsl()));
343  q->setSocketError(QAbstractSocket::UnknownSocketError);
345  return false;
346  }
347 
348  // Add all our CAs to this store.
349  QList<QSslCertificate> expiredCerts;
350  foreach (const QSslCertificate &caCertificate, q->caCertificates()) {
351  // add expired certs later, so that the
352  // valid ones are used before the expired ones
353  if (! caCertificate.isValid()) {
354  expiredCerts.append(caCertificate);
355  } else {
356  q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
357  }
358  }
359 
360  bool addExpiredCerts = true;
361 #if defined(Q_OS_MAC) && (MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5)
362  //On Leopard SSL does not work if we add the expired certificates.
364  addExpiredCerts = false;
365 #endif
366  // now add the expired certs
367  if (addExpiredCerts) {
368  foreach (const QSslCertificate &caCertificate, expiredCerts) {
369  q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
370  }
371  }
372 
374  // tell OpenSSL the directories where to look up the root certs on demand
376  for (int a = 0; a < unixDirs.count(); ++a)
378  }
379 
381  // Require a private key as well.
383  q->setErrorString(QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(getErrorsFromOpenSsl()));
385  return false;
386  }
387 
388  // Load certificate
390  q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(getErrorsFromOpenSsl()));
392  return false;
393  }
394 
395  // Load private key
396  pkey = q_EVP_PKEY_new();
397  // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
398  // this lead to a memory leak. Now we use the *_set1_* functions which do not
399  // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
402  else
405  q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(getErrorsFromOpenSsl()));
407  return false;
408  }
409 
410  // Check if the certificate matches the private key.
412  q->setErrorString(QSslSocket::tr("Private key does not certify public key, %1").arg(getErrorsFromOpenSsl()));
414  return false;
415  }
416  }
417 
418  // Initialize peer verification.
420  q_SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
421  } else {
422  q_SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, q_X509Callback);
423  }
424 
425  // Set verification depth.
428 
429  // Create and initialize SSL session
430  if (!(ssl = q_SSL_new(ctx))) {
431  // ### Bad error code
432  q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl()));
433  q->setSocketError(QAbstractSocket::UnknownSocketError);
435  return false;
436  }
437 
438 #if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
443  client && q_SSLeay() >= 0x00090806fL) {
444  // Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
445  QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
446  if (tlsHostName.isEmpty())
447  tlsHostName = hostName;
448  QByteArray ace = QUrl::toAce(tlsHostName);
449  // only send the SNI header if the URL is valid and not an IP
450  if (!ace.isEmpty()
451  && !QHostAddress().setAddress(tlsHostName)
453  if (!q_SSL_ctrl(ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, ace.data()))
454  qWarning("could not set SSL_CTRL_SET_TLSEXT_HOSTNAME, Server Name Indication disabled");
455  }
456  }
457 #endif
458 
459  // Clear the session.
460  q_SSL_clear(ssl);
461  errorList.clear();
462 
463  // Initialize memory BIOs for encryption and decryption.
466  if (!readBio || !writeBio) {
467  // ### Bad error code
468  q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl()));
469  q->setSocketError(QAbstractSocket::UnknownSocketError);
471  return false;
472  }
473 
474  // Assign the bios.
476 
479  else
481 
482  return true;
483 }
484 
486 {
487  if (ssl) {
488  q_SSL_free(ssl);
489  ssl = 0;
490  }
491  if (ctx) {
493  ctx = 0;
494  }
495  if (pkey) {
497  pkey = 0;
498  }
499 }
500 
505 {
508 }
509 
521 {
522  return ensureLibraryLoaded();
523 }
524 
526 {
528  return false;
529 
530  // Check if the library itself needs to be initialized.
531  QMutexLocker locker(openssl_locks()->initLock());
532  if (!s_libraryLoaded) {
533  s_libraryLoaded = true;
534 
535  // Initialize OpenSSL.
538  if (q_SSL_library_init() != 1)
539  return false;
542 
543  // Initialize OpenSSL's random seed.
544  if (!q_RAND_status()) {
545  struct {
546  int msec;
547  int sec;
548  void *stack;
549  } randomish;
550 
551  int attempts = 500;
552  do {
553  if (attempts < 500) {
554 #ifdef Q_OS_UNIX
555  struct timespec ts = {0, 33333333};
556  nanosleep(&ts, 0);
557 #else
558  Sleep(3);
559 #endif
560  randomish.msec = attempts;
561  }
562  randomish.stack = (void *)&randomish;
563  randomish.msec = QTime::currentTime().msec();
564  randomish.sec = QTime::currentTime().second();
565  q_RAND_seed((const char *)&randomish, sizeof(randomish));
566  } while (!q_RAND_status() && --attempts);
567  if (!attempts)
568  return false;
569  }
570  }
571  return true;
572 }
573 
575 {
576  QMutexLocker locker(openssl_locks()->initLock());
578  return;
580 
582 
583  //load symbols needed to receive certificates from system store
584 #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
585  QLibrary securityLib("/System/Library/Frameworks/Security.framework/Versions/Current/Security");
586  if (securityLib.load()) {
587  ptrSecCertificateGetData = (PtrSecCertificateGetData) securityLib.resolve("SecCertificateGetData");
589  qWarning("could not resolve symbols in security library"); // should never happen
590 
591  ptrSecTrustSettingsCopyCertificates = (PtrSecTrustSettingsCopyCertificates) securityLib.resolve("SecTrustSettingsCopyCertificates");
592  if (!ptrSecTrustSettingsCopyCertificates) { // method was introduced in Leopard, use legacy method if it's not there
593  ptrSecTrustCopyAnchorCertificates = (PtrSecTrustCopyAnchorCertificates) securityLib.resolve("SecTrustCopyAnchorCertificates");
595  qWarning("could not resolve symbols in security library"); // should never happen
596  }
597  } else {
598  qWarning("could not load security library");
599  }
600 #elif defined(Q_OS_WIN)
601  HINSTANCE hLib = LoadLibraryW(L"Crypt32");
602  if (hLib) {
603 #if defined(Q_OS_WINCE)
604  ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, L"CertOpenStore");
605  ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, L"CertFindCertificateInStore");
606  ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, L"CertCloseStore");
607 #else
608  ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
609  ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
610  ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
611 #endif
612  if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
613  qWarning("could not resolve symbols in crypt32 library"); // should never happen
614  } else {
615  qWarning("could not load crypt32 library"); // should never happen
616  }
617 #elif defined(Q_OS_QNX)
619 #elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_MAC)
620  // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
622  QStringList symLinkFilter;
623  symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
624  for (int a = 0; a < dirs.count(); ++a) {
625  QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
626  if (iterator.hasNext()) {
628  break;
629  }
630  }
631 #endif
632  // if on-demand loading was not enabled, load the certs now
635 }
636 
648 {
649  if (!supportsSsl())
650  return;
651 
653 }
654 
665 {
666  SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method());
667  SSL *mySsl = q_SSL_new(myCtx);
668 
669  QList<QSslCipher> ciphers;
670 
671  STACK_OF(SSL_CIPHER) *supportedCiphers = q_SSL_get_ciphers(mySsl);
672  for (int i = 0; i < q_sk_SSL_CIPHER_num(supportedCiphers); ++i) {
673  if (SSL_CIPHER *cipher = q_sk_SSL_CIPHER_value(supportedCiphers, i)) {
674  if (cipher->valid) {
676  if (!ciph.isNull()) {
677  if (!ciph.name().toLower().startsWith(QLatin1String("adh")))
678  ciphers << ciph;
679  }
680  }
681  }
682  }
683 
684  q_SSL_CTX_free(myCtx);
685  q_SSL_free(mySsl);
686 
688  setDefaultCiphers(ciphers);
689 }
690 
691 #if defined(Q_OS_SYMBIAN)
692 
693 CSymbianCertificateRetriever::CSymbianCertificateRetriever() : CActive(CActive::EPriorityStandard),
694  iCertificatePtr(0,0,0), iSequenceError(KErrNone)
695 {
696 }
697 
698 CSymbianCertificateRetriever::~CSymbianCertificateRetriever()
699 {
700  iThread.Close();
701 }
702 
703 CSymbianCertificateRetriever* CSymbianCertificateRetriever::NewL()
704 {
705  CSymbianCertificateRetriever* self = new (ELeave) CSymbianCertificateRetriever();
706  CleanupStack::PushL(self);
707  self->ConstructL();
708  CleanupStack::Pop();
709  return self;
710 }
711 
712 int CSymbianCertificateRetriever::GetCertificates(QList<QByteArray> &certificates)
713 {
714  iCertificates = &certificates;
715 
716  TRequestStatus status;
717  iThread.Logon(status);
718  iThread.Resume();
719  User::WaitForRequest(status);
720  if (iThread.ExitType() == EExitKill)
721  return KErrDied;
722  else
723  return status.Int(); // Logon() completes with the thread's exit value
724 }
725 
726 void CSymbianCertificateRetriever::doThreadEntryL()
727 {
728  CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
729  CleanupStack::PushL(activeScheduler);
730  CActiveScheduler::Install(activeScheduler);
731 
732  CActiveScheduler::Add(this);
733 
734  // These aren't deleted in the destructor so leaving the to CS is ok
735  iCertStore = CUnifiedCertStore::NewLC(qt_s60GetRFs(), EFalse);
736  iCertFilter = CCertAttributeFilter::NewLC();
737 
738  // only interested in CA certs
739  iCertFilter->SetOwnerType(ECACertificate);
740  // only interested in X.509 format (we don't support WAP formats)
741  iCertFilter->SetFormat(EX509Certificate);
742 
743  // Kick off the sequence by initializing the cert store
744  iState = Initializing;
745  iCertStore->Initialize(iStatus);
746  SetActive();
747 
748  CActiveScheduler::Start();
749 
750  // Sequence complete, clean up
751 
752  // These MUST be cleaned up before the installed CActiveScheduler is destroyed and can't be left to the
753  // destructor of CSymbianCertificateRetriever. Otherwise the destructor of CActiveScheduler will get
754  // stuck.
755  iCertInfos.Close();
756  CleanupStack::PopAndDestroy(3); // activeScheduler, iCertStore, iCertFilter
757 }
758 
759 
760 TInt CSymbianCertificateRetriever::ThreadEntryPoint(TAny* aParams)
761 {
762  User::SetCritical(User::EProcessCritical);
763  CTrapCleanup* cleanupStack = CTrapCleanup::New();
764 
765  CSymbianCertificateRetriever* self = (CSymbianCertificateRetriever*) aParams;
766  TRAPD(err, self->doThreadEntryL());
767  delete cleanupStack;
768 
769  // doThreadEntryL() can leave only before the retrieval sequence is started
770  if (err)
771  return err;
772  else
773  return self->iSequenceError; // return any error that occurred during the retrieval
774 }
775 
776 void CSymbianCertificateRetriever::ConstructL()
777 {
778  TInt err;
779  int i=0;
780  QString name(QLatin1String("CertWorkerThread-%1"));
781  //recently closed thread names remain in use for a while until all handles have been closed
782  //including users of RUndertaker
783  do {
784  err = iThread.Create(qt_QString2TPtrC(name.arg(i++)),
785  CSymbianCertificateRetriever::ThreadEntryPoint, 16384, NULL, this);
786  } while (err == KErrAlreadyExists);
787  User::LeaveIfError(err);
788 }
789 
790 void CSymbianCertificateRetriever::DoCancel()
791 {
792  switch(iState) {
793  case Initializing:
794  iCertStore->CancelInitialize();
795  break;
796  case Listing:
797  iCertStore->CancelList();
798  break;
799  case RetrievingCertificates:
800  iCertStore->CancelGetCert();
801  break;
802  }
803 }
804 
805 TInt CSymbianCertificateRetriever::RunError(TInt aError)
806 {
807  // If something goes wrong in the sequence, abort the sequence
808  iSequenceError = aError; // this gets reported to the client in the TRequestStatus
809  CActiveScheduler::Stop();
810  return KErrNone;
811 }
812 
813 void CSymbianCertificateRetriever::GetCertificateL()
814 {
815  if (iCurrentCertIndex < iCertInfos.Count()) {
816  CCTCertInfo* certInfo = iCertInfos[iCurrentCertIndex++];
817  iCertificateData = QByteArray();
818  QT_TRYCATCH_LEAVING(iCertificateData.resize(certInfo->Size()));
819  iCertificatePtr.Set((TUint8*)iCertificateData.data(), 0, iCertificateData.size());
820 #ifdef QSSLSOCKET_DEBUG
821  qDebug() << "getting " << qt_TDesC2QString(certInfo->Label()) << " size=" << certInfo->Size();
822  qDebug() << "format=" << certInfo->CertificateFormat();
823  qDebug() << "ownertype=" << certInfo->CertificateOwnerType();
824  qDebug() << "type=" << hex << certInfo->Type().iUid;
825 #endif
826  iCertStore->Retrieve(*certInfo, iCertificatePtr, iStatus);
827  iState = RetrievingCertificates;
828  SetActive();
829  } else {
830  //reached end of list
831  CActiveScheduler::Stop();
832  }
833 }
834 
835 void CSymbianCertificateRetriever::RunL()
836 {
837 #ifdef QSSLSOCKET_DEBUG
838  qDebug() << "CSymbianCertificateRetriever::RunL status " << iStatus.Int() << " count " << iCertInfos.Count() << " index " << iCurrentCertIndex;
839 #endif
840  switch (iState) {
841  case Initializing:
842  User::LeaveIfError(iStatus.Int()); // initialise fail means pointless to continue
843  iState = Listing;
844  iCertStore->List(iCertInfos, *iCertFilter, iStatus);
845  SetActive();
846  break;
847 
848  case Listing:
849  User::LeaveIfError(iStatus.Int()); // listing fail means pointless to continue
850  iCurrentCertIndex = 0;
851  GetCertificateL();
852  break;
853 
854  case RetrievingCertificates:
855  if (iStatus.Int() == KErrNone)
856  iCertificates->append(iCertificateData);
857  else
858  qWarning() << "CSymbianCertificateRetriever: failed to retrieve a certificate, error " << iStatus.Int();
859  GetCertificateL();
860  break;
861  }
862 }
863 #endif // defined(Q_OS_SYMBIAN)
864 
866 {
868 #ifdef QSSLSOCKET_DEBUG
870  timer.start();
871 #endif
872  QList<QSslCertificate> systemCerts;
873 #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
874  CFArrayRef cfCerts;
875  OSStatus status = 1;
876 
877  OSStatus SecCertificateGetData (
878  SecCertificateRef certificate,
879  CSSM_DATA_PTR data
880  );
881 
886  status = ptrSecTrustCopyAnchorCertificates(&cfCerts);
887  if (!status) {
888  CFIndex size = CFArrayGetCount(cfCerts);
889  for (CFIndex i = 0; i < size; ++i) {
890  SecCertificateRef cfCert = (SecCertificateRef)CFArrayGetValueAtIndex(cfCerts, i);
891  CSSM_DATA data;
892  CSSM_DATA_PTR dataPtr = &data;
893  if (ptrSecCertificateGetData(cfCert, dataPtr)) {
894  qWarning("error retrieving a CA certificate from the system store");
895  } else {
896  int len = data.Length;
897  char *rawData = reinterpret_cast<char *>(data.Data);
898  QByteArray rawCert(rawData, len);
899  systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der));
900  }
901  }
902  CFRelease(cfCerts);
903  }
904  else {
905  // no detailed error handling here
906  qWarning("could not retrieve system CA certificates");
907  }
908  }
909 #elif defined(Q_OS_WIN)
910  if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
911  HCERTSTORE hSystemStore;
912 #if defined(Q_OS_WINCE)
913  hSystemStore = ptrCertOpenSystemStoreW(CERT_STORE_PROV_SYSTEM_W,
914  0,
915  0,
916  CERT_STORE_NO_CRYPT_RELEASE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,
917  L"ROOT");
918 #else
919  hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
920 #endif
921  if(hSystemStore) {
922  PCCERT_CONTEXT pc = NULL;
923  while(1) {
924  pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
925  if(!pc)
926  break;
927  QByteArray der((const char *)(pc->pbCertEncoded), static_cast<int>(pc->cbCertEncoded));
928  QSslCertificate cert(der, QSsl::Der);
929  systemCerts.append(cert);
930  }
931  ptrCertCloseStore(hSystemStore, 0);
932  }
933  }
934 #elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
935  QSet<QString> certFiles;
937  QDir currentDir;
938  QStringList nameFilters;
939  nameFilters << QLatin1String("*.pem") << QLatin1String("*.crt");
940  currentDir.setNameFilters(nameFilters);
941  for (int a = 0; a < directories.count(); a++) {
942  currentDir.setPath(QLatin1String(directories.at(a)));
943  QDirIterator it(currentDir);
944  while(it.hasNext()) {
945  it.next();
946  // use canonical path here to not load the same certificate twice if symlinked
947  certFiles.insert(it.fileInfo().canonicalFilePath());
948  }
949  }
950  QSetIterator<QString> it(certFiles);
951  while(it.hasNext()) {
952  systemCerts.append(QSslCertificate::fromPath(it.next()));
953  }
954  systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva
955  systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss
956 
957 #elif defined(Q_OS_SYMBIAN)
958  QList<QByteArray> certs;
959  QScopedPointer<CSymbianCertificateRetriever> retriever(CSymbianCertificateRetriever::NewL());
960 
961  retriever->GetCertificates(certs);
962  foreach (const QByteArray &encodedCert, certs) {
963  QSslCertificate cert(encodedCert, QSsl::Der);
964  if (!cert.isNull()) {
965 #ifdef QSSLSOCKET_DEBUG
966  qDebug() << "imported certificate: " << cert.issuerInfo(QSslCertificate::CommonName);
967 #endif
968  systemCerts.append(cert);
969  }
970  }
971 #endif
972 #ifdef QSSLSOCKET_DEBUG
973  qDebug() << "systemCaCertificates retrieval time " << timer.elapsed() << "ms";
974  qDebug() << "imported " << systemCerts.count() << " certificates";
975 #endif
976 
977  return systemCerts;
978 }
979 
981 {
982  if (!initSslContext()) {
983  // ### report error: internal OpenSSL failure
984  return;
985  }
986 
987  // Start connecting. This will place outgoing data in the BIO, so we
988  // follow up with calling transmit().
989  startHandshake();
990  transmit();
991 }
992 
994 {
995  if (!initSslContext()) {
996  // ### report error: internal OpenSSL failure
997  return;
998  }
999 
1000  // Start connecting. This will place outgoing data in the BIO, so we
1001  // follow up with calling transmit().
1002  startHandshake();
1003  transmit();
1004 }
1005 
1015 {
1016  Q_Q(QSslSocket);
1017 
1018  // If we don't have any SSL context, don't bother transmitting.
1019  if (!ssl)
1020  return;
1021 
1022  bool transmitting;
1023  do {
1024  transmitting = false;
1025 
1026  // If the connection is secure, we can transfer data from the write
1027  // buffer (in plain text) to the write BIO through SSL_write.
1029  qint64 totalBytesWritten = 0;
1030  int nextDataBlockSize;
1031  while ((nextDataBlockSize = writeBuffer.nextDataBlockSize()) > 0) {
1032  int writtenBytes = q_SSL_write(ssl, writeBuffer.readPointer(), nextDataBlockSize);
1033  if (writtenBytes <= 0) {
1034  // ### Better error handling.
1035  q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(getErrorsFromOpenSsl()));
1036  q->setSocketError(QAbstractSocket::UnknownSocketError);
1038  return;
1039  }
1040 #ifdef QSSLSOCKET_DEBUG
1041  qDebug() << "QSslSocketBackendPrivate::transmit: encrypted" << writtenBytes << "bytes";
1042 #endif
1043  writeBuffer.free(writtenBytes);
1044  totalBytesWritten += writtenBytes;
1045 
1046  if (writtenBytes < nextDataBlockSize) {
1047  // break out of the writing loop and try again after we had read
1048  transmitting = true;
1049  break;
1050  }
1051  }
1052 
1053  if (totalBytesWritten > 0) {
1054  // Don't emit bytesWritten() recursively.
1055  if (!emittedBytesWritten) {
1056  emittedBytesWritten = true;
1057  emit q->bytesWritten(totalBytesWritten);
1058  emittedBytesWritten = false;
1059  }
1060  }
1061  }
1062 
1063  // Check if we've got any data to be written to the socket.
1065  int pendingBytes;
1066  while (plainSocket->isValid() && (pendingBytes = q_BIO_pending(writeBio)) > 0) {
1067  // Read encrypted data from the write BIO into a buffer.
1068  data.resize(pendingBytes);
1069  int encryptedBytesRead = q_BIO_read(writeBio, data.data(), pendingBytes);
1070 
1071  // Write encrypted data from the buffer to the socket.
1072  qint64 actualWritten = plainSocket->write(data.constData(), encryptedBytesRead);
1073 #ifdef QSSLSOCKET_DEBUG
1074  qDebug() << "QSslSocketBackendPrivate::transmit: wrote" << encryptedBytesRead << "encrypted bytes to the socket" << actualWritten << "actual.";
1075 #endif
1076  if (actualWritten < 0) {
1077  //plain socket write fails if it was in the pending close state.
1078  q->setErrorString(plainSocket->errorString());
1079  q->setSocketError(plainSocket->error());
1080  emit q->error(plainSocket->error());
1081  return;
1082  }
1083  transmitting = true;
1084  }
1085 
1086  // Check if we've got any data to be read from the socket.
1088  while ((pendingBytes = plainSocket->bytesAvailable()) > 0) {
1089  // Read encrypted data from the socket into a buffer.
1090  data.resize(pendingBytes);
1091  // just peek() here because q_BIO_write could write less data than expected
1092  int encryptedBytesRead = plainSocket->peek(data.data(), pendingBytes);
1093 #ifdef QSSLSOCKET_DEBUG
1094  qDebug() << "QSslSocketBackendPrivate::transmit: read" << encryptedBytesRead << "encrypted bytes from the socket";
1095 #endif
1096  // Write encrypted data from the buffer into the read BIO.
1097  int writtenToBio = q_BIO_write(readBio, data.constData(), encryptedBytesRead);
1098 
1099  // do the actual read() here and throw away the results.
1100  if (writtenToBio > 0) {
1101  // ### TODO: make this cheaper by not making it memcpy. E.g. make it work with data=0x0 or make it work with seek
1102  plainSocket->read(data.data(), writtenToBio);
1103  } else {
1104  // ### Better error handling.
1105  q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(getErrorsFromOpenSsl()));
1106  q->setSocketError(QAbstractSocket::UnknownSocketError);
1108  return;
1109  }
1110 
1111  transmitting = true;
1112  }
1113 
1114  // If the connection isn't secured yet, this is the time to retry the
1115  // connect / accept.
1116  if (!connectionEncrypted) {
1117 #ifdef QSSLSOCKET_DEBUG
1118  qDebug() << "QSslSocketBackendPrivate::transmit: testing encryption";
1119 #endif
1120  if (startHandshake()) {
1121 #ifdef QSSLSOCKET_DEBUG
1122  qDebug() << "QSslSocketBackendPrivate::transmit: encryption established";
1123 #endif
1124  connectionEncrypted = true;
1125  transmitting = true;
1127 #ifdef QSSLSOCKET_DEBUG
1128  qDebug() << "QSslSocketBackendPrivate::transmit: connection lost";
1129 #endif
1130  break;
1131  } else {
1132 #ifdef QSSLSOCKET_DEBUG
1133  qDebug() << "QSslSocketBackendPrivate::transmit: encryption not done yet";
1134 #endif
1135  }
1136  }
1137 
1138  // If the request is small and the remote host closes the transmission
1139  // after sending, there's a chance that startHandshake() will already
1140  // have triggered a shutdown.
1141  if (!ssl)
1142  continue;
1143 
1144  // We always read everything from the SSL decryption buffers, even if
1145  // we have a readBufferMaxSize. There's no point in leaving data there
1146  // just so that readBuffer.size() == readBufferMaxSize.
1147  int readBytes = 0;
1148  data.resize(4096);
1149  ::memset(data.data(), 0, data.size());
1150  do {
1151  // Don't use SSL_pending(). It's very unreliable.
1152  if ((readBytes = q_SSL_read(ssl, data.data(), data.size())) > 0) {
1153 #ifdef QSSLSOCKET_DEBUG
1154  qDebug() << "QSslSocketBackendPrivate::transmit: decrypted" << readBytes << "bytes";
1155 #endif
1156  char *ptr = readBuffer.reserve(readBytes);
1157  ::memcpy(ptr, data.data(), readBytes);
1158 
1160  *readyReadEmittedPointer = true;
1161  emit q->readyRead();
1162  transmitting = true;
1163  continue;
1164  }
1165 
1166  // Error.
1167  switch (q_SSL_get_error(ssl, readBytes)) {
1168  case SSL_ERROR_WANT_READ:
1169  case SSL_ERROR_WANT_WRITE:
1170  // Out of data.
1171  break;
1172  case SSL_ERROR_ZERO_RETURN:
1173  // The remote host closed the connection.
1174 #ifdef QSSLSOCKET_DEBUG
1175  qDebug() << "QSslSocketBackendPrivate::transmit: remote disconnect";
1176 #endif
1177  shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
1178  q->setErrorString(QSslSocket::tr("The TLS/SSL connection has been closed"));
1179  q->setSocketError(QAbstractSocket::RemoteHostClosedError);
1181  return;
1182  case SSL_ERROR_SYSCALL: // some IO error
1183  case SSL_ERROR_SSL: // error in the SSL library
1184  // we do not know exactly what the error is, nor whether we can recover from it,
1185  // so just return to prevent an endless loop in the outer "while" statement
1186  q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
1187  q->setSocketError(QAbstractSocket::UnknownSocketError);
1189  return;
1190  default:
1191  // SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a
1192  // BIO_s_connect() or BIO_s_accept(), which we do not call.
1193  // SSL_ERROR_WANT_X509_LOOKUP: can only happen with a
1194  // SSL_CTX_set_client_cert_cb(), which we do not call.
1195  // So this default case should never be triggered.
1196  q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
1197  q->setSocketError(QAbstractSocket::UnknownSocketError);
1199  break;
1200  }
1201  } while (ssl && readBytes > 0);
1202  } while (ssl && ctx && transmitting);
1203 }
1204 
1205 static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &cert)
1206 {
1207  QSslError error;
1208  switch (errorCode) {
1209  case X509_V_OK:
1210  // X509_V_OK is also reported if the peer had no certificate.
1211  break;
1212  case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
1213  error = QSslError(QSslError::UnableToGetIssuerCertificate, cert); break;
1214  case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
1216  case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
1218  case X509_V_ERR_CERT_SIGNATURE_FAILURE:
1219  error = QSslError(QSslError::CertificateSignatureFailed, cert); break;
1220  case X509_V_ERR_CERT_NOT_YET_VALID:
1221  error = QSslError(QSslError::CertificateNotYetValid, cert); break;
1222  case X509_V_ERR_CERT_HAS_EXPIRED:
1223  error = QSslError(QSslError::CertificateExpired, cert); break;
1224  case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
1225  error = QSslError(QSslError::InvalidNotBeforeField, cert); break;
1226  case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
1227  error = QSslError(QSslError::InvalidNotAfterField, cert); break;
1228  case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1229  error = QSslError(QSslError::SelfSignedCertificate, cert); break;
1230  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1231  error = QSslError(QSslError::SelfSignedCertificateInChain, cert); break;
1232  case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1234  case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1236  case X509_V_ERR_CERT_REVOKED:
1237  error = QSslError(QSslError::CertificateRevoked, cert); break;
1238  case X509_V_ERR_INVALID_CA:
1239  error = QSslError(QSslError::InvalidCaCertificate, cert); break;
1240  case X509_V_ERR_PATH_LENGTH_EXCEEDED:
1241  error = QSslError(QSslError::PathLengthExceeded, cert); break;
1242  case X509_V_ERR_INVALID_PURPOSE:
1243  error = QSslError(QSslError::InvalidPurpose, cert); break;
1244  case X509_V_ERR_CERT_UNTRUSTED:
1245  error = QSslError(QSslError::CertificateUntrusted, cert); break;
1246  case X509_V_ERR_CERT_REJECTED:
1247  error = QSslError(QSslError::CertificateRejected, cert); break;
1248  default:
1249  error = QSslError(QSslError::UnspecifiedError, cert); break;
1250  }
1251  return error;
1252 }
1253 
1255 {
1256  Q_Q(QSslSocket);
1257 
1258  // Check if the connection has been established. Get all errors from the
1259  // verification stage.
1260  _q_sslErrorList()->mutex.lock();
1261  _q_sslErrorList()->errors.clear();
1263 
1264  const QList<QPair<int, int> > &lastErrors = _q_sslErrorList()->errors;
1265  for (int i = 0; i < lastErrors.size(); ++i) {
1266  const QPair<int, int> &currentError = lastErrors.at(i);
1267  // Initialize the peer certificate chain in order to find which certificate caused this error
1270  emit q->peerVerifyError(_q_OpenSSL_to_QSslError(currentError.first,
1272  if (q->state() != QAbstractSocket::ConnectedState)
1273  break;
1274  }
1275 
1276  errorList << lastErrors;
1277  _q_sslErrorList()->mutex.unlock();
1278 
1279  // Connection aborted during handshake phase.
1280  if (q->state() != QAbstractSocket::ConnectedState)
1281  return false;
1282 
1283  // Check if we're encrypted or not.
1284  if (result <= 0) {
1285  switch (q_SSL_get_error(ssl, result)) {
1286  case SSL_ERROR_WANT_READ:
1287  case SSL_ERROR_WANT_WRITE:
1288  // The handshake is not yet complete.
1289  break;
1290  default:
1291  q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl()));
1292  q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
1293 #ifdef QSSLSOCKET_DEBUG
1294  qDebug() << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString();
1295 #endif
1297  q->abort();
1298  }
1299  return false;
1300  }
1301 
1302  // Store the peer certificate and chain. For clients, the peer certificate
1303  // chain includes the peer certificate; for servers, it doesn't. Both the
1304  // peer certificate and the chain may be empty if the peer didn't present
1305  // any certificate.
1310  q_X509_free(x509);
1311 
1312  // Start translating errors.
1313  QList<QSslError> errors;
1314 
1315  // check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer)
1316  foreach (const QSslCertificate &cert, configuration.peerCertificateChain) {
1319  errors << error;
1320  emit q->peerVerifyError(error);
1321  if (q->state() != QAbstractSocket::ConnectedState)
1322  return false;
1323  }
1324  }
1325 
1326  bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
1329 
1330  // Check the peer certificate itself. First try the subject's common name
1331  // (CN) as a wildcard, then try all alternate subject name DNS entries the
1332  // same way.
1334  // but only if we're a client connecting to a server
1335  // if we're the server, don't check CN
1336  if (mode == QSslSocket::SslClientMode) {
1339 
1340  if (!isMatchingHostname(commonName.toLower(), peerName.toLower())) {
1341  bool matched = false;
1342  foreach (const QString &altName, configuration.peerCertificate
1344  if (isMatchingHostname(altName.toLower(), peerName.toLower())) {
1345  matched = true;
1346  break;
1347  }
1348  }
1349 
1350  if (!matched) {
1351  // No matches in common names or alternate names.
1353  errors << error;
1354  emit q->peerVerifyError(error);
1355  if (q->state() != QAbstractSocket::ConnectedState)
1356  return false;
1357  }
1358  }
1359  }
1360  } else {
1361  // No peer certificate presented. Report as error if the socket
1362  // expected one.
1363  if (doVerifyPeer) {
1365  errors << error;
1366  emit q->peerVerifyError(error);
1367  if (q->state() != QAbstractSocket::ConnectedState)
1368  return false;
1369  }
1370  }
1371 
1372  // Translate errors from the error list into QSslErrors.
1373  for (int i = 0; i < errorList.size(); ++i) {
1374  const QPair<int, int> &errorAndDepth = errorList.at(i);
1375  int err = errorAndDepth.first;
1376  int depth = errorAndDepth.second;
1378  }
1379 
1380  if (!errors.isEmpty()) {
1381  sslErrors = errors;
1382  emit q->sslErrors(errors);
1383 
1384  bool doEmitSslError;
1385  if (!ignoreErrorsList.empty()) {
1386  // check whether the errors we got are all in the list of expected errors
1387  // (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors)
1388  // was called)
1389  doEmitSslError = false;
1390  for (int a = 0; a < errors.count(); a++) {
1391  if (!ignoreErrorsList.contains(errors.at(a))) {
1392  doEmitSslError = true;
1393  break;
1394  }
1395  }
1396  } else {
1397  // if QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) was not called and
1398  // we get an SSL error, emit a signal unless we ignored all errors (by calling
1399  // QSslSocket::ignoreSslErrors() )
1400  doEmitSslError = !ignoreAllSslErrors;
1401  }
1402  // check whether we need to emit an SSL handshake error
1403  if (doVerifyPeer && doEmitSslError) {
1404  q->setErrorString(sslErrors.first().errorString());
1405  q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
1408  return false;
1409  }
1410  } else {
1411  sslErrors.clear();
1412  }
1413 
1414  // if we have a max read buffer size, reset the plain socket's to 32k
1415  if (readBufferMaxSize)
1417 
1418 #ifdef QT_DECRYPT_SSL_TRAFFIC
1419  if (ssl->session && ssl->s3) {
1420  const char *mk = reinterpret_cast<const char *>(ssl->session->master_key);
1421  QByteArray masterKey(mk, ssl->session->master_key_length);
1422  const char *random = reinterpret_cast<const char *>(ssl->s3->client_random);
1423  QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
1424 
1425  // different format, needed for e.g. older Wireshark versions:
1426 // const char *sid = reinterpret_cast<const char *>(ssl->session->session_id);
1427 // QByteArray sessionID(sid, ssl->session->session_id_length);
1428 // QByteArray debugLineRSA("RSA Session-ID:");
1429 // debugLineRSA.append(sessionID.toHex().toUpper());
1430 // debugLineRSA.append(" Master-Key:");
1431 // debugLineRSA.append(masterKey.toHex().toUpper());
1432 // debugLineRSA.append("\n");
1433 
1434  QByteArray debugLineClientRandom("CLIENT_RANDOM ");
1435  debugLineClientRandom.append(clientRandom.toHex().toUpper());
1436  debugLineClientRandom.append(" ");
1437  debugLineClientRandom.append(masterKey.toHex().toUpper());
1438  debugLineClientRandom.append("\n");
1439 
1440  QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
1441  QFile file(sslKeyFile);
1442  if (!file.open(QIODevice::Append))
1443  qWarning() << "could not open file" << sslKeyFile << "for appending";
1444  if (!file.write(debugLineClientRandom))
1445  qWarning() << "could not write to file" << sslKeyFile;
1446  file.close();
1447  } else {
1448  qWarning("could not decrypt SSL traffic");
1449  }
1450 #endif
1451 
1452  connectionEncrypted = true;
1453  emit q->encrypted();
1455  pendingClose = false;
1456  q->disconnectFromHost();
1457  }
1458  return true;
1459 }
1460 
1462 {
1463  if (ssl) {
1464  if (!shutdown) {
1466  shutdown = true;
1467  transmit();
1468  }
1469  }
1471 }
1472 
1474 {
1475  if (plainSocket->bytesAvailable() <= 0)
1477  //if there is still buffered data in the plain socket, don't destroy the ssl context yet.
1478  //it will be destroyed when the socket is deleted.
1479 }
1480 
1482 {
1483  if (!ssl || !ctx)
1484  return QSslCipher();
1485 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
1486  // FIXME This is fairly evil, but needed to keep source level compatibility
1487  // with the OpenSSL 0.9.x implementation at maximum -- some other functions
1488  // don't take a const SSL_CIPHER* when they should
1489  SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(q_SSL_get_current_cipher(ssl));
1490 #else
1491  SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
1492 #endif
1493  return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
1494 }
1495 
1497 {
1499  QList<QSslCertificate> certificates;
1500  for (int i = 0; i < q_sk_X509_num(x509); ++i) {
1501  if (X509 *entry = q_sk_X509_value(x509, i))
1503  }
1504  return certificates;
1505 }
1506 
1508 {
1510  unsigned long errNum;
1511  while((errNum = q_ERR_get_error())) {
1512  if (! errorString.isEmpty())
1513  errorString.append(QLatin1String(", "));
1514  const char *error = q_ERR_error_string(errNum, NULL);
1515  errorString.append(QString::fromAscii(error)); // error is ascii according to man ERR_error_string
1516  }
1517  return errorString;
1518 }
1519 
1521 {
1522  int wildcard = cn.indexOf(QLatin1Char('*'));
1523 
1524  // Check this is a wildcard cert, if not then just compare the strings
1525  if (wildcard < 0)
1526  return cn == hostname;
1527 
1528  int firstCnDot = cn.indexOf(QLatin1Char('.'));
1529  int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1);
1530 
1531  // Check at least 3 components
1532  if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length()))
1533  return false;
1534 
1535  // Check * is last character of 1st component (ie. there's a following .)
1536  if (wildcard+1 != firstCnDot)
1537  return false;
1538 
1539  // Check only one star
1540  if (cn.lastIndexOf(QLatin1Char('*')) != wildcard)
1541  return false;
1542 
1543  // Check characters preceding * (if any) match
1544  if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard)))
1545  return false;
1546 
1547  // Check characters following first . match
1548  if (hostname.midRef(hostname.indexOf(QLatin1Char('.'))) != cn.midRef(firstCnDot))
1549  return false;
1550 
1551  // Check if the hostname is an IP address, if so then wildcards are not allowed
1552  QHostAddress addr(hostname);
1553  if (!addr.isNull())
1554  return false;
1555 
1556  // Ok, I guess this was a wildcard CN and the hostname matches.
1557  return true;
1558 }
1559 
static PtrSecTrustCopyAnchorCertificates ptrSecTrustCopyAnchorCertificates
Definition: qsslsocket_p.h:145
The QDir class provides access to directory structures and their contents.
Definition: qdir.h:58
int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath)
void resize(int size)
#define q_OpenSSL_add_all_algorithms()
int q_BIO_read(BIO *a, void *b, int c)
static void deinitialize()
const T * constData() const
int q_SSL_CTX_check_private_key(SSL_CTX *a)
QSsl::KeyAlgorithm algorithm() const
Returns the key algorithm.
Definition: qsslkey.cpp:347
int q_SSL_CTX_use_certificate(SSL_CTX *a, X509 *b)
#define q_sk_X509_value(st, i)
bool isNull() const
Returns true if this host address is null (INADDR_ANY or in6addr_any).
int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b)
SSL_METHOD * q_SSLv3_client_method()
BIO_METHOD * q_BIO_s_mem()
QIntegerForSizeof< void * >::Unsigned quintptr
Definition: qglobal.h:986
SSL_METHOD * q_SSLv3_server_method()
void q_CRYPTO_set_id_callback(unsigned long(*a)())
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool q_resolveOpenSslSymbols()
void lock()
Locks the mutex.
Definition: qmutex.cpp:151
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
static QString fromAscii(const char *, int size=-1)
Returns a QString initialized with the first size characters from the string str. ...
Definition: qstring.cpp:4276
bool hasNext() const
Returns true if there is at least one more entry in the directory; otherwise, false is returned...
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
QByteArray toUpper() const
Returns an uppercase copy of the byte array.
const char * readPointer() const
Definition: qringbuffer_p.h:73
static void setDefaultSupportedCiphers(const QList< QSslCipher > &ciphers)
qint64 bytesAvailable() const
Returns the number of incoming bytes that are waiting to be read.
#define it(className, varName)
int q_SSL_CTX_set_cipher_list(SSL_CTX *a, const char *b)
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
QByteArray & append(char c)
Appends the character ch to this byte array.
static QList< QByteArray > unixRootCertDirectories()
Qt::HANDLE handle() const
Returns a pointer to the native key handle, if it is available; otherwise a null pointer is returned...
Definition: qsslkey.cpp:430
void setPath(const QString &path)
Sets the path of the directory to path.
Definition: qdir.cpp:590
HCERTSTORE(WINAPI * PtrCertOpenSystemStoreW)(LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, const void *)
Definition: qsslsocket_p.h:88
void q_SSL_CTX_free(SSL_CTX *a)
#define error(msg)
QList< QSslCipher > ciphers
int nextDataBlockSize() const
Definition: qringbuffer_p.h:69
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
bool empty() const
This function is provided for STL compatibility.
Definition: qlist.h:304
QString errorString() const
Returns a human-readable description of the last device error that occurred.
Definition: qiodevice.cpp:1671
T1 first
Definition: qpair.h:65
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition: qsslsocket.h:67
T2 second
Definition: qpair.h:66
SSL_CIPHER * q_SSL_get_current_cipher(SSL *a)
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
Definition: qssl.h:67
static LibLoadStatus status
Definition: qlocale_icu.cpp:69
static int q_X509Callback(int ok, X509_STORE_CTX *ctx)
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
int q_SSL_get_error(SSL *a, int b)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int msec() const
Returns the millisecond part (0 to 999) of the time.
Definition: qdatetime.cpp:1611
long ASN1_INTEGER_get ASN1_INTEGER * a
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
EventLoopTimerRef timer
int q_SSL_write(SSL *a, const void *b, int c)
void * resolve(const char *symbol)
Returns the address of the exported symbol symbol.
Definition: qlibrary.cpp:1155
static bool isBlacklisted(const QSslCertificate &certificate)
bool isEmpty() const
The QDirIterator class provides an iterator for directory entrylists.
Definition: qdiriterator.h:54
The QString class provides a Unicode character string.
Definition: qstring.h:83
QList< QPair< int, int > > errors
static QList< QSslCertificate > STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
QFileInfo fileInfo() const
Returns a QFileInfo for the current directory entry.
QByteArray toHex() const
Returns a hex encoded copy of the byte array.
BOOL(WINAPI * PtrCertCloseStore)(HCERTSTORE, DWORD)
Definition: qsslsocket_p.h:93
QString errorString() const
Returns a short localized human-readable description of the error.
Definition: qsslerror.cpp:224
QSslSocket::SslMode mode
Definition: qsslsocket_p.h:108
#define kSecTrustSettingsDomainSystem
The QElapsedTimer class provides a fast way to calculate elapsed times.
Definition: qelapsedtimer.h:53
QMutex * lock(int num)
int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b)
static bool s_loadRootCertsOnDemand
Definition: qsslsocket_p.h:187
The QSslCipher class represents an SSL cryptographic cipher.
Definition: qsslcipher.h:59
qint64 elapsed() const
Returns the number of milliseconds since this QElapsedTimer was last started.
Q_CORE_EXPORT QTextStream & hex(QTextStream &s)
QString encryptionMethod
Definition: qsslcipher_p.h:72
int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
void setNameFilters(const QStringList &nameFilters)
Sets the name filters used by entryList() and entryInfoList() to the list of filters specified by nam...
Definition: qdir.cpp:966
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
#define Q_Q(Class)
Definition: qglobal.h:2483
QStringRef leftRef(int n) const Q_REQUIRED_RESULT
Returns a substring reference to the n leftmost characters of the string.
Definition: qstring.cpp:9045
OSStatus(* PtrSecTrustCopyAnchorCertificates)(CFArrayRef *)
Definition: qsslsocket_p.h:83
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
bool isNull() const
Returns true if this is a null certificate (i.e., a certificate with no contents); otherwise returns ...
Q_CORE_EXPORT void qDebug(const char *,...)
char * q_ERR_error_string(unsigned long a, char *b)
static void setDefaultCiphers(const QList< QSslCipher > &ciphers)
static QByteArray toAce(const QString &)
Returns the ASCII Compatible Encoding of the given domain name domain.
Definition: qurl.cpp:6158
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
char * reserve(int bytes)
void q_SSL_set_bio(SSL *a, BIO *b, BIO *c)
QList< QSslError > ignoreErrorsList
Definition: qsslsocket_p.h:113
EVP_PKEY * q_EVP_PKEY_new()
#define q_sk_SSL_CIPHER_value(st, i)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
BIO * q_BIO_new(BIO_METHOD *a)
int q_SSL_library_init()
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
void q_SSL_set_accept_state(SSL *a)
bool isValid() const
Returns true if this certificate is valid; otherwise returns false.
SSL_METHOD * q_SSLv2_server_method()
int q_SSL_shutdown(SSL *a)
struct x509_st X509
#define q_sk_SSL_CIPHER_num(st)
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static bool s_loadedCiphersAndCerts
Definition: qsslsocket_p.h:185
QScopedPointer< QSslCipherPrivate > d
Definition: qsslcipher.h:82
Qt::HANDLE handle() const
Returns a pointer to the native certificate handle, if there is one, or a null pointer otherwise...
static unsigned long id_function()
void q_CRYPTO_set_locking_callback(void(*a)(int, int, const char *, int))
const char * name
SSL_METHOD * q_SSLv23_client_method()
static void locking_function(int mode, int lockNumber, const char *, int)
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
SSL_METHOD * q_TLSv1_server_method()
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static void setDefaultCaCertificates(const QList< QSslCertificate > &certs)
qint64 peek(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, without side effects (i.
Definition: qiodevice.cpp:1563
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
Definition: qfileinfo.cpp:551
QSslSocket::PeerVerifyMode peerVerifyMode
Q_CORE_EXPORT void qWarning(const char *,...)
int second() const
Returns the second part (0 to 59) of the time.
Definition: qdatetime.cpp:1600
const_iterator insert(const T &value)
Definition: qset.h:179
static QSslCertificate QSslCertificate_from_X509(X509 *x509)
static const char * data(const QByteArray &arr)
int q_CRYPTO_num_locks()
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QString subjectInfo(SubjectInfo info) const
Returns the information for the subject, or an empty string if there is no information for subject in...
QString issuerInfo(SubjectInfo info) const
Returns the issuer information for the subject from the certificate, or an empty string if there is n...
QString errorString
Definition: qiodevice_p.h:213
T value(int i) const
Returns the value at index position i in the list.
Definition: qlist.h:661
const T * ptr(const T &t)
void transmit()
Transmits encrypted data between the BIOs and the socket.
void setReadBufferSize(qint64 size)
Sets the size of QAbstractSocket&#39;s internal read buffer to be size bytes.
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &cert)
void clear()
Removes all items from the list.
Definition: qlist.h:764
void q_X509_free(X509 *a)
__int64 qint64
Definition: qglobal.h:942
int q_RAND_status()
QString name() const
Returns the name of the cipher, or an empty QString if this is a null cipher.
Definition: qsslcipher.cpp:162
int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b)
static bool supportsSsl()
Does the minimum amount of initialization to determine whether SSL is supported or not...
int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
static void ensureCiphersAndCertsLoaded()
signed long OSStatus
Definition: qssl.h:62
static bool s_libraryLoaded
Definition: qsslsocket_p.h:184
void unlock()
Unlocks the mutex.
Definition: qmutex.cpp:296
SSL_METHOD * q_SSLv2_client_method()
int q_SSL_accept(SSL *a)
void q_SSL_CTX_set_verify_depth(SSL_CTX *a, int b)
#define q_BIO_pending(b)
QSslConfigurationPrivate configuration
Definition: qsslsocket_p.h:116
static QString tempPath()
Returns the absolute path of the system&#39;s temporary directory.
Definition: qdir.cpp:1987
SSL * q_SSL_new(SSL_CTX *a)
long q_SSLeay()
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QSslCertificate localCertificate
QStringRef midRef(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a substring reference to n characters of this string, starting at the specified position...
Definition: qstring.cpp:9099
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
OSStatus(* PtrSecTrustSettingsCopyCertificates)(int, CFArrayRef *)
Definition: qsslsocket_p.h:82
static PtrSecCertificateGetData ptrSecCertificateGetData
Definition: qsslsocket_p.h:143
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
QMultiMap< QSsl::AlternateNameEntryType, QString > alternateSubjectNames() const
Returns the list of alternative subject names for this certificate.
QString & append(QChar c)
Definition: qstring.cpp:1777
void free(int bytes)
bool load()
Loads the library and returns true if the library was loaded successfully; otherwise returns false...
Definition: qlibrary.cpp:909
QString next()
Advances the iterator to the next entry, and returns the file path of this new entry.
void setAddress(quint32 ip4Addr)
Set the IPv4 address specified by ip4Addr.
QSsl::SslProtocol protocol
Definition: qsslcipher_p.h:75
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
static PtrSecTrustSettingsCopyCertificates ptrSecTrustSettingsCopyCertificates
Definition: qsslsocket_p.h:144
SSL_METHOD * q_TLSv1_client_method()
static QTime currentTime()
Returns the current time as reported by the system clock.
Definition: qdatetime.cpp:3125
void q_SSL_CTX_set_verify(SSL_CTX *a, int b, int(*c)(int, X509_STORE_CTX *))
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
static void resetDefaultCiphers()
Declared static in QSslSocketPrivate, backend-dependent loading of application-wide global ciphers...
static QList< QSslCertificate > systemCaCertificates()
bool isNull() const
Returns true if this is a null cipher; otherwise returns false.
Definition: qsslcipher.cpp:151
#define ctx
Definition: qgl.cpp:6094
QTcpSocket * plainSocket
Definition: qsslsocket_p.h:153
void q_SSL_load_error_strings()
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
QSslCipher sessionCipher() const
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
unsigned long q_ERR_get_error()
OSStatus(* PtrSecCertificateGetData)(SecCertificateRef, CSSM_DATA_PTR)
Definition: qsslsocket_p.h:81
int q_SSL_read(SSL *a, void *b, int c)
void q_SSL_set_connect_state(SSL *a)
Definition: qssl.h:63
static QList< QSslCertificate > fromPath(const QString &path, QSsl::EncodingFormat format=QSsl::Pem, QRegExp::PatternSyntax syntax=QRegExp::FixedString)
Searches all files in the path for certificates encoded in the specified format and returns them in a...
void q_RAND_seed(const void *a, int b)
bool * readyReadEmittedPointer
Definition: qsslsocket_p.h:114
void disconnectFromHost()
Attempts to close the socket.
#define q_sk_X509_num(st)
void q_SSL_free(SSL *a)
QString verificationPeerName
Definition: qsslsocket_p.h:121
static void ensureInitialized()
Declared static in QSslSocketPrivate, makes sure the SSL libraries have been initialized.
QList< QPair< int, int > > errorList
bool isNull() const
Returns true if this is a null key; otherwise false.
Definition: qsslkey.cpp:310
static const MacVersion MacintoshVersion
the version of the Macintosh operating system on which the application is run (Mac only)...
Definition: qglobal.h:1646
int q_SSL_connect(SSL *a)
QList< QSslError > sslErrors
Definition: qsslsocket_p.h:117
static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
The QSslCertificate class provides a convenient API for an X509 certificate.
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
void q_EVP_PKEY_free(EVP_PKEY *a)
static QList< QSslCipher > supportedCiphers()
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
The QSslError class provides an SSL error.
Definition: qsslerror.h:58
char * q_SSL_CIPHER_description(SSL_CIPHER *a, char *b, int c)
int q_SSL_clear(SSL *a)
static QList< QSslCipher > defaultCiphers()
The QHostAddress class provides an IP address.
Definition: qhostaddress.h:70
bool allowRootCertOnDemandLoading
Definition: qsslsocket_p.h:123
PCCERT_CONTEXT(WINAPI * PtrCertFindCertificateInStore)(HCERTSTORE, DWORD, DWORD, DWORD, const void *, PCCERT_CONTEXT)
Definition: qsslsocket_p.h:92
SSL_METHOD * q_SSLv23_server_method()
QString keyExchangeMethod
Definition: qsslcipher_p.h:70
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
QList< QSslCertificate > peerCertificateChain
SocketError error() const
Returns the type of error that last occurred.
static QString getErrorsFromOpenSsl()
STACK_OF(SSL_CIPHER) *SSL_get_ciphers SSL *a
const struct __CFArray * CFArrayRef
virtual void close()
Calls QFile::flush() and closes the file.
Definition: qfile.cpp:1680
int q_BIO_write(BIO *a, const void *b, int c)
SSL_CTX * q_SSL_CTX_new(SSL_METHOD *a)
void start()
Starts this timer.
#define q_SSL_CTX_set_options(ctx, op)
static QList< QSslCertificate > fromData(const QByteArray &data, QSsl::EncodingFormat format=QSsl::Pem)
Searches for and parses all certificates in data that are encoded in the specified format and returns...
static Q_AUTOTEST_EXPORT bool isMatchingHostname(const QString &cn, const QString &hostname)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
static bool ensureLibraryLoaded()
SocketState state() const
Returns the state of the socket.
int size() const
QString protocolString
Definition: qsslcipher_p.h:74
The QLibrary class loads shared libraries at runtime.
Definition: qlibrary.h:62
int size() const
bool isValid() const
Returns true if the socket is valid and ready for use; otherwise returns false.
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
int q_X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
static Qt::HANDLE currentThreadId()
Returns the thread handle of the currently executing thread.
QString authenticationMethod
Definition: qsslcipher_p.h:71
X509 * q_SSL_get_peer_certificate(SSL *a)