KDECore
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 public: 00241 //from QAbstractSocket 00242 void abort(); 00243 void connectToHost(const QString &hostName, quint16 port, ProxyPolicy policy = AutoProxy); 00244 void connectToHost(const QHostAddress &hostAddress, quint16 port, ProxyPolicy policy = AutoProxy); 00245 00252 void connectToHost(const KUrl &url, ProxyPolicy policy = AutoProxy); 00253 void disconnectFromHost(); 00254 Error error() const; //### QAbstractSocket's model is strange. error() should be related to the 00255 //current state and *NOT* just report the last error if there was one. 00256 QList<KSslError> sslErrors() const; //### the errors returned can only have a subset of all 00257 //possible QSslError::SslError enum values depending on backend 00258 bool flush(); 00259 bool isValid() const; 00260 QHostAddress localAddress() const; 00261 QHostAddress peerAddress() const; 00262 QString peerName() const; 00263 quint16 peerPort() const; 00264 void setVerificationPeerName(const QString& hostName); 00265 00266 #ifndef QT_NO_NETWORKPROXY 00267 00270 QNetworkProxy proxy() const; 00271 #endif 00272 qint64 readBufferSize() const; //probably hard to implement correctly 00273 00274 #ifndef QT_NO_NETWORKPROXY 00275 00278 void setProxy(const QNetworkProxy &proxy); //people actually seem to need it 00279 #endif 00280 void setReadBufferSize(qint64 size); 00281 State state() const; 00282 bool waitForConnected(int msecs = 30000); 00283 bool waitForDisconnected(int msecs = 30000); 00284 00285 //from QSslSocket 00286 void addCaCertificate(const QSslCertificate &certificate); 00287 // bool addCaCertificates(const QString &path, QSsl::EncodingFormat format = QSsl::Pem, 00288 // QRegExp::PatternSyntax syntax = QRegExp::FixedString); 00289 void addCaCertificates(const QList<QSslCertificate> &certificates); 00290 QList<QSslCertificate> caCertificates() const; 00291 QList<KSslCipher> ciphers() const; 00292 void connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite); 00293 // bool isEncrypted() const { return encryptionMode() != UnencryptedMode } 00294 QSslCertificate localCertificate() const; 00295 QList<QSslCertificate> peerCertificateChain() const; 00296 KSslKey privateKey() const; 00297 KSslCipher sessionCipher() const; 00298 void setCaCertificates(const QList<QSslCertificate> &certificates); 00299 void setCiphers(const QList<KSslCipher> &ciphers); 00300 //### void setCiphers(const QString &ciphers); //what about i18n? 00301 void setLocalCertificate(const QSslCertificate &certificate); 00302 void setLocalCertificate(const QString &fileName, QSsl::EncodingFormat format = QSsl::Pem); 00303 void setPrivateKey(const KSslKey &key); //implement 00304 void setPrivateKey(const QString &fileName, KSslKey::Algorithm algorithm = KSslKey::Rsa, 00305 QSsl::EncodingFormat format = QSsl::Pem, 00306 const QByteArray &passPhrase = QByteArray()); //TODO 00307 void setAdvertisedSslVersion(SslVersion version); 00308 SslVersion advertisedSslVersion() const; //always equal to last setSslAdvertisedVersion 00309 SslVersion negotiatedSslVersion() const; //negotiated version; downgrades are possible. 00310 QString negotiatedSslVersionName() const; 00311 bool waitForEncrypted(int msecs = 30000); 00312 00313 EncryptionMode encryptionMode() const; 00314 00322 QVariant socketOption(QAbstractSocket::SocketOption options) const; 00323 00331 void setSocketOption(QAbstractSocket::SocketOption options, const QVariant &value); 00332 00333 Q_SIGNALS: 00334 //from QAbstractSocket 00335 void connected(); 00336 void disconnected(); 00337 void error(KTcpSocket::Error); 00338 void hostFound(); 00339 #ifndef QT_NO_NETWORKPROXY 00340 void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator); 00341 #endif 00342 // only for raw socket state, SSL is separate 00343 void stateChanged(KTcpSocket::State); 00344 00345 //from QSslSocket 00346 void encrypted(); 00347 void encryptionModeChanged(EncryptionMode); 00348 void sslErrors(const QList<KSslError> &errors); 00349 00350 public Q_SLOTS: 00351 void ignoreSslErrors(); 00352 void startClientEncryption(); 00353 // void startServerEncryption(); //not implemented 00354 private: 00355 Q_PRIVATE_SLOT(d, void reemitReadyRead()) 00356 Q_PRIVATE_SLOT(d, void reemitSocketError(QAbstractSocket::SocketError)) 00357 Q_PRIVATE_SLOT(d, void reemitSslErrors(const QList<QSslError> &)) 00358 Q_PRIVATE_SLOT(d, void reemitStateChanged(QAbstractSocket::SocketState)) 00359 Q_PRIVATE_SLOT(d, void reemitModeChanged(QSslSocket::SslMode)) 00360 00361 //debugging H4X 00362 void showSslErrors(); 00363 00364 friend class KTcpSocketPrivate; 00365 KTcpSocketPrivate *const d; 00366 }; 00367 00368 00376 class KDECORE_EXPORT KSslErrorUiData 00377 { 00378 public: 00382 KSslErrorUiData(); 00386 KSslErrorUiData(const KTcpSocket *socket); 00387 KSslErrorUiData(const KSslErrorUiData &other); 00388 KSslErrorUiData &operator=(const KSslErrorUiData &); 00393 ~KSslErrorUiData(); 00394 class Private; 00395 private: 00396 friend class Private; 00397 Private *const d; 00398 }; 00399 00400 00401 #endif // KTCPSOCKET_H
KDE 4.7 API Reference