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) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
|
||||||
** Contact: http://www.qt-project.org/legal
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** 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::SslOptionDisableCompression
|
||||||
|QSsl::SslOptionDisableSessionPersistence;
|
|QSsl::SslOptionDisableSessionPersistence;
|
||||||
|
|
||||||
|
const char QSslConfiguration::NextProtocolSpdy3_0[] = "spdy/3";
|
||||||
|
const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1";
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QSslConfiguration
|
\class QSslConfiguration
|
||||||
\brief The QSslConfiguration class holds the configuration and state of an SSL connection
|
\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()
|
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
|
Constructs an empty SSL configuration. This configuration contains
|
||||||
no valid settings and the state will be empty. isNull() will
|
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->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
|
||||||
d->sslOptions == other.d->sslOptions &&
|
d->sslOptions == other.d->sslOptions &&
|
||||||
d->sslSession == other.d->sslSession &&
|
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->peerCertificateChain.count() == 0 &&
|
||||||
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
|
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
|
||||||
d->sslSession.isNull() &&
|
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;
|
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
|
Returns the default SSL configuration to be used in new SSL
|
||||||
connections.
|
connections.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
** 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
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||||
@ -131,6 +132,21 @@ public:
|
|||||||
static QSslConfiguration defaultConfiguration();
|
static QSslConfiguration defaultConfiguration();
|
||||||
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
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:
|
private:
|
||||||
friend class QSslSocket;
|
friend class QSslSocket;
|
||||||
friend class QSslConfigurationPrivate;
|
friend class QSslConfigurationPrivate;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
** 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
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||||
@ -86,7 +87,8 @@ public:
|
|||||||
allowRootCertOnDemandLoading(true),
|
allowRootCertOnDemandLoading(true),
|
||||||
peerSessionShared(false),
|
peerSessionShared(false),
|
||||||
sslOptions(QSslConfigurationPrivate::defaultSslOptions),
|
sslOptions(QSslConfigurationPrivate::defaultSslOptions),
|
||||||
sslSessionTicketLifeTimeHint(-1)
|
sslSessionTicketLifeTimeHint(-1),
|
||||||
|
nextProtocolNegotiationStatus(QSslConfiguration::NextProtocolNegotiationNone)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
QSslCertificate peerCertificate;
|
QSslCertificate peerCertificate;
|
||||||
@ -114,6 +116,10 @@ public:
|
|||||||
QByteArray sslSession;
|
QByteArray sslSession;
|
||||||
int sslSessionTicketLifeTimeHint;
|
int sslSessionTicketLifeTimeHint;
|
||||||
|
|
||||||
|
QList<QByteArray> nextAllowedProtocols;
|
||||||
|
QByteArray nextNegotiatedProtocol;
|
||||||
|
QSslConfiguration::NextProtocolNegotiationStatus nextProtocolNegotiationStatus;
|
||||||
|
|
||||||
// in qsslsocket.cpp:
|
// in qsslsocket.cpp:
|
||||||
static QSslConfiguration defaultConfiguration();
|
static QSslConfiguration defaultConfiguration();
|
||||||
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
static void setDefaultConfiguration(const QSslConfiguration &configuration);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
** 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
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||||
@ -263,6 +264,45 @@ init_context:
|
|||||||
return sslContext;
|
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
|
// Needs to be deleted by caller
|
||||||
SSL* QSslContext::createSsl()
|
SSL* QSslContext::createSsl()
|
||||||
{
|
{
|
||||||
@ -283,6 +323,26 @@ SSL* QSslContext::createSsl()
|
|||||||
session = 0;
|
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;
|
return ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
** 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
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||||
@ -72,6 +73,21 @@ public:
|
|||||||
QByteArray sessionASN1() const;
|
QByteArray sessionASN1() const;
|
||||||
void setSessionASN1(const QByteArray &sessionASN1);
|
void setSessionASN1(const QByteArray &sessionASN1);
|
||||||
int sessionTicketLifeTimeHint() const;
|
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:
|
protected:
|
||||||
QSslContext();
|
QSslContext();
|
||||||
|
|
||||||
@ -84,6 +100,10 @@ private:
|
|||||||
QSslError::SslError errorCode;
|
QSslError::SslError errorCode;
|
||||||
QString errorStr;
|
QString errorStr;
|
||||||
QSslConfiguration sslConfiguration;
|
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
|
#endif // QT_NO_SSL
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
** 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
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** 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.sslOptions = configuration.d->sslOptions;
|
||||||
d->configuration.sslSession = configuration.sessionTicket();
|
d->configuration.sslSession = configuration.sessionTicket();
|
||||||
d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
|
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
|
// if the CA certificates were set explicitly (either via
|
||||||
// QSslConfiguration::setCaCertificates() or QSslSocket::setCaCertificates(),
|
// 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;
|
connectionEncrypted = true;
|
||||||
emit q->encrypted();
|
emit q->encrypted();
|
||||||
if (autoStartHandshake && pendingClose) {
|
if (autoStartHandshake && pendingClose) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
** 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
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** 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)
|
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)
|
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)
|
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) \
|
#define RESOLVEFUNC(func) \
|
||||||
if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \
|
if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \
|
||||||
@ -815,6 +830,11 @@ bool q_resolveOpenSslSymbols()
|
|||||||
RESOLVEFUNC(SSLeay_version)
|
RESOLVEFUNC(SSLeay_version)
|
||||||
RESOLVEFUNC(i2d_SSL_SESSION)
|
RESOLVEFUNC(i2d_SSL_SESSION)
|
||||||
RESOLVEFUNC(d2i_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;
|
symbolsResolved = true;
|
||||||
delete libs.first;
|
delete libs.first;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
** 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
|
** Contact: http://www.qt-project.org/legal
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** 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);
|
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);
|
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
|
// Helper function
|
||||||
class QDateTime;
|
class QDateTime;
|
||||||
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime);
|
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime);
|
||||||
|
@ -25,6 +25,7 @@ qnetworkreply \
|
|||||||
qpainfo \
|
qpainfo \
|
||||||
qscreen \
|
qscreen \
|
||||||
qssloptions \
|
qssloptions \
|
||||||
|
qsslsocket \
|
||||||
qtabletevent \
|
qtabletevent \
|
||||||
qtexteditlist \
|
qtexteditlist \
|
||||||
qtbug-8933 \
|
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