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 | const QString sslCipher = | ||
91 | cipher.encryptionMethod() + QLatin1Char('\n') + | 93 | cipher.encryptionMethod() + QLatin1Char('\n') + | ||
92 | cipher.authenticationMethod() + QLatin1Char('\n') + | 94 | cipher.authenticationMethod() + QLatin1Char('\n') + | ||
93 | cipher.keyExchangeMethod() + QLatin1Char('\n') + | 95 | cipher.keyExchangeMethod() + QLatin1Char('\n') + | ||
94 | cipher.digestMethod(); | 96 | cipherDigestMethod(cipher.name()); | ||
95 | sslMetaData.insert(QStringLiteral("ssl_cipher"), sslCipher); | 97 | sslMetaData.insert(QStringLiteral("ssl_cipher"), sslCipher); | ||
96 | sslMetaData.insert(QStringLiteral("ssl_cipher_name"), cipher.name()); | 98 | sslMetaData.insert(QStringLiteral("ssl_cipher_name"), cipher.name()); | ||
97 | sslMetaData.insert(QStringLiteral("ssl_cipher_used_bits"), QString::number(cipher.usedBits())); | 99 | sslMetaData.insert(QStringLiteral("ssl_cipher_used_bits"), QString::number(cipher.usedBits())); | ||
98 | sslMetaData.insert(QStringLiteral("ssl_cipher_bits"), QString::number(cipher.supportedBits())); | 100 | sslMetaData.insert(QStringLiteral("ssl_cipher_bits"), QString::number(cipher.supportedBits())); | ||
99 | sslMetaData.insert(QStringLiteral("ssl_peer_ip"), ip); | 101 | sslMetaData.insert(QStringLiteral("ssl_peer_ip"), ip); | ||
100 | 102 | | |||
101 | const QList<QSslCertificate> peerCertificateChain = socket.peerCertificateChain(); | 103 | const QList<QSslCertificate> peerCertificateChain = socket.peerCertificateChain(); | ||
102 | // try to fill in the blanks, i.e. missing certificates, and just assume that | 104 | // try to fill in the blanks, i.e. missing certificates, and just assume that | ||
103 | // those belong to the peer (==website or similar) certificate. | 105 | // those belong to the peer (==website or similar) certificate. | ||
104 | for (int i = 0; i < sslErrors.count(); i++) { | 106 | for (int i = 0; i < sslErrors.count(); i++) { | ||
105 | if (sslErrors[i].certificate().isNull()) { | 107 | if (sslErrors[i].certificate().isNull()) { | ||
106 | sslErrors[i] = QSslError(sslErrors[i].sslError().error(), peerCertificateChain[0]); | 108 | sslErrors[i] = QSslError(sslErrors[i].error(), peerCertificateChain[0]); | ||
107 | } | 109 | } | ||
108 | } | 110 | } | ||
109 | 111 | | |||
110 | QString errorStr; | 112 | QString errorStr; | ||
111 | // encode the two-dimensional numeric error list using '\n' and '\t' as outer and inner separators | 113 | // encode the two-dimensional numeric error list using '\n' and '\t' as outer and inner separators | ||
112 | for (const QSslCertificate &cert : peerCertificateChain ) { | 114 | for (const QSslCertificate &cert : peerCertificateChain ) { | ||
113 | for (const KSslError &error : qAsConst(sslErrors)) { | 115 | for (const KSslError &error : qAsConst(sslErrors)) { | ||
114 | if (error.certificate() == cert) { | 116 | if (error.certificate() == cert) { | ||
Show All 27 Lines | |||||
142 | void sendSslMetaData() | 144 | void sendSslMetaData() | ||
143 | { | 145 | { | ||
144 | MetaData::ConstIterator it = sslMetaData.constBegin(); | 146 | MetaData::ConstIterator it = sslMetaData.constBegin(); | ||
145 | for (; it != sslMetaData.constEnd(); ++it) { | 147 | for (; it != sslMetaData.constEnd(); ++it) { | ||
146 | q->setMetaData(it.key(), it.value()); | 148 | q->setMetaData(it.key(), it.value()); | ||
147 | } | 149 | } | ||
148 | } | 150 | } | ||
149 | 151 | | |||
150 | SslResult startTLSInternal(KTcpSocket::SslVersion sslVersion, | 152 | QString cipherDigestMethod(const QString &cipherName) const | ||
153 | { | ||||
154 | //### This is not really backend neutral. It works for OpenSSL and | ||||
155 | // for RFC compliant names, though. | ||||
156 | if (cipherName.endsWith(QLatin1String("SHA"))) { | ||||
157 | return QLatin1String("SHA-1"); | ||||
158 | } else if (cipherName.endsWith(QLatin1String("MD5"))) { | ||||
159 | return QLatin1String("MD5"); | ||||
160 | } else { | ||||
161 | return QString(); | ||||
162 | } | ||||
163 | } | ||||
164 | | ||||
165 | SslResult startTLSInternal(QSsl::SslProtocol sslVersion, | ||||
151 | int waitForEncryptedTimeout = -1); | 166 | int waitForEncryptedTimeout = -1); | ||
152 | 167 | | |||
153 | TCPSlaveBase * const q; | 168 | TCPSlaveBase * const q; | ||
154 | 169 | | |||
155 | bool isBlocking; | 170 | bool isBlocking; | ||
156 | 171 | | |||
157 | KTcpSocket socket; | 172 | QSslSocket socket; | ||
158 | 173 | | |||
159 | QString host; | 174 | QString host; | ||
160 | QString ip; | 175 | QString ip; | ||
161 | quint16 port; | 176 | quint16 port; | ||
162 | QByteArray serviceName; | 177 | QByteArray serviceName; | ||
163 | 178 | | |||
164 | KSSLSettings sslSettings; | 179 | KSSLSettings sslSettings; | ||
165 | bool usingSSL; | 180 | bool usingSSL; | ||
166 | bool autoSSL; | 181 | bool autoSSL; | ||
167 | bool sslNoUi; // If true, we just drop the connection silently | 182 | bool sslNoUi; // If true, we just drop the connection silently | ||
168 | // if SSL certificate check fails in some way. | 183 | // if SSL certificate check fails in some way. | ||
169 | QList<KSslError> sslErrors; | 184 | QList<QSslError> sslErrors; | ||
170 | 185 | | |||
171 | MetaData sslMetaData; | 186 | MetaData sslMetaData; | ||
172 | }; | 187 | }; | ||
173 | 188 | | |||
174 | //### uh, is this a good idea?? | 189 | //### uh, is this a good idea?? | ||
175 | QIODevice *TCPSlaveBase::socket() const | 190 | QIODevice *TCPSlaveBase::socket() const | ||
176 | { | 191 | { | ||
177 | return &d->socket; | 192 | return &d->socket; | ||
Show All 39 Lines | 231 | } else { | |||
217 | // ### I don't know how to make sure that all data does get written at some point | 232 | // ### 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. | 233 | // without doing it now. There is no event loop to do it behind the scenes. | ||
219 | // Polling in the dispatch() loop? Something timeout based? | 234 | // Polling in the dispatch() loop? Something timeout based? | ||
220 | success = d->socket.waitForBytesWritten(0); | 235 | success = d->socket.waitForBytesWritten(0); | ||
221 | } | 236 | } | ||
222 | 237 | | |||
223 | d->socket.flush(); //this is supposed to get the data on the wire faster | 238 | d->socket.flush(); //this is supposed to get the data on the wire faster | ||
224 | 239 | | |||
225 | if (d->socket.state() != KTcpSocket::ConnectedState || !success) { | 240 | if (d->socket.state() != QAbstractSocket::ConnectedState || !success) { | ||
226 | /*qDebug() << "Write failed, will return -1! Socket error is" | 241 | /*qDebug() << "Write failed, will return -1! Socket error is" | ||
227 | << d->socket.error() << ", Socket state is" << d->socket.state() | 242 | << d->socket.error() << ", Socket state is" << d->socket.state() | ||
228 | << "Return value of waitForBytesWritten() is" << success;*/ | 243 | << "Return value of waitForBytesWritten() is" << success;*/ | ||
229 | return -1; | 244 | return -1; | ||
230 | } | 245 | } | ||
231 | 246 | | |||
232 | return written; | 247 | return written; | ||
233 | } | 248 | } | ||
234 | 249 | | |||
235 | ssize_t TCPSlaveBase::read(char *data, ssize_t len) | 250 | ssize_t TCPSlaveBase::read(char *data, ssize_t len) | ||
236 | { | 251 | { | ||
237 | if (d->usingSSL && (d->socket.encryptionMode() != KTcpSocket::SslClientMode)) { | 252 | if (d->usingSSL && (d->socket.mode() != QSslSocket::SslClientMode)) { | ||
238 | d->clearSslMetaData(); | 253 | d->clearSslMetaData(); | ||
239 | //qDebug() << "lost SSL connection."; | 254 | //qDebug() << "lost SSL connection."; | ||
240 | return -1; | 255 | return -1; | ||
241 | } | 256 | } | ||
242 | 257 | | |||
243 | if (!d->socket.bytesAvailable()) { | 258 | if (!d->socket.bytesAvailable()) { | ||
244 | const int timeout = d->isBlocking ? -1 : (readTimeout() * 1000); | 259 | const int timeout = d->isBlocking ? -1 : (readTimeout() * 1000); | ||
245 | d->socket.waitForReadyRead(timeout); | 260 | d->socket.waitForReadyRead(timeout); | ||
246 | } | 261 | } | ||
247 | #if 0 | 262 | #if 0 | ||
248 | // Do not do this because its only benefit is to cause a nasty side effect | 263 | // Do not do this because its only benefit is to cause a nasty side effect | ||
249 | // upstream in Qt. See BR# 260769. | 264 | // upstream in Qt. See BR# 260769. | ||
250 | else if (d->socket.encryptionMode() != KTcpSocket::SslClientMode || | 265 | else if (d->socket.mode() != QSslSocket::SslClientMode || | ||
251 | QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy) { | 266 | QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy) { | ||
252 | // we only do this when it doesn't trigger Qt socket bugs. When it doesn't break anything | 267 | // we only do this when it doesn't trigger Qt socket bugs. When it doesn't break anything | ||
253 | // it seems to help performance. | 268 | // it seems to help performance. | ||
254 | d->socket.waitForReadyRead(0); | 269 | d->socket.waitForReadyRead(0); | ||
255 | } | 270 | } | ||
256 | #endif | 271 | #endif | ||
257 | return d->socket.read(data, len); | 272 | return d->socket.read(data, len); | ||
258 | } | 273 | } | ||
259 | 274 | | |||
260 | ssize_t TCPSlaveBase::readLine(char *data, ssize_t len) | 275 | ssize_t TCPSlaveBase::readLine(char *data, ssize_t len) | ||
261 | { | 276 | { | ||
262 | if (d->usingSSL && (d->socket.encryptionMode() != KTcpSocket::SslClientMode)) { | 277 | if (d->usingSSL && (d->socket.mode() != QSslSocket::SslClientMode)) { | ||
263 | d->clearSslMetaData(); | 278 | d->clearSslMetaData(); | ||
264 | //qDebug() << "lost SSL connection."; | 279 | //qDebug() << "lost SSL connection."; | ||
265 | return -1; | 280 | return -1; | ||
266 | } | 281 | } | ||
267 | 282 | | |||
268 | const int timeout = (d->isBlocking ? -1 : (readTimeout() * 1000)); | 283 | const int timeout = (d->isBlocking ? -1 : (readTimeout() * 1000)); | ||
269 | ssize_t readTotal = 0; | 284 | ssize_t readTotal = 0; | ||
270 | do { | 285 | do { | ||
271 | if (!d->socket.bytesAvailable()) { | 286 | if (!d->socket.bytesAvailable()) { | ||
272 | d->socket.waitForReadyRead(timeout); | 287 | d->socket.waitForReadyRead(timeout); | ||
273 | } | 288 | } | ||
274 | ssize_t readStep = d->socket.readLine(&data[readTotal], len - readTotal); | 289 | ssize_t readStep = d->socket.readLine(&data[readTotal], len - readTotal); | ||
275 | if (readStep == -1 || (readStep == 0 && d->socket.state() != KTcpSocket::ConnectedState)) { | 290 | if (readStep == -1 || (readStep == 0 && d->socket.state() != QAbstractSocket::ConnectedState)) { | ||
276 | return -1; | 291 | return -1; | ||
277 | } | 292 | } | ||
278 | readTotal += readStep; | 293 | readTotal += readStep; | ||
279 | } while (readTotal == 0 || data[readTotal - 1] != '\n'); | 294 | } while (readTotal == 0 || data[readTotal - 1] != '\n'); | ||
280 | 295 | | |||
281 | return readTotal; | 296 | return readTotal; | ||
282 | } | 297 | } | ||
283 | 298 | | |||
Show All 14 Lines | |||||
298 | int TCPSlaveBase::connectToHost(const QString &host, quint16 port, QString *errorString) | 313 | int TCPSlaveBase::connectToHost(const QString &host, quint16 port, QString *errorString) | ||
299 | { | 314 | { | ||
300 | d->clearSslMetaData(); //We have separate connection and SSL setup phases | 315 | d->clearSslMetaData(); //We have separate connection and SSL setup phases | ||
301 | 316 | | |||
302 | if (errorString) { | 317 | if (errorString) { | ||
303 | errorString->clear(); // clear prior error messages. | 318 | errorString->clear(); // clear prior error messages. | ||
304 | } | 319 | } | ||
305 | 320 | | |||
306 | d->socket.setVerificationPeerName(host); // Used for ssl certificate verification (SNI) | 321 | d->socket.setPeerVerifyName(host); // Used for ssl certificate verification (SNI) | ||
307 | 322 | | |||
308 | // - leaving SSL - warn before we even connect | 323 | // - leaving SSL - warn before we even connect | ||
309 | //### see if it makes sense to move this into the HTTP ioslave which is the only | 324 | //### see if it makes sense to move this into the HTTP ioslave which is the only | ||
310 | // user. | 325 | // user. | ||
311 | if (metaData(QStringLiteral("main_frame_request")) == QLatin1String("TRUE") //### this looks *really* unreliable | 326 | if (metaData(QStringLiteral("main_frame_request")) == QLatin1String("TRUE") //### this looks *really* unreliable | ||
312 | && metaData(QStringLiteral("ssl_activate_warnings")) == QLatin1String("TRUE") | 327 | && metaData(QStringLiteral("ssl_activate_warnings")) == QLatin1String("TRUE") | ||
313 | && metaData(QStringLiteral("ssl_was_in_use")) == QLatin1String("TRUE") | 328 | && metaData(QStringLiteral("ssl_was_in_use")) == QLatin1String("TRUE") | ||
314 | && !d->autoSSL) { | 329 | && !d->autoSSL) { | ||
Show All 24 Lines | |||||
339 | 354 | | |||
340 | d->socket.connectToHost(host, port); | 355 | d->socket.connectToHost(host, port); | ||
341 | /*const bool connectOk = */d->socket.waitForConnected(timeout > -1 ? timeout : -1); | 356 | /*const bool connectOk = */d->socket.waitForConnected(timeout > -1 ? timeout : -1); | ||
342 | 357 | | |||
343 | /*qDebug() << "Socket: state=" << d->socket.state() | 358 | /*qDebug() << "Socket: state=" << d->socket.state() | ||
344 | << ", error=" << d->socket.error() | 359 | << ", error=" << d->socket.error() | ||
345 | << ", connected?" << connectOk;*/ | 360 | << ", connected?" << connectOk;*/ | ||
346 | 361 | | |||
347 | if (d->socket.state() != KTcpSocket::ConnectedState) { | 362 | if (d->socket.state() != QAbstractSocket::ConnectedState) { | ||
348 | if (errorString) { | 363 | if (errorString) { | ||
349 | *errorString = host + QLatin1String(": ") + d->socket.errorString(); | 364 | *errorString = host + QLatin1String(": ") + d->socket.errorString(); | ||
350 | } | 365 | } | ||
351 | switch (d->socket.error()) { | 366 | switch (d->socket.error()) { | ||
352 | case KTcpSocket::UnsupportedSocketOperationError: | 367 | case QAbstractSocket::UnsupportedSocketOperationError: | ||
353 | return ERR_UNSUPPORTED_ACTION; | 368 | return ERR_UNSUPPORTED_ACTION; | ||
354 | case KTcpSocket::RemoteHostClosedError: | 369 | case QAbstractSocket::RemoteHostClosedError: | ||
355 | return ERR_CONNECTION_BROKEN; | 370 | return ERR_CONNECTION_BROKEN; | ||
356 | case KTcpSocket::SocketTimeoutError: | 371 | case QAbstractSocket::SocketTimeoutError: | ||
357 | return ERR_SERVER_TIMEOUT; | 372 | return ERR_SERVER_TIMEOUT; | ||
358 | case KTcpSocket::HostNotFoundError: | 373 | case QAbstractSocket::HostNotFoundError: | ||
359 | return ERR_UNKNOWN_HOST; | 374 | return ERR_UNKNOWN_HOST; | ||
360 | default: | 375 | default: | ||
361 | return ERR_CANNOT_CONNECT; | 376 | return ERR_CANNOT_CONNECT; | ||
362 | } | 377 | } | ||
363 | } | 378 | } | ||
364 | 379 | | |||
365 | //### check for proxyAuthenticationRequiredError | 380 | //### check for proxyAuthenticationRequiredError | ||
366 | 381 | | |||
367 | d->ip = d->socket.peerAddress().toString(); | 382 | d->ip = d->socket.peerAddress().toString(); | ||
368 | d->port = d->socket.peerPort(); | 383 | d->port = d->socket.peerPort(); | ||
369 | 384 | | |||
370 | if (d->autoSSL) { | 385 | if (d->autoSSL) { | ||
371 | const SslResult res = d->startTLSInternal(KTcpSocket::SecureProtocols, timeout); | 386 | const SslResult res = d->startTLSInternal(QSsl::SecureProtocols, timeout); | ||
372 | 387 | | |||
373 | if (res & ResultFailed) { | 388 | if (res & ResultFailed) { | ||
374 | if (errorString) { | 389 | if (errorString) { | ||
375 | *errorString = i18nc("%1 is a host name", "%1: SSL negotiation failed", host); | 390 | *errorString = i18nc("%1 is a host name", "%1: SSL negotiation failed", host); | ||
376 | } | 391 | } | ||
377 | return ERR_CANNOT_CONNECT; | 392 | return ERR_CANNOT_CONNECT; | ||
378 | } | 393 | } | ||
379 | } | 394 | } | ||
380 | return 0; | 395 | return 0; | ||
381 | } | 396 | } | ||
382 | 397 | | |||
383 | void TCPSlaveBase::disconnectFromHost() | 398 | void TCPSlaveBase::disconnectFromHost() | ||
384 | { | 399 | { | ||
385 | //qDebug(); | 400 | //qDebug(); | ||
386 | d->host.clear(); | 401 | d->host.clear(); | ||
387 | d->ip.clear(); | 402 | d->ip.clear(); | ||
388 | d->usingSSL = false; | 403 | d->usingSSL = false; | ||
389 | 404 | | |||
390 | if (d->socket.state() == KTcpSocket::UnconnectedState) { | 405 | if (d->socket.state() == QAbstractSocket::UnconnectedState) { | ||
391 | // discard incoming data - the remote host might have disconnected us in the meantime | 406 | // discard incoming data - the remote host might have disconnected us in the meantime | ||
392 | // but the visible effect of disconnectFromHost() should stay the same. | 407 | // but the visible effect of disconnectFromHost() should stay the same. | ||
393 | d->socket.close(); | 408 | d->socket.close(); | ||
394 | return; | 409 | return; | ||
395 | } | 410 | } | ||
396 | 411 | | |||
397 | //### maybe save a session for reuse on SSL shutdown if and when QSslSocket | 412 | //### 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 | 413 | // 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. | 414 | // we want to present that as KDE API. Not a big loss in any case. | ||
400 | d->socket.disconnectFromHost(); | 415 | d->socket.disconnectFromHost(); | ||
401 | if (d->socket.state() != KTcpSocket::UnconnectedState) { | 416 | if (d->socket.state() != QAbstractSocket::UnconnectedState) { | ||
402 | d->socket.waitForDisconnected(-1); // wait for unsent data to be sent | 417 | d->socket.waitForDisconnected(-1); // wait for unsent data to be sent | ||
403 | } | 418 | } | ||
404 | d->socket.close(); //whatever that means on a socket | 419 | d->socket.close(); //whatever that means on a socket | ||
405 | } | 420 | } | ||
406 | 421 | | |||
407 | bool TCPSlaveBase::isAutoSsl() const | 422 | bool TCPSlaveBase::isAutoSsl() const | ||
408 | { | 423 | { | ||
409 | return d->autoSSL; | 424 | return d->autoSSL; | ||
Show All 14 Lines | 438 | { | |||
424 | return d->socket.atEnd(); | 439 | return d->socket.atEnd(); | ||
425 | } | 440 | } | ||
426 | 441 | | |||
427 | bool TCPSlaveBase::startSsl() | 442 | bool TCPSlaveBase::startSsl() | ||
428 | { | 443 | { | ||
429 | if (d->usingSSL) { | 444 | if (d->usingSSL) { | ||
430 | return false; | 445 | return false; | ||
431 | } | 446 | } | ||
432 | return d->startTLSInternal(KTcpSocket::SecureProtocols) & ResultOk; | 447 | return d->startTLSInternal(QSsl::SecureProtocols) & ResultOk; | ||
433 | } | 448 | } | ||
434 | 449 | | |||
435 | TCPSlaveBase::SslResult TCPSlaveBase::TcpSlaveBasePrivate::startTLSInternal(KTcpSocket::SslVersion version, | 450 | TCPSlaveBase::SslResult TCPSlaveBase::TcpSlaveBasePrivate::startTLSInternal(QSsl::SslProtocol sslVersion, | ||
436 | int waitForEncryptedTimeout) | 451 | int waitForEncryptedTimeout) | ||
437 | { | 452 | { | ||
438 | q->selectClientCertificate(); | 453 | q->selectClientCertificate(); | ||
439 | 454 | | |||
440 | //setMetaData("ssl_session_id", d->kssl->session()->toString()); | 455 | //setMetaData("ssl_session_id", d->kssl->session()->toString()); | ||
441 | //### we don't support session reuse for now... | 456 | //### we don't support session reuse for now... | ||
442 | usingSSL = true; | 457 | usingSSL = true; | ||
443 | 458 | | |||
444 | // Set the SSL version to use... | 459 | // Set the SSL protocol version to use... | ||
445 | socket.setAdvertisedSslVersion(version); | 460 | socket.setProtocol(sslVersion); | ||
446 | 461 | | |||
447 | /* Usually ignoreSslErrors() would be called in the slot invoked by the sslErrors() | 462 | /* 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 | 463 | 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() | 464 | anyway to decide if we want to continue connecting. Otherwise ignoreSslErrors() | ||
450 | before connecting would be very insecure. */ | 465 | before connecting would be very insecure. */ | ||
451 | socket.ignoreSslErrors(); | 466 | socket.ignoreSslErrors(); | ||
452 | socket.startClientEncryption(); | 467 | socket.startClientEncryption(); | ||
453 | const bool encryptionStarted = socket.waitForEncrypted(waitForEncryptedTimeout); | 468 | const bool encryptionStarted = socket.waitForEncrypted(waitForEncryptedTimeout); | ||
454 | 469 | | |||
455 | //Set metadata, among other things for the "SSL Details" dialog | 470 | //Set metadata, among other things for the "SSL Details" dialog | ||
456 | KSslCipher cipher = socket.sessionCipher(); | 471 | QSslCipher cipher = socket.sessionCipher(); | ||
457 | 472 | | |||
458 | if (!encryptionStarted || socket.encryptionMode() != KTcpSocket::SslClientMode | 473 | if (!encryptionStarted || socket.mode() != QSslSocket::SslClientMode | ||
459 | || cipher.isNull() || cipher.usedBits() == 0 || socket.peerCertificateChain().isEmpty()) { | 474 | || cipher.isNull() || cipher.usedBits() == 0 || socket.peerCertificateChain().isEmpty()) { | ||
460 | usingSSL = false; | 475 | usingSSL = false; | ||
461 | clearSslMetaData(); | 476 | clearSslMetaData(); | ||
462 | /*qDebug() << "Initial SSL handshake failed. encryptionStarted is" | 477 | /*qDebug() << "Initial SSL handshake failed. encryptionStarted is" | ||
463 | << encryptionStarted << ", cipher.isNull() is" << cipher.isNull() | 478 | << encryptionStarted << ", cipher.isNull() is" << cipher.isNull() | ||
464 | << ", cipher.usedBits() is" << cipher.usedBits() | 479 | << ", cipher.usedBits() is" << cipher.usedBits() | ||
465 | << ", length of certificate chain is" << socket.peerCertificateChain().count() | 480 | << ", length of certificate chain is" << socket.peerCertificateChain().count() | ||
466 | << ", the socket says:" << socket.errorString() | 481 | << ", the socket says:" << socket.errorString() | ||
467 | << "and the list of SSL errors contains" | 482 | << "and the list of SSL errors contains" | ||
468 | << socket.sslErrors().count() << "items.";*/ | 483 | << socket.sslErrors().count() << "items.";*/ | ||
469 | /*Q_FOREACH(const KSslError& sslError, socket.sslErrors()) { | 484 | /*for (const QSslError &sslError : socket.sslErrors()) { | ||
470 | qDebug() << "SSL ERROR: (" << sslError.error() << ")" << sslError.errorString(); | 485 | qDebug() << "SSL ERROR: (" << sslError.error() << ")" << sslError.errorString(); | ||
471 | }*/ | 486 | }*/ | ||
472 | return ResultFailed | ResultFailedEarly; | 487 | return ResultFailed | ResultFailedEarly; | ||
473 | } | 488 | } | ||
474 | 489 | | |||
475 | /*qDebug() << "Cipher info - " | 490 | /*qDebug() << "Cipher info - " | ||
476 | << " advertised SSL protocol version" << socket.advertisedSslVersion() | 491 | << " advertised SSL protocol version" << socket.protocol() | ||
477 | << " negotiated SSL protocol version" << socket.negotiatedSslVersion() | 492 | << " negotiated SSL protocol version" << socket.sessionProtocol() | ||
478 | << " authenticationMethod:" << cipher.authenticationMethod() | 493 | << " authenticationMethod:" << cipher.authenticationMethod() | ||
479 | << " encryptionMethod:" << cipher.encryptionMethod() | 494 | << " encryptionMethod:" << cipher.encryptionMethod() | ||
480 | << " keyExchangeMethod:" << cipher.keyExchangeMethod() | 495 | << " keyExchangeMethod:" << cipher.keyExchangeMethod() | ||
481 | << " name:" << cipher.name() | 496 | << " name:" << cipher.name() | ||
482 | << " supportedBits:" << cipher.supportedBits() | 497 | << " supportedBits:" << cipher.supportedBits() | ||
483 | << " usedBits:" << cipher.usedBits();*/ | 498 | << " usedBits:" << cipher.usedBits();*/ | ||
484 | 499 | | |||
485 | sslErrors = socket.sslErrors(); | 500 | sslErrors = socket.sslErrors(); | ||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Line(s) | 730 | { | |||
716 | d->sslNoUi = hasMetaData(QStringLiteral("ssl_no_ui")) && (metaData(QStringLiteral("ssl_no_ui")) != QLatin1String("FALSE")); | 731 | d->sslNoUi = hasMetaData(QStringLiteral("ssl_no_ui")) && (metaData(QStringLiteral("ssl_no_ui")) != QLatin1String("FALSE")); | ||
717 | 732 | | |||
718 | if (d->sslErrors.isEmpty()) { | 733 | if (d->sslErrors.isEmpty()) { | ||
719 | return ResultOk; | 734 | return ResultOk; | ||
720 | } else if (d->sslNoUi) { | 735 | } else if (d->sslNoUi) { | ||
721 | return ResultFailed; | 736 | return ResultFailed; | ||
722 | } | 737 | } | ||
723 | 738 | | |||
724 | QList<KSslError> fatalErrors = KSslCertificateManager::nonIgnorableErrors(d->sslErrors); | 739 | const QList<QSslError> fatalErrors = KSslCertificateManager::nonIgnorableErrors(d->sslErrors); | ||
725 | if (!fatalErrors.isEmpty()) { | 740 | if (!fatalErrors.isEmpty()) { | ||
726 | //TODO message "sorry, fatal error, you can't override it" | 741 | //TODO message "sorry, fatal error, you can't override it" | ||
727 | return ResultFailed; | 742 | return ResultFailed; | ||
728 | } | 743 | } | ||
729 | QList<QSslCertificate> peerCertificationChain = d->socket.peerCertificateChain(); | 744 | QList<QSslCertificate> peerCertificationChain = d->socket.peerCertificateChain(); | ||
730 | KSslCertificateManager *const cm = KSslCertificateManager::self(); | 745 | KSslCertificateManager *const cm = KSslCertificateManager::self(); | ||
731 | KSslCertificateRule rule = cm->rule(peerCertificationChain.first(), d->host); | 746 | KSslCertificateRule rule = cm->rule(peerCertificationChain.first(), d->host); | ||
732 | 747 | | |||
733 | // remove previously seen and acknowledged errors | 748 | // remove previously seen and acknowledged errors | ||
734 | QList<KSslError> remainingErrors = rule.filterErrors(d->sslErrors); | 749 | const QList<QSslError> remainingErrors = rule.filterErrors(d->sslErrors); | ||
735 | if (remainingErrors.isEmpty()) { | 750 | if (remainingErrors.isEmpty()) { | ||
736 | //qDebug() << "Error list empty after removing errors to be ignored. Continuing."; | 751 | //qDebug() << "Error list empty after removing errors to be ignored. Continuing."; | ||
737 | return ResultOk | ResultOverridden; | 752 | return ResultOk | ResultOverridden; | ||
738 | } | 753 | } | ||
739 | 754 | | |||
740 | //### We don't ask to permanently reject the certificate | 755 | //### We don't ask to permanently reject the certificate | ||
741 | 756 | | |||
742 | QString message = i18n("The server failed the authenticity check (%1).\n\n", d->host); | 757 | QString message = i18n("The server failed the authenticity check (%1).\n\n", d->host); | ||
743 | for (const KSslError &err : qAsConst(d->sslErrors)) { | 758 | for (const QSslError &err : qAsConst(d->sslErrors)) { | ||
744 | message += err.errorString() + QLatin1Char('\n'); | 759 | message += err.errorString() + QLatin1Char('\n'); | ||
745 | } | 760 | } | ||
746 | message = message.trimmed(); | 761 | message = message.trimmed(); | ||
747 | 762 | | |||
748 | int msgResult; | 763 | int msgResult; | ||
749 | QDateTime ruleExpiry = QDateTime::currentDateTime(); | 764 | QDateTime ruleExpiry = QDateTime::currentDateTime(); | ||
750 | do { | 765 | do { | ||
751 | msgResult = messageBox(WarningYesNoCancel, message, | 766 | msgResult = messageBox(WarningYesNoCancel, message, | ||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Line(s) | 846 | } else { // Child frame | |||
900 | } | 915 | } | ||
901 | } | 916 | } | ||
902 | } | 917 | } | ||
903 | #endif //#if 0 | 918 | #endif //#if 0 | ||
904 | } | 919 | } | ||
905 | 920 | | |||
906 | bool TCPSlaveBase::isConnected() const | 921 | bool TCPSlaveBase::isConnected() const | ||
907 | { | 922 | { | ||
908 | //QSslSocket::isValid() and therefore KTcpSocket::isValid() are shady... | 923 | // QSslSocket::isValid() is shady... | ||
909 | return d->socket.state() == KTcpSocket::ConnectedState; | 924 | return d->socket.state() == QAbstractSocket::ConnectedState; | ||
910 | } | 925 | } | ||
911 | 926 | | |||
912 | bool TCPSlaveBase::waitForResponse(int t) | 927 | bool TCPSlaveBase::waitForResponse(int t) | ||
913 | { | 928 | { | ||
914 | if (d->socket.bytesAvailable()) { | 929 | if (d->socket.bytesAvailable()) { | ||
915 | return true; | 930 | return true; | ||
916 | } | 931 | } | ||
917 | return d->socket.waitForReadyRead(t * 1000); | 932 | return d->socket.waitForReadyRead(t * 1000); | ||
Show All 19 Lines |