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.

902 lines
24 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: debug.cxx
  7. //
  8. // Contents: Debug definitions that shouldn't be necessary
  9. // in the retail build.
  10. //
  11. // History: 19-Nov-92 WadeR Created
  12. //
  13. // Notes: If you change or add a debug level, also fix debug.hxx
  14. // This is only compiled if DBG > 0
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "kdcsvr.hxx"
  18. #include <kdcdbg.h>
  19. #include "debug.hxx"
  20. //
  21. // The "#pragma hdrstop" causes the preprocessor to forget any "#if"s
  22. // is is processing. Therefore you can't have it inside an "#if" block.
  23. // So the includes will always compile, and the rest of this code becomes
  24. // conditional.
  25. //
  26. #include <stddef.h>
  27. #ifdef RETAIL_LOG_SUPPORT
  28. //
  29. // Variables for heap checking and used by sectrace.hxx:
  30. //
  31. // Set following to HEAP_CHECK_ON_ENTER | HEAP_CHECK_ON_EXIT for heap checking.
  32. DWORD dwHeapChecking = 0;
  33. // This keeps a registry key handle to the HKLM\System\CCSet\Control\LSA\
  34. // Kerberoskey
  35. HKEY hKerbParams = NULL;
  36. HANDLE hKerbWait = NULL;
  37. //
  38. // Tons and tons of global data to get debugging params from the ini file.
  39. //
  40. // Note: For every trace bit, there must be a label in this array matching
  41. // that trace bit and only that trace bit. There can be other labels
  42. // matching combinations of trace bits.
  43. //
  44. DEBUG_KEY KdcDebugKeys[] = { {DEB_ERROR, "Error"},
  45. {DEB_WARN, "Warning"},
  46. {DEB_TRACE, "Trace"},
  47. {DEB_T_KDC, "Kdc"},
  48. {DEB_T_TICKETS, "Tickets"},
  49. {DEB_T_DOMAIN, "Domain"},
  50. {DEB_T_SOCK, "Sock"},
  51. {DEB_T_TIME, "Time"},
  52. {DEB_T_TRANSIT, "Transit"},
  53. {DEB_T_PERF_STATS, "Perf"},
  54. {DEB_T_PKI, "PKI"},
  55. {DEB_T_PAPI, "PAPI"},
  56. {DEB_T_U2U, "U2U"},
  57. {DEB_T_PAC, "PAC"},
  58. {DEB_T_KEY, "KEY"},
  59. {DEB_T_S4U, "S4U"},
  60. {0, NULL},
  61. };
  62. DEFINE_DEBUG2(KDC);
  63. VOID
  64. FillExtendedError(
  65. IN NTSTATUS NtStatus,
  66. IN ULONG Flags,
  67. IN ULONG FileNum,
  68. IN ULONG LineNum,
  69. OUT PKERB_EXT_ERROR ExtendedError
  70. )
  71. {
  72. ExtendedError->status = NtStatus;
  73. ExtendedError->klininfo = EXT_ERROR_ON(KDCInfoLevel) ? KLIN(FileNum, LineNum) : 0;
  74. ExtendedError->flags = Flags;
  75. }
  76. ////////////////////////////////////////////////////////////////////
  77. //
  78. // Name: GetDebugParams
  79. //
  80. // Synopsis: Gets the debug paramaters from the ini file.
  81. //
  82. // Arguments: <none>
  83. //
  84. // Notes: .
  85. //
  86. void
  87. GetDebugParams()
  88. {
  89. KDCInitDebug(KdcDebugKeys);
  90. }
  91. #if DBG // moved here to utilize debug logging in free builds.
  92. NTSTATUS
  93. KDC_GetState( handle_t hBinding,
  94. DWORD * KDCFlags,
  95. DWORD * MaxLifespan,
  96. DWORD * MaxRenewSpan,
  97. PTimeStamp FudgeFactor)
  98. {
  99. *FudgeFactor = SkewTime;
  100. TimeStamp tsLife, tsRenew;
  101. NTSTATUS hr = SecData.DebugGetState(KDCFlags, &tsLife, &tsRenew );
  102. tsLife.QuadPart = (tsLife.QuadPart / ulTsPerSecond);
  103. *MaxLifespan =tsLife.LowPart;
  104. tsRenew.QuadPart = (tsRenew.QuadPart / ulTsPerSecond);
  105. *MaxRenewSpan = tsRenew.LowPart;
  106. return(hr);
  107. }
  108. NTSTATUS
  109. KDC_SetState( handle_t hBinding,
  110. DWORD KdcFlags,
  111. DWORD MaxLifespan,
  112. DWORD MaxRenewSpan,
  113. TimeStamp FudgeFactor)
  114. {
  115. NTSTATUS hr;
  116. TimeStamp tsLife = {0,0};
  117. TimeStamp tsRenew = {0,0};
  118. if (FudgeFactor.QuadPart != 0)
  119. {
  120. SkewTime = FudgeFactor;
  121. Authenticators->SetMaxAge( SkewTime );
  122. }
  123. tsLife.QuadPart = (LONGLONG) MaxLifespan * 10000000;
  124. tsRenew.QuadPart = (LONGLONG) MaxRenewSpan * 10000000;
  125. if (KdcFlags == 0)
  126. {
  127. KdcFlags = SecData.KdcFlags();
  128. }
  129. if (MaxLifespan == 0)
  130. {
  131. tsLife = SecData.KdcTgtTicketLifespan();
  132. }
  133. if (MaxRenewSpan == 0)
  134. {
  135. tsLife = SecData.KdcTicketRenewSpan();
  136. }
  137. hr = SecData.DebugSetState(KdcFlags, tsLife, tsRenew);
  138. SecData.DebugShowState();
  139. return(hr);
  140. }
  141. void PrintIntervalTime (
  142. ULONG DebugFlag,
  143. LPSTR Message,
  144. PLARGE_INTEGER Interval )
  145. {
  146. LONGLONG llTime = Interval->QuadPart;
  147. LONG lSeconds = (LONG) ( llTime / 10000000 );
  148. LONG lMinutes = ( lSeconds / 60 ) % 60;
  149. LONG lHours = ( lSeconds / 3600 );
  150. DebugLog(( DebugFlag, "%s %d:%2.2d:%2.2d \n", Message, lHours, lMinutes, lSeconds % 60 ));
  151. }
  152. void PrintTime (
  153. ULONG DebugFlag,
  154. LPSTR Message,
  155. PLARGE_INTEGER Time )
  156. {
  157. SYSTEMTIME st;
  158. FileTimeToSystemTime ( (PFILETIME) Time, & st );
  159. DebugLog((DebugFlag, "%s %d-%d-%d %d:%2.2d:%2.2d\n", Message, st.wMonth, st.wDay, st.wYear,
  160. st.wHour, st.wMinute, st.wSecond ));
  161. }
  162. #else // DBG
  163. NTSTATUS
  164. KDC_GetState( handle_t hBinding,
  165. DWORD * KDCFlags,
  166. DWORD * MaxLifespan,
  167. DWORD * MaxRenewSpan,
  168. PTimeStamp FudgeFactor)
  169. {
  170. return(STATUS_NOT_SUPPORTED);
  171. }
  172. NTSTATUS
  173. KDC_SetState( handle_t hBinding,
  174. DWORD KDCFlags,
  175. DWORD MaxLifespan,
  176. DWORD MaxRenewSpan,
  177. TimeStamp FudgeFactor)
  178. {
  179. return(STATUS_NOT_SUPPORTED);
  180. }
  181. #endif
  182. #endif
  183. BOOLEAN
  184. KdcSetPassSupported(
  185. VOID
  186. )
  187. {
  188. NET_API_STATUS NetStatus;
  189. ULONG SetPassUnsupported = 0;
  190. LPNET_CONFIG_HANDLE ConfigHandle = NULL;
  191. NetStatus = NetpOpenConfigData(
  192. &ConfigHandle,
  193. NULL, // noserer name
  194. L"kdc",
  195. TRUE // read only
  196. );
  197. if (NetStatus != NO_ERROR)
  198. {
  199. return(TRUE);
  200. }
  201. NetStatus = NetpGetConfigDword(
  202. ConfigHandle,
  203. L"SetPassUnsupported",
  204. 0,
  205. &SetPassUnsupported
  206. );
  207. NetpCloseConfigData( ConfigHandle );
  208. if ((NetStatus == NO_ERROR) && (SetPassUnsupported == 1))
  209. {
  210. return(FALSE);
  211. }
  212. else
  213. {
  214. return(TRUE);
  215. }
  216. }
  217. //+-------------------------------------------------------------------------
  218. //
  219. // Function: KDC_SetPassword
  220. //
  221. // Synopsis: Sets password for an account
  222. //
  223. // Effects:
  224. //
  225. // Arguments:
  226. //
  227. // Requires:
  228. //
  229. // Returns:
  230. //
  231. // Notes:
  232. //
  233. //
  234. //--------------------------------------------------------------------------
  235. NTSTATUS
  236. KDC_SetPassword(
  237. IN handle_t hBinding,
  238. IN PUNICODE_STRING UserName,
  239. IN PUNICODE_STRING PrincipalName,
  240. IN PUNICODE_STRING Password,
  241. IN ULONG Flags
  242. )
  243. {
  244. NTSTATUS Status = STATUS_SUCCESS;
  245. KERBERR KerbErr;
  246. SECPKG_SUPPLEMENTAL_CRED Credentials;
  247. KDC_TICKET_INFO TicketInfo;
  248. SAMPR_HANDLE UserHandle = NULL;
  249. KERB_EXT_ERROR ExtendedError; // dummy var.
  250. Credentials.Credentials = NULL;
  251. if (!KdcSetPassSupported())
  252. {
  253. Status = STATUS_NOT_SUPPORTED;
  254. goto Cleanup;
  255. }
  256. //
  257. // Make sure we can impersonate the caller.
  258. //
  259. if (RpcImpersonateClient(NULL) != ERROR_SUCCESS)
  260. {
  261. Status = STATUS_ACCESS_DENIED;
  262. goto Cleanup;
  263. }
  264. else
  265. {
  266. RpcRevertToSelf();
  267. }
  268. // According to bug 228139, rpc definition of unicode strings allow
  269. // for odd lengths. We will set them to even (1 less) so that we
  270. // don't av in the lsa.
  271. if (ARGUMENT_PRESENT(UserName) && UserName->Buffer)
  272. {
  273. UserName->Length = (UserName->Length/sizeof(WCHAR)) * sizeof(WCHAR);
  274. }
  275. else
  276. {
  277. Status = STATUS_INVALID_PARAMETER;
  278. goto Cleanup;
  279. }
  280. KerbErr = KdcGetTicketInfo(
  281. UserName,
  282. 0, // no flags
  283. FALSE, // do not restrict user accounts (user2user)
  284. NULL,
  285. NULL,
  286. &TicketInfo,
  287. &ExtendedError,
  288. &UserHandle,
  289. 0L, // no fields to fetch
  290. 0L, // no extended fields
  291. NULL, // no user all
  292. NULL
  293. );
  294. if (!KERB_SUCCESS(KerbErr))
  295. {
  296. DebugLog((DEB_ERROR, "Failed to get ticket info for %wZ: 0x%x\n",
  297. UserName, KerbErr ));
  298. Status = STATUS_NO_SUCH_USER;
  299. goto Cleanup;
  300. }
  301. FreeTicketInfo(&TicketInfo);
  302. if (ARGUMENT_PRESENT(Password) && Password->Buffer)
  303. {
  304. Password->Length = (Password->Length/sizeof(WCHAR)) * sizeof(WCHAR);
  305. }
  306. else
  307. {
  308. Status = STATUS_INVALID_PARAMETER;
  309. goto Cleanup;
  310. }
  311. if (ARGUMENT_PRESENT(PrincipalName) && PrincipalName->Buffer)
  312. {
  313. PrincipalName->Length = (PrincipalName->Length/sizeof(WCHAR)) * sizeof(WCHAR);
  314. }
  315. else
  316. {
  317. Status = STATUS_INVALID_PARAMETER;
  318. goto Cleanup;
  319. }
  320. Status = KdcBuildPasswordList(
  321. Password,
  322. PrincipalName,
  323. SecData.KdcDnsRealmName(),
  324. UnknownAccount,
  325. NULL, // no stored creds
  326. 0, // no stored creds
  327. TRUE, // marshall
  328. FALSE, // don't include builtins
  329. Flags,
  330. Unknown,
  331. (PKERB_STORED_CREDENTIAL *) &Credentials.Credentials,
  332. &Credentials.CredentialSize
  333. );
  334. if (!NT_SUCCESS(Status))
  335. {
  336. goto Cleanup;
  337. }
  338. RtlInitUnicodeString(
  339. &Credentials.PackageName,
  340. MICROSOFT_KERBEROS_NAME_W
  341. );
  342. Status = SamIStorePrimaryCredentials(
  343. UserHandle,
  344. &Credentials
  345. );
  346. if (!NT_SUCCESS(Status))
  347. {
  348. DebugLog((DEB_ERROR, "Failed to store primary credentials: 0x%x\n",Status));
  349. goto Cleanup;
  350. }
  351. Cleanup:
  352. if (UserHandle != NULL)
  353. {
  354. SamrCloseHandle(&UserHandle);
  355. }
  356. if (Credentials.Credentials != NULL)
  357. {
  358. MIDL_user_free(Credentials.Credentials);
  359. }
  360. return(Status);
  361. }
  362. NTSTATUS
  363. KDC_GetDomainList(
  364. IN handle_t hBinding,
  365. OUT PKDC_DBG_DOMAIN_LIST * DomainList
  366. )
  367. {
  368. NTSTATUS Status = STATUS_SUCCESS;
  369. PKDC_DBG_DOMAIN_LIST TempList;
  370. PKDC_DBG_DOMAIN_INFO DomainInfo = NULL;
  371. PKDC_DOMAIN_INFO Domain;
  372. ULONG DomainCount = 0;
  373. PLIST_ENTRY ListEntry;
  374. ULONG Index = 0;
  375. *DomainList = NULL;
  376. KdcLockDomainListFn();
  377. TempList = (PKDC_DBG_DOMAIN_LIST) MIDL_user_allocate(sizeof(KDC_DBG_DOMAIN_LIST));
  378. if (TempList == NULL)
  379. {
  380. Status = STATUS_INSUFFICIENT_RESOURCES;
  381. goto Cleanup;
  382. }
  383. for (ListEntry = KdcDomainList.Flink;
  384. ListEntry != &KdcDomainList ;
  385. ListEntry = ListEntry->Flink )
  386. {
  387. DomainCount++;
  388. }
  389. DomainInfo = (PKDC_DBG_DOMAIN_INFO) MIDL_user_allocate(DomainCount * sizeof(KDC_DBG_DOMAIN_INFO));
  390. if (DomainInfo == NULL)
  391. {
  392. Status = STATUS_INSUFFICIENT_RESOURCES;
  393. goto Cleanup;
  394. }
  395. RtlZeroMemory(
  396. DomainInfo,
  397. DomainCount * sizeof(KDC_DBG_DOMAIN_INFO)
  398. );
  399. Index = 0;
  400. for (ListEntry = KdcDomainList.Flink;
  401. ListEntry != &KdcDomainList ;
  402. ListEntry = ListEntry->Flink )
  403. {
  404. Domain = (PKDC_DOMAIN_INFO) CONTAINING_RECORD(ListEntry, KDC_DOMAIN_INFO, Next);
  405. KerbDuplicateString(
  406. &DomainInfo[Index].DnsName,
  407. &Domain->DnsName
  408. );
  409. KerbDuplicateString(
  410. &DomainInfo[Index].NetbiosName,
  411. &Domain->NetbiosName
  412. );
  413. if (Domain->ClosestRoute != NULL)
  414. {
  415. KerbDuplicateString(
  416. &DomainInfo[Index].ClosestRoute,
  417. &Domain->ClosestRoute->DnsName
  418. );
  419. }
  420. DomainInfo->Type = Domain->Type;
  421. DomainInfo->Attributes = Domain->Attributes;
  422. Index++;
  423. }
  424. TempList->Count = DomainCount;
  425. TempList->Domains = DomainInfo;
  426. *DomainList = TempList;
  427. TempList = NULL;
  428. DomainInfo = NULL;
  429. Cleanup:
  430. KdcUnlockDomainListFn();
  431. if (TempList != NULL)
  432. {
  433. MIDL_user_free(TempList);
  434. }
  435. if (DomainInfo != NULL)
  436. {
  437. MIDL_user_free(DomainInfo);
  438. }
  439. return(Status);
  440. }
  441. VOID
  442. KdcCopyKeyData(
  443. OUT PKERB_KEY_DATA NewKey,
  444. IN PKERB_KEY_DATA OldKey,
  445. IN OUT PBYTE * Where,
  446. IN LONG_PTR Offset
  447. )
  448. {
  449. //
  450. // Copy the key
  451. //
  452. NewKey->Key.keytype = OldKey->Key.keytype;
  453. NewKey->Key.keyvalue.length = OldKey->Key.keyvalue.length;
  454. NewKey->Key.keyvalue.value = (*Where) - Offset;
  455. RtlCopyMemory(
  456. (*Where),
  457. OldKey->Key.keyvalue.value,
  458. OldKey->Key.keyvalue.length
  459. );
  460. (*Where) += OldKey->Key.keyvalue.length;
  461. //
  462. // Copy the salt
  463. //
  464. if (OldKey->Salt.Buffer != NULL)
  465. {
  466. NewKey->Salt.Length =
  467. NewKey->Salt.MaximumLength =
  468. OldKey->Salt.Length;
  469. NewKey->Salt.Buffer = (LPWSTR) ((*Where) - Offset);
  470. RtlCopyMemory(
  471. (*Where),
  472. OldKey->Salt.Buffer,
  473. OldKey->Salt.Length
  474. );
  475. (*Where) += OldKey->Salt.Length;
  476. }
  477. }
  478. //+-------------------------------------------------------------------------
  479. //
  480. // Function: KDC_SetAccountKeys
  481. //
  482. // Synopsis: Set the keys for an account
  483. //
  484. // Effects:
  485. //
  486. // Arguments:
  487. //
  488. // Requires:
  489. //
  490. // Returns:
  491. //
  492. // Notes:
  493. //
  494. //
  495. //--------------------------------------------------------------------------
  496. NTSTATUS
  497. KDC_SetAccountKeys(
  498. IN handle_t hBinding,
  499. IN PUNICODE_STRING UserName,
  500. IN ULONG Flags,
  501. IN PKERB_STORED_CREDENTIAL Keys
  502. )
  503. {
  504. NTSTATUS Status = STATUS_SUCCESS;
  505. KERBERR KerbErr;
  506. KERB_EXT_ERROR ExtendedError; // dummy var
  507. SECPKG_SUPPLEMENTAL_CRED Credentials = {0};
  508. KDC_TICKET_INFO TicketInfo= {0};
  509. SAMPR_HANDLE UserHandle = NULL;
  510. PKERB_STORED_CREDENTIAL StoredCreds = NULL;
  511. PKERB_STORED_CREDENTIAL Passwords = NULL;
  512. ULONG StoredCredSize = 0;
  513. ULONG CredentialCount = 0;
  514. ULONG CredentialIndex = 0;
  515. ULONG Index;
  516. PBYTE Where;
  517. UNICODE_STRING DefaultSalt;
  518. LONG_PTR Offset;
  519. if (!KdcSetPassSupported())
  520. {
  521. Status = STATUS_NOT_SUPPORTED;
  522. goto Cleanup;
  523. }
  524. //
  525. // Make sure we can impersonate the caller.
  526. //
  527. if (RpcImpersonateClient(NULL) != ERROR_SUCCESS)
  528. {
  529. Status = STATUS_ACCESS_DENIED;
  530. goto Cleanup;
  531. }
  532. else
  533. {
  534. RpcRevertToSelf();
  535. }
  536. // According to bug 228139, rpc definition of unicode strings allow
  537. // for odd lengths. We will set them to even (1 less) so that we
  538. // don't av in the lsa.
  539. if (ARGUMENT_PRESENT(UserName) && UserName->Buffer)
  540. {
  541. UserName->Length = (UserName->Length/sizeof(WCHAR)) * sizeof(WCHAR);
  542. }
  543. else
  544. {
  545. Status = STATUS_INVALID_PARAMETER;
  546. goto Cleanup;
  547. }
  548. KerbErr = KdcGetTicketInfo(
  549. UserName,
  550. 0, // no flags
  551. FALSE, // do not restrict user accounts (user2user)
  552. NULL,
  553. NULL,
  554. &TicketInfo,
  555. &ExtendedError,
  556. &UserHandle,
  557. 0L, // no fields to fetch
  558. 0L, // no extended fields
  559. NULL, // no user all
  560. NULL
  561. );
  562. if (!KERB_SUCCESS(KerbErr))
  563. {
  564. DebugLog((DEB_ERROR, "Failed to get ticket info for %wZ: 0x%x\n",
  565. UserName, KerbErr ));
  566. Status = STATUS_NO_SUCH_USER;
  567. goto Cleanup;
  568. }
  569. //
  570. // If the caller asks us to replace keys, then clobber all supplemental
  571. // creds with the new ones. Otherwise, just replace the current ones
  572. // with the old ones
  573. //
  574. Passwords = TicketInfo.Passwords;
  575. if ((Flags & KERB_SET_KEYS_REPLACE) ||
  576. (Passwords == NULL))
  577. {
  578. KerbErr = KdcDuplicateCredentials(
  579. &StoredCreds,
  580. &StoredCredSize,
  581. Keys,
  582. TRUE // marshall
  583. );
  584. if (!KERB_SUCCESS(KerbErr))
  585. {
  586. Status = KerbMapKerbError(KerbErr);
  587. goto Cleanup;
  588. }
  589. }
  590. else
  591. {
  592. if (Keys->OldCredentialCount != 0)
  593. {
  594. DebugLog((DEB_ERROR,"OldCredentialCount supplied with merge-in keys - illegal\n"));
  595. Status = STATUS_INVALID_PARAMETER;
  596. goto Cleanup;
  597. }
  598. //
  599. // Calculate the size of the stored creds.
  600. //
  601. StoredCredSize = FIELD_OFFSET(KERB_STORED_CREDENTIAL,Credentials) +
  602. Keys->CredentialCount * sizeof(KERB_KEY_DATA) +
  603. Keys->DefaultSalt.Length;
  604. for (Index = 0; Index < Keys->CredentialCount; Index++ )
  605. {
  606. StoredCredSize += Keys->Credentials[Index].Salt.Length +
  607. Keys->Credentials[Index].Key.keyvalue.length;
  608. CredentialCount++;
  609. }
  610. //
  611. // Add in the keys that aren't in the supplied ones
  612. //
  613. if (Keys->DefaultSalt.Buffer == NULL)
  614. {
  615. StoredCredSize += Passwords->DefaultSalt.Length;
  616. }
  617. //
  618. // Add the size for all the keys in the passwords that weren't
  619. // in the passed in keys
  620. //
  621. for (Index = 0; Index < Passwords->CredentialCount ; Index++ )
  622. {
  623. if (KerbGetKeyFromList(Keys, Passwords->Credentials[Index].Key.keytype) == NULL)
  624. {
  625. //
  626. // Make sure it is not a builtin
  627. //
  628. if ((Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_LM) ||
  629. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_MD4) ||
  630. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD) ||
  631. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD_EXP) ||
  632. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT) ||
  633. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT_EXP) ||
  634. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_NULL))
  635. {
  636. continue;
  637. }
  638. StoredCredSize += Passwords->Credentials[Index].Salt.Length
  639. + Passwords->Credentials[Index].Key.keyvalue.length
  640. + sizeof(KERB_KEY_DATA);
  641. CredentialCount++;
  642. }
  643. }
  644. //
  645. // Add in the old keys
  646. //
  647. for (Index = 0; Index < Passwords->OldCredentialCount; Index++ )
  648. {
  649. StoredCredSize += sizeof(KERB_KEY_DATA) +
  650. Passwords->Credentials[Index + Passwords->OldCredentialCount].Salt.Length +
  651. Passwords->Credentials[Index + Passwords->OldCredentialCount].Key.keyvalue.length;
  652. }
  653. //
  654. // Allocate a new buffer to contain the marshalled keys
  655. //
  656. StoredCreds = (PKERB_STORED_CREDENTIAL) MIDL_user_allocate(StoredCredSize);
  657. if (StoredCreds == NULL)
  658. {
  659. Status = STATUS_INSUFFICIENT_RESOURCES;
  660. goto Cleanup;
  661. }
  662. RtlZeroMemory(
  663. StoredCreds,
  664. StoredCredSize
  665. );
  666. //
  667. // Set the standard bits
  668. //
  669. StoredCreds->Revision = KERB_PRIMARY_CRED_REVISION;
  670. StoredCreds->Flags = 0;
  671. Offset = (LONG_PTR) StoredCreds;
  672. Where = (PBYTE) &(StoredCreds->Credentials[CredentialCount + Passwords->OldCredentialCount]);
  673. //
  674. // Copy in the default salt.
  675. //
  676. if (Keys->DefaultSalt.Buffer != NULL)
  677. {
  678. DefaultSalt = Keys->DefaultSalt;
  679. }
  680. else
  681. {
  682. DefaultSalt = Passwords->DefaultSalt;
  683. }
  684. if (DefaultSalt.Buffer != NULL)
  685. {
  686. StoredCreds->DefaultSalt.Length =
  687. StoredCreds->DefaultSalt.MaximumLength = DefaultSalt.Length;
  688. StoredCreds->DefaultSalt.Buffer = (LPWSTR) (Where - Offset);
  689. RtlCopyMemory(
  690. Where,
  691. DefaultSalt.Buffer,
  692. DefaultSalt.Length
  693. );
  694. Where += DefaultSalt.Length;
  695. }
  696. //
  697. // Copy in all the new keys
  698. //
  699. for (Index = 0; Index < Keys->CredentialCount ; Index++ )
  700. {
  701. KdcCopyKeyData(
  702. &StoredCreds->Credentials[CredentialIndex],
  703. &Keys->Credentials[Index],
  704. &Where,
  705. Offset
  706. );
  707. CredentialIndex++;
  708. }
  709. //
  710. // Copy in the existing keys
  711. //
  712. for (Index = 0; Index < Passwords->CredentialCount ; Index++ )
  713. {
  714. if (KerbGetKeyFromList(Keys, Passwords->Credentials[Index].Key.keytype) == NULL)
  715. {
  716. if ((Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_LM) ||
  717. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_MD4) ||
  718. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD) ||
  719. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_OLD_EXP) ||
  720. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT) ||
  721. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_RC4_HMAC_NT_EXP) ||
  722. (Passwords->Credentials[Index].Key.keytype == KERB_ETYPE_NULL))
  723. {
  724. continue;
  725. }
  726. KdcCopyKeyData(
  727. &StoredCreds->Credentials[CredentialIndex],
  728. &Passwords->Credentials[Index],
  729. &Where,
  730. Offset
  731. );
  732. CredentialIndex++;
  733. }
  734. }
  735. StoredCreds->CredentialCount = (USHORT) CredentialIndex;
  736. //
  737. // Copy in the old keys from the existing keys
  738. //
  739. for (Index = 0; Index < Passwords->OldCredentialCount; Index++ )
  740. {
  741. KdcCopyKeyData(
  742. &StoredCreds->Credentials[CredentialIndex],
  743. &Passwords->Credentials[Index + Passwords->OldCredentialCount],
  744. &Where,
  745. Offset
  746. );
  747. CredentialIndex++;
  748. }
  749. StoredCreds->OldCredentialCount = Passwords->OldCredentialCount;
  750. }
  751. RtlInitUnicodeString(
  752. &Credentials.PackageName,
  753. MICROSOFT_KERBEROS_NAME_W
  754. );
  755. Credentials.Credentials = (PBYTE) StoredCreds;
  756. Credentials.CredentialSize = StoredCredSize;
  757. Status = SamIStorePrimaryCredentials(
  758. UserHandle,
  759. &Credentials
  760. );
  761. if (!NT_SUCCESS(Status))
  762. {
  763. DebugLog((DEB_ERROR, "Failed to store primary credentials: 0x%x\n",Status));
  764. goto Cleanup;
  765. }
  766. Cleanup:
  767. FreeTicketInfo(&TicketInfo);
  768. if (UserHandle != NULL)
  769. {
  770. SamrCloseHandle(&UserHandle);
  771. }
  772. if (StoredCreds != NULL)
  773. {
  774. MIDL_user_free(StoredCreds);
  775. }
  776. return(Status);
  777. }