2004-11-05 08:54:01 +00:00
|
|
|
/*
|
2007-07-04 00:54:52 +00:00
|
|
|
* Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com>
|
2005-01-01 02:44:28 +00:00
|
|
|
* Copyright (C) 2004,2005 Brad Hards <bradh@frogmouth.net>
|
2004-11-05 08:54:01 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2007-01-02 05:01:25 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
2004-11-05 08:54:01 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2005-01-01 02:44:28 +00:00
|
|
|
#include "qca_securelayer.h"
|
2004-11-05 08:54:01 +00:00
|
|
|
|
|
|
|
#include "qcaprovider.h"
|
|
|
|
|
2007-04-17 12:12:36 +00:00
|
|
|
#include <QTimer>
|
2007-07-04 00:54:52 +00:00
|
|
|
#include <QPointer>
|
2007-04-17 12:12:36 +00:00
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
namespace QCA {
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
Provider::Context *getContext(const QString &type, const QString &provider);
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// LayerTracker
|
|
|
|
//----------------------------------------------------------------------------
|
2007-07-06 00:35:13 +00:00
|
|
|
class LayerTracker
|
2007-07-04 00:54:52 +00:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
struct Item
|
|
|
|
{
|
|
|
|
int plain;
|
|
|
|
qint64 encoded;
|
|
|
|
};
|
|
|
|
|
|
|
|
int p;
|
|
|
|
QList<Item> list;
|
|
|
|
|
|
|
|
public:
|
|
|
|
LayerTracker()
|
|
|
|
{
|
|
|
|
p = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
p = 0;
|
|
|
|
list.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void addPlain(int plain)
|
|
|
|
{
|
|
|
|
p += plain;
|
|
|
|
}
|
|
|
|
|
|
|
|
void specifyEncoded(int encoded, int plain)
|
|
|
|
{
|
|
|
|
// can't specify more bytes than we have
|
|
|
|
if(plain > p)
|
|
|
|
plain = p;
|
|
|
|
p -= plain;
|
|
|
|
Item i;
|
|
|
|
i.plain = plain;
|
|
|
|
i.encoded = encoded;
|
|
|
|
list += i;
|
|
|
|
}
|
|
|
|
|
|
|
|
int finished(qint64 encoded)
|
|
|
|
{
|
|
|
|
int plain = 0;
|
|
|
|
for(QList<Item>::Iterator it = list.begin(); it != list.end();)
|
|
|
|
{
|
|
|
|
Item &i = *it;
|
|
|
|
|
|
|
|
// not enough?
|
|
|
|
if(encoded < i.encoded)
|
|
|
|
{
|
|
|
|
i.encoded -= encoded;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
encoded -= i.encoded;
|
|
|
|
plain += i.plain;
|
|
|
|
it = list.erase(it);
|
|
|
|
}
|
|
|
|
return plain;
|
|
|
|
}
|
2007-07-06 00:35:13 +00:00
|
|
|
};
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// SecureLayer
|
|
|
|
//----------------------------------------------------------------------------
|
2005-02-27 01:12:26 +00:00
|
|
|
SecureLayer::SecureLayer(QObject *parent)
|
|
|
|
:QObject(parent)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2004-11-17 00:28:34 +00:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
bool SecureLayer::isClosable() const
|
2004-11-17 00:28:34 +00:00
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
return false;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
void SecureLayer::close()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
QByteArray SecureLayer::readUnprocessed()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
return QByteArray();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 18:57:03 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// TLSSession
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
TLSSession::TLSSession()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TLSSession::TLSSession(const TLSSession &from)
|
|
|
|
:Algorithm(from)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TLSSession::~TLSSession()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TLSSession & TLSSession::operator=(const TLSSession &from)
|
|
|
|
{
|
|
|
|
Algorithm::operator=(from);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TLSSession::isNull() const
|
|
|
|
{
|
|
|
|
return (!context() ? true : false);
|
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// TLS
|
|
|
|
//----------------------------------------------------------------------------
|
2005-04-24 19:09:06 +00:00
|
|
|
enum ResetMode
|
|
|
|
{
|
|
|
|
ResetSession = 0,
|
|
|
|
ResetSessionAndData = 1,
|
|
|
|
ResetAll = 2
|
|
|
|
};
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
class TLS::Private : public QObject
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
Q_OBJECT
|
2004-11-05 08:54:01 +00:00
|
|
|
public:
|
2005-04-24 19:09:06 +00:00
|
|
|
TLS *q;
|
|
|
|
TLSContext *c;
|
2007-07-04 00:54:52 +00:00
|
|
|
TLS::Mode mode;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
bool active, server;
|
2005-04-24 19:09:06 +00:00
|
|
|
CertificateChain localCert;
|
|
|
|
PrivateKey localKey;
|
|
|
|
CertificateCollection trusted;
|
|
|
|
bool con_ssfMode;
|
|
|
|
int con_minSSF, con_maxSSF;
|
|
|
|
QStringList con_cipherSuites;
|
2007-07-04 00:54:52 +00:00
|
|
|
QList<CertificateInfoOrdered> issuerList;
|
2007-07-06 18:57:03 +00:00
|
|
|
TLSSession session;
|
2005-04-24 19:09:06 +00:00
|
|
|
bool tryCompress;
|
2007-07-04 00:54:52 +00:00
|
|
|
int packet_mtu;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
|
|
|
QString host;
|
|
|
|
CertificateChain peerCert;
|
|
|
|
Validity peerValidity;
|
2007-07-06 18:57:03 +00:00
|
|
|
bool blocked;
|
2005-04-24 19:09:06 +00:00
|
|
|
bool hostMismatch;
|
|
|
|
TLSContext::SessionInfo sessionInfo;
|
|
|
|
|
2005-06-24 23:41:25 +00:00
|
|
|
QByteArray in, out;
|
2005-04-24 19:09:06 +00:00
|
|
|
QByteArray to_net, from_net;
|
2007-07-04 00:54:52 +00:00
|
|
|
int pending_write;
|
2007-07-06 00:35:13 +00:00
|
|
|
LayerTracker layer;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
QList<QByteArray> packet_in, packet_out;
|
|
|
|
QList<QByteArray> packet_to_net, packet_from_net;
|
|
|
|
QList<int> packet_to_net_encoded;
|
2005-07-28 12:17:09 +00:00
|
|
|
|
2007-07-06 18:57:03 +00:00
|
|
|
bool connect_hostNameReceived, connect_certificateRequested, connect_handshaken;
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
enum { OpStart, OpUpdate };
|
|
|
|
|
|
|
|
int op;
|
|
|
|
|
|
|
|
bool handshaken, closing;
|
2005-04-24 19:09:06 +00:00
|
|
|
bool tryMore;
|
|
|
|
int bytesEncoded;
|
|
|
|
Error errorCode;
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
Private(TLS *_q, TLS::Mode _mode) : QObject(_q), q(_q), mode(_mode)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
// c is 0 during initial reset, so we don't redundantly reset it
|
2005-04-24 19:09:06 +00:00
|
|
|
c = 0;
|
2007-07-04 00:54:52 +00:00
|
|
|
connect_hostNameReceived = false;
|
2007-07-06 18:57:03 +00:00
|
|
|
connect_certificateRequested = false;
|
2007-07-04 00:54:52 +00:00
|
|
|
connect_handshaken = false;
|
2007-07-06 18:03:29 +00:00
|
|
|
server = false;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
|
|
|
reset(ResetAll);
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
c = static_cast<TLSContext *>(q->context());
|
|
|
|
|
|
|
|
// parent the context to us, so that moveToThread works
|
|
|
|
c->setParent(this);
|
|
|
|
|
|
|
|
connect(c, SIGNAL(resultsReady()), SLOT(tls_resultsReady()));
|
|
|
|
}
|
|
|
|
|
|
|
|
~Private()
|
|
|
|
{
|
|
|
|
// context is owned by Algorithm, unparent so we don't double-delete
|
|
|
|
c->setParent(0);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
void reset(ResetMode mode)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
if(c)
|
|
|
|
c->reset();
|
|
|
|
|
2007-07-06 18:03:29 +00:00
|
|
|
if(!server)
|
|
|
|
issuerList.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
active = false;
|
|
|
|
server = false;
|
2005-04-24 19:09:06 +00:00
|
|
|
host = QString();
|
|
|
|
out.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
packet_out.clear();
|
2004-11-05 08:54:01 +00:00
|
|
|
handshaken = false;
|
|
|
|
closing = false;
|
|
|
|
tryMore = false;
|
2005-04-24 19:09:06 +00:00
|
|
|
bytesEncoded = 0;
|
2007-07-04 00:54:52 +00:00
|
|
|
op = -1;
|
|
|
|
pending_write = 0;
|
|
|
|
blocked = false;
|
2007-07-06 00:35:13 +00:00
|
|
|
layer.reset();
|
2005-04-24 19:09:06 +00:00
|
|
|
|
|
|
|
if(mode >= ResetSessionAndData)
|
|
|
|
{
|
|
|
|
peerCert = CertificateChain();
|
2005-05-10 04:10:23 +00:00
|
|
|
peerValidity = ErrorValidityUnknown;
|
|
|
|
hostMismatch = false;
|
2005-04-24 19:09:06 +00:00
|
|
|
in.clear();
|
|
|
|
to_net.clear();
|
|
|
|
from_net.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
packet_in.clear();
|
|
|
|
packet_to_net.clear();
|
|
|
|
packet_to_net_encoded.clear();
|
|
|
|
packet_from_net.clear();
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(mode >= ResetAll)
|
|
|
|
{
|
|
|
|
localCert = CertificateChain();
|
|
|
|
localKey = PrivateKey();
|
|
|
|
trusted = CertificateCollection();
|
|
|
|
con_ssfMode = true;
|
|
|
|
con_minSSF = 128;
|
|
|
|
con_maxSSF = -1;
|
|
|
|
con_cipherSuites = QStringList();
|
|
|
|
tryCompress = false;
|
2007-07-04 00:54:52 +00:00
|
|
|
packet_mtu = -1;
|
2007-07-06 18:03:29 +00:00
|
|
|
issuerList.clear();
|
2007-07-06 18:57:03 +00:00
|
|
|
session = TLSSession();
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
void start(bool serverMode)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
active = true;
|
|
|
|
server = serverMode;
|
|
|
|
|
|
|
|
c->setup(serverMode, host, tryCompress);
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
if(con_ssfMode)
|
|
|
|
c->setConstraints(con_minSSF, con_maxSSF);
|
|
|
|
else
|
|
|
|
c->setConstraints(con_cipherSuites);
|
|
|
|
|
2007-04-11 02:13:20 +00:00
|
|
|
c->setCertificate(localCert, localKey);
|
2007-07-04 00:54:52 +00:00
|
|
|
c->setTrustedCertificates(trusted);
|
|
|
|
if(serverMode)
|
|
|
|
c->setIssuerList(issuerList);
|
2007-07-06 18:57:03 +00:00
|
|
|
if(!session.isNull())
|
|
|
|
{
|
|
|
|
TLSSessionContext *sc = static_cast<TLSSessionContext*>(session.context());
|
|
|
|
c->setSessionId(*sc);
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
c->setMTU(packet_mtu);
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
op = OpStart;
|
2005-07-30 09:16:05 +00:00
|
|
|
c->start();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
void close()
|
|
|
|
{
|
|
|
|
if(!handshaken || closing)
|
|
|
|
return;
|
|
|
|
|
|
|
|
closing = true;
|
2007-07-04 00:54:52 +00:00
|
|
|
c->shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
void continueAfterStep()
|
|
|
|
{
|
|
|
|
//printf("continuing\n");
|
|
|
|
|
|
|
|
blocked = false;
|
|
|
|
update();
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void update()
|
|
|
|
{
|
2007-07-06 00:35:13 +00:00
|
|
|
//printf("update attempt\n");
|
2007-07-04 00:54:52 +00:00
|
|
|
if(blocked)
|
|
|
|
return;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
// only allow one operation at a time
|
|
|
|
if(op != -1)
|
|
|
|
return;
|
2005-07-28 12:17:09 +00:00
|
|
|
|
2007-07-06 00:35:13 +00:00
|
|
|
//printf("update\n");
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(!handshaken)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
// FIXME: optimize this somehow. we need to force
|
|
|
|
// the update after start() succeeds, but not in any
|
|
|
|
// other case afaict.
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(mode == TLS::Stream)
|
|
|
|
{
|
|
|
|
// during handshake, only send from_net (no app data)
|
|
|
|
//if(!from_net.isEmpty())
|
|
|
|
//{
|
|
|
|
op = OpUpdate;
|
|
|
|
c->update(from_net, QByteArray());
|
|
|
|
from_net.clear();
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// note: there may not be a packet
|
|
|
|
QByteArray pkt = packet_from_net.takeFirst();
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
op = OpUpdate;
|
|
|
|
c->update(pkt, QByteArray());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(mode == TLS::Stream)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
// FIXME: we should be able to send both at once,
|
|
|
|
// but if we do this then qca-ossl gives us
|
|
|
|
// broken security layer. probably a bug in
|
|
|
|
// qca-ossl?
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
// otherwise, send both from_net and out
|
2007-07-05 23:33:32 +00:00
|
|
|
/*if(!from_net.isEmpty() || !out.isEmpty())
|
2007-07-04 00:54:52 +00:00
|
|
|
{
|
|
|
|
op = OpUpdate;
|
|
|
|
pending_write += out.size();
|
|
|
|
c->update(from_net, out);
|
|
|
|
from_net.clear();
|
|
|
|
out.clear();
|
2007-07-05 23:33:32 +00:00
|
|
|
}*/
|
|
|
|
|
|
|
|
if(!from_net.isEmpty())
|
|
|
|
{
|
|
|
|
op = OpUpdate;
|
|
|
|
c->update(from_net, QByteArray());
|
|
|
|
from_net.clear();
|
|
|
|
}
|
2007-07-06 00:35:13 +00:00
|
|
|
else //if(!out.isEmpty())
|
2007-07-05 23:33:32 +00:00
|
|
|
{
|
|
|
|
op = OpUpdate;
|
|
|
|
pending_write += out.size();
|
|
|
|
c->update(QByteArray(), out);
|
|
|
|
out.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
op = OpUpdate;
|
|
|
|
QByteArray pkta = packet_from_net.takeFirst();
|
|
|
|
QByteArray pktb = packet_out.takeFirst();
|
|
|
|
if(!pktb.isEmpty())
|
|
|
|
packet_to_net_encoded += pktb.size();
|
|
|
|
c->update(pkta, pktb);
|
|
|
|
}
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
private slots:
|
|
|
|
void tls_resultsReady()
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
QPointer<QObject> self = this;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
int last_op = op;
|
|
|
|
op = -1;
|
|
|
|
//printf("results ready: %d\n", last_op);
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(last_op == OpStart)
|
|
|
|
{
|
|
|
|
bool ok = c->result() == TLSContext::Success;
|
|
|
|
if(!ok)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2007-07-04 00:54:52 +00:00
|
|
|
errorCode = TLS::ErrorInit;
|
2007-07-06 00:35:13 +00:00
|
|
|
QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
|
|
|
|
//emit q->error();
|
2005-04-24 19:09:06 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
update();
|
|
|
|
}
|
|
|
|
else // OpUpdate
|
|
|
|
{
|
|
|
|
TLSContext::Result r = c->result();
|
|
|
|
QByteArray a = c->to_net();
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(closing)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(r == TLSContext::Error)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
reset(ResetSession);
|
|
|
|
errorCode = ErrorHandshake;
|
2007-07-06 00:35:13 +00:00
|
|
|
QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
|
|
|
|
//emit q->error();
|
2007-07-04 00:54:52 +00:00
|
|
|
return;
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(mode == TLS::Stream)
|
|
|
|
to_net.append(a);
|
|
|
|
else
|
|
|
|
packet_to_net += a;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(!a.isEmpty())
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
QMetaObject::invokeMethod(q, "readyReadOutgoing", Qt::QueuedConnection);
|
|
|
|
//emit q->readyReadOutgoing();
|
2007-07-04 00:54:52 +00:00
|
|
|
if(!self)
|
2005-04-24 19:09:06 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
if(r == TLSContext::Success)
|
|
|
|
{
|
|
|
|
from_net = c->unprocessed();
|
|
|
|
reset(ResetSession);
|
2007-07-06 00:35:13 +00:00
|
|
|
QMetaObject::invokeMethod(q, "closed", Qt::QueuedConnection);
|
|
|
|
//emit q->closed();
|
2007-07-04 00:54:52 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(!handshaken)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(r == TLSContext::Error)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2007-07-04 00:54:52 +00:00
|
|
|
errorCode = TLS::ErrorHandshake;
|
2007-07-06 00:35:13 +00:00
|
|
|
QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
|
|
|
|
//emit q->error();
|
2005-04-24 19:09:06 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
if(mode == TLS::Stream)
|
|
|
|
to_net.append(a);
|
|
|
|
else
|
|
|
|
packet_to_net += a;
|
|
|
|
|
|
|
|
if(!a.isEmpty())
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
QMetaObject::invokeMethod(q, "readyReadOutgoing", Qt::QueuedConnection);
|
|
|
|
//emit q->readyReadOutgoing();
|
2007-07-04 00:54:52 +00:00
|
|
|
if(!self)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(r == TLSContext::Success)
|
|
|
|
{
|
|
|
|
peerCert = c->peerCertificateChain();
|
|
|
|
if(!peerCert.isEmpty())
|
|
|
|
{
|
|
|
|
peerValidity = c->peerCertificateValidity();
|
|
|
|
if(peerValidity == ValidityGood && !host.isEmpty() && !peerCert.primary().matchesHostName(host))
|
|
|
|
hostMismatch = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
sessionInfo = c->sessionInfo();
|
2007-07-06 18:57:03 +00:00
|
|
|
if(sessionInfo.id)
|
|
|
|
{
|
|
|
|
TLSSessionContext *sc = static_cast<TLSSessionContext*>(sessionInfo.id->clone());
|
|
|
|
session.change(sc);
|
|
|
|
}
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
handshaken = true;
|
|
|
|
if(connect_handshaken)
|
|
|
|
{
|
|
|
|
blocked = true;
|
|
|
|
emit q->handshaken();
|
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
// FIXME: else?
|
2007-07-04 00:54:52 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else // Continue
|
|
|
|
{
|
|
|
|
if(server)
|
|
|
|
{
|
|
|
|
bool clientHello = c->clientHelloReceived();
|
|
|
|
if(clientHello)
|
|
|
|
{
|
|
|
|
host = c->hostName();
|
|
|
|
if(!host.isEmpty())
|
|
|
|
{
|
|
|
|
if(connect_hostNameReceived)
|
|
|
|
{
|
|
|
|
blocked = true;
|
|
|
|
emit q->hostNameReceived();
|
|
|
|
if(!self)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool serverHello = c->serverHelloReceived();
|
|
|
|
if(serverHello)
|
|
|
|
{
|
2007-07-06 18:57:03 +00:00
|
|
|
if(c->certificateRequested())
|
2007-07-04 00:54:52 +00:00
|
|
|
{
|
2007-07-06 18:57:03 +00:00
|
|
|
issuerList = c->issuerList();
|
|
|
|
if(connect_certificateRequested)
|
|
|
|
{
|
|
|
|
blocked = true;
|
|
|
|
emit q->certificateRequested();
|
|
|
|
if(!self)
|
|
|
|
return;
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
bool ok = (r == TLSContext::Success);
|
|
|
|
if(!ok)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
reset(ResetSession);
|
|
|
|
errorCode = ErrorCrypt;
|
2007-07-06 00:35:13 +00:00
|
|
|
QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
|
|
|
|
//emit q->error();
|
2005-04-24 19:09:06 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-07-28 12:17:09 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
QByteArray b = c->to_app();
|
2007-07-06 00:35:13 +00:00
|
|
|
//printf("to_app: %d (%s)\n", b.size(), b.data());
|
2007-07-04 00:54:52 +00:00
|
|
|
bool eof = c->eof();
|
|
|
|
int enc = c->encoded();
|
|
|
|
|
|
|
|
bool more = false;
|
|
|
|
if(mode == TLS::Stream)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
pending_write -= enc;
|
|
|
|
if(pending_write > 0)
|
2007-07-04 00:54:52 +00:00
|
|
|
more = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(!a.isEmpty() && enc > 0)
|
|
|
|
{
|
|
|
|
enc = packet_to_net_encoded.takeFirst();
|
|
|
|
if(!packet_to_net_encoded.isEmpty())
|
|
|
|
more = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// datagram mode might have more pending out
|
|
|
|
if(!packet_out.isEmpty())
|
|
|
|
more = true;
|
|
|
|
}
|
|
|
|
|
2007-07-06 00:35:13 +00:00
|
|
|
if(!out.isEmpty())
|
|
|
|
more = true;
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(mode == TLS::Stream)
|
|
|
|
{
|
|
|
|
to_net.append(a);
|
|
|
|
in.append(b);
|
2007-07-05 23:33:32 +00:00
|
|
|
bytesEncoded += enc;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
packet_to_net += a;
|
|
|
|
packet_in += b;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!a.isEmpty())
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
QMetaObject::invokeMethod(q, "readyReadOutgoing", Qt::QueuedConnection);
|
|
|
|
//emit q->readyReadOutgoing();
|
2007-07-04 00:54:52 +00:00
|
|
|
if(!self)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!b.isEmpty())
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
QMetaObject::invokeMethod(q, "readyRead", Qt::QueuedConnection);
|
|
|
|
//emit q->readyRead();
|
2007-07-04 00:54:52 +00:00
|
|
|
if(!self)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
if(eof)
|
2007-07-04 00:54:52 +00:00
|
|
|
close();
|
|
|
|
|
|
|
|
if(eof || more)
|
|
|
|
update();
|
|
|
|
}
|
2005-07-28 12:17:09 +00:00
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
};
|
|
|
|
|
2005-02-27 01:12:26 +00:00
|
|
|
TLS::TLS(QObject *parent, const QString &provider)
|
|
|
|
:SecureLayer(parent), Algorithm("tls", provider)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
d = new Private(this, TLS::Stream);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-07-31 01:27:27 +00:00
|
|
|
TLS::TLS(Mode mode, QObject *parent, const QString &provider)
|
|
|
|
:SecureLayer(parent), Algorithm(mode == Stream ? "tls" : "dtls", provider)
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
d = new Private(this, mode);
|
2005-07-31 01:27:27 +00:00
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
TLS::~TLS()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
void TLS::reset()
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->reset(ResetAll);
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2007-04-12 17:54:53 +00:00
|
|
|
QStringList TLS::supportedCipherSuites(const Version &version) const
|
2005-02-24 10:07:14 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
return d->c->supportedCipherSuites(version);
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2005-01-14 06:36:12 +00:00
|
|
|
void TLS::setCertificate(const CertificateChain &cert, const PrivateKey &key)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->localCert = cert;
|
|
|
|
d->localKey = key;
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->active)
|
|
|
|
d->c->setCertificate(cert, key);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 07:16:11 +00:00
|
|
|
void TLS::setCertificate(const KeyBundle &kb)
|
|
|
|
{
|
|
|
|
setCertificate(kb.certificateChain(), kb.privateKey());
|
|
|
|
}
|
|
|
|
|
2007-06-08 04:02:55 +00:00
|
|
|
CertificateCollection TLS::trustedCertificates() const
|
|
|
|
{
|
|
|
|
return d->trusted;
|
|
|
|
}
|
|
|
|
|
2005-03-28 07:11:58 +00:00
|
|
|
void TLS::setTrustedCertificates(const CertificateCollection &trusted)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->trusted = trusted;
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->active)
|
|
|
|
d->c->setTrustedCertificates(trusted);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2004-11-17 00:28:34 +00:00
|
|
|
void TLS::setConstraints(SecurityLevel s)
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
int min = 128;
|
2005-04-24 19:09:06 +00:00
|
|
|
switch(s)
|
|
|
|
{
|
|
|
|
case SL_None:
|
|
|
|
min = 0;
|
|
|
|
break;
|
|
|
|
case SL_Integrity:
|
|
|
|
min = 1;
|
|
|
|
break;
|
|
|
|
case SL_Export:
|
|
|
|
min = 40;
|
|
|
|
break;
|
|
|
|
case SL_Baseline:
|
|
|
|
min = 128;
|
|
|
|
break;
|
|
|
|
case SL_High:
|
|
|
|
min = 129;
|
|
|
|
break;
|
|
|
|
case SL_Highest:
|
2005-07-06 21:33:27 +00:00
|
|
|
min = qMax(129, d->c->maxSSF());
|
2005-04-24 19:09:06 +00:00
|
|
|
break;
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
d->con_ssfMode = true;
|
|
|
|
d->con_minSSF = min;
|
|
|
|
d->con_maxSSF = -1;
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
if(d->active)
|
|
|
|
d->c->setConstraints(d->con_minSSF, d->con_maxSSF);
|
2004-11-17 00:28:34 +00:00
|
|
|
}
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
void TLS::setConstraints(int minSSF, int maxSSF)
|
2004-11-17 00:28:34 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->con_ssfMode = true;
|
|
|
|
d->con_minSSF = minSSF;
|
|
|
|
d->con_maxSSF = maxSSF;
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
if(d->active)
|
|
|
|
d->c->setConstraints(d->con_minSSF, d->con_maxSSF);
|
2004-11-17 00:28:34 +00:00
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
void TLS::setConstraints(const QStringList &cipherSuiteList)
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->con_ssfMode = false;
|
|
|
|
d->con_cipherSuites = cipherSuiteList;
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
if(d->active)
|
|
|
|
d->c->setConstraints(d->con_cipherSuites);
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2007-04-11 02:13:20 +00:00
|
|
|
QList<CertificateInfoOrdered> TLS::issuerList() const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
return d->issuerList;
|
2007-04-11 02:13:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TLS::setIssuerList(const QList<CertificateInfoOrdered> &issuers)
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
d->issuerList = issuers;
|
|
|
|
if(d->active)
|
|
|
|
d->c->setIssuerList(issuers);
|
2007-04-11 02:13:20 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 18:57:03 +00:00
|
|
|
void TLS::setSession(const TLSSession &session)
|
|
|
|
{
|
|
|
|
d->session = session;
|
|
|
|
}
|
|
|
|
|
2007-04-12 17:54:53 +00:00
|
|
|
bool TLS::canCompress() const
|
2005-01-27 16:42:44 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
return d->c->canCompress();
|
2007-04-12 17:54:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool TLS::canSetHostName() const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
return d->c->canSetHostName();
|
2005-01-27 16:42:44 +00:00
|
|
|
}
|
|
|
|
|
2007-06-08 04:02:55 +00:00
|
|
|
bool TLS::compressionEnabled() const
|
|
|
|
{
|
|
|
|
return d->tryCompress;
|
|
|
|
}
|
|
|
|
|
2004-11-17 00:28:34 +00:00
|
|
|
void TLS::setCompressionEnabled(bool b)
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->tryCompress = b;
|
2004-11-17 00:28:34 +00:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
void TLS::startClient(const QString &host)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->reset(ResetSessionAndData);
|
2004-11-05 08:54:01 +00:00
|
|
|
d->host = host;
|
2007-07-06 18:03:29 +00:00
|
|
|
d->issuerList.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
// client mode
|
|
|
|
d->start(false);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
void TLS::startServer()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->reset(ResetSessionAndData);
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
// server mode
|
|
|
|
d->start(true);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-04-11 02:13:20 +00:00
|
|
|
void TLS::continueAfterStep()
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
d->continueAfterStep();
|
2007-04-11 02:13:20 +00:00
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
bool TLS::isHandshaken() const
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-02-24 10:07:14 +00:00
|
|
|
return d->handshaken;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-02-25 03:36:58 +00:00
|
|
|
bool TLS::isCompressed() const
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->sessionInfo.isCompressed;
|
2005-02-25 03:36:58 +00:00
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
TLS::Version TLS::version() const
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->sessionInfo.version;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
QString TLS::cipherSuite() const
|
2004-11-17 00:28:34 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->sessionInfo.cipherSuite;
|
2004-11-17 00:28:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int TLS::cipherBits() const
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->sessionInfo.cipherBits;
|
2004-11-17 00:28:34 +00:00
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
int TLS::cipherMaxBits() const
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->sessionInfo.cipherMaxBits;
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 18:57:03 +00:00
|
|
|
TLSSession TLS::session() const
|
|
|
|
{
|
|
|
|
return d->session;
|
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
TLS::Error TLS::errorCode() const
|
|
|
|
{
|
|
|
|
return d->errorCode;
|
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
TLS::IdentityResult TLS::peerIdentityResult() const
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
if(d->peerCert.isEmpty())
|
|
|
|
return NoCertificate;
|
2005-02-24 10:07:14 +00:00
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
if(d->peerValidity != ValidityGood)
|
|
|
|
return InvalidCertificate;
|
2005-02-24 10:07:14 +00:00
|
|
|
|
|
|
|
if(d->hostMismatch)
|
|
|
|
return HostMismatch;
|
|
|
|
|
|
|
|
return Valid;
|
|
|
|
}
|
|
|
|
|
2005-02-25 06:51:06 +00:00
|
|
|
Validity TLS::peerCertificateValidity() const
|
2005-02-24 10:07:14 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->peerValidity;
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CertificateChain TLS::localCertificateChain() const
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->localCert;
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2007-06-08 04:02:55 +00:00
|
|
|
PrivateKey TLS::localPrivateKey() const
|
|
|
|
{
|
|
|
|
return d->localKey;
|
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
CertificateChain TLS::peerCertificateChain() const
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->peerCert;
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
bool TLS::isClosable() const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2004-11-07 11:40:11 +00:00
|
|
|
int TLS::bytesAvailable() const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->mode == Stream)
|
|
|
|
return d->in.size();
|
|
|
|
else
|
|
|
|
return 0;
|
2004-11-07 11:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int TLS::bytesOutgoingAvailable() const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->mode == Stream)
|
|
|
|
return d->to_net.size();
|
|
|
|
else
|
|
|
|
return 0;
|
2004-11-07 11:40:11 +00:00
|
|
|
}
|
|
|
|
|
2005-02-24 10:07:14 +00:00
|
|
|
void TLS::close()
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->close();
|
|
|
|
d->update();
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2005-06-24 23:41:25 +00:00
|
|
|
void TLS::write(const QByteArray &a)
|
2004-11-07 11:40:11 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->mode == Stream)
|
2007-07-06 00:35:13 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
d->out.append(a);
|
2007-07-06 00:35:13 +00:00
|
|
|
d->layer.addPlain(a.size());
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
else
|
|
|
|
d->packet_out.append(a);
|
2005-04-24 19:09:06 +00:00
|
|
|
d->update();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-06-24 23:41:25 +00:00
|
|
|
QByteArray TLS::read()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->mode == Stream)
|
|
|
|
{
|
|
|
|
QByteArray a = d->in;
|
|
|
|
d->in.clear();
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return d->packet_in.takeFirst();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TLS::writeIncoming(const QByteArray &a)
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->mode == Stream)
|
|
|
|
d->from_net.append(a);
|
|
|
|
else
|
|
|
|
d->packet_from_net.append(a);
|
2005-04-24 19:09:06 +00:00
|
|
|
d->update();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2004-11-13 10:13:12 +00:00
|
|
|
QByteArray TLS::readOutgoing(int *plainBytes)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->mode == Stream)
|
|
|
|
{
|
|
|
|
QByteArray a = d->to_net;
|
|
|
|
d->to_net.clear();
|
|
|
|
if(plainBytes)
|
|
|
|
*plainBytes = d->bytesEncoded;
|
2007-07-06 00:35:13 +00:00
|
|
|
d->layer.specifyEncoded(a.size(), d->bytesEncoded);
|
2007-07-04 00:54:52 +00:00
|
|
|
d->bytesEncoded = 0;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QByteArray a = d->packet_to_net.takeFirst();
|
|
|
|
int x = d->packet_to_net_encoded.takeFirst();
|
|
|
|
if(plainBytes)
|
|
|
|
*plainBytes = x;
|
|
|
|
return a;
|
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
QByteArray TLS::readUnprocessed()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
if(d->mode == Stream)
|
|
|
|
{
|
|
|
|
QByteArray a = d->from_net;
|
|
|
|
d->from_net.clear();
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return QByteArray();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-07-06 00:35:13 +00:00
|
|
|
int TLS::convertBytesWritten(qint64 bytes)
|
|
|
|
{
|
|
|
|
return d->layer.finished(bytes);
|
|
|
|
}
|
|
|
|
|
2005-07-30 09:16:05 +00:00
|
|
|
int TLS::packetsAvailable() const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
return d->packet_in.count();
|
2005-07-30 09:16:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int TLS::packetsOutgoingAvailable() const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
return d->packet_to_net.count();
|
2005-07-30 09:16:05 +00:00
|
|
|
}
|
|
|
|
|
2007-06-08 04:02:55 +00:00
|
|
|
int TLS::packetMTU() const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
return d->packet_mtu;
|
2007-06-08 04:02:55 +00:00
|
|
|
}
|
|
|
|
|
2005-07-30 09:16:05 +00:00
|
|
|
void TLS::setPacketMTU(int size) const
|
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
d->packet_mtu = size;
|
|
|
|
if(d->active)
|
|
|
|
d->c->setMTU(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TLS::connectNotify(const char *signal)
|
|
|
|
{
|
2007-07-06 18:57:03 +00:00
|
|
|
if(signal == QMetaObject::normalizedSignature(SIGNAL(hostNameReceived())))
|
2007-07-04 00:54:52 +00:00
|
|
|
d->connect_hostNameReceived = true;
|
2007-07-06 18:57:03 +00:00
|
|
|
else if(signal == QMetaObject::normalizedSignature(SIGNAL(certificateRequested())))
|
|
|
|
d->connect_certificateRequested = true;
|
2007-07-04 11:46:01 +00:00
|
|
|
else if(signal == QMetaObject::normalizedSignature(SIGNAL(handshaken())))
|
2007-07-04 00:54:52 +00:00
|
|
|
d->connect_handshaken = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TLS::disconnectNotify(const char *signal)
|
|
|
|
{
|
2007-07-06 18:57:03 +00:00
|
|
|
if(signal == QMetaObject::normalizedSignature(SIGNAL(hostNameReceived())))
|
2007-07-04 00:54:52 +00:00
|
|
|
d->connect_hostNameReceived = false;
|
2007-07-06 18:57:03 +00:00
|
|
|
else if(signal == QMetaObject::normalizedSignature(SIGNAL(certificateRequested())))
|
|
|
|
d->connect_certificateRequested = false;
|
2007-07-04 11:46:01 +00:00
|
|
|
else if(signal == QMetaObject::normalizedSignature(SIGNAL(handshaken())))
|
2007-07-04 00:54:52 +00:00
|
|
|
d->connect_handshaken = false;
|
2005-07-30 09:16:05 +00:00
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
//----------------------------------------------------------------------------
|
2007-06-11 23:18:19 +00:00
|
|
|
// SASL::Params
|
2004-11-05 08:54:01 +00:00
|
|
|
//----------------------------------------------------------------------------
|
2007-06-11 23:18:19 +00:00
|
|
|
class SASL::Params::Private
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
bool needUsername, canSendAuthzid, needPassword, canSendRealm;
|
|
|
|
};
|
|
|
|
|
|
|
|
SASL::Params::Params()
|
|
|
|
:d(new Private)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SASL::Params::Params(bool user, bool authzid, bool pass, bool realm)
|
|
|
|
:d(new Private)
|
|
|
|
{
|
|
|
|
d->needUsername = user;
|
|
|
|
d->canSendAuthzid = authzid;
|
|
|
|
d->needPassword = pass;
|
|
|
|
d->canSendRealm = realm;
|
|
|
|
}
|
|
|
|
|
|
|
|
SASL::Params::Params(const SASL::Params &from)
|
|
|
|
:d(new Private(*from.d))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SASL::Params::~Params()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
SASL::Params & SASL::Params::operator=(const SASL::Params &from)
|
|
|
|
{
|
|
|
|
*d = *from.d;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SASL::Params::needUsername() const
|
|
|
|
{
|
|
|
|
return d->needUsername;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SASL::Params::canSendAuthzid() const
|
|
|
|
{
|
|
|
|
return d->canSendAuthzid;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SASL::Params::needPassword() const
|
|
|
|
{
|
|
|
|
return d->needPassword;
|
|
|
|
}
|
2005-07-31 01:27:27 +00:00
|
|
|
|
2007-06-11 23:18:19 +00:00
|
|
|
bool SASL::Params::canSendRealm() const
|
|
|
|
{
|
|
|
|
return d->canSendRealm;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// SASL
|
|
|
|
//----------------------------------------------------------------------------
|
2005-07-31 01:27:27 +00:00
|
|
|
/*
|
|
|
|
These don't map, but I don't think it matters much..
|
|
|
|
SASL_TRYAGAIN (-8) transient failure (e.g., weak key)
|
|
|
|
SASL_BADMAC (-9) integrity check failed
|
|
|
|
-- client only codes --
|
|
|
|
SASL_WRONGMECH (-11) mechanism doesn't support requested feature
|
|
|
|
SASL_NEWSECRET (-12) new secret needed
|
|
|
|
-- server only codes --
|
|
|
|
SASL_TRANS (-17) One time use of a plaintext password will
|
|
|
|
enable requested mechanism for user
|
|
|
|
SASL_PWLOCK (-21) password locked
|
|
|
|
SASL_NOCHANGE (-22) requested change was not needed
|
|
|
|
*/
|
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
class SASL::Private : public QObject
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
Q_OBJECT
|
2004-11-05 08:54:01 +00:00
|
|
|
public:
|
2007-07-05 23:33:32 +00:00
|
|
|
SASL *q;
|
|
|
|
SASLContext *c;
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
OpStart,
|
|
|
|
OpServerFirstStep,
|
|
|
|
OpNextStep,
|
|
|
|
OpTryAgain,
|
|
|
|
OpUpdate
|
|
|
|
};
|
|
|
|
|
|
|
|
AuthFlags auth_flags;
|
|
|
|
int ssfmin, ssfmax;
|
|
|
|
QString ext_authid;
|
|
|
|
int ext_ssf;
|
|
|
|
bool localSet, remoteSet;
|
|
|
|
SASLContext::HostPort local, remote;
|
|
|
|
|
|
|
|
bool set_username, set_authzid, set_password, set_realm;
|
|
|
|
QString username, authzid, realm;
|
|
|
|
SecureArray password;
|
|
|
|
|
|
|
|
bool server;
|
|
|
|
QStringList mechlist;
|
|
|
|
QString server_realm;
|
|
|
|
bool allowClientSendFirst;
|
|
|
|
bool disableServerSendLast;
|
|
|
|
|
|
|
|
int op;
|
|
|
|
bool first;
|
|
|
|
bool authed;
|
|
|
|
Error errorCode;
|
|
|
|
QByteArray out;
|
|
|
|
QByteArray in;
|
|
|
|
QByteArray to_net;
|
|
|
|
QByteArray from_net;
|
|
|
|
int bytesEncoded;
|
|
|
|
int pending_write;
|
2007-07-06 00:35:13 +00:00
|
|
|
LayerTracker layer;
|
2007-07-05 23:33:32 +00:00
|
|
|
|
|
|
|
Private(SASL *_q) : QObject(_q), q(_q)
|
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
set_username = false;
|
|
|
|
set_authzid = false;
|
|
|
|
set_password = false;
|
|
|
|
set_realm = false;
|
|
|
|
|
|
|
|
reset(ResetAll);
|
|
|
|
|
|
|
|
c = static_cast<SASLContext *>(q->context());
|
|
|
|
|
|
|
|
// parent the context to us, so that moveToThread works
|
|
|
|
c->setParent(this);
|
|
|
|
|
|
|
|
connect(c, SIGNAL(resultsReady()), SLOT(sasl_resultsReady()));
|
|
|
|
}
|
|
|
|
|
|
|
|
~Private()
|
|
|
|
{
|
|
|
|
// context is owned by Algorithm, unparent so we don't double-delete
|
|
|
|
c->setParent(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset(ResetMode mode)
|
2006-11-14 05:58:28 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
if(c)
|
|
|
|
{
|
|
|
|
c->reset();
|
|
|
|
|
|
|
|
if(mode < ResetAll)
|
|
|
|
{
|
|
|
|
QString *p_username = 0;
|
|
|
|
QString *p_authzid = 0;
|
|
|
|
SecureArray *p_password = 0;
|
|
|
|
QString *p_realm = 0;
|
|
|
|
|
|
|
|
if(set_username)
|
|
|
|
p_username = &username;
|
|
|
|
if(set_authzid)
|
|
|
|
p_authzid = &authzid;
|
|
|
|
if(set_password)
|
|
|
|
p_password = &password;
|
|
|
|
if(set_realm)
|
|
|
|
p_realm = &realm;
|
|
|
|
|
|
|
|
c->setClientParams(p_username, p_authzid, p_password, p_realm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
op = -1;
|
|
|
|
authed = false;
|
|
|
|
out.clear();
|
|
|
|
from_net.clear();
|
|
|
|
bytesEncoded = 0;
|
|
|
|
pending_write = 0;
|
2007-07-06 00:35:13 +00:00
|
|
|
layer.reset();
|
2007-07-05 23:33:32 +00:00
|
|
|
|
|
|
|
if(mode >= ResetSessionAndData)
|
|
|
|
{
|
|
|
|
in.clear();
|
|
|
|
to_net.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(mode >= ResetAll)
|
|
|
|
{
|
|
|
|
auth_flags = SASL::AuthFlagsNone;
|
|
|
|
ssfmin = 0;
|
|
|
|
ssfmax = 0;
|
|
|
|
ext_authid = QString();
|
|
|
|
ext_ssf = 0;
|
|
|
|
localSet = false;
|
|
|
|
remoteSet = false;
|
|
|
|
local = SASLContext::HostPort();
|
|
|
|
remote = SASLContext::HostPort();
|
|
|
|
|
|
|
|
set_username = false;
|
|
|
|
username = QString();
|
|
|
|
set_authzid = false;
|
|
|
|
authzid = QString();
|
|
|
|
set_password = false;
|
|
|
|
password = SecureArray();
|
|
|
|
set_realm = false;
|
|
|
|
realm = QString();
|
|
|
|
}
|
2006-11-14 05:58:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setup(const QString &service, const QString &host)
|
|
|
|
{
|
|
|
|
c->setup(service, host, localSet ? &local : 0, remoteSet ? &remote : 0, ext_authid, ext_ssf);
|
|
|
|
c->setConstraints(auth_flags, ssfmin, ssfmax);
|
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
void start()
|
2006-11-14 05:58:28 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
op = OpStart;
|
|
|
|
first = true;
|
|
|
|
|
|
|
|
if(server)
|
|
|
|
c->startServer(server_realm, disableServerSendLast);
|
2006-11-14 05:58:28 +00:00
|
|
|
else
|
2007-07-05 23:33:32 +00:00
|
|
|
c->startClient(mechlist, allowClientSendFirst);
|
|
|
|
}
|
|
|
|
|
|
|
|
void putServerFirstStep(const QString &mech, const QByteArray *clientInit)
|
|
|
|
{
|
|
|
|
if(op != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
op = OpServerFirstStep;
|
|
|
|
|
|
|
|
c->serverFirstStep(mech, clientInit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void putStep(const QByteArray &stepData)
|
|
|
|
{
|
|
|
|
if(op != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
op = OpNextStep;
|
|
|
|
|
|
|
|
c->nextStep(stepData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tryAgain()
|
|
|
|
{
|
|
|
|
if(op != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
op = OpTryAgain;
|
|
|
|
|
|
|
|
c->tryAgain();
|
2006-11-14 05:58:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void update()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
if(op != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
op = OpUpdate;
|
|
|
|
|
2007-07-04 01:22:12 +00:00
|
|
|
pending_write += out.size();
|
|
|
|
c->update(from_net, out);
|
|
|
|
from_net.clear();
|
|
|
|
out.clear();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
private slots:
|
2007-07-04 01:22:12 +00:00
|
|
|
void sasl_resultsReady()
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
QPointer<QObject> self = this;
|
|
|
|
|
|
|
|
int last_op = op;
|
|
|
|
op = -1;
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
SASLContext::Result r = c->result();
|
|
|
|
|
|
|
|
if(last_op == OpStart)
|
2007-07-04 01:22:12 +00:00
|
|
|
{
|
|
|
|
if(server)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
if(r != SASLContext::Success)
|
|
|
|
{
|
|
|
|
errorCode = SASL::ErrorInit;
|
2007-07-04 01:22:12 +00:00
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
|
|
|
|
emit q->serverStarted();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else // client
|
|
|
|
{
|
|
|
|
// fall into this logic
|
|
|
|
last_op = OpTryAgain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(last_op == OpServerFirstStep)
|
|
|
|
{
|
|
|
|
// fall into this logic
|
|
|
|
last_op = OpTryAgain;
|
|
|
|
}
|
|
|
|
else if(last_op == OpNextStep)
|
|
|
|
{
|
|
|
|
// fall into this logic
|
|
|
|
last_op = OpTryAgain;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(last_op == OpTryAgain)
|
|
|
|
{
|
|
|
|
if(server)
|
|
|
|
{
|
|
|
|
if(r == SASLContext::Continue)
|
|
|
|
{
|
|
|
|
emit q->nextStep(c->stepData());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(r == SASLContext::AuthCheck)
|
|
|
|
{
|
|
|
|
emit q->authCheck(c->username(), c->authzid());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(r == SASLContext::Success)
|
|
|
|
{
|
|
|
|
// FIXME: not signal safe
|
|
|
|
emit q->nextStep(c->stepData());
|
|
|
|
|
|
|
|
authed = true;
|
|
|
|
emit q->authenticated();
|
2007-07-04 01:22:12 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
else // error
|
|
|
|
{
|
|
|
|
errorCode = SASL::ErrorHandshake;
|
|
|
|
emit q->error();
|
2007-07-04 01:22:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // client
|
|
|
|
{
|
|
|
|
if(first)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
if(r == SASLContext::Error)
|
|
|
|
{
|
|
|
|
if(first)
|
|
|
|
errorCode = SASL::ErrorInit;
|
|
|
|
else
|
|
|
|
errorCode = SASL::ErrorHandshake;
|
2007-07-04 01:22:12 +00:00
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
else if(r == SASLContext::Params)
|
|
|
|
{
|
|
|
|
Params np = c->clientParams();
|
2007-07-04 01:22:12 +00:00
|
|
|
emit q->needParams(np);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
first = false;
|
|
|
|
emit q->clientStarted(c->haveClientInit(), c->stepData());
|
|
|
|
return;
|
2007-07-04 01:22:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
if(r == SASLContext::Error)
|
|
|
|
{
|
|
|
|
errorCode = ErrorHandshake;
|
2007-07-04 01:22:12 +00:00
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
else if(r == SASLContext::Params)
|
|
|
|
{
|
|
|
|
Params np = c->clientParams();
|
2007-07-04 01:22:12 +00:00
|
|
|
emit q->needParams(np);
|
|
|
|
return;
|
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
else if(r == SASLContext::Continue)
|
|
|
|
{
|
|
|
|
emit q->nextStep(c->stepData());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(r == SASLContext::Success)
|
|
|
|
{
|
|
|
|
// FIXME: not signal safe
|
|
|
|
emit q->nextStep(c->stepData());
|
|
|
|
|
|
|
|
authed = true;
|
|
|
|
emit q->authenticated();
|
|
|
|
return;
|
|
|
|
}
|
2007-07-04 01:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
}
|
|
|
|
else if(last_op == OpUpdate)
|
|
|
|
{
|
|
|
|
if(r != SASLContext::Success)
|
2007-07-04 01:22:12 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
errorCode = ErrorCrypt;
|
2007-07-04 01:22:12 +00:00
|
|
|
emit q->error();
|
2007-07-05 23:33:32 +00:00
|
|
|
return;
|
2007-07-04 01:22:12 +00:00
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
QByteArray a = c->to_net();
|
|
|
|
QByteArray b = c->to_app();
|
|
|
|
int enc = c->encoded();
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
to_net += a;
|
|
|
|
in += b;
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
bool more = false;
|
|
|
|
pending_write -= enc;
|
|
|
|
if(pending_write > 0)
|
|
|
|
more = true;
|
|
|
|
bytesEncoded += enc;
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
if(!a.isEmpty())
|
2007-07-04 01:22:12 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
emit q->readyReadOutgoing();
|
|
|
|
if(!self)
|
|
|
|
return;
|
2007-07-04 01:22:12 +00:00
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
if(!b.isEmpty())
|
2007-07-04 01:22:12 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
emit q->readyRead();
|
|
|
|
if(!self)
|
|
|
|
return;
|
2007-07-04 01:22:12 +00:00
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
if(more)
|
|
|
|
update();
|
2007-07-04 01:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
};
|
|
|
|
|
2005-02-27 01:12:26 +00:00
|
|
|
SASL::SASL(QObject *parent, const QString &provider)
|
|
|
|
:SecureLayer(parent), Algorithm("sasl", provider)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d = new Private(this);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SASL::~SASL()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::reset()
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->reset(ResetAll);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SASL::Error SASL::errorCode() const
|
|
|
|
{
|
|
|
|
return d->errorCode;
|
|
|
|
}
|
|
|
|
|
2004-11-13 10:13:12 +00:00
|
|
|
SASL::AuthCondition SASL::authCondition() const
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
return d->c->authCondition();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2004-11-17 00:28:34 +00:00
|
|
|
void SASL::setConstraints(AuthFlags f, SecurityLevel s)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
int min = 0;
|
|
|
|
if (s == SL_Integrity)
|
|
|
|
min = 1;
|
|
|
|
else if (s == SL_Export)
|
|
|
|
min = 56;
|
|
|
|
else if (s == SL_Baseline)
|
|
|
|
min = 128;
|
|
|
|
else if (s == SL_High)
|
|
|
|
min = 192;
|
|
|
|
else if (s == SL_Highest)
|
|
|
|
min = 256;
|
2006-02-23 23:21:06 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
setConstraints(f, min, 256);
|
2004-11-17 00:28:34 +00:00
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
void SASL::setConstraints(AuthFlags f, int minSSF, int maxSSF)
|
2004-11-17 00:28:34 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->auth_flags = f;
|
|
|
|
|
|
|
|
d->ssfmin = minSSF;
|
|
|
|
d->ssfmax = maxSSF;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2004-12-20 08:08:39 +00:00
|
|
|
void SASL::setExternalAuthId(const QString &authid)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
|
|
|
d->ext_authid = authid;
|
|
|
|
}
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
void SASL::setExternalSSF(int strength)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->ext_ssf = strength;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-06-08 20:31:50 +00:00
|
|
|
void SASL::setLocalAddress(const QString &addr, quint16 port)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->localSet = true;
|
2006-11-14 05:58:28 +00:00
|
|
|
d->local.addr = addr;
|
|
|
|
d->local.port = port;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-06-08 20:31:50 +00:00
|
|
|
void SASL::setRemoteAddress(const QString &addr, quint16 port)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->remoteSet = true;
|
2006-11-14 05:58:28 +00:00
|
|
|
d->remote.addr = addr;
|
|
|
|
d->remote.port = port;
|
2005-02-28 09:01:59 +00:00
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
|
2005-07-31 01:27:27 +00:00
|
|
|
void SASL::startClient(const QString &service, const QString &host, const QStringList &mechlist, ClientSendMode mode)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->reset(ResetSessionAndData);
|
2006-11-14 05:58:28 +00:00
|
|
|
d->setup(service, host);
|
2004-11-05 08:54:01 +00:00
|
|
|
d->server = false;
|
2007-07-05 23:33:32 +00:00
|
|
|
d->mechlist = mechlist;
|
|
|
|
d->allowClientSendFirst = (mode == AllowClientSendFirst);
|
|
|
|
d->start();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-07-31 01:27:27 +00:00
|
|
|
void SASL::startServer(const QString &service, const QString &host, const QString &realm, ServerSendMode mode)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->reset(ResetSessionAndData);
|
2006-11-14 05:58:28 +00:00
|
|
|
d->setup(service, host);
|
2004-11-05 08:54:01 +00:00
|
|
|
d->server = true;
|
2007-07-05 23:33:32 +00:00
|
|
|
d->server_realm = realm;
|
|
|
|
d->disableServerSendLast = (mode == DisableServerSendLast);
|
|
|
|
d->start();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::putServerFirstStep(const QString &mech)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->putServerFirstStep(mech, 0);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::putServerFirstStep(const QString &mech, const QByteArray &clientInit)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->putServerFirstStep(mech, &clientInit);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::putStep(const QByteArray &stepData)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->putStep(stepData);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::setUsername(const QString &user)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->set_username = true;
|
|
|
|
d->username = user;
|
2004-11-05 08:54:01 +00:00
|
|
|
d->c->setClientParams(&user, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::setAuthzid(const QString &authzid)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->set_authzid = true;
|
|
|
|
d->authzid = authzid;
|
2004-11-05 08:54:01 +00:00
|
|
|
d->c->setClientParams(0, &authzid, 0, 0);
|
|
|
|
}
|
|
|
|
|
2007-04-13 19:04:16 +00:00
|
|
|
void SASL::setPassword(const SecureArray &pass)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->set_password = true;
|
|
|
|
d->password = pass;
|
2004-11-05 08:54:01 +00:00
|
|
|
d->c->setClientParams(0, 0, &pass, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::setRealm(const QString &realm)
|
|
|
|
{
|
2007-07-05 23:33:32 +00:00
|
|
|
d->set_realm = true;
|
|
|
|
d->realm = realm;
|
2004-11-05 08:54:01 +00:00
|
|
|
d->c->setClientParams(0, 0, 0, &realm);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::continueAfterParams()
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->tryAgain();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::continueAfterAuthCheck()
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->tryAgain();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-07-31 01:27:27 +00:00
|
|
|
QString SASL::mechanism() const
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
return d->c->mech();
|
2005-07-31 01:27:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QStringList SASL::mechanismList() const
|
|
|
|
{
|
2007-06-08 22:08:57 +00:00
|
|
|
return d->c->mechlist();
|
2005-07-31 01:27:27 +00:00
|
|
|
}
|
|
|
|
|
2007-06-11 23:18:19 +00:00
|
|
|
QStringList SASL::realmList() const
|
|
|
|
{
|
|
|
|
return d->c->realmlist();
|
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
int SASL::ssf() const
|
|
|
|
{
|
2005-07-31 01:27:27 +00:00
|
|
|
return d->c->ssf();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2004-11-13 10:13:12 +00:00
|
|
|
int SASL::bytesAvailable() const
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
return d->in.size();
|
2004-11-13 10:13:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int SASL::bytesOutgoingAvailable() const
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
return d->to_net.size();
|
2004-11-13 10:13:12 +00:00
|
|
|
}
|
|
|
|
|
2005-06-24 23:41:25 +00:00
|
|
|
void SASL::write(const QByteArray &a)
|
2004-11-13 10:13:12 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->out.append(a);
|
2007-07-06 00:35:13 +00:00
|
|
|
d->layer.addPlain(a.size());
|
2006-11-14 05:58:28 +00:00
|
|
|
d->update();
|
2004-11-13 10:13:12 +00:00
|
|
|
}
|
|
|
|
|
2005-06-24 23:41:25 +00:00
|
|
|
QByteArray SASL::read()
|
2004-11-13 10:13:12 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
QByteArray a = d->in;
|
|
|
|
d->in.clear();
|
|
|
|
return a;
|
2004-11-13 10:13:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::writeIncoming(const QByteArray &a)
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->from_net.append(a);
|
|
|
|
d->update();
|
2004-11-13 10:13:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray SASL::readOutgoing(int *plainBytes)
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
QByteArray a = d->to_net;
|
|
|
|
d->to_net.clear();
|
|
|
|
if(plainBytes)
|
|
|
|
*plainBytes = d->bytesEncoded;
|
2007-07-06 00:35:13 +00:00
|
|
|
d->layer.specifyEncoded(a.size(), d->bytesEncoded);
|
2006-11-14 05:58:28 +00:00
|
|
|
d->bytesEncoded = 0;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2007-07-06 00:35:13 +00:00
|
|
|
int SASL::convertBytesWritten(qint64 bytes)
|
|
|
|
{
|
|
|
|
return d->layer.finished(bytes);
|
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
2005-07-28 12:17:09 +00:00
|
|
|
|
|
|
|
#include "qca_securelayer.moc"
|