File indexing completed on 2023-10-03 03:20:03

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2007, 2008 Andreas Hartmetz <ahartmetz@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "ktcpsocket.h"
0009 #include "kiocoredebug.h"
0010 #include "ksslerror_p.h"
0011 
0012 #include <KLocalizedString>
0013 #include <ksslcertificatemanager.h>
0014 
0015 #include <QAbstractSocket>
0016 #include <QAuthenticator>
0017 #include <QHostAddress>
0018 #include <QNetworkProxy>
0019 #include <QSslCipher>
0020 #include <QSslKey>
0021 #include <QUrl>
0022 
0023 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 65)
0024 
0025 static KTcpSocket::SslVersion kSslVersionFromQ(QSsl::SslProtocol protocol)
0026 {
0027     switch (protocol) {
0028     case QSsl::TlsV1_0:
0029         return KTcpSocket::TlsV1;
0030     case QSsl::TlsV1_1:
0031         return KTcpSocket::TlsV1_1;
0032     case QSsl::TlsV1_2:
0033         return KTcpSocket::TlsV1_2;
0034     case QSsl::TlsV1_3:
0035         return KTcpSocket::TlsV1_3;
0036     case QSsl::AnyProtocol:
0037         return KTcpSocket::AnySslVersion;
0038     case QSsl::SecureProtocols:
0039         return KTcpSocket::SecureProtocols;
0040     default:
0041         return KTcpSocket::UnknownSslVersion;
0042     }
0043 }
0044 
0045 static QSsl::SslProtocol qSslProtocolFromK(KTcpSocket::SslVersion sslVersion)
0046 {
0047     // ### this lowlevel bit-banging is a little dangerous and a likely source of bugs
0048     if (sslVersion == KTcpSocket::AnySslVersion) {
0049         return QSsl::AnyProtocol;
0050     }
0051     // does it contain any valid protocol?
0052     KTcpSocket::SslVersions validVersions(KTcpSocket::TlsV1);
0053     validVersions |= KTcpSocket::TlsV1_1;
0054     validVersions |= KTcpSocket::TlsV1_2;
0055     validVersions |= KTcpSocket::TlsV1_3;
0056     validVersions |= KTcpSocket::SecureProtocols;
0057 
0058     if (!(sslVersion & validVersions)) {
0059         return QSsl::UnknownProtocol;
0060     }
0061 
0062     switch (sslVersion) {
0063     case KTcpSocket::TlsV1_0:
0064         return QSsl::TlsV1_0;
0065     case KTcpSocket::TlsV1_1:
0066         return QSsl::TlsV1_1;
0067     case KTcpSocket::TlsV1_2:
0068         return QSsl::TlsV1_2;
0069     case KTcpSocket::TlsV1_3:
0070         return QSsl::TlsV1_3;
0071     case KTcpSocket::SecureProtocols:
0072         return QSsl::SecureProtocols;
0073 
0074     default:
0075         // QSslSocket doesn't really take arbitrary combinations. It's one or all.
0076         return QSsl::AnyProtocol;
0077     }
0078 }
0079 
0080 static QString protocolString(QSsl::SslProtocol protocol)
0081 {
0082     switch (protocol) {
0083     case QSsl::TlsV1_0:
0084         return QStringLiteral("TLSv1.0");
0085     case QSsl::TlsV1_1:
0086         return QStringLiteral("TLSv1.1");
0087     case QSsl::TlsV1_2:
0088         return QStringLiteral("TLSv1.2");
0089     case QSsl::TlsV1_3:
0090         return QStringLiteral("TLSv1.3");
0091     default:
0092         return QStringLiteral("Unknown");
0093         ;
0094     }
0095 }
0096 
0097 // cipher class converter KSslCipher -> QSslCipher
0098 class CipherCc
0099 {
0100 public:
0101     CipherCc()
0102     {
0103         const QList<QSslCipher> list = QSslConfiguration::supportedCiphers();
0104         for (const QSslCipher &c : list) {
0105             allCiphers.insert(c.name(), c);
0106         }
0107     }
0108 
0109     QSslCipher converted(const KSslCipher &ksc)
0110     {
0111         return allCiphers.value(ksc.name());
0112     }
0113 
0114 private:
0115     QHash<QString, QSslCipher> allCiphers;
0116 };
0117 
0118 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 65)
0119 KSslError::Error KSslErrorPrivate::errorFromQSslError(QSslError::SslError e)
0120 {
0121     switch (e) {
0122     case QSslError::NoError:
0123         return KSslError::NoError;
0124     case QSslError::UnableToGetLocalIssuerCertificate:
0125     case QSslError::InvalidCaCertificate:
0126         return KSslError::InvalidCertificateAuthorityCertificate;
0127     case QSslError::InvalidNotBeforeField:
0128     case QSslError::InvalidNotAfterField:
0129     case QSslError::CertificateNotYetValid:
0130     case QSslError::CertificateExpired:
0131         return KSslError::ExpiredCertificate;
0132     case QSslError::UnableToDecodeIssuerPublicKey:
0133     case QSslError::SubjectIssuerMismatch:
0134     case QSslError::AuthorityIssuerSerialNumberMismatch:
0135         return KSslError::InvalidCertificate;
0136     case QSslError::SelfSignedCertificate:
0137     case QSslError::SelfSignedCertificateInChain:
0138         return KSslError::SelfSignedCertificate;
0139     case QSslError::CertificateRevoked:
0140         return KSslError::RevokedCertificate;
0141     case QSslError::InvalidPurpose:
0142         return KSslError::InvalidCertificatePurpose;
0143     case QSslError::CertificateUntrusted:
0144         return KSslError::UntrustedCertificate;
0145     case QSslError::CertificateRejected:
0146         return KSslError::RejectedCertificate;
0147     case QSslError::NoPeerCertificate:
0148         return KSslError::NoPeerCertificate;
0149     case QSslError::HostNameMismatch:
0150         return KSslError::HostNameMismatch;
0151     case QSslError::UnableToVerifyFirstCertificate:
0152     case QSslError::UnableToDecryptCertificateSignature:
0153     case QSslError::UnableToGetIssuerCertificate:
0154     case QSslError::CertificateSignatureFailed:
0155         return KSslError::CertificateSignatureFailed;
0156     case QSslError::PathLengthExceeded:
0157         return KSslError::PathLengthExceeded;
0158     case QSslError::UnspecifiedError:
0159     case QSslError::NoSslSupport:
0160     default:
0161         return KSslError::UnknownError;
0162     }
0163 }
0164 
0165 QSslError::SslError KSslErrorPrivate::errorFromKSslError(KSslError::Error e)
0166 {
0167     switch (e) {
0168     case KSslError::NoError:
0169         return QSslError::NoError;
0170     case KSslError::InvalidCertificateAuthorityCertificate:
0171         return QSslError::InvalidCaCertificate;
0172     case KSslError::InvalidCertificate:
0173         return QSslError::UnableToDecodeIssuerPublicKey;
0174     case KSslError::CertificateSignatureFailed:
0175         return QSslError::CertificateSignatureFailed;
0176     case KSslError::SelfSignedCertificate:
0177         return QSslError::SelfSignedCertificate;
0178     case KSslError::ExpiredCertificate:
0179         return QSslError::CertificateExpired;
0180     case KSslError::RevokedCertificate:
0181         return QSslError::CertificateRevoked;
0182     case KSslError::InvalidCertificatePurpose:
0183         return QSslError::InvalidPurpose;
0184     case KSslError::RejectedCertificate:
0185         return QSslError::CertificateRejected;
0186     case KSslError::UntrustedCertificate:
0187         return QSslError::CertificateUntrusted;
0188     case KSslError::NoPeerCertificate:
0189         return QSslError::NoPeerCertificate;
0190     case KSslError::HostNameMismatch:
0191         return QSslError::HostNameMismatch;
0192     case KSslError::PathLengthExceeded:
0193         return QSslError::PathLengthExceeded;
0194     case KSslError::UnknownError:
0195     default:
0196         return QSslError::UnspecifiedError;
0197     }
0198 }
0199 
0200 KSslError::KSslError(Error errorCode, const QSslCertificate &certificate)
0201     : d(new KSslErrorPrivate())
0202 {
0203     d->error = QSslError(d->errorFromKSslError(errorCode), certificate);
0204 }
0205 
0206 KSslError::KSslError(const QSslError &other)
0207     : d(new KSslErrorPrivate())
0208 {
0209     d->error = other;
0210 }
0211 
0212 KSslError::KSslError(const KSslError &other)
0213     : d(new KSslErrorPrivate())
0214 {
0215     *d = *other.d;
0216 }
0217 
0218 KSslError::~KSslError() = default;
0219 
0220 KSslError &KSslError::operator=(const KSslError &other)
0221 {
0222     *d = *other.d;
0223     return *this;
0224 }
0225 
0226 KSslError::Error KSslError::error() const
0227 {
0228     return KSslErrorPrivate::errorFromQSslError(d->error.error());
0229 }
0230 
0231 QString KSslError::errorString() const
0232 {
0233     return d->error.errorString();
0234 }
0235 
0236 QSslCertificate KSslError::certificate() const
0237 {
0238     return d->error.certificate();
0239 }
0240 
0241 QSslError KSslError::sslError() const
0242 {
0243     return d->error;
0244 }
0245 #endif
0246 
0247 class KTcpSocketPrivate
0248 {
0249 public:
0250     explicit KTcpSocketPrivate(KTcpSocket *qq)
0251         : q(qq)
0252         , certificatesLoaded(false)
0253         , emittedReadyRead(false)
0254     {
0255         // create the instance, which sets Qt's static internal cert set to empty.
0256         KSslCertificateManager::self();
0257     }
0258 
0259     KTcpSocket::State state(QAbstractSocket::SocketState s)
0260     {
0261         switch (s) {
0262         case QAbstractSocket::UnconnectedState:
0263             return KTcpSocket::UnconnectedState;
0264         case QAbstractSocket::HostLookupState:
0265             return KTcpSocket::HostLookupState;
0266         case QAbstractSocket::ConnectingState:
0267             return KTcpSocket::ConnectingState;
0268         case QAbstractSocket::ConnectedState:
0269             return KTcpSocket::ConnectedState;
0270         case QAbstractSocket::ClosingState:
0271             return KTcpSocket::ClosingState;
0272         case QAbstractSocket::BoundState:
0273         case QAbstractSocket::ListeningState:
0274         // ### these two are not relevant as long as this can't be a server socket
0275         default:
0276             return KTcpSocket::UnconnectedState; // the closest to "error"
0277         }
0278     }
0279 
0280     KTcpSocket::EncryptionMode encryptionMode(QSslSocket::SslMode mode)
0281     {
0282         switch (mode) {
0283         case QSslSocket::SslClientMode:
0284             return KTcpSocket::SslClientMode;
0285         case QSslSocket::SslServerMode:
0286             return KTcpSocket::SslServerMode;
0287         default:
0288             return KTcpSocket::UnencryptedMode;
0289         }
0290     }
0291 
0292     KTcpSocket::Error errorFromAbsSocket(QAbstractSocket::SocketError e)
0293     {
0294         switch (e) {
0295         case QAbstractSocket::ConnectionRefusedError:
0296             return KTcpSocket::ConnectionRefusedError;
0297         case QAbstractSocket::RemoteHostClosedError:
0298             return KTcpSocket::RemoteHostClosedError;
0299         case QAbstractSocket::HostNotFoundError:
0300             return KTcpSocket::HostNotFoundError;
0301         case QAbstractSocket::SocketAccessError:
0302             return KTcpSocket::SocketAccessError;
0303         case QAbstractSocket::SocketResourceError:
0304             return KTcpSocket::SocketResourceError;
0305         case QAbstractSocket::SocketTimeoutError:
0306             return KTcpSocket::SocketTimeoutError;
0307         case QAbstractSocket::NetworkError:
0308             return KTcpSocket::NetworkError;
0309         case QAbstractSocket::UnsupportedSocketOperationError:
0310             return KTcpSocket::UnsupportedSocketOperationError;
0311         case QAbstractSocket::SslHandshakeFailedError:
0312             return KTcpSocket::SslHandshakeFailedError;
0313         case QAbstractSocket::DatagramTooLargeError:
0314         // we don't do UDP
0315         case QAbstractSocket::AddressInUseError:
0316         case QAbstractSocket::SocketAddressNotAvailableError:
0317         // ### own values if/when we ever get server socket support
0318         case QAbstractSocket::ProxyAuthenticationRequiredError:
0319         // ### maybe we need an enum value for this
0320         case QAbstractSocket::UnknownSocketError:
0321         default:
0322             return KTcpSocket::UnknownError;
0323         }
0324     }
0325 
0326     // private slots
0327     void reemitSocketError(QAbstractSocket::SocketError e)
0328     {
0329         q->setErrorString(sock.errorString());
0330         Q_EMIT q->error(errorFromAbsSocket(e));
0331     }
0332 
0333     void reemitSslErrors(const QList<QSslError> &errors)
0334     {
0335         q->setErrorString(sock.errorString());
0336         q->showSslErrors(); // H4X
0337         QList<KSslError> kErrors;
0338         kErrors.reserve(errors.size());
0339         for (const QSslError &e : errors) {
0340             kErrors.append(KSslError(e));
0341         }
0342         Q_EMIT q->sslErrors(kErrors);
0343     }
0344 
0345     void reemitStateChanged(QAbstractSocket::SocketState s)
0346     {
0347         Q_EMIT q->stateChanged(state(s));
0348     }
0349 
0350     void reemitModeChanged(QSslSocket::SslMode m)
0351     {
0352         Q_EMIT q->encryptionModeChanged(encryptionMode(m));
0353     }
0354 
0355     // This method is needed because we might emit readyRead() due to this QIODevice
0356     // having some data buffered, so we need to care about blocking, too.
0357     // ### useless ATM as readyRead() now just calls d->sock.readyRead().
0358     void reemitReadyRead()
0359     {
0360         if (!emittedReadyRead) {
0361             emittedReadyRead = true;
0362             Q_EMIT q->readyRead();
0363             emittedReadyRead = false;
0364         }
0365     }
0366 
0367     void maybeLoadCertificates()
0368     {
0369         if (!certificatesLoaded) {
0370             q->setCaCertificates(KSslCertificateManager::self()->caCertificates());
0371         }
0372     }
0373 
0374     KTcpSocket *const q;
0375     bool certificatesLoaded;
0376     bool emittedReadyRead;
0377     QSslSocket sock;
0378     QList<KSslCipher> ciphers;
0379     KTcpSocket::SslVersion advertisedSslVersion;
0380     CipherCc ccc;
0381 };
0382 
0383 KTcpSocket::KTcpSocket(QObject *parent)
0384     : QIODevice(parent)
0385     , d(new KTcpSocketPrivate(this))
0386 {
0387     d->advertisedSslVersion = SslV3;
0388 
0389     connect(&d->sock, &QIODevice::aboutToClose, this, &QIODevice::aboutToClose);
0390     connect(&d->sock, &QIODevice::bytesWritten, this, &QIODevice::bytesWritten);
0391     connect(&d->sock, &QSslSocket::encryptedBytesWritten, this, &KTcpSocket::encryptedBytesWritten);
0392     connect(&d->sock, &QSslSocket::readyRead, this, [this]() {
0393         d->reemitReadyRead();
0394     });
0395     connect(&d->sock, &QAbstractSocket::connected, this, &KTcpSocket::connected);
0396     connect(&d->sock, &QSslSocket::encrypted, this, &KTcpSocket::encrypted);
0397     connect(&d->sock, &QAbstractSocket::disconnected, this, &KTcpSocket::disconnected);
0398 #ifndef QT_NO_NETWORKPROXY
0399     connect(&d->sock, &QAbstractSocket::proxyAuthenticationRequired, this, &KTcpSocket::proxyAuthenticationRequired);
0400 #endif
0401 
0402     connect(&d->sock, &QSslSocket::errorOccurred, this, [this](QAbstractSocket::SocketError err) {
0403         d->reemitSocketError(err);
0404     });
0405 
0406     connect(&d->sock, qOverload<const QList<QSslError> &>(&QSslSocket::sslErrors), this, [this](const QList<QSslError> &errorList) {
0407         d->reemitSslErrors(errorList);
0408     });
0409     connect(&d->sock, &QAbstractSocket::hostFound, this, &KTcpSocket::hostFound);
0410     connect(&d->sock, &QSslSocket::stateChanged, this, [this](QAbstractSocket::SocketState state) {
0411         d->reemitStateChanged(state);
0412     });
0413     connect(&d->sock, &QSslSocket::modeChanged, this, [this](QSslSocket::SslMode mode) {
0414         d->reemitModeChanged(mode);
0415     });
0416 }
0417 
0418 KTcpSocket::~KTcpSocket()
0419 {
0420     // Cleanup before ~KTcpSocketPrivate does that with d being null (on libc++)
0421     // (stateChanged will be emitted, and the above slots use 'd')
0422     abort();
0423 }
0424 
0425 ////////////////////////////// (mostly) virtuals from QIODevice
0426 
0427 bool KTcpSocket::atEnd() const
0428 {
0429     return d->sock.atEnd() && QIODevice::atEnd();
0430 }
0431 
0432 qint64 KTcpSocket::bytesAvailable() const
0433 {
0434     return d->sock.bytesAvailable() + QIODevice::bytesAvailable();
0435 }
0436 
0437 qint64 KTcpSocket::bytesToWrite() const
0438 {
0439     return d->sock.bytesToWrite();
0440 }
0441 
0442 bool KTcpSocket::canReadLine() const
0443 {
0444     return d->sock.canReadLine() || QIODevice::canReadLine();
0445 }
0446 
0447 void KTcpSocket::close()
0448 {
0449     d->sock.close();
0450     QIODevice::close();
0451 }
0452 
0453 bool KTcpSocket::isSequential() const
0454 {
0455     return true;
0456 }
0457 
0458 bool KTcpSocket::open(QIODevice::OpenMode open)
0459 {
0460     bool ret = d->sock.open(open);
0461     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0462     return ret;
0463 }
0464 
0465 bool KTcpSocket::waitForBytesWritten(int msecs)
0466 {
0467     return d->sock.waitForBytesWritten(msecs);
0468 }
0469 
0470 bool KTcpSocket::waitForReadyRead(int msecs)
0471 {
0472     return d->sock.waitForReadyRead(msecs);
0473 }
0474 
0475 qint64 KTcpSocket::readData(char *data, qint64 maxSize)
0476 {
0477     return d->sock.read(data, maxSize);
0478 }
0479 
0480 qint64 KTcpSocket::writeData(const char *data, qint64 maxSize)
0481 {
0482     return d->sock.write(data, maxSize);
0483 }
0484 
0485 ////////////////////////////// public methods from QAbstractSocket
0486 
0487 void KTcpSocket::abort()
0488 {
0489     d->sock.abort();
0490 }
0491 
0492 void KTcpSocket::connectToHost(const QString &hostName, quint16 port, ProxyPolicy policy)
0493 {
0494     if (policy == AutoProxy) {
0495         // ###
0496     }
0497     d->sock.connectToHost(hostName, port);
0498     // there are enough layers of buffers between us and the network, and there is a quirk
0499     // in QIODevice that can make it try to readData() twice per read() call if buffered and
0500     // reaData() does not deliver enough data the first time. like when the other side is
0501     // simply not sending any more data...
0502     // this can *apparently* lead to long delays sometimes which stalls applications.
0503     // do not want.
0504     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0505 }
0506 
0507 void KTcpSocket::connectToHost(const QHostAddress &hostAddress, quint16 port, ProxyPolicy policy)
0508 {
0509     if (policy == AutoProxy) {
0510         // ###
0511     }
0512     d->sock.connectToHost(hostAddress, port);
0513     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0514 }
0515 
0516 void KTcpSocket::connectToHost(const QUrl &url, ProxyPolicy policy)
0517 {
0518     if (policy == AutoProxy) {
0519         // ###
0520     }
0521     d->sock.connectToHost(url.host(), url.port());
0522     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0523 }
0524 
0525 void KTcpSocket::disconnectFromHost()
0526 {
0527     d->sock.disconnectFromHost();
0528     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0529 }
0530 
0531 KTcpSocket::Error KTcpSocket::error() const
0532 {
0533     const auto networkError = d->sock.error();
0534     return d->errorFromAbsSocket(networkError);
0535 }
0536 
0537 QList<KSslError> KTcpSocket::sslErrors() const
0538 {
0539     // ### pretty slow; also consider throwing out duplicate error codes. We may get
0540     //     duplicates even though there were none in the original list because KSslError
0541     //     has a smallest common denominator range of SSL error codes.
0542     const auto qsslErrors = d->sock.sslHandshakeErrors();
0543     QList<KSslError> ret;
0544     ret.reserve(qsslErrors.size());
0545     for (const QSslError &e : qsslErrors) {
0546         ret.append(KSslError(e));
0547     }
0548     return ret;
0549 }
0550 
0551 bool KTcpSocket::flush()
0552 {
0553     return d->sock.flush();
0554 }
0555 
0556 bool KTcpSocket::isValid() const
0557 {
0558     return d->sock.isValid();
0559 }
0560 
0561 QHostAddress KTcpSocket::localAddress() const
0562 {
0563     return d->sock.localAddress();
0564 }
0565 
0566 QHostAddress KTcpSocket::peerAddress() const
0567 {
0568     return d->sock.peerAddress();
0569 }
0570 
0571 QString KTcpSocket::peerName() const
0572 {
0573     return d->sock.peerName();
0574 }
0575 
0576 quint16 KTcpSocket::peerPort() const
0577 {
0578     return d->sock.peerPort();
0579 }
0580 
0581 #ifndef QT_NO_NETWORKPROXY
0582 QNetworkProxy KTcpSocket::proxy() const
0583 {
0584     return d->sock.proxy();
0585 }
0586 #endif
0587 
0588 qint64 KTcpSocket::readBufferSize() const
0589 {
0590     return d->sock.readBufferSize();
0591 }
0592 
0593 #ifndef QT_NO_NETWORKPROXY
0594 void KTcpSocket::setProxy(const QNetworkProxy &proxy)
0595 {
0596     d->sock.setProxy(proxy);
0597 }
0598 #endif
0599 
0600 void KTcpSocket::setReadBufferSize(qint64 size)
0601 {
0602     d->sock.setReadBufferSize(size);
0603 }
0604 
0605 KTcpSocket::State KTcpSocket::state() const
0606 {
0607     return d->state(d->sock.state());
0608 }
0609 
0610 bool KTcpSocket::waitForConnected(int msecs)
0611 {
0612     bool ret = d->sock.waitForConnected(msecs);
0613     if (!ret) {
0614         setErrorString(d->sock.errorString());
0615     }
0616     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0617     return ret;
0618 }
0619 
0620 bool KTcpSocket::waitForDisconnected(int msecs)
0621 {
0622     bool ret = d->sock.waitForDisconnected(msecs);
0623     if (!ret) {
0624         setErrorString(d->sock.errorString());
0625     }
0626     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0627     return ret;
0628 }
0629 
0630 ////////////////////////////// public methods from QSslSocket
0631 
0632 void KTcpSocket::addCaCertificate(const QSslCertificate &certificate)
0633 {
0634     d->maybeLoadCertificates();
0635     d->sock.sslConfiguration().addCaCertificate(certificate);
0636 }
0637 
0638 /*
0639 bool KTcpSocket::addCaCertificates(const QString &path, QSsl::EncodingFormat format,
0640                                    QRegExp::PatternSyntax syntax)
0641 {
0642     d->maybeLoadCertificates();
0643     return d->sock.addCaCertificates(path, format, syntax);
0644 }
0645 */
0646 
0647 void KTcpSocket::addCaCertificates(const QList<QSslCertificate> &certificates)
0648 {
0649     d->maybeLoadCertificates();
0650     d->sock.sslConfiguration().addCaCertificates(certificates);
0651 }
0652 
0653 QList<QSslCertificate> KTcpSocket::caCertificates() const
0654 {
0655     d->maybeLoadCertificates();
0656     return d->sock.sslConfiguration().caCertificates();
0657 }
0658 
0659 QList<KSslCipher> KTcpSocket::ciphers() const
0660 {
0661     return d->ciphers;
0662 }
0663 
0664 void KTcpSocket::connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode openMode)
0665 {
0666     d->maybeLoadCertificates();
0667     d->sock.setProtocol(qSslProtocolFromK(d->advertisedSslVersion));
0668     d->sock.connectToHostEncrypted(hostName, port, openMode);
0669     setOpenMode(d->sock.openMode() | QIODevice::Unbuffered);
0670 }
0671 
0672 QSslCertificate KTcpSocket::localCertificate() const
0673 {
0674     return d->sock.localCertificate();
0675 }
0676 
0677 QList<QSslCertificate> KTcpSocket::peerCertificateChain() const
0678 {
0679     return d->sock.peerCertificateChain();
0680 }
0681 
0682 KSslKey KTcpSocket::privateKey() const
0683 {
0684     return KSslKey(d->sock.privateKey());
0685 }
0686 
0687 KSslCipher KTcpSocket::sessionCipher() const
0688 {
0689     return KSslCipher(d->sock.sessionCipher());
0690 }
0691 
0692 void KTcpSocket::setCaCertificates(const QList<QSslCertificate> &certificates)
0693 {
0694     QSslConfiguration configuration = d->sock.sslConfiguration();
0695     configuration.setCaCertificates(certificates);
0696     d->sock.setSslConfiguration(configuration);
0697     d->certificatesLoaded = true;
0698 }
0699 
0700 void KTcpSocket::setCiphers(const QList<KSslCipher> &ciphers)
0701 {
0702     d->ciphers = ciphers;
0703     QList<QSslCipher> cl;
0704     cl.reserve(d->ciphers.size());
0705     for (const KSslCipher &c : ciphers) {
0706         cl.append(d->ccc.converted(c));
0707     }
0708     QSslConfiguration configuration = d->sock.sslConfiguration();
0709     configuration.setCiphers(cl);
0710     d->sock.setSslConfiguration(configuration);
0711 }
0712 
0713 void KTcpSocket::setLocalCertificate(const QSslCertificate &certificate)
0714 {
0715     d->sock.setLocalCertificate(certificate);
0716 }
0717 
0718 void KTcpSocket::setLocalCertificate(const QString &fileName, QSsl::EncodingFormat format)
0719 {
0720     d->sock.setLocalCertificate(fileName, format);
0721 }
0722 
0723 void KTcpSocket::setVerificationPeerName(const QString &hostName)
0724 {
0725     d->sock.setPeerVerifyName(hostName);
0726 }
0727 
0728 void KTcpSocket::setPrivateKey(const KSslKey &key)
0729 {
0730     // We cannot map KSslKey::Algorithm:Dh to anything in QSsl::KeyAlgorithm.
0731     if (key.algorithm() == KSslKey::Dh) {
0732         return;
0733     }
0734 
0735     QSslKey _key(key.toDer(),
0736                  (key.algorithm() == KSslKey::Rsa) ? QSsl::Rsa : QSsl::Dsa,
0737                  QSsl::Der,
0738                  (key.secrecy() == KSslKey::PrivateKey) ? QSsl::PrivateKey : QSsl::PublicKey);
0739 
0740     d->sock.setPrivateKey(_key);
0741 }
0742 
0743 void KTcpSocket::setPrivateKey(const QString &fileName, KSslKey::Algorithm algorithm, QSsl::EncodingFormat format, const QByteArray &passPhrase)
0744 {
0745     // We cannot map KSslKey::Algorithm:Dh to anything in QSsl::KeyAlgorithm.
0746     if (algorithm == KSslKey::Dh) {
0747         return;
0748     }
0749 
0750     d->sock.setPrivateKey(fileName, (algorithm == KSslKey::Rsa) ? QSsl::Rsa : QSsl::Dsa, format, passPhrase);
0751 }
0752 
0753 bool KTcpSocket::waitForEncrypted(int msecs)
0754 {
0755     return d->sock.waitForEncrypted(msecs);
0756 }
0757 
0758 KTcpSocket::EncryptionMode KTcpSocket::encryptionMode() const
0759 {
0760     return d->encryptionMode(d->sock.mode());
0761 }
0762 
0763 QVariant KTcpSocket::socketOption(QAbstractSocket::SocketOption options) const
0764 {
0765     return d->sock.socketOption(options);
0766 }
0767 
0768 void KTcpSocket::setSocketOption(QAbstractSocket::SocketOption options, const QVariant &value)
0769 {
0770     d->sock.setSocketOption(options, value);
0771 }
0772 
0773 QSslConfiguration KTcpSocket::sslConfiguration() const
0774 {
0775     return d->sock.sslConfiguration();
0776 }
0777 
0778 void KTcpSocket::setSslConfiguration(const QSslConfiguration &configuration)
0779 {
0780     d->sock.setSslConfiguration(configuration);
0781 }
0782 
0783 // slot
0784 void KTcpSocket::ignoreSslErrors()
0785 {
0786     d->sock.ignoreSslErrors();
0787 }
0788 
0789 // slot
0790 void KTcpSocket::startClientEncryption()
0791 {
0792     d->maybeLoadCertificates();
0793     d->sock.setProtocol(qSslProtocolFromK(d->advertisedSslVersion));
0794     d->sock.startClientEncryption();
0795 }
0796 
0797 // debugging H4X
0798 void KTcpSocket::showSslErrors()
0799 {
0800     const QList<QSslError> list = d->sock.sslHandshakeErrors();
0801     for (const QSslError &e : list) {
0802         qCDebug(KIO_CORE) << e.errorString();
0803     }
0804 }
0805 
0806 void KTcpSocket::setAdvertisedSslVersion(KTcpSocket::SslVersion version)
0807 {
0808     d->advertisedSslVersion = version;
0809 }
0810 
0811 KTcpSocket::SslVersion KTcpSocket::advertisedSslVersion() const
0812 {
0813     return d->advertisedSslVersion;
0814 }
0815 
0816 KTcpSocket::SslVersion KTcpSocket::negotiatedSslVersion() const
0817 {
0818     if (!d->sock.isEncrypted()) {
0819         return UnknownSslVersion;
0820     }
0821 
0822     return kSslVersionFromQ(d->sock.sessionProtocol());
0823 }
0824 
0825 QString KTcpSocket::negotiatedSslVersionName() const
0826 {
0827     if (!d->sock.isEncrypted()) {
0828         return QString();
0829     }
0830 
0831     return protocolString(d->sock.sessionProtocol());
0832 }
0833 
0834 ////////////////////////////// KSslKey
0835 
0836 class KSslKeyPrivate
0837 {
0838 public:
0839     KSslKey::Algorithm convertAlgorithm(QSsl::KeyAlgorithm a)
0840     {
0841         switch (a) {
0842         case QSsl::Dsa:
0843             return KSslKey::Dsa;
0844         default:
0845             return KSslKey::Rsa;
0846         }
0847     }
0848 
0849     KSslKey::Algorithm algorithm;
0850     KSslKey::KeySecrecy secrecy;
0851     bool isExportable;
0852     QByteArray der;
0853 };
0854 
0855 KSslKey::KSslKey()
0856     : d(new KSslKeyPrivate)
0857 {
0858     d->algorithm = Rsa;
0859     d->secrecy = PublicKey;
0860     d->isExportable = true;
0861 }
0862 
0863 KSslKey::KSslKey(const KSslKey &other)
0864     : d(new KSslKeyPrivate)
0865 {
0866     *d = *other.d;
0867 }
0868 
0869 KSslKey::KSslKey(const QSslKey &qsk)
0870     : d(new KSslKeyPrivate)
0871 {
0872     d->algorithm = d->convertAlgorithm(qsk.algorithm());
0873     d->secrecy = (qsk.type() == QSsl::PrivateKey) ? PrivateKey : PublicKey;
0874     d->isExportable = true;
0875     d->der = qsk.toDer();
0876 }
0877 
0878 KSslKey::~KSslKey() = default;
0879 
0880 KSslKey &KSslKey::operator=(const KSslKey &other)
0881 {
0882     *d = *other.d;
0883     return *this;
0884 }
0885 
0886 KSslKey::Algorithm KSslKey::algorithm() const
0887 {
0888     return d->algorithm;
0889 }
0890 
0891 bool KSslKey::isExportable() const
0892 {
0893     return d->isExportable;
0894 }
0895 
0896 KSslKey::KeySecrecy KSslKey::secrecy() const
0897 {
0898     return d->secrecy;
0899 }
0900 
0901 QByteArray KSslKey::toDer() const
0902 {
0903     return d->der;
0904 }
0905 
0906 ////////////////////////////// KSslCipher
0907 
0908 // nice-to-have: make implicitly shared
0909 class KSslCipherPrivate
0910 {
0911 public:
0912     QString authenticationMethod;
0913     QString encryptionMethod;
0914     QString keyExchangeMethod;
0915     QString name;
0916     bool isNull;
0917     int supportedBits;
0918     int usedBits;
0919 };
0920 
0921 KSslCipher::KSslCipher()
0922     : d(new KSslCipherPrivate)
0923 {
0924     d->isNull = true;
0925     d->supportedBits = 0;
0926     d->usedBits = 0;
0927 }
0928 
0929 KSslCipher::KSslCipher(const KSslCipher &other)
0930     : d(new KSslCipherPrivate)
0931 {
0932     *d = *other.d;
0933 }
0934 
0935 KSslCipher::KSslCipher(const QSslCipher &qsc)
0936     : d(new KSslCipherPrivate)
0937 {
0938     d->authenticationMethod = qsc.authenticationMethod();
0939     d->encryptionMethod = qsc.encryptionMethod();
0940     // Qt likes to append the number of bits (usedBits?) to the algorithm,
0941     // for example "AES(256)". We only want the pure algorithm name, though.
0942     int parenIdx = d->encryptionMethod.indexOf(QLatin1Char('('));
0943     if (parenIdx > 0) {
0944         d->encryptionMethod.truncate(parenIdx);
0945     }
0946     d->keyExchangeMethod = qsc.keyExchangeMethod();
0947     d->name = qsc.name();
0948     d->isNull = qsc.isNull();
0949     d->supportedBits = qsc.supportedBits();
0950     d->usedBits = qsc.usedBits();
0951 }
0952 
0953 KSslCipher::~KSslCipher() = default;
0954 
0955 KSslCipher &KSslCipher::operator=(const KSslCipher &other)
0956 {
0957     *d = *other.d;
0958     return *this;
0959 }
0960 
0961 bool KSslCipher::isNull() const
0962 {
0963     return d->isNull;
0964 }
0965 
0966 QString KSslCipher::authenticationMethod() const
0967 {
0968     return d->authenticationMethod;
0969 }
0970 
0971 QString KSslCipher::encryptionMethod() const
0972 {
0973     return d->encryptionMethod;
0974 }
0975 
0976 QString KSslCipher::keyExchangeMethod() const
0977 {
0978     return d->keyExchangeMethod;
0979 }
0980 
0981 QString KSslCipher::digestMethod() const
0982 {
0983     // ### This is not really backend neutral. It works for OpenSSL and
0984     //     for RFC compliant names, though.
0985     if (d->name.endsWith(QLatin1String("SHA"))) {
0986         return QStringLiteral("SHA-1");
0987     } else if (d->name.endsWith(QLatin1String("MD5"))) {
0988         return QStringLiteral("MD5");
0989     } else {
0990         return QString();
0991     }
0992 }
0993 
0994 QString KSslCipher::name() const
0995 {
0996     return d->name;
0997 }
0998 
0999 int KSslCipher::supportedBits() const
1000 {
1001     return d->supportedBits;
1002 }
1003 
1004 int KSslCipher::usedBits() const
1005 {
1006     return d->usedBits;
1007 }
1008 
1009 // static
1010 QList<KSslCipher> KSslCipher::supportedCiphers()
1011 {
1012     QList<KSslCipher> ret;
1013     const QList<QSslCipher> candidates = QSslConfiguration::supportedCiphers();
1014     ret.reserve(candidates.size());
1015     for (const QSslCipher &c : candidates) {
1016         ret.append(KSslCipher(c));
1017     }
1018     return ret;
1019 }
1020 
1021 #include "moc_ktcpsocket.cpp"
1022 
1023 #endif