[Development] QSsl: finer-grained protocol selection

Mikkel Krautz mikkel at krautz.dk
Fri Dec 26 13:12:47 CET 2014


Hi,

For Mumble (http://mumble.info), we'd like the ability to select the
allowed protocols for a QSslSocket in more fine-grained manner.

Very old versions of Mumble, version 1.x, used SSLv3, where as newer
versions,
1.2 and above, use TLSv1.0. We'd like to upgrade to TLSv1.2, and we also
need
backwards compatibility with TLSv1.0 in order to be compatible with older
Mumble
clients and servers. But we're kind of stuck.

Specifying QSsl::TlsV1_2 means "TLS 1.2 only!", so that won't work for us.

We could use QSsl::SecureProtocols, but from reading the documentation, it's
a moving target (and rightfully so). In Qt 5.4, QSsl::SecureProtocols means
"TLS 1.0, TLS 1.1 and TLS 1.2". But in Qt 5.0, it also meant SSLv3.

(Aside: From a technical standpoint - not worrying about security for a
minute -
 we can't allow SSLv3. The 1.2 versions of Mumble displays a
 'backwards compatibility' warning if it connects to an SSLv3 server -
 which means a Mumble 1.x server. We would like to keep that behavior
around.)

For our use, we'd like to only allow TLS 1.0 and TLS 1.2. (But TLS 1.1 is
fine,
too!). So, the current QSsl::SecureProtocols in Qt 5.4 is fine for our use.
But since QSsl::SecureProtocols is a moving target, we're afraid that if we
commit to using it, a future Qt 5.x version may remove TLS 1.0 support. That
would break backwards compatibility to older Mumble servers and/or clients,
so
that's a no-no for us.

So:

Is QSsl::SecureProtocols guaranteed to be TLS 1.0, TLS 1.1 and TLS 1.2 for
the
rest of Qt 5?

If not, we'd like to discuss the possibility of adding more fine-grained
protocol
selection to QSslSocket. I'm happy to send code for review if we can find an
acceptable method.

One possibility would be to set the protocol to QSsl::AnyProtocol, and then
add
a new blacklist feature:

Protocol blacklist
==================

   /*
    * Sets the socket's protocol blacklist. Any protocols listed in the
blacklist
    * can not be used as the protocol for the socket.
    *
    * This method can be used with the QSsl::AnyProtocol protocol
    * to allow fine-grained selection of the allowed set of protocols
    * for the socket.
    *
    * See also: setProtocol().
    */
   void setProtocolBlacklist(QList<QSsl::SslProtocol> protocolBlacklist);

Technically (at least when using OpenSSL as the backend) this would use
SSLv23_client_method()/SSLv23_server_method() along with, for example,
SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3 to blacklist SSLv2 and SSLv3.

The API mirrors the blacklist approach used by OpenSSL itself (SSL_OP_NO*),
so it's a good match. But maybe it's not a good API.

Another option for the blacklist would be to add flags for each blacklist
candidate to QSsl::SslOptions, like so:

QSsl::SslOptionDisableSSLv2 = 0x080
QSsl::SslOptionDisableSSLv2 = 0x100
QSsl::SslOptionDisableTLSv1_0 = 0x200
QSsl::SslOptionDisableTLSv1_1 = 0x400
QSsl::SslOptionDisableTLSv1_2 = 0x800

These could be used with QSsl::AnyProtocol, and it would fit our use-case
perfectly.

Protocol list
=============

Instead of a blacklist, a new set of methods specifying a protocol list
could be added.

/*
 * Sets the socket's SSL protocol list. This is the list of protocols
 * the socket will support in its handshake.
 */
void setProtocols(QList<QSsl::SslProtocol> protocols);

/*
 * Returns the socket's SSL protocol list.
 */
QList<QSsl::SslProtocol> protocols() const;

If these were introduced, a new member would probably need to be introduced
to QSsl::SslProtocol as well, signalling that a list has been specified.

Something like:

QSsl::ProtocolListSpecified. // This signals that a list of protocols has
been
                             // specified using setProtocols(). Use
protocols()
                             // to get the list of allowed protocols.

Perhaps the list needs to be more than a QList<QSsl::SslProtocol> (to have
an isNull() to
mean 'use the default'?). I don't know yet.

The simply way
==============

For our use case, we'd also be perfectly happy to have an explicit
QSsl::SslProtocol
that says "TLS 1.0 or greater".

QSsl::TlsV1OrGreater // This option allows the use of TLS 1.0 or greater

This would be equivalent to the QSsl::SecureProtocols of the current Qt 5.4
release.
But it would explicitly contain TLS 1.0, to avoid the "moving target"
problem of
QSsl::SecureProtocols.


These are just some of the possible implementations that I could come up
with to
get a discussion started.

I hope we can find an acceptable solution to this problem.  For Windows and
OS X,
where most of our users are, we build Qt ourselves, and can patch this in
ourselves.
But we'd like a solution that distros can make use of as well.

Thanks,
Mikkel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20141226/c74050b6/attachment.html>


More information about the Development mailing list