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

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