summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslcontext.cpp
diff options
context:
space:
mode:
authorPeter Hartmann <phartmann@blackberry.com>2013-04-30 14:48:22 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-05-10 09:15:55 +0200
commit3be197881f100d1c3c8f3ce00501d7a32eb51119 (patch)
treef37ff774e4182560f45f9a2c85efe25bf43cce3f /src/network/ssl/qsslcontext.cpp
parent2116f9904afca7b3942433269b66a9756d5876bc (diff)
QSslConfiguration: add API to persist and resume SSL sessions
Session tickets can be cached on the client side for hours (e.g. graph.facebook.com: ~ 24 hours, api.twitter.com: 4 hours), because the server does not need to maintain state. We need public API for it so an application can cache the session (e.g. to disk) and resume a session already with the 1st handshake, saving one network round trip. Task-number: QTBUG-20668 Change-Id: I10255932dcd528ee1231538cb72b52b97f9f4a3c Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/network/ssl/qsslcontext.cpp')
-rw-r--r--src/network/ssl/qsslcontext.cpp41
1 files changed, 39 insertions, 2 deletions
diff --git a/src/network/ssl/qsslcontext.cpp b/src/network/ssl/qsslcontext.cpp
index 22ad42116b..6d281c390d 100644
--- a/src/network/ssl/qsslcontext.cpp
+++ b/src/network/ssl/qsslcontext.cpp
@@ -57,7 +57,8 @@ extern QString getErrorsFromOpenSsl();
QSslContext::QSslContext()
: ctx(0),
pkey(0),
- session(0)
+ session(0),
+ m_sessionTicketLifeTimeHint(-1)
{
}
@@ -258,6 +259,10 @@ init_context:
if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
+ // set persisted session if the user set it
+ if (!configuration.session().isEmpty())
+ sslContext->setSessionASN1(configuration.session());
+
return sslContext;
}
@@ -267,6 +272,12 @@ SSL* QSslContext::createSsl()
SSL* ssl = q_SSL_new(ctx);
q_SSL_clear(ssl);
+ if (!session && !sessionASN1().isEmpty()
+ && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
+ const unsigned char *data = reinterpret_cast<const unsigned char *>(m_sessionASN1.constData());
+ session = q_d2i_SSL_SESSION(0, &data, m_sessionASN1.size()); // refcount is 1 already, set by function above
+ }
+
if (session) {
// Try to resume the last session we cached
if (!q_SSL_set_session(ssl, session)) {
@@ -292,8 +303,34 @@ bool QSslContext::cacheSession(SSL* ssl)
// cache the session the caller gave us and increase reference count
session = q_SSL_get1_session(ssl);
- return (session != NULL);
+ if (session && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
+ int sessionSize = q_i2d_SSL_SESSION(session, 0);
+ if (sessionSize > 0) {
+ m_sessionASN1.resize(sessionSize);
+ unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
+ if (!q_i2d_SSL_SESSION(session, &data))
+ qWarning("could not store persistent version of SSL session");
+ m_sessionTicketLifeTimeHint = session->tlsext_tick_lifetime_hint;
+ }
+ }
+
+ return (session != 0);
+}
+
+QByteArray QSslContext::sessionASN1() const
+{
+ return m_sessionASN1;
+}
+
+void QSslContext::setSessionASN1(const QByteArray &session)
+{
+ m_sessionASN1 = session;
+}
+
+int QSslContext::sessionTicketLifeTimeHint() const
+{
+ return m_sessionTicketLifeTimeHint;
}
QSslError::SslError QSslContext::error() const