⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qtsslsocket.cpp

📁 Qtopia下的邮件处理程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        if (!lib->SSL_CTX_use_certificate_file(d->ctx, QFile::encodeName(d->cert).constData(), SSL_FILETYPE_PEM)) {            setErrorString(tr("Error loading certificate, %1").arg(SSL_ERRORSTR()));            emit error(UnknownSocketError);            return false;        }        // Load private key        if (!lib->SSL_CTX_use_PrivateKey_file(d->ctx, QFile::encodeName(d->key).constData(), SSL_FILETYPE_PEM)) {            setErrorString(tr("Error loading private key, %1").arg(SSL_ERRORSTR()));            emit error(UnknownSocketError);            return false;        }        // Check if the certificate matches the private key.        if  (!lib->SSL_CTX_check_private_key(d->ctx)) {            setErrorString(tr("Private key do not certificate public key, %1").arg(SSL_ERRORSTR()));            emit error(UnknownSocketError);            return false;        }    }    if (!d->cafile.isEmpty() || !d->cadir.isEmpty()) {        // Load trusted certificate authority (CA) certificates.        if (!lib->SSL_CTX_load_verify_locations(d->ctx,                                           d->cafile.isEmpty() ? 0 : QFile::encodeName(d->cafile).constData(),                                           d->cadir.isEmpty() ? 0 : QFile::encodeName(d->cadir).constData())) {            setErrorString(tr("Failed to load the list of trusted CAs").arg(SSL_ERRORSTR()));            emit error(UnknownSocketError);            return false;        }        // Prior to 0.9.6, OpenSSL was unable to determine whether or        // not a certificate came from a CA or not. We need to set the        // verify depth to 1 in those cases, so that only root level        // CAs are accepted for signing certificates.#if OPENSSL_VERSION_NUMBER < 0x00906000L        lib->SSL_CTX_set_verify_depth(d->ctx, 1);#endif    }    // Create and initialize SSL session    if (!(d->ssl = lib->SSL_new(d->ctx))) {        setErrorString(tr("Error creating SSL session, %1").arg(SSL_ERRORSTR()));        emit error(UnknownSocketError);        return false;    }    lib->SSL_clear(d->ssl);    // Have the SSL library read from a memory location. We will store    // encrypted data in the write buffer, and read decrypted data    // from the read buffer.    d->rbio = lib->BIO_new(lib->BIO_s_mem());    d->wbio = lib->BIO_new(lib->BIO_s_mem());    if (!d->rbio || !d->wbio) {        setErrorString(tr("Error creating SSL session"));        emit error(UnknownSocketError);        return false;    }    lib->SSL_set_bio(d->ssl, d->rbio, d->wbio);    if (d->mode == Server)        lib->SSL_set_accept_state(d->ssl);    else        lib->SSL_set_connect_state(d->ssl);#if QT_VERSION >= 0x040100    setPeerAddress(d->socket->peerAddress());    setPeerPort(d->socket->peerPort());    setPeerName(d->socket->peerName());    setLocalAddress(d->socket->localAddress());    setLocalPort(d->socket->localPort());#endif    // It is required that there is no data in the any output buffer    // when the SSL library takes over communication. Subclasses with    // buffers should reimplement flush.    d->socket->flush();    d->initialized = true;    return true;}/*!    \internal*/void QtSslSocket::handleSocketError(SocketError socketError){    setErrorString(d->socket->errorString());    emit error(socketError);}/*!    \internal*/void QtSslSocket::readFromSocket(){    QByteArray block = d->socket->readAll();    if (lib->BIO_write(d->rbio, block.data(), block.size()) != block.size()) {        setErrorString(tr("Failed to write protocol data to BIO"));        emit error(UnknownSocketError);        return;    }    if (!d->connectionSecured) {        if (d->mode == Client && sslConnect()) {            emit connected();        } else if (d->mode == Server && sslAccept()) {            emit connected();        }        writeToSocket();    }    // The connected() and accepted() signals can be connected to    // slots that close the socket. We don't want to read more data    // from the SSL buffers if the socket is closing.    if (d->socket->state() == ClosingState || d->socket->state() == UnconnectedState) {#ifdef QTSSLSOCKET_DEBUG        qDebug() << "QtSslSocket::readFromSocket(), socket is closing";#endif        return;    }    int ret = 0;    do {        char buffer[SslReadBlockSize];        ret = lib->SSL_read(d->ssl, buffer, sizeof(buffer));        if (ret <= 0) {            if (ret < 0 && lib->SSL_get_error(d->ssl, ret) == SSL_ERROR_WANT_READ) {                // If a renegotiation is taking place, we will not be able to                // read data. Rather we must submit whatever is in our                // outbound queue (placed by SSL_read) to complete the                // handshake. Note that this condition is also met when                // SSL_read is called and there is no pending data.                writeToSocket();            } else if (ret == 0) {                // The read operation was not successful, probably because no                // data was available or the remote host closed the                // connection.                if (lib->SSL_get_error(d->ssl, 0) == SSL_ERROR_ZERO_RETURN) {#ifdef QTSSLSOCKET_DEBUG                    qDebug() << "QtSslSocket::readFromSocket(), failed to read";#endif                    d->socket->disconnectFromHost();                } else {                    setErrorString(tr("Failed to read from SSL, %1")                                   .arg(SSL_ERRORSTR()));                    emit error(UnknownSocketError);                }            } else {                setErrorString(tr("Failed to read from SSL, %1")                               .arg(SSL_ERRORSTR()));                emit error(UnknownSocketError);            }            break;        }#ifdef QTSSLSOCKET_DEBUG        qDebug() << "QtSslSocket::readFromSocket(), read" << ret << "bytes";#endif        char *ptr = d->readBuffer.reserve(ret);        memcpy(ptr, buffer, ret);        emit readyRead();        d->readyReadEmitted = true;    } while (ret > 0);}/*!    \internal*/void QtSslSocket::writeToSocket(){    d->calledWriteToSocket = false;    if (d->connectionSecured) {        while (!d->writeBuffer.isEmpty()) {            int ret = lib->SSL_write(d->ssl, d->writeBuffer.readPointer(), d->writeBuffer.nextDataBlockSize());            if (ret <= 0) {                setErrorString(tr("SSL error: %1").arg(SSL_ERRORSTR()));                emit error(UnknownSocketError);                return;            }            d->writeBuffer.free(ret);        }    }                    int pending = (int)lib->BIO_ctrl(d->wbio,BIO_CTRL_PENDING,0,NULL);    if (pending > 0) {        QByteArray buffer;        buffer.resize(pending);        // With BIO_s_mem(), BIO_read can not fail.        lib->BIO_read(d->wbio, buffer.data(), buffer.size());        d->socket->write(buffer);#ifdef QTSSLSOCKET_DEBUG        qDebug() << "QtSslSocket::writeToSocket(), wrote" << buffer.size() << "bytes";#endif    }}/*!    \internal*/void QtSslSocket::socketBytesWritten(qint64 bytes){    emit bytesWritten(bytes);}/*!    \internal*/QString QtSslSocket::verifyErrorString(int err){    // Comments from man verify(1)    switch (err) {        case X509_V_OK:            // the operation was successful.            return tr("An unknown error occurred");        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:            // the passed certificate is self signed and the same            // certificate cannot be found in the list of trusted            // certificates.            return tr("Self signed certificate");        case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:            // the certificate chain could be built up using the            // untrusted certificates but the root could not be found            // locally.            return tr("Self signed certificate in certificate chain");        case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:            // the certificate signature could not be decrypted. This            // means that the actual signature value could not be            // determined rather than it not matching the expected            // value, this is only meaningful for RSA keys.            return tr("Unable to decrypt certificate's signature");        case X509_V_ERR_CERT_SIGNATURE_FAILURE:            // the signature of the certificate is invalid.            return tr("Certificate signature failure");        case X509_V_ERR_CERT_NOT_YET_VALID:            // the certificate is not yet valid: the notBefore date is            // after the current time.            return tr("The certificate is not yet valid");        case X509_V_ERR_CERT_HAS_EXPIRED:            // the certificate has expired: that is the notAfter date            // is before the current time.            return tr("The certificate has expired");        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:            // the certificate notBefore field contains an invalid            // time.            return tr("Format error in certificate's notBefore field");        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:            // the certificate notAfter field contains an invalid            // time.            return tr("Format error in certificate's notAfter field");        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:            // the issuer certificate of a locally looked up            // certificate could not be found. This normally means            // the list of trusted certificates is not complete.            return tr("Unable to get local issuer certificate");        case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:            // no signatures could be verified because the chain            // contains only one certificate and it is not self            // signed.            return tr("Unable to verify the first certificate");        case X509_V_ERR_INVALID_CA:            // a CA certificate is invalid. Either it is not a CA or            // its extensions are not consistent with the supplied            // purpose            return tr("Invalid CA certificate");        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:            // the issuer certificate could not be found: this occurs            // if the issuer certificate of an untrusted certificate            // cannot be found.            return tr("Unable to get issuer certificate");        case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:            // the public key in the certificate SubjectPublicKeyInfo            // could not be read.            return tr("Unable to decode issuer public key");        case X509_V_ERR_PATH_LENGTH_EXCEEDED:            // the basicConstraints pathlength parameter has been            // exceeded.            return tr("Path length constraint exceeded");        case X509_V_ERR_INVALID_PURPOSE:            // the supplied certificate cannot be used for the            // specified purpose.            return tr("Unsupported certificate purpose");        case X509_V_ERR_CERT_UNTRUSTED:            // the root CA is not marked as trusted for the specified            // purpose.            return tr("Certificate not trusted");        case X509_V_ERR_CERT_REJECTED:            // the root CA is marked to reject the specified purpose.            return tr("Certificate rejected");        case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:            // the current candidate issuer certificate was rejected            // because its subject name did not match the issuer name            // of the current certificate.            return tr("Subject issuer mismatch");        case X509_V_ERR_AKID_SKID_MISMATCH:            // the current candidate issuer certificate was rejected            // because its subject key identifier was present and did            // not match the authority key identifier current            // certificate.            return tr("Authority and subject key identifier mismatch");        case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:            // the current candidate issuer certificate was rejected            // because its issuer name and serial number was present            // and did not match the authority key identifier of the            // current certificate.            return tr("Authority and issuer serial number mismatch");        case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:            // the current candidate issuer certificate was rejected            // because its keyUsage extension does not permit            // certificate signing.            return tr("Key usage does not include certificate signing");        case X509_V_ERR_OUT_OF_MEM:            // an error occurred trying to allocate memory. This            // should never happen.            return tr("Out of memory");        default:            return tr("Unknown error");    }}/*! \internal    If \a accept is true, this function will attempt to negotiate a    server side handshake with the remote client, otherwise it will    negotiate a client side handshake with the remote server.*/bool QtSslSocket::sslAcceptOrConnect(bool accept){    if (!d->initialized && !initSsl())        return false;    // SSL connect (handshake). Note that during the handshake, the    // verify callback is called and it might emit warnings.    int result = accept ? lib->SSL_accept(d->ssl) : lib->SSL_connect(d->ssl);    if (result <= 0) {        if (result < 0) {            int err = lib->SSL_get_error(d->ssl, result);            if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {                // The handshake is not yet complete.                writeToSocket();                return false;            }        }        setErrorString(tr("SSL error: %1").arg(SSL_ERRORSTR()));        emit error(UnknownSocketError);        return false;    }    // Parse certificate    QStringList items = peerCertificate().split('/');    QString certHost;    QDateTime notValidBefore;    QDateTime notValidAfter;    for (int i = 0; i < (int) items.count(); ++i) {        QString s = items.at(i);        if (s.startsWith("CN="))            certHost = s.mid(3);        else if (s.startsWith("notValidBefore="))            notValidBefore = QDateTime::fromString(s.mid(15), Qt::ISODate);        else if (s.startsWith("notValidAfter="))            notValidAfter = QDateTime::fromString(s.mid(14), Qt::ISODate);    }    // Check if the certificate was verified. Note that err is    // X509_V_OK also if the peer had no certificate.    int err = lib->SSL_get_verify_result(d->ssl);    if (err != X509_V_OK) {        VerifyResult res = VerifyOk;        switch (err) {        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:        case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:            res = SelfSigned;            break;        default:            res = UnableToVerify;        }        emit connectionVerificationDone(res, certHost.toLower() != d->socket->peerName().toLower(),                                        verifyErrorString(err));    } else {        QString errorString = tr("The SSL certificate has been verified");        VerifyResult result = VerifyOk;        if (notValidBefore > QDateTime::currentDateTime()) {            result = NotYetValid;            errorString = tr("The SSL certificate is not valid until %1").arg(notValidBefore.toString());        } else if (notValidAfter < QDateTime::currentDateTime()) {            result = Expired;            errorString = tr("The SSL certificate expired on %1").arg(notValidAfter.toString());        }        if (certHost.toLower() != d->socket->peerName().toLower()) {            errorString += tr(", %1 ").arg(result == VerifyOk ? "but" : "and");            errorString += tr("the host name \"%0\" doesn't match the host name in the certificate \"%1\"")                           .arg(d->socket->peerName()).arg(certHost);        }        emit connectionVerificationDone(result,certHost.toLower() != d->socket->peerName().toLower(),                                        errorString);    }    if (d->socket->state() != ConnectedState) {#ifdef QTSSLSOCKET_DEBUG        qDebug() << "QtSslSocket::sslAcceptOrConnect(), socket not connected";#endif        return false;    }#ifdef QTSSLSOCKET_DEBUG    qDebug() << "QtSslSocket::sslAcceptOrConnect(), connected!" << d->socket->bytesAvailable() << d->socket->bytesToWrite() << d->writeBuffer.size() << d->readBuffer.size();#endif    setSocketState(ConnectedState);    emit stateChanged(ConnectedState);    d->connectionSecured = true;    readFromSocket();    return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -