1 /***************************************************************************
2 * Copyright (C) 2005-2020 by the Quassel Project *
3 * devel@quassel-irc.org *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21 #include "serializers.h"
22
23 namespace {
24
25 template<typename T>
toVariant(QDataStream & stream,Quassel::Features features,QVariant & data)26 bool toVariant(QDataStream& stream, Quassel::Features features, QVariant& data)
27 {
28 T content;
29 if (!Serializers::deserialize(stream, features, content)) {
30 return false;
31 }
32 data = QVariant::fromValue(content);
33 return true;
34 }
35
36 } // anon
37
checkStreamValid(QDataStream & stream)38 bool checkStreamValid(QDataStream& stream)
39 {
40 if (stream.status() != QDataStream::Ok) {
41 qWarning() << "Peer sent corrupt data";
42 return false;
43 }
44
45 return true;
46 }
47
deserialize(QDataStream & stream,const Quassel::Features & features,QVariantList & data)48 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantList& data)
49 {
50 uint32_t size;
51 if (!deserialize(stream, features, size))
52 return false;
53 if (size > 4 * 1024 * 1024) {
54 qWarning() << "Peer sent too large QVariantList: " << size;
55 return false;
56 }
57 for (uint32_t i = 0; i < size; i++) {
58 QVariant element;
59 if (!deserialize(stream, features, element))
60 return false;
61 data << element;
62 }
63 return checkStreamValid(stream);
64 }
65
deserialize(QDataStream & stream,const Quassel::Features & features,QVariantMap & data)66 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariantMap& data)
67 {
68 uint32_t size;
69 if (!deserialize(stream, features, size))
70 return false;
71 if (size > 4 * 1024 * 1024) {
72 qWarning() << "Peer sent too large QVariantMap: " << size;
73 return false;
74 }
75 for (uint32_t i = 0; i < size; i++) {
76 QString key;
77 QVariant value;
78 if (!deserialize(stream, features, key))
79 return false;
80 if (!deserialize(stream, features, value))
81 return false;
82 data[key] = value;
83 }
84 return checkStreamValid(stream);
85 }
86
deserialize(QDataStream & stream,const Quassel::Features & features,QVariant & data)87 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data)
88 {
89 Types::VariantType type;
90 int8_t isNull;
91 if (!deserialize(stream, features, type))
92 return false;
93 if (!deserialize(stream, features, isNull))
94 return false;
95 if (type == Types::VariantType::UserType) {
96 QByteArray name;
97 if (!deserialize(stream, features, name))
98 return false;
99 while (name.length() > 0 && name.at(name.length() - 1) == 0)
100 name.chop(1);
101 if (!deserialize(stream, features, data, Types::fromName(name)))
102 return false;
103 }
104 else {
105 if (!deserialize(stream, features, data, type))
106 return false;
107 }
108 return checkStreamValid(stream);
109 }
110
deserialize(QDataStream & stream,const Quassel::Features & features,QVariant & data,Types::VariantType type)111 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::VariantType type)
112 {
113 switch (type) {
114 case Types::VariantType::Void:
115 return true;
116 case Types::VariantType::Bool:
117 return toVariant<bool>(stream, features, data);
118 case Types::VariantType::Int:
119 return toVariant<int32_t>(stream, features, data);
120 case Types::VariantType::UInt:
121 return toVariant<uint32_t>(stream, features, data);
122 case Types::VariantType::QChar:
123 return toVariant<QChar>(stream, features, data);
124 case Types::VariantType::QVariantMap:
125 return toVariant<QVariantMap>(stream, features, data);
126 case Types::VariantType::QVariantList:
127 return toVariant<QVariantList>(stream, features, data);
128 case Types::VariantType::QString:
129 return toVariant<QString>(stream, features, data);
130 case Types::VariantType::QStringList:
131 return toVariant<QStringList>(stream, features, data);
132 case Types::VariantType::QByteArray:
133 return toVariant<QByteArray>(stream, features, data);
134 case Types::VariantType::QDate:
135 return toVariant<QDate>(stream, features, data);
136 case Types::VariantType::QTime:
137 return toVariant<QTime>(stream, features, data);
138 case Types::VariantType::QDateTime:
139 return toVariant<QDateTime>(stream, features, data);
140 case Types::VariantType::Long:
141 return toVariant<qlonglong>(stream, features, data);
142 case Types::VariantType::Short:
143 return toVariant<int16_t>(stream, features, data);
144 case Types::VariantType::Char:
145 return toVariant<int8_t>(stream, features, data);
146 case Types::VariantType::ULong:
147 return toVariant<qulonglong>(stream, features, data);
148 case Types::VariantType::UShort:
149 return toVariant<uint16_t>(stream, features, data);
150 case Types::VariantType::UChar:
151 return toVariant<uint8_t>(stream, features, data);
152 case Types::VariantType::QVariant:
153 return toVariant<QVariant>(stream, features, data);
154 default:
155 qWarning() << "Usertype should have been caught earlier already";
156 return false;
157 }
158 }
159
deserialize(QDataStream & stream,const Quassel::Features & features,QVariant & data,Types::QuasselType type)160 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QVariant& data, Types::QuasselType type)
161 {
162 switch (type) {
163 case Types::QuasselType::BufferId:
164 return toVariant<BufferId>(stream, features, data);
165 case Types::QuasselType::BufferInfo:
166 return toVariant<BufferInfo>(stream, features, data);
167 case Types::QuasselType::Identity:
168 return toVariant<Identity>(stream, features, data);
169 case Types::QuasselType::IdentityId:
170 return toVariant<IdentityId>(stream, features, data);
171 case Types::QuasselType::Message:
172 return toVariant<Message>(stream, features, data);
173 case Types::QuasselType::MsgId:
174 return toVariant<MsgId>(stream, features, data);
175 case Types::QuasselType::NetworkId:
176 return toVariant<NetworkId>(stream, features, data);
177 case Types::QuasselType::NetworkInfo:
178 return toVariant<NetworkInfo>(stream, features, data);
179 case Types::QuasselType::Network_Server:
180 return toVariant<Network::Server>(stream, features, data);
181 case Types::QuasselType::PeerPtr:
182 return toVariant<PeerPtr>(stream, features, data);
183 default:
184 qWarning() << "Invalid QType";
185 return false;
186 }
187 }
188
deserialize(QDataStream & stream,const Quassel::Features & features,Types::VariantType & data)189 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Types::VariantType& data)
190 {
191 uint32_t raw;
192 if (!deserialize(stream, features, raw))
193 return false;
194 data = static_cast<Types::VariantType>(raw);
195 return checkStreamValid(stream);
196 }
197
deserialize(QDataStream & stream,const Quassel::Features & features,QStringList & data)198 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QStringList& data)
199 {
200 uint32_t size;
201 if (!deserialize(stream, features, size))
202 return false;
203 for (uint32_t i = 0; i < size; i++) {
204 QString element;
205 if (!deserialize(stream, features, element))
206 return false;
207 data << element;
208 }
209 return checkStreamValid(stream);
210 }
211
deserialize(QDataStream & stream,const Quassel::Features & features,Network::Server & server)212 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Network::Server& server)
213 {
214 Q_UNUSED(features);
215 QVariantMap serverMap;
216 if (!deserialize(stream, features, serverMap))
217 return false;
218 server.host = serverMap["Host"].toString();
219 server.port = serverMap["Port"].toUInt();
220 server.password = serverMap["Password"].toString();
221 server.useSsl = serverMap["UseSSL"].toBool();
222 server.sslVerify = serverMap["sslVerify"].toBool();
223 server.sslVersion = serverMap["sslVersion"].toInt();
224 server.useProxy = serverMap["UseProxy"].toBool();
225 server.proxyType = serverMap["ProxyType"].toInt();
226 server.proxyHost = serverMap["ProxyHost"].toString();
227 server.proxyPort = serverMap["ProxyPort"].toUInt();
228 server.proxyUser = serverMap["ProxyUser"].toString();
229 server.proxyPass = serverMap["ProxyPass"].toString();
230 return checkStreamValid(stream);
231 }
232
deserialize(QDataStream & stream,const Quassel::Features & features,Identity & data)233 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Identity& data)
234 {
235 Q_UNUSED(features);
236 QVariantMap raw;
237 if (!deserialize(stream, features, raw))
238 return false;
239 data.fromVariantMap(raw);
240 return checkStreamValid(stream);
241 }
242
deserialize(QDataStream & stream,const Quassel::Features & features,NetworkInfo & info)243 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkInfo& info)
244 {
245 Q_UNUSED(features);
246 QVariantMap i;
247 if (!deserialize(stream, features, i))
248 return false;
249 info.networkId = i["NetworkId"].value<NetworkId>();
250 info.networkName = i["NetworkName"].toString();
251 info.identity = i["Identity"].value<IdentityId>();
252 info.codecForServer = i["CodecForServer"].toByteArray();
253 info.codecForEncoding = i["CodecForEncoding"].toByteArray();
254 info.codecForDecoding = i["CodecForDecoding"].toByteArray();
255 info.serverList = fromVariantList<Network::Server>(i["ServerList"].toList());
256 info.useRandomServer = i["UseRandomServer"].toBool();
257 info.perform = i["Perform"].toStringList();
258 info.skipCaps = i["SkipCaps"].toStringList();
259 info.useAutoIdentify = i["UseAutoIdentify"].toBool();
260 info.autoIdentifyService = i["AutoIdentifyService"].toString();
261 info.autoIdentifyPassword = i["AutoIdentifyPassword"].toString();
262 info.useSasl = i["UseSasl"].toBool();
263 info.saslAccount = i["SaslAccount"].toString();
264 info.saslPassword = i["SaslPassword"].toString();
265 info.useAutoReconnect = i["UseAutoReconnect"].toBool();
266 info.autoReconnectInterval = i["AutoReconnectInterval"].toUInt();
267 info.autoReconnectRetries = i["AutoReconnectRetries"].toInt();
268 info.unlimitedReconnectRetries = i["UnlimitedReconnectRetries"].toBool();
269 info.rejoinChannels = i["RejoinChannels"].toBool();
270 // Custom rate limiting
271 info.useCustomMessageRate = i["UseCustomMessageRate"].toBool();
272 info.messageRateBurstSize = i["MessageRateBurstSize"].toUInt();
273 info.messageRateDelay = i["MessageRateDelay"].toUInt();
274 info.unlimitedMessageRate = i["UnlimitedMessageRate"].toBool();
275 return checkStreamValid(stream);
276 }
277
deserialize(QDataStream & stream,const Quassel::Features & features,PeerPtr & data)278 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, PeerPtr& data)
279 {
280 Q_UNUSED(features);
281 stream >> data;
282 return checkStreamValid(stream);
283 }
284
deserialize(QDataStream & stream,const Quassel::Features & features,QByteArray & data)285 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QByteArray& data)
286 {
287 Q_UNUSED(features);
288 data.clear();
289 uint32_t length;
290 if (!deserialize(stream, features, length))
291 return false;
292 // -1 - or 0xffffffff - is used for an empty byte array
293 if (length == 0xffffffff) {
294 return true;
295 }
296
297 // 64 MB should be enough
298 if (length > 64 * 1024 * 1024) {
299 qWarning() << "Peer sent too large QByteArray: " << length;
300 return false;
301 }
302
303 const uint32_t Step = 1024 * 1024;
304 uint32_t allocated = 0;
305 do {
306 int blockSize = std::min(Step, length - allocated);
307 data.resize(allocated + blockSize);
308 if (stream.readRawData(data.data() + allocated, blockSize) != blockSize) {
309 data.clear();
310 qWarning() << "BufferUnderFlow while reading QByteArray";
311 return false;
312 }
313 allocated += blockSize;
314 } while (allocated < length);
315 return checkStreamValid(stream);
316 }
317
deserialize(QDataStream & stream,const Quassel::Features & features,QString & data)318 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QString& data)
319 {
320 Q_UNUSED(features);
321 uint32_t bytes = 0;
322 // read size of string
323 if (!deserialize(stream, features, bytes))
324 return false;
325
326 // empty string
327 if (bytes == 0) {
328 return true;
329 }
330
331 // null string
332 if (bytes == 0xffffffff) {
333 data.clear();
334 return true;
335 }
336
337 // 64 MB should be enough
338 if (bytes > 64 * 1024 * 1024) {
339 qWarning() << "Peer sent too large QString: " << bytes;
340 return false;
341 }
342
343 if (bytes & 0x1) {
344 data.clear();
345 qWarning() << "Read corrupted data: UTF-6 String with odd length: " << bytes;
346 return false;
347 }
348 const uint32_t step = 1024 * 1024;
349 uint32_t length = bytes / 2;
350 uint32_t allocated = 0;
351 while (allocated < length) {
352 int blockSize = std::min(step, length - allocated);
353 data.resize(allocated + blockSize);
354 if (stream.readRawData(reinterpret_cast<char*>(data.data()) + allocated * 2, blockSize * 2) != blockSize * 2) {
355 data.clear();
356 qWarning() << "BufferUnderFlow while reading QString";
357 return false;
358 }
359 allocated += blockSize;
360 }
361 if ((stream.byteOrder() == QDataStream::BigEndian) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
362 auto* rawData = reinterpret_cast<uint16_t*>(data.data());
363 while (length--) {
364 *rawData = qbswap(*rawData);
365 ++rawData;
366 }
367 }
368 return checkStreamValid(stream);
369 }
370
deserialize(QDataStream & stream,const Quassel::Features & features,QChar & data)371 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QChar& data)
372 {
373 Q_UNUSED(features);
374 stream >> data;
375 return checkStreamValid(stream);
376 }
377
deserialize(QDataStream & stream,const Quassel::Features & features,QDate & data)378 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDate& data)
379 {
380 Q_UNUSED(features);
381 stream >> data;
382 return checkStreamValid(stream);
383 }
384
deserialize(QDataStream & stream,const Quassel::Features & features,QTime & data)385 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QTime& data)
386 {
387 Q_UNUSED(features);
388 stream >> data;
389 return checkStreamValid(stream);
390 }
391
deserialize(QDataStream & stream,const Quassel::Features & features,QDateTime & data)392 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, QDateTime& data)
393 {
394 Q_UNUSED(features);
395 stream >> data;
396 return checkStreamValid(stream);
397 }
398
deserialize(QDataStream & stream,const Quassel::Features & features,int32_t & data)399 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int32_t& data)
400 {
401 Q_UNUSED(features);
402 stream >> data;
403 return checkStreamValid(stream);
404 }
405
deserialize(QDataStream & stream,const Quassel::Features & features,uint32_t & data)406 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint32_t& data)
407 {
408 Q_UNUSED(features);
409 stream >> data;
410 return checkStreamValid(stream);
411 }
412
deserialize(QDataStream & stream,const Quassel::Features & features,int16_t & data)413 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int16_t& data)
414 {
415 Q_UNUSED(features);
416 stream >> data;
417 return checkStreamValid(stream);
418 }
419
deserialize(QDataStream & stream,const Quassel::Features & features,uint16_t & data)420 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint16_t& data)
421 {
422 Q_UNUSED(features);
423 stream >> data;
424 return checkStreamValid(stream);
425 }
426
deserialize(QDataStream & stream,const Quassel::Features & features,int8_t & data)427 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, int8_t& data)
428 {
429 Q_UNUSED(features);
430 stream >> data;
431 return checkStreamValid(stream);
432 }
433
deserialize(QDataStream & stream,const Quassel::Features & features,uint8_t & data)434 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, uint8_t& data)
435 {
436 Q_UNUSED(features);
437 stream >> data;
438 return checkStreamValid(stream);
439 }
440
deserialize(QDataStream & stream,const Quassel::Features & features,qlonglong & data)441 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qlonglong& data)
442 {
443 Q_UNUSED(features);
444 stream >> data;
445 return checkStreamValid(stream);
446 }
447
deserialize(QDataStream & stream,const Quassel::Features & features,qulonglong & data)448 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, qulonglong& data)
449 {
450 Q_UNUSED(features);
451 stream >> data;
452 return checkStreamValid(stream);
453 }
454
deserialize(QDataStream & stream,const Quassel::Features & features,bool & data)455 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, bool& data)
456 {
457 Q_UNUSED(features);
458 stream >> data;
459 return checkStreamValid(stream);
460 }
461
deserialize(QDataStream & stream,const Quassel::Features & features,BufferInfo & data)462 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferInfo& data)
463 {
464 Q_UNUSED(features);
465 stream >> data;
466 return checkStreamValid(stream);
467 }
468
deserialize(QDataStream & stream,const Quassel::Features & features,Message & data)469 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, Message& data)
470 {
471 Q_UNUSED(features);
472 stream >> data;
473 return checkStreamValid(stream);
474 }
475
deserialize(QDataStream & stream,const Quassel::Features & features,NetworkId & data)476 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, NetworkId& data)
477 {
478 Q_UNUSED(features);
479 stream >> data;
480 return checkStreamValid(stream);
481 }
482
deserialize(QDataStream & stream,const Quassel::Features & features,IdentityId & data)483 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, IdentityId& data)
484 {
485 Q_UNUSED(features);
486 stream >> data;
487 return checkStreamValid(stream);
488 }
489
deserialize(QDataStream & stream,const Quassel::Features & features,BufferId & data)490 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, BufferId& data)
491 {
492 Q_UNUSED(features);
493 stream >> data;
494 return checkStreamValid(stream);
495 }
496
deserialize(QDataStream & stream,const Quassel::Features & features,MsgId & data)497 bool Serializers::deserialize(QDataStream& stream, const Quassel::Features& features, MsgId& data)
498 {
499 Q_UNUSED(features);
500 stream >> data;
501 return checkStreamValid(stream);
502 }
503
variantType(Serializers::Types::QuasselType type)504 Serializers::Types::VariantType Serializers::Types::variantType(Serializers::Types::QuasselType type)
505 {
506 switch (type) {
507 case QuasselType::BufferId:
508 return VariantType::UserType;
509 case QuasselType::BufferInfo:
510 return VariantType::UserType;
511 case QuasselType::Identity:
512 return VariantType::UserType;
513 case QuasselType::IdentityId:
514 return VariantType::UserType;
515 case QuasselType::Message:
516 return VariantType::UserType;
517 case QuasselType::MsgId:
518 return VariantType::UserType;
519 case QuasselType::NetworkId:
520 return VariantType::UserType;
521 case QuasselType::NetworkInfo:
522 return VariantType::UserType;
523 case QuasselType::Network_Server:
524 return VariantType::UserType;
525 case QuasselType::PeerPtr:
526 return VariantType::Long;
527 default:
528 return VariantType::UserType;
529 }
530 }
531
toName(Serializers::Types::QuasselType type)532 QString Serializers::Types::toName(Serializers::Types::QuasselType type)
533 {
534 switch (type) {
535 case QuasselType::BufferId:
536 return QString("BufferId");
537 case QuasselType::BufferInfo:
538 return QString("BufferInfo");
539 case QuasselType::Identity:
540 return QString("Identity");
541 case QuasselType::IdentityId:
542 return QString("IdentityId");
543 case QuasselType::Message:
544 return QString("Message");
545 case QuasselType::MsgId:
546 return QString("MsgId");
547 case QuasselType::NetworkId:
548 return QString("NetworkId");
549 case QuasselType::NetworkInfo:
550 return QString("NetworkInfo");
551 case QuasselType::Network_Server:
552 return QString("Network::Server");
553 case QuasselType::PeerPtr:
554 return QString("PeerPtr");
555 default:
556 return QString("Invalid Type");
557 }
558 }
559
fromName(::QByteArray & name)560 Serializers::Types::QuasselType Serializers::Types::fromName(::QByteArray& name)
561 {
562 if (qstrcmp(name, "BufferId") == 0)
563 return QuasselType::BufferId;
564 else if (qstrcmp(name, "BufferInfo") == 0)
565 return QuasselType::BufferInfo;
566 else if (qstrcmp(name, "Identity") == 0)
567 return QuasselType::Identity;
568 else if (qstrcmp(name, "IdentityId") == 0)
569 return QuasselType::IdentityId;
570 else if (qstrcmp(name, "Message") == 0)
571 return QuasselType::Message;
572 else if (qstrcmp(name, "MsgId") == 0)
573 return QuasselType::MsgId;
574 else if (qstrcmp(name, "NetworkId") == 0)
575 return QuasselType::NetworkId;
576 else if (qstrcmp(name, "NetworkInfo") == 0)
577 return QuasselType::NetworkInfo;
578 else if (qstrcmp(name, "Network::Server") == 0)
579 return QuasselType::Network_Server;
580 else if (qstrcmp(name, "PeerPtr") == 0)
581 return QuasselType::PeerPtr;
582 else {
583 qWarning() << "Type name is not valid: " << name;
584 return QuasselType::Invalid;
585 }
586 }
587