On 04/29/2014 01:13 PM, Sorvig Morten wrote:
> QSSLSocket/QSslCertificate/QSslCipher is a relatively large API - make sure 
> you are aware of the scope of the project and remember you have to maintain 
> it :)

I definitely realise implementing the whole of the API is a large task.
However, just getting a basic QSslSocket to work seems doable. So far I
have been able to get as far as a successful client handshake with few
lines of code using Apple's "Secure Transport" API:

https://developer.apple.com/library/ios/documentation/Security/Reference/secureTransportRef/Reference/reference.html

For now I am implementing a rough proof of concept (attached) outside Qt
by subclassing QTcpSocket the way QSslSocket does .

Cheers,
Jeremy
#include <Security/Security.h>
#include <QTcpSocket>

class FooSocket : public QTcpSocket
{
    Q_OBJECT

public:
    FooSocket(QObject *parent = 0);
    ~FooSocket();

    void connectToHostEncrypted(const QString &hostName, quint16 port);
    void startClientEncryption();

signals:
    void encrypted();

private slots:
    void _q_connectedSlot();
    void _q_readyReadSlot();

private:
    void tryHandshake();

    bool autoStartHandshake;
    bool inHandshake;
    SSLContextRef ctx;
    QTcpSocket *plainSocket;
};
#include <Security/Security.h>

#include "foosocket.h"

OSStatus _q_SSLRead(QTcpSocket *plainSocket, char *data, size_t *dataLength)
{
    if ((size_t)plainSocket->bytesAvailable() < *dataLength) {
        *dataLength = 0;
        return errSSLWouldBlock;
    }
    qint64 bytes = plainSocket->read(data, *dataLength);
    *dataLength = bytes;
    return 0;
}

OSStatus _q_SSLWrite(QTcpSocket *plainSocket, const char *data, size_t *dataLength)
{
    plainSocket->write(data, *dataLength);
    return 0;
}

FooSocket::FooSocket(QObject *parent)
    : QTcpSocket(parent)
    , autoStartHandshake(false)
    , inHandshake(false)
{
    plainSocket = new QTcpSocket(this);
    connect(plainSocket, &QTcpSocket::connected,
            this, &FooSocket::_q_connectedSlot);
    connect(plainSocket, &QTcpSocket::readyRead,
            this, &FooSocket::_q_readyReadSlot);

    ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
    SSLSetIOFuncs(ctx, (SSLReadFunc)&_q_SSLRead, (SSLWriteFunc)&_q_SSLWrite);
    SSLSetConnection(ctx, plainSocket);
}

FooSocket::~FooSocket()
{
    CFRelease(ctx);
}

void FooSocket::connectToHostEncrypted(const QString &hostName, quint16 port)
{
    autoStartHandshake = true;
    plainSocket->connectToHost(hostName, port);
}

void FooSocket::startClientEncryption()
{
    if (!inHandshake) {
        inHandshake = true;
        tryHandshake();
    }
}

void FooSocket::tryHandshake()
{
    OSStatus err = SSLHandshake(ctx);
    if (err == noErr) {
        qWarning("handshake succeeded");
        inHandshake = false;
        emit encrypted();
    } else if (err != errSSLWouldBlock) {
        qWarning("handshake failed!");
        inHandshake = false;
    }
}

void FooSocket::_q_connectedSlot()
{
    qDebug("connected");
    if (autoStartHandshake) {
        startClientEncryption();
    }
}

void FooSocket::_q_readyReadSlot()
{
    if (inHandshake) {
        tryHandshake();
    }
}
_______________________________________________
Development mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/development

Reply via email to