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 //TODO 00737 void KTcpSocket::setPrivateKey(const KSslKey &key) 00738 { 00739 Q_UNUSED(key) 00740 } 00741 00742 00743 //TODO 00744 void KTcpSocket::setPrivateKey(const QString &fileName, KSslKey::Algorithm algorithm, 00745 QSsl::EncodingFormat format, const QByteArray &passPhrase) 00746 { 00747 Q_UNUSED(fileName) 00748 Q_UNUSED(algorithm) 00749 Q_UNUSED(format) 00750 Q_UNUSED(passPhrase) 00751 } 00752 00753 00754 bool KTcpSocket::waitForEncrypted(int msecs) 00755 { 00756 return d->sock.waitForEncrypted(msecs); 00757 } 00758 00759 00760 KTcpSocket::EncryptionMode KTcpSocket::encryptionMode() const 00761 { 00762 return d->encryptionMode(d->sock.mode()); 00763 } 00764 00765 QVariant KTcpSocket::socketOption(QAbstractSocket::SocketOption options) const 00766 { 00767 return d->sock.socketOption(options); 00768 } 00769 00770 void KTcpSocket::setSocketOption(QAbstractSocket::SocketOption options, const QVariant &value) 00771 { 00772 return d->sock.setSocketOption(options, value); 00773 } 00774 00775 //slot 00776 void KTcpSocket::ignoreSslErrors() 00777 { 00778 d->sock.ignoreSslErrors(); 00779 } 00780 00781 00782 //slot 00783 void KTcpSocket::startClientEncryption() 00784 { 00785 d->maybeLoadCertificates(); 00786 d->sock.setProtocol(qSslProtocolFromK(d->advertisedSslVersion)); 00787 d->sock.startClientEncryption(); 00788 } 00789 00790 00791 //debugging H4X 00792 void KTcpSocket::showSslErrors() 00793 { 00794 foreach (const QSslError &e, d->sock.sslErrors()) 00795 kDebug(7029) << e.errorString(); 00796 } 00797 00798 00799 void KTcpSocket::setAdvertisedSslVersion(KTcpSocket::SslVersion version) 00800 { 00801 d->advertisedSslVersion = version; 00802 } 00803 00804 00805 KTcpSocket::SslVersion KTcpSocket::advertisedSslVersion() const 00806 { 00807 return d->advertisedSslVersion; 00808 } 00809 00810 00811 KTcpSocket::SslVersion KTcpSocket::negotiatedSslVersion() const 00812 { 00813 if (!d->sock.isEncrypted()) { 00814 return UnknownSslVersion; 00815 } 00816 return kSslVersionFromQ(d->sock.protocol()); 00817 } 00818 00819 00820 QString KTcpSocket::negotiatedSslVersionName() const 00821 { 00822 if (!d->sock.isEncrypted()) { 00823 return QString(); 00824 } 00825 return d->sock.sessionCipher().protocolString(); 00826 } 00827 00828 00830 00831 class KSslKeyPrivate 00832 { 00833 public: 00834 KSslKey::Algorithm convertAlgorithm(QSsl::KeyAlgorithm a) 00835 { 00836 switch(a) { 00837 case QSsl::Dsa: 00838 return KSslKey::Dsa; 00839 default: 00840 return KSslKey::Rsa; 00841 } 00842 } 00843 00844 KSslKey::Algorithm algorithm; 00845 KSslKey::KeySecrecy secrecy; 00846 bool isExportable; 00847 QByteArray der; 00848 }; 00849 00850 00851 KSslKey::KSslKey() 00852 : d(new KSslKeyPrivate) 00853 { 00854 d->algorithm = Rsa; 00855 d->secrecy = PublicKey; 00856 d->isExportable = true; 00857 } 00858 00859 00860 KSslKey::KSslKey(const KSslKey &other) 00861 : d(new KSslKeyPrivate) 00862 { 00863 *d = *other.d; 00864 } 00865 00866 00867 KSslKey::KSslKey(const QSslKey &qsk) 00868 : d(new KSslKeyPrivate) 00869 { 00870 d->algorithm = d->convertAlgorithm(qsk.algorithm()); 00871 d->secrecy = (qsk.type() == QSsl::PrivateKey) ? PrivateKey : PublicKey; 00872 d->isExportable = true; 00873 d->der = qsk.toDer(); 00874 } 00875 00876 00877 KSslKey::~KSslKey() 00878 { 00879 delete d; 00880 } 00881 00882 00883 KSslKey &KSslKey::operator=(const KSslKey &other) 00884 { 00885 *d = *other.d; 00886 return *this; 00887 } 00888 00889 00890 KSslKey::Algorithm KSslKey::algorithm() const 00891 { 00892 return d->algorithm; 00893 } 00894 00895 00896 bool KSslKey::isExportable() const 00897 { 00898 return d->isExportable; 00899 } 00900 00901 00902 KSslKey::KeySecrecy KSslKey::secrecy() const 00903 { 00904 return d->secrecy; 00905 } 00906 00907 00908 QByteArray KSslKey::toDer() const 00909 { 00910 return d->der; 00911 } 00912 00914 00915 //nice-to-have: make implicitly shared 00916 class KSslCipherPrivate 00917 { 00918 public: 00919 00920 QString authenticationMethod; 00921 QString encryptionMethod; 00922 QString keyExchangeMethod; 00923 QString name; 00924 bool isNull; 00925 int supportedBits; 00926 int usedBits; 00927 }; 00928 00929 00930 KSslCipher::KSslCipher() 00931 : d(new KSslCipherPrivate) 00932 { 00933 d->isNull = true; 00934 d->supportedBits = 0; 00935 d->usedBits = 0; 00936 } 00937 00938 00939 KSslCipher::KSslCipher(const KSslCipher &other) 00940 : d(new KSslCipherPrivate) 00941 { 00942 *d = *other.d; 00943 } 00944 00945 00946 KSslCipher::KSslCipher(const QSslCipher &qsc) 00947 : d(new KSslCipherPrivate) 00948 { 00949 d->authenticationMethod = qsc.authenticationMethod(); 00950 d->encryptionMethod = qsc.encryptionMethod(); 00951 //Qt likes to append the number of bits (usedBits?) to the algorithm, 00952 //for example "AES(256)". We only want the pure algorithm name, though. 00953 int parenIdx = d->encryptionMethod.indexOf(QLatin1Char('(')); 00954 if (parenIdx > 0) 00955 d->encryptionMethod.truncate(parenIdx); 00956 d->keyExchangeMethod = qsc.keyExchangeMethod(); 00957 d->name = qsc.name(); 00958 d->isNull = qsc.isNull(); 00959 d->supportedBits = qsc.supportedBits(); 00960 d->usedBits = qsc.usedBits(); 00961 } 00962 00963 00964 KSslCipher::~KSslCipher() 00965 { 00966 delete d; 00967 } 00968 00969 00970 KSslCipher &KSslCipher::operator=(const KSslCipher &other) 00971 { 00972 *d = *other.d; 00973 return *this; 00974 } 00975 00976 00977 bool KSslCipher::isNull() const 00978 { 00979 return d->isNull; 00980 } 00981 00982 00983 QString KSslCipher::authenticationMethod() const 00984 { 00985 return d->authenticationMethod; 00986 } 00987 00988 00989 QString KSslCipher::encryptionMethod() const 00990 { 00991 return d->encryptionMethod; 00992 } 00993 00994 00995 QString KSslCipher::keyExchangeMethod() const 00996 { 00997 return d->keyExchangeMethod; 00998 } 00999 01000 01001 QString KSslCipher::digestMethod() const 01002 { 01003 //### This is not really backend neutral. It works for OpenSSL and 01004 // for RFC compliant names, though. 01005 if (d->name.endsWith(QLatin1String("SHA"))) 01006 return QString::fromLatin1("SHA-1"); 01007 else if (d->name.endsWith(QLatin1String("MD5"))) 01008 return QString::fromLatin1("MD5"); 01009 else 01010 return QString::fromLatin1(""); // ## probably QString() is enough 01011 } 01012 01013 01014 QString KSslCipher::name() const 01015 { 01016 return d->name; 01017 } 01018 01019 01020 int KSslCipher::supportedBits() const 01021 { 01022 return d->supportedBits; 01023 } 01024 01025 01026 int KSslCipher::usedBits() const 01027 { 01028 return d->usedBits; 01029 } 01030 01031 01032 //static 01033 QList<KSslCipher> KSslCipher::supportedCiphers() 01034 { 01035 QList<KSslCipher> ret; 01036 QList<QSslCipher> candidates = QSslSocket::supportedCiphers(); 01037 foreach(const QSslCipher &c, candidates) { 01038 ret.append(KSslCipher(c)); 01039 } 01040 return ret; 01041 } 01042 01043 01044 KSslErrorUiData::KSslErrorUiData() 01045 : d(new Private()) 01046 { 01047 d->usedBits = 0; 01048 d->bits = 0; 01049 } 01050 01051 01052 KSslErrorUiData::KSslErrorUiData(const KTcpSocket *socket) 01053 : d(new Private()) 01054 { 01055 d->certificateChain = socket->peerCertificateChain(); 01056 d->sslErrors = socket->sslErrors(); 01057 d->ip = socket->peerAddress().toString(); 01058 d->host = socket->peerName(); 01059 d->sslProtocol = socket->negotiatedSslVersionName(); 01060 d->cipher = socket->sessionCipher().name(); 01061 d->usedBits = socket->sessionCipher().usedBits(); 01062 d->bits = socket->sessionCipher().supportedBits(); 01063 } 01064 01065 01066 KSslErrorUiData::KSslErrorUiData(const KSslErrorUiData &other) 01067 : d(new Private(*other.d)) 01068 {} 01069 01070 01071 KSslErrorUiData &KSslErrorUiData::operator=(const KSslErrorUiData &other) 01072 { 01073 *d = *other.d; 01074 return *this; 01075 } 01076 01077 01078 #include "ktcpsocket.moc"
KDE 4.6 API Reference