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