2 securestream.cpp - Kopete Groupwise Protocol
3 Combines a ByteStream with TLS and SASL
5 Copyright (c) 2006,2007 Novell, Inc http://www.opensuse.org
6 Copyright (c) 2004 SUSE Linux AG http://www.suse.com
8 Based on Iris, Copyright (C) 2003 Justin Karneges <justin@affinix.com>
10 Kopete (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
12 *************************************************************************
14 * This library is free software; you can redistribute it and/or *
15 * modify it under the terms of the GNU Lesser General Public *
16 * License as published by the Free Software Foundation; either *
17 * version 2 of the License, or (at your option) any later version. *
19 *************************************************************************
23 Note: SecureStream depends on the underlying security layers to signal
24 plain-to-encrypted results immediately (as opposed to waiting for the
25 event loop) so that the user cannot add/remove security layers during
26 this conversion moment. QCA::TLS and QCA::SASL behave as expected,
27 but future layers might not.
34 #include "securestream.h"
36 #include "compressionhandler.h"
37 //----------------------------------------------------------------------------
39 //----------------------------------------------------------------------------
40 LayerTracker::LayerTracker()
45 void LayerTracker::reset()
51 void LayerTracker::addPlain(int plain
)
56 void LayerTracker::specifyEncoded(int encoded
, int plain
)
58 // can't specify more bytes than we have
68 int LayerTracker::finished(int encoded
)
71 for(QList
<Item
>::Iterator it
= list
.begin(); it
!= list
.end();) {
75 if(encoded
< i
.encoded
) {
87 //----------------------------------------------------------------------------
89 //----------------------------------------------------------------------------
91 SecureLayer::SecureLayer(QCA::TLS
*t
)
96 connect(p
.tls
, SIGNAL(handshaken()), SLOT(tls_handshaken()));
97 connect(p
.tls
, SIGNAL(readyRead()), SLOT(tls_readyRead()));
98 connect(p
.tls
, SIGNAL(readyReadOutgoing(int)), SLOT(tls_readyReadOutgoing(int)));
99 connect(p
.tls
, SIGNAL(closed()), SLOT(tls_closed()));
100 connect(p
.tls
, SIGNAL(error(int)), SLOT(tls_error(int)));
103 SecureLayer::SecureLayer(QCA::SASL
*s
)
108 connect(p
.sasl
, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
109 connect(p
.sasl
, SIGNAL(readyReadOutgoing(int)), SLOT(sasl_readyReadOutgoing(int)));
110 connect(p
.sasl
, SIGNAL(error(int)), SLOT(sasl_error(int)));
113 #ifdef USE_TLSHANDLER
114 SecureLayer::SecureLayer(TLSHandler
*t
)
119 connect(p
.tlsHandler
, SIGNAL(success()), SLOT(tlsHandler_success()));
120 connect(p
.tlsHandler
, SIGNAL(fail()), SLOT(tlsHandler_fail()));
121 connect(p
.tlsHandler
, SIGNAL(closed()), SLOT(tlsHandler_closed()));
122 connect(p
.tlsHandler
, SIGNAL(readyRead(const QByteArray
&)), SLOT(tlsHandler_readyRead(const QByteArray
&)));
123 connect(p
.tlsHandler
, SIGNAL(readyReadOutgoing(const QByteArray
&, int)), SLOT(tlsHandler_readyReadOutgoing(const QByteArray
&, int)));
127 SecureLayer::SecureLayer(CompressionHandler
*t
)
130 p
.compressionHandler
= t
;
132 connect(p
.compressionHandler
, SIGNAL(readyRead()), SLOT(compressionHandler_readyRead()));
133 connect(p
.compressionHandler
, SIGNAL(readyReadOutgoing(int)), SLOT(compressionHandler_readyReadOutgoing(int)));
134 connect(p
.compressionHandler
, SIGNAL(error(int)), SLOT(compressionHandler_error(int)));
137 void SecureLayer::init()
143 void SecureLayer::write(const QByteArray
&a
)
145 layer
.addPlain(a
.size());
147 case TLS
: { p
.tls
->write(a
); break; }
148 case SASL
: { p
.sasl
->write(a
); break; }
149 #ifdef USE_TLSHANDLER
150 case TLSH
: { p
.tlsHandler
->write(a
); break; }
152 case Compression
: { p
.compressionHandler
->write(a
); break; }
156 void SecureLayer::writeIncoming(const QByteArray
&a
)
159 case TLS
: { p
.tls
->writeIncoming(a
); break; }
160 case SASL
: { p
.sasl
->writeIncoming(a
); break; }
161 #ifdef USE_TLSHANDLER
162 case TLSH
: { p
.tlsHandler
->writeIncoming(a
); break; }
164 case Compression
: { p
.compressionHandler
->writeIncoming(a
); break; }
168 int SecureLayer::finished(int plain
)
172 // deal with prebytes (bytes sent prior to this security layer)
174 if(prebytes
>= plain
) {
186 // put remainder into the layer tracker
187 if(type
== SASL
|| tls_done
)
188 written
+= layer
.finished(plain
);
193 void SecureLayer::tls_handshaken()
199 void SecureLayer::tls_readyRead()
201 QByteArray a
= p
.tls
->read();
205 void SecureLayer::tls_readyReadOutgoing(int plainBytes
)
207 QByteArray a
= p
.tls
->readOutgoing();
209 layer
.specifyEncoded(a
.size(), plainBytes
);
213 void SecureLayer::tls_closed()
215 QByteArray a
= p
.tls
->readUnprocessed();
219 void SecureLayer::tls_error(int x
)
224 void SecureLayer::sasl_readyRead()
226 QByteArray a
= p
.sasl
->read();
230 void SecureLayer::sasl_readyReadOutgoing()
233 QByteArray a
= p
.sasl
->readOutgoing(&plainBytes
);
234 layer
.specifyEncoded(a
.size(), plainBytes
);
238 void SecureLayer::sasl_error()
240 error(p
.sasl
->errorCode());
243 void SecureLayer::compressionHandler_readyRead()
245 QByteArray a
= p
.compressionHandler
->read();
249 void SecureLayer::compressionHandler_readyReadOutgoing()
252 QByteArray a
= p
.compressionHandler
->readOutgoing(&plainBytes
);
253 layer
.specifyEncoded(a
.size(), plainBytes
);
257 void SecureLayer::compressionHandler_error()
259 error(p
.compressionHandler
->errorCode());
262 #ifdef USE_TLSHANDLER
263 void SecureLayer::tlsHandler_success()
269 void SecureLayer::tlsHandler_fail()
274 void SecureLayer::tlsHandler_closed()
276 tlsClosed(QByteArray());
279 void SecureLayer::tlsHandler_readyRead(const QByteArray
&a
)
284 void SecureLayer::tlsHandler_readyReadOutgoing(const QByteArray
&a
, int plainBytes
)
287 layer
.specifyEncoded(a
.size(), plainBytes
);
292 typedef QList
<SecureLayer
*> SecureLayerList
;
294 class SecureStream::Private
298 SecureLayerList layers
;
306 foreach ( SecureLayer
*s
, layers
) {
307 if(s
->type
== SecureLayer::TLS
308 #ifdef USE_TLSHANDLER
309 || s
->type
== SecureLayer::TLSH
318 bool haveSASL() const
320 SecureLayerList::iterator it
;
321 foreach ( SecureLayer
* s
, layers
) {
322 if(s
->type
== SecureLayer::SASL
)
328 bool haveCompress() const
330 SecureLayerList::iterator it
;
331 foreach ( SecureLayer
* s
, layers
) {
332 if(s
->type
== SecureLayer::Compression
)
339 SecureStream::SecureStream(ByteStream
*s
)
340 :ByteStream(0), d(new Private())
343 connect(d
->bs
, SIGNAL(readyRead()), SLOT(bs_readyRead()));
344 connect(d
->bs
, SIGNAL(bytesWritten(int)), SLOT(bs_bytesWritten(int)));
348 d
->topInProgress
= false;
351 SecureStream::~SecureStream()
356 void SecureStream::linkLayer(QObject
*s
)
358 connect(s
, SIGNAL(tlsHandshaken()), SLOT(layer_tlsHandshaken()));
359 connect(s
, SIGNAL(tlsClosed(const QByteArray
&)), SLOT(layer_tlsClosed(const QByteArray
&)));
360 connect(s
, SIGNAL(readyRead(const QByteArray
&)), SLOT(layer_readyRead(const QByteArray
&)));
361 connect(s
, SIGNAL(needWrite(const QByteArray
&)), SLOT(layer_needWrite(const QByteArray
&)));
362 connect(s
, SIGNAL(error(int)), SLOT(layer_error(int)));
365 int SecureStream::calcPrebytes() const
368 foreach ( SecureLayer
*s
, d
->layers
)
370 return (d
->pending
- x
);
373 void SecureStream::startTLSClient(QCA::TLS
*t
, const QByteArray
&spare
)
375 if(!d
->active
|| d
->topInProgress
|| d
->haveTLS())
378 SecureLayer
*s
= new SecureLayer(t
);
379 s
->prebytes
= calcPrebytes();
382 d
->topInProgress
= true;
387 void SecureStream::startTLSServer(QCA::TLS
*t
, const QByteArray
&spare
)
389 if(!d
->active
|| d
->topInProgress
|| d
->haveTLS())
392 SecureLayer
*s
= new SecureLayer(t
);
393 s
->prebytes
= calcPrebytes();
396 d
->topInProgress
= true;
401 void SecureStream::setLayerCompress(const QByteArray
& spare
)
403 if(!d
->active
|| d
->topInProgress
|| d
->haveCompress())
406 SecureLayer
*s
= new SecureLayer(new CompressionHandler());
407 s
->prebytes
= calcPrebytes();
414 void SecureStream::setLayerSASL(QCA::SASL
*sasl
, const QByteArray
&spare
)
416 if(!d
->active
|| d
->topInProgress
|| d
->haveSASL())
419 SecureLayer
*s
= new SecureLayer(sasl
);
420 s
->prebytes
= calcPrebytes();
427 #ifdef USE_TLSHANDLER
428 void SecureStream::startTLSClient(TLSHandler
*t
, const QString
&server
, const QByteArray
&spare
)
430 if(!d
->active
|| d
->topInProgress
|| d
->haveTLS())
433 SecureLayer
*s
= new SecureLayer(t
);
434 s
->prebytes
= calcPrebytes();
437 d
->topInProgress
= true;
439 // unlike QCA::TLS, TLSHandler has no return value
440 s
->p
.tlsHandler
->startClient(server
);
446 void SecureStream::closeTLS()
448 SecureLayer
*s
= d
->layers
.last();
450 if(s
->type
== SecureLayer::TLS
)
455 int SecureStream::errorCode() const
460 bool SecureStream::isOpen() const
465 void SecureStream::write(const QByteArray
&a
)
470 d
->pending
+= a
.size();
472 // send to the last layer
473 SecureLayer
*s
= d
->layers
.last();
480 int SecureStream::bytesToWrite() const
485 void SecureStream::bs_readyRead()
487 QByteArray a
= d
->bs
->read();
489 // send to the first layer
490 SecureLayer
*s
= d
->layers
.first();
498 void SecureStream::bs_bytesWritten(int bytes
)
500 SecureLayerList::iterator it
;
501 for(it
= d
->layers
.begin(); it
!= d
->layers
.end(); ++it
)
502 bytes
= (*it
)->finished(bytes
);
510 void SecureStream::layer_tlsHandshaken()
512 d
->topInProgress
= false;
516 void SecureStream::layer_tlsClosed(const QByteArray
&)
519 qDeleteAll(d
->layers
);
524 void SecureStream::layer_readyRead(const QByteArray
&a
)
526 SecureLayer
*s
= (SecureLayer
*)sender();
527 SecureLayerList::iterator it
= d
->layers
.begin();
528 while(*it
!= s
&& it
!= d
->layers
.end())
534 if (it
!= d
->layers
.end()) {
545 void SecureStream::layer_needWrite(const QByteArray
&a
)
547 SecureLayer
*s
= (SecureLayer
*)sender();
548 SecureLayerList::const_iterator it
= d
->layers
.constBegin();
549 while(*it
!= s
&& it
!= d
->layers
.constEnd())
553 if ( it
!= d
->layers
.constBegin() ) {
563 void SecureStream::layer_error(int x
)
565 SecureLayer
*s
= (SecureLayer
*)sender();
569 qDeleteAll(d
->layers
);
571 if(type
== SecureLayer::TLS
)
573 else if(type
== SecureLayer::SASL
)
575 #ifdef USE_TLSHANDLER
576 else if(type
== SecureLayer::TLSH
)
581 void SecureStream::insertData(const QByteArray
&a
)
584 if (!d
->layers
.isEmpty())
585 d
->layers
.last()->writeIncoming(a
);
591 void SecureStream::writeRawData(const QByteArray
&a
)
596 void SecureStream::incomingData(const QByteArray
&a
)
599 //qDebug( "SecureStream::incomingData() got %i bytes ", a.size() );
605 #include "securestream.moc"