-
Bug
-
Resolution: Fixed
-
P2: Important
-
6.10.0
-
None
-
-
69e1037be (dev), e0a759944 (6.10), 5ec542027 (tqtc/lts-6.8)
When using Schannel as the TLS backend, if the hostname contains Unicode characters (IDN), the TLS handshake fails, but using OpenSSL as the backend works correctly.
Minimal Reproducible Example:
#include <QSslSocket> #include <QDebug> #include <QUrl> int main(){ QSslSocket::setActiveBackend("schannel"); qDebug() << "Current TLS backend:" << QSslSocket::activeBackend(); qDebug() << "Available TLS backends:" << QSslSocket::availableBackends(); QUrl url("https://www.久盛电缆.com"); auto test = [&](const QString &host) { QSslSocket socket; socket.connectToHostEncrypted(host, 443); if (!socket.waitForEncrypted()) { qDebug() << host << socket.errorString(); } else { qDebug() << host << "Handshake succeeded"; } }; test(url.host()); test(url.host(QUrl::EncodeUnicode)); }
Actual Output:
Current TLS backend: "schannel" Available TLS backends: QList("cert-only", "openssl", "schannel") "www.久盛电缆.com" "Handshake failed: Internal error" "www.xn--3iq226gfdb94q.com" Handshake succeeded
Using Wireshark to capture the traffic, I found that Schannel sends raw Unicode in the SNI instead of converting hostnames to Punycode (ACE).
I also found a similar issue that might be caused by the same reason, but it has not been resolved for a long time:
https://bugreports.qt.io/browse/QTBUG-113028
If this is a Schannel-specific behavior, Qt should convert the hostname to ASCII-compatible Punycode (ACE) before passing it to the TLS layer.
For Gerrit Dashboard: QTBUG-141061 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
683966,3 | Schannel: encode the peer name for SNI | dev | qt/qtbase | Status: MERGED | +2 | 0 |
684763,2 | Schannel: encode the peer name for SNI | 6.10 | qt/qtbase | Status: MERGED | +2 | 0 |
684813,2 | Schannel: encode the peer name for SNI | tqtc/lts-6.8 | qt/tqtc-qtbase | Status: MERGED | +2 | 0 |