Leaked source code of windows server 2003
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.

838 lines
21 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. Tower.cxx
  5. Abstract:
  6. Common code from building and exploding towers. Each
  7. protocol supported by the transport interface needs
  8. a section in this file.
  9. Author:
  10. Mario Goertzel [MarioGo]
  11. Revision History:
  12. MarioGo 11/11/1996 Bits 'n pieces
  13. KamenM 05/02/2002 Major security and cleanup changes
  14. --*/
  15. #include <precomp.hxx>
  16. #include <epmp.h>
  17. #include <twrtypes.h>
  18. #include <twrproto.h>
  19. // Transport protocols defined in cotrans.hxx and dgtrans.hxx
  20. RPC_STATUS
  21. RPC_ENTRY
  22. COMMON_TowerConstruct(
  23. IN PCHAR Protseq,
  24. IN PCHAR NetworkAddress,
  25. IN PCHAR Endpoint,
  26. OUT PUSHORT Floors,
  27. OUT PULONG ByteCount,
  28. OUT PUCHAR *Tower
  29. )
  30. /*++
  31. Routine Description:
  32. Constructs a OSF tower for the protocol, network address and endpoint.
  33. Arguments:
  34. Protseq - The protocol for the tower.
  35. NetworkAddress - The network address to be encoded in the tower.
  36. Endpoint - The endpoint to be encoded in the tower.
  37. Floors - The number of twoer floors it encoded into the tower.
  38. ByteCount - The size of the "upper-transport-specific" tower that
  39. is encoded by this call.
  40. Tower - The encoded "upper tower" that is encoded by this call.
  41. This caller is responsible for freeing this memory.
  42. Return Value:
  43. RPC_S_OK
  44. RPC_S_OUT_OF_MEMORY
  45. RPC_S_OUT_OF_RESOURCES
  46. RPC_S_INVALID_RPC_PROTSEQ
  47. --*/
  48. {
  49. PFLOOR_234 Floor;
  50. ADDRINFO *AddrInfo;
  51. ADDRINFO Hint;
  52. INT index = MapProtseq(Protseq);
  53. if (index == 0)
  54. {
  55. return(RPC_S_INVALID_RPC_PROTSEQ);
  56. }
  57. RPC_TRANSPORT_INTERFACE pInfo = TransportTable[index].pInfo;
  58. ASSERT(pInfo);
  59. if (Endpoint == NULL || *Endpoint == '\0')
  60. {
  61. Endpoint = pInfo->WellKnownEndpoint;
  62. }
  63. // Currently all protocols have 5 floors. If a new protocol
  64. // is added with < 5 floors watch out in tower explode.
  65. *Floors = 5;
  66. // Figure out the size of the tower
  67. size_t addr_size;
  68. size_t ept_size;
  69. size_t size;
  70. // Figure out the endpoint size
  71. switch (index)
  72. {
  73. // Protocols which use port numbers (ushorts) as endpoints
  74. case TCP:
  75. #ifdef SPX_ON
  76. case SPX:
  77. #endif
  78. case HTTP:
  79. case UDP:
  80. #ifdef IPX_ON
  81. case IPX:
  82. #endif
  83. ept_size = 2;
  84. break;
  85. // Protocols which use strings as endpoints
  86. case NMP:
  87. #ifdef NETBIOS_ON
  88. case NBF:
  89. case NBT:
  90. case NBI:
  91. #endif
  92. #ifdef NCADG_MQ_ON
  93. case MSMQ:
  94. #endif
  95. #ifdef APPLETALK_ON
  96. case DSP:
  97. #endif
  98. {
  99. ASSERT(Endpoint && *Endpoint);
  100. ept_size = strlen(Endpoint) + 1;
  101. break;
  102. }
  103. #if DBG
  104. default:
  105. ASSERT(0);
  106. return(RPC_S_INTERNAL_ERROR);
  107. #endif
  108. }
  109. // Figure out the address size
  110. switch(index)
  111. {
  112. // Protocols which use 4 bytes longs as the address size
  113. case TCP:
  114. case UDP:
  115. case HTTP:
  116. {
  117. addr_size = 4;
  118. break;
  119. }
  120. #ifndef SPX_IPX_OFF
  121. // Protocols which use 10 byte (32+48 bit) address size
  122. #ifdef SPX_ON
  123. case SPX:
  124. #endif
  125. #ifdef IPX_ON
  126. case IPX:
  127. #endif
  128. {
  129. addr_size = 10;
  130. break;
  131. }
  132. #endif
  133. // Protocols which use the string as the address
  134. case NMP:
  135. #ifdef NETBIOS_ON
  136. case NBF:
  137. case NBT:
  138. case NBI:
  139. #endif
  140. #ifdef NCADG_MQ_ON
  141. case MSMQ:
  142. #endif
  143. #ifdef APPLETALK_ON
  144. case DSP:
  145. #endif
  146. {
  147. if ((NetworkAddress == NULL) || (*NetworkAddress== '\0'))
  148. {
  149. addr_size = 2;
  150. }
  151. else
  152. {
  153. addr_size = strlen(NetworkAddress) + 1;
  154. }
  155. break;
  156. }
  157. #if DBG
  158. default:
  159. ASSERT(0);
  160. return(RPC_S_INTERNAL_ERROR);
  161. #endif
  162. }
  163. // Compute total size.
  164. // Note: FLOOR_234 already contains 2 bytes of data.
  165. size = addr_size + ept_size + 2*(sizeof(FLOOR_234) - 2);
  166. // Allocate tower
  167. *Tower = new UCHAR[size];
  168. if (!*Tower)
  169. {
  170. return(RPC_S_OUT_OF_MEMORY);
  171. }
  172. *ByteCount = size;
  173. // Now fill-in the endpoint part of the tower
  174. Floor = (PFLOOR_234)*Tower;
  175. Floor->ProtocolIdByteCount = 1;
  176. Floor->FloorId = (UCHAR)pInfo->TransId;
  177. switch(index)
  178. {
  179. // Protocols which use big endian ushorts
  180. case TCP:
  181. case HTTP:
  182. #ifdef SPX_ON
  183. case SPX:
  184. #endif
  185. case UDP:
  186. #ifdef IPX_ON
  187. case IPX:
  188. #endif
  189. {
  190. Floor->AddressByteCount = 2;
  191. USHORT port = (USHORT) atoi(Endpoint);
  192. port = htons(port);
  193. memcpy((char PAPI *)&Floor->Data[0], &port, 2);
  194. break;
  195. }
  196. // Protocols which use ansi strings
  197. case NMP:
  198. #ifdef NETBIOS_ON
  199. case NBT:
  200. case NBF:
  201. case NBI:
  202. #endif
  203. #ifdef NCADG_MQ_ON
  204. case MSMQ:
  205. #endif
  206. #ifdef APPLETALK_ON
  207. case DSP:
  208. #endif
  209. {
  210. Floor->AddressByteCount = (unsigned short) ept_size;
  211. memcpy(&Floor->Data[0], Endpoint, ept_size);
  212. break;
  213. }
  214. #if DBG
  215. default:
  216. ASSERT(0);
  217. #endif
  218. }
  219. // Move to the next tower and fill-in the address part of the tower
  220. Floor = NEXTFLOOR(PFLOOR_234, Floor);
  221. Floor->ProtocolIdByteCount = 1;
  222. Floor->FloorId = (unsigned char) pInfo->TransAddrId;
  223. switch (index)
  224. {
  225. // IP protocols use 4 byte big endian IP addreses
  226. case TCP:
  227. case HTTP:
  228. case UDP:
  229. {
  230. int err;
  231. RpcpMemorySet(&Hint, 0, sizeof(Hint));
  232. Hint.ai_flags = AI_NUMERICHOST;
  233. err = getaddrinfo(NetworkAddress,
  234. NULL,
  235. &Hint,
  236. &AddrInfo);
  237. if (err)
  238. {
  239. // if it's not a dot address, keep it zero
  240. RpcpMemorySet(&Floor->Data[0], 0, 4);
  241. }
  242. else
  243. {
  244. RpcpMemoryCopy(&Floor->Data[0], &(((SOCKADDR_IN *)AddrInfo->ai_addr)->sin_addr.s_addr), 4);
  245. freeaddrinfo(AddrInfo);
  246. }
  247. Floor->AddressByteCount = 4;
  248. break;
  249. }
  250. #ifndef SPX_IPX_OFF
  251. // IPX protocols use little endian net (32 bit) + node (48 bit) addresses
  252. #ifdef SPX_ON
  253. case SPX:
  254. #endif
  255. #ifdef IPX_ON
  256. case IPX:
  257. #endif
  258. {
  259. Floor->AddressByteCount = 10;
  260. memset(&Floor->Data[0], 0, 10); // Zero is fine..
  261. break;
  262. }
  263. #endif
  264. // Protocols which use string names.
  265. case NMP:
  266. #ifdef NETBIOS_ON
  267. case NBF:
  268. case NBT:
  269. case NBI:
  270. #endif
  271. #ifdef NCADG_MQ_ON
  272. case MSMQ:
  273. #endif
  274. #ifdef APPLETALK_ON
  275. case DSP:
  276. #endif
  277. {
  278. if ((NetworkAddress) && (*NetworkAddress))
  279. {
  280. Floor->AddressByteCount = (unsigned short) addr_size;
  281. memcpy(&Floor->Data[0], NetworkAddress, addr_size);
  282. }
  283. else
  284. {
  285. Floor->AddressByteCount = 2;
  286. Floor->Data[0] = 0;
  287. }
  288. break;
  289. }
  290. #if DBG
  291. default:
  292. ASSERT(0);
  293. #endif
  294. }
  295. return(RPC_S_OK);
  296. }
  297. const INT HTTP_OLD_ADDRESS_ID = 0x20;
  298. RPC_STATUS
  299. FixupFloorForMac(
  300. IN BYTE *Floor,
  301. IN BYTE *UpperBound
  302. )
  303. /*++
  304. Routine Description:
  305. Mac clients have their LHS and RHS byte counts in big endian format.
  306. This routine fixes the bug counts.
  307. Arguments:
  308. Floor - The floor to fix
  309. UpperBound - The first invalid byte after the end of the buffer.
  310. Return Value:
  311. RPC_S_OK
  312. EP_S_CANT_PERFORM_OP - The floor provided is invalid.
  313. Note:
  314. The function expects the LHSBytes value to be present.
  315. The caller should have verified that we can read this floor:
  316. &Floor->Data[0] < UpperBound
  317. --*/
  318. {
  319. USHORT LHSBytes, RHSBytes;
  320. BYTE *RHSBytesPosition;
  321. // The caller must verify that we are given a full floor.
  322. // PFLOOR_234 is defined as unaligned - no need to worry about alignment
  323. LHSBytes = ((PFLOOR_234)Floor)->ProtocolIdByteCount;
  324. // Swap the LHSBytes,
  325. LHSBytes = RpcpByteSwapShort(LHSBytes);
  326. ((PFLOOR_234)Floor)->ProtocolIdByteCount = LHSBytes;
  327. // find the RHSBytes and swap them too
  328. RHSBytesPosition = Floor + 2 + LHSBytes;
  329. // Make sure we can read the field.
  330. if (RHSBytesPosition + 2 >= UpperBound)
  331. return EP_S_CANT_PERFORM_OP;
  332. RHSBytes = *(USHORT UNALIGNED *)RHSBytesPosition;
  333. RHSBytes = RpcpByteSwapShort(RHSBytes);
  334. *(USHORT UNALIGNED *)RHSBytesPosition = RHSBytes;
  335. return RPC_S_OK;
  336. }
  337. #define BadMacByteCount 0x0100
  338. RPC_STATUS
  339. COMMON_TowerExplode(
  340. IN BYTE *Tower,
  341. IN BYTE *UpperBound,
  342. IN ULONG RemainingFloors,
  343. OUT PCHAR *Protseq,
  344. OUT PCHAR *NetworkAddress,
  345. OUT PCHAR *Endpoint
  346. )
  347. /*++
  348. Routine Description:
  349. Decodes an OSF transport "upper tower" for the runtime.
  350. Arguments:
  351. Tower - The encoded "upper tower" to decode
  352. UpperBound - the first invalid byte after the end of the buffer.
  353. RemainingFloors - the number of floors remaining
  354. Protseq - The protseq encoded in the Tower
  355. Does not need to be freed by the caller.
  356. NetworkAddress - The network address encoded in the Tower
  357. Must be freed by the caller.
  358. Endpoint - The endpoint encoded in the Tower.
  359. Must be freed by the caller.
  360. Return Value:
  361. RPC_S_OK
  362. EP_S_CANT_PERFORM_OP - The tower provided is invalid.
  363. RPC_S_INVALID_RPC_PROTSEQ
  364. RPC_S_OUT_OF_MEMORY
  365. --*/
  366. {
  367. PFLOOR_234 Floor = (PFLOOR_234)Tower;
  368. BYTE *FloorAfterThat;
  369. RPC_STATUS Status = RPC_S_OK;
  370. INT Index;
  371. BOOL NextFloorVerified;
  372. ULONG EndpointLength;
  373. char *NewEndpoint;
  374. ULONG NetworkAddressLength;
  375. char *NewNetworkAddress;
  376. USHORT LHSBytes, RHSBytes;
  377. unsigned short TransportId;
  378. BOOL fBadMacClient = FALSE;
  379. if (RemainingFloors == 0)
  380. return EP_S_CANT_PERFORM_OP;
  381. // Verify that we can access the floor data.
  382. if (&Floor->Data[0] >= UpperBound)
  383. return EP_S_CANT_PERFORM_OP;
  384. PFLOOR_234 NextFloor = NEXTFLOOR(PFLOOR_234, Tower);
  385. // The pointer to the tower is actually a pointer to the 3rd floor.
  386. TransportId = Floor->FloorId;
  387. // Mac clients have their LHS and RHS byte counts in big endian format.
  388. // Detect such clients, and byte swap them.
  389. // PFLOOR_234 is defined as unaligned - no need to worry about alignment
  390. LHSBytes = Floor->ProtocolIdByteCount;
  391. if ((LHSBytes == BadMacByteCount) && (TransportId == TCP_TOWER_ID))
  392. {
  393. fBadMacClient = TRUE;
  394. if (FixupFloorForMac((BYTE*)Floor,
  395. UpperBound
  396. ) != RPC_S_OK)
  397. {
  398. return EP_S_CANT_PERFORM_OP;
  399. }
  400. }
  401. NextFloor = (PFLOOR_234)VerifyFloorLHSAndRHS (Tower,
  402. UpperBound,
  403. 3 // FloorNum
  404. );
  405. if (NextFloor == NULL)
  406. return EP_S_CANT_PERFORM_OP;
  407. // Find the protocol based first on the ID from this floor,
  408. // and then the next floor. We only dereference the next
  409. // floor if we match the ID on this floor.
  410. NextFloorVerified = FALSE;
  411. for (unsigned i = 1; i < cTransportTable; i++)
  412. {
  413. if (TransportTable[i].ProtocolTowerId == Floor->FloorId)
  414. {
  415. if (NextFloorVerified == FALSE)
  416. {
  417. if (RemainingFloors == 1)
  418. return EP_S_CANT_PERFORM_OP;
  419. if ((BYTE *)NextFloor + sizeof(FLOOR_234) - 2 >= UpperBound)
  420. return EP_S_CANT_PERFORM_OP;
  421. // Don't forget to byteswap NextFloor if it came from a Mac client.
  422. if (fBadMacClient)
  423. {
  424. if (FixupFloorForMac((BYTE *)NextFloor,
  425. UpperBound
  426. ) != RPC_S_OK)
  427. {
  428. return EP_S_CANT_PERFORM_OP;
  429. }
  430. }
  431. FloorAfterThat = VerifyFloorLHSAndRHS ((BYTE *)NextFloor,
  432. UpperBound,
  433. 4 // FloorNum
  434. );
  435. if (FloorAfterThat == NULL)
  436. return EP_S_CANT_PERFORM_OP;
  437. NextFloorVerified = TRUE;
  438. }
  439. if (TransportTable[i].AddressTowerId == NextFloor->FloorId)
  440. break;
  441. //
  442. // The & 0x0F is needed because the legacy server code incorrectly
  443. // cleared the high nibble before sending the address tower id
  444. //
  445. if ((TransportTable[i].AddressTowerId & 0x0F) == NextFloor->FloorId )
  446. break;
  447. // N.B. Old (Win9x/NT4) clients would send a AddressTowerId of 0x20
  448. // (HTTP_OLD_ADDRESS_ID). We need to match this as well.
  449. if ((Floor->FloorId == HTTP_TOWER_ID)
  450. && (NextFloor->FloorId == HTTP_OLD_ADDRESS_ID))
  451. break;
  452. }
  453. }
  454. if (i == cTransportTable)
  455. {
  456. return(RPC_S_INVALID_RPC_PROTSEQ);
  457. }
  458. // the only way to break early of the loop passed through the second floor
  459. // verification code
  460. ASSERT(NextFloorVerified);
  461. Index = i;
  462. RPC_TRANSPORT_INTERFACE pInfo = TransportTable[Index].pInfo;
  463. if (pInfo == NULL){
  464. ASSERT(pInfo);
  465. return EP_S_CANT_PERFORM_OP;
  466. }
  467. //
  468. // Figure out the protseq
  469. //
  470. if (ARGUMENT_PRESENT(Protseq))
  471. {
  472. size_t len = RpcpStringLength(pInfo->ProtocolSequence);
  473. *Protseq = new char[len + 1];
  474. if (*Protseq)
  475. {
  476. RPC_CHAR *MySrc = (RPC_CHAR *) pInfo->ProtocolSequence;
  477. char *MyDest = *Protseq;
  478. while (*MyDest++ = (char) *MySrc++);
  479. }
  480. else
  481. {
  482. return(RPC_S_OUT_OF_MEMORY);
  483. }
  484. }
  485. //
  486. // Figure out the endpoint
  487. //
  488. if (ARGUMENT_PRESENT(Endpoint))
  489. {
  490. switch(Index)
  491. {
  492. // Protocols which use strings as the endpoint format.
  493. case NMP:
  494. #ifdef NETBIOS_ON
  495. case NBT:
  496. case NBI:
  497. case NBF:
  498. #endif
  499. #ifdef NCADG_MQ_ON
  500. case MSMQ:
  501. #endif
  502. #ifdef APPLETALK_ON
  503. case DSP:
  504. #endif
  505. {
  506. EndpointLength = Floor->AddressByteCount;
  507. Status = ExtractStringFromUntrustedPacket (UpperBound,
  508. EndpointLength,
  509. (char *)&Floor->Data[0],
  510. Endpoint
  511. );
  512. }
  513. break;
  514. // Protocols which use ushort's as the endpoint format.
  515. case TCP:
  516. #ifdef SPX_ON
  517. case SPX:
  518. #endif
  519. case HTTP:
  520. case UDP:
  521. #ifdef IPX_ON
  522. case IPX:
  523. #endif
  524. {
  525. if (Tower + sizeof(FLOOR_234) >= UpperBound)
  526. {
  527. Status = EP_S_CANT_PERFORM_OP;
  528. break;
  529. }
  530. USHORT PortNum = *(USHORT UNALIGNED *)(&Floor->Data[0]);
  531. PortNum = RpcpByteSwapShort(PortNum); // Towers are big endian.
  532. *Endpoint = new CHAR[6]; // 65535'\0'
  533. if (*Endpoint)
  534. {
  535. RpcpItoa(PortNum, *Endpoint, 10);
  536. Status = RPC_S_OK;
  537. }
  538. else
  539. Status = RPC_S_OUT_OF_MEMORY;
  540. }
  541. break;
  542. default:
  543. CORRUPTION_ASSERT(0);
  544. Status = RPC_S_INVALID_RPC_PROTSEQ;
  545. }
  546. if (Status != RPC_S_OK)
  547. {
  548. if (ARGUMENT_PRESENT(Protseq))
  549. {
  550. delete *Protseq;
  551. *Protseq = 0;
  552. }
  553. return(Status);
  554. }
  555. }
  556. //
  557. // Now the hard part, figure out the network address.
  558. //
  559. if (ARGUMENT_PRESENT(NetworkAddress))
  560. {
  561. Floor = NextFloor;
  562. Status = RPC_S_OUT_OF_MEMORY;
  563. switch(Index)
  564. {
  565. // Protocols which use strings as their network address
  566. case NMP:
  567. #ifdef NETBIOS_ON
  568. case NBF:
  569. case NBT:
  570. case NBI:
  571. #endif
  572. #ifdef NCADG_MQ_ON
  573. case MSMQ:
  574. #endif
  575. #ifdef APPLETALK_ON
  576. case DSP:
  577. #endif
  578. Status = ExtractStringFromUntrustedPacket (UpperBound,
  579. Floor->AddressByteCount,
  580. (char *)&Floor->Data[0],
  581. NetworkAddress
  582. );
  583. break;
  584. // Protocols using IP addresses
  585. case TCP:
  586. case HTTP:
  587. case UDP:
  588. {
  589. if (Floor->AddressByteCount != 4)
  590. {
  591. Status = RPC_S_INVALID_RPC_PROTSEQ;
  592. break;
  593. }
  594. // make sure we have all four bytes. The check
  595. // above does not ensure that
  596. if (&Floor->Data[3] >= UpperBound)
  597. {
  598. Status = RPC_S_INVALID_RPC_PROTSEQ;
  599. break;
  600. }
  601. struct in_addr in;
  602. in.S_un.S_un_b.s_b1 = Floor->Data[0];
  603. in.S_un.S_un_b.s_b2 = Floor->Data[1];
  604. in.S_un.S_un_b.s_b3 = Floor->Data[2];
  605. in.S_un.S_un_b.s_b4 = Floor->Data[3];
  606. PCHAR t = inet_ntoa(in);
  607. if (t)
  608. {
  609. *NetworkAddress = new CHAR[16+1];
  610. if (*NetworkAddress)
  611. {
  612. strcpy(*NetworkAddress, t);
  613. Status = RPC_S_OK;
  614. }
  615. }
  616. else
  617. {
  618. ASSERT(0);
  619. Status = RPC_S_INVALID_RPC_PROTSEQ;
  620. }
  621. }
  622. break;
  623. #ifndef SPX_IPX_OFF
  624. // Protocols using IPX 80 bit addresses
  625. #ifdef SPX_ON
  626. case SPX:
  627. #endif
  628. #ifdef IPX_ON
  629. case IPX:
  630. #endif
  631. {
  632. if (Floor->AddressByteCount != 10)
  633. {
  634. Status = RPC_S_INVALID_RPC_PROTSEQ;
  635. break;
  636. }
  637. if (&Floor->Data[9] >= UpperBound)
  638. {
  639. Status = RPC_S_INVALID_RPC_PROTSEQ;
  640. break;
  641. }
  642. // Format: ~NNNNNNNNAAAAAAAAAAAA'\0'
  643. // Network number (32bits) and IEEE 802 address (48bits)
  644. *NetworkAddress = new CHAR[1 + 8 + 12 + 1];
  645. if (*NetworkAddress)
  646. {
  647. PCHAR p = *NetworkAddress;
  648. PCHAR pInput = (PCHAR) &Floor->Data[0];
  649. *p++ = '~';
  650. for (int i = 0; i < 10; i++)
  651. {
  652. CHAR c = *pInput ++;
  653. *p++ = (char) HexDigits[(c >> 4) & 0xF];
  654. *p++ = (char) HexDigits[ c & 0xF];
  655. }
  656. *p = '\0';
  657. Status = RPC_S_OK;
  658. }
  659. break;
  660. }
  661. #endif
  662. }
  663. if (Status != RPC_S_OK)
  664. {
  665. if (ARGUMENT_PRESENT(Endpoint))
  666. {
  667. delete *Endpoint;
  668. *Endpoint = 0;
  669. }
  670. if (ARGUMENT_PRESENT(Protseq))
  671. {
  672. delete *Protseq;
  673. *Protseq = 0;
  674. }
  675. return(Status);
  676. }
  677. }
  678. ASSERT(Status == RPC_S_OK);
  679. return(Status);
  680. }