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, &currentState);
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