PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/kdenetwork-4.8.97/kopete/protocols/groupwise/libgroupwise/securestream.cpp

#
C++ | 605 lines | 474 code | 88 blank | 43 comment | 67 complexity | cb2a46c0481f51ff8e71c2c0741e42d3 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0
  1. /*
  2. securestream.cpp - Kopete Groupwise Protocol
  3. Combines a ByteStream with TLS and SASL
  4. Copyright (c) 2006,2007 Novell, Inc http://www.opensuse.org
  5. Copyright (c) 2004 SUSE Linux AG http://www.suse.com
  6. Based on Iris, Copyright (C) 2003 Justin Karneges <justin@affinix.com>
  7. Kopete (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
  8. *************************************************************************
  9. * *
  10. * This library is free software; you can redistribute it and/or *
  11. * modify it under the terms of the GNU Lesser General Public *
  12. * License as published by the Free Software Foundation; either *
  13. * version 2 of the License, or (at your option) any later version. *
  14. * *
  15. *************************************************************************
  16. */
  17. /*
  18. Note: SecureStream depends on the underlying security layers to signal
  19. plain-to-encrypted results immediately (as opposed to waiting for the
  20. event loop) so that the user cannot add/remove security layers during
  21. this conversion moment. QCA::TLS and QCA::SASL behave as expected,
  22. but future layers might not.
  23. */
  24. #include <qpointer.h>
  25. #include <qtimer.h>
  26. #include <QList>
  27. #include "securestream.h"
  28. #include "compressionhandler.h"
  29. //----------------------------------------------------------------------------
  30. // LayerTracker
  31. //----------------------------------------------------------------------------
  32. LayerTracker::LayerTracker()
  33. {
  34. p = 0;
  35. }
  36. void LayerTracker::reset()
  37. {USE_TLSHANDLER
  38. p = 0;
  39. list.clear();
  40. }
  41. void LayerTracker::addPlain(int plain)
  42. {
  43. p += plain;
  44. }
  45. void LayerTracker::specifyEncoded(int encoded, int plain)
  46. {
  47. // can't specify more bytes than we have
  48. if(plain > p)
  49. plain = p;
  50. p -= plain;
  51. Item i;
  52. i.plain = plain;
  53. i.encoded = encoded;
  54. list += i;
  55. }
  56. int LayerTracker::finished(int encoded)
  57. {
  58. int plain = 0;
  59. for(QList<Item>::Iterator it = list.begin(); it != list.end();) {
  60. Item &i = *it;
  61. // not enough?
  62. if(encoded < i.encoded) {
  63. i.encoded -= encoded;
  64. break;
  65. }
  66. encoded -= i.encoded;
  67. plain += i.plain;
  68. it = list.erase(it);
  69. }
  70. return plain;
  71. }
  72. //----------------------------------------------------------------------------
  73. // SecureStream
  74. //----------------------------------------------------------------------------
  75. SecureLayer::SecureLayer(QCA::TLS *t)
  76. {
  77. type = TLS;
  78. p.tls = t;
  79. init();
  80. connect(p.tls, SIGNAL(handshaken()), SLOT(tls_handshaken()));
  81. connect(p.tls, SIGNAL(readyRead()), SLOT(tls_readyRead()));
  82. connect(p.tls, SIGNAL(readyReadOutgoing(int)), SLOT(tls_readyReadOutgoing(int)));
  83. connect(p.tls, SIGNAL(closed()), SLOT(tls_closed()));
  84. connect(p.tls, SIGNAL(error(int)), SLOT(tls_error(int)));
  85. }
  86. SecureLayer::SecureLayer(QCA::SASL *s)
  87. {
  88. type = SASL;
  89. p.sasl = s;
  90. init();
  91. connect(p.sasl, SIGNAL(readyRead()), SLOT(sasl_readyRead()));
  92. connect(p.sasl, SIGNAL(readyReadOutgoing(int)), SLOT(sasl_readyReadOutgoing(int)));
  93. connect(p.sasl, SIGNAL(error(int)), SLOT(sasl_error(int)));
  94. }
  95. #ifdef USE_TLSHANDLER
  96. SecureLayer::SecureLayer(TLSHandler *t)
  97. {
  98. type = TLSH;
  99. p.tlsHandler = t;
  100. init();
  101. connect(p.tlsHandler, SIGNAL(success()), SLOT(tlsHandler_success()));
  102. connect(p.tlsHandler, SIGNAL(fail()), SLOT(tlsHandler_fail()));
  103. connect(p.tlsHandler, SIGNAL(closed()), SLOT(tlsHandler_closed()));
  104. connect(p.tlsHandler, SIGNAL(readyRead(QByteArray)), SLOT(tlsHandler_readyRead(QByteArray)));
  105. connect(p.tlsHandler, SIGNAL(readyReadOutgoing(QByteArray,int)), SLOT(tlsHandler_readyReadOutgoing(QByteArray,int)));
  106. }
  107. #endif
  108. SecureLayer::SecureLayer(CompressionHandler *t)
  109. {
  110. type = Compression;
  111. p.compressionHandler = t;
  112. init();
  113. connect(p.compressionHandler, SIGNAL(readyRead()), SLOT(compressionHandler_readyRead()));
  114. connect(p.compressionHandler, SIGNAL(readyReadOutgoing(int)), SLOT(compressionHandler_readyReadOutgoing(int)));
  115. connect(p.compressionHandler, SIGNAL(error(int)), SLOT(compressionHandler_error(int)));
  116. }
  117. void SecureLayer::init()
  118. {
  119. tls_done = false;
  120. prebytes = 0;
  121. }
  122. void SecureLayer::write(const QByteArray &a)
  123. {
  124. layer.addPlain(a.size());
  125. switch(type) {
  126. case TLS: { p.tls->write(a); break; }
  127. case SASL: { p.sasl->write(a); break; }
  128. #ifdef USE_TLSHANDLER
  129. case TLSH: { p.tlsHandler->write(a); break; }
  130. #endif
  131. case Compression: { p.compressionHandler->write(a); break; }
  132. }
  133. }
  134. void SecureLayer::writeIncoming(const QByteArray &a)
  135. {
  136. switch(type) {
  137. case TLS: { p.tls->writeIncoming(a); break; }
  138. case SASL: { p.sasl->writeIncoming(a); break; }
  139. #ifdef USE_TLSHANDLER
  140. case TLSH: { p.tlsHandler->writeIncoming(a); break; }
  141. #endif
  142. case Compression: { p.compressionHandler->writeIncoming(a); break; }
  143. }
  144. }
  145. int SecureLayer::finished(int plain)
  146. {
  147. int written = 0;
  148. // deal with prebytes (bytes sent prior to this security layer)
  149. if(prebytes > 0) {
  150. if(prebytes >= plain) {
  151. written += plain;
  152. prebytes -= plain;
  153. plain = 0;
  154. }
  155. else {
  156. written += prebytes;
  157. plain -= prebytes;
  158. prebytes = 0;
  159. }
  160. }
  161. // put remainder into the layer tracker
  162. if(type == SASL || tls_done)
  163. written += layer.finished(plain);
  164. return written;
  165. }
  166. void SecureLayer::tls_handshaken()
  167. {
  168. tls_done = true;
  169. tlsHandshaken();
  170. }
  171. void SecureLayer::tls_readyRead()
  172. {
  173. QByteArray a = p.tls->read();
  174. readyRead(a);
  175. }
  176. void SecureLayer::tls_readyReadOutgoing(int plainBytes)
  177. {
  178. QByteArray a = p.tls->readOutgoing();
  179. if(tls_done)
  180. layer.specifyEncoded(a.size(), plainBytes);
  181. needWrite(a);
  182. }
  183. void SecureLayer::tls_closed()
  184. {
  185. QByteArray a = p.tls->readUnprocessed();
  186. tlsClosed(a);
  187. }
  188. void SecureLayer::tls_error(int x)
  189. {
  190. error(x);
  191. }
  192. void SecureLayer::sasl_readyRead()
  193. {
  194. QByteArray a = p.sasl->read();
  195. readyRead(a);
  196. }
  197. void SecureLayer::sasl_readyReadOutgoing()
  198. {
  199. int plainBytes;
  200. QByteArray a = p.sasl->readOutgoing(&plainBytes);
  201. layer.specifyEncoded(a.size(), plainBytes);
  202. needWrite(a);
  203. }
  204. void SecureLayer::sasl_error()
  205. {
  206. error(p.sasl->errorCode());
  207. }
  208. void SecureLayer::compressionHandler_readyRead()
  209. {
  210. QByteArray a = p.compressionHandler->read();
  211. readyRead(a);
  212. }
  213. void SecureLayer::compressionHandler_readyReadOutgoing()
  214. {
  215. int plainBytes;
  216. QByteArray a = p.compressionHandler->readOutgoing(&plainBytes);
  217. layer.specifyEncoded(a.size(), plainBytes);
  218. needWrite(a);
  219. }
  220. void SecureLayer::compressionHandler_error()
  221. {
  222. error(p.compressionHandler->errorCode());
  223. }
  224. #ifdef USE_TLSHANDLER
  225. void SecureLayer::tlsHandler_success()
  226. {
  227. tls_done = true;
  228. tlsHandshaken();
  229. }
  230. void SecureLayer::tlsHandler_fail()
  231. {
  232. error(0);
  233. }
  234. void SecureLayer::tlsHandler_closed()
  235. {
  236. tlsClosed(QByteArray());
  237. }
  238. void SecureLayer::tlsHandler_readyRead(const QByteArray &a)
  239. {
  240. readyRead(a);
  241. }
  242. void SecureLayer::tlsHandler_readyReadOutgoing(const QByteArray &a, int plainBytes)
  243. {
  244. if(tls_done)
  245. layer.specifyEncoded(a.size(), plainBytes);
  246. needWrite(a);
  247. }
  248. #endif
  249. typedef QList<SecureLayer*> SecureLayerList;
  250. class SecureStream::Private
  251. {
  252. public:
  253. ByteStream *bs;
  254. SecureLayerList layers;
  255. int pending;
  256. int errorCode;
  257. bool active;
  258. bool topInProgress;
  259. bool haveTLS() const
  260. {
  261. foreach ( SecureLayer *s, layers ) {
  262. if(s->type == SecureLayer::TLS
  263. #ifdef USE_TLSHANDLER
  264. || s->type == SecureLayer::TLSH
  265. #endif
  266. ) {
  267. return true;
  268. }
  269. }
  270. return false;
  271. }
  272. bool haveSASL() const
  273. {
  274. SecureLayerList::iterator it;
  275. foreach ( SecureLayer * s, layers ) {
  276. if(s->type == SecureLayer::SASL)
  277. return true;
  278. }
  279. return false;
  280. }
  281. bool haveCompress() const
  282. {
  283. SecureLayerList::iterator it;
  284. foreach ( SecureLayer * s, layers ) {
  285. if(s->type == SecureLayer::Compression)
  286. return true;
  287. }
  288. return false;
  289. }
  290. };
  291. SecureStream::SecureStream(ByteStream *s)
  292. :ByteStream(0), d(new Private())
  293. {
  294. d->bs = s;
  295. connect(d->bs, SIGNAL(readyRead()), SLOT(bs_readyRead()));
  296. connect(d->bs, SIGNAL(bytesWritten(int)), SLOT(bs_bytesWritten(int)));
  297. d->pending = 0;
  298. d->active = true;
  299. d->topInProgress = false;
  300. }
  301. SecureStream::~SecureStream()
  302. {
  303. delete d;
  304. }
  305. void SecureStream::linkLayer(QObject *s)
  306. {
  307. connect(s, SIGNAL(tlsHandshaken()), SLOT(layer_tlsHandshaken()));
  308. connect(s, SIGNAL(tlsClosed(QByteArray)), SLOT(layer_tlsClosed(QByteArray)));
  309. connect(s, SIGNAL(readyRead(QByteArray)), SLOT(layer_readyRead(QByteArray)));
  310. connect(s, SIGNAL(needWrite(QByteArray)), SLOT(layer_needWrite(QByteArray)));
  311. connect(s, SIGNAL(error(int)), SLOT(layer_error(int)));
  312. }
  313. int SecureStream::calcPrebytes() const
  314. {
  315. int x = 0;
  316. foreach ( SecureLayer *s, d->layers )
  317. x += s->prebytes;
  318. return (d->pending - x);
  319. }
  320. void SecureStream::startTLSClient(QCA::TLS *t, const QByteArray &spare)
  321. {
  322. if(!d->active || d->topInProgress || d->haveTLS())
  323. return;
  324. SecureLayer *s = new SecureLayer(t);
  325. s->prebytes = calcPrebytes();
  326. linkLayer(s);
  327. d->layers.append(s);
  328. d->topInProgress = true;
  329. insertData(spare);
  330. }
  331. void SecureStream::startTLSServer(QCA::TLS *t, const QByteArray &spare)
  332. {
  333. if(!d->active || d->topInProgress || d->haveTLS())
  334. return;
  335. SecureLayer *s = new SecureLayer(t);
  336. s->prebytes = calcPrebytes();
  337. linkLayer(s);
  338. d->layers.append(s);
  339. d->topInProgress = true;
  340. insertData(spare);
  341. }
  342. void SecureStream::setLayerCompress(const QByteArray& spare)
  343. {
  344. if(!d->active || d->topInProgress || d->haveCompress())
  345. return;
  346. SecureLayer *s = new SecureLayer(new CompressionHandler());
  347. s->prebytes = calcPrebytes();
  348. linkLayer(s);
  349. d->layers.append(s);
  350. insertData(spare);
  351. }
  352. void SecureStream::setLayerSASL(QCA::SASL *sasl, const QByteArray &spare)
  353. {
  354. if(!d->active || d->topInProgress || d->haveSASL())
  355. return;
  356. SecureLayer *s = new SecureLayer(sasl);
  357. s->prebytes = calcPrebytes();
  358. linkLayer(s);
  359. d->layers.append(s);
  360. insertData(spare);
  361. }
  362. #ifdef USE_TLSHANDLER
  363. void SecureStream::startTLSClient(TLSHandler *t, const QString &server, const QByteArray &spare)
  364. {
  365. if(!d->active || d->topInProgress || d->haveTLS())
  366. return;
  367. SecureLayer *s = new SecureLayer(t);
  368. s->prebytes = calcPrebytes();
  369. linkLayer(s);
  370. d->layers.append(s);
  371. d->topInProgress = true;
  372. // unlike QCA::TLS, TLSHandler has no return value
  373. s->p.tlsHandler->startClient(server);
  374. insertData(spare);
  375. }
  376. #endif
  377. void SecureStream::closeTLS()
  378. {
  379. SecureLayer *s = d->layers.last();
  380. if(s) {
  381. if(s->type == SecureLayer::TLS)
  382. s->p.tls->close();
  383. }
  384. }
  385. int SecureStream::errorCode() const
  386. {
  387. return d->errorCode;
  388. }
  389. bool SecureStream::isOpen() const
  390. {
  391. return d->active;
  392. }
  393. void SecureStream::write(const QByteArray &a)
  394. {
  395. if(!isOpen())
  396. return;
  397. d->pending += a.size();
  398. // send to the last layer
  399. SecureLayer *s = d->layers.last();
  400. if(s)
  401. s->write(a);
  402. else
  403. writeRawData(a);
  404. }
  405. int SecureStream::bytesToWrite() const
  406. {
  407. return d->pending;
  408. }
  409. void SecureStream::bs_readyRead()
  410. {
  411. QByteArray a = d->bs->read();
  412. // send to the first layer
  413. SecureLayer *s = d->layers.first();
  414. if(s) {
  415. s->writeIncoming(a);
  416. }
  417. else
  418. incomingData(a);
  419. }
  420. void SecureStream::bs_bytesWritten(int bytes)
  421. {
  422. SecureLayerList::iterator it;
  423. for(it = d->layers.begin(); it != d->layers.end(); ++it)
  424. bytes = (*it)->finished(bytes);
  425. if(bytes > 0) {
  426. d->pending -= bytes;
  427. bytesWritten(bytes);
  428. }
  429. }
  430. void SecureStream::layer_tlsHandshaken()
  431. {
  432. d->topInProgress = false;
  433. tlsHandshaken();
  434. }
  435. void SecureStream::layer_tlsClosed(const QByteArray &)
  436. {
  437. d->active = false;
  438. qDeleteAll(d->layers);
  439. d->layers.clear();
  440. tlsClosed();
  441. }
  442. void SecureStream::layer_readyRead(const QByteArray &a)
  443. {
  444. SecureLayer *s = (SecureLayer *)sender();
  445. SecureLayerList::iterator it = d->layers.begin();
  446. while(*it != s && it != d->layers.end())
  447. ++it;
  448. // pass upwards
  449. ++it;
  450. if (it != d->layers.end()) {
  451. s = *it;
  452. if(s)
  453. s->writeIncoming(a);
  454. else
  455. incomingData(a);
  456. }
  457. else
  458. incomingData(a);
  459. }
  460. void SecureStream::layer_needWrite(const QByteArray &a)
  461. {
  462. SecureLayer *s = (SecureLayer *)sender();
  463. SecureLayerList::const_iterator it = d->layers.constBegin();
  464. while(*it != s && it != d->layers.constEnd())
  465. ++it;
  466. // pass downwards
  467. if ( it != d->layers.constBegin() ) {
  468. --it;
  469. s = *it;
  470. if(s)
  471. s->write(a);
  472. }
  473. else
  474. writeRawData(a);
  475. }
  476. void SecureStream::layer_error(int x)
  477. {
  478. SecureLayer *s = (SecureLayer *)sender();
  479. int type = s->type;
  480. d->errorCode = x;
  481. d->active = false;
  482. qDeleteAll(d->layers);
  483. d->layers.clear();
  484. if(type == SecureLayer::TLS)
  485. error(ErrTLS);
  486. else if(type == SecureLayer::SASL)
  487. error(ErrSASL);
  488. #ifdef USE_TLSHANDLER
  489. else if(type == SecureLayer::TLSH)
  490. error(ErrTLS);
  491. #endif
  492. }
  493. void SecureStream::insertData(const QByteArray &a)
  494. {
  495. if(!a.isEmpty()) {
  496. if (!d->layers.isEmpty())
  497. d->layers.last()->writeIncoming(a);
  498. else
  499. incomingData(a);
  500. }
  501. }
  502. void SecureStream::writeRawData(const QByteArray &a)
  503. {
  504. d->bs->write(a);
  505. }
  506. void SecureStream::incomingData(const QByteArray &a)
  507. {
  508. appendRead(a);
  509. //qDebug( "SecureStream::incomingData() got %i bytes ", a.size() );
  510. if(bytesAvailable())
  511. readyRead();
  512. }
  513. #include "securestream.moc"