diff options
author | Peter Hartmann <phartmann@blackberry.com> | 2013-04-30 14:48:22 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-10 09:15:55 +0200 |
commit | 3be197881f100d1c3c8f3ce00501d7a32eb51119 (patch) | |
tree | f37ff774e4182560f45f9a2c85efe25bf43cce3f /src/network/ssl/qsslcontext.cpp | |
parent | 2116f9904afca7b3942433269b66a9756d5876bc (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.cpp | 41 |
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 |