ktcpsocket.h
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2007 Thiago Macieira <thiago@kde.org> 00003 Copyright (C) 2007 Andreas Hartmetz <ahartmetz@gmail.com> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #ifndef KTCPSOCKET_H 00022 #define KTCPSOCKET_H 00023 00024 #include <QtNetwork/QSslSocket> 00025 //#include <QtCore/QRegExp> 00026 00027 #include "kdecore_export.h" 00028 00029 /* 00030 Notes on QCA::TLS compatibility 00031 In order to check for all validation problems as far as possible we need to use: 00032 Validity QCA::TLS::peerCertificateValidity() 00033 TLS::IdentityResult QCA::TLS::peerIdentityResult() 00034 CertificateChain QCA::TLS::peerCertificateChain().validate() - to find the failing cert! 00035 TLS::Error QCA::TLS::errorCode() - for more generic (but stil SSL) errors 00036 */ 00037 00038 00039 class KSslKeyPrivate; 00040 00041 class KDECORE_EXPORT KSslKey { 00042 public: 00043 enum Algorithm { 00044 Rsa = 0, 00045 Dsa, 00046 Dh 00047 }; 00048 enum KeySecrecy { 00049 PublicKey, 00050 PrivateKey 00051 }; 00052 00053 KSslKey(); 00054 KSslKey(const KSslKey &other); 00055 KSslKey(const QSslKey &sslKey); 00056 ~KSslKey(); 00057 KSslKey &operator=(const KSslKey &other); 00058 00059 Algorithm algorithm() const; 00060 bool isExportable() const; 00061 KeySecrecy secrecy() const; 00062 QByteArray toDer() const; 00063 private: 00064 KSslKeyPrivate *const d; 00065 }; 00066 00067 00068 class KSslCipherPrivate; 00069 00070 class KDECORE_EXPORT KSslCipher { 00071 public: 00072 KSslCipher(); 00073 KSslCipher(const KSslCipher &other); 00074 KSslCipher(const QSslCipher &); 00075 ~KSslCipher(); 00076 KSslCipher &operator=(const KSslCipher &other); 00077 00078 bool isNull() const; 00079 QString authenticationMethod() const; 00080 QString encryptionMethod() const; 00081 QString keyExchangeMethod() const; 00082 QString digestMethod() const; 00083 /* mainly for internal use */ 00084 QString name() const; 00085 int supportedBits() const; 00086 int usedBits() const; 00087 00088 static QList<KSslCipher> supportedCiphers(); 00089 00090 private: 00091 KSslCipherPrivate *const d; 00092 }; 00093 00094 00095 class KSslErrorPrivate; 00096 class KTcpSocket; 00097 00098 class KDECORE_EXPORT KSslError 00099 { 00100 public: 00101 enum Error { 00102 NoError = 0, 00103 UnknownError, 00104 InvalidCertificateAuthorityCertificate, 00105 InvalidCertificate, 00106 CertificateSignatureFailed, 00107 SelfSignedCertificate, 00108 ExpiredCertificate, 00109 RevokedCertificate, 00110 InvalidCertificatePurpose, 00111 RejectedCertificate, 00112 UntrustedCertificate, 00113 NoPeerCertificate, 00114 HostNameMismatch, 00115 PathLengthExceeded 00116 }; 00117 KSslError(KSslError::Error error = NoError, const QSslCertificate &cert = QSslCertificate()); 00118 KSslError(const QSslError &error); //### explicit yes or no? 00119 KSslError(const KSslError &other); 00120 ~KSslError(); 00121 KSslError &operator=(const KSslError &other); 00122 00123 Error error() const; 00124 QString errorString() const; 00125 QSslCertificate certificate() const; 00126 private: 00127 KSslErrorPrivate *const d; 00128 }; 00129 00130 00131 //consider killing more convenience functions with huge signatures 00132 //### do we need setSession() / session() ? 00133 00134 //BIG FAT TODO: do we keep openMode() up to date everywhere it can change? 00135 00136 //other TODO: limit possible error strings?, SSL key stuff 00137 00138 //TODO protocol (or maybe even application?) dependent automatic proxy choice 00139 00140 class KTcpSocketPrivate; 00141 class QHostAddress; 00142 class KUrl; 00143 00144 class KDECORE_EXPORT KTcpSocket: public QIODevice 00145 { 00146 Q_OBJECT 00147 public: 00148 enum State { 00149 UnconnectedState = 0, 00150 HostLookupState, 00151 ConnectingState, 00152 ConnectedState, 00153 BoundState, 00154 ListeningState, 00155 ClosingState 00156 //hmmm, do we need an SslNegotiatingState? 00157 }; 00158 enum SslVersion { 00159 UnknownSslVersion = 0x01, 00160 SslV2 = 0x02, 00161 SslV3 = 0x04, 00162 TlsV1 = 0x08, 00163 SslV3_1 = 0x08, 00164 AnySslVersion = SslV2 | SslV3 | TlsV1 00165 }; 00166 Q_DECLARE_FLAGS(SslVersions, SslVersion) 00167 enum Error { 00168 UnknownError = 0, 00169 ConnectionRefusedError, 00170 RemoteHostClosedError, 00171 HostNotFoundError, 00172 SocketAccessError, 00173 SocketResourceError, 00174 SocketTimeoutError, 00175 NetworkError, 00176 UnsupportedSocketOperationError 00177 }; 00178 /* 00179 The following is based on reading the OpenSSL interface code of both QSslSocket 00180 and QCA::TLS. Barring oversights it should be accurate. The two cases with the 00181 question marks apparently will never be emitted by QSslSocket so there is nothing 00182 to compare. 00183 00184 QSslError::NoError KTcpSocket::NoError 00185 QSslError::UnableToGetIssuerCertificate QCA::ErrorSignatureFailed 00186 QSslError::UnableToDecryptCertificateSignature QCA::ErrorSignatureFailed 00187 QSslError::UnableToDecodeIssuerPublicKey QCA::ErrorInvalidCA 00188 QSslError::CertificateSignatureFailed QCA::ErrorSignatureFailed 00189 QSslError::CertificateNotYetValid QCA::ErrorExpired 00190 QSslError::CertificateExpired QCA::ErrorExpired 00191 QSslError::InvalidNotBeforeField QCA::ErrorExpired 00192 QSslError::InvalidNotAfterField QCA::ErrorExpired 00193 QSslError::SelfSignedCertificate QCA::ErrorSelfSigned 00194 QSslError::SelfSignedCertificateInChain QCA::ErrorSelfSigned 00195 QSslError::UnableToGetLocalIssuerCertificate QCA::ErrorInvalidCA 00196 QSslError::UnableToVerifyFirstCertificate QCA::ErrorSignatureFailed 00197 QSslError::CertificateRevoked QCA::ErrorRevoked 00198 QSslError::InvalidCaCertificate QCA::ErrorInvalidCA 00199 QSslError::PathLengthExceeded QCA::ErrorPathLengthExceeded 00200 QSslError::InvalidPurpose QCA::ErrorInvalidPurpose 00201 QSslError::CertificateUntrusted QCA::ErrorUntrusted 00202 QSslError::CertificateRejected QCA::ErrorRejected 00203 QSslError::SubjectIssuerMismatch QCA::TLS::InvalidCertificate ? 00204 QSslError::AuthorityIssuerSerialNumberMismatch QCA::TLS::InvalidCertificate ? 00205 QSslError::NoPeerCertificate QCA::TLS::NoCertificate 00206 QSslError::HostNameMismatch QCA::TLS::HostMismatch 00207 QSslError::UnspecifiedError KTcpSocket::UnknownError 00208 QSslError::NoSslSupport Never happens :) 00209 */ 00210 enum EncryptionMode { 00211 UnencryptedMode = 0, 00212 SslClientMode, 00213 SslServerMode //### not implemented 00214 }; 00215 enum ProxyPolicy { 00217 AutoProxy = 0, 00219 ManualProxy 00220 }; 00221 00222 KTcpSocket(QObject *parent = 0); 00223 ~KTcpSocket(); 00224 00225 //from QIODevice 00226 //reimplemented virtuals - the ones not reimplemented are OK for us 00227 virtual bool atEnd() const; 00228 virtual qint64 bytesAvailable() const; 00229 virtual qint64 bytesToWrite() const; 00230 virtual bool canReadLine() const; 00231 virtual void close(); 00232 virtual bool isSequential() const; 00233 virtual bool open(QIODevice::OpenMode open); 00234 virtual bool waitForBytesWritten(int msecs); 00235 //### Document that this actually tries to read *more* data 00236 virtual bool waitForReadyRead(int msecs = 30000); 00237 protected: 00238 virtual qint64 readData (char *data, qint64 maxSize); 00239 virtual qint64 writeData (const char *data, qint64 maxSize); 00240 signals: 00243 void encryptedBytesWritten( qint64 written ); 00244 public: 00245 //from QAbstractSocket 00246 void abort(); 00247 void connectToHost(const QString &hostName, quint16 port, ProxyPolicy policy = AutoProxy); 00248 void connectToHost(const QHostAddress &hostAddress, quint16 port, ProxyPolicy policy = AutoProxy); 00249 00256 void connectToHost(const KUrl &url, ProxyPolicy policy = AutoProxy); 00257 void disconnectFromHost(); 00258 Error error() const; //### QAbstractSocket's model is strange. error() should be related to the 00259 //current state and *NOT* just report the last error if there was one. 00260 QList<KSslError> sslErrors() const; //### the errors returned can only have a subset of all 00261 //possible QSslError::SslError enum values depending on backend 00262 bool flush(); 00263 bool isValid() const; 00264 QHostAddress localAddress() const; 00265 QHostAddress peerAddress() const; 00266 QString peerName() const; 00267 quint16 peerPort() const; 00268 void setVerificationPeerName(const QString& hostName); 00269 00270 #ifndef QT_NO_NETWORKPROXY 00271 00274 QNetworkProxy proxy() const; 00275 #endif 00276 qint64 readBufferSize() const; //probably hard to implement correctly 00277 00278 #ifndef QT_NO_NETWORKPROXY 00279 00282 void setProxy(const QNetworkProxy &proxy); //people actually seem to need it 00283 #endif 00284 void setReadBufferSize(qint64 size); 00285 State state() const; 00286 bool waitForConnected(int msecs = 30000); 00287 bool waitForDisconnected(int msecs = 30000); 00288 00289 //from QSslSocket 00290 void addCaCertificate(const QSslCertificate &certificate); 00291 // bool addCaCertificates(const QString &path, QSsl::EncodingFormat format = QSsl::Pem, 00292 // QRegExp::PatternSyntax syntax = QRegExp::FixedString); 00293 void addCaCertificates(const QList<QSslCertificate> &certificates); 00294 QList<QSslCertificate> caCertificates() const; 00295 QList<KSslCipher> ciphers() const; 00296 void connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite); 00297 // bool isEncrypted() const { return encryptionMode() != UnencryptedMode } 00298 QSslCertificate localCertificate() const; 00299 QList<QSslCertificate> peerCertificateChain() const; 00300 KSslKey privateKey() const; 00301 KSslCipher sessionCipher() const; 00302 void setCaCertificates(const QList<QSslCertificate> &certificates); 00303 void setCiphers(const QList<KSslCipher> &ciphers); 00304 //### void setCiphers(const QString &ciphers); //what about i18n? 00305 void setLocalCertificate(const QSslCertificate &certificate); 00306 void setLocalCertificate(const QString &fileName, QSsl::EncodingFormat format = QSsl::Pem); 00307 void setPrivateKey(const KSslKey &key); //implement 00308 void setPrivateKey(const QString &fileName, KSslKey::Algorithm algorithm = KSslKey::Rsa, 00309 QSsl::EncodingFormat format = QSsl::Pem, 00310 const QByteArray &passPhrase = QByteArray()); //TODO 00311 void setAdvertisedSslVersion(SslVersion version); 00312 SslVersion advertisedSslVersion() const; //always equal to last setSslAdvertisedVersion 00313 SslVersion negotiatedSslVersion() const; //negotiated version; downgrades are possible. 00314 QString negotiatedSslVersionName() const; 00315 bool waitForEncrypted(int msecs = 30000); 00316 00317 EncryptionMode encryptionMode() const; 00318 00326 QVariant socketOption(QAbstractSocket::SocketOption options) const; 00327 00335 void setSocketOption(QAbstractSocket::SocketOption options, const QVariant &value); 00336 00337 Q_SIGNALS: 00338 //from QAbstractSocket 00339 void connected(); 00340 void disconnected(); 00341 void error(KTcpSocket::Error); 00342 void hostFound(); 00343 #ifndef QT_NO_NETWORKPROXY 00344 void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator); 00345 #endif 00346 // only for raw socket state, SSL is separate 00347 void stateChanged(KTcpSocket::State); 00348 00349 //from QSslSocket 00350 void encrypted(); 00351 void encryptionModeChanged(EncryptionMode); 00352 void sslErrors(const QList<KSslError> &errors); 00353 00354 public Q_SLOTS: 00355 void ignoreSslErrors(); 00356 void startClientEncryption(); 00357 // void startServerEncryption(); //not implemented 00358 private: 00359 Q_PRIVATE_SLOT(d, void reemitReadyRead()) 00360 Q_PRIVATE_SLOT(d, void reemitSocketError(QAbstractSocket::SocketError)) 00361 Q_PRIVATE_SLOT(d, void reemitSslErrors(const QList<QSslError> &)) 00362 Q_PRIVATE_SLOT(d, void reemitStateChanged(QAbstractSocket::SocketState)) 00363 Q_PRIVATE_SLOT(d, void reemitModeChanged(QSslSocket::SslMode)) 00364 00365 //debugging H4X 00366 void showSslErrors(); 00367 00368 friend class KTcpSocketPrivate; 00369 KTcpSocketPrivate *const d; 00370 }; 00371 00372 00380 class KDECORE_EXPORT KSslErrorUiData 00381 { 00382 public: 00386 KSslErrorUiData(); 00390 KSslErrorUiData(const KTcpSocket *socket); 00394 KSslErrorUiData(const QSslSocket *socket); 00395 KSslErrorUiData(const KSslErrorUiData &other); 00396 KSslErrorUiData &operator=(const KSslErrorUiData &); 00401 ~KSslErrorUiData(); 00402 class Private; 00403 private: 00404 friend class Private; 00405 Private *const d; 00406 }; 00407 00408 00409 #endif // KTCPSOCKET_H
KDE 4.8 API Reference