1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org>
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qsslsocket.h"
41
42 #include "qssl_p.h"
43 #include "qsslsocket_mac_p.h"
44 #include "qasn1element_p.h"
45 #include "qsslcertificate_p.h"
46 #include "qsslcipher_p.h"
47 #include "qsslkey_p.h"
48
49 #include <QtCore/qmessageauthenticationcode.h>
50 #include <QtCore/qoperatingsystemversion.h>
51 #include <QtCore/qscopedvaluerollback.h>
52 #include <QtCore/qcryptographichash.h>
53 #include <QtCore/qsystemdetection.h>
54 #include <QtCore/qdatastream.h>
55 #include <QtCore/qsysinfo.h>
56 #include <QtCore/qvector.h>
57 #include <QtCore/qmutex.h>
58 #include <QtCore/qdebug.h>
59 #include <QtCore/quuid.h>
60 #include <QtCore/qdir.h>
61
62 #include <algorithm>
63 #include <cstddef>
64 #include <limits>
65 #include <vector>
66
67 #include <QtCore/private/qcore_mac_p.h>
68
69 #ifdef Q_OS_MACOS
70 #include <CoreServices/CoreServices.h>
71 #endif
72
73 QT_BEGIN_NAMESPACE
74
75 namespace
76 {
77 #ifdef Q_OS_MACOS
78 /*
79
80 Our own temporarykeychain is needed only on macOS where SecPKCS12Import changes
81 the default keychain and where we see annoying pop-ups asking about accessing a
82 private key.
83
84 */
85
86 struct EphemeralSecKeychain
87 {
88 EphemeralSecKeychain();
89 ~EphemeralSecKeychain();
90
91 SecKeychainRef keychain = nullptr;
92 Q_DISABLE_COPY_MOVE(EphemeralSecKeychain)
93 };
94
EphemeralSecKeychain()95 EphemeralSecKeychain::EphemeralSecKeychain()
96 {
97 const auto uuid = QUuid::createUuid();
98 if (uuid.isNull()) {
99 qCWarning(lcSsl) << "Failed to create a unique keychain name";
100 return;
101 }
102
103 const QByteArray uuidAsByteArray = uuid.toByteArray();
104 Q_ASSERT(uuidAsByteArray.size() > 2);
105 Q_ASSERT(uuidAsByteArray.startsWith('{'));
106 Q_ASSERT(uuidAsByteArray.endsWith('}'));
107 const auto uuidAsString = QLatin1String(uuidAsByteArray.data(), uuidAsByteArray.size()).mid(1, uuidAsByteArray.size() - 2);
108
109 const QString keychainName
110 = QDir::tempPath() + QDir::separator() + uuidAsString + QLatin1String(".keychain");
111 // SecKeychainCreate, pathName parameter:
112 //
113 // "A constant character string representing the POSIX path indicating where
114 // to store the keychain."
115 //
116 // Internally they seem to use std::string, but this does not really help.
117 // Fortunately, CFString has a convenient API.
118 QCFType<CFStringRef> cfName = keychainName.toCFString();
119 std::vector<char> posixPath;
120 // "Extracts the contents of a string as a NULL-terminated 8-bit string
121 // appropriate for passing to POSIX APIs."
122 posixPath.resize(CFStringGetMaximumSizeOfFileSystemRepresentation(cfName));
123 const auto ok = CFStringGetFileSystemRepresentation(cfName, &posixPath[0],
124 CFIndex(posixPath.size()));
125 if (!ok) {
126 qCWarning(lcSsl) << "Failed to create a unique keychain name from"
127 << "QDir::tempPath()";
128 return;
129 }
130
131 std::vector<uint8_t> passUtf8(256);
132 if (SecRandomCopyBytes(kSecRandomDefault, passUtf8.size(), &passUtf8[0])) {
133 qCWarning(lcSsl) << "SecRandomCopyBytes: failed to create a key";
134 return;
135 }
136
137 const OSStatus status = SecKeychainCreate(&posixPath[0], passUtf8.size(),
138 &passUtf8[0], FALSE, nullptr,
139 &keychain);
140 if (status != errSecSuccess || !keychain) {
141 qCWarning(lcSsl) << "SecKeychainCreate: failed to create a custom keychain";
142 if (keychain) {
143 SecKeychainDelete(keychain);
144 CFRelease(keychain);
145 keychain = nullptr;
146 }
147 }
148
149 if (keychain) {
150 SecKeychainSettings settings = {};
151 settings.version = SEC_KEYCHAIN_SETTINGS_VERS1;
152 // Strange, huh? But that's what their docs say to do! With lockOnSleep
153 // == false, set interval to INT_MAX to never lock ...
154 settings.lockInterval = INT_MAX;
155 if (SecKeychainSetSettings(keychain, &settings) != errSecSuccess)
156 qCWarning(lcSsl) << "SecKeychainSettings: failed to disable lock on sleep";
157 }
158
159 #ifdef QSSLSOCKET_DEBUG
160 if (keychain) {
161 qCDebug(lcSsl) << "Custom keychain with name" << keychainName << "was created"
162 << "successfully";
163 }
164 #endif
165 }
166
~EphemeralSecKeychain()167 EphemeralSecKeychain::~EphemeralSecKeychain()
168 {
169 if (keychain) {
170 // clear file off disk
171 SecKeychainDelete(keychain);
172 CFRelease(keychain);
173 }
174 }
175
176 #endif // Q_OS_MACOS
177
178 } // unnamed namespace
179
qt_createSecureTransportContext(QSslSocket::SslMode mode)180 static SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode)
181 {
182 const bool isServer = mode == QSslSocket::SslServerMode;
183 const SSLProtocolSide side = isServer ? kSSLServerSide : kSSLClientSide;
184 // We never use kSSLDatagramType, so it's kSSLStreamType unconditionally.
185 SSLContextRef context = SSLCreateContext(nullptr, side, kSSLStreamType);
186 if (!context)
187 qCWarning(lcSsl) << "SSLCreateContext failed";
188 return context;
189 }
190
qt_releaseSecureTransportContext(SSLContextRef context)191 static void qt_releaseSecureTransportContext(SSLContextRef context)
192 {
193 if (context)
194 CFRelease(context);
195 }
196
QSecureTransportContext(SSLContextRef c)197 QSecureTransportContext::QSecureTransportContext(SSLContextRef c)
198 : context(c)
199 {
200 }
201
~QSecureTransportContext()202 QSecureTransportContext::~QSecureTransportContext()
203 {
204 qt_releaseSecureTransportContext(context);
205 }
206
operator SSLContextRef() const207 QSecureTransportContext::operator SSLContextRef()const
208 {
209 return context;
210 }
211
reset(SSLContextRef newContext)212 void QSecureTransportContext::reset(SSLContextRef newContext)
213 {
214 qt_releaseSecureTransportContext(context);
215 context = newContext;
216 }
217
218 Q_GLOBAL_STATIC(QRecursiveMutex, qt_securetransport_mutex)
219
220 //#define QSSLSOCKET_DEBUG
221
222 bool QSslSocketPrivate::s_libraryLoaded = false;
223 bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
224 bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
225
226
227 #if !defined(QT_PLATFORM_UIKIT) // dhparam is only used on macOS. (see the SSLSetDiffieHellmanParams call below)
228 static const uint8_t dhparam[] =
229 "\x30\x82\x01\x08\x02\x82\x01\x01\x00\x97\xea\xd0\x46\xf7\xae\xa7\x76\x80"
230 "\x9c\x74\x56\x98\xd8\x56\x97\x2b\x20\x6c\x77\xe2\x82\xbb\xc8\x84\xbe\xe7"
231 "\x63\xaf\xcc\x30\xd0\x67\x97\x7d\x1b\xab\x59\x30\xa9\x13\x67\x21\xd7\xd4"
232 "\x0e\x46\xcf\xe5\x80\xdf\xc9\xb9\xba\x54\x9b\x46\x2f\x3b\x45\xfc\x2f\xaf"
233 "\xad\xc0\x17\x56\xdd\x52\x42\x57\x45\x70\x14\xe5\xbe\x67\xaa\xde\x69\x75"
234 "\x30\x0d\xf9\xa2\xc4\x63\x4d\x7a\x39\xef\x14\x62\x18\x33\x44\xa1\xf9\xc1"
235 "\x52\xd1\xb6\x72\x21\x98\xf8\xab\x16\x1b\x7b\x37\x65\xe3\xc5\x11\x00\xf6"
236 "\x36\x1f\xd8\x5f\xd8\x9f\x43\xa8\xce\x9d\xbf\x5e\xd6\x2d\xfa\x0a\xc2\x01"
237 "\x54\xc2\xd9\x81\x54\x55\xb5\x26\xf8\x88\x37\xf5\xfe\xe0\xef\x4a\x34\x81"
238 "\xdc\x5a\xb3\x71\x46\x27\xe3\xcd\x24\xf6\x1b\xf1\xe2\x0f\xc2\xa1\x39\x53"
239 "\x5b\xc5\x38\x46\x8e\x67\x4c\xd9\xdd\xe4\x37\x06\x03\x16\xf1\x1d\x7a\xba"
240 "\x2d\xc1\xe4\x03\x1a\x58\xe5\x29\x5a\x29\x06\x69\x61\x7a\xd8\xa9\x05\x9f"
241 "\xc1\xa2\x45\x9c\x17\xad\x52\x69\x33\xdc\x18\x8d\x15\xa6\x5e\xcd\x94\xf4"
242 "\x45\xbb\x9f\xc2\x7b\x85\x00\x61\xb0\x1a\xdc\x3c\x86\xaa\x9f\x5c\x04\xb3"
243 "\x90\x0b\x35\x64\xff\xd9\xe3\xac\xf2\xf2\xeb\x3a\x63\x02\x01\x02";
244 #endif
245
ReadCallback(QSslSocketBackendPrivate * socket,char * data,size_t * dataLength)246 OSStatus QSslSocketBackendPrivate::ReadCallback(QSslSocketBackendPrivate *socket,
247 char *data, size_t *dataLength)
248 {
249 Q_ASSERT(socket);
250 Q_ASSERT(data);
251 Q_ASSERT(dataLength);
252
253 QTcpSocket *plainSocket = socket->plainSocket;
254 Q_ASSERT(plainSocket);
255
256 if (socket->isHandshakeComplete()) {
257 // Check if it's a renegotiation attempt, when the handshake is complete, the
258 // session state is 'kSSLConnected':
259 SSLSessionState currentState = kSSLConnected;
260 const OSStatus result = SSLGetSessionState(socket->context, ¤tState);
261 if (result != noErr) {
262 *dataLength = 0;
263 return result;
264 }
265
266 if (currentState == kSSLHandshake) {
267 // Renegotiation detected, don't allow read more yet - 'transmit'
268 // will notice this and will call 'startHandshake':
269 *dataLength = 0;
270 socket->renegotiating = true;
271 return errSSLWouldBlock;
272 }
273 }
274
275 const qint64 bytes = plainSocket->read(data, *dataLength);
276 #ifdef QSSLSOCKET_DEBUG
277 qCDebug(lcSsl) << plainSocket << "read" << bytes;
278 #endif
279 if (bytes < 0) {
280 *dataLength = 0;
281 return errSecIO;
282 }
283
284 const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : errSecSuccess;
285 *dataLength = bytes;
286
287 return err;
288 }
289
WriteCallback(QSslSocketBackendPrivate * socket,const char * data,size_t * dataLength)290 OSStatus QSslSocketBackendPrivate::WriteCallback(QSslSocketBackendPrivate *socket,
291 const char *data, size_t *dataLength)
292 {
293 Q_ASSERT(socket);
294 Q_ASSERT(data);
295 Q_ASSERT(dataLength);
296
297 QTcpSocket *plainSocket = socket->plainSocket;
298 Q_ASSERT(plainSocket);
299
300 const qint64 bytes = plainSocket->write(data, *dataLength);
301 #ifdef QSSLSOCKET_DEBUG
302 qCDebug(lcSsl) << plainSocket << "write" << bytes;
303 #endif
304 if (bytes < 0) {
305 *dataLength = 0;
306 return errSecIO;
307 }
308
309 const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : errSecSuccess;
310 *dataLength = bytes;
311
312 return err;
313 }
314
ensureInitialized()315 void QSslSocketPrivate::ensureInitialized()
316 {
317 const QMutexLocker locker(qt_securetransport_mutex);
318 if (s_loadedCiphersAndCerts)
319 return;
320
321 // We have to set it before setDefaultSupportedCiphers,
322 // since this function can trigger static (global)'s initialization
323 // and as a result - recursive ensureInitialized call
324 // from QSslCertificatePrivate's ctor.
325 s_loadedCiphersAndCerts = true;
326
327 const QSecureTransportContext context(qt_createSecureTransportContext(QSslSocket::SslClientMode));
328 if (context) {
329 QList<QSslCipher> ciphers;
330 QList<QSslCipher> defaultCiphers;
331
332 size_t numCiphers = 0;
333 // Fails only if any of parameters is null.
334 SSLGetNumberSupportedCiphers(context, &numCiphers);
335 QVector<SSLCipherSuite> cfCiphers(numCiphers);
336 // Fails only if any of parameter is null or number of ciphers is wrong.
337 SSLGetSupportedCiphers(context, cfCiphers.data(), &numCiphers);
338
339 for (size_t i = 0; i < size_t(cfCiphers.size()); ++i) {
340 const QSslCipher ciph(QSslSocketBackendPrivate::QSslCipher_from_SSLCipherSuite(cfCiphers.at(i)));
341 if (!ciph.isNull()) {
342 ciphers << ciph;
343 if (ciph.usedBits() >= 128)
344 defaultCiphers << ciph;
345 }
346 }
347
348 setDefaultSupportedCiphers(ciphers);
349 setDefaultCiphers(defaultCiphers);
350
351 if (!s_loadRootCertsOnDemand)
352 setDefaultCaCertificates(systemCaCertificates());
353 } else {
354 s_loadedCiphersAndCerts = false;
355 }
356
357 }
358
sslLibraryVersionNumber()359 long QSslSocketPrivate::sslLibraryVersionNumber()
360 {
361 return 0;
362 }
363
sslLibraryVersionString()364 QString QSslSocketPrivate::sslLibraryVersionString()
365 {
366 return QLatin1String("Secure Transport, ") + QSysInfo::prettyProductName();
367 }
368
sslLibraryBuildVersionNumber()369 long QSslSocketPrivate::sslLibraryBuildVersionNumber()
370 {
371 return 0;
372 }
373
sslLibraryBuildVersionString()374 QString QSslSocketPrivate::sslLibraryBuildVersionString()
375 {
376 return sslLibraryVersionString();
377 }
378
supportsSsl()379 bool QSslSocketPrivate::supportsSsl()
380 {
381 return true;
382 }
383
resetDefaultCiphers()384 void QSslSocketPrivate::resetDefaultCiphers()
385 {
386 Q_UNIMPLEMENTED();
387 }
388
resetDefaultEllipticCurves()389 void QSslSocketPrivate::resetDefaultEllipticCurves()
390 {
391 // No public API for this (?).
392 Q_UNIMPLEMENTED();
393 }
394
QSslSocketBackendPrivate()395 QSslSocketBackendPrivate::QSslSocketBackendPrivate()
396 : context(nullptr)
397 {
398 }
399
~QSslSocketBackendPrivate()400 QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
401 {
402 destroySslContext();
403 }
404
continueHandshake()405 void QSslSocketBackendPrivate::continueHandshake()
406 {
407 #ifdef QSSLSOCKET_DEBUG
408 qCDebug(lcSsl) << plainSocket << "connection encrypted";
409 #endif
410 Q_Q(QSslSocket);
411 connectionEncrypted = true;
412
413 #if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
414 // Unlike OpenSSL, Secure Transport does not allow to negotiate protocols via
415 // a callback during handshake. We can only set our list of preferred protocols
416 // (and send it during handshake) and then receive what our peer has sent to us.
417 // And here we can finally try to find a match (if any).
418 if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
419 const auto &requestedProtocols = configuration.nextAllowedProtocols;
420 if (const int requestedCount = requestedProtocols.size()) {
421 configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNone;
422 configuration.nextNegotiatedProtocol.clear();
423
424 QCFType<CFArrayRef> cfArray;
425 const OSStatus result = SSLCopyALPNProtocols(context, &cfArray);
426 if (result == errSecSuccess && cfArray && CFArrayGetCount(cfArray)) {
427 const int size = CFArrayGetCount(cfArray);
428 QVector<QString> peerProtocols(size);
429 for (int i = 0; i < size; ++i)
430 peerProtocols[i] = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(cfArray, i));
431
432 for (int i = 0; i < requestedCount; ++i) {
433 const auto requestedName = QString::fromLatin1(requestedProtocols[i]);
434 for (int j = 0; j < size; ++j) {
435 if (requestedName == peerProtocols[j]) {
436 configuration.nextNegotiatedProtocol = requestedName.toLatin1();
437 configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
438 break;
439 }
440 }
441 if (configuration.nextProtocolNegotiationStatus == QSslConfiguration::NextProtocolNegotiationNegotiated)
442 break;
443 }
444 }
445 }
446 }
447 #endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE
448
449 if (!renegotiating)
450 emit q->encrypted();
451
452 if (autoStartHandshake && pendingClose) {
453 pendingClose = false;
454 q->disconnectFromHost();
455 }
456 }
457
disconnected()458 void QSslSocketBackendPrivate::disconnected()
459 {
460 if (plainSocket->bytesAvailable() <= 0)
461 destroySslContext();
462 // If there is still buffered data in the plain socket, don't destroy the ssl context yet.
463 // It will be destroyed when the socket is deleted.
464 }
465
disconnectFromHost()466 void QSslSocketBackendPrivate::disconnectFromHost()
467 {
468 if (context) {
469 if (!shutdown) {
470 SSLClose(context);
471 shutdown = true;
472 }
473 }
474 plainSocket->disconnectFromHost();
475 }
476
sessionCipher() const477 QSslCipher QSslSocketBackendPrivate::sessionCipher() const
478 {
479 SSLCipherSuite cipher = 0;
480 if (context && SSLGetNegotiatedCipher(context, &cipher) == errSecSuccess)
481 return QSslCipher_from_SSLCipherSuite(cipher);
482
483 return QSslCipher();
484 }
485
sessionProtocol() const486 QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
487 {
488 if (!context)
489 return QSsl::UnknownProtocol;
490
491 SSLProtocol protocol = kSSLProtocolUnknown;
492 const OSStatus err = SSLGetNegotiatedProtocolVersion(context, &protocol);
493 if (err != errSecSuccess) {
494 qCWarning(lcSsl) << "SSLGetNegotiatedProtocolVersion failed:" << err;
495 return QSsl::UnknownProtocol;
496 }
497
498 switch (protocol) {
499 case kSSLProtocol2:
500 return QSsl::SslV2;
501 case kSSLProtocol3:
502 return QSsl::SslV3;
503 case kTLSProtocol1:
504 return QSsl::TlsV1_0;
505 case kTLSProtocol11:
506 return QSsl::TlsV1_1;
507 case kTLSProtocol12:
508 return QSsl::TlsV1_2;
509 case kTLSProtocol13:
510 return QSsl::TlsV1_3;
511 default:
512 return QSsl::UnknownProtocol;
513 }
514 }
515
startClientEncryption()516 void QSslSocketBackendPrivate::startClientEncryption()
517 {
518 if (!initSslContext()) {
519 // Error description/code were set, 'error' emitted
520 // by initSslContext, but OpenSSL socket also sets error
521 // emits a signal twice, so ...
522 setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("Unable to init SSL Context"));
523 return;
524 }
525
526 startHandshake();
527 }
528
startServerEncryption()529 void QSslSocketBackendPrivate::startServerEncryption()
530 {
531 if (!initSslContext()) {
532 // Error description/code were set, 'error' emitted
533 // by initSslContext, but OpenSSL socket also sets error
534 // emits a signal twice, so ...
535 setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("Unable to init SSL Context"));
536 return;
537 }
538
539 startHandshake();
540 }
541
transmit()542 void QSslSocketBackendPrivate::transmit()
543 {
544 Q_Q(QSslSocket);
545
546 // If we don't have any SSL context, don't bother transmitting.
547 // Edit: if SSL session closed, don't bother either.
548 if (!context || shutdown)
549 return;
550
551 if (!isHandshakeComplete())
552 startHandshake();
553
554 if (isHandshakeComplete() && !writeBuffer.isEmpty()) {
555 qint64 totalBytesWritten = 0;
556 while (writeBuffer.nextDataBlockSize() > 0 && context) {
557 const size_t nextDataBlockSize = writeBuffer.nextDataBlockSize();
558 size_t writtenBytes = 0;
559 const OSStatus err = SSLWrite(context, writeBuffer.readPointer(), nextDataBlockSize, &writtenBytes);
560 #ifdef QSSLSOCKET_DEBUG
561 qCDebug(lcSsl) << plainSocket << "SSLWrite returned" << err;
562 #endif
563 if (err != errSecSuccess && err != errSSLWouldBlock) {
564 setErrorAndEmit(QAbstractSocket::SslInternalError,
565 QStringLiteral("SSLWrite failed: %1").arg(err));
566 break;
567 }
568
569 if (writtenBytes) {
570 writeBuffer.free(writtenBytes);
571 totalBytesWritten += writtenBytes;
572 }
573
574 if (writtenBytes < nextDataBlockSize)
575 break;
576 }
577
578 if (totalBytesWritten > 0) {
579 // Don't emit bytesWritten() recursively.
580 if (!emittedBytesWritten) {
581 emittedBytesWritten = true;
582 emit q->bytesWritten(totalBytesWritten);
583 emittedBytesWritten = false;
584 }
585 emit q->channelBytesWritten(0, totalBytesWritten);
586 }
587 }
588
589 if (isHandshakeComplete()) {
590 QVarLengthArray<char, 4096> data;
591 while (context && (!readBufferMaxSize || buffer.size() < readBufferMaxSize)) {
592 size_t readBytes = 0;
593 data.resize(4096);
594 const OSStatus err = SSLRead(context, data.data(), data.size(), &readBytes);
595 #ifdef QSSLSOCKET_DEBUG
596 qCDebug(lcSsl) << plainSocket << "SSLRead returned" << err;
597 #endif
598 if (err == errSSLClosedGraceful) {
599 shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
600 setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
601 QSslSocket::tr("The TLS/SSL connection has been closed"));
602 break;
603 } else if (err != errSecSuccess && err != errSSLWouldBlock) {
604 setErrorAndEmit(QAbstractSocket::SslInternalError,
605 QStringLiteral("SSLRead failed: %1").arg(err));
606 break;
607 }
608
609 if (err == errSSLWouldBlock && renegotiating) {
610 startHandshake();
611 break;
612 }
613
614 if (readBytes) {
615 buffer.append(data.constData(), readBytes);
616 if (readyReadEmittedPointer)
617 *readyReadEmittedPointer = true;
618 emit q->readyRead();
619 emit q->channelReadyRead(0);
620 }
621
622 if (err == errSSLWouldBlock)
623 break;
624 }
625 }
626 }
627
628
629 QList<QSslError> (QSslSocketBackendPrivate::verify)(QList<QSslCertificate> certificateChain, const QString &hostName)
630 {
631 Q_UNIMPLEMENTED();
632 Q_UNUSED(certificateChain)
633 Q_UNUSED(hostName)
634
635 QList<QSslError> errors;
636 errors << QSslError(QSslError::UnspecifiedError);
637
638 return errors;
639 }
640
importPkcs12(QIODevice * device,QSslKey * key,QSslCertificate * cert,QList<QSslCertificate> * caCertificates,const QByteArray & passPhrase)641 bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
642 QSslKey *key, QSslCertificate *cert,
643 QList<QSslCertificate> *caCertificates,
644 const QByteArray &passPhrase)
645 {
646 Q_UNIMPLEMENTED();
647 Q_UNUSED(device)
648 Q_UNUSED(key)
649 Q_UNUSED(cert)
650 Q_UNUSED(caCertificates)
651 Q_UNUSED(passPhrase)
652 return false;
653 }
654
QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher)655 QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher)
656 {
657 QSslCipher ciph;
658 switch (cipher) {
659 // Sorted as in CipherSuite.h (and groupped by their RFC)
660 case SSL_RSA_WITH_NULL_MD5:
661 ciph.d->name = QLatin1String("NULL-MD5");
662 ciph.d->protocol = QSsl::SslV3;
663 break;
664 case SSL_RSA_WITH_NULL_SHA:
665 ciph.d->name = QLatin1String("NULL-SHA");
666 ciph.d->protocol = QSsl::SslV3;
667 break;
668 case SSL_RSA_WITH_RC4_128_MD5:
669 ciph.d->name = QLatin1String("RC4-MD5");
670 ciph.d->protocol = QSsl::SslV3;
671 break;
672 case SSL_RSA_WITH_RC4_128_SHA:
673 ciph.d->name = QLatin1String("RC4-SHA");
674 ciph.d->protocol = QSsl::SslV3;
675 break;
676
677 // TLS addenda using AES, per RFC 3268
678 case TLS_RSA_WITH_AES_128_CBC_SHA:
679 ciph.d->name = QLatin1String("AES128-SHA");
680 break;
681 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
682 ciph.d->name = QLatin1String("DHE-RSA-AES128-SHA");
683 break;
684 case TLS_RSA_WITH_AES_256_CBC_SHA:
685 ciph.d->name = QLatin1String("AES256-SHA");
686 break;
687 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
688 ciph.d->name = QLatin1String("DHE-RSA-AES256-SHA");
689 break;
690
691 // ECDSA addenda, RFC 4492
692 case TLS_ECDH_ECDSA_WITH_NULL_SHA:
693 ciph.d->name = QLatin1String("ECDH-ECDSA-NULL-SHA");
694 break;
695 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
696 ciph.d->name = QLatin1String("ECDH-ECDSA-RC4-SHA");
697 break;
698 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
699 ciph.d->name = QLatin1String("ECDH-ECDSA-DES-CBC3-SHA");
700 break;
701 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
702 ciph.d->name = QLatin1String("ECDH-ECDSA-AES128-SHA");
703 break;
704 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
705 ciph.d->name = QLatin1String("ECDH-ECDSA-AES256-SHA");
706 break;
707 case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
708 ciph.d->name = QLatin1String("ECDHE-ECDSA-NULL-SHA");
709 break;
710 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
711 ciph.d->name = QLatin1String("ECDHE-ECDSA-RC4-SHA");
712 break;
713 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
714 ciph.d->name = QLatin1String("ECDHE-ECDSA-DES-CBC3-SHA");
715 break;
716 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
717 ciph.d->name = QLatin1String("ECDHE-ECDSA-AES128-SHA");
718 break;
719 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
720 ciph.d->name = QLatin1String("ECDHE-ECDSA-AES256-SHA");
721 break;
722 case TLS_ECDH_RSA_WITH_NULL_SHA:
723 ciph.d->name = QLatin1String("ECDH-RSA-NULL-SHA");
724 break;
725 case TLS_ECDH_RSA_WITH_RC4_128_SHA:
726 ciph.d->name = QLatin1String("ECDH-RSA-RC4-SHA");
727 break;
728 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
729 ciph.d->name = QLatin1String("ECDH-RSA-DES-CBC3-SHA");
730 break;
731 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
732 ciph.d->name = QLatin1String("ECDH-RSA-AES128-SHA");
733 break;
734 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
735 ciph.d->name = QLatin1String("ECDH-RSA-AES256-SHA");
736 break;
737 case TLS_ECDHE_RSA_WITH_NULL_SHA:
738 ciph.d->name = QLatin1String("ECDHE-RSA-NULL-SHA");
739 break;
740 case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
741 ciph.d->name = QLatin1String("ECDHE-RSA-RC4-SHA");
742 break;
743 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
744 ciph.d->name = QLatin1String("ECDHE-RSA-DES-CBC3-SHA");
745 break;
746 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
747 ciph.d->name = QLatin1String("ECDHE-RSA-AES128-SHA");
748 break;
749 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
750 ciph.d->name = QLatin1String("ECDHE-RSA-AES256-SHA");
751 break;
752
753 // TLS 1.2 addenda, RFC 5246
754 case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
755 ciph.d->name = QLatin1String("DES-CBC3-SHA");
756 break;
757 case TLS_RSA_WITH_AES_128_CBC_SHA256:
758 ciph.d->name = QLatin1String("AES128-SHA256");
759 break;
760 case TLS_RSA_WITH_AES_256_CBC_SHA256:
761 ciph.d->name = QLatin1String("AES256-SHA256");
762 break;
763 case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
764 ciph.d->name = QLatin1String("DHE-RSA-DES-CBC3-SHA");
765 break;
766 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
767 ciph.d->name = QLatin1String("DHE-RSA-AES128-SHA256");
768 break;
769 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
770 ciph.d->name = QLatin1String("DHE-RSA-AES256-SHA256");
771 break;
772
773 // Addendum from RFC 4279, TLS PSK
774 // all missing atm.
775
776 // RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption
777 // all missing atm.
778
779 // Addenda from rfc 5288 AES Galois Counter Mode (CGM) Cipher Suites for TLS
780 case TLS_RSA_WITH_AES_256_GCM_SHA384:
781 ciph.d->name = QLatin1String("AES256-GCM-SHA384");
782 break;
783
784 // RFC 5487 - PSK with SHA-256/384 and AES GCM
785 // all missing atm.
786
787 // Addenda from rfc 5289 Elliptic Curve Cipher Suites with HMAC SHA-256/384
788 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
789 ciph.d->name = QLatin1String("ECDHE-ECDSA-AES128-SHA256");
790 break;
791 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
792 ciph.d->name = QLatin1String("ECDHE-ECDSA-AES256-SHA384");
793 break;
794 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
795 ciph.d->name = QLatin1String("ECDH-ECDSA-AES128-SHA256");
796 break;
797 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
798 ciph.d->name = QLatin1String("ECDH-ECDSA-AES256-SHA384");
799 break;
800 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
801 ciph.d->name = QLatin1String("ECDHE-RSA-AES128-SHA256");
802 break;
803 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
804 ciph.d->name = QLatin1String("ECDHE-RSA-AES256-SHA384");
805 break;
806 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
807 ciph.d->name = QLatin1String("ECDH-RSA-AES128-SHA256");
808 break;
809 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
810 ciph.d->name = QLatin1String("ECDH-RSA-AES256-SHA384");
811 break;
812
813 // Addenda from rfc 5289 Elliptic Curve Cipher Suites
814 // with SHA-256/384 and AES Galois Counter Mode (GCM)
815 case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
816 ciph.d->name = QLatin1String("ECDHE-RSA-AES256-GCM-SHA384");
817 break;
818
819 default:
820 return ciph;
821 }
822 ciph.d->isNull = false;
823
824 // protocol
825 if (ciph.d->protocol == QSsl::SslV3) {
826 ciph.d->protocolString = QLatin1String("SSLv3");
827 } else {
828 ciph.d->protocol = QSsl::TlsV1_2;
829 ciph.d->protocolString = QLatin1String("TLSv1.2");
830 }
831
832 const auto bits = ciph.d->name.splitRef(QLatin1Char('-'));
833 if (bits.size() >= 2) {
834 if (bits.size() == 2 || bits.size() == 3) {
835 ciph.d->keyExchangeMethod = QLatin1String("RSA");
836 } else if (bits.front() == QLatin1String("DH") || bits.front() == QLatin1String("DHE")) {
837 ciph.d->keyExchangeMethod = QLatin1String("DH");
838 } else if (bits.front() == QLatin1String("ECDH") || bits.front() == QLatin1String("ECDHE")) {
839 ciph.d->keyExchangeMethod = QLatin1String("ECDH");
840 } else {
841 qCWarning(lcSsl) << "Unknown Kx" << ciph.d->name;
842 }
843
844 if (bits.size() == 2 || bits.size() == 3) {
845 ciph.d->authenticationMethod = QLatin1String("RSA");
846 } else if (ciph.d->name.contains(QLatin1String("-ECDSA-"))) {
847 ciph.d->authenticationMethod = QLatin1String("ECDSA");
848 } else if (ciph.d->name.contains(QLatin1String("-RSA-"))) {
849 ciph.d->authenticationMethod = QLatin1String("RSA");
850 } else {
851 qCWarning(lcSsl) << "Unknown Au" << ciph.d->name;
852 }
853
854 if (ciph.d->name.contains(QLatin1String("RC4-"))) {
855 ciph.d->encryptionMethod = QLatin1String("RC4(128)");
856 ciph.d->bits = 128;
857 ciph.d->supportedBits = 128;
858 } else if (ciph.d->name.contains(QLatin1String("DES-CBC3-"))) {
859 ciph.d->encryptionMethod = QLatin1String("3DES(168)");
860 ciph.d->bits = 168;
861 ciph.d->supportedBits = 168;
862 } else if (ciph.d->name.contains(QLatin1String("AES128-"))) {
863 ciph.d->encryptionMethod = QLatin1String("AES(128)");
864 ciph.d->bits = 128;
865 ciph.d->supportedBits = 128;
866 } else if (ciph.d->name.contains(QLatin1String("AES256-GCM"))) {
867 ciph.d->encryptionMethod = QLatin1String("AESGCM(256)");
868 ciph.d->bits = 256;
869 ciph.d->supportedBits = 256;
870 } else if (ciph.d->name.contains(QLatin1String("AES256-"))) {
871 ciph.d->encryptionMethod = QLatin1String("AES(256)");
872 ciph.d->bits = 256;
873 ciph.d->supportedBits = 256;
874 } else if (ciph.d->name.contains(QLatin1String("NULL-"))) {
875 ciph.d->encryptionMethod = QLatin1String("NULL");
876 } else {
877 qCWarning(lcSsl) << "Unknown Enc" << ciph.d->name;
878 }
879 }
880 return ciph;
881 }
882
initSslContext()883 bool QSslSocketBackendPrivate::initSslContext()
884 {
885 Q_Q(QSslSocket);
886
887 Q_ASSERT_X(!context, Q_FUNC_INFO, "invalid socket state, context is not null");
888 Q_ASSERT(plainSocket);
889
890 context.reset(qt_createSecureTransportContext(mode));
891 if (!context) {
892 setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("SSLCreateContext failed"));
893 return false;
894 }
895
896 const OSStatus err = SSLSetIOFuncs(context,
897 reinterpret_cast<SSLReadFunc>(&QSslSocketBackendPrivate::ReadCallback),
898 reinterpret_cast<SSLWriteFunc>(&QSslSocketBackendPrivate::WriteCallback));
899 if (err != errSecSuccess) {
900 destroySslContext();
901 setErrorAndEmit(QAbstractSocket::SslInternalError,
902 QStringLiteral("SSLSetIOFuncs failed: %1").arg(err));
903 return false;
904 }
905
906 SSLSetConnection(context, this);
907
908 if (mode == QSslSocket::SslServerMode
909 && !configuration.localCertificateChain.isEmpty()) {
910 QString errorDescription;
911 QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
912 if (!setSessionCertificate(errorDescription, errorCode)) {
913 destroySslContext();
914 setErrorAndEmit(errorCode, errorDescription);
915 return false;
916 }
917 }
918
919 if (!setSessionProtocol()) {
920 destroySslContext();
921 setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("Failed to set protocol version"));
922 return false;
923 }
924
925 #if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
926 if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
927 const auto protocolNames = configuration.nextAllowedProtocols;
928 QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks));
929 if (cfNames) {
930 for (const QByteArray &name : protocolNames) {
931 if (name.size() > 255) {
932 qCWarning(lcSsl) << "TLS ALPN extension" << name
933 << "is too long and will be ignored.";
934 continue;
935 } else if (name.isEmpty()) {
936 continue;
937 }
938 QCFString cfName(QString::fromLatin1(name).toCFString());
939 CFArrayAppendValue(cfNames, cfName);
940 }
941
942 if (CFArrayGetCount(cfNames)) {
943 // Up to the application layer to check that negotiation
944 // failed, and handle this non-TLS error, we do not handle
945 // the result of this call as an error:
946 if (SSLSetALPNProtocols(context, cfNames) != errSecSuccess)
947 qCWarning(lcSsl) << "SSLSetALPNProtocols failed - too long protocol names?";
948 }
949 } else {
950 qCWarning(lcSsl) << "failed to allocate ALPN names array";
951 }
952 }
953 #endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE
954
955 if (mode == QSslSocket::SslClientMode) {
956 // enable Server Name Indication (SNI)
957 QString tlsHostName(verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName);
958 if (tlsHostName.isEmpty())
959 tlsHostName = hostName;
960
961 const QByteArray ace(QUrl::toAce(tlsHostName));
962 SSLSetPeerDomainName(context, ace.data(), ace.size());
963 // tell SecureTransport we handle peer verification ourselves
964 OSStatus err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnServerAuth, true);
965 if (err == errSecSuccess)
966 err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnCertRequested, true);
967
968 if (err != errSecSuccess) {
969 destroySslContext();
970 setErrorAndEmit(QSslSocket::SslInternalError,
971 QStringLiteral("SSLSetSessionOption failed: %1").arg(err));
972 return false;
973 }
974 //
975 } else {
976 if (configuration.peerVerifyMode != QSslSocket::VerifyNone) {
977 // kAlwaysAuthenticate - always fails even if we set break on client auth.
978 OSStatus err = SSLSetClientSideAuthenticate(context, kTryAuthenticate);
979 if (err == errSecSuccess) {
980 // We'd like to verify peer ourselves, otherwise handshake will
981 // most probably fail before we can do anything.
982 err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnClientAuth, true);
983 }
984
985 if (err != errSecSuccess) {
986 destroySslContext();
987 setErrorAndEmit(QAbstractSocket::SslInternalError,
988 QStringLiteral("failed to set SSL context option in server mode: %1").arg(err));
989 return false;
990 }
991 }
992 #if !defined(QT_PLATFORM_UIKIT)
993 // No SSLSetDiffieHellmanParams on iOS; calling it is optional according to docs.
994 SSLSetDiffieHellmanParams(context, dhparam, sizeof(dhparam));
995 #endif
996 }
997 return true;
998 }
999
destroySslContext()1000 void QSslSocketBackendPrivate::destroySslContext()
1001 {
1002 context.reset(nullptr);
1003 }
1004
setSessionCertificate(QString & errorDescription,QAbstractSocket::SocketError & errorCode)1005 bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription, QAbstractSocket::SocketError &errorCode)
1006 {
1007 Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
1008
1009 QSslCertificate localCertificate;
1010 if (!configuration.localCertificateChain.isEmpty())
1011 localCertificate = configuration.localCertificateChain.at(0);
1012
1013 if (!localCertificate.isNull()) {
1014 // Require a private key as well.
1015 if (configuration.privateKey.isNull()) {
1016 errorCode = QAbstractSocket::SslInvalidUserDataError;
1017 errorDescription = QStringLiteral("Cannot provide a certificate with no key");
1018 return false;
1019 }
1020
1021 // import certificates and key
1022 const QString passPhrase(QString::fromLatin1("foobar"));
1023 QCFType<CFDataRef> pkcs12 = _q_makePkcs12(configuration.localCertificateChain,
1024 configuration.privateKey, passPhrase).toCFData();
1025 QCFType<CFStringRef> password = passPhrase.toCFString();
1026 const void *keys[2] = { kSecImportExportPassphrase };
1027 const void *values[2] = { password };
1028 CFIndex nKeys = 1;
1029 #ifdef Q_OS_MACOS
1030 bool envOk = false;
1031 const int env = qEnvironmentVariableIntValue("QT_SSL_USE_TEMPORARY_KEYCHAIN", &envOk);
1032 if (envOk && env) {
1033 static const EphemeralSecKeychain temporaryKeychain;
1034 if (temporaryKeychain.keychain) {
1035 nKeys = 2;
1036 keys[1] = kSecImportExportKeychain;
1037 values[1] = temporaryKeychain.keychain;
1038 }
1039 }
1040 #endif
1041 QCFType<CFDictionaryRef> options = CFDictionaryCreate(nullptr, keys, values, nKeys,
1042 nullptr, nullptr);
1043 QCFType<CFArrayRef> items;
1044 OSStatus err = SecPKCS12Import(pkcs12, options, &items);
1045 if (err != errSecSuccess) {
1046 #ifdef QSSLSOCKET_DEBUG
1047 qCWarning(lcSsl) << plainSocket
1048 << QStringLiteral("SecPKCS12Import failed: %1").arg(err);
1049 #endif
1050 errorCode = QAbstractSocket::SslInvalidUserDataError;
1051 errorDescription = QStringLiteral("SecPKCS12Import failed: %1").arg(err);
1052 return false;
1053 }
1054
1055 if (!CFArrayGetCount(items)) {
1056 #ifdef QSSLSOCKET_DEBUG
1057 qCWarning(lcSsl) << plainSocket << "SecPKCS12Import returned no items";
1058 #endif
1059 errorCode = QAbstractSocket::SslInvalidUserDataError;
1060 errorDescription = QStringLiteral("SecPKCS12Import returned no items");
1061 return false;
1062 }
1063
1064 CFDictionaryRef import = (CFDictionaryRef)CFArrayGetValueAtIndex(items, 0);
1065 SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(import, kSecImportItemIdentity);
1066 if (!identity) {
1067 #ifdef QSSLSOCKET_DEBUG
1068 qCWarning(lcSsl) << plainSocket << "SecPKCS12Import returned no identity";
1069 #endif
1070 errorCode = QAbstractSocket::SslInvalidUserDataError;
1071 errorDescription = QStringLiteral("SecPKCS12Import returned no identity");
1072 return false;
1073 }
1074
1075 QCFType<CFMutableArrayRef> certs = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks);
1076 if (!certs) {
1077 errorCode = QAbstractSocket::SslInternalError;
1078 errorDescription = QStringLiteral("Failed to allocate certificates array");
1079 return false;
1080 }
1081
1082 CFArrayAppendValue(certs, identity);
1083
1084 CFArrayRef chain = (CFArrayRef)CFDictionaryGetValue(import, kSecImportItemCertChain);
1085 if (chain) {
1086 for (CFIndex i = 1, e = CFArrayGetCount(chain); i < e; ++i)
1087 CFArrayAppendValue(certs, CFArrayGetValueAtIndex(chain, i));
1088 }
1089
1090 err = SSLSetCertificate(context, certs);
1091 if (err != errSecSuccess) {
1092 #ifdef QSSLSOCKET_DEBUG
1093 qCWarning(lcSsl) << plainSocket
1094 << QStringLiteral("Cannot set certificate and key: %1").arg(err);
1095 #endif
1096 errorCode = QAbstractSocket::SslInvalidUserDataError;
1097 errorDescription = QStringLiteral("Cannot set certificate and key: %1").arg(err);
1098 return false;
1099 }
1100 }
1101
1102 return true;
1103 }
1104
setSessionProtocol()1105 bool QSslSocketBackendPrivate::setSessionProtocol()
1106 {
1107 Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
1108
1109 // QSsl::SslV2 == kSSLProtocol2 is disabled in Secure Transport and
1110 // always fails with errSSLIllegalParam:
1111 // if (version < MINIMUM_STREAM_VERSION || version > MAXIMUM_STREAM_VERSION)
1112 // return errSSLIllegalParam;
1113 // where MINIMUM_STREAM_VERSION is SSL_Version_3_0, MAXIMUM_STREAM_VERSION is TLS_Version_1_2.
1114 if (configuration.protocol == QSsl::SslV2) {
1115 qCDebug(lcSsl) << "protocol QSsl::SslV2 is disabled";
1116 return false;
1117 }
1118
1119 // SslV3 is unsupported.
1120 if (configuration.protocol == QSsl::SslV3) {
1121 qCDebug(lcSsl) << "protocol QSsl::SslV3 is disabled";
1122 return false;
1123 }
1124
1125 // SecureTransport has kTLSProtocol13 constant and also, kTLSProtocolMaxSupported.
1126 // Calling SSLSetProtocolVersionMax/Min with any of these two constants results
1127 // in errInvalidParam and a failure to set the protocol version. This means
1128 // no TLS 1.3 on macOS and iOS.
1129 switch (configuration.protocol) {
1130 case QSsl::TlsV1_3:
1131 case QSsl::TlsV1_3OrLater:
1132 qCWarning(lcSsl) << plainSocket << "SecureTransport does not support TLS 1.3";
1133 return false;
1134 default:;
1135 }
1136
1137 OSStatus err = errSecSuccess;
1138
1139 if (configuration.protocol == QSsl::TlsV1_0) {
1140 #ifdef QSSLSOCKET_DEBUG
1141 qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0";
1142 #endif
1143 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
1144 if (err == errSecSuccess)
1145 err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
1146 } else if (configuration.protocol == QSsl::TlsV1_1) {
1147 #ifdef QSSLSOCKET_DEBUG
1148 qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1";
1149 #endif
1150 err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
1151 if (err == errSecSuccess)
1152 err = SSLSetProtocolVersionMax(context, kTLSProtocol11);
1153 } else if (configuration.protocol == QSsl::TlsV1_2) {
1154 #ifdef QSSLSOCKET_DEBUG
1155 qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2";
1156 #endif
1157 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
1158 if (err == errSecSuccess)
1159 err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
1160 } else if (configuration.protocol == QSsl::AnyProtocol) {
1161 #ifdef QSSLSOCKET_DEBUG
1162 qCDebug(lcSsl) << plainSocket << "requesting : any";
1163 #endif
1164 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
1165 } else if (configuration.protocol == QSsl::TlsV1SslV3) {
1166 #ifdef QSSLSOCKET_DEBUG
1167 qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2";
1168 #endif
1169 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
1170 if (err == errSecSuccess)
1171 err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
1172 } else if (configuration.protocol == QSsl::SecureProtocols) {
1173 #ifdef QSSLSOCKET_DEBUG
1174 qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2";
1175 #endif
1176 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
1177 } else if (configuration.protocol == QSsl::TlsV1_0OrLater) {
1178 #ifdef QSSLSOCKET_DEBUG
1179 qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2";
1180 #endif
1181 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
1182 } else if (configuration.protocol == QSsl::TlsV1_1OrLater) {
1183 #ifdef QSSLSOCKET_DEBUG
1184 qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1 - TLSv1.2";
1185 #endif
1186 err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
1187 } else if (configuration.protocol == QSsl::TlsV1_2OrLater) {
1188 #ifdef QSSLSOCKET_DEBUG
1189 qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2";
1190 #endif
1191 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
1192 } else {
1193 #ifdef QSSLSOCKET_DEBUG
1194 qCDebug(lcSsl) << plainSocket << "no protocol version found in the configuration";
1195 #endif
1196 return false;
1197 }
1198
1199 return err == errSecSuccess;
1200 }
1201
canIgnoreTrustVerificationFailure() const1202 bool QSslSocketBackendPrivate::canIgnoreTrustVerificationFailure() const
1203 {
1204 const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode;
1205 return mode == QSslSocket::SslServerMode
1206 && (verifyMode == QSslSocket::QueryPeer
1207 || verifyMode == QSslSocket::AutoVerifyPeer
1208 || verifyMode == QSslSocket::VerifyNone);
1209 }
1210
verifySessionProtocol() const1211 bool QSslSocketBackendPrivate::verifySessionProtocol() const
1212 {
1213 bool protocolOk = false;
1214 if (configuration.protocol == QSsl::AnyProtocol)
1215 protocolOk = true;
1216 else if (configuration.protocol == QSsl::TlsV1SslV3)
1217 protocolOk = (sessionProtocol() == QSsl::TlsV1_0);
1218 else if (configuration.protocol == QSsl::SecureProtocols)
1219 protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
1220 else if (configuration.protocol == QSsl::TlsV1_0OrLater)
1221 protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
1222 else if (configuration.protocol == QSsl::TlsV1_1OrLater)
1223 protocolOk = (sessionProtocol() >= QSsl::TlsV1_1);
1224 else if (configuration.protocol == QSsl::TlsV1_2OrLater)
1225 protocolOk = (sessionProtocol() >= QSsl::TlsV1_2);
1226 else if (configuration.protocol == QSsl::TlsV1_3OrLater)
1227 protocolOk = (sessionProtocol() >= QSsl::TlsV1_3OrLater);
1228 else
1229 protocolOk = (sessionProtocol() == configuration.protocol);
1230
1231 return protocolOk;
1232 }
1233
verifyPeerTrust()1234 bool QSslSocketBackendPrivate::verifyPeerTrust()
1235 {
1236 Q_Q(QSslSocket);
1237
1238 const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode;
1239 const bool canIgnoreVerify = canIgnoreTrustVerificationFailure();
1240
1241 Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)");
1242 Q_ASSERT(plainSocket);
1243
1244 QCFType<SecTrustRef> trust;
1245 OSStatus err = SSLCopyPeerTrust(context, &trust);
1246 // !trust - SSLCopyPeerTrust can return errSecSuccess but null trust.
1247 if (err != errSecSuccess || !trust) {
1248 if (!canIgnoreVerify) {
1249 setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
1250 QStringLiteral("Failed to obtain peer trust: %1").arg(err));
1251 plainSocket->disconnectFromHost();
1252 return false;
1253 } else {
1254 return true;
1255 }
1256 }
1257
1258 QList<QSslError> errors;
1259
1260 // Store certificates.
1261 // Apple's docs say SetTrustEvaluate must be called before
1262 // SecTrustGetCertificateAtIndex, but this results
1263 // in 'kSecTrustResultRecoverableTrustFailure', so
1264 // here we just ignore 'res' (later we'll use SetAnchor etc.
1265 // and evaluate again).
1266 SecTrustResultType res = kSecTrustResultInvalid;
1267 err = SecTrustEvaluate(trust, &res);
1268 if (err != errSecSuccess) {
1269 // We can not ignore this, it's not even about trust verification
1270 // probably ...
1271 setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
1272 QStringLiteral("SecTrustEvaluate failed: %1").arg(err));
1273 plainSocket->disconnectFromHost();
1274 return false;
1275 }
1276
1277 configuration.peerCertificate.clear();
1278 configuration.peerCertificateChain.clear();
1279
1280 const CFIndex certCount = SecTrustGetCertificateCount(trust);
1281 for (CFIndex i = 0; i < certCount; ++i) {
1282 SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
1283 QCFType<CFDataRef> derData = SecCertificateCopyData(cert);
1284 configuration.peerCertificateChain << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
1285 }
1286
1287 if (configuration.peerCertificateChain.size())
1288 configuration.peerCertificate = configuration.peerCertificateChain.at(0);
1289
1290 // Check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer):
1291 for (const QSslCertificate &cert : qAsConst(configuration.peerCertificateChain)) {
1292 if (QSslCertificatePrivate::isBlacklisted(cert) && !canIgnoreVerify) {
1293 const QSslError error(QSslError::CertificateBlacklisted, cert);
1294 errors << error;
1295 emit q->peerVerifyError(error);
1296 if (q->state() != QAbstractSocket::ConnectedState)
1297 return false;
1298 }
1299 }
1300
1301 const bool doVerifyPeer = verifyMode == QSslSocket::VerifyPeer
1302 || (verifyMode == QSslSocket::AutoVerifyPeer
1303 && mode == QSslSocket::SslClientMode);
1304 // Check the peer certificate itself. First try the subject's common name
1305 // (CN) as a wildcard, then try all alternate subject name DNS entries the
1306 // same way.
1307 if (!configuration.peerCertificate.isNull()) {
1308 // but only if we're a client connecting to a server
1309 // if we're the server, don't check CN
1310 if (mode == QSslSocket::SslClientMode) {
1311 const QString peerName(verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
1312 if (!isMatchingHostname(configuration.peerCertificate, peerName) && !canIgnoreVerify) {
1313 // No matches in common names or alternate names.
1314 const QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate);
1315 errors << error;
1316 emit q->peerVerifyError(error);
1317 if (q->state() != QAbstractSocket::ConnectedState)
1318 return false;
1319 }
1320 }
1321 } else {
1322 // No peer certificate presented. Report as error if the socket
1323 // expected one.
1324 if (doVerifyPeer && !canIgnoreVerify) {
1325 const QSslError error(QSslError::NoPeerCertificate);
1326 errors << error;
1327 emit q->peerVerifyError(error);
1328 if (q->state() != QAbstractSocket::ConnectedState)
1329 return false;
1330 }
1331 }
1332
1333 // verify certificate chain
1334 QCFType<CFMutableArrayRef> certArray = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks);
1335 for (const QSslCertificate &cert : qAsConst(configuration.caCertificates)) {
1336 QCFType<CFDataRef> certData = cert.d->derData.toCFData();
1337 if (QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(nullptr, certData))
1338 CFArrayAppendValue(certArray, secRef);
1339 else
1340 qCWarning(lcSsl, "Failed to create SecCertificate from QSslCertificate");
1341 }
1342
1343 SecTrustSetAnchorCertificates(trust, certArray);
1344
1345 // By default SecTrustEvaluate uses both CA certificates provided in
1346 // QSslConfiguration and the ones from the system database. This behavior can
1347 // be unexpected if a user's code tries to limit the trusted CAs to those
1348 // explicitly set in QSslConfiguration.
1349 // Since on macOS we initialize the default QSslConfiguration copying the
1350 // system CA certificates (using SecTrustSettingsCopyCertificates) we can
1351 // call SecTrustSetAnchorCertificatesOnly(trust, true) to force SecTrustEvaluate
1352 // to use anchors only from our QSslConfiguration.
1353 // Unfortunately, SecTrustSettingsCopyCertificates is not available on iOS
1354 // and the default QSslConfiguration always has an empty list of system CA
1355 // certificates. This leaves no way to provide client code with access to the
1356 // actual system CA certificate list (which most use-cases need) other than
1357 // by letting SecTrustEvaluate fall through to the system list; so, in this case
1358 // (even though the client code may have provided its own certs), we retain
1359 // the default behavior. Note, with macOS SDK below 10.12 using 'trust my
1360 // anchors only' may result in some valid chains rejected, apparently the
1361 // ones containing intermediated certificates; so we use this functionality
1362 // on more recent versions only.
1363
1364 bool anchorsFromConfigurationOnly = false;
1365
1366 #ifdef Q_OS_MACOS
1367 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra)
1368 anchorsFromConfigurationOnly = true;
1369 #endif // Q_OS_MACOS
1370
1371 SecTrustSetAnchorCertificatesOnly(trust, anchorsFromConfigurationOnly);
1372
1373 SecTrustResultType trustResult = kSecTrustResultInvalid;
1374 SecTrustEvaluate(trust, &trustResult);
1375 switch (trustResult) {
1376 case kSecTrustResultUnspecified:
1377 case kSecTrustResultProceed:
1378 break;
1379 default:
1380 if (!canIgnoreVerify) {
1381 const QSslError error(QSslError::CertificateUntrusted, configuration.peerCertificate);
1382 errors << error;
1383 emit q->peerVerifyError(error);
1384 }
1385 }
1386
1387 // report errors
1388 if (!errors.isEmpty() && !canIgnoreVerify) {
1389 sslErrors = errors;
1390 // checkSslErrors unconditionally emits sslErrors:
1391 // a user's slot can abort/close/disconnect on this
1392 // signal, so we also test the socket's state:
1393 if (!checkSslErrors() || q->state() != QAbstractSocket::ConnectedState)
1394 return false;
1395 } else {
1396 sslErrors.clear();
1397 }
1398
1399 return true;
1400 }
1401
1402 /*
1403 Copied verbatim from qsslsocket_openssl.cpp
1404 */
checkSslErrors()1405 bool QSslSocketBackendPrivate::checkSslErrors()
1406 {
1407 Q_Q(QSslSocket);
1408 if (sslErrors.isEmpty())
1409 return true;
1410
1411 emit q->sslErrors(sslErrors);
1412
1413 const bool doVerifyPeer = configuration.peerVerifyMode == QSslSocket::VerifyPeer
1414 || (configuration.peerVerifyMode == QSslSocket::AutoVerifyPeer
1415 && mode == QSslSocket::SslClientMode);
1416 const bool doEmitSslError = !verifyErrorsHaveBeenIgnored();
1417 // check whether we need to emit an SSL handshake error
1418 if (doVerifyPeer && doEmitSslError) {
1419 if (q->pauseMode() & QAbstractSocket::PauseOnSslErrors) {
1420 pauseSocketNotifiers(q);
1421 paused = true;
1422 } else {
1423 setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
1424 sslErrors.constFirst().errorString());
1425 plainSocket->disconnectFromHost();
1426 }
1427 return false;
1428 }
1429
1430 return true;
1431 }
1432
startHandshake()1433 bool QSslSocketBackendPrivate::startHandshake()
1434 {
1435 Q_ASSERT(context);
1436 Q_Q(QSslSocket);
1437
1438 OSStatus err = SSLHandshake(context);
1439 #ifdef QSSLSOCKET_DEBUG
1440 qCDebug(lcSsl) << plainSocket << "SSLHandhake returned" << err;
1441 #endif
1442
1443 if (err == errSSLWouldBlock) {
1444 // startHandshake has to be called again ... later.
1445 return false;
1446 } else if (err == errSSLServerAuthCompleted) {
1447 // errSSLServerAuthCompleted is a define for errSSLPeerAuthCompleted,
1448 // it works for both server/client modes.
1449 // In future we'll evaluate peer's trust at this point,
1450 // for now we just continue.
1451 // if (!verifyPeerTrust())
1452 // ...
1453 return startHandshake();
1454 } else if (err == errSSLClientCertRequested) {
1455 Q_ASSERT(mode == QSslSocket::SslClientMode);
1456 QString errorDescription;
1457 QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
1458 // setSessionCertificate does not fail if we have no certificate.
1459 // Failure means a real error (invalid certificate, no private key, etc).
1460 if (!setSessionCertificate(errorDescription, errorCode)) {
1461 setErrorAndEmit(errorCode, errorDescription);
1462 renegotiating = false;
1463 return false;
1464 } else {
1465 // We try to resume a handshake, even if have no
1466 // local certificates ... (up to server to deal with our failure).
1467 return startHandshake();
1468 }
1469 } else if (err != errSecSuccess) {
1470 if (err == errSSLBadCert && canIgnoreTrustVerificationFailure()) {
1471 // We're on the server side and client did not provide any
1472 // certificate. This is the new 'nice' error returned by
1473 // Security Framework after it was recently updated.
1474 return startHandshake();
1475 }
1476
1477 renegotiating = false;
1478 setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
1479 QStringLiteral("SSLHandshake failed: %1").arg(err));
1480 plainSocket->disconnectFromHost();
1481 return false;
1482 }
1483
1484 // Connection aborted during handshake phase.
1485 if (q->state() != QAbstractSocket::ConnectedState) {
1486 qCDebug(lcSsl) << "connection aborted";
1487 renegotiating = false;
1488 return false;
1489 }
1490
1491 // check protocol version ourselves, as Secure Transport does not enforce
1492 // the requested min / max versions.
1493 if (!verifySessionProtocol()) {
1494 setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, QStringLiteral("Protocol version mismatch"));
1495 plainSocket->disconnectFromHost();
1496 renegotiating = false;
1497 return false;
1498 }
1499
1500 if (verifyPeerTrust()) {
1501 continueHandshake();
1502 renegotiating = false;
1503 return true;
1504 } else {
1505 renegotiating = false;
1506 return false;
1507 }
1508 }
1509
1510 QT_END_NAMESPACE
1511