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.

4439 lines
107 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1991 - 1992
  6. //
  7. // File: tickets.c
  8. //
  9. // Contents: Ticket bundling code
  10. //
  11. //
  12. // History: 6 Dec 91, RichardW Created
  13. // 04 Jun 92 RichardW NT-ized
  14. // 08-Jun-93 WadeR Converted to C++, rewrote packing code
  15. //
  16. //------------------------------------------------------------------------
  17. #ifdef WIN32_CHICAGO
  18. #include<kerb.hxx>
  19. #include<kerbp.h>
  20. #endif // WIN32_CHICAGO
  21. #ifndef WIN32_CHICAGO
  22. extern "C"
  23. {
  24. #include "krbprgma.h"
  25. #include <nt.h>
  26. #include <ntrtl.h>
  27. #include <nturtl.h>
  28. #include <windows.h>
  29. #include <ntlsa.h>
  30. #include <samrpc.h>
  31. #include <samisrv.h>
  32. #include <lsarpc.h>
  33. #include <lsaisrv.h>
  34. #include <lsaitf.h>
  35. #include <wincrypt.h>
  36. }
  37. #include <kerbcomm.h>
  38. #include <kerberr.h>
  39. #include <kerbcon.h>
  40. #include <midles.h>
  41. #include <authen.hxx>
  42. #include <kerberos.h>
  43. #include "debug.h"
  44. #include "fileno.h"
  45. #else// WIN32_CHICAGO
  46. #include "tostring.hxx"
  47. #endif // WIN32_CHICAGO
  48. #include <utils.hxx>
  49. #define FILENO FILENO_TICKETS
  50. //
  51. // Debugging support.
  52. //
  53. #ifndef WIN32_CHICAGO
  54. #ifdef DEBUG_SUPPORT
  55. DEBUG_KEY KSuppDebugKeys[] = { {DEB_ERROR, "Error"},
  56. {DEB_WARN, "Warning"},
  57. {DEB_TRACE, "Trace"},
  58. {DEB_T_SOCK, "Sock"},
  59. {0, NULL }
  60. };
  61. #endif
  62. DEFINE_DEBUG_DEFER(KSupp, KSuppDebugKeys);
  63. #endif // WIN32_CHICAGO
  64. RTL_CRITICAL_SECTION OssCriticalSection;
  65. BOOLEAN TicketsInitialized;
  66. BOOLEAN KerbUseFastDecodeAlloc = FALSE;
  67. #define I_LsaIThreadAlloc MIDL_user_allocate
  68. #define I_LsaIThreadFree MIDL_user_free
  69. //+-------------------------------------------------------------------------
  70. //
  71. // Function: KerbConvertGeneralizedTimeToLargeInt
  72. //
  73. // Synopsis: Converts a generalized time (ASN.1 format) to a large integer
  74. // (NT format)
  75. //
  76. // Effects:
  77. //
  78. // Arguments: TimeStamp - receives NT-style time
  79. // ClientTime - client generalized time
  80. // ClientUsec - client micro second count
  81. //
  82. // Requires: none
  83. //
  84. // Returns:
  85. //
  86. // Notes:
  87. //
  88. //
  89. //--------------------------------------------------------------------------
  90. VOID
  91. KerbConvertGeneralizedTimeToLargeInt(
  92. OUT PTimeStamp TimeStamp,
  93. IN PKERB_TIME ClientTime,
  94. IN int ClientUsec
  95. )
  96. {
  97. KERB_TIME ZeroTime;
  98. TIME_FIELDS TimeFields;
  99. //
  100. // Special case zero time
  101. //
  102. RtlZeroMemory(
  103. &ZeroTime,
  104. sizeof(KERB_TIME)
  105. );
  106. ZeroTime.universal = TRUE;
  107. //
  108. // Skip this check after 3/1/97 - no clients should send this sort of
  109. // zero time
  110. //
  111. if (RtlEqualMemory(
  112. &ZeroTime,
  113. ClientTime,
  114. sizeof(KERB_TIME)
  115. ))
  116. {
  117. #ifndef WIN32_CHICAGO
  118. TimeStamp->QuadPart = 0;
  119. #else // WIN32_CHICAGO
  120. *TimeStamp = 0;
  121. #endif // WIN32_CHICAGO
  122. return;
  123. }
  124. //
  125. // Check for MIT zero time
  126. //
  127. ZeroTime.year = 1970;
  128. ZeroTime.month = 1;
  129. ZeroTime.day = 1;
  130. if (RtlEqualMemory(
  131. &ZeroTime,
  132. ClientTime,
  133. sizeof(KERB_TIME)
  134. ))
  135. {
  136. #ifndef WIN32_CHICAGO
  137. TimeStamp->QuadPart = 0;
  138. #else // WIN32_CHICAGO
  139. *TimeStamp = 0;
  140. #endif // WIN32_CHICAGO
  141. return;
  142. }
  143. else
  144. {
  145. TimeFields.Year = ClientTime->year;
  146. TimeFields.Month = ClientTime->month;
  147. TimeFields.Day = ClientTime->day;
  148. TimeFields.Hour = ClientTime->hour;
  149. TimeFields.Minute = ClientTime->minute;
  150. TimeFields.Second = ClientTime->second;
  151. TimeFields.Milliseconds = ClientTime->millisecond; // to convert from micro to milli
  152. TimeFields.Weekday = 0;
  153. #ifndef WIN32_CHICAGO
  154. RtlTimeFieldsToTime(
  155. &TimeFields,
  156. TimeStamp
  157. );
  158. #else // WIN32_CHICAGO
  159. LARGE_INTEGER TempTimeStamp;
  160. RtlTimeFieldsToTime(
  161. &TimeFields,
  162. &TempTimeStamp
  163. );
  164. *TimeStamp = TempTimeStamp.QuadPart;
  165. #endif // WIN32_CHICAGO
  166. //
  167. // add in any micro seconds
  168. //
  169. #ifndef WIN32_CHICAGO
  170. TimeStamp->QuadPart += ClientUsec * 10;
  171. #else // WIN32_CHICAGO
  172. *TimeStamp += ClientUsec * 10;
  173. #endif // WIN32_CHICAGO
  174. }
  175. }
  176. //+-------------------------------------------------------------------------
  177. //
  178. // Function: KerbConvertLargeIntToGeneralizedTime
  179. //
  180. // Synopsis: Converts a large integer to ageneralized time
  181. //
  182. // Effects:
  183. //
  184. // Arguments: ClientTime - receives generalized time
  185. // ClientUsec - receives micro second count
  186. // TimeStamp - contains NT-style time
  187. //
  188. // Requires: none
  189. //
  190. // Returns:
  191. //
  192. // Notes:
  193. //
  194. //
  195. //--------------------------------------------------------------------------
  196. VOID
  197. KerbConvertLargeIntToGeneralizedTime(
  198. OUT PKERB_TIME ClientTime,
  199. OUT OPTIONAL int * ClientUsec,
  200. IN PTimeStamp TimeStamp
  201. )
  202. {
  203. TIME_FIELDS TimeFields;
  204. //
  205. // Special case zero time
  206. //
  207. #ifndef WIN32_CHICAGO
  208. if (TimeStamp->QuadPart == 0)
  209. #else // WIN32_CHICAGO
  210. if (*TimeStamp == 0)
  211. #endif // WIN32_CHICAGO
  212. {
  213. RtlZeroMemory(
  214. ClientTime,
  215. sizeof(KERB_TIME)
  216. );
  217. //
  218. // For MIT compatibility, time zero is 1/1/70
  219. //
  220. ClientTime->year = 1970;
  221. ClientTime->month = 1;
  222. ClientTime->day = 1;
  223. if (ARGUMENT_PRESENT(ClientUsec))
  224. {
  225. *ClientUsec = 0;
  226. }
  227. ClientTime->universal = TRUE;
  228. }
  229. else
  230. {
  231. #ifndef WIN32_CHICAGO
  232. RtlTimeToTimeFields(
  233. TimeStamp,
  234. &TimeFields
  235. );
  236. #else // WIN32_CHICAGO
  237. RtlTimeToTimeFields(
  238. (LARGE_INTEGER*)TimeStamp,
  239. &TimeFields
  240. );
  241. #endif // WIN32_CHICAGO
  242. //
  243. // Generalized times can only contains years up to four digits.
  244. //
  245. if (TimeFields.Year > 2037)
  246. {
  247. ClientTime->year = 2037;
  248. }
  249. else
  250. {
  251. ClientTime->year = TimeFields.Year;
  252. }
  253. ClientTime->month = (ASN1uint8_t) TimeFields.Month;
  254. ClientTime->day = (ASN1uint8_t) TimeFields.Day;
  255. ClientTime->hour = (ASN1uint8_t) TimeFields.Hour;
  256. ClientTime->minute = (ASN1uint8_t) TimeFields.Minute;
  257. ClientTime->second = (ASN1uint8_t) TimeFields.Second;
  258. // MIT kerberos does not support millseconds
  259. //
  260. ClientTime->millisecond = 0;
  261. if (ARGUMENT_PRESENT(ClientUsec))
  262. {
  263. //
  264. // Since we don't include milliseconds above, use the whole
  265. // thing here.
  266. //
  267. #ifndef WIN32_CHICAGO
  268. *ClientUsec = (TimeStamp->LowPart / 10) % 1000000;
  269. #else // WIN32_CHICAGO
  270. *ClientUsec = (int) ((*TimeStamp / 10) % 1000000);
  271. #endif // WIN32_CHICAGO
  272. }
  273. ClientTime->diff = 0;
  274. ClientTime->universal = TRUE;
  275. }
  276. }
  277. VOID
  278. KerbConvertLargeIntToGeneralizedTimeWrapper(
  279. OUT PKERB_TIME ClientTime,
  280. OUT OPTIONAL long * ClientUsec,
  281. IN PTimeStamp TimeStamp
  282. )
  283. {
  284. int temp;
  285. if (ClientUsec != NULL)
  286. {
  287. KerbConvertLargeIntToGeneralizedTime(
  288. ClientTime,
  289. &temp,
  290. TimeStamp
  291. );
  292. *ClientUsec = temp;
  293. }
  294. else
  295. {
  296. KerbConvertLargeIntToGeneralizedTime(
  297. ClientTime,
  298. NULL,
  299. TimeStamp
  300. );
  301. }
  302. }
  303. //+-------------------------------------------------------------------------
  304. //
  305. // Function: KerbFreeHostAddresses
  306. //
  307. // Synopsis: Frees a host address allocated with KerbBuildHostAddresses
  308. //
  309. // Effects:
  310. //
  311. // Arguments: Addresses - The name to free
  312. //
  313. // Requires:
  314. //
  315. // Returns:
  316. //
  317. // Notes:
  318. //
  319. //
  320. //--------------------------------------------------------------------------
  321. VOID
  322. KerbFreeHostAddresses(
  323. IN PKERB_HOST_ADDRESSES Addresses
  324. )
  325. {
  326. PKERB_HOST_ADDRESSES Elem,NextElem;
  327. Elem = Addresses;
  328. while (Elem != NULL)
  329. {
  330. if (Elem->value.address.value != NULL)
  331. {
  332. MIDL_user_free(Elem->value.address.value);
  333. }
  334. NextElem = Elem->next;
  335. MIDL_user_free(Elem);
  336. Elem = NextElem;
  337. }
  338. }
  339. #ifndef WIN32_CHICAGO
  340. //+-------------------------------------------------------------------------
  341. //
  342. // Function: KerbCheckTimeSkew
  343. //
  344. // Synopsis: Verifies the supplied time is within the skew of another
  345. // supplied time
  346. //
  347. // Effects:
  348. //
  349. // Arguments:
  350. //
  351. // Requires:
  352. //
  353. // Returns:
  354. //
  355. // Notes:
  356. //
  357. //
  358. //--------------------------------------------------------------------------
  359. BOOLEAN
  360. KerbCheckTimeSkew(
  361. IN PTimeStamp CurrentTime,
  362. IN PTimeStamp ClientTime,
  363. IN PTimeStamp AllowedSkew
  364. )
  365. {
  366. TimeStamp TimePlus, TimeMinus;
  367. TimePlus.QuadPart = CurrentTime->QuadPart + AllowedSkew->QuadPart;
  368. TimeMinus.QuadPart = CurrentTime->QuadPart - AllowedSkew->QuadPart;
  369. if ((ClientTime->QuadPart > TimePlus.QuadPart) ||
  370. (ClientTime->QuadPart < TimeMinus.QuadPart))
  371. {
  372. return(FALSE);
  373. }
  374. return(TRUE);
  375. }
  376. //+-------------------------------------------------------------------------
  377. //
  378. // Function: KerbVerifyTicket
  379. //
  380. // Synopsis: Verifies that the specified ticket is valid by checking
  381. // for valid times, flags, and server principal name. This is
  382. // called by KerbCheckTicket to verify an AP request and by the
  383. // KDC to verify additional tickets in TGS request
  384. //
  385. // Effects:
  386. //
  387. // Arguments:
  388. //
  389. // Requires:
  390. //
  391. // Returns:
  392. //
  393. // Notes:
  394. //
  395. //
  396. //--------------------------------------------------------------------------
  397. KERBERR
  398. KerbVerifyTicket(
  399. IN PKERB_TICKET PackedTicket,
  400. IN ULONG NameCount,
  401. IN OPTIONAL PUNICODE_STRING ServiceNames,
  402. IN PUNICODE_STRING ServiceRealm,
  403. IN PKERB_ENCRYPTION_KEY ServiceKey,
  404. IN OPTIONAL PTimeStamp SkewTime,
  405. OUT PKERB_ENCRYPTED_TICKET * DecryptedTicket
  406. )
  407. {
  408. KERBERR KerbErr = KDC_ERR_NONE;
  409. UNICODE_STRING TicketRealm = {0};
  410. PKERB_ENCRYPTED_TICKET EncryptPart = NULL;
  411. TimeStamp TimePlus, TimeMinus, TimeNow, StartTime,EndTime, Time2Plus;
  412. ULONG TicketFlags = 0;
  413. #ifdef notedef
  414. if ( ARGUMENT_PRESENT(ServiceNames) )
  415. {
  416. ULONG Index;
  417. KerbErr = KRB_AP_ERR_NOT_US;
  418. //
  419. // Loop through names looking for a match
  420. //
  421. for (Index = 0; Index < NameCount ; Index++ )
  422. {
  423. if (KerbCompareStringToPrincipalName(
  424. &PackedTicket->server_name,
  425. &ServiceNames[Index]
  426. ) )
  427. {
  428. KerbErr = KDC_ERR_NONE;
  429. break;
  430. }
  431. }
  432. if (!KERB_SUCCESS(KerbErr))
  433. {
  434. DebugLog(( DEB_WARN, "KLIN(%x) Ticket (%s) not for this service (%wZ).\n",
  435. KLIN(FILENO, __LINE__),
  436. PackedTicket->server_name.name_string->value,
  437. &ServiceNames[0] ));
  438. goto Cleanup;
  439. }
  440. }
  441. if (ARGUMENT_PRESENT(ServiceRealm))
  442. {
  443. KerbErr = KerbConvertRealmToUnicodeString(
  444. &TicketRealm,
  445. &PackedTicket->realm
  446. );
  447. if (!KERB_SUCCESS(KerbErr))
  448. {
  449. goto Cleanup;
  450. }
  451. if (!KerbCompareUnicodeRealmNames(
  452. &TicketRealm,
  453. ServiceRealm
  454. ))
  455. {
  456. KerbErr = KRB_AP_ERR_NOT_US;
  457. DebugLog(( DEB_WARN, "KLIN(%x) Ticket (%wZ) not for this realm (%wZ).\n",
  458. KLIN(FILENO, __LINE__), &TicketRealm, ServiceRealm ));
  459. goto Cleanup;
  460. }
  461. }
  462. #endif
  463. //
  464. // Unpack ticket.
  465. //
  466. KerbErr = KerbUnpackTicket(
  467. PackedTicket,
  468. ServiceKey,
  469. &EncryptPart
  470. );
  471. if (!KERB_SUCCESS(KerbErr))
  472. {
  473. DebugLog((DEB_WARN, "KLIN(%x) KerbUnpackTicket failed: 0x%x",
  474. KLIN(FILENO, __LINE__), KerbErr));
  475. goto Cleanup;
  476. }
  477. if (PackedTicket->ticket_version != KERBEROS_VERSION)
  478. {
  479. DebugLog(( DEB_WARN, "KLIN(%x) Ticket has bad version %d\n",
  480. KLIN(FILENO, __LINE__),PackedTicket->ticket_version ));
  481. KerbErr = KRB_AP_ERR_BADVERSION;
  482. goto Cleanup;
  483. }
  484. //
  485. // If the caller provided a skew time, check the times on the ticket.
  486. // Otherwise it is up to the caller to check that the ticket times are
  487. // correct
  488. //
  489. if (ARGUMENT_PRESENT(SkewTime))
  490. {
  491. //
  492. // Check the times on the ticket. We do this last because when the KDC
  493. // wants to renew a ticket, the timestamps may be incorrect, but it will
  494. // accept the ticket anyway. This way the KDC can be certain when the
  495. // times are wrong that everything else is OK.
  496. //
  497. GetSystemTimeAsFileTime((PFILETIME) &TimeNow );
  498. #ifndef WIN32_CHICAGO
  499. TimePlus.QuadPart = TimeNow.QuadPart + SkewTime->QuadPart;
  500. Time2Plus.QuadPart = TimePlus.QuadPart + SkewTime->QuadPart;
  501. TimeMinus.QuadPart = TimeNow.QuadPart - SkewTime->QuadPart;
  502. #else // WIN32_CHICAGO
  503. TimePlus = TimeNow + *SkewTime;
  504. Time2Plus = TimePlus + *SkewTime;
  505. TimeMinus = TimeNow - *SkewTime;
  506. #endif // WIN32_CHICAGO
  507. KerbConvertGeneralizedTimeToLargeInt(
  508. &EndTime,
  509. &EncryptPart->endtime,
  510. 0
  511. );
  512. //
  513. // Did the ticket expire already?
  514. //
  515. #ifndef WIN32_CHICAGO
  516. if ( EndTime.QuadPart < TimeMinus.QuadPart )
  517. #else // WIN32_CHICAGO
  518. if ( EndTime < TimeMinus )
  519. #endif // WIN32_CHICAGO
  520. {
  521. DebugLog(( DEB_WARN, "KLIN(%x) KerbCheckTicket: ticket is expired.\n",
  522. KLIN(FILENO, __LINE__)));
  523. KerbErr = KRB_AP_ERR_TKT_EXPIRED;
  524. goto Cleanup;
  525. }
  526. //
  527. // Is the ticket valid yet?
  528. //
  529. if (EncryptPart->bit_mask & KERB_ENCRYPTED_TICKET_starttime_present)
  530. {
  531. KerbConvertGeneralizedTimeToLargeInt(
  532. &StartTime,
  533. &EncryptPart->KERB_ENCRYPTED_TICKET_starttime,
  534. 0
  535. );
  536. TicketFlags = KerbConvertFlagsToUlong(
  537. &EncryptPart->flags
  538. );
  539. //
  540. // BUG 403734: Look into this a bit more
  541. // We don't check for tickets that aren't valid yet, as
  542. // our KDC doesn't normally hand out post dated tickets. As long
  543. // as the end time is valid, that is good enough for us.
  544. //
  545. //
  546. // Does the ticket start in the future? Allow twice the skew in
  547. // the reverse direction.
  548. //
  549. #ifndef WIN32_CHICAGO
  550. if ( (StartTime.QuadPart > Time2Plus.QuadPart) ||
  551. #else // WIN32_CHICAGO
  552. if ( (StartTime > Time2Plus) ||
  553. #endif // WIN32_CHICAGO
  554. ((TicketFlags & KERB_TICKET_FLAGS_invalid) != 0 ))
  555. {
  556. KerbErr = KRB_AP_ERR_TKT_NYV;
  557. goto Cleanup;
  558. }
  559. }
  560. }
  561. *DecryptedTicket = EncryptPart;
  562. EncryptPart = NULL;
  563. Cleanup:
  564. if (EncryptPart != NULL)
  565. {
  566. KerbFreeTicket(EncryptPart);
  567. }
  568. KerbFreeString(&TicketRealm);
  569. return(KerbErr);
  570. }
  571. //+---------------------------------------------------------------------------
  572. //
  573. // Function: KerbCheckTicket
  574. //
  575. // Synopsis: Decrypts a ticket and authenticator, verifies them.
  576. //
  577. // Effects: decrypts the ticket and authenticator (in place) allocates mem.
  578. //
  579. // Arguments: [PackedTicket] -- Encrypted ticket
  580. // [PackedTicketSize] - Size of encrypted ticket
  581. // [pedAuth] -- Encrypted authenticator
  582. // [pkKey] -- Key to decrypt ticket with
  583. // [alAuthenList] -- List of authenticators to check against
  584. // [NameCount] -- Count of service names
  585. // [pwzServiceName] -- Name of service (may be NULL).
  586. // [CheckForTimeSKewReplay] -- If TRUE, check authenticator cache for timeskew and/or replay
  587. // [KdcRequest] -- If TRUE, this is the ticket in a TGS req (allows for checking time skew only)
  588. // [pkitTicket] -- Decrypted ticket
  589. // [pkiaAuth] -- Decrypted authenticator
  590. // [pkTicketKey] -- Session key from ticket
  591. // [pkSessionKey] -- Session key to use
  592. //
  593. // Returns: KDC_ERR_NONE if everything is OK, else error.
  594. //
  595. // History: 4-04-93 WadeR Created
  596. //
  597. // Notes: The caller must call KerbFreeTicket and
  598. // KerbFreeAuthenticator on pkitTicket and pkiaAuth,
  599. // respectively.
  600. //
  601. // If pwzServiceName == NULL, it won't check the service name.
  602. //
  603. // See sections 3.2.3 and A.10 of the Kerberos V5 R5.2 spec
  604. //
  605. //----------------------------------------------------------------------------
  606. KERBERR NTAPI
  607. KerbCheckTicket(
  608. IN PKERB_TICKET PackedTicket,
  609. IN PKERB_ENCRYPTED_DATA EncryptedAuthenticator,
  610. IN PKERB_ENCRYPTION_KEY pkKey,
  611. IN OUT CAuthenticatorList * AuthenticatorList,
  612. IN PTimeStamp SkewTime,
  613. IN ULONG NameCount,
  614. IN PUNICODE_STRING ServiceNames,
  615. IN PUNICODE_STRING ServiceRealm,
  616. IN BOOLEAN CheckForTimeSkewReplay,
  617. IN BOOLEAN KdcRequest,
  618. OUT PKERB_ENCRYPTED_TICKET * EncryptTicket,
  619. OUT PKERB_AUTHENTICATOR * Authenticator,
  620. OUT OPTIONAL PKERB_ENCRYPTION_KEY pkTicketKey,
  621. OUT PKERB_ENCRYPTION_KEY pkSessionKey,
  622. OUT PBOOLEAN UseSubKey
  623. )
  624. {
  625. KERBERR KerbErr = KDC_ERR_NONE;
  626. PKERB_ENCRYPTED_TICKET EncryptPart = NULL;
  627. LARGE_INTEGER AuthenticatorTime;
  628. //
  629. // The caller will free these, so we must make sure they are valid
  630. // if we return before putting anything in them. This will zero out
  631. // all of the pointers in them, so it's safe to free them later.
  632. //
  633. *EncryptTicket = NULL;
  634. *Authenticator = NULL;
  635. *UseSubKey = FALSE;
  636. RtlZeroMemory(
  637. pkSessionKey,
  638. sizeof(KERB_ENCRYPTION_KEY)
  639. );
  640. if (ARGUMENT_PRESENT(pkTicketKey))
  641. {
  642. *pkTicketKey = *pkSessionKey;
  643. }
  644. //
  645. // Is the ticket for this service?
  646. // ServerName in ticket is different length then ServerName passed in,
  647. // or same length but contents don't match.
  648. //
  649. // If either of KerbUnpackTicket or KerbUnpackAuthenticator
  650. // get bad data, they could access violate.
  651. //
  652. __try
  653. {
  654. KerbErr = KerbVerifyTicket(
  655. PackedTicket,
  656. NameCount,
  657. ServiceNames,
  658. ServiceRealm,
  659. pkKey,
  660. SkewTime,
  661. &EncryptPart
  662. );
  663. if (!KERB_SUCCESS(KerbErr))
  664. {
  665. __leave;
  666. }
  667. //
  668. // Unpack Authenticator.
  669. //
  670. KerbErr = KerbUnpackAuthenticator(
  671. &EncryptPart->key,
  672. EncryptedAuthenticator,
  673. KdcRequest,
  674. Authenticator
  675. );
  676. if (!KERB_SUCCESS(KerbErr))
  677. {
  678. DebugLog((DEB_WARN,"KerbUnpackAuthenticator failed: 0x%x\n", KerbErr) );
  679. __leave;
  680. }
  681. //
  682. // Check the contents of the authenticator
  683. //
  684. if ((*Authenticator)->authenticator_version != KERBEROS_VERSION)
  685. {
  686. DebugLog(( DEB_WARN, "Authenticator has bad version %d\n",
  687. (*Authenticator)->authenticator_version ));
  688. KerbErr = KRB_AP_ERR_BADVERSION;
  689. __leave;
  690. }
  691. if (!KerbComparePrincipalNames(
  692. &EncryptPart->client_name,
  693. &(*Authenticator)->client_name
  694. ) ||
  695. !KerbCompareRealmNames(
  696. &EncryptPart->client_realm,
  697. &(*Authenticator)->client_realm
  698. ) )
  699. {
  700. DebugLog(( DEB_WARN, "Authenticator principal != ticket principal\n"));
  701. KerbErr = KRB_AP_ERR_BADMATCH;
  702. __leave;
  703. }
  704. //
  705. // Make sure the authenticator isn't a repeat, or too old.
  706. //
  707. if (CheckForTimeSkewReplay)
  708. {
  709. BOOLEAN fCheckReplay = TRUE;
  710. if (KdcRequest)
  711. {
  712. fCheckReplay = FALSE; // bug 38404 for KDC TGS check timeskew only
  713. }
  714. KerbConvertGeneralizedTimeToLargeInt(
  715. &AuthenticatorTime,
  716. &(*Authenticator)->client_time,
  717. (*Authenticator)->client_usec
  718. );
  719. KerbErr = (KERBERR) AuthenticatorList->Check(
  720. EncryptedAuthenticator->cipher_text.value,
  721. EncryptedAuthenticator->cipher_text.length,
  722. NULL,
  723. 0,
  724. &AuthenticatorTime,
  725. TRUE,
  726. FALSE,
  727. fCheckReplay);
  728. if (!KERB_SUCCESS(KerbErr))
  729. {
  730. DebugLog((DEB_WARN,"Failed authenticator (replay/time_skew) check: 0x%x\n",KerbErr));
  731. __leave;
  732. }
  733. }
  734. }
  735. __except(EXCEPTION_EXECUTE_HANDLER)
  736. {
  737. // Any exceptions are likely from bad ticket data being unmarshalled.
  738. DebugLog(( DEB_WARN, "Exception 0x%X in KerbCheckTicket (likely bad ticket or auth.\n",
  739. GetExceptionCode() ));
  740. KerbErr = KRB_AP_ERR_BADVERSION;
  741. }
  742. if (!KERB_SUCCESS(KerbErr))
  743. {
  744. goto Cleanup;
  745. }
  746. //
  747. // Extract the correct session key. If the Sub-session key in the
  748. // Authenticator is present, use it. Otherwise, use the session key
  749. // from the ticket.
  750. //
  751. if (((*Authenticator)->bit_mask & KERB_AUTHENTICATOR_subkey_present) != 0)
  752. {
  753. D_DebugLog(( DEB_TRACE, "KerbCheckTicket: Using sub session key from authenticator.\n" ));
  754. KerbErr = KerbDuplicateKey(
  755. pkSessionKey,
  756. &(*Authenticator)->KERB_AUTHENTICATOR_subkey
  757. );
  758. *UseSubKey = TRUE;
  759. }
  760. else
  761. {
  762. KerbErr = KerbDuplicateKey(
  763. pkSessionKey,
  764. &EncryptPart->key
  765. );
  766. }
  767. if (!KERB_SUCCESS(KerbErr))
  768. {
  769. goto Cleanup;
  770. }
  771. //
  772. // The reply has to be encrypted with the ticket key, not the new
  773. // session key
  774. //
  775. if (ARGUMENT_PRESENT(pkTicketKey))
  776. {
  777. KerbErr = KerbDuplicateKey(
  778. pkTicketKey,
  779. &EncryptPart->key
  780. );
  781. if (!KERB_SUCCESS(KerbErr))
  782. {
  783. goto Cleanup;
  784. }
  785. }
  786. *EncryptTicket = EncryptPart;
  787. EncryptPart = NULL;
  788. Cleanup:
  789. if (EncryptPart != NULL)
  790. {
  791. KerbFreeTicket(EncryptPart);
  792. }
  793. if (!KERB_SUCCESS(KerbErr))
  794. {
  795. KerbFreeKey(pkSessionKey);
  796. if (ARGUMENT_PRESENT(pkTicketKey))
  797. {
  798. KerbFreeKey(pkTicketKey);
  799. }
  800. }
  801. return(KerbErr);
  802. }
  803. //+-------------------------------------------------------------------------
  804. //
  805. // Function: KerbDuplicateSid
  806. //
  807. // Synopsis: Duplicates a SID
  808. //
  809. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  810. //
  811. // Arguments: DestinationSid - Receives a copy of the SourceSid
  812. // SourceSid - SID to copy
  813. //
  814. // Requires:
  815. //
  816. // Returns: STATUS_SUCCESS - the copy succeeded
  817. // STATUS_INSUFFICIENT_RESOURCES - the call to allocate memory
  818. // failed
  819. //
  820. // Notes:
  821. //
  822. //
  823. //--------------------------------------------------------------------------
  824. NTSTATUS
  825. KerbDuplicateSid(
  826. OUT PSID * DestinationSid,
  827. IN PSID SourceSid
  828. )
  829. {
  830. ULONG SidSize;
  831. if (!RtlValidSid(SourceSid))
  832. {
  833. return STATUS_INVALID_PARAMETER;
  834. }
  835. DsysAssert(RtlValidSid(SourceSid));
  836. SidSize = RtlLengthSid(SourceSid);
  837. *DestinationSid = (PSID) MIDL_user_allocate( SidSize );
  838. if (*DestinationSid == NULL)
  839. {
  840. return(STATUS_INSUFFICIENT_RESOURCES);
  841. }
  842. RtlCopyMemory(
  843. *DestinationSid,
  844. SourceSid,
  845. SidSize
  846. );
  847. return(STATUS_SUCCESS);
  848. }
  849. #endif // WIN32_CHICAGO
  850. //
  851. // Ticket pack/unpack code.
  852. //
  853. //+---------------------------------------------------------------------------
  854. //
  855. // Function: KerbPackTicket
  856. //
  857. // Synopsis: Packs a KerbInternalTicket to a KerbTicket
  858. //
  859. // Effects: Allocates the KerbTicket via MIDL.
  860. //
  861. // Arguments: [InternalTicket] -- Internal ticket to pack. Those fields
  862. // reused in the packed ticket are zeroed.
  863. // [pkKey] -- Key to pack it with
  864. // [KeyVersion] -- Key version of pkKey (KERB_NO_KEY_VERSION if none)
  865. // [PackedTicket] -- (out) encrypted ticket. Only the encrypt_part
  866. // is allocated.
  867. //
  868. // History: 08-Jun-93 WadeR Created
  869. //
  870. // Notes: The MES encoding needs to be changed to ASN1 encoding
  871. //
  872. //----------------------------------------------------------------------------
  873. KERBERR NTAPI
  874. KerbPackTicket(
  875. IN PKERB_TICKET InternalTicket,
  876. IN PKERB_ENCRYPTION_KEY pkKey,
  877. IN ULONG KeyVersion,
  878. OUT PKERB_TICKET PackedTicket
  879. )
  880. {
  881. KERBERR KerbErr = KDC_ERR_NONE;
  882. PKERB_ENCRYPTED_TICKET EncryptedTicket = NULL;
  883. ULONG cbEncryptedPart;
  884. KERB_TICKET TemporaryTicket;
  885. PUCHAR MarshalledEncryptPart = NULL;
  886. BOOLEAN RestoreDataOnError = FALSE;
  887. //
  888. // Pack the data into the encrypted portion.
  889. //
  890. RtlZeroMemory(
  891. &TemporaryTicket,
  892. sizeof(KERB_TICKET)
  893. );
  894. EncryptedTicket = (PKERB_ENCRYPTED_TICKET) InternalTicket->encrypted_part.cipher_text.value;
  895. KerbErr = KerbPackData(
  896. EncryptedTicket,
  897. KERB_ENCRYPTED_TICKET_PDU,
  898. &cbEncryptedPart,
  899. &MarshalledEncryptPart
  900. );
  901. if (!KERB_SUCCESS(KerbErr))
  902. {
  903. DebugLog((DEB_ERROR,"Failed to marshall ticket: 0x%x\n",KerbErr));
  904. goto Cleanup;
  905. }
  906. //
  907. // And encrypt it.
  908. //
  909. TemporaryTicket = *InternalTicket;
  910. RtlZeroMemory(
  911. &InternalTicket->realm,
  912. sizeof(KERB_REALM)
  913. );
  914. RtlZeroMemory(
  915. &InternalTicket->server_name,
  916. sizeof(KERB_PRINCIPAL_NAME)
  917. );
  918. InternalTicket->ticket_extensions = NULL;
  919. RestoreDataOnError = TRUE;
  920. KerbErr = KerbAllocateEncryptionBufferWrapper(
  921. pkKey->keytype,
  922. cbEncryptedPart,
  923. &TemporaryTicket.encrypted_part.cipher_text.length,
  924. &TemporaryTicket.encrypted_part.cipher_text.value
  925. );
  926. if (!KERB_SUCCESS(KerbErr))
  927. {
  928. goto Cleanup;
  929. }
  930. DebugLog((DEB_TRACE,"KerbPackTicket: Using KeyVersion 0x%x and Algorithm %d to encrypt ticket\n",
  931. KeyVersion, pkKey->keytype));
  932. KerbErr = KerbEncryptDataEx(
  933. &TemporaryTicket.encrypted_part,
  934. cbEncryptedPart,
  935. MarshalledEncryptPart,
  936. KeyVersion,
  937. KERB_TICKET_SALT,
  938. pkKey
  939. );
  940. if (!KERB_SUCCESS(KerbErr))
  941. {
  942. DebugLog((DEB_ERROR,"Failed to encrypt data: 0x%x\n",KerbErr));
  943. goto Cleanup;
  944. }
  945. *PackedTicket = TemporaryTicket;
  946. Cleanup:
  947. if (MarshalledEncryptPart != NULL)
  948. {
  949. MIDL_user_free(MarshalledEncryptPart);
  950. }
  951. if (!KERB_SUCCESS(KerbErr))
  952. {
  953. if (TemporaryTicket.encrypted_part.cipher_text.value != NULL)
  954. {
  955. MIDL_user_free(TemporaryTicket.encrypted_part.cipher_text.value);
  956. }
  957. if (RestoreDataOnError)
  958. {
  959. InternalTicket->realm = TemporaryTicket.realm;
  960. InternalTicket->server_name = TemporaryTicket.server_name;
  961. InternalTicket->ticket_extensions = TemporaryTicket.ticket_extensions;
  962. }
  963. }
  964. return(KerbErr);
  965. }
  966. //+---------------------------------------------------------------------------
  967. //
  968. // Function: KerbUnpackTicket
  969. //
  970. // Synopsis: Decrypts and unpacks the encyrpted part of aticket.
  971. //
  972. // Effects: Allocates memory, decrypts pktTicket in place
  973. //
  974. // Arguments: [PackedTicket] -- ticket to unpack
  975. // [PackedTicketSize] -- length of packed ticket
  976. // [pkKey] -- key to unpack it with
  977. // [InternalTicket] -- (out) unpacked ticket
  978. //
  979. // Returns: KDC_ERR_NONE or error from decrypt
  980. //
  981. // Signals: Any exception the MIDL unpacking code throws.
  982. //
  983. // History: 09-Jun-93 WadeR Created
  984. //
  985. // Notes: Free InternalTicket with KerbFreeTicket, below.
  986. //
  987. //----------------------------------------------------------------------------
  988. KERBERR NTAPI
  989. KerbUnpackTicket(
  990. IN PKERB_TICKET PackedTicket,
  991. IN PKERB_ENCRYPTION_KEY pkKey,
  992. OUT PKERB_ENCRYPTED_TICKET * InternalTicket
  993. )
  994. {
  995. KERBERR KerbErr = KDC_ERR_NONE;
  996. PUCHAR EncryptedPart = NULL;
  997. ULONG EncryptSize;
  998. PKERB_ENCRYPTED_TICKET EncryptedTicket = NULL;
  999. //
  1000. // Now decrypt the encrypted part of the ticket
  1001. //
  1002. EncryptedPart = (PUCHAR) MIDL_user_allocate(PackedTicket->encrypted_part.cipher_text.length);
  1003. if (EncryptedPart == NULL)
  1004. {
  1005. return(KRB_ERR_GENERIC);
  1006. }
  1007. EncryptSize = PackedTicket->encrypted_part.cipher_text.length;
  1008. KerbErr = KerbDecryptDataEx(
  1009. &PackedTicket->encrypted_part,
  1010. pkKey,
  1011. KERB_TICKET_SALT,
  1012. &EncryptSize,
  1013. EncryptedPart
  1014. );
  1015. if (!KERB_SUCCESS(KerbErr))
  1016. {
  1017. DebugLog((DEB_ERROR,"Failed to decrypt ticket: 0x%x\n",KerbErr));
  1018. #if DBG
  1019. //
  1020. // Who's this ticket *supposed* to be for?
  1021. //
  1022. KerbPrintPrincipalName(DEB_ERROR, &PackedTicket->server_name);
  1023. KerbPrintKerbRealm(DEB_ERROR, &PackedTicket->realm);
  1024. #endif
  1025. goto Cleanup;
  1026. }
  1027. KerbErr = KerbUnpackData(
  1028. EncryptedPart,
  1029. EncryptSize,
  1030. KERB_ENCRYPTED_TICKET_PDU,
  1031. (PVOID *) &EncryptedTicket
  1032. );
  1033. if (!KERB_SUCCESS(KerbErr))
  1034. {
  1035. DebugLog((DEB_ERROR,"Failed to unmarshall ticket: 0x%x\n",KerbErr));
  1036. goto Cleanup;
  1037. }
  1038. *InternalTicket = EncryptedTicket;
  1039. Cleanup:
  1040. if (EncryptedPart != NULL)
  1041. {
  1042. MIDL_user_free(EncryptedPart);
  1043. }
  1044. return(KerbErr);
  1045. }
  1046. //+---------------------------------------------------------------------------
  1047. //
  1048. // Function: KerbCreateAuthenticator
  1049. //
  1050. // Synopsis: Creates an authenticator for a client to pass to a service
  1051. //
  1052. // Effects: Encrypts pedAuthenticator
  1053. //
  1054. // Arguments: [pkKey] -- (in) session key from the ticket this
  1055. // authenticator is for.
  1056. // [dwEncrType] -- (in) Desired encryption type
  1057. // [dwSeq] -- (in) nonce for authenticator
  1058. // [pTimeStamp] -- (out) Time for authenticator
  1059. // [ClientName] -- (in) name of principal
  1060. // [ClientRealm] -- (in) logon realm of principal
  1061. // [SkewTime] -- (in) Skew of server's time
  1062. // [pkSubKey] -- (in) desired sub key (may be NULL)
  1063. // [GssChecksum] -- (in) optional checksum message to put in authenticator
  1064. // [KdcRequest] -- (in) If TRUE, this is an authenticator for a KDC request
  1065. // and we use a different salt
  1066. // [Authenticator]-- (out) completed authenticator
  1067. // [pAuthenticatorTime] -- (out optional) timestamp placed on AP request
  1068. //
  1069. // History: 4-28-93 WadeR Created
  1070. //
  1071. // Notes: If pkKey is NULL, a null subkey is used.
  1072. //
  1073. //
  1074. //----------------------------------------------------------------------------
  1075. KERBERR NTAPI
  1076. KerbCreateAuthenticator(
  1077. IN PKERB_ENCRYPTION_KEY pkKey,
  1078. IN ULONG SequenceNumber,
  1079. OUT OPTIONAL PTimeStamp pAuthenticatorTime,
  1080. IN PKERB_INTERNAL_NAME ClientName,
  1081. IN PUNICODE_STRING ClientRealm,
  1082. IN OPTIONAL PTimeStamp SkewTime,
  1083. IN PKERB_ENCRYPTION_KEY pkSubKey,
  1084. IN OPTIONAL PKERB_CHECKSUM GssChecksum,
  1085. IN BOOLEAN KdcRequest,
  1086. OUT PKERB_ENCRYPTED_DATA Authenticator
  1087. )
  1088. {
  1089. KERB_AUTHENTICATOR InternalAuthenticator;
  1090. PKERB_AUTHENTICATOR AuthPointer = &InternalAuthenticator;
  1091. ULONG cbAuthenticator;
  1092. PUCHAR PackedAuthenticator = NULL;
  1093. KERBERR KerbErr = KDC_ERR_NONE;
  1094. TimeStamp TimeToUse;
  1095. Authenticator->cipher_text.value = NULL;
  1096. RtlZeroMemory(
  1097. &InternalAuthenticator,
  1098. sizeof(KERB_AUTHENTICATOR)
  1099. );
  1100. // Build an authenticator
  1101. InternalAuthenticator.authenticator_version = KERBEROS_VERSION;
  1102. // Use "InitString" because we will marshall and then discard the
  1103. // InternalAthenticator. Therefore it's not a problem having the
  1104. // string point to memory we don't own.
  1105. KerbErr = KerbConvertUnicodeStringToRealm(
  1106. &InternalAuthenticator.client_realm,
  1107. ClientRealm
  1108. );
  1109. if (!KERB_SUCCESS(KerbErr))
  1110. {
  1111. goto Cleanup;
  1112. }
  1113. KerbErr = KerbConvertKdcNameToPrincipalName(
  1114. &InternalAuthenticator.client_name,
  1115. ClientName
  1116. );
  1117. if (!KERB_SUCCESS(KerbErr))
  1118. {
  1119. goto Cleanup;
  1120. }
  1121. //
  1122. // Stick the correct time in the authenticator
  1123. //
  1124. GetSystemTimeAsFileTime((PFILETIME)&TimeToUse);
  1125. if (ARGUMENT_PRESENT(SkewTime))
  1126. {
  1127. #ifndef WIN32_CHICAGO
  1128. TimeToUse.QuadPart += SkewTime->QuadPart;
  1129. #else // WIN32_CHICAGO
  1130. TimeToUse += *SkewTime;
  1131. #endif // WIN32_CHICAGO
  1132. }
  1133. KerbConvertLargeIntToGeneralizedTimeWrapper(
  1134. &InternalAuthenticator.client_time,
  1135. &InternalAuthenticator.client_usec,
  1136. &TimeToUse
  1137. );
  1138. if (pAuthenticatorTime)
  1139. {
  1140. *pAuthenticatorTime = TimeToUse; // return the authenticator time
  1141. }
  1142. InternalAuthenticator.bit_mask |= KERB_AUTHENTICATOR_sequence_number_present;
  1143. ASN1intx_setuint32(
  1144. &InternalAuthenticator.KERB_AUTHENTICATOR_sequence_number,
  1145. SequenceNumber
  1146. );
  1147. if (InternalAuthenticator.KERB_AUTHENTICATOR_sequence_number.value == NULL)
  1148. {
  1149. KerbErr = KRB_ERR_GENERIC;
  1150. goto Cleanup;
  1151. }
  1152. if (ARGUMENT_PRESENT(pkSubKey))
  1153. {
  1154. InternalAuthenticator.bit_mask |= KERB_AUTHENTICATOR_subkey_present;
  1155. InternalAuthenticator.KERB_AUTHENTICATOR_subkey = *pkSubKey;
  1156. }
  1157. //
  1158. // If the GSS checksum is present, include it and set it in the bitmask
  1159. //
  1160. if (ARGUMENT_PRESENT(GssChecksum))
  1161. {
  1162. InternalAuthenticator.checksum = *GssChecksum;
  1163. InternalAuthenticator.bit_mask |= checksum_present;
  1164. }
  1165. KerbErr = KerbPackData(
  1166. AuthPointer,
  1167. KERB_AUTHENTICATOR_PDU,
  1168. &cbAuthenticator,
  1169. &PackedAuthenticator
  1170. );
  1171. if (!KERB_SUCCESS(KerbErr))
  1172. {
  1173. DebugLog((DEB_ERROR,"Failed to marshall authenticator: 0x%x\n",KerbErr));
  1174. goto Cleanup;
  1175. }
  1176. //
  1177. // Now we need to encrypt the buffer
  1178. //
  1179. KerbErr = KerbAllocateEncryptionBufferWrapper(
  1180. pkKey->keytype,
  1181. cbAuthenticator,
  1182. &Authenticator->cipher_text.length,
  1183. &Authenticator->cipher_text.value
  1184. );
  1185. if (!KERB_SUCCESS(KerbErr))
  1186. {
  1187. goto Cleanup;
  1188. }
  1189. KerbErr = KerbEncryptDataEx(
  1190. Authenticator,
  1191. cbAuthenticator,
  1192. PackedAuthenticator,
  1193. KERB_NO_KEY_VERSION,
  1194. KdcRequest ? KERB_TGS_REQ_AP_REQ_AUTH_SALT : KERB_AP_REQ_AUTH_SALT,
  1195. pkKey
  1196. );
  1197. if (!KERB_SUCCESS(KerbErr))
  1198. {
  1199. DebugLog((DEB_ERROR,"Failed to encrypt data: 0x%x\n",KerbErr));
  1200. goto Cleanup;
  1201. }
  1202. Cleanup:
  1203. KerbFreePrincipalName(&InternalAuthenticator.client_name);
  1204. KerbFreeRealm(&InternalAuthenticator.client_realm);
  1205. if (InternalAuthenticator.KERB_AUTHENTICATOR_sequence_number.value != NULL)
  1206. {
  1207. ASN1intx_free(&InternalAuthenticator.KERB_AUTHENTICATOR_sequence_number);
  1208. }
  1209. if (PackedAuthenticator != NULL)
  1210. {
  1211. MIDL_user_free(PackedAuthenticator);
  1212. }
  1213. return(KerbErr);
  1214. }
  1215. //+-------------------------------------------------------------------------
  1216. //
  1217. // Function: KerbUnpackAuthenticator
  1218. //
  1219. // Synopsis: Unpacks and decrypts an authenticator
  1220. //
  1221. // Effects: allocates memory for output authenticator
  1222. //
  1223. // Arguments:
  1224. //
  1225. // Requires:
  1226. //
  1227. // Returns:
  1228. //
  1229. // Notes:
  1230. //
  1231. //
  1232. //--------------------------------------------------------------------------
  1233. KERBERR NTAPI
  1234. KerbUnpackAuthenticator(
  1235. IN PKERB_ENCRYPTION_KEY Key,
  1236. IN PKERB_ENCRYPTED_DATA EncryptedAuthenticator,
  1237. IN BOOLEAN KdcRequest,
  1238. OUT PKERB_AUTHENTICATOR * Authenticator
  1239. )
  1240. {
  1241. KERBERR KerbErr = KDC_ERR_NONE;
  1242. PUCHAR EncryptedPart;
  1243. ULONG EncryptedSize;
  1244. ULONG Pdu = KERB_AUTHENTICATOR_PDU;
  1245. *Authenticator = NULL;
  1246. //
  1247. // Decrypt it
  1248. //
  1249. EncryptedPart = (PUCHAR) MIDL_user_allocate(EncryptedAuthenticator->cipher_text.length);
  1250. if (EncryptedPart == NULL)
  1251. {
  1252. return(KRB_ERR_GENERIC);
  1253. }
  1254. EncryptedSize = EncryptedAuthenticator->cipher_text.length;
  1255. KerbErr = KerbDecryptDataEx(
  1256. EncryptedAuthenticator,
  1257. Key,
  1258. KdcRequest ? KERB_TGS_REQ_AP_REQ_AUTH_SALT : KERB_AP_REQ_AUTH_SALT,
  1259. &EncryptedSize,
  1260. EncryptedPart
  1261. );
  1262. if (!KERB_SUCCESS(KerbErr))
  1263. {
  1264. DebugLog((DEB_ERROR,"Failed to decrypt authenticator: 0x%x\n",KerbErr));
  1265. goto Cleanup;
  1266. }
  1267. //
  1268. // Unpack it
  1269. //
  1270. KerbErr = KerbUnpackData(
  1271. EncryptedPart,
  1272. EncryptedSize,
  1273. Pdu,
  1274. (PVOID *) Authenticator
  1275. );
  1276. if (!KERB_SUCCESS(KerbErr))
  1277. {
  1278. DebugLog((DEB_ERROR,"Failed to unmarshall authenticator: 0x%x\n",KerbErr));
  1279. goto Cleanup;
  1280. }
  1281. Cleanup:
  1282. if (EncryptedPart != NULL)
  1283. {
  1284. MIDL_user_free(EncryptedPart);
  1285. }
  1286. if (!KERB_SUCCESS(KerbErr) && (*Authenticator != NULL))
  1287. {
  1288. MIDL_user_free(*Authenticator);
  1289. *Authenticator = NULL;
  1290. }
  1291. return (KerbErr);
  1292. }
  1293. //
  1294. // KDC Reply stuff
  1295. //
  1296. //+-------------------------------------------------------------------------
  1297. //
  1298. // Function: KerbPackKdcReplyBody
  1299. //
  1300. // Synopsis: Marshalls a the body of a KDC reply
  1301. //
  1302. // Effects: allocates value of encrypted reply
  1303. //
  1304. // Arguments: ReplyBody - The reply body to marshall
  1305. // Key - The key to encrypt the reply
  1306. // Pdu - Pdu to pack with, eith AS or TGS reply
  1307. // EncryptedReplyBody - receives the encrypted and marshalled reply
  1308. //
  1309. // Requires:
  1310. //
  1311. // Returns:
  1312. //
  1313. // Notes:
  1314. //
  1315. //
  1316. //--------------------------------------------------------------------------
  1317. KERBERR NTAPI
  1318. KerbPackKdcReplyBody(
  1319. IN PKERB_ENCRYPTED_KDC_REPLY ReplyBody,
  1320. IN PKERB_ENCRYPTION_KEY Key,
  1321. IN ULONG KeyVersion,
  1322. IN ULONG KeySalt,
  1323. IN ULONG Pdu,
  1324. OUT PKERB_ENCRYPTED_DATA EncryptedReply
  1325. )
  1326. {
  1327. KERBERR KerbErr = KDC_ERR_NONE;
  1328. ULONG BodySize;
  1329. ULONG EncryptionOverhead;
  1330. PUCHAR MarshalledReply = NULL;
  1331. ULONG TotalSize;
  1332. ULONG BlockSize = 0;
  1333. EncryptedReply->cipher_text.value = NULL;
  1334. KerbErr = KerbPackData(
  1335. ReplyBody,
  1336. Pdu,
  1337. &BodySize,
  1338. &MarshalledReply
  1339. );
  1340. if (!KERB_SUCCESS(KerbErr))
  1341. {
  1342. DebugLog((DEB_ERROR, "Failed to marshall kdc reply body: 0x%x\n", KerbErr));
  1343. goto Cleanup;
  1344. }
  1345. //
  1346. // Now we need to encrypt this into the encrypted data structure.
  1347. //
  1348. //
  1349. // First get the overhead size
  1350. //
  1351. KerbErr = KerbGetEncryptionOverhead(
  1352. Key->keytype,
  1353. &EncryptionOverhead,
  1354. &BlockSize
  1355. );
  1356. if (!KERB_SUCCESS(KerbErr))
  1357. {
  1358. goto Cleanup;
  1359. }
  1360. DsysAssert(BlockSize <= 8);
  1361. TotalSize = ROUND_UP_COUNT(EncryptionOverhead + BodySize, BlockSize);
  1362. EncryptedReply->cipher_text.length = TotalSize;
  1363. EncryptedReply->cipher_text.value = (PUCHAR) MIDL_user_allocate(TotalSize);
  1364. if (EncryptedReply->cipher_text.value == NULL)
  1365. {
  1366. KerbErr = KRB_ERR_GENERIC;
  1367. goto Cleanup;
  1368. }
  1369. //
  1370. // Now encrypt the buffer see raid 502476 if adding in new etypes - must fix I_GetASTIcket()'s call to
  1371. // pass in correct value KERB_AS_REP_SALT rather than KERB_AS_REP_SALT but need to map for rc4 first
  1372. //
  1373. KerbErr = KerbEncryptDataEx(
  1374. EncryptedReply,
  1375. BodySize,
  1376. MarshalledReply,
  1377. KeyVersion,
  1378. KeySalt,
  1379. Key
  1380. );
  1381. DebugLog((DEB_TRACE,"KerbPackKdcReplyBody: KeyVersion 0x%lx Algorithm %d KerbErr 0x%x\n",
  1382. KeyVersion, Key->keytype, KerbErr));
  1383. Cleanup:
  1384. if (MarshalledReply != NULL)
  1385. {
  1386. MIDL_user_free(MarshalledReply);
  1387. }
  1388. if (!KERB_SUCCESS(KerbErr) && (EncryptedReply->cipher_text.value != NULL))
  1389. {
  1390. MIDL_user_free(EncryptedReply->cipher_text.value);
  1391. EncryptedReply->cipher_text.value = NULL;
  1392. }
  1393. return(KerbErr);
  1394. }
  1395. //+-------------------------------------------------------------------------
  1396. //
  1397. // Function: KerbUnpackKdcReplyBody
  1398. //
  1399. // Synopsis: Unpacks a KDC reply body
  1400. //
  1401. // Effects:
  1402. //
  1403. // Arguments: EncryptedReplyBody - an encrypted marshalled reply body.
  1404. // Key - Key to decrypt the reply.
  1405. // Pdu - PDU of reply body (eithe AS or TGS)
  1406. // ReplyBody - receives the decrypted reply body, allocated with
  1407. // MIDL_user_allocate.
  1408. //
  1409. // Requires:
  1410. //
  1411. // Returns:
  1412. //
  1413. // Notes:
  1414. //
  1415. //
  1416. //--------------------------------------------------------------------------
  1417. KERBERR NTAPI
  1418. KerbUnpackKdcReplyBody(
  1419. IN PKERB_ENCRYPTED_DATA EncryptedReplyBody,
  1420. IN PKERB_ENCRYPTION_KEY Key,
  1421. IN ULONG Pdu,
  1422. OUT PKERB_ENCRYPTED_KDC_REPLY * ReplyBody
  1423. )
  1424. {
  1425. KERBERR KerbErr = KDC_ERR_NONE;
  1426. PUCHAR MarshalledReply = NULL;
  1427. ULONG ReplySize;
  1428. *ReplyBody = NULL;
  1429. MarshalledReply = (PUCHAR) MIDL_user_allocate(EncryptedReplyBody->cipher_text.length);
  1430. if (MarshalledReply == NULL)
  1431. {
  1432. return(KRB_ERR_GENERIC);
  1433. }
  1434. //
  1435. // First decrypt the buffer
  1436. // Note: The switch on KERB_AS_REPLY_PDU below is incorrect. See bug 502476
  1437. //
  1438. ReplySize = EncryptedReplyBody->cipher_text.length;
  1439. KerbErr = KerbDecryptDataEx(
  1440. EncryptedReplyBody,
  1441. Key,
  1442. (Pdu == KERB_AS_REPLY_PDU) ? KERB_AS_REP_SALT : KERB_TGS_REP_SALT,
  1443. &ReplySize,
  1444. MarshalledReply
  1445. );
  1446. if (!KERB_SUCCESS(KerbErr))
  1447. {
  1448. goto Cleanup;
  1449. }
  1450. KerbErr = KerbUnpackData(
  1451. MarshalledReply,
  1452. ReplySize,
  1453. Pdu,
  1454. (PVOID *) ReplyBody
  1455. );
  1456. if (!KERB_SUCCESS(KerbErr))
  1457. {
  1458. //
  1459. // MIT KDCs send back TGS reply bodies instead of AS reply bodies
  1460. // so try TGS here
  1461. //
  1462. if (Pdu == KERB_ENCRYPTED_AS_REPLY_PDU)
  1463. {
  1464. KerbErr = KerbUnpackData(
  1465. MarshalledReply,
  1466. ReplySize,
  1467. KERB_ENCRYPTED_TGS_REPLY_PDU,
  1468. (PVOID *) ReplyBody
  1469. );
  1470. }
  1471. if (!KERB_SUCCESS(KerbErr))
  1472. {
  1473. DebugLog((DEB_ERROR,"Failed to unmarshall kdc reply body: 0x%x\n",KerbErr));
  1474. goto Cleanup;
  1475. }
  1476. }
  1477. Cleanup:
  1478. if (MarshalledReply != NULL)
  1479. {
  1480. MIDL_user_free(MarshalledReply);
  1481. }
  1482. if (!KERB_SUCCESS(KerbErr) && (*ReplyBody != NULL))
  1483. {
  1484. MIDL_user_free(*ReplyBody);
  1485. *ReplyBody = NULL;
  1486. }
  1487. return(KerbErr);
  1488. }
  1489. //+-------------------------------------------------------------------------
  1490. //
  1491. // Function: KerbFindAuthDataEntry
  1492. //
  1493. // Synopsis: Finds a specific entry in an authorization data structure
  1494. //
  1495. // Effects:
  1496. //
  1497. // Arguments: EntryId - ID of the entry to locate
  1498. // AuthData - the authorization data to search
  1499. //
  1500. // Requires:
  1501. //
  1502. // Returns: NULL if it wasn't found of the auth data entry
  1503. //
  1504. // Notes:
  1505. //
  1506. //
  1507. //--------------------------------------------------------------------------
  1508. PKERB_AUTHORIZATION_DATA
  1509. KerbFindAuthDataEntry(
  1510. IN ULONG EntryId,
  1511. IN PKERB_AUTHORIZATION_DATA AuthData
  1512. )
  1513. {
  1514. PKERB_AUTHORIZATION_DATA TempData = AuthData;
  1515. while (TempData != NULL)
  1516. {
  1517. if (TempData->value.auth_data_type == (int) EntryId)
  1518. {
  1519. break;
  1520. }
  1521. TempData = TempData->next;
  1522. }
  1523. return(TempData);
  1524. }
  1525. //+-------------------------------------------------------------------------
  1526. //
  1527. // Function: KerbFindPreAuthDataEntry
  1528. //
  1529. // Synopsis: Finds a specific entry in an authorization data structure
  1530. //
  1531. // Effects:
  1532. //
  1533. // Arguments: EntryId - ID of the entry to locate
  1534. // AuthData - the authorization data to search
  1535. //
  1536. // Requires:
  1537. //
  1538. // Returns: NULL if it wasn't found of the auth data entry
  1539. //
  1540. // Notes:
  1541. //
  1542. //
  1543. //--------------------------------------------------------------------------
  1544. PKERB_PA_DATA
  1545. KerbFindPreAuthDataEntry(
  1546. IN ULONG EntryId,
  1547. IN PKERB_PA_DATA_LIST AuthData
  1548. )
  1549. {
  1550. PKERB_PA_DATA_LIST TempData = AuthData;
  1551. while (TempData != NULL)
  1552. {
  1553. if (TempData->value.preauth_data_type == (int) EntryId)
  1554. {
  1555. break;
  1556. }
  1557. TempData = TempData->next;
  1558. }
  1559. return(TempData != NULL ? &TempData->value : NULL);
  1560. }
  1561. //+-------------------------------------------------------------------------
  1562. //
  1563. // Function: KerbFreePreAuthData
  1564. //
  1565. // Synopsis: Frees a pa-data list
  1566. //
  1567. // Effects:
  1568. //
  1569. // Arguments: PreAuthData - data to free
  1570. //
  1571. // Requires:
  1572. //
  1573. // Returns:
  1574. //
  1575. // Notes:
  1576. //
  1577. //
  1578. //--------------------------------------------------------------------------
  1579. VOID
  1580. KerbFreePreAuthData(
  1581. IN OPTIONAL PKERB_PA_DATA_LIST PreAuthData
  1582. )
  1583. {
  1584. PKERB_PA_DATA_LIST Next,Last;
  1585. Next = PreAuthData;
  1586. while (Next != NULL)
  1587. {
  1588. Last = Next->next;
  1589. if (Next->value.preauth_data.value != NULL)
  1590. {
  1591. MIDL_user_free(Next->value.preauth_data.value);
  1592. }
  1593. MIDL_user_free(Next);
  1594. Next = Last;
  1595. }
  1596. }
  1597. //+-------------------------------------------------------------------------
  1598. //
  1599. // Function: KerbFreeAuthData
  1600. //
  1601. // Synopsis: Frees and auth data structure that was allocated in
  1602. // pieces
  1603. //
  1604. // Effects: frees with MIDL_user_Free
  1605. //
  1606. // Arguments: AuthData - the auth data to free
  1607. //
  1608. // Requires:
  1609. //
  1610. // Returns:
  1611. //
  1612. // Notes:
  1613. //
  1614. //
  1615. //--------------------------------------------------------------------------
  1616. VOID
  1617. KerbFreeAuthData(
  1618. IN PKERB_AUTHORIZATION_DATA AuthData
  1619. )
  1620. {
  1621. PKERB_AUTHORIZATION_DATA TempData1,TempData2;
  1622. TempData1 = AuthData;
  1623. while (TempData1 != NULL)
  1624. {
  1625. TempData2 = TempData1->next;
  1626. if (TempData1->value.auth_data.value != NULL)
  1627. {
  1628. MIDL_user_free(TempData1->value.auth_data.value);
  1629. }
  1630. MIDL_user_free(TempData1);
  1631. TempData1 = TempData2;
  1632. }
  1633. }
  1634. //+-------------------------------------------------------------------------
  1635. //
  1636. // Function: KerbCopyAndAppendAuthData
  1637. //
  1638. // Synopsis: copies the elements from the input auth data and appends
  1639. // them to the end of the output auth data.
  1640. //
  1641. // Effects: allocates each auth data with MIDL_user_allocate
  1642. //
  1643. // Arguments: OutputAuthData - receives list of append auth data
  1644. // InputAuthData - optionally contains auth data to append
  1645. //
  1646. // Requires:
  1647. //
  1648. // Returns: KDC_ERR_NONE or KRB_ERR_GENERIC;
  1649. //
  1650. // Notes: on failure output auth data will be freed and set to NULL.
  1651. //
  1652. //
  1653. //--------------------------------------------------------------------------
  1654. KERBERR
  1655. KerbCopyAndAppendAuthData(
  1656. OUT PKERB_AUTHORIZATION_DATA * OutputAuthData,
  1657. IN PKERB_AUTHORIZATION_DATA InputAuthData
  1658. )
  1659. {
  1660. KERBERR KerbErr = KDC_ERR_NONE;
  1661. PKERB_AUTHORIZATION_DATA *LastEntry = OutputAuthData;
  1662. PKERB_AUTHORIZATION_DATA TempEntry = NULL;
  1663. //
  1664. // Find the end of the list
  1665. //
  1666. while (*LastEntry != NULL)
  1667. {
  1668. LastEntry = &((*LastEntry)->next);
  1669. }
  1670. while (InputAuthData != NULL)
  1671. {
  1672. //
  1673. // copy the existing entry
  1674. //
  1675. TempEntry = (PKERB_AUTHORIZATION_DATA) MIDL_user_allocate(sizeof(KERB_AUTHORIZATION_DATA));
  1676. if (TempEntry == NULL)
  1677. {
  1678. KerbErr = KRB_ERR_GENERIC;
  1679. goto Cleanup;
  1680. }
  1681. TempEntry->value.auth_data.length = InputAuthData->value.auth_data.length;
  1682. TempEntry->value.auth_data_type = InputAuthData->value.auth_data_type;
  1683. TempEntry->next = NULL;
  1684. TempEntry->value.auth_data.value = (PUCHAR) MIDL_user_allocate(InputAuthData->value.auth_data.length);
  1685. if (TempEntry->value.auth_data.value == NULL)
  1686. {
  1687. MIDL_user_free(TempEntry);
  1688. goto Cleanup;
  1689. }
  1690. RtlCopyMemory(
  1691. TempEntry->value.auth_data.value,
  1692. InputAuthData->value.auth_data.value,
  1693. InputAuthData->value.auth_data.length
  1694. );
  1695. //
  1696. // add it to the end of the list
  1697. //
  1698. *LastEntry = TempEntry;
  1699. LastEntry = &TempEntry->next;
  1700. InputAuthData = InputAuthData->next;
  1701. }
  1702. KerbErr = KDC_ERR_NONE;
  1703. Cleanup:
  1704. if (!KERB_SUCCESS(KerbErr))
  1705. {
  1706. KerbFreeAuthData(*OutputAuthData);
  1707. *OutputAuthData = NULL;
  1708. }
  1709. return(KerbErr);
  1710. }
  1711. //+-------------------------------------------------------------------------
  1712. //
  1713. // Function: KerbConvertCryptListToArray
  1714. //
  1715. // Synopsis: Converts a linked-list crypt vector to an array of ULONGs
  1716. //
  1717. // Effects: allocates return with MIDL_user_allocate
  1718. //
  1719. // Arguments:
  1720. //
  1721. // Requires:
  1722. //
  1723. // Returns:
  1724. //
  1725. // Notes:
  1726. //
  1727. //
  1728. //--------------------------------------------------------------------------
  1729. KERBERR
  1730. KerbConvertCryptListToArray(
  1731. OUT PULONG * ETypeArray,
  1732. OUT PULONG ETypeCount,
  1733. IN PKERB_CRYPT_LIST CryptList
  1734. )
  1735. {
  1736. KERBERR Status = KDC_ERR_NONE;
  1737. PKERB_CRYPT_LIST NextEType;
  1738. ULONG ClientETypeCount;
  1739. PULONG ClientETypes = NULL;
  1740. //
  1741. // Build a vector of the client encrypt types
  1742. //
  1743. NextEType = CryptList;
  1744. ClientETypeCount = 0;
  1745. while (NextEType != NULL)
  1746. {
  1747. ClientETypeCount++;
  1748. NextEType = NextEType->next;
  1749. }
  1750. ClientETypes = (PULONG) MIDL_user_allocate(sizeof(ULONG) * ClientETypeCount);
  1751. if (ClientETypes == NULL)
  1752. {
  1753. Status = KRB_ERR_GENERIC;
  1754. goto Cleanup;
  1755. }
  1756. NextEType = CryptList;
  1757. ClientETypeCount = 0;
  1758. while (NextEType != NULL)
  1759. {
  1760. ClientETypes[ClientETypeCount] = NextEType->value;
  1761. ClientETypeCount++;
  1762. NextEType = NextEType->next;
  1763. }
  1764. *ETypeCount = ClientETypeCount;
  1765. *ETypeArray = ClientETypes;
  1766. Cleanup:
  1767. return(Status);
  1768. }
  1769. //+-------------------------------------------------------------------------
  1770. //
  1771. // Function: KerbConvertArrayToCryptList
  1772. //
  1773. // Synopsis: Converts an array of encryption to types to a linked list
  1774. //
  1775. // Effects:
  1776. //
  1777. // Arguments:
  1778. //
  1779. // Requires:
  1780. //
  1781. // Returns:
  1782. //
  1783. // Notes:
  1784. //
  1785. //
  1786. //--------------------------------------------------------------------------
  1787. KERBERR
  1788. KerbConvertArrayToCryptList(
  1789. OUT PKERB_CRYPT_LIST * CryptList,
  1790. IN PULONG ETypeArray,
  1791. IN ULONG ETypeCount,
  1792. IN BOOL bIncludeOldEtypes
  1793. )
  1794. {
  1795. KERBERR KerbErr = KDC_ERR_NONE;
  1796. ULONG Index;
  1797. PKERB_CRYPT_LIST ListHead = NULL;
  1798. PKERB_CRYPT_LIST ListTail = NULL;
  1799. PKERB_CRYPT_LIST NewListEntry = NULL;
  1800. //
  1801. // If there no encryption types, bail out now.
  1802. //
  1803. if (ETypeCount == 0)
  1804. {
  1805. *CryptList = NULL;
  1806. return(KDC_ERR_NONE);
  1807. }
  1808. for (Index = 0; Index < ETypeCount ; Index++)
  1809. {
  1810. if ( !bIncludeOldEtypes &&
  1811. ((ETypeArray[Index] == KERB_ETYPE_RC4_MD4) ||
  1812. (ETypeArray[Index] == KERB_ETYPE_RC4_HMAC_OLD)) )
  1813. {
  1814. continue;
  1815. }
  1816. NewListEntry = (PKERB_CRYPT_LIST) MIDL_user_allocate(sizeof(KERB_CRYPT_LIST));
  1817. if (NewListEntry == NULL)
  1818. {
  1819. KerbErr = KRB_ERR_GENERIC;
  1820. goto Cleanup;
  1821. }
  1822. NewListEntry->value = ETypeArray[Index];
  1823. NewListEntry->next = NULL;
  1824. if (ListTail != NULL)
  1825. {
  1826. ListTail->next = NewListEntry;
  1827. }
  1828. else
  1829. {
  1830. DsysAssert(ListHead == NULL);
  1831. ListHead = NewListEntry;
  1832. }
  1833. ListTail = NewListEntry;
  1834. }
  1835. *CryptList = ListHead;
  1836. ListHead = NULL;
  1837. Cleanup:
  1838. while (ListHead != NULL)
  1839. {
  1840. NewListEntry = ListHead->next;
  1841. MIDL_user_free(ListHead);
  1842. ListHead = NewListEntry;
  1843. }
  1844. return(KerbErr);
  1845. }
  1846. //+-------------------------------------------------------------------------
  1847. //
  1848. // Function: KerbConvertKeysToCryptList
  1849. //
  1850. // Synopsis: Converts an array of keys to types to a linked list
  1851. //
  1852. // Effects:
  1853. //
  1854. // Arguments:
  1855. //
  1856. // Requires:
  1857. //
  1858. // Returns:
  1859. //
  1860. // Notes:
  1861. //
  1862. //
  1863. //--------------------------------------------------------------------------
  1864. KERBERR
  1865. KerbConvertKeysToCryptList(
  1866. OUT PKERB_CRYPT_LIST * CryptList,
  1867. IN PKERB_STORED_CREDENTIAL Keys
  1868. )
  1869. {
  1870. KERBERR KerbErr = KDC_ERR_NONE;
  1871. ULONG Index;
  1872. PKERB_CRYPT_LIST ListHead = NULL;
  1873. PKERB_CRYPT_LIST ListTail = NULL;
  1874. PKERB_CRYPT_LIST NewListEntry = NULL;
  1875. //
  1876. // If there no encryption types, bail out now.
  1877. //
  1878. if (Keys->CredentialCount == 0)
  1879. {
  1880. *CryptList = NULL;
  1881. return(KDC_ERR_NONE);
  1882. }
  1883. for (Index = 0; Index < Keys->CredentialCount ; Index++ )
  1884. {
  1885. NewListEntry = (PKERB_CRYPT_LIST) MIDL_user_allocate(sizeof(KERB_CRYPT_LIST));
  1886. if (NewListEntry == NULL)
  1887. {
  1888. KerbErr = KRB_ERR_GENERIC;
  1889. goto Cleanup;
  1890. }
  1891. NewListEntry->value = Keys->Credentials[Index].Key.keytype;
  1892. NewListEntry->next = NULL;
  1893. if (ListTail != NULL)
  1894. {
  1895. ListTail->next = NewListEntry;
  1896. }
  1897. else
  1898. {
  1899. DsysAssert(ListHead == NULL);
  1900. ListHead = NewListEntry;
  1901. }
  1902. ListTail = NewListEntry;
  1903. }
  1904. *CryptList = ListHead;
  1905. ListHead = NULL;
  1906. Cleanup:
  1907. while (ListHead != NULL)
  1908. {
  1909. NewListEntry = ListHead->next;
  1910. MIDL_user_free(ListHead);
  1911. ListHead = NewListEntry;
  1912. }
  1913. return(KerbErr);
  1914. }
  1915. //+-------------------------------------------------------------------------
  1916. //
  1917. // Function: KerbFreeCryptList
  1918. //
  1919. // Synopsis: Frees a list of crypt types
  1920. //
  1921. // Effects:
  1922. //
  1923. // Arguments: CryptList - List to free
  1924. //
  1925. // Requires:
  1926. //
  1927. // Returns:
  1928. //
  1929. // Notes:
  1930. //
  1931. //
  1932. //--------------------------------------------------------------------------
  1933. VOID
  1934. KerbFreeCryptList(
  1935. IN PKERB_CRYPT_LIST CryptList
  1936. )
  1937. {
  1938. PKERB_CRYPT_LIST ListHead = CryptList;
  1939. PKERB_CRYPT_LIST NewListEntry;
  1940. while (ListHead != NULL)
  1941. {
  1942. NewListEntry = ListHead->next;
  1943. MIDL_user_free(ListHead);
  1944. ListHead = NewListEntry;
  1945. }
  1946. }
  1947. //+-------------------------------------------------------------------------
  1948. //
  1949. // Function: KerbInitAsn
  1950. //
  1951. // Synopsis: Initializes asn1 marshalling code
  1952. //
  1953. // Effects:
  1954. //
  1955. // Arguments: none
  1956. //
  1957. // Requires:
  1958. //
  1959. // Returns: KDC_ERR_NONE on success, KRB_ERR_GENERIC on failure
  1960. //
  1961. // Notes:
  1962. //
  1963. //
  1964. //--------------------------------------------------------------------------
  1965. BOOL fKRB5ModuleStarted = FALSE;
  1966. KERBERR
  1967. KerbInitAsn(
  1968. IN OUT ASN1encoding_t * pEnc,
  1969. IN OUT ASN1decoding_t * pDec
  1970. )
  1971. {
  1972. KERBERR KerbErr = KRB_ERR_GENERIC;
  1973. ASN1error_e Asn1Err;
  1974. if (!fKRB5ModuleStarted)
  1975. {
  1976. fKRB5ModuleStarted = TRUE;
  1977. KRB5_Module_Startup();
  1978. }
  1979. if (pEnc != NULL)
  1980. {
  1981. Asn1Err = ASN1_CreateEncoder(
  1982. KRB5_Module,
  1983. pEnc,
  1984. NULL, // pbBuf
  1985. 0, // cbBufSize
  1986. NULL // pParent
  1987. );
  1988. }
  1989. else
  1990. {
  1991. Asn1Err = ASN1_CreateDecoder(
  1992. KRB5_Module,
  1993. pDec,
  1994. NULL, // pbBuf
  1995. 0, // cbBufSize
  1996. NULL // pParent
  1997. );
  1998. }
  1999. if (ASN1_SUCCESS != Asn1Err)
  2000. {
  2001. DebugLog((DEB_ERROR, "Failed to init ASN1: 0x%x\n",Asn1Err));
  2002. goto Cleanup;
  2003. }
  2004. KerbErr = KDC_ERR_NONE;
  2005. Cleanup:
  2006. return(KerbErr);
  2007. }
  2008. //+-------------------------------------------------------------------------
  2009. //
  2010. // Function: KerbTermAsn
  2011. //
  2012. // Synopsis: terminates an ASN world
  2013. //
  2014. // Effects:
  2015. //
  2016. // Arguments:
  2017. //
  2018. // Requires:
  2019. //
  2020. // Returns:
  2021. //
  2022. // Notes:
  2023. //
  2024. //
  2025. //--------------------------------------------------------------------------
  2026. VOID
  2027. KerbTermAsn(
  2028. IN ASN1encoding_t pEnc,
  2029. IN ASN1decoding_t pDec
  2030. )
  2031. {
  2032. if (pEnc != NULL)
  2033. {
  2034. ASN1_CloseEncoder(pEnc);
  2035. }
  2036. else if (pDec != NULL)
  2037. {
  2038. ASN1_CloseDecoder(pDec);
  2039. }
  2040. //KRB5_Module_Cleanup();
  2041. }
  2042. //+-------------------------------------------------------------------------
  2043. //
  2044. // Function: KerbPackData
  2045. //
  2046. // Synopsis: Packs a datatype using ASN.1 encoding
  2047. //
  2048. // Effects: allocates memory with MIDL_user_allocate
  2049. //
  2050. // Arguments: Data - The message to marshall/pack.
  2051. // PduValue - The PDU for the message type
  2052. // DataSize - receives the size of the marshalled message in
  2053. // bytes.
  2054. // MarshalledData - receives a pointer to the marshalled
  2055. // message buffer.
  2056. //
  2057. // Requires:
  2058. //
  2059. // Returns:
  2060. //
  2061. // Notes:
  2062. //
  2063. //
  2064. //--------------------------------------------------------------------------
  2065. KERBERR NTAPI
  2066. KerbPackData(
  2067. IN PVOID Data,
  2068. IN ULONG PduValue,
  2069. OUT PULONG DataSize,
  2070. OUT PUCHAR * MarshalledData
  2071. )
  2072. {
  2073. KERBERR KerbErr = KDC_ERR_NONE;
  2074. ASN1encoding_t pEnc = NULL;
  2075. ASN1error_e Asn1Err;
  2076. KerbErr = KerbInitAsn(
  2077. &pEnc, // we are encoding
  2078. NULL
  2079. );
  2080. if (!KERB_SUCCESS(KerbErr))
  2081. {
  2082. goto Cleanup;
  2083. }
  2084. //
  2085. // Encode the data type.
  2086. //
  2087. // D_DebugLog((DEB_TRACE, "KerbPackData encoding pdu #%d\n", PduValue));
  2088. Asn1Err = ASN1_Encode(
  2089. pEnc,
  2090. Data,
  2091. PduValue,
  2092. ASN1ENCODE_ALLOCATEBUFFER,
  2093. NULL, // pbBuf
  2094. 0 // cbBufSize
  2095. );
  2096. if (!ASN1_SUCCEEDED(Asn1Err))
  2097. {
  2098. DebugLog((DEB_ERROR,"Failed to encode data: %d\n",Asn1Err));
  2099. KerbErr = KRB_ERR_GENERIC;
  2100. goto Cleanup;
  2101. }
  2102. else
  2103. {
  2104. //
  2105. // when the oss compiler was used the allocation routines were configurable.
  2106. // therefore, the encoded data could just be free'd using our
  2107. // deallocator. in the new model we cannot configure the allocation routines
  2108. // for encoding.
  2109. // so we do not have to go and change every place where a free
  2110. // of an encoded buffer is done, use our allocator to allocate a new buffer,
  2111. // then copy the encoded data to it, and free the buffer that was allocated by
  2112. // the encoding engine. THIS SHOULD BE CHANGED FOR BETTER PERFORMANCE
  2113. //
  2114. *MarshalledData = (PUCHAR) MIDL_user_allocate(pEnc->len);
  2115. if (*MarshalledData == NULL)
  2116. {
  2117. KerbErr = KRB_ERR_GENERIC;
  2118. *DataSize = 0;
  2119. }
  2120. else
  2121. {
  2122. RtlCopyMemory(*MarshalledData, pEnc->buf, pEnc->len);
  2123. *DataSize = pEnc->len;
  2124. }
  2125. ASN1_FreeEncoded(pEnc, pEnc->buf);
  2126. }
  2127. Cleanup:
  2128. KerbTermAsn(pEnc, NULL);
  2129. return(KerbErr);
  2130. }
  2131. //+-------------------------------------------------------------------------
  2132. //
  2133. // Function: KerbUnpackData
  2134. //
  2135. // Synopsis: Unpacks an message from the ASN.1 encoding
  2136. //
  2137. // Effects:
  2138. //
  2139. // Arguments: Data - Buffer containing the reply message.
  2140. // DataSize - Size of the reply message in bytes
  2141. // Reply - receives a KERB_ENCRYPTED_DATA structure allocated with
  2142. // MIDL_user_allocate.
  2143. //
  2144. // Requires:
  2145. //
  2146. // Returns:
  2147. //
  2148. // Notes:
  2149. //
  2150. //
  2151. //--------------------------------------------------------------------------
  2152. KERBERR NTAPI
  2153. KerbUnpackData(
  2154. IN PUCHAR Data,
  2155. IN ULONG DataSize,
  2156. IN ULONG PduValue,
  2157. OUT PVOID * DecodedData
  2158. )
  2159. {
  2160. KERBERR KerbErr = KDC_ERR_NONE;
  2161. ASN1decoding_t pDec = NULL;
  2162. ASN1error_e Asn1Err;
  2163. if ((DataSize == 0) || (Data == NULL))
  2164. {
  2165. DebugLog((DEB_ERROR, "KerbUnpackData Trying to unpack NULL data\n"));
  2166. return(KRB_ERR_GENERIC);
  2167. }
  2168. KerbErr = KerbInitAsn(
  2169. NULL,
  2170. &pDec // we are decoding
  2171. );
  2172. if (!KERB_SUCCESS(KerbErr))
  2173. {
  2174. DebugLog((DEB_ERROR, "KerbUnpackData failed to init Asn %#x\n", KerbErr));
  2175. return(KerbErr);
  2176. }
  2177. *DecodedData = NULL;
  2178. Asn1Err = ASN1_Decode(
  2179. pDec,
  2180. DecodedData,
  2181. PduValue,
  2182. ASN1DECODE_SETBUFFER,
  2183. (BYTE *) Data,
  2184. DataSize
  2185. );
  2186. if (!ASN1_SUCCEEDED(Asn1Err))
  2187. {
  2188. D_DebugLog((DEB_TRACE, "KerbUnpackData Asn1Err %#x\n", Asn1Err));
  2189. if ((ASN1_ERR_BADARGS == Asn1Err) ||
  2190. (ASN1_ERR_EOD == Asn1Err))
  2191. {
  2192. D_DebugLog((DEB_TRACE, "More input required to decode data %d.\n", PduValue));
  2193. KerbErr = KDC_ERR_MORE_DATA;
  2194. }
  2195. else
  2196. {
  2197. if (ASN1_ERR_BADTAG != Asn1Err)
  2198. {
  2199. DebugLog((DEB_ERROR, "Failed to decode data: %d\n", Asn1Err ));
  2200. }
  2201. KerbErr = KRB_ERR_GENERIC;
  2202. }
  2203. *DecodedData = NULL;
  2204. }
  2205. KerbTermAsn(NULL, pDec);
  2206. return(KerbErr);
  2207. }
  2208. //+-------------------------------------------------------------------------
  2209. //
  2210. // Function: KerbFreeData
  2211. //
  2212. // Synopsis: Frees a structure unpacked by the ASN1 decoder
  2213. //
  2214. // Effects:
  2215. //
  2216. // Arguments:
  2217. //
  2218. // Requires:
  2219. //
  2220. // Returns:
  2221. //
  2222. // Notes:
  2223. //
  2224. //
  2225. //--------------------------------------------------------------------------
  2226. VOID
  2227. KerbFreeData(
  2228. IN ULONG PduValue,
  2229. IN PVOID Data
  2230. )
  2231. {
  2232. ASN1decoding_t pDec = NULL;
  2233. if (ARGUMENT_PRESENT(Data))
  2234. {
  2235. KERBERR KerbErr;
  2236. KerbErr = KerbInitAsn(
  2237. NULL,
  2238. &pDec // this is a decoded structure
  2239. );
  2240. if (KERB_SUCCESS(KerbErr))
  2241. {
  2242. ASN1_FreeDecoded(pDec, Data, PduValue);
  2243. KerbTermAsn(NULL, pDec);
  2244. }
  2245. }
  2246. }
  2247. //+-------------------------------------------------------------------------
  2248. //
  2249. // Function: KerbFreeTicketExtensions
  2250. //
  2251. // Synopsis: Frees a host address allocated with KerbDuplicateTicketExtensions
  2252. //
  2253. // Effects:
  2254. //
  2255. // Arguments: Addresses - The name to free
  2256. //
  2257. // Requires:
  2258. //
  2259. // Returns:
  2260. //
  2261. // Notes:
  2262. //
  2263. //
  2264. //--------------------------------------------------------------------------
  2265. VOID
  2266. KerbFreeTicketExtensions(
  2267. IN PKERB_TICKET_EXTENSIONS Extensions
  2268. )
  2269. {
  2270. PKERB_TICKET_EXTENSIONS Elem,NextElem;
  2271. Elem = Extensions;
  2272. while (Elem != NULL)
  2273. {
  2274. if (Elem->value.te_data.value != NULL)
  2275. {
  2276. MIDL_user_free(Elem->value.te_data.value);
  2277. }
  2278. NextElem = Elem->next;
  2279. MIDL_user_free(Elem);
  2280. Elem = NextElem;
  2281. }
  2282. }
  2283. //+-------------------------------------------------------------------------
  2284. //
  2285. // Function: KerbDuplicateTicketExtensions
  2286. //
  2287. // Synopsis: duplicates the ticket extensions field from a ticket
  2288. //
  2289. // Effects:
  2290. //
  2291. // Arguments:
  2292. //
  2293. // Requires:
  2294. //
  2295. // Returns:
  2296. //
  2297. // Notes:
  2298. //
  2299. //
  2300. //--------------------------------------------------------------------------
  2301. KERBERR
  2302. KerbDuplicateTicketExtensions(
  2303. OUT PKERB_TICKET_EXTENSIONS * Dest,
  2304. IN PKERB_TICKET_EXTENSIONS Source
  2305. )
  2306. {
  2307. KERBERR Status = KDC_ERR_NONE;
  2308. PKERB_TICKET_EXTENSIONS SourceElem;
  2309. PKERB_TICKET_EXTENSIONS DestElem;
  2310. PKERB_TICKET_EXTENSIONS * NextElem;
  2311. *Dest = NULL;
  2312. SourceElem = Source;
  2313. NextElem = Dest;
  2314. while (SourceElem != NULL)
  2315. {
  2316. DestElem = (PKERB_TICKET_EXTENSIONS) MIDL_user_allocate(sizeof(KERB_TICKET_EXTENSIONS));
  2317. if (DestElem == NULL)
  2318. {
  2319. Status = KRB_ERR_GENERIC;
  2320. goto Cleanup;
  2321. }
  2322. *DestElem = *SourceElem;
  2323. DestElem->value.te_data.value = (PUCHAR) MIDL_user_allocate(SourceElem->value.te_data.length);
  2324. if (DestElem->value.te_data.value == NULL)
  2325. {
  2326. MIDL_user_free(DestElem);
  2327. Status = KRB_ERR_GENERIC;
  2328. goto Cleanup;
  2329. }
  2330. RtlCopyMemory(
  2331. DestElem->value.te_data.value,
  2332. SourceElem->value.te_data.value,
  2333. SourceElem->value.te_data.length
  2334. );
  2335. DestElem->next = NULL;
  2336. *NextElem = DestElem;
  2337. NextElem = &DestElem->next;
  2338. SourceElem = SourceElem->next;
  2339. }
  2340. Cleanup:
  2341. if (!KERB_SUCCESS(Status))
  2342. {
  2343. KerbFreeTicketExtensions(*Dest);
  2344. *Dest = NULL;
  2345. }
  2346. return(Status);
  2347. }
  2348. //+-------------------------------------------------------------------------
  2349. //
  2350. // Function: KerbDuplicateTicket
  2351. //
  2352. // Synopsis: Duplicates a ticket so the original may be freed
  2353. //
  2354. // Effects:
  2355. //
  2356. // Arguments: Dest - Destination, receives duplicate
  2357. // Source - Source ticket
  2358. //
  2359. // Requires:
  2360. //
  2361. // Returns: KDC_ERR_NONE or KRB_ERR_GENERIC;
  2362. //
  2363. // Notes:
  2364. //
  2365. //
  2366. //--------------------------------------------------------------------------
  2367. KERBERR NTAPI
  2368. KerbDuplicateTicket(
  2369. OUT PKERB_TICKET Dest,
  2370. IN PKERB_TICKET Source
  2371. )
  2372. {
  2373. KERBERR KerbErr = KDC_ERR_NONE;
  2374. RtlZeroMemory(
  2375. Dest,
  2376. sizeof(KERB_TICKET)
  2377. );
  2378. Dest->ticket_version = Source->ticket_version;
  2379. KerbErr = KerbDuplicatePrincipalName(
  2380. &Dest->server_name,
  2381. &Source->server_name
  2382. );
  2383. if (!KERB_SUCCESS(KerbErr))
  2384. {
  2385. goto Cleanup;
  2386. }
  2387. KerbErr = KerbDuplicateRealm(
  2388. &Dest->realm,
  2389. Source->realm
  2390. );
  2391. if (!KERB_SUCCESS(KerbErr))
  2392. {
  2393. goto Cleanup;
  2394. }
  2395. KerbErr = KerbDuplicateTicketExtensions(
  2396. &Dest->ticket_extensions,
  2397. Source->ticket_extensions
  2398. );
  2399. if (!KERB_SUCCESS(KerbErr))
  2400. {
  2401. goto Cleanup;
  2402. }
  2403. Dest->encrypted_part = Source->encrypted_part;
  2404. Dest->encrypted_part.cipher_text.value = (PUCHAR) MIDL_user_allocate(Dest->encrypted_part.cipher_text.length);
  2405. if (Dest->encrypted_part.cipher_text.value == NULL)
  2406. {
  2407. KerbErr = KRB_ERR_GENERIC;
  2408. goto Cleanup;
  2409. }
  2410. RtlCopyMemory(
  2411. Dest->encrypted_part.cipher_text.value,
  2412. Source->encrypted_part.cipher_text.value,
  2413. Dest->encrypted_part.cipher_text.length
  2414. );
  2415. Cleanup:
  2416. if (!KERB_SUCCESS(KerbErr))
  2417. {
  2418. KerbFreeDuplicatedTicket(Dest);
  2419. }
  2420. return(KerbErr);
  2421. }
  2422. //+-------------------------------------------------------------------------
  2423. //
  2424. // Function: KerbFreeDuplicatedTicket
  2425. //
  2426. // Synopsis: Frees ticket duplicated with KerbDuplicateTicket
  2427. //
  2428. // Effects: frees memory
  2429. //
  2430. // Arguments: Ticket - ticket to free
  2431. //
  2432. // Requires:
  2433. //
  2434. // Returns: none
  2435. //
  2436. // Notes:
  2437. //
  2438. //
  2439. //--------------------------------------------------------------------------
  2440. VOID
  2441. KerbFreeDuplicatedTicket(
  2442. IN PKERB_TICKET Ticket
  2443. )
  2444. {
  2445. KerbFreePrincipalName(
  2446. &Ticket->server_name
  2447. );
  2448. KerbFreeRealm(
  2449. &Ticket->realm
  2450. );
  2451. if (Ticket->encrypted_part.cipher_text.value != NULL)
  2452. {
  2453. MIDL_user_free(Ticket->encrypted_part.cipher_text.value);
  2454. }
  2455. KerbFreeTicketExtensions(
  2456. Ticket->ticket_extensions
  2457. );
  2458. }
  2459. //+-------------------------------------------------------------------------
  2460. //
  2461. // Function: KerbBuildErrorMessageEx
  2462. //
  2463. // Synopsis: Builds an error message
  2464. //
  2465. // Effects:
  2466. //
  2467. // Arguments:
  2468. //
  2469. // Requires:
  2470. //
  2471. // Returns: marshalled error message, to be freed with MIDL_user_free
  2472. //
  2473. // Notes:
  2474. //
  2475. //
  2476. //--------------------------------------------------------------------------
  2477. KERBERR
  2478. KerbBuildErrorMessageEx(
  2479. IN KERBERR ErrorCode,
  2480. IN OPTIONAL PKERB_EXT_ERROR pExtendedError,
  2481. IN PUNICODE_STRING ServerRealm,
  2482. IN PKERB_INTERNAL_NAME ServerName,
  2483. IN OPTIONAL PUNICODE_STRING ClientRealm,
  2484. IN PBYTE ErrorData,
  2485. IN ULONG ErrorDataSize,
  2486. OUT PULONG ErrorMessageSize,
  2487. OUT PUCHAR* ErrorMessage
  2488. )
  2489. {
  2490. KERBERR KerbErr = KDC_ERR_NONE;
  2491. KERB_ERROR Error;
  2492. KERB_TYPED_DATA Data = {0};
  2493. TimeStamp TimeNow;
  2494. *ErrorMessageSize = 0;
  2495. *ErrorMessage = NULL;
  2496. GetSystemTimeAsFileTime(
  2497. (PFILETIME) &TimeNow
  2498. );
  2499. RtlZeroMemory(
  2500. &Error,
  2501. sizeof(KERB_ERROR)
  2502. );
  2503. DsysAssert(ErrorCode != KDC_ERR_MORE_DATA);
  2504. Error.version = KERBEROS_VERSION;
  2505. Error.message_type = KRB_ERROR;
  2506. KerbConvertLargeIntToGeneralizedTimeWrapper(
  2507. &Error.server_time,
  2508. &Error.server_usec,
  2509. &TimeNow
  2510. );
  2511. //
  2512. // These errors must *never* hit the wire. They're for use in the KDC
  2513. // and kerb innards only.
  2514. //
  2515. switch (ErrorCode)
  2516. {
  2517. case KDC_ERR_MORE_DATA:
  2518. case KDC_ERR_NOT_RUNNING:
  2519. case KDC_ERR_NO_RESPONSE:
  2520. case KDC_ERR_NO_TRUST_PATH:
  2521. case KRB_ERR_NAME_TOO_LONG:
  2522. ErrorCode = KRB_ERR_GENERIC;
  2523. break;
  2524. default:
  2525. NOTHING;
  2526. }
  2527. Error.error_code = ErrorCode;
  2528. //
  2529. // Ignore errors because this is already an error return
  2530. //
  2531. KerbConvertUnicodeStringToRealm(
  2532. &Error.realm,
  2533. ServerRealm
  2534. );
  2535. if (ARGUMENT_PRESENT(ClientRealm) && (ClientRealm->Buffer != NULL))
  2536. {
  2537. KerbConvertUnicodeStringToRealm(
  2538. &Error.client_realm,
  2539. ClientRealm
  2540. );
  2541. Error.bit_mask |= client_realm_present;
  2542. }
  2543. KerbConvertKdcNameToPrincipalName(
  2544. &Error.server_name,
  2545. ServerName
  2546. );
  2547. //
  2548. // Small problem here. We may have preauth data that we want
  2549. // to return to the client, instead of extended errors. To
  2550. // avoid this, we just make sure that we only return extended
  2551. // errors if no ErrorData previously set.
  2552. //
  2553. if (ARGUMENT_PRESENT(ErrorData))
  2554. {
  2555. Error.error_data.length = (int) ErrorDataSize;
  2556. Error.error_data.value = ErrorData;
  2557. Error.bit_mask |= error_data_present;
  2558. }
  2559. else if (ARGUMENT_PRESENT(pExtendedError) && !EXT_ERROR_SUCCESS((*pExtendedError)))
  2560. {
  2561. Data.data_type = TD_EXTENDED_ERROR;
  2562. KerbErr = KerbPackData(
  2563. pExtendedError,
  2564. KERB_EXT_ERROR_PDU,
  2565. &Data.data_value.length,
  2566. &Data.data_value.value
  2567. );
  2568. if (!KERB_SUCCESS(KerbErr))
  2569. {
  2570. DebugLog((DEB_WARN, "KerbBuildErrorMessageEx failed To pack extended error %#x!\n", KerbErr));
  2571. goto Cleanup;
  2572. }
  2573. Error.bit_mask |= error_data_present;
  2574. KerbErr = TypedDataListPushFront(
  2575. NULL,
  2576. &Data,
  2577. &Error.error_data.length,
  2578. &Error.error_data.value
  2579. );
  2580. if (!KERB_SUCCESS(KerbErr))
  2581. {
  2582. DebugLog((DEB_WARN, "KerbBuildErrorMessageEx failed To pack typed data %#x!\n", KerbErr));
  2583. goto Cleanup;
  2584. }
  2585. }
  2586. KerbErr = KerbPackData(
  2587. &Error,
  2588. KERB_ERROR_PDU,
  2589. ErrorMessageSize,
  2590. ErrorMessage
  2591. );
  2592. Cleanup:
  2593. KerbFreeRealm(
  2594. &Error.realm
  2595. );
  2596. KerbFreeRealm(
  2597. &Error.client_realm
  2598. );
  2599. KerbFreePrincipalName(
  2600. &Error.server_name
  2601. );
  2602. if (Data.data_value.value && Data.data_value.length)
  2603. {
  2604. MIDL_user_free(Data.data_value.value);
  2605. }
  2606. if ((ErrorData != Error.error_data.value)
  2607. && Error.error_data.value
  2608. && Error.error_data.length)
  2609. {
  2610. MIDL_user_free(Error.error_data.value);
  2611. }
  2612. return (KerbErr);
  2613. }
  2614. //+-------------------------------------------------------------------------
  2615. //
  2616. // Function: KerbGetKeyFromList
  2617. //
  2618. // Synopsis: Gets the key of the appropriate encryption type off the list
  2619. //
  2620. // Effects:
  2621. //
  2622. // Arguments: Passwords - list of keys
  2623. // EncryptionType - Encryption type to use
  2624. //
  2625. // Requires:
  2626. //
  2627. // Returns: The found key, or NULL if one wasn't found
  2628. //
  2629. // Notes:
  2630. //
  2631. //
  2632. //--------------------------------------------------------------------------
  2633. PKERB_ENCRYPTION_KEY
  2634. KerbGetKeyFromList(
  2635. IN PKERB_STORED_CREDENTIAL Passwords,
  2636. IN ULONG EncryptionType
  2637. )
  2638. {
  2639. ULONG Index;
  2640. if (!ARGUMENT_PRESENT(Passwords))
  2641. {
  2642. return(NULL);
  2643. }
  2644. for (Index = 0; Index < Passwords->CredentialCount ; Index++ )
  2645. {
  2646. if (Passwords->Credentials[Index].Key.keytype == (int) EncryptionType)
  2647. {
  2648. return(&Passwords->Credentials[Index].Key);
  2649. }
  2650. }
  2651. return(NULL);
  2652. }
  2653. //+-------------------------------------------------------------------------
  2654. //
  2655. // Function: KerbGetKeyFromListByIndex
  2656. //
  2657. // Synopsis: Gets the key of the appropriate encryption type off the list
  2658. // starting from a provided index
  2659. //
  2660. // Effects:
  2661. //
  2662. // Arguments: Passwords - list of keys
  2663. // EncryptionType - Encryption type to use
  2664. // pIndex - provides starting location for key selection
  2665. //
  2666. // Requires:
  2667. //
  2668. // Returns: The found key, or NULL if one wasn't found
  2669. //
  2670. // Notes:
  2671. //
  2672. //
  2673. //--------------------------------------------------------------------------
  2674. PKERB_ENCRYPTION_KEY
  2675. KerbGetKeyFromListByIndex(
  2676. IN PKERB_STORED_CREDENTIAL Passwords,
  2677. IN ULONG EncryptionType,
  2678. OUT PULONG pIndex
  2679. )
  2680. {
  2681. ULONG Index;
  2682. if (!ARGUMENT_PRESENT(Passwords) || !ARGUMENT_PRESENT(pIndex))
  2683. {
  2684. return(NULL);
  2685. }
  2686. if (*pIndex >= Passwords->CredentialCount)
  2687. {
  2688. return(NULL);
  2689. }
  2690. for (Index = *pIndex; Index < Passwords->CredentialCount ; Index++ )
  2691. {
  2692. if (Passwords->Credentials[Index].Key.keytype == (int) EncryptionType)
  2693. {
  2694. *pIndex = Index + 1; // Start on next key if called again
  2695. return(&Passwords->Credentials[Index].Key);
  2696. }
  2697. }
  2698. return(NULL);
  2699. }
  2700. //+-------------------------------------------------------------------------
  2701. //
  2702. // Function: KerbFindCommonCryptSystem
  2703. //
  2704. // Synopsis: Finds a common crypt system including availablity
  2705. // of passwords.
  2706. //
  2707. // Effects:
  2708. //
  2709. // Arguments: CryptList - List of client's crypto systems
  2710. // Passwords - List of passwords
  2711. // MorePassword - Optionally another list of passwords to consider
  2712. // Key - Receives key for common crypt system
  2713. //
  2714. // Requires:
  2715. //
  2716. // Returns: KDC_ERR_ETYPE_NOTSUPP if no common system can be found
  2717. //
  2718. // Notes:
  2719. //
  2720. //
  2721. //--------------------------------------------------------------------------
  2722. KERBERR
  2723. KerbFindCommonCryptSystem(
  2724. IN PKERB_CRYPT_LIST CryptList,
  2725. IN PKERB_STORED_CREDENTIAL Passwords,
  2726. IN OPTIONAL PKERB_STORED_CREDENTIAL MorePasswords,
  2727. OUT PKERB_ENCRYPTION_KEY * Key
  2728. )
  2729. {
  2730. ULONG PasswordTypes[KERB_MAX_CRYPTO_SYSTEMS] = {0};
  2731. PULONG pCryptoSystems = NULL;
  2732. ULONG CryptoSystems[KERB_MAX_CRYPTO_SYSTEMS];
  2733. ULONG PasswordCount;
  2734. ULONG CryptoCount;
  2735. ULONG Index;
  2736. PKERB_CRYPT_LIST NextEType;
  2737. ULONG Index2;
  2738. ULONG KeyCount;
  2739. KERBERR KerbErr = KDC_ERR_ETYPE_NOTSUPP;
  2740. ULONG CommonCryptSystem = KERB_ETYPE_DEFAULT;
  2741. DsysAssert(CryptList != NULL);
  2742. if ((Passwords == NULL ) || (CryptList == NULL))
  2743. {
  2744. DebugLog((DEB_ERROR, "Null password or crypt list passed to KerbFindCommonCryptSystem\n"));
  2745. DsysAssert(FALSE);
  2746. return(KDC_ERR_ETYPE_NOTSUPP);
  2747. }
  2748. PasswordCount = Passwords->CredentialCount;
  2749. if (PasswordCount >= KERB_MAX_CRYPTO_SYSTEMS)
  2750. {
  2751. D_DebugLog((DEB_ERROR, "Got more than 20 crypto systems in password list\n"));
  2752. DsysAssert(PasswordCount < KERB_MAX_CRYPTO_SYSTEMS);
  2753. return(KDC_ERR_ETYPE_NOTSUPP);
  2754. }
  2755. KeyCount = 0;
  2756. for (Index = 0; Index < PasswordCount ; Index++ )
  2757. {
  2758. if (ARGUMENT_PRESENT(MorePasswords))
  2759. {
  2760. for (Index2 = 0; Index2 < MorePasswords->CredentialCount; Index2++ )
  2761. {
  2762. if (Passwords->Credentials[Index].Key.keytype == MorePasswords->Credentials[Index2].Key.keytype)
  2763. {
  2764. PasswordTypes[KeyCount++] = (ULONG) Passwords->Credentials[Index].Key.keytype;
  2765. break;
  2766. }
  2767. }
  2768. }
  2769. else
  2770. {
  2771. PasswordTypes[KeyCount++] = (ULONG) Passwords->Credentials[Index].Key.keytype;
  2772. }
  2773. }
  2774. CryptoCount = 0;
  2775. NextEType = CryptList;
  2776. while (NextEType != NULL)
  2777. {
  2778. NextEType = NextEType->next;
  2779. CryptoCount++;
  2780. // restrict to 100 crypt systems, even on a slowbuffer.
  2781. if (CryptoCount > KERB_MAX_CRYPTO_SYSTEMS_SLOWBUFF)
  2782. {
  2783. return(KDC_ERR_ETYPE_NOTSUPP);
  2784. }
  2785. }
  2786. if (CryptoCount >= KERB_MAX_CRYPTO_SYSTEMS)
  2787. {
  2788. pCryptoSystems = (PULONG) MIDL_user_allocate(CryptoCount * sizeof(ULONG));
  2789. if (NULL == pCryptoSystems)
  2790. {
  2791. return ( KRB_ERR_GENERIC );
  2792. }
  2793. }
  2794. else // fast buff
  2795. {
  2796. pCryptoSystems = CryptoSystems;
  2797. }
  2798. // populate values
  2799. NextEType = CryptList;
  2800. Index = 0;
  2801. while (NextEType != NULL)
  2802. {
  2803. pCryptoSystems[Index] = NextEType->value;
  2804. NextEType = NextEType->next;
  2805. Index++;
  2806. }
  2807. DsysAssert(Index == CryptoCount);
  2808. KerbErr = KerbMapStatusToKerbError(
  2809. CDFindCommonCSystemWithKey(
  2810. CryptoCount,
  2811. pCryptoSystems,
  2812. PasswordCount,
  2813. PasswordTypes,
  2814. &CommonCryptSystem
  2815. ));
  2816. if (!KERB_SUCCESS(KerbErr))
  2817. {
  2818. DebugLog((DEB_ERROR, "KLIN(%x) Missing common crypt system: %#x\n", KLIN(FILENO, __LINE__), KerbErr));
  2819. goto cleanup;
  2820. }
  2821. //
  2822. // Now find the key to return.
  2823. //
  2824. for (Index = 0; Index < Passwords->CredentialCount ; Index++ )
  2825. {
  2826. if (Passwords->Credentials[Index].Key.keytype == (int) CommonCryptSystem)
  2827. {
  2828. *Key = &Passwords->Credentials[Index].Key;
  2829. KerbErr = KDC_ERR_NONE;
  2830. break;
  2831. }
  2832. }
  2833. if (!KERB_SUCCESS(KerbErr))
  2834. {
  2835. DebugLog((DEB_ERROR,"KLIN(%x) Couldn't find password type after finding common csystem!\n", KLIN(FILENO, __LINE__)));
  2836. }
  2837. cleanup:
  2838. if ((pCryptoSystems != NULL) &&
  2839. (pCryptoSystems != CryptoSystems))
  2840. {
  2841. MIDL_user_free(pCryptoSystems);
  2842. }
  2843. return (KerbErr);
  2844. }
  2845. //+-------------------------------------------------------------------------
  2846. //
  2847. // Function: KerbFindCommonCryptSystemForSKey
  2848. //
  2849. // Synopsis: Finds a common crypt system including availablity
  2850. // for session keys.
  2851. //
  2852. // Effects:
  2853. //
  2854. // Arguments: CryptList - List of client's crypto systems
  2855. // CryptListSupported - List of crypto systems supported
  2856. // Etype - Receives the common crypt system
  2857. //
  2858. // Requires:
  2859. //
  2860. // Returns: KDC_ERR_ETYPE_NOTSUPP if no common system can be found
  2861. //
  2862. // Notes:
  2863. //
  2864. //
  2865. //--------------------------------------------------------------------------
  2866. KERBERR
  2867. KerbFindCommonCryptSystemForSKey(
  2868. IN PKERB_CRYPT_LIST CryptList,
  2869. IN PKERB_CRYPT_LIST CryptListSupported,
  2870. OUT ULONG * Etype
  2871. )
  2872. {
  2873. *Etype = KERB_ETYPE_NULL;
  2874. for (PKERB_CRYPT_LIST NextEType1 = CryptList;
  2875. NextEType1 != NULL;
  2876. NextEType1 = NextEType1->next)
  2877. {
  2878. for (PKERB_CRYPT_LIST NextEType2 = CryptListSupported;
  2879. NextEType2 != NULL;
  2880. NextEType2 = NextEType2->next)
  2881. {
  2882. if (NextEType1->value == NextEType2->value)
  2883. {
  2884. *Etype = NextEType1->value;
  2885. return KDC_ERR_NONE;
  2886. }
  2887. }
  2888. }
  2889. return KDC_ERR_ETYPE_NOTSUPP;
  2890. }
  2891. //+-------------------------------------------------------------------------
  2892. //
  2893. // Function: KerbMapKerbError
  2894. //
  2895. // Synopsis: Maps a kerb error to an NTSTATUS
  2896. //
  2897. // Effects:
  2898. //
  2899. // Arguments:
  2900. //
  2901. // Requires:
  2902. //
  2903. // Returns:
  2904. //
  2905. // Notes:
  2906. //
  2907. //
  2908. //--------------------------------------------------------------------------
  2909. NTSTATUS
  2910. KerbMapKerbError(
  2911. IN KERBERR KerbError
  2912. )
  2913. {
  2914. NTSTATUS Status;
  2915. switch(KerbError) {
  2916. case KDC_ERR_NONE:
  2917. Status = STATUS_SUCCESS;
  2918. break;
  2919. case KDC_ERR_CLIENT_REVOKED:
  2920. Status = STATUS_ACCOUNT_DISABLED;
  2921. break;
  2922. case KDC_ERR_KEY_EXPIRED:
  2923. Status = STATUS_PASSWORD_EXPIRED;
  2924. break;
  2925. case KRB_ERR_GENERIC:
  2926. Status = STATUS_INSUFFICIENT_RESOURCES;
  2927. break;
  2928. case KRB_AP_ERR_SKEW:
  2929. case KRB_AP_ERR_TKT_NYV:
  2930. // Note this was added because of the following scenario:
  2931. // Let's say the dc and the client have the correct time. And the
  2932. // server's time is off. We aren't going to get rid of the ticket for the
  2933. // server on the client because it hasn't expired yet. But, the server
  2934. // thinks it has. If event logging was turned on, then admins could look
  2935. // at the server's event log and potentially deduce that the server's
  2936. // time is off relative to the dc.
  2937. case KRB_AP_ERR_TKT_EXPIRED:
  2938. Status = STATUS_TIME_DIFFERENCE_AT_DC;
  2939. break;
  2940. case KDC_ERR_POLICY:
  2941. Status = STATUS_ACCOUNT_RESTRICTION;
  2942. break;
  2943. case KDC_ERR_C_PRINCIPAL_UNKNOWN:
  2944. Status = STATUS_NO_SUCH_USER;
  2945. break;
  2946. case KDC_ERR_S_PRINCIPAL_UNKNOWN:
  2947. Status = STATUS_NO_TRUST_SAM_ACCOUNT;
  2948. break;
  2949. case KRB_AP_ERR_MODIFIED:
  2950. case KDC_ERR_PREAUTH_FAILED:
  2951. case KDC_ERR_PREAUTH_REQUIRED:
  2952. Status = STATUS_WRONG_PASSWORD;
  2953. break;
  2954. case KRB_ERR_RESPONSE_TOO_BIG:
  2955. Status = STATUS_INVALID_BUFFER_SIZE;
  2956. break;
  2957. case KDC_ERR_PADATA_TYPE_NOSUPP:
  2958. Status = STATUS_NOT_SUPPORTED;
  2959. break;
  2960. case KRB_AP_ERR_NOT_US:
  2961. Status = SEC_E_WRONG_PRINCIPAL;
  2962. break;
  2963. case KDC_ERR_SVC_UNAVAILABLE:
  2964. Status = STATUS_NO_LOGON_SERVERS;
  2965. break;
  2966. case KDC_ERR_WRONG_REALM:
  2967. Status = STATUS_NO_LOGON_SERVERS;
  2968. break;
  2969. case KDC_ERR_CANT_VERIFY_CERTIFICATE:
  2970. Status = TRUST_E_SYSTEM_ERROR;
  2971. break;
  2972. case KDC_ERR_INVALID_CERTIFICATE:
  2973. Status = STATUS_INVALID_PARAMETER;
  2974. break;
  2975. case KDC_ERR_REVOKED_CERTIFICATE:
  2976. Status = CRYPT_E_REVOKED;
  2977. break;
  2978. case KDC_ERR_REVOCATION_STATUS_UNKNOWN:
  2979. Status = CRYPT_E_NO_REVOCATION_CHECK;
  2980. break;
  2981. case KDC_ERR_REVOCATION_STATUS_UNAVAILABLE:
  2982. Status = CRYPT_E_REVOCATION_OFFLINE;
  2983. break;
  2984. case KDC_ERR_CLIENT_NAME_MISMATCH:
  2985. case KERB_PKINIT_CLIENT_NAME_MISMATCH:
  2986. case KDC_ERR_KDC_NAME_MISMATCH:
  2987. Status = STATUS_PKINIT_NAME_MISMATCH;
  2988. break;
  2989. case KDC_ERR_PATH_NOT_ACCEPTED:
  2990. Status = STATUS_TRUST_FAILURE;
  2991. break;
  2992. case KDC_ERR_ETYPE_NOTSUPP:
  2993. Status = STATUS_KDC_UNKNOWN_ETYPE;
  2994. break;
  2995. case KDC_ERR_MUST_USE_USER2USER:
  2996. case KRB_AP_ERR_USER_TO_USER_REQUIRED:
  2997. Status = STATUS_USER2USER_REQUIRED;
  2998. break;
  2999. case KRB_AP_ERR_NOKEY:
  3000. Status = STATUS_NO_KERB_KEY;
  3001. break;
  3002. case KRB_ERR_NAME_TOO_LONG:
  3003. Status = STATUS_NAME_TOO_LONG;
  3004. break;
  3005. default:
  3006. Status = STATUS_LOGON_FAILURE;
  3007. }
  3008. return(Status);
  3009. }
  3010. //+-------------------------------------------------------------------------
  3011. //
  3012. // Function: KerbMakeDomainRelativeSid
  3013. //
  3014. // Synopsis: Given a domain Id and a relative ID create the corresponding
  3015. // SID allocated with MIDL_user_allocate.
  3016. //
  3017. // Effects:
  3018. //
  3019. // Arguments: DomainId - The template SID to use.
  3020. //
  3021. // RelativeId - The relative Id to append to the DomainId.
  3022. //
  3023. // Requires:
  3024. //
  3025. // Returns: Sid - Returns a pointer to a buffer allocated from
  3026. // MIDL_user_allocate containing the resultant Sid.
  3027. //
  3028. // Notes:
  3029. //
  3030. //
  3031. //--------------------------------------------------------------------------
  3032. PSID
  3033. KerbMakeDomainRelativeSid(
  3034. IN PSID DomainId,
  3035. IN ULONG RelativeId
  3036. )
  3037. {
  3038. UCHAR DomainIdSubAuthorityCount;
  3039. ULONG Size;
  3040. PSID Sid;
  3041. //
  3042. // Allocate a Sid which has one more sub-authority than the domain ID.
  3043. //
  3044. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  3045. Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  3046. if ((Sid = MIDL_user_allocate( Size )) == NULL ) {
  3047. return NULL;
  3048. }
  3049. //
  3050. // Initialize the new SID to have the same inital value as the
  3051. // domain ID.
  3052. //
  3053. if ( !NT_SUCCESS( RtlCopySid( Size, Sid, DomainId ) ) ) {
  3054. MIDL_user_free( Sid );
  3055. return NULL;
  3056. }
  3057. //
  3058. // Adjust the sub-authority count and
  3059. // add the relative Id unique to the newly allocated SID
  3060. //
  3061. (*(RtlSubAuthorityCountSid( Sid ))) ++;
  3062. *RtlSubAuthoritySid( Sid, DomainIdSubAuthorityCount ) = RelativeId;
  3063. return Sid;
  3064. }
  3065. //+-------------------------------------------------------------------------
  3066. //
  3067. // Function: KerbFreeCertificateList
  3068. //
  3069. // Synopsis: Frees a list of certificates created by KerbCreateCertificateList
  3070. //
  3071. // Effects:
  3072. //
  3073. // Arguments:
  3074. //
  3075. // Requires:
  3076. //
  3077. // Returns:
  3078. //
  3079. // Notes:
  3080. //
  3081. //
  3082. //--------------------------------------------------------------------------
  3083. VOID
  3084. KerbFreeCertificateList(
  3085. IN PKERB_CERTIFICATE_LIST Certificates
  3086. )
  3087. {
  3088. PKERB_CERTIFICATE_LIST Last,Next;
  3089. Last = NULL;
  3090. Next = Certificates;
  3091. while (Next != NULL)
  3092. {
  3093. Last = Next;
  3094. Next = Next->next;
  3095. if (Last->value.cert_data.value != NULL)
  3096. {
  3097. MIDL_user_free(Last->value.cert_data.value);
  3098. }
  3099. MIDL_user_free(Last);
  3100. }
  3101. }
  3102. //+-------------------------------------------------------------------------
  3103. //
  3104. // Function: KerbCreateCertificateList
  3105. //
  3106. // Synopsis: Creates a list of certificates from a cert context
  3107. //
  3108. // Effects:
  3109. //
  3110. // Arguments: Certficates - receives list of certificates.
  3111. // CertContext - Context containing certificates
  3112. //
  3113. // Requires:
  3114. //
  3115. // Returns:
  3116. //
  3117. // Notes:
  3118. //
  3119. //
  3120. //--------------------------------------------------------------------------
  3121. KERBERR
  3122. KerbCreateCertificateList(
  3123. OUT PKERB_CERTIFICATE_LIST * Certificates,
  3124. IN PCCERT_CONTEXT CertContext
  3125. )
  3126. {
  3127. KERBERR KerbErr = KDC_ERR_NONE;
  3128. PKERB_CERTIFICATE_LIST ListEntry = NULL;
  3129. if (!ARGUMENT_PRESENT(CertContext))
  3130. {
  3131. KerbErr = KRB_ERR_GENERIC;
  3132. goto Cleanup;
  3133. }
  3134. //
  3135. // Croft up a bogus certificate entry
  3136. //
  3137. ListEntry = (PKERB_CERTIFICATE_LIST) MIDL_user_allocate(sizeof(KERB_CERTIFICATE_LIST));
  3138. if (ListEntry == NULL)
  3139. {
  3140. KerbErr = KRB_ERR_GENERIC;
  3141. goto Cleanup;
  3142. }
  3143. ListEntry->next = NULL;
  3144. ListEntry->value.cert_type = KERB_CERTIFICATE_TYPE_X509;
  3145. ListEntry->value.cert_data.length = CertContext->cbCertEncoded;
  3146. ListEntry->value.cert_data.value = (PUCHAR) MIDL_user_allocate(ListEntry->value.cert_data.length);
  3147. if (ListEntry->value.cert_data.value == NULL)
  3148. {
  3149. KerbErr = KRB_ERR_GENERIC;
  3150. goto Cleanup;
  3151. }
  3152. RtlCopyMemory(
  3153. ListEntry->value.cert_data.value,
  3154. CertContext->pbCertEncoded,
  3155. CertContext->cbCertEncoded
  3156. );
  3157. *Certificates = ListEntry;
  3158. ListEntry = NULL;
  3159. Cleanup:
  3160. KerbFreeCertificateList(ListEntry);
  3161. return(KerbErr);
  3162. }
  3163. //+-------------------------------------------------------------------------
  3164. //
  3165. // Function: KerbConvertFlagsToUlong
  3166. //
  3167. // Synopsis: Converts a bit-stream flags field into a ULONG
  3168. //
  3169. // Effects:
  3170. //
  3171. // Arguments:
  3172. //
  3173. // Requires:
  3174. //
  3175. // Returns:
  3176. //
  3177. // Notes:
  3178. //
  3179. //
  3180. //--------------------------------------------------------------------------
  3181. ULONG
  3182. KerbConvertFlagsToUlong(
  3183. IN PVOID Flags
  3184. )
  3185. {
  3186. ULONG Output = 0;
  3187. PUCHAR OutputPointer = &((PUCHAR) &Output)[3];
  3188. ULONG Index = 0;
  3189. PKERB_TICKET_FLAGS InternalFlags = (PKERB_TICKET_FLAGS) Flags;
  3190. ULONG InternalLength;
  3191. if (InternalFlags->length > 32)
  3192. {
  3193. InternalLength = 32;
  3194. }
  3195. else
  3196. {
  3197. InternalLength = (ULONG) InternalFlags->length;
  3198. }
  3199. while (InternalLength > 7)
  3200. {
  3201. *OutputPointer = InternalFlags->value[Index++];
  3202. OutputPointer--;
  3203. InternalLength -= 8;
  3204. }
  3205. //
  3206. // Copy the remaining bits, masking off what should be zero
  3207. //
  3208. if (InternalLength != 0)
  3209. {
  3210. *OutputPointer = (UCHAR) (InternalFlags->value[Index] & ~((1 << (8-InternalLength)) - 1));
  3211. }
  3212. return(Output);
  3213. }
  3214. //+-------------------------------------------------------------------------
  3215. //
  3216. // Function: KerbConvertUlongToFlagUlong
  3217. //
  3218. // Synopsis: Converts the byte order of a ULONG into that used by flags
  3219. //
  3220. // Effects:
  3221. //
  3222. // Arguments:
  3223. //
  3224. // Requires:
  3225. //
  3226. // Returns:
  3227. //
  3228. // Notes:
  3229. //
  3230. //
  3231. //--------------------------------------------------------------------------
  3232. ULONG
  3233. KerbConvertUlongToFlagUlong(
  3234. IN ULONG Flag
  3235. )
  3236. {
  3237. ULONG ReturnFlag;
  3238. ((PUCHAR) &ReturnFlag)[0] = ((PUCHAR) &Flag)[3];
  3239. ((PUCHAR) &ReturnFlag)[1] = ((PUCHAR) &Flag)[2];
  3240. ((PUCHAR) &ReturnFlag)[2] = ((PUCHAR) &Flag)[1];
  3241. ((PUCHAR) &ReturnFlag)[3] = ((PUCHAR) &Flag)[0];
  3242. return(ReturnFlag);
  3243. }
  3244. //+-------------------------------------------------------------------------
  3245. //
  3246. // Function: KerbCompareObjectIds
  3247. //
  3248. // Synopsis: Compares two object IDs for equality
  3249. //
  3250. // Effects:
  3251. //
  3252. // Arguments:
  3253. //
  3254. // Requires:
  3255. //
  3256. // Returns:
  3257. //
  3258. // Notes:
  3259. //
  3260. //
  3261. //--------------------------------------------------------------------------
  3262. BOOLEAN
  3263. KerbCompareObjectIds(
  3264. IN PKERB_OBJECT_ID Object1,
  3265. IN PKERB_OBJECT_ID Object2
  3266. )
  3267. {
  3268. while (Object1 != NULL)
  3269. {
  3270. if (Object2 == NULL)
  3271. {
  3272. return(FALSE);
  3273. }
  3274. if (Object1->value != Object2->value)
  3275. {
  3276. return(FALSE);
  3277. }
  3278. Object1 = Object1->next;
  3279. Object2 = Object2->next;
  3280. }
  3281. if (Object2 != NULL)
  3282. {
  3283. return(FALSE);
  3284. }
  3285. else
  3286. {
  3287. return(TRUE);
  3288. }
  3289. }
  3290. //+-------------------------------------------------------------------------
  3291. //
  3292. // Function: KdcGetClientNetbiosAddress
  3293. //
  3294. // Synopsis: Gets the client's netbios address from the list of
  3295. // addresses it sends.
  3296. //
  3297. // Effects:
  3298. //
  3299. // Arguments:
  3300. //
  3301. // Requires:
  3302. //
  3303. // Returns:
  3304. //
  3305. // Notes:
  3306. //
  3307. //
  3308. //--------------------------------------------------------------------------
  3309. KERBERR
  3310. KerbGetClientNetbiosAddress(
  3311. OUT PUNICODE_STRING ClientNetbiosAddress,
  3312. IN PKERB_HOST_ADDRESSES Addresses
  3313. )
  3314. {
  3315. PKERB_HOST_ADDRESSES TempAddress = Addresses;
  3316. STRING TempString;
  3317. KERBERR KerbErr;
  3318. RtlInitUnicodeString(
  3319. ClientNetbiosAddress,
  3320. NULL
  3321. );
  3322. while (TempAddress != NULL)
  3323. {
  3324. //
  3325. // Check for netbios
  3326. //
  3327. if (TempAddress->value.address_type == KERB_ADDRTYPE_NETBIOS)
  3328. {
  3329. //
  3330. // Copy out the string
  3331. //
  3332. TempString.Buffer = (PCHAR) TempAddress->value.address.value;
  3333. TempString.Length = TempString.MaximumLength = (USHORT) TempAddress->value.address.length;
  3334. KerbErr = KerbStringToUnicodeString(
  3335. ClientNetbiosAddress,
  3336. &TempString
  3337. );
  3338. if (KERB_SUCCESS(KerbErr))
  3339. {
  3340. //
  3341. // Strip trailing spaces
  3342. //
  3343. if (ClientNetbiosAddress->Length >= sizeof(WCHAR))
  3344. {
  3345. while ((ClientNetbiosAddress->Length > 0) &&
  3346. (ClientNetbiosAddress->Buffer[(ClientNetbiosAddress->Length / sizeof(WCHAR))-1] == L' '))
  3347. {
  3348. ClientNetbiosAddress->Length -= sizeof(WCHAR);
  3349. }
  3350. return(KDC_ERR_NONE);
  3351. }
  3352. }
  3353. else
  3354. {
  3355. return(KerbErr);
  3356. }
  3357. }
  3358. TempAddress = TempAddress->next;
  3359. }
  3360. //
  3361. // It is o.k. to not have a netbios name
  3362. //
  3363. return(KDC_ERR_NONE);
  3364. }
  3365. //+-------------------------------------------------------------------------
  3366. //
  3367. // Function: KerbGetPacFromAuthData
  3368. //
  3369. // Synopsis: Gets the PAC from the auth data list
  3370. //
  3371. // Effects:
  3372. //
  3373. // Arguments:
  3374. //
  3375. // Requires:
  3376. //
  3377. // Returns:
  3378. //
  3379. // Notes:
  3380. //
  3381. //
  3382. //--------------------------------------------------------------------------
  3383. KERBERR
  3384. KerbGetPacFromAuthData(
  3385. IN PKERB_AUTHORIZATION_DATA AuthData,
  3386. OUT PKERB_IF_RELEVANT_AUTH_DATA ** ReturnIfRelevantData,
  3387. OUT PKERB_AUTHORIZATION_DATA * Pac
  3388. )
  3389. {
  3390. KERBERR KerbErr = KDC_ERR_NONE;
  3391. PKERB_AUTHORIZATION_DATA PacAuthData = NULL;
  3392. PKERB_AUTHORIZATION_DATA RelevantAuthData = NULL;
  3393. PKERB_IF_RELEVANT_AUTH_DATA * IfRelevantData = NULL;
  3394. *ReturnIfRelevantData = NULL;
  3395. *Pac = NULL;
  3396. //
  3397. // Look for the if-relevant data
  3398. //
  3399. RelevantAuthData = KerbFindAuthDataEntry(
  3400. KERB_AUTH_DATA_IF_RELEVANT,
  3401. AuthData
  3402. );
  3403. if (RelevantAuthData != NULL)
  3404. {
  3405. //
  3406. // Unpack it
  3407. //
  3408. KerbErr = KerbUnpackData(
  3409. RelevantAuthData->value.auth_data.value,
  3410. RelevantAuthData->value.auth_data.length,
  3411. PKERB_IF_RELEVANT_AUTH_DATA_PDU,
  3412. (PVOID *) &IfRelevantData
  3413. );
  3414. if (KERB_SUCCESS(KerbErr))
  3415. {
  3416. //
  3417. // Look for the PAC in the if-relevant data
  3418. //
  3419. PacAuthData = KerbFindAuthDataEntry(
  3420. KERB_AUTH_DATA_PAC,
  3421. *IfRelevantData
  3422. );
  3423. }
  3424. else
  3425. {
  3426. //
  3427. // We don't mind if we couldn't unpack it.
  3428. // Tickets do not always have PAC information.
  3429. //
  3430. KerbErr = KDC_ERR_NONE;
  3431. }
  3432. }
  3433. //
  3434. // If we didn't find it in the if-relevant data, look outside
  3435. //
  3436. if (PacAuthData == NULL)
  3437. {
  3438. PacAuthData = KerbFindAuthDataEntry(
  3439. KERB_AUTH_DATA_PAC,
  3440. AuthData
  3441. );
  3442. }
  3443. //
  3444. // Copy the PAC to return it
  3445. //
  3446. if (PacAuthData != NULL)
  3447. {
  3448. *Pac = PacAuthData;
  3449. }
  3450. *ReturnIfRelevantData = IfRelevantData;
  3451. IfRelevantData = NULL;
  3452. return(KerbErr);
  3453. }
  3454. #if DBG
  3455. #define KERB_DEBUG_WARN_LEVEL 0x0002
  3456. //+-------------------------------------------------------------------------
  3457. //
  3458. // Function: DebugDisplayTime
  3459. //
  3460. // Synopsis: Displays a FILETIME
  3461. //
  3462. // Effects:
  3463. //
  3464. // Arguments:
  3465. //
  3466. // Requires:
  3467. //
  3468. // Returns:
  3469. //
  3470. // Notes:
  3471. //
  3472. //
  3473. //--------------------------------------------------------------------------
  3474. void
  3475. DebugDisplayTime(
  3476. IN ULONG DebugLevel,
  3477. IN FILETIME *pFileTime
  3478. )
  3479. {
  3480. SYSTEMTIME SystemTime;
  3481. if (DebugLevel & KERB_DEBUG_WARN_LEVEL)
  3482. {
  3483. FileTimeToSystemTime(pFileTime, &SystemTime);
  3484. DebugLog((DEB_ERROR," %02d:%02d:%02d - %02d %02d %04d\n",
  3485. SystemTime.wHour,SystemTime.wMinute,SystemTime.wSecond,
  3486. SystemTime.wDay,SystemTime.wMonth,SystemTime.wYear));
  3487. }
  3488. return;
  3489. }
  3490. #endif
  3491. //+-------------------------------------------------------------------------
  3492. //
  3493. // Function: VerifyClientAddress
  3494. //
  3495. // Synopsis: Verifies that the client address is present in the address list
  3496. //
  3497. // Effects:
  3498. //
  3499. // Arguments:
  3500. //
  3501. // Requires:
  3502. //
  3503. // Returns: TRUE if the address checks out OK, FALSE otherwise
  3504. //
  3505. // Notes:
  3506. //
  3507. //
  3508. //--------------------------------------------------------------------------
  3509. BOOLEAN
  3510. KerbVerifyClientAddress(
  3511. IN SOCKADDR * ClientAddress,
  3512. IN PKERB_HOST_ADDRESSES Addresses
  3513. )
  3514. {
  3515. PKERB_HOST_ADDRESSES TempAddress = Addresses;
  3516. BOOLEAN IpAddressesPresent = FALSE;
  3517. //
  3518. // ISSUE-2001/03/05-markpu
  3519. // This routine is inadequate in that it only deals with IPv4
  3520. // addresses. Address matching has to be more elaborate than that.
  3521. //
  3522. while (TempAddress != NULL)
  3523. {
  3524. if ( TempAddress->value.address_type == KERB_ADDRTYPE_INET &&
  3525. ClientAddress->sa_family == AF_INET )
  3526. {
  3527. struct sockaddr_in * InetAddress = (struct sockaddr_in *) ClientAddress;
  3528. IpAddressesPresent = TRUE;
  3529. //
  3530. // Check that the addresses match
  3531. //
  3532. if (TempAddress->value.address.length == sizeof(ULONG))
  3533. {
  3534. if (RtlEqualMemory(
  3535. TempAddress->value.address.value,
  3536. &InetAddress->sin_addr.S_un.S_addr,
  3537. sizeof(ULONG)))
  3538. {
  3539. return TRUE;
  3540. }
  3541. }
  3542. }
  3543. TempAddress = TempAddress->next;
  3544. }
  3545. D_DebugLog((DEB_WARN,"Client address not in address list\n"));
  3546. //
  3547. // If there were no IP addresses in the ticket, return TRUE, since we
  3548. // probably are in a situation where only netbios addresses are in the
  3549. // ticket, so the socket address matched none of them
  3550. //
  3551. return !IpAddressesPresent;
  3552. }
  3553. //+-------------------------------------------------------------------------
  3554. //
  3555. // Function: KerbCopyDomainRelativeSid
  3556. //
  3557. // Synopsis: Given a domain Id and a relative ID create the corresponding
  3558. // SID at the location indicated by TargetSid
  3559. //
  3560. // Effects:
  3561. //
  3562. // Arguments: TargetSid - target memory location
  3563. // DomainId - The template SID to use.
  3564. //
  3565. // RelativeId - The relative Id to append to the DomainId.
  3566. //
  3567. // Requires:
  3568. //
  3569. // Returns: Size - Size of the sid copied
  3570. //
  3571. // Notes:
  3572. //
  3573. //
  3574. //--------------------------------------------------------------------------
  3575. DWORD
  3576. KerbCopyDomainRelativeSid(
  3577. OUT PSID TargetSid,
  3578. IN PSID DomainId,
  3579. IN ULONG RelativeId
  3580. )
  3581. {
  3582. UCHAR DomainIdSubAuthorityCount;
  3583. ULONG Size;
  3584. //
  3585. // Allocate a Sid which has one more sub-authority than the domain ID.
  3586. //
  3587. DomainIdSubAuthorityCount = *(RtlSubAuthorityCountSid( DomainId ));
  3588. Size = RtlLengthRequiredSid(DomainIdSubAuthorityCount+1);
  3589. //
  3590. // Initialize the new SID to have the same inital value as the
  3591. // domain ID.
  3592. //
  3593. if ( !NT_SUCCESS( RtlCopySid( Size, TargetSid, DomainId ) ) ) {
  3594. return 0;
  3595. }
  3596. //
  3597. // Adjust the sub-authority count and
  3598. // add the relative Id unique to the newly allocated SID
  3599. //
  3600. (*(RtlSubAuthorityCountSid( TargetSid ))) ++;
  3601. *RtlSubAuthoritySid( TargetSid, DomainIdSubAuthorityCount ) = RelativeId;
  3602. return Size;
  3603. }
  3604. //+-------------------------------------------------------------------------
  3605. //
  3606. // Function: KerbHashS4UPreauth
  3607. //
  3608. // Synopsis: Given a domain Id and a relative ID create the corresponding
  3609. // SID at the location indicated by TargetSid
  3610. //
  3611. // Effects:
  3612. //
  3613. // Arguments: TargetSid - target memory location
  3614. // DomainId - The template SID to use.
  3615. //
  3616. // RelativeId - The relative Id to append to the DomainId.
  3617. //
  3618. // Requires:
  3619. //
  3620. // Returns: Size - Size of the sid copied
  3621. //
  3622. // Notes:
  3623. //
  3624. //
  3625. //--------------------------------------------------------------------------
  3626. NTSTATUS
  3627. KerbHashS4UPreauth(
  3628. IN PKERB_PA_FOR_USER S4UPreauth,
  3629. IN PKERB_ENCRYPTION_KEY Key,
  3630. IN LONG ChecksumType,
  3631. IN OUT PKERB_CHECKSUM CheckSum
  3632. )
  3633. {
  3634. NTSTATUS Status;
  3635. PCHECKSUM_FUNCTION MD5Check = NULL;
  3636. PCHECKSUM_BUFFER MD5ScratchBuffer = NULL;
  3637. PKERB_PRINCIPAL_NAME_name_string TmpName = S4UPreauth->userName.name_string;
  3638. //
  3639. // Locate the MD5 Hash Function
  3640. //
  3641. Status = CDLocateCheckSum(ChecksumType, &MD5Check);
  3642. if( !NT_SUCCESS(Status) )
  3643. {
  3644. D_DebugLog( (DEB_ERROR,
  3645. "Failure Locating MD5: 0x%x.\n",
  3646. Status));
  3647. goto Cleanup;
  3648. }
  3649. //
  3650. // Initialize the HMAC using the TGT session key
  3651. //
  3652. if (NULL != MD5Check->InitializeEx2)
  3653. {
  3654. Status = MD5Check->InitializeEx2(
  3655. Key->keyvalue.value,
  3656. Key->keyvalue.length,
  3657. NULL,
  3658. KERB_NON_KERB_CKSUM_SALT,
  3659. &MD5ScratchBuffer
  3660. );
  3661. }
  3662. else
  3663. {
  3664. Status = MD5Check->InitializeEx(
  3665. Key->keyvalue.value,
  3666. Key->keyvalue.length,
  3667. KERB_NON_KERB_CKSUM_SALT,
  3668. &MD5ScratchBuffer
  3669. );
  3670. }
  3671. if( !NT_SUCCESS(Status) )
  3672. {
  3673. D_DebugLog((DEB_ERROR,"Failure initializing MD5HMAC: 0x%x.\n",Status));
  3674. goto Cleanup;
  3675. }
  3676. //
  3677. // Build the MD5 hash
  3678. //
  3679. //
  3680. // Pull in client realm name.
  3681. //
  3682. Status = MD5Check->Sum(
  3683. MD5ScratchBuffer,
  3684. sizeof(DWORD),
  3685. (PUCHAR) &S4UPreauth->userName.name_type
  3686. );
  3687. if( !NT_SUCCESS(Status) )
  3688. {
  3689. D_DebugLog((DEB_ERROR,"Failure building MD5: 0x%x.\n",Status));
  3690. goto Cleanup;
  3691. }
  3692. if (TmpName->value == NULL)
  3693. {
  3694. DsysAssert(FALSE);
  3695. goto Cleanup;
  3696. }
  3697. do
  3698. {
  3699. Status = MD5Check->Sum(
  3700. MD5ScratchBuffer,
  3701. lstrlenA( TmpName->value ),
  3702. (PUCHAR) TmpName->value
  3703. );
  3704. if( !NT_SUCCESS(Status) )
  3705. {
  3706. D_DebugLog((DEB_ERROR,"Failure building MD5: 0x%x.\n",Status));
  3707. goto Cleanup;
  3708. }
  3709. TmpName = TmpName->next;
  3710. } while ( TmpName != NULL );
  3711. //
  3712. // Then the client realm
  3713. //
  3714. Status = MD5Check->Sum(
  3715. MD5ScratchBuffer,
  3716. lstrlenA( S4UPreauth->userRealm ),
  3717. (PUCHAR) S4UPreauth->userRealm
  3718. );
  3719. if( !NT_SUCCESS(Status) )
  3720. {
  3721. D_DebugLog((DEB_ERROR,"Failure building MD5: 0x%x.\n",Status));
  3722. goto Cleanup;
  3723. }
  3724. //
  3725. // Authentication package.
  3726. //
  3727. Status = MD5Check->Sum(
  3728. MD5ScratchBuffer,
  3729. lstrlenA( S4UPreauth->authentication_package ),
  3730. (PUCHAR) S4UPreauth->authentication_package
  3731. );
  3732. if( !NT_SUCCESS(Status) )
  3733. {
  3734. D_DebugLog( (DEB_ERROR,"Failure building MD5: 0x%x.\n",Status));
  3735. goto Cleanup;
  3736. }
  3737. if ( S4UPreauth->bit_mask & KERB_PA_FOR_USER_authorization_data_present )
  3738. {
  3739. //
  3740. // Hash authorization data.
  3741. //
  3742. Status = MD5Check->Sum(
  3743. MD5ScratchBuffer,
  3744. S4UPreauth->authorization_data.length,
  3745. (PUCHAR) S4UPreauth->authorization_data.value
  3746. );
  3747. if( !NT_SUCCESS(Status) )
  3748. {
  3749. D_DebugLog( (DEB_ERROR,"Failure building MD5: 0x%x.\n",Status));
  3750. goto Cleanup;
  3751. }
  3752. }
  3753. //
  3754. // Copy the hash results into the checksum field
  3755. //
  3756. CheckSum->checksum_type = ChecksumType;
  3757. CheckSum->checksum.length = MD5Check->CheckSumSize;
  3758. Status = MD5Check->Finalize(
  3759. MD5ScratchBuffer,
  3760. CheckSum->checksum.value
  3761. );
  3762. if ( !NT_SUCCESS(Status) )
  3763. {
  3764. D_DebugLog( (DEB_ERROR,"Failure FINALIZING MD5: 0x%x.\n",Status));
  3765. goto Cleanup;
  3766. }
  3767. Cleanup:
  3768. if ( MD5Check != NULL )
  3769. {
  3770. MD5Check->Finish( &MD5ScratchBuffer );
  3771. }
  3772. return Status;
  3773. }