File indexing completed on 2024-06-02 04:07:03

0001 /*
0002  * securestream.cpp - combines a ByteStream with TLS and SASL
0003  * Copyright (C) 2004  Justin Karneges
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation; either
0008  * either version 2
0009    of the License, or (at your option) any later version.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library; if not, write to the Free Software
0018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0019  *
0020  */
0021 
0022 /*
0023   Note: SecureStream depends on the underlying security layers to signal
0024     plain-to-encrypted results immediately (as opposed to waiting for the
0025     event loop) so that the user cannot add/remove security layers during
0026     this conversion moment.  QCA::TLS and QCA::SASL behave as expected,
0027     but future layers might not.
0028 */
0029 
0030 #include "securestream.h"
0031 
0032 #include <QPointer>
0033 #include <QList>
0034 #include <QTimer>
0035 
0036 #ifdef USE_TLSHANDLER
0037 #include "xmpp.h"
0038 #endif
0039 #include "compressionhandler.h"
0040 
0041 //----------------------------------------------------------------------------
0042 // LayerTracker
0043 //----------------------------------------------------------------------------
0044 class LayerTracker
0045 {
0046 public:
0047     struct Item
0048     {
0049         int plain;
0050         int encoded;
0051     };
0052 
0053     LayerTracker();
0054 
0055     void reset();
0056     void addPlain(int plain);
0057     void specifyEncoded(int encoded, int plain);
0058     int finished(int encoded);
0059 
0060     int p;
0061     QList<Item> list;
0062 };
0063 
0064 LayerTracker::LayerTracker()
0065 {
0066     p = 0;
0067 }
0068 
0069 void LayerTracker::reset()
0070 {
0071     p = 0;
0072     list.clear();
0073 }
0074 
0075 void LayerTracker::addPlain(int plain)
0076 {
0077     p += plain;
0078 }
0079 
0080 void LayerTracker::specifyEncoded(int encoded, int plain)
0081 {
0082     // can't specify more bytes than we have
0083     if(plain > p)
0084         plain = p;
0085     p -= plain;
0086     Item i;
0087     i.plain = plain;
0088     i.encoded = encoded;
0089     list += i;
0090 }
0091 
0092 int LayerTracker::finished(int encoded)
0093 {
0094     int plain = 0;
0095     for(QList<Item>::Iterator it = list.begin(); it != list.end();) {
0096         Item &i = *it;
0097 
0098         // not enough?
0099         if(encoded < i.encoded) {
0100             i.encoded -= encoded;
0101             break;
0102         }
0103 
0104         encoded -= i.encoded;
0105         plain += i.plain;
0106         it = list.erase(it);
0107     }
0108     return plain;
0109 }
0110 
0111 //----------------------------------------------------------------------------
0112 // SecureStream
0113 //----------------------------------------------------------------------------
0114 class SecureLayer : public QObject
0115 {
0116     Q_OBJECT
0117 public:
0118     enum { TLS, SASL, TLSH, Compression };
0119     int type;
0120     union {
0121         QCA::TLS *tls;
0122         QCA::SASL *sasl;
0123 #ifdef USE_TLSHANDLER
0124         XMPP::TLSHandler *tlsHandler;
0125 #endif
0126         CompressionHandler *compressionHandler;
0127     } p;
0128     LayerTracker layer;
0129     bool tls_done;
0130     int prebytes;
0131 
0132     SecureLayer(QCA::TLS *t)
0133     {
0134         type = TLS;
0135         p.tls = t;
0136         init();
0137         connect(p.tls, &QCA::TLS::handshaken, this, &SecureLayer::tls_handshaken);
0138         connect(p.tls, &QCA::SecureLayer::readyRead, this, &SecureLayer::tls_readyRead);
0139         connect(p.tls, SIGNAL(readyReadOutgoing(int)), SLOT(tls_readyReadOutgoing(int)));
0140         connect(p.tls, &QCA::SecureLayer::closed, this, &SecureLayer::tls_closed);
0141         connect(p.tls, SIGNAL(error(int)), SLOT(tls_error(int)));
0142     }
0143 
0144     SecureLayer(QCA::SASL *s)
0145     {
0146         type = SASL;
0147         p.sasl = s;
0148         init();
0149         connect(p.sasl, &QCA::SecureLayer::readyRead, this, &SecureLayer::sasl_readyRead);
0150         connect(p.sasl, &QCA::SecureLayer::readyReadOutgoing, this, &SecureLayer::sasl_readyReadOutgoing);
0151         connect(p.sasl, &QCA::SecureLayer::error, this, &SecureLayer::sasl_error);
0152     }
0153     
0154     SecureLayer(CompressionHandler *t)
0155     {
0156         t->setParent(this); // automatically clean up CompressionHandler when SecureLayer is destroyed
0157         type = Compression;
0158         p.compressionHandler = t;
0159         init();
0160         connect(p.compressionHandler, &CompressionHandler::readyRead, this, &SecureLayer::compressionHandler_readyRead);
0161         connect(p.compressionHandler, &CompressionHandler::readyReadOutgoing, this, &SecureLayer::compressionHandler_readyReadOutgoing);
0162         connect(p.compressionHandler, &CompressionHandler::error, this, &SecureLayer::compressionHandler_error);
0163     }
0164 
0165 #ifdef USE_TLSHANDLER
0166     SecureLayer(XMPP::TLSHandler *t)
0167     {
0168         type = TLSH;
0169         p.tlsHandler = t;
0170         init();
0171         connect(p.tlsHandler, &XMPP::TLSHandler::success, this, &SecureLayer::tlsHandler_success);
0172         connect(p.tlsHandler, &XMPP::TLSHandler::fail, this, &SecureLayer::tlsHandler_fail);
0173         connect(p.tlsHandler, &XMPP::TLSHandler::closed, this, &SecureLayer::tlsHandler_closed);
0174         connect(p.tlsHandler, &XMPP::TLSHandler::readyRead, this, &SecureLayer::tlsHandler_readyRead);
0175         connect(p.tlsHandler, &XMPP::TLSHandler::readyReadOutgoing, this, &SecureLayer::tlsHandler_readyReadOutgoing);
0176     }
0177 #endif
0178 
0179     void init()
0180     {
0181         tls_done = false;
0182         prebytes = 0;
0183     }
0184 
0185     void write(const QByteArray &a)
0186     {
0187         layer.addPlain(a.size());
0188         switch(type) {
0189             case TLS:  { p.tls->write(a); break; }
0190             case SASL: { p.sasl->write(a); break; }
0191 #ifdef USE_TLSHANDLER
0192             case TLSH: { p.tlsHandler->write(a); break; }
0193 #endif
0194             case Compression: { p.compressionHandler->write(a); break; }
0195         }
0196     }
0197 
0198     void writeIncoming(const QByteArray &a)
0199     {
0200         switch(type) {
0201             case TLS:  { p.tls->writeIncoming(a); break; }
0202             case SASL: { p.sasl->writeIncoming(a); break; }
0203 #ifdef USE_TLSHANDLER
0204             case TLSH: { p.tlsHandler->writeIncoming(a); break; }
0205 #endif
0206             case Compression: { p.compressionHandler->writeIncoming(a); break; }
0207         }
0208     }
0209 
0210     int finished(int plain)
0211     {
0212         int written = 0;
0213 
0214         // deal with prebytes (bytes sent prior to this security layer)
0215         if(prebytes > 0) {
0216             if(prebytes >= plain) {
0217                 written += plain;
0218                 prebytes -= plain;
0219                 plain = 0;
0220             }
0221             else {
0222                 written += prebytes;
0223                 plain -= prebytes;
0224                 prebytes = 0;
0225             }
0226         }
0227 
0228         // put remainder into the layer tracker
0229         if(type == SASL || tls_done)
0230             written += layer.finished(plain);
0231 
0232         return written;
0233     }
0234 
0235 signals:
0236     void tlsHandshaken();
0237     void tlsClosed(const QByteArray &);
0238     void readyRead(const QByteArray &);
0239     void needWrite(const QByteArray &);
0240     void error(int);
0241 
0242 private slots:
0243     void tls_handshaken()
0244     {
0245         tls_done = true;
0246         tlsHandshaken();
0247     }
0248 
0249     void tls_readyRead()
0250     {
0251         QByteArray a = p.tls->read();
0252         readyRead(a);
0253     }
0254 
0255     void tls_readyReadOutgoing(int plainBytes)
0256     {
0257         QByteArray a = p.tls->readOutgoing();
0258         if(tls_done)
0259             layer.specifyEncoded(a.size(), plainBytes);
0260         needWrite(a);
0261     }
0262 
0263     void tls_closed()
0264     {
0265         QByteArray a = p.tls->readUnprocessed();
0266         tlsClosed(a);
0267     }
0268 
0269     void tls_error(int x)
0270     {
0271         error(x);
0272     }
0273 
0274     void sasl_readyRead()
0275     {
0276         QByteArray a = p.sasl->read();
0277         readyRead(a);
0278     }
0279 
0280     void sasl_readyReadOutgoing()
0281     {
0282         int plainBytes;
0283         QByteArray a = p.sasl->readOutgoing(&plainBytes);
0284         layer.specifyEncoded(a.size(), plainBytes);
0285         needWrite(a);
0286     }
0287 
0288     void sasl_error()
0289     {
0290         error(p.sasl->errorCode());
0291     }
0292     
0293     void compressionHandler_readyRead()
0294     {
0295         QByteArray a = p.compressionHandler->read();
0296         readyRead(a);
0297     }
0298 
0299     void compressionHandler_readyReadOutgoing()
0300     {
0301         int plainBytes;
0302         QByteArray a = p.compressionHandler->readOutgoing(&plainBytes);
0303         layer.specifyEncoded(a.size(), plainBytes);
0304         needWrite(a);
0305     }
0306 
0307     void compressionHandler_error()
0308     {
0309         error(p.compressionHandler->errorCode());
0310     }
0311 
0312 #ifdef USE_TLSHANDLER
0313     void tlsHandler_success()
0314     {
0315         tls_done = true;
0316         tlsHandshaken();
0317     }
0318 
0319     void tlsHandler_fail()
0320     {
0321         error(0);
0322     }
0323 
0324     void tlsHandler_closed()
0325     {
0326         tlsClosed(QByteArray());
0327     }
0328 
0329     void tlsHandler_readyRead(const QByteArray &a)
0330     {
0331         readyRead(a);
0332     }
0333 
0334     void tlsHandler_readyReadOutgoing(const QByteArray &a, int plainBytes)
0335     {
0336         if(tls_done)
0337             layer.specifyEncoded(a.size(), plainBytes);
0338         needWrite(a);
0339     }
0340 #endif
0341 };
0342 
0343 #include "securestream.moc"
0344 
0345 class SecureStream::Private
0346 {
0347 public:
0348     ByteStream *bs;
0349     QList<SecureLayer*> layers;
0350     int pending;
0351     int errorCode;
0352     bool active;
0353     bool topInProgress;
0354 
0355     bool haveTLS() const
0356     {
0357         foreach(SecureLayer *s, layers) {
0358             if(s->type == SecureLayer::TLS
0359 #ifdef USE_TLSHANDLER
0360             || s->type == SecureLayer::TLSH
0361 #endif
0362             ) {
0363                 return true;
0364             }
0365         }
0366         return false;
0367     }
0368 
0369     bool haveSASL() const
0370     {
0371         foreach(SecureLayer *s, layers) {
0372             if(s->type == SecureLayer::SASL)
0373                 return true;
0374         }
0375         return false;
0376     }
0377     
0378     bool haveCompress() const
0379     {
0380         foreach(SecureLayer *s, layers) {
0381             if(s->type == SecureLayer::Compression)
0382                 return true;
0383         }
0384         return false;
0385     }
0386 };
0387 
0388 SecureStream::SecureStream(ByteStream *s)
0389 :ByteStream(0)
0390 {
0391     d = new Private;
0392 
0393     d->bs = s;
0394     connect(d->bs, &ByteStream::readyRead, this, &SecureStream::bs_readyRead);
0395     connect(d->bs, &ByteStream::bytesWritten, this, &SecureStream::bs_bytesWritten);
0396 
0397     d->pending = 0;
0398     d->active = true;
0399     d->topInProgress = false;
0400 }
0401 
0402 SecureStream::~SecureStream()
0403 {
0404     delete d;
0405 }
0406 
0407 void SecureStream::linkLayer(QObject *s)
0408 {
0409     connect(s, SIGNAL(tlsHandshaken()), SLOT(layer_tlsHandshaken()));
0410     connect(s, SIGNAL(tlsClosed(QByteArray)), SLOT(layer_tlsClosed(QByteArray)));
0411     connect(s, SIGNAL(readyRead(QByteArray)), SLOT(layer_readyRead(QByteArray)));
0412     connect(s, SIGNAL(needWrite(QByteArray)), SLOT(layer_needWrite(QByteArray)));
0413     connect(s, SIGNAL(error(int)), SLOT(layer_error(int)));
0414 }
0415 
0416 int SecureStream::calcPrebytes() const
0417 {
0418     int x = 0;
0419     foreach(SecureLayer *s, d->layers) {
0420         x += s->prebytes;
0421     }
0422     return (d->pending - x);
0423 }
0424 
0425 void SecureStream::startTLSClient(QCA::TLS *t, const QByteArray &spare)
0426 {
0427     if(!d->active || d->topInProgress || d->haveTLS())
0428         return;
0429 
0430     SecureLayer *s = new SecureLayer(t);
0431     s->prebytes = calcPrebytes();
0432     linkLayer(s);
0433     d->layers.append(s);
0434     d->topInProgress = true;
0435 
0436     insertData(spare);
0437 }
0438 
0439 void SecureStream::startTLSServer(QCA::TLS *t, const QByteArray &spare)
0440 {
0441     if(!d->active || d->topInProgress || d->haveTLS())
0442         return;
0443 
0444     SecureLayer *s = new SecureLayer(t);
0445     s->prebytes = calcPrebytes();
0446     linkLayer(s);
0447     d->layers.append(s);
0448     d->topInProgress = true;
0449 
0450     insertData(spare);
0451 }
0452 
0453 void SecureStream::setLayerCompress(const QByteArray& spare)
0454 {
0455     if(!d->active || d->topInProgress || d->haveCompress())
0456         return;
0457 
0458     SecureLayer *s = new SecureLayer(new CompressionHandler());
0459     s->prebytes = calcPrebytes();
0460     linkLayer(s);
0461     d->layers.append(s);
0462 
0463     insertData(spare);
0464 }
0465 
0466 void SecureStream::setLayerSASL(QCA::SASL *sasl, const QByteArray &spare)
0467 {
0468     if(!d->active || d->topInProgress || d->haveSASL())
0469         return;
0470 
0471     SecureLayer *s = new SecureLayer(sasl);
0472     s->prebytes = calcPrebytes();
0473     linkLayer(s);
0474     d->layers.append(s);
0475 
0476     insertData(spare);
0477 }
0478 
0479 #ifdef USE_TLSHANDLER
0480 void SecureStream::startTLSClient(XMPP::TLSHandler *t, const QString &server, const QByteArray &spare)
0481 {
0482     if(!d->active || d->topInProgress || d->haveTLS())
0483         return;
0484 
0485     SecureLayer *s = new SecureLayer(t);
0486     s->prebytes = calcPrebytes();
0487     linkLayer(s);
0488     d->layers.append(s);
0489     d->topInProgress = true;
0490 
0491     // unlike QCA::TLS, XMPP::TLSHandler has no return value
0492     s->p.tlsHandler->startClient(server);
0493 
0494     insertData(spare);
0495 }
0496 #endif
0497 
0498 void SecureStream::closeTLS()
0499 {
0500     if (!d->layers.isEmpty()) {
0501         SecureLayer *s = d->layers.last();
0502         if(s->type == SecureLayer::TLS) {
0503             s->p.tls->close();
0504         }
0505     }
0506 }
0507 
0508 int SecureStream::errorCode() const
0509 {
0510     return d->errorCode;
0511 }
0512 
0513 bool SecureStream::isOpen() const
0514 {
0515     return d->active;
0516 }
0517 
0518 void SecureStream::write(const QByteArray &a)
0519 {
0520     if(!isOpen())
0521         return;
0522 
0523     d->pending += a.size();
0524 
0525     // send to the last layer
0526     if (!d->layers.isEmpty()) {
0527         SecureLayer *s = d->layers.last();
0528         s->write(a);
0529     }
0530     else {
0531         writeRawData(a);
0532     }
0533 }
0534 
0535 int SecureStream::bytesToWrite() const
0536 {
0537     return d->pending;
0538 }
0539 
0540 void SecureStream::bs_readyRead()
0541 {
0542     QByteArray a = d->bs->read();
0543 
0544     // send to the first layer
0545     if (!d->layers.isEmpty()) {
0546         SecureLayer *s = d->layers.first();
0547         s->writeIncoming(a);
0548     }
0549     else {
0550         incomingData(a);
0551     }
0552 }
0553 
0554 void SecureStream::bs_bytesWritten(int bytes)
0555 {
0556     foreach(SecureLayer *s, d->layers) {
0557         bytes = s->finished(bytes);
0558     }
0559 
0560     if(bytes > 0) {
0561         d->pending -= bytes;
0562         bytesWritten(bytes);
0563     }
0564 }
0565 
0566 void SecureStream::layer_tlsHandshaken()
0567 {
0568     d->topInProgress = false;
0569     tlsHandshaken();
0570 }
0571 
0572 void SecureStream::layer_tlsClosed(const QByteArray &)
0573 {
0574     d->active = false;
0575     while (!d->layers.isEmpty()) {
0576         delete d->layers.takeFirst();
0577     }
0578     tlsClosed();
0579 }
0580 
0581 void SecureStream::layer_readyRead(const QByteArray &a)
0582 {
0583     SecureLayer *s = (SecureLayer *)sender();
0584     QList<SecureLayer*>::Iterator it(d->layers.begin());
0585     while((*it) != s) {
0586         Q_ASSERT(it != d->layers.end());
0587         ++it;
0588     }
0589     Q_ASSERT(it != d->layers.end());
0590 
0591     // pass upwards
0592     ++it;
0593     if (it != d->layers.end()) {
0594         s = (*it);
0595         s->writeIncoming(a);
0596     }
0597     else {
0598         incomingData(a);
0599     }
0600 }
0601 
0602 void SecureStream::layer_needWrite(const QByteArray &a)
0603 {
0604     SecureLayer *s = (SecureLayer *)sender();
0605     QList<SecureLayer*>::Iterator it(d->layers.begin());
0606     while((*it) != s) {
0607         Q_ASSERT(it != d->layers.end());
0608         ++it;
0609     }
0610     Q_ASSERT(it != d->layers.end());
0611 
0612     // pass downwards
0613     if (it != d->layers.begin()) {
0614         --it;
0615         s = (*it);
0616         s->write(a);
0617     }
0618     else {
0619         writeRawData(a);
0620     }
0621 }
0622 
0623 void SecureStream::layer_error(int x)
0624 {
0625     SecureLayer *s = (SecureLayer *)sender();
0626     int type = s->type;
0627     d->errorCode = x;
0628     d->active = false;
0629     while (!d->layers.isEmpty()) {
0630         delete d->layers.takeFirst();
0631     }
0632     if(type == SecureLayer::TLS)
0633         error(ErrTLS);
0634     else if(type == SecureLayer::SASL)
0635         error(ErrSASL);
0636 #ifdef USE_TLSHANDLER
0637     else if(type == SecureLayer::TLSH)
0638         error(ErrTLS);
0639 #endif
0640 }
0641 
0642 void SecureStream::insertData(const QByteArray &a)
0643 {
0644     if(!a.isEmpty()) {
0645         if (!d->layers.isEmpty()) {
0646             SecureLayer *s = d->layers.last();
0647             s->writeIncoming(a);
0648         }
0649         else {
0650             incomingData(a);
0651         }
0652     }
0653 }
0654 
0655 void SecureStream::writeRawData(const QByteArray &a)
0656 {
0657     d->bs->write(a);
0658 }
0659 
0660 void SecureStream::incomingData(const QByteArray &a)
0661 {
0662     appendRead(a);
0663     if(bytesAvailable())
0664         readyRead();
0665 }