support for tracking written TLS bytes

svn path=/trunk/kdesupport/qca/; revision=257147
This commit is contained in:
Justin Karneges 2003-10-08 02:26:11 +00:00
parent eaa4a1973c
commit 231ec39c5b
8 changed files with 116 additions and 19 deletions

1
TODO
View File

@ -1,5 +1,6 @@
* plugins: thread safety ?
* make qca into a real installable library
* tls: support shutting down the session
* dsa
* diffie-hellman

View File

@ -40,7 +40,7 @@ public:
connect(sasl, SIGNAL(needParams(bool, bool, bool, bool)), SLOT(sasl_needParams(bool, bool, bool, bool)));
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
connect(sasl, SIGNAL(readyReadOutgoing()), SLOT(sasl_readyReadOutgoing()));
connect(sasl, SIGNAL(readyReadOutgoing(int)), SLOT(sasl_readyReadOutgoing(int)));
connect(sasl, SIGNAL(error(int)), SLOT(sasl_error(int)));
}
@ -172,7 +172,7 @@ private slots:
processInbuf();
}
void sasl_readyReadOutgoing()
void sasl_readyReadOutgoing(int)
{
QByteArray a = sasl->readOutgoing();
sock->writeBlock(a.data(), a.size());
@ -341,7 +341,7 @@ public:
connect(sasl, SIGNAL(nextStep(const QByteArray &)), SLOT(sasl_nextStep(const QByteArray &)));
connect(sasl, SIGNAL(authenticated()), SLOT(sasl_authenticated()));
connect(sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
connect(sasl, SIGNAL(readyReadOutgoing()), SLOT(sasl_readyReadOutgoing()));
connect(sasl, SIGNAL(readyReadOutgoing(int)), SLOT(sasl_readyReadOutgoing(int)));
connect(sasl, SIGNAL(error(int)), SLOT(sasl_error(int)));
sock->setSocket(s);
@ -446,7 +446,7 @@ private slots:
processInbuf();
}
void sasl_readyReadOutgoing()
void sasl_readyReadOutgoing(int)
{
QByteArray a = sasl->readOutgoing();
toWrite = a.size();

View File

@ -60,7 +60,7 @@ public:
ssl = new QCA::TLS;
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
connect(ssl, SIGNAL(readyReadOutgoing()), SLOT(ssl_readyReadOutgoing()));
connect(ssl, SIGNAL(readyReadOutgoing(int)), SLOT(ssl_readyReadOutgoing(int)));
connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
cert.fromPEM(pemdata_cert);
@ -163,7 +163,7 @@ private slots:
ssl->write(b);
}
void ssl_readyReadOutgoing()
void ssl_readyReadOutgoing(int)
{
QByteArray a = ssl->readOutgoing();

View File

@ -130,7 +130,7 @@ public:
ssl = new QCA::TLS;
connect(ssl, SIGNAL(handshaken()), SLOT(ssl_handshaken()));
connect(ssl, SIGNAL(readyRead()), SLOT(ssl_readyRead()));
connect(ssl, SIGNAL(readyReadOutgoing()), SLOT(ssl_readyReadOutgoing()));
connect(ssl, SIGNAL(readyReadOutgoing(int)), SLOT(ssl_readyReadOutgoing(int)));
connect(ssl, SIGNAL(error(int)), SLOT(ssl_error(int)));
rootCerts.setAutoDelete(true);
@ -222,7 +222,7 @@ private slots:
printf("%s", cs.data());
}
void ssl_readyReadOutgoing()
void ssl_readyReadOutgoing(int)
{
QByteArray a = ssl->readOutgoing();
sock->writeBlock(a.data(), a.size());

View File

@ -964,6 +964,7 @@ public:
BIO *rbio, *wbio;
CertContext cc;
int vr;
bool v_eof;
TLSContext()
{
@ -1009,6 +1010,12 @@ public:
mode = Idle;
cc.reset();
vr = QCA::TLS::Unknown;
v_eof = false;
}
bool eof() const
{
return v_eof;
}
bool startClient(const QPtrList<QCA_CertContext> &store, const QCA_CertContext &cert, const QCA_RSAKeyContext &key)
@ -1154,20 +1161,49 @@ public:
vr = code;
}
bool encode(const QByteArray &plain, QByteArray *to_net)
bool encode(const QByteArray &plain, QByteArray *to_net, int *enc)
{
if(mode != Active)
return false;
appendArray(&sendQueue, plain);
int encoded = 0;
if(sendQueue.size() > 0) {
int ret = SSL_write(ssl, sendQueue.data(), sendQueue.size());
sendQueue.resize(0);
if(ret <= 0)
enum { Good, Continue, Done, Error };
int m;
if(ret <= 0) {
int x = SSL_get_error(ssl, ret);
if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
m = Continue;
else if(x == SSL_ERROR_ZERO_RETURN)
m = Done;
else
m = Error;
}
else {
m = Good;
encoded = ret;
int newsize = sendQueue.size() - encoded;
char *r = sendQueue.data();
memmove(r, r + encoded, newsize);
sendQueue.resize(newsize);
}
if(m == Done) {
sendQueue.resize(0);
v_eof = true;
return false;
}
if(m == Error) {
sendQueue.resize(0);
return false;
}
}
*to_net = readOutgoing();
*enc = encoded;
return true;
}
@ -1186,6 +1222,10 @@ public:
int x = SSL_get_error(ssl, ret);
if(x == SSL_ERROR_WANT_READ || x == SSL_ERROR_WANT_WRITE)
break;
else if(x == SSL_ERROR_ZERO_RETURN) {
v_eof = true;
return false;
}
else
return false;
}
@ -1202,6 +1242,24 @@ public:
return true;
}
QByteArray unprocessed()
{
QByteArray a;
int size = BIO_pending(rbio);
if(size <= 0)
return a;
a.resize(size);
int r = BIO_read(rbio, a.data(), size);
if(r <= 0) {
a.resize(0);
return a;
}
if(r != size)
a.resize(r);
return a;
}
QByteArray readOutgoing()
{
QByteArray a;

View File

@ -865,6 +865,9 @@ public:
to_net.resize(0);
host = "";
hostMismatch = false;
cert = Cert();
bytesEncoded = 0;
tryMore = false;
}
void appendArray(QByteArray *a, const QByteArray &b)
@ -877,6 +880,8 @@ public:
Cert cert;
QCA_TLSContext *c;
QByteArray in, out, to_net, from_net;
int bytesEncoded;
bool tryMore;
bool handshaken;
QString host;
bool hostMismatch;
@ -912,6 +917,11 @@ void TLS::setCertificateStore(const QPtrList<Cert> &store)
d->store.append(cert->d->c);
}
void TLS::reset()
{
d->reset();
}
bool TLS::startClient(const QString &host)
{
d->reset();
@ -933,6 +943,11 @@ bool TLS::startServer()
return true;
}
bool TLS::isHandshaken() const
{
return d->handshaken;
}
void TLS::write(const QByteArray &a)
{
d->appendArray(&d->out, a);
@ -981,6 +996,7 @@ void TLS::update()
int r = d->c->handshake(d->from_net, &a);
d->from_net.resize(0);
if(r == QCA_TLSContext::Error) {
reset();
error(ErrHandshake);
return;
}
@ -1001,21 +1017,37 @@ void TLS::update()
}
if(d->handshaken) {
if(!d->out.isEmpty()) {
if(!d->out.isEmpty() || d->tryMore) {
d->tryMore = false;
QByteArray a;
bool ok = d->c->encode(d->out, &a);
int enc;
bool more = false;
bool ok = d->c->encode(d->out, &a, &enc);
bool eof = d->c->eof();
if(ok && enc < (int)d->out.size())
more = true;
d->out.resize(0);
if(eof)
return;
if(!ok) {
reset();
error(ErrCrypt);
return;
}
d->bytesEncoded += enc;
if(more)
d->tryMore = true;
d->appendArray(&d->to_net, a);
}
if(!d->from_net.isEmpty() || force_read) {
QByteArray a, b;
bool ok = d->c->decode(d->from_net, &a, &b);
bool eof = d->c->eof();
d->from_net.resize(0);
if(eof)
return;
if(!ok) {
reset();
error(ErrCrypt);
return;
}
@ -1027,8 +1059,11 @@ void TLS::update()
readyRead();
}
if(!d->to_net.isEmpty())
readyReadOutgoing();
if(!d->to_net.isEmpty()) {
int bytes = d->bytesEncoded;
d->bytesEncoded = 0;
readyReadOutgoing(bytes);
}
}
@ -1387,7 +1422,7 @@ void SASL::write(const QByteArray &a)
int oldsize = d->outbuf.size();
d->outbuf.resize(oldsize + b.size());
memcpy(d->outbuf.data() + oldsize, b.data(), b.size());
readyReadOutgoing();
readyReadOutgoing(a.size());
}
QByteArray SASL::read()

View File

@ -314,8 +314,10 @@ namespace QCA
void setCertificate(const Cert &cert, const RSAKey &key);
void setCertificateStore(const QPtrList<Cert> &store); // note: store must persist
void reset();
bool startClient(const QString &host="");
bool startServer();
bool isHandshaken() const;
// plain (application side)
void write(const QByteArray &a);
@ -332,7 +334,7 @@ namespace QCA
signals:
void handshaken();
void readyRead();
void readyReadOutgoing();
void readyReadOutgoing(int plainBytes);
void error(int);
private slots:
@ -404,7 +406,7 @@ namespace QCA
// for security layer
void readyRead();
void readyReadOutgoing();
void readyReadOutgoing(int plainBytes);
// error
void error(int);

View File

@ -134,8 +134,9 @@ public:
virtual bool startServer(const QPtrList<QCA_CertContext> &store, const QCA_CertContext &cert, const QCA_RSAKeyContext &key)=0;
virtual int handshake(const QByteArray &in, QByteArray *out)=0;
virtual bool encode(const QByteArray &plain, QByteArray *to_net)=0;
virtual bool encode(const QByteArray &plain, QByteArray *to_net, int *encoded)=0;
virtual bool decode(const QByteArray &from_net, QByteArray *plain, QByteArray *to_net)=0;
virtual bool eof() const=0;
virtual QCA_CertContext *peerCertificate() const=0;
virtual int validityResult() const=0;