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

1205 lines
28 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // File: secdata.cxx
  4. //
  5. // Contents: Global data and methods on it.
  6. //
  7. //
  8. // History:
  9. //
  10. //------------------------------------------------------------------------
  11. #include "kdcsvr.hxx"
  12. #include <tostring.hxx>
  13. #include <kpasswd.h>
  14. ///////////////////////////////////////////////////////////////
  15. //
  16. //
  17. // Global data
  18. //
  19. // This is all the security information that gets cached.
  20. CSecurityData SecData;
  21. CAuthenticatorList * Authenticators;
  22. CAuthenticatorList * FailedRequests;
  23. ///////////////////////////////////////////////////////////////
  24. //
  25. //
  26. // Prototypes
  27. //
  28. fLsaPolicyChangeNotificationCallback KdcPolicyChangeCallback;
  29. //+-------------------------------------------------------------------------
  30. //
  31. // Function: KdcPolicyChangeCallBack
  32. //
  33. // Synopsis: Function that gets called when policy changes
  34. //
  35. // Effects: Changes policy variables
  36. //
  37. // Arguments: MonitorInfoClass - class of data that changed
  38. //
  39. // Requires:
  40. //
  41. // Returns:
  42. //
  43. // Notes:
  44. //
  45. //
  46. //--------------------------------------------------------------------------
  47. VOID
  48. KdcPolicyChangeCallBack(
  49. IN POLICY_NOTIFICATION_INFORMATION_CLASS MonitorInfoClass
  50. )
  51. {
  52. NTSTATUS Status;
  53. WCHAR Class[10];
  54. TRACE(KDC, KdcPolicyChangeCallBack, DEB_FUNCTION);
  55. Status = SecData.ReloadPolicy(MonitorInfoClass);
  56. if (!NT_SUCCESS(Status))
  57. {
  58. _itow(MonitorInfoClass, Class, 10 );
  59. ReportServiceEvent(
  60. EVENTLOG_ERROR_TYPE,
  61. KDCEVENT_POLICY_UPDATE_FAILED,
  62. sizeof(NTSTATUS),
  63. &Status,
  64. 1, // number of strings
  65. Class
  66. );
  67. }
  68. }
  69. //+-------------------------------------------------------------------------
  70. //
  71. // Function: CSecurityData::ReloadPolicy
  72. //
  73. // Synopsis: Reloads a particular piece of policy
  74. //
  75. // Effects:
  76. //
  77. // Arguments:
  78. //
  79. // Requires:
  80. //
  81. // Returns:
  82. //
  83. // Notes:
  84. //
  85. //
  86. //--------------------------------------------------------------------------
  87. NTSTATUS
  88. CSecurityData::ReloadPolicy(
  89. IN POLICY_NOTIFICATION_INFORMATION_CLASS MonitorInfoClass
  90. )
  91. {
  92. NTSTATUS Status = STATUS_SUCCESS;
  93. PLSAPR_POLICY_DOMAIN_INFORMATION DomainPolicy = NULL;
  94. PLSAPR_POLICY_INFORMATION LocalPolicy = NULL;
  95. WCHAR Class[10];
  96. TRACE(KDC, CSecurityData::ReloadPolicy, DEB_FUNCTION);
  97. //
  98. // Ignore changes to non-kerberos ticket information
  99. //
  100. switch(MonitorInfoClass) {
  101. case PolicyNotifyDomainKerberosTicketInformation:
  102. Status = LsarQueryDomainInformationPolicy(
  103. GlobalPolicyHandle,
  104. PolicyDomainKerberosTicketInformation,
  105. &DomainPolicy
  106. );
  107. if (!NT_SUCCESS(Status))
  108. {
  109. goto Cleanup;
  110. }
  111. break;
  112. case PolicyNotifyAuditEventsInformation:
  113. Status = LsarQueryInformationPolicy(
  114. GlobalPolicyHandle,
  115. PolicyAuditEventsInformation,
  116. &LocalPolicy
  117. );
  118. if (!NT_SUCCESS(Status))
  119. {
  120. goto Cleanup;
  121. }
  122. break;
  123. default:
  124. return(STATUS_SUCCESS);
  125. }
  126. //
  127. // Update the changed information in the KDCs global data structures.
  128. //
  129. //
  130. // Current policy defaults, see KirkSol/JBrezak
  131. // [Kerberos Policy]
  132. // MaxTicketAge=10 ;Maximum User Ticket Lifetime (hours)
  133. // MaxRenewAge=7 ;Maximum lifetime that a user tickeet can be renewed (days)
  134. // MaxServiceAge=60 ;Maximum Service Ticket Lifetime (minutes)
  135. // MaxClockSkew=5 ;Maximum tolerance for synchronization of computer clocks (minutes)
  136. // TicketValidateClient=1 ;Enforce user logon restrictions
  137. WriteLock();
  138. switch(MonitorInfoClass) {
  139. case PolicyNotifyDomainKerberosTicketInformation:
  140. // Validate parameters
  141. if ((DomainPolicy->PolicyDomainKerbTicketInfo.MaxServiceTicketAge.QuadPart <= (LONGLONG) -1) ||
  142. (DomainPolicy->PolicyDomainKerbTicketInfo.MaxTicketAge.QuadPart <= (LONGLONG) -1) ||
  143. (DomainPolicy->PolicyDomainKerbTicketInfo.MaxRenewAge.QuadPart <= (LONGLONG) -1) ||
  144. (DomainPolicy->PolicyDomainKerbTicketInfo.MaxClockSkew.QuadPart <= (LONGLONG) -1) ||
  145. (DomainPolicy->PolicyDomainKerbTicketInfo.MaxServiceTicketAge.QuadPart == (LONGLONG) 0) ||
  146. (DomainPolicy->PolicyDomainKerbTicketInfo.MaxTicketAge.QuadPart == (LONGLONG) 0) ||
  147. (DomainPolicy->PolicyDomainKerbTicketInfo.MaxRenewAge.QuadPart == (LONGLONG) 0) )
  148. {
  149. _itow(MonitorInfoClass, Class, 10 );
  150. ReportServiceEvent(
  151. EVENTLOG_ERROR_TYPE,
  152. KDCEVENT_POLICY_UPDATE_FAILED,
  153. sizeof(NTSTATUS),
  154. &Status,
  155. 1, // number of strings
  156. Class
  157. );
  158. }
  159. else
  160. {
  161. _KDC_TgsTicketLifespan = DomainPolicy->PolicyDomainKerbTicketInfo.MaxServiceTicketAge;
  162. _KDC_TgtTicketLifespan = DomainPolicy->PolicyDomainKerbTicketInfo.MaxTicketAge;
  163. _KDC_TicketRenewSpan = DomainPolicy->PolicyDomainKerbTicketInfo.MaxRenewAge;
  164. SkewTime = DomainPolicy->PolicyDomainKerbTicketInfo.MaxClockSkew;
  165. }
  166. // Update domain policy flags. Don't depend on the flags keeping in sync
  167. // with the kerberos internal flags
  168. if ( DomainPolicy->PolicyDomainKerbTicketInfo.AuthenticationOptions &
  169. POLICY_KERBEROS_VALIDATE_CLIENT)
  170. {
  171. _KDC_Flags |= AUTH_REQ_VALIDATE_CLIENT;
  172. }
  173. else
  174. {
  175. _KDC_Flags &= ~AUTH_REQ_VALIDATE_CLIENT;
  176. }
  177. break;
  178. case PolicyNotifyAuditEventsInformation:
  179. if ((LocalPolicy->PolicyAuditEventsInfo.AuditingMode) &&
  180. (LocalPolicy->PolicyAuditEventsInfo.MaximumAuditEventCount > AuditCategoryAccountLogon))
  181. {
  182. if (LocalPolicy->PolicyAuditEventsInfo.EventAuditingOptions[AuditCategoryAccountLogon] & POLICY_AUDIT_EVENT_SUCCESS )
  183. {
  184. _KDC_AuditEvents |= KDC_AUDIT_AS_SUCCESS | KDC_AUDIT_TGS_SUCCESS | KDC_AUDIT_MAP_SUCCESS;
  185. }
  186. else
  187. {
  188. _KDC_AuditEvents &= ~(KDC_AUDIT_AS_SUCCESS | KDC_AUDIT_TGS_SUCCESS | KDC_AUDIT_MAP_SUCCESS);
  189. }
  190. if (LocalPolicy->PolicyAuditEventsInfo.EventAuditingOptions[AuditCategoryAccountLogon] & POLICY_AUDIT_EVENT_FAILURE )
  191. {
  192. _KDC_AuditEvents |= KDC_AUDIT_AS_FAILURE | KDC_AUDIT_TGS_FAILURE | KDC_AUDIT_MAP_FAILURE;
  193. }
  194. else
  195. {
  196. _KDC_AuditEvents &= ~(KDC_AUDIT_AS_FAILURE | KDC_AUDIT_TGS_FAILURE | KDC_AUDIT_MAP_FAILURE);
  197. }
  198. }
  199. break;
  200. }
  201. Release();
  202. Cleanup:
  203. if (DomainPolicy != NULL)
  204. {
  205. LsaIFree_LSAPR_POLICY_DOMAIN_INFORMATION (
  206. PolicyDomainKerberosTicketInformation,
  207. DomainPolicy);
  208. }
  209. if (LocalPolicy != NULL)
  210. {
  211. LsaIFree_LSAPR_POLICY_INFORMATION(
  212. PolicyAuditEventsInformation,
  213. LocalPolicy);
  214. }
  215. return(Status);
  216. }
  217. //+-------------------------------------------------------------------------
  218. //
  219. // Function: CSecurityData::SetForestRoot
  220. //
  221. // Synopsis: Sets the forest root
  222. //
  223. // Effects:
  224. //
  225. // Arguments:
  226. //
  227. // Requires:
  228. //
  229. // Returns:
  230. //
  231. // Notes:
  232. //
  233. //
  234. //--------------------------------------------------------------------------
  235. NTSTATUS
  236. CSecurityData::SetForestRoot(
  237. IN PUNICODE_STRING NewForestRoot
  238. )
  239. {
  240. NTSTATUS Status;
  241. UNICODE_STRING Temp;
  242. WriteLock();
  243. RtlCopyMemory(
  244. &Temp,
  245. &_ForestRoot,
  246. sizeof(UNICODE_STRING)
  247. );
  248. Status = KerbDuplicateString(
  249. &_ForestRoot,
  250. NewForestRoot
  251. );
  252. // on alloc failure, just keep old version as it will never change
  253. if (!NT_SUCCESS(Status))
  254. {
  255. RtlCopyMemory(
  256. &_ForestRoot,
  257. &Temp,
  258. sizeof(UNICODE_STRING)
  259. );
  260. }
  261. else
  262. {
  263. KerbFreeString(&Temp);
  264. }
  265. _KDC_IsForestRoot = IsOurRealm(&_ForestRoot);
  266. Release();
  267. return Status;
  268. }
  269. ////////////////////////////////////////////////////////////////////
  270. //
  271. // Name: CSecurityData::CSecurityData
  272. //
  273. // Synopsis: Constructor.
  274. //
  275. // Arguments: <none>
  276. //
  277. // Notes: .
  278. //
  279. CSecurityData::CSecurityData()
  280. {
  281. TRACE(KDC, CSecurityData::CSecurityData, DEB_FUNCTION);
  282. RtlInitUnicodeString(
  283. &_MachineName,
  284. NULL
  285. );
  286. RtlInitUnicodeString(
  287. &_MachineUpn,
  288. NULL
  289. );
  290. RtlInitUnicodeString(
  291. &_RealmName,
  292. NULL
  293. );
  294. RtlInitUnicodeString(
  295. &_KDC_Name,
  296. NULL
  297. );
  298. RtlInitUnicodeString(
  299. &_KDC_FullName,
  300. NULL
  301. );
  302. RtlInitUnicodeString(
  303. &_KDC_FullDnsName,
  304. NULL
  305. );
  306. RtlInitUnicodeString(
  307. &_KDC_FullKdcName,
  308. NULL
  309. );
  310. RtlInitUnicodeString(
  311. &_ForestRoot,
  312. NULL
  313. );
  314. _KerbRealmName = NULL;
  315. _KerbDnsRealmName = NULL;
  316. _KrbtgtServiceName = NULL;
  317. _KpasswdServiceName = NULL;
  318. RtlZeroMemory(
  319. &_KrbtgtTicketInfo,
  320. sizeof(KDC_TICKET_INFO)
  321. );
  322. _KrbtgtTicketInfoValid = FALSE;
  323. _KDC_CrossForestEnabled = FALSE;
  324. _KDC_IsForestRoot = FALSE;
  325. RtlInitializeCriticalSection(&_Monitor);
  326. }
  327. //+---------------------------------------------------------------------------
  328. //
  329. // Member: CSecurityData::Init
  330. //
  331. // Synopsis: Initializes the global data.
  332. //
  333. // Effects: Allocates memory
  334. //
  335. // Arguments: (none)
  336. //
  337. // Returns: STATUS_SUCCESS or error code
  338. //
  339. // Signals: May raise exception on out of memory.
  340. //
  341. // History: 4-02-93 WadeR Created
  342. //
  343. // Notes: This must be called before any other method of
  344. // CSecurityData. It gets data from the registry, the domain
  345. // object, and the kdc.ini file.
  346. //
  347. //----------------------------------------------------------------------------
  348. NTSTATUS
  349. CSecurityData::Init()
  350. {
  351. TRACE(KDC, CSecurityData::Init, DEB_FUNCTION);
  352. NTSTATUS Status;
  353. UNICODE_STRING TempString;
  354. WCHAR TempMachineName[CNLEN+1];
  355. ULONG MachineNameLength = CNLEN+1;
  356. NET_API_STATUS NetStatus;
  357. LARGE_INTEGER MaxAuthenticatorAge;
  358. PLSAPR_POLICY_INFORMATION PolicyInfo = NULL;
  359. UNICODE_STRING KadminName;
  360. UNICODE_STRING ChangePwName;
  361. D_DebugLog(( DEB_TRACE, "Entered CSecurityData::Init()\n" ));
  362. //
  363. // Get the domain name and ID from the registry
  364. //
  365. Status = KerbDuplicateString(
  366. &_RealmName,
  367. &GlobalDomainName
  368. );
  369. if (!NT_SUCCESS(Status))
  370. {
  371. goto Cleanup;
  372. }
  373. if (!KERB_SUCCESS(KerbConvertUnicodeStringToRealm(
  374. &_KerbRealmName,
  375. &GlobalDomainName)))
  376. {
  377. Status = STATUS_INSUFFICIENT_RESOURCES;
  378. goto Cleanup;
  379. }
  380. //
  381. // Construct the KDC Name from the realm and the suffix.
  382. //
  383. RtlInitUnicodeString(
  384. &TempString,
  385. KDC_PRINCIPAL_NAME
  386. );
  387. Status = KerbDuplicateString(
  388. &_KDC_Name,
  389. &TempString
  390. );
  391. if (!NT_SUCCESS(Status))
  392. {
  393. goto Cleanup;
  394. }
  395. if (!GetComputerName(
  396. TempMachineName,
  397. &MachineNameLength
  398. ))
  399. {
  400. Status = STATUS_BUFFER_TOO_SMALL;
  401. goto Cleanup;
  402. }
  403. RtlInitUnicodeString(
  404. &TempString,
  405. TempMachineName
  406. );
  407. Status = KerbDuplicateString(
  408. &_MachineName,
  409. &TempString
  410. );
  411. if (!NT_SUCCESS(Status))
  412. {
  413. goto Cleanup;
  414. }
  415. Status = LsaIQueryInformationPolicyTrusted(
  416. PolicyDnsDomainInformation,
  417. &PolicyInfo
  418. );
  419. if (!NT_SUCCESS(Status))
  420. {
  421. goto Cleanup;
  422. }
  423. //
  424. // WAS BUG: this DNS name may have a trailing '.' - if so, strip it off
  425. //
  426. if (PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Length >= sizeof(WCHAR))
  427. {
  428. if (PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Buffer[ -1 + PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Length / sizeof(WCHAR) ] == L'.')
  429. {
  430. PolicyInfo->PolicyDnsDomainInfo.DnsDomainName.Length -= sizeof(WCHAR);
  431. }
  432. }
  433. Status = KerbDuplicateString(
  434. &_DnsRealmName,
  435. (PUNICODE_STRING) &PolicyInfo->PolicyDnsDomainInfo.DnsDomainName
  436. );
  437. if (!NT_SUCCESS(Status))
  438. {
  439. goto Cleanup;
  440. }
  441. Status = RtlUpcaseUnicodeString(
  442. &_DnsRealmName,
  443. &_DnsRealmName,
  444. FALSE
  445. );
  446. if (!NT_SUCCESS(Status))
  447. {
  448. goto Cleanup;
  449. }
  450. if (!KERB_SUCCESS(KerbConvertUnicodeStringToRealm(
  451. &_KerbDnsRealmName,
  452. &_DnsRealmName)))
  453. {
  454. Status = STATUS_INSUFFICIENT_RESOURCES;
  455. goto Cleanup;
  456. }
  457. //
  458. // Build the machine UPN: [email protected]
  459. //
  460. _MachineUpn.Length = _MachineName.Length + 2 * sizeof(WCHAR) + _DnsRealmName.Length;
  461. _MachineUpn.MaximumLength = _MachineUpn.Length + sizeof(WCHAR);
  462. _MachineUpn.Buffer = (LPWSTR) MIDL_user_allocate(_MachineUpn.MaximumLength);
  463. if (_MachineUpn.Buffer == NULL)
  464. {
  465. Status = STATUS_INSUFFICIENT_RESOURCES;
  466. goto Cleanup;
  467. }
  468. RtlCopyMemory(
  469. _MachineUpn.Buffer,
  470. _MachineName.Buffer,
  471. _MachineName.Length
  472. );
  473. _MachineUpn.Buffer[_MachineName.Length / sizeof(WCHAR)] = L'$';
  474. _MachineUpn.Buffer[1+_MachineName.Length / sizeof(WCHAR)] = L'@';
  475. RtlCopyMemory(
  476. _MachineUpn.Buffer + _MachineName.Length / sizeof(WCHAR) + 2 ,
  477. _DnsRealmName.Buffer,
  478. _DnsRealmName.Length
  479. );
  480. _MachineUpn.Buffer[_MachineUpn.Length / sizeof(WCHAR)] = L'\0';
  481. if (!KERB_SUCCESS(KerbBuildFullServiceName(
  482. &_RealmName,
  483. &_KDC_Name,
  484. &_KDC_FullName
  485. )))
  486. {
  487. Status = STATUS_INSUFFICIENT_RESOURCES;
  488. goto Cleanup;
  489. }
  490. if (!KERB_SUCCESS(KerbBuildFullServiceName(
  491. &_DnsRealmName,
  492. &_KDC_Name,
  493. &_KDC_FullDnsName
  494. )))
  495. {
  496. Status = STATUS_INSUFFICIENT_RESOURCES;
  497. goto Cleanup;
  498. }
  499. //
  500. // Build the full kdc name - a kerberos style name
  501. //
  502. _KDC_FullKdcName.Length = _KDC_Name.Length + _DnsRealmName.Length + sizeof(WCHAR);
  503. _KDC_FullKdcName.MaximumLength = _KDC_FullKdcName.Length + sizeof(WCHAR);
  504. _KDC_FullKdcName.Buffer = (LPWSTR) MIDL_user_allocate(_KDC_FullDnsName.MaximumLength);
  505. if (_KDC_FullKdcName.Buffer == NULL)
  506. {
  507. Status = STATUS_INSUFFICIENT_RESOURCES;
  508. goto Cleanup;
  509. }
  510. RtlCopyMemory(
  511. _KDC_FullKdcName.Buffer,
  512. _KDC_Name.Buffer,
  513. _KDC_Name.Length
  514. );
  515. _KDC_FullKdcName.Buffer[_KDC_Name.Length / sizeof(WCHAR)] = L'/';
  516. RtlCopyMemory(
  517. _KDC_FullKdcName.Buffer + 1 + _KDC_Name.Length / sizeof(WCHAR),
  518. _DnsRealmName.Buffer,
  519. _DnsRealmName.Length
  520. );
  521. _KDC_FullKdcName.Buffer[_KDC_FullKdcName.Length / sizeof(WCHAR)] = L'\0';
  522. D_DebugLog((DEB_TRACE, "_KDC_Name='%wZ', MachineName='%wZ'\n",
  523. &_KDC_Name,
  524. &_MachineName ));
  525. if (!KERB_SUCCESS(KerbBuildFullServiceKdcName(
  526. &_DnsRealmName,
  527. &_KDC_Name,
  528. KRB_NT_SRV_INST,
  529. &_KrbtgtServiceName
  530. )))
  531. {
  532. Status = STATUS_INSUFFICIENT_RESOURCES;
  533. goto Cleanup;
  534. }
  535. //
  536. // Build the kdc name for kadmin/changepw.
  537. //
  538. RtlInitUnicodeString(
  539. &KadminName,
  540. KERB_KPASSWD_NAME
  541. );
  542. RtlInitUnicodeString(
  543. &ChangePwName,
  544. L"changepw"
  545. );
  546. if (!KERB_SUCCESS(KerbBuildFullServiceKdcName(
  547. &ChangePwName,
  548. &KadminName,
  549. KRB_NT_SRV_INST,
  550. &_KpasswdServiceName
  551. )))
  552. {
  553. Status = STATUS_INSUFFICIENT_RESOURCES;
  554. goto Cleanup;
  555. }
  556. Status = LoadParameters(GlobalAccountDomainHandle);
  557. if (!NT_SUCCESS(Status))
  558. {
  559. DebugLog((DEB_ERROR,"Failed to load parameters: 0x%x\n",Status));
  560. goto Cleanup;
  561. }
  562. //
  563. // Create the authenticators.
  564. //
  565. //
  566. // In reality, set skew time to 5 minutes and same for authenticators.
  567. //
  568. SkewTime.QuadPart = (LONGLONG) 10000000 * 60 * 5;
  569. MaxAuthenticatorAge = SkewTime;
  570. //
  571. // Create the authenticator list
  572. //
  573. Authenticators = new CAuthenticatorList( MaxAuthenticatorAge );
  574. if (Authenticators == NULL)
  575. {
  576. Status = STATUS_INSUFFICIENT_RESOURCES;
  577. goto Cleanup;
  578. }
  579. //
  580. // Setup a list to track failed requests - we don't fail the
  581. // same request twice for the timeout time
  582. //
  583. FailedRequests = new CAuthenticatorList( MaxAuthenticatorAge );
  584. if (FailedRequests == NULL)
  585. {
  586. Status = STATUS_INSUFFICIENT_RESOURCES;
  587. goto Cleanup;
  588. }
  589. //
  590. // Register for policy callbacks
  591. //
  592. Status = LsaIRegisterPolicyChangeNotificationCallback(
  593. KdcPolicyChangeCallBack,
  594. PolicyNotifyDomainKerberosTicketInformation
  595. );
  596. if (NT_SUCCESS(Status))
  597. {
  598. Status = LsaIRegisterPolicyChangeNotificationCallback(
  599. KdcPolicyChangeCallBack,
  600. PolicyNotifyAuditEventsInformation
  601. );
  602. }
  603. if (!NT_SUCCESS(Status))
  604. {
  605. DebugLog((DEB_ERROR,"Failed to register for policy changes: 0x%x\n",Status));
  606. goto Cleanup;
  607. }
  608. Status = UpdateKrbtgtTicketInfo();
  609. if (!NT_SUCCESS(Status))
  610. {
  611. goto Cleanup;
  612. }
  613. Cleanup:
  614. if (PolicyInfo != NULL)
  615. {
  616. LsaIFree_LSAPR_POLICY_INFORMATION(
  617. PolicyDnsDomainInformation,
  618. PolicyInfo
  619. );
  620. }
  621. return(Status);
  622. }
  623. //+---------------------------------------------------------------------------
  624. //
  625. // Member: CSecurityData::~CSecurityData
  626. //
  627. // Synopsis: Destructor
  628. //
  629. // Effects: Frees memory
  630. //
  631. // Arguments: (none)
  632. //
  633. // History: 4-02-93 WadeR Created
  634. //
  635. // Notes:
  636. //
  637. //----------------------------------------------------------------------------
  638. VOID
  639. CSecurityData::Cleanup()
  640. {
  641. TRACE(KDC, CSecurityData::Cleanup, DEB_FUNCTION);
  642. KerbFreeString(&_RealmName);
  643. KerbFreeString(&_KDC_Name);
  644. KerbFreeString(&_KDC_FullName);
  645. KerbFreeString(&_KDC_FullDnsName);
  646. KerbFreeString(&_KDC_FullKdcName);
  647. KerbFreeString(&_MachineName);
  648. KerbFreeString(&_MachineUpn);
  649. KerbFreeString(&_DnsRealmName);
  650. KerbFreeRealm(&_KerbRealmName);
  651. KerbFreeRealm(&_KerbDnsRealmName);
  652. KerbFreeKdcName(&_KrbtgtServiceName);
  653. KerbFreeKdcName(&_KpasswdServiceName);
  654. if (Authenticators != NULL)
  655. {
  656. delete Authenticators;
  657. Authenticators = NULL;
  658. }
  659. if (FailedRequests != NULL)
  660. {
  661. delete FailedRequests;
  662. FailedRequests = NULL;
  663. }
  664. LsaIUnregisterAllPolicyChangeNotificationCallback(
  665. KdcPolicyChangeCallBack
  666. );
  667. }
  668. //+---------------------------------------------------------------------------
  669. //
  670. // Member: CSecurityData::~CSecurityData
  671. //
  672. // Synopsis: Destructor
  673. //
  674. // Effects: Frees memory
  675. //
  676. // Arguments: (none)
  677. //
  678. // History: 4-02-93 WadeR Created
  679. //
  680. // Notes:
  681. //
  682. //----------------------------------------------------------------------------
  683. CSecurityData::~CSecurityData()
  684. {
  685. TRACE(KDC, CSecurityData::~CSecurityData, DEB_FUNCTION);
  686. Cleanup();
  687. //
  688. // This doesn't happen during Cleanup() because we want to
  689. // make sure it only happens once.
  690. //
  691. RtlDeleteCriticalSection(&_Monitor);
  692. }
  693. NTSTATUS
  694. CSecurityData::LoadParameters(SAMPR_HANDLE DomainHandle)
  695. {
  696. NTSTATUS Status = STATUS_SUCCESS;
  697. LARGE_INTEGER TempDeltaTime;
  698. LARGE_INTEGER OneHour, EightHours, TenHours;
  699. TRACE(KDC, CSecurityData::LoadParameters, DEB_FUNCTION);
  700. OneHour.QuadPart = (LONGLONG) 10000000 * 60 * 60 * 1;
  701. EightHours.QuadPart = (LONGLONG) 10000000 * 60 * 60 * 8;
  702. TenHours.QuadPart = (LONGLONG) 10000000 * 60 * 60 * 10;
  703. // New internal defaults according to JBrezak. 7/28/99
  704. //
  705. // Initialize Tgt lifetime to 10 hours.
  706. //
  707. _KDC_TgtTicketLifespan = TenHours;
  708. //
  709. // Initialize ticket max renew time to one hour.
  710. //
  711. _KDC_TicketRenewSpan = OneHour;
  712. //
  713. // Initialize Tgs lifetime to one hour.
  714. //
  715. _KDC_TgsTicketLifespan = OneHour;
  716. //
  717. // Initialize domain password replication skew tolerance to 60 minutes.
  718. //
  719. _KDC_DomainPasswordReplSkew.QuadPart = (LONGLONG) 60*60*10000000;
  720. //
  721. // Initialize restriciton lifetime to 20 minutes
  722. //
  723. _KDC_RestrictionLifetime.QuadPart = (LONGLONG) 20*60*10000000;
  724. //
  725. // Default authentication flags
  726. //
  727. _KDC_Flags = AUTH_REQ_ALLOW_FORWARDABLE |
  728. AUTH_REQ_ALLOW_PROXIABLE |
  729. AUTH_REQ_ALLOW_POSTDATE |
  730. AUTH_REQ_ALLOW_RENEWABLE |
  731. AUTH_REQ_ALLOW_NOADDRESS |
  732. AUTH_REQ_ALLOW_ENC_TKT_IN_SKEY |
  733. AUTH_REQ_ALLOW_VALIDATE |
  734. AUTH_REQ_VALIDATE_CLIENT |
  735. AUTH_REQ_OK_AS_DELEGATE;
  736. _KDC_AuditEvents = 0;
  737. //
  738. // Get kerberos policy information
  739. //
  740. Status = ReloadPolicy(
  741. PolicyNotifyDomainKerberosTicketInformation
  742. );
  743. if (!NT_SUCCESS(Status))
  744. {
  745. if ((Status != STATUS_NOT_FOUND) && (Status != STATUS_OBJECT_NAME_NOT_FOUND))
  746. {
  747. DebugLog((DEB_ERROR,"Failed to reload kerberos ticket policy: 0x%x\n",Status));
  748. goto Cleanup;
  749. }
  750. Status = STATUS_SUCCESS;
  751. }
  752. //
  753. // Get audit information
  754. //
  755. Status = ReloadPolicy(
  756. PolicyNotifyAuditEventsInformation
  757. );
  758. if (!NT_SUCCESS(Status))
  759. {
  760. if (Status != STATUS_NOT_FOUND)
  761. {
  762. DebugLog((DEB_ERROR,"Failed to query audit event info: 0x%x\n",Status));
  763. goto Cleanup;
  764. }
  765. Status = STATUS_SUCCESS;
  766. }
  767. Cleanup:
  768. #if DBG
  769. DebugShowState();
  770. #endif
  771. return(Status);
  772. }
  773. //+-------------------------------------------------------------------------
  774. //
  775. // Function: CSecurityData::GetKrbtgtTicketInfo
  776. //
  777. // Synopsis: Duplicates ticket info for krbtgt account
  778. //
  779. // Effects:
  780. //
  781. // Arguments:
  782. //
  783. // Requires:
  784. //
  785. // Returns:
  786. //
  787. // Notes:
  788. //
  789. //
  790. //--------------------------------------------------------------------------
  791. KERBERR
  792. CSecurityData::GetKrbtgtTicketInfo(
  793. OUT PKDC_TICKET_INFO TicketInfo
  794. )
  795. {
  796. KERBERR KerbErr = KDC_ERR_NONE;
  797. ULONG CredentialSize;
  798. RtlZeroMemory(
  799. TicketInfo,
  800. sizeof(KDC_TICKET_INFO)
  801. );
  802. ReadLock();
  803. if (!_KrbtgtTicketInfoValid)
  804. {
  805. KerbErr = KDC_ERR_S_PRINCIPAL_UNKNOWN;
  806. goto Cleanup;
  807. }
  808. //
  809. // Duplicate the cached copy of the KRBTGT information
  810. //
  811. *TicketInfo = _KrbtgtTicketInfo;
  812. TicketInfo->Passwords = NULL;
  813. TicketInfo->OldPasswords = NULL;
  814. TicketInfo->TrustSid = NULL;
  815. TicketInfo->AccountName.Buffer = NULL;
  816. if (!NT_SUCCESS(KerbDuplicateString(
  817. &TicketInfo->AccountName,
  818. &_KrbtgtTicketInfo.AccountName
  819. )))
  820. {
  821. KerbErr = KRB_ERR_GENERIC;
  822. goto Cleanup;
  823. }
  824. KerbErr = KdcDuplicateCredentials(
  825. &TicketInfo->Passwords,
  826. &CredentialSize,
  827. _KrbtgtTicketInfo.Passwords,
  828. FALSE // don't marshall
  829. );
  830. if (!KERB_SUCCESS(KerbErr))
  831. {
  832. goto Cleanup;
  833. }
  834. KerbErr = KdcDuplicateCredentials(
  835. &TicketInfo->OldPasswords,
  836. &CredentialSize,
  837. _KrbtgtTicketInfo.OldPasswords,
  838. FALSE // don't marshall
  839. );
  840. Cleanup:
  841. Release();
  842. if (!KERB_SUCCESS(KerbErr))
  843. {
  844. FreeTicketInfo(TicketInfo);
  845. }
  846. return(KerbErr);
  847. }
  848. //+-------------------------------------------------------------------------
  849. //
  850. // Function: CSecurityData::UpdateKrbtgtTicketInfo
  851. //
  852. // Synopsis: Triggers an update of the krbtgt ticket info
  853. //
  854. // Effects:
  855. //
  856. // Arguments:
  857. //
  858. // Requires:
  859. //
  860. // Returns:
  861. //
  862. // Notes:
  863. //
  864. //
  865. //--------------------------------------------------------------------------
  866. NTSTATUS
  867. CSecurityData::UpdateKrbtgtTicketInfo(
  868. VOID
  869. )
  870. {
  871. NTSTATUS Status = STATUS_SUCCESS;
  872. KERBERR KerbErr;
  873. KDC_TICKET_INFO NewTicketInfo = {0};
  874. PUSER_INTERNAL6_INFORMATION UserInfo = NULL;
  875. KERB_EXT_ERROR ExtendedError; // dummy var
  876. ReadLock();
  877. _KrbtgtTicketInfoValid = FALSE;
  878. KerbErr = KdcGetTicketInfo(
  879. SecData.KdcServiceName(),
  880. 0, // no lookup flags
  881. NULL, // no principal name
  882. NULL, // no realm
  883. &NewTicketInfo,
  884. &ExtendedError, // dummy
  885. NULL, // no user handle
  886. USER_ALL_PASSWORDLASTSET,
  887. 0L, // no extended fields
  888. &UserInfo,
  889. NULL // no group membership
  890. );
  891. if (KERB_SUCCESS(KerbErr))
  892. {
  893. FreeTicketInfo(
  894. &_KrbtgtTicketInfo
  895. );
  896. _KrbtgtTicketInfo = NewTicketInfo;
  897. _KrbtgtTicketInfoValid = TRUE;
  898. _KrbtgtPasswordLastSet = UserInfo->I1.PasswordLastSet;
  899. SamIFree_UserInternal6Information( UserInfo );
  900. }
  901. else
  902. {
  903. Status = KerbMapKerbError(KerbErr);
  904. }
  905. Release();
  906. return(Status);
  907. }
  908. //+-------------------------------------------------------------------------
  909. //
  910. // Function: KdcAccountChangeNotificationRoutine
  911. //
  912. // Synopsis: Receives notification of changes to interesting accounts
  913. //
  914. // Effects: updatees cached krbtgt information
  915. //
  916. // Arguments:
  917. //
  918. // Requires:
  919. //
  920. // Returns:
  921. //
  922. // Notes:
  923. //
  924. //
  925. //--------------------------------------------------------------------------
  926. NTSTATUS
  927. KdcAccountChangeNotification (
  928. IN PSID DomainSid,
  929. IN SECURITY_DB_DELTA_TYPE DeltaType,
  930. IN SECURITY_DB_OBJECT_TYPE ObjectType,
  931. IN ULONG ObjectRid,
  932. IN OPTIONAL PUNICODE_STRING ObjectName,
  933. IN PLARGE_INTEGER ModifiedCount,
  934. IN PSAM_DELTA_DATA DeltaData OPTIONAL
  935. )
  936. {
  937. NTSTATUS Status;
  938. //
  939. // We are only interested in the krbtgt account
  940. //
  941. if (ObjectRid != DOMAIN_USER_RID_KRBTGT)
  942. {
  943. return(STATUS_SUCCESS);
  944. }
  945. Status = SecData.UpdateKrbtgtTicketInfo();
  946. if (!NT_SUCCESS(Status))
  947. {
  948. DebugLog((DEB_ERROR,"Failed to update krbtgt ticket info: 0x%x\n",Status));
  949. }
  950. return(Status);
  951. }
  952. #if DBG
  953. ////////////////////////////////////////////////////////////////////////////
  954. //
  955. // Some debugging functions.
  956. //
  957. void
  958. CSecurityData::DebugShowState(void)
  959. {
  960. TRACE(KDC, CSecurityData::DebugShowState, DEB_FUNCTION);
  961. PrintTime(DEB_TRACE, " TGT Ticket lifespan\t", &_KDC_TgtTicketLifespan );
  962. PrintTime(DEB_TRACE, " Ticket Renew Span\t",&_KDC_TicketRenewSpan );
  963. D_DebugLog((DEB_TRACE, " Blank Addresses?\t%s\n",(_KDC_Flags & AUTH_REQ_ALLOW_NOADDRESS ? "Yes" : "No")));
  964. D_DebugLog((DEB_TRACE, " Proxies? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_PROXIABLE ? "Yes" : "No")));
  965. D_DebugLog((DEB_TRACE, " Renewable? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_RENEWABLE ? "Yes" : "No")));
  966. D_DebugLog((DEB_TRACE, " Postdated? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_POSTDATE ? "Yes" : "No")));
  967. D_DebugLog((DEB_TRACE, " Forwardable? \t%s\n", (_KDC_Flags & AUTH_REQ_ALLOW_FORWARDABLE ? "Yes" : "No")));
  968. }
  969. NTSTATUS
  970. CSecurityData::DebugGetState( DWORD * KDCFlags,
  971. TimeStamp * MaxLifespan,
  972. TimeStamp * MaxRenewSpan)
  973. {
  974. TRACE(KDC, CSecurityData::DebugGetState, DEB_FUNCTION);
  975. *KDCFlags = _KDC_Flags;
  976. *MaxLifespan = _KDC_TgtTicketLifespan;
  977. *MaxRenewSpan = _KDC_TicketRenewSpan;
  978. return(STATUS_SUCCESS);
  979. }
  980. NTSTATUS
  981. CSecurityData::DebugSetState( DWORD KDCFlags,
  982. TimeStamp MaxLifespan,
  983. TimeStamp MaxRenewSpan)
  984. {
  985. TRACE(KDC, CSecurityData::DebugSetState, DEB_FUNCTION);
  986. _KDC_Flags = KDC_AUTH_STATE(KDCFlags);
  987. _KDC_AuditEvents = KDC_AUDIT_STATE(KDCFlags);
  988. _KDC_TgtTicketLifespan = MaxLifespan;
  989. _KDC_TicketRenewSpan = MaxRenewSpan;
  990. return(STATUS_SUCCESS);
  991. }
  992. #endif // DBG