1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
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 
41 #ifndef QSSLSOCKET_P_H
42 #define QSSLSOCKET_P_H
43 
44 #include "qsslsocket.h"
45 
46 //
47 //  W A R N I N G
48 //  -------------
49 //
50 // This file is not part of the Qt API. It exists purely as an
51 // implementation detail. This header file may change from version to
52 // version without notice, or even be removed.
53 //
54 // We mean it.
55 //
56 
57 #include <QtNetwork/private/qtnetworkglobal_p.h>
58 #include <private/qtcpsocket_p.h>
59 #include "qsslkey.h"
60 #include "qsslconfiguration_p.h"
61 #include "qocspresponse.h"
62 #ifndef QT_NO_OPENSSL
63 #include <private/qsslcontext_openssl_p.h>
64 #else
65 class QSslContext;
66 #endif
67 
68 #include <QtCore/qstringlist.h>
69 #include <QtCore/qvector.h>
70 #include <private/qringbuffer_p.h>
71 
72 #if defined(Q_OS_MAC)
73 #include <Security/SecCertificate.h>
74 #include <CoreFoundation/CFArray.h>
75 #elif defined(Q_OS_WIN)
76 #include <QtCore/qt_windows.h>
77 #include <memory>
78 #ifndef Q_OS_WINRT
79 #include <wincrypt.h>
80 #endif // !Q_OS_WINRT
81 #ifndef HCRYPTPROV_LEGACY
82 #define HCRYPTPROV_LEGACY HCRYPTPROV
83 #endif // !HCRYPTPROV_LEGACY
84 #endif // Q_OS_WIN
85 
86 QT_BEGIN_NAMESPACE
87 
88 #if defined(Q_OS_MACX)
89     typedef CFDataRef (*PtrSecCertificateCopyData)(SecCertificateRef);
90     typedef OSStatus (*PtrSecTrustSettingsCopyCertificates)(int, CFArrayRef*);
91     typedef OSStatus (*PtrSecTrustCopyAnchorCertificates)(CFArrayRef*);
92 #endif
93 
94 #if defined(Q_OS_WIN)
95 
96 // Those are needed by both OpenSSL and SChannel back-ends on Windows:
97 struct QHCertStoreDeleter {
operatorQHCertStoreDeleter98     void operator()(HCERTSTORE store)
99     {
100         CertCloseStore(store, 0);
101     }
102 };
103 
104 using QHCertStorePointer = std::unique_ptr<void, QHCertStoreDeleter>;
105 
106 #endif // Q_OS_WIN
107 
108 class QSslSocketPrivate : public QTcpSocketPrivate
109 {
110     Q_DECLARE_PUBLIC(QSslSocket)
111 public:
112     QSslSocketPrivate();
113     virtual ~QSslSocketPrivate();
114 
115     void init();
116     bool verifyProtocolSupported(const char *where);
117     bool initialized;
118 
119     QSslSocket::SslMode mode;
120     bool autoStartHandshake;
121     bool connectionEncrypted;
122     bool shutdown;
123     bool ignoreAllSslErrors;
124     QList<QSslError> ignoreErrorsList;
125     bool* readyReadEmittedPointer;
126 
127     QSslConfigurationPrivate configuration;
128     QList<QSslError> sslErrors;
129     QSharedPointer<QSslContext> sslContextPointer;
130 
131     // if set, this hostname is used for certificate validation instead of the hostname
132     // that was used for connecting to.
133     QString verificationPeerName;
134 
135     bool allowRootCertOnDemandLoading;
136 
137     static bool s_loadRootCertsOnDemand;
138 
139     static bool supportsSsl();
140     static long sslLibraryVersionNumber();
141     static QString sslLibraryVersionString();
142     static long sslLibraryBuildVersionNumber();
143     static QString sslLibraryBuildVersionString();
144     static void ensureInitialized();
145     static QList<QSslCipher> defaultCiphers();
146     static QList<QSslCipher> supportedCiphers();
147     static void setDefaultCiphers(const QList<QSslCipher> &ciphers);
148     static void setDefaultSupportedCiphers(const QList<QSslCipher> &ciphers);
149     static void resetDefaultCiphers();
150 
151     static QVector<QSslEllipticCurve> supportedEllipticCurves();
152     static void setDefaultSupportedEllipticCurves(const QVector<QSslEllipticCurve> &curves);
153     static void resetDefaultEllipticCurves();
154 
155     static QList<QSslCertificate> defaultCaCertificates();
156     static QList<QSslCertificate> systemCaCertificates();
157     static void setDefaultCaCertificates(const QList<QSslCertificate> &certs);
158     static bool addDefaultCaCertificates(const QString &path, QSsl::EncodingFormat format,
159                                          QRegExp::PatternSyntax syntax);
160     static void addDefaultCaCertificate(const QSslCertificate &cert);
161     static void addDefaultCaCertificates(const QList<QSslCertificate> &certs);
162     Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QSslCertificate &cert,
163                                                      const QString &peerName);
164     Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
165 
166     // The socket itself, including private slots.
167     QTcpSocket *plainSocket;
168     void createPlainSocket(QIODevice::OpenMode openMode);
169     static void pauseSocketNotifiers(QSslSocket*);
170     static void resumeSocketNotifiers(QSslSocket*);
171     // ### The 2 methods below should be made member methods once the QSslContext class is made public
172     static void checkSettingSslContext(QSslSocket*, QSharedPointer<QSslContext>);
173     static QSharedPointer<QSslContext> sslContext(QSslSocket *socket);
174     bool isPaused() const;
175     bool bind(const QHostAddress &address, quint16, QAbstractSocket::BindMode) override;
176     void _q_connectedSlot();
177     void _q_hostFoundSlot();
178     void _q_disconnectedSlot();
179     void _q_stateChangedSlot(QAbstractSocket::SocketState);
180     void _q_errorSlot(QAbstractSocket::SocketError);
181     void _q_readyReadSlot();
182     void _q_channelReadyReadSlot(int);
183     void _q_bytesWrittenSlot(qint64);
184     void _q_channelBytesWrittenSlot(int, qint64);
185     void _q_readChannelFinishedSlot();
186     void _q_flushWriteBuffer();
187     void _q_flushReadBuffer();
188     void _q_resumeImplementation();
189 #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !QT_CONFIG(schannel)
190     virtual void _q_caRootLoaded(QSslCertificate,QSslCertificate) = 0;
191 #endif
192 
193     static QList<QByteArray> unixRootCertDirectories(); // used also by QSslContext
194 
195     virtual qint64 peek(char *data, qint64 maxSize) override;
196     virtual QByteArray peek(qint64 maxSize) override;
197     qint64 skip(qint64 maxSize) override;
198     bool flush() override;
199 
200     // Platform specific functions
201     virtual void startClientEncryption() = 0;
202     virtual void startServerEncryption() = 0;
203     virtual void transmit() = 0;
204     virtual void disconnectFromHost() = 0;
205     virtual void disconnected() = 0;
206     virtual QSslCipher sessionCipher() const = 0;
207     virtual QSsl::SslProtocol sessionProtocol() const = 0;
208     virtual void continueHandshake() = 0;
209 
210     Q_AUTOTEST_EXPORT static bool rootCertOnDemandLoadingSupported();
211 
212 private:
213     static bool ensureLibraryLoaded();
214     static void ensureCiphersAndCertsLoaded();
215 #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
216     static QList<QByteArray> fetchSslCertificateData();
217 #endif
218 
219     static bool s_libraryLoaded;
220     static bool s_loadedCiphersAndCerts;
221 protected:
222     bool verifyErrorsHaveBeenIgnored();
223     bool paused;
224     bool flushTriggered;
225     bool systemOrSslErrorDetected = false;
226     QVector<QOcspResponse> ocspResponses;
227     bool fetchAuthorityInformation = false;
228 };
229 
230 #if QT_CONFIG(securetransport) || QT_CONFIG(schannel)
231 // Implemented in qsslsocket_qt.cpp
232 QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase);
233 #endif
234 
235 QT_END_NAMESPACE
236 
237 #endif
238