Prevent data loss when an ssl socket is closed by remote
authorShane Kearns <ext-shane.2.kearns@nokia.com>
Mon, 30 Jan 2012 15:52:27 +0000 (15:52 +0000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 1 Feb 2012 18:18:12 +0000 (19:18 +0100)
SSL context was destroyed on disconnect. This makes it impossible to
decrypt buffered encrypted data. So if there is encrypted data in the
receive buffers, then don't destroy the ssl context until the socket is
destroyed.

Task-Number: QTBUG-23607
Change-Id: I16a7b4fa006647ec73049c90cdbc72686696850f
Reviewed-by: Jonas Gastal <jgastal@profusion.mobi>
Reviewed-by: Richard J. Moore <rich@kde.org>
src/network/ssl/qsslsocket_openssl.cpp
src/network/ssl/qsslsocket_openssl_p.h

index bdd8961..f62f3c1 100644 (file)
@@ -172,6 +172,7 @@ QSslSocketBackendPrivate::QSslSocketBackendPrivate()
 
 QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
 {
+    destroySslContext();
 }
 
 QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
@@ -508,6 +509,22 @@ init_context:
     return true;
 }
 
+void QSslSocketBackendPrivate::destroySslContext()
+{
+    if (ssl) {
+        q_SSL_free(ssl);
+        ssl = 0;
+    }
+    if (ctx) {
+        q_SSL_CTX_free(ctx);
+        ctx = 0;
+    }
+    if (pkey) {
+        q_EVP_PKEY_free(pkey);
+        pkey = 0;
+    }
+}
+
 /*!
     \internal
 */
@@ -1232,18 +1249,10 @@ void QSslSocketBackendPrivate::disconnectFromHost()
 
 void QSslSocketBackendPrivate::disconnected()
 {
-    if (ssl) {
-        q_SSL_free(ssl);
-        ssl = 0;
-    }
-    if (ctx) {
-        q_SSL_CTX_free(ctx);
-        ctx = 0;
-    }
-    if (pkey) {
-        q_EVP_PKEY_free(pkey);
-        pkey = 0;
-    }
+    if (plainSocket->bytesAvailable() <= 0)
+        destroySslContext();
+    //if there is still buffered data in the plain socket, don't destroy the ssl context yet.
+    //it will be destroyed when the socket is deleted.
 }
 
 QSslCipher QSslSocketBackendPrivate::sessionCipher() const
index 83f485d..b31eae9 100644 (file)
@@ -99,6 +99,7 @@ public:
 
     // SSL context
     bool initSslContext();
+    void destroySslContext();
     SSL *ssl;
     SSL_CTX *ctx;
     EVP_PKEY *pkey;