Russian Qt Forum

Qt => Работа с сетью => Тема начата: Magvaj от Июль 30, 2009, 21:20



Название: QSslSocket Клиент-сервер
Отправлено: Magvaj от Июль 30, 2009, 21:20
Нелепая проблема, но никак не могу найти решение.

Делаю по докам: переопределил QTcpServer::incomingConnection():

Код:
void SslServer::incomingConnection(int socketDescriptor)
{
    QSslSocket *serverSocket=new QSslSocket(this);
    if(serverSocket->setSocketDescriptor(socketDescriptor))
    {
        QObject::connect(serverSocket, SIGNAL(encrypted()), this, SLOT(socketReady()));
        QObject::connect(serverSocket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(socketSslErrors(const QList<QSslError> &)));
        QObject::connect(serverSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
        serverSocket->startServerEncryption();
    }
    else
    {
        delete serverSocket;
    }
}

На стороне клиента создаю сокет и подсоединяюсь(всё по докам):

Код:
    socket=new QSslSocket(this);
    QObject::connect(socket, SIGNAL(encrypted()), this, SLOT(socketReady()));
    QObject::connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(socketSslErrors(const QList<QSslError> &)));
    QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
    socket->connectToHostEncrypted(this->serverHost, this->serverPort);

Что только не делал выдаёт ошибку:
Error during SSL handshake: error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher

Что это и как это исправить?


Название: Re: QSslSocket Клиент-сервер
Отправлено: VAP от Июль 30, 2009, 23:17
 Возможно ошибка криптографии. Полезный материал по теме здесь: http://lists.trolltech.com/qt4-preview-feedback/2007-05/thread00001-0.html


Название: Re: QSslSocket Клиент-сервер
Отправлено: Magvaj от Июль 31, 2009, 09:07
почитал.. там идёт явная установка ключа и сертификата... я же ничего не устанавливаю... без этого же можно обойтись?


Название: Re: QSslSocket Клиент-сервер
Отправлено: Magvaj от Июль 31, 2009, 11:43
попробовал с сертификатами- та же лажа:


вот код сервера:
Код:
#include "sslserver.h"
#include <QSslConfiguration>
#include <QFile>

SslServer::SslServer(QObject *parent): QTcpServer(parent)
{

}

void SslServer::socketReady()
{
    qDebug("Connected!");
}

void SslServer::socketSslErrors(const QList<QSslError> &errors)
{
    emit logString(qobject_cast<QSslSocket*>(sender())->errorString(), SSLSERVER_LOG_ERROR);
}

void SslServer::socketError(QAbstractSocket::SocketError socketError)
{
    emit logString(qobject_cast<QSslSocket*>(sender())->errorString(), SSLSERVER_LOG_ERROR);
}

void SslServer::incomingConnection(int socketDescriptor)
{
    QSslSocket *serverSocket=new QSslSocket(this);
    if(serverSocket->setSocketDescriptor(socketDescriptor))
    {

        QSslConfiguration a;
        QFile *f=new QFile("./RSA/server.crt");
        QFile *f1=new QFile("./RSA/server.key");
        f->open(QIODevice::ReadWrite);
        f1->open(QIODevice::ReadWrite);
        a.setCaCertificates(QSslCertificate::fromDevice(f));
        a.setPrivateKey(QSslKey(f1, QSsl::Rsa));
        f->close();
        f1->close();
        serverSocket->setSslConfiguration(a);
        serverSocket->setCiphers("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC4-SHA:RC4-MD5:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC4-MD5");

        QObject::connect(serverSocket, SIGNAL(encrypted()), this, SLOT(socketReady()));
        QObject::connect(serverSocket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(socketSslErrors(const QList<QSslError> &)));
        QObject::connect(serverSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
        serverSocket->startServerEncryption();
    }
    else
    {
     delete serverSocket;
    }
}

и клиента:
Код:
MegaConnector::MegaConnector()
{
    socket=new QSslSocket(this);
    QObject::connect(socket, SIGNAL(encrypted()), this, SLOT(socketReady()));
    QObject::connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(socketSslErrors(const QList<QSslError> &)));
    QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError)));
}

MegaConnector::~MegaConnector()
{
    delete socket;
}

void MegaConnector::connect()
{
    socket->connectToHostEncrypted(this->serverHost, this->serverPort);
}

void MegaConnector::socketReady()
{
    qDebug("Ready!");
}

void MegaConnector::socketSslErrors(const QList<QSslError> &errors)
{
    qDebug("SSL error");
}

void MegaConnector::socketError(QAbstractSocket::SocketError socketError)
{
    qDebug("Error");
    qDebug(QVariant(socketError).toString().toAscii());
    qDebug(socket->errorString().toAscii());
}

может кто посмотрит? может я вообще чтото нелепое упустил...


Название: Re: QSslSocket Клиент-сервер
Отправлено: denka от Июль 31, 2009, 11:59
Попробуй в MegaConnector::socketSslErrors вызвать QSslSocket::ignoreSslErrors


Название: Re: QSslSocket Клиент-сервер
Отправлено: Magvaj от Август 03, 2009, 10:06
Попробуй в MegaConnector::socketSslErrors вызвать QSslSocket::ignoreSslErrors


он туда даже не попадает... на клиенте ошибка сокета QAbstractSocket::RemoteHostClosedError, а на сервере QAbstractSocket::SslHandshakeFailedError


Название: Re: QSslSocket Клиент-сервер
Отправлено: Magvaj от Август 05, 2009, 08:31
решение было выпрошено у поддержки Qt. Питер Хартманн любезно объяснил причину возникновения сей ситуации, за что ему поклон.

Для того чтобы соединение проходило нормально, надо на сервере установить локальный сертификат и приватный ключ:

serverSocket->setPrivateKey("../rsa/server.key");
serverSocket->setLocalCertificate("../rsa/server.pem");

для каждого вновь созданного сокета...

Также было обещано включить сие в документацию, чтобы подобные вопросы больше не мучали умы людей ;-)

Вот оригинал конечного сообщения из переписки:


Цитировать
...In order to make SSL encryption work on the server side,
you need to set the local certificate and the private key. So you want
to do something like the following in your code:
----------------
    serverSocket->setPrivateKey("../rsa/server.key");
    serverSocket->setLocalCertificate("../rsa/server.pem");
----------------
Then it should work. In case you also get an error about wrong version
numbers, you can also set
----------------
    serverSocket->setProtocol(QSsl::AnyProtocol);
----------------
However, that might be a security risk and you probably only want to use
SSLv3 and TLS.
But I agree that this is not well documented, so I am planning to either
extend the documentation or just write a small SSL server example and
put that on the documentation pages, because you are not the first one
to ask about this...