KDECore
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(readyRead()), this, SLOT(reemitReadyRead())); 00384 connect(&d->sock, SIGNAL(connected()), this, SIGNAL(connected())); 00385 connect(&d->sock, SIGNAL(encrypted()), this, SIGNAL(encrypted())); 00386 connect(&d->sock, SIGNAL(disconnected()), this, SIGNAL(disconnected())); 00387 #ifndef QT_NO_NETWORKPROXY 00388 connect(&d->sock, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), 00389 this, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); 00390 #endif 00391 connect(&d->sock, SIGNAL(error(QAbstractSocket::SocketError)), 00392 this, SLOT(reemitSocketError(QAbstractSocket::SocketError))); 00393 connect(&d->sock, SIGNAL(sslErrors(const QList<QSslError> &)), 00394 this, SLOT(reemitSslErrors(const QList<QSslError> &))); 00395 connect(&d->sock, SIGNAL(hostFound()), this, SIGNAL(hostFound())); 00396 connect(&d->sock, SIGNAL(stateChanged(QAbstractSocket::SocketState)), 00397 this, SLOT(reemitStateChanged(QAbstractSocket::SocketState))); 00398 connect(&d->sock, SIGNAL(modeChanged(QSslSocket::SslMode)), 00399 this, SLOT(reemitModeChanged(QSslSocket::SslMode))); 00400 } 00401 00402 00403 KTcpSocket::~KTcpSocket() 00404 { 00405 delete d; 00406 } 00407 00409 00410 bool KTcpSocket::atEnd() const 00411 { 00412 return d->sock.atEnd() && QIODevice::atEnd(); 00413 } 00414 00415 00416 qint64 KTcpSocket::bytesAvailable() const 00417 { 00418 return d->sock.bytesAvailable() + QIODevice::bytesAvailable(); 00419 } 00420 00421 00422 qint64 KTcpSocket::bytesToWrite() const 00423 { 00424 return d->sock.bytesToWrite(); 00425 } 00426 00427 00428 bool KTcpSocket::canReadLine() const 00429 { 00430 return d->sock.canReadLine() || QIODevice::canReadLine(); 00431 } 00432 00433 00434 void KTcpSocket::close() 00435 { 00436 d->sock.close(); 00437 QIODevice::close(); 00438 } 00439 00440 00441 bool KTcpSocket::isSequential() const 00442 { 00443 return true; 00444 } 00445 00446 00447 bool KTcpSocket::open(QIODevice::OpenMode open) 00448 { 00449 bool ret = d->sock.open(open); 00450 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00451 return ret; 00452 } 00453 00454 00455 bool KTcpSocket::waitForBytesWritten(int msecs) 00456 { 00457 return d->sock.waitForBytesWritten(msecs); 00458 } 00459 00460 00461 bool KTcpSocket::waitForReadyRead(int msecs) 00462 { 00463 return d->sock.waitForReadyRead(msecs); 00464 } 00465 00466 00467 qint64 KTcpSocket::readData(char *data, qint64 maxSize) 00468 { 00469 return d->sock.read(data, maxSize); 00470 } 00471 00472 00473 qint64 KTcpSocket::writeData(const char *data, qint64 maxSize) 00474 { 00475 return d->sock.write(data, maxSize); 00476 } 00477 00479 00480 void KTcpSocket::abort() 00481 { 00482 d->sock.abort(); 00483 } 00484 00485 00486 void KTcpSocket::connectToHost(const QString &hostName, quint16 port, ProxyPolicy policy) 00487 { 00488 if (policy == AutoProxy) { 00489 //### 00490 } 00491 d->sock.connectToHost(hostName, port); 00492 // there are enough layers of buffers between us and the network, and there is a quirk 00493 // in QIODevice that can make it try to readData() twice per read() call if buffered and 00494 // reaData() does not deliver enough data the first time. like when the other side is 00495 // simply not sending any more data... 00496 // this can *apparently* lead to long delays sometimes which stalls applications. 00497 // do not want. 00498 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00499 } 00500 00501 00502 void KTcpSocket::connectToHost(const QHostAddress &hostAddress, quint16 port, ProxyPolicy policy) 00503 { 00504 if (policy == AutoProxy) { 00505 //### 00506 } 00507 d->sock.connectToHost(hostAddress, port); 00508 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00509 } 00510 00511 00512 void KTcpSocket::connectToHost(const KUrl &url, ProxyPolicy policy) 00513 { 00514 if (policy == AutoProxy) { 00515 //### 00516 } 00517 d->sock.connectToHost(url.host(), url.port()); 00518 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00519 } 00520 00521 00522 void KTcpSocket::disconnectFromHost() 00523 { 00524 d->sock.disconnectFromHost(); 00525 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00526 } 00527 00528 00529 KTcpSocket::Error KTcpSocket::error() const 00530 { 00531 return d->errorFromAbsSocket(d->sock.error()); 00532 } 00533 00534 00535 QList<KSslError> KTcpSocket::sslErrors() const 00536 { 00537 //### pretty slow; also consider throwing out duplicate error codes. We may get 00538 // duplicates even though there were none in the original list because KSslError 00539 // has a smallest common denominator range of SSL error codes. 00540 QList<KSslError> ret; 00541 foreach (const QSslError &e, d->sock.sslErrors()) 00542 ret.append(KSslError(e)); 00543 return ret; 00544 } 00545 00546 00547 bool KTcpSocket::flush() 00548 { 00549 return d->sock.flush(); 00550 } 00551 00552 00553 bool KTcpSocket::isValid() const 00554 { 00555 return d->sock.isValid(); 00556 } 00557 00558 00559 QHostAddress KTcpSocket::localAddress() const 00560 { 00561 return d->sock.localAddress(); 00562 } 00563 00564 00565 QHostAddress KTcpSocket::peerAddress() const 00566 { 00567 return d->sock.peerAddress(); 00568 } 00569 00570 00571 QString KTcpSocket::peerName() const 00572 { 00573 return d->sock.peerName(); 00574 } 00575 00576 00577 quint16 KTcpSocket::peerPort() const 00578 { 00579 return d->sock.peerPort(); 00580 } 00581 00582 00583 #ifndef QT_NO_NETWORKPROXY 00584 QNetworkProxy KTcpSocket::proxy() const 00585 { 00586 return d->sock.proxy(); 00587 } 00588 #endif 00589 00590 qint64 KTcpSocket::readBufferSize() const 00591 { 00592 return d->sock.readBufferSize(); 00593 } 00594 00595 00596 #ifndef QT_NO_NETWORKPROXY 00597 void KTcpSocket::setProxy(const QNetworkProxy &proxy) 00598 { 00599 d->sock.setProxy(proxy); 00600 } 00601 #endif 00602 00603 void KTcpSocket::setReadBufferSize(qint64 size) 00604 { 00605 d->sock.setReadBufferSize(size); 00606 } 00607 00608 00609 KTcpSocket::State KTcpSocket::state() const 00610 { 00611 return d->state(d->sock.state()); 00612 } 00613 00614 00615 bool KTcpSocket::waitForConnected(int msecs) 00616 { 00617 bool ret = d->sock.waitForConnected(msecs); 00618 if (!ret) 00619 setErrorString(d->sock.errorString()); 00620 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00621 return ret; 00622 } 00623 00624 00625 bool KTcpSocket::waitForDisconnected(int msecs) 00626 { 00627 bool ret = d->sock.waitForDisconnected(msecs); 00628 if (!ret) 00629 setErrorString(d->sock.errorString()); 00630 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00631 return ret; 00632 } 00633 00635 00636 void KTcpSocket::addCaCertificate(const QSslCertificate &certificate) 00637 { 00638 d->maybeLoadCertificates(); 00639 d->sock.addCaCertificate(certificate); 00640 } 00641 00642 00643 /* 00644 bool KTcpSocket::addCaCertificates(const QString &path, QSsl::EncodingFormat format, 00645 QRegExp::PatternSyntax syntax) 00646 { 00647 d->maybeLoadCertificates(); 00648 return d->sock.addCaCertificates(path, format, syntax); 00649 } 00650 */ 00651 00652 00653 void KTcpSocket::addCaCertificates(const QList<QSslCertificate> &certificates) 00654 { 00655 d->maybeLoadCertificates(); 00656 d->sock.addCaCertificates(certificates); 00657 } 00658 00659 00660 QList<QSslCertificate> KTcpSocket::caCertificates() const 00661 { 00662 d->maybeLoadCertificates(); 00663 return d->sock.caCertificates(); 00664 } 00665 00666 00667 QList<KSslCipher> KTcpSocket::ciphers() const 00668 { 00669 return d->ciphers; 00670 } 00671 00672 00673 void KTcpSocket::connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode openMode) 00674 { 00675 d->maybeLoadCertificates(); 00676 d->sock.setProtocol(qSslProtocolFromK(d->advertisedSslVersion)); 00677 d->sock.connectToHostEncrypted(hostName, port, openMode); 00678 setOpenMode(d->sock.openMode() | QIODevice::Unbuffered); 00679 } 00680 00681 00682 QSslCertificate KTcpSocket::localCertificate() const 00683 { 00684 return d->sock.localCertificate(); 00685 } 00686 00687 00688 QList<QSslCertificate> KTcpSocket::peerCertificateChain() const 00689 { 00690 return d->sock.peerCertificateChain(); 00691 } 00692 00693 00694 KSslKey KTcpSocket::privateKey() const 00695 { 00696 return KSslKey(d->sock.privateKey()); 00697 } 00698 00699 00700 KSslCipher KTcpSocket::sessionCipher() const 00701 { 00702 return KSslCipher(d->sock.sessionCipher()); 00703 } 00704 00705 00706 void KTcpSocket::setCaCertificates(const QList<QSslCertificate> &certificates) 00707 { 00708 d->sock.setCaCertificates(certificates); 00709 d->certificatesLoaded = true; 00710 } 00711 00712 00713 void KTcpSocket::setCiphers(const QList<KSslCipher> &ciphers) 00714 { 00715 d->ciphers = ciphers; 00716 QList<QSslCipher> cl; 00717 foreach (const KSslCipher &c, d->ciphers) { 00718 cl.append(d->ccc.converted(c)); 00719 } 00720 d->sock.setCiphers(cl); 00721 } 00722 00723 00724 void KTcpSocket::setLocalCertificate(const QSslCertificate &certificate) 00725 { 00726 d->sock.setLocalCertificate(certificate); 00727 } 00728 00729 00730 void KTcpSocket::setLocalCertificate(const QString &fileName, QSsl::EncodingFormat format) 00731 { 00732 d->sock.setLocalCertificate(fileName, format); 00733 } 00734 00735 00736 void KTcpSocket::setVerificationPeerName(const QString& hostName) 00737 { 00738 #if QT_VERSION >= 0x040800 00739 d->sock.setPeerVerifyName(hostName); 00740 #else 00741 Q_UNUSED(hostName); 00742 #endif 00743 } 00744 00745 00746 //TODO 00747 void KTcpSocket::setPrivateKey(const KSslKey &key) 00748 { 00749 Q_UNUSED(key) 00750 } 00751 00752 00753 //TODO 00754 void KTcpSocket::setPrivateKey(const QString &fileName, KSslKey::Algorithm algorithm, 00755 QSsl::EncodingFormat format, const QByteArray &passPhrase) 00756 { 00757 Q_UNUSED(fileName) 00758 Q_UNUSED(algorithm) 00759 Q_UNUSED(format) 00760 Q_UNUSED(passPhrase) 00761 } 00762 00763 00764 bool KTcpSocket::waitForEncrypted(int msecs) 00765 { 00766 return d->sock.waitForEncrypted(msecs); 00767 } 00768 00769 00770 KTcpSocket::EncryptionMode KTcpSocket::encryptionMode() const 00771 { 00772 return d->encryptionMode(d->sock.mode()); 00773 } 00774 00775 QVariant KTcpSocket::socketOption(QAbstractSocket::SocketOption options) const 00776 { 00777 return d->sock.socketOption(options); 00778 } 00779 00780 void KTcpSocket::setSocketOption(QAbstractSocket::SocketOption options, const QVariant &value) 00781 { 00782 return d->sock.setSocketOption(options, value); 00783 } 00784 00785 //slot 00786 void KTcpSocket::ignoreSslErrors() 00787 { 00788 d->sock.ignoreSslErrors(); 00789 } 00790 00791 00792 //slot 00793 void KTcpSocket::startClientEncryption() 00794 { 00795 d->maybeLoadCertificates(); 00796 d->sock.setProtocol(qSslProtocolFromK(d->advertisedSslVersion)); 00797 d->sock.startClientEncryption(); 00798 } 00799 00800 00801 //debugging H4X 00802 void KTcpSocket::showSslErrors() 00803 { 00804 foreach (const QSslError &e, d->sock.sslErrors()) 00805 kDebug(7029) << e.errorString(); 00806 } 00807 00808 00809 void KTcpSocket::setAdvertisedSslVersion(KTcpSocket::SslVersion version) 00810 { 00811 d->advertisedSslVersion = version; 00812 } 00813 00814 00815 KTcpSocket::SslVersion KTcpSocket::advertisedSslVersion() const 00816 { 00817 return d->advertisedSslVersion; 00818 } 00819 00820 00821 KTcpSocket::SslVersion KTcpSocket::negotiatedSslVersion() const 00822 { 00823 if (!d->sock.isEncrypted()) { 00824 return UnknownSslVersion; 00825 } 00826 return kSslVersionFromQ(d->sock.protocol()); 00827 } 00828 00829 00830 QString KTcpSocket::negotiatedSslVersionName() const 00831 { 00832 if (!d->sock.isEncrypted()) { 00833 return QString(); 00834 } 00835 return d->sock.sessionCipher().protocolString(); 00836 } 00837 00838 00840 00841 class KSslKeyPrivate 00842 { 00843 public: 00844 KSslKey::Algorithm convertAlgorithm(QSsl::KeyAlgorithm a) 00845 { 00846 switch(a) { 00847 case QSsl::Dsa: 00848 return KSslKey::Dsa; 00849 default: 00850 return KSslKey::Rsa; 00851 } 00852 } 00853 00854 KSslKey::Algorithm algorithm; 00855 KSslKey::KeySecrecy secrecy; 00856 bool isExportable; 00857 QByteArray der; 00858 }; 00859 00860 00861 KSslKey::KSslKey() 00862 : d(new KSslKeyPrivate) 00863 { 00864 d->algorithm = Rsa; 00865 d->secrecy = PublicKey; 00866 d->isExportable = true; 00867 } 00868 00869 00870 KSslKey::KSslKey(const KSslKey &other) 00871 : d(new KSslKeyPrivate) 00872 { 00873 *d = *other.d; 00874 } 00875 00876 00877 KSslKey::KSslKey(const QSslKey &qsk) 00878 : d(new KSslKeyPrivate) 00879 { 00880 d->algorithm = d->convertAlgorithm(qsk.algorithm()); 00881 d->secrecy = (qsk.type() == QSsl::PrivateKey) ? PrivateKey : PublicKey; 00882 d->isExportable = true; 00883 d->der = qsk.toDer(); 00884 } 00885 00886 00887 KSslKey::~KSslKey() 00888 { 00889 delete d; 00890 } 00891 00892 00893 KSslKey &KSslKey::operator=(const KSslKey &other) 00894 { 00895 *d = *other.d; 00896 return *this; 00897 } 00898 00899 00900 KSslKey::Algorithm KSslKey::algorithm() const 00901 { 00902 return d->algorithm; 00903 } 00904 00905 00906 bool KSslKey::isExportable() const 00907 { 00908 return d->isExportable; 00909 } 00910 00911 00912 KSslKey::KeySecrecy KSslKey::secrecy() const 00913 { 00914 return d->secrecy; 00915 } 00916 00917 00918 QByteArray KSslKey::toDer() const 00919 { 00920 return d->der; 00921 } 00922 00924 00925 //nice-to-have: make implicitly shared 00926 class KSslCipherPrivate 00927 { 00928 public: 00929 00930 QString authenticationMethod; 00931 QString encryptionMethod; 00932 QString keyExchangeMethod; 00933 QString name; 00934 bool isNull; 00935 int supportedBits; 00936 int usedBits; 00937 }; 00938 00939 00940 KSslCipher::KSslCipher() 00941 : d(new KSslCipherPrivate) 00942 { 00943 d->isNull = true; 00944 d->supportedBits = 0; 00945 d->usedBits = 0; 00946 } 00947 00948 00949 KSslCipher::KSslCipher(const KSslCipher &other) 00950 : d(new KSslCipherPrivate) 00951 { 00952 *d = *other.d; 00953 } 00954 00955 00956 KSslCipher::KSslCipher(const QSslCipher &qsc) 00957 : d(new KSslCipherPrivate) 00958 { 00959 d->authenticationMethod = qsc.authenticationMethod(); 00960 d->encryptionMethod = qsc.encryptionMethod(); 00961 //Qt likes to append the number of bits (usedBits?) to the algorithm, 00962 //for example "AES(256)". We only want the pure algorithm name, though. 00963 int parenIdx = d->encryptionMethod.indexOf(QLatin1Char('(')); 00964 if (parenIdx > 0) 00965 d->encryptionMethod.truncate(parenIdx); 00966 d->keyExchangeMethod = qsc.keyExchangeMethod(); 00967 d->name = qsc.name(); 00968 d->isNull = qsc.isNull(); 00969 d->supportedBits = qsc.supportedBits(); 00970 d->usedBits = qsc.usedBits(); 00971 } 00972 00973 00974 KSslCipher::~KSslCipher() 00975 { 00976 delete d; 00977 } 00978 00979 00980 KSslCipher &KSslCipher::operator=(const KSslCipher &other) 00981 { 00982 *d = *other.d; 00983 return *this; 00984 } 00985 00986 00987 bool KSslCipher::isNull() const 00988 { 00989 return d->isNull; 00990 } 00991 00992 00993 QString KSslCipher::authenticationMethod() const 00994 { 00995 return d->authenticationMethod; 00996 } 00997 00998 00999 QString KSslCipher::encryptionMethod() const 01000 { 01001 return d->encryptionMethod; 01002 } 01003 01004 01005 QString KSslCipher::keyExchangeMethod() const 01006 { 01007 return d->keyExchangeMethod; 01008 } 01009 01010 01011 QString KSslCipher::digestMethod() const 01012 { 01013 //### This is not really backend neutral. It works for OpenSSL and 01014 // for RFC compliant names, though. 01015 if (d->name.endsWith(QLatin1String("SHA"))) 01016 return QString::fromLatin1("SHA-1"); 01017 else if (d->name.endsWith(QLatin1String("MD5"))) 01018 return QString::fromLatin1("MD5"); 01019 else 01020 return QString::fromLatin1(""); // ## probably QString() is enough 01021 } 01022 01023 01024 QString KSslCipher::name() const 01025 { 01026 return d->name; 01027 } 01028 01029 01030 int KSslCipher::supportedBits() const 01031 { 01032 return d->supportedBits; 01033 } 01034 01035 01036 int KSslCipher::usedBits() const 01037 { 01038 return d->usedBits; 01039 } 01040 01041 01042 //static 01043 QList<KSslCipher> KSslCipher::supportedCiphers() 01044 { 01045 QList<KSslCipher> ret; 01046 QList<QSslCipher> candidates = QSslSocket::supportedCiphers(); 01047 foreach(const QSslCipher &c, candidates) { 01048 ret.append(KSslCipher(c)); 01049 } 01050 return ret; 01051 } 01052 01053 01054 KSslErrorUiData::KSslErrorUiData() 01055 : d(new Private()) 01056 { 01057 d->usedBits = 0; 01058 d->bits = 0; 01059 } 01060 01061 01062 KSslErrorUiData::KSslErrorUiData(const KTcpSocket *socket) 01063 : d(new Private()) 01064 { 01065 d->certificateChain = socket->peerCertificateChain(); 01066 d->sslErrors = socket->sslErrors(); 01067 d->ip = socket->peerAddress().toString(); 01068 d->host = socket->peerName(); 01069 d->sslProtocol = socket->negotiatedSslVersionName(); 01070 d->cipher = socket->sessionCipher().name(); 01071 d->usedBits = socket->sessionCipher().usedBits(); 01072 d->bits = socket->sessionCipher().supportedBits(); 01073 } 01074 01075 01076 KSslErrorUiData::KSslErrorUiData(const KSslErrorUiData &other) 01077 : d(new Private(*other.d)) 01078 {} 01079 01080 KSslErrorUiData::~KSslErrorUiData() 01081 { 01082 delete d; 01083 } 01084 01085 KSslErrorUiData &KSslErrorUiData::operator=(const KSslErrorUiData &other) 01086 { 01087 *d = *other.d; 01088 return *this; 01089 } 01090 01091 01092 #include "ktcpsocket.moc"
KDE 4.7 API Reference