📄 qtsslsocket.cpp
字号:
// Set the path to the CA certificates socket->setPathToCACertDir("/etc/ssl/certs/"); // Connect the socket's signals to slots in our client // implementation. connect(socket, SIGNAL(connected()), this, SLOT(connectedToHost())); connect(socket, SIGNAL(readyRead()), this, SLOT(readData())); connect(socket, SIGNAL(disconnected()), this, SLOT(connectionClosed())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(inspectError(QAbstractSocket::SocketError))); connect(socket, SIGNAL(connectionVerificationDone(QtSslSocket::VerifyResult, bool, const QString &)), this, SLOT(checkCertError(QtSslSocket::VerifyResult, bool, const QString &))); // Initiate a connection. socket->connectToHost(host, port); } \endcode Use connectToHost() when connecting to an SSL server. QtSslSocket will eventually emit the connected() signal if the connection was established, or the error() signal if the connection failed. In the case of accepting incoming connections, one common approach is to create a subclass of QTcpServer and reimplement QTcpServer::incomingConnection(). In this function, create a QtSslSocket object and call setSocketDescriptor() passing the provided socketDescriptor. Connect QtSslSocket's signals to slots in the server class. The path to a file containing a PEM encoded certificate is set with setPathToCertificate(). The path to the private key file is set with setPathToPrivateKey(). Finally, call sslAccept() to establish the secure connection. When QtSslSocket emits \l connectionVerificationDone(), the SSL encrypted link is established. Example: \code void MyServer::incomingConnection(int socketDescriptor) { // Create a new socket and pass it a new QSocket socket = new QtSslSocket(QtSslSocket::Server, this); socket->setSocketDescriptor(socketDescriptor); // Set up the certificate and private key. socket->setPathToCertificate("/etc/ssl/servercert.pem"); socket->setPathToPrivateKey("/etc/ssl/serverkey.pem"); // Connect the socket's signals to slots in our server // implementation connect(socket, SIGNAL(disconnected()), this, SLOT(connectionClosed())); connect(socket, SIGNAL(readyRead()), this, SLOT(readData())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(error(QAbstractSocket::SocketError))); // Initiate SSL handshake. Eventually, QtSslSocket will emit // connectionVerificationDone. socket->sslAccept(); } \endcode In order to convert an existing socket into an SSL-encrypted socket (i.e., using the "STARTTLS" command or something similar), you can create a new QtSslSocket and then pass your existing socket to setSocket(). The original socket is assumed to be in ConnectedState. Most often clients, but sometimes also servers need a set of CA (Certificate Authority) certificates to verify the identity of their peer. Use setPathToCACertFile() and setPathToCACertDir() to point QtSslSocket to these certificates. CA certificates are usually bundled as part of any Unix distribution or Mac OS X as part of the OpenSSL package. On Windows, you can either use the bundle provided with OpenSSL, or export CA certificates from your web browser. In rare occasions, it also is useful to restrict the encryption ciphers available to the client or server with setCiphers(). This is mostly useful when debugging faulty connections. As mentioned, QtSslSocket emits connected() when the connection has been established and connectionVerificationDone() when the SSL handshake has been completed. Make sure to connect to error() and connectionVerificationDone() to catch errors. The readyRead() signal is emitted when there is new incoming data. Call read() to read the new data into a buffer. When disconnected() is emitted, the other peer has closed the connection. If the ceritificate check fails, it is often useful to display details about the failing certificate to the user. peerCertificate() returns information about this certificate. To get the local certificate, call localCertificate(). When building an application that uses QtSslSocket, you must link your application against the SSL library. Include the bundled .pri file, or add the following line to your .pro file, modified with the path to your installation of OpenSSL: \code unix:LIBS += -L/usr/lib -lssl -lcrypto win32:INCLUDEPATH += /openssl/include win32:LIBS += -L/openssl/lib ssleay32.lib libeay32.lib \endcode The pri file must be edited to set the paths of the SSL files. \i {Note: QtSslSocket requires OpenSSL. The OpenSSL toolkit is licensed under an Apache-style licence, which basically means that you are free to get and use it for commercial and non-commercial purposes subject to certain license conditions. The official web site is:} \l http://www.openssl.org/ \i {. Windows binaries are available from:} \l http://www.openssl.org/related/binaries.html \i {.} \i {Note: Since Qt 4.1, you can pass a QtSslSocket to QHttp by calling QHttp::setSocket() to achieve an SSL encrypted HTTP transport. (SSL over HTTP uses port 443.)} \sa QTcpSocket, QTcpServer*//*! \enum QtSslSocket::Mode Describes whether QtSslSocket is used on the client side or the server side. Pass a suitable value to QtSslSocket's constructor to ensure that the SSL handshake is performed correctly. \value Client QtSslSocket is used for a client side socket (i.e., you call connectToHost() to connect to a remote SSL server. \value Server QtSslSocket is used to handle a server side connection (i.e., someone connected to your server).*//*! \fn void QtSslSocket::connectionVerificationDone(QtSslSocket::VerifyResult result, bool hostNameMatched, const QString &description); This signal is emitted by QtSslSocket to notify that the SSL handshake has completed, and the connecion is ready for use. The result of the handshake is available through \a result, and in addition, \a hostNameMatched will be set to true if the hostname of the peer certificate matches the hostname passed to connectToHost(), or false if it doesn't. (For server-side connections, hostNameMatched is always true.) For displaying to the user, \a description contains a human readable description of the result of the certificate verification.*//*! \enum QtSslSocket::VerifyResult Describes the result of the SSL handshake. \value VerifyOk The certificate has been successfully verified, and the peer authenticity has been established. The connection is secure, and ready to use. \value SelfSigned The peer certificate is self-signed (i.e., does not use a certificate authority for verification). This means that the identity of the peer has not been established. Self-signed peer certificates provide no security beyond transport encryption, and should only be used on closed networks or for debugging. \value Expired The peer certificate has expired. This means that the associated certificate authority no longer guarantees the identity of the peer. An expired certificate provides no security beyond transport encryption, and the administrators of the remote server should be notified as soon as possible. \value NotYetValid The peer certificate is not valid yet (i.e., the "opposite" of Expired). It provides no security beyond transport encryption, and the administrators of the remote server should be notified as soon as possible. \value UnableToVerify This value signifies an error that was not covered by the other (non-VerifyOK) VerifyResult values. A common cause for the UnableToVerify value is that there is a technical fault on either side of the connection that prevents the handshake from completing, such as the server running out of diskspace, or the client running out of memory.*//*! Constructs a QtSslSocket running with mode \a mode. \a parent is passed to QTcpSocket's constructor.*/QtSslSocket::QtSslSocket(Mode mode, QObject *parent) : QTcpSocket(parent),lib(0), d(new QtSslSocketPrivate(this)){ d->mode = mode; d->socket = new QTcpSocket; d->initializeConnection(d->socket); //get the path to the SSL library QString libPath = Qtopia::qtopiaDir() + "lib/libssl.so"; lib = new SSLLibrary(libPath); lib->SSL_library_init(); lib->SSL_load_error_strings(); lib->OpenSSL_add_ssl_algorithms(); if (!lib->RAND_status()) { struct { int msec; int sec; void *stack; } randomish; randomish.stack = (void *)&randomish; randomish.msec = QTime::currentTime().msec(); randomish.sec = QTime::currentTime().second(); lib->RAND_seed(&randomish, sizeof(randomish)); }}/*! Destroys the QtSslSocket object.*/QtSslSocket::~QtSslSocket(){ delete d; delete lib;}/*! Initiates a connection to \a hostName on port \a port, using the open mode \a openMode. QtSslSocket will emit connected() when the connection has been established, and connectionVerificationDone() when the SSL handshake has completed and the socket is ready to use. Note: The implementation of this function invokes the slot connectToHostImplementation(). To alter its behavior, you should reimplement connectToHostImplementation() instead.*/void QtSslSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode){ QMetaObject::invokeMethod(this, "connectToHostImplementation", Q_ARG(QString, hostName), Q_ARG(quint16, port), Q_ARG(OpenMode, openMode));}/*! Initiates a disconnect from the remote host. Note: The implementation of this function invokes the disconnectFromHostImplementation() slot.*/void QtSslSocket::disconnectFromHost(){ QMetaObject::invokeMethod(this, "disconnectFromHostImplementation");}/*! Sets the path to a local file containing the client's certificate to \a path. This is useful for server side connections, or for clients that connect to servers that need to verify the peer identity (client verification is not yet supported by QtSslSocket). \sa pathToCertificate()*/void QtSslSocket::setPathToCertificate(const QString &path){ d->cert = path;}/*! Returns the path to the client's certificate. \sa setPathToCertificate()*/QString QtSslSocket::pathToCertificate() const{ return d->cert;}/*! Sets the path the a local file containing the client's private key to \a path. This is useful for server side connections, or for clients that connect to servers that need to verify the peer identity (client verification is not yet supported by QtSslSocket). \sa pathToPrivateKey()*/void QtSslSocket::setPathToPrivateKey(const QString &path){ d->key = path;}/*! Returns the path to the client's private key. \sa setPathToPrivateKey()*/QString QtSslSocket::pathToPrivateKey() const{ return d->key;}/*! Sets the path to a local file containing a bundle of CA certificates to \a path. You can either use the bundle that comes with OpenSSL, or use a bundle exported by your web browser. This CA bundle is necessary for verifying the authenticity of the remote peer. Without such a bundle, QtSslSocket can never verify the peer's identity, but it will still encrypt the transferred data. \sa pathToCACertFile()*/void QtSslSocket::setPathToCACertFile(const QString &path){ d->cafile = path;}/*! Returns the path to a local file containing a bundle of CA certificates. \sa setPathToCACertFile() */QString QtSslSocket::pathToCACertFile() const{ return d->cafile;}/*! Sets the path to a local directory containing files with CA certificates to \a path. This directory is generated by OpenSSL using the program "c_rehash", and is often installed by default as part of installing OpenSSL. It's common to use a CA directory containing several CA files instead of using only a single CA file, as you can then add more CA files without interfering with ones provided by the operating system, your web browser or by OpenSSL. \sa pathToCACertDir(), setPathToCACertFile()*/void QtSslSocket::setPathToCACertDir(const QString &path){ d->cadir = path;}/*! Returns the path to a locale directory containing files with CA certificates. \sa setPathToCACertDir()*/QString QtSslSocket::pathToCACertDir() const{ return d->cadir;}/*! Sets the list of ciphers QtSslSocket will advertise to the remote peer during the SSL handshake. This effectively limits the ciphers QtSslSocket can use, and is therefore mostly useful for debugging the SSL handshake. \a ciphers contains a list of ciphers listed by name, separated by a ':', and listed in descending order from the most secure to the least secure cipher. The default behavior for QtSslSocket is to advertise all available ciphers to the remote peer, thereby maximizing the chance that a secure connection can be established. \sa ciphers()*/void QtSslSocket::setCiphers(const QString &ciphers){ d->ciph = ciphers;}/*! Returns the list of ciphers QtSslSocket will advertise to the remote peer during the SSL handshake. \sa setCiphers()*/QString QtSslSocket::ciphers() const{ return d->ciph;}//==============================================================================// contributed by Jay Case of Sarvega, Inc.; http://sarvega.com/// Based on X509_cmp_time() for intitial buffer hacking.//==============================================================================static time_t getTimeFromASN1(const ASN1_TIME *aTime){ time_t lResult = 0; char lBuffer[24]; char *pBuffer = lBuffer; size_t lTimeLength = aTime->length; char *pString = (char *) aTime->data; if (aTime->type == V_ASN1_UTCTIME) { if ((lTimeLength < 11) || (lTimeLength > 17)) return 0; memcpy(pBuffer, pString, 10); pBuffer += 10; pString += 10; } else { if (lTimeLength < 13) return 0; memcpy(pBuffer, pString, 12); pBuffer += 12; pString += 12; } if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) { *pBuffer++ = '0'; *pBuffer++ = '0'; } else { *pBuffer++ = *pString++; *pBuffer++ = *pString++; // Skip any fractional seconds... if (*pString == '.') { pString++; while ((*pString >= '0') && (*pString <= '9')) pString++; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -