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.

730 lines
17 KiB

  1. //=============================================================================
  2. //
  3. // MODULE: Kerbparser.cxx
  4. //
  5. // Description:
  6. //
  7. // Bloodhound Parser DLL for Kerberos Authentication Protocol
  8. //
  9. // Modification History
  10. //
  11. // Michael Webb & Kris Frost Date: 06/04/99
  12. // Mark Pustilnik Date: 02/04/02 - Clean-up / rewrite
  13. //
  14. //=============================================================================
  15. #include "ASN1Parser.hxx"
  16. //
  17. // Protocol entry points.
  18. //
  19. VOID
  20. WINAPI
  21. KerberosRegister(
  22. IN HPROTOCOL hKerberosProtocol
  23. );
  24. VOID
  25. WINAPI
  26. KerberosDeregister(
  27. IN HPROTOCOL hKerberosProtocol
  28. );
  29. LPBYTE
  30. WINAPI
  31. KerberosRecognizeFrame(
  32. IN HFRAME hFrame,
  33. IN ULPBYTE MacFrame,
  34. IN ULPBYTE KerberosFrame,
  35. IN DWORD MacType,
  36. IN DWORD BytesLeft,
  37. IN HPROTOCOL hPreviousProtocol,
  38. IN DWORD nPreviousProtocolOffset,
  39. OUT LPDWORD ProtocolStatusCode,
  40. OUT LPHPROTOCOL hNextProtocol,
  41. OUT PDWORD_PTR InstData
  42. );
  43. LPBYTE
  44. WINAPI
  45. KerberosAttachProperties(
  46. IN HFRAME hFrame,
  47. IN ULPBYTE MacFrame,
  48. IN ULPBYTE KerberosFrame,
  49. IN DWORD MacType,
  50. IN DWORD BytesLeft,
  51. IN HPROTOCOL hPreviousProtocol,
  52. IN DWORD nPreviousProtocolOffset,
  53. IN DWORD_PTR InstData
  54. );
  55. DWORD
  56. WINAPI
  57. KerberosFormatProperties(
  58. IN HFRAME hFrame,
  59. IN ULPBYTE MacFrame,
  60. IN ULPBYTE FrameData,
  61. IN DWORD nPropertyInsts,
  62. IN LPPROPERTYINST p
  63. );
  64. ENTRYPOINTS g_KerberosEntryPoints =
  65. {
  66. KerberosRegister,
  67. KerberosDeregister,
  68. KerberosRecognizeFrame,
  69. KerberosAttachProperties,
  70. KerberosFormatProperties
  71. };
  72. //
  73. // Protocol handle
  74. //
  75. HPROTOCOL g_hKerberos = NULL;
  76. //
  77. // Protocol status
  78. //
  79. DWORD g_Attached = 0;
  80. //
  81. // Protocol handles used to check for continuation packets.
  82. //
  83. HPROTOCOL g_hTCP = NULL;
  84. HPROTOCOL g_hUDP = NULL;
  85. //
  86. // Definitions of exported functions
  87. //
  88. //-----------------------------------------------------------------------------
  89. //
  90. // Routine name: ParserAutoInstallInfo
  91. //
  92. // Routine description:
  93. //
  94. // Sets up a parser information structure describing which ports are
  95. // being listened on, etc.
  96. //
  97. // Arguments:
  98. //
  99. // None
  100. //
  101. // Returns:
  102. //
  103. // Pointer to a PF_PARSERDLLINFO structure describing the protocol
  104. //
  105. //-----------------------------------------------------------------------------
  106. PPF_PARSERDLLINFO
  107. ParserAutoInstallInfo()
  108. {
  109. PPF_PARSERDLLINFO pParserDllInfo = NULL;
  110. PPF_PARSERINFO pParserInfo = NULL;
  111. PPF_HANDOFFSET pHandoffSet = NULL;
  112. PPF_HANDOFFENTRY pHandoffEntry = NULL;
  113. DWORD NumProtocols, NumHandoffs;
  114. //
  115. // Allocate memory for parser info
  116. //
  117. NumProtocols = 1;
  118. pParserDllInfo = (PPF_PARSERDLLINFO)HeapAlloc(
  119. GetProcessHeap(),
  120. HEAP_ZERO_MEMORY,
  121. sizeof( PF_PARSERDLLINFO ) +
  122. NumProtocols * sizeof( PF_PARSERINFO )
  123. );
  124. if ( pParserDllInfo == NULL )
  125. {
  126. goto Error;
  127. }
  128. //
  129. // Fill in the parser DLL info
  130. //
  131. pParserDllInfo->nParsers = NumProtocols;
  132. pParserInfo = &(pParserDllInfo->ParserInfo[0]);
  133. strncpy(
  134. pParserInfo->szProtocolName,
  135. "KERBEROS",
  136. sizeof( pParserInfo->szProtocolName )
  137. );
  138. strncpy(
  139. pParserInfo->szComment,
  140. "Kerberos Authentication Protocol",
  141. sizeof( pParserInfo->szComment )
  142. );
  143. strncpy(
  144. pParserInfo->szHelpFile,
  145. "",
  146. sizeof( pParserInfo->szHelpFile )
  147. );
  148. NumHandoffs = 2;
  149. pHandoffSet = (PPF_HANDOFFSET)HeapAlloc(
  150. GetProcessHeap(),
  151. HEAP_ZERO_MEMORY,
  152. sizeof( PF_HANDOFFSET ) +
  153. NumHandoffs * sizeof( PF_HANDOFFENTRY )
  154. );
  155. if ( pHandoffSet == NULL )
  156. {
  157. goto Error;
  158. }
  159. pParserInfo->pWhoHandsOffToMe = pHandoffSet;
  160. pHandoffSet->nEntries = NumHandoffs;
  161. //
  162. // UDP port 88
  163. //
  164. pHandoffEntry = &(pHandoffSet->Entry[0]);
  165. strncpy(
  166. pHandoffEntry->szIniFile,
  167. "TCPIP.INI",
  168. sizeof( pHandoffEntry->szIniFile )
  169. );
  170. strncpy(
  171. pHandoffEntry->szIniSection,
  172. "UDP_HandoffSet",
  173. sizeof( pHandoffEntry->szIniSection )
  174. );
  175. strncpy(
  176. pHandoffEntry->szProtocol,
  177. "KERBEROS",
  178. sizeof( pHandoffEntry->szProtocol )
  179. );
  180. pHandoffEntry->dwHandOffValue = 88; // TODO: make configurable?
  181. pHandoffEntry->ValueFormatBase = HANDOFF_VALUE_FORMAT_BASE_DECIMAL;
  182. //
  183. // TCP port 88
  184. //
  185. pHandoffEntry = &(pHandoffSet->Entry[0]);
  186. strncpy(
  187. pHandoffEntry->szIniFile,
  188. "TCPIP.INI",
  189. sizeof( pHandoffEntry->szIniFile )
  190. );
  191. strncpy(
  192. pHandoffEntry->szIniSection,
  193. "TCP_HandoffSet",
  194. sizeof( pHandoffEntry->szIniSection )
  195. );
  196. strncpy(
  197. pHandoffEntry->szProtocol,
  198. "KERBEROS",
  199. sizeof( pHandoffEntry->szProtocol )
  200. );
  201. pHandoffEntry->dwHandOffValue = 88; // TODO: make configurable?
  202. pHandoffEntry->ValueFormatBase = HANDOFF_VALUE_FORMAT_BASE_DECIMAL;
  203. Cleanup:
  204. return pParserDllInfo;
  205. Error:
  206. HeapFree( GetProcessHeap(), 0, pHandoffSet );
  207. pHandoffSet = NULL;
  208. HeapFree( GetProcessHeap(), 0, pParserDllInfo );
  209. pParserDllInfo = NULL;
  210. goto Cleanup;
  211. }
  212. //-----------------------------------------------------------------------------
  213. //
  214. // Routine name: DllEntry
  215. //
  216. // Routine description:
  217. //
  218. // Mail DLL entrypoint
  219. //
  220. // Arguments:
  221. //
  222. // hInstance process instance
  223. // Command ATTACH/DETACH/etc.
  224. // Reserved Reserved
  225. //
  226. // Returns:
  227. //
  228. // Standard DllEntry TRUE or FALSE
  229. //
  230. //-----------------------------------------------------------------------------
  231. extern "C" {
  232. BOOL
  233. WINAPI
  234. DLLEntry(
  235. IN HANDLE hInstance,
  236. IN ULONG Command,
  237. IN LPVOID Reserved
  238. )
  239. {
  240. if ( Command == DLL_PROCESS_ATTACH )
  241. {
  242. if ( g_Attached++ == 0 )
  243. {
  244. g_hKerberos = CreateProtocol(
  245. "KERBEROS",
  246. &g_KerberosEntryPoints,
  247. ENTRYPOINTS_SIZE
  248. );
  249. }
  250. }
  251. else if ( Command == DLL_PROCESS_DETACH )
  252. {
  253. if ( --g_Attached == 0 )
  254. {
  255. DestroyProtocol( g_hKerberos );
  256. g_hKerberos = NULL;
  257. }
  258. }
  259. return TRUE; //... Bloodhound parsers ALWAYS return TRUE.
  260. }
  261. } // extern "C"
  262. //-----------------------------------------------------------------------------
  263. //
  264. // Routine name: KerberosRegister
  265. //
  266. // Routine description:
  267. //
  268. // Registers the Kerberos protocol with the parser
  269. //
  270. // Arguments:
  271. //
  272. // hKerberosProtocol protocol handle
  273. //
  274. // Returns:
  275. //
  276. // Nothing
  277. //
  278. //-----------------------------------------------------------------------------
  279. VOID
  280. WINAPI
  281. KerberosRegister(
  282. IN HPROTOCOL hKerberosProtocol
  283. )
  284. {
  285. DWORD NmErr;
  286. //
  287. // Start by creating the property database
  288. //
  289. NmErr = CreatePropertyDatabase(
  290. hKerberosProtocol,
  291. ARRAY_COUNT( g_KerberosDatabase )
  292. );
  293. if ( NmErr != NMERR_SUCCESS )
  294. {
  295. SetLastError( NmErr );
  296. return;
  297. }
  298. for ( DWORD i = 0;
  299. i < ARRAY_COUNT( g_KerberosDatabase );
  300. i++ )
  301. {
  302. if ( NULL == AddProperty(
  303. hKerberosProtocol,
  304. &g_KerberosDatabase[i] ))
  305. {
  306. // TODO: find a better way to report this error
  307. SetLastError( ERROR_INTERNAL_ERROR );
  308. return;
  309. }
  310. }
  311. //
  312. // Check to see whether TCP or UDP are being used
  313. //
  314. g_hTCP = GetProtocolFromName( "TCP" );
  315. g_hUDP = GetProtocolFromName( "UDP" );
  316. return;
  317. }
  318. //-----------------------------------------------------------------------------
  319. //
  320. // Routine name: KerberosDeregister
  321. //
  322. // Routine description:
  323. //
  324. // Unregisters the Kerberos protocol from the parser
  325. //
  326. // Arguments:
  327. //
  328. // hKerberosProtocol protocol handle
  329. //
  330. // Returns:
  331. //
  332. // Nothing
  333. //
  334. //-----------------------------------------------------------------------------
  335. VOID
  336. WINAPI
  337. KerberosDeregister(
  338. IN HPROTOCOL hKerberosProtocol
  339. )
  340. {
  341. DestroyPropertyDatabase( hKerberosProtocol );
  342. }
  343. //-----------------------------------------------------------------------------
  344. //
  345. // Routine name: KerberosRecognizeFrame
  346. //
  347. // Routine description:
  348. //
  349. // Looks at a frame with the purpose of "recognizing it".
  350. // Kerberos has no sub-protocols, so every frame is claimed.
  351. //
  352. // Arguments:
  353. //
  354. // hFrame frame handle
  355. // MacFrame frame pointer
  356. // KerberosFrame relative pointer
  357. // MacType MAC type
  358. // BytesLeft bytes left
  359. // hPreviousProtocol previous protocol or NULL if none
  360. // nPreviousProtocolOffset offset of previous protocols
  361. // ProtocolStatusCode used to return the status code
  362. // hNextProtocol next protocol to call (optional)
  363. // InstData next protocol instance data
  364. //
  365. // Returns:
  366. //
  367. // Nothing
  368. //
  369. //-----------------------------------------------------------------------------
  370. LPBYTE
  371. WINAPI
  372. KerberosRecognizeFrame(
  373. IN HFRAME hFrame,
  374. IN ULPBYTE MacFrame,
  375. IN ULPBYTE KerberosFrame,
  376. IN DWORD MacType,
  377. IN DWORD BytesLeft,
  378. IN HPROTOCOL hPreviousProtocol,
  379. IN DWORD nPreviousProtocolOffset,
  380. OUT LPDWORD ProtocolStatusCode,
  381. OUT LPHPROTOCOL hNextProtocol,
  382. OUT PDWORD_PTR InstData
  383. )
  384. {
  385. //
  386. // There are no sub-protocols; claim every frame
  387. //
  388. *ProtocolStatusCode = PROTOCOL_STATUS_CLAIMED;
  389. return NULL;
  390. }
  391. //-----------------------------------------------------------------------------
  392. //
  393. // Routine name: KerberosAttachProperties
  394. //
  395. // Routine description:
  396. //
  397. // Parses out the frame given the request type
  398. //
  399. // Arguments:
  400. //
  401. // hFrame frame handle
  402. // MacFrame frame pointer
  403. // KerberosFrame relative pointer
  404. // MacType MAC type
  405. // BytesLeft bytes left
  406. // hPreviousProtocol previous protocol or NULL if none
  407. // nPreviousProtocolOffset offset of previous protocols
  408. // InstData next protocol instance data
  409. //
  410. // Returns:
  411. //
  412. // Pointer to data just past whatever was consumed or NULL on error
  413. //
  414. //-----------------------------------------------------------------------------
  415. LPBYTE
  416. WINAPI
  417. KerberosAttachProperties(
  418. IN HFRAME hFrame,
  419. IN ULPBYTE MacFrame,
  420. IN ULPBYTE KerberosFrame,
  421. IN DWORD MacType,
  422. IN DWORD BytesLeft,
  423. IN HPROTOCOL hPreviousProtocol,
  424. IN DWORD nPreviousProtocolOffset,
  425. IN DWORD_PTR InstData
  426. )
  427. {
  428. LPBYTE pKerberosFrame; // pointer to a TCP or UDP frame
  429. LPBYTE Address;
  430. //
  431. // Check to see if first two octets of the frame are equal to 00 00 which
  432. // would be the case should the packet be the first of TCP
  433. //
  434. if( KerberosFrame[0] == 0x00 &&
  435. KerberosFrame[1] == 0x00 )
  436. {
  437. Address = KerberosFrame+4; // TODO: add frame length check?
  438. pKerberosFrame = Address;
  439. }
  440. else
  441. {
  442. Address = KerberosFrame;
  443. pKerberosFrame = Address;
  444. }
  445. //
  446. // Here we are going to do a check to see if the packet is TCP and
  447. // check to see if the first two octets of the packet don't have the
  448. // value of 00 00. If not, then we mark the frame as a continuation
  449. // packet. Reason for doing this is because, sometimes 0x1F of the
  450. // first packet can still match one of the case statements which
  451. // erroneously displays a continuation packet.
  452. //
  453. if( hPreviousProtocol == g_hTCP &&
  454. KerberosFrame[0] != 0 &&
  455. KerberosFrame[1] != 0 )
  456. {
  457. //
  458. // Treat this as a continutation packet
  459. //
  460. if ( FALSE == AttachPropertyInstance(
  461. hFrame,
  462. g_KerberosDatabase[ContinuationPacket].hProperty,
  463. BytesLeft,
  464. Address,
  465. 0,
  466. 0,
  467. 0 ))
  468. {
  469. return NULL;
  470. }
  471. }
  472. else
  473. {
  474. //
  475. // pKerberosFrame is a local variable and is used
  476. // to display TCP data as well.
  477. //
  478. switch (*(pKerberosFrame) & 0x1F)
  479. {
  480. case ASN1_KRB_AS_REQ:
  481. case ASN1_KRB_TGS_REQ:
  482. {
  483. //
  484. // AS-REQ ::= [APPLICATION 10] KDC-REQ
  485. // TGS-REQ ::= [APPLICATION 12] KDC-REQ
  486. //
  487. DWORD dw;
  488. ASN1FRAME Frame;
  489. HPROPERTY hProp;
  490. Frame.Address = Address;
  491. Frame.hFrame = hFrame;
  492. Frame.Level = 0;
  493. if (( *(pKerberosFrame) & 0x1F ) == ASN1_KRB_AS_REQ )
  494. {
  495. hProp = PROP( KRB_AS_REQ );
  496. }
  497. else
  498. {
  499. hProp = PROP( KRB_TGS_REQ );
  500. }
  501. ASN1ParserKdcReq
  502. KdcReq(
  503. FALSE,
  504. BuildDescriptor( ctApplication, pcConstructed, (*(pKerberosFrame) & 0x1F)),
  505. hProp );
  506. dw = KdcReq.Parse( &Frame );
  507. //
  508. // TODO: display "data in error" if unhappy
  509. //
  510. break;
  511. }
  512. case ASN1_KRB_AS_REP:
  513. case ASN1_KRB_TGS_REP:
  514. {
  515. //
  516. // AS-REP ::= [APPLICATION 11] KDC-REP
  517. // TGS-REP ::= [APPLICATION 13] KDC-REP
  518. //
  519. DWORD dw;
  520. ASN1FRAME Frame;
  521. HPROPERTY hProp;
  522. Frame.Address = Address;
  523. Frame.hFrame = hFrame;
  524. Frame.Level = 0;
  525. if (( *(pKerberosFrame) & 0x1F ) == ASN1_KRB_AS_REP )
  526. {
  527. hProp = PROP( KRB_AS_REP );
  528. }
  529. else
  530. {
  531. hProp = PROP( KRB_TGS_REP );
  532. }
  533. ASN1ParserKdcRep
  534. KdcRep(
  535. FALSE,
  536. BuildDescriptor( ctApplication, pcConstructed, (*(pKerberosFrame) & 0x1F)),
  537. hProp );
  538. dw = KdcRep.Parse( &Frame );
  539. //
  540. // TODO: display "data in error" if unhappy
  541. //
  542. break;
  543. }
  544. case ASN1_KRB_ERROR:
  545. {
  546. DWORD dw;
  547. ASN1FRAME Frame;
  548. Frame.Address = Address;
  549. Frame.hFrame = hFrame;
  550. Frame.Level = 0;
  551. ASN1ParserKrbError
  552. KrbError(
  553. FALSE,
  554. BuildDescriptor( ctApplication, pcConstructed, (*(pKerberosFrame) & 0x1F)),
  555. PROP( KRB_ERROR ));
  556. dw = KrbError.Parse( &Frame );
  557. //
  558. // TODO: display "data in error" if unhappy
  559. //
  560. break;
  561. }
  562. case ASN1_KRB_AP_REQ:
  563. case ASN1_KRB_AP_REP:
  564. case ASN1_KRB_SAFE:
  565. case ASN1_KRB_PRIV:
  566. case ASN1_KRB_CRED:
  567. default:
  568. //
  569. // TODO: this is most certainly wrong; use a different property handle
  570. //
  571. if ( FALSE == AttachPropertyInstance(hFrame,
  572. g_KerberosDatabase[ContinuationPacket].hProperty,
  573. BytesLeft,
  574. Address,
  575. 0,
  576. 0,
  577. 0 ))
  578. {
  579. return NULL;
  580. }
  581. break;
  582. }
  583. }
  584. return (LPBYTE) KerberosFrame + BytesLeft;
  585. }
  586. DWORD
  587. WINAPI
  588. KerberosFormatProperties(
  589. IN HFRAME hFrame,
  590. IN ULPBYTE MacFrame,
  591. IN ULPBYTE FrameData,
  592. IN DWORD nPropertyInsts,
  593. IN LPPROPERTYINST p
  594. )
  595. {
  596. //=========================================================================
  597. // Format each property in the property instance table.
  598. //
  599. // The property-specific instance data was used to store the address of a
  600. // property-specific formatting function so all we do here is call each
  601. // function via the instance data pointer.
  602. //=========================================================================
  603. //
  604. // Doing a check here for TCP packets. If it's the first packet,
  605. // we increment FrameData by 4 to get past the length header
  606. //
  607. if ( FrameData[0] == 0x00 &&
  608. FrameData[1] == 0x00 )
  609. {
  610. FrameData += 4;
  611. }
  612. while ( nPropertyInsts-- )
  613. {
  614. ((FORMAT) p->lpPropertyInfo->InstanceData)(p);
  615. p++;
  616. }
  617. return NMERR_SUCCESS;
  618. }