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.

3290 lines
91 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: gettgs.cxx
  7. //
  8. // Contents: GetTGSTicket and support functions
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 04-Mar-94 wader Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "kdcsvr.hxx"
  18. #include "kdctrace.h"
  19. #include <tostring.hxx>
  20. #include <userall.h>
  21. #include "fileno.h"
  22. #define FILENO FILENO_GETTGS
  23. extern LARGE_INTEGER tsInfinity;
  24. extern LONG lInfinity;
  25. UNICODE_STRING KdcNullString = {0,0,NULL};
  26. //--------------------------------------------------------------------
  27. //
  28. // Name: KdcGetS4UPac
  29. //
  30. // Synopsis: Track down the user acct for PAC info.
  31. //
  32. // Effects: Get the PAC
  33. //
  34. // Arguments: S4UClientName - ClientName from S4U PA Data
  35. // PAC - Resultant PAC (signed w/? key)
  36. //
  37. // Requires:
  38. //
  39. // Returns: KDC_ERR_ or KRB_AP_ERR errors only
  40. //
  41. // Notes: Free client name and realm w/
  42. //
  43. //
  44. //--------------------------------------------------------------------------
  45. KERBERR
  46. KdcGetS4UTicketInfo(
  47. IN PKERB_INTERNAL_NAME S4UClientName,
  48. IN OUT PUSER_INTERNAL6_INFORMATION * UserInfo,
  49. IN OUT PSID_AND_ATTRIBUTES_LIST GroupMembership,
  50. IN OUT PKERB_EXT_ERROR ExtendedError
  51. )
  52. {
  53. KERBERR KerbErr;
  54. UNICODE_STRING S4UClient = {0};
  55. KDC_TICKET_INFO S4UClientInfo;
  56. KerbErr = KerbConvertKdcNameToString(
  57. &S4UClient,
  58. S4UClientName,
  59. NULL
  60. );
  61. if (!KERB_SUCCESS(KerbErr))
  62. {
  63. goto Cleanup;
  64. }
  65. //
  66. // Get the user information...
  67. //
  68. KerbErr = KdcGetTicketInfo(
  69. &S4UClient,
  70. SAM_OPEN_BY_UPN_OR_ACCOUNTNAME, // extra flags?
  71. S4UClientName,
  72. NULL,
  73. &S4UClientInfo,
  74. ExtendedError,
  75. NULL,
  76. USER_ALL_KDC_GET_PAC_AUTH_DATA,
  77. 0L,
  78. UserInfo,
  79. GroupMembership
  80. );
  81. if (!KERB_SUCCESS(KerbErr))
  82. {
  83. DebugLog((DEB_ERROR, "Getting the ticket info for S4U req failed - %x\n", KerbErr));
  84. DsysAssert(FALSE);
  85. goto Cleanup;
  86. }
  87. Cleanup:
  88. KerbFreeString(&S4UClient);
  89. FreeTicketInfo(
  90. &S4UClientInfo
  91. );
  92. return KerbErr;
  93. }
  94. //+-------------------------------------------------------------------------
  95. //
  96. // Function: KdcAuditAccountMapping
  97. //
  98. // Synopsis: Generates, if necessary, a success/failure audit for name
  99. // mapping. The names are converted to a string before
  100. // being passed to the LSA.
  101. //
  102. // Effects:
  103. //
  104. // Arguments:
  105. //
  106. // Requires:
  107. //
  108. // Returns:
  109. //
  110. // Notes:
  111. //
  112. //
  113. //--------------------------------------------------------------------------
  114. VOID
  115. KdcAuditAccountMapping(
  116. IN PKERB_INTERNAL_NAME ClientName,
  117. IN KERB_REALM ClientRealm,
  118. IN OPTIONAL PKDC_TICKET_INFO MappedTicketInfo
  119. )
  120. {
  121. UNICODE_STRING ClientString = {0};
  122. PUNICODE_STRING MappedName = NULL;
  123. UNICODE_STRING UnicodeRealm = {0};
  124. UNICODE_STRING NullString = {0};
  125. KERBERR KerbErr;
  126. BOOLEAN Successful;
  127. if (ARGUMENT_PRESENT(MappedTicketInfo))
  128. {
  129. if (!SecData.AuditKdcEvent(KDC_AUDIT_MAP_SUCCESS))
  130. {
  131. return;
  132. }
  133. Successful = TRUE;
  134. MappedName = &MappedTicketInfo->AccountName;
  135. }
  136. else
  137. {
  138. if (!SecData.AuditKdcEvent(KDC_AUDIT_MAP_FAILURE))
  139. {
  140. return;
  141. }
  142. MappedName = &NullString;
  143. Successful = FALSE;
  144. }
  145. KerbErr = KerbConvertRealmToUnicodeString(
  146. &UnicodeRealm,
  147. &ClientRealm
  148. );
  149. if (!KERB_SUCCESS(KerbErr))
  150. {
  151. return;
  152. }
  153. if (KERB_SUCCESS(KerbConvertKdcNameToString(
  154. &ClientString,
  155. ClientName,
  156. &UnicodeRealm
  157. )))
  158. {
  159. LsaIAuditAccountLogon(
  160. SE_AUDITID_ACCOUNT_MAPPED,
  161. Successful,
  162. &GlobalKdcName,
  163. &ClientString,
  164. MappedName,
  165. 0 // no status
  166. );
  167. KerbFreeString(
  168. &ClientString
  169. );
  170. }
  171. KerbFreeString(
  172. &UnicodeRealm
  173. );
  174. }
  175. //----------------------------------------------------------------
  176. //
  177. // Name: KdcInsertAuthorizationData
  178. //
  179. // Synopsis: Inserts auth data into a newly created ticket.
  180. //
  181. // Arguments: FinalTicket - Ticket to insert Auth data into
  182. // EncryptedAuthData - Auth data (optional)
  183. // SourceTicket - Source ticket
  184. //
  185. // Notes: This copies the authorization data from the source ticket
  186. // to the destiation ticket, and adds the authorization data
  187. // passed in. It is called by GetTGSTicket.
  188. //
  189. // This assumes that pedAuthData is an encrypted
  190. // KERB_AUTHORIZATION_DATA.
  191. // It will copy all the elements of that list to the new ticket.
  192. // If pedAuthData is not supplied (or is empty), and there is
  193. // auth data in the source ticket, it is copied to the new
  194. // ticket. If no source ticket, and no auth data is passed
  195. // in, nothing is done.
  196. //
  197. //----------------------------------------------------------------
  198. KERBERR
  199. KdcInsertAuthorizationData(
  200. OUT PKERB_ENCRYPTED_TICKET FinalTicket,
  201. OUT PKERB_EXT_ERROR pExtendedError,
  202. IN OPTIONAL PKERB_ENCRYPTED_DATA EncryptedAuthData,
  203. IN OPTIONAL PKERB_INTERNAL_NAME S4UClientName,
  204. IN BOOLEAN DoingS4U,
  205. IN PKERB_ENCRYPTED_TICKET SourceTicket,
  206. IN BOOLEAN AddResourceGroups,
  207. IN OPTIONAL PKDC_TICKET_INFO OriginalServerInfo,
  208. IN OPTIONAL PKERB_ENCRYPTION_KEY OriginalServerKey,
  209. IN OPTIONAL PKERB_ENCRYPTION_KEY TargetServerKey
  210. )
  211. {
  212. PKERB_AUTHORIZATION_DATA SourceAuthData = NULL;
  213. PKERB_AUTHORIZATION_DATA FinalAuthData = NULL;
  214. PKERB_AUTHORIZATION_DATA PacAuthData = NULL;
  215. PKERB_AUTHORIZATION_DATA NewPacAuthData = NULL;
  216. KERBERR KerbErr = KDC_ERR_NONE;
  217. PKERB_AUTHORIZATION_DATA_LIST * TempAuthData = NULL;
  218. PKERB_AUTHORIZATION_DATA NextAuthData;
  219. PKERB_INTERNAL_NAME ClientName = NULL;
  220. PKERB_IF_RELEVANT_AUTH_DATA * IfRelevantData = NULL;
  221. PKERB_AUTHORIZATION_DATA SuppliedAuthData = NULL;
  222. UNICODE_STRING DummyName = {0};
  223. SID_AND_ATTRIBUTES_LIST S4UGroupMembership = {0};
  224. PUSER_INTERNAL6_INFORMATION S4UUserInfo = NULL;
  225. TRACE(KDC, InsertAuthorizationData, DEB_FUNCTION);
  226. D_DebugLog(( DEB_T_TICKETS, "Inserting authorization data into ticket.\n" ));
  227. //
  228. // First try to decrypt the supplied authorization data
  229. //
  230. if (!DoingS4U)
  231. {
  232. if (ARGUMENT_PRESENT(EncryptedAuthData))
  233. {
  234. KerbErr = KerbDecryptDataEx(
  235. EncryptedAuthData,
  236. &SourceTicket->key,
  237. KERB_NON_KERB_SALT, // WAS BUG: wrong salt, removed per MikeSw
  238. &EncryptedAuthData->cipher_text.length,
  239. EncryptedAuthData->cipher_text.value
  240. );
  241. if (!KERB_SUCCESS(KerbErr))
  242. {
  243. DebugLog((DEB_WARN,
  244. "KLIN(%x) Failed to decrypt encrypted auth data: 0x%x\n",
  245. KLIN(FILENO, __LINE__),
  246. KerbErr));
  247. goto Cleanup;
  248. }
  249. //
  250. // Now decode it
  251. //
  252. KerbErr = KerbUnpackData(
  253. EncryptedAuthData->cipher_text.value,
  254. EncryptedAuthData->cipher_text.length,
  255. PKERB_AUTHORIZATION_DATA_LIST_PDU,
  256. (PVOID *) &TempAuthData
  257. );
  258. if (!KERB_SUCCESS(KerbErr))
  259. {
  260. goto Cleanup;
  261. }
  262. if (TempAuthData != NULL)
  263. {
  264. SuppliedAuthData = *TempAuthData;
  265. }
  266. }
  267. if (SourceTicket->bit_mask & KERB_ENCRYPTED_TICKET_authorization_data_present)
  268. {
  269. DsysAssert(SourceTicket->KERB_ENCRYPTED_TICKET_authorization_data != NULL);
  270. SourceAuthData = SourceTicket->KERB_ENCRYPTED_TICKET_authorization_data;
  271. //
  272. // Get the AuthData from the source ticket
  273. //
  274. KerbErr = KerbGetPacFromAuthData(
  275. SourceAuthData,
  276. &IfRelevantData,
  277. &PacAuthData
  278. );
  279. if (!KERB_SUCCESS(KerbErr))
  280. {
  281. DebugLog((DEB_ERROR,"KLIN(%x) Failed to get pac from auth data: 0x%x\n",
  282. KLIN(FILENO, __LINE__),
  283. KerbErr));
  284. goto Cleanup;
  285. }
  286. }
  287. //
  288. // The new auth data is the original auth data appended to the
  289. // supplied auth data. The new auth data goes first, followed by the
  290. // auth data from the original ticket.
  291. //
  292. //
  293. // Update the PAC, if it is present.
  294. //
  295. if (ARGUMENT_PRESENT(OriginalServerKey) && (PacAuthData != NULL))
  296. {
  297. KerbErr = KdcVerifyAndResignPac(
  298. OriginalServerKey,
  299. TargetServerKey,
  300. OriginalServerInfo,
  301. AddResourceGroups,
  302. PacAuthData
  303. );
  304. if (!KERB_SUCCESS(KerbErr))
  305. {
  306. DebugLog((DEB_ERROR,"KLIN(%x) Failed to verify & resign pac: 0x%x\n",
  307. KLIN(FILENO, __LINE__),
  308. KerbErr));
  309. goto Cleanup;
  310. }
  311. //
  312. // Copy the old auth data & insert the PAC
  313. //
  314. KerbErr = KdcInsertPacIntoAuthData(
  315. SourceAuthData,
  316. (IfRelevantData != NULL) ? *IfRelevantData : NULL,
  317. PacAuthData,
  318. &FinalAuthData
  319. );
  320. if (!KERB_SUCCESS(KerbErr))
  321. {
  322. DebugLog((DEB_ERROR,"KLIN(%x) Failed to insert pac into auth data: 0x%x\n",
  323. KLIN(FILENO, __LINE__),
  324. KerbErr));
  325. goto Cleanup;
  326. }
  327. }
  328. }
  329. if (DoingS4U)
  330. {
  331. //
  332. // Use the PAC from the S4U data to return in the TGT / Service Ticket
  333. //
  334. KerbErr = KdcGetS4UTicketInfo(
  335. S4UClientName,
  336. &S4UUserInfo,
  337. &S4UGroupMembership,
  338. pExtendedError
  339. );
  340. if (!KERB_SUCCESS(KerbErr))
  341. {
  342. goto Cleanup;
  343. }
  344. KerbErr = KdcGetPacAuthData(
  345. S4UUserInfo,
  346. &S4UGroupMembership,
  347. TargetServerKey,
  348. NULL, // no credential key
  349. AddResourceGroups,
  350. FinalTicket,
  351. S4UClientName,
  352. &NewPacAuthData,
  353. pExtendedError
  354. );
  355. SamIFreeSidAndAttributesList(&S4UGroupMembership);
  356. SamIFree_UserInternal6Information( S4UUserInfo );
  357. if (!KERB_SUCCESS(KerbErr))
  358. {
  359. DebugLog((DEB_ERROR, "Failed to get S4UPacAUthData\n"));
  360. DsysAssert(FALSE);
  361. goto Cleanup;
  362. }
  363. FinalAuthData = NewPacAuthData;
  364. NewPacAuthData = NULL;
  365. }
  366. //
  367. // If there was no original PAC, try to insert one here. If the ticket
  368. // was issued from this realm we don't add a pac.
  369. //
  370. else if ((PacAuthData == NULL) && !SecData.IsOurRealm(&SourceTicket->client_realm))
  371. {
  372. KDC_TICKET_INFO ClientTicketInfo = {0};
  373. SID_AND_ATTRIBUTES_LIST GroupMembership = {0};
  374. PUSER_INTERNAL6_INFORMATION UserInfo = NULL;
  375. //
  376. // Try mapping the name to get a PAC
  377. //
  378. KerbErr = KerbConvertPrincipalNameToKdcName(
  379. &ClientName,
  380. &SourceTicket->client_name
  381. );
  382. if (!KERB_SUCCESS(KerbErr))
  383. {
  384. goto Cleanup;
  385. }
  386. KerbErr = KdcGetTicketInfo(
  387. &DummyName,
  388. SAM_OPEN_BY_ALTERNATE_ID,
  389. ClientName,
  390. &SourceTicket->client_realm,
  391. &ClientTicketInfo,
  392. pExtendedError,
  393. NULL, // no handle
  394. USER_ALL_KDC_GET_PAC_AUTH_DATA,
  395. 0L, // no extended fields
  396. &UserInfo,
  397. &GroupMembership
  398. );
  399. if (KERB_SUCCESS(KerbErr))
  400. {
  401. KdcAuditAccountMapping(
  402. ClientName,
  403. SourceTicket->client_realm,
  404. &ClientTicketInfo
  405. );
  406. FreeTicketInfo(&ClientTicketInfo);
  407. KerbFreeKdcName(&ClientName);
  408. KerbErr = KdcGetPacAuthData(
  409. UserInfo,
  410. &GroupMembership,
  411. TargetServerKey,
  412. NULL, // no credential key
  413. AddResourceGroups,
  414. FinalTicket,
  415. NULL, // no S4U client
  416. &NewPacAuthData,
  417. pExtendedError
  418. );
  419. SamIFreeSidAndAttributesList(&GroupMembership);
  420. SamIFree_UserInternal6Information( UserInfo );
  421. if (!KERB_SUCCESS(KerbErr))
  422. {
  423. goto Cleanup;
  424. }
  425. } else if (KerbErr == KDC_ERR_C_PRINCIPAL_UNKNOWN) {
  426. KdcAuditAccountMapping(
  427. ClientName,
  428. SourceTicket->client_realm,
  429. NULL
  430. );
  431. KerbFreeKdcName(&ClientName);
  432. KerbErr = KDC_ERR_NONE;
  433. }
  434. if (!KERB_SUCCESS(KerbErr))
  435. {
  436. goto Cleanup;
  437. }
  438. //
  439. // If we got a PAC, stick it in the list
  440. //
  441. if (NewPacAuthData != NULL)
  442. {
  443. //
  444. // Copy the old auth data & insert the PAC
  445. //
  446. KerbErr = KerbCopyAndAppendAuthData(
  447. &NewPacAuthData,
  448. SourceAuthData
  449. );
  450. if (!KERB_SUCCESS(KerbErr))
  451. {
  452. DebugLog((DEB_ERROR,"KLIN(%x) Failed to insert pac into auth data: 0x%x\n",
  453. KLIN(FILENO, __LINE__), KerbErr));
  454. goto Cleanup;
  455. }
  456. FinalAuthData = NewPacAuthData;
  457. NewPacAuthData = NULL;
  458. }
  459. }
  460. //
  461. // if there was any auth data and we didn't copy it transfering the
  462. // PAC, do so now
  463. //
  464. if ((SourceAuthData != NULL) && (FinalAuthData == NULL))
  465. {
  466. KerbErr = KerbCopyAndAppendAuthData(
  467. &FinalAuthData,
  468. SourceAuthData
  469. );
  470. if (!KERB_SUCCESS(KerbErr))
  471. {
  472. goto Cleanup;
  473. }
  474. }
  475. if (SuppliedAuthData != NULL)
  476. {
  477. KerbErr = KerbCopyAndAppendAuthData(
  478. &FinalAuthData,
  479. SuppliedAuthData
  480. );
  481. if (!KERB_SUCCESS(KerbErr))
  482. {
  483. goto Cleanup;
  484. }
  485. }
  486. if (FinalAuthData != NULL)
  487. {
  488. FinalTicket->bit_mask |= KERB_ENCRYPTED_TICKET_authorization_data_present;
  489. FinalTicket->KERB_ENCRYPTED_TICKET_authorization_data = FinalAuthData;
  490. FinalAuthData = NULL;
  491. }
  492. KerbErr = KDC_ERR_NONE;
  493. Cleanup:
  494. KerbFreeAuthData(
  495. FinalAuthData
  496. );
  497. if (TempAuthData != NULL)
  498. {
  499. KerbFreeData(
  500. PKERB_AUTHORIZATION_DATA_LIST_PDU,
  501. TempAuthData
  502. );
  503. }
  504. KerbFreeAuthData(NewPacAuthData);
  505. if (IfRelevantData != NULL)
  506. {
  507. KerbFreeData(
  508. PKERB_IF_RELEVANT_AUTH_DATA_PDU,
  509. IfRelevantData
  510. );
  511. }
  512. return(KerbErr);
  513. }
  514. //+---------------------------------------------------------------------------
  515. //
  516. // Function: BuildTicketTGS
  517. //
  518. // Synopsis: Builds (most of) a TGS ticket
  519. //
  520. // Arguments: ServiceTicketInfo - Ticket info for the requested service
  521. // ReferralRealm - Realm to build referral to
  522. // RequestBody - The request causing this ticket to be built
  523. // SourceTicket - The TGT used to make this request
  524. // Referral - TRUE if this is an inter-realm referral ticke
  525. // CommonEType - Contains the common encryption type between
  526. // client and server
  527. // NewTicket - The new ticket built here.
  528. //
  529. //
  530. // History: 24-May-93 WadeR Created
  531. //
  532. // Notes: see 3.3.3, A.6 of the Kerberos V5 R5.2 spec
  533. //
  534. //----------------------------------------------------------------------------
  535. KERBERR
  536. BuildTicketTGS(
  537. IN PKDC_TICKET_INFO ServiceTicketInfo,
  538. IN PKERB_KDC_REQUEST_BODY RequestBody,
  539. IN PKERB_TICKET SourceTicket,
  540. IN BOOLEAN Referral,
  541. IN OPTIONAL PKERB_INTERNAL_NAME S4UClientName,
  542. IN OPTIONAL PUNICODE_STRING S4UClientRealm,
  543. IN ULONG CommonEType,
  544. OUT PKERB_TICKET NewTicket,
  545. IN OUT PKERB_EXT_ERROR ExtendedError
  546. )
  547. {
  548. KERBERR KerbErr = KDC_ERR_NONE;
  549. KERB_TICKET OutputTicket;
  550. PKERB_ENCRYPTED_TICKET EncryptedTicket;
  551. PKERB_ENCRYPTED_TICKET SourceEncryptPart;
  552. LARGE_INTEGER SourceRenewUntil;
  553. LARGE_INTEGER SourceEndTime;
  554. LARGE_INTEGER SourceStartTime;
  555. LARGE_INTEGER TicketLifespan;
  556. LARGE_INTEGER TicketRenewspan;
  557. UNICODE_STRING NewTransitedInfo = {0,0,NULL};
  558. UNICODE_STRING ClientRealm = {0,0,NULL};
  559. UNICODE_STRING TransitedRealm = {0,0,NULL};
  560. UNICODE_STRING OldTransitedInfo = {0,0,NULL};
  561. STRING OldTransitedString;
  562. ULONG KdcOptions = 0;
  563. BOOLEAN fKpasswd = FALSE;
  564. ULONG TicketFlags = 0;
  565. ULONG SourceTicketFlags = 0;
  566. PKERB_HOST_ADDRESSES Addresses = NULL;
  567. TRACE(KDC, BuildTicketTGS, DEB_FUNCTION);
  568. D_DebugLog(( DEB_T_TICKETS, "Building a TGS ticket\n" ));
  569. SourceEncryptPart = (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  570. OutputTicket = *NewTicket;
  571. EncryptedTicket = (PKERB_ENCRYPTED_TICKET) OutputTicket.encrypted_part.cipher_text.value;
  572. KdcOptions = KerbConvertFlagsToUlong( &RequestBody->kdc_options );
  573. //
  574. // Get the times from the source ticket into a usable form
  575. //
  576. if (SourceEncryptPart->bit_mask & KERB_ENCRYPTED_TICKET_renew_until_present)
  577. {
  578. KerbConvertGeneralizedTimeToLargeInt(
  579. &SourceRenewUntil,
  580. &SourceEncryptPart->KERB_ENCRYPTED_TICKET_renew_until,
  581. 0
  582. );
  583. }
  584. else
  585. {
  586. SourceRenewUntil.QuadPart = 0;
  587. }
  588. KerbConvertGeneralizedTimeToLargeInt(
  589. &SourceEndTime,
  590. &SourceEncryptPart->endtime,
  591. 0
  592. );
  593. if (SourceEncryptPart->bit_mask & KERB_ENCRYPTED_TICKET_starttime_present)
  594. {
  595. KerbConvertGeneralizedTimeToLargeInt(
  596. &SourceStartTime,
  597. &SourceEncryptPart->KERB_ENCRYPTED_TICKET_starttime,
  598. 0
  599. );
  600. }
  601. else
  602. {
  603. SourceStartTime.QuadPart = 0;
  604. }
  605. //
  606. // Check to see if the request is for the kpasswd service, in
  607. // which case, we only want the ticket to be good for 2 minutes.
  608. //
  609. KerbErr = KerbCompareKdcNameToPrincipalName(
  610. &RequestBody->server_name,
  611. GlobalKpasswdName,
  612. &fKpasswd
  613. );
  614. if (!fKpasswd || !KERB_SUCCESS(KerbErr))
  615. {
  616. TicketLifespan = SecData.KdcTgsTicketLifespan();
  617. TicketRenewspan = SecData.KdcTicketRenewSpan();
  618. }
  619. else
  620. {
  621. TicketLifespan.QuadPart = (LONGLONG) 10000000 * 60 * 2;
  622. TicketRenewspan.QuadPart = (LONGLONG) 10000000 * 60 * 2;
  623. }
  624. //
  625. // TBD: We need to make the ticket 10 minutes if we're doing s4U
  626. //
  627. KerbErr = KdcBuildTicketTimesAndFlags(
  628. 0, // no client policy
  629. ServiceTicketInfo->fTicketOpts,
  630. &TicketLifespan,
  631. &TicketRenewspan,
  632. NULL, // no logoff time
  633. NULL, // no acct expiry.
  634. RequestBody,
  635. SourceEncryptPart,
  636. EncryptedTicket,
  637. ExtendedError
  638. );
  639. if (!KERB_SUCCESS(KerbErr))
  640. {
  641. D_DebugLog((DEB_ERROR,"KLIN(%x) Failed to build ticket times and flags: 0x%x\n",
  642. KLIN(FILENO, __LINE__), KerbErr));
  643. goto Cleanup;
  644. }
  645. TicketFlags = KerbConvertFlagsToUlong( &EncryptedTicket->flags );
  646. SourceTicketFlags = KerbConvertFlagsToUlong( &SourceEncryptPart->flags );
  647. KerbErr = KerbMakeKey(
  648. CommonEType,
  649. &EncryptedTicket->key
  650. );
  651. if (!KERB_SUCCESS(KerbErr))
  652. {
  653. goto Cleanup;
  654. }
  655. OldTransitedString.Buffer = (PCHAR) SourceEncryptPart->transited.contents.value;
  656. OldTransitedString.Length = OldTransitedString.MaximumLength = (USHORT) SourceEncryptPart->transited.contents.length;
  657. //
  658. // Fill in the service names
  659. //
  660. if (Referral)
  661. {
  662. PKERB_INTERNAL_NAME TempServiceName;
  663. //
  664. // For referral tickets we put a the name "krbtgt/remoterealm@localrealm"
  665. //
  666. //
  667. // We should only be doing this when we didn't get a non-ms principal
  668. //
  669. KerbErr = KerbBuildFullServiceKdcName(
  670. &ServiceTicketInfo->AccountName,
  671. SecData.KdcServiceName(),
  672. KRB_NT_SRV_INST,
  673. &TempServiceName
  674. );
  675. if (!KERB_SUCCESS(KerbErr))
  676. {
  677. goto Cleanup;
  678. }
  679. KerbErr = KerbConvertKdcNameToPrincipalName(
  680. &OutputTicket.server_name,
  681. TempServiceName
  682. );
  683. KerbFreeKdcName(&TempServiceName);
  684. if (!KERB_SUCCESS(KerbErr))
  685. {
  686. goto Cleanup;
  687. }
  688. //
  689. // If we got here on a referral ticket and are generating one
  690. // and the referral ticket we received was not from the client's
  691. // realm, add in the transited information.
  692. //
  693. if (!KerbCompareRealmNames(
  694. &SourceEncryptPart->client_realm,
  695. &SourceTicket->realm))
  696. {
  697. KerbErr = KerbStringToUnicodeString(
  698. &OldTransitedInfo,
  699. &OldTransitedString
  700. );
  701. if (!KERB_SUCCESS(KerbErr))
  702. {
  703. goto Cleanup;
  704. }
  705. KerbErr = KerbConvertRealmToUnicodeString(
  706. &TransitedRealm,
  707. &SourceTicket->realm
  708. );
  709. if (!KERB_SUCCESS(KerbErr))
  710. {
  711. goto Cleanup;
  712. }
  713. KerbErr = KerbConvertRealmToUnicodeString(
  714. &ClientRealm,
  715. &SourceEncryptPart->client_realm
  716. );
  717. if (!KERB_SUCCESS(KerbErr))
  718. {
  719. goto Cleanup;
  720. }
  721. KerbErr = KdcInsertTransitedRealm(
  722. &NewTransitedInfo,
  723. &OldTransitedInfo,
  724. &ClientRealm,
  725. &TransitedRealm,
  726. SecData.KdcDnsRealmName()
  727. );
  728. if (!KERB_SUCCESS(KerbErr))
  729. {
  730. goto Cleanup;
  731. }
  732. }
  733. }
  734. else
  735. {
  736. UNICODE_STRING TempServiceName;
  737. //
  738. // If the client didn't request name canonicalization, use the
  739. // name supplied by the client
  740. //
  741. if (((KdcOptions & KERB_KDC_OPTIONS_name_canonicalize) != 0) &&
  742. ((ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY) == 0))
  743. {
  744. if (ServiceTicketInfo->UserId == DOMAIN_USER_RID_KRBTGT)
  745. {
  746. PKERB_INTERNAL_NAME TempServiceName = NULL;
  747. KerbErr = KerbBuildFullServiceKdcName(
  748. SecData.KdcDnsRealmName(),
  749. SecData.KdcServiceName(),
  750. KRB_NT_SRV_INST,
  751. &TempServiceName
  752. );
  753. if (!KERB_SUCCESS(KerbErr))
  754. {
  755. goto Cleanup;
  756. }
  757. KerbErr = KerbConvertKdcNameToPrincipalName(
  758. &OutputTicket.server_name,
  759. TempServiceName
  760. );
  761. KerbFreeKdcName(&TempServiceName);
  762. }
  763. else
  764. //
  765. // We no longer use the NC bit to change the server name, so just
  766. // duplicate the non-NC case, and return the server name from
  767. // the TGS_REQ. NC is still used for building PA DATA for referral
  768. // however. and we should keep it for TGT renewal. TS 2001-4-03
  769. //
  770. {
  771. KerbErr = KerbDuplicatePrincipalName(
  772. &OutputTicket.server_name,
  773. &RequestBody->KERB_KDC_REQUEST_BODY_server_name
  774. );
  775. }
  776. }
  777. else
  778. {
  779. KerbErr = KerbDuplicatePrincipalName(
  780. &OutputTicket.server_name,
  781. &RequestBody->KERB_KDC_REQUEST_BODY_server_name
  782. );
  783. }
  784. if (!KERB_SUCCESS(KerbErr))
  785. {
  786. goto Cleanup;
  787. }
  788. }
  789. //
  790. // Copy all the other strings over
  791. //
  792. EncryptedTicket->client_realm = SourceEncryptPart->client_realm;
  793. //
  794. // S4U dance... Get the client name and realm from
  795. //
  796. if (ARGUMENT_PRESENT(S4UClientName) &&
  797. ARGUMENT_PRESENT(S4UClientRealm) &&
  798. !Referral)
  799. {
  800. DebugLog((DEB_ERROR, "Swapping real client name for S4U CLient name\n"));
  801. KerbErr = KerbConvertKdcNameToPrincipalName(
  802. &EncryptedTicket->client_name,
  803. S4UClientName
  804. );
  805. if (!KERB_SUCCESS(KerbErr))
  806. {
  807. goto Cleanup;
  808. }
  809. KerbErr = KerbConvertUnicodeStringToRealm(
  810. &EncryptedTicket->client_realm,
  811. S4UClientRealm
  812. );
  813. if (!KERB_SUCCESS(KerbErr))
  814. {
  815. goto Cleanup;
  816. }
  817. }
  818. else
  819. {
  820. KerbErr = KerbDuplicatePrincipalName(
  821. &EncryptedTicket->client_name,
  822. &SourceEncryptPart->client_name
  823. );
  824. if (!KERB_SUCCESS(KerbErr))
  825. {
  826. goto Cleanup;
  827. }
  828. EncryptedTicket->client_realm = SourceEncryptPart->client_realm;
  829. }
  830. //
  831. // If the client did not request canonicalization, return the same
  832. // realm as it sent. Otherwise, send our DNS realm name
  833. //
  834. // if (((KdcOptions & KERB_KDC_OPTIONS_name_canonicalize) != 0) ||
  835. // ((ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY) == 0))
  836. //
  837. // {
  838. OutputTicket.realm = SecData.KdcKerbDnsRealmName();
  839. // }
  840. // else
  841. // {
  842. // OutputTicket.realm = RequestBody->realm;
  843. // }
  844. //
  845. // Insert transited realms, if present
  846. //
  847. if (NewTransitedInfo.Length != 0)
  848. {
  849. STRING TempString;
  850. KerbErr = KerbUnicodeStringToKerbString(
  851. &TempString,
  852. &NewTransitedInfo
  853. );
  854. if (!KERB_SUCCESS(KerbErr))
  855. {
  856. goto Cleanup;
  857. }
  858. EncryptedTicket->transited.transited_type = DOMAIN_X500_COMPRESS;
  859. EncryptedTicket->transited.contents.value = (PUCHAR) TempString.Buffer;
  860. EncryptedTicket->transited.contents.length = (int) TempString.Length;
  861. }
  862. else
  863. {
  864. EncryptedTicket->transited.transited_type = DOMAIN_X500_COMPRESS;
  865. EncryptedTicket->transited.contents.value = (PUCHAR) MIDL_user_allocate(OldTransitedString.Length);
  866. if (EncryptedTicket->transited.contents.value == NULL)
  867. {
  868. KerbErr = KRB_ERR_GENERIC;
  869. goto Cleanup;
  870. }
  871. EncryptedTicket->transited.contents.length = (int) OldTransitedString.Length;
  872. RtlCopyMemory(
  873. EncryptedTicket->transited.contents.value,
  874. OldTransitedString.Buffer,
  875. OldTransitedString.Length
  876. );
  877. }
  878. //
  879. // Insert the client addresses. We only update them if the new ticket
  880. // is forwarded of proxied and the source ticket was forwardable or proxiable
  881. // - else we copy the old ones
  882. //
  883. if ((((TicketFlags & KERB_TICKET_FLAGS_forwarded) != 0) &&
  884. ((SourceTicketFlags & KERB_TICKET_FLAGS_forwardable) != 0)) ||
  885. (((TicketFlags & KERB_TICKET_FLAGS_proxy) != 0) &&
  886. ((SourceTicketFlags & KERB_TICKET_FLAGS_proxiable) != 0)))
  887. {
  888. if ((RequestBody->bit_mask & addresses_present) != 0)
  889. {
  890. Addresses = RequestBody->addresses;
  891. }
  892. }
  893. else
  894. {
  895. if ((SourceEncryptPart->bit_mask & KERB_ENCRYPTED_TICKET_client_addresses_present) != 0)
  896. {
  897. Addresses = SourceEncryptPart->KERB_ENCRYPTED_TICKET_client_addresses;
  898. }
  899. }
  900. if (Addresses != NULL)
  901. {
  902. EncryptedTicket->KERB_ENCRYPTED_TICKET_client_addresses = Addresses;
  903. EncryptedTicket->bit_mask |= KERB_ENCRYPTED_TICKET_client_addresses_present;
  904. }
  905. //
  906. // The authorization data will be added by the caller, so set it
  907. // to NULL here.
  908. //
  909. EncryptedTicket->KERB_ENCRYPTED_TICKET_authorization_data = NULL;
  910. OutputTicket.ticket_version = KERBEROS_VERSION;
  911. *NewTicket = OutputTicket;
  912. Cleanup:
  913. if (!KERB_SUCCESS(KerbErr))
  914. {
  915. KdcFreeInternalTicket(&OutputTicket);
  916. }
  917. KerbFreeString(&NewTransitedInfo);
  918. KerbFreeString(&OldTransitedInfo);
  919. KerbFreeString(&ClientRealm);
  920. KerbFreeString(&TransitedRealm);
  921. return(KerbErr);
  922. }
  923. //+-------------------------------------------------------------------------
  924. //
  925. // Function: KdcVerifyTgsLogonRestrictions
  926. //
  927. // Synopsis: Verifies that a client is allowed to request a TGS ticket
  928. // by checking logon restrictions.
  929. //
  930. // Effects:
  931. //
  932. // Arguments: ClientName - Name of client to check
  933. //
  934. // Requires:
  935. //
  936. // Returns: KDC_ERR_NONE or a logon restriction error
  937. //
  938. // Notes:
  939. //
  940. //
  941. //--------------------------------------------------------------------------
  942. KERBERR
  943. KdcCheckTgsLogonRestrictions(
  944. IN PKERB_INTERNAL_NAME ClientName,
  945. IN PUNICODE_STRING ClientRealm,
  946. OUT PKERB_EXT_ERROR pExtendedError
  947. )
  948. {
  949. KERBERR Status;
  950. UNICODE_STRING MappedClientRealm = {0};
  951. BOOLEAN ClientReferral;
  952. KDC_TICKET_INFO ClientInfo = {0};
  953. SAMPR_HANDLE UserHandle = NULL;
  954. PUSER_INTERNAL6_INFORMATION UserInfo = NULL;
  955. LARGE_INTEGER LogoffTime;
  956. NTSTATUS LogonStatus = STATUS_SUCCESS;
  957. //
  958. // If the client is from a different realm, don't bother looking
  959. // it up - the account won't be here.
  960. //
  961. if (!SecData.IsOurRealm(
  962. ClientRealm
  963. ))
  964. {
  965. return(KDC_ERR_NONE);
  966. }
  967. //
  968. // Normalize the client name
  969. //
  970. Status = KdcNormalize(
  971. ClientName,
  972. NULL,
  973. ClientRealm,
  974. KDC_NAME_CLIENT,
  975. &ClientReferral,
  976. &MappedClientRealm,
  977. &ClientInfo,
  978. pExtendedError,
  979. &UserHandle,
  980. USER_ALL_KERB_CHECK_LOGON_RESTRICTIONS,
  981. 0L,
  982. &UserInfo,
  983. NULL // no group memberships
  984. );
  985. if (!KERB_SUCCESS(Status))
  986. {
  987. DebugLog((DEB_ERROR,"KLIN(%x) Failed to normalize name ", KLIN(FILENO, __LINE__)));
  988. KerbPrintKdcName(DEB_ERROR,ClientName);
  989. goto Cleanup;
  990. }
  991. Status = KerbCheckLogonRestrictions(
  992. UserHandle,
  993. NULL, // No client address is available
  994. &UserInfo->I1,
  995. KDC_RESTRICT_PKINIT_USED | KDC_RESTRICT_IGNORE_PW_EXPIRATION, // Don't bother checking for password expiration
  996. &LogoffTime,
  997. &LogonStatus
  998. );
  999. if (!KERB_SUCCESS(Status))
  1000. {
  1001. DebugLog((DEB_WARN,"KLIN (%x) Logon restriction check failed: 0x%x\n",
  1002. KLIN(FILENO, __LINE__),Status));
  1003. //
  1004. // This is a *very* important error to trickle back. See 23456 in bug DB
  1005. //
  1006. FILL_EXT_ERROR(pExtendedError, LogonStatus, FILENO, __LINE__);
  1007. goto Cleanup;
  1008. }
  1009. Cleanup:
  1010. KerbFreeString( &MappedClientRealm );
  1011. FreeTicketInfo( &ClientInfo );
  1012. SamIFree_UserInternal6Information( UserInfo );
  1013. if (UserHandle != NULL)
  1014. {
  1015. SamrCloseHandle(&UserHandle);
  1016. }
  1017. return Status;
  1018. }
  1019. //+-------------------------------------------------------------------------
  1020. //
  1021. // Function: KdcBuildReferralInfo
  1022. //
  1023. // Synopsis: Builds the referral information to return to the client.
  1024. // We only return the realm name and no server name
  1025. //
  1026. // Effects:
  1027. //
  1028. // Arguments: ReferralRealm - realm to refer client to
  1029. // ReferralInfo - recevies encoded referral info
  1030. //
  1031. // Requires:
  1032. //
  1033. // Returns:
  1034. //
  1035. // Notes:
  1036. //
  1037. //
  1038. //--------------------------------------------------------------------------
  1039. KERBERR
  1040. KdcBuildReferralInfo(
  1041. IN PUNICODE_STRING ReferralRealm,
  1042. OUT PKERB_PA_DATA_LIST *ReferralInfo
  1043. )
  1044. {
  1045. KERBERR KerbErr = KDC_ERR_NONE;
  1046. PKERB_PA_DATA_LIST ListElem = NULL;
  1047. KERB_PA_SERV_REFERRAL ReferralData = {0};
  1048. //
  1049. // Fill in the unencoded structure.
  1050. //
  1051. KerbErr = KerbConvertUnicodeStringToRealm(
  1052. &ReferralData.referred_server_realm,
  1053. ReferralRealm
  1054. );
  1055. if (!KERB_SUCCESS(KerbErr))
  1056. {
  1057. goto Cleanup;
  1058. }
  1059. ListElem = (PKERB_PA_DATA_LIST) MIDL_user_allocate(sizeof(KERB_PA_DATA_LIST));
  1060. if (ListElem == NULL)
  1061. {
  1062. KerbErr = KRB_ERR_GENERIC;
  1063. goto Cleanup;
  1064. }
  1065. RtlZeroMemory(ListElem, sizeof(KERB_PA_DATA_LIST));
  1066. ListElem->value.preauth_data_type = KRB5_PADATA_REFERRAL_INFO;
  1067. KerbErr = KerbPackData(
  1068. &ReferralData,
  1069. KERB_PA_SERV_REFERRAL_PDU,
  1070. (PULONG) &ListElem->value.preauth_data.length,
  1071. &ListElem->value.preauth_data.value
  1072. );
  1073. if (!KERB_SUCCESS(KerbErr))
  1074. {
  1075. goto Cleanup;
  1076. }
  1077. *ReferralInfo = ListElem;
  1078. ListElem = NULL;
  1079. Cleanup:
  1080. if (ListElem != NULL)
  1081. {
  1082. if (ListElem->value.preauth_data.value != NULL)
  1083. {
  1084. KdcFreeEncodedData(ListElem->value.preauth_data.value);
  1085. }
  1086. MIDL_user_free(ListElem);
  1087. }
  1088. KerbFreeRealm(&ReferralData.referred_server_realm);
  1089. return(KerbErr);
  1090. }
  1091. //--------------------------------------------------------------------
  1092. //
  1093. // Name: I_RenewTicket
  1094. //
  1095. // Synopsis: Renews an internal ticket.
  1096. //
  1097. // Arguments: SourceTicket - Source ticket for this request
  1098. // ServiceName - Name of service for ticket
  1099. // ClientRealm - Realm of client
  1100. // ServiceTicketInfo - Ticket info from service account
  1101. // RequestBody - Body of ticket request
  1102. // NewTicket - Receives new ticket
  1103. // CommonEType - Receives common encryption type for service ticket
  1104. // TicketKey - Receives key used to encrypt the ticket
  1105. //
  1106. // Notes: Validates the ticket, gets the service's current key,
  1107. // and builds the reply.
  1108. //
  1109. //
  1110. //--------------------------------------------------------------------
  1111. KERBERR
  1112. I_RenewTicket(
  1113. IN PKERB_TICKET SourceTicket,
  1114. IN PKERB_INTERNAL_NAME ServiceName,
  1115. IN PKDC_TICKET_INFO ServiceTicketInfo,
  1116. IN PKERB_KDC_REQUEST_BODY RequestBody,
  1117. IN PULONG CommonEType,
  1118. OUT PKERB_TICKET NewTicket,
  1119. OUT PKERB_EXT_ERROR pExtendedError
  1120. )
  1121. {
  1122. KERBERR KerbErr = KDC_ERR_NONE;
  1123. PKERB_ENCRYPTED_TICKET SourceEncryptPart = (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  1124. PKERB_ENCRYPTED_TICKET NewEncryptPart = (PKERB_ENCRYPTED_TICKET) NewTicket->encrypted_part.cipher_text.value;
  1125. PKERB_ENCRYPTION_KEY ServerKey;
  1126. BOOLEAN NamesEqual = FALSE;
  1127. TRACE(KDC, I_RenewTicket, DEB_FUNCTION);
  1128. D_DebugLog(( DEB_TRACE, "Trying to renew a ticket to "));
  1129. D_KerbPrintKdcName(DEB_TRACE, ServiceName );
  1130. //
  1131. // Make sure the original is renewable.
  1132. //
  1133. if ((KerbConvertFlagsToUlong(&SourceEncryptPart->flags) & KERB_TICKET_FLAGS_renewable) == 0)
  1134. {
  1135. D_DebugLog((DEB_WARN, "KLIN(%x) Attempt made to renew non-renewable ticket\n",
  1136. KLIN(FILENO, __LINE__)));
  1137. KerbErr = KDC_ERR_BADOPTION;
  1138. goto Cleanup;
  1139. }
  1140. //
  1141. // Make sure the source ticket service equals the service from the ticket info
  1142. //
  1143. KerbErr = KerbCompareKdcNameToPrincipalName(
  1144. &SourceTicket->server_name,
  1145. ServiceName,
  1146. &NamesEqual
  1147. );
  1148. if (!KERB_SUCCESS(KerbErr))
  1149. {
  1150. goto Cleanup;
  1151. }
  1152. if (!NamesEqual)
  1153. {
  1154. //
  1155. // Make sure we the renewed ticket is for the same service as the original.
  1156. //
  1157. FILL_EXT_ERROR(pExtendedError, STATUS_KDC_INVALID_REQUEST, FILENO, __LINE__);
  1158. KerbErr = KDC_ERR_BADOPTION;
  1159. goto Cleanup;
  1160. }
  1161. //
  1162. // Find the common crypt system.
  1163. //
  1164. KerbErr = KerbFindCommonCryptSystem(
  1165. RequestBody->encryption_type,
  1166. ServiceTicketInfo->Passwords,
  1167. NULL,
  1168. CommonEType,
  1169. &ServerKey
  1170. );
  1171. if (!KERB_SUCCESS(KerbErr))
  1172. {
  1173. KdcReportKeyError(
  1174. &ServiceTicketInfo->AccountName,
  1175. &ServiceTicketInfo->AccountName,
  1176. KDCEVENT_NO_KEY_UNION_TGS,
  1177. RequestBody->encryption_type,
  1178. ServiceTicketInfo->Passwords
  1179. );
  1180. goto Cleanup;
  1181. }
  1182. //
  1183. // Build the renewal ticket
  1184. //
  1185. KerbErr = BuildTicketTGS(
  1186. ServiceTicketInfo,
  1187. RequestBody,
  1188. SourceTicket,
  1189. FALSE, // not referral
  1190. NULL, // not doing s4u
  1191. NULL, // not doing s4u
  1192. *CommonEType,
  1193. NewTicket,
  1194. pExtendedError
  1195. );
  1196. if (!KERB_SUCCESS(KerbErr))
  1197. {
  1198. D_DebugLog((DEB_ERROR,
  1199. "KLIN(%x) Failed to build TGS ticket for renewal: 0x%x\n",
  1200. KLIN(FILENO, __LINE__), KerbErr));
  1201. goto Cleanup;
  1202. }
  1203. //
  1204. // BuildTicket puts a random session key in the ticket,
  1205. // so replace it with the one from the source ticket.
  1206. //
  1207. KerbFreeKey(
  1208. &NewEncryptPart->key
  1209. );
  1210. KerbErr = KerbDuplicateKey(
  1211. &NewEncryptPart->key,
  1212. &SourceEncryptPart->key
  1213. );
  1214. if (!KERB_SUCCESS(KerbErr))
  1215. {
  1216. goto Cleanup;
  1217. }
  1218. //
  1219. // Insert the auth data into the new ticket.
  1220. //
  1221. //
  1222. // BUG 455049: if the service password changes, this will cause problems
  1223. // because we don't resign the pac.
  1224. //
  1225. KerbErr = KdcInsertAuthorizationData(
  1226. NewEncryptPart,
  1227. pExtendedError,
  1228. (RequestBody->bit_mask & enc_authorization_data_present) ?
  1229. &RequestBody->enc_authorization_data : NULL,
  1230. NULL,
  1231. FALSE,
  1232. SourceEncryptPart,
  1233. FALSE, // don't add local groups
  1234. NULL,
  1235. NULL,
  1236. NULL
  1237. );
  1238. if (!KERB_SUCCESS(KerbErr))
  1239. {
  1240. DebugLog((DEB_ERROR,"KLIN(%x) Failed to insert authorization data: 0x%x\n",
  1241. KLIN(FILENO, __LINE__), KerbErr));
  1242. goto Cleanup;
  1243. }
  1244. Cleanup:
  1245. if (!KERB_SUCCESS(KerbErr))
  1246. {
  1247. KdcFreeInternalTicket(
  1248. NewTicket
  1249. );
  1250. }
  1251. return(KerbErr);
  1252. }
  1253. //--------------------------------------------------------------------
  1254. //
  1255. // Name: I_Validate
  1256. //
  1257. // Synopsis: Validates a post-dated ticket so that it can be used.
  1258. // This is not implemented.
  1259. //
  1260. // Arguments: pkitSourceTicket - (in) ticket to be validated
  1261. // pkiaAuthenticator -
  1262. // pService - (in) service ticket is for
  1263. // pRealm - (in) realm service exists in
  1264. // pktrRequest - (in) holds nonce for new ticket
  1265. // pkdPAData - (in)
  1266. // pkitTicket - (out) new ticket
  1267. //
  1268. // Notes: See 3.3 of the Kerberos V5 R5.2 spec
  1269. //
  1270. //--------------------------------------------------------------------
  1271. KERBERR
  1272. I_Validate(
  1273. IN PKERB_TICKET SourceTicket,
  1274. IN PKERB_INTERNAL_NAME ServiceName,
  1275. IN PUNICODE_STRING ClientRealm,
  1276. IN PKERB_KDC_REQUEST_BODY RequestBody,
  1277. OUT PULONG CommonEType,
  1278. OUT PKERB_TICKET NewTicket,
  1279. OUT PKERB_EXT_ERROR pExtendedError
  1280. )
  1281. {
  1282. return(KRB_ERR_GENERIC);
  1283. #ifdef notdef
  1284. TRACE(KDC, I_Validate, DEB_FUNCTION);
  1285. HRESULT hr;
  1286. D_DebugLog(( DEB_TRACE, "Trying to validate a ticket to '%ws' for '%ws'...\n",
  1287. pkitSourceTicket->ServerName.accsid.pwszDisplayName,
  1288. pkitSourceTicket->kitEncryptPart.Principal.accsid.pwszDisplayName ));
  1289. PrintRequest( DEB_T_TICKETS, pktrRequest );
  1290. PrintTicket( DEB_T_TICKETS, "Ticket to validate:", pkitSourceTicket );
  1291. if ( (pkitSourceTicket->kitEncryptPart.fTicketFlags &
  1292. (KERBFLAG_POSTDATED | KERBFLAG_INVALID))
  1293. != (KERBFLAG_POSTDATED | KERBFLAG_INVALID) )
  1294. {
  1295. hr = KDC_E_BADOPTION;
  1296. }
  1297. else if (_wcsicmp(pkitSourceTicket->ServerName.accsid.pwszDisplayName,
  1298. pasService->pwszDisplayName) != 0)
  1299. {
  1300. hr = KDC_E_BADOPTION;
  1301. }
  1302. else
  1303. {
  1304. TimeStamp tsNow, tsMinus, tsPlus;
  1305. GetCurrentTimeStamp( &tsNow );
  1306. tsMinus = tsNow - SkewTime;
  1307. tsPlus = tsNow + SkewTime;
  1308. PrintTime(DEB_TRACE, "Current time: ", tsNow );
  1309. PrintTime(DEB_TRACE, "Past time: ", tsMinus );
  1310. PrintTime(DEB_TRACE, "Future time: ", tsPlus );
  1311. if (pkitSourceTicket->kitEncryptPart.tsStartTime > tsPlus )
  1312. hr = KRB_E_TKT_NYV;
  1313. else if (pkitSourceTicket->kitEncryptPart.tsEndTime < tsMinus )
  1314. hr = KRB_E_TKT_EXPIRED;
  1315. else
  1316. {
  1317. *pkitTicket = *pkitSourceTicket;
  1318. pkitTicket->kitEncryptPart.fTicketFlags &= (~KERBFLAG_INVALID);
  1319. hr = S_OK;
  1320. }
  1321. }
  1322. return(hr);
  1323. #endif // notdef
  1324. }
  1325. //--------------------------------------------------------------------
  1326. //
  1327. // Name: I_GetTGSTicket
  1328. //
  1329. // Synopsis: Gets an internal ticket using a KDC ticket (TGT).
  1330. //
  1331. // Arguments: SourceTicket - TGT for the client
  1332. // ServiceName - Service to get a ticket to
  1333. // RequestBody - Body of KDC request message
  1334. // ServiceTicketInfo - Ticket info for the service of the
  1335. // source ticket
  1336. // TicketEncryptionKey - If present, then this is a
  1337. // enc_tkt_in_skey request and the PAC should be
  1338. // encrypted with this key.
  1339. // CommonEType - Receives common encrytion type
  1340. // NewTicket - Receives newly created ticket
  1341. // ReplyPaData - Contains any PA data to put in the reply
  1342. //
  1343. // Notes: See GetTGSTicket.
  1344. //
  1345. //
  1346. //--------------------------------------------------------------------
  1347. KERBERR
  1348. I_GetTGSTicket(
  1349. IN PKERB_TICKET SourceTicket,
  1350. IN PKERB_INTERNAL_NAME ServiceName,
  1351. IN PUNICODE_STRING RequestRealm,
  1352. IN PKERB_KDC_REQUEST_BODY RequestBody,
  1353. IN PKDC_TICKET_INFO ServiceTicketInfo,
  1354. IN OPTIONAL PKERB_ENCRYPTION_KEY TicketEncryptionKey,
  1355. IN OPTIONAL PKERB_INTERNAL_NAME S4UClientName,
  1356. IN OPTIONAL PUNICODE_STRING S4UClientRealm,
  1357. OUT PULONG CommonEType,
  1358. OUT PKERB_TICKET Ticket,
  1359. OUT PKERB_PA_DATA_LIST * ReplyPaData,
  1360. OUT PKERB_EXT_ERROR pExtendedError
  1361. )
  1362. {
  1363. KERBERR KerbErr = KDC_ERR_NONE;
  1364. UNICODE_STRING LocalServiceName;
  1365. UNICODE_STRING ServicePrincipal;
  1366. UNICODE_STRING ServiceRealm = {0};
  1367. UNICODE_STRING ClientRealm = {0};
  1368. BOOLEAN Referral = FALSE;
  1369. KERB_ENCRYPTED_TICKET EncryptedTicket = {0};
  1370. PKERB_ENCRYPTED_TICKET OutputEncryptedTicket = NULL;
  1371. PKERB_ENCRYPTED_TICKET SourceEncryptPart = NULL;
  1372. PKERB_INTERNAL_NAME TargetPrincipal = ServiceName;
  1373. KERB_TICKET NewTicket = {0};
  1374. PKERB_ENCRYPTION_KEY ServerKey;
  1375. PKERB_ENCRYPTION_KEY OldServerKey;
  1376. KDC_TICKET_INFO OldServiceTicketInfo = {0};
  1377. ULONG NameFlags = 0;
  1378. ULONG KdcOptions = 0;
  1379. BOOLEAN GetS4UPac = FALSE;
  1380. TRACE(KDC, I_GetTGSTicket, DEB_FUNCTION);
  1381. //
  1382. // Store away the encrypted ticket from the output ticket to
  1383. // assign it at the end.
  1384. //
  1385. SourceEncryptPart = (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  1386. OutputEncryptedTicket = (PKERB_ENCRYPTED_TICKET) Ticket->encrypted_part.cipher_text.value;
  1387. NewTicket.encrypted_part.cipher_text.value = (PUCHAR) &EncryptedTicket;
  1388. //
  1389. // Copy the space for flags from the real destination.
  1390. //
  1391. EncryptedTicket.flags = OutputEncryptedTicket->flags;
  1392. LocalServiceName.Buffer = NULL;
  1393. D_DebugLog(( DEB_TRACE, "Trying to build a new ticket to "));
  1394. D_KerbPrintKdcName( DEB_TRACE, ServiceName );
  1395. KdcOptions = KerbConvertFlagsToUlong( &RequestBody->kdc_options );
  1396. if (KdcOptions & (KERB_KDC_OPTIONS_unused7 |
  1397. KERB_KDC_OPTIONS_reserved |
  1398. KERB_KDC_OPTIONS_unused9) )
  1399. {
  1400. DebugLog(( DEB_ERROR,"KLIN(%x) Bad options in TGS request: 0x%x\n",
  1401. KLIN(FILENO, __LINE__), KdcOptions ));
  1402. KerbErr = KDC_ERR_BADOPTION;
  1403. goto Cleanup;
  1404. }
  1405. //
  1406. // Check if the client said to canonicalize the name
  1407. //
  1408. // if ((KdcOptions & KERB_KDC_OPTIONS_name_canonicalize) != 0)
  1409. {
  1410. NameFlags |= KDC_NAME_CHECK_GC;
  1411. }
  1412. //
  1413. // Verify this account is allowed to issue tickets.
  1414. //
  1415. if ((ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&
  1416. ((ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0))
  1417. {
  1418. D_DebugLog((DEB_ERROR,"Trying to make a TGS request with a ticket to %wZ\n",
  1419. &ServiceTicketInfo->AccountName ));
  1420. KerbErr = KRB_AP_ERR_NOT_US;
  1421. goto Cleanup;
  1422. }
  1423. //
  1424. // Copy the ticket info into the old structure. It will be replaced with
  1425. // new info from Normalize.
  1426. //
  1427. OldServiceTicketInfo = *ServiceTicketInfo;
  1428. RtlZeroMemory(
  1429. ServiceTicketInfo,
  1430. sizeof(KDC_TICKET_INFO)
  1431. );
  1432. //
  1433. // If the client name is in our realm, verify client
  1434. // identity and build the PAC for the client.
  1435. //
  1436. if ( ARGUMENT_PRESENT(S4UClientRealm) &&
  1437. SecData.IsOurRealm(S4UClientRealm) )
  1438. {
  1439. // Fester:
  1440. DebugLog((DEB_ERROR, "Doing S4U client lookup!\n"));
  1441. GetS4UPac = TRUE;
  1442. }
  1443. //
  1444. // If we have to refer, Normalize will put the credentials of the target
  1445. // realm in ServiceTicketInfo. Otherwise, it will be NULL.
  1446. //
  1447. KerbErr = KdcNormalize(
  1448. TargetPrincipal,
  1449. NULL,
  1450. RequestRealm,
  1451. NameFlags | KDC_NAME_SERVER | KDC_NAME_FOLLOW_REFERRALS,
  1452. &Referral,
  1453. &ServiceRealm,
  1454. ServiceTicketInfo,
  1455. pExtendedError,
  1456. NULL, // no user handle
  1457. 0L, // no fields to fetch
  1458. 0L, // no extended fields
  1459. NULL, // no user all information
  1460. NULL // no group membership
  1461. );
  1462. if (!KERB_SUCCESS(KerbErr))
  1463. {
  1464. DebugLog((DEB_WARN,"KLIN(%x) Failed to normalize ", KLIN(FILENO, __LINE__)));
  1465. KerbPrintKdcName(DEB_WARN,ServiceName);
  1466. DebugLog((DEB_WARN,"\t 0x%x\n",KerbErr));
  1467. goto Cleanup;
  1468. }
  1469. if (ServiceTicketInfo != NULL)
  1470. {
  1471. if ((ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&
  1472. (ServiceTicketInfo->UserAccountControl & USER_ACCOUNT_DISABLED) != 0)
  1473. {
  1474. KerbErr = KDC_ERR_CLIENT_REVOKED;
  1475. D_DebugLog((DEB_WARN,"KLIN(%x) Failed to normalize, account is disabled ",
  1476. KLIN(FILENO, __LINE__)));
  1477. KerbPrintKdcName(DEB_WARN,ServiceName);
  1478. D_DebugLog((DEB_WARN,"\t 0x%x\n",KerbErr));
  1479. FILL_EXT_ERROR(pExtendedError, STATUS_ACCOUNT_DISABLED, FILENO, __LINE__);
  1480. goto Cleanup;
  1481. }
  1482. }
  1483. //
  1484. // If this isn't an interdomain trust account, go ahead and issue a normal
  1485. // ticket.
  1486. //
  1487. if ((ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0)
  1488. {
  1489. //
  1490. // Find the common crypt system.
  1491. //
  1492. KerbErr = KerbFindCommonCryptSystem(
  1493. RequestBody->encryption_type,
  1494. ServiceTicketInfo->Passwords,
  1495. NULL,
  1496. CommonEType,
  1497. &ServerKey
  1498. );
  1499. if (!KERB_SUCCESS(KerbErr))
  1500. {
  1501. KdcReportKeyError(
  1502. &ServiceTicketInfo->AccountName,
  1503. &ServiceTicketInfo->AccountName,
  1504. KDCEVENT_NO_KEY_UNION_TGS,
  1505. RequestBody->encryption_type,
  1506. ServiceTicketInfo->Passwords
  1507. );
  1508. goto Cleanup;
  1509. }
  1510. //
  1511. // Check whether service is interactive, 'cause you can't
  1512. // get a ticket to an interactive service.
  1513. //
  1514. KerbErr = BuildTicketTGS(
  1515. ServiceTicketInfo,
  1516. RequestBody,
  1517. SourceTicket,
  1518. Referral,
  1519. S4UClientName,
  1520. S4UClientRealm,
  1521. *CommonEType,
  1522. &NewTicket,
  1523. pExtendedError
  1524. );
  1525. if (!KERB_SUCCESS(KerbErr))
  1526. {
  1527. D_DebugLog((DEB_ERROR,"KLIN(%x) Failed to build TGS ticket for %wZ : 0x%x\n",
  1528. KLIN(FILENO, __LINE__), &LocalServiceName, KerbErr ));
  1529. goto Cleanup;
  1530. }
  1531. }
  1532. else
  1533. {
  1534. //
  1535. // Need to build a referal ticket.
  1536. //
  1537. D_DebugLog(( DEB_T_KDC, "GetTGSTicket: referring to domain '%wZ'\n",
  1538. &ServiceTicketInfo->AccountName ));
  1539. //
  1540. // Verify that if the trust is not transitive, the client is from
  1541. // this realm.
  1542. //
  1543. SourceEncryptPart =(PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  1544. if (((ServiceTicketInfo->fTicketOpts & AUTH_REQ_TRANSITIVE_TRUST) == 0) &&
  1545. (ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT))
  1546. {
  1547. if (!SecData.IsOurRealm(&SourceEncryptPart->client_realm))
  1548. {
  1549. D_DebugLog((DEB_WARN,"Client from realm %s attempted to access non transitve trust to %wZ : illegal\n",
  1550. SourceEncryptPart->client_realm,
  1551. &ServiceTicketInfo->AccountName
  1552. ));
  1553. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  1554. }
  1555. }
  1556. //
  1557. // Verify that the trust for the client is transitive as well, if it isn't
  1558. // from this domain. This means that if the source ticket trust isn't
  1559. // transitive, then this ticket can't be used to get further
  1560. // tgt's, in any realm.
  1561. //
  1562. // e.g. the TGT from client comes from a domain w/ which we don't
  1563. // have transitive trust.
  1564. //
  1565. if (((OldServiceTicketInfo.fTicketOpts & AUTH_REQ_TRANSITIVE_TRUST) == 0) &&
  1566. (OldServiceTicketInfo.UserId != DOMAIN_USER_RID_KRBTGT))
  1567. {
  1568. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  1569. }
  1570. //
  1571. // This is probably not a common error, but could
  1572. // indicate a configuration problem, so log an explicit
  1573. // error. See bug 87879.
  1574. //
  1575. if (KerbErr == KDC_ERR_PATH_NOT_ACCEPTED)
  1576. {
  1577. KerbErr = KerbConvertRealmToUnicodeString(
  1578. &ClientRealm,
  1579. &SourceEncryptPart->client_realm
  1580. );
  1581. if (KERB_SUCCESS(KerbErr))
  1582. {
  1583. ReportServiceEvent(
  1584. EVENTLOG_ERROR_TYPE,
  1585. KDCEVENT_FAILED_TRANSITIVE_TRUST,
  1586. 0, // no raw data
  1587. NULL, // no raw data
  1588. 2, // number of strings
  1589. ClientRealm.Buffer,
  1590. ServiceTicketInfo->AccountName.Buffer
  1591. );
  1592. }
  1593. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  1594. goto Cleanup;
  1595. }
  1596. //
  1597. // Find the common crypt system.
  1598. //
  1599. KerbErr = KerbFindCommonCryptSystem(
  1600. RequestBody->encryption_type,
  1601. ServiceTicketInfo->Passwords,
  1602. NULL,
  1603. CommonEType,
  1604. &ServerKey
  1605. );
  1606. if (!KERB_SUCCESS(KerbErr))
  1607. {
  1608. KdcReportKeyError(
  1609. &ServiceTicketInfo->AccountName,
  1610. &ServiceTicketInfo->AccountName,
  1611. KDCEVENT_NO_KEY_UNION_TGS,
  1612. RequestBody->encryption_type,
  1613. ServiceTicketInfo->Passwords
  1614. );
  1615. goto Cleanup;
  1616. }
  1617. KerbErr = BuildTicketTGS(
  1618. ServiceTicketInfo,
  1619. RequestBody,
  1620. SourceTicket,
  1621. TRUE,
  1622. NULL, // not doing s4u
  1623. NULL, // not doing s4u
  1624. *CommonEType,
  1625. &NewTicket,
  1626. pExtendedError
  1627. );
  1628. if (!KERB_SUCCESS(KerbErr))
  1629. {
  1630. D_DebugLog((DEB_ERROR,"KLIN(%x) Failed to build TGS ticket for %wZ : 0x%x\n",
  1631. KLIN(FILENO, __LINE__), &ServiceTicketInfo->AccountName, KerbErr ));
  1632. goto Cleanup;
  1633. }
  1634. //
  1635. // If this is a referral/canonicaliztion, return the target realm
  1636. //
  1637. if (Referral && ((KdcOptions & KERB_KDC_OPTIONS_name_canonicalize) != 0))
  1638. {
  1639. D_DebugLog((DEB_TRACE,"Building referral info for realm %wZ\n",
  1640. &ServiceRealm ));
  1641. KerbErr = KdcBuildReferralInfo(
  1642. &ServiceRealm,
  1643. ReplyPaData
  1644. );
  1645. if (!KERB_SUCCESS(KerbErr))
  1646. {
  1647. goto Cleanup;
  1648. }
  1649. }
  1650. }
  1651. OldServerKey = KerbGetKeyFromList(
  1652. OldServiceTicketInfo.Passwords,
  1653. SourceTicket->encrypted_part.encryption_type
  1654. );
  1655. DsysAssert(OldServerKey != NULL);
  1656. if (OldServerKey == NULL)
  1657. {
  1658. KerbErr = KRB_ERR_GENERIC;
  1659. goto Cleanup;
  1660. }
  1661. //
  1662. // Insert the auth data into the new ticket.
  1663. //
  1664. KerbErr = KdcInsertAuthorizationData(
  1665. &EncryptedTicket,
  1666. pExtendedError,
  1667. (RequestBody->bit_mask & enc_authorization_data_present) ?
  1668. &RequestBody->enc_authorization_data : NULL,
  1669. S4UClientName,
  1670. GetS4UPac,
  1671. (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value,
  1672. ((ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&
  1673. ((ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0)), // only insert for non-referrals
  1674. &OldServiceTicketInfo,
  1675. OldServerKey,
  1676. ARGUMENT_PRESENT(TicketEncryptionKey) ? TicketEncryptionKey : ServerKey
  1677. );
  1678. if (!KERB_SUCCESS(KerbErr))
  1679. {
  1680. DebugLog((DEB_ERROR,"KLIN(%x) Failed to insert authorization data: 0x%x\n",
  1681. KLIN(FILENO, __LINE__), KerbErr));
  1682. goto Cleanup;
  1683. }
  1684. *Ticket = NewTicket;
  1685. *OutputEncryptedTicket = EncryptedTicket;
  1686. Ticket->encrypted_part.cipher_text.value = (PUCHAR) OutputEncryptedTicket;
  1687. Cleanup:
  1688. //
  1689. // Now free the original service ticket info (which was for the KDC) so
  1690. // we can get it for the real service
  1691. //
  1692. FreeTicketInfo(
  1693. &OldServiceTicketInfo
  1694. );
  1695. if (!KERB_SUCCESS(KerbErr))
  1696. {
  1697. KdcFreeInternalTicket(
  1698. &NewTicket
  1699. );
  1700. }
  1701. KerbFreeString(
  1702. &ServiceRealm
  1703. );
  1704. KerbFreeString(
  1705. &ClientRealm
  1706. );
  1707. return(KerbErr);
  1708. }
  1709. //+-------------------------------------------------------------------------
  1710. //
  1711. // Function: KerbUnpackAdditionalTickets
  1712. //
  1713. // Synopsis: Unpacks the AdditionalTickets field of a KDC request
  1714. // and (a) verifies that the ticket is TGT for this realm
  1715. // and (b) the ticket is encrypted with the corret key and
  1716. // (c) the ticket is valid
  1717. //
  1718. // Effects: allocate output ticket
  1719. //
  1720. // Arguments:
  1721. //
  1722. // Requires:
  1723. //
  1724. // Returns:
  1725. //
  1726. // Notes: there can only be one additional ticket
  1727. //
  1728. //
  1729. //--------------------------------------------------------------------------
  1730. KERBERR
  1731. KdcUnpackAdditionalTickets(
  1732. IN PKERB_TICKET_LIST TicketList,
  1733. OUT PKERB_ENCRYPTED_TICKET * AdditionalTicket
  1734. )
  1735. {
  1736. KERBERR KerbErr = KDC_ERR_NONE;
  1737. PKERB_ENCRYPTED_TICKET EncryptedTicket = NULL;
  1738. UNICODE_STRING ServerNames[3];
  1739. PKERB_ENCRYPTION_KEY EncryptionKey = NULL;
  1740. PKERB_TICKET Ticket;
  1741. KERB_REALM LocalRealm;
  1742. KDC_TICKET_INFO KrbtgtTicketInfo = {0};
  1743. //
  1744. // Verify that there is a ticket & that there is only one ticket
  1745. //
  1746. //
  1747. // TBD: Make this work w/ S4U && U2U as there will be more than 1 ticket
  1748. // at that point. Evaluate options by lowest id first...
  1749. // S4UToSelf (12)
  1750. //
  1751. if ((TicketList == NULL) || (TicketList->next != NULL))
  1752. {
  1753. D_DebugLog((DEB_ERROR,"KLIN(%x) Trying to unpack null ticket or more than one ticket\n",
  1754. KLIN(FILENO, __LINE__)));
  1755. KerbErr = KRB_ERR_GENERIC;
  1756. goto Cleanup;
  1757. }
  1758. KerbErr = SecData.GetKrbtgtTicketInfo(&KrbtgtTicketInfo);
  1759. if (!KERB_SUCCESS(KerbErr))
  1760. {
  1761. goto Cleanup;
  1762. }
  1763. Ticket = &TicketList->value;
  1764. //
  1765. // Verify the ticket, first with the normal password list
  1766. //
  1767. ServerNames[0] = *SecData.KdcFullServiceKdcName();
  1768. ServerNames[1] = *SecData.KdcFullServiceDnsName();
  1769. ServerNames[2] = *SecData.KdcFullServiceName();
  1770. EncryptionKey = KerbGetKeyFromList(
  1771. KrbtgtTicketInfo.Passwords,
  1772. Ticket->encrypted_part.encryption_type
  1773. );
  1774. if (EncryptionKey == NULL)
  1775. {
  1776. KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  1777. goto Cleanup;
  1778. }
  1779. //
  1780. // NOTE: we only allow additional tickets from our realm. This
  1781. // means cross-realm TGTs can't be used as additional tickets.
  1782. //
  1783. KerbErr = KerbVerifyTicket(
  1784. Ticket,
  1785. 3, // 3 names
  1786. ServerNames,
  1787. SecData.KdcDnsRealmName(),
  1788. EncryptionKey,
  1789. &SkewTime,
  1790. &EncryptedTicket
  1791. );
  1792. //
  1793. // if it failed due to wrong password, try again with older password
  1794. //
  1795. if ((KerbErr == KRB_AP_ERR_MODIFIED) && (KrbtgtTicketInfo.OldPasswords != NULL))
  1796. {
  1797. EncryptionKey = KerbGetKeyFromList(
  1798. KrbtgtTicketInfo.OldPasswords,
  1799. Ticket->encrypted_part.encryption_type
  1800. );
  1801. if (EncryptionKey == NULL)
  1802. {
  1803. KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  1804. goto Cleanup;
  1805. }
  1806. KerbErr = KerbVerifyTicket(
  1807. &TicketList->value,
  1808. 2, // 2 names
  1809. ServerNames,
  1810. SecData.KdcDnsRealmName(),
  1811. EncryptionKey,
  1812. &SkewTime,
  1813. &EncryptedTicket
  1814. );
  1815. }
  1816. if (!KERB_SUCCESS(KerbErr))
  1817. {
  1818. DebugLog((DEB_ERROR,"KLIN(%x) Failed to verify additional ticket: 0x%x\n",
  1819. KLIN(FILENO, __LINE__),KerbErr));
  1820. goto Cleanup;
  1821. }
  1822. LocalRealm = SecData.KdcKerbDnsRealmName();
  1823. //
  1824. // Verify the realm of the ticket
  1825. //
  1826. if (!KerbCompareRealmNames(
  1827. &LocalRealm,
  1828. &Ticket->realm
  1829. ))
  1830. {
  1831. D_DebugLog((DEB_ERROR,"KLIN(%x) Additional ticket realm is wrong: %s instead of %s\n",
  1832. KLIN(FILENO, __LINE__), Ticket->realm, LocalRealm));
  1833. KerbErr = KDC_ERR_POLICY;
  1834. goto Cleanup;
  1835. }
  1836. //
  1837. // Verify the realm of the client is the same as our realm
  1838. //
  1839. if (!KerbCompareRealmNames(
  1840. &LocalRealm,
  1841. &EncryptedTicket->client_realm
  1842. ))
  1843. {
  1844. D_DebugLog((DEB_ERROR,"KLIN(%x) Additional ticket client realm is wrong: %s instead of %s\n",
  1845. KLIN(FILENO, __LINE__),EncryptedTicket->client_realm, LocalRealm));
  1846. KerbErr = KDC_ERR_POLICY;
  1847. goto Cleanup;
  1848. }
  1849. *AdditionalTicket = EncryptedTicket;
  1850. EncryptedTicket = NULL;
  1851. Cleanup:
  1852. if (EncryptedTicket != NULL)
  1853. {
  1854. KerbFreeTicket(EncryptedTicket);
  1855. }
  1856. FreeTicketInfo(&KrbtgtTicketInfo);
  1857. return(KerbErr);
  1858. }
  1859. //--------------------------------------------------------------------
  1860. //
  1861. // Name: KdcFindS4UClientAndRealm
  1862. //
  1863. // Synopsis: Decodes PA DATA to find PA_DATA_FOR_USER entry.
  1864. //
  1865. // Effects: Get a client name and realm for processing S4U request
  1866. //
  1867. // Arguments: PAList - Preauth data list from TGS_REQ
  1868. // ServerKey - Key in authenticator, used to sign PA_DATA.
  1869. // ClientRealm - Target for client realm
  1870. // ClientName - Principal to get S4U ticket for
  1871. //
  1872. // Requires:
  1873. //
  1874. // Returns: KDC_ERR_ or KRB_AP_ERR errors only
  1875. //
  1876. // Notes: Free client name and realm w/
  1877. //
  1878. //
  1879. //--------------------------------------------------------------------------
  1880. KERBERR
  1881. KdcFindS4UClientAndRealm(
  1882. IN PKERB_PA_DATA_LIST PaList,
  1883. IN OUT PUNICODE_STRING ClientRealm,
  1884. IN OUT PKERB_INTERNAL_NAME * ClientName
  1885. )
  1886. {
  1887. KERBERR Kerberr = KRB_ERR_GENERIC;
  1888. PKERB_PA_DATA PaData = NULL;
  1889. PKERB_PA_FOR_USER S4URequest = NULL;
  1890. *ClientName = NULL;
  1891. RtlInitUnicodeString(
  1892. ClientRealm,
  1893. NULL
  1894. );
  1895. PaData = KerbFindPreAuthDataEntry(
  1896. KRB5_PADATA_S4U,
  1897. PaList
  1898. );
  1899. if (NULL == PaData)
  1900. {
  1901. DebugLog((DEB_ERROR, "No S4U pa data \n"));
  1902. Kerberr = KDC_ERR_BADOPTION;
  1903. goto Cleanup;
  1904. }
  1905. Kerberr = KerbUnpackData(
  1906. PaData->preauth_data.value,
  1907. PaData->preauth_data.length,
  1908. KERB_PA_FOR_USER_PDU,
  1909. (PVOID* ) &S4URequest
  1910. );
  1911. if (!KERB_SUCCESS(Kerberr))
  1912. {
  1913. DebugLog((DEB_ERROR, "Failed to unpack PA_FOR_USER\n"));
  1914. goto Cleanup;
  1915. }
  1916. Kerberr = KerbConvertRealmToUnicodeString(
  1917. ClientRealm,
  1918. &S4URequest->client_realm
  1919. );
  1920. if (!KERB_SUCCESS(Kerberr))
  1921. {
  1922. goto Cleanup;
  1923. }
  1924. Kerberr = KerbConvertPrincipalNameToKdcName(
  1925. ClientName,
  1926. &S4URequest->client_name
  1927. );
  1928. if (!KERB_SUCCESS(Kerberr))
  1929. {
  1930. goto Cleanup;
  1931. }
  1932. Cleanup:
  1933. if (S4URequest != NULL)
  1934. {
  1935. KerbFreeData(
  1936. KERB_PA_FOR_USER_PDU,
  1937. S4URequest
  1938. );
  1939. }
  1940. return Kerberr;
  1941. }
  1942. //--------------------------------------------------------------------
  1943. //
  1944. // Name: HandleTGSRequest
  1945. //
  1946. // Synopsis: Gets a ticket using a KDC ticket (TGT).
  1947. //
  1948. // Effects: Allocates and encrypts a KDC reply
  1949. //
  1950. // Arguments: ClientAddress - Optionally contains client IP address
  1951. // RequestMessage - contains the TGS request message
  1952. // RequestRealm - The realm of the request, from the request
  1953. // message
  1954. // OutputMessage - Contains the buffer to send back to the client
  1955. // Requires:
  1956. //
  1957. // Returns: KDC_ERR_ or KRB_AP_ERR errors only
  1958. //
  1959. // Notes:
  1960. //
  1961. //
  1962. //--------------------------------------------------------------------------
  1963. KERBERR
  1964. HandleTGSRequest(
  1965. IN OPTIONAL SOCKADDR * ClientAddress,
  1966. IN PKERB_TGS_REQUEST RequestMessage,
  1967. IN PUNICODE_STRING RequestRealm,
  1968. OUT PKERB_MESSAGE_BUFFER OutputMessage,
  1969. OUT PKERB_EXT_ERROR pExtendedError
  1970. )
  1971. {
  1972. KERBERR KerbErr = KDC_ERR_NONE;
  1973. KDC_TICKET_INFO ServerTicketInfo = {0};
  1974. KDC_TICKET_INFO TgtTicketInfo = {0};
  1975. KERB_TICKET SourceTicket = {0};
  1976. KERB_TICKET NewTicket = {0};
  1977. KERB_ENCRYPTED_TICKET EncryptedTicket = {0};
  1978. PKERB_ENCRYPTED_TICKET SourceEncryptPart = NULL;
  1979. PKERB_ENCRYPTED_TICKET AdditionalTicket = NULL;
  1980. PKERB_KDC_REQUEST_BODY RequestBody = &RequestMessage->request_body;
  1981. KERB_TGS_REPLY Reply = {0};
  1982. KERB_ENCRYPTED_KDC_REPLY ReplyBody = {0};
  1983. PKERB_AP_REQUEST UnmarshalledApRequest = NULL;
  1984. PKERB_AUTHENTICATOR UnmarshalledAuthenticator = NULL;
  1985. PKERB_PA_DATA ApRequest = NULL;
  1986. PKERB_PA_DATA_LIST ReplyPaData = NULL;
  1987. KERB_ENCRYPTION_KEY ReplyKey = {0};
  1988. PKERB_ENCRYPTION_KEY ServerKey;
  1989. PKERB_INTERNAL_NAME ServerName = NULL;
  1990. PKERB_INTERNAL_NAME ClientName = NULL;
  1991. PKERB_INTERNAL_NAME S4UClientName = NULL;
  1992. UNICODE_STRING ClientRealm = {0};
  1993. UNICODE_STRING ClientStringName = {0};
  1994. UNICODE_STRING ServerStringName = {0};
  1995. UNICODE_STRING S4UClientRealm = {0};
  1996. PUNICODE_STRING S4URealm = NULL;
  1997. ULONG CommonEType;
  1998. ULONG KdcOptions = 0;
  1999. ULONG TicketFlags = 0;
  2000. ULONG ReplyTicketFlags = 0;
  2001. BOOLEAN Validating = FALSE;
  2002. BOOLEAN UseSubKey = FALSE;
  2003. BOOLEAN Renew = FALSE;
  2004. BOOLEAN CheckAdditionalTicketMatch = FALSE;
  2005. KDC_TGS_EVENT_INFO TGSEventTraceInfo = {0};
  2006. TRACE(KDC, HandleTGSRequest, DEB_FUNCTION);
  2007. //
  2008. // Initialize [out] structures, so if we terminate early, they can
  2009. // be correctly marshalled by the stub
  2010. //
  2011. NewTicket.encrypted_part.cipher_text.value = (PUCHAR) &EncryptedTicket;
  2012. EncryptedTicket.flags.value = (PUCHAR) &TicketFlags;
  2013. EncryptedTicket.flags.length = sizeof(ULONG) * 8;
  2014. ReplyBody.flags.value = (PUCHAR) &ReplyTicketFlags;
  2015. ReplyBody.flags.length = sizeof(ULONG) * 8;
  2016. KdcOptions = KerbConvertFlagsToUlong( &RequestBody->kdc_options );
  2017. //
  2018. // Start event tracing
  2019. //
  2020. if (KdcEventTraceFlag){
  2021. TGSEventTraceInfo.EventTrace.Guid = KdcHandleTGSRequestGuid;
  2022. TGSEventTraceInfo.EventTrace.Class.Type = EVENT_TRACE_TYPE_START;
  2023. TGSEventTraceInfo.EventTrace.Flags = WNODE_FLAG_TRACED_GUID;
  2024. TGSEventTraceInfo.EventTrace.Size = sizeof (EVENT_TRACE_HEADER) + sizeof (ULONG);
  2025. TGSEventTraceInfo.KdcOptions = KdcOptions;
  2026. TraceEvent(
  2027. KdcTraceLoggerHandle,
  2028. (PEVENT_TRACE_HEADER)&TGSEventTraceInfo
  2029. );
  2030. }
  2031. //
  2032. // Check for additional tickets
  2033. //
  2034. if ((RequestBody->bit_mask & additional_tickets_present) != 0)
  2035. {
  2036. //
  2037. // The ticket must be unpacked with the krbtgt key
  2038. //
  2039. KerbErr = KdcUnpackAdditionalTickets(
  2040. RequestBody->additional_tickets,
  2041. &AdditionalTicket
  2042. );
  2043. if (!KERB_SUCCESS(KerbErr))
  2044. {
  2045. D_DebugLog((DEB_ERROR,"KLIN(%x) Failed to unpack additional tickets: 0x%x\n",
  2046. KLIN(FILENO, __LINE__),KerbErr));
  2047. goto Cleanup;
  2048. }
  2049. }
  2050. //
  2051. // Make sure that if there is a ticket, then enc_tkt_in_skey is set and
  2052. // if not, then it isn't set
  2053. //
  2054. //
  2055. // TBD: S4UToProxy (E) Ok to have additional ticket if
  2056. // CNAME-IN-ADDL-TKT set.
  2057. //
  2058. if ((((KdcOptions & KERB_KDC_OPTIONS_enc_tkt_in_skey) != 0) ^
  2059. (AdditionalTicket != NULL)))
  2060. {
  2061. // tbd: more logic for determining if multiple addl tickets are "bad option"
  2062. D_DebugLog((DEB_ERROR,"KLIN(%x) Client didn't match enc_tkt_in_skey with additional tickts : %d vs %d\n",
  2063. KLIN(FILENO, __LINE__),((KdcOptions & KERB_KDC_OPTIONS_enc_tkt_in_skey) != 0),
  2064. (AdditionalTicket != NULL)));
  2065. KerbErr = KDC_ERR_BADOPTION;
  2066. goto Cleanup;
  2067. }
  2068. //
  2069. // Pass data to next level, w/ flag
  2070. //
  2071. // TBD: S4UToProxy (D)
  2072. // Forwardable flag must be set in the service ticket
  2073. // Check our options, that the additional ticket has bit set.
  2074. // This additional service ticket must have the fwdable flag set,
  2075. // and must validate correctly.
  2076. //
  2077. // We'll need to crack the server key, and the ticket, as validation of
  2078. // identity.
  2079. //
  2080. //
  2081. // The server name is optional.
  2082. //
  2083. if ((RequestBody->bit_mask & KERB_KDC_REQUEST_BODY_server_name_present) != 0)
  2084. {
  2085. KerbErr = KerbConvertPrincipalNameToKdcName(
  2086. &ServerName,
  2087. &RequestBody->KERB_KDC_REQUEST_BODY_server_name
  2088. );
  2089. if (!KERB_SUCCESS(KerbErr))
  2090. {
  2091. goto Cleanup;
  2092. }
  2093. //
  2094. // Verify the at the server name is the same as the client name
  2095. // from the addional ticket by getting the ticket info for supplied
  2096. // TGT for the server. Later on we will compare it against the real
  2097. // ticket info.
  2098. //
  2099. if (AdditionalTicket != NULL)
  2100. {
  2101. PKERB_INTERNAL_NAME TgtClientName = NULL;
  2102. UNICODE_STRING TgtRealmName = {0};
  2103. UNICODE_STRING CrackedRealm = {0};
  2104. BOOLEAN Referral = FALSE;
  2105. KerbErr = KerbConvertPrincipalNameToKdcName(
  2106. &TgtClientName,
  2107. &AdditionalTicket->client_name
  2108. );
  2109. if (KERB_SUCCESS(KerbErr))
  2110. {
  2111. KerbErr = KerbConvertRealmToUnicodeString(
  2112. &TgtRealmName,
  2113. &AdditionalTicket->client_realm
  2114. );
  2115. if (KERB_SUCCESS(KerbErr))
  2116. {
  2117. // TBD: make sure normalize takes into account
  2118. // deleg restrictions, but not here, for god' sake.
  2119. // .
  2120. KerbErr = KdcNormalize(
  2121. TgtClientName,
  2122. &TgtRealmName,
  2123. &TgtRealmName,
  2124. KDC_NAME_CLIENT | KDC_NAME_INBOUND,
  2125. &Referral,
  2126. &CrackedRealm,
  2127. &TgtTicketInfo,
  2128. pExtendedError,
  2129. NULL, // no user handle
  2130. 0L, // no fields to fetch
  2131. 0L, // no extended fields
  2132. NULL, // no user all
  2133. NULL // no group membership
  2134. );
  2135. if (KERB_SUCCESS(KerbErr))
  2136. {
  2137. KerbFreeString(&CrackedRealm);
  2138. if (Referral)
  2139. {
  2140. KerbErr = KRB_AP_ERR_BADMATCH;
  2141. }
  2142. else
  2143. {
  2144. CheckAdditionalTicketMatch = FALSE;
  2145. }
  2146. }
  2147. KerbFreeString(&TgtRealmName);
  2148. }
  2149. KerbFreeKdcName(&TgtClientName);
  2150. }
  2151. if (!KERB_SUCCESS(KerbErr))
  2152. {
  2153. DebugLog((DEB_ERROR,"KLIN(%x) Failed to normalize client name from supplied ticket\n",
  2154. KLIN(FILENO, __LINE__)));
  2155. goto Cleanup;
  2156. }
  2157. }
  2158. }
  2159. else
  2160. {
  2161. //
  2162. // There must be an additional ticket.
  2163. //
  2164. if (AdditionalTicket == NULL)
  2165. {
  2166. KerbErr = KDC_ERR_S_PRINCIPAL_UNKNOWN;
  2167. goto Cleanup;
  2168. }
  2169. KerbErr = KerbConvertPrincipalNameToKdcName(
  2170. &ServerName,
  2171. &AdditionalTicket->client_name
  2172. );
  2173. if (!KERB_SUCCESS(KerbErr))
  2174. {
  2175. goto Cleanup;
  2176. }
  2177. }
  2178. //
  2179. // Convert the server name to a string for auditing.
  2180. //
  2181. KerbErr = KerbConvertKdcNameToString(
  2182. &ServerStringName,
  2183. ServerName,
  2184. NULL
  2185. );
  2186. if (!KERB_SUCCESS(KerbErr))
  2187. {
  2188. goto Cleanup;
  2189. }
  2190. D_DebugLog((DEB_TRACE, "GetTGSTicket called. Service=" ));
  2191. D_KerbPrintKdcName(DEB_TRACE, ServerName );
  2192. //
  2193. // The TGS and authenticator are in an AP request in the pre-auth data.
  2194. // Find it and decode the AP request now.
  2195. //
  2196. if ((RequestMessage->bit_mask & KERB_KDC_REQUEST_preauth_data_present) == 0)
  2197. {
  2198. D_DebugLog((DEB_ERROR,
  2199. "KLIN(%x) No pre-auth data in TGS request - not allowed.\n",
  2200. KLIN(FILENO, __LINE__)));
  2201. KerbErr = KDC_ERR_PADATA_TYPE_NOSUPP;
  2202. goto Cleanup;
  2203. }
  2204. //
  2205. // Get the TGT from the PA data.
  2206. //
  2207. ApRequest = KerbFindPreAuthDataEntry(
  2208. KRB5_PADATA_TGS_REQ,
  2209. RequestMessage->KERB_KDC_REQUEST_preauth_data
  2210. );
  2211. if (ApRequest == NULL)
  2212. {
  2213. D_DebugLog((DEB_ERROR,"KLIN(%x) No pre-auth data in TGS request - not allowed.\n",
  2214. KLIN(FILENO, __LINE__)));
  2215. FILL_EXT_ERROR(pExtendedError, STATUS_NO_PA_DATA, FILENO, __LINE__);
  2216. KerbErr = KDC_ERR_PADATA_TYPE_NOSUPP;
  2217. goto Cleanup;
  2218. }
  2219. //
  2220. // Verify the request. This includes decoding the AP request,
  2221. // finding the appropriate key to decrypt the ticket, and checking
  2222. // the ticket.
  2223. //
  2224. KerbErr = KdcVerifyKdcRequest(
  2225. ApRequest->preauth_data.value,
  2226. ApRequest->preauth_data.length,
  2227. ClientAddress,
  2228. TRUE, // this is a kdc request
  2229. &UnmarshalledApRequest,
  2230. &UnmarshalledAuthenticator,
  2231. &SourceEncryptPart,
  2232. &ReplyKey,
  2233. NULL, // no ticket key
  2234. &ServerTicketInfo,
  2235. &UseSubKey,
  2236. pExtendedError
  2237. );
  2238. //
  2239. // If you want to validate a ticket, then it's OK if it isn't
  2240. // currently valid.
  2241. //
  2242. if (KerbErr == KRB_AP_ERR_TKT_NYV && (KdcOptions & KERB_KDC_OPTIONS_validate))
  2243. {
  2244. D_DebugLog((DEB_TRACE,"Validating a not-yet-valid ticket\n"));
  2245. KerbErr = KDC_ERR_NONE;
  2246. }
  2247. else if (KerbErr == KRB_AP_ERR_MODIFIED)
  2248. {
  2249. //
  2250. // Bug 276943: When the authenticator is encrypted with something other
  2251. // than the session key, KRB_AP_ERR_BAD_INTEGRITY must be
  2252. // returned per RFC 1510
  2253. //
  2254. D_DebugLog((DEB_TRACE,"Could not decrypt the ticket\n"));
  2255. KerbErr = KRB_AP_ERR_BAD_INTEGRITY;
  2256. }
  2257. //
  2258. // Verify the checksum on the ticket, if present
  2259. //
  2260. if ( KERB_SUCCESS(KerbErr) &&
  2261. (UnmarshalledAuthenticator != NULL) &&
  2262. (UnmarshalledAuthenticator->bit_mask & checksum_present) != 0)
  2263. {
  2264. KerbErr = KdcVerifyTgsChecksum(
  2265. &RequestMessage->request_body,
  2266. &ReplyKey,
  2267. &UnmarshalledAuthenticator->checksum
  2268. );
  2269. }
  2270. if (!KERB_SUCCESS(KerbErr))
  2271. {
  2272. DebugLog((DEB_ERROR,"KLIN(%x) Failed to verify TGS request: 0x%x\n",
  2273. KLIN(FILENO, __LINE__),KerbErr));
  2274. FILL_EXT_ERROR(pExtendedError, STATUS_KDC_INVALID_REQUEST, FILENO, __LINE__);
  2275. goto Cleanup;
  2276. }
  2277. //
  2278. // Now that we've validated the request,
  2279. // Check to see if the cname in padata bit is set, and
  2280. // we have the KDC option set.
  2281. //
  2282. if ((KdcOptions & KERB_KDC_OPTIONS_cname_in_pa_data) != 0)
  2283. {
  2284. KerbErr = KdcFindS4UClientAndRealm(
  2285. RequestMessage->KERB_KDC_REQUEST_preauth_data,
  2286. &S4UClientRealm,
  2287. &S4UClientName
  2288. );
  2289. if (!KERB_SUCCESS(KerbErr))
  2290. {
  2291. DebugLog((DEB_ERROR, "KdcFindS4UClientAndRealm failed\n"));
  2292. FILL_EXT_ERROR(pExtendedError, STATUS_NO_PA_DATA, FILENO, __LINE__);
  2293. goto Cleanup;
  2294. }
  2295. S4URealm = &S4UClientRealm;
  2296. }
  2297. KerbErr = KerbConvertPrincipalNameToKdcName(
  2298. &ClientName,
  2299. &SourceEncryptPart->client_name
  2300. );
  2301. if (!KERB_SUCCESS(KerbErr))
  2302. {
  2303. goto Cleanup;
  2304. }
  2305. KerbErr = KerbConvertKdcNameToString(
  2306. &ClientStringName,
  2307. ClientName,
  2308. NULL
  2309. );
  2310. if (!KERB_SUCCESS(KerbErr))
  2311. {
  2312. goto Cleanup;
  2313. }
  2314. //
  2315. // And the realm
  2316. //
  2317. KerbErr = KerbConvertRealmToUnicodeString(
  2318. &ClientRealm,
  2319. &SourceEncryptPart->client_realm
  2320. );
  2321. if (!KERB_SUCCESS(KerbErr))
  2322. {
  2323. goto Cleanup;
  2324. }
  2325. //
  2326. // If the client is in this domain and if we are supposed to
  2327. // verify the client's account is still good,
  2328. // do it now.
  2329. //
  2330. if ((SecData.KdcFlags() & AUTH_REQ_VALIDATE_CLIENT) != 0)
  2331. {
  2332. LARGE_INTEGER AuthTime;
  2333. LARGE_INTEGER CurrentTime;
  2334. NtQuerySystemTime(&CurrentTime);
  2335. KerbConvertGeneralizedTimeToLargeInt(
  2336. &AuthTime,
  2337. &SourceEncryptPart->authtime,
  2338. 0
  2339. );
  2340. //
  2341. // Only check if we haven't checked recently
  2342. //
  2343. if ((CurrentTime.QuadPart > AuthTime.QuadPart) &&
  2344. ((CurrentTime.QuadPart - AuthTime.QuadPart) > SecData.KdcRestrictionLifetime().QuadPart))
  2345. {
  2346. KerbErr = KdcCheckTgsLogonRestrictions(
  2347. ClientName,
  2348. &ClientRealm,
  2349. pExtendedError
  2350. );
  2351. if (!KERB_SUCCESS(KerbErr))
  2352. {
  2353. D_DebugLog((DEB_WARN, "KLIN(%x) Client failed TGS logon restrictions: 0x%x : ",
  2354. KLIN(FILENO, __LINE__),KerbErr));
  2355. KerbPrintKdcName(DEB_WARN, ClientName);
  2356. goto Cleanup;
  2357. }
  2358. }
  2359. }
  2360. //
  2361. // Build a ticket struture to pass to the worker functions
  2362. //
  2363. SourceTicket = UnmarshalledApRequest->ticket;
  2364. SourceTicket.encrypted_part.cipher_text.value = (PUCHAR) SourceEncryptPart;
  2365. //
  2366. // Build the new ticket
  2367. //
  2368. D_DebugLog((DEB_TRACE, "Handle TGS request: Client = %wZ,\n ",&ClientRealm));
  2369. D_KerbPrintKdcName(DEB_TRACE, ClientName);
  2370. D_DebugLog((DEB_TRACE, "\t ServerName = \n"));
  2371. D_KerbPrintKdcName(DEB_TRACE, ServerName);
  2372. //
  2373. // Pass off the work to the worker routines
  2374. //
  2375. if (KdcOptions & KERB_KDC_OPTIONS_renew)
  2376. {
  2377. D_DebugLog((DEB_T_KDC,"Renewing ticket ticket\n"));
  2378. Renew = TRUE;
  2379. KerbErr = I_RenewTicket(
  2380. &SourceTicket,
  2381. ServerName,
  2382. &ServerTicketInfo,
  2383. RequestBody,
  2384. &CommonEType,
  2385. &NewTicket,
  2386. pExtendedError
  2387. );
  2388. }
  2389. else if (KdcOptions & KERB_KDC_OPTIONS_validate)
  2390. {
  2391. D_DebugLog((DEB_T_KDC,"Validating ticket\n"));
  2392. KerbErr = I_Validate(
  2393. &SourceTicket,
  2394. ServerName,
  2395. &ClientRealm,
  2396. RequestBody,
  2397. &CommonEType,
  2398. &NewTicket,
  2399. pExtendedError
  2400. );
  2401. Validating = TRUE;
  2402. }
  2403. else
  2404. {
  2405. D_DebugLog((DEB_T_KDC,"Getting TGS ticket\n"));
  2406. KerbErr = I_GetTGSTicket(
  2407. &SourceTicket,
  2408. ServerName,
  2409. RequestRealm,
  2410. RequestBody,
  2411. &ServerTicketInfo,
  2412. AdditionalTicket != NULL ? &AdditionalTicket->key : NULL,
  2413. S4UClientName,
  2414. S4URealm,
  2415. &CommonEType,
  2416. &NewTicket,
  2417. &ReplyPaData,
  2418. pExtendedError
  2419. );
  2420. }
  2421. if (!KERB_SUCCESS(KerbErr))
  2422. {
  2423. DebugLog((DEB_WARN,"KLIN(%x) TGS ticket worker failed: 0x%x\n",
  2424. KLIN(FILENO, __LINE__),KerbErr));
  2425. goto Cleanup;
  2426. }
  2427. DsysAssert(ServerTicketInfo.Passwords != NULL);
  2428. //
  2429. // Check to see if the additional ticket supplied is the one for this
  2430. // server, if necessary
  2431. //
  2432. if (CheckAdditionalTicketMatch )
  2433. {
  2434. if (ServerTicketInfo.UserId != TgtTicketInfo.UserId)
  2435. {
  2436. D_DebugLog((DEB_ERROR,"KLIN(%x) Supplied ticket is not for server: %wZ vs. %wZ\n",
  2437. KLIN(FILENO, __LINE__),&TgtTicketInfo.AccountName,
  2438. &ServerTicketInfo.AccountName ));
  2439. KerbErr = KRB_AP_ERR_BADMATCH;
  2440. goto Cleanup;
  2441. }
  2442. }
  2443. //
  2444. // Determine the keys to encrypt the ticket with. (The key to encrypt the
  2445. // reply with was determined by CheckTicket.)
  2446. if ((KdcOptions & KERB_KDC_OPTIONS_enc_tkt_in_skey) &&
  2447. (AdditionalTicket != NULL))
  2448. {
  2449. //
  2450. // Use the session key from the tgt
  2451. //
  2452. ServerKey = &AdditionalTicket->key;
  2453. } else {
  2454. ServerKey = KerbGetKeyFromList(
  2455. ServerTicketInfo.Passwords,
  2456. CommonEType
  2457. );
  2458. DsysAssert(ServerKey != NULL);
  2459. if (ServerKey == NULL)
  2460. {
  2461. D_DebugLog((DEB_ERROR,
  2462. "KLIN(%x) BADERROR: cannot find server key while validating\n",
  2463. KLIN(FILENO, __LINE__)));
  2464. KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  2465. goto Cleanup;
  2466. }
  2467. }
  2468. KerbErr = BuildReply(
  2469. NULL,
  2470. RequestBody->nonce,
  2471. &NewTicket.server_name,
  2472. NewTicket.realm,
  2473. ((EncryptedTicket.bit_mask & KERB_ENCRYPTED_TICKET_client_addresses_present) != 0) ?
  2474. EncryptedTicket.KERB_ENCRYPTED_TICKET_client_addresses : NULL,
  2475. &NewTicket,
  2476. &ReplyBody
  2477. );
  2478. if (!KERB_SUCCESS(KerbErr))
  2479. {
  2480. goto Cleanup;
  2481. }
  2482. //
  2483. // Put in any PA data for the reply
  2484. //
  2485. if (ReplyPaData != NULL)
  2486. {
  2487. ReplyBody.encrypted_pa_data = (struct KERB_ENCRYPTED_KDC_REPLY_encrypted_pa_data_s *) ReplyPaData;
  2488. ReplyBody.bit_mask |= encrypted_pa_data_present;
  2489. }
  2490. //
  2491. // Now build the real reply and return it.
  2492. //
  2493. Reply.version = KERBEROS_VERSION;
  2494. Reply.message_type = KRB_TGS_REP;
  2495. Reply.KERB_KDC_REPLY_preauth_data = NULL;
  2496. Reply.bit_mask = 0;
  2497. Reply.client_realm = SourceEncryptPart->client_realm;
  2498. Reply.client_name = SourceEncryptPart->client_name;
  2499. //
  2500. // Copy in the ticket
  2501. //
  2502. KerbErr = KerbPackTicket(
  2503. &NewTicket,
  2504. ServerKey,
  2505. CommonEType,
  2506. &Reply.ticket
  2507. );
  2508. if (!KERB_SUCCESS(KerbErr))
  2509. {
  2510. D_DebugLog((DEB_ERROR,"KLIN(%x) Failed to pack ticket: 0x%x\n",
  2511. KLIN(FILENO, __LINE__),KerbErr));
  2512. goto Cleanup;
  2513. }
  2514. //
  2515. // Copy in the encrypted part
  2516. //
  2517. KerbErr = KerbPackKdcReplyBody(
  2518. &ReplyBody,
  2519. &ReplyKey,
  2520. ReplyKey.keytype,
  2521. KERB_ENCRYPTED_TGS_REPLY_PDU,
  2522. &Reply.encrypted_part
  2523. );
  2524. if (!KERB_SUCCESS(KerbErr))
  2525. {
  2526. D_DebugLog((DEB_ERROR,"KLIN(%x)Failed to pack KDC reply body: 0x%x\n",
  2527. KLIN(FILENO, __LINE__),KerbErr));
  2528. goto Cleanup;
  2529. }
  2530. //
  2531. // Now build the real reply message
  2532. //
  2533. KerbErr = KerbPackData(
  2534. &Reply,
  2535. KERB_TGS_REPLY_PDU,
  2536. &OutputMessage->BufferSize,
  2537. &OutputMessage->Buffer
  2538. );
  2539. if (!KERB_SUCCESS(KerbErr))
  2540. {
  2541. goto Cleanup;
  2542. }
  2543. //
  2544. // Audit the successful ticket generation
  2545. //
  2546. if (SecData.AuditKdcEvent(KDC_AUDIT_TGS_SUCCESS))
  2547. {
  2548. BYTE ServerSid[MAX_SID_LEN];
  2549. GUID LogonGuid;
  2550. NTSTATUS Status = STATUS_SUCCESS;
  2551. PKERB_TIME pStartTime;
  2552. pStartTime =
  2553. &(((PKERB_ENCRYPTED_TICKET) NewTicket.encrypted_part.cipher_text.value)->KERB_ENCRYPTED_TICKET_starttime);
  2554. Status = LsaIGetLogonGuid(
  2555. &ClientStringName,
  2556. &ClientRealm,
  2557. (PBYTE) pStartTime,
  2558. sizeof(KERB_TIME),
  2559. &LogonGuid
  2560. );
  2561. ASSERT(NT_SUCCESS( Status ));
  2562. KdcMakeAccountSid(ServerSid, ServerTicketInfo.UserId);
  2563. KdcLsaIAuditKdcEvent(
  2564. Renew ? SE_AUDITID_TICKET_RENEW_SUCCESS : SE_AUDITID_TGS_TICKET_REQUEST,
  2565. &ClientStringName,
  2566. &ClientRealm,
  2567. NULL, // no client SID
  2568. &ServerTicketInfo.AccountName,
  2569. ServerSid,
  2570. (PULONG) &KdcOptions,
  2571. NULL, // success
  2572. &CommonEType,
  2573. NULL, // no preauth type
  2574. GET_CLIENT_ADDRESS(ClientAddress),
  2575. &LogonGuid
  2576. );
  2577. }
  2578. Cleanup:
  2579. //
  2580. // Complete the event
  2581. //
  2582. if (KdcEventTraceFlag){
  2583. //These variables point to either a unicode string struct containing
  2584. //the corresponding string or a pointer to KdcNullString
  2585. PUNICODE_STRING pStringToCopy;
  2586. WCHAR UnicodeNullChar = 0;
  2587. UNICODE_STRING UnicodeEmptyString = {sizeof(WCHAR),sizeof(WCHAR),&UnicodeNullChar};
  2588. TGSEventTraceInfo.EventTrace.Class.Type = EVENT_TRACE_TYPE_END;
  2589. TGSEventTraceInfo.EventTrace.Flags = WNODE_FLAG_USE_MOF_PTR |
  2590. WNODE_FLAG_TRACED_GUID;
  2591. // Always output error code. KdcOptions was captured on the start event
  2592. TGSEventTraceInfo.eventInfo[0].DataPtr = (ULONGLONG) &KerbErr;
  2593. TGSEventTraceInfo.eventInfo[0].Length = sizeof(ULONG);
  2594. TGSEventTraceInfo.EventTrace.Size =
  2595. sizeof (EVENT_TRACE_HEADER) + sizeof(MOF_FIELD);
  2596. // Build counted MOF strings from the unicode strings.
  2597. // If data is unavailable then output a NULL string
  2598. if (ClientStringName.Buffer != NULL &&
  2599. ClientStringName.Length > 0)
  2600. {
  2601. pStringToCopy = &ClientStringName;
  2602. }
  2603. else {
  2604. pStringToCopy = &UnicodeEmptyString;
  2605. }
  2606. TGSEventTraceInfo.eventInfo[1].DataPtr =
  2607. (ULONGLONG) &pStringToCopy->Length;
  2608. TGSEventTraceInfo.eventInfo[1].Length =
  2609. sizeof(pStringToCopy->Length);
  2610. TGSEventTraceInfo.eventInfo[2].DataPtr =
  2611. (ULONGLONG) pStringToCopy->Buffer;
  2612. TGSEventTraceInfo.eventInfo[2].Length =
  2613. pStringToCopy->Length;
  2614. TGSEventTraceInfo.EventTrace.Size += sizeof(MOF_FIELD)*2;
  2615. if (ServerStringName.Buffer != NULL &&
  2616. ServerStringName.Length > 0)
  2617. {
  2618. pStringToCopy = &ServerStringName;
  2619. }
  2620. else
  2621. {
  2622. pStringToCopy = &UnicodeEmptyString;
  2623. }
  2624. TGSEventTraceInfo.eventInfo[3].DataPtr =
  2625. (ULONGLONG) &pStringToCopy->Length;
  2626. TGSEventTraceInfo.eventInfo[3].Length =
  2627. sizeof(pStringToCopy->Length);
  2628. TGSEventTraceInfo.eventInfo[4].DataPtr =
  2629. (ULONGLONG) pStringToCopy->Buffer;
  2630. TGSEventTraceInfo.eventInfo[4].Length =
  2631. pStringToCopy->Length;
  2632. TGSEventTraceInfo.EventTrace.Size += sizeof(MOF_FIELD)*2;
  2633. if (ClientRealm.Buffer != NULL &&
  2634. ClientRealm.Length > 0)
  2635. {
  2636. pStringToCopy = &ClientRealm;
  2637. }
  2638. else
  2639. {
  2640. pStringToCopy = &UnicodeEmptyString;
  2641. }
  2642. TGSEventTraceInfo.eventInfo[5].DataPtr =
  2643. (ULONGLONG) &pStringToCopy->Length;
  2644. TGSEventTraceInfo.eventInfo[5].Length =
  2645. sizeof(pStringToCopy->Length);
  2646. TGSEventTraceInfo.eventInfo[6].DataPtr =
  2647. (ULONGLONG) pStringToCopy->Buffer;
  2648. TGSEventTraceInfo.eventInfo[6].Length =
  2649. pStringToCopy->Length;
  2650. TGSEventTraceInfo.EventTrace.Size += sizeof(MOF_FIELD)*2;
  2651. TraceEvent(
  2652. KdcTraceLoggerHandle,
  2653. (PEVENT_TRACE_HEADER)&TGSEventTraceInfo
  2654. );
  2655. }
  2656. //
  2657. // Audit *most* failures (see bug 37126)
  2658. //
  2659. if (!KERB_SUCCESS(KerbErr) &&
  2660. SecData.AuditKdcEvent(KDC_AUDIT_TGS_FAILURE))
  2661. {
  2662. // it is not uncommon to hit this error when
  2663. // clients attempt to get a ticket outside of their
  2664. // realm...
  2665. if (KerbErr != KDC_ERR_S_PRINCIPAL_UNKNOWN && SecData.IsOurRealm(RequestRealm))
  2666. {
  2667. KdcLsaIAuditKdcEvent(
  2668. SE_AUDITID_TGS_TICKET_REQUEST,
  2669. (ClientStringName.Buffer != NULL) ? &ClientStringName : &KdcNullString,
  2670. &ClientRealm, // no domain name
  2671. NULL,
  2672. &ServerStringName,
  2673. NULL,
  2674. &KdcOptions,
  2675. (PULONG) &KerbErr,
  2676. NULL, // no etype
  2677. NULL, // no preauth type
  2678. GET_CLIENT_ADDRESS(ClientAddress),
  2679. NULL // no logon guid
  2680. );
  2681. }
  2682. }
  2683. KerbFreeKdcName(
  2684. &ClientName
  2685. );
  2686. KerbFreeString(
  2687. &ClientRealm
  2688. );
  2689. KerbFreeKdcName(
  2690. &S4UClientName
  2691. );
  2692. KerbFreeString(
  2693. &S4UClientRealm
  2694. );
  2695. KerbFreeKdcName(
  2696. &ServerName
  2697. );
  2698. KerbFreeKey(
  2699. &ReplyKey
  2700. );
  2701. KdcFreeKdcReplyBody(
  2702. &ReplyBody
  2703. );
  2704. KerbFreeString(
  2705. &ClientStringName
  2706. );
  2707. KerbFreeString(
  2708. &ServerStringName
  2709. );
  2710. //
  2711. // If we are validating the ticket key is in the serverticketinfo
  2712. //
  2713. if (AdditionalTicket != NULL)
  2714. {
  2715. KerbFreeTicket(AdditionalTicket);
  2716. }
  2717. if (ReplyPaData != NULL)
  2718. {
  2719. KerbFreePreAuthData(ReplyPaData);
  2720. }
  2721. KerbFreeApRequest(UnmarshalledApRequest);
  2722. KerbFreeAuthenticator(UnmarshalledAuthenticator);
  2723. KerbFreeTicket(SourceEncryptPart);
  2724. KdcFreeInternalTicket(&NewTicket);
  2725. FreeTicketInfo(&ServerTicketInfo);
  2726. FreeTicketInfo(&TgtTicketInfo);
  2727. KdcFreeKdcReply(
  2728. &Reply
  2729. );
  2730. return(KerbErr);
  2731. }