Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

684 lines
16 KiB

  1. #include "stdafx.h"
  2. //
  3. // V5 Mirabulus ICQ encryption
  4. //
  5. static CHAR M_ICQ_TABLE[]={
  6. 0x59,0x60,0x37,0x6B,0x65,0x62,0x46,0x48,0x53,0x61,0x4C,0x59,0x60,0x57,0x5B,0x3D
  7. ,0x5E,0x34,0x6D,0x36,0x50,0x3F,0x6F,0x67,0x53,0x61,0x4C,0x59,0x40,0x47,0x63,0x39
  8. ,0x50,0x5F,0x5F,0x3F,0x6F,0x47,0x43,0x69,0x48,0x33,0x31,0x64,0x35,0x5A,0x4A,0x42
  9. ,0x56,0x40,0x67,0x53,0x41,0x07,0x6C,0x49,0x58,0x3B,0x4D,0x46,0x68,0x43,0x69,0x48
  10. ,0x33,0x31,0x44,0x65,0x62,0x46,0x48,0x53,0x41,0x07,0x6C,0x69,0x48,0x33,0x51,0x54
  11. ,0x5D,0x4E,0x6C,0x49,0x38,0x4B,0x55,0x4A,0x62,0x46,0x48,0x33,0x51,0x34,0x6D,0x36
  12. ,0x50,0x5F,0x5F,0x5F,0x3F,0x6F,0x47,0x63,0x59,0x40,0x67,0x33,0x31,0x64,0x35,0x5A
  13. ,0x6A,0x52,0x6E,0x3C,0x51,0x34,0x6D,0x36,0x50,0x5F,0x5F,0x3F,0x4F,0x37,0x4B,0x35
  14. ,0x5A,0x4A,0x62,0x66,0x58,0x3B,0x4D,0x66,0x58,0x5B,0x5D,0x4E,0x6C,0x49,0x58,0x3B
  15. ,0x4D,0x66,0x58,0x3B,0x4D,0x46,0x48,0x53,0x61,0x4C,0x59,0x40,0x67,0x33,0x31,0x64
  16. ,0x55,0x6A,0x32,0x3E,0x44,0x45,0x52,0x6E,0x3C,0x31,0x64,0x55,0x6A,0x52,0x4E,0x6C
  17. ,0x69,0x48,0x53,0x61,0x4C,0x39,0x30,0x6F,0x47,0x63,0x59,0x60,0x57,0x5B,0x3D,0x3E
  18. ,0x64,0x35,0x3A,0x3A,0x5A,0x6A,0x52,0x4E,0x6C,0x69,0x48,0x53,0x61,0x6C,0x49,0x58
  19. ,0x3B,0x4D,0x46,0x68,0x63,0x39,0x50,0x5F,0x5F,0x3F,0x6F,0x67,0x53,0x41,0x25,0x41
  20. ,0x3C,0x51,0x54,0x3D,0x5E,0x54,0x5D,0x4E,0x4C,0x39,0x50,0x5F,0x5F,0x5F,0x3F,0x6F
  21. ,0x47,0x43,0x69,0x48,0x33,0x51,0x54,0x5D,0x6E,0x3C,0x31,0x64,0x35,0x5A,0x00,0x00
  22. };
  23. int icq5_crypt(UCHAR *p,
  24. int len,
  25. int decrypt)
  26. /*++
  27. Routine Description:
  28. Arguments:
  29. none.
  30. Return Value:
  31. --*/
  32. {
  33. ULONG REALCHECKCODE,A1,A2,A3,A4,A5,DATA;
  34. ULONG CODE1,CODE2,CODE3,CHECKCODE,POS,N,PL,T;
  35. ULONG NUMBER1,NUMBER2,R1,R2;
  36. if (decrypt)
  37. {
  38. CHECKCODE = *(PULONG)(p+20);
  39. /*CHECKCODE = 0x89EC34FE;/**/
  40. A1 = CHECKCODE & 0x0001F000;
  41. A2 = CHECKCODE & 0x07C007C0;
  42. A3 = CHECKCODE & 0x003E0001;
  43. A4 = CHECKCODE & 0xF8000000;
  44. A5 = CHECKCODE & 0x0000083E;
  45. A1 = A1 >> 0x0C; // 12 Right
  46. A2 = A2 >> 0x01; // 1 Right
  47. A3 = A3 << 0x0A; // 10 Left
  48. A4 = A4 >> 0x10; // 16 Right
  49. A5 = A5 << 0x0F; // 15 Left
  50. REALCHECKCODE = A1 + A2 + A3 + A4 + A5;
  51. /*ICQ_TRC(TM_MSG, TL_TRACE,(" %x -> %x ", CHECKCODE, REALCHECKCODE);/**/
  52. CHECKCODE = REALCHECKCODE;
  53. }
  54. else
  55. {
  56. *(PULONG)(p+20) = 0L;
  57. NUMBER1 = (p[8]<<24) + (p[4]<<16) + (p[2]<<8) + p[6];
  58. PL = len;
  59. R1 = 24%(PL - 18); /* PL - 24 */
  60. R2 = 24%0x0100;
  61. NUMBER2 = ((R1<<24)&0xFF000000L) + (((~p[R1])<<16)&0x00FF0000L) + ((R2<<8)&0x0000FF00L) + ((~M_ICQ_TABLE[R2])&0x000000FFL);
  62. CHECKCODE = NUMBER1^NUMBER2;
  63. }
  64. PL = len;
  65. CODE1 = PL * 0x68656C6CL;
  66. CODE2 = CODE1 + CHECKCODE;
  67. N = PL + 0x03;
  68. POS = 0x0A;
  69. while (POS < N)
  70. {
  71. T = POS%0x0100;
  72. CODE3 = CODE2 + M_ICQ_TABLE[T];
  73. DATA = (*(PULONG)(p + POS));
  74. DATA ^= CODE3;
  75. *(PULONG)(p + POS) = (DATA);
  76. POS = POS + 4;
  77. }
  78. if (decrypt == 0)
  79. {
  80. A1 = CHECKCODE & 0x0000001F;
  81. A2 = CHECKCODE & 0x03E003E0;
  82. A3 = CHECKCODE & 0xF8000400;
  83. A4 = CHECKCODE & 0x0000F800;
  84. A5 = CHECKCODE & 0x041F0000;
  85. A1 = A1 << 0x0C;
  86. A2 = A2 << 0x01;
  87. A3 = A3 >> 0x0A;
  88. A4 = A4 << 0x10;
  89. A5 = A5 >> 0x0F;
  90. REALCHECKCODE = A1 + A2 + A3 + A4 + A5;
  91. /*ICQ_TRC(TM_MSG, TL_TRACE,(" %x -> %x ", CHECKCODE, REALCHECKCODE);/**/
  92. *(PULONG)(p+20) = REALCHECKCODE;
  93. }
  94. return 0;
  95. }
  96. ULONG
  97. _ICQ_CLIENT::IcqClientToServerUdp(
  98. PUCHAR buf,
  99. ULONG size
  100. )
  101. /*++
  102. Routine Description:
  103. Processes MEssages going from the CLient to the SErver.
  104. Especially the data where the Login Data is sent.
  105. This packet will contain the advertised port to which
  106. Peers will contact.
  107. Arguments:
  108. none.
  109. Return Value:
  110. --*/
  111. {
  112. ULONG Error = NO_ERROR;
  113. UCHAR bbuf[1024];
  114. PUCHAR tbuf = bbuf;
  115. USHORT port, NewExternalPort;
  116. ULONG clientUIN;
  117. ULONG BestSrcAdrr = 0L;
  118. //
  119. // version 5.0... written in the first two bytes.
  120. //
  121. if(buf[0] is 0x05 && buf[1] is 0x00)
  122. {
  123. //
  124. // STORE the original buffer in another place.
  125. //
  126. memcpy(tbuf, buf, size);
  127. icq5_crypt(buf, size, 1);
  128. //
  129. // ICQ login cmd
  130. //
  131. if(*(PUSHORT)(buf+14) is 0x03E8)
  132. {
  133. //
  134. // *(PUSHORT)(buf+28)
  135. //
  136. port = htons(*(PUSHORT)(buf+28));
  137. clientUIN = *(PULONG)(buf+6);
  138. ICQ_TRC(TM_MSG, TL_INFO,(" ICQ UIN is %lu", clientUIN));
  139. ICQ_TRC(TM_MSG, TL_INFO,(" ICQ TCP (client port is at) %hu", htons(port)));
  140. ICQ_TRC(TM_MSG, TL_INFO,(" ICQ password %s ", (buf +34)));
  141. //
  142. // IF we had enrolled previously then delete the old one and note
  143. // this new DETECT previous enrollment if we have redirection AND
  144. // an imitation port AND the client Peer port is different
  145. //
  146. if(this->IncomingPeerControlRedirectionp &&
  147. this->ImitatedPeerPort)
  148. {
  149. NewExternalPort = this->ImitatedPeerPort;
  150. }
  151. else
  152. {
  153. //
  154. // step 1 - reserve a port to be used for the redirection
  155. //
  156. Error = g_IAlgServicesp->ReservePort(1, &NewExternalPort);
  157. if( FAILED(Error) )
  158. {
  159. ICQ_TRC(TM_MSG, TL_ERROR,
  160. ("** !! ERROR - PORT RESERVATION HAS FAILED"));
  161. return E_FAIL;
  162. }
  163. //
  164. // Step 2 - Instantiate the Redirection
  165. // NOTE: RRAS problem here..
  166. //
  167. // Create on each Interface the Redirects that we see here.
  168. //
  169. BestSrcAdrr = g_MyPublicIp;
  170. this->IncomingPeerControlRedirectionp =
  171. PeerRedirection(BestSrcAdrr,
  172. NewExternalPort,
  173. 0,
  174. 0,
  175. (ICQ_DIRECTION_FLAGS)eALG_INBOUND);
  176. if(this->IncomingPeerControlRedirectionp is NULL)
  177. {
  178. g_IAlgServicesp->ReleaseReservedPort(NewExternalPort, 1);
  179. ICQ_TRC(TM_MSG, TL_ERROR,
  180. (" ERROR - Port Redirection for the Incoming packets - CRITICAL for this client"));
  181. return E_FAIL;
  182. }
  183. this->ImitatedPeerPort = NewExternalPort;
  184. ICQ_TRC(TM_MSG, TL_INFO, ("New ICQ Advertised PEER port is %hu",
  185. htons(NewExternalPort)));
  186. }
  187. //
  188. // IF success then commit the changes to the PORT section of this
  189. // message - IF we have error above it doesn't matter how we commit
  190. // the changes here.
  191. //
  192. *(PUSHORT)(buf+28) = htons(NewExternalPort);
  193. this->ClientToPeerPort = port;
  194. this->UIN = clientUIN;
  195. //
  196. // Encrypt the packet again.
  197. //
  198. icq5_crypt(buf,size,0);
  199. }
  200. else
  201. {
  202. //
  203. // Restore the buffer.
  204. //
  205. memcpy(buf, tbuf, size);
  206. }
  207. }
  208. return Error;
  209. } // End of _ICQ_CLIENT::IcqClientToServerUdp
  210. //
  211. //
  212. //
  213. ULONG
  214. _ICQ_CLIENT::IcqServerToClientUdp(
  215. PUCHAR mcp,
  216. ULONG mcplen
  217. )
  218. /*++
  219. Routine Description:
  220. Arguments:
  221. none.
  222. Return Value:
  223. --*/
  224. {
  225. ULONG cmd_len, Error = NO_ERROR;
  226. USHORT mcmd;
  227. ULONG changed;
  228. PICQ_PEER IcqPeerp = NULL;
  229. ULONG curPeerIp;
  230. USHORT curPeerPort;
  231. ULONG IcqUIN;
  232. changed = 0;
  233. cmd_len = 0;
  234. while (*(PUSHORT)mcp is 0x0005)
  235. {
  236. mcmd = *(PUSHORT)(mcp+7);
  237. switch (mcmd)
  238. {
  239. case 0x0212:
  240. cmd_len = 22;
  241. break;
  242. case 0x021C:
  243. cmd_len = 25;
  244. break;
  245. case 0x000A: /* ACK */
  246. cmd_len = 21;
  247. break;
  248. case 0x005A:
  249. cmd_len = 53;
  250. break;
  251. case 0x01A4:
  252. cmd_len = 29;
  253. break;
  254. case 0x0078:
  255. cmd_len = 25;
  256. break;
  257. /*case 0x024E: USER_FOUND */
  258. case 0x006E: /* USER_ONLINE */
  259. cmd_len = 70; // this is 62 in ME
  260. //
  261. // Not encrypted in this direction BUG BUG: alignment for ia64
  262. //
  263. IcqUIN = *(PULONG)(mcp+21);
  264. curPeerIp = *(PULONG)(mcp+25);
  265. curPeerPort = htons(*(PUSHORT)(mcp+29));
  266. ICQ_TRC(TM_TEST, TL_ERROR,
  267. (" USER_ONLINE: UIN %ul %s:%hu",
  268. IcqUIN,
  269. INET_NTOA(curPeerIp), // IP
  270. htons(curPeerPort))); // PORT
  271. //
  272. // For us ?
  273. //
  274. //
  275. // Determine the existence of any Internal ICQ Peer here.
  276. // scan the "g_IcqClientList" for UINs given here.
  277. // IF the Peer is internal change the IP : PORT information to the original
  278. // IP and PORT information and do not create any redirections
  279. // Note that we can't give the ICS-Local clients IP as the interface might be
  280. // Firewalled...
  281. //
  282. if(ScanTheListForLocalPeer(&curPeerIp, &curPeerPort, IcqUIN))
  283. {
  284. //
  285. // Change the appropriate fields in the buffer
  286. //
  287. *(PULONG)(mcp+25) = curPeerIp;
  288. *(PUSHORT)(mcp+29) = htons(curPeerPort);
  289. ICQ_TRC(TM_MSG, TL_INFO,
  290. ("Local ICQ Peer Online !! The original ADDR is %s:%hu UIN(%lu)",
  291. INET_NTOA(curPeerIp), htons(curPeerPort), IcqUIN));
  292. break; // break from the switch-case loop
  293. }
  294. // DO we have alredy the client in the List?
  295. IcqPeerp = dynamic_cast<PICQ_PEER>\
  296. (this->IcqPeerList.SearchNodeKeys(IcqUIN, 0));
  297. // check if IP:PORT information has changed or not.
  298. if(IcqPeerp != NULL)
  299. {
  300. if(IcqPeerp->PeerIp != curPeerIp ||
  301. IcqPeerp->PeerPort != curPeerPort)
  302. {
  303. ICQ_TRC(TM_MSG, TL_INFO,
  304. ("IP:PORT change of existing Client - Changing values"));
  305. this->IcqPeerList.RemoveNodeFromList(IcqPeerp);
  306. IcqPeerp = NULL;
  307. }
  308. else // if there is no change don't go further
  309. {
  310. ICQ_TRC(TM_MSG, TL_TRACE, ("Already such an entry - skipping"));
  311. break;
  312. }
  313. }
  314. // IF Peer is outside the Local NET DO:
  315. // - Create a Redirection from our ICQ(IP) -> Peer(IP:PORT) to the
  316. // Dispatch IP:PORT
  317. do
  318. {
  319. NEW_OBJECT(IcqPeerp, ICQ_PEER);
  320. //IcqPeerp = new ICQ_PEER();
  321. if(IcqPeerp is NULL)
  322. {
  323. Error = E_OUTOFMEMORY;
  324. ICQ_TRC(TM_MSG, TL_ERROR,
  325. ("Error - can't create Peer object"));
  326. break;
  327. }
  328. IcqPeerp->PeerUIN = IcqUIN;
  329. IcqPeerp->PeerIp = curPeerIp;
  330. IcqPeerp->PeerPort = curPeerPort;
  331. //
  332. // set the research
  333. //
  334. IcqPeerp->iKey1 = IcqUIN;
  335. IcqPeerp->iKey2 = 0;
  336. // - Request a Dispatch for this destination IP.. but also add the source IP
  337. // information as it is important too. THESE CONNECTIONS are from the
  338. // Internal guy.. so add the appropriate flag or context to the Requests
  339. IcqPeerp->OutgoingPeerControlRedirectp
  340. = this->PeerRedirection(IcqPeerp->PeerIp, // search Key 1
  341. IcqPeerp->PeerPort, // search Key 2
  342. this->ClientIp,
  343. 0,
  344. (ICQ_DIRECTION_FLAGS)eALG_OUTBOUND);
  345. if(IcqPeerp->OutgoingPeerControlRedirectp is NULL)
  346. {
  347. STOP_COMPONENT( IcqPeerp );
  348. DEREF_COMPONENT( IcqPeerp, eRefInitialization );
  349. break;
  350. }
  351. //
  352. // put this into the list of Peers
  353. //
  354. this->IcqPeerList.InsertSorted(IcqPeerp);
  355. //
  356. // relinquish the ownership - removal from the list should
  357. // cause deletion
  358. //
  359. DEREF_COMPONENT( IcqPeerp, eRefList );
  360. } while(FALSE);
  361. break;
  362. default:
  363. break;
  364. }
  365. if (cmd_len is 0) // cannot decode, so skip out
  366. {
  367. break; // got to recognize the first one at least
  368. }
  369. mcp += cmd_len;
  370. mcplen -= cmd_len;
  371. if (mcplen > 1)
  372. {
  373. cmd_len = *(PUSHORT)mcp;
  374. mcp += 2;
  375. if (mcplen < cmd_len) // not enough bytes to satisfy
  376. {
  377. break;
  378. }
  379. }
  380. else
  381. {
  382. break;
  383. }
  384. }
  385. return changed;
  386. } // End of IcqServerToClientUdp
  387. //
  388. //
  389. //
  390. ULONG
  391. _ICQ_PEER::ProcessOutgoingPeerMessage(PUCHAR Bufp, ULONG mesgLen)
  392. /*++
  393. Routine Description:
  394. Upon detection of an outgoing Peer TCP packet this Function is called.
  395. We are supposed to just create a DATA redirection should the need arise.
  396. Missing parts: do we need multiple redirections? If so how do we tear 'em
  397. down ???? test this out.
  398. Arguments:
  399. none.
  400. Return Value:
  401. --*/
  402. {
  403. USHORT port1, port2;
  404. PUSHORT FirstPortp = NULL;
  405. PUSHORT SecondPortp = NULL;
  406. ULONG Error = NO_ERROR;
  407. USHORT portAllocated = 0, portClient = 0;
  408. ULONG ipClient = 0L;
  409. if(mesgLen is 0x37 || mesgLen is (0x37 +2))
  410. {
  411. FirstPortp = (PUSHORT)&Bufp[0x20 + 11];
  412. SecondPortp = (PUSHORT)&Bufp[0x20 + 15];
  413. }
  414. else if(mesgLen is 0x3B || mesgLen is (0x3B +2))
  415. {
  416. FirstPortp = (PUSHORT)&Bufp[0x28];
  417. SecondPortp = (PUSHORT)&Bufp[0x33];
  418. }
  419. else if(mesgLen is 0x2A)
  420. {
  421. FirstPortp = (PUSHORT)&Bufp[0x22];
  422. SecondPortp = (PUSHORT)&Bufp[0x26];
  423. }
  424. else if(mesgLen is 0x2E)
  425. {
  426. FirstPortp = (PUSHORT)&Bufp[0x1F];
  427. SecondPortp = (PUSHORT)&Bufp[0x2A];
  428. }
  429. if(FirstPortp && SecondPortp)
  430. {
  431. port1 = htons(*FirstPortp);
  432. port2 = *SecondPortp;
  433. if(port1 && port2 && port1 is port2)
  434. {
  435. ICQ_TRC(TM_MSG, TL_TRACE,
  436. ("Data Session will be handled on port 1 %hu - port 2 %hu",
  437. *FirstPortp, // in NET format
  438. *SecondPortp) // in x86 format
  439. );
  440. //
  441. // Reserve A port for this operation !?
  442. Error = g_IAlgServicesp->ReservePort(1, &portAllocated);
  443. if ( FAILED(Error) )
  444. {
  445. ICQ_TRC(TM_MSG, TL_ERROR, ("Error !! - CAN't ALLOCATE PORT"));
  446. ErrorOut();
  447. return Error;
  448. }
  449. this->ToClientSocketp->NhQueryRemoteEndpointSocket(&ipClient,
  450. NULL);
  451. //
  452. // Create A redirect and save the handle - NOTE:
  453. // we can add the peer's IP as an additional security feature.
  454. //
  455. Error = g_IAlgServicesp->CreateDataChannel(eALG_TCP,
  456. ipClient,
  457. *FirstPortp,
  458. g_MyPublicIp,
  459. portAllocated,
  460. 0,
  461. 0,
  462. eALG_INBOUND,
  463. eALG_NONE,
  464. FALSE,
  465. &IncomingDataRedirectp);
  466. if( FAILED(Error) || (IncomingDataRedirectp is NULL))
  467. {
  468. g_IAlgServicesp->ReleaseReservedPort(portAllocated, 1);
  469. ICQ_TRC(TM_MSG, TL_ERROR,
  470. ("** !! ERROR - Can't create Redirect for DATA !! **"));
  471. ICQ_TRC(TM_MSG, TL_ERROR,
  472. ("** !! ERROR FAILED PARAM - ipClient public:%hu -> %s:%u",
  473. htons(portAllocated),
  474. INET_NTOA(ipClient),
  475. htons(*FirstPortp)));
  476. ErrorOut();
  477. return Error;
  478. }
  479. //
  480. // NOTE: possible hazard clarify with jonburs and jp
  481. // we actually do not care about this Release - if the ALG doesn't clean up
  482. // BUG BUG
  483. // IncomingDataRedirectp->Release();
  484. //
  485. // Save the new port information appropriately.
  486. *SecondPortp = htons(portAllocated); // x86
  487. *FirstPortp = portAllocated; // NET format
  488. ICQ_TRC(TM_MSG, TL_TRACE,
  489. ("DATA port Allocated is %hu", *SecondPortp));
  490. }
  491. }
  492. return NO_ERROR;
  493. }