2004-11-05 08:54:01 +00:00
|
|
|
/*
|
2005-01-01 02:44:28 +00:00
|
|
|
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
|
|
|
|
* 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
|
|
|
|
2005-02-27 01:12:26 +00:00
|
|
|
#include <QtCore>
|
2004-11-05 08:54:01 +00:00
|
|
|
#include "qcaprovider.h"
|
|
|
|
|
|
|
|
namespace QCA {
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
Provider::Context *getContext(const QString &type, const QString &provider);
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
CertificateChain localCert;
|
|
|
|
PrivateKey localKey;
|
|
|
|
CertificateCollection trusted;
|
|
|
|
bool con_ssfMode;
|
|
|
|
int con_minSSF, con_maxSSF;
|
|
|
|
QStringList con_cipherSuites;
|
|
|
|
bool tryCompress;
|
|
|
|
|
|
|
|
QString host;
|
|
|
|
CertificateChain peerCert;
|
|
|
|
Validity peerValidity;
|
|
|
|
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;
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
enum { OpStart, OpHandshake, OpShutdown, OpEncode, OpDecode };
|
|
|
|
int last_op;
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
bool handshaken, closing, closed, error;
|
|
|
|
bool tryMore;
|
|
|
|
int bytesEncoded;
|
|
|
|
Error errorCode;
|
|
|
|
|
2005-07-28 12:17:09 +00:00
|
|
|
Private(TLS *_q) : QObject(_q), q(_q)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
c = 0;
|
|
|
|
|
|
|
|
reset(ResetAll);
|
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();
|
|
|
|
|
|
|
|
host = QString();
|
|
|
|
out.clear();
|
2004-11-05 08:54:01 +00:00
|
|
|
handshaken = false;
|
|
|
|
closing = false;
|
2005-04-24 19:09:06 +00:00
|
|
|
closed = false;
|
|
|
|
error = false;
|
2004-11-05 08:54:01 +00:00
|
|
|
tryMore = false;
|
2005-04-24 19:09:06 +00:00
|
|
|
bytesEncoded = 0;
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(mode >= ResetAll)
|
|
|
|
{
|
|
|
|
localCert = CertificateChain();
|
|
|
|
localKey = PrivateKey();
|
|
|
|
trusted = CertificateCollection();
|
|
|
|
con_ssfMode = true;
|
|
|
|
con_minSSF = 128;
|
|
|
|
con_maxSSF = -1;
|
|
|
|
con_cipherSuites = QStringList();
|
|
|
|
tryCompress = false;
|
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
bool start(bool serverMode)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
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->setup(trusted, serverMode, QList<CertificateInfoOrdered>(), host, tryCompress);
|
|
|
|
c->setCertificate(localCert, localKey);
|
2005-04-24 19:09:06 +00:00
|
|
|
|
|
|
|
bool ok;
|
2005-07-30 09:16:05 +00:00
|
|
|
c->start();
|
2005-07-28 12:17:09 +00:00
|
|
|
last_op = OpStart;
|
|
|
|
c->waitForResultsReady(-1);
|
2005-07-30 09:16:05 +00:00
|
|
|
ok = c->result() == TLSContext::Success;
|
2005-04-24 19:09:06 +00:00
|
|
|
if(!ok)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
update();
|
|
|
|
return true;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
void close()
|
|
|
|
{
|
|
|
|
if(!handshaken || closing)
|
|
|
|
return;
|
|
|
|
|
|
|
|
closing = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void update()
|
|
|
|
{
|
|
|
|
bool wasHandshaken = handshaken;
|
2005-07-28 12:17:09 +00:00
|
|
|
//q->layerUpdateBegin();
|
|
|
|
int _read = q->bytesAvailable();
|
|
|
|
int _readout = q->bytesOutgoingAvailable();
|
|
|
|
bool _closed = closed;
|
|
|
|
bool _error = error;
|
2005-04-24 19:09:06 +00:00
|
|
|
|
|
|
|
if(closing)
|
|
|
|
updateClosing();
|
|
|
|
else
|
|
|
|
updateMain();
|
|
|
|
|
|
|
|
if(!wasHandshaken && handshaken)
|
2005-07-28 12:17:09 +00:00
|
|
|
QMetaObject::invokeMethod(q, "handshaken", Qt::QueuedConnection);
|
|
|
|
|
|
|
|
if(q->bytesAvailable() > _read)
|
|
|
|
{
|
|
|
|
emit q->readyRead();
|
|
|
|
//QMetaObject::invokeMethod(q, "readyRead", Qt::QueuedConnection);
|
|
|
|
}
|
|
|
|
if(q->bytesOutgoingAvailable() > _readout)
|
|
|
|
QMetaObject::invokeMethod(q, "readyReadOutgoing", Qt::QueuedConnection);
|
|
|
|
if(!_closed && closed)
|
|
|
|
QMetaObject::invokeMethod(q, "closed", Qt::QueuedConnection);
|
|
|
|
if(!_error && error)
|
|
|
|
QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
|
|
|
|
//q->layerUpdateEnd();
|
2005-04-24 19:09:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void updateClosing()
|
|
|
|
{
|
|
|
|
QByteArray a;
|
2005-07-28 12:17:09 +00:00
|
|
|
TLSContext::Result r;
|
2005-07-30 09:16:05 +00:00
|
|
|
c->update(from_net, QByteArray());
|
2005-07-28 12:17:09 +00:00
|
|
|
last_op = OpShutdown;
|
|
|
|
c->waitForResultsReady(-1);
|
|
|
|
a = c->to_net();
|
2005-07-30 09:16:05 +00:00
|
|
|
r = c->result();
|
2005-04-24 19:09:06 +00:00
|
|
|
from_net.clear();
|
|
|
|
|
|
|
|
if(r == TLSContext::Error)
|
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2005-04-24 19:09:06 +00:00
|
|
|
error = true;
|
|
|
|
errorCode = ErrorHandshake;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
to_net.append(a);
|
|
|
|
|
|
|
|
if(r == TLSContext::Success)
|
|
|
|
{
|
|
|
|
from_net = c->unprocessed();
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2005-04-24 19:09:06 +00:00
|
|
|
closed = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2004-11-05 08:54:01 +00:00
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
void updateMain()
|
|
|
|
{
|
|
|
|
bool force_read = false;
|
|
|
|
|
|
|
|
if(!handshaken)
|
|
|
|
{
|
|
|
|
QByteArray a;
|
2005-07-28 12:17:09 +00:00
|
|
|
TLSContext::Result r;
|
2005-07-30 09:16:05 +00:00
|
|
|
c->update(from_net, QByteArray());
|
2005-07-28 12:17:09 +00:00
|
|
|
last_op = OpHandshake;
|
|
|
|
c->waitForResultsReady(-1);
|
|
|
|
a = c->to_net();
|
2005-07-30 09:16:05 +00:00
|
|
|
r = c->result();
|
2005-04-24 19:09:06 +00:00
|
|
|
from_net.clear();
|
|
|
|
|
|
|
|
if(r == TLSContext::Error)
|
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2005-04-24 19:09:06 +00:00
|
|
|
error = true;
|
|
|
|
errorCode = ErrorHandshake;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
to_net.append(a);
|
|
|
|
|
|
|
|
if(r == TLSContext::Success)
|
|
|
|
{
|
|
|
|
peerCert = c->peerCertificateChain();
|
|
|
|
if(!peerCert.isEmpty())
|
|
|
|
{
|
|
|
|
peerValidity = c->peerCertificateValidity();
|
|
|
|
if(peerValidity == ValidityGood && !host.isEmpty() && !peerCert.primary().matchesHostname(host))
|
|
|
|
hostMismatch = true;
|
|
|
|
}
|
2005-05-06 07:12:35 +00:00
|
|
|
sessionInfo = c->sessionInfo();
|
2005-04-24 19:09:06 +00:00
|
|
|
handshaken = true;
|
|
|
|
force_read = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(handshaken)
|
|
|
|
{
|
|
|
|
bool eof = false;
|
|
|
|
|
|
|
|
if(!out.isEmpty() || tryMore)
|
|
|
|
{
|
|
|
|
tryMore = false;
|
|
|
|
QByteArray a;
|
|
|
|
int enc;
|
|
|
|
bool more = false;
|
2005-07-30 09:16:05 +00:00
|
|
|
c->update(QByteArray(), out);
|
2005-07-28 12:17:09 +00:00
|
|
|
c->waitForResultsReady(-1);
|
2005-07-30 09:16:05 +00:00
|
|
|
bool ok = c->result() == TLSContext::Success;
|
2005-07-28 12:17:09 +00:00
|
|
|
a = c->to_net();
|
|
|
|
enc = c->encoded();
|
2005-04-24 19:09:06 +00:00
|
|
|
eof = c->eof();
|
|
|
|
if(ok && enc < out.size())
|
|
|
|
more = true;
|
|
|
|
out.clear();
|
|
|
|
if(!eof)
|
|
|
|
{
|
|
|
|
if(!ok)
|
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2005-04-24 19:09:06 +00:00
|
|
|
error = true;
|
|
|
|
errorCode = ErrorCrypt;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bytesEncoded += enc;
|
|
|
|
if(more)
|
|
|
|
tryMore = true;
|
|
|
|
to_net.append(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!from_net.isEmpty() || force_read)
|
|
|
|
{
|
2005-06-24 23:41:25 +00:00
|
|
|
QByteArray a;
|
2005-04-24 19:09:06 +00:00
|
|
|
QByteArray b;
|
2005-07-30 09:16:05 +00:00
|
|
|
c->update(from_net, QByteArray());
|
2005-07-28 12:17:09 +00:00
|
|
|
c->waitForResultsReady(-1);
|
2005-07-30 09:16:05 +00:00
|
|
|
bool ok = c->result() == TLSContext::Success;
|
|
|
|
a = c->to_app();
|
2005-07-28 12:17:09 +00:00
|
|
|
b = c->to_net();
|
2005-04-24 19:09:06 +00:00
|
|
|
eof = c->eof();
|
|
|
|
from_net.clear();
|
|
|
|
if(!ok)
|
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
reset(ResetSession);
|
2005-04-24 19:09:06 +00:00
|
|
|
error = true;
|
|
|
|
errorCode = ErrorCrypt;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
in.append(a);
|
|
|
|
to_net.append(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(eof)
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
updateClosing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-07-28 12:17:09 +00:00
|
|
|
|
|
|
|
private slots:
|
|
|
|
void tls_resultsReady()
|
|
|
|
{
|
|
|
|
//printf("results ready\n");
|
|
|
|
}
|
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
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d = new Private(this);
|
|
|
|
d->c = static_cast<TLSContext *>(context());
|
2005-07-28 12:17:09 +00:00
|
|
|
d->c->setParent(d);
|
|
|
|
connect(d->c, SIGNAL(resultsReady()), d, SLOT(tls_resultsReady()));
|
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)
|
|
|
|
{
|
|
|
|
d = new Private(this);
|
|
|
|
d->c = static_cast<TLSContext *>(context());
|
|
|
|
d->c->setParent(d);
|
|
|
|
connect(d->c, SIGNAL(resultsReady()), d, SLOT(tls_resultsReady()));
|
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
TLS::~TLS()
|
|
|
|
{
|
2005-07-28 12:17:09 +00:00
|
|
|
d->c->setParent(0);
|
2004-11-05 08:54:01 +00:00
|
|
|
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-04-12 17:54:53 +00:00
|
|
|
// TODO
|
|
|
|
Q_UNUSED(version);
|
|
|
|
/*QStringList list;
|
2006-03-17 11:16:23 +00:00
|
|
|
const TLSContext *c = static_cast<const TLSContext *>(getContext(version == DTLS_v1 ? "dtls" : "tls", provider));
|
2005-04-24 19:09:06 +00:00
|
|
|
if(!c)
|
|
|
|
return list;
|
2006-03-17 11:16:23 +00:00
|
|
|
list = c->supportedCipherSuites(version);
|
2005-04-24 19:09:06 +00:00
|
|
|
delete c;
|
2007-04-12 17:54:53 +00:00
|
|
|
return list;*/
|
|
|
|
return QStringList();
|
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;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
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;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2004-11-17 00:28:34 +00:00
|
|
|
void TLS::setConstraints(SecurityLevel s)
|
|
|
|
{
|
2006-02-23 23:21:06 +00:00
|
|
|
int min = SL_Baseline;
|
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;
|
|
|
|
}
|
|
|
|
d->con_ssfMode = true;
|
|
|
|
d->con_minSSF = min;
|
|
|
|
d->con_maxSSF = -1;
|
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;
|
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;
|
2005-02-24 10:07:14 +00:00
|
|
|
}
|
|
|
|
|
2007-04-11 02:13:20 +00:00
|
|
|
QList<CertificateInfoOrdered> TLS::issuerList() const
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
return QList<CertificateInfoOrdered>();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TLS::setIssuerList(const QList<CertificateInfoOrdered> &issuers)
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
Q_UNUSED(issuers);
|
|
|
|
}
|
|
|
|
|
2007-04-12 17:54:53 +00:00
|
|
|
bool TLS::canCompress() const
|
2005-01-27 16:42:44 +00:00
|
|
|
{
|
2007-04-12 17:54:53 +00:00
|
|
|
// TODO
|
|
|
|
/*bool ok = false;
|
2005-07-31 01:27:27 +00:00
|
|
|
const TLSContext *c = static_cast<const TLSContext *>(getContext(mode == Stream ? "tls" : "dtls", provider));
|
2005-04-24 19:09:06 +00:00
|
|
|
if(!c)
|
|
|
|
return ok;
|
|
|
|
ok = c->canCompress();
|
|
|
|
delete c;
|
2007-04-12 17:54:53 +00:00
|
|
|
return ok;*/
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool TLS::canSetHostName() const
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
return false;
|
2005-01-27 16:42:44 +00:00
|
|
|
}
|
|
|
|
|
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;
|
2005-07-28 12:17:09 +00:00
|
|
|
//layerUpdateBegin();
|
|
|
|
if(!d->start(false))
|
|
|
|
{
|
|
|
|
d->reset(ResetSession);
|
|
|
|
d->error = true;
|
|
|
|
d->errorCode = ErrorInit;
|
|
|
|
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection);
|
|
|
|
}
|
|
|
|
//layerUpdateEnd();
|
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);
|
2005-07-28 12:17:09 +00:00
|
|
|
//layerUpdateBegin();
|
|
|
|
if(!d->start(true))
|
|
|
|
{
|
|
|
|
d->reset(ResetSession);
|
|
|
|
d->error = true;
|
|
|
|
d->errorCode = ErrorInit;
|
|
|
|
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection);
|
|
|
|
}
|
|
|
|
//layerUpdateEnd();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2007-04-11 02:13:20 +00:00
|
|
|
void TLS::continueAfterStep()
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->in.size();
|
2004-11-07 11:40:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int TLS::bytesOutgoingAvailable() const
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
return d->to_net.size();
|
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
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->out.append(a);
|
|
|
|
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
|
|
|
{
|
2005-06-24 23:41:25 +00:00
|
|
|
QByteArray a = d->in;
|
2005-04-24 19:09:06 +00:00
|
|
|
d->in.clear();
|
2004-11-05 08:54:01 +00:00
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TLS::writeIncoming(const QByteArray &a)
|
|
|
|
{
|
2005-04-24 19:09:06 +00:00
|
|
|
d->from_net.append(a);
|
|
|
|
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
|
|
|
{
|
2005-02-27 01:12:26 +00:00
|
|
|
QByteArray a = d->to_net;
|
2005-04-24 19:09:06 +00:00
|
|
|
d->to_net.clear();
|
|
|
|
if(plainBytes)
|
|
|
|
*plainBytes = d->bytesEncoded;
|
|
|
|
d->bytesEncoded = 0;
|
2004-11-05 08:54:01 +00:00
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2005-04-24 19:09:06 +00:00
|
|
|
QByteArray TLS::readUnprocessed()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2005-02-27 01:12:26 +00:00
|
|
|
QByteArray a = d->from_net;
|
2005-04-24 19:09:06 +00:00
|
|
|
d->from_net.clear();
|
2004-11-05 08:54:01 +00:00
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2005-07-30 09:16:05 +00:00
|
|
|
int TLS::packetsAvailable() const
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int TLS::packetsOutgoingAvailable() const
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TLS::setPacketMTU(int size) const
|
|
|
|
{
|
|
|
|
// TODO
|
|
|
|
Q_UNUSED(size);
|
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// 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
|
|
|
|
*/
|
|
|
|
|
2004-11-13 10:13:12 +00:00
|
|
|
QString *saslappname = 0;
|
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
|
|
|
|
private:
|
|
|
|
SASL *sasl;
|
2004-11-05 08:54:01 +00:00
|
|
|
public:
|
2006-11-14 05:58:28 +00:00
|
|
|
Private(SASL *parent)
|
|
|
|
{
|
|
|
|
sasl = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void handleServerFirstStep()
|
|
|
|
{
|
|
|
|
errorCode = ErrorHandshake;
|
|
|
|
|
|
|
|
if(c->result() == SASLContext::Success)
|
|
|
|
QMetaObject::invokeMethod(sasl, "authenticated", Qt::QueuedConnection);
|
|
|
|
else if(c->result() == SASLContext::Continue)
|
|
|
|
QMetaObject::invokeMethod(sasl, "nextStep", Qt::QueuedConnection, Q_ARG(QByteArray, c->stepData())); // TODO: double-check this!
|
|
|
|
else if(c->result() == SASLContext::AuthCheck ||
|
|
|
|
c->result() == SASLContext::NeedParams)
|
|
|
|
QMetaObject::invokeMethod(this, "tryAgain", Qt::QueuedConnection);
|
|
|
|
else
|
|
|
|
QMetaObject::invokeMethod(sasl, "error", Qt::QueuedConnection);
|
|
|
|
}
|
|
|
|
|
|
|
|
void update()
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
int _read = sasl->bytesAvailable();
|
|
|
|
int _readout = sasl->bytesOutgoingAvailable();
|
|
|
|
|
|
|
|
// bool force_read = false;
|
2007-01-02 05:01:25 +00:00
|
|
|
//
|
2006-11-14 05:58:28 +00:00
|
|
|
// if(!handshaken)
|
|
|
|
// {
|
|
|
|
// QByteArray a;
|
|
|
|
// TLSContext::Result r;
|
|
|
|
// c->update(from_net, QByteArray());
|
|
|
|
// last_op = OpHandshake;
|
|
|
|
// c->waitForResultsReady(-1);
|
|
|
|
// a = c->to_net();
|
|
|
|
// r = c->result();
|
|
|
|
// from_net.clear();
|
2007-01-02 05:01:25 +00:00
|
|
|
//
|
2006-11-14 05:58:28 +00:00
|
|
|
// if(r == TLSContext::Error)
|
|
|
|
// {
|
|
|
|
// reset(ResetSession);
|
|
|
|
// error = true;
|
|
|
|
// errorCode = ErrorHandshake;
|
|
|
|
// return;
|
|
|
|
// }
|
2007-01-02 05:01:25 +00:00
|
|
|
//
|
2006-11-14 05:58:28 +00:00
|
|
|
// to_net.append(a);
|
2007-01-02 05:01:25 +00:00
|
|
|
//
|
2006-11-14 05:58:28 +00:00
|
|
|
// 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();
|
|
|
|
// handshaken = true;
|
|
|
|
// force_read = true;
|
|
|
|
// }
|
|
|
|
// }
|
2007-01-02 05:01:25 +00:00
|
|
|
//
|
2006-11-14 05:58:28 +00:00
|
|
|
// if(handshaken)
|
|
|
|
// {
|
|
|
|
bool eof = false;
|
|
|
|
bool tryMore = false;
|
|
|
|
bool force_read = false;
|
2007-01-02 05:01:25 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
if(!out.isEmpty() || tryMore)
|
|
|
|
{
|
|
|
|
tryMore = false;
|
|
|
|
QByteArray a;
|
|
|
|
int enc;
|
|
|
|
bool more = false;
|
|
|
|
c->update(QByteArray(), out);
|
|
|
|
c->waitForResultsReady(-1);
|
|
|
|
bool ok = c->result() == SASLContext::Success;
|
|
|
|
a = c->to_net();
|
|
|
|
enc = c->encoded();
|
|
|
|
// eof = c->eof();
|
|
|
|
if(ok && enc < out.size())
|
|
|
|
more = true;
|
|
|
|
out.clear();
|
|
|
|
if(!eof)
|
|
|
|
{
|
|
|
|
if(!ok)
|
|
|
|
{
|
|
|
|
sasl->reset();
|
|
|
|
// error = true;
|
|
|
|
// errorCode = ErrorCrypt;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bytesEncoded += enc;
|
|
|
|
if(more)
|
|
|
|
tryMore = true;
|
|
|
|
to_net.append(a);
|
|
|
|
}
|
|
|
|
}
|
2007-01-02 05:01:25 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
if(!from_net.isEmpty() || force_read)
|
|
|
|
{
|
|
|
|
QByteArray a;
|
|
|
|
QByteArray b;
|
|
|
|
c->update(from_net, QByteArray());
|
|
|
|
c->waitForResultsReady(-1);
|
|
|
|
bool ok = c->result() == SASLContext::Success;
|
|
|
|
a = c->to_app();
|
|
|
|
b = c->to_net();
|
|
|
|
// eof = c->eof();
|
|
|
|
from_net.clear();
|
|
|
|
if(!ok)
|
|
|
|
{
|
|
|
|
sasl->reset();
|
|
|
|
// error = true;
|
|
|
|
// errorCode = ErrorCrypt;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
in.append(a);
|
|
|
|
to_net.append(b);
|
|
|
|
}
|
2007-01-02 05:01:25 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
// if(eof)
|
|
|
|
// {
|
|
|
|
// close();
|
|
|
|
// updateClosing();
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// }
|
2007-01-02 05:01:25 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
if(sasl->bytesAvailable() > _read)
|
|
|
|
{
|
|
|
|
//emit sasl->readyRead();
|
|
|
|
QMetaObject::invokeMethod(sasl, "readyRead", Qt::QueuedConnection);
|
|
|
|
}
|
|
|
|
if(sasl->bytesOutgoingAvailable() > _readout)
|
|
|
|
QMetaObject::invokeMethod(sasl, "readyReadOutgoing", Qt::QueuedConnection);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
QByteArray out;
|
|
|
|
QByteArray in;
|
|
|
|
QByteArray to_net;
|
|
|
|
QByteArray from_net;
|
|
|
|
int bytesEncoded;
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
// security opts
|
2006-11-14 05:58:28 +00:00
|
|
|
AuthFlags auth_flags;
|
2004-11-05 08:54:01 +00:00
|
|
|
int ssfmin, ssfmax;
|
|
|
|
QString ext_authid;
|
|
|
|
int ext_ssf;
|
|
|
|
|
|
|
|
bool tried;
|
|
|
|
SASLContext *c;
|
2006-11-14 05:58:28 +00:00
|
|
|
SASLContext::HostPort local, remote;
|
|
|
|
bool localSet, remoteSet;
|
|
|
|
QByteArray stepData; // mblsha: wtf is this for?
|
|
|
|
bool allowClientSendFirst;
|
|
|
|
bool disableServerSendLast;
|
2004-11-05 08:54:01 +00:00
|
|
|
bool first, server;
|
|
|
|
Error errorCode;
|
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
public slots:
|
|
|
|
void tryAgain();
|
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
|
|
|
d->c = (SASLContext *)context();
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
SASL::~SASL()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::reset()
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->localSet = false;
|
|
|
|
d->remoteSet = false;
|
|
|
|
|
|
|
|
d->ssfmin = 0;
|
|
|
|
d->ssfmax = 0;
|
2004-12-31 04:21:08 +00:00
|
|
|
d->ext_authid = QString();
|
2006-11-14 05:58:28 +00:00
|
|
|
d->ext_ssf = 0;
|
2004-11-05 08:54:01 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
d->out.clear();
|
|
|
|
d->in.clear();
|
|
|
|
d->to_net.clear();
|
|
|
|
d->from_net.clear();
|
|
|
|
d->bytesEncoded = 0;
|
2004-11-05 08:54:01 +00:00
|
|
|
|
|
|
|
d->c->reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::setExternalSSF(int x)
|
|
|
|
{
|
|
|
|
d->ext_ssf = x;
|
|
|
|
}
|
|
|
|
|
2005-02-28 09:01:59 +00:00
|
|
|
void SASL::setLocalAddr(const QString &addr, quint16 port)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->localSet = true;
|
|
|
|
d->local.addr = addr;
|
|
|
|
d->local.port = port;
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
2005-02-28 09:01:59 +00:00
|
|
|
void SASL::setRemoteAddr(const QString &addr, quint16 port)
|
2004-11-05 08:54:01 +00:00
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->remoteSet = true;
|
|
|
|
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
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->setup(service, host);
|
|
|
|
d->allowClientSendFirst = (mode == AllowClientSendFirst);
|
|
|
|
d->c->startClient(mechlist, d->allowClientSendFirst);
|
|
|
|
d->first = true;
|
2004-11-05 08:54:01 +00:00
|
|
|
d->server = false;
|
2006-11-14 05:58:28 +00:00
|
|
|
d->tried = false;
|
|
|
|
QTimer::singleShot(0, d, SLOT(tryAgain()));
|
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
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->setup(service, host);
|
2004-11-05 08:54:01 +00:00
|
|
|
|
|
|
|
QString appname;
|
|
|
|
if(saslappname)
|
|
|
|
appname = *saslappname;
|
|
|
|
else
|
|
|
|
appname = "qca";
|
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
// TODO: use appname!!
|
|
|
|
|
|
|
|
d->disableServerSendLast = (mode == DisableServerSendLast);
|
|
|
|
d->c->startServer(realm, d->disableServerSendLast);
|
|
|
|
d->first = true;
|
2004-11-05 08:54:01 +00:00
|
|
|
d->server = true;
|
2006-11-14 05:58:28 +00:00
|
|
|
d->tried = false;
|
|
|
|
if(d->c->result() == SASLContext::Success)
|
|
|
|
QMetaObject::invokeMethod(this, "serverStarted", Qt::QueuedConnection);
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::putServerFirstStep(const QString &mech)
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->c->serverFirstStep(mech, 0);
|
|
|
|
d->handleServerFirstStep();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::putServerFirstStep(const QString &mech, const QByteArray &clientInit)
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
d->c->serverFirstStep(mech, &clientInit);
|
|
|
|
d->handleServerFirstStep();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::putStep(const QByteArray &stepData)
|
|
|
|
{
|
2005-02-27 01:12:26 +00:00
|
|
|
d->stepData = stepData;
|
2006-11-14 05:58:28 +00:00
|
|
|
d->tryAgain();
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::setUsername(const QString &user)
|
|
|
|
{
|
|
|
|
d->c->setClientParams(&user, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::setAuthzid(const QString &authzid)
|
|
|
|
{
|
|
|
|
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
|
|
|
{
|
|
|
|
d->c->setClientParams(0, 0, &pass, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::setRealm(const QString &realm)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
2006-11-14 05:58:28 +00:00
|
|
|
return d->c->mechlist().split(" ");
|
2005-07-31 01:27:27 +00:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
d->bytesEncoded = 0;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SASL::Private::tryAgain()
|
|
|
|
{
|
|
|
|
Private *d = this;
|
|
|
|
SASL *q = sasl;
|
|
|
|
|
|
|
|
if(d->server) {
|
|
|
|
if(!d->tried) {
|
|
|
|
d->c->nextStep(d->stepData);
|
|
|
|
d->tried = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
d->c->tryAgain();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(d->c->result() == SASLContext::Error) {
|
|
|
|
d->errorCode = ErrorHandshake;
|
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(d->c->result() == SASLContext::Continue) {
|
|
|
|
d->tried = false;
|
|
|
|
emit q->nextStep(d->c->stepData());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(d->c->result() == SASLContext::AuthCheck) {
|
|
|
|
emit q->authCheck(d->c->username(), d->c->authzid());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(d->first) {
|
|
|
|
if(d->c->result() == SASLContext::Error) {
|
|
|
|
d->errorCode = ErrorInit;
|
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->c->tryAgain();
|
|
|
|
|
|
|
|
if(d->c->result() == SASLContext::Error) {
|
|
|
|
d->errorCode = ErrorHandshake;
|
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(d->c->result() == SASLContext::NeedParams) {
|
|
|
|
//d->tried = false;
|
|
|
|
Params np = d->c->clientParamsNeeded();
|
|
|
|
emit q->needParams(np);
|
|
|
|
return;
|
|
|
|
}
|
2007-01-02 05:01:25 +00:00
|
|
|
|
2006-11-14 05:58:28 +00:00
|
|
|
d->first = false;
|
|
|
|
d->tried = false;
|
|
|
|
emit q->clientStarted(d->c->haveClientInit(), d->c->stepData());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(!d->tried) {
|
|
|
|
d->c->nextStep(d->stepData);
|
|
|
|
d->tried = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
d->c->tryAgain();
|
|
|
|
|
|
|
|
if(d->c->result() == SASLContext::Error) {
|
|
|
|
d->errorCode = ErrorHandshake;
|
|
|
|
emit q->error();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if(d->c->result() == SASLContext::NeedParams) {
|
|
|
|
//d->tried = false;
|
|
|
|
Params np = d->c->clientParamsNeeded();
|
|
|
|
emit q->needParams(np);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// else if(d->c->result() == SASLContext::Continue) {
|
|
|
|
d->tried = false;
|
|
|
|
emit q->nextStep(d->c->stepData());
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(d->c->result() == SASLContext::Success)
|
|
|
|
emit q->authenticated();
|
|
|
|
else if(d->c->result() == SASLContext::Error) {
|
|
|
|
d->errorCode = ErrorHandshake;
|
|
|
|
emit q->error();
|
|
|
|
}
|
2004-11-13 10:13:12 +00:00
|
|
|
}
|
|
|
|
|
2004-11-05 08:54:01 +00:00
|
|
|
}
|
2005-07-28 12:17:09 +00:00
|
|
|
|
|
|
|
#include "qca_securelayer.moc"
|