1 /* Ricochet - https://ricochet.im/
2 * Copyright (C) 2014, John Brooks <john.brooks@dereferenced.net>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * * Neither the names of the copyright owners nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "Connection_p.h"
34 #include "ControlChannel.h"
35 #include "utils/Useful.h"
36 #include <QTcpSocket>
37 #include <QTimer>
38 #include <QtEndian>
39 #include <QDebug>
40
41 using namespace Protocol;
42
Connection(QTcpSocket * socket,Direction direction)43 Connection::Connection(QTcpSocket *socket, Direction direction)
44 : QObject()
45 , d(new ConnectionPrivate(this))
46 {
47 d->setSocket(socket, direction);
48 }
49
ConnectionPrivate(Connection * qq)50 ConnectionPrivate::ConnectionPrivate(Connection *qq)
51 : QObject(qq)
52 , q(qq)
53 , socket(0)
54 , direction(Connection::ClientSide)
55 , purpose(Connection::Purpose::Unknown)
56 , wasClosed(false)
57 , handshakeDone(false)
58 , nextOutboundChannelId(-1)
59 {
60 ageTimer.start();
61
62 QTimer *timeout = new QTimer(this);
63 timeout->setSingleShot(true);
64 timeout->setInterval(UnknownPurposeTimeout * 1000);
65 connect(timeout, &QTimer::timeout, this,
66 [this,timeout]() {
67 if (purpose == Connection::Purpose::Unknown) {
68 qDebug() << "Closing connection" << q << "with unknown purpose after timeout";
69 q->close();
70 }
71 timeout->deleteLater();
72 }
73 );
74 timeout->start();
75 }
76
~Connection()77 Connection::~Connection()
78 {
79 qDebug() << this << "Destroying connection";
80
81 // When we call closeImmediately, the list of channels will be cleared.
82 // In the normal case, they will all use deleteLater to be freed at the
83 // next event loop. Since the connection is being destructed immediately,
84 // and we want to be certain that channels don't outlive it, copy the
85 // list before it's cleared and delete them immediately afterwards.
86 auto channels = d->channels;
87 d->closeImmediately();
88
89 // These would be deleted by QObject ownership as well, but we want to
90 // give them a chance to destruct before the connection d pointer is reset.
91 foreach (Channel *c, channels)
92 delete c;
93
94 // Reset d pointer, so we'll crash nicely if anything tries to call
95 // into Connection after this.
96 d = 0;
97 }
98
~ConnectionPrivate()99 ConnectionPrivate::~ConnectionPrivate()
100 {
101 // Reset q pointer, for the same reason as above
102 q = 0;
103 }
104
direction() const105 Connection::Direction Connection::direction() const
106 {
107 return d->direction;
108 }
109
isConnected() const110 bool Connection::isConnected() const
111 {
112 bool re = d->socket && d->socket->state() == QAbstractSocket::ConnectedState;
113 if (d->wasClosed) {
114 Q_ASSERT(!re);
115 }
116 return re;
117 }
118
serverHostname() const119 QString Connection::serverHostname() const
120 {
121 QString hostname;
122 if (direction() == ClientSide)
123 hostname = d->socket->peerName();
124 else if (direction() == ServerSide)
125 hostname = d->socket->property("localHostname").toString();
126
127 if (!hostname.endsWith(QStringLiteral(".onion"))) {
128 BUG() << "Connection does not have a valid server hostname:" << hostname;
129 return QString();
130 }
131
132 return hostname;
133 }
134
age() const135 int Connection::age() const
136 {
137 return qRound(d->ageTimer.elapsed() / 1000.0);
138 }
139
setSocket(QTcpSocket * s,Connection::Direction d)140 void ConnectionPrivate::setSocket(QTcpSocket *s, Connection::Direction d)
141 {
142 if (socket) {
143 BUG() << "Connection already has a socket";
144 return;
145 }
146
147 socket = s;
148 direction = d;
149 connect(socket, &QAbstractSocket::disconnected, this, &ConnectionPrivate::socketDisconnected);
150 connect(socket, &QIODevice::readyRead, this, &ConnectionPrivate::socketReadable);
151
152 socket->setParent(q);
153
154 if (socket->state() != QAbstractSocket::ConnectedState) {
155 BUG() << "Connection created with socket in a non-connected state" << socket->state();
156 }
157
158 Channel *control = new ControlChannel(direction == Connection::ClientSide ? Channel::Outbound : Channel::Inbound, q);
159 // Closing the control channel must also close the connection
160 connect(control, &Channel::invalidated, q, &Connection::close);
161 insertChannel(control);
162
163 if (!control->isOpened() || control->identifier() != 0 || q->channel(0) != control) {
164 BUG() << "Control channel on new connection is not set up properly";
165 q->close();
166 return;
167 }
168
169 if (direction == Connection::ClientSide) {
170 // The server side is implicitly authenticated (by the transport) as the correct service, so grant that
171 QString serverName = q->serverHostname();
172 if (serverName.isEmpty()) {
173 BUG() << "Server side of connection doesn't have an authenticated name, aborting";
174 q->close();
175 return;
176 }
177
178 q->grantAuthentication(Connection::HiddenServiceAuth, serverName);
179
180 // Send the introduction version handshake message
181 char intro[] = { 0x49, 0x4D, 0x02, ProtocolVersion, 0 };
182 if (socket->write(intro, sizeof(intro)) < (int)sizeof(intro)) {
183 qDebug() << "Failed writing introduction message to socket";
184 q->close();
185 return;
186 }
187 }
188 }
189
close()190 void Connection::close()
191 {
192 if (isConnected()) {
193 Q_ASSERT(!d->wasClosed);
194 qDebug() << "Disconnecting socket for connection" << this;
195 d->socket->disconnectFromHost();
196
197 // If not fully closed in 5 seconds, abort
198 QTimer *timeout = new QTimer(this);
199 timeout->setSingleShot(true);
200 connect(timeout, &QTimer::timeout, d, &ConnectionPrivate::closeImmediately);
201 timeout->start(5000);
202 }
203 }
204
closeImmediately()205 void ConnectionPrivate::closeImmediately()
206 {
207 if (socket)
208 socket->abort();
209
210 if (!wasClosed) {
211 BUG() << "Socket was forcefully closed but never emitted closed signal";
212 wasClosed = true;
213 emit q->closed();
214 }
215
216 if (!channels.isEmpty()) {
217 foreach (Channel *c, channels)
218 qDebug() << "Open channel:" << c << c->type() << c->connection();
219 BUG() << "Channels remain open after forcefully closing connection socket";
220 }
221 }
222
socketDisconnected()223 void ConnectionPrivate::socketDisconnected()
224 {
225 qDebug() << "Connection" << this << "disconnected";
226 closeAllChannels();
227
228 if (!wasClosed) {
229 wasClosed = true;
230 emit q->closed();
231 }
232 }
233
socketReadable()234 void ConnectionPrivate::socketReadable()
235 {
236 if (!handshakeDone) {
237 qint64 available = socket->bytesAvailable();
238
239 if (direction == Connection::ClientSide && available >= 1) {
240 // Expecting a single byte in response with the chosen version
241 uchar version = ProtocolVersionFailed;
242 if (socket->read(reinterpret_cast<char*>(&version), 1) < 1) {
243 qDebug() << "Connection socket error" << socket->error() << "during read:" << socket->errorString();
244 socket->abort();
245 return;
246 }
247
248 handshakeDone = true;
249 if (version == 0) {
250 qDebug() << "Server in outbound connection is using the version 1.0 protocol";
251 emit q->oldVersionNegotiated(socket);
252 q->close();
253 return;
254 } else if (version != ProtocolVersion) {
255 qDebug() << "Version negotiation failed on outbound connection";
256 emit q->versionNegotiationFailed();
257 socket->abort();
258 return;
259 } else
260 emit q->ready();
261 } else if (direction == Connection::ServerSide && available >= 3) {
262 // Expecting at least 3 bytes
263 uchar intro[3] = { 0 };
264 qint64 re = socket->peek(reinterpret_cast<char*>(intro), sizeof(intro));
265 if (re < (int)sizeof(intro)) {
266 qDebug() << "Connection socket error" << socket->error() << "during read:" << socket->errorString();
267 socket->abort();
268 return;
269 }
270
271 quint8 nVersions = intro[2];
272 if (intro[0] != 0x49 || intro[1] != 0x4D || nVersions == 0) {
273 qDebug() << "Invalid introduction sequence on inbound connection";
274 socket->abort();
275 return;
276 }
277
278 if (available < (qint64)sizeof(intro) + nVersions)
279 return;
280
281 // Discard intro header
282 re = socket->read(reinterpret_cast<char*>(intro), sizeof(intro));
283
284 QByteArray versions(nVersions, 0);
285 re = socket->read(versions.data(), versions.size());
286 if (re != versions.size()) {
287 qDebug() << "Connection socket error" << socket->error() << "during read:" << socket->errorString();
288 socket->abort();
289 return;
290 }
291
292 quint8 selectedVersion = ProtocolVersionFailed;
293 foreach (quint8 v, versions) {
294 if (v == ProtocolVersion) {
295 selectedVersion = v;
296 break;
297 }
298 }
299
300 re = socket->write(reinterpret_cast<char*>(&selectedVersion), 1);
301 if (re != 1) {
302 qDebug() << "Connection socket error" << socket->error() << "during write:" << socket->errorString();
303 socket->abort();
304 return;
305 }
306
307 handshakeDone = true;
308 if (selectedVersion != ProtocolVersion) {
309 qDebug() << "Version negotiation failed on inbound connection";
310 emit q->versionNegotiationFailed();
311 // Close gracefully to allow the response to write
312 q->close();
313 return;
314 } else
315 emit q->ready();
316 } else {
317 return;
318 }
319 }
320
321 qint64 available;
322 while ((available = socket->bytesAvailable()) >= PacketHeaderSize) {
323 uchar header[PacketHeaderSize];
324 // Peek at the header first, to read the size of the packet and make sure
325 // the entire thing is available within the buffer.
326 qint64 re = socket->peek(reinterpret_cast<char*>(header), PacketHeaderSize);
327 if (re < 0) {
328 qDebug() << "Connection socket error" << socket->error() << "during read:" << socket->errorString();
329 socket->abort();
330 return;
331 } else if (re < PacketHeaderSize) {
332 BUG() << "Socket had" << available << "bytes available but peek only returned" << re;
333 return;
334 }
335
336 Q_STATIC_ASSERT(PacketHeaderSize == 4);
337 quint16 packetSize = qFromBigEndian<quint16>(header);
338 quint16 channelId = qFromBigEndian<quint16>(&header[2]);
339
340 if (packetSize < PacketHeaderSize) {
341 qWarning() << "Corrupted data from connection (packet size is too small); disconnecting";
342 socket->abort();
343 return;
344 }
345
346 if (packetSize > available)
347 break;
348
349 // Read header out of the buffer and discard
350 re = socket->read(reinterpret_cast<char*>(header), PacketHeaderSize);
351 if (re != PacketHeaderSize) {
352 if (re < 0) {
353 qDebug() << "Connection socket error" << socket->error() << "during read:" << socket->errorString();
354 } else {
355 // Because of QTcpSocket buffering, we can expect that up to 'available' bytes
356 // will read. Treat anything less as an error condition.
357 BUG() << "Socket read was unexpectedly small;" << available << "bytes should've been available but we read" << re;
358 }
359 socket->abort();
360 return;
361 }
362
363 // Read data
364 QByteArray data(packetSize - PacketHeaderSize, 0);
365 re = (data.size() == 0) ? 0 : socket->read(data.data(), data.size());
366 if (re != data.size()) {
367 if (re < 0) {
368 qDebug() << "Connection socket error" << socket->error() << "during read:" << socket->errorString();
369 } else {
370 // As above
371 BUG() << "Socket read was unexpectedly small;" << available << "bytes should've been available but we read" << re;
372 }
373 socket->abort();
374 return;
375 }
376
377 Channel *channel = q->channel(channelId);
378 if (!channel) {
379 // XXX We should sanity-check and rate limit these responses better
380 if (data.isEmpty()) {
381 qDebug() << "Ignoring channel close message for non-existent channel" << channelId;
382 } else {
383 qDebug() << "Ignoring" << data.size() << "byte packet for non-existent channel" << channelId;
384 // Send channel close message
385 writePacket(channelId, QByteArray());
386 }
387 continue;
388 }
389
390 if (channel->connection() != q) {
391 // If this fails, something is extremely broken. It may be dangerous to continue
392 // processing any data at all. Crash gracefully.
393 BUG() << "Channel" << channelId << "found on connection" << this << "but its connection is"
394 << channel->connection();
395 qFatal("Connection mismatch while handling packet");
396 return;
397 }
398
399 if (data.isEmpty()) {
400 channel->closeChannel();
401 } else {
402 channel->receivePacket(data);
403 }
404 }
405 }
406
writePacket(Channel * channel,const QByteArray & data)407 bool ConnectionPrivate::writePacket(Channel *channel, const QByteArray &data)
408 {
409 if (channel->connection() != q) {
410 // As above, dangerously broken, crash the process to avoid damage
411 BUG() << "Writing packet for channel" << channel->identifier() << "on connection" << this
412 << "but its connection is" << channel->connection();
413 qFatal("Connection mismatch while writing packet");
414 return false;
415 }
416
417 return writePacket(channel->identifier(), data);
418 }
419
writePacket(int channelId,const QByteArray & data)420 bool ConnectionPrivate::writePacket(int channelId, const QByteArray &data)
421 {
422 if (channelId < 0 || channelId > UINT16_MAX) {
423 BUG() << "Cannot write packet for channel with invalid identifier" << channelId;
424 return false;
425 }
426
427 if (data.size() > PacketMaxDataSize) {
428 BUG() << "Cannot write oversized packet of" << data.size() << "bytes to channel" << channelId;
429 return false;
430 }
431
432 if (!q->isConnected()) {
433 qDebug() << "Cannot write packet to closed connection";
434 return false;
435 }
436
437 Q_STATIC_ASSERT(PacketHeaderSize + PacketMaxDataSize <= UINT16_MAX);
438 Q_STATIC_ASSERT(PacketHeaderSize == 4);
439 uchar header[PacketHeaderSize] = { 0 };
440 qToBigEndian(static_cast<quint16>(PacketHeaderSize + data.size()), header);
441 qToBigEndian(static_cast<quint16>(channelId), &header[2]);
442
443 qint64 re = socket->write(reinterpret_cast<char*>(header), PacketHeaderSize);
444 if (re != PacketHeaderSize) {
445 qDebug() << "Connection socket error" << socket->error() << "during write:" << socket->errorString();
446 socket->abort();
447 return false;
448 }
449
450 re = socket->write(data);
451 if (re != data.size()) {
452 qDebug() << "Connection socket error" << socket->error() << "during write:" << socket->errorString();
453 socket->abort();
454 return false;
455 }
456
457 return true;
458 }
459
availableOutboundChannelId()460 int ConnectionPrivate::availableOutboundChannelId()
461 {
462 // Server opens even-nubmered channels, client opens odd-numbered
463 bool evenNumbered = (direction == Connection::ServerSide);
464 const int minId = evenNumbered ? 2 : 1;
465 const int maxId = evenNumbered ? (UINT16_MAX-1) : UINT16_MAX;
466
467 if (nextOutboundChannelId < minId || nextOutboundChannelId > maxId)
468 nextOutboundChannelId = minId;
469
470 // Find an unused id, trying a maximum of 100 times, using a random step to avoid collision
471 for (int i = 0; i < 100 && channels.contains(nextOutboundChannelId); i++) {
472 nextOutboundChannelId += 1 + (qrand() % 200);
473 if (evenNumbered)
474 nextOutboundChannelId += nextOutboundChannelId % 2;
475 if (nextOutboundChannelId > maxId)
476 nextOutboundChannelId = minId;
477 }
478
479 if (channels.contains(nextOutboundChannelId)) {
480 // Abort the connection if we still couldn't find an id, because it's probably a nasty bug
481 BUG() << "Can't find an available outbound channel ID for connection; aborting connection";
482 socket->abort();
483 return -1;
484 }
485
486 if (nextOutboundChannelId < minId || nextOutboundChannelId > maxId) {
487 BUG() << "Selected a channel id that isn't within range";
488 return -1;
489 }
490
491 if (evenNumbered == bool(nextOutboundChannelId % 2)) {
492 BUG() << "Selected a channel id that isn't valid for this side of the connection";
493 return -1;
494 }
495
496 int re = nextOutboundChannelId;
497 nextOutboundChannelId += 2;
498 return re;
499 }
500
isValidAvailableChannelId(int id,Connection::Direction side)501 bool ConnectionPrivate::isValidAvailableChannelId(int id, Connection::Direction side)
502 {
503 if (id < 1 || id > UINT16_MAX)
504 return false;
505
506 bool evenNumbered = bool(id % 2);
507 if (evenNumbered == (side == Connection::ServerSide))
508 return false;
509
510 if (channels.contains(id))
511 return false;
512
513 return true;
514 }
515
insertChannel(Channel * channel)516 bool ConnectionPrivate::insertChannel(Channel *channel)
517 {
518 if (channel->connection() != q) {
519 BUG() << "Connection tried to insert a channel assigned to a different connection";
520 return false;
521 }
522
523 if (channel->identifier() < 0) {
524 BUG() << "Connection tried to insert a channel without a valid identifier";
525 return false;
526 }
527
528 if (channels.contains(channel->identifier())) {
529 BUG() << "Connection tried to insert a channel with a duplicate id" << channel->identifier()
530 << "- we have" << channels.value(channel->identifier()) << "and inserted" << channel;
531 return false;
532 }
533
534 if (channel->parent() != q) {
535 BUG() << "Connection inserted a channel without expected parent object. Fixing.";
536 channel->setParent(q);
537 }
538
539 channels.insert(channel->identifier(), channel);
540 return true;
541 }
542
removeChannel(Channel * channel)543 void ConnectionPrivate::removeChannel(Channel *channel)
544 {
545 if (channel->connection() != q) {
546 BUG() << "Connection tried to remove a channel assigned to a different connection";
547 return;
548 }
549
550 // Out of caution, find the channel by pointer instead of identifier. This will make sure
551 // it's always removed from the list, even if the identifier was somehow reset or lost.
552 for (auto it = channels.begin(); it != channels.end(); ) {
553 if (*it == channel)
554 it = channels.erase(it);
555 else
556 it++;
557 }
558 }
559
closeAllChannels()560 void ConnectionPrivate::closeAllChannels()
561 {
562 // Takes a copy, won't be broken by removeChannel calls
563 foreach (Channel *channel, channels)
564 channel->closeChannel();
565
566 if (!channels.isEmpty())
567 BUG() << "Channels remain open on connection after calling closeAllChannels";
568 }
569
channels()570 QHash<int,Channel*> Connection::channels()
571 {
572 return d->channels;
573 }
574
channel(int identifier)575 Channel *Connection::channel(int identifier)
576 {
577 return d->channels.value(identifier);
578 }
579
purpose() const580 Connection::Purpose Connection::purpose() const
581 {
582 return d->purpose;
583 }
584
setPurpose(Purpose value)585 bool Connection::setPurpose(Purpose value)
586 {
587 if (d->purpose == value)
588 return true;
589
590 switch (value) {
591 case Purpose::Unknown:
592 BUG() << "A connection can't reset to unknown purpose";
593 return false;
594 case Purpose::KnownContact:
595 if (!hasAuthenticated(HiddenServiceAuth)) {
596 BUG() << "Connection purpose cannot be KnownContact without authenticating a service";
597 return false;
598 }
599 break;
600 case Purpose::OutboundRequest:
601 if (d->direction != ClientSide) {
602 BUG() << "Connection purpose cannot be OutboundRequest on an inbound connection";
603 return false;
604 } else if (d->purpose != Purpose::Unknown) {
605 BUG() << "Connection purpose cannot change from" << int(d->purpose) << "to OutboundRequest";
606 return false;
607 }
608 break;
609 case Purpose::InboundRequest:
610 if (d->direction != ServerSide) {
611 BUG() << "Connection purpose cannot be InboundRequest on an outbound connection";
612 return false;
613 } else if (d->purpose != Purpose::Unknown) {
614 BUG() << "Connection purpose cannot change from" << int(d->purpose) << "to InboundRequest";
615 return false;
616 }
617 break;
618 default:
619 BUG() << "Purpose type" << int(value) << "is not defined";
620 return false;
621 }
622
623 Purpose old = d->purpose;
624 d->purpose = value;
625 emit purposeChanged(d->purpose, old);
626 return true;
627 }
628
hasAuthenticated(AuthenticationType type) const629 bool Connection::hasAuthenticated(AuthenticationType type) const
630 {
631 return d->authentication.contains(type);
632 }
633
hasAuthenticatedAs(AuthenticationType type,const QString & identity) const634 bool Connection::hasAuthenticatedAs(AuthenticationType type, const QString &identity) const
635 {
636 auto it = d->authentication.find(type);
637 if (!identity.isEmpty() && it != d->authentication.end())
638 return *it == identity;
639 return false;
640 }
641
authenticatedIdentity(AuthenticationType type) const642 QString Connection::authenticatedIdentity(AuthenticationType type) const
643 {
644 return d->authentication.value(type);
645 }
646
grantAuthentication(AuthenticationType type,const QString & identity)647 void Connection::grantAuthentication(AuthenticationType type, const QString &identity)
648 {
649 if (hasAuthenticated(type)) {
650 BUG() << "Tried to redundantly grant" << type << "authentication to connection";
651 return;
652 }
653
654 qDebug() << "Granting" << type << "authentication as" << identity << "to connection";
655
656 d->authentication.insert(type, identity);
657 emit authenticated(type, identity);
658 }
659
660