1 /*
2 * This file is part of Licq, an instant messaging client for UNIX.
3 * Copyright (C) 1998-2013 Licq developers <licq-dev@googlegroups.com>
4 *
5 * Licq 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) any later version.
9 *
10 * Licq 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 Licq; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "icq.h"
21
22 #include <ctime>
23 #include <sstream>
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <cerrno>
30 #include <fcntl.h>
31 #include <ctype.h>
32 #include <langinfo.h>
33
34 #include <licq/byteorder.h>
35 #include <licq/contactlist/usermanager.h>
36 #include <licq/daemon.h>
37 #include <licq/event.h>
38 #include <licq/gpghelper.h>
39 #include <licq/icq/chat.h>
40 #include <licq/oneventmanager.h>
41 #include <licq/plugin/pluginmanager.h>
42 #include <licq/pluginsignal.h>
43 #include <licq/protocolmanager.h>
44 #include <licq/protocolsignal.h>
45 #include <licq/statistics.h>
46 #include <licq/translator.h>
47 #include <licq/userevents.h>
48 #include <licq/logging/log.h>
49 #include <licq/version.h>
50
51 #include "filetransfer.h"
52 #include "gettext.h"
53 #include "oscarservice.h"
54 #include "owner.h"
55 #include "packet-srv.h"
56 #include "packet-tcp.h"
57 #include "protocolsignal.h"
58 #include "socket.h"
59 #include "user.h"
60
61 using namespace LicqIcq;
62 using Licq::Daemon;
63 using Licq::IcqPluginActive;
64 using Licq::IcqPluginBusy;
65 using Licq::IcqPluginInactive;
66 using Licq::Log;
67 using Licq::OnEventData;
68 using Licq::StringList;
69 using Licq::gDaemon;
70 using Licq::gLog;
71 using Licq::gOnEventManager;
72 using Licq::gTranslator;
73 using std::list;
74 using std::string;
75
icqSendMessage(const Licq::ProtoSendMessageSignal * ps)76 void IcqProtocol::icqSendMessage(const Licq::ProtoSendMessageSignal* ps)
77 {
78 const Licq::UserId& userId(ps->userId());
79 unsigned flags(ps->flags());
80 const Licq::Color* pColor(ps->color());
81 const string accountId = userId.accountId();
82 string m = gTranslator.returnToDos(ps->message());
83
84 bool bUserOffline = true;
85 Licq::EventMsg* e = NULL;
86
87 unsigned long f = Licq::EventMsg::FlagLicqVerMask | Licq::EventMsg::FlagSender;
88 bool useGpg = false;
89 {
90 Licq::UserReadGuard u(userId);
91 if (u.isLocked())
92 {
93 bUserOffline = !u->isOnline();
94 if (!bUserOffline)
95 useGpg = u->UseGPG();
96 }
97 }
98 if (useGpg)
99 {
100 char* cipher = Licq::gGpgHelper.Encrypt(m.c_str(), userId);
101 if (cipher != NULL)
102 {
103 m = cipher;
104 free(cipher);
105 f |= Licq::UserEvent::FlagEncrypted;
106 }
107 else
108 useGpg = false;
109 }
110
111 unsigned short nLevel = ICQ_TCPxMSG_NORMAL;
112 if (flags & Licq::ProtocolSignal::SendUrgent)
113 {
114 f |= Licq::UserEvent::FlagUrgent;
115 nLevel = ICQ_TCPxMSG_URGENT;
116 }
117 else if (flags & Licq::ProtocolSignal::SendToList)
118 nLevel = ICQ_TCPxMSG_LIST;
119 if (flags & Licq::ProtocolSignal::SendToMultiple)
120 f |= Licq::UserEvent::FlagMultiRec;
121
122 if ((flags & Licq::ProtocolSignal::SendDirect) == 0)
123 {
124 unsigned short nCharset = CHARSET_ASCII;
125
126 if (!useGpg && !gTranslator.isAscii(m))
127 {
128 nCharset = CHARSET_UNICODE;
129 m = gTranslator.fromUtf8(m, "UCS-2BE");
130 }
131
132 e = new Licq::EventMsg(ps->message(), Licq::EventMsg::TimeNow, f);
133 unsigned short nMaxSize = bUserOffline ? Licq::IcqProtocol::MaxOfflineMessageSize : Licq::IcqProtocol::MaxMessageSize;
134 if (m.size() > nMaxSize)
135 {
136 gLog.warning(tr("Truncating message to %d characters to send through server."), nMaxSize);
137 m.resize(nMaxSize);
138 }
139 icqSendThroughServer(ps->callerThread(), ps->eventId(), userId,
140 ICQ_CMDxSUB_MSG | ((flags & Licq::ProtocolSignal::SendToMultiple) ? ICQ_CMDxSUB_FxMULTIREC : 0),
141 m, e, nCharset);
142 }
143
144 UserWriteGuard u(userId);
145
146 if (flags & Licq::ProtocolSignal::SendDirect)
147 {
148 f |= Licq::UserEvent::FlagDirect;
149
150 if (!u.isLocked())
151 return;
152 if (u->Secure())
153 f |= Licq::UserEvent::FlagEncrypted;
154 e = new Licq::EventMsg(ps->message(), Licq::EventMsg::TimeNow, f);
155 if (pColor != NULL) e->SetColor(pColor);
156 CPT_Message* p = new CPT_Message(m, nLevel, flags & Licq::ProtocolSignal::SendToMultiple,
157 pColor, *u, !gTranslator.isAscii(m));
158 gLog.info(tr("Sending %smessage to %s (#%d)."),
159 (flags & Licq::ProtocolSignal::SendUrgent) ? tr("urgent ") : "",
160 u->getAlias().c_str(), -p->Sequence());
161 SendExpectEvent_Client(ps, *u, p, e);
162 }
163
164 if (u.isLocked())
165 {
166 u->SetSendServer((flags & Licq::ProtocolSignal::SendDirect) == 0);
167 u->SetSendLevel(nLevel);
168 }
169
170 if (pColor != NULL)
171 Licq::Color::setDefaultColors(pColor);
172 }
173
icqFetchAutoResponse(const Licq::ProtocolSignal * ps)174 void IcqProtocol::icqFetchAutoResponse(const Licq::ProtocolSignal* ps)
175 {
176 const Licq::UserId& userId(ps->userId());
177 if (userId.isOwner())
178 return;
179
180 if (isalpha(userId.accountId()[0]))
181 {
182 icqFetchAutoResponseServer(ps);
183 return;
184 }
185
186 UserWriteGuard u(userId);
187
188 if (u->normalSocketDesc() <= 0 && u->Version() > 6)
189 {
190 // Generic read, gets changed in constructor
191 CSrvPacketTcp *s = new CPU_AdvancedMessage(*u, ICQ_CMDxTCP_READxAWAYxMSG, 0, false, 0, 0, 0);
192 gLog.info(tr("Requesting auto response from %s."), u->getAlias().c_str());
193 SendExpectEvent_Server(ps, userId, s, NULL);
194 }
195 else
196 {
197 CPT_ReadAwayMessage *p = new CPT_ReadAwayMessage(*u);
198 gLog.info(tr("Requesting auto response from %s (#%d)."),
199 u->getAlias().c_str(), -p->Sequence());
200 SendExpectEvent_Client(ps, *u, p, NULL);
201 }
202 }
203
icqSendUrl(const Licq::ProtoSendUrlSignal * ps)204 void IcqProtocol::icqSendUrl(const Licq::ProtoSendUrlSignal* ps)
205 {
206 if (ps->userId().isOwner())
207 return;
208
209 string userEncoding = getUserEncoding(ps->userId());
210 const Licq::UserId& userId(ps->userId());
211 unsigned flags(ps->flags());
212 const Licq::Color* pColor(ps->color());
213 const string accountId = userId.accountId();
214
215 // make the URL info string
216 string m = gTranslator.fromUtf8(gTranslator.returnToDos(ps->message()), userEncoding);
217 int n = ps->url().size() + m.size() + 2;
218 if ((flags & Licq::ProtocolSignal::SendDirect) == 0 && n > Licq::IcqProtocol::MaxMessageSize)
219 m.erase(Licq::IcqProtocol::MaxMessageSize - ps->url().size() - 2);
220 m += '\xFE';
221 m += gTranslator.fromUtf8(ps->url(), userEncoding);
222
223 unsigned long f = Licq::EventUrl::FlagLicqVerMask | Licq::EventUrl::FlagSender;
224 unsigned short nLevel = ICQ_TCPxMSG_NORMAL;
225 if (flags & Licq::ProtocolSignal::SendDirect)
226 f |= Licq::UserEvent::FlagDirect;
227 if (flags & Licq::ProtocolSignal::SendUrgent)
228 {
229 f |= Licq::UserEvent::FlagUrgent;
230 nLevel = ICQ_TCPxMSG_URGENT;
231 }
232 else if (flags & Licq::ProtocolSignal::SendToList)
233 {
234 nLevel = ICQ_TCPxMSG_LIST;
235 }
236 if (flags & Licq::ProtocolSignal::SendToMultiple)
237 f |= Licq::UserEvent::FlagMultiRec;
238
239 if ((flags & Licq::ProtocolSignal::SendDirect) == 0)
240 {
241 unsigned short nCharset = 0;
242 {
243 Licq::UserReadGuard u(userId);
244 if (u.isLocked() && !u->userEncoding().empty())
245 nCharset = 3;
246 }
247
248 Licq::EventUrl* e = new Licq::EventUrl(ps->url(), ps->message(), Licq::EventUrl::TimeNow, f);
249 icqSendThroughServer(ps->callerThread(), ps->eventId(), userId,
250 ICQ_CMDxSUB_URL | ((flags & Licq::ProtocolSignal::SendToMultiple) ? ICQ_CMDxSUB_FxMULTIREC : 0), m, e, nCharset);
251 }
252
253 UserWriteGuard u(userId);
254
255 if (flags & Licq::ProtocolSignal::SendDirect)
256 {
257 if (!u.isLocked())
258 return;
259 if (u->Secure())
260 f |= Licq::UserEvent::FlagEncrypted;
261 Licq::EventUrl* e = new Licq::EventUrl(ps->url(), ps->message(), Licq::EventUrl::TimeNow, f);
262 if (pColor != NULL) e->SetColor(pColor);
263 CPT_Url* p = new CPT_Url(m, nLevel, flags & Licq::ProtocolSignal::SendToMultiple, pColor, *u);
264 gLog.info(tr("Sending %sURL to %s (#%d)."),
265 (flags & Licq::ProtocolSignal::SendUrgent) ? tr("urgent ") : "",
266 u->getAlias().c_str(), -p->Sequence());
267 SendExpectEvent_Client(ps, *u, p, e);
268 }
269 if (u.isLocked())
270 {
271 u->SetSendServer((flags & Licq::ProtocolSignal::SendDirect) == 0);
272 u->SetSendLevel(nLevel);
273 }
274
275 if (pColor != NULL)
276 Licq::Color::setDefaultColors(pColor);
277 }
278
icqFileTransfer(const Licq::ProtoSendFileSignal * ps)279 void IcqProtocol::icqFileTransfer(const Licq::ProtoSendFileSignal* ps)
280 {
281 const Licq::UserId& userId(ps->userId());
282 unsigned flags(ps->flags());
283
284 if (userId.isOwner())
285 return;
286
287 UserWriteGuard u(userId);
288 if (!u.isLocked())
289 return;
290
291 string dosDesc = gTranslator.fromUtf8(gTranslator.returnToDos(ps->message()), u->userEncoding());
292
293 unsigned short nLevel;
294
295 if ((flags & Licq::ProtocolSignal::SendDirect) == 0)
296 {
297 unsigned long f = LICQ_VERSION | Licq::EventFile::FlagSender;
298 //flags through server are a little different
299 if (flags & Licq::ProtocolSignal::SendUrgent)
300 {
301 f |= Licq::UserEvent::FlagUrgent;
302 nLevel = ICQ_TCPxMSG_URGENT2;
303 }
304 else if (flags & Licq::ProtocolSignal::SendToList)
305 nLevel = ICQ_TCPxMSG_LIST2;
306 else
307 nLevel = ICQ_TCPxMSG_NORMAL2;
308
309 CPU_FileTransfer* p = new CPU_FileTransfer(*u, ps->files(), ps->filename(),
310 dosDesc, nLevel, (u->Version() > 7));
311
312 if (!p->IsValid())
313 {
314 delete p;
315 }
316 else
317 {
318 Licq::EventFile* e = new Licq::EventFile(ps->filename(), ps->message(), p->GetFileSize(),
319 ps->files(), p->Sequence(), Licq::EventFile::TimeNow, f);
320 gLog.info(tr("Sending file transfer to %s (#%d)."),
321 u->getAlias().c_str(), -p->Sequence());
322
323 SendExpectEvent_Server(userId, p, e);
324 }
325 }
326 else
327 {
328 unsigned long f = Licq::EventFile::FlagLicqVerMask | Licq::EventFile::FlagDirect | Licq::EventFile::FlagSender;
329
330 if (flags & Licq::ProtocolSignal::SendUrgent)
331 {
332 f |= Licq::UserEvent::FlagUrgent;
333 nLevel = ICQ_TCPxMSG_URGENT;
334 }
335 else if (flags & Licq::ProtocolSignal::SendToList)
336 nLevel = ICQ_TCPxMSG_LIST;
337 else
338 nLevel = ICQ_TCPxMSG_NORMAL;
339 if (u->Secure())
340 f |= Licq::UserEvent::FlagEncrypted;
341
342 CPT_FileTransfer* p = new CPT_FileTransfer(ps->files(), ps->filename(), dosDesc, nLevel, *u);
343
344 if (!p->IsValid())
345 {
346 delete p;
347 }
348 else
349 {
350 Licq::EventFile* e = new Licq::EventFile(ps->filename(), ps->message(), p->GetFileSize(),
351 ps->files(), p->Sequence(), Licq::EventFile::TimeNow, f);
352 gLog.info(tr("Sending %sfile transfer to %s (#%d)."),
353 (flags & Licq::ProtocolSignal::SendUrgent) ? tr("urgent ") : "",
354 u->getAlias().c_str(), -p->Sequence());
355
356 SendExpectEvent_Client(ps, *u, p, e);
357 }
358 }
359
360 u->SetSendServer((flags & Licq::ProtocolSignal::SendDirect) == 0);
361 u->SetSendLevel(nLevel);
362 }
363
364 //-----CICQDaemon::sendContactList-------------------------------------------
icqSendContactList(const ProtoSendContactsSignal * ps)365 void IcqProtocol::icqSendContactList(const ProtoSendContactsSignal* ps)
366 {
367 const Licq::UserId& userId(ps->userId());
368 const StringList& users(ps->users());
369 unsigned flags = ps->flags();
370 const Licq::Color* pColor(ps->color());
371
372 if (userId.isOwner())
373 return;
374
375 string userEncoding = getUserEncoding(userId);
376
377 std::stringstream buf;
378 buf << users.size() << '\xFE';
379 Licq::EventContactList::ContactList vc;
380
381 StringList::const_iterator iter;
382 for (iter = users.begin(); iter != users.end(); ++iter)
383 {
384 Licq::UserId uId(myOwnerId, *iter);
385 Licq::UserReadGuard u(uId);
386 string alias = (u.isLocked() ? u->getAlias() : "");
387 buf << *iter << '\xFE';
388 buf << gTranslator.fromUtf8(alias, userEncoding) << '\xFE';
389 vc.push_back(new Licq::EventContactList::Contact(uId, alias));
390 }
391 string m = buf.str();
392
393 if ((flags & Licq::ProtocolSignal::SendDirect) == 0 && (int)m.size() > Licq::IcqProtocol::MaxMessageSize)
394 {
395 gLog.warning(tr("Contact list too large to send through server."));
396 return;
397 }
398
399 unsigned long f = Licq::EventContactList::FlagLicqVerMask | Licq::EventContactList::FlagSender;
400 unsigned short nLevel = ICQ_TCPxMSG_NORMAL;
401 if (flags & Licq::ProtocolSignal::SendDirect)
402 f |= Licq::UserEvent::FlagDirect;
403 if (flags & Licq::ProtocolSignal::SendUrgent)
404 {
405 f |= Licq::UserEvent::FlagUrgent;
406 nLevel = ICQ_TCPxMSG_URGENT;
407 }
408 else if (flags & Licq::ProtocolSignal::SendToList)
409 nLevel = ICQ_TCPxMSG_LIST;
410 if (flags & Licq::ProtocolSignal::SendToMultiple)
411 f |= Licq::UserEvent::FlagMultiRec;
412
413 if ((flags & Licq::ProtocolSignal::SendDirect) == 0) // send offline
414 {
415 Licq::EventContactList* e = new Licq::EventContactList(vc, false, Licq::EventContactList::TimeNow, f);
416 icqSendThroughServer(ps->callerThread(), ps->eventId(), userId,
417 ICQ_CMDxSUB_CONTACTxLIST | ((flags & Licq::ProtocolSignal::SendToMultiple) ? ICQ_CMDxSUB_FxMULTIREC : 0),
418 m, e);
419 }
420
421 UserWriteGuard u(userId);
422 if (flags & Licq::ProtocolSignal::SendDirect)
423 {
424 if (!u.isLocked())
425 return;
426 if (u->Secure())
427 f |= Licq::UserEvent::FlagEncrypted;
428 Licq::EventContactList* e = new Licq::EventContactList(vc, false, Licq::EventContactList::TimeNow, f);
429 if (pColor != NULL) e->SetColor(pColor);
430 CPT_ContactList *p = new CPT_ContactList(m, nLevel, flags & Licq::ProtocolSignal::SendToMultiple, pColor, *u);
431 gLog.info(tr("Sending %scontact list to %s (#%d)."),
432 (flags & Licq::ProtocolSignal::SendUrgent) ? tr("urgent ") : "",
433 u->getAlias().c_str(), -p->Sequence());
434 SendExpectEvent_Client(ps, *u, p, e);
435 }
436 if (u.isLocked())
437 {
438 u->SetSendServer((flags & Licq::ProtocolSignal::SendDirect) == 0);
439 u->SetSendLevel(nLevel);
440 }
441
442 if (pColor != NULL)
443 Licq::Color::setDefaultColors(pColor);
444 }
445
icqRequestPluginInfo(const Licq::UserId & userId,Licq::IcqProtocol::PluginType type,bool bServer,const Licq::ProtocolSignal * ps)446 void IcqProtocol::icqRequestPluginInfo(const Licq::UserId& userId, Licq::IcqProtocol::PluginType type,
447 bool bServer, const Licq::ProtocolSignal* ps)
448 {
449 if (userId.isOwner())
450 return;
451
452 UserWriteGuard u(userId);
453 if (!u.isLocked())
454 return;
455
456 switch (type)
457 {
458 case Licq::IcqProtocol::PluginInfoList:
459 gLog.info(tr("Requesting info plugin list from %s%s."),
460 u->getAlias().c_str(), bServer ? " through server" : "");
461 icqRequestInfoPlugin(*u, bServer, PLUGIN_QUERYxINFO, ps);
462
463 case Licq::IcqProtocol::PluginPhoneBook:
464 bServer = (u->infoSocketDesc() < 0);
465 gLog.info(tr("Requesting Phone Book from %s%s."),
466 u->getAlias().c_str(), bServer ? " through server" : "");
467 icqRequestInfoPlugin(*u, bServer, PLUGIN_PHONExBOOK, ps);
468
469 case Licq::IcqProtocol::PluginPicture:
470 bServer = (u->infoSocketDesc() < 0);
471 gLog.info(tr("Requesting Picture from %s%s."),
472 u->getAlias().c_str(), bServer ? " through server" : "");
473 icqRequestInfoPlugin(*u, bServer, PLUGIN_PICTURE, ps);
474
475 case Licq::IcqProtocol::PluginStatusList:
476 gLog.info(tr("Requesting status plugin list from %s%s."),
477 u->getAlias().c_str(), bServer ? " through server" : "");
478 icqRequestStatusPlugin(*u, bServer, PLUGIN_QUERYxSTATUS, ps);
479
480 case Licq::IcqProtocol::PluginSharedFiles:
481 gLog.info(tr("Requesting file server status from %s%s."),
482 u->getAlias().c_str(), bServer ? " through server" : "");
483 icqRequestStatusPlugin(*u, bServer, PLUGIN_FILExSERVER, ps);
484
485 case Licq::IcqProtocol::PluginPhoneFollowMe:
486 gLog.info(tr("Requesting Phone \"Follow Me\" status from %s%s."),
487 u->getAlias().c_str(), bServer ? " through server" : "");
488 icqRequestStatusPlugin(*u, bServer, PLUGIN_FOLLOWxME, ps);
489
490 case Licq::IcqProtocol::PluginIcqPhone:
491 gLog.info(tr("Requesting ICQphone status from %s%s."),
492 u->getAlias().c_str(), bServer ? " through server" : "");
493 icqRequestStatusPlugin(*u, bServer, PLUGIN_FILExSERVER, ps);
494 };
495 }
496
497 //-----CICQDaemon::sendInfoPluginReq--------------------------------------------
icqRequestInfoPlugin(User * u,bool bServer,const uint8_t * GUID,const Licq::ProtocolSignal * ps)498 void IcqProtocol::icqRequestInfoPlugin(User* u, bool bServer,
499 const uint8_t* GUID, const Licq::ProtocolSignal* ps)
500 {
501 if (bServer)
502 {
503 CPU_InfoPluginReq *p = new CPU_InfoPluginReq(u, GUID, 0);
504 SendExpectEvent_Server(ps, u->id(), p, NULL);
505 }
506 else
507 {
508 CPT_InfoPluginReq *p = new CPT_InfoPluginReq(u, GUID, 0);
509 SendExpectEvent_Client(ps, u, p, NULL);
510 }
511 }
512
513 //-----CICQDaemon::sendPictureReq-----------------------------------------------
icqRequestPicture(const Licq::ProtocolSignal * ps)514 void IcqProtocol::icqRequestPicture(const Licq::ProtocolSignal* ps)
515 {
516 bool useBart;
517 {
518 OwnerReadGuard o(myOwnerId);
519 useBart = o->useBart();
520 }
521
522 size_t iconHashSize;
523 {
524 UserReadGuard user(ps->userId());
525 if (!user.isLocked())
526 return;
527
528 iconHashSize = user->buddyIconHash().size();
529 }
530
531 if (useBart && iconHashSize > 0)
532 return m_xBARTService->SendEvent(ps->callerThread(), ps->eventId(), ps->userId(),
533 ICQ_SNACxBART_DOWNLOADxREQUEST, true);
534
535 icqRequestPluginInfo(ps->userId(), Licq::IcqProtocol::PluginPicture, false, ps);
536 }
537
538 //-----CICQDaemon::sendStatusPluginReq------------------------------------------
icqRequestStatusPlugin(User * u,bool bServer,const uint8_t * GUID,const Licq::ProtocolSignal * ps)539 void IcqProtocol::icqRequestStatusPlugin(User* u, bool bServer,
540 const uint8_t* GUID, const Licq::ProtocolSignal* ps)
541 {
542 if (bServer)
543 {
544 CPU_StatusPluginReq *p = new CPU_StatusPluginReq(u, GUID, 0);
545 SendExpectEvent_Server(ps, u->id(), p, NULL);
546 }
547 else
548 {
549 CPT_StatusPluginReq *p = new CPT_StatusPluginReq(u, GUID, 0);
550 SendExpectEvent_Client(ps, u, p, NULL);
551 }
552 }
553
icqFileTransferCancel(const Licq::UserId & userId,unsigned short nSequence)554 void IcqProtocol::icqFileTransferCancel(const Licq::UserId& userId, unsigned short nSequence)
555 {
556 // add to history ??
557 UserWriteGuard u(userId);
558 if (!u.isLocked())
559 return;
560 gLog.info(tr("Cancelling file transfer to %s (#%d)."), u->getAlias().c_str(), -nSequence);
561 CPT_CancelFile p(nSequence, *u);
562 AckTCP(p, u->normalSocketDesc());
563 }
564
icqFileTransferAccept(const Licq::ProtoSendEventReplySignal * ps)565 void IcqProtocol::icqFileTransferAccept(const Licq::ProtoSendEventReplySignal* ps)
566 {
567 // basically a fancy tcp ack packet which is sent late
568 UserWriteGuard u(ps->userId());
569 if (!u.isLocked())
570 return;
571 gLog.info(tr("Accepting file transfer from %s (#%lu)."), u->getAlias().c_str(), ps->eventId());
572 if (ps->direct())
573 {
574 CPT_AckFileAccept p(ps->port(), ps->eventId(), *u);
575 AckTCP(p, u->normalSocketDesc());
576 }
577 else
578 {
579 unsigned long msgId[2] = { ps->flag1(), ps->flag2() };
580 CPU_AckFileAccept *p = new CPU_AckFileAccept(*u, msgId, ps->eventId(), ps->port(),
581 gTranslator.fromUtf8(gTranslator.returnToDos(ps->message()), u->userEncoding()),
582 ps->filename(), ps->filesize());
583 SendEvent_Server(p);
584 }
585 }
586
icqFileTransferRefuse(const Licq::ProtoSendEventReplySignal * ps)587 void IcqProtocol::icqFileTransferRefuse(const Licq::ProtoSendEventReplySignal* ps)
588 {
589 // add to history ??
590 UserWriteGuard u(ps->userId());
591 if (!u.isLocked())
592 return;
593 string reasonDos = gTranslator.fromUtf8(gTranslator.returnToDos(ps->message()), u->userEncoding());
594 gLog.info(tr("Refusing file transfer from %s (#%lu)."), u->getAlias().c_str(), ps->eventId());
595
596 if (ps->direct())
597 {
598 CPT_AckFileRefuse p(reasonDos, ps->eventId(), *u);
599 AckTCP(p, u->normalSocketDesc());
600 }
601 else
602 {
603 unsigned long msgId[2] = { ps->flag1(), ps->flag2() };
604 CPU_AckFileRefuse *p = new CPU_AckFileRefuse(*u, msgId, ps->eventId(), reasonDos);
605 SendEvent_Server(p);
606 }
607 }
608
icqChatRequest(const ProtoChatRequestSignal * ps)609 void IcqProtocol::icqChatRequest(const ProtoChatRequestSignal* ps)
610 {
611 const Licq::UserId& userId(ps->userId());
612 const string& reason(ps->reason());
613 unsigned flags = ps->flags();
614 const string& chatUsers(ps->chatUsers());
615 unsigned short nPort = ps->port();
616 if (userId.isOwner())
617 return;
618
619 UserWriteGuard u(userId);
620 if (!u.isLocked())
621 return;
622 string reasonDos = gTranslator.toUtf8(gTranslator.returnToDos(reason), u->userEncoding());
623
624 unsigned long f;
625 unsigned short nLevel;
626 if ((flags & Licq::ProtocolSignal::SendDirect) == 0)
627 {
628 f = Licq::EventChat::FlagLicqVerMask | Licq::EventChat::FlagSender;
629
630 //flags through server are a little different
631 if (flags & Licq::ProtocolSignal::SendUrgent)
632 {
633 f |= Licq::UserEvent::FlagUrgent;
634 nLevel = ICQ_TCPxMSG_URGENT2;
635 }
636 else if (flags & Licq::ProtocolSignal::SendToList)
637 nLevel = ICQ_TCPxMSG_LIST2;
638 else
639 nLevel = ICQ_TCPxMSG_NORMAL2;
640
641 CPU_ChatRequest *p = new CPU_ChatRequest(reasonDos,
642 chatUsers, nPort, nLevel, *u, (u->Version() > 7));
643
644 Licq::EventChat* e = new Licq::EventChat(reason, chatUsers, nPort, p->Sequence(),
645 Licq::EventChat::TimeNow, f);
646 gLog.info(tr("Sending chat request to %s (#%d)."), u->getAlias().c_str(), -p->Sequence());
647
648 SendExpectEvent_Server(ps, u->id(), p, e);
649 }
650 else
651 {
652 f = Licq::EventChat::FlagLicqVerMask | Licq::EventChat::FlagDirect | Licq::EventChat::FlagSender;
653 nLevel = ICQ_TCPxMSG_NORMAL;
654 if (flags & Licq::ProtocolSignal::SendUrgent)
655 {
656 f |= Licq::UserEvent::FlagUrgent;
657 nLevel = ICQ_TCPxMSG_URGENT;
658 }
659 else if (flags & Licq::ProtocolSignal::SendToList)
660 nLevel = ICQ_TCPxMSG_LIST;
661 if (u->Secure())
662 f |= Licq::UserEvent::FlagEncrypted;
663
664 CPT_ChatRequest* p = new CPT_ChatRequest(reasonDos, chatUsers, nPort,
665 nLevel, *u, (u->Version() > 7));
666 Licq::EventChat* e = new Licq::EventChat(reason, chatUsers, nPort, p->Sequence(),
667 Licq::UserEvent::TimeNow, f);
668 gLog.info(tr("Sending %schat request to %s (#%d)."),
669 (flags & Licq::ProtocolSignal::SendUrgent) ? tr("urgent ") : "",
670 u->getAlias().c_str(), -p->Sequence());
671 SendExpectEvent_Client(ps, *u, p, e);
672 }
673
674 u->SetSendServer((flags & Licq::ProtocolSignal::SendDirect) == 0);
675 u->SetSendLevel(nLevel);
676 }
677
icqChatRequestCancel(const Licq::UserId & userId,unsigned short nSequence)678 void IcqProtocol::icqChatRequestCancel(const Licq::UserId& userId, unsigned short nSequence)
679 {
680 UserWriteGuard u(userId);
681 if (!u.isLocked())
682 return;
683 gLog.info(tr("Cancelling chat request with %s (#%d)."), u->getAlias().c_str(), -nSequence);
684 CPT_CancelChat p(nSequence, *u);
685 AckTCP(p, u->normalSocketDesc());
686 }
687
icqChatRequestRefuse(const ProtoChatRefuseSignal * ps)688 void IcqProtocol::icqChatRequestRefuse(const ProtoChatRefuseSignal* ps)
689 {
690 // add to history ??
691 UserWriteGuard u(ps->userId());
692 if (!u.isLocked())
693 return;
694 gLog.info(tr("Refusing chat request with %s (#%d)."), u->getAlias().c_str(), -ps->sequence());
695 string reasonDos = gTranslator.fromUtf8(gTranslator.returnToDos(ps->reason()), u->userEncoding());
696
697 if (ps->direct())
698 {
699 CPT_AckChatRefuse p(reasonDos, ps->sequence(), *u);
700 AckTCP(p, u->normalSocketDesc());
701 }
702 else
703 {
704 unsigned long nMsgID[2] = { ps->msgid1(), ps->msgid2() };
705 CPU_AckChatRefuse* p = new CPU_AckChatRefuse(*u, nMsgID, ps->sequence(), reasonDos);
706 SendEvent_Server(p);
707 }
708 }
709
icqChatRequestAccept(const ProtoChatAcceptSignal * ps)710 void IcqProtocol::icqChatRequestAccept(const ProtoChatAcceptSignal* ps)
711 {
712 // basically a fancy tcp ack packet which is sent late
713 // add to history ??
714 UserWriteGuard u(ps->userId());
715 if (!u.isLocked())
716 return;
717 gLog.info(tr("Accepting chat request with %s (#%d)."), u->getAlias().c_str(), -ps->sequence());
718
719 if (ps->direct())
720 {
721 CPT_AckChatAccept p(ps->port(), ps->clients(), ps->sequence(), *u, u->Version() > 7);
722 AckTCP(p, u->normalSocketDesc());
723 }
724 else
725 {
726 unsigned long nMsgID[2] = { ps->msgid1(), ps->msgid2() };
727 CPU_AckChatAccept* p = new CPU_AckChatAccept(*u, ps->clients(), nMsgID, ps->sequence(), ps->port());
728 SendEvent_Server(p);
729 }
730 }
731
732 /*---------------------------------------------------------------------------
733 * OpenSSL stuff
734 *-------------------------------------------------------------------------*/
735
icqOpenSecureChannel(const Licq::ProtocolSignal * ps)736 void IcqProtocol::icqOpenSecureChannel(const Licq::ProtocolSignal* ps)
737 {
738 if (!Licq::gDaemon.haveCryptoSupport())
739 {
740 gLog.warning(tr("icqOpenSecureChannel() to %s called when we do not support OpenSSL."),
741 ps->userId().toString().c_str());
742 return;
743 }
744
745 UserWriteGuard u(ps->userId());
746 if (!u.isLocked())
747 return;
748
749 CPT_OpenSecureChannel *pkt = new CPT_OpenSecureChannel(*u);
750 gLog.info(tr("Sending request for secure channel to %s (#%d)."),
751 u->getAlias().c_str(), -pkt->Sequence());
752 SendExpectEvent_Client(ps, *u, pkt, NULL);
753
754 u->SetSendServer(false);
755 }
756
icqCloseSecureChannel(const Licq::ProtocolSignal * ps)757 void IcqProtocol::icqCloseSecureChannel(const Licq::ProtocolSignal* ps)
758 {
759 if (!Licq::gDaemon.haveCryptoSupport())
760 {
761 gLog.warning(tr("icqCloseSecureChannel() to %s called when we do not support OpenSSL."),
762 ps->userId().toString().c_str());
763 return;
764 }
765
766 UserWriteGuard u(ps->userId());
767 if (!u.isLocked())
768 return;
769
770 CPT_CloseSecureChannel *pkt = new CPT_CloseSecureChannel(*u);
771 gLog.info(tr("Closing secure channel with %s (#%d)."),
772 u->getAlias().c_str(), -pkt->Sequence());
773 SendExpectEvent_Client(ps, *u, pkt, NULL);
774
775 u->SetSendServer(false);
776 }
777
icqOpenSecureChannelCancel(const Licq::UserId & userId,unsigned short nSequence)778 void IcqProtocol::icqOpenSecureChannelCancel(const Licq::UserId& userId,
779 unsigned short nSequence)
780 {
781 Licq::UserWriteGuard u(userId);
782 if (!u.isLocked())
783 return;
784 gLog.info(tr("Cancelling secure channel request to %s (#%d)."),
785 u->getAlias().c_str(), -nSequence);
786 // XXX Tear down tcp connection ??
787 }
788
789 /*---------------------------------------------------------------------------
790 * Handshake
791 *
792 * Shake hands on the given socket with the given user.
793 *-------------------------------------------------------------------------*/
handshake_Send(DcSocket * s,const Licq::UserId & userId,unsigned short nPort,unsigned short nVersion,bool bConfirm,unsigned long nId)794 bool IcqProtocol::handshake_Send(DcSocket* s, const Licq::UserId& userId,
795 unsigned short nPort, unsigned short nVersion, bool bConfirm,
796 unsigned long nId)
797 {
798 s->SetVersion(nVersion);
799 s->setUserId(userId);
800
801 unsigned long nUin = strtoul(userId.accountId().c_str(), NULL, 10);
802
803 switch (nVersion)
804 {
805 case 2:
806 case 3:
807 {
808 CPacketTcp_Handshake_v2 p(s->getLocalPort());
809 if (!s->send(*p.getBuffer()))
810 goto sock_error;
811 break;
812 }
813 case 4:
814 case 5:
815 {
816 CPacketTcp_Handshake_v4 p(s->getLocalPort());
817 if (!s->send(*p.getBuffer()))
818 goto sock_error;
819 break;
820 }
821 case 6:
822 {
823 // Send the hanshake
824 CPacketTcp_Handshake_v6 p(nUin, 0, nPort);
825 if (!s->send(*p.getBuffer()))
826 goto sock_error;
827
828 // Wait for the handshake ack
829 do
830 {
831 if (!s->RecvPacket()) goto sock_error;
832 } while (!s->RecvBufferFull());
833 s->RecvBuffer().unpackUInt16LE(); // Packet length
834 unsigned long nOk = s->RecvBuffer().UnpackUnsignedLong();
835 s->ClearRecvBuffer();
836 if (nOk != 1)
837 {
838 gLog.warning(tr("Bad handshake ack: %ld."), nOk);
839 return false;
840 }
841
842 // Wait for the reverse handshake
843 do
844 {
845 if (!s->RecvPacket()) goto sock_error;
846 } while (!s->RecvBufferFull());
847 CPacketTcp_Handshake_v6 p_in(&s->RecvBuffer());
848 s->ClearRecvBuffer();
849 if (p.SessionId() != p_in.SessionId())
850 {
851 gLog.warning(tr("Bad handshake session id: received %ld, expecting %ld."),
852 p_in.SessionId(), p.SessionId());
853 return false;
854 }
855
856 // Send the hanshake ack
857 CPacketTcp_Handshake_Ack p_ack;
858 if (!s->send(*p_ack.getBuffer()))
859 goto sock_error;
860
861 break;
862 }
863
864 case 7:
865 case 8:
866 {
867 // Send the hanshake
868 CPacketTcp_Handshake_v7 p(nUin, 0, nPort, nId);
869 if (!s->send(*p.getBuffer()))
870 goto sock_error;
871
872 // Wait for the handshake ack
873 do
874 {
875 if (!s->RecvPacket()) goto sock_error;
876 } while (!s->RecvBufferFull());
877 s->RecvBuffer().unpackUInt16LE(); // Packet length
878 unsigned long nOk = s->RecvBuffer().UnpackUnsignedLong();
879 s->ClearRecvBuffer();
880 if (nOk != 1)
881 {
882 gLog.warning(tr("Bad handshake ack: %ld."), nOk);
883 return false;
884 }
885
886 // Wait for the reverse handshake
887 do
888 {
889 if (!s->RecvPacket()) goto sock_error;
890 } while (!s->RecvBufferFull());
891 CPacketTcp_Handshake_v7 p_in(&s->RecvBuffer());
892 s->ClearRecvBuffer();
893 if (p_in.SessionId() && p.SessionId() != p_in.SessionId())
894 {
895 gLog.warning(tr("Bad handshake cookie: received %ld, expecting %ld."),
896 p_in.SessionId(), p.SessionId());
897 return false;
898 }
899
900 // Send the hanshake ack
901 CPacketTcp_Handshake_Ack p_ack;
902 if (!s->send(*p_ack.getBuffer()))
903 goto sock_error;
904
905 // Files and chats don't get this.
906 // They do in icq2002a but for some reason icq2002a does not
907 // reply to this when licq sends it. It will reply from a normal
908 // handshake though, just not file or chat...
909 if (bConfirm)
910 {
911 if (nId == 0)
912 {
913 if (!Handshake_SendConfirm_v7(s))
914 return false;
915 }
916 else
917 {
918 if (!Handshake_RecvConfirm_v7(s))
919 goto sock_error;
920 }
921 }
922
923 break;
924 }
925
926 default:
927 // Should never happen
928 gLog.error(tr("Unknown ICQ TCP version (%d)."), nVersion);
929 return false;
930 }
931
932 return true;
933
934 sock_error:
935 if (s->Error() == 0)
936 gLog.warning(tr("Handshake error, remote side closed connection."));
937 else
938 gLog.warning(tr("Handshake socket error: %s."), s->errorStr().c_str());
939 return false;
940 }
941
942
943 /*------------------------------------------------------------------------------
944 * ConnectToUser
945 *
946 * Creates a new TCPSocket and connects it to a given user. Adds the socket
947 * to the global socket manager and to the user.
948 *----------------------------------------------------------------------------*/
connectToUser(const Licq::UserId & userId,int channel)949 int IcqProtocol::connectToUser(const Licq::UserId& userId, int channel)
950 {
951 {
952 UserReadGuard u(userId);
953 if (!u.isLocked())
954 return -1;
955
956 // Check that we need to connect at all
957 int sd = u->socketDesc(channel);
958 if (sd != -1)
959 {
960 gLog.warning(tr("Connection attempted to already connected user (%s)."),
961 userId.toString().c_str());
962 return sd;
963 }
964 }
965
966 // Poll if there is a connection in progress already
967 while (1)
968 {
969 {
970 Licq::UserReadGuard u(userId);
971 if (u.isLocked() && !u->ConnectionInProgress())
972 break;
973 }
974 struct timeval tv = { 2, 0 };
975 if (select(0, NULL, NULL, NULL, &tv) == -1 && errno == EINTR) return -1;
976 }
977
978 string alias;
979 unsigned nPort;
980 unsigned nVersion;
981
982 {
983 UserWriteGuard u(userId);
984 int sd = u->normalSocketDesc();
985 if (sd == -1)
986 u->SetConnectionInProgress(true);
987 else
988 return sd;
989
990 alias = u->getAlias();
991 nPort = u->Port();
992 nVersion = u->ConnectionVersion();
993 }
994
995 DcSocket* s = new DcSocket(userId);
996 if (!openConnectionToUser(userId, s, nPort))
997 {
998 Licq::UserWriteGuard u(userId);
999 if (u.isLocked())
1000 u->SetConnectionInProgress(false);
1001 delete s;
1002 return -1;
1003 }
1004 s->setChannel(channel);
1005
1006 gLog.info(tr("Shaking hands with %s (%s) [v%d]."),
1007 alias.c_str(), userId.toString().c_str(), nVersion);
1008 nPort = s->getLocalPort();
1009
1010 if (!handshake_Send(s, userId, 0, nVersion))
1011 {
1012 Licq::UserWriteGuard u(userId);
1013 if (u.isLocked())
1014 u->SetConnectionInProgress(false);
1015 delete s;
1016 return -1;
1017 }
1018 s->SetVersion(nVersion);
1019 int nSD = s->Descriptor();
1020
1021 // Set the socket descriptor in the user
1022 {
1023 UserWriteGuard u(userId);
1024 if (!u.isLocked())
1025 return -1;
1026 u->setSocketDesc(s);
1027 u->SetConnectionInProgress(false);
1028 }
1029
1030 // Add the new socket to the socket manager
1031 gSocketManager.AddSocket(s);
1032 gSocketManager.DropSocket(s);
1033
1034 // Alert the select thread that there is a new socket
1035 myNewSocketPipe.putChar('S');
1036
1037 return nSD;
1038 }
1039
1040
1041
1042 /*------------------------------------------------------------------------------
1043 * OpenConnectionToUser
1044 *
1045 * Connects a socket to a given user on a given port.
1046 *----------------------------------------------------------------------------*/
openConnectionToUser(const Licq::UserId & userId,Licq::TCPSocket * sock,unsigned short nPort)1047 bool IcqProtocol::openConnectionToUser(const Licq::UserId& userId,
1048 Licq::TCPSocket* sock, unsigned short nPort)
1049 {
1050 string name;
1051 unsigned long ip;
1052 unsigned long intip;
1053 bool bSendIntIp;
1054 {
1055 Licq::UserReadGuard u(userId);
1056 if (!u.isLocked())
1057 return false;
1058
1059 name = u->getAlias() + " (" + u->accountId() + ")";
1060 ip = u->Ip();
1061 intip = u->IntIp();
1062 bSendIntIp = u->SendIntIp();
1063 }
1064
1065 return OpenConnectionToUser(name, ip, intip, sock, nPort, bSendIntIp);
1066 }
1067
1068
OpenConnectionToUser(const string & name,unsigned long nIp,unsigned long nIntIp,Licq::TCPSocket * sock,unsigned short nPort,bool bSendIntIp)1069 bool IcqProtocol::OpenConnectionToUser(const string& name, unsigned long nIp,
1070 unsigned long nIntIp, Licq::TCPSocket* sock, unsigned short nPort, bool bSendIntIp)
1071 {
1072 char buf[128];
1073
1074 // Sending to internet ip
1075 if (!bSendIntIp)
1076 {
1077 gLog.info(tr("Connecting to %s at %s:%d."), name.c_str(),
1078 Licq::ip_ntoa(nIp, buf), nPort);
1079 // If we fail to set the remote address, the ip must be 0
1080 if (!sock->connectTo(nIp, nPort))
1081 {
1082 gLog.warning(tr("Connect to %s failed: %s."), name.c_str(),
1083 sock->errorStr().c_str());
1084
1085 // Now try the internal ip if it is different from this one and we are behind a firewall
1086 if (sock->Error() != EINTR && nIntIp != nIp &&
1087 nIntIp != 0 && CPacket::Firewall())
1088 {
1089 gLog.info(tr("Connecting to %s at %s:%d."), name.c_str(),
1090 Licq::ip_ntoa(nIntIp, buf), nPort);
1091
1092 if (!sock->connectTo(nIntIp, nPort))
1093 {
1094 gLog.warning(tr("Connect to %s real ip failed: %s."), name.c_str(),
1095 sock->errorStr().c_str());
1096 return false;
1097 }
1098 }
1099 else
1100 {
1101 return false;
1102 }
1103 }
1104 }
1105
1106 // Sending to Internal IP
1107 else
1108 {
1109 gLog.info(tr("Connecting to %s at %s:%d."), name.c_str(),
1110 Licq::ip_ntoa(nIntIp, buf), nPort);
1111 if (!sock->connectTo(nIntIp, nPort))
1112 {
1113 gLog.warning(tr("Connect to %s real ip failed: %s."), name.c_str(),
1114 sock->errorStr().c_str());
1115 return false;
1116 }
1117 }
1118
1119
1120 return true;
1121 }
1122
1123
1124
1125 /*------------------------------------------------------------------------------
1126 * ReverseConnectToUser
1127 *
1128 * Creates a new TCPSocket and connects it to a given user. Adds the socket
1129 * to the global socket manager and to the user.
1130 *----------------------------------------------------------------------------*/
reverseConnectToUser(const Licq::UserId & userId,unsigned long nIp,unsigned short nPort,unsigned short nVersion,unsigned short nFailedPort,unsigned long nId,unsigned long nMsgID1,unsigned long nMsgID2)1131 int IcqProtocol::reverseConnectToUser(const Licq::UserId& userId, unsigned long nIp,
1132 unsigned short nPort, unsigned short nVersion, unsigned short nFailedPort,
1133 unsigned long nId, unsigned long nMsgID1, unsigned long nMsgID2)
1134 {
1135 FileTransferManager* ftm = FileTransferManager::FindByPort(nFailedPort);
1136 ChatManager *cm = ChatManager::FindByPort(nFailedPort);
1137
1138 DcSocket* s = new DcSocket(userId);
1139 char buf[32];
1140
1141 gLog.info(tr("Reverse connecting to %s at %s:%d."), userId.toString().c_str(),
1142 Licq::ip_ntoa(nIp, buf), nPort);
1143
1144 // If we fail to set the remote address, the ip must be 0
1145 if (!s->connectTo(nIp, nPort))
1146 {
1147 gLog.warning(tr("Reverse connect to %s failed: %s."),
1148 userId.toString().c_str(), s->errorStr().c_str());
1149
1150 CPU_ReverseConnectFailed* p = new CPU_ReverseConnectFailed(userId.accountId(), nMsgID1,
1151 nMsgID2, nPort, nFailedPort, nId);
1152 SendEvent_Server(p);
1153 return -1;
1154 }
1155
1156 gLog.info(tr("Reverse shaking hands with %s."), userId.toString().c_str());
1157 bool bConfirm = ftm == NULL && cm == NULL;
1158
1159 // Make sure we use the right version
1160 nVersion = IcqProtocol::dcVersionToUse(nVersion);
1161
1162 if (!handshake_Send(s, userId, 0, nVersion, bConfirm, nId))
1163 {
1164 delete s;
1165 return -1;
1166 }
1167 s->SetVersion(nVersion);
1168 int nSD = s->Descriptor();
1169
1170 // File transfer port
1171 if (ftm != NULL)
1172 {
1173 ftm->AcceptReverseConnection(s);
1174 delete s;
1175 }
1176
1177 // Chat port
1178 else if (cm != NULL)
1179 {
1180 cm->AcceptReverseConnection(s);
1181 delete s;
1182 }
1183
1184 // It's the main port
1185 else
1186 {
1187 // Set the socket descriptor in the user if this user is on our list
1188 {
1189 UserWriteGuard u(userId);
1190 if (u.isLocked())
1191 u->setSocketDesc(s);
1192 }
1193
1194 // Add the new socket to the socket manager, alert the thread
1195 gSocketManager.AddSocket(s);
1196 gSocketManager.DropSocket(s);
1197 myNewSocketPipe.putChar('S');
1198 }
1199
1200 return nSD;
1201 }
1202
ProcessTcpPacket(DcSocket * pSock)1203 bool IcqProtocol::ProcessTcpPacket(DcSocket* pSock)
1204 {
1205 unsigned long senderIp, localIp,
1206 senderPort, junkLong, nPort, nPortReversed;
1207 unsigned short version, command, junkShort, newCommand, messageLen,
1208 headerLen, ackFlags, msgFlags, licqVersion, theSequence;
1209 char licqChar = '\0', junkChar;
1210 bool errorOccured = false;
1211 Licq::UserId userId;
1212
1213 // only used for v7,v8
1214 headerLen = 0;
1215
1216 CBuffer &packet = pSock->RecvBuffer();
1217 int sockfd = pSock->Descriptor();
1218
1219 unsigned short nInVersion = pSock->Version();
1220
1221 switch (nInVersion)
1222 {
1223 case 1:
1224 case 2:
1225 case 3:
1226 {
1227 packet.unpackUInt16LE(); // Packet length
1228 unsigned long nUin;
1229 packet >> nUin
1230 >> version
1231 >> command // main tcp command (start, cancel, ack)
1232 >> junkShort // 00 00 to fill in the MSB of the command long int which is read in as a short
1233 >> nUin
1234 >> newCommand // sub command (message/chat/read away message/...)
1235 >> messageLen // length of incoming message
1236 ;
1237 char id[16];
1238 snprintf(id, 15, "%lu", nUin);
1239 userId = Licq::UserId(myOwnerId, id);
1240 break;
1241 }
1242 case 4:
1243 case 5:
1244 {
1245 if (!Decrypt_Client(&packet, 4))
1246 {
1247 packet.log(Log::Unknown, "Invalid TCPv4 encryption");
1248 return false;
1249 }
1250 packet.unpackUInt16LE(); // Packet length
1251 unsigned long nUin;
1252 packet >> nUin
1253 >> version
1254 >> junkLong // checksum
1255 >> command // main tcp command (start, cancel, ack)
1256 >> junkShort // 00 00 to fill in the MSB of the command long int which is read in as a short
1257 >> nUin
1258 >> newCommand // sub command (message/chat/read away message/...)
1259 >> messageLen // length of incoming message
1260 ;
1261 char id[16];
1262 snprintf(id, 15, "%lu", nUin);
1263 userId = Licq::UserId(myOwnerId, id);
1264 break;
1265 }
1266 case 6:
1267 {
1268 userId = pSock->userId();
1269 if (!Decrypt_Client(&packet, 6))
1270 {
1271 packet.log(Log::Unknown, "Invalid TCPv6 encryption");
1272 return false;
1273 }
1274 packet.unpackUInt16LE(); // Packet length
1275 packet.UnpackUnsignedLong(); // Checksum
1276 command = packet.UnpackUnsignedShort(); // Command
1277 packet.UnpackUnsignedShort(); // 0x000E
1278 theSequence = (signed short)packet.UnpackUnsignedShort();
1279 unsigned long junkLong1, junkLong2, junkLong3;
1280 packet >> junkLong1 >> junkLong2 >> junkLong3; // maybe always zero ??!
1281 newCommand = packet.UnpackUnsignedShort();
1282 ackFlags = packet.UnpackUnsignedShort();
1283 msgFlags = packet.UnpackUnsignedShort();
1284 packet >> messageLen;
1285 break;
1286 }
1287 case 7:
1288 case 8:
1289 {
1290 userId = pSock->userId();
1291 if (!Decrypt_Client(&packet, nInVersion))
1292 {
1293 packet.log(Log::Unknown, "Unknown TCPv%d packet", nInVersion);
1294 break;
1295 }
1296 packet.unpackUInt16LE(); // Packet length
1297 packet.UnpackChar(); // 0x02
1298 packet.UnpackUnsignedLong(); // Checksum
1299 command = packet.UnpackUnsignedShort(); // Command
1300 headerLen = packet.UnpackUnsignedShort();
1301 theSequence = (signed short)packet.UnpackUnsignedShort();
1302 packet.incDataPosRead(headerLen - 2);
1303 newCommand = packet.UnpackUnsignedShort();
1304
1305 if (pSock->channel() == DcSocket::ChannelNormal)
1306 {
1307 ackFlags = packet.UnpackUnsignedShort();
1308 msgFlags = packet.UnpackUnsignedShort();
1309 packet >> messageLen;
1310
1311 // Stupid AOL
1312 if (msgFlags & ICQ_TCPxMSG_URGENT2)
1313 msgFlags |= ICQ_TCPxMSG_URGENT;
1314 if (msgFlags & ICQ_TCPxMSG_LIST2)
1315 msgFlags |= ICQ_TCPxMSG_LIST;
1316 }
1317
1318 break;
1319 }
1320 default:
1321 {
1322 gLog.warning(tr("Unknown TCP version %d from socket."), nInVersion);
1323 break;
1324 }
1325 }
1326
1327 // Some simple validation of the packet
1328 if (!userId.isValid() || command == 0)
1329 {
1330 packet.log(Log::Unknown, "Invalid TCP packet (uin: %s, cmd: %04x)",
1331 userId.toString().c_str(), command);
1332 return false;
1333 }
1334
1335 if (userId.isOwner())
1336 {
1337 packet.log(Log::Warning, tr("TCP message from self (probable spoof)"));
1338 return false;
1339 }
1340 if (userId != pSock->userId())
1341 {
1342 packet.log(Log::Warning, tr("TCP message from invalid UIN (%s, expect %s)"),
1343 userId.toString().c_str(), pSock->userId().toString().c_str());
1344 return false;
1345 }
1346
1347 // Store our status for later use
1348 unsigned ownerStatus;
1349 {
1350 Licq::OwnerReadGuard o(myOwnerId);
1351 ownerStatus = o->status();
1352 }
1353
1354 // find which user was sent
1355 bool bNewUser = false;
1356 UserWriteGuard u(userId, true, &bNewUser);
1357 if (bNewUser)
1358 u->setSocketDesc(pSock);
1359
1360 // Check for spoofing
1361 if (u->socketDesc(pSock->channel()) != sockfd)
1362 {
1363 gLog.warning(tr("User %s (%s) socket (%d) does not match incoming message (%d)."),
1364 u->getAlias().c_str(), u->accountId().c_str(),
1365 u->socketDesc(pSock->channel()), sockfd);
1366 }
1367
1368 if (pSock->channel() != DcSocket::ChannelNormal)
1369 {
1370 errorOccured = processPluginMessage(packet, *u, pSock->channel(),
1371 command == ICQ_CMDxTCP_ACK,
1372 0, 0, theSequence, pSock);
1373 }
1374 else
1375 {
1376
1377 // read in the message minus any stupid DOS \r's
1378 string message = parseRtf(gTranslator.returnToUnix(packet.unpackRawString(messageLen)));
1379
1380 if (nInVersion < 6)
1381 {
1382 // read in some more stuff common to all tcp packets
1383 packet >> senderIp
1384 >> localIp
1385 >> senderPort
1386 >> junkChar // whether use can receive tcp packets directly
1387 >> ackFlags
1388 >> msgFlags
1389 ;
1390 senderIp = LE_32(senderIp);
1391 localIp = LE_32(localIp);
1392 }
1393
1394 unsigned long nMask = Licq::UserEvent::FlagDirect |
1395 ((newCommand & ICQ_CMDxSUB_FxMULTIREC) ? (int)Licq::UserEvent::FlagMultiRec : 0) |
1396 ((msgFlags & ICQ_TCPxMSG_URGENT) ? (int)Licq::UserEvent::FlagUrgent : 0) |
1397 (pSock->Secure() ? (int)Licq::UserEvent::FlagEncrypted : 0);
1398 newCommand &= ~ICQ_CMDxSUB_FxMULTIREC;
1399 bool bAccept = msgFlags & ICQ_TCPxMSG_URGENT || msgFlags & ICQ_TCPxMSG_LIST;
1400 // Flag as sent urgent as well if we are in occ or dnd and auto-accept is on
1401 if ( (((ownerStatus & Licq::User::OccupiedStatus) || (u->statusToUser() & Licq::User::OccupiedStatus))
1402 && u->AcceptInOccupied() ) ||
1403 (((ownerStatus & Licq::User::DoNotDisturbStatus) || (u->statusToUser() & Licq::User::DoNotDisturbStatus))
1404 && u->AcceptInDND() ) ||
1405 (u->statusToUser() != Licq::User::OfflineStatus
1406 && (u->statusToUser() & (Licq::User::OccupiedStatus | Licq::User::DoNotDisturbStatus)) == 0) )
1407 bAccept = true;
1408
1409 //fprintf(stderr, "status: %04X (%04X) msgtype: %04X\n", ackFlags, u->Status(), msgFlags);
1410
1411 switch(command)
1412 {
1413
1414 //-----START------------------------------------------------------------------
1415 case ICQ_CMDxTCP_START:
1416 {
1417 // Process the status bits
1418 unsigned short s = 0, ns = 0;
1419
1420 // Stupid AOL
1421 if (nInVersion >= 7)
1422 {
1423 s = 0;
1424 ns = ackFlags;
1425 }
1426 else
1427 s = msgFlags & 0xFF80;
1428
1429 if (s & ICQ_TCPxMSG_FxINVISIBLE)
1430 {
1431 s &= ~ICQ_TCPxMSG_FxINVISIBLE;
1432 ns |= ICQ_STATUS_FxPRIVATE;
1433 }
1434 switch(s)
1435 {
1436 case ICQ_TCPxMSG_FxONLINE: ns |= ICQ_STATUS_ONLINE; break;
1437 case ICQ_TCPxMSG_FxAWAY: ns |= ICQ_STATUS_AWAY; break;
1438 case ICQ_TCPxMSG_FxOCCUPIED: ns |= ICQ_STATUS_OCCUPIED; break;
1439 case ICQ_TCPxMSG_FxNA: ns |= ICQ_STATUS_NA; break;
1440 case ICQ_TCPxMSG_FxDND: ns |= ICQ_STATUS_DND; break;
1441 default:
1442 ns = ICQ_STATUS_OFFLINE;
1443 gLog.warning(tr("Unknown TCP status: %04X"), msgFlags);
1444 break;
1445 }
1446 //fprintf(stderr, "%08lX\n", addStatusFlags(ns, u));
1447 /*if (!bNewUser && ns != ICQ_STATUS_OFFLINE &&
1448 !((ns & ICQ_STATUS_FxPRIVATE) && !u->isOnline()))*/
1449 if (!bNewUser && ns != ICQ_STATUS_OFFLINE &&
1450 !(ns == ICQ_STATUS_ONLINE && (u->status() & Licq::User::FreeForChatStatus)) &&
1451 ns != (icqStatusFromStatus(u->status()) | (u->isInvisible() ? ICQ_STATUS_FxPRIVATE : 0)))
1452 {
1453 bool r = u->OfflineOnDisconnect() || !u->isOnline();
1454 u->statusChanged(statusFromIcqStatus(ns));
1455 gLog.info(tr("%s (%s) is %s to us."), u->getAlias().c_str(),
1456 u->id().toString().c_str(), u->statusString().c_str());
1457 if (r) u->SetOfflineOnDisconnect(true);
1458 }
1459
1460 // Process the command
1461 switch(newCommand)
1462 {
1463 case ICQ_CMDxSUB_MSG: // straight message from a user
1464 {
1465 unsigned long back = 0xFFFFFF, fore = 0x000000;
1466 bool isUtf8 = false;
1467 if (nInVersion < 6)
1468 {
1469 if (packet.getDataPosRead() + 4 >
1470 (packet.getDataStart() + packet.getDataSize()))
1471 {
1472 theSequence = (signed short)packet.UnpackUnsignedShort();
1473 }
1474 else
1475 packet >> theSequence;
1476
1477 packet >> licqChar >> licqVersion;
1478 nMask |= licqVersion;
1479 }
1480 else
1481 {
1482 packet >> fore >> back;
1483 if( fore == back ) {
1484 back = 0xFFFFFF;
1485 fore = 0x000000;
1486 }
1487
1488 // Check if message is marked as UTF8
1489 unsigned long guidlen;
1490 packet >> guidlen;
1491 while (guidlen >= 38)
1492 {
1493 string guid = packet.unpackRawString(38);
1494 if (guid == ICQ_CAPABILITY_UTF8_STR)
1495 isUtf8 = true;
1496 guidlen -= 38;
1497 }
1498 }
1499
1500 if (licqChar == 'L')
1501 gLog.info(tr("Message from %s (%s) [Licq %s]."),
1502 u->getAlias().c_str(), userId.toString().c_str(),
1503 Licq::UserEvent::licqVersionToString(licqVersion).c_str());
1504 else
1505 gLog.info(tr("Message from %s (%s)."), u->getAlias().c_str(), userId.toString().c_str());
1506
1507 CPT_AckGeneral p(newCommand, theSequence, true, bAccept, *u);
1508 AckTCP(p, pSock);
1509
1510 Licq::EventMsg* e = new Licq::EventMsg(
1511 (isUtf8 ? message : gTranslator.toUtf8(message, u->userEncoding())),
1512 Licq::EventMsg::TimeNow, nMask);
1513 e->SetColor(fore, back);
1514
1515 // If we are in DND or Occupied and message isn't urgent then we ignore it
1516 if (!bAccept)
1517 {
1518 if (ownerStatus & (Licq::User::OccupiedStatus | Licq::User::DoNotDisturbStatus))
1519 {
1520 delete e;
1521 break;
1522 }
1523 }
1524 // Add the user to our list if they are new
1525 if (bNewUser)
1526 {
1527 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1528 {
1529 // FIXME should log a message here or in reject event
1530 // FIXME should either refuse the event or have a special auto response
1531 // for rejected events instead of pretending to accept the user
1532 gDaemon.rejectEvent(userId, e);
1533 break;
1534 }
1535 bNewUser = false;
1536 }
1537
1538 if (!gDaemon.addUserEvent(*u, e))
1539 break;
1540 gOnEventManager.performOnEvent(OnEventData::OnEventMessage, *u);
1541 break;
1542 }
1543 case ICQ_CMDxTCP_READxNAxMSG:
1544 case ICQ_CMDxTCP_READxDNDxMSG:
1545 case ICQ_CMDxTCP_READxOCCUPIEDxMSG:
1546 case ICQ_CMDxTCP_READxFFCxMSG:
1547 case ICQ_CMDxTCP_READxAWAYxMSG: // read away message
1548 {
1549 if (nInVersion < 6)
1550 {
1551 if (packet.getDataPosRead() + 4 >
1552 (packet.getDataStart() + packet.getDataSize()))
1553 {
1554 theSequence = (signed short)packet.UnpackUnsignedShort();
1555 }
1556 else
1557 packet >> theSequence;
1558
1559 packet >> licqChar >> licqVersion;
1560 }
1561 else
1562 packet >> junkLong >> junkLong;
1563
1564 if (licqChar == 'L')
1565 gLog.info(tr("%s (%s) requested auto response [Licq %s]."),
1566 u->getAlias().c_str(), userId.toString().c_str(),
1567 Licq::UserEvent::licqVersionToString(licqVersion).c_str());
1568 else
1569 gLog.info(tr("%s (%s) requested auto response."), u->getAlias().c_str(), userId.toString().c_str());
1570
1571 CPT_AckGeneral p(newCommand, theSequence, true, false, *u);
1572 AckTCP(p, pSock);
1573
1574 Licq::gStatistics.increase(Licq::Statistics::AutoResponseCheckedCounter);
1575 u->SetLastCheckedAutoResponse();
1576
1577 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
1578 Licq::PluginSignal::SignalUser,
1579 Licq::PluginSignal::UserEvents, u->id()));
1580 break;
1581 }
1582
1583 case ICQ_CMDxSUB_URL: // url sent
1584 {
1585 unsigned long back = 0xFFFFFF, fore = 0x000000;
1586 if (nInVersion < 6)
1587 {
1588 if (packet.getDataPosRead() + 4 >
1589 (packet.getDataStart() + packet.getDataSize()))
1590 {
1591 theSequence = (signed short)packet.UnpackUnsignedShort();
1592 }
1593 else
1594 packet >> theSequence;
1595
1596 packet >> licqChar >> licqVersion;
1597 nMask |= licqVersion;
1598 }
1599 else
1600 {
1601 packet >> fore >> back;
1602 if(fore == back)
1603 {
1604 fore = 0x000000;
1605 back = 0xFFFFFF;
1606 }
1607 }
1608 if (licqChar == 'L')
1609 gLog.info(tr("URL from %s (%s) [Licq %s]."), u->getAlias().c_str(),
1610 userId.toString().c_str(), Licq::UserEvent::licqVersionToString(licqVersion).c_str());
1611 else
1612 gLog.info(tr("URL from %s (%s)."), u->getAlias().c_str(), userId.toString().c_str());
1613
1614 Licq::EventUrl* e = parseUrlEvent(message, Licq::EventUrl::TimeNow, nMask, u->userEncoding());
1615 if (e == NULL)
1616 {
1617 packet.log(Log::Warning, tr("Invalid URL message"));
1618 errorOccured = true;
1619 break;
1620 }
1621 e->SetColor(fore, back);
1622
1623 CPT_AckGeneral p(newCommand, theSequence, true, bAccept, *u);
1624 AckTCP(p, pSock);
1625
1626 // If we are in DND or Occupied and message isn't urgent then we ignore it
1627 if (!bAccept)
1628 {
1629 if (ownerStatus & (Licq::User::OccupiedStatus | Licq::User::DoNotDisturbStatus))
1630 {
1631 delete e;
1632 break;
1633 }
1634 }
1635 // Add the user to our list if they are new
1636 if (bNewUser)
1637 {
1638 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1639 {
1640 gDaemon.rejectEvent(userId, e);
1641 break;
1642 }
1643 bNewUser = false;
1644 }
1645
1646 if (!gDaemon.addUserEvent(*u, e))
1647 break;
1648 gOnEventManager.performOnEvent(OnEventData::OnEventUrl, *u);
1649 break;
1650 }
1651
1652 // Contact List
1653 case ICQ_CMDxSUB_CONTACTxLIST:
1654 {
1655 unsigned long back = 0xFFFFFF, fore = 0x000000;
1656 if (nInVersion < 6)
1657 {
1658 if (packet.getDataPosRead() + 4 >
1659 (packet.getDataStart() + packet.getDataSize()))
1660 {
1661 theSequence = (signed short)packet.UnpackUnsignedShort();
1662 }
1663 else
1664 packet >> theSequence;
1665
1666 packet >> licqChar >> licqVersion;
1667 nMask |= licqVersion;
1668 }
1669 else
1670 {
1671 packet >> fore >> back;
1672 if(fore == back) {
1673 fore = 0x000000;
1674 back = 0xFFFFFF;
1675 }
1676 }
1677 if (licqChar == 'L')
1678 gLog.info(tr("Contact list from %s (%s) [Licq %s]."),
1679 u->getAlias().c_str(), userId.toString().c_str(),
1680 Licq::UserEvent::licqVersionToString(licqVersion).c_str());
1681 else
1682 gLog.info(tr("Contact list from %s (%s).\n"),
1683 u->getAlias().c_str(), userId.toString().c_str());
1684
1685 Licq::EventContactList* e = parseContactEvent(message, Licq::EventContactList::TimeNow,
1686 nMask, u->userEncoding());
1687 if (e == NULL)
1688 {
1689 packet.log(Log::Warning, tr("Invalid contact list message"));
1690 errorOccured = true;
1691 break;
1692 }
1693 e->SetColor(fore, back);
1694
1695 CPT_AckGeneral p(newCommand, theSequence, true, bAccept, *u);
1696 AckTCP(p, pSock);
1697
1698 // If we are in DND or Occupied and message isn't urgent then we ignore it
1699 if (!bAccept)
1700 {
1701 if (ownerStatus & (Licq::User::OccupiedStatus | Licq::User::DoNotDisturbStatus))
1702 {
1703 delete e;
1704 break;
1705 }
1706 }
1707 // Add the user to our list if they are new
1708 if (bNewUser)
1709 {
1710 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1711 {
1712 gDaemon.rejectEvent(userId, e);
1713 break;
1714 }
1715 bNewUser = false;
1716 }
1717
1718 if (!gDaemon.addUserEvent(*u, e))
1719 break;
1720 gOnEventManager.performOnEvent(OnEventData::OnEventMessage, *u);
1721 break;
1722 }
1723
1724 // Chat Request
1725 case ICQ_CMDxSUB_CHAT:
1726 {
1727 string msgUtf8 = gTranslator.toUtf8(message, u->userEncoding());
1728
1729 string chatClients = packet.unpackShortStringLE();
1730 packet.UnpackUnsignedLong(); // reversed port
1731 unsigned short nPort = packet.UnpackUnsignedLong();
1732 if (nInVersion < 6)
1733 {
1734 if (packet.getDataPosRead() + 4 >
1735 (packet.getDataStart() + packet.getDataSize()))
1736 {
1737 theSequence = (signed short)packet.UnpackUnsignedShort();
1738 }
1739 else
1740 packet >> theSequence;
1741
1742 packet >> licqChar >> licqVersion;
1743 }
1744
1745 if (licqChar == 'L')
1746 gLog.info(tr("Chat request from %s (%s) [Licq %s]."),
1747 u->getAlias().c_str(), userId.toString().c_str(),
1748 Licq::UserEvent::licqVersionToString(licqVersion).c_str());
1749 else
1750 gLog.info(tr("Chat request from %s (%s)."),
1751 u->getAlias().c_str(), userId.toString().c_str());
1752
1753 Licq::EventChat* e = new Licq::EventChat(msgUtf8, chatClients, nPort, theSequence,
1754 Licq::EventChat::TimeNow, nMask | licqVersion);
1755
1756 // Add the user to our list if they are new
1757 if (bNewUser)
1758 {
1759 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1760 {
1761 gDaemon.rejectEvent(userId, e);
1762 break;
1763 }
1764 bNewUser = false;
1765 }
1766
1767 if (!gDaemon.addUserEvent(*u, e))
1768 break;
1769 gOnEventManager.performOnEvent(OnEventData::OnEventChat, *u);
1770 break;
1771 }
1772
1773 // File transfer
1774 case ICQ_CMDxSUB_FILE:
1775 {
1776 string msgUtf8 = gTranslator.toUtf8(message, u->userEncoding());
1777
1778 unsigned long nFileLength;
1779 packet.UnpackUnsignedLong();
1780 string filename = packet.unpackShortStringLE();
1781 packet >> nFileLength
1782 >> junkLong;
1783 if (nInVersion < 6)
1784 {
1785 if (packet.getDataPosRead() + 4 >
1786 (packet.getDataStart() + packet.getDataSize()))
1787 {
1788 theSequence = (signed short)packet.UnpackUnsignedShort();
1789 }
1790 else
1791 packet >> theSequence;
1792
1793 packet >> licqChar >> licqVersion;
1794 }
1795
1796 if (licqChar == 'L')
1797 gLog.info(tr("File transfer request from %s (%s) [Licq %s]."),
1798 u->getAlias().c_str(), userId.toString().c_str(),
1799 Licq::UserEvent::licqVersionToString(licqVersion).c_str());
1800 else
1801 gLog.info(tr("File transfer request from %s (%s)."),
1802 u->getAlias().c_str(), userId.toString().c_str());
1803
1804 list<string> filelist;
1805 filelist.push_back(filename);
1806
1807 Licq::EventFile* e = new Licq::EventFile(filename, msgUtf8, nFileLength,
1808 filelist, theSequence, Licq::EventFile::TimeNow, nMask | licqVersion);
1809 // Add the user to our list if they are new
1810 if (bNewUser)
1811 {
1812 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1813 {
1814 gDaemon.rejectEvent(userId, e);
1815 break;
1816 }
1817 bNewUser = false;
1818 }
1819
1820 if (!gDaemon.addUserEvent(*u, e))
1821 break;
1822 gOnEventManager.performOnEvent(OnEventData::OnEventFile, *u);
1823 break;
1824 }
1825
1826 // Yuck, ICBM
1827 // XXX If we are in DND or OCC, don't accept the message!
1828 case ICQ_CMDxSUB_ICBM:
1829 {
1830 unsigned short nLen;
1831 packet >> nLen;
1832 packet.incDataPosRead(18);
1833
1834 string plugin = packet.unpackLongStringLE();
1835
1836 packet.incDataPosRead(nLen - 22 - plugin.size());
1837 packet.incDataPosRead(4); // bytes left in packet
1838
1839 int nICBMCommand = 0;
1840 if (plugin.find("File") != string::npos)
1841 nICBMCommand = ICQ_CMDxSUB_FILE;
1842 else if (plugin.find("URL") != string::npos)
1843 nICBMCommand = ICQ_CMDxSUB_URL;
1844 else if (plugin.find("Chat") != string::npos)
1845 nICBMCommand = ICQ_CMDxSUB_CHAT;
1846 else if (plugin.find("Contacts") != string::npos)
1847 nICBMCommand = ICQ_CMDxSUB_CONTACTxLIST;
1848 else
1849 {
1850 gLog.info(tr("Unknown ICBM plugin type: %s"), plugin.c_str());
1851 break;
1852 }
1853
1854 string icbmMessage = packet.unpackLongStringLE();
1855
1856 switch (nICBMCommand)
1857 {
1858 case ICQ_CMDxSUB_FILE:
1859 {
1860 icbmMessage = gTranslator.toUtf8(icbmMessage, u->userEncoding());
1861
1862 unsigned long nFileSize;
1863 packet.incDataPosRead(2); // port (BE)
1864 packet.incDataPosRead(2); // unknown
1865 string filename = packet.unpackShortStringLE();
1866 packet >> nFileSize;
1867 packet.incDataPosRead(2); // reversed port (BE)
1868
1869 gLog.info(tr("File transfer request from %s (%s)."),
1870 u->getAlias().c_str(), userId.toString().c_str());
1871
1872 list<string> filelist;
1873 filelist.push_back(filename);
1874 Licq::EventFile* e = new Licq::EventFile(filename, icbmMessage, nFileSize,
1875 filelist, theSequence, Licq::EventFile::TimeNow, nMask);
1876 if (bNewUser)
1877 {
1878 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1879 {
1880 gDaemon.rejectEvent(userId, e);
1881 break;
1882 }
1883 bNewUser = false;
1884 }
1885
1886 if (!gDaemon.addUserEvent(*u, e))
1887 break;
1888 gOnEventManager.performOnEvent(OnEventData::OnEventFile, *u);
1889 break;
1890 }
1891 case ICQ_CMDxSUB_CHAT:
1892 {
1893 icbmMessage = gTranslator.toUtf8(icbmMessage, u->userEncoding());
1894 string chatClients = packet.unpackShortStringLE();
1895 nPort = packet.UnpackUnsignedShortBE();
1896 packet >> nPortReversed;
1897
1898 if (nPort == 0)
1899 nPort = nPortReversed;
1900
1901 gLog.info(tr("Chat request from %s (%s)."),
1902 u->getAlias().c_str(), userId.toString().c_str());
1903
1904 Licq::EventChat* e = new Licq::EventChat(icbmMessage, chatClients, nPort,
1905 theSequence, Licq::EventChat::TimeNow, nMask);
1906 if (bNewUser)
1907 {
1908 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1909 {
1910 gDaemon.rejectEvent(userId, e);
1911 break;
1912 }
1913 bNewUser = false;
1914 }
1915
1916 if (!gDaemon.addUserEvent(*u, e))
1917 break;
1918 gOnEventManager.performOnEvent(OnEventData::OnEventChat, *u);
1919 break;
1920 }
1921 case ICQ_CMDxSUB_URL:
1922 {
1923 gLog.info(tr("URL from %s (%s)."), u->getAlias().c_str(), userId.toString().c_str());
1924 Licq::EventUrl* e = parseUrlEvent(icbmMessage, Licq::EventUrl::TimeNow, nMask, u->userEncoding());
1925 if (e == NULL)
1926 {
1927 packet.log(Log::Warning, tr("Invalid URL message"));
1928 errorOccured = true;
1929 break;
1930 }
1931
1932 if (bNewUser)
1933 {
1934 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1935 {
1936 gDaemon.rejectEvent(userId, e);
1937 break;
1938 }
1939 bNewUser = false;
1940 }
1941
1942 if (!gDaemon.addUserEvent(*u, e))
1943 break;
1944 gOnEventManager.performOnEvent(OnEventData::OnEventUrl, *u);
1945 break;
1946 }
1947 case ICQ_CMDxSUB_CONTACTxLIST:
1948 {
1949 gLog.info(tr("Contact list from %s (%s)."),
1950 u->getAlias().c_str(), userId.toString().c_str());
1951 Licq::EventContactList* e = parseContactEvent(icbmMessage,
1952 Licq::EventContactList::TimeNow, nMask, u->userEncoding());
1953 if (e == NULL)
1954 {
1955 packet.log(Log::Warning, tr("Invalid contact list message"));
1956 errorOccured = true;
1957 break;
1958 }
1959
1960 if (bNewUser)
1961 {
1962 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
1963 {
1964 gDaemon.rejectEvent(userId, e);
1965 break;
1966 }
1967 bNewUser = false;
1968 }
1969
1970 if (!gDaemon.addUserEvent(*u, e))
1971 break;
1972 gOnEventManager.performOnEvent(OnEventData::OnEventMessage, *u);
1973 break;
1974 }
1975 } // switch nICBMCommand
1976 break;
1977 }
1978
1979 // Old-style encryption request:
1980 case ICQ_CMDxSUB_SECURExOLD:
1981 {
1982 gLog.info(tr("Received old-style key request from %s (%s) but we do not support it."),
1983 u->getAlias().c_str(), userId.toString().c_str());
1984 // Send the nack back
1985 CPT_AckOldSecureChannel p(theSequence, *u);
1986 AckTCP(p, pSock);
1987 break;
1988 }
1989
1990 // Secure channel request
1991 case ICQ_CMDxSUB_SECURExOPEN:
1992 {
1993 if (!Licq::gDaemon.haveCryptoSupport())
1994 {
1995 gLog.info(tr("Received secure channel request from %s (%s) but we do not support OpenSSL."),
1996 u->getAlias().c_str(), userId.toString().c_str());
1997 // Send the nack back
1998 CPT_AckOpenSecureChannel p(theSequence, false, *u);
1999 AckTCP(p, pSock);
2000 break;
2001 }
2002
2003 if (nInVersion < 6)
2004 {
2005 if (packet.getDataPosRead() + 4 >
2006 (packet.getDataStart() + packet.getDataSize()))
2007 {
2008 theSequence = (signed short)packet.UnpackUnsignedShort();
2009 }
2010 else
2011 packet >> theSequence;
2012
2013 packet >> licqChar >> licqVersion;
2014 }
2015
2016 if (licqChar == 'L')
2017 gLog.info(tr("Secure channel request from %s (%s) [Licq %s]."),
2018 u->getAlias().c_str(), userId.toString().c_str(),
2019 Licq::UserEvent::licqVersionToString(licqVersion).c_str());
2020 else
2021 gLog.info(tr("Secure channel request from %s (%s)."),
2022 u->getAlias().c_str(), userId.toString().c_str());
2023
2024 CPT_AckOpenSecureChannel p(theSequence, true, *u);
2025 AckTCP(p, pSock);
2026
2027 if (!pSock->SecureListen())
2028 {
2029 errorOccured = true;
2030 break;
2031 }
2032 u->SetSecure(true);
2033
2034 // Add the user to our list if they are new
2035 if (bNewUser)
2036 {
2037 if (gDaemon.ignoreType(Daemon::IgnoreNewUsers))
2038 break;
2039 bNewUser = false;
2040 }
2041
2042 u->SetSendServer(false);
2043 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2044 Licq::PluginSignal::SignalUser,
2045 Licq::PluginSignal::UserSecurity, u->id(), 1));
2046
2047 gLog.info(tr("Secure channel established with %s (%s)"),
2048 u->getAlias().c_str(), userId.toString().c_str());
2049
2050 break;
2051 }
2052
2053
2054 // Secure channel close request
2055 case ICQ_CMDxSUB_SECURExCLOSE:
2056 {
2057 if (!Licq::gDaemon.haveCryptoSupport())
2058 {
2059 gLog.info(tr("Received secure channel close from %s (%s) but we do not support OpenSSL."),
2060 u->getAlias().c_str(), userId.toString().c_str());
2061 // Send the nack back
2062 CPT_AckCloseSecureChannel p(theSequence, *u);
2063 AckTCP(p, pSock);
2064 break;
2065 }
2066
2067 if (nInVersion < 6)
2068 {
2069 if (packet.getDataPosRead() + 4 >
2070 (packet.getDataStart() + packet.getDataSize()))
2071 {
2072 theSequence = (signed short)packet.UnpackUnsignedShort();
2073 }
2074 else
2075 packet >> theSequence;
2076
2077 packet >> licqChar >> licqVersion;
2078 }
2079
2080 if (licqChar == 'L')
2081 gLog.info(tr("Secure channel closed by %s (%s) [Licq %s]."),
2082 u->getAlias().c_str(), userId.toString().c_str(),
2083 Licq::UserEvent::licqVersionToString(licqVersion).c_str());
2084 else
2085 gLog.info(tr("Secure channel closed by %s (%s)."),
2086 u->getAlias().c_str(), userId.toString().c_str());
2087
2088 // send ack
2089 CPT_AckCloseSecureChannel p(theSequence, *u);
2090 AckTCP(p, pSock);
2091
2092 pSock->SecureStop();
2093 u->SetSecure(false);
2094 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2095 Licq::PluginSignal::SignalUser,
2096 Licq::PluginSignal::UserSecurity, u->id(), 0));
2097 break;
2098 }
2099
2100 default:
2101 packet.log(Log::Unknown, "Unknown TCP message type (%04x)",
2102 newCommand);
2103 errorOccured = true;
2104 }
2105 break;
2106 }
2107
2108 //-----ACK--------------------------------------------------------------------
2109 case ICQ_CMDxTCP_ACK: // message received packet
2110 {
2111 // If this is not from a user on our list then ignore it
2112 if (bNewUser) break;
2113
2114 Licq::ExtendedData *pExtendedAck = NULL;
2115
2116 switch (newCommand)
2117 {
2118 case ICQ_CMDxSUB_MSG:
2119 case ICQ_CMDxTCP_READxNAxMSG:
2120 case ICQ_CMDxTCP_READxDNDxMSG:
2121 case ICQ_CMDxTCP_READxOCCUPIEDxMSG:
2122 case ICQ_CMDxTCP_READxAWAYxMSG:
2123 case ICQ_CMDxTCP_READxFFCxMSG:
2124 case ICQ_CMDxSUB_URL:
2125 case ICQ_CMDxSUB_CONTACTxLIST:
2126 if (nInVersion < 6)
2127 {
2128 if (packet.getDataPosRead() + 4 >
2129 (packet.getDataStart() + packet.getDataSize()))
2130 {
2131 theSequence = (signed short)packet.UnpackUnsignedShort();
2132 }
2133 else
2134 packet >> theSequence;
2135
2136 packet >> licqChar >> licqVersion;
2137 }
2138 else
2139 packet >> junkLong >> junkLong;
2140 break;
2141
2142 case ICQ_CMDxSUB_CHAT:
2143 {
2144 string ul = packet.unpackShortStringLE();
2145 packet >> nPortReversed // port backwards
2146 >> nPort; // port to connect to for chat
2147 if (nInVersion < 6)
2148 {
2149 if (packet.getDataPosRead() + 4 >
2150 (packet.getDataStart() + packet.getDataSize()))
2151 {
2152 theSequence = (signed short)packet.UnpackUnsignedShort();
2153 }
2154 else
2155 packet >> theSequence;
2156
2157 packet >> licqChar >> licqVersion;
2158 }
2159
2160 if (nPort == 0) nPort = (nPortReversed >> 8) | ((nPortReversed & 0xFF) << 8);
2161
2162 pExtendedAck = new Licq::ExtendedData(nPort != 0, nPort,
2163 gTranslator.toUtf8(message, u->userEncoding()));
2164 break;
2165 }
2166
2167 case ICQ_CMDxSUB_FILE:
2168 {
2169 /* 50 A5 82 00 03 00 DA 07 00 00 50 A5 82 00 03 00 0A 00 6E 6F 20 74 68 61
2170 6E 6B 73 00 D1 EF 04 9F 7F 00 00 01 4A 1F 00 00 04 01 00 00 00 00 00 00
2171 00 01 00 00 00 00 00 00 00 00 00 00 03 00 00 00 */
2172 packet >> nPortReversed
2173 >> junkShort;
2174 for (int i = 0; i < junkShort; i++) packet >> junkChar;
2175 packet >> junkLong
2176 >> nPort;
2177 if (nInVersion < 6)
2178 {
2179 if (packet.getDataPosRead() + 4 >
2180 (packet.getDataStart() + packet.getDataSize()))
2181 {
2182 theSequence = (signed short)packet.UnpackUnsignedShort();
2183 }
2184 else
2185 packet >> theSequence;
2186
2187 packet >> licqChar >> licqVersion;
2188 }
2189
2190 // Some clients only send the first port (reversed)
2191 if (nPort == 0) nPort = (nPortReversed >> 8) | ((nPortReversed & 0xFF) << 8);
2192
2193 pExtendedAck = new Licq::ExtendedData(nPort != 0, nPort,
2194 gTranslator.toUtf8(message, u->userEncoding()));
2195 break;
2196 }
2197
2198 case ICQ_CMDxSUB_ICBM:
2199 {
2200 unsigned short nLen;
2201 packet >> nLen;
2202 packet.incDataPosRead(18); // eh?
2203 string plugin = packet.unpackLongStringLE();
2204
2205 packet.incDataPosRead(nLen - 22 - plugin.size());
2206 packet.incDataPosRead(4); // left in packet
2207
2208 int nICBMCommand = 0;
2209 if (plugin.find("File") != string::npos)
2210 nICBMCommand = ICQ_CMDxSUB_FILE;
2211 else if (plugin.find("Chat") != string::npos)
2212 nICBMCommand = ICQ_CMDxSUB_CHAT;
2213 else if (plugin.find("URL") != string::npos)
2214 nICBMCommand = ICQ_CMDxSUB_URL;
2215 else if (plugin.find("Contacts") != string::npos)
2216 nICBMCommand = ICQ_CMDxSUB_CONTACTxLIST;
2217 else
2218 {
2219 gLog.info(tr("Unknown direct ack ICBM plugin type: %s"), plugin.c_str());
2220
2221 if (bNewUser)
2222 {
2223 u.unlock();
2224 Licq::gUserManager.removeLocalUser(userId);
2225 }
2226 return true;
2227 }
2228
2229 string msg = packet.unpackLongStringLE();
2230
2231 switch (nICBMCommand)
2232 {
2233 case ICQ_CMDxSUB_FILE:
2234 {
2235 nPort = packet.UnpackUnsignedShortBE();
2236 packet.incDataPosRead(2); // unknown
2237 packet >> nLen; // filename len, including NULL
2238 packet.incDataPosRead(nLen); // filename
2239 packet.incDataPosRead(4); // file size
2240 packet >> nPortReversed;
2241
2242 if (nPort == 0)
2243 nPort = nPortReversed;
2244
2245 pExtendedAck = new Licq::ExtendedData(nPort != 0, nPort,
2246 gTranslator.toUtf8((!message.empty() ? message : msg), u->userEncoding()));
2247 break;
2248 }
2249 case ICQ_CMDxSUB_CHAT:
2250 {
2251 string ul = packet.unpackShortStringLE();
2252 nPort = packet.UnpackUnsignedShortBE();
2253 packet >> nPortReversed;
2254
2255 if (nPort == 0)
2256 nPort = nPortReversed;
2257
2258 /* this is silly, but appearantly the only way to tell if chat is
2259 accepted (multiparty chat is accepted if port is 0, and rejected
2260 otherwise, normal chat is accepted if the port is given and
2261 rejected if it's 0) */
2262 bool bAccepted = (nPort != 0 && ul[0] == '\0') ||
2263 (nPort == 0 && ul[0] != '\0');
2264 pExtendedAck = new Licq::ExtendedData(bAccepted, nPort,
2265 gTranslator.toUtf8((!message.empty() ? message : msg), u->userEncoding()));
2266 break;
2267 }
2268 } // switch nICBMCommand
2269
2270 break;
2271 }
2272
2273 case ICQ_CMDxSUB_SECURExOPEN:
2274 {
2275 if (!Licq::gDaemon.haveCryptoSupport())
2276 {
2277 errorOccured = true;
2278 break;
2279 }
2280
2281 if (nInVersion < 6)
2282 {
2283 if (packet.getDataPosRead() + 4 >
2284 (packet.getDataStart() + packet.getDataSize()))
2285 {
2286 theSequence = (signed short)packet.UnpackUnsignedShort();
2287 }
2288 else
2289 packet >> theSequence;
2290
2291 packet >> licqChar >> licqVersion;
2292 }
2293
2294 char l[32] = "";
2295 if (licqChar == 'L')
2296 sprintf(l, " [Licq %s]", Licq::UserEvent::licqVersionToString(licqVersion).c_str());
2297 gLog.info(tr("Secure channel response from %s (%s)%s."),
2298 u->getAlias().c_str(), userId.toString().c_str(), l);
2299
2300 Licq::Event* e = NULL;
2301
2302 // Check if the response is ok
2303 if (message.empty())
2304 {
2305 gLog.info(tr("%s (%s) does not support OpenSSL."),
2306 u->getAlias().c_str(), userId.toString().c_str());
2307 u->SetSecure(false);
2308 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2309 Licq::PluginSignal::SignalUser,
2310 Licq::PluginSignal::UserSecurity, u->id(), 0));
2311 // find the event, fail it
2312 e = DoneEvent(sockfd, theSequence, Licq::Event::ResultFailed);
2313 }
2314 else
2315 {
2316 // Find the event, succeed it
2317 e = DoneEvent(sockfd, theSequence, Licq::Event::ResultSuccess);
2318
2319 // Check that a request was in progress...should always be ok
2320 if (e == NULL)
2321 {
2322 gLog.warning(tr("Secure channel response from %s (%s) when no request in progress."),
2323 u->getAlias().c_str(), userId.toString().c_str());
2324 // Close the connection as we are in trouble
2325 u->SetSecure(false);
2326 u.unlock();
2327 if (bNewUser)
2328 Licq::gUserManager.removeLocalUser(userId);
2329 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2330 Licq::PluginSignal::SignalUser,
2331 Licq::PluginSignal::UserSecurity, userId, 0));
2332 return false;
2333 }
2334
2335 if (!pSock->SecureConnect())
2336 {
2337 errorOccured = true;
2338 e->m_eResult = Licq::Event::ResultFailed;
2339 }
2340 else
2341 {
2342 gLog.info(tr("Secure channel established with %s (%s)"),
2343 u->getAlias().c_str(), userId.toString().c_str());
2344 u->SetSecure(true);
2345 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2346 Licq::PluginSignal::SignalUser,
2347 Licq::PluginSignal::UserSecurity, u->id(), 1));
2348 }
2349 }
2350
2351 // finish up
2352 e->mySubResult = Licq::Event::SubResultAccept;
2353 u.unlock();
2354 if (bNewUser)
2355 Licq::gUserManager.removeLocalUser(userId);
2356 ProcessDoneEvent(e);
2357
2358 // get out of here now as we don't want standard ack processing
2359 return !errorOccured;
2360 }
2361
2362
2363 case ICQ_CMDxSUB_SECURExCLOSE:
2364 {
2365 if (!Licq::gDaemon.haveCryptoSupport())
2366 {
2367 errorOccured = true;
2368 break;
2369 }
2370 if (nInVersion < 6)
2371 {
2372 if (packet.getDataPosRead() + 4 >
2373 (packet.getDataStart() + packet.getDataSize()))
2374 {
2375 theSequence = (signed short)packet.UnpackUnsignedShort();
2376 }
2377 else
2378 packet >> theSequence;
2379
2380 packet >> licqChar >> licqVersion;
2381 }
2382
2383 char l[32] = "";
2384 if (licqChar == 'L')
2385 sprintf(l, " [Licq %s]", Licq::UserEvent::licqVersionToString(licqVersion).c_str());
2386 gLog.info(tr("Secure channel with %s (%s) closed %s."),
2387 u->getAlias().c_str(), userId.toString().c_str(), l);
2388
2389 // Find the event, succeed it
2390 Licq::Event* e = DoneEvent(sockfd, theSequence, Licq::Event::ResultSuccess);
2391
2392 // Check that a request was in progress...should always be ok
2393 if (e == NULL)
2394 {
2395 // Close the connection as we are in trouble
2396 if (bNewUser)
2397 {
2398 u.unlock();
2399 Licq::gUserManager.removeLocalUser(userId);
2400 }
2401 delete e;
2402 return false;
2403 }
2404
2405 pSock->SecureStop();
2406 u->SetSecure(false);
2407 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2408 Licq::PluginSignal::SignalUser,
2409 Licq::PluginSignal::UserSecurity, u->id(), 0));
2410
2411 u.unlock();
2412 if (bNewUser)
2413 Licq::gUserManager.removeLocalUser(userId);
2414
2415 // finish up
2416 e->mySubResult = Licq::Event::SubResultAccept;
2417 ProcessDoneEvent(e);
2418
2419 // get out of here now as we don't want standard ack processing
2420 return true;
2421 }
2422
2423 default:
2424 packet.log(Log::Unknown, "Unknown TCP Ack subcommand (%04x)",
2425 newCommand);
2426 errorOccured = true;
2427 }
2428
2429 char l[32] = "";
2430 if (licqChar == 'L')
2431 sprintf(l, " [Licq %s]", Licq::UserEvent::licqVersionToString(licqVersion).c_str());
2432
2433 // output the away message if there is one (ie if user status is not online)
2434 unsigned subResult;
2435 if (ackFlags == ICQ_TCPxACK_REFUSE)
2436 {
2437 gLog.info(tr("Refusal from %s (#%d)%s."), u->getAlias().c_str(), -theSequence, l);
2438 subResult = Licq::Event::SubResultRefuse;
2439 }
2440 else
2441 {
2442 // Update the away message if it's changed
2443 string awayMsg = gTranslator.toUtf8(message, u->userEncoding());
2444 if (u->autoResponse() != awayMsg)
2445 {
2446 u->setAutoResponse(awayMsg);
2447 u->SetShowAwayMsg(!awayMsg.empty());
2448 gLog.info(tr("Auto response from %s (#%d)%s."), u->getAlias().c_str(), -theSequence, l);
2449 }
2450
2451 switch(ackFlags)
2452 {
2453 case ICQ_TCPxACK_ONLINE:
2454 gLog.info(tr("Ack from %s (#%d)%s."), u->getAlias().c_str(), -theSequence, l);
2455 if (pExtendedAck && !pExtendedAck->accepted())
2456 subResult = Licq::Event::SubResultReturn;
2457 else
2458 subResult = Licq::Event::SubResultAccept;
2459 break;
2460 case ICQ_TCPxACK_AWAY:
2461 case ICQ_TCPxACK_NA:
2462 case ICQ_TCPxACK_OCCUPIEDx2: //auto decline due to occupied mode
2463 gLog.info(tr("Ack from %s (#%d)%s."), u->getAlias().c_str(), -theSequence, l);
2464 subResult = Licq::Event::SubResultRefuse;
2465 break;
2466 case ICQ_TCPxACK_OCCUPIED:
2467 case ICQ_TCPxACK_DND:
2468 gLog.info(tr("Returned from %s (#%d)%s."), u->getAlias().c_str(), -theSequence, l);
2469 subResult = Licq::Event::SubResultReturn;
2470 break;
2471 case ICQ_TCPxACK_OCCUPIEDxCAR:
2472 case ICQ_TCPxACK_DNDxCAR:
2473 gLog.info(tr("Custom %s response from %s (#%d)%s."),
2474 (ackFlags == ICQ_TCPxACK_DNDxCAR ? tr("DnD") : tr("Occupied")),
2475 u->getAlias().c_str(), -theSequence, l);
2476 subResult = Licq::Event::SubResultAccept; // FIXME: or should this be ACK_RETURN ?
2477 break;
2478 default:
2479 gLog.unknown(tr("Unknown ack flag from %s (#%d): %04x %s"),
2480 u->getAlias().c_str(), -theSequence, ackFlags, l);
2481 subResult = Licq::Event::SubResultAccept;
2482 }
2483 }
2484
2485 Licq::Event *e = DoneEvent(sockfd, theSequence, Licq::Event::ResultAcked);
2486 if (e != NULL)
2487 {
2488 e->m_pExtendedAck = pExtendedAck;
2489 e->mySubResult = subResult;
2490
2491 u.unlock();
2492 if (bNewUser)
2493 Licq::gUserManager.removeLocalUser(userId);
2494
2495 ProcessDoneEvent(e);
2496 return true;
2497 }
2498 else
2499 {
2500 gLog.warning(tr("Ack for unknown event."));
2501 errorOccured = true;
2502 delete pExtendedAck;
2503 }
2504 break;
2505 }
2506
2507 //-----CANCEL-----------------------------------------------------------------
2508 case ICQ_CMDxTCP_CANCEL:
2509 // If from a new user, ignore it
2510 if (bNewUser) break;
2511
2512 switch (newCommand)
2513 {
2514 case ICQ_CMDxSUB_CHAT:
2515 {
2516 gLog.info(tr("Chat request from %s (%s) cancelled."),
2517 u->getAlias().c_str(), userId.toString().c_str());
2518 if (nInVersion < 6)
2519 {
2520 packet >> junkLong >> junkLong >> junkShort >> junkChar;
2521 if (packet.getDataPosRead() + 4 >
2522 (packet.getDataStart() + packet.getDataSize()))
2523 {
2524 theSequence = (signed short)packet.UnpackUnsignedShort();
2525 }
2526 else
2527 packet >> theSequence;
2528 }
2529
2530 for (unsigned short i = 0; i < u->NewMessages(); i++)
2531 {
2532 if (u->EventPeek(i)->Sequence() == theSequence)
2533 {
2534 u->CancelEvent(i);
2535 break;
2536 }
2537 }
2538 break;
2539 }
2540 case ICQ_CMDxSUB_FILE:
2541 {
2542 gLog.info(tr("File transfer request from %s (%s) cancelled."),
2543 u->getAlias().c_str(), userId.toString().c_str());
2544 if (nInVersion < 6)
2545 {
2546 packet >> junkLong >> junkShort >> junkChar >> junkLong >> junkLong;
2547 if (packet.getDataPosRead() + 4 >
2548 (packet.getDataStart() + packet.getDataSize()))
2549 {
2550 theSequence = (signed short)packet.UnpackUnsignedShort();
2551 }
2552 else
2553 packet >> theSequence;
2554 }
2555
2556 for (unsigned short i = 0; i < u->NewMessages(); i++)
2557 {
2558 if (u->EventPeek(i)->Sequence() == theSequence)
2559 {
2560 u->CancelEvent(i);
2561 break;
2562 }
2563 }
2564 break;
2565 }
2566
2567 default:
2568 break;
2569 }
2570
2571 break;
2572
2573 default:
2574 packet.log(Log::Unknown, "Unknown TCP packet (command 0x%04x)",
2575 command);
2576 errorOccured = true;
2577 break;
2578 }
2579
2580 }
2581 if (bNewUser)
2582 {
2583 u.unlock();
2584 Licq::gUserManager.removeLocalUser(userId);
2585 return false;
2586 }
2587 return !errorOccured;
2588 }
2589
processPluginMessage(CBuffer & packet,User * u,int channel,bool bIsAck,unsigned long nMsgID1,unsigned long nMsgID2,unsigned short nSequence,Licq::TCPSocket * pSock)2590 bool IcqProtocol::processPluginMessage(CBuffer &packet, User* u,
2591 int channel,
2592 bool bIsAck,
2593 unsigned long nMsgID1,
2594 unsigned long nMsgID2,
2595 unsigned short nSequence,
2596 Licq::TCPSocket* pSock)
2597 {
2598 bool errorOccured = false;
2599
2600 switch (channel)
2601 {
2602 case DcSocket::ChannelInfo:
2603 {
2604 packet.incDataPosRead(2);
2605 char error_level = packet.UnpackChar();
2606
2607 if (!bIsAck)
2608 {
2609 if (error_level != ICQ_PLUGIN_REQUEST)
2610 {
2611 gLog.warning(tr("Info plugin request with unknown level %u from %s."),
2612 error_level, u->getAlias().c_str());
2613 errorOccured = true;
2614 break;
2615 }
2616 char GUID[GUID_LENGTH];
2617 for (int i = 0 ; i < GUID_LENGTH; i ++)
2618 packet >> GUID[i];
2619
2620 if (memcmp(GUID, PLUGIN_QUERYxINFO, GUID_LENGTH) == 0)
2621 {
2622 gLog.info(tr("Info plugin list request from %s."), u->getAlias().c_str());
2623 if (pSock)
2624 {
2625 CPT_InfoPluginListResp p(u, nSequence);
2626 AckTCP(p, pSock);
2627 }
2628 else
2629 {
2630 CPU_InfoPluginListResp *p = new CPU_InfoPluginListResp(u, nMsgID1,
2631 nMsgID2, nSequence);
2632 SendEvent_Server(p);
2633 }
2634 }
2635 else if (memcmp(GUID, PLUGIN_PHONExBOOK, GUID_LENGTH) == 0)
2636 {
2637 gLog.info(tr("Phone Book request from %s."), u->getAlias().c_str());
2638 if (pSock)
2639 {
2640 CPT_InfoPhoneBookResp p(u, nSequence);
2641 AckTCP(p, pSock);
2642 }
2643 else
2644 {
2645 CPU_InfoPhoneBookResp *p = new CPU_InfoPhoneBookResp(u, nMsgID1,
2646 nMsgID2, nSequence);
2647 SendEvent_Server(p);
2648 }
2649 }
2650 else if (memcmp(GUID, PLUGIN_PICTURE, GUID_LENGTH) == 0)
2651 {
2652 gLog.info(tr("Picture request from %s."), u->getAlias().c_str());
2653
2654 if (pSock)
2655 {
2656 CPT_InfoPictureResp p(u, nSequence);
2657 AckTCP(p, pSock);
2658 }
2659 else
2660 {
2661 CPU_InfoPictureResp *p = new CPU_InfoPictureResp(u, nMsgID1, nMsgID2,
2662 nSequence);
2663 SendEvent_Server(p);
2664 }
2665 }
2666 else
2667 {
2668 gLog.warning(tr("Unknown info request from %s."), u->getAlias().c_str());
2669 if (pSock)
2670 {
2671 CPT_PluginError p(u, nSequence, DcSocket::ChannelInfo);
2672 AckTCP(p, pSock);
2673 }
2674 else
2675 {
2676 CPU_PluginError *p = new CPU_PluginError(u, nMsgID1, nMsgID2, nSequence,
2677 PLUGIN_INFOxMANAGER);
2678 SendEvent_Server(p);
2679 }
2680 errorOccured = true;
2681 }
2682 }
2683 else
2684 {
2685 Licq::Event::ResultType result;
2686
2687 switch (error_level)
2688 {
2689 case ICQ_PLUGIN_SUCCESS:
2690 {
2691 packet.incDataPosRead(4); //Unknown
2692 //Time of last update
2693 unsigned long nTime = packet.UnpackUnsignedLong();
2694 if (nTime == u->ClientInfoTimestamp())
2695 u->SetOurClientInfoTimestamp(nTime);
2696
2697 //bytes remaining in packet
2698 unsigned long len = packet.UnpackUnsignedLong();
2699 if (len < 8)
2700 {
2701 //this could be no plugins or no picture, need to check
2702 Licq::Event* e = pSock ? DoneEvent(pSock->Descriptor(), nSequence,
2703 Licq::Event::ResultAcked) :
2704 DoneServerEvent(nMsgID2, Licq::Event::ResultAcked);
2705
2706 if (e == NULL)
2707 {
2708 gLog.warning(tr("Ack for unknown event from %s."), u->getAlias().c_str());
2709 return true;
2710 }
2711
2712 const char *GUID;
2713 CPacketTcp* packetTcp = dynamic_cast<CPacketTcp*>(e->m_pPacket);
2714 if (e->SNAC() ==
2715 MAKESNAC(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SENDxSERVER) &&
2716 e->ExtraInfo() == ServerInfoPluginRequest)
2717 {
2718 GUID = ((CPU_InfoPluginReq *)e->m_pPacket)->RequestGUID();
2719 }
2720 else if (packetTcp != NULL && packetTcp->channel() == DcSocket::ChannelInfo &&
2721 e->ExtraInfo() == DirectInfoPluginRequest)
2722 {
2723 GUID = ((CPT_InfoPluginReq *)e->m_pPacket)->RequestGUID();
2724 }
2725 else
2726 {
2727 gLog.warning(tr("Ack for the wrong event from %s."), u->getAlias().c_str());
2728 delete e;
2729 return true;
2730 }
2731
2732 if (memcmp(GUID, PLUGIN_PICTURE, GUID_LENGTH) == 0)
2733 {
2734 gLog.info(tr("%s has no picture."), u->getAlias().c_str());
2735
2736 if (remove(u->pictureFileName().c_str()) != 0 && errno != ENOENT)
2737 {
2738 gLog.error(tr("Unable to delete %s's picture file (%s): %s."),
2739 u->getAlias().c_str(), u->pictureFileName().c_str(), strerror(errno));
2740 }
2741
2742 u->SetEnableSave(false);
2743 u->SetPicturePresent(false);
2744 u->SetEnableSave(true);
2745 u->save(Licq::User::SavePictureInfo);
2746
2747 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2748 Licq::PluginSignal::SignalUser,
2749 Licq::PluginSignal::UserPicture, u->id()));
2750 }
2751 else if (memcmp(GUID, PLUGIN_QUERYxINFO, GUID_LENGTH) == 0)
2752 {
2753 gLog.info(tr("%s has no info plugins."), u->getAlias().c_str());
2754 }
2755 else
2756 {
2757 gLog.unknown(tr("Unknown info response with no data from %s."), u->getAlias().c_str());
2758 }
2759
2760 ProcessDoneEvent(e);
2761 return false;
2762 }
2763 else
2764 {
2765 unsigned long nRequest = packet.UnpackUnsignedLong();
2766 unsigned long nEntries = packet.UnpackUnsignedLong();
2767 switch (nRequest)
2768 {
2769 case ICQ_PLUGIN_RESP_INFOxLIST:
2770 case ICQ_PLUGIN_RESP_INFOxLISTx0:
2771 {
2772 for (; nEntries > 0; nEntries --)
2773 {
2774 packet.incDataPosRead(GUID_LENGTH); // GUID of plugin
2775 packet.incDataPosRead(4); //Unknown
2776 string name = packet.unpackLongStringLE();
2777 string fullName = packet.unpackLongStringLE();
2778
2779 packet.incDataPosRead(4); //Unknown (always 0?)
2780
2781 gLog.info(tr("%s has %s (%s)."), u->getAlias().c_str(), name.c_str(), fullName.c_str());
2782 }
2783 break;
2784 }
2785
2786 case ICQ_PLUGIN_RESP_PHONExBOOK:
2787 {
2788 gLog.info(tr("Phone Book reply from %s."), u->getAlias().c_str());
2789 struct Licq::PhoneBookEntry* pb = new Licq::PhoneBookEntry[nEntries];
2790 char* buf;
2791 for (unsigned long i = 0; i < nEntries; i ++)
2792 {
2793 unsigned long nLen = packet.UnpackUnsignedLong();
2794 buf = new char[nLen + 1];
2795 for (unsigned long j = 0; j < nLen; j++)
2796 packet >> buf[j];
2797 buf[nLen] = '\0';
2798 pb[i].description = buf;
2799 delete[] buf;
2800
2801 nLen = packet.UnpackUnsignedLong();
2802 buf = new char[nLen + 1];
2803 for (unsigned long j = 0; j < nLen; j++)
2804 packet >> buf[j];
2805 buf[nLen] = '\0';
2806 pb[i].areaCode = buf;
2807 delete[] buf;
2808
2809 nLen = packet.UnpackUnsignedLong();
2810 buf = new char[nLen + 1];
2811 for (unsigned long j = 0; j < nLen; j++)
2812 packet >> buf[j];
2813 buf[nLen] = '\0';
2814 pb[i].phoneNumber = buf;
2815 delete[] buf;
2816
2817 nLen = packet.UnpackUnsignedLong();
2818 buf = new char[nLen + 1];
2819 for (unsigned long j = 0; j < nLen; j++)
2820 packet >> buf[j];
2821 buf[nLen] = '\0';
2822 pb[i].extension = buf;
2823 delete[] buf;
2824
2825 nLen = packet.UnpackUnsignedLong();
2826 buf = new char[nLen + 1];
2827 for (unsigned long j = 0; j < nLen; j++)
2828 packet >> buf[j];
2829 buf[nLen] = '\0';
2830 pb[i].country = buf;
2831 delete[] buf;
2832
2833 pb[i].nActive = packet.UnpackUnsignedLong();
2834 }
2835 for (unsigned long i = 0; i < nEntries; i ++)
2836 {
2837 packet.UnpackUnsignedLong(); // entry length
2838
2839 pb[i].nType = packet.UnpackUnsignedLong();
2840
2841 unsigned long nLen = packet.UnpackUnsignedLong();
2842 buf = new char[nLen + 1];
2843 for (unsigned long j = 0; j < nLen; j++)
2844 packet >> buf[j];
2845 buf[nLen] = '\0';
2846 pb[i].gateway = buf;
2847 delete[] buf;
2848
2849 pb[i].nGatewayType = packet.UnpackUnsignedLong();
2850 pb[i].nSmsAvailable = packet.UnpackUnsignedLong();
2851 pb[i].nRemoveLeading0s = packet.UnpackUnsignedLong();
2852 pb[i].nPublish = packet.UnpackUnsignedLong();
2853 }
2854
2855 u->SetEnableSave(false);
2856 u->getPhoneBook().clear();
2857 for (unsigned long i = 0; i < nEntries; i++)
2858 {
2859 u->getPhoneBook().push_back(pb[i]);
2860 }
2861 u->SetEnableSave(true);
2862 u->save(User::SaveUserInfo);
2863 delete [] pb;
2864
2865 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2866 Licq::PluginSignal::SignalUser,
2867 Licq::PluginSignal::UserInfo, u->id()));
2868 break;
2869 }
2870
2871 case ICQ_PLUGIN_RESP_PICTURE:
2872 {
2873 gLog.info(tr("Picture reply from %s."), u->getAlias().c_str());
2874 packet.incDataPosRead(nEntries); // filename, don't care
2875 unsigned long nLen = packet.UnpackUnsignedLong();
2876 if (nLen == 0) // do not create empty .pic files
2877 break;
2878
2879 int nFD = open(u->pictureFileName().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 00664);
2880 if (nFD == -1)
2881 {
2882 gLog.error(tr("Unable to open picture file (%s): %s."),
2883 u->pictureFileName().c_str(), strerror(errno));
2884 break;
2885 }
2886
2887 string data = packet.unpackRawString(nLen);
2888 write(nFD, data.c_str(), nLen);
2889 close(nFD);
2890
2891 u->SetEnableSave(false);
2892 u->SetPicturePresent(true);
2893 u->SetEnableSave(true);
2894 u->save(Licq::User::SavePictureInfo);
2895
2896 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
2897 Licq::PluginSignal::SignalUser,
2898 Licq::PluginSignal::UserPicture, u->id()));
2899 break;
2900 }
2901 }
2902 }
2903
2904 result = Licq::Event::ResultAcked;
2905 break;
2906 }
2907 case ICQ_PLUGIN_ERROR:
2908 {
2909 gLog.warning(tr("Info plugin not available from %s."), u->getAlias().c_str());
2910 result = Licq::Event::ResultError;
2911 break;
2912 }
2913 case ICQ_PLUGIN_REJECTED:
2914 {
2915 gLog.info(tr("%s refused our request."), u->getAlias().c_str());
2916 result = Licq::Event::ResultFailed;
2917 break;
2918 }
2919 case ICQ_PLUGIN_AWAY:
2920 {
2921 gLog.info(tr("Our request was refused because %s is away."), u->getAlias().c_str());
2922 result = Licq::Event::ResultFailed;
2923 break;
2924 }
2925 default:
2926 {
2927 gLog.warning(tr("Unknown reply level %u from %s"),
2928 error_level, u->getAlias().c_str());
2929 errorOccured = true;
2930 result = Licq::Event::ResultError;
2931 break;
2932 }
2933 }
2934
2935 Licq::Event* e = pSock ? DoneEvent(pSock->Descriptor(), nSequence,
2936 result) :
2937 DoneServerEvent(nMsgID2, result);
2938 if (e == NULL)
2939 gLog.warning(tr("Ack for unknown event from %s."), u->getAlias().c_str());
2940 else
2941 ProcessDoneEvent(e);
2942
2943 }
2944
2945 break;
2946 }
2947 case DcSocket::ChannelStatus:
2948 {
2949 packet.incDataPosRead(2);
2950 char error_level = packet.UnpackChar();
2951
2952 if (!bIsAck)
2953 {
2954 if (error_level != ICQ_PLUGIN_REQUEST)
2955 {
2956 gLog.warning(tr("Unknown status plugin request level %u from %s."),
2957 error_level, u->getAlias().c_str());
2958 errorOccured = true;
2959 break;
2960 }
2961
2962 char GUID[GUID_LENGTH];
2963 for (int i = 0 ; i < GUID_LENGTH; i ++)
2964 packet >> GUID[i];
2965
2966 if (memcmp(GUID, PLUGIN_QUERYxSTATUS, GUID_LENGTH) == 0)
2967 {
2968 gLog.info(tr("Status plugin list request from %s."), u->getAlias().c_str());
2969 if (pSock)
2970 {
2971 CPT_StatusPluginListResp p(u, nSequence);
2972 AckTCP(p, pSock);
2973 }
2974 else
2975 {
2976 CPU_StatusPluginListResp *p = new CPU_StatusPluginListResp(u, nMsgID1,
2977 nMsgID2, nSequence);
2978 SendEvent_Server(p);
2979 }
2980 }
2981 else if (memcmp(GUID, PLUGIN_FILExSERVER, GUID_LENGTH) == 0)
2982 {
2983 gLog.info(tr("File server status request from %s."), u->getAlias().c_str());
2984 unsigned long nStatus;
2985 {
2986 OwnerReadGuard o(myOwnerId);
2987 switch (o->sharedFilesStatus())
2988 {
2989 case IcqPluginActive: nStatus = ICQ_PLUGIN_STATUSxACTIVE; break;
2990 case IcqPluginBusy: nStatus = ICQ_PLUGIN_STATUSxBUSY; break;
2991 default: nStatus = ICQ_PLUGIN_STATUSxINACTIVE; break;
2992 }
2993 }
2994 if (pSock)
2995 {
2996 CPT_StatusPluginResp p(u, nSequence, nStatus);
2997 AckTCP(p, pSock);
2998 }
2999 else
3000 {
3001 CPU_StatusPluginResp *p = new CPU_StatusPluginResp(u, nMsgID1, nMsgID2,
3002 nSequence, nStatus);
3003 SendEvent_Server(p);
3004 }
3005 }
3006 else if (memcmp(GUID, PLUGIN_ICQxPHONE, GUID_LENGTH) == 0)
3007 {
3008 gLog.info(tr("ICQphone status request from %s."), u->getAlias().c_str());
3009 unsigned long nStatus;
3010 {
3011 OwnerReadGuard o(myOwnerId);
3012 switch (o->icqPhoneStatus())
3013 {
3014 case IcqPluginActive: nStatus = ICQ_PLUGIN_STATUSxACTIVE; break;
3015 case IcqPluginBusy: nStatus = ICQ_PLUGIN_STATUSxBUSY; break;
3016 default: nStatus = ICQ_PLUGIN_STATUSxINACTIVE; break;
3017 }
3018 }
3019 if (pSock)
3020 {
3021 CPT_StatusPluginResp p(u, nSequence, nStatus);
3022 AckTCP(p, pSock);
3023 }
3024 else
3025 {
3026 CPU_StatusPluginResp *p = new CPU_StatusPluginResp(u, nMsgID1, nMsgID2,
3027 nSequence, nStatus);
3028 SendEvent_Server(p);
3029 }
3030 }
3031 else if (memcmp(GUID, PLUGIN_FOLLOWxME, GUID_LENGTH) == 0)
3032 {
3033 gLog.info(tr("Phone \"Follow Me\" status request from %s."), u->getAlias().c_str());
3034 unsigned long nStatus;
3035 {
3036 OwnerReadGuard o(myOwnerId);
3037 switch (o->phoneFollowMeStatus())
3038 {
3039 case IcqPluginActive: nStatus = ICQ_PLUGIN_STATUSxACTIVE; break;
3040 case IcqPluginBusy: nStatus = ICQ_PLUGIN_STATUSxBUSY; break;
3041 default: nStatus = ICQ_PLUGIN_STATUSxINACTIVE; break;
3042 }
3043 }
3044 if (pSock)
3045 {
3046 CPT_StatusPluginResp p(u, nSequence, nStatus);
3047 AckTCP(p, pSock);
3048 }
3049 else
3050 {
3051 CPU_StatusPluginResp *p = new CPU_StatusPluginResp(u, nMsgID1, nMsgID2,
3052 nSequence, nStatus);
3053 SendEvent_Server(p);
3054 }
3055 }
3056 else
3057 {
3058 gLog.warning(tr("Unknown status request from %s."), u->getAlias().c_str());
3059 if (pSock)
3060 {
3061 CPT_PluginError p(u, nSequence, DcSocket::ChannelStatus);
3062 AckTCP(p, pSock);
3063 }
3064 else
3065 {
3066 CPU_PluginError *p = new CPU_PluginError(u, nMsgID1, nMsgID2, nSequence,
3067 PLUGIN_STATUSxMANAGER);
3068 SendEvent_Server(p);
3069 }
3070 errorOccured = true;
3071 }
3072 }
3073 else
3074 {
3075 Licq::Event::ResultType result;
3076
3077 switch (error_level)
3078 {
3079 case ICQ_PLUGIN_SUCCESS:
3080 {
3081 packet.incDataPosRead(13); //Unknown
3082 //Time of last installation of new status plugins
3083 unsigned long nTime = packet.UnpackUnsignedLong();
3084 if (nTime == u->ClientStatusTimestamp())
3085 u->SetOurClientStatusTimestamp(nTime);
3086
3087 //bytes remaining in packet
3088 unsigned long len = packet.UnpackUnsignedLong();
3089 if (len < 8)
3090 {
3091 gLog.info(tr("%s has no status plugins.\n"), u->getAlias().c_str());
3092 }
3093 else
3094 {
3095 packet.incDataPosRead(4); // Unknown
3096 unsigned long nEntries = packet.UnpackUnsignedLong();
3097 for (; nEntries > 0; nEntries --)
3098 {
3099 packet.incDataPosRead(GUID_LENGTH); // GUID of plugin
3100 packet.incDataPosRead(4); //Unknown
3101 string name = packet.unpackLongStringLE();
3102 string fullName = packet.unpackLongStringLE();
3103
3104 packet.incDataPosRead(4); //Unknown (always 0?)
3105
3106 gLog.info(tr("%s has %s (%s)."), u->getAlias().c_str(), name.c_str(), fullName.c_str());
3107 }
3108 }
3109
3110 result = Licq::Event::ResultAcked;
3111 break;
3112 }
3113 case ICQ_PLUGIN_STATUSxREPLY:
3114 {
3115 Licq::Event* e = pSock ? DoneEvent(pSock->Descriptor(), nSequence,
3116 Licq::Event::ResultAcked) :
3117 DoneServerEvent(nMsgID2, Licq::Event::ResultAcked);
3118
3119 if (e == NULL)
3120 {
3121 gLog.warning(tr("Ack for unknown event from %s."), u->getAlias().c_str());
3122 return true;
3123 }
3124
3125 const char *GUID;
3126 CPacketTcp* packetTcp = dynamic_cast<CPacketTcp*>(e->m_pPacket);
3127 if (e->SNAC() ==
3128 MAKESNAC(ICQ_SNACxFAM_MESSAGE, ICQ_SNACxMSG_SENDxSERVER) &&
3129 e->ExtraInfo() == ServerStatusPluginRequest)
3130 {
3131 GUID = ((CPU_StatusPluginReq *)e->m_pPacket)->RequestGUID();
3132 }
3133 else if (packetTcp != NULL && packetTcp->channel() == DcSocket::ChannelInfo &&
3134 e->ExtraInfo() == DirectStatusPluginRequest)
3135 {
3136 GUID = ((CPT_StatusPluginReq *)e->m_pPacket)->RequestGUID();
3137 }
3138 else
3139 {
3140 gLog.warning(tr("Ack for the wrong event from %s."), u->getAlias().c_str());
3141 delete e;
3142 return true;
3143 }
3144
3145 packet.incDataPosRead(4); // Unknown
3146 unsigned long nState = packet.UnpackUnsignedLong();
3147 unsigned long nTime = packet.UnpackUnsignedLong();
3148
3149 if (nTime == u->ClientStatusTimestamp())
3150 u->SetOurClientStatusTimestamp(nTime);
3151
3152 const char* szState;
3153 unsigned pluginState;
3154 switch (nState)
3155 {
3156 case ICQ_PLUGIN_STATUSxINACTIVE:
3157 szState = "inactive";
3158 pluginState = IcqPluginInactive;
3159 break;
3160 case ICQ_PLUGIN_STATUSxACTIVE:
3161 szState = "active";
3162 pluginState = IcqPluginActive;
3163 break;
3164 case ICQ_PLUGIN_STATUSxBUSY:
3165 szState = "busy";
3166 pluginState = IcqPluginBusy;
3167 break;
3168 default:
3169 szState = "unknown";
3170 pluginState = IcqPluginInactive;
3171 break;
3172 }
3173
3174 if (memcmp(GUID, PLUGIN_FILExSERVER, GUID_LENGTH) == 0)
3175 {
3176 gLog.info(tr("%s's Shared Files Directory is %s."), u->getAlias().c_str(), szState);
3177 u->setSharedFilesStatus(pluginState);
3178 }
3179 else if (memcmp(GUID, PLUGIN_FOLLOWxME, GUID_LENGTH) == 0)
3180 {
3181 gLog.info(tr("%s's Phone \"Follow Me\" is %s."), u->getAlias().c_str(), szState);
3182 u->setPhoneFollowMeStatus(pluginState);
3183 }
3184 else if (memcmp(GUID, PLUGIN_ICQxPHONE, GUID_LENGTH) == 0)
3185 {
3186 gLog.info(tr("%s's ICQphone is %s."), u->getAlias().c_str(), szState);
3187 u->setIcqPhoneStatus(pluginState);
3188 }
3189
3190 // Which plugin?
3191 Licq::gPluginManager.pushPluginSignal(new Licq::PluginSignal(
3192 Licq::PluginSignal::SignalUser,
3193 Licq::PluginSignal::UserPluginStatus, u->id(), 0));
3194
3195 ProcessDoneEvent(e);
3196 return false;
3197 }
3198 case ICQ_PLUGIN_ERROR:
3199 {
3200 gLog.warning(tr("Status plugin not available from %s."), u->getAlias().c_str());
3201 result = Licq::Event::ResultError;
3202 break;
3203 }
3204 case ICQ_PLUGIN_REJECTED:
3205 {
3206 gLog.info(tr("%s refused our request."), u->getAlias().c_str());
3207 result = Licq::Event::ResultFailed;
3208 break;
3209 }
3210 case ICQ_PLUGIN_AWAY:
3211 {
3212 gLog.info(tr("Our request was refused because %s is away."), u->getAlias().c_str());
3213 result = Licq::Event::ResultFailed;
3214 break;
3215 }
3216 default:
3217 {
3218 gLog.warning(tr("Unknown reply level %u from %s"),
3219 error_level, u->getAlias().c_str());
3220 errorOccured = true;
3221 result = Licq::Event::ResultError;
3222 break;
3223 }
3224 }
3225
3226 Licq::Event* e = pSock ? DoneEvent(pSock->Descriptor(), nSequence,
3227 result) :
3228 DoneServerEvent(nMsgID2, result);
3229 if (e == NULL)
3230 gLog.warning(tr("Ack for unknown event from %s."), u->getAlias().c_str());
3231 else
3232 ProcessDoneEvent(e);
3233
3234 }
3235
3236 break;
3237 }
3238 default:
3239 {
3240 gLog.warning(tr("Unknown channel %u from %s"), channel, u->getAlias().c_str());
3241 if (!pSock)
3242 {
3243 CPU_NoManager *p = new CPU_NoManager(u, nMsgID1, nMsgID2);
3244 SendEvent_Server(p);
3245 }
3246
3247 errorOccured = true;
3248 break;
3249 }
3250 }
3251 return errorOccured;
3252 }
3253
3254 //-----CICQDaemon::AckTCP--------------------------------------------------------------
AckTCP(CPacketTcp & p,int nSd)3255 void IcqProtocol::AckTCP(CPacketTcp &p, int nSd)
3256 {
3257 #if ICQ_VERSION_TCP == 3
3258 Licq::TCPSocket* s = dynamic_cast<Licq::TCPSocket*>(gSocketManager.FetchSocket(nSD));
3259 if (s != NULL)
3260 {
3261 s->Send(p.getBuffer());
3262 gSocketManager.DropSocket(s);
3263 }
3264 #else
3265 SendEvent(nSd, p, false);
3266 #endif
3267 }
3268
AckTCP(CPacketTcp & p,Licq::TCPSocket * tcp)3269 void IcqProtocol::AckTCP(CPacketTcp &p, Licq::TCPSocket* tcp)
3270 {
3271 #if ICQ_VERSION_TCP == 3
3272 tcp->Send(p.getBuffer());
3273 #else
3274 SendEvent(tcp, p, false);
3275 #endif
3276 }
3277
Handshake_Recv(DcSocket * s,unsigned short nPort,bool bConfirm,bool bChat)3278 bool IcqProtocol::Handshake_Recv(DcSocket* s, unsigned short nPort, bool bConfirm, bool bChat)
3279 {
3280 char cHandshake;
3281 unsigned short nVersionMajor, nVersionMinor;
3282 CBuffer &b = s->RecvBuffer();
3283 b.unpackUInt16LE(); // Packet length
3284 b >> cHandshake >> nVersionMajor >> nVersionMinor;
3285
3286 unsigned long nUin = 0;
3287 unsigned short nVersion = 0;
3288 char id[16];
3289 Licq::UserId userId;
3290
3291 switch (IcqProtocol::dcVersionToUse(nVersionMajor))
3292 {
3293 case 8:
3294 case 7:
3295 {
3296 b.Reset();
3297 CPacketTcp_Handshake_v7 p_in(&b);
3298 nUin = p_in.SourceUin();
3299 snprintf(id, 16, "%lu", nUin);
3300 userId = Licq::UserId(myOwnerId, id);
3301
3302 unsigned long nCookie;
3303 {
3304 UserReadGuard u(userId);
3305 if (!u.isLocked() && !bChat)
3306 {
3307 gLog.warning(tr("Connection from unknown user."));
3308 return false;
3309 }
3310 nCookie = u.isLocked() ? u->Cookie() : 0;
3311 }
3312
3313 if (nCookie != p_in.SessionId())
3314 {
3315 gLog.warning(tr("Spoofed connection from %s as uin %s."),
3316 s->getRemoteIpString().c_str(), userId.toString().c_str());
3317 return false;
3318 }
3319
3320 // Send the ack
3321 CPacketTcp_Handshake_Ack p_ack;
3322 if (!s->send(*p_ack.getBuffer()))
3323 goto sock_error;
3324
3325 // Send the handshake
3326 CPacketTcp_Handshake_v7 p_out(nUin, p_in.SessionId(), nPort);
3327 if (!s->send(*p_out.getBuffer()))
3328 goto sock_error;
3329
3330 // Wait for the ack (this is very bad form...blocking recv here)
3331 s->ClearRecvBuffer();
3332 do
3333 {
3334 if (!s->RecvPacket()) goto sock_error;
3335 } while (!s->RecvBufferFull());
3336
3337 if (s->RecvBuffer().getDataSize() != 6)
3338 {
3339 gLog.warning(tr("Handshake ack not the right size."));
3340 return false;
3341 }
3342
3343 s->RecvBuffer().unpackUInt16LE(); // Packet length
3344 unsigned long nOk = s->RecvBuffer().UnpackUnsignedLong();
3345 if (nOk != 1)
3346 {
3347 gLog.warning(tr("Bad handshake ack: %ld."), nOk);
3348 return false;
3349 }
3350
3351 if (bConfirm)
3352 {
3353 if (p_in.Id() == 0)
3354 {
3355 if (!Handshake_RecvConfirm_v7(s))
3356 goto sock_error;
3357 }
3358 else
3359 {
3360 pthread_mutex_lock(&mutex_reverseconnect);
3361 std::list<CReverseConnectToUserData *>::iterator iter;
3362 for (iter = m_lReverseConnect.begin(); ; ++iter)
3363 {
3364 if (iter == m_lReverseConnect.end())
3365 {
3366 gLog.warning(tr("Reverse connection with unknown id (%lu)"), p_in.Id());
3367 pthread_mutex_unlock(&mutex_reverseconnect);
3368 return false;
3369 }
3370 if ((*iter)->nId == p_in.Id() && (*iter)->myIdString == id)
3371 {
3372 s->setChannel((*iter)->nData);
3373 (*iter)->bSuccess = true;
3374 (*iter)->bFinished = true;
3375 if (!Handshake_SendConfirm_v7(s))
3376 {
3377 pthread_mutex_unlock(&mutex_reverseconnect);
3378 return false;
3379 }
3380 break;
3381 }
3382 }
3383 pthread_mutex_unlock(&mutex_reverseconnect);
3384 }
3385 }
3386
3387 nVersion = IcqProtocol::dcVersionToUse(nVersionMajor);
3388
3389 break;
3390 }
3391
3392 case 6:
3393 {
3394 b.Reset();
3395 CPacketTcp_Handshake_v6 p_in(&b);
3396 nUin = p_in.SourceUin();
3397 snprintf(id, 16, "%lu", nUin);
3398 userId = Licq::UserId(myOwnerId, id);
3399
3400 unsigned long nCookie;
3401 {
3402 UserReadGuard u(userId);
3403 if (!u.isLocked())
3404 {
3405 gLog.warning(tr("Connection from unknown user."));
3406 return false;
3407 }
3408 nCookie = u->Cookie();
3409 }
3410
3411 if (nCookie != p_in.SessionId())
3412 {
3413 gLog.warning(tr("Spoofed connection from %s as uin %s."),
3414 s->getRemoteIpString().c_str(), userId.toString().c_str());
3415 return false;
3416 }
3417
3418 // Send the ack
3419 CPacketTcp_Handshake_Ack p_ack;
3420 if (!s->send(*p_ack.getBuffer()))
3421 goto sock_error;
3422
3423 // Send the handshake
3424 CPacketTcp_Handshake_v6 p_out(nUin, p_in.SessionId(), nPort);
3425 if (!s->send(*p_out.getBuffer()))
3426 goto sock_error;
3427
3428 // Wait for the ack (this is very bad form...blocking recv here)
3429 s->ClearRecvBuffer();
3430 do
3431 {
3432 if (!s->RecvPacket()) goto sock_error;
3433 } while (!s->RecvBufferFull());
3434 s->RecvBuffer().unpackUInt16LE(); // Packet length
3435 unsigned long nOk = s->RecvBuffer().UnpackUnsignedLong();
3436 s->ClearRecvBuffer();
3437 if (nOk != 1)
3438 {
3439 gLog.warning(tr("Bad handshake ack: %ld."), nOk);
3440 return false;
3441 }
3442 nVersion = 6;
3443
3444 pthread_mutex_lock(&mutex_reverseconnect);
3445 std::list<CReverseConnectToUserData *>::iterator iter;
3446 for (iter = m_lReverseConnect.begin(); iter != m_lReverseConnect.end();
3447 ++iter)
3448 {
3449 // For v6 there is no connection id, so just use uin
3450 if ((*iter)->myIdString == id)
3451 {
3452 (*iter)->bSuccess = true;
3453 (*iter)->bFinished = true;
3454 break;
3455 }
3456 }
3457 pthread_mutex_unlock(&mutex_reverseconnect);
3458
3459 break;
3460 }
3461
3462 case 5:
3463 case 4:
3464 {
3465 b.UnpackUnsignedLong(); // port number
3466 nUin = b.UnpackUnsignedLong();
3467 snprintf(id, 16, "%lu", nUin);
3468 userId = Licq::UserId(myOwnerId, id);
3469 nVersion = IcqProtocol::dcVersionToUse(nVersionMajor);
3470
3471 unsigned long nIntIp;
3472 unsigned long nIp;
3473 {
3474 Licq::UserReadGuard u(userId);
3475 if (!u.isLocked())
3476 {
3477 gLog.warning(tr("Connection from unknown user."));
3478 return false;
3479 }
3480 nIntIp = u->IntIp();
3481 nIp = u->Ip();
3482 }
3483 /* This might prevent connections from clients behind assymetric
3484 connections (i.e. direct to ICQ server and through socks to clients)
3485 but they should be using v6+ anyway */
3486 if (nIntIp != s->getRemoteIpInt() && nIp != s->getRemoteIpInt())
3487 {
3488 gLog.warning(tr("Connection from %s as %s possible spoof."),
3489 s->getRemoteIpString().c_str(), userId.toString().c_str());
3490 return false;
3491 }
3492
3493 pthread_mutex_lock(&mutex_reverseconnect);
3494 std::list<CReverseConnectToUserData *>::iterator iter;
3495 for (iter = m_lReverseConnect.begin(); iter != m_lReverseConnect.end();
3496 ++iter)
3497 {
3498 // For v4 there is no connection id, so just use uin
3499 if ((*iter)->myIdString == id)
3500 {
3501 (*iter)->bSuccess = true;
3502 (*iter)->bFinished = true;
3503 break;
3504 }
3505 }
3506 pthread_mutex_unlock(&mutex_reverseconnect);
3507
3508 break;
3509 }
3510
3511 case 3:
3512 case 2:
3513 case 1:
3514 {
3515 b.UnpackUnsignedLong(); // port number
3516 nUin = b.UnpackUnsignedLong();
3517 snprintf(id, 16, "%lu", nUin);
3518 userId = Licq::UserId(myOwnerId, id);
3519 nVersion = 2;
3520
3521 unsigned long nIntIp;
3522 unsigned long nIp;
3523 {
3524 Licq::UserReadGuard u(userId);
3525 if (!u.isLocked())
3526 {
3527 gLog.warning(tr("Connection from unknown user."));
3528 return false;
3529 }
3530 nIntIp = u->IntIp();
3531 nIp = u->Ip();
3532 }
3533
3534 /* This might prevent connections from clients behind assymetric
3535 connections (i.e. direct to ICQ server and through socks to clients)
3536 but they should be using v6+ anyway */
3537 if (nIntIp != s->getRemoteIpInt() && nIp != s->getRemoteIpInt())
3538 {
3539 gLog.warning(tr("Connection from %s as %s possible spoof."),
3540 s->getRemoteIpString().c_str(), userId.toString().c_str());
3541 return false;
3542 }
3543
3544 pthread_mutex_lock(&mutex_reverseconnect);
3545 std::list<CReverseConnectToUserData *>::iterator iter;
3546 for (iter = m_lReverseConnect.begin(); iter != m_lReverseConnect.end();
3547 ++iter)
3548 {
3549 // For v2 there is no connection id, so just use uin
3550 if ((*iter)->myIdString == id)
3551 {
3552 (*iter)->bSuccess = true;
3553 (*iter)->bFinished = true;
3554 break;
3555 }
3556 }
3557 pthread_mutex_unlock(&mutex_reverseconnect);
3558
3559 break;
3560 }
3561
3562 default:
3563 b.log(Log::Unknown, "Unknown TCP handshake packet");
3564 return false;
3565 }
3566
3567 s->setUserId(userId);
3568 s->SetVersion(nVersion);
3569
3570 return true;
3571
3572 sock_error:
3573 if (s->Error() == 0)
3574 gLog.warning(tr("Handshake error, remote side closed connection."));
3575 else
3576 gLog.warning(tr("Handshake socket error: %s."), s->errorStr().c_str());
3577 return false;
3578 }
3579
Handshake_SendConfirm_v7(DcSocket * s)3580 bool IcqProtocol::Handshake_SendConfirm_v7(DcSocket* s)
3581 {
3582 // Send handshake accepted
3583 CPacketTcp_Handshake_Confirm p_confirm(s->channel(), 0);
3584 if (!s->send(*p_confirm.getBuffer()))
3585 return false;
3586
3587 // Wait for reverse handshake accepted
3588 s->ClearRecvBuffer();
3589 do
3590 {
3591 if (!s->RecvPacket())
3592 return false;
3593 } while (!s->RecvBufferFull());
3594 s->ClearRecvBuffer();
3595
3596 return true;
3597 }
3598
Handshake_RecvConfirm_v7(DcSocket * s)3599 bool IcqProtocol::Handshake_RecvConfirm_v7(DcSocket* s)
3600 {
3601 // Get handshake confirmation
3602 s->ClearRecvBuffer();
3603 do
3604 {
3605 if (!s->RecvPacket()) goto sock_error;
3606 } while (!s->RecvBufferFull());
3607
3608 { // damn scoping
3609 CBuffer &b = s->RecvBuffer();
3610 if (b.getDataSize() != 35)
3611 {
3612 gLog.warning(tr("Handshake confirm not the right size."));
3613 return false;
3614 }
3615 b.unpackUInt16LE(); // Packet length
3616 unsigned char c = b.UnpackChar();
3617 unsigned long l = b.UnpackUnsignedLong();
3618 if (c != 0x03 || l != 0x0000000A)
3619 {
3620 gLog.warning(tr("Unknown handshake response %2X,%8lX."), c, l);
3621 return false;
3622 }
3623 b.Reset();
3624 CPacketTcp_Handshake_Confirm p_confirm_in(&b);
3625 if (p_confirm_in.channel() != DcSocket::ChannelUnknown)
3626 s->setChannel(p_confirm_in.channel());
3627 else
3628 {
3629 gLog.warning(tr("Unknown channel in ack packet."));
3630 return false;
3631 }
3632
3633 s->ClearRecvBuffer();
3634
3635 CPacketTcp_Handshake_Confirm p_confirm_out(p_confirm_in.channel(),
3636 p_confirm_in.Id());
3637
3638 if (s->send(*p_confirm_out.getBuffer()))
3639 return true;
3640 }
3641
3642 sock_error:
3643 if (s->Error() == 0)
3644 gLog.warning(tr("Handshake error, remote side closed connection."));
3645 else
3646 gLog.warning(tr("Handshake socket error: %s."), s->errorStr().c_str());
3647 return false;
3648 }
3649
3650 /*------------------------------------------------------------------------------
3651 * ProcessTcpHandshake
3652 *
3653 * Takes the first buffer from a socket and parses it as a icq handshake.
3654 * Does not check that the given user already has a socket or not.
3655 *----------------------------------------------------------------------------*/
ProcessTcpHandshake(DcSocket * s)3656 bool IcqProtocol::ProcessTcpHandshake(DcSocket* s)
3657 {
3658 if (!Handshake_Recv(s, 0)) return false;
3659 Licq::UserId userId = s->userId();
3660 if (!userId.isValid())
3661 return false;
3662
3663 UserWriteGuard u(userId);
3664 if (u.isLocked())
3665 {
3666 gLog.info(tr("Connection from %s (%s) [v%ld]."),
3667 u->getAlias().c_str(), userId.toString().c_str(), s->Version());
3668 if (u->socketDesc(s->channel()) != s->Descriptor())
3669 {
3670 if (u->socketDesc(s->channel()) != -1)
3671 {
3672 gLog.warning(tr("User %s (%s) already has an associated socket."),
3673 u->getAlias().c_str(), userId.toString().c_str());
3674 return true;
3675 /* gSocketManager.CloseSocket(u->socketDesc(s->channel()), false);
3676 u->clearSocketDesc(s);*/
3677 }
3678 u->setSocketDesc(s);
3679 }
3680 }
3681 else
3682 {
3683 gLog.info(tr("Connection from new user (%s) [v%ld]."),
3684 userId.toString().c_str(), s->Version());
3685 }
3686
3687 //awaken waiting threads, maybe unnecessarily, but doesn't hurt
3688 pthread_cond_broadcast(&cond_reverseconnect_done);
3689
3690 return true;
3691 }
3692