Show invite menu in wlm chat window immediately
[kdenetwork.git] / kopete / protocols / groupwise / libgroupwise / securestream.cpp
blobdfaef6067ac00cbc198c6aa80d3b9a970a9b1f0d
1 /*
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 *************************************************************************
13 * *
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. *
18 * *
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.
30 #include <qpointer.h>
31 #include <qtimer.h>
32 #include <QList>
34 #include "securestream.h"
36 #include "compressionhandler.h"
37 //----------------------------------------------------------------------------
38 // LayerTracker
39 //----------------------------------------------------------------------------
40 LayerTracker::LayerTracker()
42 p = 0;
45 void LayerTracker::reset()
46 {USE_TLSHANDLER
47 p = 0;
48 list.clear();
51 void LayerTracker::addPlain(int plain)
53 p += plain;
56 void LayerTracker::specifyEncoded(int encoded, int plain)
58 // can't specify more bytes than we have
59 if(plain > p)
60 plain = p;
61 p -= plain;
62 Item i;
63 i.plain = plain;
64 i.encoded = encoded;
65 list += i;
68 int LayerTracker::finished(int encoded)
70 int plain = 0;
71 for(QList<Item>::Iterator it = list.begin(); it != list.end();) {
72 Item &i = *it;
74 // not enough?
75 if(encoded < i.encoded) {
76 i.encoded -= encoded;
77 break;
80 encoded -= i.encoded;
81 plain += i.plain;
82 it = list.erase(it);
84 return plain;
87 //----------------------------------------------------------------------------
88 // SecureStream
89 //----------------------------------------------------------------------------
91 SecureLayer::SecureLayer(QCA::TLS *t)
93 type = TLS;
94 p.tls = t;
95 init();
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)
105 type = SASL;
106 p.sasl = s;
107 init();
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)
116 type = TLSH;
117 p.tlsHandler = t;
118 init();
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)));
125 #endif
127 SecureLayer::SecureLayer(CompressionHandler *t)
129 type = Compression;
130 p.compressionHandler = t;
131 init();
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()
139 tls_done = false;
140 prebytes = 0;
143 void SecureLayer::write(const QByteArray &a)
145 layer.addPlain(a.size());
146 switch(type) {
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; }
151 #endif
152 case Compression: { p.compressionHandler->write(a); break; }
156 void SecureLayer::writeIncoming(const QByteArray &a)
158 switch(type) {
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; }
163 #endif
164 case Compression: { p.compressionHandler->writeIncoming(a); break; }
168 int SecureLayer::finished(int plain)
170 int written = 0;
172 // deal with prebytes (bytes sent prior to this security layer)
173 if(prebytes > 0) {
174 if(prebytes >= plain) {
175 written += plain;
176 prebytes -= plain;
177 plain = 0;
179 else {
180 written += prebytes;
181 plain -= prebytes;
182 prebytes = 0;
186 // put remainder into the layer tracker
187 if(type == SASL || tls_done)
188 written += layer.finished(plain);
190 return written;
193 void SecureLayer::tls_handshaken()
195 tls_done = true;
196 tlsHandshaken();
199 void SecureLayer::tls_readyRead()
201 QByteArray a = p.tls->read();
202 readyRead(a);
205 void SecureLayer::tls_readyReadOutgoing(int plainBytes)
207 QByteArray a = p.tls->readOutgoing();
208 if(tls_done)
209 layer.specifyEncoded(a.size(), plainBytes);
210 needWrite(a);
213 void SecureLayer::tls_closed()
215 QByteArray a = p.tls->readUnprocessed();
216 tlsClosed(a);
219 void SecureLayer::tls_error(int x)
221 error(x);
224 void SecureLayer::sasl_readyRead()
226 QByteArray a = p.sasl->read();
227 readyRead(a);
230 void SecureLayer::sasl_readyReadOutgoing()
232 int plainBytes;
233 QByteArray a = p.sasl->readOutgoing(&plainBytes);
234 layer.specifyEncoded(a.size(), plainBytes);
235 needWrite(a);
238 void SecureLayer::sasl_error()
240 error(p.sasl->errorCode());
243 void SecureLayer::compressionHandler_readyRead()
245 QByteArray a = p.compressionHandler->read();
246 readyRead(a);
249 void SecureLayer::compressionHandler_readyReadOutgoing()
251 int plainBytes;
252 QByteArray a = p.compressionHandler->readOutgoing(&plainBytes);
253 layer.specifyEncoded(a.size(), plainBytes);
254 needWrite(a);
257 void SecureLayer::compressionHandler_error()
259 error(p.compressionHandler->errorCode());
262 #ifdef USE_TLSHANDLER
263 void SecureLayer::tlsHandler_success()
265 tls_done = true;
266 tlsHandshaken();
269 void SecureLayer::tlsHandler_fail()
271 error(0);
274 void SecureLayer::tlsHandler_closed()
276 tlsClosed(QByteArray());
279 void SecureLayer::tlsHandler_readyRead(const QByteArray &a)
281 readyRead(a);
284 void SecureLayer::tlsHandler_readyReadOutgoing(const QByteArray &a, int plainBytes)
286 if(tls_done)
287 layer.specifyEncoded(a.size(), plainBytes);
288 needWrite(a);
290 #endif
292 typedef QList<SecureLayer*> SecureLayerList;
294 class SecureStream::Private
296 public:
297 ByteStream *bs;
298 SecureLayerList layers;
299 int pending;
300 int errorCode;
301 bool active;
302 bool topInProgress;
304 bool haveTLS() const
306 foreach ( SecureLayer *s, layers ) {
307 if(s->type == SecureLayer::TLS
308 #ifdef USE_TLSHANDLER
309 || s->type == SecureLayer::TLSH
310 #endif
312 return true;
315 return false;
318 bool haveSASL() const
320 SecureLayerList::iterator it;
321 foreach ( SecureLayer * s, layers ) {
322 if(s->type == SecureLayer::SASL)
323 return true;
325 return false;
328 bool haveCompress() const
330 SecureLayerList::iterator it;
331 foreach ( SecureLayer * s, layers ) {
332 if(s->type == SecureLayer::Compression)
333 return true;
335 return false;
339 SecureStream::SecureStream(ByteStream *s)
340 :ByteStream(0), d(new Private())
342 d->bs = s;
343 connect(d->bs, SIGNAL(readyRead()), SLOT(bs_readyRead()));
344 connect(d->bs, SIGNAL(bytesWritten(int)), SLOT(bs_bytesWritten(int)));
346 d->pending = 0;
347 d->active = true;
348 d->topInProgress = false;
351 SecureStream::~SecureStream()
353 delete d;
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
367 int x = 0;
368 foreach ( SecureLayer *s, d->layers )
369 x += s->prebytes;
370 return (d->pending - x);
373 void SecureStream::startTLSClient(QCA::TLS *t, const QByteArray &spare)
375 if(!d->active || d->topInProgress || d->haveTLS())
376 return;
378 SecureLayer *s = new SecureLayer(t);
379 s->prebytes = calcPrebytes();
380 linkLayer(s);
381 d->layers.append(s);
382 d->topInProgress = true;
384 insertData(spare);
387 void SecureStream::startTLSServer(QCA::TLS *t, const QByteArray &spare)
389 if(!d->active || d->topInProgress || d->haveTLS())
390 return;
392 SecureLayer *s = new SecureLayer(t);
393 s->prebytes = calcPrebytes();
394 linkLayer(s);
395 d->layers.append(s);
396 d->topInProgress = true;
398 insertData(spare);
401 void SecureStream::setLayerCompress(const QByteArray& spare)
403 if(!d->active || d->topInProgress || d->haveCompress())
404 return;
406 SecureLayer *s = new SecureLayer(new CompressionHandler());
407 s->prebytes = calcPrebytes();
408 linkLayer(s);
409 d->layers.append(s);
411 insertData(spare);
414 void SecureStream::setLayerSASL(QCA::SASL *sasl, const QByteArray &spare)
416 if(!d->active || d->topInProgress || d->haveSASL())
417 return;
419 SecureLayer *s = new SecureLayer(sasl);
420 s->prebytes = calcPrebytes();
421 linkLayer(s);
422 d->layers.append(s);
424 insertData(spare);
427 #ifdef USE_TLSHANDLER
428 void SecureStream::startTLSClient(TLSHandler *t, const QString &server, const QByteArray &spare)
430 if(!d->active || d->topInProgress || d->haveTLS())
431 return;
433 SecureLayer *s = new SecureLayer(t);
434 s->prebytes = calcPrebytes();
435 linkLayer(s);
436 d->layers.append(s);
437 d->topInProgress = true;
439 // unlike QCA::TLS, TLSHandler has no return value
440 s->p.tlsHandler->startClient(server);
442 insertData(spare);
444 #endif
446 void SecureStream::closeTLS()
448 SecureLayer *s = d->layers.last();
449 if(s) {
450 if(s->type == SecureLayer::TLS)
451 s->p.tls->close();
455 int SecureStream::errorCode() const
457 return d->errorCode;
460 bool SecureStream::isOpen() const
462 return d->active;
465 void SecureStream::write(const QByteArray &a)
467 if(!isOpen())
468 return;
470 d->pending += a.size();
472 // send to the last layer
473 SecureLayer *s = d->layers.last();
474 if(s)
475 s->write(a);
476 else
477 writeRawData(a);
480 int SecureStream::bytesToWrite() const
482 return d->pending;
485 void SecureStream::bs_readyRead()
487 QByteArray a = d->bs->read();
489 // send to the first layer
490 SecureLayer *s = d->layers.first();
491 if(s) {
492 s->writeIncoming(a);
494 else
495 incomingData(a);
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);
504 if(bytes > 0) {
505 d->pending -= bytes;
506 bytesWritten(bytes);
510 void SecureStream::layer_tlsHandshaken()
512 d->topInProgress = false;
513 tlsHandshaken();
516 void SecureStream::layer_tlsClosed(const QByteArray &)
518 d->active = false;
519 qDeleteAll(d->layers);
520 d->layers.clear();
521 tlsClosed();
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())
529 ++it;
531 // pass upwards
532 ++it;
534 if (it != d->layers.end()) {
535 s = *it;
536 if(s)
537 s->writeIncoming(a);
538 else
539 incomingData(a);
541 else
542 incomingData(a);
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())
550 ++it;
552 // pass downwards
553 if ( it != d->layers.constBegin() ) {
554 --it;
555 s = *it;
556 if(s)
557 s->write(a);
559 else
560 writeRawData(a);
563 void SecureStream::layer_error(int x)
565 SecureLayer *s = (SecureLayer *)sender();
566 int type = s->type;
567 d->errorCode = x;
568 d->active = false;
569 qDeleteAll(d->layers);
570 d->layers.clear();
571 if(type == SecureLayer::TLS)
572 error(ErrTLS);
573 else if(type == SecureLayer::SASL)
574 error(ErrSASL);
575 #ifdef USE_TLSHANDLER
576 else if(type == SecureLayer::TLSH)
577 error(ErrTLS);
578 #endif
581 void SecureStream::insertData(const QByteArray &a)
583 if(!a.isEmpty()) {
584 if (!d->layers.isEmpty())
585 d->layers.last()->writeIncoming(a);
586 else
587 incomingData(a);
591 void SecureStream::writeRawData(const QByteArray &a)
593 d->bs->write(a);
596 void SecureStream::incomingData(const QByteArray &a)
598 appendRead(a);
599 //qDebug( "SecureStream::incomingData() got %i bytes ", a.size() );
601 if(bytesAvailable())
602 readyRead();
605 #include "securestream.moc"