Qt 4.8
Public Functions | Static Public Functions | Public Variables | List of all members
QSslSocketBackendPrivate Class Reference

#include <qsslsocket_openssl_p.h>

Inheritance diagram for QSslSocketBackendPrivate:
QSslSocketPrivate QTcpSocketPrivate QAbstractSocketPrivate QIODevicePrivate QAbstractSocketEngineReceiver QObjectPrivate QObjectData

Public Functions

void destroySslContext ()
 
void disconnected ()
 
void disconnectFromHost ()
 
bool initSslContext ()
 
 QSslSocketBackendPrivate ()
 
QSslCipher sessionCipher () const
 
void startClientEncryption ()
 
bool startHandshake ()
 
void startServerEncryption ()
 
void transmit ()
 Transmits encrypted data between the BIOs and the socket. More...
 
virtual ~QSslSocketBackendPrivate ()
 
- Public Functions inherited from QSslSocketPrivate
void _q_bytesWrittenSlot (qint64)
 
void _q_connectedSlot ()
 
void _q_disconnectedSlot ()
 
void _q_errorSlot (QAbstractSocket::SocketError)
 
void _q_flushReadBuffer ()
 
void _q_flushWriteBuffer ()
 
void _q_hostFoundSlot ()
 
void _q_readyReadSlot ()
 
void _q_stateChangedSlot (QAbstractSocket::SocketState)
 
void createPlainSocket (QIODevice::OpenMode openMode)
 
void init ()
 
virtual qint64 peek (char *data, qint64 maxSize)
 
virtual QByteArray peek (qint64 maxSize)
 
 QSslSocketPrivate ()
 
virtual ~QSslSocketPrivate ()
 
- Public Functions inherited from QAbstractSocketPrivate
void _q_abortConnectionAttempt ()
 This function is called after a certain number of seconds has passed while waiting for a connection. More...
 
void _q_connectToNextAddress ()
 Called by a queued or direct connection from _q_startConnecting() or _q_testConnection(), this function takes the first address of the pending addresses list and tries to connect to it. More...
 
void _q_forceDisconnect ()
 
void _q_startConnecting (const QHostInfo &hostInfo)
 Slot connected to QHostInfo::lookupHost() in connectToHost(). More...
 
void _q_testConnection ()
 Tests if a connection has been established. More...
 
bool canReadNotification ()
 Slot connected to the read socket notifier. More...
 
bool canWriteNotification ()
 Slot connected to the write socket notifier. More...
 
void connectionNotification ()
 Slot connected to a notification of connection status change. More...
 
void exceptionNotification ()
 
void fetchConnectionParameters ()
 Sets up the internal state after the connection has succeeded. More...
 
bool flush ()
 Writes pending data in the write buffers to the socket. More...
 
bool initSocketLayer (QAbstractSocket::NetworkLayerProtocol protocol)
 Initializes the socket layer to by of type type, using the network layer protocol protocol. More...
 
void proxyAuthenticationRequired (const QNetworkProxy &proxy, QAuthenticator *authenticator)
 
 QAbstractSocketPrivate ()
 Constructs a QAbstractSocketPrivate. More...
 
bool readFromSocket ()
 Reads data from the socket layer into the read buffer. More...
 
void readNotification ()
 
void resetSocketLayer ()
 Resets the socket layer, clears the read and write buffers and deletes any socket notifiers. More...
 
void resolveProxy (const QString &hostName, quint16 port)
 Resolve the proxy to its final value. More...
 
void resolveProxy (quint16 port)
 
void setupSocketNotifiers ()
 
void startConnectingByName (const QString &host)
 Starts the connection to host, like _q_startConnecting below, but without hostname resolution. More...
 
void writeNotification ()
 
virtual ~QAbstractSocketPrivate ()
 Destructs the QAbstractSocket. More...
 
- Public Functions inherited from QIODevicePrivate
bool isSequential () const
 
virtual bool putCharHelper (char c)
 
 QIODevicePrivate ()
 
virtual ~QIODevicePrivate ()
 
- Public Functions inherited from QObjectPrivate
void _q_reregisterTimers (void *pointer)
 
void addConnection (int signal, Connection *c)
 
void cleanConnectionLists ()
 
void connectNotify (const char *signal)
 
void deleteChildren ()
 
void disconnectNotify (const char *signal)
 
bool isSender (const QObject *receiver, const char *signal) const
 
bool isSignalConnected (uint signalIdx) const
 Returns true if the signal with index signal_index from object sender is connected. More...
 
void moveToThread_helper ()
 
 QObjectPrivate (int version=QObjectPrivateVersion)
 
QObjectList receiverList (const char *signal) const
 
QObjectList senderList () const
 
void setParent_helper (QObject *)
 
void setThreadData_helper (QThreadData *currentData, QThreadData *targetData)
 
int signalIndex (const char *signalName) const
 Returns the signal index used in the internal connectionLists vector. More...
 
virtual ~QObjectPrivate ()
 
- Public Functions inherited from QObjectData
virtual ~QObjectData ()=0
 
- Public Functions inherited from QAbstractSocketEngineReceiver
virtual ~QAbstractSocketEngineReceiver ()
 

Static Public Functions

static QString getErrorsFromOpenSsl ()
 
static Q_AUTOTEST_EXPORT bool isMatchingHostname (const QString &cn, const QString &hostname)
 
static QSslCipher QSslCipher_from_SSL_CIPHER (SSL_CIPHER *cipher)
 
static QList< QSslCertificateSTACKOFX509_to_QSslCertificates (STACK_OF(X509) *x509)
 
- Static Public Functions inherited from QSslSocketPrivate
static void addDefaultCaCertificate (const QSslCertificate &cert)
 
static bool addDefaultCaCertificates (const QString &path, QSsl::EncodingFormat format, QRegExp::PatternSyntax syntax)
 
static void addDefaultCaCertificates (const QList< QSslCertificate > &certs)
 
static QList< QSslCertificatedefaultCaCertificates ()
 
static QList< QSslCipherdefaultCiphers ()
 
static void deinitialize ()
 
static void ensureInitialized ()
 Declared static in QSslSocketPrivate, makes sure the SSL libraries have been initialized. More...
 
static void pauseSocketNotifiers (QSslSocket *)
 
static void resetDefaultCiphers ()
 Declared static in QSslSocketPrivate, backend-dependent loading of application-wide global ciphers. More...
 
static void resumeSocketNotifiers (QSslSocket *)
 
static Q_AUTOTEST_EXPORT bool rootCertOnDemandLoadingSupported ()
 
static void setDefaultCaCertificates (const QList< QSslCertificate > &certs)
 
static void setDefaultCiphers (const QList< QSslCipher > &ciphers)
 
static void setDefaultSupportedCiphers (const QList< QSslCipher > &ciphers)
 
static QList< QSslCiphersupportedCiphers ()
 
static bool supportsSsl ()
 Does the minimum amount of initialization to determine whether SSL is supported or not. More...
 
static QList< QSslCertificatesystemCaCertificates ()
 
- Static Public Functions inherited from QAbstractSocketPrivate
static QAbstractSocketEnginegetSocketEngine (QAbstractSocket *)
 
static void pauseSocketNotifiers (QAbstractSocket *)
 
static void resumeSocketNotifiers (QAbstractSocket *)
 
- Static Public Functions inherited from QObjectPrivate
static void clearGuards (QObject *)
 
static QObjectPrivateget (QObject *o)
 
static void resetCurrentSender (QObject *receiver, Sender *currentSender, Sender *previousSender)
 
static SendersetCurrentSender (QObject *receiver, Sender *sender)
 
static void signalSignature (const QMetaMethod &signal, QVarLengthArray< char > *result)
 

Public Variables

X509_STORE * certificateStore
 
X509_STORE_CTX * certificateStoreCtx
 
SSL_CTX * ctx
 
QList< QPair< int, int > > errorList
 
EVP_PKEY * pkey
 
BIO * readBio
 
SSL_SESSION * session
 
SSL * ssl
 
BIO * writeBio
 
- Public Variables inherited from QSslSocketPrivate
bool allowRootCertOnDemandLoading
 
bool autoStartHandshake
 
QSslConfigurationPrivate configuration
 
bool connectionEncrypted
 
bool ignoreAllSslErrors
 
QList< QSslErrorignoreErrorsList
 
bool initialized
 
QSslSocket::SslMode mode
 
QTcpSocketplainSocket
 
bool * readyReadEmittedPointer
 
bool shutdown
 
QList< QSslErrorsslErrors
 
QString verificationPeerName
 
- Public Variables inherited from QAbstractSocketPrivate
bool abortCalled
 
QList< QHostAddressaddresses
 
int blockingTimeout
 
int cachedSocketDescriptor
 
bool closeCalled
 
int connectTimeElapsed
 
QTimerconnectTimer
 
QTimerdisconnectTimer
 
bool emittedBytesWritten
 
bool emittedReadyRead
 
QHostAddress host
 
int hostLookupId
 
QString hostName
 
bool isBuffered
 
QHostAddress localAddress
 
quint16 localPort
 
QHostAddress peerAddress
 
QString peerName
 
quint16 peerPort
 
bool pendingClose
 
quint16 port
 
bool prePauseExceptionSocketNotifierState
 
bool prePauseReadSocketNotifierState
 
bool prePauseWriteSocketNotifierState
 
QNetworkProxy proxy
 
QNetworkProxy proxyInUse
 
QRingBuffer readBuffer
 
qint64 readBufferMaxSize
 
bool readSocketNotifierCalled
 
bool readSocketNotifierState
 
bool readSocketNotifierStateSet
 
QAbstractSocketEnginesocketEngine
 
QAbstractSocket::SocketError socketError
 
QAbstractSocket::SocketType socketType
 
QAbstractSocket::SocketState state
 
QRingBuffer writeBuffer
 
- Public Variables inherited from QIODevicePrivate
AccessMode accessMode
 
bool baseReadLineDataCalled
 
QIODevicePrivateLinearBuffer buffer
 
qint64 devicePos
 
QString errorString
 
bool firstRead
 
QIODevice::OpenMode openMode
 
qint64pDevicePos
 
qint64 pos
 
qint64pPos
 
qint64 seqDumpPos
 
- Public Variables inherited from QObjectPrivate
union {
   QObject *   currentChildBeingDeleted
 
   QAbstractDeclarativeData *   declarativeData
 
}; 
 
quint32 connectedSignals [2]
 
QObjectConnectionListVectorconnectionLists
 
SendercurrentSender
 
QList< QPointer< QObject > > eventFilters
 
ExtraDataextraData
 
QString objectName
 
Connectionsenders
 
QAtomicPointer< QtSharedPointer::ExternalRefCountData > sharedRefcount
 
QThreadDatathreadData
 
void * unused
 
- Public Variables inherited from QObjectData
uint blockSig: 1
 
QObjectList children
 
uint hasGuards: 1
 
uint inEventHandler: 1
 
uint inThreadChangeEvent: 1
 
uint isWidget: 1
 
QMetaObjectmetaObject
 
uint ownObjectName: 1
 
QObjectparent
 
uint pendTimer: 1
 
int postedEvents
 
QObjectq_ptr
 
uint receiveChildEvents: 1
 
uint sendChildEvents: 1
 
uint unused: 22
 
uint wasDeleted: 1
 

Additional Inherited Members

- Public Types inherited from QIODevicePrivate
enum  AccessMode { Unset, Sequential, RandomAccess }
 
- Public Types inherited from QObjectPrivate
typedef void(* StaticMetaCallFunction) (QObject *, QMetaObject::Call, int, void **)
 
- Static Public Variables inherited from QSslSocketPrivate
static PtrSecCertificateGetData ptrSecCertificateGetData = 0
 
static PtrSecTrustCopyAnchorCertificates ptrSecTrustCopyAnchorCertificates = 0
 
static PtrSecTrustSettingsCopyCertificates ptrSecTrustSettingsCopyCertificates = 0
 
- Static Protected Functions inherited from QSslSocketPrivate
static QList< QByteArrayunixRootCertDirectories ()
 
- Static Protected Variables inherited from QSslSocketPrivate
static bool s_loadRootCertsOnDemand = false
 

Detailed Description

Definition at line 93 of file qsslsocket_openssl_p.h.

Constructors and Destructors

◆ QSslSocketBackendPrivate()

QSslSocketBackendPrivate::QSslSocketBackendPrivate ( )

Definition at line 173 of file qsslsocket_openssl.cpp.

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 }
static void ensureInitialized()
Declared static in QSslSocketPrivate, makes sure the SSL libraries have been initialized.

◆ ~QSslSocketBackendPrivate()

QSslSocketBackendPrivate::~QSslSocketBackendPrivate ( )
virtual

Definition at line 185 of file qsslsocket_openssl.cpp.

186 {
188 }

Functions

◆ destroySslContext()

void QSslSocketBackendPrivate::destroySslContext ( )

Definition at line 485 of file qsslsocket_openssl.cpp.

Referenced by disconnected(), and ~QSslSocketBackendPrivate().

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 }
void q_SSL_CTX_free(SSL_CTX *a)
void q_SSL_free(SSL *a)
void q_EVP_PKEY_free(EVP_PKEY *a)

◆ disconnected()

void QSslSocketBackendPrivate::disconnected ( )
virtual

Implements QSslSocketPrivate.

Definition at line 1473 of file qsslsocket_openssl.cpp.

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 }
qint64 bytesAvailable() const
Returns the number of incoming bytes that are waiting to be read.
QTcpSocket * plainSocket
Definition: qsslsocket_p.h:153

◆ disconnectFromHost()

void QSslSocketBackendPrivate::disconnectFromHost ( )
virtual

Implements QSslSocketPrivate.

Definition at line 1461 of file qsslsocket_openssl.cpp.

1462 {
1463  if (ssl) {
1464  if (!shutdown) {
1466  shutdown = true;
1467  transmit();
1468  }
1469  }
1471 }
int q_SSL_shutdown(SSL *a)
void transmit()
Transmits encrypted data between the BIOs and the socket.
QTcpSocket * plainSocket
Definition: qsslsocket_p.h:153
void disconnectFromHost()
Attempts to close the socket.

◆ getErrorsFromOpenSsl()

QString QSslSocketBackendPrivate::getErrorsFromOpenSsl ( )
static

Definition at line 1507 of file qsslsocket_openssl.cpp.

Referenced by initSslContext(), startHandshake(), and transmit().

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 }
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
#define error(msg)
The QString class provides a Unicode character string.
Definition: qstring.h:83
char * q_ERR_error_string(unsigned long a, char *b)
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QString errorString
Definition: qiodevice_p.h:213
QString & append(QChar c)
Definition: qstring.cpp:1777
unsigned long q_ERR_get_error()

◆ initSslContext()

bool QSslSocketBackendPrivate::initSslContext ( )

Definition at line 248 of file qsslsocket_openssl.cpp.

Referenced by startClientEncryption(), and startServerEncryption().

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 }
int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath)
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)
int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b)
SSL_METHOD * q_SSLv3_client_method()
BIO_METHOD * q_BIO_s_mem()
SSL_METHOD * q_SSLv3_server_method()
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
int q_SSL_CTX_set_cipher_list(SSL_CTX *a, const char *b)
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
QList< QSslCipher > ciphers
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition: qsslsocket.h:67
Definition: qssl.h:67
static int q_X509Callback(int ok, X509_STORE_CTX *ctx)
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
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
The QString class provides a Unicode character string.
Definition: qstring.h:83
QSslSocket::SslMode mode
Definition: qsslsocket_p.h:108
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
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
#define Q_Q(Class)
Definition: qglobal.h:2483
bool isNull() const
Returns true if this is a null certificate (i.e., a certificate with no contents); otherwise returns ...
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
void q_SSL_set_bio(SSL *a, BIO *b, BIO *c)
EVP_PKEY * q_EVP_PKEY_new()
BIO * q_BIO_new(BIO_METHOD *a)
int q_SSL_library_init()
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()
struct x509_st X509
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
Qt::HANDLE handle() const
Returns a pointer to the native certificate handle, if there is one, or a null pointer otherwise...
SSL_METHOD * q_SSLv23_client_method()
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
QSslSocket::PeerVerifyMode peerVerifyMode
Q_CORE_EXPORT void qWarning(const char *,...)
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
void clear()
Removes all items from the list.
Definition: qlist.h:764
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)
SSL_METHOD * q_SSLv2_client_method()
void q_SSL_CTX_set_verify_depth(SSL_CTX *a, int b)
QSslConfigurationPrivate configuration
Definition: qsslsocket_p.h:116
SSL * q_SSL_new(SSL_CTX *a)
long q_SSLeay()
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QSslCertificate localCertificate
void setAddress(quint32 ip4Addr)
Set the IPv4 address specified by ip4Addr.
SSL_METHOD * q_TLSv1_client_method()
void q_SSL_CTX_set_verify(SSL_CTX *a, int b, int(*c)(int, X509_STORE_CTX *))
void q_SSL_set_connect_state(SSL *a)
QString verificationPeerName
Definition: qsslsocket_p.h:121
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
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
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
SSL_METHOD * q_SSLv23_server_method()
static QString getErrorsFromOpenSsl()
SSL_CTX * q_SSL_CTX_new(SSL_METHOD *a)
#define q_SSL_CTX_set_options(ctx, op)
int q_X509_STORE_add_cert(X509_STORE *ctx, X509 *x)

◆ isMatchingHostname()

bool QSslSocketBackendPrivate::isMatchingHostname ( const QString cn,
const QString hostname 
)
static

Definition at line 1520 of file qsslsocket_openssl.cpp.

Referenced by startHandshake().

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 }
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QStringRef leftRef(int n) const Q_REQUIRED_RESULT
Returns a substring reference to the n leftmost characters of the string.
Definition: qstring.cpp:9045
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
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
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
The QHostAddress class provides an IP address.
Definition: qhostaddress.h:70
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55

◆ QSslCipher_from_SSL_CIPHER()

QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER ( SSL_CIPHER *  cipher)
static

Definition at line 190 of file qsslsocket_openssl.cpp.

Referenced by QSslSocketPrivate::resetDefaultCiphers(), and sessionCipher().

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 }
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
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QSslCipher class represents an SSL cryptographic cipher.
Definition: qsslcipher.h:59
QString encryptionMethod
Definition: qsslcipher_p.h:72
QScopedPointer< QSslCipherPrivate > d
Definition: qsslcipher.h:82
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
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
QSsl::SslProtocol protocol
Definition: qsslcipher_p.h:75
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
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
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
char * q_SSL_CIPHER_description(SSL_CIPHER *a, char *b, int c)
QString keyExchangeMethod
Definition: qsslcipher_p.h:70
QString protocolString
Definition: qsslcipher_p.h:74
QString authenticationMethod
Definition: qsslcipher_p.h:71

◆ sessionCipher()

QSslCipher QSslSocketBackendPrivate::sessionCipher ( ) const
virtual

Implements QSslSocketPrivate.

Definition at line 1481 of file qsslsocket_openssl.cpp.

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 }
SSL_CIPHER * q_SSL_get_current_cipher(SSL *a)
The QSslCipher class represents an SSL cryptographic cipher.
Definition: qsslcipher.h:59
QSslCipher sessionCipher() const
static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)

◆ STACKOFX509_to_QSslCertificates()

QList< QSslCertificate > QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates ( STACK_OF(X509) *  x509)
static

Definition at line 1496 of file qsslsocket_openssl.cpp.

Referenced by startHandshake().

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 }
#define q_sk_X509_value(st, i)
struct x509_st X509
static QSslCertificate QSslCertificate_from_X509(X509 *x509)
#define q_sk_X509_num(st)
static void ensureInitialized()
Declared static in QSslSocketPrivate, makes sure the SSL libraries have been initialized.

◆ startClientEncryption()

void QSslSocketBackendPrivate::startClientEncryption ( )
virtual

Implements QSslSocketPrivate.

Definition at line 980 of file qsslsocket_openssl.cpp.

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 }
void transmit()
Transmits encrypted data between the BIOs and the socket.

◆ startHandshake()

bool QSslSocketBackendPrivate::startHandshake ( )

Definition at line 1254 of file qsslsocket_openssl.cpp.

Referenced by startClientEncryption(), startServerEncryption(), and transmit().

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 }
#define error(msg)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
bool empty() const
This function is provided for STL compatibility.
Definition: qlist.h:304
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
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
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
static bool isBlacklisted(const QSslCertificate &certificate)
The QString class provides a Unicode character string.
Definition: qstring.h:83
static QList< QSslCertificate > STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
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
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
#define Q_Q(Class)
Definition: qglobal.h:2483
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 *,...)
QList< QSslError > ignoreErrorsList
Definition: qsslsocket_p.h:113
QBool contains(const T &t) const
Returns true if the list contains an occurrence of value; otherwise returns false.
Definition: qlist.h:880
struct x509_st X509
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
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
QSslSocket::PeerVerifyMode peerVerifyMode
Q_CORE_EXPORT void qWarning(const char *,...)
static QSslCertificate QSslCertificate_from_X509(X509 *x509)
QString subjectInfo(SubjectInfo info) const
Returns the information for the subject, or an empty string if there is no information for subject in...
T value(int i) const
Returns the value at index position i in the list.
Definition: qlist.h:661
void setReadBufferSize(qint64 size)
Sets the size of QAbstractSocket&#39;s internal read buffer to be size bytes.
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)
int q_SSL_accept(SSL *a)
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
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
QMultiMap< QSsl::AlternateNameEntryType, QString > alternateSubjectNames() const
Returns the list of alternative subject names for this certificate.
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
QTcpSocket * plainSocket
Definition: qsslsocket_p.h:153
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
void disconnectFromHost()
Attempts to close the socket.
QString verificationPeerName
Definition: qsslsocket_p.h:121
QList< QPair< int, int > > errorList
int q_SSL_connect(SSL *a)
QList< QSslError > sslErrors
Definition: qsslsocket_p.h:117
The QSslCertificate class provides a convenient API for an X509 certificate.
The QSslError class provides an SSL error.
Definition: qsslerror.h:58
QList< QSslCertificate > peerCertificateChain
static QString getErrorsFromOpenSsl()
static Q_AUTOTEST_EXPORT bool isMatchingHostname(const QString &cn, const QString &hostname)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
X509 * q_SSL_get_peer_certificate(SSL *a)

◆ startServerEncryption()

void QSslSocketBackendPrivate::startServerEncryption ( )
virtual

Implements QSslSocketPrivate.

Definition at line 993 of file qsslsocket_openssl.cpp.

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 }
void transmit()
Transmits encrypted data between the BIOs and the socket.

◆ transmit()

void QSslSocketBackendPrivate::transmit ( )
virtual

Transmits encrypted data between the BIOs and the socket.

Warning
This function is not part of the public interface.

Implements QSslSocketPrivate.

Definition at line 1014 of file qsslsocket_openssl.cpp.

Referenced by disconnectFromHost(), startClientEncryption(), and startServerEncryption().

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 }
void resize(int size)
int q_BIO_read(BIO *a, void *b, int c)
const T * constData() const
const char * readPointer() const
Definition: qringbuffer_p.h:73
qint64 bytesAvailable() const
Returns the number of incoming bytes that are waiting to be read.
int nextDataBlockSize() const
Definition: qringbuffer_p.h:69
QString errorString() const
Returns a human-readable description of the last device error that occurred.
Definition: qiodevice.cpp:1671
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition: qsslsocket.h:67
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
int q_SSL_get_error(SSL *a, int b)
int q_SSL_write(SSL *a, const void *b, int c)
bool isEmpty() const
#define Q_Q(Class)
Definition: qglobal.h:2483
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
Q_CORE_EXPORT void qDebug(const char *,...)
char * reserve(int bytes)
#define emit
Definition: qobjectdefs.h:76
qint64 peek(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, without side effects (i.
Definition: qiodevice.cpp:1563
static const char * data(const QByteArray &arr)
const T * ptr(const T &t)
__int64 qint64
Definition: qglobal.h:942
#define q_BIO_pending(b)
void free(int bytes)
QTcpSocket * plainSocket
Definition: qsslsocket_p.h:153
int q_SSL_read(SSL *a, void *b, int c)
bool * readyReadEmittedPointer
Definition: qsslsocket_p.h:114
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
SocketError error() const
Returns the type of error that last occurred.
static QString getErrorsFromOpenSsl()
int q_BIO_write(BIO *a, const void *b, int c)
SocketState state() const
Returns the state of the socket.
int size() const
int size() const
bool isValid() const
Returns true if the socket is valid and ready for use; otherwise returns false.

Properties

◆ certificateStore

X509_STORE* QSslSocketBackendPrivate::certificateStore

Definition at line 109 of file qsslsocket_openssl_p.h.

◆ certificateStoreCtx

X509_STORE_CTX* QSslSocketBackendPrivate::certificateStoreCtx

Definition at line 110 of file qsslsocket_openssl_p.h.

◆ ctx

SSL_CTX* QSslSocketBackendPrivate::ctx

Definition at line 104 of file qsslsocket_openssl_p.h.

Referenced by destroySslContext(), initSslContext(), sessionCipher(), and transmit().

◆ errorList

QList<QPair<int, int> > QSslSocketBackendPrivate::errorList

Definition at line 111 of file qsslsocket_openssl_p.h.

Referenced by initSslContext(), and startHandshake().

◆ pkey

EVP_PKEY* QSslSocketBackendPrivate::pkey

Definition at line 105 of file qsslsocket_openssl_p.h.

Referenced by destroySslContext(), and initSslContext().

◆ readBio

BIO* QSslSocketBackendPrivate::readBio

Definition at line 106 of file qsslsocket_openssl_p.h.

Referenced by initSslContext(), and transmit().

◆ session

SSL_SESSION* QSslSocketBackendPrivate::session

Definition at line 108 of file qsslsocket_openssl_p.h.

◆ ssl

SSL* QSslSocketBackendPrivate::ssl

◆ writeBio

BIO* QSslSocketBackendPrivate::writeBio

Definition at line 107 of file qsslsocket_openssl_p.h.

Referenced by initSslContext(), and transmit().


The documentation for this class was generated from the following files: