Changeset View
Changeset View
Standalone View
Standalone View
src/core/tcpslavebase.cpp
Show All 25 Lines | |||||
26 | 26 | | |||
27 | #include "tcpslavebase.h" | 27 | #include "tcpslavebase.h" | ||
28 | #include "kiocoredebug.h" | 28 | #include "kiocoredebug.h" | ||
29 | 29 | | |||
30 | #include <kconfiggroup.h> | 30 | #include <kconfiggroup.h> | ||
31 | #include <ksslcertificatemanager.h> | 31 | #include <ksslcertificatemanager.h> | ||
32 | #include <ksslsettings.h> | 32 | #include <ksslsettings.h> | ||
33 | #include <klocalizedstring.h> | 33 | #include <klocalizedstring.h> | ||
34 | #include <ktcpsocket.h> | 34 | | ||
35 | #include <QSslCipher> | ||||
36 | #include <QSslSocket> | ||||
35 | 37 | | |||
36 | #include <QDBusConnection> | 38 | #include <QDBusConnection> | ||
37 | 39 | | |||
38 | using namespace KIO; | 40 | using namespace KIO; | ||
39 | //using namespace KNetwork; | 41 | //using namespace KNetwork; | ||
40 | 42 | | |||
41 | namespace KIO | 43 | namespace KIO | ||
42 | { | 44 | { | ||
Show All 37 Lines | |||||
80 | public: | 82 | public: | ||
81 | explicit TcpSlaveBasePrivate(TCPSlaveBase *qq) | 83 | explicit TcpSlaveBasePrivate(TCPSlaveBase *qq) | ||
82 | : q(qq) | 84 | : q(qq) | ||
83 | {} | 85 | {} | ||
84 | 86 | | |||
85 | void setSslMetaData() | 87 | void setSslMetaData() | ||
86 | { | 88 | { | ||
87 | sslMetaData.insert(QStringLiteral("ssl_in_use"), QStringLiteral("TRUE")); | 89 | sslMetaData.insert(QStringLiteral("ssl_in_use"), QStringLiteral("TRUE")); | ||
88 | KSslCipher cipher = socket.sessionCipher(); | 90 | QSslCipher cipher = socket.sessionCipher(); | ||
89 | sslMetaData.insert(QStringLiteral("ssl_protocol_version"), socket.negotiatedSslVersionName()); | 91 | sslMetaData.insert(QStringLiteral("ssl_protocol_version"), cipher.protocolString()); | ||
90 | const QString sslCipher = | 92 | sslMetaData.insert(QStringLiteral("ssl_cipher"), cipher.name()); | ||
91 | cipher.encryptionMethod() + QLatin1Char('\n') + | | |||
92 | cipher.authenticationMethod() + QLatin1Char('\n') + | | |||
93 | cipher.keyExchangeMethod() + QLatin1Char('\n') + | | |||
94 | cipher.digestMethod(); | | |||
95 | sslMetaData.insert(QStringLiteral("ssl_cipher"), sslCipher); | | |||
96 | sslMetaData.insert(QStringLiteral("ssl_cipher_name"), cipher.name()); | | |||
97 | sslMetaData.insert(QStringLiteral("ssl_cipher_used_bits"), QString::number(cipher.usedBits())); | 93 | sslMetaData.insert(QStringLiteral("ssl_cipher_used_bits"), QString::number(cipher.usedBits())); | ||
98 | sslMetaData.insert(QStringLiteral("ssl_cipher_bits"), QString::number(cipher.supportedBits())); | 94 | sslMetaData.insert(QStringLiteral("ssl_cipher_bits"), QString::number(cipher.supportedBits())); | ||
99 | sslMetaData.insert(QStringLiteral("ssl_peer_ip"), ip); | 95 | sslMetaData.insert(QStringLiteral("ssl_peer_ip"), ip); | ||
100 | 96 | | |||
101 | const QList<QSslCertificate> peerCertificateChain = socket.peerCertificateChain(); | 97 | const QList<QSslCertificate> peerCertificateChain = socket.peerCertificateChain(); | ||
102 | // try to fill in the blanks, i.e. missing certificates, and just assume that | 98 | // try to fill in the blanks, i.e. missing certificates, and just assume that | ||
103 | // those belong to the peer (==website or similar) certificate. | 99 | // those belong to the peer (==website or similar) certificate. | ||
104 | for (int i = 0; i < sslErrors.count(); i++) { | 100 | for (int i = 0; i < sslErrors.count(); i++) { | ||
105 | if (sslErrors[i].certificate().isNull()) { | 101 | if (sslErrors[i].certificate().isNull()) { | ||
106 | sslErrors[i] = QSslError(sslErrors[i].sslError().error(), peerCertificateChain[0]); | 102 | sslErrors[i] = QSslError(sslErrors[i].error(), peerCertificateChain[0]); | ||
107 | } | 103 | } | ||
108 | } | 104 | } | ||
109 | 105 | | |||
110 | QString errorStr; | 106 | QString errorStr; | ||
111 | // encode the two-dimensional numeric error list using '\n' and '\t' as outer and inner separators | 107 | // encode the two-dimensional numeric error list using '\n' and '\t' as outer and inner separators | ||
112 | for (const QSslCertificate &cert : peerCertificateChain ) { | 108 | for (const QSslCertificate &cert : peerCertificateChain ) { | ||
113 | for (const KSslError &error : qAsConst(sslErrors)) { | 109 | for (const KSslError &error : qAsConst(sslErrors)) { | ||
114 | if (error.certificate() == cert) { | 110 | if (error.certificate() == cert) { | ||
Show All 27 Lines | |||||
142 | void sendSslMetaData() | 138 | void sendSslMetaData() | ||
143 | { | 139 | { | ||
144 | MetaData::ConstIterator it = sslMetaData.constBegin(); | 140 | MetaData::ConstIterator it = sslMetaData.constBegin(); | ||
145 | for (; it != sslMetaData.constEnd(); ++it) { | 141 | for (; it != sslMetaData.constEnd(); ++it) { | ||
146 | q->setMetaData(it.key(), it.value()); | 142 | q->setMetaData(it.key(), it.value()); | ||
147 | } | 143 | } | ||
148 | } | 144 | } | ||
149 | 145 | | |||
150 | SslResult startTLSInternal(KTcpSocket::SslVersion sslVersion, | 146 | SslResult startTLSInternal(QSsl::SslProtocol sslVersion, | ||
151 | int waitForEncryptedTimeout = -1); | 147 | int waitForEncryptedTimeout = -1); | ||
152 | 148 | | |||
153 | TCPSlaveBase * const q; | 149 | TCPSlaveBase * const q; | ||
154 | 150 | | |||
155 | bool isBlocking; | 151 | bool isBlocking; | ||
156 | 152 | | |||
157 | KTcpSocket socket; | 153 | QSslSocket socket; | ||
158 | 154 | | |||
159 | QString host; | 155 | QString host; | ||
160 | QString ip; | 156 | QString ip; | ||
161 | quint16 port; | 157 | quint16 port; | ||
162 | QByteArray serviceName; | 158 | QByteArray serviceName; | ||
163 | 159 | | |||
164 | KSSLSettings sslSettings; | 160 | KSSLSettings sslSettings; | ||
165 | bool usingSSL; | 161 | bool usingSSL; | ||
166 | bool autoSSL; | 162 | bool autoSSL; | ||
167 | bool sslNoUi; // If true, we just drop the connection silently | 163 | bool sslNoUi; // If true, we just drop the connection silently | ||
168 | // if SSL certificate check fails in some way. | 164 | // if SSL certificate check fails in some way. | ||
169 | QList<KSslError> sslErrors; | 165 | QList<QSslError> sslErrors; | ||
170 | 166 | | |||
171 | MetaData sslMetaData; | 167 | MetaData sslMetaData; | ||
172 | }; | 168 | }; | ||
173 | 169 | | |||
174 | //### uh, is this a good idea?? | 170 | //### uh, is this a good idea?? | ||
175 | QIODevice *TCPSlaveBase::socket() const | 171 | QIODevice *TCPSlaveBase::socket() const | ||
176 | { | 172 | { | ||
177 | return &d->socket; | 173 | return &d->socket; | ||
Show All 39 Lines | 212 | } else { | |||
217 | // ### I don't know how to make sure that all data does get written at some point | 213 | // ### I don't know how to make sure that all data does get written at some point | ||
218 | // without doing it now. There is no event loop to do it behind the scenes. | 214 | // without doing it now. There is no event loop to do it behind the scenes. | ||
219 | // Polling in the dispatch() loop? Something timeout based? | 215 | // Polling in the dispatch() loop? Something timeout based? | ||
220 | success = d->socket.waitForBytesWritten(0); | 216 | success = d->socket.waitForBytesWritten(0); | ||
221 | } | 217 | } | ||
222 | 218 | | |||
223 | d->socket.flush(); //this is supposed to get the data on the wire faster | 219 | d->socket.flush(); //this is supposed to get the data on the wire faster | ||
224 | 220 | | |||
225 | if (d->socket.state() != KTcpSocket::ConnectedState || !success) { | 221 | if (d->socket.state() != QAbstractSocket::ConnectedState || !success) { | ||
226 | /*qDebug() << "Write failed, will return -1! Socket error is" | 222 | /*qDebug() << "Write failed, will return -1! Socket error is" | ||
227 | << d->socket.error() << ", Socket state is" << d->socket.state() | 223 | << d->socket.error() << ", Socket state is" << d->socket.state() | ||
228 | << "Return value of waitForBytesWritten() is" << success;*/ | 224 | << "Return value of waitForBytesWritten() is" << success;*/ | ||
229 | return -1; | 225 | return -1; | ||
230 | } | 226 | } | ||
231 | 227 | | |||
232 | return written; | 228 | return written; | ||
233 | } | 229 | } | ||
234 | 230 | | |||
235 | ssize_t TCPSlaveBase::read(char *data, ssize_t len) | 231 | ssize_t TCPSlaveBase::read(char *data, ssize_t len) | ||
236 | { | 232 | { | ||
237 | if (d->usingSSL && (d->socket.encryptionMode() != KTcpSocket::SslClientMode)) { | 233 | if (d->usingSSL && (d->socket.mode() != QSslSocket::SslClientMode)) { | ||
238 | d->clearSslMetaData(); | 234 | d->clearSslMetaData(); | ||
239 | //qDebug() << "lost SSL connection."; | 235 | //qDebug() << "lost SSL connection."; | ||
240 | return -1; | 236 | return -1; | ||
241 | } | 237 | } | ||
242 | 238 | | |||
243 | if (!d->socket.bytesAvailable()) { | 239 | if (!d->socket.bytesAvailable()) { | ||
244 | const int timeout = d->isBlocking ? -1 : (readTimeout() * 1000); | 240 | const int timeout = d->isBlocking ? -1 : (readTimeout() * 1000); | ||
245 | d->socket.waitForReadyRead(timeout); | 241 | d->socket.waitForReadyRead(timeout); | ||
246 | } | 242 | } | ||
247 | #if 0 | 243 | #if 0 | ||
248 | // Do not do this because its only benefit is to cause a nasty side effect | 244 | // Do not do this because its only benefit is to cause a nasty side effect | ||
249 | // upstream in Qt. See BR# 260769. | 245 | // upstream in Qt. See BR# 260769. | ||
250 | else if (d->socket.encryptionMode() != KTcpSocket::SslClientMode || | 246 | else if (d->socket.mode() != QSslSocket::SslClientMode || | ||
251 | QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy) { | 247 | QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy) { | ||
252 | // we only do this when it doesn't trigger Qt socket bugs. When it doesn't break anything | 248 | // we only do this when it doesn't trigger Qt socket bugs. When it doesn't break anything | ||
253 | // it seems to help performance. | 249 | // it seems to help performance. | ||
254 | d->socket.waitForReadyRead(0); | 250 | d->socket.waitForReadyRead(0); | ||
255 | } | 251 | } | ||
256 | #endif | 252 | #endif | ||
257 | return d->socket.read(data, len); | 253 | return d->socket.read(data, len); | ||
258 | } | 254 | } | ||
259 | 255 | | |||
260 | ssize_t TCPSlaveBase::readLine(char *data, ssize_t len) | 256 | ssize_t TCPSlaveBase::readLine(char *data, ssize_t len) | ||
261 | { | 257 | { | ||
262 | if (d->usingSSL && (d->socket.encryptionMode() != KTcpSocket::SslClientMode)) { | 258 | if (d->usingSSL && (d->socket.mode() != QSslSocket::SslClientMode)) { | ||
263 | d->clearSslMetaData(); | 259 | d->clearSslMetaData(); | ||
264 | //qDebug() << "lost SSL connection."; | 260 | //qDebug() << "lost SSL connection."; | ||
265 | return -1; | 261 | return -1; | ||
266 | } | 262 | } | ||
267 | 263 | | |||
268 | const int timeout = (d->isBlocking ? -1 : (readTimeout() * 1000)); | 264 | const int timeout = (d->isBlocking ? -1 : (readTimeout() * 1000)); | ||
269 | ssize_t readTotal = 0; | 265 | ssize_t readTotal = 0; | ||
270 | do { | 266 | do { | ||
271 | if (!d->socket.bytesAvailable()) { | 267 | if (!d->socket.bytesAvailable()) { | ||
272 | d->socket.waitForReadyRead(timeout); | 268 | d->socket.waitForReadyRead(timeout); | ||
273 | } | 269 | } | ||
274 | ssize_t readStep = d->socket.readLine(&data[readTotal], len - readTotal); | 270 | ssize_t readStep = d->socket.readLine(&data[readTotal], len - readTotal); | ||
275 | if (readStep == -1 || (readStep == 0 && d->socket.state() != KTcpSocket::ConnectedState)) { | 271 | if (readStep == -1 || (readStep == 0 && d->socket.state() != QAbstractSocket::ConnectedState)) { | ||
276 | return -1; | 272 | return -1; | ||
277 | } | 273 | } | ||
278 | readTotal += readStep; | 274 | readTotal += readStep; | ||
279 | } while (readTotal == 0 || data[readTotal - 1] != '\n'); | 275 | } while (readTotal == 0 || data[readTotal - 1] != '\n'); | ||
280 | 276 | | |||
281 | return readTotal; | 277 | return readTotal; | ||
282 | } | 278 | } | ||
283 | 279 | | |||
Show All 14 Lines | |||||
298 | int TCPSlaveBase::connectToHost(const QString &host, quint16 port, QString *errorString) | 294 | int TCPSlaveBase::connectToHost(const QString &host, quint16 port, QString *errorString) | ||
299 | { | 295 | { | ||
300 | d->clearSslMetaData(); //We have separate connection and SSL setup phases | 296 | d->clearSslMetaData(); //We have separate connection and SSL setup phases | ||
301 | 297 | | |||
302 | if (errorString) { | 298 | if (errorString) { | ||
303 | errorString->clear(); // clear prior error messages. | 299 | errorString->clear(); // clear prior error messages. | ||
304 | } | 300 | } | ||
305 | 301 | | |||
306 | d->socket.setVerificationPeerName(host); // Used for ssl certificate verification (SNI) | 302 | d->socket.setPeerVerifyName(host); // Used for ssl certificate verification (SNI) | ||
307 | 303 | | |||
308 | // - leaving SSL - warn before we even connect | 304 | // - leaving SSL - warn before we even connect | ||
309 | //### see if it makes sense to move this into the HTTP ioslave which is the only | 305 | //### see if it makes sense to move this into the HTTP ioslave which is the only | ||
310 | // user. | 306 | // user. | ||
311 | if (metaData(QStringLiteral("main_frame_request")) == QLatin1String("TRUE") //### this looks *really* unreliable | 307 | if (metaData(QStringLiteral("main_frame_request")) == QLatin1String("TRUE") //### this looks *really* unreliable | ||
312 | && metaData(QStringLiteral("ssl_activate_warnings")) == QLatin1String("TRUE") | 308 | && metaData(QStringLiteral("ssl_activate_warnings")) == QLatin1String("TRUE") | ||
313 | && metaData(QStringLiteral("ssl_was_in_use")) == QLatin1String("TRUE") | 309 | && metaData(QStringLiteral("ssl_was_in_use")) == QLatin1String("TRUE") | ||
314 | && !d->autoSSL) { | 310 | && !d->autoSSL) { | ||
Show All 24 Lines | |||||
339 | 335 | | |||
340 | d->socket.connectToHost(host, port); | 336 | d->socket.connectToHost(host, port); | ||
341 | /*const bool connectOk = */d->socket.waitForConnected(timeout > -1 ? timeout : -1); | 337 | /*const bool connectOk = */d->socket.waitForConnected(timeout > -1 ? timeout : -1); | ||
342 | 338 | | |||
343 | /*qDebug() << "Socket: state=" << d->socket.state() | 339 | /*qDebug() << "Socket: state=" << d->socket.state() | ||
344 | << ", error=" << d->socket.error() | 340 | << ", error=" << d->socket.error() | ||
345 | << ", connected?" << connectOk;*/ | 341 | << ", connected?" << connectOk;*/ | ||
346 | 342 | | |||
347 | if (d->socket.state() != KTcpSocket::ConnectedState) { | 343 | if (d->socket.state() != QAbstractSocket::ConnectedState) { | ||
348 | if (errorString) { | 344 | if (errorString) { | ||
349 | *errorString = host + QLatin1String(": ") + d->socket.errorString(); | 345 | *errorString = host + QLatin1String(": ") + d->socket.errorString(); | ||
350 | } | 346 | } | ||
351 | switch (d->socket.error()) { | 347 | switch (d->socket.error()) { | ||
352 | case KTcpSocket::UnsupportedSocketOperationError: | 348 | case QAbstractSocket::UnsupportedSocketOperationError: | ||
353 | return ERR_UNSUPPORTED_ACTION; | 349 | return ERR_UNSUPPORTED_ACTION; | ||
354 | case KTcpSocket::RemoteHostClosedError: | 350 | case QAbstractSocket::RemoteHostClosedError: | ||
355 | return ERR_CONNECTION_BROKEN; | 351 | return ERR_CONNECTION_BROKEN; | ||
356 | case KTcpSocket::SocketTimeoutError: | 352 | case QAbstractSocket::SocketTimeoutError: | ||
357 | return ERR_SERVER_TIMEOUT; | 353 | return ERR_SERVER_TIMEOUT; | ||
358 | case KTcpSocket::HostNotFoundError: | 354 | case QAbstractSocket::HostNotFoundError: | ||
359 | return ERR_UNKNOWN_HOST; | 355 | return ERR_UNKNOWN_HOST; | ||
360 | default: | 356 | default: | ||
361 | return ERR_CANNOT_CONNECT; | 357 | return ERR_CANNOT_CONNECT; | ||
362 | } | 358 | } | ||
363 | } | 359 | } | ||
364 | 360 | | |||
365 | //### check for proxyAuthenticationRequiredError | 361 | //### check for proxyAuthenticationRequiredError | ||
366 | 362 | | |||
367 | d->ip = d->socket.peerAddress().toString(); | 363 | d->ip = d->socket.peerAddress().toString(); | ||
368 | d->port = d->socket.peerPort(); | 364 | d->port = d->socket.peerPort(); | ||
369 | 365 | | |||
370 | if (d->autoSSL) { | 366 | if (d->autoSSL) { | ||
371 | const SslResult res = d->startTLSInternal(KTcpSocket::SecureProtocols, timeout); | 367 | const SslResult res = d->startTLSInternal(QSsl::SecureProtocols, timeout); | ||
372 | 368 | | |||
373 | if (res & ResultFailed) { | 369 | if (res & ResultFailed) { | ||
374 | if (errorString) { | 370 | if (errorString) { | ||
375 | *errorString = i18nc("%1 is a host name", "%1: SSL negotiation failed", host); | 371 | *errorString = i18nc("%1 is a host name", "%1: SSL negotiation failed", host); | ||
376 | } | 372 | } | ||
377 | return ERR_CANNOT_CONNECT; | 373 | return ERR_CANNOT_CONNECT; | ||
378 | } | 374 | } | ||
379 | } | 375 | } | ||
380 | return 0; | 376 | return 0; | ||
381 | } | 377 | } | ||
382 | 378 | | |||
383 | void TCPSlaveBase::disconnectFromHost() | 379 | void TCPSlaveBase::disconnectFromHost() | ||
384 | { | 380 | { | ||
385 | //qDebug(); | 381 | //qDebug(); | ||
386 | d->host.clear(); | 382 | d->host.clear(); | ||
387 | d->ip.clear(); | 383 | d->ip.clear(); | ||
388 | d->usingSSL = false; | 384 | d->usingSSL = false; | ||
389 | 385 | | |||
390 | if (d->socket.state() == KTcpSocket::UnconnectedState) { | 386 | if (d->socket.state() == QAbstractSocket::UnconnectedState) { | ||
391 | // discard incoming data - the remote host might have disconnected us in the meantime | 387 | // discard incoming data - the remote host might have disconnected us in the meantime | ||
392 | // but the visible effect of disconnectFromHost() should stay the same. | 388 | // but the visible effect of disconnectFromHost() should stay the same. | ||
393 | d->socket.close(); | 389 | d->socket.close(); | ||
394 | return; | 390 | return; | ||
395 | } | 391 | } | ||
396 | 392 | | |||
397 | //### maybe save a session for reuse on SSL shutdown if and when QSslSocket | 393 | //### maybe save a session for reuse on SSL shutdown if and when QSslSocket | ||
398 | // does that. QCA::TLS can do it apparently but that is not enough if | 394 | // does that. QCA::TLS can do it apparently but that is not enough if | ||
399 | // we want to present that as KDE API. Not a big loss in any case. | 395 | // we want to present that as KDE API. Not a big loss in any case. | ||
400 | d->socket.disconnectFromHost(); | 396 | d->socket.disconnectFromHost(); | ||
401 | if (d->socket.state() != KTcpSocket::UnconnectedState) { | 397 | if (d->socket.state() != QAbstractSocket::UnconnectedState) { | ||
402 | d->socket.waitForDisconnected(-1); // wait for unsent data to be sent | 398 | d->socket.waitForDisconnected(-1); // wait for unsent data to be sent | ||
403 | } | 399 | } | ||
404 | d->socket.close(); //whatever that means on a socket | 400 | d->socket.close(); //whatever that means on a socket | ||
405 | } | 401 | } | ||
406 | 402 | | |||
407 | bool TCPSlaveBase::isAutoSsl() const | 403 | bool TCPSlaveBase::isAutoSsl() const | ||
408 | { | 404 | { | ||
409 | return d->autoSSL; | 405 | return d->autoSSL; | ||
Show All 14 Lines | 419 | { | |||
424 | return d->socket.atEnd(); | 420 | return d->socket.atEnd(); | ||
425 | } | 421 | } | ||
426 | 422 | | |||
427 | bool TCPSlaveBase::startSsl() | 423 | bool TCPSlaveBase::startSsl() | ||
428 | { | 424 | { | ||
429 | if (d->usingSSL) { | 425 | if (d->usingSSL) { | ||
430 | return false; | 426 | return false; | ||
431 | } | 427 | } | ||
432 | return d->startTLSInternal(KTcpSocket::SecureProtocols) & ResultOk; | 428 | return d->startTLSInternal(QSsl::SecureProtocols) & ResultOk; | ||
433 | } | 429 | } | ||
434 | 430 | | |||
435 | TCPSlaveBase::SslResult TCPSlaveBase::TcpSlaveBasePrivate::startTLSInternal(KTcpSocket::SslVersion version, | 431 | TCPSlaveBase::SslResult TCPSlaveBase::TcpSlaveBasePrivate::startTLSInternal(QSsl::SslProtocol sslVersion, | ||
436 | int waitForEncryptedTimeout) | 432 | int waitForEncryptedTimeout) | ||
437 | { | 433 | { | ||
438 | q->selectClientCertificate(); | 434 | q->selectClientCertificate(); | ||
439 | 435 | | |||
440 | //setMetaData("ssl_session_id", d->kssl->session()->toString()); | 436 | //setMetaData("ssl_session_id", d->kssl->session()->toString()); | ||
441 | //### we don't support session reuse for now... | 437 | //### we don't support session reuse for now... | ||
442 | usingSSL = true; | 438 | usingSSL = true; | ||
443 | 439 | | |||
444 | // Set the SSL version to use... | 440 | // Set the SSL protocol version to use... | ||
445 | socket.setAdvertisedSslVersion(version); | 441 | socket.setProtocol(sslVersion); | ||
446 | 442 | | |||
447 | /* Usually ignoreSslErrors() would be called in the slot invoked by the sslErrors() | 443 | /* Usually ignoreSslErrors() would be called in the slot invoked by the sslErrors() | ||
448 | signal but that would mess up the flow of control. We will check for errors | 444 | signal but that would mess up the flow of control. We will check for errors | ||
449 | anyway to decide if we want to continue connecting. Otherwise ignoreSslErrors() | 445 | anyway to decide if we want to continue connecting. Otherwise ignoreSslErrors() | ||
450 | before connecting would be very insecure. */ | 446 | before connecting would be very insecure. */ | ||
451 | socket.ignoreSslErrors(); | 447 | socket.ignoreSslErrors(); | ||
452 | socket.startClientEncryption(); | 448 | socket.startClientEncryption(); | ||
453 | const bool encryptionStarted = socket.waitForEncrypted(waitForEncryptedTimeout); | 449 | const bool encryptionStarted = socket.waitForEncrypted(waitForEncryptedTimeout); | ||
454 | 450 | | |||
455 | //Set metadata, among other things for the "SSL Details" dialog | 451 | //Set metadata, among other things for the "SSL Details" dialog | ||
456 | KSslCipher cipher = socket.sessionCipher(); | 452 | QSslCipher cipher = socket.sessionCipher(); | ||
457 | 453 | | |||
458 | if (!encryptionStarted || socket.encryptionMode() != KTcpSocket::SslClientMode | 454 | if (!encryptionStarted || socket.mode() != QSslSocket::SslClientMode | ||
459 | || cipher.isNull() || cipher.usedBits() == 0 || socket.peerCertificateChain().isEmpty()) { | 455 | || cipher.isNull() || cipher.usedBits() == 0 || socket.peerCertificateChain().isEmpty()) { | ||
460 | usingSSL = false; | 456 | usingSSL = false; | ||
461 | clearSslMetaData(); | 457 | clearSslMetaData(); | ||
462 | /*qDebug() << "Initial SSL handshake failed. encryptionStarted is" | 458 | /*qDebug() << "Initial SSL handshake failed. encryptionStarted is" | ||
463 | << encryptionStarted << ", cipher.isNull() is" << cipher.isNull() | 459 | << encryptionStarted << ", cipher.isNull() is" << cipher.isNull() | ||
464 | << ", cipher.usedBits() is" << cipher.usedBits() | 460 | << ", cipher.usedBits() is" << cipher.usedBits() | ||
465 | << ", length of certificate chain is" << socket.peerCertificateChain().count() | 461 | << ", length of certificate chain is" << socket.peerCertificateChain().count() | ||
466 | << ", the socket says:" << socket.errorString() | 462 | << ", the socket says:" << socket.errorString() | ||
467 | << "and the list of SSL errors contains" | 463 | << "and the list of SSL errors contains" | ||
468 | << socket.sslErrors().count() << "items.";*/ | 464 | << socket.sslErrors().count() << "items.";*/ | ||
469 | /*Q_FOREACH(const KSslError& sslError, socket.sslErrors()) { | 465 | /*for (const QSslError &sslError : socket.sslErrors()) { | ||
470 | qDebug() << "SSL ERROR: (" << sslError.error() << ")" << sslError.errorString(); | 466 | qDebug() << "SSL ERROR: (" << sslError.error() << ")" << sslError.errorString(); | ||
471 | }*/ | 467 | }*/ | ||
472 | return ResultFailed | ResultFailedEarly; | 468 | return ResultFailed | ResultFailedEarly; | ||
473 | } | 469 | } | ||
474 | 470 | | |||
475 | /*qDebug() << "Cipher info - " | 471 | /*qDebug() << "Cipher info - " | ||
476 | << " advertised SSL protocol version" << socket.advertisedSslVersion() | 472 | << " advertised SSL protocol version" << socket.protocol() | ||
477 | << " negotiated SSL protocol version" << socket.negotiatedSslVersion() | 473 | << " negotiated SSL protocol version" << socket.sessionProtocol() | ||
478 | << " authenticationMethod:" << cipher.authenticationMethod() | 474 | << " authenticationMethod:" << cipher.authenticationMethod() | ||
479 | << " encryptionMethod:" << cipher.encryptionMethod() | 475 | << " encryptionMethod:" << cipher.encryptionMethod() | ||
480 | << " keyExchangeMethod:" << cipher.keyExchangeMethod() | 476 | << " keyExchangeMethod:" << cipher.keyExchangeMethod() | ||
481 | << " name:" << cipher.name() | 477 | << " name:" << cipher.name() | ||
482 | << " supportedBits:" << cipher.supportedBits() | 478 | << " supportedBits:" << cipher.supportedBits() | ||
483 | << " usedBits:" << cipher.usedBits();*/ | 479 | << " usedBits:" << cipher.usedBits();*/ | ||
484 | 480 | | |||
485 | sslErrors = socket.sslErrors(); | 481 | sslErrors = socket.sslErrors(); | ||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Line(s) | 711 | { | |||
716 | d->sslNoUi = hasMetaData(QStringLiteral("ssl_no_ui")) && (metaData(QStringLiteral("ssl_no_ui")) != QLatin1String("FALSE")); | 712 | d->sslNoUi = hasMetaData(QStringLiteral("ssl_no_ui")) && (metaData(QStringLiteral("ssl_no_ui")) != QLatin1String("FALSE")); | ||
717 | 713 | | |||
718 | if (d->sslErrors.isEmpty()) { | 714 | if (d->sslErrors.isEmpty()) { | ||
719 | return ResultOk; | 715 | return ResultOk; | ||
720 | } else if (d->sslNoUi) { | 716 | } else if (d->sslNoUi) { | ||
721 | return ResultFailed; | 717 | return ResultFailed; | ||
722 | } | 718 | } | ||
723 | 719 | | |||
724 | QList<KSslError> fatalErrors = KSslCertificateManager::nonIgnorableErrors(d->sslErrors); | 720 | const QList<QSslError> fatalErrors = KSslCertificateManager::nonIgnorableErrors(d->sslErrors); | ||
725 | if (!fatalErrors.isEmpty()) { | 721 | if (!fatalErrors.isEmpty()) { | ||
726 | //TODO message "sorry, fatal error, you can't override it" | 722 | //TODO message "sorry, fatal error, you can't override it" | ||
727 | return ResultFailed; | 723 | return ResultFailed; | ||
728 | } | 724 | } | ||
729 | QList<QSslCertificate> peerCertificationChain = d->socket.peerCertificateChain(); | 725 | QList<QSslCertificate> peerCertificationChain = d->socket.peerCertificateChain(); | ||
730 | KSslCertificateManager *const cm = KSslCertificateManager::self(); | 726 | KSslCertificateManager *const cm = KSslCertificateManager::self(); | ||
731 | KSslCertificateRule rule = cm->rule(peerCertificationChain.first(), d->host); | 727 | KSslCertificateRule rule = cm->rule(peerCertificationChain.first(), d->host); | ||
732 | 728 | | |||
733 | // remove previously seen and acknowledged errors | 729 | // remove previously seen and acknowledged errors | ||
734 | QList<KSslError> remainingErrors = rule.filterErrors(d->sslErrors); | 730 | const QList<QSslError> remainingErrors = rule.filterErrors(d->sslErrors); | ||
735 | if (remainingErrors.isEmpty()) { | 731 | if (remainingErrors.isEmpty()) { | ||
736 | //qDebug() << "Error list empty after removing errors to be ignored. Continuing."; | 732 | //qDebug() << "Error list empty after removing errors to be ignored. Continuing."; | ||
737 | return ResultOk | ResultOverridden; | 733 | return ResultOk | ResultOverridden; | ||
738 | } | 734 | } | ||
739 | 735 | | |||
740 | //### We don't ask to permanently reject the certificate | 736 | //### We don't ask to permanently reject the certificate | ||
741 | 737 | | |||
742 | QString message = i18n("The server failed the authenticity check (%1).\n\n", d->host); | 738 | QString message = i18n("The server failed the authenticity check (%1).\n\n", d->host); | ||
743 | for (const KSslError &err : qAsConst(d->sslErrors)) { | 739 | for (const QSslError &err : qAsConst(d->sslErrors)) { | ||
744 | message += err.errorString() + QLatin1Char('\n'); | 740 | message += err.errorString() + QLatin1Char('\n'); | ||
745 | } | 741 | } | ||
746 | message = message.trimmed(); | 742 | message = message.trimmed(); | ||
747 | 743 | | |||
748 | int msgResult; | 744 | int msgResult; | ||
749 | QDateTime ruleExpiry = QDateTime::currentDateTime(); | 745 | QDateTime ruleExpiry = QDateTime::currentDateTime(); | ||
750 | do { | 746 | do { | ||
751 | msgResult = messageBox(WarningYesNoCancel, message, | 747 | msgResult = messageBox(WarningYesNoCancel, message, | ||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Line(s) | 827 | } else { // Child frame | |||
900 | } | 896 | } | ||
901 | } | 897 | } | ||
902 | } | 898 | } | ||
903 | #endif //#if 0 | 899 | #endif //#if 0 | ||
904 | } | 900 | } | ||
905 | 901 | | |||
906 | bool TCPSlaveBase::isConnected() const | 902 | bool TCPSlaveBase::isConnected() const | ||
907 | { | 903 | { | ||
908 | //QSslSocket::isValid() and therefore KTcpSocket::isValid() are shady... | 904 | // QSslSocket::isValid() is shady... | ||
909 | return d->socket.state() == KTcpSocket::ConnectedState; | 905 | return d->socket.state() == QAbstractSocket::ConnectedState; | ||
910 | } | 906 | } | ||
911 | 907 | | |||
912 | bool TCPSlaveBase::waitForResponse(int t) | 908 | bool TCPSlaveBase::waitForResponse(int t) | ||
913 | { | 909 | { | ||
914 | if (d->socket.bytesAvailable()) { | 910 | if (d->socket.bytesAvailable()) { | ||
915 | return true; | 911 | return true; | ||
916 | } | 912 | } | ||
917 | return d->socket.waitForReadyRead(t * 1000); | 913 | return d->socket.waitForReadyRead(t * 1000); | ||
Show All 19 Lines |