SSL: add support for the Next Protocol Negotiation extension
... which is needed to negotiate the SPDY protocol. [ChangeLog][QtNetwork][QSslConfiguration] Added support for the Next Protocol Negotiation (NPN) TLS extension. Task-number: QTBUG-33208 Change-Id: I3c945f9b7e2d2ffb0814bfdd3e87de1dae6c20ef Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
This commit is contained in:
parent
df62c31807
commit
42cfb5fe4d
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -52,6 +53,9 @@ const QSsl::SslOptions QSslConfigurationPrivate::defaultSslOptions = QSsl::SslOp
|
||||
|QSsl::SslOptionDisableCompression
|
||||
|QSsl::SslOptionDisableSessionPersistence;
|
||||
|
||||
const char QSslConfiguration::NextProtocolSpdy3_0[] = "spdy/3";
|
||||
const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1";
|
||||
|
||||
/*!
|
||||
\class QSslConfiguration
|
||||
\brief The QSslConfiguration class holds the configuration and state of an SSL connection
|
||||
@ -112,6 +116,33 @@ const QSsl::SslOptions QSslConfigurationPrivate::defaultSslOptions = QSsl::SslOp
|
||||
QSslSocket::sslConfiguration(), QSslSocket::setSslConfiguration()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QSslConfiguration::NextProtocolNegotiationStatus
|
||||
|
||||
Describes the status of the Next Protocol Negotiation (NPN).
|
||||
|
||||
\value NextProtocolNegotiationNone No application protocol
|
||||
has been negotiated (yet).
|
||||
|
||||
\value NextProtocolNegotiationNegotiated A next protocol
|
||||
has been negotiated (see nextNegotiatedProtocol()).
|
||||
|
||||
\value NextProtocolNegotiationUnsupported The client and
|
||||
server could not agree on a common next application protocol.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QSslConfiguration::NextProtocolSpdy3_0
|
||||
\brief The value used for negotiating SPDY 3.0 during the Next
|
||||
Protocol Negotiation.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QSslConfiguration::NextProtocolHttp1_1
|
||||
\brief The value used for negotiating HTTP 1.1 during the Next
|
||||
Protocol Negotiation.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs an empty SSL configuration. This configuration contains
|
||||
no valid settings and the state will be empty. isNull() will
|
||||
@ -185,7 +216,10 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
|
||||
d->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
|
||||
d->sslOptions == other.d->sslOptions &&
|
||||
d->sslSession == other.d->sslSession &&
|
||||
d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint;
|
||||
d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint &&
|
||||
d->nextAllowedProtocols == other.d->nextAllowedProtocols &&
|
||||
d->nextNegotiatedProtocol == other.d->nextNegotiatedProtocol &&
|
||||
d->nextProtocolNegotiationStatus == other.d->nextProtocolNegotiationStatus;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -221,7 +255,10 @@ bool QSslConfiguration::isNull() const
|
||||
d->peerCertificateChain.count() == 0 &&
|
||||
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
|
||||
d->sslSession.isNull() &&
|
||||
d->sslSessionTicketLifeTimeHint == -1);
|
||||
d->sslSessionTicketLifeTimeHint == -1 &&
|
||||
d->nextAllowedProtocols.isEmpty() &&
|
||||
d->nextNegotiatedProtocol.isNull() &&
|
||||
d->nextProtocolNegotiationStatus == QSslConfiguration::NextProtocolNegotiationNone);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -652,6 +689,71 @@ int QSslConfiguration::sessionTicketLifeTimeHint() const
|
||||
return d->sslSessionTicketLifeTimeHint;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
This function returns the protocol negotiated with the server
|
||||
if the Next Protocol Negotiation (NPN) TLS extension was enabled.
|
||||
In order for the NPN extension to be enabled, setAllowedNextProtocols()
|
||||
needs to be called explicitly before connecting to the server.
|
||||
|
||||
If no protocol could be negotiated or the extension was not enabled,
|
||||
this function returns a QByteArray which is null.
|
||||
|
||||
\sa setAllowedNextProtocols(), nextProtocolNegotiationStatus()
|
||||
*/
|
||||
QByteArray QSslConfiguration::nextNegotiatedProtocol() const
|
||||
{
|
||||
return d->nextNegotiatedProtocol;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
This function sets the allowed \a protocols to be negotiated with the
|
||||
server through the Next Protocol Negotiation (NPN) TLS extension; each
|
||||
element in \a protocols must define one allowed protocol.
|
||||
The function must be called explicitly before connecting to send the NPN
|
||||
extension in the SSL handshake.
|
||||
Whether or not the negotiation succeeded can be queried through
|
||||
nextProtocolNegotiationStatus().
|
||||
|
||||
\sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), allowedNextProtocols(), QSslConfiguration::NextProtocolSpdy3_0, QSslConfiguration::NextProtocolHttp1_1
|
||||
*/
|
||||
void QSslConfiguration::setAllowedNextProtocols(QList<QByteArray> protocols)
|
||||
{
|
||||
d->nextAllowedProtocols = protocols;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
This function returns the allowed protocols to be negotiated with the
|
||||
server through the Next Protocol Negotiation (NPN) TLS extension, as set
|
||||
by setAllowedNextProtocols().
|
||||
|
||||
\sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), setAllowedNextProtocols(), QSslConfiguration::NextProtocolSpdy3_0, QSslConfiguration::NextProtocolHttp1_1
|
||||
*/
|
||||
QList<QByteArray> QSslConfiguration::allowedNextProtocols() const
|
||||
{
|
||||
return d->nextAllowedProtocols;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.3
|
||||
|
||||
This function returns the status of the Next Protocol Negotiation (NPN).
|
||||
If the feature has not been enabled through setAllowedNextProtocols(),
|
||||
this function returns NextProtocolNegotiationNone.
|
||||
The status will be set before emitting the encrypted() signal.
|
||||
|
||||
\sa setAllowedNextProtocols(), allowedNextProtocols(), nextNegotiatedProtocol(), QSslConfiguration::NextProtocolNegotiationStatus
|
||||
*/
|
||||
QSslConfiguration::NextProtocolNegotiationStatus QSslConfiguration::nextProtocolNegotiationStatus() const
|
||||
{
|
||||
return d->nextProtocolNegotiationStatus;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the default SSL configuration to be used in new SSL
|
||||
connections.
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -131,6 +132,21 @@ public:
|
||||
static QSslConfiguration defaultConfiguration();
|
||||
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
||||
|
||||
enum NextProtocolNegotiationStatus {
|
||||
NextProtocolNegotiationNone,
|
||||
NextProtocolNegotiationNegotiated,
|
||||
NextProtocolNegotiationUnsupported
|
||||
};
|
||||
|
||||
void setAllowedNextProtocols(QList<QByteArray> protocols);
|
||||
QList<QByteArray> allowedNextProtocols() const;
|
||||
|
||||
QByteArray nextNegotiatedProtocol() const;
|
||||
NextProtocolNegotiationStatus nextProtocolNegotiationStatus() const;
|
||||
|
||||
static const char NextProtocolSpdy3_0[];
|
||||
static const char NextProtocolHttp1_1[];
|
||||
|
||||
private:
|
||||
friend class QSslSocket;
|
||||
friend class QSslConfigurationPrivate;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -86,7 +87,8 @@ public:
|
||||
allowRootCertOnDemandLoading(true),
|
||||
peerSessionShared(false),
|
||||
sslOptions(QSslConfigurationPrivate::defaultSslOptions),
|
||||
sslSessionTicketLifeTimeHint(-1)
|
||||
sslSessionTicketLifeTimeHint(-1),
|
||||
nextProtocolNegotiationStatus(QSslConfiguration::NextProtocolNegotiationNone)
|
||||
{ }
|
||||
|
||||
QSslCertificate peerCertificate;
|
||||
@ -114,6 +116,10 @@ public:
|
||||
QByteArray sslSession;
|
||||
int sslSessionTicketLifeTimeHint;
|
||||
|
||||
QList<QByteArray> nextAllowedProtocols;
|
||||
QByteArray nextNegotiatedProtocol;
|
||||
QSslConfiguration::NextProtocolNegotiationStatus nextProtocolNegotiationStatus;
|
||||
|
||||
// in qsslsocket.cpp:
|
||||
static QSslConfiguration defaultConfiguration();
|
||||
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -263,6 +264,45 @@ init_context:
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
|
||||
static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen, void *arg)
|
||||
{
|
||||
QSslContext::NPNContext *ctx = reinterpret_cast<QSslContext::NPNContext *>(arg);
|
||||
|
||||
// comment out to debug:
|
||||
// QList<QByteArray> supportedVersions;
|
||||
// for (unsigned int i = 0; i < inlen; ) {
|
||||
// QByteArray version(reinterpret_cast<const char *>(&in[i+1]), in[i]);
|
||||
// supportedVersions << version;
|
||||
// i += in[i] + 1;
|
||||
// }
|
||||
|
||||
int proto = q_SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len);
|
||||
switch (proto) {
|
||||
case OPENSSL_NPN_UNSUPPORTED:
|
||||
ctx->status = QSslConfiguration::NextProtocolNegotiationNone;
|
||||
break;
|
||||
case OPENSSL_NPN_NEGOTIATED:
|
||||
ctx->status = QSslConfiguration::NextProtocolNegotiationNegotiated;
|
||||
break;
|
||||
case OPENSSL_NPN_NO_OVERLAP:
|
||||
ctx->status = QSslConfiguration::NextProtocolNegotiationUnsupported;
|
||||
break;
|
||||
default:
|
||||
qWarning("OpenSSL sent unknown NPN status");
|
||||
}
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
QSslContext::NPNContext QSslContext::npnContext() const
|
||||
{
|
||||
return m_npnContext;
|
||||
}
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
|
||||
// Needs to be deleted by caller
|
||||
SSL* QSslContext::createSsl()
|
||||
{
|
||||
@ -283,6 +323,26 @@ SSL* QSslContext::createSsl()
|
||||
session = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
QList<QByteArray> protocols = sslConfiguration.d->nextAllowedProtocols;
|
||||
if (!protocols.isEmpty()) {
|
||||
m_supportedNPNVersions.clear();
|
||||
for (int a = 0; a < protocols.count(); ++a) {
|
||||
if (protocols.at(a).size() > 255) {
|
||||
qWarning() << "TLS NPN extension" << protocols.at(a)
|
||||
<< "is too long and will be truncated to 255 characters.";
|
||||
protocols[a] = protocols.at(a).left(255);
|
||||
}
|
||||
m_supportedNPNVersions.append(protocols.at(a).size()).append(protocols.at(a));
|
||||
}
|
||||
m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data());
|
||||
m_npnContext.len = m_supportedNPNVersions.count();
|
||||
m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
|
||||
q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext);
|
||||
}
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
|
||||
return ssl;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -72,6 +73,21 @@ public:
|
||||
QByteArray sessionASN1() const;
|
||||
void setSessionASN1(const QByteArray &sessionASN1);
|
||||
int sessionTicketLifeTimeHint() const;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
// must be public because we want to use it from an OpenSSL callback
|
||||
struct NPNContext {
|
||||
NPNContext() : data(0),
|
||||
len(0),
|
||||
status(QSslConfiguration::NextProtocolNegotiationNone)
|
||||
{ }
|
||||
unsigned char *data;
|
||||
unsigned short len;
|
||||
QSslConfiguration::NextProtocolNegotiationStatus status;
|
||||
};
|
||||
NPNContext npnContext() const;
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
|
||||
protected:
|
||||
QSslContext();
|
||||
|
||||
@ -84,6 +100,10 @@ private:
|
||||
QSslError::SslError errorCode;
|
||||
QString errorStr;
|
||||
QSslConfiguration sslConfiguration;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
QByteArray m_supportedNPNVersions;
|
||||
NPNContext m_npnContext;
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
};
|
||||
|
||||
#endif // QT_NO_SSL
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -905,6 +906,9 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
|
||||
d->configuration.sslOptions = configuration.d->sslOptions;
|
||||
d->configuration.sslSession = configuration.sessionTicket();
|
||||
d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
|
||||
d->configuration.nextAllowedProtocols = configuration.allowedNextProtocols();
|
||||
d->configuration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol();
|
||||
d->configuration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus();
|
||||
|
||||
// if the CA certificates were set explicitly (either via
|
||||
// QSslConfiguration::setCaCertificates() or QSslSocket::setCaCertificates(),
|
||||
|
@ -1486,6 +1486,15 @@ void QSslSocketBackendPrivate::continueHandshake()
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
const unsigned char *proto;
|
||||
unsigned int proto_len;
|
||||
q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
|
||||
QByteArray nextProtocol(reinterpret_cast<const char *>(proto), proto_len);
|
||||
configuration.nextNegotiatedProtocol = nextProtocol;
|
||||
configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
|
||||
connectionEncrypted = true;
|
||||
emit q->encrypted();
|
||||
if (autoStartHandshake && pendingClose) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -346,6 +347,20 @@ DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
|
||||
DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
|
||||
DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return)
|
||||
DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
DEFINEFUNC6(int, SSL_select_next_proto, unsigned char **out, out, unsigned char *outlen, outlen,
|
||||
const unsigned char *in, in, unsigned int inlen, inlen,
|
||||
const unsigned char *client, client, unsigned int client_len, client_len,
|
||||
return -1, return)
|
||||
DEFINEFUNC3(void, SSL_CTX_set_next_proto_select_cb, SSL_CTX *s, s,
|
||||
int (*cb) (SSL *ssl, unsigned char **out,
|
||||
unsigned char *outlen,
|
||||
const unsigned char *in,
|
||||
unsigned int inlen, void *arg), cb,
|
||||
void *arg, arg, return, DUMMYARG)
|
||||
DEFINEFUNC3(void, SSL_get0_next_proto_negotiated, const SSL *s, s,
|
||||
const unsigned char **data, data, unsigned *len, len, return, DUMMYARG)
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
|
||||
#define RESOLVEFUNC(func) \
|
||||
if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \
|
||||
@ -815,6 +830,11 @@ bool q_resolveOpenSslSymbols()
|
||||
RESOLVEFUNC(SSLeay_version)
|
||||
RESOLVEFUNC(i2d_SSL_SESSION)
|
||||
RESOLVEFUNC(d2i_SSL_SESSION)
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
RESOLVEFUNC(SSL_select_next_proto)
|
||||
RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb)
|
||||
RESOLVEFUNC(SSL_get0_next_proto_negotiated)
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
|
||||
symbolsResolved = true;
|
||||
delete libs.first;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||
@ -473,6 +474,20 @@ const char *q_SSLeay_version(int type);
|
||||
int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
|
||||
SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
int q_SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen,
|
||||
const unsigned char *client, unsigned int client_len);
|
||||
void q_SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
|
||||
int (*cb) (SSL *ssl, unsigned char **out,
|
||||
unsigned char *outlen,
|
||||
const unsigned char *in,
|
||||
unsigned int inlen, void *arg),
|
||||
void *arg);
|
||||
void q_SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
|
||||
unsigned *len);
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
|
||||
|
||||
// Helper function
|
||||
class QDateTime;
|
||||
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime);
|
||||
|
@ -25,6 +25,7 @@ qnetworkreply \
|
||||
qpainfo \
|
||||
qscreen \
|
||||
qssloptions \
|
||||
qsslsocket \
|
||||
qtabletevent \
|
||||
qtexteditlist \
|
||||
qtbug-8933 \
|
||||
|
164
tests/manual/qsslsocket/main.cpp
Normal file
164
tests/manual/qsslsocket/main.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <QtNetwork/qsslconfiguration.h>
|
||||
#include <QtNetwork/qsslsocket.h>
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
Q_DECLARE_METATYPE(QSslConfiguration::NextProtocolNegotiationStatus)
|
||||
#endif
|
||||
|
||||
class tst_QSslSocket : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
private slots:
|
||||
void nextProtocolNegotiation_data();
|
||||
void nextProtocolNegotiation();
|
||||
#endif // QT_NO_SSL
|
||||
};
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
void tst_QSslSocket::nextProtocolNegotiation_data()
|
||||
{
|
||||
QTest::addColumn<bool>("setConfiguration");
|
||||
QTest::addColumn<QString>("host");
|
||||
QTest::addColumn<QList<QByteArray> >("allowedProtocols");
|
||||
QTest::addColumn<QByteArray>("expectedProtocol");
|
||||
QTest::addColumn<QSslConfiguration::NextProtocolNegotiationStatus>("expectedStatus");
|
||||
|
||||
QList<QString> hosts = QList<QString>()
|
||||
<< QStringLiteral("www.google.com")
|
||||
<< QStringLiteral("www.facebook.com")
|
||||
<< QStringLiteral("www.twitter.com")
|
||||
<< QStringLiteral("graph.facebook.com")
|
||||
<< QStringLiteral("api.twitter.com");
|
||||
|
||||
foreach (QString host, hosts) {
|
||||
QByteArray tag = host.toLocal8Bit();
|
||||
tag.append("-none");
|
||||
QTest::newRow(tag)
|
||||
<< false
|
||||
<< host
|
||||
<< QList<QByteArray>()
|
||||
<< QByteArray()
|
||||
<< QSslConfiguration::NextProtocolNegotiationNone;
|
||||
|
||||
tag = host.toLocal8Bit();
|
||||
tag.append("-none-explicit");
|
||||
QTest::newRow(tag)
|
||||
<< true
|
||||
<< host
|
||||
<< QList<QByteArray>()
|
||||
<< QByteArray()
|
||||
<< QSslConfiguration::NextProtocolNegotiationNone;
|
||||
|
||||
tag = host.toLocal8Bit();
|
||||
tag.append("-http/1.1");
|
||||
QTest::newRow(tag)
|
||||
<< true
|
||||
<< host
|
||||
<< (QList<QByteArray>() << QSslConfiguration::NextProtocolHttp1_1)
|
||||
<< QByteArray(QSslConfiguration::NextProtocolHttp1_1)
|
||||
<< QSslConfiguration::NextProtocolNegotiationNegotiated;
|
||||
|
||||
tag = host.toLocal8Bit();
|
||||
tag.append("-spdy/3");
|
||||
QTest::newRow(tag)
|
||||
<< true
|
||||
<< host
|
||||
<< (QList<QByteArray>() << QSslConfiguration::NextProtocolSpdy3_0)
|
||||
<< QByteArray(QSslConfiguration::NextProtocolSpdy3_0)
|
||||
<< QSslConfiguration::NextProtocolNegotiationNegotiated;
|
||||
|
||||
tag = host.toLocal8Bit();
|
||||
tag.append("-spdy/3-and-http/1.1");
|
||||
QTest::newRow(tag)
|
||||
<< true
|
||||
<< host
|
||||
<< (QList<QByteArray>() << QSslConfiguration::NextProtocolSpdy3_0 << QSslConfiguration::NextProtocolHttp1_1)
|
||||
<< QByteArray(QSslConfiguration::NextProtocolSpdy3_0)
|
||||
<< QSslConfiguration::NextProtocolNegotiationNegotiated;
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QSslSocket::nextProtocolNegotiation()
|
||||
{
|
||||
if (!QSslSocket::supportsSsl())
|
||||
return;
|
||||
|
||||
QSslSocket socket;
|
||||
|
||||
QFETCH(bool, setConfiguration);
|
||||
|
||||
if (setConfiguration) {
|
||||
QSslConfiguration conf = socket.sslConfiguration();
|
||||
QFETCH(QList<QByteArray>, allowedProtocols);
|
||||
conf.setAllowedNextProtocols(allowedProtocols);
|
||||
socket.setSslConfiguration(conf);
|
||||
}
|
||||
|
||||
QFETCH(QString, host);
|
||||
|
||||
socket.connectToHostEncrypted(host, 443);
|
||||
socket.ignoreSslErrors();
|
||||
|
||||
QVERIFY(socket.waitForEncrypted(10000));
|
||||
|
||||
QFETCH(QByteArray, expectedProtocol);
|
||||
QCOMPARE(socket.sslConfiguration().nextNegotiatedProtocol(), expectedProtocol);
|
||||
|
||||
QFETCH(QSslConfiguration::NextProtocolNegotiationStatus, expectedStatus);
|
||||
QCOMPARE(socket.sslConfiguration().nextProtocolNegotiationStatus(), expectedStatus);
|
||||
|
||||
socket.disconnectFromHost();
|
||||
QVERIFY(socket.waitForDisconnected());
|
||||
|
||||
}
|
||||
|
||||
#endif // QT_NO_SSL
|
||||
|
||||
QTEST_MAIN(tst_QSslSocket)
|
||||
|
||||
#include "main.moc"
|
6
tests/manual/qsslsocket/qsslsocket.pro
Normal file
6
tests/manual/qsslsocket/qsslsocket.pro
Normal file
@ -0,0 +1,6 @@
|
||||
CONFIG += testcase
|
||||
|
||||
SOURCES += main.cpp
|
||||
QT = core network testlib
|
||||
|
||||
TARGET = tst_qsslsocket
|
Loading…
x
Reference in New Issue
Block a user