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-08-20 00:15:19 +00:00
|
|
|
enum ResetMode
|
|
|
|
{
|
|
|
|
ResetSession = 0,
|
|
|
|
ResetSessionAndData = 1,
|
|
|
|
ResetAll = 2
|
|
|
|
};
|
|
|
|
|
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-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:
|
2007-08-20 00:15:19 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
OpStart,
|
|
|
|
OpUpdate
|
|
|
|
};
|
|
|
|
|
|
|
|
enum State
|
|
|
|
{
|
|
|
|
Inactive,
|
|
|
|
Initializing,
|
|
|
|
Handshaking,
|
|
|
|
Connected,
|
|
|
|
Closing
|
|
|
|
};
|
|
|
|
|
|
|
|
class Action
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum Type
|
|
|
|
{
|
|
|
|
ReadyRead,
|
|
|
|
ReadyReadOutgoing,
|
|
|
|
Handshaken,
|
|
|
|
Close,
|
|
|
|
CheckPeerCertificate,
|
|
|
|
CertificateRequested,
|
|
|
|
HostNameReceived
|
|
|
|
};
|
|
|
|
|
|
|
|
int type;
|
|
|
|
|
|
|
|
Action(int _type) : type(_type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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-08-20 00:15:19 +00:00
|
|
|
// signal connected flags
|
|
|
|
bool connect_hostNameReceived;
|
|
|
|
bool connect_certificateRequested;
|
|
|
|
bool connect_peerCertificateAvailable;
|
|
|
|
bool connect_handshaken;
|
|
|
|
|
|
|
|
// persistent settings (survives ResetSessionAndData)
|
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;
|
|
|
|
bool tryCompress;
|
2007-07-04 00:54:52 +00:00
|
|
|
int packet_mtu;
|
2007-08-20 00:15:19 +00:00
|
|
|
QList<CertificateInfoOrdered> issuerList;
|
|
|
|
TLSSession session;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// session
|
|
|
|
State state;
|
|
|
|
bool blocked;
|
|
|
|
bool server;
|
2005-04-24 19:09:06 +00:00
|
|
|
QString host;
|
2007-08-20 00:15:19 +00:00
|
|
|
TLSContext::SessionInfo sessionInfo;
|
|
|
|
QTimer actionTrigger;
|
|
|
|
int op;
|
|
|
|
QList<Action> actionQueue;
|
|
|
|
bool need_update;
|
|
|
|
bool maybe_input;
|
|
|
|
bool emitted_hostNameReceived;
|
|
|
|
bool emitted_certificateRequested;
|
|
|
|
bool emitted_peerCertificateAvailable;
|
|
|
|
|
|
|
|
// data (survives ResetSession)
|
2005-04-24 19:09:06 +00:00
|
|
|
CertificateChain peerCert;
|
|
|
|
Validity peerValidity;
|
|
|
|
bool hostMismatch;
|
2007-08-20 00:15:19 +00:00
|
|
|
Error errorCode;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// stream i/o
|
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-08-20 00:15:19 +00:00
|
|
|
QByteArray unprocessed;
|
|
|
|
int out_pending;
|
|
|
|
int to_net_encoded;
|
2007-07-06 00:35:13 +00:00
|
|
|
LayerTracker layer;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// datagram i/o
|
2007-07-04 00:54:52 +00:00
|
|
|
QList<QByteArray> packet_in, packet_out;
|
|
|
|
QList<QByteArray> packet_to_net, packet_from_net;
|
2007-08-20 00:15:19 +00:00
|
|
|
int packet_out_pending; // packet count
|
2007-07-04 00:54:52 +00:00
|
|
|
QList<int> packet_to_net_encoded;
|
2005-07-28 12:17:09 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
Private(TLS *_q, TLS::Mode _mode) : QObject(_q), q(_q), mode(_mode), actionTrigger(this)
|
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-06 19:50:55 +00:00
|
|
|
connect_peerCertificateAvailable = 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
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
connect(&actionTrigger, SIGNAL(timeout()), SLOT(doNextAction()));
|
|
|
|
actionTrigger.setSingleShot(true);
|
|
|
|
|
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()));
|
2007-08-20 00:15:19 +00:00
|
|
|
connect(c, SIGNAL(dtlsTimeout()), SLOT(tls_dtlsTimeout()));
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
~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-08-20 00:15:19 +00:00
|
|
|
// if we reset while in client mode, then clear this list
|
|
|
|
// (it should only persist when used for server mode)
|
2007-07-06 18:03:29 +00:00
|
|
|
if(!server)
|
|
|
|
issuerList.clear();
|
2007-08-20 00:15:19 +00:00
|
|
|
|
|
|
|
state = Inactive;
|
|
|
|
blocked = false;
|
2007-07-04 00:54:52 +00:00
|
|
|
server = false;
|
2005-04-24 19:09:06 +00:00
|
|
|
host = QString();
|
2007-08-20 00:15:19 +00:00
|
|
|
sessionInfo = TLSContext::SessionInfo();
|
|
|
|
actionTrigger.stop();
|
|
|
|
op = -1;
|
|
|
|
actionQueue.clear();
|
|
|
|
need_update = false;
|
|
|
|
maybe_input = false;
|
|
|
|
emitted_hostNameReceived = false;
|
|
|
|
emitted_certificateRequested = false;
|
|
|
|
emitted_peerCertificateAvailable = false;
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
out.clear();
|
2007-08-20 00:15:19 +00:00
|
|
|
out_pending = 0;
|
2007-07-04 00:54:52 +00:00
|
|
|
packet_out.clear();
|
2007-08-20 00:15:19 +00:00
|
|
|
packet_out_pending = 0;
|
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;
|
2007-08-20 00:15:19 +00:00
|
|
|
errorCode = (TLS::Error)-1;
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
in.clear();
|
|
|
|
to_net.clear();
|
|
|
|
from_net.clear();
|
2007-08-20 00:15:19 +00:00
|
|
|
unprocessed.clear();
|
|
|
|
to_net_encoded = 0;
|
|
|
|
layer.reset();
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
packet_in.clear();
|
|
|
|
packet_to_net.clear();
|
|
|
|
packet_from_net.clear();
|
2007-08-20 00:15:19 +00:00
|
|
|
packet_to_net_encoded.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-08-20 00:15:19 +00:00
|
|
|
state = Initializing;
|
2007-07-04 00:54:52 +00:00
|
|
|
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-08-20 00:15:19 +00:00
|
|
|
QCA_logTextMessage(QString("tls[%1]: c->start()").arg(q->objectName()), Logger::Information);
|
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()
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
QCA_logTextMessage(QString("tls[%1]: close").arg(q->objectName()), Logger::Information);
|
|
|
|
|
|
|
|
if(state != Connected)
|
2005-04-24 19:09:06 +00:00
|
|
|
return;
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
state = Closing;
|
2007-07-04 00:54:52 +00:00
|
|
|
c->shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
void continueAfterStep()
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
QCA_logTextMessage(QString("tls[%1]: continueAfterStep").arg(q->objectName()), Logger::Information);
|
|
|
|
|
|
|
|
if(!blocked)
|
|
|
|
return;
|
2007-07-04 00:54:52 +00:00
|
|
|
|
|
|
|
blocked = false;
|
|
|
|
update();
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
void processNextAction()
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
if(actionQueue.isEmpty())
|
|
|
|
{
|
|
|
|
if(need_update)
|
2007-08-28 00:45:38 +00:00
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: need_update").arg(q->objectName()), Logger::Information);
|
2007-08-20 00:15:19 +00:00
|
|
|
update();
|
2007-08-28 00:45:38 +00:00
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
return;
|
2007-08-20 00:15:19 +00:00
|
|
|
}
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
Action a = actionQueue.takeFirst();
|
2005-07-28 12:17:09 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// set up for the next one, if necessary
|
|
|
|
if(!actionQueue.isEmpty() || need_update)
|
2007-07-06 19:50:55 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!actionTrigger.isActive())
|
|
|
|
actionTrigger.start();
|
|
|
|
}
|
2007-07-06 19:50:55 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(a.type == Action::ReadyRead)
|
|
|
|
{
|
|
|
|
emit q->readyRead();
|
|
|
|
}
|
|
|
|
else if(a.type == Action::ReadyReadOutgoing)
|
|
|
|
{
|
|
|
|
emit q->readyReadOutgoing();
|
|
|
|
}
|
|
|
|
else if(a.type == Action::Handshaken)
|
|
|
|
{
|
|
|
|
state = Connected;
|
2007-08-20 04:01:00 +00:00
|
|
|
|
|
|
|
// write any app data waiting during handshake
|
|
|
|
if(!out.isEmpty())
|
|
|
|
{
|
|
|
|
need_update = true;
|
|
|
|
if(!actionTrigger.isActive())
|
|
|
|
actionTrigger.start();
|
|
|
|
}
|
|
|
|
|
2007-07-06 19:50:55 +00:00
|
|
|
if(connect_handshaken)
|
|
|
|
{
|
|
|
|
blocked = true;
|
2007-08-20 00:15:19 +00:00
|
|
|
emit q->handshaken();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(a.type == Action::Close)
|
|
|
|
{
|
|
|
|
unprocessed = c->unprocessed();
|
|
|
|
reset(ResetSession);
|
|
|
|
emit q->closed();
|
|
|
|
}
|
|
|
|
else if(a.type == Action::CheckPeerCertificate)
|
|
|
|
{
|
|
|
|
peerCert = c->peerCertificateChain();
|
|
|
|
if(!peerCert.isEmpty())
|
|
|
|
{
|
|
|
|
peerValidity = c->peerCertificateValidity();
|
|
|
|
if(peerValidity == ValidityGood && !host.isEmpty() && !peerCert.primary().matchesHostName(host))
|
|
|
|
hostMismatch = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(connect_peerCertificateAvailable)
|
|
|
|
{
|
|
|
|
blocked = true;
|
|
|
|
emitted_peerCertificateAvailable = true;
|
|
|
|
emit q->peerCertificateAvailable();
|
2007-07-06 19:50:55 +00:00
|
|
|
}
|
|
|
|
}
|
2007-08-20 00:15:19 +00:00
|
|
|
else if(a.type == Action::CertificateRequested)
|
|
|
|
{
|
|
|
|
issuerList = c->issuerList();
|
|
|
|
if(connect_certificateRequested)
|
|
|
|
{
|
|
|
|
blocked = true;
|
|
|
|
emitted_certificateRequested = true;
|
|
|
|
emit q->certificateRequested();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(a.type == Action::HostNameReceived)
|
|
|
|
{
|
|
|
|
if(connect_hostNameReceived)
|
|
|
|
{
|
|
|
|
blocked = true;
|
|
|
|
emitted_hostNameReceived = true;
|
|
|
|
emit q->hostNameReceived();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void update()
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: update").arg(q->objectName()), Logger::Information);
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(blocked)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
QCA_logTextMessage(QString("tls[%1]: ignoring update while blocked").arg(q->objectName()), Logger::Information);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!actionQueue.isEmpty())
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: ignoring update while processing actions").arg(q->objectName()), Logger::Information);
|
|
|
|
need_update = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// only allow one operation at a time
|
|
|
|
if(op != -1)
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: ignoring update while operation active").arg(q->objectName()), Logger::Information);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-08-23 05:05:08 +00:00
|
|
|
need_update = false;
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
QByteArray arg_from_net, arg_from_app;
|
|
|
|
|
|
|
|
if(state == Handshaking)
|
|
|
|
{
|
|
|
|
// during handshake, only send from_net (no app data)
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
if(mode == TLS::Stream)
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
arg_from_net = from_net;
|
|
|
|
from_net.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// note: there may not be a packet
|
2007-08-20 01:13:19 +00:00
|
|
|
if(!packet_from_net.isEmpty())
|
|
|
|
arg_from_net = packet_from_net.takeFirst();
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
if(!from_net.isEmpty())
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
arg_from_net = from_net;
|
2007-07-05 23:33:32 +00:00
|
|
|
from_net.clear();
|
|
|
|
}
|
2007-08-20 01:13:19 +00:00
|
|
|
|
|
|
|
if(!out.isEmpty())
|
2007-07-05 23:33:32 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
out_pending += out.size();
|
|
|
|
arg_from_app = out;
|
2007-07-05 23:33:32 +00:00
|
|
|
out.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-20 01:13:19 +00:00
|
|
|
if(!packet_from_net.isEmpty())
|
|
|
|
arg_from_net = packet_from_net.takeFirst();
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!packet_out.isEmpty())
|
|
|
|
{
|
|
|
|
arg_from_app = packet_out.takeFirst();
|
|
|
|
++packet_out_pending;
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
2007-08-20 00:15:19 +00:00
|
|
|
|
|
|
|
if(arg_from_net.isEmpty() && arg_from_app.isEmpty() && !maybe_input)
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: ignoring update: no output and no expected input").arg(q->objectName()), Logger::Information);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// clear this flag
|
|
|
|
maybe_input = false;
|
|
|
|
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: c->update").arg(q->objectName()), Logger::Information);
|
|
|
|
op = OpUpdate;
|
|
|
|
c->update(arg_from_net, arg_from_app);
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
void start_finished()
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
bool ok = c->result() == TLSContext::Success;
|
|
|
|
if(!ok)
|
|
|
|
{
|
|
|
|
reset(ResetSession);
|
|
|
|
errorCode = TLS::ErrorInit;
|
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
state = Handshaking;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// immediately update so we can get the first packet to send
|
|
|
|
maybe_input = true;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void update_finished()
|
|
|
|
{
|
|
|
|
TLSContext::Result r = c->result();
|
|
|
|
if(r == TLSContext::Error)
|
2007-07-04 00:54:52 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
if(state == Handshaking || state == Closing)
|
|
|
|
{
|
|
|
|
reset(ResetSession);
|
|
|
|
errorCode = ErrorHandshake;
|
|
|
|
}
|
|
|
|
else
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2007-08-20 00:15:19 +00:00
|
|
|
errorCode = ErrorCrypt;
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
emit q->error();
|
|
|
|
return;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
2007-08-20 00:15:19 +00:00
|
|
|
|
|
|
|
QByteArray c_to_net = c->to_net();
|
2007-08-28 00:45:38 +00:00
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: to_net %2").arg(q->objectName(), QString::number(c_to_net.size())), Logger::Information);
|
|
|
|
}
|
2007-08-20 00:15:19 +00:00
|
|
|
|
|
|
|
if(state == Closing)
|
2007-07-04 00:54:52 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
if(mode == TLS::Stream)
|
|
|
|
to_net += c_to_net;
|
|
|
|
else
|
|
|
|
packet_to_net += c_to_net;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
actionQueue += Action(Action::ReadyReadOutgoing);
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(r == TLSContext::Success)
|
|
|
|
actionQueue += Action(Action::Close);
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
processNextAction();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(state == Handshaking)
|
|
|
|
{
|
|
|
|
if(mode == TLS::Stream)
|
|
|
|
to_net += c_to_net;
|
|
|
|
else
|
|
|
|
packet_to_net += c_to_net;
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
actionQueue += Action(Action::ReadyReadOutgoing);
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
bool clientHello = false;
|
|
|
|
bool serverHello = false;
|
|
|
|
if(server)
|
|
|
|
clientHello = c->clientHelloReceived();
|
|
|
|
else
|
|
|
|
serverHello = c->serverHelloReceived();
|
2005-04-24 19:09:06 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// client specifies a host?
|
|
|
|
if(!emitted_hostNameReceived && clientHello)
|
2005-04-24 19:09:06 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
host = c->hostName();
|
|
|
|
if(!host.isEmpty())
|
|
|
|
actionQueue += Action(Action::HostNameReceived);
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// successful handshake or server hello means there might be a peer cert
|
|
|
|
if(!emitted_peerCertificateAvailable && (r == TLSContext::Success || (!server && serverHello)))
|
|
|
|
actionQueue += Action(Action::CheckPeerCertificate);
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
// server requests a cert from us?
|
|
|
|
if(!emitted_certificateRequested && (serverHello && c->certificateRequested()))
|
|
|
|
actionQueue += Action(Action::CertificateRequested);
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(r == TLSContext::Success)
|
|
|
|
{
|
|
|
|
sessionInfo = c->sessionInfo();
|
|
|
|
if(sessionInfo.id)
|
2007-07-04 00:54:52 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
TLSSessionContext *sc = static_cast<TLSSessionContext*>(sessionInfo.id->clone());
|
|
|
|
session.change(sc);
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
actionQueue += Action(Action::Handshaken);
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
processNextAction();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else // Connected
|
|
|
|
{
|
|
|
|
QByteArray c_to_app = c->to_app();
|
2007-08-28 00:45:38 +00:00
|
|
|
if(!c_to_app.isEmpty())
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: to_app %2").arg(q->objectName(), QString::number(c_to_app.size())), Logger::Information);
|
|
|
|
}
|
|
|
|
|
2007-07-04 00:54:52 +00:00
|
|
|
bool eof = c->eof();
|
2007-08-20 00:15:19 +00:00
|
|
|
int enc = -1;
|
|
|
|
if(!c_to_net.isEmpty())
|
2007-08-15 00:29:44 +00:00
|
|
|
enc = c->encoded();
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
bool io_pending = false;
|
2007-07-04 00:54:52 +00:00
|
|
|
if(mode == TLS::Stream)
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
out_pending -= enc;
|
|
|
|
|
|
|
|
if(out_pending > 0)
|
2007-07-10 18:16:06 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
maybe_input = true;
|
|
|
|
io_pending = true;
|
2007-07-10 18:16:06 +00:00
|
|
|
}
|
2007-08-20 00:15:19 +00:00
|
|
|
|
|
|
|
if(!out.isEmpty())
|
|
|
|
io_pending = true;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
--packet_out_pending;
|
|
|
|
|
|
|
|
if(packet_out_pending > 0)
|
2007-07-04 00:54:52 +00:00
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
maybe_input = true;
|
|
|
|
io_pending = true;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!packet_out.isEmpty())
|
2007-08-20 00:15:19 +00:00
|
|
|
io_pending = true;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(mode == TLS::Stream)
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
to_net += c_to_net;
|
|
|
|
in += c_to_app;
|
|
|
|
to_net_encoded += enc;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
packet_to_net += c_to_net;
|
|
|
|
packet_in += c_to_app;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
actionQueue += Action(Action::ReadyReadOutgoing);
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(!c_to_app.isEmpty())
|
|
|
|
actionQueue += Action(Action::ReadyRead);
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
if(eof)
|
2007-08-20 00:15:19 +00:00
|
|
|
{
|
2007-07-04 00:54:52 +00:00
|
|
|
close();
|
2007-08-20 00:15:19 +00:00
|
|
|
maybe_input = true;
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(eof || io_pending)
|
2007-08-28 00:45:38 +00:00
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: eof || io_pending").arg(q->objectName()), Logger::Information);
|
2007-07-04 00:54:52 +00:00
|
|
|
update();
|
2007-08-28 00:45:38 +00:00
|
|
|
}
|
2007-08-20 00:15:19 +00:00
|
|
|
|
|
|
|
processNextAction();
|
|
|
|
return;
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
2005-07-28 12:17:09 +00:00
|
|
|
}
|
2007-08-20 00:15:19 +00:00
|
|
|
|
|
|
|
private slots:
|
|
|
|
void tls_resultsReady()
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: c->resultsReady()").arg(q->objectName()), Logger::Information);
|
|
|
|
|
|
|
|
Q_ASSERT(op != -1);
|
|
|
|
|
|
|
|
int last_op = op;
|
|
|
|
op = -1;
|
|
|
|
|
|
|
|
if(last_op == OpStart)
|
|
|
|
start_finished();
|
|
|
|
else // OpUpdate
|
|
|
|
update_finished();
|
|
|
|
}
|
|
|
|
|
|
|
|
void tls_dtlsTimeout()
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("tls[%1]: c->dtlsTimeout()").arg(q->objectName()), Logger::Information);
|
|
|
|
|
|
|
|
maybe_input = true;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void doNextAction()
|
|
|
|
{
|
|
|
|
processNextAction();
|
|
|
|
}
|
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-08-20 00:15:19 +00:00
|
|
|
if(d->state != TLS::Private::Inactive)
|
2007-07-04 00:54:52 +00:00
|
|
|
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-08-20 00:15:19 +00:00
|
|
|
if(d->state != TLS::Private::Inactive)
|
2007-07-04 00:54:52 +00:00
|
|
|
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
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(d->state != TLS::Private::Inactive)
|
2007-07-04 00:54:52 +00:00
|
|
|
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
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(d->state != TLS::Private::Inactive)
|
2007-07-04 00:54:52 +00:00
|
|
|
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
|
|
|
|
2007-08-20 00:15:19 +00:00
|
|
|
if(d->state != TLS::Private::Inactive)
|
2007-07-04 00:54:52 +00:00
|
|
|
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;
|
2007-08-20 00:15:19 +00:00
|
|
|
if(d->state != TLS::Private::Inactive)
|
2007-07-04 00:54:52 +00:00
|
|
|
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
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
if(d->state == TLS::Private::Connected || d->state == TLS::Private::Closing)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
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);
|
2007-08-28 00:45:38 +00:00
|
|
|
QCA_logTextMessage(QString("tls[%1]: write").arg(objectName()), Logger::Information);
|
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
|
2007-08-20 01:13:19 +00:00
|
|
|
{
|
|
|
|
if(!d->packet_in.isEmpty())
|
|
|
|
return d->packet_in.takeFirst();
|
|
|
|
else
|
|
|
|
return QByteArray();
|
|
|
|
}
|
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);
|
2007-08-28 00:45:38 +00:00
|
|
|
QCA_logTextMessage(QString("tls[%1]: writeIncoming %2").arg(objectName(), QString::number(a.size())), Logger::Information);
|
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)
|
2007-08-20 00:15:19 +00:00
|
|
|
*plainBytes = d->to_net_encoded;
|
|
|
|
d->layer.specifyEncoded(a.size(), d->to_net_encoded);
|
|
|
|
d->to_net_encoded = 0;
|
2007-07-04 00:54:52 +00:00
|
|
|
return a;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-08-20 01:13:19 +00:00
|
|
|
if(!d->packet_to_net.isEmpty())
|
|
|
|
{
|
|
|
|
QByteArray a = d->packet_to_net.takeFirst();
|
|
|
|
int x = d->packet_to_net_encoded.takeFirst();
|
|
|
|
if(plainBytes)
|
|
|
|
*plainBytes = x;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(plainBytes)
|
|
|
|
*plainBytes = 0;
|
|
|
|
return QByteArray();
|
|
|
|
}
|
2007-07-04 00:54:52 +00:00
|
|
|
}
|
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)
|
|
|
|
{
|
2007-08-20 00:15:19 +00:00
|
|
|
QByteArray a = d->unprocessed;
|
|
|
|
d->unprocessed.clear();
|
2007-07-04 00:54:52 +00:00
|
|
|
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;
|
2007-08-20 00:15:19 +00:00
|
|
|
if(d->state != TLS::Private::Inactive)
|
2007-07-04 00:54:52 +00:00
|
|
|
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-06 19:50:55 +00:00
|
|
|
else if(signal == QMetaObject::normalizedSignature(SIGNAL(peerCertificateAvailable())))
|
|
|
|
d->connect_peerCertificateAvailable = 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-06 19:50:55 +00:00
|
|
|
else if(signal == QMetaObject::normalizedSignature(SIGNAL(peerCertificateAvailable())))
|
|
|
|
d->connect_peerCertificateAvailable = 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
|
|
|
enum
|
|
|
|
{
|
|
|
|
OpStart,
|
|
|
|
OpServerFirstStep,
|
|
|
|
OpNextStep,
|
|
|
|
OpTryAgain,
|
|
|
|
OpUpdate
|
|
|
|
};
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
class Action
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
enum Type
|
|
|
|
{
|
|
|
|
NextStep,
|
|
|
|
Authenticated,
|
|
|
|
ReadyRead,
|
|
|
|
ReadyReadOutgoing
|
|
|
|
};
|
|
|
|
|
|
|
|
int type;
|
|
|
|
QByteArray stepData;
|
|
|
|
|
|
|
|
Action(int _type) : type(_type)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Action(int _type, const QByteArray &_stepData) : type(_type), stepData(_stepData)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
SASL *q;
|
|
|
|
SASLContext *c;
|
|
|
|
|
|
|
|
// persistent settings (survives ResetSessionAndData)
|
2007-07-05 23:33:32 +00:00
|
|
|
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;
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
// session
|
2007-07-05 23:33:32 +00:00
|
|
|
bool server;
|
|
|
|
QStringList mechlist;
|
|
|
|
QString server_realm;
|
|
|
|
bool allowClientSendFirst;
|
|
|
|
bool disableServerSendLast;
|
2007-08-20 04:01:00 +00:00
|
|
|
QTimer actionTrigger;
|
2007-07-05 23:33:32 +00:00
|
|
|
int op;
|
2007-08-20 04:01:00 +00:00
|
|
|
QList<Action> actionQueue;
|
|
|
|
bool need_update;
|
2007-07-05 23:33:32 +00:00
|
|
|
bool first;
|
|
|
|
bool authed;
|
2007-08-20 04:01:00 +00:00
|
|
|
|
|
|
|
// data (survives ResetSession)
|
|
|
|
QString mech; // selected mech
|
2007-07-05 23:33:32 +00:00
|
|
|
Error errorCode;
|
2007-08-20 04:01:00 +00:00
|
|
|
|
|
|
|
// stream i/o
|
|
|
|
QByteArray in, out;
|
|
|
|
QByteArray to_net, from_net;
|
|
|
|
int out_pending;
|
|
|
|
int to_net_encoded;
|
2007-07-06 00:35:13 +00:00
|
|
|
LayerTracker layer;
|
2007-07-05 23:33:32 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
Private(SASL *_q) : QObject(_q), q(_q), actionTrigger(this)
|
2007-07-05 23:33:32 +00:00
|
|
|
{
|
|
|
|
c = 0;
|
|
|
|
set_username = false;
|
|
|
|
set_authzid = false;
|
|
|
|
set_password = false;
|
|
|
|
set_realm = false;
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
connect(&actionTrigger, SIGNAL(timeout()), SLOT(doNextAction()));
|
|
|
|
actionTrigger.setSingleShot(true);
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
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();
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
server = false;
|
|
|
|
mechlist.clear();
|
|
|
|
server_realm = QString();
|
|
|
|
allowClientSendFirst = false;
|
|
|
|
disableServerSendLast = true;
|
|
|
|
actionTrigger.stop();
|
2007-07-05 23:33:32 +00:00
|
|
|
op = -1;
|
2007-08-20 04:01:00 +00:00
|
|
|
actionQueue.clear();
|
|
|
|
need_update = false;
|
|
|
|
first = false;
|
2007-07-05 23:33:32 +00:00
|
|
|
authed = false;
|
2007-08-20 04:01:00 +00:00
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
out.clear();
|
2007-08-20 04:01:00 +00:00
|
|
|
out_pending = 0;
|
2007-07-05 23:33:32 +00:00
|
|
|
|
|
|
|
if(mode >= ResetSessionAndData)
|
|
|
|
{
|
2007-08-20 04:01:00 +00:00
|
|
|
mech = QString();
|
|
|
|
errorCode = (SASL::Error)-1;
|
|
|
|
|
2007-07-05 23:33:32 +00:00
|
|
|
in.clear();
|
|
|
|
to_net.clear();
|
2007-08-20 04:01:00 +00:00
|
|
|
from_net.clear();
|
|
|
|
to_net_encoded = 0;
|
|
|
|
layer.reset();
|
2007-07-05 23:33:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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-08-20 04:01:00 +00:00
|
|
|
|
|
|
|
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);
|
2006-11-14 05:58:28 +00:00
|
|
|
}
|
|
|
|
|
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)
|
2007-08-20 04:01:00 +00:00
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("sasl[%1]: c->startServer()").arg(q->objectName()), Logger::Information);
|
2007-07-05 23:33:32 +00:00
|
|
|
c->startServer(server_realm, disableServerSendLast);
|
2007-08-20 04:01:00 +00:00
|
|
|
}
|
2006-11-14 05:58:28 +00:00
|
|
|
else
|
2007-08-20 04:01:00 +00:00
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("sasl[%1]: c->startClient()").arg(q->objectName()), Logger::Information);
|
2007-07-05 23:33:32 +00:00
|
|
|
c->startClient(mechlist, allowClientSendFirst);
|
2007-08-20 04:01:00 +00:00
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void putServerFirstStep(const QString &mech, const QByteArray *clientInit)
|
|
|
|
{
|
|
|
|
if(op != -1)
|
|
|
|
return;
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
QCA_logTextMessage(QString("sasl[%1]: c->serverFirstStep()").arg(q->objectName()), Logger::Information);
|
2007-07-05 23:33:32 +00:00
|
|
|
op = OpServerFirstStep;
|
|
|
|
c->serverFirstStep(mech, clientInit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void putStep(const QByteArray &stepData)
|
|
|
|
{
|
|
|
|
if(op != -1)
|
|
|
|
return;
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
QCA_logTextMessage(QString("sasl[%1]: c->nextStep()").arg(q->objectName()), Logger::Information);
|
2007-07-05 23:33:32 +00:00
|
|
|
op = OpNextStep;
|
|
|
|
c->nextStep(stepData);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tryAgain()
|
|
|
|
{
|
|
|
|
if(op != -1)
|
|
|
|
return;
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
QCA_logTextMessage(QString("sasl[%1]: c->tryAgain()").arg(q->objectName()), Logger::Information);
|
2007-07-05 23:33:32 +00:00
|
|
|
op = OpTryAgain;
|
|
|
|
c->tryAgain();
|
2006-11-14 05:58:28 +00:00
|
|
|
}
|
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
void processNextAction()
|
|
|
|
{
|
|
|
|
if(actionQueue.isEmpty())
|
|
|
|
{
|
|
|
|
if(need_update)
|
|
|
|
update();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Action a = actionQueue.takeFirst();
|
|
|
|
|
|
|
|
// set up for the next one, if necessary
|
|
|
|
if(!actionQueue.isEmpty() || need_update)
|
|
|
|
{
|
|
|
|
if(!actionTrigger.isActive())
|
|
|
|
actionTrigger.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(a.type == Action::NextStep)
|
|
|
|
{
|
|
|
|
emit q->nextStep(a.stepData);
|
|
|
|
}
|
|
|
|
else if(a.type == Action::Authenticated)
|
|
|
|
{
|
|
|
|
authed = true;
|
|
|
|
if(!out.isEmpty())
|
|
|
|
{
|
|
|
|
need_update = true;
|
|
|
|
if(!actionTrigger.isActive())
|
|
|
|
actionTrigger.start();
|
|
|
|
}
|
|
|
|
emit q->authenticated();
|
|
|
|
}
|
|
|
|
else if(a.type == Action::ReadyRead)
|
|
|
|
{
|
|
|
|
emit q->readyRead();
|
|
|
|
}
|
|
|
|
else if(a.type == Action::ReadyReadOutgoing)
|
|
|
|
{
|
|
|
|
emit q->readyReadOutgoing();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
void update()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2007-08-20 04:01:00 +00:00
|
|
|
// defer writes while authenticating
|
|
|
|
if(!authed)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(!actionQueue.isEmpty())
|
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("sasl[%1]: ignoring update while processing actions").arg(q->objectName()), Logger::Information);
|
|
|
|
need_update = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// only allow one operation at a time
|
2007-07-05 23:33:32 +00:00
|
|
|
if(op != -1)
|
2007-08-20 04:01:00 +00:00
|
|
|
{
|
|
|
|
QCA_logTextMessage(QString("sasl[%1]: ignoring update while operation active").arg(q->objectName()), Logger::Information);
|
2007-07-05 23:33:32 +00:00
|
|
|
return;
|
2007-08-20 04:01:00 +00:00
|
|
|
}
|
2007-07-05 23:33:32 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
QCA_logTextMessage(QString("sasl[%1]: c->update()").arg(q->objectName()), Logger::Information);
|
2007-07-05 23:33:32 +00:00
|
|
|
op = OpUpdate;
|
2007-08-20 04:01:00 +00:00
|
|
|
out_pending += out.size();
|
2007-07-04 01:22:12 +00:00
|
|
|
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
|
|
|
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
|
|
|
{
|
2007-08-20 04:01:00 +00:00
|
|
|
mech = c->mech();
|
|
|
|
|
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)
|
|
|
|
{
|
2007-07-08 02:02:59 +00:00
|
|
|
if(!disableServerSendLast)
|
2007-08-20 04:01:00 +00:00
|
|
|
actionQueue += Action(Action::NextStep, c->stepData());
|
2007-07-05 23:33:32 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
actionQueue += Action(Action::Authenticated);
|
|
|
|
|
|
|
|
processNextAction();
|
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)
|
|
|
|
{
|
2007-08-20 04:01:00 +00:00
|
|
|
actionQueue += Action(Action::NextStep, c->stepData());
|
|
|
|
actionQueue += Action(Action::Authenticated);
|
2007-07-05 23:33:32 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
processNextAction();
|
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
|
|
|
}
|
|
|
|
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-08-20 04:01:00 +00:00
|
|
|
QByteArray c_to_net = c->to_net();
|
|
|
|
QByteArray c_to_app = c->to_app();
|
|
|
|
int enc = -1;
|
|
|
|
if(!c_to_net.isEmpty())
|
2007-08-15 00:29:44 +00:00
|
|
|
enc = c->encoded();
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
bool io_pending = false;
|
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
out_pending -= enc;
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
if(out_pending > 0)
|
|
|
|
io_pending = true;
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
if(!out.isEmpty())
|
|
|
|
io_pending = true;
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
to_net += c_to_net;
|
|
|
|
in += c_to_app;
|
|
|
|
to_net_encoded += enc;
|
|
|
|
|
|
|
|
if(!c_to_net.isEmpty())
|
|
|
|
actionQueue += Action(Action::ReadyReadOutgoing);
|
|
|
|
|
|
|
|
if(!c_to_app.isEmpty())
|
|
|
|
actionQueue += Action(Action::ReadyRead);
|
2007-07-04 01:22:12 +00:00
|
|
|
|
2007-08-20 04:01:00 +00:00
|
|
|
if(io_pending)
|
2007-07-05 23:33:32 +00:00
|
|
|
update();
|
2007-08-20 04:01:00 +00:00
|
|
|
|
|
|
|
processNextAction();
|
|
|
|
return;
|
2007-07-04 01:22:12 +00:00
|
|
|
}
|
|
|
|
}
|
2007-08-20 04:01:00 +00:00
|
|
|
|
|
|
|
void doNextAction()
|
|
|
|
{
|
|
|
|
processNextAction();
|
|
|
|
}
|
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;
|
2007-08-20 04:01:00 +00:00
|
|
|
if(s == SL_Integrity)
|
2006-11-14 05:58:28 +00:00
|
|
|
min = 1;
|
2007-08-20 04:01:00 +00:00
|
|
|
else if(s == SL_Export)
|
2006-11-14 05:58:28 +00:00
|
|
|
min = 56;
|
2007-08-20 04:01:00 +00:00
|
|
|
else if(s == SL_Baseline)
|
2006-11-14 05:58:28 +00:00
|
|
|
min = 128;
|
2007-08-20 04:01:00 +00:00
|
|
|
else if(s == SL_High)
|
2006-11-14 05:58:28 +00:00
|
|
|
min = 192;
|
2007-08-20 04:01:00 +00:00
|
|
|
else if(s == SL_Highest)
|
2006-11-14 05:58:28 +00:00
|
|
|
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
|
|
|
|
{
|
2007-08-20 04:01:00 +00:00
|
|
|
return d->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)
|
2007-08-20 04:01:00 +00:00
|
|
|
*plainBytes = d->to_net_encoded;
|
|
|
|
d->layer.specifyEncoded(a.size(), d->to_net_encoded);
|
|
|
|
d->to_net_encoded = 0;
|
2006-11-14 05:58:28 +00:00
|
|
|
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"
|