ktcpsocket.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2007, 2008 Andreas Hartmetz <ahartmetz@gmail.com> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "ktcpsocket.h" 00021 #include "ktcpsocket_p.h" 00022 00023 #include <kdebug.h> 00024 #include <kurl.h> 00025 #include <kglobal.h> 00026 #include <ksslcertificatemanager.h> 00027 #include <kstandarddirs.h> 00028 #include <klocale.h> 00029 00030 #include <QtCore/QStringList> 00031 #include <QtNetwork/QSslKey> 00032 #include <QtNetwork/QSslCipher> 00033 #include <QtNetwork/QHostAddress> 00034 #include <QtNetwork/QNetworkProxy> 00035 00036 static KTcpSocket::SslVersion kSslVersionFromQ(QSsl::SslProtocol protocol) 00037 { 00038 switch (protocol) { 00039 case QSsl::SslV2: 00040 return KTcpSocket::SslV2; 00041 case QSsl::SslV3: 00042 return KTcpSocket::SslV3; 00043 case QSsl::TlsV1: 00044 return KTcpSocket::TlsV1; 00045 case QSsl::AnyProtocol: 00046 return KTcpSocket::AnySslVersion; 00047 default: 00048 return KTcpSocket::UnknownSslVersion; 00049 } 00050 } 00051 00052 00053 static QSsl::SslProtocol qSslProtocolFromK(KTcpSocket::SslVersion sslVersion) 00054 { 00055 //### this lowlevel bit-banging is a little dangerous and a likely source of bugs 00056 if (sslVersion == KTcpSocket::AnySslVersion) { 00057 return QSsl::AnyProtocol; 00058 } 00059 //does it contain any valid protocol? 00060 if (!(sslVersion & (KTcpSocket::SslV2 | KTcpSocket::SslV3 | KTcpSocket::TlsV1))) { 00061 return QSsl::UnknownProtocol; 00062 } 00063 00064 switch (sslVersion) { 00065 case KTcpSocket::SslV2: 00066 return QSsl::SslV2; 00067 case KTcpSocket::SslV3: 00068 return QSsl::SslV3; 00069 case KTcpSocket::TlsV1: 00070 return QSsl::TlsV1; 00071 default: 00072 //QSslSocket doesn't really take arbitrary combinations. It's one or all. 00073 return QSsl::AnyProtocol; 00074 } 00075 } 00076 00077 00078 //cipher class converter KSslCipher -> QSslCipher 00079 class CipherCc 00080 { 00081 public: 00082 CipherCc() 00083 { 00084 foreach (const QSslCipher &c, QSslSocket::supportedCiphers()) { 00085 allCiphers.insert(c.name(), c); 00086 } 00087 } 00088 00089 QSslCipher converted(const KSslCipher &ksc) 00090 { 00091 return allCiphers.value(ksc.name()); 00092 } 00093 00094 private: 00095 QHash<QString, QSslCipher> allCiphers; 00096 }; 00097 00098 00099 class KSslErrorPrivate 00100 { 00101 public: 00102 static KSslError::Error errorFromQSslError(QSslError::SslError e) 00103 { 00104 switch (e) { 00105 case QSslError::NoError: 00106 return KSslError::NoError; 00107 case QSslError::UnableToGetLocalIssuerCertificate: 00108 case QSslError::InvalidCaCertificate: 00109 return KSslError::InvalidCertificateAuthorityCertificate; 00110 case QSslError::InvalidNotBeforeField: 00111 case QSslError::InvalidNotAfterField: 00112 case QSslError::CertificateNotYetValid: 00113 case QSslError::CertificateExpired: 00114 return KSslError::ExpiredCertificate; 00115 case QSslError::UnableToDecodeIssuerPublicKey: 00116 case QSslError::SubjectIssuerMismatch: 00117 case QSslError::AuthorityIssuerSerialNumberMismatch: 00118 return KSslError::InvalidCertificate; 00119 case QSslError::SelfSignedCertificate: 00120 case QSslError::SelfSignedCertificateInChain: 00121 return KSslError::SelfSignedCertificate; 00122 case QSslError::CertificateRevoked: 00123 return KSslError::RevokedCertificate; 00124 case QSslError::InvalidPurpose: 00125 return KSslError::InvalidCertificatePurpose; 00126 case QSslError::CertificateUntrusted: 00127 return KSslError::UntrustedCertificate; 00128 case QSslError::CertificateRejected: 00129 return KSslError::RejectedCertificate; 00130 case QSslError::NoPeerCertificate: 00131 return KSslError::NoPeerCertificate; 00132 case QSslError::HostNameMismatch: 00133 return KSslError::HostNameMismatch; 00134 case QSslError::UnableToVerifyFirstCertificate: 00135 case QSslError::UnableToDecryptCertificateSignature: 00136 case QSslError::UnableToGetIssuerCertificate: 00137 case QSslError::CertificateSignatureFailed: 00138 return KSslError::CertificateSignatureFailed; 00139 case QSslError::PathLengthExceeded: 00140 return KSslError::PathLengthExceeded; 00141 case QSslError::UnspecifiedError: 00142 case QSslError::NoSslSupport: 00143 default: 00144 return KSslError::UnknownError; 00145 } 00146 } 00147 00148 static QString errorString(KSslError::Error e) 00149 { 00150 switch (e) { 00151 case KSslError::NoError: 00152 return i18nc("SSL error","No error"); 00153 case KSslError::InvalidCertificateAuthorityCertificate: 00154 return i18nc("SSL error","The certificate authority's certificate is invalid"); 00155 case KSslError::ExpiredCertificate: 00156 return i18nc("SSL error","The certificate has expired"); 00157 case KSslError::InvalidCertificate: 00158 return i18nc("SSL error","The certificate is invalid"); 00159 case KSslError::SelfSignedCertificate: 00160 return i18nc("SSL error","The certificate is not signed by any trusted certificate authority"); 00161 case KSslError::RevokedCertificate: 00162 return i18nc("SSL error","The certificate has been revoked"); 00163 case KSslError::InvalidCertificatePurpose: 00164 return i18nc("SSL error","The certificate is unsuitable for this purpose"); 00165 case KSslError::UntrustedCertificate: 00166 return i18nc("SSL error","The root certificate authority's certificate is not trusted for this purpose"); 00167 case KSslError::RejectedCertificate: 00168 return i18nc("SSL error","The certificate authority's certificate is marked to reject this certificate's purpose"); 00169 case KSslError::NoPeerCertificate: 00170 return i18nc("SSL error","The peer did not present any certificate"); 00171 case KSslError::HostNameMismatch: 00172 return i18nc("SSL error","The certificate does not apply to the given host"); 00173 case KSslError::CertificateSignatureFailed: 00174 return i18nc("SSL error","The certificate cannot be verified for internal reasons"); 00175 case KSslError::PathLengthExceeded: 00176 return i18nc("SSL error","The certificate chain is too long"); 00177 case KSslError::UnknownError: 00178 default: 00179 return i18nc("SSL error","Unknown error"); 00180 } 00181 } 00182 00183 KSslError::Error error; 00184 QSslCertificate certificate; 00185 }; 00186 00187 00188 KSslError::KSslError(Error errorCode, const QSslCertificate &certificate) 00189 : d(new KSslErrorPrivate()) 00190 { 00191 d->error = errorCode; 00192 d->certificate = certificate; 00193 } 00194 00195 00196 KSslError::KSslError(const QSslError &other) 00197 : d(new KSslErrorPrivate()) 00198 { 00199 d->error = KSslErrorPrivate::errorFromQSslError(other.error()); 00200 d->certificate = other.certificate(); 00201 } 00202 00203 00204 KSslError::KSslError(const KSslError &other) 00205 : d(new KSslErrorPrivate()) 00206 { 00207 *d = *other.d; 00208 } 00209 00210 00211 KSslError::~KSslError() 00212 { 00213 delete d; 00214 } 00215 00216 00217 KSslError &KSslError::operator=(const KSslError &other) 00218 { 00219 *d = *other.d; 00220 return *this; 00221 } 00222 00223 00224 KSslError::Error KSslError::error() const 00225 { 00226 return d->error; 00227 } 00228 00229 00230 QString KSslError::errorString() const 00231 { 00232 return KSslErrorPrivate::errorString(d->error); 00233 } 00234 00235 00236 QSslCertificate KSslError::certificate() const 00237 { 00238 return d->certificate; 00239 } 00240 00241 00242 class KTcpSocketPrivate 00243 { 00244 public: 00245 KTcpSocketPrivate(KTcpSocket *qq) 00246 : q(qq), 00247 certificatesLoaded(false), 00248 emittedReadyRead(false) 00249 { 00250 // create the instance, which sets Qt's static internal cert set to empty. 00251 KSslCertificateManager::self(); 00252 } 00253 00254 KTcpSocket::State state(QAbstractSocket::SocketState s) 00255 { 00256 switch (s) { 00257 case QAbstractSocket::UnconnectedState: 00258 return KTcpSocket::UnconnectedState; 00259 case QAbstractSocket::HostLookupState: 00260 return KTcpSocket::HostLookupState; 00261 case QAbstractSocket::ConnectingState: 00262 return KTcpSocket::ConnectingState; 00263 case QAbstractSocket::ConnectedState: 00264 return KTcpSocket::ConnectedState; 00265 case QAbstractSocket::ClosingState: 00266 return KTcpSocket::ClosingState; 00267 case QAbstractSocket::BoundState: 00268 case QAbstractSocket::ListeningState: 00269 //### these two are not relevant as long as this can't be a server socket 00270 default: 00271 return KTcpSocket::UnconnectedState; //the closest to "error" 00272 } 00273 } 00274 00275 KTcpSocket::EncryptionMode encryptionMode(QSslSocket::SslMode mode) 00276 { 00277 switch (mode) { 00278 case QSslSocket::SslClientMode: 00279 return KTcpSocket::SslClientMode; 00280 case QSslSocket::SslServerMode: 00281 return KTcpSocket::SslServerMode; 00282 default: 00283 return KTcpSocket::UnencryptedMode; 00284 } 00285 } 00286 00287 KTcpSocket::Error errorFromAbsSocket(QAbstractSocket::SocketError e) 00288 { 00289 switch (e) { 00290 case QAbstractSocket::ConnectionRefusedError: 00291 return KTcpSocket::ConnectionRefusedError; 00292 case QAbstractSocket::RemoteHostClosedError: 00293 return KTcpSocket::RemoteHostClosedError; 00294 case QAbstractSocket::HostNotFoundError: 00295 return KTcpSocket::HostNotFoundError; 00296 case QAbstractSocket::SocketAccessError: 00297 return KTcpSocket::SocketAccessError; 00298 case QAbstractSocket::SocketResourceError: 00299 return KTcpSocket::SocketResourceError; 00300 case QAbstractSocket::SocketTimeoutError: 00301 return KTcpSocket::SocketTimeoutError; 00302 case QAbstractSocket::NetworkError: 00303 return KTcpSocket::NetworkError; 00304 case QAbstractSocket::UnsupportedSocketOperationError: 00305 return KTcpSocket::UnsupportedSocketOperationError; 00306 case QAbstractSocket::DatagramTooLargeError: 00307 //we don't do UDP 00308 case QAbstractSocket::AddressInUseError: 00309 case QAbstractSocket::SocketAddressNotAvailableError: 00310 //### own values if/when we ever get server socket support 00311 case QAbstractSocket::ProxyAuthenticationRequiredError: 00312 //### maybe we need an enum value for this 00313 case QAbstractSocket::UnknownSocketError: 00314 default: 00315 return KTcpSocket::UnknownError; 00316 } 00317 } 00318 00319 //private slots 00320 void reemitSocketError(QAbstractSocket::SocketError e) 00321 { 00322 emit q->error(errorFromAbsSocket(e)); 00323 } 00324 00325 void reemitSslErrors(const QList<QSslError> &errors) 00326 { 00327 q->showSslErrors(); //H4X 00328 QList<KSslError> kErrors; 00329 foreach (const QSslError &e, errors) { 00330 kErrors.append(KSslError(e)); 00331 } 00332 emit q->sslErrors(kErrors); 00333 } 00334 00335 void reemitStateChanged(QAbstractSocket::SocketState s) 00336 { 00337 emit q->stateChanged(state(s)); 00338 } 00339 00340 void reemitModeChanged(QSslSocket::SslMode m) 00341 { 00342 emit q->encryptionModeChanged(encryptionMode(m)); 00343 } 00344 00345 // This method is needed because we might emit readyRead() due to this QIODevice 00346 // having some data buffered, so we need to care about blocking, too. 00347 //### useless ATM as readyRead() now just calls d->sock.readyRead(). 00348 void reemitReadyRead() 00349 { 00350 if (!emittedReadyRead) { 00351 emittedReadyRead = true; 00352 emit q->readyRead(); 00353 emittedReadyRead = false; 00354 } 00355 } 00356 00357 void maybeLoadCertificates() 00358 { 00359 if (!certificatesLoaded) { 00360 sock.setCaCertificates(KSslCertificateManager::self()->caCertificates()); 00361 certificatesLoaded = true; 00362 } 00363 } 00364 00365 KTcpSocket *const q; 00366 bool certificatesLoaded; 00367 bool emittedReadyRead; 00368 QSslSocket sock; 00369 QList<KSslCipher> ciphers; 00370 KTcpSocket::SslVersion advertisedSslVersion; 00371 CipherCc ccc; 00372 }; 00373 00374 00375 KTcpSocket::KTcpSocket(QObject *parent) 00376 : QIODevice(parent), 00377 d(new KTcpSocketPrivate(this)) 00378 { 00379 d->advertisedSslVersion = SslV3; 00380 00381 connect(&d->sock, SIGNAL(aboutToClose()), this, SIGNAL(aboutToClose())); 00382 connect(&d->sock, SIGNAL(bytesWritten(qint64)), this, SIGNAL(bytesWritten(qint64))); 00383 connect(&d->sock, SIGNAL(encryptedBytesWritten(qint64)), this, SIGNAL(encryptedBytesWritten(qint64))); 00384 connect(&d->sock, SIGNAL(readyRead()), this, SLOT(reemitReadyRead())); 00385 connect(&d->sock, SIGNAL(connected()), this, SIGNAL(connected())); 00386 connect(&d->sock, SIGNAL(encrypted()), this, SIGNAL(encrypted())); 00387 connect(&d->sock, SIGNAL(disconnected()), this, SIGNAL(disconnected())); 00388 #ifndef QT_NO_NETWORKPROXY 00389 connect(&d->sock, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), 00390 this, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); 00391 #endif 00392 connect(&d->sock, SIGNAL(error(QAbstractSocket::SocketError)), 00393 this, SLOT(reemitSocketError(QAbstractSocket::SocketError))); 00394 connect(&d->sock, SIGNAL(sslErrors(const QList<QSslError> &)), 00395 this, SLOT(reemitSslErrors(const QList<QSslError> &))); 00396 connect(&d->sock, SIGNAL(hostFound()), this, SIGNAL(hostFound())); 00397 connect(&d->sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), 00398 this, SLOT(reemitStateChanged(QAbstractSocket::SocketState))); 00399 connect(&d->sock, SIGNAL(modeChanged(QSslSocket::SslMode)), 00400 this, SLOT(reemitModeChanged(QSslSocket::SslMode))); 00401 } 00402 00403 00404 KTcpSocket::~KTcpSocket() 00405 { 00406 delete d; 00407 } 00408 00410 00411 bool KTcpSocket::atEnd() const 00412 { 00413 return d->sock.atEnd() && QIODevice::atEnd(); 00414 } 00415 00416 00417 qint64 KTcpSocket::bytesAvailable() const 00418 { 00419 return d->sock.bytesAvailable() + QIODevice::bytesAvailable(); 00420 } 00421 00422 00423 qint64 KTcpSocket::bytesToWrite() const 00424 { 00425 return d->sock.bytesToWrite(); 00426 } 00427 00428 00429 bool KTcpSocket::canReadLine() const 00430 { 00431 return d->sock.canReadLine() || QIODevice::canReadLine(); 00432 } 00433 00434 00435 void KTcpSocket::close() 00436 { 00437 d->sock.close(); 00438 QIODevice::close(); 00439 } 00440 00441 00442 bool KTcpSocket::isSequential() const 00443 { 00444 return true; 00445 } 00446 00447 00448 bool KTcpSocket::open(QIODevice::OpenMode open) 00449 { 00450 bool ret = d->sock.open(open); 00451 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00452 return ret; 00453 } 00454 00455 00456 bool KTcpSocket::waitForBytesWritten(int msecs) 00457 { 00458 return d->sock.waitForBytesWritten(msecs); 00459 } 00460 00461 00462 bool KTcpSocket::waitForReadyRead(int msecs) 00463 { 00464 return d->sock.waitForReadyRead(msecs); 00465 } 00466 00467 00468 qint64 KTcpSocket::readData(char *data, qint64 maxSize) 00469 { 00470 return d->sock.read(data, maxSize); 00471 } 00472 00473 00474 qint64 KTcpSocket::writeData(const char *data, qint64 maxSize) 00475 { 00476 return d->sock.write(data, maxSize); 00477 } 00478 00480 00481 void KTcpSocket::abort() 00482 { 00483 d->sock.abort(); 00484 } 00485 00486 00487 void KTcpSocket::connectToHost(const QString &hostName, quint16 port, ProxyPolicy policy) 00488 { 00489 if (policy == AutoProxy) { 00490 //### 00491 } 00492 d->sock.connectToHost(hostName, port); 00493 // there are enough layers of buffers between us and the network, and there is a quirk 00494 // in QIODevice that can make it try to readData() twice per read() call if buffered and 00495 // reaData() does not deliver enough data the first time. like when the other side is 00496 // simply not sending any more data... 00497 // this can *apparently* lead to long delays sometimes which stalls applications. 00498 // do not want. 00499 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00500 } 00501 00502 00503 void KTcpSocket::connectToHost(const QHostAddress &hostAddress, quint16 port, ProxyPolicy policy) 00504 { 00505 if (policy == AutoProxy) { 00506 //### 00507 } 00508 d->sock.connectToHost(hostAddress, port); 00509 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00510 } 00511 00512 00513 void KTcpSocket::connectToHost(const KUrl &url, ProxyPolicy policy) 00514 { 00515 if (policy == AutoProxy) { 00516 //### 00517 } 00518 d->sock.connectToHost(url.host(), url.port()); 00519 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00520 } 00521 00522 00523 void KTcpSocket::disconnectFromHost() 00524 { 00525 d->sock.disconnectFromHost(); 00526 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00527 } 00528 00529 00530 KTcpSocket::Error KTcpSocket::error() const 00531 { 00532 return d->errorFromAbsSocket(d->sock.error()); 00533 } 00534 00535 00536 QList<KSslError> KTcpSocket::sslErrors() const 00537 { 00538 //### pretty slow; also consider throwing out duplicate error codes. We may get 00539 // duplicates even though there were none in the original list because KSslError 00540 // has a smallest common denominator range of SSL error codes. 00541 QList<KSslError> ret; 00542 foreach (const QSslError &e, d->sock.sslErrors()) 00543 ret.append(KSslError(e)); 00544 return ret; 00545 } 00546 00547 00548 bool KTcpSocket::flush() 00549 { 00550 return d->sock.flush(); 00551 } 00552 00553 00554 bool KTcpSocket::isValid() const 00555 { 00556 return d->sock.isValid(); 00557 } 00558 00559 00560 QHostAddress KTcpSocket::localAddress() const 00561 { 00562 return d->sock.localAddress(); 00563 } 00564 00565 00566 QHostAddress KTcpSocket::peerAddress() const 00567 { 00568 return d->sock.peerAddress(); 00569 } 00570 00571 00572 QString KTcpSocket::peerName() const 00573 { 00574 return d->sock.peerName(); 00575 } 00576 00577 00578 quint16 KTcpSocket::peerPort() const 00579 { 00580 return d->sock.peerPort(); 00581 } 00582 00583 00584 #ifndef QT_NO_NETWORKPROXY 00585 QNetworkProxy KTcpSocket::proxy() const 00586 { 00587 return d->sock.proxy(); 00588 } 00589 #endif 00590 00591 qint64 KTcpSocket::readBufferSize() const 00592 { 00593 return d->sock.readBufferSize(); 00594 } 00595 00596 00597 #ifndef QT_NO_NETWORKPROXY 00598 void KTcpSocket::setProxy(const QNetworkProxy &proxy) 00599 { 00600 d->sock.setProxy(proxy); 00601 } 00602 #endif 00603 00604 void KTcpSocket::setReadBufferSize(qint64 size) 00605 { 00606 d->sock.setReadBufferSize(size); 00607 } 00608 00609 00610 KTcpSocket::State KTcpSocket::state() const 00611 { 00612 return d->state(d->sock.state()); 00613 } 00614 00615 00616 bool KTcpSocket::waitForConnected(int msecs) 00617 { 00618 bool ret = d->sock.waitForConnected(msecs); 00619 if (!ret) 00620 setErrorString(d->sock.errorString()); 00621 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00622 return ret; 00623 } 00624 00625 00626 bool KTcpSocket::waitForDisconnected(int msecs) 00627 { 00628 bool ret = d->sock.waitForDisconnected(msecs); 00629 if (!ret) 00630 setErrorString(d->sock.errorString()); 00631 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00632 return ret; 00633 } 00634 00636 00637 void KTcpSocket::addCaCertificate(const QSslCertificate &certificate) 00638 { 00639 d->maybeLoadCertificates(); 00640 d->sock.addCaCertificate(certificate); 00641 } 00642 00643 00644 /* 00645 bool KTcpSocket::addCaCertificates(const QString &path, QSsl::EncodingFormat format, 00646 QRegExp::PatternSyntax syntax) 00647 { 00648 d->maybeLoadCertificates(); 00649 return d->sock.addCaCertificates(path, format, syntax); 00650 } 00651 */ 00652 00653 00654 void KTcpSocket::addCaCertificates(const QList<QSslCertificate> &certificates) 00655 { 00656 d->maybeLoadCertificates(); 00657 d->sock.addCaCertificates(certificates); 00658 } 00659 00660 00661 QList<QSslCertificate> KTcpSocket::caCertificates() const 00662 { 00663 d->maybeLoadCertificates(); 00664 return d->sock.caCertificates(); 00665 } 00666 00667 00668 QList<KSslCipher> KTcpSocket::ciphers() const 00669 { 00670 return d->ciphers; 00671 } 00672 00673 00674 void KTcpSocket::connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode openMode) 00675 { 00676 d->maybeLoadCertificates(); 00677 d->sock.setProtocol(qSslProtocolFromK(d->advertisedSslVersion)); 00678 d->sock.connectToHostEncrypted(hostName, port, openMode); 00679 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00680 } 00681 00682 00683 QSslCertificate KTcpSocket::localCertificate() const 00684 { 00685 return d->sock.localCertificate(); 00686 } 00687 00688 00689 QList<QSslCertificate> KTcpSocket::peerCertificateChain() const 00690 { 00691 return d->sock.peerCertificateChain(); 00692 } 00693 00694 00695 KSslKey KTcpSocket::privateKey() const 00696 { 00697 return KSslKey(d->sock.privateKey()); 00698 } 00699 00700 00701 KSslCipher KTcpSocket::sessionCipher() const 00702 { 00703 return KSslCipher(d->sock.sessionCipher()); 00704 } 00705 00706 00707 void KTcpSocket::setCaCertificates(const QList<QSslCertificate> &certificates) 00708 { 00709 d->sock.setCaCertificates(certificates); 00710 d->certificatesLoaded = true; 00711 } 00712 00713 00714 void KTcpSocket::setCiphers(const QList<KSslCipher> &ciphers) 00715 { 00716 d->ciphers = ciphers; 00717 QList<QSslCipher> cl; 00718 foreach (const KSslCipher &c, d->ciphers) { 00719 cl.append(d->ccc.converted(c)); 00720 } 00721 d->sock.setCiphers(cl); 00722 } 00723 00724 00725 void KTcpSocket::setLocalCertificate(const QSslCertificate &certificate) 00726 { 00727 d->sock.setLocalCertificate(certificate); 00728 } 00729 00730 00731 void KTcpSocket::setLocalCertificate(const QString &fileName, QSsl::EncodingFormat format) 00732 { 00733 d->sock.setLocalCertificate(fileName, format); 00734 } 00735 00736 00737 void KTcpSocket::setVerificationPeerName(const QString& hostName) 00738 { 00739 #if QT_VERSION >= 0x040800 00740 d->sock.setPeerVerifyName(hostName); 00741 #else 00742 Q_UNUSED(hostName); 00743 #endif 00744 } 00745 00746 00747 //TODO 00748 void KTcpSocket::setPrivateKey(const KSslKey &key) 00749 { 00750 Q_UNUSED(key) 00751 } 00752 00753 00754 //TODO 00755 void KTcpSocket::setPrivateKey(const QString &fileName, KSslKey::Algorithm algorithm, 00756 QSsl::EncodingFormat format, const QByteArray &passPhrase) 00757 { 00758 Q_UNUSED(fileName) 00759 Q_UNUSED(algorithm) 00760 Q_UNUSED(format) 00761 Q_UNUSED(passPhrase) 00762 } 00763 00764 00765 bool KTcpSocket::waitForEncrypted(int msecs) 00766 { 00767 return d->sock.waitForEncrypted(msecs); 00768 } 00769 00770 00771 KTcpSocket::EncryptionMode KTcpSocket::encryptionMode() const 00772 { 00773 return d->encryptionMode(d->sock.mode()); 00774 } 00775 00776 QVariant KTcpSocket::socketOption(QAbstractSocket::SocketOption options) const 00777 { 00778 return d->sock.socketOption(options); 00779 } 00780 00781 void KTcpSocket::setSocketOption(QAbstractSocket::SocketOption options, const QVariant &value) 00782 { 00783 d->sock.setSocketOption(options, value); 00784 } 00785 00786 //slot 00787 void KTcpSocket::ignoreSslErrors() 00788 { 00789 d->sock.ignoreSslErrors(); 00790 } 00791 00792 00793 //slot 00794 void KTcpSocket::startClientEncryption() 00795 { 00796 d->maybeLoadCertificates(); 00797 d->sock.setProtocol(qSslProtocolFromK(d->advertisedSslVersion)); 00798 d->sock.startClientEncryption(); 00799 } 00800 00801 00802 //debugging H4X 00803 void KTcpSocket::showSslErrors() 00804 { 00805 foreach (const QSslError &e, d->sock.sslErrors()) 00806 kDebug(7029) << e.errorString(); 00807 } 00808 00809 00810 void KTcpSocket::setAdvertisedSslVersion(KTcpSocket::SslVersion version) 00811 { 00812 d->advertisedSslVersion = version; 00813 } 00814 00815 00816 KTcpSocket::SslVersion KTcpSocket::advertisedSslVersion() const 00817 { 00818 return d->advertisedSslVersion; 00819 } 00820 00821 00822 KTcpSocket::SslVersion KTcpSocket::negotiatedSslVersion() const 00823 { 00824 if (!d->sock.isEncrypted()) { 00825 return UnknownSslVersion; 00826 } 00827 return kSslVersionFromQ(d->sock.protocol()); 00828 } 00829 00830 00831 QString KTcpSocket::negotiatedSslVersionName() const 00832 { 00833 if (!d->sock.isEncrypted()) { 00834 return QString(); 00835 } 00836 return d->sock.sessionCipher().protocolString(); 00837 } 00838 00839 00841 00842 class KSslKeyPrivate 00843 { 00844 public: 00845 KSslKey::Algorithm convertAlgorithm(QSsl::KeyAlgorithm a) 00846 { 00847 switch(a) { 00848 case QSsl::Dsa: 00849 return KSslKey::Dsa; 00850 default: 00851 return KSslKey::Rsa; 00852 } 00853 } 00854 00855 KSslKey::Algorithm algorithm; 00856 KSslKey::KeySecrecy secrecy; 00857 bool isExportable; 00858 QByteArray der; 00859 }; 00860 00861 00862 KSslKey::KSslKey() 00863 : d(new KSslKeyPrivate) 00864 { 00865 d->algorithm = Rsa; 00866 d->secrecy = PublicKey; 00867 d->isExportable = true; 00868 } 00869 00870 00871 KSslKey::KSslKey(const KSslKey &other) 00872 : d(new KSslKeyPrivate) 00873 { 00874 *d = *other.d; 00875 } 00876 00877 00878 KSslKey::KSslKey(const QSslKey &qsk) 00879 : d(new KSslKeyPrivate) 00880 { 00881 d->algorithm = d->convertAlgorithm(qsk.algorithm()); 00882 d->secrecy = (qsk.type() == QSsl::PrivateKey) ? PrivateKey : PublicKey; 00883 d->isExportable = true; 00884 d->der = qsk.toDer(); 00885 } 00886 00887 00888 KSslKey::~KSslKey() 00889 { 00890 delete d; 00891 } 00892 00893 00894 KSslKey &KSslKey::operator=(const KSslKey &other) 00895 { 00896 *d = *other.d; 00897 return *this; 00898 } 00899 00900 00901 KSslKey::Algorithm KSslKey::algorithm() const 00902 { 00903 return d->algorithm; 00904 } 00905 00906 00907 bool KSslKey::isExportable() const 00908 { 00909 return d->isExportable; 00910 } 00911 00912 00913 KSslKey::KeySecrecy KSslKey::secrecy() const 00914 { 00915 return d->secrecy; 00916 } 00917 00918 00919 QByteArray KSslKey::toDer() const 00920 { 00921 return d->der; 00922 } 00923 00925 00926 //nice-to-have: make implicitly shared 00927 class KSslCipherPrivate 00928 { 00929 public: 00930 00931 QString authenticationMethod; 00932 QString encryptionMethod; 00933 QString keyExchangeMethod; 00934 QString name; 00935 bool isNull; 00936 int supportedBits; 00937 int usedBits; 00938 }; 00939 00940 00941 KSslCipher::KSslCipher() 00942 : d(new KSslCipherPrivate) 00943 { 00944 d->isNull = true; 00945 d->supportedBits = 0; 00946 d->usedBits = 0; 00947 } 00948 00949 00950 KSslCipher::KSslCipher(const KSslCipher &other) 00951 : d(new KSslCipherPrivate) 00952 { 00953 *d = *other.d; 00954 } 00955 00956 00957 KSslCipher::KSslCipher(const QSslCipher &qsc) 00958 : d(new KSslCipherPrivate) 00959 { 00960 d->authenticationMethod = qsc.authenticationMethod(); 00961 d->encryptionMethod = qsc.encryptionMethod(); 00962 //Qt likes to append the number of bits (usedBits?) to the algorithm, 00963 //for example "AES(256)". We only want the pure algorithm name, though. 00964 int parenIdx = d->encryptionMethod.indexOf(QLatin1Char('(')); 00965 if (parenIdx > 0) 00966 d->encryptionMethod.truncate(parenIdx); 00967 d->keyExchangeMethod = qsc.keyExchangeMethod(); 00968 d->name = qsc.name(); 00969 d->isNull = qsc.isNull(); 00970 d->supportedBits = qsc.supportedBits(); 00971 d->usedBits = qsc.usedBits(); 00972 } 00973 00974 00975 KSslCipher::~KSslCipher() 00976 { 00977 delete d; 00978 } 00979 00980 00981 KSslCipher &KSslCipher::operator=(const KSslCipher &other) 00982 { 00983 *d = *other.d; 00984 return *this; 00985 } 00986 00987 00988 bool KSslCipher::isNull() const 00989 { 00990 return d->isNull; 00991 } 00992 00993 00994 QString KSslCipher::authenticationMethod() const 00995 { 00996 return d->authenticationMethod; 00997 } 00998 00999 01000 QString KSslCipher::encryptionMethod() const 01001 { 01002 return d->encryptionMethod; 01003 } 01004 01005 01006 QString KSslCipher::keyExchangeMethod() const 01007 { 01008 return d->keyExchangeMethod; 01009 } 01010 01011 01012 QString KSslCipher::digestMethod() const 01013 { 01014 //### This is not really backend neutral. It works for OpenSSL and 01015 // for RFC compliant names, though. 01016 if (d->name.endsWith(QLatin1String("SHA"))) 01017 return QString::fromLatin1("SHA-1"); 01018 else if (d->name.endsWith(QLatin1String("MD5"))) 01019 return QString::fromLatin1("MD5"); 01020 else 01021 return QString::fromLatin1(""); // ## probably QString() is enough 01022 } 01023 01024 01025 QString KSslCipher::name() const 01026 { 01027 return d->name; 01028 } 01029 01030 01031 int KSslCipher::supportedBits() const 01032 { 01033 return d->supportedBits; 01034 } 01035 01036 01037 int KSslCipher::usedBits() const 01038 { 01039 return d->usedBits; 01040 } 01041 01042 01043 //static 01044 QList<KSslCipher> KSslCipher::supportedCiphers() 01045 { 01046 QList<KSslCipher> ret; 01047 QList<QSslCipher> candidates = QSslSocket::supportedCiphers(); 01048 foreach(const QSslCipher &c, candidates) { 01049 ret.append(KSslCipher(c)); 01050 } 01051 return ret; 01052 } 01053 01054 01055 KSslErrorUiData::KSslErrorUiData() 01056 : d(new Private()) 01057 { 01058 d->usedBits = 0; 01059 d->bits = 0; 01060 } 01061 01062 01063 KSslErrorUiData::KSslErrorUiData(const KTcpSocket *socket) 01064 : d(new Private()) 01065 { 01066 d->certificateChain = socket->peerCertificateChain(); 01067 d->sslErrors = socket->sslErrors(); 01068 d->ip = socket->peerAddress().toString(); 01069 d->host = socket->peerName(); 01070 d->sslProtocol = socket->negotiatedSslVersionName(); 01071 d->cipher = socket->sessionCipher().name(); 01072 d->usedBits = socket->sessionCipher().usedBits(); 01073 d->bits = socket->sessionCipher().supportedBits(); 01074 } 01075 01076 KSslErrorUiData::KSslErrorUiData(const QSslSocket *socket) 01077 : d(new Private()) 01078 { 01079 d->certificateChain = socket->peerCertificateChain(); 01080 01081 // See KTcpSocket::sslErrors() 01082 foreach (const QSslError &e, socket->sslErrors()) 01083 d->sslErrors.append(KSslError(e)); 01084 01085 d->ip = socket->peerAddress().toString(); 01086 d->host = socket->peerName(); 01087 if (socket->isEncrypted()) { 01088 d->sslProtocol = socket->sessionCipher().protocolString(); 01089 } 01090 d->cipher = socket->sessionCipher().name(); 01091 d->usedBits = socket->sessionCipher().usedBits(); 01092 d->bits = socket->sessionCipher().supportedBits(); 01093 } 01094 01095 01096 KSslErrorUiData::KSslErrorUiData(const KSslErrorUiData &other) 01097 : d(new Private(*other.d)) 01098 {} 01099 01100 KSslErrorUiData::~KSslErrorUiData() 01101 { 01102 delete d; 01103 } 01104 01105 KSslErrorUiData &KSslErrorUiData::operator=(const KSslErrorUiData &other) 01106 { 01107 *d = *other.d; 01108 return *this; 01109 } 01110 01111 01112 #include "ktcpsocket.moc"
KDE 4.8 API Reference