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.

4982 lines
155 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 <userall.h>
  20. #include <ntdef.h>
  21. extern "C"
  22. {
  23. #include <md5.h>
  24. }
  25. #include "fileno.h"
  26. #define FILENO FILENO_GETTGS
  27. extern LARGE_INTEGER tsInfinity;
  28. extern LONG lInfinity;
  29. UNICODE_STRING KdcNullString = {0,0,NULL};
  30. GUID GUID_A_TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL = {0x46a9b11d,0x60ae,0x405a,0xb7,0xe8,0xff,0x8a,0x58,0xd4,0x56,0xd2};
  31. GUID GUID_A_SECURED_FOR_CROSS_ORGANIZATION = {0x68B1D179,0x0D15,0x4d4f,0xAB,0x71,0x46,0x15,0x2E,0x79,0xA7,0xBC};
  32. //
  33. // If defined, all trusts, not just MIT, will be namespace filtered
  34. //
  35. #define NAMESPACE_FILTER_EVERY_TRUST
  36. //--------------------------------------------------------------------
  37. //
  38. // Name: KdcCheckGroupExpansionAccess
  39. //
  40. // Synopsis: Validate that S4U caller has access to expand groups
  41. //
  42. // Effects: Use Authz to check client context.
  43. //
  44. // Arguments: S4UClientName - ClientName from S4U PA Data
  45. // TgtAccountInfo - Information from the inbound tgt account,
  46. // derived from KdcVerfiyKdcRequest.
  47. // SD - Security descriptor from the user object.
  48. //
  49. // Requires:
  50. //
  51. // Returns: KDC_ERR_ or KRB_AP_ERR errors only
  52. //
  53. // Notes: Free client name and realm w/
  54. //
  55. //
  56. //---
  57. GUID GUID_PS_REMOTE_ACCESS_INFO = {0x037088f8,0x0ae1,0x11d2,0xb4,0x22,0x00,0xa0,0xc9,0x68,0xf9,0x39};
  58. GUID GUID_C_COMPUTER = {0xbf967a86,0x0de6,0x11d0,0xa2,0x85,0x00,0xaa,0x00,0x30,0x49,0xe2};
  59. GUID GUID_C_USER = {0xbf967aba,0x0de6,0x11d0,0xa2,0x85,0x00,0xaa,0x00,0x30,0x49,0xe2};
  60. NTSTATUS
  61. KdcCheckGroupExpansionAccess(
  62. IN PKDC_S4U_TICKET_INFO S4UTicketInfo,
  63. IN PKDC_TICKET_INFO TgtAccountInfo,
  64. IN PUSER_INTERNAL6_INFORMATION UserInfo
  65. )
  66. {
  67. NTSTATUS Status = STATUS_SUCCESS;
  68. KERBERR KerbErr;
  69. LUID ZeroLuid = {0,0};
  70. DWORD AccessMask[3];
  71. DWORD Error[3];
  72. AUTHZ_CLIENT_CONTEXT_HANDLE hClientContext = NULL;
  73. AUTHZ_ACCESS_REQUEST Request = {0};
  74. AUTHZ_ACCESS_REPLY Reply = {0};
  75. KDC_AUTHZ_INFO AuthzInfo = {0};
  76. KDC_AUTHZ_GROUP_BUFFERS InfoToFree = {0};
  77. ULONG i = 0;
  78. OBJECT_TYPE_LIST TypeList[3] = {0};
  79. BOOLEAN ComputerAccount = (( UserInfo->I1.UserAccountControl &
  80. ( USER_WORKSTATION_TRUST_ACCOUNT | USER_SERVER_TRUST_ACCOUNT )) != 0);
  81. PSECURITY_DESCRIPTOR Sd = UserInfo->I1.SecurityDescriptor.SecurityDescriptor;
  82. //
  83. // Extract the netlogon validation info from
  84. // the TGT used in the S4UToSelf request.
  85. //
  86. KerbErr = KdcGetSidsFromTgt(
  87. S4UTicketInfo->EvidenceTicket,
  88. &S4UTicketInfo->EvidenceTicketKey,
  89. 0, // no etype needed if we've got the evidence ticket key.
  90. TgtAccountInfo,
  91. &AuthzInfo,
  92. &InfoToFree,
  93. &Status
  94. );
  95. if (!KERB_SUCCESS( KerbErr ))
  96. {
  97. goto Cleanup;
  98. }
  99. if (!AuthzInitializeContextFromSid(
  100. AUTHZ_SKIP_TOKEN_GROUPS,
  101. AuthzInfo.SidAndAttributes[0].Sid, // userid is first element in array
  102. KdcAuthzRM,
  103. NULL,
  104. ZeroLuid,
  105. &AuthzInfo,
  106. &hClientContext
  107. ))
  108. {
  109. DebugLog((DEB_ERROR, "AuthzInitializeContextFromSid() failed %x\n", GetLastError()));
  110. Status = STATUS_INTERNAL_ERROR;
  111. goto Cleanup;
  112. }
  113. //
  114. // Do access check.
  115. //
  116. TypeList[0].Level = ACCESS_OBJECT_GUID;
  117. TypeList[0].ObjectType = (ComputerAccount ? &GUID_C_COMPUTER : &GUID_C_USER );
  118. TypeList[0].Sbz = 0;
  119. TypeList[1].Level = ACCESS_PROPERTY_SET_GUID;
  120. TypeList[1].ObjectType = &GUID_PS_REMOTE_ACCESS_INFO;
  121. TypeList[1].Sbz = 0;
  122. TypeList[2].Level = ACCESS_PROPERTY_GUID;
  123. TypeList[2].ObjectType = &GUID_A_TOKEN_GROUPS_GLOBAL_AND_UNIVERSAL;
  124. TypeList[2].Sbz = 0;
  125. Request.DesiredAccess = ACTRL_DS_READ_PROP;
  126. Request.ObjectTypeList = TypeList;
  127. Request.ObjectTypeListLength = 3;
  128. Request.OptionalArguments = NULL;
  129. Request.PrincipalSelfSid = NULL;
  130. Reply.ResultListLength = 3;
  131. Reply.GrantedAccessMask = AccessMask;
  132. Reply.Error = Error;
  133. if (!AuthzAccessCheck(
  134. 0,
  135. hClientContext,
  136. &Request,
  137. NULL, // TBD: add audit
  138. Sd,
  139. NULL,
  140. NULL,
  141. &Reply,
  142. NULL // don't cache result? Check to see if optimal.
  143. ))
  144. {
  145. Error[0] = GetLastError();
  146. DebugLog((DEB_ERROR, "AuthzAccessCheck() failed %x\n", Error[0]));
  147. Status = STATUS_ACCESS_DENIED;
  148. goto Cleanup;
  149. }
  150. for ( i = 0; i < Reply.ResultListLength; i++)
  151. {
  152. if ( Error[i] != ERROR_SUCCESS )
  153. {
  154. DebugLog((DEB_ERROR, "GroupExpansion AuthZAC failed %x, lvl %x",Error[i],i));
  155. Status = STATUS_ACCESS_DENIED;
  156. goto Cleanup;
  157. }
  158. }
  159. Status = STATUS_SUCCESS;
  160. Cleanup:
  161. if ( Status == STATUS_ACCESS_DENIED )
  162. {
  163. // catch unknown errors here.
  164. DsysAssert(Error[i] == ERROR_ACCESS_DENIED);
  165. KdcReportS4UGroupExpansionError(
  166. UserInfo,
  167. S4UTicketInfo,
  168. Error[i] // use whatever status was returned to us that caused failure.
  169. );
  170. }
  171. if ( hClientContext != NULL )
  172. {
  173. AuthzFreeContext(hClientContext);
  174. }
  175. KdcFreeAuthzInfo( &InfoToFree );
  176. return Status;
  177. }
  178. //--------------------------------------------------------------------
  179. //
  180. // Name: KdcGetS4UTicketInfo
  181. //
  182. // Synopsis: Track down the user acct for PAC info.
  183. //
  184. // Effects: Get the PAC
  185. //
  186. // Arguments: S4UTicketInfo - Information used in processing S4U
  187. // TgtAccountInfo - Info on TGT used in request.
  188. // UserInfo - Internal 6 info for S4USelf client
  189. // GroupMembership - Group membership of S4USelf client
  190. //
  191. // Requires:
  192. //
  193. // Returns: KDC_ERR_ or KRB_AP_ERR errors only
  194. //
  195. // Notes:
  196. //
  197. //
  198. //--------------------------------------------------------------------------
  199. KERBERR
  200. KdcGetS4UTicketInfo(
  201. IN PKDC_S4U_TICKET_INFO S4UTicketInfo,
  202. IN PKDC_TICKET_INFO TgtAccountInfo,
  203. IN OUT PUSER_INTERNAL6_INFORMATION * UserInfo,
  204. IN OUT PSID_AND_ATTRIBUTES_LIST GroupMembership,
  205. IN OUT PKERB_EXT_ERROR ExtendedError
  206. )
  207. {
  208. KERBERR KerbErr;
  209. UNICODE_STRING ReferralRealm = {0};
  210. BOOLEAN Referral = FALSE;
  211. NTSTATUS Status = STATUS_SUCCESS;
  212. LARGE_INTEGER LogoffTime;
  213. *UserInfo = NULL;
  214. RtlZeroMemory(
  215. GroupMembership,
  216. sizeof(SID_AND_ATTRIBUTES_LIST)
  217. );
  218. PUSER_INTERNAL6_INFORMATION LocalUserInfo = NULL;
  219. KDC_TICKET_INFO LocalTicketInfo = {0};
  220. SID_AND_ATTRIBUTES_LIST LocalGroupMembership ={0};
  221. KerbErr = KdcNormalize(
  222. S4UTicketInfo->PACCName,
  223. NULL,
  224. NULL,
  225. NULL,
  226. KDC_NAME_CLIENT | KDC_NAME_S4U_CLIENT | KDC_NAME_FOLLOW_REFERRALS | KDC_NAME_CHECK_GC,
  227. FALSE, // do not restrict user accounts (user2user)
  228. &Referral,
  229. &ReferralRealm,
  230. &LocalTicketInfo,
  231. ExtendedError,
  232. NULL,
  233. USER_ALL_KDC_GET_PAC_AUTH_DATA | USER_ALL_SECURITYDESCRIPTOR,
  234. 0L,
  235. &LocalUserInfo,
  236. &LocalGroupMembership
  237. );
  238. if (!KERB_SUCCESS(KerbErr))
  239. {
  240. DebugLog((DEB_ERROR, "KdcGetS4UTicketInfo normalize in KdcGetS4uTicketInfo failed %x\n", KerbErr));
  241. goto cleanup;
  242. }
  243. else if (Referral)
  244. {
  245. DebugLog((DEB_ERROR, "KdcGetS4UTicketInfo normalize returned referral for S4U client\n"));
  246. KerbErr = KDC_ERR_C_PRINCIPAL_UNKNOWN;
  247. goto cleanup;
  248. }
  249. //
  250. // Some account restrictions apply to S4u
  251. // 1. Disabled accounts.
  252. // 2. Expired accounts.
  253. //
  254. KerbErr = KerbCheckLogonRestrictions(
  255. NULL, // no user handle, since we're not doing sam check.
  256. NULL, // No client address is available
  257. &LocalUserInfo->I1,
  258. KDC_RESTRICT_S4U_CHECKS, // Don't bother checking for password expiration, wkstation , account hours
  259. &LogoffTime,
  260. &Status
  261. );
  262. if (!KERB_SUCCESS( KerbErr ))
  263. {
  264. DebugLog((DEB_ERROR, "S4USelf client restricted %x\n", Status));
  265. FILL_EXT_ERROR_EX2( ExtendedError, Status, FILENO, __LINE__);
  266. goto cleanup;
  267. }
  268. //
  269. // Make sure S4U to self caller has access rights to user object.
  270. //
  271. Status = KdcCheckGroupExpansionAccess(
  272. S4UTicketInfo,
  273. TgtAccountInfo,
  274. LocalUserInfo
  275. );
  276. if (!NT_SUCCESS( Status ))
  277. {
  278. DebugLog((DEB_ERROR, "Failed Authz check \n"));
  279. KerbErr = KDC_ERR_C_PRINCIPAL_UNKNOWN;
  280. goto cleanup;
  281. }
  282. if (( LocalTicketInfo.fTicketOpts & AUTH_REQ_ALLOW_FORWARDABLE ) == 0)
  283. {
  284. S4UTicketInfo->Flags |= TI_SENSITIVE_CLIENT_ACCOUNT;
  285. }
  286. *UserInfo = LocalUserInfo;
  287. LocalUserInfo = NULL;
  288. *GroupMembership = LocalGroupMembership;
  289. RtlZeroMemory(
  290. &LocalGroupMembership,
  291. sizeof(SID_AND_ATTRIBUTES_LIST)
  292. );
  293. cleanup:
  294. KerbFreeString(&ReferralRealm);
  295. FreeTicketInfo(&LocalTicketInfo);
  296. SamIFreeSidAndAttributesList(&LocalGroupMembership);
  297. if (LocalUserInfo != NULL)
  298. {
  299. SamIFree_UserInternal6Information( LocalUserInfo );
  300. }
  301. return KerbErr;
  302. }
  303. //+-------------------------------------------------------------------------
  304. //
  305. // Function: KdcAuditAccountMapping
  306. //
  307. // Synopsis: Generates, if necessary, a success/failure audit for name
  308. // mapping. The names are converted to a string before
  309. // being passed to the LSA.
  310. //
  311. // Effects:
  312. //
  313. // Arguments:
  314. //
  315. // Requires:
  316. //
  317. // Returns:
  318. //
  319. // Notes:
  320. //
  321. //
  322. //--------------------------------------------------------------------------
  323. VOID
  324. KdcAuditAccountMapping(
  325. IN PKERB_INTERNAL_NAME ClientName,
  326. IN KERB_REALM ClientRealm,
  327. IN OPTIONAL PKDC_TICKET_INFO MappedTicketInfo
  328. )
  329. {
  330. UNICODE_STRING ClientString = {0};
  331. PUNICODE_STRING MappedName = NULL;
  332. UNICODE_STRING UnicodeRealm = {0};
  333. UNICODE_STRING NullString = {0};
  334. KERBERR KerbErr;
  335. BOOLEAN Successful;
  336. UCHAR ClientSidBuffer[256]; // rtl functions also use hard-coded 256
  337. PSID ClientSid = (PSID) ClientSidBuffer;
  338. if (ARGUMENT_PRESENT(MappedTicketInfo))
  339. {
  340. if (!SecData.AuditKdcEvent(KDC_AUDIT_MAP_SUCCESS))
  341. {
  342. return;
  343. }
  344. Successful = TRUE;
  345. MappedName = &MappedTicketInfo->AccountName;
  346. }
  347. else
  348. {
  349. if (!SecData.AuditKdcEvent(KDC_AUDIT_MAP_FAILURE))
  350. {
  351. return;
  352. }
  353. MappedName = &NullString;
  354. Successful = FALSE;
  355. }
  356. KerbErr = KerbConvertRealmToUnicodeString(
  357. &UnicodeRealm,
  358. &ClientRealm
  359. );
  360. if (!KERB_SUCCESS(KerbErr))
  361. {
  362. return;
  363. }
  364. if (KERB_SUCCESS(KerbConvertKdcNameToString(
  365. &ClientString,
  366. ClientName,
  367. &UnicodeRealm
  368. )))
  369. {
  370. if ( ARGUMENT_PRESENT( MappedTicketInfo ))
  371. {
  372. KdcMakeAccountSid(ClientSid, MappedTicketInfo->UserId);
  373. }
  374. else
  375. {
  376. ClientSid = NULL;
  377. }
  378. LsaIAuditAccountLogonEx(
  379. SE_AUDITID_ACCOUNT_MAPPED,
  380. Successful,
  381. &GlobalKdcName,
  382. &ClientString,
  383. MappedName,
  384. 0, // no status
  385. ClientSid
  386. );
  387. KerbFreeString(
  388. &ClientString
  389. );
  390. }
  391. KerbFreeString(
  392. &UnicodeRealm
  393. );
  394. }
  395. //----------------------------------------------------------------
  396. //
  397. // Name: KdcInsertAuthorizationData
  398. //
  399. // Synopsis: Inserts auth data into a newly created ticket.
  400. //
  401. // Arguments: FinalTicket - Ticket to insert Auth data into
  402. // EncryptedAuthData - Auth data (optional)
  403. // SourceTicket - Source ticket
  404. //
  405. // Notes: This copies the authorization data from the source ticket
  406. // to the destiation ticket, and adds the authorization data
  407. // passed in. It is called by GetTGSTicket.
  408. //
  409. // This assumes that pedAuthData is an encrypted
  410. // KERB_AUTHORIZATION_DATA.
  411. // It will copy all the elements of that list to the new ticket.
  412. // If pedAuthData is not supplied (or is empty), and there is
  413. // auth data in the source ticket, it is copied to the new
  414. // ticket. If no source ticket, and no auth data is passed
  415. // in, nothing is done.
  416. //
  417. //----------------------------------------------------------------
  418. KERBERR
  419. KdcInsertInitialS4UAuthorizationData(
  420. OUT PKERB_ENCRYPTED_TICKET FinalTicket,
  421. OUT PKERB_EXT_ERROR pExtendedError,
  422. IN PKDC_S4U_TICKET_INFO S4UTicketInfo,
  423. IN PUSER_INTERNAL6_INFORMATION S4UClientInternalInfo,
  424. IN PSID_AND_ATTRIBUTES_LIST S4UGroupMembership,
  425. IN BOOLEAN AddResourceGroups,
  426. IN PKERB_ENCRYPTION_KEY TargetServerKey
  427. )
  428. {
  429. KERBERR KerbErr = KDC_ERR_NONE;
  430. PKERB_AUTHORIZATION_DATA FinalAuthData = NULL;
  431. TRACE(KDC, InsertAuthorizationData, DEB_FUNCTION);
  432. D_DebugLog(( DEB_T_TICKETS, "Inserting S4U authorization data into ticket.\n" ));
  433. //
  434. // Use the PAC from the S4U data to return in the TGT / Service Ticket
  435. //
  436. KerbErr = KdcGetPacAuthData(
  437. S4UClientInternalInfo,
  438. S4UGroupMembership,
  439. TargetServerKey,
  440. NULL, // no credential key
  441. AddResourceGroups,
  442. FinalTicket,
  443. S4UTicketInfo,
  444. &FinalAuthData,
  445. pExtendedError
  446. );
  447. if (!KERB_SUCCESS(KerbErr))
  448. {
  449. DebugLog((DEB_ERROR, "Failed to get S4UPacAUthData\n"));
  450. goto Cleanup;
  451. }
  452. if (FinalAuthData != NULL)
  453. {
  454. FinalTicket->bit_mask |= KERB_ENCRYPTED_TICKET_authorization_data_present;
  455. FinalTicket->KERB_ENCRYPTED_TICKET_authorization_data = FinalAuthData;
  456. FinalAuthData = NULL;
  457. }
  458. KerbErr = KDC_ERR_NONE;
  459. Cleanup:
  460. KerbFreeAuthData(FinalAuthData);
  461. return(KerbErr);
  462. }
  463. //----------------------------------------------------------------
  464. //
  465. // Name: KdcInsertAuthorizationData
  466. //
  467. // Synopsis: Inserts auth data into a newly created ticket.
  468. //
  469. // Arguments: FinalTicket - Ticket to insert Auth data into
  470. // EncryptedAuthData - Auth data (optional)
  471. // SourceTicket - Source ticket
  472. //
  473. // Notes: This copies the authorization data from the source ticket
  474. // to the destiation ticket, and adds the authorization data
  475. // passed in. It is called by GetTGSTicket.
  476. //
  477. // This assumes that pedAuthData is an encrypted
  478. // KERB_AUTHORIZATION_DATA.
  479. // It will copy all the elements of that list to the new ticket.
  480. // If pedAuthData is not supplied (or is empty), and there is
  481. // auth data in the source ticket, it is copied to the new
  482. // ticket. If no source ticket, and no auth data is passed
  483. // in, nothing is done.
  484. //
  485. //----------------------------------------------------------------
  486. KERBERR
  487. KdcInsertAuthorizationData(
  488. OUT PKERB_ENCRYPTED_TICKET FinalTicket,
  489. OUT PKERB_EXT_ERROR pExtendedError,
  490. IN OPTIONAL PKERB_ENCRYPTED_DATA EncryptedAuthData,
  491. IN PKERB_ENCRYPTED_TICKET SourceTicket,
  492. IN OPTIONAL PKDC_TICKET_INFO TargetServiceTicketInfo,
  493. IN OPTIONAL PKDC_S4U_TICKET_INFO S4UTicketInfo,
  494. IN OPTIONAL PKDC_TICKET_INFO OriginalServerInfo,
  495. IN OPTIONAL PKERB_ENCRYPTION_KEY OriginalServerKey,
  496. IN OPTIONAL PKERB_ENCRYPTION_KEY TargetServerKey,
  497. IN OPTIONAL PKERB_ENCRYPTION_KEY Subkey,
  498. OUT OPTIONAL PS4U_DELEGATION_INFO* S4UDelegationInfo
  499. )
  500. {
  501. PKERB_AUTHORIZATION_DATA SourceAuthData = NULL;
  502. PKERB_AUTHORIZATION_DATA FinalAuthData = NULL;
  503. PKERB_AUTHORIZATION_DATA PacAuthData = NULL;
  504. PKERB_AUTHORIZATION_DATA NewPacAuthData = NULL;
  505. KERBERR KerbErr = KDC_ERR_NONE;
  506. PKERB_AUTHORIZATION_DATA_LIST * TempAuthData = NULL;
  507. PKERB_INTERNAL_NAME ClientName = NULL;
  508. PKERB_IF_RELEVANT_AUTH_DATA * IfRelevantData = NULL;
  509. PKERB_AUTHORIZATION_DATA SuppliedAuthData = NULL;
  510. UNICODE_STRING DummyName = {0};
  511. NTSTATUS LogonStatus = STATUS_SUCCESS;
  512. TimeStamp LogoffTime;
  513. SAMPR_HANDLE UserHandle = NULL;
  514. BOOLEAN AddResourceGroups = FALSE;
  515. PKERB_ENCRYPTED_TICKET EvidenceTicket = NULL;
  516. TRACE(KDC, InsertAuthorizationData, DEB_FUNCTION);
  517. if (ARGUMENT_PRESENT(TargetServiceTicketInfo))
  518. {
  519. //
  520. // Only add resource groups for non-referals.
  521. //
  522. AddResourceGroups = ((TargetServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&
  523. ((TargetServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0));
  524. }
  525. if (( ARGUMENT_PRESENT(S4UTicketInfo) ) &&
  526. (( S4UTicketInfo->Flags & TI_S4UPROXY_INFO ) != 0))
  527. {
  528. D_DebugLog((DEB_T_PAC, "KdcInsertAuthorizationData EvidenceTicket is S4UTicketInfo\n"));
  529. D_DebugLog((DEB_T_PAC, "S4UTicketInfo (%p)\n", S4UTicketInfo));
  530. D_DebugLog((DEB_T_PAC, "PAC CName "));
  531. D_KerbPrintKdcName((DEB_T_PAC, S4UTicketInfo->PACCName));
  532. D_DebugLog((DEB_T_PAC, "PAC CRealm %wZ\n", &S4UTicketInfo->PACCRealm));
  533. D_DebugLog((DEB_T_PAC, "Requestor : "));
  534. D_KerbPrintKdcName((DEB_T_PAC, S4UTicketInfo->RequestorServiceName ));
  535. D_DebugLog((DEB_T_PAC, "Realm %wZ\n", &S4UTicketInfo->RequestorServiceRealm ));
  536. //
  537. // 2 choices here - either we're grabbing the PAC from the accompanying
  538. // evidence ticket (if the S4Uprxy request is coming from our realm), or
  539. // we'll grab it out of the xrealm tgt.
  540. //
  541. // If we change the xrealm behavior, we'll need to modify this.
  542. //
  543. if ( S4UTicketInfo->Flags & TI_PRXY_REQUESTOR_THIS_REALM )
  544. {
  545. EvidenceTicket = S4UTicketInfo->EvidenceTicket;
  546. DebugLog((DEB_T_PAC, "Using evidence ticket PAC\n"));
  547. }
  548. else
  549. {
  550. EvidenceTicket = SourceTicket;
  551. DebugLog((DEB_T_PAC, "Using xrealm Tgt PAC\n"));
  552. }
  553. }
  554. else // traditional TGS
  555. {
  556. D_DebugLog((DEB_T_PAC, "KdcInsertAuthorizationData EvidenceTicket is SourceTicket (TGT in TGS AP request)\n"));
  557. EvidenceTicket = SourceTicket;
  558. }
  559. //
  560. // First try to decrypt the supplied authorization data
  561. //
  562. if (ARGUMENT_PRESENT(EncryptedAuthData))
  563. {
  564. //
  565. // The enc_authorization_data must be decrypted with the sub session
  566. // key from the authenticator if it is present (per the RFC)
  567. //
  568. PKERB_ENCRYPTION_KEY EncryptionKey;
  569. ULONG SaltType = KERB_NON_KERB_SALT;
  570. if ( ARGUMENT_PRESENT( Subkey ))
  571. {
  572. EncryptionKey = Subkey;
  573. SaltType = KERB_TGS_REQ_SUBKEY_SALT;
  574. D_DebugLog((DEB_TRACE, "KdcInsertAuthorizationData: using SUBsession key & salt\n"));
  575. } else {
  576. EncryptionKey = &EvidenceTicket->key;
  577. SaltType = KERB_TGS_REQ_SESSKEY_SALT;
  578. D_DebugLog((DEB_TRACE, "KdcInsertAuthorizationData: using Session key & salt\n"));
  579. }
  580. KerbErr = KerbDecryptDataEx(
  581. EncryptedAuthData,
  582. EncryptionKey,
  583. SaltType, // was KERB_NON_KERB_SALT
  584. &EncryptedAuthData->cipher_text.length,
  585. EncryptedAuthData->cipher_text.value
  586. );
  587. if (!KERB_SUCCESS( KerbErr ))
  588. {
  589. DebugLog((DEB_ERROR,
  590. "KdcInsertAuthorizationData KLIN(%x) Failed to decrypt encrypted auth data: 0x%x\n",
  591. KLIN(FILENO, __LINE__),
  592. KerbErr));
  593. goto Cleanup;
  594. }
  595. //
  596. // Now decode it
  597. //
  598. KerbErr = KerbUnpackData(
  599. EncryptedAuthData->cipher_text.value,
  600. EncryptedAuthData->cipher_text.length,
  601. PKERB_AUTHORIZATION_DATA_LIST_PDU,
  602. (PVOID *) &TempAuthData
  603. );
  604. if (!KERB_SUCCESS(KerbErr))
  605. {
  606. DebugLog((DEB_ERROR,
  607. "KdcInsertAuthorizationData KLIN(%x) Failed to unpack data: 0x%x\n",
  608. KLIN(FILENO, __LINE__),
  609. KerbErr));
  610. goto Cleanup;
  611. }
  612. if (TempAuthData != NULL)
  613. {
  614. SuppliedAuthData = *TempAuthData;
  615. }
  616. D_DebugLog((DEB_T_PAC, "KdcInsertAuthorizationData using supplied authorization data\n"));
  617. }
  618. if (EvidenceTicket->bit_mask & KERB_ENCRYPTED_TICKET_authorization_data_present)
  619. {
  620. DsysAssert(EvidenceTicket->KERB_ENCRYPTED_TICKET_authorization_data != NULL);
  621. SourceAuthData = EvidenceTicket->KERB_ENCRYPTED_TICKET_authorization_data;
  622. //
  623. // Get the AuthData from the source ticket
  624. //
  625. KerbErr = KerbGetPacFromAuthData(
  626. SourceAuthData,
  627. &IfRelevantData,
  628. &PacAuthData
  629. );
  630. if (!KERB_SUCCESS(KerbErr))
  631. {
  632. DebugLog((DEB_ERROR,"KLIN(%x) Failed to get pac from auth data: 0x%x\n",
  633. KLIN(FILENO, __LINE__),
  634. KerbErr));
  635. goto Cleanup;
  636. }
  637. D_DebugLog((DEB_T_PAC, "KdcInsertAuthorizationData extracted PAC from evidence ticket\n"));
  638. }
  639. #ifdef NAMESPACE_FILTER_EVERY_TRUST // Enable once we decide that namespace filtering should be performed over all trusts
  640. //
  641. // Namespace filtering can not be done for S4U2self requests since the fundamental
  642. // premise of namespace filtering is not satisfied there by design
  643. //
  644. if ( !S4UTicketInfo ||
  645. !(S4UTicketInfo->Flags & TI_S4USELF_INFO))
  646. {
  647. //
  648. // Verify that the namespace presented via crealm is valid across this trust link
  649. //
  650. KerbErr = KdcFilterNamespace(
  651. OriginalServerInfo,
  652. SourceTicket->client_realm,
  653. pExtendedError
  654. );
  655. if ( !KERB_SUCCESS( KerbErr ))
  656. {
  657. DebugLog((DEB_ERROR, "Failed filtering namespaces\n"));
  658. goto Cleanup;
  659. }
  660. }
  661. #endif
  662. //
  663. // The new auth data is the original auth data appended to the
  664. // supplied auth data. The new auth data goes first, followed by the
  665. // auth data from the original ticket.
  666. //
  667. //
  668. // Update the PAC, if it is present.
  669. //
  670. if (ARGUMENT_PRESENT(OriginalServerKey) && (PacAuthData != NULL))
  671. {
  672. D_DebugLog((DEB_T_PAC, "KdcInsertAuthorizationData OriginalServerInfo %wZ\\%wZ\n", &OriginalServerInfo->TrustedForest, &OriginalServerInfo->AccountName));
  673. KerbErr = KdcVerifyAndResignPac(
  674. OriginalServerKey,
  675. TargetServerKey,
  676. OriginalServerInfo,
  677. TargetServiceTicketInfo,
  678. S4UTicketInfo,
  679. FinalTicket,
  680. AddResourceGroups,
  681. pExtendedError,
  682. PacAuthData,
  683. S4UDelegationInfo
  684. );
  685. if (!KERB_SUCCESS(KerbErr))
  686. {
  687. DebugLog((DEB_ERROR,"KLIN(%x) Failed to verify & resign pac: 0x%x\n",
  688. KLIN(FILENO, __LINE__),
  689. KerbErr));
  690. goto Cleanup;
  691. }
  692. //
  693. // Copy the old auth data & insert the PAC
  694. //
  695. KerbErr = KdcInsertPacIntoAuthData(
  696. SourceAuthData,
  697. (IfRelevantData != NULL) ? *IfRelevantData : NULL,
  698. PacAuthData,
  699. &FinalAuthData
  700. );
  701. if (!KERB_SUCCESS(KerbErr))
  702. {
  703. DebugLog((DEB_ERROR,"KLIN(%x) Failed to insert pac into auth data: 0x%x\n",
  704. KLIN(FILENO, __LINE__),
  705. KerbErr));
  706. goto Cleanup;
  707. }
  708. }
  709. //
  710. // If there was no original PAC, try to insert one here. If the ticket
  711. // was issued from this realm we don't add a pac.
  712. //
  713. else if ((PacAuthData == NULL) && !SecData.IsOurRealm(&SourceTicket->client_realm))
  714. {
  715. KDC_TICKET_INFO ClientTicketInfo = {0};
  716. SID_AND_ATTRIBUTES_LIST GroupMembership = {0};
  717. PUSER_INTERNAL6_INFORMATION UserInfo = NULL;
  718. D_DebugLog((DEB_T_PAC, "KdcInsertAuthorizationData getting new PAC\n"));
  719. KerbErr = KerbConvertPrincipalNameToKdcName(
  720. &ClientName,
  721. &EvidenceTicket->client_name
  722. );
  723. if (!KERB_SUCCESS(KerbErr))
  724. {
  725. DebugLog((DEB_WARN,
  726. "KdcInsertAuthorizationData KLIN(%x) Convertname to kdc name failed: 0x%x\n",
  727. KLIN(FILENO, __LINE__),
  728. KerbErr));
  729. goto Cleanup;
  730. }
  731. //
  732. // S4UProxy
  733. // Our evidence ticket *must* have auth data.
  734. //
  735. if (( ARGUMENT_PRESENT( S4UTicketInfo )) &&
  736. (( S4UTicketInfo->Flags & TI_S4UPROXY_INFO ) != 0))
  737. {
  738. DebugLog((DEB_ERROR, "Trying S4UProxy w/ no PAC\n"));
  739. KerbErr = KRB_ERR_GENERIC;
  740. goto Cleanup;
  741. }
  742. #ifndef NAMESPACE_FILTER_EVERY_TRUST
  743. //
  744. // This will perform an AltSecId mapping so first we must verify that
  745. // the namespace presented via crealm is valid across this trust link
  746. //
  747. KerbErr = KdcFilterNamespace(
  748. OriginalServerInfo,
  749. SourceTicket->client_realm,
  750. pExtendedError
  751. );
  752. if ( !KERB_SUCCESS( KerbErr ))
  753. {
  754. // TODO: add logging/auditing
  755. goto Cleanup;
  756. }
  757. #endif
  758. KerbErr = KdcGetTicketInfo(
  759. &DummyName,
  760. SAM_OPEN_BY_ALTERNATE_ID,
  761. FALSE, // do not restrict user accounts (user2user)
  762. ClientName,
  763. &SourceTicket->client_realm,
  764. &ClientTicketInfo,
  765. pExtendedError,
  766. &UserHandle, // no handle
  767. USER_ALL_KDC_GET_PAC_AUTH_DATA | USER_ALL_KERB_CHECK_LOGON_RESTRICTIONS,
  768. 0L, // no extended fields
  769. &UserInfo,
  770. &GroupMembership
  771. );
  772. if (KERB_SUCCESS(KerbErr))
  773. {
  774. KdcAuditAccountMapping(
  775. ClientName,
  776. SourceTicket->client_realm,
  777. &ClientTicketInfo
  778. );
  779. //
  780. // Check for any interesting account restrictions.
  781. //
  782. KerbErr = KerbCheckLogonRestrictions(
  783. UserHandle,
  784. NULL, // No client address is available
  785. &UserInfo->I1,
  786. KDC_RESTRICT_PKINIT_USED | KDC_RESTRICT_IGNORE_PW_EXPIRATION,
  787. &LogoffTime,
  788. &LogonStatus
  789. );
  790. if (!KERB_SUCCESS( KerbErr ))
  791. {
  792. DebugLog((DEB_ERROR, "MIT PAC Client account restriction %x\n", LogonStatus));
  793. FILL_EXT_ERROR_EX2(pExtendedError, LogonStatus, FILENO,__LINE__);
  794. goto Cleanup;
  795. }
  796. FreeTicketInfo(&ClientTicketInfo);
  797. KerbFreeKdcName(&ClientName);
  798. KerbErr = KdcGetPacAuthData(
  799. UserInfo,
  800. &GroupMembership,
  801. TargetServerKey,
  802. NULL, // no credential key
  803. AddResourceGroups,
  804. FinalTicket,
  805. NULL, // no S4U client
  806. &NewPacAuthData,
  807. pExtendedError
  808. );
  809. SamIFreeSidAndAttributesList( &GroupMembership );
  810. SamIFree_UserInternal6Information( UserInfo );
  811. if (!KERB_SUCCESS(KerbErr))
  812. {
  813. goto Cleanup;
  814. }
  815. } else if ( KerbErr == KDC_ERR_C_PRINCIPAL_UNKNOWN ) {
  816. KdcAuditAccountMapping(
  817. ClientName,
  818. SourceTicket->client_realm,
  819. NULL
  820. );
  821. KerbFreeKdcName(&ClientName);
  822. DebugLog((DEB_WARN, "GetTicketInfo Client Principal Unknown\n"));
  823. KerbErr = KDC_ERR_NONE;
  824. }
  825. if (!KERB_SUCCESS(KerbErr))
  826. {
  827. DebugLog((DEB_WARN,
  828. "KdcInsertAuthorizationData KLIN(%x) Failed to GetTicketInfo: 0x%x\n",
  829. KLIN(FILENO, __LINE__),
  830. KerbErr));
  831. goto Cleanup;
  832. }
  833. //
  834. // If we got a PAC, stick it in the list
  835. //
  836. if (NewPacAuthData != NULL)
  837. {
  838. //
  839. // Copy the old auth data & insert the PAC
  840. //
  841. KerbErr = KerbCopyAndAppendAuthData(
  842. &NewPacAuthData,
  843. SourceAuthData
  844. );
  845. if (!KERB_SUCCESS(KerbErr))
  846. {
  847. DebugLog((DEB_ERROR,"KLIN(%x) Failed to insert pac into auth data: 0x%x\n",
  848. KLIN(FILENO, __LINE__), KerbErr));
  849. goto Cleanup;
  850. }
  851. FinalAuthData = NewPacAuthData;
  852. NewPacAuthData = NULL;
  853. }
  854. }
  855. //
  856. // if there was any auth data and we didn't copy it transfering the
  857. // PAC, do so now
  858. //
  859. if ((SourceAuthData != NULL) && (FinalAuthData == NULL))
  860. {
  861. KerbErr = KerbCopyAndAppendAuthData(
  862. &FinalAuthData,
  863. SourceAuthData
  864. );
  865. if (!KERB_SUCCESS(KerbErr))
  866. {
  867. DebugLog((DEB_ERROR,"KLIN(%x) Failed to appened auth data: 0x%x\n",
  868. KLIN(FILENO, __LINE__), KerbErr));
  869. goto Cleanup;
  870. }
  871. }
  872. if (SuppliedAuthData != NULL)
  873. {
  874. KerbErr = KerbCopyAndAppendAuthData(
  875. &FinalAuthData,
  876. SuppliedAuthData
  877. );
  878. if (!KERB_SUCCESS(KerbErr))
  879. {
  880. DebugLog((DEB_ERROR,"KLIN(%x) Failed to appened auth data with supplied authdata: 0x%x\n",
  881. KLIN(FILENO, __LINE__), KerbErr));
  882. goto Cleanup;
  883. }
  884. }
  885. if (FinalAuthData != NULL)
  886. {
  887. FinalTicket->bit_mask |= KERB_ENCRYPTED_TICKET_authorization_data_present;
  888. FinalTicket->KERB_ENCRYPTED_TICKET_authorization_data = FinalAuthData;
  889. FinalAuthData = NULL;
  890. }
  891. KerbErr = KDC_ERR_NONE;
  892. Cleanup:
  893. KerbFreeAuthData(
  894. FinalAuthData
  895. );
  896. if (UserHandle != NULL)
  897. {
  898. SamrCloseHandle(&UserHandle);
  899. }
  900. if (TempAuthData != NULL)
  901. {
  902. KerbFreeData(
  903. PKERB_AUTHORIZATION_DATA_LIST_PDU,
  904. TempAuthData
  905. );
  906. }
  907. KerbFreeAuthData(NewPacAuthData);
  908. if (IfRelevantData != NULL)
  909. {
  910. KerbFreeData(
  911. PKERB_IF_RELEVANT_AUTH_DATA_PDU,
  912. IfRelevantData
  913. );
  914. }
  915. return(KerbErr);
  916. }
  917. //+---------------------------------------------------------------------------
  918. //
  919. // Function: BuildTicketTGS
  920. //
  921. // Synopsis: Builds (most of) a TGS ticket
  922. //
  923. // Arguments: ServiceTicketInfo - Ticket info for the requested service
  924. // ReferralRealm - Realm to build referral to
  925. // RequestBody - The request causing this ticket to be built
  926. // SourceTicket - The TGT used to make this request
  927. // Referral - TRUE if this is an inter-realm referral ticke
  928. // CommonEType - Contains the common encryption type between
  929. // client and server
  930. // NewTicket - The new ticket built here.
  931. //
  932. //
  933. // History: 24-May-93 WadeR Created
  934. //
  935. // Notes: see 3.3.3, A.6 of the Kerberos V5 R5.2 spec
  936. //
  937. //----------------------------------------------------------------------------
  938. KERBERR
  939. BuildTicketTGS(
  940. IN PKDC_TICKET_INFO ServiceTicketInfo,
  941. IN PKERB_KDC_REQUEST_BODY RequestBody,
  942. IN PKERB_TICKET SourceTicket,
  943. IN BOOLEAN Referral,
  944. IN OPTIONAL PKDC_S4U_TICKET_INFO S4UTicketInfo,
  945. IN ULONG CommonEType,
  946. OUT PKERB_TICKET NewTicket,
  947. IN OUT PKERB_EXT_ERROR ExtendedError
  948. )
  949. {
  950. KERBERR KerbErr = KDC_ERR_NONE;
  951. KERB_TICKET OutputTicket;
  952. PKERB_ENCRYPTED_TICKET EncryptedTicket;
  953. PKERB_ENCRYPTED_TICKET SourceEncryptPart;
  954. LARGE_INTEGER TicketLifespan;
  955. LARGE_INTEGER TicketRenewspan;
  956. UNICODE_STRING NewTransitedInfo = {0,0,NULL};
  957. UNICODE_STRING ClientRealm = {0,0,NULL};
  958. UNICODE_STRING TransitedRealm = {0,0,NULL};
  959. UNICODE_STRING OldTransitedInfo = {0,0,NULL};
  960. STRING OldTransitedString;
  961. ULONG KdcOptions = 0;
  962. ULONG TicketFlags = 0;
  963. ULONG SourceTicketFlags = 0;
  964. PKERB_HOST_ADDRESSES Addresses = NULL;
  965. BOOLEAN fKpasswd = FALSE;
  966. TRACE(KDC, BuildTicketTGS, DEB_FUNCTION);
  967. D_DebugLog((DEB_T_KEY, "BuildTicketTGS building a TGS ticket Referral ? %s, CommonEType %#x\n", Referral ? "true" : "false", CommonEType));
  968. SourceEncryptPart = (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  969. OutputTicket = *NewTicket;
  970. EncryptedTicket = (PKERB_ENCRYPTED_TICKET) OutputTicket.encrypted_part.cipher_text.value;
  971. KdcOptions = KerbConvertFlagsToUlong( &RequestBody->kdc_options );
  972. //
  973. // Check to see if the request is for the kpasswd service, in
  974. // which case, we only want the ticket to be good for 2 minutes.
  975. //
  976. KerbErr = KerbCompareKdcNameToPrincipalName(
  977. &RequestBody->server_name,
  978. GlobalKpasswdName,
  979. &fKpasswd
  980. );
  981. if (fKpasswd)
  982. {
  983. TicketLifespan.QuadPart = (LONGLONG) 10000000 * 60 * 2;
  984. TicketRenewspan.QuadPart = (LONGLONG) 10000000 * 60 * 2;
  985. }
  986. else
  987. {
  988. TicketLifespan = SecData.KdcTgsTicketLifespan();
  989. TicketRenewspan = SecData.KdcTicketRenewSpan();
  990. }
  991. //
  992. // TBD: We need to make the ticket 10 minutes if we're doing s4U
  993. //
  994. KerbErr = KdcBuildTicketTimesAndFlags(
  995. 0,
  996. ServiceTicketInfo->fTicketOpts,
  997. &TicketLifespan,
  998. &TicketRenewspan,
  999. S4UTicketInfo,
  1000. NULL, // no logoff time
  1001. NULL, // no acct expiry.
  1002. RequestBody,
  1003. SourceEncryptPart,
  1004. EncryptedTicket,
  1005. ExtendedError
  1006. );
  1007. if (!KERB_SUCCESS(KerbErr))
  1008. {
  1009. D_DebugLog((DEB_ERROR, "KLIN(%x) Failed to build ticket times and flags: 0x%x\n",
  1010. KLIN(FILENO, __LINE__), KerbErr));
  1011. goto Cleanup;
  1012. }
  1013. TicketFlags = KerbConvertFlagsToUlong( &EncryptedTicket->flags );
  1014. SourceTicketFlags = KerbConvertFlagsToUlong( &SourceEncryptPart->flags );
  1015. KerbErr = KerbMakeKey(
  1016. CommonEType,
  1017. &EncryptedTicket->key
  1018. );
  1019. if (!KERB_SUCCESS(KerbErr))
  1020. {
  1021. goto Cleanup;
  1022. }
  1023. OldTransitedString.Buffer = (PCHAR) SourceEncryptPart->transited.contents.value;
  1024. OldTransitedString.Length = OldTransitedString.MaximumLength = (USHORT) SourceEncryptPart->transited.contents.length;
  1025. //
  1026. // Fill in the service names
  1027. //
  1028. if (Referral)
  1029. {
  1030. PKERB_INTERNAL_NAME TempServiceName;
  1031. //
  1032. // For referral tickets we put a the name "krbtgt/remoterealm@localrealm"
  1033. //
  1034. //
  1035. // We should only be doing this when we didn't get a non-ms principal
  1036. //
  1037. KerbErr = KerbBuildFullServiceKdcName(
  1038. &ServiceTicketInfo->AccountName,
  1039. SecData.KdcServiceName(),
  1040. KRB_NT_SRV_INST,
  1041. &TempServiceName
  1042. );
  1043. if (!KERB_SUCCESS(KerbErr))
  1044. {
  1045. goto Cleanup;
  1046. }
  1047. KerbErr = KerbConvertKdcNameToPrincipalName(
  1048. &OutputTicket.server_name,
  1049. TempServiceName
  1050. );
  1051. KerbFreeKdcName(&TempServiceName);
  1052. if (!KERB_SUCCESS(KerbErr))
  1053. {
  1054. goto Cleanup;
  1055. }
  1056. //
  1057. // If we got here on a referral ticket and are generating one
  1058. // and the referral ticket we received was not from the client's
  1059. // realm, add in the transited information.
  1060. //
  1061. if (!KerbCompareRealmNames(
  1062. &SourceEncryptPart->client_realm,
  1063. &SourceTicket->realm))
  1064. {
  1065. KerbErr = KerbStringToUnicodeString(
  1066. &OldTransitedInfo,
  1067. &OldTransitedString
  1068. );
  1069. if (!KERB_SUCCESS(KerbErr))
  1070. {
  1071. goto Cleanup;
  1072. }
  1073. KerbErr = KerbConvertRealmToUnicodeString(
  1074. &TransitedRealm,
  1075. &SourceTicket->realm
  1076. );
  1077. if (!KERB_SUCCESS(KerbErr))
  1078. {
  1079. goto Cleanup;
  1080. }
  1081. KerbErr = KerbConvertRealmToUnicodeString(
  1082. &ClientRealm,
  1083. &SourceEncryptPart->client_realm
  1084. );
  1085. if (!KERB_SUCCESS(KerbErr))
  1086. {
  1087. goto Cleanup;
  1088. }
  1089. KerbErr = KdcInsertTransitedRealm(
  1090. &NewTransitedInfo,
  1091. &OldTransitedInfo,
  1092. &ClientRealm,
  1093. &TransitedRealm,
  1094. SecData.KdcDnsRealmName()
  1095. );
  1096. if (!KERB_SUCCESS(KerbErr))
  1097. {
  1098. goto Cleanup;
  1099. }
  1100. }
  1101. }
  1102. else
  1103. {
  1104. //
  1105. // If the client didn't request name canonicalization, use the
  1106. // name supplied by the client
  1107. //
  1108. if (((KdcOptions & KERB_KDC_OPTIONS_name_canonicalize) != 0) &&
  1109. ((ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY) == 0))
  1110. {
  1111. if (ServiceTicketInfo->UserId == DOMAIN_USER_RID_KRBTGT)
  1112. {
  1113. PKERB_INTERNAL_NAME TempServiceName = NULL;
  1114. KerbErr = KerbBuildFullServiceKdcName(
  1115. SecData.KdcDnsRealmName(),
  1116. SecData.KdcServiceName(),
  1117. KRB_NT_SRV_INST,
  1118. &TempServiceName
  1119. );
  1120. if (!KERB_SUCCESS(KerbErr))
  1121. {
  1122. goto Cleanup;
  1123. }
  1124. KerbErr = KerbConvertKdcNameToPrincipalName(
  1125. &OutputTicket.server_name,
  1126. TempServiceName
  1127. );
  1128. KerbFreeKdcName(&TempServiceName);
  1129. }
  1130. else
  1131. //
  1132. // We no longer use the NC bit to change the server name, so just
  1133. // duplicate the non-NC case, and return the server name from
  1134. // the TGS_REQ. NC is still used for building PA DATA for referral
  1135. // however. and we should keep it for TGT renewal. TS 2001-4-03
  1136. //
  1137. {
  1138. KerbErr = KerbDuplicatePrincipalName(
  1139. &OutputTicket.server_name,
  1140. &RequestBody->KERB_KDC_REQUEST_BODY_server_name
  1141. );
  1142. }
  1143. }
  1144. else
  1145. {
  1146. KerbErr = KerbDuplicatePrincipalName(
  1147. &OutputTicket.server_name,
  1148. &RequestBody->KERB_KDC_REQUEST_BODY_server_name
  1149. );
  1150. }
  1151. if (!KERB_SUCCESS(KerbErr))
  1152. {
  1153. goto Cleanup;
  1154. }
  1155. }
  1156. //
  1157. // Get cname for service ticket ...
  1158. //
  1159. // S4UToSelf / S4UProxy - We're in our realm, so take the "client" name
  1160. // (supplied as PA DATA, or, alternately, the name in a additional ticket),
  1161. // and make that the server name.
  1162. //
  1163. // Otherwise, normal TGS_REQ - use source ticket (tgt)
  1164. //
  1165. if (( ARGUMENT_PRESENT( S4UTicketInfo ) ) &&
  1166. ( (S4UTicketInfo->Flags & ( TI_S4UPROXY_INFO | TI_S4USELF_INFO ) ) != 0) &&
  1167. ( !Referral ))
  1168. {
  1169. KerbErr = KerbConvertKdcNameToPrincipalName(
  1170. &EncryptedTicket->client_name,
  1171. S4UTicketInfo->PACCName
  1172. );
  1173. if (!KERB_SUCCESS(KerbErr))
  1174. {
  1175. goto Cleanup;
  1176. }
  1177. KerbErr = KerbConvertUnicodeStringToRealm(
  1178. &EncryptedTicket->client_realm,
  1179. &S4UTicketInfo->PACCRealm
  1180. );
  1181. if (!KERB_SUCCESS(KerbErr))
  1182. {
  1183. goto Cleanup;
  1184. }
  1185. }
  1186. else
  1187. {
  1188. KerbErr = KerbDuplicatePrincipalName(
  1189. &EncryptedTicket->client_name,
  1190. &SourceEncryptPart->client_name
  1191. );
  1192. if (!KERB_SUCCESS(KerbErr))
  1193. {
  1194. goto Cleanup;
  1195. }
  1196. KerbErr = KerbDuplicateRealm(
  1197. &EncryptedTicket->client_realm,
  1198. SourceEncryptPart->client_realm
  1199. );
  1200. if (!KERB_SUCCESS(KerbErr))
  1201. {
  1202. goto Cleanup;
  1203. }
  1204. }
  1205. //
  1206. // If the client did not request canonicalization, return the same
  1207. // realm as it sent. Otherwise, send our DNS realm name
  1208. //
  1209. OutputTicket.realm = SecData.KdcKerbDnsRealmName();
  1210. //
  1211. // Insert transited realms, if present
  1212. //
  1213. if (NewTransitedInfo.Length != 0)
  1214. {
  1215. STRING TempString;
  1216. KerbErr = KerbUnicodeStringToKerbString(
  1217. &TempString,
  1218. &NewTransitedInfo
  1219. );
  1220. if (!KERB_SUCCESS(KerbErr))
  1221. {
  1222. goto Cleanup;
  1223. }
  1224. EncryptedTicket->transited.transited_type = DOMAIN_X500_COMPRESS;
  1225. EncryptedTicket->transited.contents.value = (PUCHAR) TempString.Buffer;
  1226. EncryptedTicket->transited.contents.length = (int) TempString.Length;
  1227. }
  1228. else
  1229. {
  1230. EncryptedTicket->transited.transited_type = DOMAIN_X500_COMPRESS;
  1231. EncryptedTicket->transited.contents.value = (PUCHAR) MIDL_user_allocate(OldTransitedString.Length);
  1232. if (EncryptedTicket->transited.contents.value == NULL)
  1233. {
  1234. KerbErr = KRB_ERR_GENERIC;
  1235. goto Cleanup;
  1236. }
  1237. EncryptedTicket->transited.contents.length = (int) OldTransitedString.Length;
  1238. RtlCopyMemory(
  1239. EncryptedTicket->transited.contents.value,
  1240. OldTransitedString.Buffer,
  1241. OldTransitedString.Length
  1242. );
  1243. }
  1244. //
  1245. // Insert the client addresses. We only update them if the new ticket
  1246. // is forwarded of proxied and the source ticket was forwardable or proxiable
  1247. // - else we copy the old ones
  1248. //
  1249. if ((((TicketFlags & KERB_TICKET_FLAGS_forwarded) != 0) &&
  1250. ((SourceTicketFlags & KERB_TICKET_FLAGS_forwardable) != 0)) ||
  1251. (((TicketFlags & KERB_TICKET_FLAGS_proxy) != 0) &&
  1252. ((SourceTicketFlags & KERB_TICKET_FLAGS_proxiable) != 0)))
  1253. {
  1254. if ((RequestBody->bit_mask & addresses_present) != 0)
  1255. {
  1256. Addresses = RequestBody->addresses;
  1257. }
  1258. }
  1259. else
  1260. {
  1261. if ((SourceEncryptPart->bit_mask & KERB_ENCRYPTED_TICKET_client_addresses_present) != 0)
  1262. {
  1263. Addresses = SourceEncryptPart->KERB_ENCRYPTED_TICKET_client_addresses;
  1264. }
  1265. }
  1266. if (Addresses != NULL)
  1267. {
  1268. EncryptedTicket->KERB_ENCRYPTED_TICKET_client_addresses = Addresses;
  1269. EncryptedTicket->bit_mask |= KERB_ENCRYPTED_TICKET_client_addresses_present;
  1270. }
  1271. else
  1272. {
  1273. EncryptedTicket->KERB_ENCRYPTED_TICKET_client_addresses = NULL;
  1274. EncryptedTicket->bit_mask &= ~KERB_ENCRYPTED_TICKET_client_addresses_present;
  1275. }
  1276. //
  1277. // The authorization data will be added by the caller, so set it
  1278. // to NULL here.
  1279. //
  1280. EncryptedTicket->KERB_ENCRYPTED_TICKET_authorization_data = NULL;
  1281. OutputTicket.ticket_version = KERBEROS_VERSION;
  1282. *NewTicket = OutputTicket;
  1283. Cleanup:
  1284. if (!KERB_SUCCESS(KerbErr))
  1285. {
  1286. KdcFreeInternalTicket(&OutputTicket);
  1287. }
  1288. KerbFreeString(&NewTransitedInfo);
  1289. KerbFreeString(&OldTransitedInfo);
  1290. KerbFreeString(&ClientRealm);
  1291. KerbFreeString(&TransitedRealm);
  1292. return (KerbErr);
  1293. }
  1294. //+-------------------------------------------------------------------------
  1295. //
  1296. // Function: KdcVerifyTgsLogonRestrictions
  1297. //
  1298. // Synopsis: Verifies that a client is allowed to request a TGS ticket
  1299. // by checking logon restrictions.
  1300. //
  1301. // Effects:
  1302. //
  1303. // Arguments: ClientName - Name of client to check
  1304. //
  1305. // Requires:
  1306. //
  1307. // Returns: KDC_ERR_NONE or a logon restriction error
  1308. //
  1309. // Notes:
  1310. //
  1311. //
  1312. //--------------------------------------------------------------------------
  1313. KERBERR
  1314. KdcCheckTgsLogonRestrictions(
  1315. IN PKERB_INTERNAL_NAME ClientName,
  1316. IN PUNICODE_STRING ClientRealm,
  1317. OUT PKERB_EXT_ERROR pExtendedError
  1318. )
  1319. {
  1320. KERBERR Status;
  1321. UNICODE_STRING MappedClientRealm = {0};
  1322. BOOLEAN ClientReferral;
  1323. KDC_TICKET_INFO ClientInfo = {0};
  1324. SAMPR_HANDLE UserHandle = NULL;
  1325. PUSER_INTERNAL6_INFORMATION UserInfo = NULL;
  1326. LARGE_INTEGER LogoffTime;
  1327. NTSTATUS LogonStatus = STATUS_SUCCESS;
  1328. SECPKG_CALL_INFO CallInfo ;
  1329. //
  1330. // If the client is from a different realm, don't bother looking
  1331. // it up - the account won't be here.
  1332. //
  1333. if (!SecData.IsOurRealm(
  1334. ClientRealm
  1335. ))
  1336. {
  1337. return(KDC_ERR_NONE);
  1338. }
  1339. //
  1340. // Normalize the client name
  1341. //
  1342. //
  1343. // Note: In some cases, attempts to normalize our own client name, e.g. the
  1344. // KDC's name someRealm\FooDc$, will result in recursion as follows :
  1345. //
  1346. // 1. We may need to talk to a GC to normalize the DC's name.
  1347. // 2. We try to get a ticket to a GC from this DC (aka the ClientName below)
  1348. // 3. We check logon restrictions
  1349. // 4. We try to normalize, recurse...
  1350. //
  1351. // We *should* in most cases be able to satisfy the DC lookup internally,
  1352. // unless the DS is just starting up, and replication is firing up. Assert,
  1353. // so we can determine why the client name is causing recursion in the normalize
  1354. // code path.
  1355. //
  1356. if ( LsaIGetCallInfo( &CallInfo ) )
  1357. {
  1358. if (( CallInfo.Attributes & SECPKG_CALL_RECURSIVE ) &&
  1359. ( ClientName->NameCount == 1) &&
  1360. ( SecData.IsOurMachineName(&ClientName->Names[0])))
  1361. {
  1362. D_DebugLog((DEB_ERROR, "Recursion detected during TGS logon restrictions\n"));
  1363. return (KDC_ERR_NONE);
  1364. }
  1365. }
  1366. Status = KdcNormalize(
  1367. ClientName,
  1368. NULL,
  1369. ClientRealm,
  1370. NULL,
  1371. KDC_NAME_CLIENT,
  1372. FALSE, // do not restrict user accounts (user2user)
  1373. &ClientReferral,
  1374. &MappedClientRealm,
  1375. &ClientInfo,
  1376. pExtendedError,
  1377. &UserHandle,
  1378. USER_ALL_KERB_CHECK_LOGON_RESTRICTIONS,
  1379. 0L,
  1380. &UserInfo,
  1381. NULL // no group memberships
  1382. );
  1383. if (!KERB_SUCCESS(Status))
  1384. {
  1385. DebugLog((DEB_ERROR, "KdcCheckTgsLogonRestrictions KLIN(%x) failed to normalize name %#x: ", KLIN(FILENO, __LINE__), Status));
  1386. KerbPrintKdcName(DEB_ERROR,ClientName);
  1387. goto Cleanup;
  1388. }
  1389. Status = KerbCheckLogonRestrictions(
  1390. UserHandle,
  1391. NULL, // No client address is available
  1392. &UserInfo->I1,
  1393. KDC_RESTRICT_PKINIT_USED | KDC_RESTRICT_IGNORE_PW_EXPIRATION, // Don't bother checking for password expiration
  1394. &LogoffTime,
  1395. &LogonStatus
  1396. );
  1397. if (!KERB_SUCCESS(Status))
  1398. {
  1399. DebugLog((DEB_WARN,"KLIN (%x) Logon restriction check failed: 0x%x\n",
  1400. KLIN(FILENO, __LINE__),Status));
  1401. //
  1402. // This is a *very* important error to trickle back. See 23456 in bug DB
  1403. //
  1404. FILL_EXT_ERROR(pExtendedError, LogonStatus, FILENO, __LINE__);
  1405. goto Cleanup;
  1406. }
  1407. Cleanup:
  1408. KerbFreeString( &MappedClientRealm );
  1409. FreeTicketInfo( &ClientInfo );
  1410. SamIFree_UserInternal6Information( UserInfo );
  1411. if (UserHandle != NULL)
  1412. {
  1413. SamrCloseHandle(&UserHandle);
  1414. }
  1415. return Status;
  1416. }
  1417. //+-------------------------------------------------------------------------
  1418. //
  1419. // Function: KdcBuildReferralInfo
  1420. //
  1421. // Synopsis: Builds the referral information to return to the client.
  1422. // We only return the realm name and no server name
  1423. //
  1424. // Effects:
  1425. //
  1426. // Arguments: ReferralRealm - realm to refer client to
  1427. // ReferralInfo - recevies encoded referral info
  1428. //
  1429. // Requires:
  1430. //
  1431. // Returns:
  1432. //
  1433. // Notes:
  1434. //
  1435. //
  1436. //--------------------------------------------------------------------------
  1437. KERBERR
  1438. KdcBuildReferralInfo(
  1439. IN PUNICODE_STRING ReferralRealm,
  1440. OUT PKERB_PA_DATA_LIST *ReferralInfo
  1441. )
  1442. {
  1443. KERBERR KerbErr = KDC_ERR_NONE;
  1444. PKERB_PA_DATA_LIST ListElem = NULL;
  1445. KERB_PA_SERV_REFERRAL ReferralData = {0};
  1446. //
  1447. // Fill in the unencoded structure.
  1448. //
  1449. KerbErr = KerbConvertUnicodeStringToRealm(
  1450. &ReferralData.referred_server_realm,
  1451. ReferralRealm
  1452. );
  1453. if (!KERB_SUCCESS(KerbErr))
  1454. {
  1455. goto Cleanup;
  1456. }
  1457. ListElem = (PKERB_PA_DATA_LIST) MIDL_user_allocate(sizeof(KERB_PA_DATA_LIST));
  1458. if (ListElem == NULL)
  1459. {
  1460. KerbErr = KRB_ERR_GENERIC;
  1461. goto Cleanup;
  1462. }
  1463. RtlZeroMemory(ListElem, sizeof(KERB_PA_DATA_LIST));
  1464. ListElem->value.preauth_data_type = KRB5_PADATA_REFERRAL_INFO;
  1465. KerbErr = KerbPackData(
  1466. &ReferralData,
  1467. KERB_PA_SERV_REFERRAL_PDU,
  1468. (PULONG) &ListElem->value.preauth_data.length,
  1469. &ListElem->value.preauth_data.value
  1470. );
  1471. if (!KERB_SUCCESS(KerbErr))
  1472. {
  1473. goto Cleanup;
  1474. }
  1475. *ReferralInfo = ListElem;
  1476. ListElem = NULL;
  1477. Cleanup:
  1478. if (ListElem != NULL)
  1479. {
  1480. if (ListElem->value.preauth_data.value != NULL)
  1481. {
  1482. KdcFreeEncodedData(ListElem->value.preauth_data.value);
  1483. }
  1484. MIDL_user_free(ListElem);
  1485. }
  1486. KerbFreeRealm(&ReferralData.referred_server_realm);
  1487. return(KerbErr);
  1488. }
  1489. //--------------------------------------------------------------------
  1490. //
  1491. // Name: I_RenewTicket
  1492. //
  1493. // Synopsis: Renews an internal ticket.
  1494. //
  1495. // Arguments: SourceTicket - Source ticket for this request
  1496. // ClientStringName - Client string name
  1497. // ServerStringName - Service string name
  1498. // ServiceName - Name of service for ticket
  1499. // ClientRealm - Realm of client
  1500. // ServiceTicketInfo - Ticket info from service account
  1501. // RequestBody - Body of ticket request
  1502. // NewTicket - Receives new ticket
  1503. // pServerKey - the key to encrypt ticket
  1504. // TicketKey - Receives key used to encrypt the ticket
  1505. //
  1506. // Notes: Validates the ticket, gets the service's current key,
  1507. // and builds the reply.
  1508. //
  1509. //
  1510. //--------------------------------------------------------------------
  1511. KERBERR
  1512. I_RenewTicket(
  1513. IN PKERB_TICKET SourceTicket,
  1514. IN PUNICODE_STRING ClientStringName,
  1515. IN PUNICODE_STRING ServerStringName,
  1516. IN PKERB_INTERNAL_NAME ServiceName,
  1517. IN PKDC_TICKET_INFO ServiceTicketInfo,
  1518. IN PKERB_KDC_REQUEST_BODY RequestBody,
  1519. IN OPTIONAL PKERB_ENCRYPTION_KEY Subkey,
  1520. OUT PKERB_TICKET NewTicket,
  1521. OUT PKERB_ENCRYPTION_KEY pServerKey,
  1522. OUT PKERB_EXT_ERROR pExtendedError
  1523. )
  1524. {
  1525. KERBERR KerbErr = KDC_ERR_NONE;
  1526. PKERB_ENCRYPTED_TICKET SourceEncryptPart = (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  1527. PKERB_ENCRYPTED_TICKET NewEncryptPart = (PKERB_ENCRYPTED_TICKET) NewTicket->encrypted_part.cipher_text.value;
  1528. BOOLEAN NamesEqual = FALSE;
  1529. ULONG CommonEType = KERB_ETYPE_DEFAULT;
  1530. PKERB_ENCRYPTION_KEY pLocalServerKey = NULL;
  1531. TRACE(KDC, I_RenewTicket, DEB_FUNCTION);
  1532. D_DebugLog((DEB_TRACE, "Trying to renew a ticket to "));
  1533. D_KerbPrintKdcName((DEB_TRACE, ServiceName));
  1534. //
  1535. // Make sure the original is renewable.
  1536. //
  1537. if ((KerbConvertFlagsToUlong(&SourceEncryptPart->flags) & KERB_TICKET_FLAGS_renewable) == 0)
  1538. {
  1539. D_DebugLog((DEB_WARN, "KLIN(%x) Attempt made to renew non-renewable ticket\n",
  1540. KLIN(FILENO, __LINE__)));
  1541. KerbErr = KDC_ERR_BADOPTION;
  1542. goto Cleanup;
  1543. }
  1544. //
  1545. // Make sure the source ticket service equals the service from the ticket info
  1546. //
  1547. KerbErr = KerbCompareKdcNameToPrincipalName(
  1548. &SourceTicket->server_name,
  1549. ServiceName,
  1550. &NamesEqual
  1551. );
  1552. if (!KERB_SUCCESS(KerbErr))
  1553. {
  1554. goto Cleanup;
  1555. }
  1556. if (!NamesEqual)
  1557. {
  1558. //
  1559. // Make sure we the renewed ticket is for the same service as the original.
  1560. //
  1561. FILL_EXT_ERROR(pExtendedError, STATUS_KDC_INVALID_REQUEST, FILENO, __LINE__);
  1562. KerbErr = KDC_ERR_BADOPTION;
  1563. goto Cleanup;
  1564. }
  1565. //
  1566. // Find the supported crypt system
  1567. //
  1568. KerbErr = KerbFindCommonCryptSystemForSKey(
  1569. RequestBody->encryption_type,
  1570. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  1571. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  1572. &CommonEType
  1573. );
  1574. if (!KERB_SUCCESS(KerbErr))
  1575. {
  1576. if (KDC_ERR_ETYPE_NOTSUPP == KerbErr)
  1577. {
  1578. KdcReportKeyError(
  1579. ClientStringName,
  1580. ServerStringName,
  1581. KDC_KEY_ID_RENEWAL_SKEY,
  1582. KDCEVENT_NO_KEY_INTERSECTION_TGS,
  1583. RequestBody->encryption_type,
  1584. ServiceTicketInfo
  1585. );
  1586. }
  1587. DebugLog((DEB_ERROR, "KLIN(%x) failed to find common ETYPE: %#x\n", KLIN(FILENO, __LINE__), KerbErr));
  1588. goto Cleanup;
  1589. }
  1590. //
  1591. // Find the common crypt system.
  1592. //
  1593. KerbErr = KerbFindCommonCryptSystem(
  1594. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  1595. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  1596. ServiceTicketInfo->Passwords,
  1597. NULL,
  1598. &pLocalServerKey
  1599. );
  1600. if (!KERB_SUCCESS(KerbErr))
  1601. {
  1602. if (KDC_ERR_ETYPE_NOTSUPP == KerbErr)
  1603. {
  1604. KdcReportKeyError(
  1605. ClientStringName,
  1606. ServerStringName,
  1607. KDC_KEY_ID_RENEWAL_TICKET,
  1608. KDCEVENT_NO_KEY_INTERSECTION_TGS,
  1609. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  1610. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  1611. ServiceTicketInfo
  1612. );
  1613. }
  1614. DebugLog((DEB_ERROR, "KLIN(%x) failed to find common ETYPE: %#x\n", KLIN(FILENO, __LINE__), KerbErr));
  1615. goto Cleanup;
  1616. }
  1617. //
  1618. // Build the renewal ticket
  1619. //
  1620. KerbErr = BuildTicketTGS(
  1621. ServiceTicketInfo,
  1622. RequestBody,
  1623. SourceTicket,
  1624. FALSE, // not referral
  1625. NULL, // not doing s4u
  1626. CommonEType,
  1627. NewTicket,
  1628. pExtendedError
  1629. );
  1630. if (!KERB_SUCCESS(KerbErr))
  1631. {
  1632. D_DebugLog((DEB_ERROR,
  1633. "KLIN(%x) Failed to build TGS ticket for renewal: 0x%x\n",
  1634. KLIN(FILENO, __LINE__), KerbErr));
  1635. goto Cleanup;
  1636. }
  1637. //
  1638. // BuildTicket puts a random session key in the ticket,
  1639. // so replace it with the one from the source ticket.
  1640. //
  1641. KerbFreeKey(
  1642. &NewEncryptPart->key
  1643. );
  1644. KerbErr = KerbDuplicateKey(
  1645. &NewEncryptPart->key,
  1646. &SourceEncryptPart->key
  1647. );
  1648. if (!KERB_SUCCESS(KerbErr))
  1649. {
  1650. goto Cleanup;
  1651. }
  1652. //
  1653. // Insert the auth data into the new ticket.
  1654. //
  1655. //
  1656. // BUG 455049: if the service password changes, this will cause problems
  1657. // because we don't resign the pac.
  1658. //
  1659. KerbErr = KdcInsertAuthorizationData(
  1660. NewEncryptPart,
  1661. pExtendedError,
  1662. (RequestBody->bit_mask & enc_authorization_data_present) ?
  1663. &RequestBody->enc_authorization_data : NULL,
  1664. SourceEncryptPart,
  1665. NULL, // no server info
  1666. NULL,
  1667. NULL,
  1668. NULL,
  1669. NULL,
  1670. Subkey,
  1671. NULL
  1672. );
  1673. if (!KERB_SUCCESS(KerbErr))
  1674. {
  1675. DebugLog((DEB_ERROR, "KLIN(%x) Failed to insert authorization data: 0x%x\n",
  1676. KLIN(FILENO, __LINE__), KerbErr));
  1677. goto Cleanup;
  1678. }
  1679. KerbErr = KerbDuplicateKey(pServerKey, pLocalServerKey);
  1680. Cleanup:
  1681. if (!KERB_SUCCESS(KerbErr))
  1682. {
  1683. KdcFreeInternalTicket(
  1684. NewTicket
  1685. );
  1686. }
  1687. return(KerbErr);
  1688. }
  1689. //--------------------------------------------------------------------
  1690. //
  1691. // Name: I_Validate
  1692. //
  1693. // Synopsis: Validates a post-dated ticket so that it can be used.
  1694. // This is not implemented.
  1695. //
  1696. // Arguments: pkitSourceTicket - (in) ticket to be validated
  1697. // pkiaAuthenticator -
  1698. // pService - (in) service ticket is for
  1699. // pRealm - (in) realm service exists in
  1700. // pktrRequest - (in) holds nonce for new ticket
  1701. // pkdPAData - (in)
  1702. // pkitTicket - (out) new ticket
  1703. //
  1704. // Notes: See 3.3 of the Kerberos V5 R5.2 spec
  1705. //
  1706. //--------------------------------------------------------------------
  1707. KERBERR
  1708. I_Validate(
  1709. IN PKERB_TICKET SourceTicket,
  1710. IN PKERB_INTERNAL_NAME ServiceName,
  1711. IN PUNICODE_STRING ClientRealm,
  1712. IN PKERB_KDC_REQUEST_BODY RequestBody,
  1713. OUT PKERB_ENCRYPTION_KEY pServerKey,
  1714. OUT PKERB_TICKET NewTicket,
  1715. OUT PKERB_EXT_ERROR pExtendedError
  1716. )
  1717. {
  1718. return(KDC_ERR_BADOPTION);
  1719. #ifdef notdef
  1720. TRACE(KDC, I_Validate, DEB_FUNCTION);
  1721. HRESULT hr;
  1722. D_DebugLog(( DEB_TRACE, "Trying to validate a ticket to '%ws' for '%ws'...\n",
  1723. pkitSourceTicket->ServerName.accsid.pwszDisplayName,
  1724. pkitSourceTicket->kitEncryptPart.Principal.accsid.pwszDisplayName ));
  1725. PrintRequest( DEB_T_TICKETS, pktrRequest );
  1726. PrintTicket( DEB_T_TICKETS, "Ticket to validate:", pkitSourceTicket );
  1727. if ( (pkitSourceTicket->kitEncryptPart.fTicketFlags &
  1728. (KERBFLAG_POSTDATED | KERBFLAG_INVALID))
  1729. != (KERBFLAG_POSTDATED | KERBFLAG_INVALID) )
  1730. {
  1731. hr = KDC_E_BADOPTION;
  1732. }
  1733. else if (_wcsicmp(pkitSourceTicket->ServerName.accsid.pwszDisplayName,
  1734. pasService->pwszDisplayName) != 0)
  1735. {
  1736. hr = KDC_E_BADOPTION;
  1737. }
  1738. else
  1739. {
  1740. TimeStamp tsNow, tsMinus, tsPlus;
  1741. GetCurrentTimeStamp( &tsNow );
  1742. tsMinus = tsNow - SkewTime;
  1743. tsPlus = tsNow + SkewTime;
  1744. PrintTime(DEB_TRACE, "Current time: ", tsNow );
  1745. PrintTime(DEB_TRACE, "Past time: ", tsMinus );
  1746. PrintTime(DEB_TRACE, "Future time: ", tsPlus );
  1747. if (pkitSourceTicket->kitEncryptPart.tsStartTime > tsPlus )
  1748. hr = KRB_E_TKT_NYV;
  1749. else if (pkitSourceTicket->kitEncryptPart.tsEndTime < tsMinus )
  1750. hr = KRB_E_TKT_EXPIRED;
  1751. else
  1752. {
  1753. *pkitTicket = *pkitSourceTicket;
  1754. pkitTicket->kitEncryptPart.fTicketFlags &= (~KERBFLAG_INVALID);
  1755. hr = S_OK;
  1756. }
  1757. }
  1758. return(hr);
  1759. #endif // notdef
  1760. }
  1761. //--------------------------------------------------------------------
  1762. //
  1763. // Name: KerbPerformTgsAccessCheck
  1764. //
  1765. // Synopsis: Access-checks the given ticket against the principal
  1766. // the ticket is for. Part of "this organization" vs.
  1767. // "other organization" logic.
  1768. //
  1769. // Arguments: TicketInfo ticket
  1770. // SdCount number of entries in the SecurityDescriptors
  1771. // array
  1772. // SecurityDescriptors security descriptors to check against
  1773. // EncryptedTicket ticket
  1774. // EncryptionType encryption type associated with ticket
  1775. //
  1776. // Notes: A successful check against _any_ of the security descriptors
  1777. // passed in causes the routine to succeed
  1778. //
  1779. // Returns:
  1780. //
  1781. // KDC_ERR_NONE - access check succeeded
  1782. // KDC_ERR_POLICY - access check failed
  1783. //
  1784. //--------------------------------------------------------------------
  1785. KERBERR
  1786. KerbPerformTgsAccessCheck(
  1787. IN PKDC_TICKET_INFO TicketInfo,
  1788. IN PUCHAR SecurityDescriptor,
  1789. IN PKERB_ENCRYPTED_TICKET EncryptedTicket,
  1790. IN ULONG EncryptionType,
  1791. OUT NTSTATUS * pStatus
  1792. )
  1793. {
  1794. KERBERR KerbErr;
  1795. KDC_AUTHZ_INFO AuthzInfo = {0};
  1796. KDC_AUTHZ_GROUP_BUFFERS InfoToFree = {0};
  1797. AUTHZ_ACCESS_REPLY Reply = {0};
  1798. OBJECT_TYPE_LIST TypeList ={0};
  1799. AUTHZ_CLIENT_CONTEXT_HANDLE hClientContext = NULL;
  1800. AUTHZ_ACCESS_REQUEST Request = {0};
  1801. DWORD AccessMask = 0;
  1802. LUID ZeroLuid = {0,0};
  1803. DWORD Error = ERROR_ACCESS_DENIED;
  1804. BOOLEAN OtherOrgSidFound = FALSE;
  1805. *pStatus = STATUS_SUCCESS;
  1806. KerbErr = KdcGetSidsFromTgt(
  1807. EncryptedTicket,
  1808. NULL, // no key for encrypted tgt.
  1809. EncryptionType,
  1810. TicketInfo,
  1811. &AuthzInfo,
  1812. &InfoToFree,
  1813. pStatus
  1814. );
  1815. if ( !KERB_SUCCESS( KerbErr ))
  1816. {
  1817. DebugLog((DEB_ERROR, "KdcGetSidsFromTgt in KerbPerformTgsAccessCheck failed %x\n", KerbErr));
  1818. goto Cleanup;
  1819. }
  1820. //
  1821. // Per the specification, the access check is only performed if the
  1822. // "other org" SID is in the list
  1823. //
  1824. for ( ULONG i = 0 ; i < AuthzInfo.SidCount ; i++ )
  1825. {
  1826. if ( RtlEqualSid( AuthzInfo.SidAndAttributes[i].Sid, GlobalOtherOrganizationSid ))
  1827. {
  1828. OtherOrgSidFound = TRUE;
  1829. break;
  1830. }
  1831. }
  1832. if ( !OtherOrgSidFound )
  1833. {
  1834. KerbErr = KDC_ERR_NONE;
  1835. goto Cleanup;
  1836. }
  1837. if (!AuthzInitializeContextFromSid(
  1838. AUTHZ_SKIP_TOKEN_GROUPS, // take the SIDs as they are
  1839. AuthzInfo.SidAndAttributes[0].Sid, // userid is first element in array
  1840. KdcAuthzRM,
  1841. NULL,
  1842. ZeroLuid,
  1843. &AuthzInfo,
  1844. &hClientContext
  1845. ))
  1846. {
  1847. DebugLog((DEB_ERROR, "AuthzInitializeContextFromSid() failed in KerbPerformTgsAccessCheck%x\n", GetLastError()));
  1848. KerbErr = KDC_ERR_POLICY;
  1849. *pStatus = STATUS_AUTHENTICATION_FIREWALL_FAILED;
  1850. goto Cleanup;
  1851. }
  1852. //
  1853. // Perform the access check
  1854. //
  1855. TypeList.Level = ACCESS_OBJECT_GUID;
  1856. TypeList.ObjectType = &GUID_A_SECURED_FOR_CROSS_ORGANIZATION;
  1857. TypeList.Sbz = 0;
  1858. Request.DesiredAccess = ACTRL_DS_CONTROL_ACCESS;
  1859. Request.ObjectTypeList = &TypeList;
  1860. Request.ObjectTypeListLength = 1;
  1861. Request.OptionalArguments = NULL;
  1862. Request.PrincipalSelfSid = NULL;
  1863. Reply.ResultListLength = 1; // all or nothing w.r.t. access check.
  1864. Reply.GrantedAccessMask = &AccessMask;
  1865. Reply.Error = &Error;
  1866. if (!AuthzAccessCheck(
  1867. 0,
  1868. hClientContext,
  1869. &Request,
  1870. NULL, // TBD: add audit
  1871. SecurityDescriptor,
  1872. NULL,
  1873. NULL,
  1874. &Reply,
  1875. NULL // don't cache result? Check to see if optimal.
  1876. ))
  1877. {
  1878. DebugLog((DEB_ERROR, "AuthzAccessCheck() failed in KerbPerformTgsAccessCheck%x\n", GetLastError()));
  1879. KerbErr = KDC_ERR_POLICY;
  1880. *pStatus = STATUS_AUTHENTICATION_FIREWALL_FAILED;
  1881. }
  1882. else if ( (*Reply.Error) != ERROR_SUCCESS )
  1883. {
  1884. DebugLog((DEB_ERROR, "CrossOrg authz AC failed %x \n",(*Reply.Error)));
  1885. KerbErr = KDC_ERR_POLICY;
  1886. *pStatus = STATUS_AUTHENTICATION_FIREWALL_FAILED;
  1887. }
  1888. else
  1889. {
  1890. KerbErr = KDC_ERR_NONE;
  1891. }
  1892. Cleanup:
  1893. if ( hClientContext != NULL )
  1894. {
  1895. AuthzFreeContext(hClientContext);
  1896. }
  1897. KdcFreeAuthzInfo( &InfoToFree );
  1898. return KerbErr;
  1899. }
  1900. #ifdef ROGUE_DC
  1901. KERBERR
  1902. KdcInstrumentRogueCrealm(
  1903. IN OUT PKERB_ENCRYPTED_TICKET EncryptedTicket
  1904. )
  1905. {
  1906. KERBERR KerbErr;
  1907. DWORD dwType;
  1908. DWORD cbData = 0;
  1909. PCHAR Buffer;
  1910. PCHAR Value = NULL;
  1911. ULONG NameType;
  1912. UNICODE_STRING ClientName = {0};
  1913. UNICODE_STRING DomainName = {0};
  1914. UNICODE_STRING EmailNameU = {0};
  1915. PCHAR EmailName = NULL;
  1916. PCHAR NewCrealm = NULL;
  1917. //
  1918. // Optimization: no "rogue" key in registry - nothing for us to do
  1919. //
  1920. if ( hKdcRogueKey == NULL )
  1921. {
  1922. return KDC_ERR_NONE;
  1923. }
  1924. //
  1925. // Build an e-mail name of the client to look up mapping for in the registry
  1926. //
  1927. KerbErr = KerbConvertPrincipalNameToString(
  1928. &ClientName,
  1929. &NameType,
  1930. &EncryptedTicket->client_name
  1931. );
  1932. if ( !KERB_SUCCESS( KerbErr )) {
  1933. DebugLog((DEB_ERROR, "ROGUE: KerbConvertPrincipalNameToString failed\n"));
  1934. goto Cleanup;
  1935. }
  1936. KerbErr = KerbConvertRealmToUnicodeString(
  1937. &DomainName,
  1938. &EncryptedTicket->client_realm
  1939. );
  1940. if ( !KERB_SUCCESS( KerbErr )) {
  1941. DebugLog((DEB_ERROR, "ROGUE: KerbConvertRealmToUnicodeString failed\n"));
  1942. goto Cleanup;
  1943. }
  1944. KerbErr = KerbBuildEmailName(
  1945. &DomainName,
  1946. &ClientName,
  1947. &EmailNameU
  1948. );
  1949. if ( !KERB_SUCCESS( KerbErr )) {
  1950. DebugLog((DEB_ERROR, "ROGUE: KerbBuildEmailName failed\n"));
  1951. goto Cleanup;
  1952. }
  1953. EmailName = KerbAllocUtf8StrFromUnicodeString( &EmailNameU );
  1954. if ( EmailName == NULL )
  1955. {
  1956. KerbErr = KRB_ERR_GENERIC;
  1957. goto Cleanup;
  1958. }
  1959. //
  1960. // See if this realm is in the substitute list in the registry
  1961. //
  1962. if ( ERROR_SUCCESS != RegQueryValueExA(
  1963. hKdcRogueKey,
  1964. EmailName,
  1965. NULL,
  1966. &dwType,
  1967. (PBYTE)Value,
  1968. &cbData ) ||
  1969. dwType != REG_MULTI_SZ ||
  1970. cbData <= 1 )
  1971. {
  1972. DebugLog((DEB_ERROR, "ROGUE: Error reading from registry\n"));
  1973. KerbErr = KRB_ERR_GENERIC;
  1974. goto Cleanup;
  1975. }
  1976. SafeAllocaAllocate( Value, cbData );
  1977. if ( Value == NULL )
  1978. {
  1979. DebugLog((DEB_ERROR, "ROGUE: Out of memory allocating substitution buffer\n" ));
  1980. KerbErr = KRB_ERR_GENERIC;
  1981. goto Cleanup;
  1982. }
  1983. if ( ERROR_SUCCESS != RegQueryValueExA(
  1984. hKdcRogueKey,
  1985. EmailName,
  1986. NULL,
  1987. &dwType,
  1988. (PBYTE)Value,
  1989. &cbData ) ||
  1990. dwType != REG_MULTI_SZ ||
  1991. cbData <= 1 )
  1992. {
  1993. DebugLog((DEB_ERROR, "ROGUE: Error reading from registry\n"));
  1994. KerbErr = KRB_ERR_GENERIC;
  1995. goto Cleanup;
  1996. }
  1997. DebugLog((DEB_ERROR, "ROGUE: Substituting the crealm for %wZ\n", &EmailName));
  1998. Buffer = Value;
  1999. while ( *Buffer != '\0' )
  2000. {
  2001. if ( 0 == _strnicmp( Buffer, "crealm:", sizeof( "crealm" ) - 1 ))
  2002. {
  2003. Buffer += strlen( "crealm:" );
  2004. if ( *Buffer != '\0' )
  2005. {
  2006. DebugLog((DEB_ERROR, "ROGUE: Replacing crealm for %wZ with %s\n", &EmailName, Buffer ));
  2007. NewCrealm = Buffer;
  2008. }
  2009. }
  2010. //
  2011. // Move to the next line
  2012. //
  2013. while (*Buffer++ != '\0');
  2014. }
  2015. if ( NewCrealm != NULL )
  2016. {
  2017. KERB_REALM NewCrealmCopy;
  2018. KerbErr = KerbDuplicateRealm(
  2019. &NewCrealmCopy,
  2020. NewCrealm
  2021. );
  2022. if ( !KERB_SUCCESS( KerbErr ))
  2023. {
  2024. DebugLog((DEB_ERROR, "ROGUE: Out of memory inside KdcInstrumentRogueCrealm\n" ));
  2025. goto Cleanup;
  2026. }
  2027. KerbFreeRealm( &EncryptedTicket->client_realm );
  2028. EncryptedTicket->client_realm = NewCrealmCopy;
  2029. }
  2030. Cleanup:
  2031. MIDL_user_free( EmailName );
  2032. KerbFreeString( &ClientName );
  2033. KerbFreeString( &DomainName );
  2034. KerbFreeString( &EmailNameU );
  2035. SafeAllocaFree( Value );
  2036. return KerbErr;
  2037. }
  2038. #endif
  2039. //--------------------------------------------------------------------
  2040. //
  2041. // Name: I_GetTGSTicket
  2042. //
  2043. // Synopsis: Gets an internal ticket using a KDC ticket (TGT).
  2044. //
  2045. // Arguments: SourceTicket - TGT for the client
  2046. // ClientStringName - Client string name
  2047. // ServerStringName - Server string name
  2048. // ServiceName - Service to get a ticket to
  2049. // RequestBody - Body of KDC request message
  2050. // ServiceTicketInfo - Ticket info for the service of the
  2051. // source ticket
  2052. // TicketEncryptionKey - If present, then this is a
  2053. // enc_tkt_in_skey request and the PAC should be
  2054. // encrypted with this key.
  2055. // NewTicket - Receives newly created ticket
  2056. // pServerKey - Key to encrypt ticket
  2057. // ReplyPaData - Contains any PA data to put in the reply
  2058. //
  2059. // Notes: See GetTGSTicket.
  2060. //
  2061. //
  2062. //--------------------------------------------------------------------
  2063. KERBERR
  2064. I_GetTGSTicket(
  2065. IN PKERB_TICKET SourceTicket,
  2066. IN PUNICODE_STRING ClientStringName,
  2067. IN PUNICODE_STRING ServerStringName,
  2068. IN PKERB_INTERNAL_NAME ServiceName,
  2069. IN PUNICODE_STRING RequestRealm,
  2070. IN PKERB_KDC_REQUEST_BODY RequestBody,
  2071. IN PKDC_TICKET_INFO ServiceTicketInfo,
  2072. IN OPTIONAL PKERB_ENCRYPTION_KEY TicketEncryptionKey,
  2073. IN PKDC_S4U_TICKET_INFO S4UTicketInfo,
  2074. IN OPTIONAL PKERB_ENCRYPTION_KEY Subkey,
  2075. OUT PKERB_TICKET Ticket,
  2076. OUT PKERB_ENCRYPTION_KEY pServerKey,
  2077. OUT PKERB_PA_DATA_LIST * ReplyPaData,
  2078. OUT PKERB_EXT_ERROR pExtendedError,
  2079. OUT OPTIONAL PS4U_DELEGATION_INFO* S4UDelegationInfo
  2080. )
  2081. {
  2082. KERBERR KerbErr = KDC_ERR_NONE;
  2083. UNICODE_STRING LocalServiceName;
  2084. UNICODE_STRING ServiceRealm = {0};
  2085. UNICODE_STRING ClientRealm = {0};
  2086. BOOLEAN Referral = FALSE;
  2087. KERB_ENCRYPTED_TICKET EncryptedTicket = {0};
  2088. PKERB_ENCRYPTED_TICKET OutputEncryptedTicket = NULL;
  2089. PKERB_ENCRYPTED_TICKET SourceEncryptPart = NULL;
  2090. PKERB_INTERNAL_NAME TargetPrincipal = ServiceName;
  2091. KERB_TICKET NewTicket = {0};
  2092. PKERB_ENCRYPTION_KEY pKeyToUse = NULL;
  2093. PKERB_ENCRYPTION_KEY OldServerKey;
  2094. KDC_TICKET_INFO OldServiceTicketInfo = {0};
  2095. SID_AND_ATTRIBUTES_LIST S4UClientGroupMembership = {0};
  2096. PUSER_INTERNAL6_INFORMATION S4UClientUserInfo = NULL;
  2097. BOOLEAN bRestrictUserAccounts = LsaINoMoreWin2KDomain() && (TicketEncryptionKey ? FALSE : TRUE);
  2098. PUSER_INTERNAL6_INFORMATION LocalUserInfo = NULL;
  2099. ULONG NameFlags = KDC_NAME_FOLLOW_REFERRALS | KDC_NAME_CHECK_GC;
  2100. ULONG KdcOptions = 0;
  2101. BOOLEAN GetInitialS4UPac = FALSE;
  2102. PKERB_ENCRYPTION_KEY pServerKeyLocal = NULL;
  2103. ULONG CommonEType = KERB_ETYPE_DEFAULT;
  2104. TRACE(KDC, I_GetTGSTicket, DEB_FUNCTION);
  2105. //
  2106. // Store away the encrypted ticket from the output ticket to
  2107. // assign it at the end.
  2108. //
  2109. SourceEncryptPart = (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  2110. OutputEncryptedTicket = (PKERB_ENCRYPTED_TICKET) Ticket->encrypted_part.cipher_text.value;
  2111. NewTicket.encrypted_part.cipher_text.value = (PUCHAR) &EncryptedTicket;
  2112. KerbErr = KerbConvertRealmToUnicodeString(
  2113. &ClientRealm,
  2114. &SourceEncryptPart->client_realm
  2115. );
  2116. if (!KERB_SUCCESS( KerbErr ))
  2117. {
  2118. goto Cleanup;
  2119. }
  2120. //
  2121. // Copy the space for flags from the real destination.
  2122. //
  2123. EncryptedTicket.flags = OutputEncryptedTicket->flags;
  2124. LocalServiceName.Buffer = NULL;
  2125. D_DebugLog((DEB_T_PAPI, "I_GetTGSTicket [entering] trying to build a new ticket\n"));
  2126. D_KerbPrintKdcName((DEB_T_PAPI, ServiceName));
  2127. KdcOptions = KerbConvertFlagsToUlong( &RequestBody->kdc_options );
  2128. if (KdcOptions & (KERB_KDC_OPTIONS_unused7 |
  2129. KERB_KDC_OPTIONS_reserved |
  2130. KERB_KDC_OPTIONS_unused9) )
  2131. {
  2132. DebugLog(( DEB_ERROR,"KLIN(%x) Bad options in TGS request: 0x%x\n",
  2133. KLIN(FILENO, __LINE__), KdcOptions ));
  2134. KerbErr = KDC_ERR_BADOPTION;
  2135. goto Cleanup;
  2136. }
  2137. //
  2138. // See if we're getting a service ticket to a UPN, and alter name flags accordingly.
  2139. //
  2140. //
  2141. // KRB_NT_SRV_HST - This is a host/server name -
  2142. //
  2143. // KRB_NT_ENTERPRISE_PRINCIPAL - UPN, a user principal is calling s4uself, or using a UPN as a target.
  2144. //
  2145. NameFlags |= ((ServiceName->NameType == KRB_NT_ENTERPRISE_PRINCIPAL) ? KDC_NAME_UPN_TARGET : KDC_NAME_SERVER);
  2146. //
  2147. // Verify this account is allowed to issue tickets.
  2148. //
  2149. if ((ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&
  2150. ((ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0))
  2151. {
  2152. D_DebugLog((DEB_ERROR,"Trying to make a TGS request with a ticket to %wZ\n",
  2153. &ServiceTicketInfo->AccountName ));
  2154. KerbErr = KRB_AP_ERR_NOT_US;
  2155. goto Cleanup;
  2156. }
  2157. //
  2158. // Copy the ticket info into the old structure. It will be replaced with
  2159. // new info from Normalize.
  2160. //
  2161. OldServiceTicketInfo = *ServiceTicketInfo;
  2162. RtlZeroMemory(
  2163. ServiceTicketInfo,
  2164. sizeof(KDC_TICKET_INFO)
  2165. );
  2166. D_DebugLog((DEB_T_U2U, "I_GetTGSTicket requesting u2u? %s\n", KdcOptions & KERB_KDC_OPTIONS_enc_tkt_in_skey ? "TRUE" : "FALSE"));
  2167. KerbErr = KdcNormalize(
  2168. TargetPrincipal,
  2169. NULL,
  2170. RequestRealm,
  2171. &ClientRealm,
  2172. NameFlags,
  2173. bRestrictUserAccounts, // restrict user accounts (user2user)
  2174. &Referral,
  2175. &ServiceRealm,
  2176. ServiceTicketInfo,
  2177. pExtendedError,
  2178. NULL, // no user handle
  2179. USER_ALL_SECURITYDESCRIPTOR, // for KerbPerformTgsAccessCheck
  2180. bRestrictUserAccounts ? USER_EXTENDED_FIELD_SPN : 0,
  2181. &LocalUserInfo,
  2182. NULL
  2183. );
  2184. if (!KERB_SUCCESS(KerbErr))
  2185. {
  2186. DebugLog((DEB_WARN, "KLIN(%x) failed to normalize %#x, ServiceName ", KLIN(FILENO, __LINE__), KerbErr));
  2187. KerbPrintKdcName(DEB_WARN, ServiceName);
  2188. goto Cleanup;
  2189. }
  2190. if (ServiceTicketInfo != NULL)
  2191. {
  2192. //
  2193. // If a service account is marked as disabled, try NTLM. This
  2194. // prevents a large number of problems where the presense of a disabled
  2195. // computer account in our domain ends up hosing authentication to
  2196. // the "moved" or identical computer account in another forest.
  2197. //
  2198. if ((ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&
  2199. (ServiceTicketInfo->UserAccountControl & USER_ACCOUNT_DISABLED) != 0)
  2200. {
  2201. KerbErr = KDC_ERR_S_PRINCIPAL_UNKNOWN;
  2202. D_DebugLog((DEB_WARN, "KLIN(%x) Failed to normalize, account is disabled ",
  2203. KLIN(FILENO, __LINE__)));
  2204. FILL_EXT_ERROR_EX(pExtendedError, STATUS_ACCOUNT_DISABLED, FILENO, __LINE__);
  2205. goto Cleanup;
  2206. }
  2207. }
  2208. //
  2209. // S4UToSelf
  2210. //
  2211. // If the client name is in our realm, verify client
  2212. // identity and build the PAC for the client. Also make sure
  2213. // the requestor is actually asking for a service ticket to himself,
  2214. // and not some other arbitrary service.
  2215. //
  2216. if (( S4UTicketInfo->Flags & TI_S4USELF_INFO ) != 0)
  2217. {
  2218. if (Referral)
  2219. {
  2220. if ((S4UTicketInfo->Flags & TI_REQUESTOR_THIS_REALM) != 0)
  2221. {
  2222. //
  2223. // The TGT's client is from this realm, but we're referring.
  2224. // The target's not in the same realm as the requesting service
  2225. // indicating an attempt to bypass the protocol.
  2226. //
  2227. DebugLog((DEB_ERROR, "S4USelf requestor realm != service realm\n"));
  2228. DebugLog((DEB_ERROR, "TGT - %wZ\n", S4UTicketInfo->RequestorServiceRealm));
  2229. DebugLog((DEB_ERROR, "Service Realm - %wZ\n", &ServiceRealm));
  2230. DsysAssert(FALSE);
  2231. KerbErr = KRB_AP_ERR_BADMATCH;
  2232. goto Cleanup;
  2233. }
  2234. }
  2235. else
  2236. {
  2237. S4UTicketInfo->Flags |= TI_TARGET_OUR_REALM;
  2238. //
  2239. // The client of the TGT and the SPN are in the same realm. Make
  2240. // sure they're the same account.
  2241. //
  2242. if ((S4UTicketInfo->Flags & TI_REQUESTOR_THIS_REALM) != 0)
  2243. {
  2244. if (S4UTicketInfo->RequestorTicketInfo.UserId != ServiceTicketInfo->UserId)
  2245. {
  2246. DebugLog((DEB_ERROR, "S4U requestor != target SPN\n"));
  2247. DebugLog((DEB_ERROR, "Requestor %p, Target %p\n", &S4UTicketInfo->RequestorTicketInfo, &ServiceTicketInfo));
  2248. DsysAssert(FALSE);
  2249. KerbErr = KRB_AP_ERR_BADMATCH;
  2250. goto Cleanup;
  2251. }
  2252. }
  2253. else
  2254. {
  2255. //
  2256. // The TGTs client is from another realm, but the SPN's in this one
  2257. // fail - someone's tinkering w/ the protocol.
  2258. //
  2259. DebugLog((DEB_ERROR, "S4USelf requestor realm != service realm\n"));
  2260. DebugLog((DEB_ERROR, "TGT - %wZ\n", S4UTicketInfo->RequestorServiceRealm));
  2261. DebugLog((DEB_ERROR, "Service Realm - %wZ\n", &ServiceRealm));
  2262. DsysAssert(FALSE);
  2263. KerbErr = KRB_AP_ERR_BADMATCH;
  2264. goto Cleanup;
  2265. }
  2266. }
  2267. //
  2268. // If we're requesting S4USelf at the client realm, then
  2269. // we'll need to generate a PAC for that client.
  2270. //
  2271. if (SecData.IsOurRealm(&S4UTicketInfo->PACCRealm))
  2272. {
  2273. //
  2274. // Normalize the client name, and get the info we need to
  2275. // generate a PAC.
  2276. //
  2277. KerbErr = KdcGetS4UTicketInfo(
  2278. S4UTicketInfo,
  2279. &OldServiceTicketInfo, // tgt's account info.
  2280. &S4UClientUserInfo,
  2281. &S4UClientGroupMembership,
  2282. pExtendedError
  2283. );
  2284. if (!KERB_SUCCESS(KerbErr))
  2285. {
  2286. DebugLog((DEB_ERROR, "KdcGetS4UTicketINfo failed - %x\n", KerbErr));
  2287. goto Cleanup;
  2288. }
  2289. GetInitialS4UPac = TRUE;
  2290. }
  2291. }
  2292. //
  2293. // We're doing S4UProxy. Make sure the target service account is in
  2294. // our realm. This is for .Net only, and we expect a xrealm sol'n
  2295. // in the Longhorn release.
  2296. //
  2297. if ((S4UTicketInfo->Flags & TI_S4UPROXY_INFO ) != 0)
  2298. {
  2299. if ( Referral )
  2300. {
  2301. DebugLog((DEB_ERROR, "Trying to do S4UProxy to another realm %wZ\n", &ServiceRealm ));
  2302. FILL_EXT_ERROR_EX2(pExtendedError, STATUS_CROSSREALM_DELEGATION_FAILURE, FILENO, __LINE__);
  2303. KerbErr = KDC_ERR_POLICY;
  2304. goto Cleanup;
  2305. }
  2306. S4UTicketInfo->Flags |= TI_TARGET_OUR_REALM;
  2307. }
  2308. else if ( !Referral &&
  2309. LocalUserInfo &&
  2310. LocalUserInfo->I1.SecurityDescriptor.SecurityDescriptor &&
  2311. LsaINoMoreWin2KDomain() &&
  2312. ( ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT ) == 0 )
  2313. {
  2314. KERB_ENCRYPTED_TICKET * ETicket = (PKERB_ENCRYPTED_TICKET)SourceTicket->encrypted_part.cipher_text.value;
  2315. if ( ETicket->bit_mask & KERB_ENCRYPTED_TICKET_authorization_data_present )
  2316. {
  2317. NTSTATUS Status = STATUS_SUCCESS;
  2318. //
  2319. // If there is no authorization data, no access check is possible
  2320. //
  2321. KerbErr = KerbPerformTgsAccessCheck(
  2322. &OldServiceTicketInfo,
  2323. LocalUserInfo->I1.SecurityDescriptor.SecurityDescriptor,
  2324. ETicket,
  2325. SourceTicket->encrypted_part.encryption_type,
  2326. &Status
  2327. );
  2328. if ( !KERB_SUCCESS( KerbErr ))
  2329. {
  2330. if ( KerbErr == KDC_ERR_POLICY &&
  2331. ( Status == STATUS_AUTHENTICATION_FIREWALL_FAILED ||
  2332. Status == STATUS_DOMAIN_TRUST_INCONSISTENT ))
  2333. {
  2334. FILL_EXT_ERROR_EX2( pExtendedError, Status, FILENO, __LINE__ );
  2335. }
  2336. goto Cleanup;
  2337. }
  2338. }
  2339. }
  2340. //
  2341. // Find the supported crypt system.
  2342. //
  2343. KerbErr = KerbFindCommonCryptSystemForSKey(
  2344. RequestBody->encryption_type,
  2345. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  2346. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  2347. &CommonEType
  2348. );
  2349. if (!KERB_SUCCESS(KerbErr))
  2350. {
  2351. if (KDC_ERR_ETYPE_NOTSUPP == KerbErr)
  2352. {
  2353. KdcReportKeyError(
  2354. ClientStringName,
  2355. ServerStringName,
  2356. KDC_KEY_ID_TGS_SKEY,
  2357. KDCEVENT_NO_KEY_INTERSECTION_TGS,
  2358. RequestBody->encryption_type,
  2359. ServiceTicketInfo
  2360. );
  2361. }
  2362. DebugLog((DEB_ERROR, "KLIN(%x) failed to find common ETYPE: %#x\n", KLIN(FILENO, __LINE__), KerbErr));
  2363. goto Cleanup;
  2364. }
  2365. //
  2366. // If this isn't an interdomain trust account, go ahead and issue a normal
  2367. // ticket.
  2368. //
  2369. if ((ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0)
  2370. {
  2371. //
  2372. // Find the common crypt system.
  2373. //
  2374. KerbErr = KerbFindCommonCryptSystem(
  2375. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  2376. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  2377. ServiceTicketInfo->Passwords,
  2378. NULL,
  2379. &pServerKeyLocal
  2380. );
  2381. if (!KERB_SUCCESS(KerbErr))
  2382. {
  2383. if (KDC_ERR_ETYPE_NOTSUPP == KerbErr)
  2384. {
  2385. KdcReportKeyError(
  2386. ClientStringName,
  2387. ServerStringName,
  2388. KDC_KEY_ID_TGS_TICKET,
  2389. KDCEVENT_NO_KEY_INTERSECTION_TGS,
  2390. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  2391. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  2392. ServiceTicketInfo
  2393. );
  2394. }
  2395. DebugLog((DEB_ERROR, "KLIN(%x) failed to find common ETYPE: %#x\n", KLIN(FILENO, __LINE__), KerbErr));
  2396. goto Cleanup;
  2397. }
  2398. //
  2399. // Check whether service is interactive, 'cause you can't
  2400. // get a ticket to an interactive service.
  2401. //
  2402. KerbErr = BuildTicketTGS(
  2403. ServiceTicketInfo,
  2404. RequestBody,
  2405. SourceTicket,
  2406. Referral,
  2407. S4UTicketInfo,
  2408. CommonEType,
  2409. &NewTicket,
  2410. pExtendedError
  2411. );
  2412. if (!KERB_SUCCESS(KerbErr))
  2413. {
  2414. D_DebugLog((DEB_ERROR,"KLIN(%x) Failed to build TGS ticket for %wZ : 0x%x\n",
  2415. KLIN(FILENO, __LINE__), &LocalServiceName, KerbErr ));
  2416. goto Cleanup;
  2417. }
  2418. }
  2419. else
  2420. {
  2421. //
  2422. // Need to build a referal ticket.
  2423. //
  2424. D_DebugLog(( DEB_T_TICKETS, "GetTGSTicket: referring to domain '%wZ'\n",
  2425. &ServiceTicketInfo->AccountName ));
  2426. //
  2427. // Verify that if the trust is not transitive, the client is from
  2428. // this realm.
  2429. // Also verify that if we came in through a non - transitive trust,
  2430. // we don't allow a referral.
  2431. //
  2432. SourceEncryptPart =(PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value;
  2433. if (( ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT ) &&
  2434. (( ServiceTicketInfo->fTicketOpts & AUTH_REQ_TRANSITIVE_TRUST ) == 0))
  2435. {
  2436. if (!SecData.IsOurRealm(&SourceEncryptPart->client_realm))
  2437. {
  2438. //
  2439. // One special case here, for S4U. Allow the hop back to our
  2440. // trusting realm.
  2441. //
  2442. if ((S4UTicketInfo->Flags & TI_S4USELF_INFO) != 0)
  2443. {
  2444. if (!RtlEqualUnicodeString(&ClientRealm, &ServiceTicketInfo->AccountName, TRUE ))
  2445. {
  2446. DebugLog((DEB_WARN,"S4U Client from realm %s attempted to access non transitve trust to %wZ : illegal\n",
  2447. SourceEncryptPart->client_realm,
  2448. &ServiceTicketInfo->AccountName
  2449. ));
  2450. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  2451. }
  2452. }
  2453. else
  2454. {
  2455. DebugLog((DEB_WARN,"Client from realm %s attempted to access non transitve trust to %wZ : illegal\n",
  2456. SourceEncryptPart->client_realm,
  2457. &ServiceTicketInfo->AccountName
  2458. ));
  2459. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  2460. }
  2461. }
  2462. }
  2463. //
  2464. // Verify that the trust for the client is transitive as well, if it isn't
  2465. // from this domain. This means that if the source ticket trust isn't
  2466. // transitive, then this ticket can't be used to get further
  2467. // tgt's, in any realm.
  2468. //
  2469. // e.g. the TGT from client comes from a domain w/ which we don't
  2470. // have transitive trust.
  2471. //
  2472. if (((OldServiceTicketInfo.fTicketOpts & AUTH_REQ_TRANSITIVE_TRUST) == 0) &&
  2473. (OldServiceTicketInfo.UserId != DOMAIN_USER_RID_KRBTGT))
  2474. {
  2475. if ((S4UTicketInfo->Flags & TI_S4USELF_INFO) != 0)
  2476. {
  2477. if (!RtlEqualUnicodeString(&ClientRealm, &OldServiceTicketInfo.AccountName, TRUE ))
  2478. {
  2479. DebugLog((DEB_WARN,"TGT S4U Client from realm %s attempted to access non transitve trust to %wZ : illegal\n",
  2480. SourceEncryptPart->client_realm,
  2481. &OldServiceTicketInfo.AccountName
  2482. ));
  2483. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  2484. }
  2485. }
  2486. else
  2487. {
  2488. DebugLog((DEB_WARN,"TGT Client from realm %s attempted to access non transitve trust to %wZ : illegal\n",
  2489. SourceEncryptPart->client_realm,
  2490. &OldServiceTicketInfo.AccountName
  2491. ));
  2492. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  2493. }
  2494. }
  2495. //
  2496. // This is probably not a common error, but could
  2497. // indicate a configuration problem, so log an explicit
  2498. // error. See bug 87879.
  2499. //
  2500. if (KerbErr == KDC_ERR_PATH_NOT_ACCEPTED)
  2501. {
  2502. if (ClientRealm.Buffer != NULL )
  2503. {
  2504. ReportServiceEvent(
  2505. EVENTLOG_ERROR_TYPE,
  2506. KDCEVENT_FAILED_TRANSITIVE_TRUST,
  2507. 0, // no raw data
  2508. NULL, // no raw data
  2509. 2, // number of strings
  2510. ClientRealm.Buffer,
  2511. ServiceTicketInfo->AccountName.Buffer
  2512. );
  2513. }
  2514. KerbErr = KDC_ERR_PATH_NOT_ACCEPTED;
  2515. goto Cleanup;
  2516. }
  2517. //
  2518. // Find the preferred crypt system
  2519. //
  2520. KerbErr = KerbFindCommonCryptSystem(
  2521. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  2522. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  2523. ServiceTicketInfo->Passwords,
  2524. NULL,
  2525. &pServerKeyLocal
  2526. );
  2527. if (!KERB_SUCCESS(KerbErr))
  2528. {
  2529. if (KDC_ERR_ETYPE_NOTSUPP == KerbErr)
  2530. {
  2531. KdcReportKeyError(
  2532. ClientStringName,
  2533. ServerStringName,
  2534. KDC_KEY_ID_TGS_REFERAL_TICKET,
  2535. KDCEVENT_NO_KEY_INTERSECTION_TGS,
  2536. ServiceTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY ?
  2537. kdc_pMitPrincipalPreferredCryptList : kdc_pPreferredCryptList,
  2538. ServiceTicketInfo
  2539. );
  2540. }
  2541. DebugLog((DEB_ERROR, "KLIN(%x) failed to find common ETYPE: 0x%x\n", KLIN(FILENO, __LINE__), KerbErr));
  2542. goto Cleanup;
  2543. }
  2544. KerbErr = BuildTicketTGS(
  2545. ServiceTicketInfo,
  2546. RequestBody,
  2547. SourceTicket,
  2548. TRUE,
  2549. S4UTicketInfo,
  2550. CommonEType,
  2551. &NewTicket,
  2552. pExtendedError
  2553. );
  2554. if (!KERB_SUCCESS(KerbErr))
  2555. {
  2556. D_DebugLog((DEB_ERROR, "KLIN(%x) Failed to build TGS ticket for %wZ : 0x%x\n", KLIN(FILENO, __LINE__), &ServiceTicketInfo->AccountName, KerbErr));
  2557. goto Cleanup;
  2558. }
  2559. //
  2560. // If this is a referral/canonicaliztion, return the target realm
  2561. //
  2562. if (Referral && ((KdcOptions & KERB_KDC_OPTIONS_name_canonicalize) != 0))
  2563. {
  2564. D_DebugLog((DEB_TRACE,"Building referral info for realm %wZ\n",
  2565. &ServiceRealm ));
  2566. KerbErr = KdcBuildReferralInfo(
  2567. &ServiceRealm,
  2568. ReplyPaData
  2569. );
  2570. if (!KERB_SUCCESS(KerbErr))
  2571. {
  2572. goto Cleanup;
  2573. }
  2574. }
  2575. }
  2576. //
  2577. // Here we're selecting a key with which to validate the PAC checksum
  2578. // before we copy it from the TGT (or evidence ticket) into the new
  2579. // service ticket or cross realm tgt.
  2580. //
  2581. //
  2582. // 3 choices -
  2583. //
  2584. // 1. U2U uses the session key in the accompanying addt'l ticket.
  2585. //
  2586. // 2. S4UProxy uses the requestor's key if we're the requestor's kdc (e.g.
  2587. // the first request of s4uproxy). Otherwise, it's just the xrealm
  2588. // krbtgt key.
  2589. //
  2590. // 3. Everything elses uses the krbtgt key, as the tgt's PAC is only
  2591. // signed w/ that key.
  2592. //
  2593. if (( S4UTicketInfo->Flags & TI_PRXY_REQUESTOR_THIS_REALM ) != 0)
  2594. {
  2595. D_DebugLog((DEB_T_KEY, "I_GetTGSTicket s4u prxy OldServerKey\n"));
  2596. OldServerKey = &S4UTicketInfo->EvidenceTicketKey;
  2597. }
  2598. else
  2599. {
  2600. D_DebugLog((DEB_T_KEY, "I_GetTGSTicket OldServiceTicketInfo OldServerKey\n"));
  2601. OldServerKey = KerbGetKeyFromList(
  2602. OldServiceTicketInfo.Passwords,
  2603. SourceTicket->encrypted_part.encryption_type
  2604. );
  2605. }
  2606. DsysAssert(OldServerKey != NULL);
  2607. if (OldServerKey == NULL)
  2608. {
  2609. KerbErr = KRB_ERR_GENERIC;
  2610. goto Cleanup;
  2611. }
  2612. if (ARGUMENT_PRESENT(TicketEncryptionKey))
  2613. {
  2614. pKeyToUse = TicketEncryptionKey;
  2615. DebugLog((DEB_T_U2U, "I_GetTGSTicket signing PAC with u2u session key\n"));
  2616. }
  2617. else
  2618. {
  2619. DebugLog((DEB_T_KEY, "I_GetTGSTicket signing PAC with server key\n"));
  2620. pKeyToUse = pServerKeyLocal;
  2621. }
  2622. //
  2623. // Insert the auth data into the new ticket.
  2624. //
  2625. if ( GetInitialS4UPac )
  2626. {
  2627. KerbErr = KdcInsertInitialS4UAuthorizationData(
  2628. &EncryptedTicket,
  2629. pExtendedError,
  2630. S4UTicketInfo,
  2631. S4UClientUserInfo,
  2632. &S4UClientGroupMembership,
  2633. ((ServiceTicketInfo->UserId != DOMAIN_USER_RID_KRBTGT) &&
  2634. ((ServiceTicketInfo->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) == 0)),
  2635. pKeyToUse
  2636. );
  2637. }
  2638. else
  2639. {
  2640. KerbErr = KdcInsertAuthorizationData(
  2641. &EncryptedTicket,
  2642. pExtendedError,
  2643. (RequestBody->bit_mask & enc_authorization_data_present) ?
  2644. &RequestBody->enc_authorization_data : NULL,
  2645. (PKERB_ENCRYPTED_TICKET) SourceTicket->encrypted_part.cipher_text.value,
  2646. ServiceTicketInfo, // Ticket info for the target service
  2647. S4UTicketInfo,
  2648. &OldServiceTicketInfo, // krbtgt account used in TGS_REQ (could be cross realm).
  2649. OldServerKey,
  2650. pKeyToUse,
  2651. Subkey,
  2652. S4UDelegationInfo
  2653. );
  2654. }
  2655. if (!KERB_SUCCESS(KerbErr))
  2656. {
  2657. DebugLog((DEB_ERROR, "KLIN(%x) Failed to insert authorization data: 0x%x\n", KLIN(FILENO, __LINE__), KerbErr));
  2658. goto Cleanup;
  2659. }
  2660. KerbErr = KerbDuplicateKey(pServerKey, pKeyToUse);
  2661. if (!KERB_SUCCESS(KerbErr))
  2662. {
  2663. DebugLog((DEB_ERROR, "KLIN(%x) Failed to insert duplicate key: 0x%x\n", KLIN(FILENO, __LINE__), KerbErr));
  2664. goto Cleanup;
  2665. }
  2666. #ifdef ROGUE_DC
  2667. KerbErr = KdcInstrumentRogueCrealm(
  2668. &EncryptedTicket
  2669. );
  2670. if (!KERB_SUCCESS(KerbErr))
  2671. {
  2672. DebugLog((DEB_ERROR, "KLIN(%x) Failed to instrument a rogue crealm: 0x%x\n", KLIN(FILENO, __LINE__), KerbErr));
  2673. KerbErr = KDC_ERR_NONE;
  2674. }
  2675. #endif
  2676. *Ticket = NewTicket;
  2677. *OutputEncryptedTicket = EncryptedTicket;
  2678. Ticket->encrypted_part.cipher_text.value = (PUCHAR) OutputEncryptedTicket;
  2679. Cleanup:
  2680. //
  2681. // Now free the original service ticket info (which was for the KDC) so
  2682. // we can get it for the real service
  2683. //
  2684. FreeTicketInfo(
  2685. &OldServiceTicketInfo
  2686. );
  2687. SamIFreeSidAndAttributesList(&S4UClientGroupMembership);
  2688. SamIFree_UserInternal6Information( S4UClientUserInfo );
  2689. SamIFree_UserInternal6Information( LocalUserInfo );
  2690. if (!KERB_SUCCESS(KerbErr))
  2691. {
  2692. KdcFreeInternalTicket(
  2693. &NewTicket
  2694. );
  2695. }
  2696. KerbFreeString(
  2697. &ServiceRealm
  2698. );
  2699. KerbFreeString(
  2700. &ClientRealm
  2701. );
  2702. D_DebugLog((DEB_T_PAPI, "I_GetTGSTicket returning %#x\n", KerbErr));
  2703. return (KerbErr);
  2704. }
  2705. //+-------------------------------------------------------------------------
  2706. //
  2707. // Function: KerbCheckA2D2Attribute
  2708. //
  2709. // Synopsis: Helper to validate the info in the A2D2 list given
  2710. // our target.
  2711. //
  2712. // Effects: allocate output ticket
  2713. //
  2714. // Arguments:
  2715. //
  2716. // Requires:
  2717. //
  2718. // Returns:
  2719. //
  2720. // Notes: there can only be one additional ticket
  2721. //
  2722. //
  2723. //--------------------------------------------------------------------------
  2724. KERBERR
  2725. KerbCheckA2D2Attribute(
  2726. IN PUSER_INTERNAL6_INFORMATION UserInternal6,
  2727. IN PUNICODE_STRING TargetToMatch,
  2728. IN PKERB_EXT_ERROR ExtendedError
  2729. )
  2730. {
  2731. KERBERR Kerberr = KDC_ERR_BADOPTION;
  2732. if (( UserInternal6->A2D2List == NULL ) ||
  2733. ( UserInternal6->A2D2List->NumSPNs == 0 ))
  2734. {
  2735. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NOT_SUPPORTED, FILENO, __LINE__ );
  2736. return Kerberr;
  2737. }
  2738. for (ULONG i = 0; i < UserInternal6->A2D2List->NumSPNs; i++)
  2739. {
  2740. if (RtlEqualUnicodeString(
  2741. &(UserInternal6->A2D2List->SPNList[i]),
  2742. TargetToMatch,
  2743. TRUE
  2744. ))
  2745. {
  2746. Kerberr = KDC_ERR_NONE;
  2747. break;
  2748. }
  2749. }
  2750. //
  2751. // We have a list, but this target name isn't in there.
  2752. // Return error to indicate such, but server is still allowed S4U,
  2753. // just not for this target.
  2754. //
  2755. if (!KERB_SUCCESS(Kerberr))
  2756. {
  2757. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NO_MATCH, FILENO, __LINE__ );
  2758. }
  2759. return Kerberr;
  2760. }
  2761. //+-------------------------------------------------------------------------
  2762. //
  2763. // Function: KerbUnpackAdditionalTickets
  2764. //
  2765. // Synopsis: Unpacks the AdditionalTickets field of a KDC request
  2766. // and (a) verifies that the ticket is TGT for this realm
  2767. // and (b) the ticket is encrypted with the corret key and
  2768. // (c) the ticket is valid
  2769. //
  2770. // Also checks for s4uproxy requests, and validates them.
  2771. //
  2772. // Effects:
  2773. //
  2774. // Arguments: TicketList - from addt'l tickets field of tgs_req
  2775. // KdcOptions - request options.
  2776. // TargetServer - spn being asked for.
  2777. // SourceCName - client name from tgt
  2778. // SourceCRealm - client realm from tgt
  2779. // SourceKey - session key from tgt.
  2780. // u2uticketinfo - out param for u2u options.
  2781. // s4uticketinfo - out param for s4uproxy option.
  2782. // ExtendedError - out param for returning e_data.
  2783. //
  2784. // Requires:
  2785. //
  2786. // Returns:
  2787. //
  2788. // Notes:
  2789. //
  2790. //
  2791. //--------------------------------------------------------------------------
  2792. KERBERR
  2793. KdcUnpackAdditionalTickets(
  2794. IN PKERB_TICKET_LIST TicketList,
  2795. IN ULONG KdcOptions,
  2796. IN PUNICODE_STRING TargetName,
  2797. IN PKERB_INTERNAL_NAME SourceCName,
  2798. IN PUNICODE_STRING SourceCRealm,
  2799. IN PKERB_ENCRYPTION_KEY SourceKey,
  2800. OUT PKDC_U2U_TICKET_INFO U2UTicketInfo,
  2801. OUT PKDC_S4U_TICKET_INFO S4UTicketInfo,
  2802. OUT PKERB_EXT_ERROR ExtendedError
  2803. )
  2804. {
  2805. KERBERR KerbErr = KDC_ERR_NONE;
  2806. PKERB_ENCRYPTED_TICKET EncryptedTicket = NULL;
  2807. PKERB_ENCRYPTION_KEY EncryptionKey = NULL;
  2808. PKERB_TICKET Ticket = NULL;
  2809. UNICODE_STRING CrackedRealm = {0};
  2810. BOOLEAN Referral = FALSE;
  2811. KDC_TICKET_INFO KrbtgtTicketInfo = {0};
  2812. KDC_TICKET_INFO RequestorTicketInfo = {0};
  2813. KERB_REALM LocalRealm;
  2814. ULONG OptionCount = 0;
  2815. ULONG TicketCount = 1;
  2816. ULONG TicketFlags;
  2817. PUSER_INTERNAL6_INFORMATION RequesterUserInfo = NULL;
  2818. if ( TicketList == NULL )
  2819. {
  2820. D_DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets KLIN(%x) Trying to unpack null ticket or more than one ticket\n", KLIN(FILENO, __LINE__)));
  2821. KerbErr = KRB_ERR_GENERIC;
  2822. goto Cleanup;
  2823. }
  2824. else if ((KdcOptions & (KERB_KDC_OPTIONS_cname_in_addl_tkt | KERB_KDC_OPTIONS_enc_tkt_in_skey)) == 0)
  2825. {
  2826. D_DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets additional tickets present, but no options\n"));
  2827. KerbErr = KDC_ERR_BADOPTION;
  2828. goto Cleanup;
  2829. }
  2830. Ticket = &TicketList->value;
  2831. LocalRealm = SecData.KdcKerbDnsRealmName();
  2832. //
  2833. // U2U request - additional ticket contains TGT w/ session
  2834. // key we want to encrypt the final ticket with.
  2835. //
  2836. if ((KdcOptions & KERB_KDC_OPTIONS_enc_tkt_in_skey) != 0)
  2837. {
  2838. D_DebugLog((DEB_T_U2U, "KdcUnpackAdditionalTickets unpacking u2u tgt ticket\n"));
  2839. UNICODE_STRING ServerNames[3];
  2840. OptionCount++;
  2841. KerbErr = SecData.GetKrbtgtTicketInfo(&KrbtgtTicketInfo);
  2842. if (!KERB_SUCCESS(KerbErr))
  2843. {
  2844. goto Cleanup;
  2845. }
  2846. //
  2847. // Verify the ticket, first with the normal password list
  2848. //
  2849. ServerNames[0] = *SecData.KdcFullServiceKdcName();
  2850. ServerNames[1] = *SecData.KdcFullServiceDnsName();
  2851. ServerNames[2] = *SecData.KdcFullServiceName();
  2852. EncryptionKey = KerbGetKeyFromList(
  2853. KrbtgtTicketInfo.Passwords,
  2854. Ticket->encrypted_part.encryption_type
  2855. );
  2856. if (EncryptionKey == NULL)
  2857. {
  2858. KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  2859. goto Cleanup;
  2860. }
  2861. KerbErr = KerbVerifyTicket(
  2862. Ticket,
  2863. 3, // 3 names
  2864. ServerNames,
  2865. SecData.KdcDnsRealmName(),
  2866. EncryptionKey,
  2867. &SkewTime,
  2868. &EncryptedTicket
  2869. );
  2870. //
  2871. // if it failed due to wrong password, try again with older password
  2872. //
  2873. if ((KerbErr == KRB_AP_ERR_MODIFIED) && (KrbtgtTicketInfo.OldPasswords != NULL))
  2874. {
  2875. EncryptionKey = KerbGetKeyFromList(
  2876. KrbtgtTicketInfo.OldPasswords,
  2877. Ticket->encrypted_part.encryption_type
  2878. );
  2879. if (EncryptionKey == NULL)
  2880. {
  2881. DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets no encryption key found in krbtgt's OldPassword\n"));
  2882. KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  2883. goto Cleanup;
  2884. }
  2885. KerbErr = KerbVerifyTicket(
  2886. &TicketList->value,
  2887. 2, // 2 names
  2888. ServerNames,
  2889. SecData.KdcDnsRealmName(),
  2890. EncryptionKey,
  2891. &SkewTime,
  2892. &EncryptedTicket
  2893. );
  2894. }
  2895. if (!KERB_SUCCESS(KerbErr))
  2896. {
  2897. DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets KLIN(%x) Failed to verify additional ticket: 0x%x\n", KLIN(FILENO, __LINE__),KerbErr));
  2898. goto Cleanup;
  2899. }
  2900. //
  2901. // Verify the realm of the ticket
  2902. //
  2903. if (!KerbCompareRealmNames(
  2904. &LocalRealm,
  2905. &Ticket->realm
  2906. ))
  2907. {
  2908. D_DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets KLIN(%x) Additional ticket realm is wrong: %s instead of %s\n",
  2909. KLIN(FILENO, __LINE__), Ticket->realm, LocalRealm));
  2910. KerbErr = KDC_ERR_POLICY;
  2911. goto Cleanup;
  2912. }
  2913. //
  2914. // Verify the realm of the client is the same as our realm
  2915. //
  2916. if (!KerbCompareRealmNames(
  2917. &LocalRealm,
  2918. &EncryptedTicket->client_realm
  2919. ))
  2920. {
  2921. D_DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets KLIN(%x) Additional ticket client realm is wrong: %s instead of %s\n",
  2922. KLIN(FILENO, __LINE__),EncryptedTicket->client_realm, LocalRealm));
  2923. KerbErr = KDC_ERR_POLICY;
  2924. goto Cleanup;
  2925. }
  2926. //
  2927. // Crack the name in the supplied TGT.
  2928. //
  2929. KerbErr = KerbConvertPrincipalNameToKdcName(
  2930. &U2UTicketInfo->TgtCName,
  2931. &EncryptedTicket->client_name
  2932. );
  2933. if (!KERB_SUCCESS( KerbErr ))
  2934. {
  2935. goto Cleanup;
  2936. }
  2937. KerbErr = KerbConvertRealmToUnicodeString(
  2938. &U2UTicketInfo->TgtCRealm,
  2939. &EncryptedTicket->client_realm
  2940. );
  2941. if (!KERB_SUCCESS( KerbErr ))
  2942. {
  2943. goto Cleanup;
  2944. }
  2945. KerbErr = KdcNormalize(
  2946. U2UTicketInfo->TgtCName,
  2947. &U2UTicketInfo->TgtCRealm,
  2948. &U2UTicketInfo->TgtCRealm,
  2949. NULL,
  2950. KDC_NAME_CLIENT | KDC_NAME_INBOUND,
  2951. FALSE, // do not restrict user accounts (user2user)
  2952. &Referral,
  2953. &CrackedRealm,
  2954. &U2UTicketInfo->TgtTicketInfo,
  2955. ExtendedError,
  2956. NULL, // no user handle
  2957. 0L, // no fields to fetch
  2958. 0L, // no extended fields
  2959. NULL, // no user all
  2960. NULL // no group membership
  2961. );
  2962. KerbFreeString( &CrackedRealm );
  2963. if ( Referral )
  2964. {
  2965. KerbErr = KRB_AP_ERR_BADMATCH;
  2966. }
  2967. if (KERB_SUCCESS(KerbErr))
  2968. {
  2969. U2UTicketInfo->Flags |= TI_CHECK_RID;
  2970. }
  2971. else
  2972. {
  2973. DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets KLIN(%x) Failed to normalize client name from supplied ticket %#x\n",
  2974. KLIN(FILENO, __LINE__), KerbErr));
  2975. KdcFreeU2UTicketInfo(U2UTicketInfo);
  2976. RtlZeroMemory(
  2977. U2UTicketInfo,
  2978. sizeof(KDC_U2U_TICKET_INFO)
  2979. );
  2980. goto Cleanup;
  2981. }
  2982. U2UTicketInfo->Tgt = EncryptedTicket;
  2983. EncryptedTicket = NULL;
  2984. if (TicketList->next != NULL)
  2985. {
  2986. TicketCount++;
  2987. Ticket = &TicketList->next->value;
  2988. }
  2989. U2UTicketInfo->Flags |= ( TI_INITIALIZED | TI_FREETICKET );
  2990. }
  2991. //
  2992. // S4UProxy request
  2993. // Now we've got to crack the additional ticket, find the server name,
  2994. // and crack the account.
  2995. //
  2996. // NOTE: The server must be in our realm to do this. This implies that
  2997. // other KDCs trust us to "do the right thing".
  2998. //
  2999. if ((KdcOptions & KERB_KDC_OPTIONS_cname_in_addl_tkt) != 0)
  3000. {
  3001. D_DebugLog((DEB_TRACE, "KdcUnpackAdditionalTickets unpacking evidence ticket\n"));
  3002. if ( Ticket == NULL )
  3003. {
  3004. D_DebugLog((DEB_ERROR, "s4u set, but no ticket\n"));
  3005. KerbErr = KDC_ERR_BADOPTION;
  3006. goto Cleanup;
  3007. }
  3008. //
  3009. // Can't do this w/o target name..
  3010. //
  3011. if ( TargetName->Buffer == NULL )
  3012. {
  3013. KerbErr = KDC_ERR_BADOPTION;
  3014. goto Cleanup;
  3015. }
  3016. OptionCount++;
  3017. KerbErr = KerbConvertPrincipalNameToKdcName(
  3018. &S4UTicketInfo->RequestorServiceName,
  3019. &Ticket->server_name
  3020. );
  3021. if (!KERB_SUCCESS(KerbErr))
  3022. {
  3023. goto Cleanup;
  3024. }
  3025. KerbErr = KerbConvertRealmToUnicodeString(
  3026. &S4UTicketInfo->RequestorServiceRealm,
  3027. &Ticket->realm
  3028. );
  3029. if (!KERB_SUCCESS( KerbErr ))
  3030. {
  3031. goto Cleanup;
  3032. }
  3033. //
  3034. // If the client of this S4UProxy request (e.g. a server running with
  3035. // an impersonated client context, asking for S4U) has an account in this
  3036. // realm (e.g. the crealm of the TGT == our realm), the accompanying
  3037. // evidence ticket must:
  3038. //
  3039. // 1. Be encrypted in the S4UClient's account key
  3040. // 2. Match the identity in the evidence ticket
  3041. //
  3042. if (SecData.IsOurRealm(SourceCRealm))
  3043. {
  3044. D_DebugLog((DEB_T_TICKETS, "S4U Request -- OUR REALM\n"));
  3045. //
  3046. // First get the TGT holder's userinfo. This is used for checking
  3047. // the A2D2 attribute.
  3048. //
  3049. KerbErr = KdcNormalize(
  3050. SourceCName,
  3051. SourceCRealm,
  3052. SourceCRealm,
  3053. NULL,
  3054. KDC_NAME_CLIENT,
  3055. FALSE, // do not restrict user accounts (user2user)
  3056. &Referral,
  3057. &CrackedRealm,
  3058. &RequestorTicketInfo,
  3059. ExtendedError,
  3060. 0,
  3061. NULL,
  3062. USER_EXTENDED_FIELD_A2D2,
  3063. &RequesterUserInfo,
  3064. NULL
  3065. );
  3066. KerbFreeString( &CrackedRealm );
  3067. if (!KERB_SUCCESS(KerbErr) || Referral )
  3068. {
  3069. D_DebugLog((DEB_ERROR, "Unknown client dt PKERB_INTERNAL_NAME(%p)\n", SourceCName));
  3070. if (KERB_SUCCESS(KerbErr) && Referral)
  3071. {
  3072. KerbErr = KDC_ERR_BADOPTION;
  3073. }
  3074. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NO_MATCH, FILENO, __LINE__ );
  3075. goto Cleanup;
  3076. }
  3077. //
  3078. // Now get the information associated with the evidence ticket.
  3079. //
  3080. KerbErr = KdcNormalize(
  3081. S4UTicketInfo->RequestorServiceName,
  3082. &S4UTicketInfo->RequestorServiceRealm,
  3083. &S4UTicketInfo->RequestorServiceRealm,
  3084. NULL,
  3085. KDC_NAME_SERVER | KDC_NAME_CHECK_GC | KDC_NAME_FOLLOW_REFERRALS,
  3086. FALSE, // do not restrict user accounts (user2user)
  3087. &Referral,
  3088. &CrackedRealm,
  3089. &S4UTicketInfo->RequestorTicketInfo,
  3090. ExtendedError,
  3091. 0,
  3092. NULL,
  3093. 0,
  3094. NULL,
  3095. NULL
  3096. );
  3097. KerbFreeString( &CrackedRealm );
  3098. if ( !KERB_SUCCESS(KerbErr) || Referral )
  3099. {
  3100. D_DebugLog((DEB_ERROR, "Unknown evidence ticket sname (%p)\n", S4UTicketInfo));
  3101. KerbErr = KDC_ERR_BADOPTION;
  3102. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NO_MATCH, FILENO, __LINE__ );
  3103. goto Cleanup;
  3104. }
  3105. //
  3106. // The userids *must* match for the evidence ticket && the
  3107. // TGT. If not, log an event???
  3108. //
  3109. if ( S4UTicketInfo->RequestorTicketInfo.UserId != RequestorTicketInfo.UserId )
  3110. {
  3111. KerbErr = KDC_ERR_BADOPTION;
  3112. D_DebugLog((DEB_ERROR, "User id's don't match (%p) (%p)!\n", &S4UTicketInfo->RequestorTicketInfo, RequestorTicketInfo));
  3113. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NO_MATCH, FILENO, __LINE__ );
  3114. goto Cleanup;
  3115. }
  3116. //
  3117. // Validate the evidence ticket was encrypted w/ the proper key.
  3118. //
  3119. EncryptionKey = KerbGetKeyFromList(
  3120. RequestorTicketInfo.Passwords,
  3121. Ticket->encrypted_part.encryption_type
  3122. );
  3123. if (EncryptionKey == NULL)
  3124. {
  3125. KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  3126. goto Cleanup;
  3127. }
  3128. KerbErr = KerbVerifyTicket(
  3129. Ticket,
  3130. 0,
  3131. NULL,
  3132. SecData.KdcDnsRealmName(),
  3133. EncryptionKey,
  3134. &SkewTime,
  3135. &EncryptedTicket
  3136. );
  3137. if ((KerbErr == KRB_AP_ERR_MODIFIED) &&
  3138. (RequestorTicketInfo.OldPasswords != NULL))
  3139. {
  3140. EncryptionKey = KerbGetKeyFromList(
  3141. RequestorTicketInfo.OldPasswords,
  3142. Ticket->encrypted_part.encryption_type
  3143. );
  3144. if (EncryptionKey == NULL)
  3145. {
  3146. KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  3147. goto Cleanup;
  3148. }
  3149. KerbErr = KerbVerifyTicket(
  3150. Ticket,
  3151. 0,
  3152. NULL,
  3153. SecData.KdcDnsRealmName(),
  3154. EncryptionKey,
  3155. &SkewTime,
  3156. &EncryptedTicket
  3157. );
  3158. }
  3159. if (!KERB_SUCCESS(KerbErr))
  3160. {
  3161. D_DebugLog((DEB_ERROR, "Couldn't decrypt evidence ticket %x\n",KerbErr));
  3162. KerbErr = KDC_ERR_BADOPTION;
  3163. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NO_MATCH, FILENO, __LINE__ );
  3164. goto Cleanup;
  3165. }
  3166. //
  3167. // Check the A2D2 attribute for our name. Also return hints to
  3168. // the server w.r.t. whether they even support S4UProxy protocol
  3169. // using extended errors.
  3170. //
  3171. KerbErr = KerbCheckA2D2Attribute(
  3172. RequesterUserInfo,
  3173. TargetName,
  3174. ExtendedError
  3175. );
  3176. if (!KERB_SUCCESS(KerbErr))
  3177. {
  3178. DebugLog((DEB_ERROR,
  3179. "KdcUnpackAdditionalTickets failed to match %wZ to user %wZ id %#x\n",
  3180. TargetName, &RequesterUserInfo->I1.UserName, RequesterUserInfo->I1.UserId));
  3181. goto Cleanup;
  3182. }
  3183. KerbErr = KerbDuplicateKey(
  3184. &S4UTicketInfo->EvidenceTicketKey,
  3185. EncryptionKey
  3186. );
  3187. if (!KERB_SUCCESS(KerbErr))
  3188. {
  3189. goto Cleanup;
  3190. }
  3191. S4UTicketInfo->Flags |= TI_PRXY_REQUESTOR_THIS_REALM;
  3192. }
  3193. else
  3194. {
  3195. //
  3196. // NOT OUR REALM!
  3197. //
  3198. // cname will == the info in the pac, as will crealm.
  3199. //
  3200. // The evidence ticket and the PAC signature will be generated using
  3201. // the session key in the cross-realm tgt.
  3202. //
  3203. DebugLog((DEB_T_TICKETS, "S4U Request !! NOT OUR REALM/n"));
  3204. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_CROSSREALM_DELEGATION_FAILURE, FILENO, __LINE__ );
  3205. KerbErr = KDC_ERR_POLICY;
  3206. goto Cleanup;
  3207. }
  3208. if (!NT_SUCCESS( KerbDuplicateStringEx(
  3209. &S4UTicketInfo->TargetName,
  3210. TargetName,
  3211. FALSE
  3212. )))
  3213. {
  3214. KerbErr = KRB_ERR_GENERIC;
  3215. goto Cleanup;
  3216. }
  3217. //
  3218. // The ticket *must* be fwdable to be used in S4UProxy.
  3219. //
  3220. TicketFlags = KerbConvertFlagsToUlong( &EncryptedTicket->flags );
  3221. if (( TicketFlags & KERB_TICKET_FLAGS_forwardable ) == 0)
  3222. {
  3223. D_DebugLog((DEB_ERROR, "Non fwdble service ticket presented as S4UPrxy evidence\n"));
  3224. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NO_MATCH, FILENO, __LINE__ );
  3225. KerbErr = KDC_ERR_BADOPTION;
  3226. goto Cleanup;
  3227. }
  3228. //
  3229. // Everything's looking good here. Grab the client name
  3230. // from the ticket, and the client realm. These will be put in
  3231. // the TGS_REP, when we need to.
  3232. //
  3233. KerbErr = KerbConvertPrincipalNameToKdcName(
  3234. &S4UTicketInfo->PACCName,
  3235. &EncryptedTicket->client_name
  3236. );
  3237. if (!KERB_SUCCESS(KerbErr))
  3238. {
  3239. goto Cleanup;
  3240. }
  3241. KerbErr = KerbConvertRealmToUnicodeString(
  3242. &S4UTicketInfo->PACCRealm,
  3243. &EncryptedTicket->client_realm
  3244. );
  3245. if (!KERB_SUCCESS( KerbErr ))
  3246. {
  3247. goto Cleanup;
  3248. }
  3249. //
  3250. // Keep a copy of the ticket, so we can copy over the pac later.
  3251. //
  3252. S4UTicketInfo->EvidenceTicket = EncryptedTicket;
  3253. EncryptedTicket = NULL;
  3254. S4UTicketInfo->Flags |= ( TI_INITIALIZED | TI_S4UPROXY_INFO | TI_FREETICKET );
  3255. }
  3256. //
  3257. // Validate that our options were matched w/ tickets.
  3258. //
  3259. if ( TicketCount != OptionCount )
  3260. {
  3261. D_DebugLog((DEB_ERROR, "Ticket count (%x) != option count (%x)\n", TicketCount, OptionCount));
  3262. FILL_EXT_ERROR_EX2( ExtendedError, STATUS_NO_MATCH, FILENO, __LINE__ );
  3263. KerbErr = KDC_ERR_BADOPTION;
  3264. goto Cleanup;
  3265. }
  3266. Cleanup:
  3267. if (!KERB_SUCCESS( KerbErr ))
  3268. {
  3269. KdcFreeS4UTicketInfo( S4UTicketInfo );
  3270. RtlZeroMemory(
  3271. S4UTicketInfo,
  3272. sizeof(KDC_S4U_TICKET_INFO)
  3273. );
  3274. KdcFreeU2UTicketInfo( U2UTicketInfo );
  3275. RtlZeroMemory(
  3276. U2UTicketInfo,
  3277. sizeof(KDC_U2U_TICKET_INFO)
  3278. );
  3279. }
  3280. SamIFree_UserInternal6Information( RequesterUserInfo );
  3281. if (EncryptedTicket != NULL)
  3282. {
  3283. KerbFreeTicket( EncryptedTicket );
  3284. }
  3285. FreeTicketInfo( &KrbtgtTicketInfo );
  3286. FreeTicketInfo( &RequestorTicketInfo );
  3287. return(KerbErr);
  3288. }
  3289. //--------------------------------------------------------------------
  3290. //
  3291. // Name: KdcFindS4UClientAndRealm
  3292. //
  3293. // Synopsis: Decodes PA DATA to find PA_DATA_FOR_USER entry.
  3294. //
  3295. // Effects: Get a client name and realm for processing S4U request
  3296. //
  3297. // Arguments: PAList - Preauth data list from TGS_REQ
  3298. // ServerKey - Key in authenticator, used to sign PA_DATA.
  3299. // ClientRealm - Target for client realm
  3300. // ClientName - Principal to get S4U ticket for
  3301. //
  3302. // Requires:
  3303. //
  3304. // Returns: KDC_ERR_ or KRB_AP_ERR errors only
  3305. //
  3306. // Notes: Free client name and realm w/
  3307. //
  3308. //
  3309. //--------------------------------------------------------------------------
  3310. KERBERR
  3311. KdcFindS4UClientAndRealm(
  3312. IN PKERB_PA_DATA_LIST PaList,
  3313. IN PKERB_INTERNAL_NAME TargetName,
  3314. IN PKERB_ENCRYPTED_TICKET SourceTicket,
  3315. IN PKERB_ENCRYPTION_KEY SourceTicketKey,
  3316. IN PKERB_INTERNAL_NAME SourceCName,
  3317. IN PUNICODE_STRING SourceCRealm,
  3318. IN OUT PKDC_S4U_TICKET_INFO S4UTicketInfo,
  3319. IN OUT PKERB_EXT_ERROR ExtendedError
  3320. )
  3321. {
  3322. KERBERR Kerberr = KDC_ERR_NONE;
  3323. PKERB_PA_DATA PaData = NULL;
  3324. PKERB_PA_FOR_USER S4URequest = NULL;
  3325. NTSTATUS Status = STATUS_SUCCESS;
  3326. unsigned char Hash[MD5DIGESTLEN];
  3327. KERB_CHECKSUM Checksum;
  3328. BOOLEAN Referral;
  3329. UNICODE_STRING FakeRealm = {0};
  3330. Checksum.checksum.value = Hash;
  3331. PaData = KerbFindPreAuthDataEntry(
  3332. KRB5_PADATA_FOR_USER,
  3333. PaList
  3334. );
  3335. if (NULL == PaData)
  3336. {
  3337. goto Cleanup;
  3338. }
  3339. if (( S4UTicketInfo->Flags & TI_S4UPROXY_INFO ) != 0)
  3340. {
  3341. D_DebugLog((DEB_ERROR, "Trying to mix S4U proxy and self requests\n"));
  3342. Kerberr = KDC_ERR_BADOPTION;
  3343. goto Cleanup;
  3344. }
  3345. Kerberr = KerbUnpackData(
  3346. PaData->preauth_data.value,
  3347. PaData->preauth_data.length,
  3348. KERB_PA_FOR_USER_PDU,
  3349. (PVOID* ) &S4URequest
  3350. );
  3351. if (!KERB_SUCCESS(Kerberr))
  3352. {
  3353. D_DebugLog((DEB_ERROR, "Failed to unpack PA_FOR_USER\n"));
  3354. goto Cleanup;
  3355. }
  3356. Status = KerbHashS4UPreauth(
  3357. S4URequest,
  3358. &SourceTicket->key,
  3359. S4URequest->cksum.checksum_type,
  3360. &Checksum
  3361. );
  3362. if (!NT_SUCCESS(Status))
  3363. {
  3364. D_DebugLog((DEB_ERROR, "Failed to create S4U checksum\n"));
  3365. Kerberr = KRB_AP_ERR_MODIFIED;
  3366. goto Cleanup;
  3367. }
  3368. if (!RtlEqualMemory(
  3369. Checksum.checksum.value,
  3370. S4URequest->cksum.checksum.value,
  3371. Checksum.checksum.length
  3372. ))
  3373. {
  3374. DebugLog((DEB_ERROR, "S4U PA checksum doesn't match!\n"));
  3375. Kerberr = KRB_AP_ERR_MODIFIED;
  3376. goto Cleanup;
  3377. }
  3378. //
  3379. // Get the information on the requestor of the S4UToSelf
  3380. // if its from our realm.
  3381. //
  3382. if (SecData.IsOurRealm(SourceCRealm))
  3383. {
  3384. Kerberr = KdcNormalize(
  3385. SourceCName,
  3386. SourceCRealm,
  3387. SourceCRealm,
  3388. NULL,
  3389. KDC_NAME_CLIENT,
  3390. FALSE,
  3391. &Referral,
  3392. &FakeRealm,
  3393. &S4UTicketInfo->RequestorTicketInfo,
  3394. ExtendedError,
  3395. NULL,
  3396. NULL,
  3397. NULL,
  3398. NULL,
  3399. NULL
  3400. );
  3401. if ( !KERB_SUCCESS( Kerberr) || Referral )
  3402. {
  3403. //
  3404. // Something's wrong here - we don't know about the client
  3405. // of this request, even though the TGTs from our realm.
  3406. //
  3407. D_DebugLog((DEB_ERROR, "Couldn't normalize S4UToSelf requestor\n"));
  3408. Kerberr = KDC_ERR_WRONG_REALM;
  3409. goto Cleanup;
  3410. }
  3411. S4UTicketInfo->Flags |= (TI_REQUESTOR_THIS_REALM | TI_CHECK_RID);
  3412. }
  3413. Kerberr = KerbConvertRealmToUnicodeString(
  3414. &S4UTicketInfo->PACCRealm,
  3415. &S4URequest->userRealm
  3416. );
  3417. if (!KERB_SUCCESS(Kerberr))
  3418. {
  3419. goto Cleanup;
  3420. }
  3421. Kerberr = KerbConvertPrincipalNameToKdcName(
  3422. &S4UTicketInfo->PACCName,
  3423. &S4URequest->userName
  3424. );
  3425. if (!KERB_SUCCESS(Kerberr))
  3426. {
  3427. goto Cleanup;
  3428. }
  3429. Status = KerbDuplicateString(
  3430. &S4UTicketInfo->RequestorServiceRealm,
  3431. SourceCRealm
  3432. );
  3433. if (!NT_SUCCESS(Status))
  3434. {
  3435. Kerberr = KRB_ERR_GENERIC;
  3436. goto Cleanup;
  3437. }
  3438. Status = KerbDuplicateKdcName(
  3439. &S4UTicketInfo->RequestorServiceName,
  3440. SourceCName
  3441. );
  3442. if (!NT_SUCCESS(Status))
  3443. {
  3444. Kerberr = KRB_ERR_GENERIC;
  3445. goto Cleanup;
  3446. }
  3447. //
  3448. // This is the requestor's tgt - save it off for
  3449. // later authz checks.
  3450. //
  3451. S4UTicketInfo->EvidenceTicket = SourceTicket;
  3452. Kerberr = KerbDuplicateKey(
  3453. &S4UTicketInfo->EvidenceTicketKey,
  3454. SourceTicketKey
  3455. );
  3456. if (!KERB_SUCCESS( Kerberr ))
  3457. {
  3458. goto Cleanup;
  3459. }
  3460. S4UTicketInfo->Flags |= ( TI_INITIALIZED | TI_S4USELF_INFO );
  3461. Cleanup:
  3462. if (S4URequest != NULL)
  3463. {
  3464. KerbFreeData(
  3465. KERB_PA_FOR_USER_PDU,
  3466. S4URequest
  3467. );
  3468. }
  3469. return Kerberr;
  3470. }
  3471. //--------------------------------------------------------------------
  3472. //
  3473. // Name: HandleTGSRequest
  3474. //
  3475. // Synopsis: Gets a ticket using a KDC ticket (TGT).
  3476. //
  3477. // Effects: Allocates and encrypts a KDC reply
  3478. //
  3479. // Arguments: ClientAddress - Optionally contains client IP address
  3480. // RequestMessage - contains the TGS request message
  3481. // RequestRealm - The realm of the request, from the request
  3482. // message
  3483. // OutputMessage - Contains the buffer to send back to the client
  3484. // Requires:
  3485. //
  3486. // Returns: KDC_ERR_ or KRB_AP_ERR errors only
  3487. //
  3488. // Notes:
  3489. //
  3490. //
  3491. //--------------------------------------------------------------------------
  3492. KERBERR
  3493. HandleTGSRequest(
  3494. IN OPTIONAL SOCKADDR * ClientAddress,
  3495. IN PKERB_TGS_REQUEST RequestMessage,
  3496. IN PUNICODE_STRING RequestRealm,
  3497. OUT PKERB_MESSAGE_BUFFER OutputMessage,
  3498. OUT PKERB_EXT_ERROR pExtendedError,
  3499. OUT PUNICODE_STRING ClientStringName,
  3500. OUT PUNICODE_STRING ServerStringName
  3501. )
  3502. {
  3503. KERBERR KerbErr = KDC_ERR_NONE;
  3504. KDC_TICKET_INFO ServerTicketInfo = {0};
  3505. KDC_U2U_TICKET_INFO U2UTicketInfo = {0};
  3506. KDC_S4U_TICKET_INFO S4UTicketInfo = {0};
  3507. KERB_TICKET SourceTicket = {0};
  3508. KERB_TICKET NewTicket = {0};
  3509. KERB_ENCRYPTED_TICKET EncryptedTicket = {0};
  3510. PKERB_ENCRYPTED_TICKET SourceEncryptPart = NULL;
  3511. PKERB_KDC_REQUEST_BODY RequestBody = &RequestMessage->request_body;
  3512. KERB_TGS_REPLY Reply = {0};
  3513. KERB_ENCRYPTED_KDC_REPLY ReplyBody = {0};
  3514. PKERB_AP_REQUEST UnmarshalledApRequest = NULL;
  3515. PKERB_AUTHENTICATOR UnmarshalledAuthenticator = NULL;
  3516. PKERB_PA_DATA ApRequest = NULL;
  3517. PKERB_PA_DATA_LIST ReplyPaData = NULL;
  3518. KERB_ENCRYPTION_KEY ReplyKey = {0};
  3519. KERB_ENCRYPTION_KEY ServerKey = {0};
  3520. KERB_ENCRYPTION_KEY SourceTicketKey ={0};
  3521. PKERB_INTERNAL_NAME ServerName = NULL;
  3522. PKERB_INTERNAL_NAME SourceClientName = NULL;
  3523. UNICODE_STRING SourceClientRealm = {0};
  3524. ULONG CommonEType = 0;
  3525. ULONG KdcOptions = 0;
  3526. ULONG TicketFlags = 0;
  3527. ULONG ReplyTicketFlags = 0;
  3528. ULONG TraceFlags = 0;
  3529. ULONG KeySalt = KERB_TGS_REP_SALT;
  3530. KERB_REALM TmpRealm = NULL;
  3531. KERB_PRINCIPAL_NAME TmpName = {0};
  3532. BOOLEAN Validating = FALSE;
  3533. BOOLEAN UseSubKey = FALSE;
  3534. BOOLEAN Renew = FALSE;
  3535. PS4U_DELEGATION_INFO S4UDelegationInfo = NULL;
  3536. KDC_TGS_EVENT_INFO TGSEventTraceInfo = {0};
  3537. PLSA_ADT_STRING_LIST TransittedServices = NULL;
  3538. TRACE(KDC, HandleTGSRequest, DEB_FUNCTION);
  3539. //
  3540. // Initialize [out] structures, so if we terminate early, they can
  3541. // be correctly marshalled by the stub
  3542. //
  3543. NewTicket.encrypted_part.cipher_text.value = (PUCHAR) &EncryptedTicket;
  3544. EncryptedTicket.flags.value = (PUCHAR) &TicketFlags;
  3545. EncryptedTicket.flags.length = sizeof(ULONG) * 8;
  3546. ReplyBody.flags.value = (PUCHAR) &ReplyTicketFlags;
  3547. ReplyBody.flags.length = sizeof(ULONG) * 8;
  3548. KdcOptions = KerbConvertFlagsToUlong( &RequestBody->kdc_options );
  3549. //
  3550. // Start event tracing
  3551. //
  3552. if (KdcEventTraceFlag){
  3553. TraceFlags = GetTraceEnableFlags(KdcTraceLoggerHandle);
  3554. TGSEventTraceInfo.EventTrace.Guid = KdcHandleTGSRequestGuid;
  3555. TGSEventTraceInfo.EventTrace.Class.Type = EVENT_TRACE_TYPE_START;
  3556. TGSEventTraceInfo.EventTrace.Flags = WNODE_FLAG_TRACED_GUID;
  3557. TGSEventTraceInfo.EventTrace.Size = sizeof (EVENT_TRACE_HEADER) + sizeof (ULONG);
  3558. TGSEventTraceInfo.KdcOptions = KdcOptions;
  3559. TraceEvent(
  3560. KdcTraceLoggerHandle,
  3561. (PEVENT_TRACE_HEADER)&TGSEventTraceInfo
  3562. );
  3563. }
  3564. //
  3565. // The TGS and authenticator are in an AP request in the pre-auth data.
  3566. // Find it and decode the AP request now.
  3567. //
  3568. if ((RequestMessage->bit_mask & KERB_KDC_REQUEST_preauth_data_present) == 0)
  3569. {
  3570. D_DebugLog((DEB_ERROR,
  3571. "KLIN(%x) No pre-auth data in TGS request - not allowed.\n",
  3572. KLIN(FILENO, __LINE__)));
  3573. KerbErr = KDC_ERR_PADATA_TYPE_NOSUPP;
  3574. goto Cleanup;
  3575. }
  3576. //
  3577. // PA Data processing for TGS_REQ
  3578. //
  3579. //
  3580. // Get the TGT from the PA data.
  3581. //
  3582. ApRequest = KerbFindPreAuthDataEntry(
  3583. KRB5_PADATA_TGS_REQ,
  3584. RequestMessage->KERB_KDC_REQUEST_preauth_data
  3585. );
  3586. if (ApRequest == NULL)
  3587. {
  3588. D_DebugLog((DEB_ERROR,"KLIN(%x) No pre-auth data in TGS request - not allowed.\n",
  3589. KLIN(FILENO, __LINE__)));
  3590. FILL_EXT_ERROR(pExtendedError, STATUS_NO_PA_DATA, FILENO, __LINE__);
  3591. KerbErr = KDC_ERR_PADATA_TYPE_NOSUPP;
  3592. goto Cleanup;
  3593. }
  3594. //
  3595. // Verify the request. This includes decoding the AP request,
  3596. // finding the appropriate key to decrypt the ticket, and checking
  3597. // the ticket.
  3598. //
  3599. KerbErr = KdcVerifyKdcRequest(
  3600. ApRequest->preauth_data.value,
  3601. ApRequest->preauth_data.length,
  3602. ClientAddress,
  3603. TRUE, // this is a kdc request
  3604. &UnmarshalledApRequest,
  3605. &UnmarshalledAuthenticator,
  3606. &SourceEncryptPart,
  3607. &ReplyKey,
  3608. &SourceTicketKey,
  3609. &ServerTicketInfo,
  3610. &UseSubKey,
  3611. pExtendedError
  3612. );
  3613. //
  3614. // If you want to validate a ticket, then it's OK if it isn't
  3615. // currently valid.
  3616. //
  3617. if (KerbErr == KRB_AP_ERR_TKT_NYV && (KdcOptions & KERB_KDC_OPTIONS_validate))
  3618. {
  3619. D_DebugLog((DEB_TRACE, "HandleTGSRequest validating a not-yet-valid ticket\n"));
  3620. KerbErr = KDC_ERR_NONE;
  3621. }
  3622. else if (KerbErr == KRB_AP_ERR_MODIFIED)
  3623. {
  3624. //
  3625. // Bug 276943: When the authenticator is encrypted with something other
  3626. // than the session key, KRB_AP_ERR_BAD_INTEGRITY must be
  3627. // returned per RFC 1510
  3628. //
  3629. D_DebugLog((DEB_TRACE, "HandleTGSRequest could not decrypt the ticket\n"));
  3630. KerbErr = KRB_AP_ERR_BAD_INTEGRITY;
  3631. }
  3632. //
  3633. // Verify the checksum on the ticket, if present
  3634. //
  3635. if ( KERB_SUCCESS(KerbErr) &&
  3636. (UnmarshalledAuthenticator != NULL) &&
  3637. (UnmarshalledAuthenticator->bit_mask & checksum_present) != 0)
  3638. {
  3639. KerbErr = KdcVerifyTgsChecksum(
  3640. &RequestMessage->request_body,
  3641. &ReplyKey,
  3642. &UnmarshalledAuthenticator->checksum
  3643. );
  3644. }
  3645. if (!KERB_SUCCESS(KerbErr))
  3646. {
  3647. DebugLog((DEB_ERROR, "HandleTGSRequest KLIN(%x) Failed to verify TGS request: 0x%x\n", KLIN(FILENO, __LINE__), KerbErr));
  3648. FILL_EXT_ERROR(pExtendedError, STATUS_KDC_INVALID_REQUEST, FILENO, __LINE__);
  3649. goto Cleanup;
  3650. }
  3651. //
  3652. // Check for additional tickets
  3653. //
  3654. //
  3655. // The server name is optional, but only if you have enc_tkt_in_skey set..
  3656. //
  3657. if ((RequestBody->bit_mask & KERB_KDC_REQUEST_BODY_server_name_present) != 0)
  3658. {
  3659. KerbErr = KerbConvertPrincipalNameToKdcName(
  3660. &ServerName,
  3661. &RequestBody->KERB_KDC_REQUEST_BODY_server_name
  3662. );
  3663. if (!KERB_SUCCESS( KerbErr ))
  3664. {
  3665. goto Cleanup;
  3666. }
  3667. //
  3668. // Convert the server name to a string for auditing.
  3669. //
  3670. KerbErr = KerbConvertKdcNameToString(
  3671. ServerStringName,
  3672. ServerName,
  3673. NULL
  3674. );
  3675. if (!KERB_SUCCESS(KerbErr))
  3676. {
  3677. goto Cleanup;
  3678. }
  3679. }
  3680. //
  3681. // Grab the cname and crealm from the TGT (aka the source ticket)
  3682. //
  3683. KerbErr = KerbConvertPrincipalNameToKdcName(
  3684. &SourceClientName,
  3685. &SourceEncryptPart->client_name
  3686. );
  3687. if (!KERB_SUCCESS(KerbErr))
  3688. {
  3689. goto Cleanup;
  3690. }
  3691. KerbErr = KerbConvertRealmToUnicodeString(
  3692. &SourceClientRealm,
  3693. &SourceEncryptPart->client_realm
  3694. );
  3695. if (!KERB_SUCCESS(KerbErr))
  3696. {
  3697. goto Cleanup;
  3698. }
  3699. //
  3700. // Validate
  3701. //
  3702. if ((RequestBody->bit_mask & additional_tickets_present) != 0)
  3703. {
  3704. KerbErr = KdcUnpackAdditionalTickets(
  3705. RequestBody->additional_tickets,
  3706. KdcOptions,
  3707. ServerStringName,
  3708. SourceClientName,
  3709. &SourceClientRealm,
  3710. &ReplyKey,
  3711. &U2UTicketInfo,
  3712. &S4UTicketInfo,
  3713. pExtendedError
  3714. );
  3715. if (!KERB_SUCCESS( KerbErr ))
  3716. {
  3717. DebugLog((DEB_ERROR, "KdcUnpackAdditionalTickets failed - %x\n", KerbErr));
  3718. goto Cleanup;
  3719. }
  3720. }
  3721. //
  3722. // Gather & convert names for auditing.
  3723. //
  3724. if ((RequestBody->bit_mask & KERB_KDC_REQUEST_BODY_server_name_present) == 0)
  3725. {
  3726. //
  3727. // There must be an additional ticket, and this *must* be U2U, right?.
  3728. //
  3729. if (( U2UTicketInfo.Flags & TI_INITIALIZED ) == 0)
  3730. {
  3731. KerbErr = KDC_ERR_S_PRINCIPAL_UNKNOWN;
  3732. DsysAssert(FALSE);
  3733. goto Cleanup;
  3734. }
  3735. KerbErr = KerbDuplicateKdcName(
  3736. &ServerName,
  3737. U2UTicketInfo.TgtCName
  3738. );
  3739. if (!KERB_SUCCESS(KerbErr))
  3740. {
  3741. goto Cleanup;
  3742. }
  3743. //
  3744. // Convert the server name to a string for auditing.
  3745. //
  3746. KerbErr = KerbConvertKdcNameToString(
  3747. ServerStringName,
  3748. ServerName,
  3749. NULL
  3750. );
  3751. if (!KERB_SUCCESS(KerbErr))
  3752. {
  3753. goto Cleanup;
  3754. }
  3755. }
  3756. KerbErr = KerbConvertKdcNameToString(
  3757. ClientStringName,
  3758. SourceClientName,
  3759. &SourceClientRealm
  3760. );
  3761. if (!KERB_SUCCESS(KerbErr))
  3762. {
  3763. goto Cleanup;
  3764. }
  3765. //
  3766. // S4UToSelf PA data
  3767. // Note: We can't do both S4U and S4UProxy requests at the same time..
  3768. //
  3769. KerbErr = KdcFindS4UClientAndRealm(
  3770. RequestMessage->KERB_KDC_REQUEST_preauth_data,
  3771. ServerName,
  3772. SourceEncryptPart,
  3773. &SourceTicketKey,
  3774. SourceClientName,
  3775. &SourceClientRealm,
  3776. &S4UTicketInfo,
  3777. pExtendedError
  3778. );
  3779. if (!KERB_SUCCESS( KerbErr ))
  3780. {
  3781. goto Cleanup;
  3782. }
  3783. //
  3784. // If the client is in this domain and if we are supposed to
  3785. // verify the client's account is still good,
  3786. // do it now.
  3787. //
  3788. if ((SecData.KdcFlags() & AUTH_REQ_VALIDATE_CLIENT) != 0)
  3789. {
  3790. LARGE_INTEGER AuthTime;
  3791. LARGE_INTEGER CurrentTime;
  3792. NtQuerySystemTime(&CurrentTime);
  3793. KerbConvertGeneralizedTimeToLargeInt(
  3794. &AuthTime,
  3795. &SourceEncryptPart->authtime,
  3796. 0
  3797. );
  3798. //
  3799. // Only check if we haven't checked recently
  3800. //
  3801. if ((CurrentTime.QuadPart > AuthTime.QuadPart) &&
  3802. ((CurrentTime.QuadPart - AuthTime.QuadPart) > SecData.KdcRestrictionLifetime().QuadPart))
  3803. {
  3804. KerbErr = KdcCheckTgsLogonRestrictions(
  3805. SourceClientName,
  3806. &SourceClientRealm,
  3807. pExtendedError
  3808. );
  3809. if (!KERB_SUCCESS(KerbErr))
  3810. {
  3811. D_DebugLog((DEB_WARN, "HandleTGSRequest KLIN(%x) Client failed TGS logon restrictions: 0x%x : ",
  3812. KLIN(FILENO, __LINE__),KerbErr));
  3813. D_KerbPrintKdcName((DEB_WARN, SourceClientName));
  3814. goto Cleanup;
  3815. }
  3816. }
  3817. }
  3818. //
  3819. // Build a ticket struture to pass to the worker functions
  3820. //
  3821. SourceTicket = UnmarshalledApRequest->ticket;
  3822. SourceTicket.encrypted_part.cipher_text.value = (PUCHAR) SourceEncryptPart;
  3823. //
  3824. // Build the new ticket
  3825. //
  3826. #if DBG
  3827. if ( (S4UTicketInfo.Flags & TI_S4USELF_INFO) != 0)
  3828. {
  3829. D_DebugLog((DEB_T_S4U, "S4USelf request: requestor = %wZ, ", &SourceClientRealm));
  3830. D_KerbPrintKdcName((DEB_T_S4U, SourceClientName));
  3831. D_DebugLog((DEB_T_S4U, "S4USelf client realm %wZ\n", &S4UTicketInfo.PACCRealm));
  3832. D_KerbPrintKdcName((DEB_T_S4U, S4UTicketInfo.PACCName));
  3833. D_DebugLog((DEB_T_S4U, "HandleTGSRequest S4UTarget = %wZ, ", &S4UTicketInfo.TargetName));
  3834. D_KerbPrintKdcName((DEB_T_S4U, ServerName));
  3835. }
  3836. else
  3837. {
  3838. D_DebugLog((DEB_TRACE, "HandleTGSRequest Service = "));
  3839. D_KerbPrintKdcName((DEB_TRACE, ServerName));
  3840. D_DebugLog((DEB_TRACE, "HandleTGSRequest: Client = %wZ, ", &SourceClientRealm));
  3841. D_KerbPrintKdcName((DEB_TRACE, SourceClientName));
  3842. }
  3843. #endif
  3844. //
  3845. // Pass off the work to the worker routines
  3846. //
  3847. if (KdcOptions & KERB_KDC_OPTIONS_renew)
  3848. {
  3849. D_DebugLog((DEB_T_KDC,"Renewing ticket ticket\n"));
  3850. Renew = TRUE;
  3851. KerbErr = I_RenewTicket(
  3852. &SourceTicket,
  3853. ClientStringName, // needed for auditing
  3854. ServerStringName, // needed for auditing
  3855. ServerName,
  3856. &ServerTicketInfo,
  3857. RequestBody,
  3858. ( UnmarshalledAuthenticator && ( UnmarshalledAuthenticator->bit_mask & KERB_AUTHENTICATOR_subkey_present )) ?
  3859. &UnmarshalledAuthenticator->subkey : NULL,
  3860. &NewTicket,
  3861. &ServerKey,
  3862. pExtendedError
  3863. );
  3864. }
  3865. else if (KdcOptions & KERB_KDC_OPTIONS_validate)
  3866. {
  3867. D_DebugLog((DEB_T_KDC, "HandleTGSRequest validating ticket\n"));
  3868. KerbErr = I_Validate(
  3869. &SourceTicket,
  3870. ServerName,
  3871. &SourceClientRealm,
  3872. RequestBody,
  3873. &ServerKey,
  3874. &NewTicket,
  3875. pExtendedError
  3876. );
  3877. Validating = TRUE;
  3878. }
  3879. else
  3880. {
  3881. D_DebugLog((DEB_T_KDC, "HandleTGSRequest getting new TGS ticket\n"));
  3882. KerbErr = I_GetTGSTicket(
  3883. &SourceTicket,
  3884. ClientStringName, // needed for auditing
  3885. ServerStringName, // needed for auditing
  3886. ServerName,
  3887. RequestRealm,
  3888. RequestBody,
  3889. &ServerTicketInfo,
  3890. (( U2UTicketInfo.Flags & TI_INITIALIZED ) ?
  3891. &U2UTicketInfo.Tgt->key : NULL ),
  3892. &S4UTicketInfo,
  3893. ( UnmarshalledAuthenticator && ( UnmarshalledAuthenticator->bit_mask & KERB_AUTHENTICATOR_subkey_present )) ?
  3894. &UnmarshalledAuthenticator->subkey :
  3895. NULL,
  3896. &NewTicket,
  3897. &ServerKey,
  3898. &ReplyPaData,
  3899. pExtendedError,
  3900. &S4UDelegationInfo
  3901. );
  3902. }
  3903. if (!KERB_SUCCESS(KerbErr))
  3904. {
  3905. goto Cleanup;
  3906. }
  3907. DsysAssert(ServerTicketInfo.Passwords != NULL);
  3908. //
  3909. // Check to see if the additional ticket supplied is the one for this
  3910. // server, if necessary
  3911. //
  3912. if ( (U2UTicketInfo.Flags & TI_CHECK_RID)
  3913. && (ServerTicketInfo.UserId != U2UTicketInfo.TgtTicketInfo.UserId) )
  3914. {
  3915. DebugLog((DEB_ERROR, "KLIN(%x) Supplied U2U ticket is not for server: %wZ (%#x) vs. %wZ (%#x)\n",
  3916. KLIN(FILENO, __LINE__), &(U2UTicketInfo.TgtTicketInfo.AccountName), ServerTicketInfo.UserId,
  3917. &(ServerTicketInfo.AccountName), U2UTicketInfo.TgtTicketInfo.UserId));
  3918. KerbErr = KRB_AP_ERR_BADMATCH;
  3919. goto Cleanup;
  3920. }
  3921. //
  3922. // S4UToSelf check - the requestor's userid must == that of the final service.
  3923. //
  3924. if ((( S4UTicketInfo.Flags & ( TI_S4USELF_INFO | TI_CHECK_RID )) == ( TI_S4USELF_INFO | TI_CHECK_RID )) &&
  3925. ( S4UTicketInfo.RequestorTicketInfo.UserId != ServerTicketInfo.UserId ))
  3926. {
  3927. DebugLog((DEB_ERROR, "KLIN(%x) Supplied S4U ticket is not for server: %wZ (%#x) vs. %wZ (%#x)\n",
  3928. KLIN(FILENO, __LINE__), &(S4UTicketInfo.RequestorTicketInfo.AccountName), ServerTicketInfo.UserId,
  3929. &(ServerTicketInfo.AccountName), S4UTicketInfo.RequestorTicketInfo.UserId));
  3930. KerbErr = KRB_AP_ERR_BADMATCH;
  3931. goto Cleanup;
  3932. }
  3933. KerbErr = BuildReply(
  3934. NULL,
  3935. RequestBody->nonce,
  3936. &NewTicket.server_name,
  3937. NewTicket.realm,
  3938. ((EncryptedTicket.bit_mask & KERB_ENCRYPTED_TICKET_client_addresses_present) != 0) ?
  3939. EncryptedTicket.KERB_ENCRYPTED_TICKET_client_addresses : NULL,
  3940. &NewTicket,
  3941. &ReplyBody
  3942. );
  3943. if (!KERB_SUCCESS(KerbErr))
  3944. {
  3945. goto Cleanup;
  3946. }
  3947. //
  3948. // Put in any PA data for the reply
  3949. //
  3950. if (ReplyPaData != NULL)
  3951. {
  3952. ReplyBody.encrypted_pa_data = (struct KERB_ENCRYPTED_KDC_REPLY_encrypted_pa_data_s *) ReplyPaData;
  3953. ReplyBody.bit_mask |= encrypted_pa_data_present;
  3954. }
  3955. //
  3956. // Now build the real reply and return it.
  3957. //
  3958. Reply.version = KERBEROS_VERSION;
  3959. Reply.message_type = KRB_TGS_REP;
  3960. Reply.KERB_KDC_REPLY_preauth_data = NULL;
  3961. Reply.bit_mask = 0;
  3962. //
  3963. // S4UToSelf.
  3964. // The client name in the reply is the client name from the
  3965. // PA Data.
  3966. //
  3967. if ((( S4UTicketInfo.Flags & ( TI_S4USELF_INFO | TI_S4UPROXY_INFO ) ) != 0) &&
  3968. (( S4UTicketInfo.Flags & TI_TARGET_OUR_REALM) != 0 ))
  3969. {
  3970. KerbErr = KerbConvertKdcNameToPrincipalName(
  3971. &TmpName,
  3972. S4UTicketInfo.PACCName
  3973. );
  3974. if (!KERB_SUCCESS(KerbErr))
  3975. {
  3976. goto Cleanup;
  3977. }
  3978. KerbErr = KerbConvertUnicodeStringToRealm(
  3979. &TmpRealm,
  3980. &S4UTicketInfo.PACCRealm
  3981. );
  3982. if (!KERB_SUCCESS(KerbErr))
  3983. {
  3984. goto Cleanup;
  3985. }
  3986. D_DebugLog((DEB_T_TICKETS, "S4U Reply client name\n"));
  3987. D_KerbPrintKdcName((DEB_T_TICKETS, S4UTicketInfo.PACCName));
  3988. D_DebugLog((DEB_T_TICKETS, "Realm %wZ\n", &S4UTicketInfo.PACCRealm));
  3989. Reply.client_realm = TmpRealm;
  3990. Reply.client_name = TmpName;
  3991. }
  3992. else
  3993. {
  3994. //
  3995. // Default to information in the TGT
  3996. //
  3997. Reply.client_realm = SourceEncryptPart->client_realm;
  3998. Reply.client_name = SourceEncryptPart->client_name;
  3999. }
  4000. //
  4001. // Copy in the ticket
  4002. //
  4003. KerbErr = KerbPackTicket(
  4004. &NewTicket,
  4005. &ServerKey,
  4006. ( U2UTicketInfo.Flags & TI_INITIALIZED ) ? KERB_NO_KEY_VERSION : ServerTicketInfo.PasswordVersion,
  4007. &Reply.ticket
  4008. );
  4009. if (!KERB_SUCCESS(KerbErr))
  4010. {
  4011. D_DebugLog((DEB_ERROR, "KLIN(%x) Failed to pack ticket: 0x%x\n", KLIN(FILENO, __LINE__), KerbErr));
  4012. goto Cleanup;
  4013. }
  4014. //
  4015. // Copy in the encrypted part (will encrypt the data first)
  4016. //
  4017. if (UseSubKey == TRUE)
  4018. {
  4019. KeySalt = KERB_TGS_REP_SUBKEY_SALT; // otherwise keep KERB_TGS_REP_SALT
  4020. }
  4021. KerbErr = KerbPackKdcReplyBody(
  4022. &ReplyBody,
  4023. &ReplyKey,
  4024. KERB_NO_KEY_VERSION,
  4025. KeySalt,
  4026. KERB_ENCRYPTED_TGS_REPLY_PDU,
  4027. &Reply.encrypted_part
  4028. );
  4029. if (!KERB_SUCCESS(KerbErr))
  4030. {
  4031. D_DebugLog((DEB_ERROR, "KLIN(%x)Failed to pack KDC reply body: 0x%x\n", KLIN(FILENO, __LINE__), KerbErr));
  4032. goto Cleanup;
  4033. }
  4034. //
  4035. // Now build the real reply message
  4036. //
  4037. KerbErr = KerbPackData(
  4038. &Reply,
  4039. KERB_TGS_REPLY_PDU,
  4040. &OutputMessage->BufferSize,
  4041. &OutputMessage->Buffer
  4042. );
  4043. if (!KERB_SUCCESS(KerbErr))
  4044. {
  4045. goto Cleanup;
  4046. }
  4047. //
  4048. // Audit the successful ticket generation
  4049. //
  4050. CommonEType = ServerKey.keytype;
  4051. if (SecData.AuditKdcEvent(KDC_AUDIT_TGS_SUCCESS))
  4052. {
  4053. BYTE ServerSid[MAX_SID_LEN];
  4054. GUID LogonGuid;
  4055. NTSTATUS Status = STATUS_SUCCESS;
  4056. PKERB_TIME pStartTime;
  4057. pStartTime = &(((PKERB_ENCRYPTED_TICKET) NewTicket.encrypted_part.cipher_text.value)->KERB_ENCRYPTED_TICKET_starttime);
  4058. Status = LsaIGetLogonGuid(
  4059. ClientStringName,
  4060. &SourceClientRealm,
  4061. (PBYTE) pStartTime,
  4062. sizeof(KERB_TIME),
  4063. &LogonGuid
  4064. );
  4065. ASSERT(NT_SUCCESS( Status ));
  4066. if (S4UDelegationInfo)
  4067. {
  4068. TransittedServices = (PLSA_ADT_STRING_LIST)MIDL_user_allocate(
  4069. sizeof(LSA_ADT_STRING_LIST) +
  4070. sizeof(LSA_ADT_STRING_LIST_ENTRY) * S4UDelegationInfo->TransitedListSize);
  4071. if (TransittedServices)
  4072. {
  4073. PLSA_ADT_STRING_LIST_ENTRY Entry;
  4074. Entry = (PLSA_ADT_STRING_LIST_ENTRY)&TransittedServices[1];
  4075. TransittedServices->cStrings = S4UDelegationInfo->TransitedListSize;
  4076. TransittedServices->Strings = Entry;
  4077. for (ULONG i = 0; i < S4UDelegationInfo->TransitedListSize; i++)
  4078. {
  4079. Entry->Flags = 0;
  4080. Entry->String.Length = S4UDelegationInfo->S4UTransitedServices[i].Length;
  4081. Entry->String.MaximumLength = S4UDelegationInfo->S4UTransitedServices[i].MaximumLength;
  4082. Entry->String.Buffer = S4UDelegationInfo->S4UTransitedServices[i].Buffer;
  4083. Entry++;
  4084. }
  4085. }
  4086. }
  4087. KdcMakeAccountSid(ServerSid, ServerTicketInfo.UserId);
  4088. KdcLsaIAuditTgsEvent(
  4089. Renew ? SE_AUDITID_TICKET_RENEW_SUCCESS : SE_AUDITID_TGS_TICKET_REQUEST,
  4090. ClientStringName,
  4091. &SourceClientRealm,
  4092. NULL, // no client SID
  4093. &ServerTicketInfo.AccountName,
  4094. ServerSid,
  4095. (PULONG) &KdcOptions,
  4096. NULL, // success
  4097. &CommonEType,
  4098. NULL, // no preauth type
  4099. GET_CLIENT_ADDRESS(ClientAddress),
  4100. &LogonGuid,
  4101. TransittedServices
  4102. );
  4103. }
  4104. Cleanup:
  4105. //
  4106. // Complete the event
  4107. //
  4108. if (KdcEventTraceFlag){
  4109. //These variables point to either a unicode string struct containing
  4110. //the corresponding string or a pointer to KdcNullString
  4111. PUNICODE_STRING pStringToCopy;
  4112. WCHAR UnicodeNullChar = 0;
  4113. UNICODE_STRING UnicodeEmptyString = {sizeof(WCHAR),sizeof(WCHAR),&UnicodeNullChar};
  4114. TGSEventTraceInfo.EventTrace.Class.Type = EVENT_TRACE_TYPE_END;
  4115. TGSEventTraceInfo.EventTrace.Flags = WNODE_FLAG_USE_MOF_PTR |
  4116. WNODE_FLAG_TRACED_GUID;
  4117. // Always output error code. KdcOptions was captured on the start event
  4118. TGSEventTraceInfo.eventInfo[0].DataPtr = (ULONGLONG) &KerbErr;
  4119. TGSEventTraceInfo.eventInfo[0].Length = sizeof(ULONG);
  4120. TGSEventTraceInfo.EventTrace.Size =
  4121. sizeof (EVENT_TRACE_HEADER) + sizeof(MOF_FIELD);
  4122. // Build counted MOF strings from the unicode strings.
  4123. // If data is unavailable then output a NULL string
  4124. if (ClientStringName->Buffer != NULL &&
  4125. ClientStringName->Length > 0)
  4126. {
  4127. pStringToCopy = ClientStringName;
  4128. }
  4129. else
  4130. {
  4131. pStringToCopy = &UnicodeEmptyString;
  4132. }
  4133. TGSEventTraceInfo.eventInfo[1].DataPtr =
  4134. (ULONGLONG) &pStringToCopy->Length;
  4135. TGSEventTraceInfo.eventInfo[1].Length =
  4136. sizeof(pStringToCopy->Length);
  4137. TGSEventTraceInfo.eventInfo[2].DataPtr =
  4138. (ULONGLONG) pStringToCopy->Buffer;
  4139. TGSEventTraceInfo.eventInfo[2].Length =
  4140. pStringToCopy->Length;
  4141. TGSEventTraceInfo.EventTrace.Size += sizeof(MOF_FIELD)*2;
  4142. if (ServerStringName->Buffer != NULL &&
  4143. ServerStringName->Length > 0)
  4144. {
  4145. pStringToCopy = ServerStringName;
  4146. }
  4147. else
  4148. {
  4149. pStringToCopy = &UnicodeEmptyString;
  4150. }
  4151. TGSEventTraceInfo.eventInfo[3].DataPtr =
  4152. (ULONGLONG) &pStringToCopy->Length;
  4153. TGSEventTraceInfo.eventInfo[3].Length =
  4154. sizeof(pStringToCopy->Length);
  4155. TGSEventTraceInfo.eventInfo[4].DataPtr =
  4156. (ULONGLONG) pStringToCopy->Buffer;
  4157. TGSEventTraceInfo.eventInfo[4].Length =
  4158. pStringToCopy->Length;
  4159. TGSEventTraceInfo.EventTrace.Size += sizeof(MOF_FIELD)*2;
  4160. if (SourceClientRealm.Buffer != NULL &&
  4161. SourceClientRealm.Length > 0)
  4162. {
  4163. pStringToCopy = &SourceClientRealm;
  4164. }
  4165. else
  4166. {
  4167. pStringToCopy = &UnicodeEmptyString;
  4168. }
  4169. TGSEventTraceInfo.eventInfo[5].DataPtr =
  4170. (ULONGLONG) &pStringToCopy->Length;
  4171. TGSEventTraceInfo.eventInfo[5].Length =
  4172. sizeof(pStringToCopy->Length);
  4173. TGSEventTraceInfo.eventInfo[6].DataPtr =
  4174. (ULONGLONG) pStringToCopy->Buffer;
  4175. TGSEventTraceInfo.eventInfo[6].Length =
  4176. pStringToCopy->Length;
  4177. TGSEventTraceInfo.EventTrace.Size += sizeof(MOF_FIELD)*2;
  4178. TraceEvent(
  4179. KdcTraceLoggerHandle,
  4180. (PEVENT_TRACE_HEADER)&TGSEventTraceInfo
  4181. );
  4182. }
  4183. if (!KERB_SUCCESS(KerbErr) &&
  4184. SecData.AuditKdcEvent(KDC_AUDIT_TGS_FAILURE))
  4185. {
  4186. if (( KerbErr != KDC_ERR_S_PRINCIPAL_UNKNOWN ) ||
  4187. (( KdcExtraLogLevel & LOG_SPN_UNKNOWN) != 0))
  4188. {
  4189. KdcLsaIAuditTgsEvent(
  4190. SE_AUDITID_TGS_TICKET_REQUEST,
  4191. (ClientStringName->Buffer != NULL) ? ClientStringName : &KdcNullString,
  4192. &SourceClientRealm, // no domain name
  4193. NULL,
  4194. ServerStringName,
  4195. NULL,
  4196. &KdcOptions,
  4197. (PULONG) &KerbErr,
  4198. NULL,
  4199. NULL,
  4200. GET_CLIENT_ADDRESS(ClientAddress),
  4201. NULL, // no logon guid
  4202. NULL // no transitted services
  4203. );
  4204. }
  4205. }
  4206. KerbFreeKdcName(
  4207. &SourceClientName
  4208. );
  4209. KerbFreeString(
  4210. &SourceClientRealm
  4211. );
  4212. KerbFreeKdcName(
  4213. &ServerName
  4214. );
  4215. KerbFreeKey(
  4216. &ReplyKey
  4217. );
  4218. KerbFreeKey(
  4219. &SourceTicketKey
  4220. );
  4221. KerbFreeKey(
  4222. &ServerKey
  4223. );
  4224. KdcFreeKdcReplyBody(
  4225. &ReplyBody
  4226. );
  4227. KerbFreePrincipalName( &TmpName );
  4228. KerbFreeRealm( &TmpRealm );
  4229. KdcFreeU2UTicketInfo(&U2UTicketInfo);
  4230. KdcFreeS4UTicketInfo(&S4UTicketInfo);
  4231. if (ReplyPaData != NULL)
  4232. {
  4233. KerbFreePreAuthData(ReplyPaData);
  4234. }
  4235. KerbFreeApRequest(UnmarshalledApRequest);
  4236. KerbFreeAuthenticator(UnmarshalledAuthenticator);
  4237. KerbFreeTicket(SourceEncryptPart);
  4238. KdcFreeInternalTicket(&NewTicket);
  4239. FreeTicketInfo(&ServerTicketInfo);
  4240. KdcFreeKdcReply(
  4241. &Reply
  4242. );
  4243. if (TransittedServices)
  4244. {
  4245. MIDL_user_free(TransittedServices);
  4246. }
  4247. if (S4UDelegationInfo)
  4248. {
  4249. #if DBG
  4250. D_DebugLog((DEB_T_PAC, "HandleTGSRequest target %wZ\n", &S4UDelegationInfo->S4U2proxyTarget));
  4251. for ( ULONG i = 0; i < S4UDelegationInfo->TransitedListSize; i++ )
  4252. {
  4253. D_DebugLog((DEB_T_PAC, "HandleTGSRequest ts %#x: %wZ\n", i, &S4UDelegationInfo->S4UTransitedServices[i]));
  4254. }
  4255. #endif // DBG
  4256. MIDL_user_free(S4UDelegationInfo);
  4257. }
  4258. return(KerbErr);
  4259. }