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.

1244 lines
38 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1996
  6. //
  7. // File: kerbwow.cxx
  8. //
  9. // Contents: Code for 32-64 bit interop for the Kerberos package
  10. //
  11. //
  12. // History: 25-Oct-2000 JSchwart Created
  13. //
  14. //------------------------------------------------------------------------
  15. #include <kerb.hxx>
  16. #include <kerbp.h>
  17. #ifdef _WIN64
  18. #ifdef DEBUG_SUPPORT
  19. static TCHAR THIS_FILE[]=TEXT(__FILE__);
  20. #endif
  21. #define FILENO FILENO_KERBWOW
  22. //
  23. // WOW versions of public Kerberos logon buffer structures. These MUST
  24. // be kept in sync with their public counterparts!
  25. //
  26. typedef struct _KERB_INTERACTIVE_LOGON_WOW64
  27. {
  28. KERB_LOGON_SUBMIT_TYPE MessageType;
  29. UNICODE_STRING_WOW64 LogonDomainName;
  30. UNICODE_STRING_WOW64 UserName;
  31. UNICODE_STRING_WOW64 Password;
  32. }
  33. KERB_INTERACTIVE_LOGON_WOW64, *PKERB_INTERACTIVE_LOGON_WOW64;
  34. typedef struct _KERB_INTERACTIVE_UNLOCK_LOGON_WOW64
  35. {
  36. KERB_INTERACTIVE_LOGON_WOW64 Logon;
  37. LUID LogonId;
  38. }
  39. KERB_INTERACTIVE_UNLOCK_LOGON_WOW64, *PKERB_INTERACTIVE_UNLOCK_LOGON_WOW64;
  40. typedef struct _KERB_SMART_CARD_LOGON_WOW64
  41. {
  42. KERB_LOGON_SUBMIT_TYPE MessageType;
  43. UNICODE_STRING_WOW64 Pin;
  44. ULONG CspDataLength;
  45. ULONG CspData;
  46. }
  47. KERB_SMART_CARD_LOGON_WOW64, *PKERB_SMART_CARD_LOGON_WOW64;
  48. typedef struct _KERB_SMART_CARD_UNLOCK_LOGON_WOW64
  49. {
  50. KERB_SMART_CARD_LOGON_WOW64 Logon;
  51. LUID LogonId;
  52. }
  53. KERB_SMART_CARD_UNLOCK_LOGON_WOW64, *PKERB_SMART_CARD_UNLOCK_LOGON_WOW64;
  54. typedef struct _KERB_TICKET_LOGON_WOW64
  55. {
  56. KERB_LOGON_SUBMIT_TYPE MessageType;
  57. ULONG Flags;
  58. ULONG ServiceTicketLength;
  59. ULONG TicketGrantingTicketLength;
  60. ULONG ServiceTicket;
  61. ULONG TicketGrantingTicket;
  62. }
  63. KERB_TICKET_LOGON_WOW64, *PKERB_TICKET_LOGON_WOW64;
  64. typedef struct _KERB_TICKET_UNLOCK_LOGON_WOW64
  65. {
  66. KERB_TICKET_LOGON_WOW64 Logon;
  67. LUID LogonId;
  68. }
  69. KERB_TICKET_UNLOCK_LOGON_WOW64, *PKERB_TICKET_UNLOCK_LOGON_WOW64;
  70. //
  71. // WOW versions of public Kerberos profile buffer structures. These MUST
  72. // be kept in sync with their public counterparts!
  73. //
  74. typedef struct _KERB_INTERACTIVE_PROFILE_WOW64
  75. {
  76. KERB_PROFILE_BUFFER_TYPE MessageType;
  77. USHORT LogonCount;
  78. USHORT BadPasswordCount;
  79. LARGE_INTEGER LogonTime;
  80. LARGE_INTEGER LogoffTime;
  81. LARGE_INTEGER KickOffTime;
  82. LARGE_INTEGER PasswordLastSet;
  83. LARGE_INTEGER PasswordCanChange;
  84. LARGE_INTEGER PasswordMustChange;
  85. UNICODE_STRING_WOW64 LogonScript;
  86. UNICODE_STRING_WOW64 HomeDirectory;
  87. UNICODE_STRING_WOW64 FullName;
  88. UNICODE_STRING_WOW64 ProfilePath;
  89. UNICODE_STRING_WOW64 HomeDirectoryDrive;
  90. UNICODE_STRING_WOW64 LogonServer;
  91. ULONG UserFlags;
  92. }
  93. KERB_INTERACTIVE_PROFILE_WOW64, *PKERB_INTERACTIVE_PROFILE_WOW64;
  94. typedef struct _KERB_SMART_CARD_PROFILE_WOW64
  95. {
  96. KERB_INTERACTIVE_PROFILE_WOW64 Profile;
  97. ULONG CertificateSize;
  98. ULONG CertificateData;
  99. }
  100. KERB_SMART_CARD_PROFILE_WOW64, *PKERB_SMART_CARD_PROFILE_WOW64;
  101. typedef struct KERB_CRYPTO_KEY_WOW64
  102. {
  103. LONG KeyType;
  104. ULONG Length;
  105. ULONG Value;
  106. }
  107. KERB_CRYPTO_KEY_WOW64, *PKERB_CRYPTO_KEY_WOW64;
  108. typedef struct _KERB_TICKET_PROFILE_WOW64
  109. {
  110. KERB_INTERACTIVE_PROFILE_WOW64 Profile;
  111. KERB_CRYPTO_KEY_WOW64 SessionKey;
  112. }
  113. KERB_TICKET_PROFILE_WOW64, *PKERB_TICKET_PROFILE_WOW64;
  114. typedef struct _KERB_INTERNAL_NAME_WOW64
  115. {
  116. SHORT NameType;
  117. USHORT NameCount;
  118. UNICODE_STRING_WOW64 Names[ANYSIZE_ARRAY];
  119. }
  120. KERB_INTERNAL_NAME_WOW64, *PKERB_INTERNAL_NAME_WOW64;
  121. typedef struct _KERB_EXTERNAL_NAME_WOW64
  122. {
  123. SHORT NameType;
  124. USHORT NameCount;
  125. UNICODE_STRING_WOW64 Names[ANYSIZE_ARRAY];
  126. }
  127. KERB_EXTERNAL_NAME_WOW64, *PKERB_EXTERNAL_NAME_WOW64;
  128. typedef struct _KERB_EXTERNAL_TICKET_WOW64
  129. {
  130. ULONG ServiceName;
  131. ULONG TargetName;
  132. ULONG ClientName;
  133. UNICODE_STRING_WOW64 DomainName;
  134. UNICODE_STRING_WOW64 TargetDomainName;
  135. UNICODE_STRING_WOW64 AltTargetDomainName;
  136. KERB_CRYPTO_KEY_WOW64 SessionKey;
  137. ULONG TicketFlags;
  138. ULONG Flags;
  139. LARGE_INTEGER KeyExpirationTime;
  140. LARGE_INTEGER StartTime;
  141. LARGE_INTEGER EndTime;
  142. LARGE_INTEGER RenewUntil;
  143. LARGE_INTEGER TimeSkew;
  144. ULONG EncodedTicketSize;
  145. ULONG EncodedTicket;
  146. }
  147. KERB_EXTERNAL_TICKET_WOW64, *PKERB_EXTERNAL_TICKET_WOW64;
  148. typedef struct _KERB_EXTERNAL_TICKET_EX_WOW64
  149. {
  150. PKERB_EXTERNAL_NAME_WOW64 ClientName;
  151. PKERB_EXTERNAL_NAME_WOW64 ServiceName;
  152. PKERB_EXTERNAL_NAME_WOW64 TargetName;
  153. UNICODE_STRING_WOW64 ClientRealm;
  154. UNICODE_STRING_WOW64 ServerRealm;
  155. UNICODE_STRING_WOW64 TargetDomainName;
  156. UNICODE_STRING_WOW64 AltTargetDomainName;
  157. KERB_CRYPTO_KEY_WOW64 SessionKey;
  158. ULONG TicketFlags;
  159. ULONG Flags;
  160. LARGE_INTEGER KeyExpirationTime;
  161. LARGE_INTEGER StartTime;
  162. LARGE_INTEGER EndTime;
  163. LARGE_INTEGER RenewUntil;
  164. LARGE_INTEGER TimeSkew;
  165. PKERB_NET_ADDRESSES TicketAddresses;
  166. PKERB_AUTH_DATA AuthorizationData;
  167. _KERB_EXTERNAL_TICKET_EX_WOW64 * SecondTicket;
  168. ULONG EncodedTicketSize;
  169. PUCHAR EncodedTicket;
  170. }
  171. KERB_EXTERNAL_TICKET_EX_WOW64, *PKERB_EXTERNAL_TICKET_EX_WOW64;
  172. #define RELOCATE_WOW_UNICODE_STRING(WOWString, NativeString, Offset) \
  173. NativeString.Length = WOWString.Length; \
  174. NativeString.MaximumLength = WOWString.MaximumLength; \
  175. NativeString.Buffer = (LPWSTR) ((LPBYTE) UlongToPtr(WOWString.Buffer) + Offset);
  176. //+-------------------------------------------------------------------------
  177. //
  178. // Function: KerbPutWOWString
  179. //
  180. // Synopsis: Copies a UNICODE_STRING into a buffer
  181. //
  182. // Effects:
  183. //
  184. // Arguments: InputString - String to 'put'
  185. // OutputString - Receives 'put' string
  186. // Offset - Difference in addresses of local and client buffers.
  187. // Where - Location in local buffer to place string.
  188. //
  189. // Requires:
  190. //
  191. // Returns:
  192. //
  193. // Notes: This code is (effectively) duplicated in
  194. // KerbPutString. Make sure any changes
  195. // made here are applied there as well.
  196. //
  197. //--------------------------------------------------------------------------
  198. VOID
  199. KerbPutWOWString(
  200. IN PUNICODE_STRING InputString,
  201. OUT PUNICODE_STRING_WOW64 OutputString,
  202. IN LONG_PTR Offset,
  203. IN OUT PBYTE * Where
  204. )
  205. {
  206. OutputString->Length = OutputString->MaximumLength = InputString->Length;
  207. OutputString->Buffer = PtrToUlong (*Where + Offset);
  208. RtlCopyMemory(
  209. *Where,
  210. InputString->Buffer,
  211. InputString->Length
  212. );
  213. *Where += InputString->Length;
  214. }
  215. //+-------------------------------------------------------------------------
  216. //
  217. // Function: KerbPutWOWKdcName
  218. //
  219. // Synopsis: Copies a Kdc name to a buffer
  220. //
  221. // Effects:
  222. //
  223. // Arguments:
  224. //
  225. // Requires:
  226. //
  227. // Returns:
  228. //
  229. // Notes: This code is (effectively) duplicated in
  230. // KerbPutKdcName. Make sure any changes
  231. // made here are applied there as well.
  232. //
  233. //--------------------------------------------------------------------------
  234. VOID
  235. KerbPutWOWKdcName(
  236. IN PKERB_INTERNAL_NAME InputName,
  237. OUT PULONG OutputName,
  238. IN LONG_PTR Offset,
  239. IN OUT PBYTE * Where
  240. )
  241. {
  242. ULONG Index;
  243. PKERB_INTERNAL_NAME_WOW64 LocalName = (PKERB_INTERNAL_NAME_WOW64) *Where;
  244. if (!ARGUMENT_PRESENT(InputName))
  245. {
  246. *OutputName = NULL;
  247. return;
  248. }
  249. *Where += sizeof(KERB_INTERNAL_NAME_WOW64) - sizeof(UNICODE_STRING_WOW64) +
  250. InputName->NameCount * sizeof(UNICODE_STRING_WOW64);
  251. LocalName->NameType = InputName->NameType;
  252. LocalName->NameCount = InputName->NameCount;
  253. for (Index = 0; Index < InputName->NameCount ; Index++ )
  254. {
  255. LocalName->Names[Index].Length =
  256. LocalName->Names[Index].MaximumLength =
  257. InputName->Names[Index].Length;
  258. LocalName->Names[Index].Buffer = PtrToUlong(*Where + Offset);
  259. RtlCopyMemory(*Where,
  260. InputName->Names[Index].Buffer,
  261. InputName->Names[Index].Length);
  262. *Where += InputName->Names[Index].Length;
  263. }
  264. *Where = (PBYTE) ROUND_UP_POINTER(*Where, sizeof(ULONG));
  265. *OutputName = PtrToUlong((PBYTE) LocalName + Offset);
  266. }
  267. //+-------------------------------------------------------------------------
  268. //
  269. // Function: KerbPutKdcNameAsWOWString
  270. //
  271. // Synopsis: Copies a KERB_INTERNAL_NAME into a buffer
  272. //
  273. // Effects:
  274. //
  275. // Arguments: InputString - String to 'put'
  276. // OutputString - Receives 'put' string
  277. // Offset - Difference in addresses of local and client buffers.
  278. // Where - Location in local buffer to place string.
  279. //
  280. // Requires:
  281. //
  282. // Returns:
  283. //
  284. // Notes: This code is (effectively) duplicated in
  285. // KerbPutKdcNameAsString. Make sure any
  286. // changes made here are applied there as well.
  287. //
  288. //--------------------------------------------------------------------------
  289. VOID
  290. KerbPutKdcNameAsWOWString(
  291. IN PKERB_INTERNAL_NAME InputName,
  292. OUT PUNICODE_STRING_WOW64 OutputName,
  293. IN LONG_PTR Offset,
  294. IN OUT PBYTE * Where
  295. )
  296. {
  297. USHORT Index;
  298. OutputName->Buffer = PtrToUlong (*Where + Offset);
  299. OutputName->Length = 0;
  300. OutputName->MaximumLength = 0;
  301. for (Index = 0; Index < InputName->NameCount ; Index++ )
  302. {
  303. RtlCopyMemory(
  304. *Where,
  305. InputName->Names[Index].Buffer,
  306. InputName->Names[Index].Length
  307. );
  308. *Where += InputName->Names[Index].Length;
  309. OutputName->Length += InputName->Names[Index].Length;
  310. if (Index == (InputName->NameCount - 1))
  311. {
  312. *((LPWSTR) *Where) = L'\0';
  313. OutputName->MaximumLength = OutputName->Length + sizeof(WCHAR);
  314. }
  315. else
  316. {
  317. *((LPWSTR) *Where) = L'/';
  318. OutputName->Length += sizeof(WCHAR);
  319. }
  320. *Where += sizeof(WCHAR);
  321. }
  322. }
  323. //+-------------------------------------------------------------------------
  324. //
  325. // Function: KerbPutWOWClientString
  326. //
  327. // Synopsis: Copies a string into a buffer that will be copied to the
  328. // 32-bit client's address space
  329. //
  330. // Effects:
  331. //
  332. // Arguments: Where - Location in local buffer to place string.
  333. // Delta - Difference in addresses of local and client buffers.
  334. // OutString - Receives 'put' string
  335. // InString - String to 'put'
  336. //
  337. // Requires:
  338. //
  339. // Returns:
  340. //
  341. // Notes: This code is (effectively) duplicated in
  342. // KerbPutClientString. Make sure any changes
  343. // made here are applied there as well.
  344. //
  345. //--------------------------------------------------------------------------
  346. VOID
  347. KerbPutWOWClientString(
  348. IN OUT PUCHAR * Where,
  349. IN LONG_PTR Delta,
  350. IN PUNICODE_STRING_WOW64 OutString,
  351. IN PUNICODE_STRING InString
  352. )
  353. {
  354. if (InString->Length == 0)
  355. {
  356. OutString->Buffer = 0;
  357. OutString->Length = OutString->MaximumLength = 0;
  358. }
  359. else
  360. {
  361. RtlCopyMemory(*Where,
  362. InString->Buffer,
  363. InString->Length);
  364. OutString->Buffer = PtrToUlong(*Where + Delta);
  365. OutString->Length = InString->Length;
  366. *Where += InString->Length;
  367. *(LPWSTR) (*Where) = L'\0';
  368. *Where += sizeof(WCHAR);
  369. OutString->MaximumLength = OutString->Length + sizeof(WCHAR);
  370. }
  371. }
  372. //+-------------------------------------------------------------------------
  373. //
  374. // Function: KerbWOWNameLength
  375. //
  376. // Synopsis: returns length in bytes of variable portion
  377. // of KERB_INTERNAL_NAME
  378. //
  379. // Effects:
  380. //
  381. // Arguments:
  382. //
  383. // Requires:
  384. //
  385. // Returns:
  386. //
  387. // Notes: This code is (effectively) duplicated in
  388. // KerbNameLength. Make sure any changes
  389. // made here are applied there as well.
  390. //
  391. //--------------------------------------------------------------------------
  392. ULONG
  393. KerbWOWNameLength(
  394. IN PKERB_INTERNAL_NAME Name
  395. )
  396. {
  397. ULONG Length = 0;
  398. ULONG Index;
  399. if (!ARGUMENT_PRESENT(Name))
  400. {
  401. return 0;
  402. }
  403. Length = sizeof(KERB_INTERNAL_NAME_WOW64)
  404. - sizeof(UNICODE_STRING_WOW64)
  405. + Name->NameCount * sizeof(UNICODE_STRING_WOW64);
  406. for (Index = 0; Index < Name->NameCount ;Index++ )
  407. {
  408. Length += Name->Names[Index].Length;
  409. }
  410. Length = ROUND_UP_COUNT(Length, sizeof(ULONG));
  411. return Length;
  412. }
  413. //+-------------------------------------------------------------------------
  414. //
  415. // Function: KerbConvertWOWLogonBuffer
  416. //
  417. // Synopsis: Converts logon buffers passed in from WOW clients to 64-bit
  418. //
  419. // Effects:
  420. //
  421. // Arguments: ProtocolSubmitBuffer -- original 32-bit logon buffer
  422. // pSubmitBufferSize -- size of the 32-bit logon buffer
  423. // MessageType -- format of the logon buffer
  424. // ppTempSubmitBuffer -- filled in with the converted buffer
  425. //
  426. // Requires:
  427. //
  428. // Returns:
  429. //
  430. // Notes: This routine allocates the converted buffer and returns it
  431. // on success. It is the caller's responsibility to free it.
  432. //
  433. //
  434. //--------------------------------------------------------------------------
  435. NTSTATUS
  436. KerbConvertWOWLogonBuffer(
  437. IN PVOID ProtocolSubmitBuffer,
  438. IN PVOID ClientBufferBase,
  439. IN OUT PULONG pSubmitBufferSize,
  440. IN KERB_LOGON_SUBMIT_TYPE MessageType,
  441. OUT PVOID *ppTempSubmitBuffer
  442. )
  443. {
  444. NTSTATUS Status = STATUS_SUCCESS;
  445. PVOID pTempBuffer = NULL;
  446. ULONG dwBufferSize = *pSubmitBufferSize;
  447. switch (MessageType)
  448. {
  449. case KerbInteractiveLogon:
  450. case KerbWorkstationUnlockLogon:
  451. {
  452. PKERB_INTERACTIVE_LOGON Logon;
  453. PKERB_INTERACTIVE_LOGON_WOW64 LogonWOW;
  454. DWORD dwOffset;
  455. DWORD dwWOWOffset;
  456. //
  457. // Scale up the size and add on 3 PVOIDs for the worst-case
  458. // scenario to align the three embedded UNICODE_STRINGs
  459. //
  460. dwBufferSize += sizeof(KERB_INTERACTIVE_LOGON)
  461. - sizeof(KERB_INTERACTIVE_LOGON_WOW64);
  462. if (dwBufferSize < sizeof(KERB_INTERACTIVE_LOGON))
  463. {
  464. DebugLog((DEB_ERROR,
  465. "Submit buffer to logon too small: %d. %ws, line %d\n",
  466. dwBufferSize,
  467. THIS_FILE,
  468. __LINE__));
  469. Status = STATUS_INVALID_PARAMETER;
  470. goto Cleanup;
  471. }
  472. pTempBuffer = KerbAllocate(dwBufferSize);
  473. if (pTempBuffer == NULL)
  474. {
  475. Status = STATUS_INSUFFICIENT_RESOURCES;
  476. goto Cleanup;
  477. }
  478. Logon = (PKERB_INTERACTIVE_LOGON) pTempBuffer;
  479. LogonWOW = (PKERB_INTERACTIVE_LOGON_WOW64) ProtocolSubmitBuffer;
  480. Logon->MessageType = LogonWOW->MessageType;
  481. dwOffset = sizeof(KERB_INTERACTIVE_LOGON);
  482. dwWOWOffset = sizeof(KERB_INTERACTIVE_LOGON_WOW64);
  483. if (MessageType == KerbWorkstationUnlockLogon)
  484. {
  485. if (dwBufferSize < sizeof(KERB_INTERACTIVE_UNLOCK_LOGON))
  486. {
  487. DebugLog((DEB_ERROR,
  488. "Submit buffer to logon too small: %d. %ws, line %d\n",
  489. dwBufferSize,
  490. THIS_FILE,
  491. __LINE__));
  492. Status = STATUS_INVALID_PARAMETER;
  493. goto Cleanup;
  494. }
  495. //
  496. // One additional field for this type (a LUID)
  497. //
  498. PKERB_INTERACTIVE_UNLOCK_LOGON Unlock;
  499. PKERB_INTERACTIVE_UNLOCK_LOGON_WOW64 UnlockWOW;
  500. Unlock = (PKERB_INTERACTIVE_UNLOCK_LOGON) pTempBuffer;
  501. UnlockWOW = (PKERB_INTERACTIVE_UNLOCK_LOGON_WOW64) ProtocolSubmitBuffer;
  502. Unlock->LogonId = UnlockWOW->LogonId;
  503. dwOffset = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON);
  504. dwWOWOffset = sizeof(KERB_INTERACTIVE_UNLOCK_LOGON_WOW64);
  505. }
  506. //
  507. // Copy the variable-length data
  508. //
  509. RtlCopyMemory((LPBYTE) Logon + dwOffset,
  510. (LPBYTE) LogonWOW + dwWOWOffset,
  511. *pSubmitBufferSize - dwWOWOffset);
  512. //
  513. // Set up the pointers in the native struct
  514. //
  515. RELOCATE_WOW_UNICODE_STRING(LogonWOW->LogonDomainName,
  516. Logon->LogonDomainName,
  517. dwOffset - dwWOWOffset);
  518. RELOCATE_WOW_UNICODE_STRING(LogonWOW->UserName,
  519. Logon->UserName,
  520. dwOffset - dwWOWOffset);
  521. RELOCATE_WOW_UNICODE_STRING(LogonWOW->Password,
  522. Logon->Password,
  523. dwOffset - dwWOWOffset);
  524. break;
  525. }
  526. case KerbSmartCardLogon:
  527. case KerbSmartCardUnlockLogon:
  528. {
  529. PKERB_SMART_CARD_LOGON Logon;
  530. PKERB_SMART_CARD_LOGON_WOW64 LogonWOW;
  531. DWORD dwOffset;
  532. DWORD dwWOWOffset;
  533. //
  534. // Scale up the size and add on 2 PVOIDs for the worst-case
  535. // scenario to align the embedded UNICODE_STRING and CspData
  536. //
  537. dwBufferSize += sizeof(KERB_SMART_CARD_LOGON)
  538. - sizeof(KERB_SMART_CARD_LOGON_WOW64);
  539. if (dwBufferSize < sizeof(KERB_SMART_CARD_LOGON))
  540. {
  541. DebugLog((DEB_ERROR,
  542. "Submit buffer to logon too small: %d. %ws, line %d\n",
  543. dwBufferSize,
  544. THIS_FILE,
  545. __LINE__));
  546. Status = STATUS_INVALID_PARAMETER;
  547. goto Cleanup;
  548. }
  549. pTempBuffer = KerbAllocate(dwBufferSize);
  550. if (pTempBuffer == NULL)
  551. {
  552. Status = STATUS_INSUFFICIENT_RESOURCES;
  553. goto Cleanup;
  554. }
  555. Logon = (PKERB_SMART_CARD_LOGON) pTempBuffer;
  556. LogonWOW = (PKERB_SMART_CARD_LOGON_WOW64) ProtocolSubmitBuffer;
  557. Logon->MessageType = LogonWOW->MessageType;
  558. Logon->CspDataLength = LogonWOW->CspDataLength;
  559. dwOffset = sizeof(KERB_SMART_CARD_LOGON);
  560. dwWOWOffset = sizeof(KERB_SMART_CARD_LOGON_WOW64);
  561. if (MessageType == KerbSmartCardUnlockLogon)
  562. {
  563. if (dwBufferSize < sizeof(KERB_SMART_CARD_UNLOCK_LOGON))
  564. {
  565. DebugLog((DEB_ERROR,
  566. "Submit buffer to logon too small: %d. %ws, line %d\n",
  567. dwBufferSize,
  568. THIS_FILE,
  569. __LINE__));
  570. Status = STATUS_INVALID_PARAMETER;
  571. goto Cleanup;
  572. }
  573. //
  574. // One additional field for this type (a LUID)
  575. //
  576. PKERB_SMART_CARD_UNLOCK_LOGON Unlock;
  577. PKERB_SMART_CARD_UNLOCK_LOGON_WOW64 UnlockWOW;
  578. Unlock = (PKERB_SMART_CARD_UNLOCK_LOGON) pTempBuffer;
  579. UnlockWOW = (PKERB_SMART_CARD_UNLOCK_LOGON_WOW64) ProtocolSubmitBuffer;
  580. Unlock->LogonId = UnlockWOW->LogonId;
  581. dwOffset = sizeof(KERB_SMART_CARD_UNLOCK_LOGON);
  582. dwWOWOffset = sizeof(KERB_SMART_CARD_UNLOCK_LOGON_WOW64);
  583. }
  584. //
  585. // Copy the variable-length data
  586. //
  587. RtlCopyMemory((LPBYTE) Logon + dwOffset,
  588. (LPBYTE) LogonWOW + dwWOWOffset,
  589. *pSubmitBufferSize - dwWOWOffset);
  590. //
  591. // Set up the pointers in the native struct
  592. //
  593. RELOCATE_WOW_UNICODE_STRING(LogonWOW->Pin,
  594. Logon->Pin,
  595. dwOffset - dwWOWOffset);
  596. Logon->CspData = (PUCHAR) ((LPBYTE) UlongToPtr(LogonWOW->CspData) + (dwOffset - dwWOWOffset));
  597. break;
  598. }
  599. case KerbTicketLogon:
  600. case KerbTicketUnlockLogon:
  601. {
  602. PKERB_TICKET_LOGON Logon;
  603. PKERB_TICKET_LOGON_WOW64 LogonWOW;
  604. DWORD dwOffset;
  605. DWORD dwWOWOffset;
  606. //
  607. // Scale up the size and add on 2 PVOIDs for the worst-case
  608. // scenario to align the two embedded pointers
  609. //
  610. dwBufferSize += sizeof(KERB_TICKET_LOGON)
  611. - sizeof(KERB_TICKET_LOGON_WOW64);
  612. if (dwBufferSize < sizeof(KERB_TICKET_LOGON))
  613. {
  614. DebugLog((DEB_ERROR,
  615. "Submit buffer to logon too small: %d. %ws, line %d\n",
  616. dwBufferSize,
  617. THIS_FILE,
  618. __LINE__));
  619. Status = STATUS_INVALID_PARAMETER;
  620. goto Cleanup;
  621. }
  622. pTempBuffer = KerbAllocate(dwBufferSize);
  623. if (pTempBuffer == NULL)
  624. {
  625. Status = STATUS_INSUFFICIENT_RESOURCES;
  626. goto Cleanup;
  627. }
  628. Logon = (PKERB_TICKET_LOGON) pTempBuffer;
  629. LogonWOW = (PKERB_TICKET_LOGON_WOW64) ProtocolSubmitBuffer;
  630. Logon->MessageType = LogonWOW->MessageType;
  631. Logon->Flags = LogonWOW->Flags;
  632. Logon->ServiceTicketLength = LogonWOW->ServiceTicketLength;
  633. Logon->TicketGrantingTicketLength = LogonWOW->TicketGrantingTicketLength;
  634. dwOffset = sizeof(KERB_TICKET_LOGON);
  635. dwWOWOffset = sizeof(KERB_TICKET_LOGON_WOW64);
  636. if (MessageType == KerbTicketUnlockLogon)
  637. {
  638. if (dwBufferSize < sizeof(KERB_TICKET_UNLOCK_LOGON))
  639. {
  640. DebugLog((DEB_ERROR,
  641. "Submit buffer to logon too small: %d. %ws, line %d\n",
  642. dwBufferSize,
  643. THIS_FILE,
  644. __LINE__));
  645. Status = STATUS_INVALID_PARAMETER;
  646. goto Cleanup;
  647. }
  648. //
  649. // One additional field for this type (a LUID)
  650. //
  651. PKERB_TICKET_UNLOCK_LOGON Unlock;
  652. PKERB_TICKET_UNLOCK_LOGON_WOW64 UnlockWOW;
  653. Unlock = (PKERB_TICKET_UNLOCK_LOGON) pTempBuffer;
  654. UnlockWOW = (PKERB_TICKET_UNLOCK_LOGON_WOW64) ProtocolSubmitBuffer;
  655. Unlock->LogonId = UnlockWOW->LogonId;
  656. dwOffset = sizeof(KERB_TICKET_UNLOCK_LOGON);
  657. dwWOWOffset = sizeof(KERB_TICKET_UNLOCK_LOGON_WOW64);
  658. }
  659. //
  660. // Copy the variable-length data
  661. //
  662. RtlCopyMemory((LPBYTE) Logon + dwOffset,
  663. (LPBYTE) LogonWOW + dwWOWOffset,
  664. *pSubmitBufferSize - dwWOWOffset);
  665. //
  666. // Set up the pointers in the native struct
  667. //
  668. Logon->ServiceTicket = (PUCHAR) ((LPBYTE) UlongToPtr(LogonWOW->ServiceTicket)
  669. + (dwOffset - dwWOWOffset));
  670. Logon->TicketGrantingTicket = (PUCHAR) ((LPBYTE) UlongToPtr(LogonWOW->TicketGrantingTicket)
  671. + (dwOffset - dwWOWOffset));
  672. break;
  673. }
  674. default:
  675. DebugLog((DEB_ERROR,
  676. "Invalid info class to logon: %d. %ws, line %d\n",
  677. MessageType,
  678. THIS_FILE,
  679. __LINE__));
  680. Status = STATUS_INVALID_INFO_CLASS;
  681. goto Cleanup;
  682. }
  683. *pSubmitBufferSize = dwBufferSize;
  684. *ppTempSubmitBuffer = pTempBuffer;
  685. return STATUS_SUCCESS;
  686. Cleanup:
  687. ASSERT(!NT_SUCCESS(Status));
  688. if (pTempBuffer)
  689. {
  690. KerbFree(pTempBuffer);
  691. }
  692. return Status;
  693. }
  694. //+-------------------------------------------------------------------------
  695. //
  696. // Function: KerbAllocateInteractiveWOWProfile
  697. //
  698. // Synopsis: This allocates and fills in the interactive profile for
  699. // a WOW64 client.
  700. //
  701. // Effects:
  702. //
  703. // Arguments:
  704. //
  705. // Requires:
  706. //
  707. // Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
  708. //
  709. // Notes: This code is (effectively) duplicated in
  710. // KerbAllocateInteractiveBuffer. Make sure any
  711. // changes made here are applied there as well.
  712. //
  713. //--------------------------------------------------------------------------
  714. NTSTATUS
  715. KerbAllocateInteractiveWOWBuffer(
  716. OUT PKERB_INTERACTIVE_PROFILE *ProfileBuffer,
  717. OUT PULONG ProfileBufferSize,
  718. IN PNETLOGON_VALIDATION_SAM_INFO3 UserInfo,
  719. IN PKERB_LOGON_SESSION LogonSession,
  720. IN OPTIONAL PKERB_ENCRYPTED_TICKET LogonTicket,
  721. IN OPTIONAL PKERB_INTERACTIVE_LOGON KerbLogonInfo,
  722. IN PUCHAR *pClientBufferBase,
  723. IN BOOLEAN BuildSmartCardProfile,
  724. IN BOOLEAN BuildTicketProfile
  725. )
  726. {
  727. NTSTATUS Status = STATUS_SUCCESS;
  728. PKERB_INTERACTIVE_PROFILE_WOW64 LocalProfileBuffer = NULL;
  729. PKERB_SMART_CARD_PROFILE_WOW64 SmartCardProfile = NULL;
  730. PKERB_TICKET_PROFILE_WOW64 TicketProfile = NULL;
  731. LONG_PTR Delta = 0;
  732. PUCHAR Where = NULL;
  733. if (BuildSmartCardProfile)
  734. {
  735. *ProfileBufferSize = sizeof(KERB_SMART_CARD_PROFILE_WOW64) +
  736. LogonSession->PrimaryCredentials.PublicKeyCreds->CertContext->cbCertEncoded;
  737. }
  738. else if (BuildTicketProfile)
  739. {
  740. *ProfileBufferSize = sizeof(KERB_TICKET_PROFILE_WOW64) +
  741. LogonTicket->key.keyvalue.length;
  742. }
  743. else
  744. {
  745. *ProfileBufferSize = sizeof(KERB_INTERACTIVE_PROFILE_WOW64);
  746. }
  747. *ProfileBufferSize +=
  748. UserInfo->LogonScript.Length + sizeof(WCHAR) +
  749. UserInfo->HomeDirectory.Length + sizeof(WCHAR) +
  750. UserInfo->HomeDirectoryDrive.Length + sizeof(WCHAR) +
  751. UserInfo->FullName.Length + sizeof(WCHAR) +
  752. UserInfo->ProfilePath.Length + sizeof(WCHAR) +
  753. UserInfo->LogonServer.Length + sizeof(WCHAR);
  754. LocalProfileBuffer = (PKERB_INTERACTIVE_PROFILE_WOW64) KerbAllocate(*ProfileBufferSize);
  755. if (LocalProfileBuffer == NULL)
  756. {
  757. Status = STATUS_INSUFFICIENT_RESOURCES;
  758. goto Cleanup;
  759. }
  760. Status = LsaFunctions->AllocateClientBuffer(
  761. NULL,
  762. *ProfileBufferSize,
  763. (PVOID *) pClientBufferBase
  764. );
  765. if ( !NT_SUCCESS( Status ) )
  766. {
  767. goto Cleanup;
  768. }
  769. Delta = (LONG_PTR) (*pClientBufferBase - (PUCHAR) LocalProfileBuffer) ;
  770. //
  771. // Don't walk over smart card data
  772. //
  773. if (BuildSmartCardProfile)
  774. {
  775. Where = (PUCHAR) ((PKERB_SMART_CARD_PROFILE_WOW64) LocalProfileBuffer + 1);
  776. }
  777. else if (BuildTicketProfile)
  778. {
  779. Where = (PUCHAR) ((PKERB_TICKET_PROFILE_WOW64) LocalProfileBuffer + 1);
  780. }
  781. else
  782. {
  783. Where = (PUCHAR) (LocalProfileBuffer + 1);
  784. }
  785. //
  786. // Copy the scalar fields into the profile buffer.
  787. //
  788. LocalProfileBuffer->MessageType = KerbInteractiveProfile;
  789. LocalProfileBuffer->LogonCount = UserInfo->LogonCount;
  790. LocalProfileBuffer->BadPasswordCount= UserInfo->BadPasswordCount;
  791. OLD_TO_NEW_LARGE_INTEGER( UserInfo->LogonTime,
  792. LocalProfileBuffer->LogonTime );
  793. OLD_TO_NEW_LARGE_INTEGER( UserInfo->LogoffTime,
  794. LocalProfileBuffer->LogoffTime );
  795. OLD_TO_NEW_LARGE_INTEGER( UserInfo->KickOffTime,
  796. LocalProfileBuffer->KickOffTime );
  797. OLD_TO_NEW_LARGE_INTEGER( UserInfo->PasswordLastSet,
  798. LocalProfileBuffer->PasswordLastSet );
  799. OLD_TO_NEW_LARGE_INTEGER( UserInfo->PasswordCanChange,
  800. LocalProfileBuffer->PasswordCanChange );
  801. OLD_TO_NEW_LARGE_INTEGER( UserInfo->PasswordMustChange,
  802. LocalProfileBuffer->PasswordMustChange );
  803. LocalProfileBuffer->UserFlags = UserInfo->UserFlags;
  804. //
  805. // Copy the Unicode strings into the profile buffer.
  806. //
  807. KerbPutWOWClientString(&Where,
  808. Delta,
  809. &LocalProfileBuffer->LogonScript,
  810. &UserInfo->LogonScript );
  811. KerbPutWOWClientString(&Where,
  812. Delta,
  813. &LocalProfileBuffer->HomeDirectory,
  814. &UserInfo->HomeDirectory );
  815. KerbPutWOWClientString(&Where,
  816. Delta,
  817. &LocalProfileBuffer->HomeDirectoryDrive,
  818. &UserInfo->HomeDirectoryDrive );
  819. KerbPutWOWClientString(&Where,
  820. Delta,
  821. &LocalProfileBuffer->FullName,
  822. &UserInfo->FullName );
  823. KerbPutWOWClientString(&Where,
  824. Delta,
  825. &LocalProfileBuffer->ProfilePath,
  826. &UserInfo->ProfilePath );
  827. KerbPutWOWClientString(&Where,
  828. Delta,
  829. &LocalProfileBuffer->LogonServer,
  830. &UserInfo->LogonServer );
  831. if (BuildSmartCardProfile)
  832. {
  833. LocalProfileBuffer->MessageType = KerbSmartCardProfile;
  834. SmartCardProfile = (PKERB_SMART_CARD_PROFILE_WOW64) LocalProfileBuffer;
  835. SmartCardProfile->CertificateSize = LogonSession->PrimaryCredentials.PublicKeyCreds->CertContext->cbCertEncoded;
  836. SmartCardProfile->CertificateData = PtrToUlong(Where + Delta);
  837. RtlCopyMemory(Where,
  838. LogonSession->PrimaryCredentials.PublicKeyCreds->CertContext->pbCertEncoded,
  839. SmartCardProfile->CertificateSize);
  840. Where += SmartCardProfile->CertificateSize;
  841. }
  842. else if (BuildTicketProfile)
  843. {
  844. LocalProfileBuffer->MessageType = KerbTicketProfile;
  845. TicketProfile = (PKERB_TICKET_PROFILE_WOW64) LocalProfileBuffer;
  846. //
  847. // If the key is exportable or we are domestic, return the key
  848. //
  849. if (KerbGlobalStrongEncryptionPermitted || KerbIsKeyExportable(&LogonTicket->key))
  850. {
  851. TicketProfile->SessionKey.KeyType = LogonTicket->key.keytype;
  852. TicketProfile->SessionKey.Length = LogonTicket->key.keyvalue.length;
  853. TicketProfile->SessionKey.Value = PtrToUlong(Where + Delta);
  854. RtlCopyMemory(Where,
  855. LogonTicket->key.keyvalue.value,
  856. LogonTicket->key.keyvalue.length);
  857. Where += TicketProfile->SessionKey.Length;
  858. }
  859. }
  860. Cleanup:
  861. if (!NT_SUCCESS(Status))
  862. {
  863. LsaFunctions->FreeClientBuffer(NULL, *pClientBufferBase);
  864. if (LocalProfileBuffer != NULL)
  865. {
  866. KerbFree(LocalProfileBuffer);
  867. }
  868. }
  869. else
  870. {
  871. *ProfileBuffer = (PKERB_INTERACTIVE_PROFILE) LocalProfileBuffer;
  872. }
  873. return Status;
  874. }
  875. //+-------------------------------------------------------------------------
  876. //
  877. // Function: KerbPackExternalWOWTicket
  878. //
  879. // Synopsis: This allocates and fills in the external ticket for
  880. // a WOW64 client.
  881. //
  882. // Effects:
  883. //
  884. // Arguments:
  885. //
  886. // Requires:
  887. //
  888. // Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
  889. //
  890. // Notes: This code is (effectively) duplicated in
  891. // KerbPackExternalTicket. Make sure any
  892. // changes made here are applied there as well.
  893. //
  894. //--------------------------------------------------------------------------
  895. NTSTATUS
  896. KerbPackExternalWOWTicket(
  897. IN PKERB_TICKET_CACHE_ENTRY pCacheEntry,
  898. IN PKERB_MESSAGE_BUFFER pEncodedTicket,
  899. OUT PKERB_EXTERNAL_TICKET *pTicketResponse,
  900. OUT PBYTE *pClientTicketResponse,
  901. OUT PULONG pTicketSize
  902. )
  903. {
  904. PKERB_EXTERNAL_TICKET_WOW64 TicketResponseWOW = NULL;
  905. PBYTE ClientTicketResponseWOW = NULL;
  906. ULONG ulTicketSize;
  907. ULONG Offset;
  908. PUCHAR Where;
  909. NTSTATUS Status;
  910. ulTicketSize = sizeof(KERB_EXTERNAL_TICKET_WOW64) +
  911. pCacheEntry->DomainName.Length +
  912. pCacheEntry->TargetDomainName.Length +
  913. pCacheEntry->AltTargetDomainName.Length +
  914. pCacheEntry->SessionKey.keyvalue.length +
  915. KerbWOWNameLength(pCacheEntry->ServiceName) +
  916. KerbWOWNameLength(pCacheEntry->TargetName) +
  917. KerbWOWNameLength(pCacheEntry->ClientName) +
  918. pEncodedTicket->BufferSize;
  919. //
  920. // Now allocate two copies of the structure - one in our process,
  921. // one in the client's process. We then build the structure in our
  922. // process but with pointer valid in the client's process
  923. //
  924. TicketResponseWOW = (PKERB_EXTERNAL_TICKET_WOW64) KerbAllocate(ulTicketSize);
  925. if (TicketResponseWOW == NULL)
  926. {
  927. Status = STATUS_INSUFFICIENT_RESOURCES;
  928. goto Cleanup;
  929. }
  930. Status = LsaFunctions->AllocateClientBuffer(NULL,
  931. ulTicketSize,
  932. (PVOID *) &ClientTicketResponseWOW);
  933. if (!NT_SUCCESS(Status))
  934. {
  935. goto Cleanup;
  936. }
  937. Offset = (ULONG) (ClientTicketResponseWOW - (PBYTE) TicketResponseWOW);
  938. Where = ((PUCHAR) (TicketResponseWOW + 1));
  939. //
  940. // Copy the non-pointer fields
  941. //
  942. TicketResponseWOW->TicketFlags = pCacheEntry->TicketFlags;
  943. TicketResponseWOW->Flags = 0;
  944. TicketResponseWOW->KeyExpirationTime = pCacheEntry->KeyExpirationTime;
  945. TicketResponseWOW->StartTime = pCacheEntry->StartTime;
  946. TicketResponseWOW->EndTime = pCacheEntry->EndTime;
  947. TicketResponseWOW->RenewUntil = pCacheEntry->RenewUntil;
  948. TicketResponseWOW->TimeSkew = pCacheEntry->TimeSkew;
  949. TicketResponseWOW->SessionKey.KeyType = pCacheEntry->SessionKey.keytype;
  950. //
  951. // Copy the structure to the client's address space
  952. //
  953. //
  954. // These are 32-bit PVOID (i.e., ULONG) aligned
  955. //
  956. //
  957. // Make sure the two name types are the same
  958. //
  959. DsysAssert(sizeof(KERB_INTERNAL_NAME_WOW64) == sizeof(KERB_EXTERNAL_NAME_WOW64));
  960. DsysAssert(FIELD_OFFSET(KERB_INTERNAL_NAME_WOW64,NameType) == FIELD_OFFSET(KERB_EXTERNAL_NAME_WOW64,NameType));
  961. DsysAssert(FIELD_OFFSET(KERB_INTERNAL_NAME_WOW64,NameCount) == FIELD_OFFSET(KERB_EXTERNAL_NAME_WOW64,NameCount));
  962. DsysAssert(FIELD_OFFSET(KERB_INTERNAL_NAME_WOW64,Names) == FIELD_OFFSET(KERB_EXTERNAL_NAME_WOW64,Names));
  963. KerbPutWOWKdcName(pCacheEntry->ServiceName,
  964. &TicketResponseWOW->ServiceName,
  965. Offset,
  966. &Where);
  967. KerbPutWOWKdcName(pCacheEntry->TargetName,
  968. &TicketResponseWOW->TargetName,
  969. Offset,
  970. &Where);
  971. KerbPutWOWKdcName(pCacheEntry->ClientName,
  972. &TicketResponseWOW->ClientName,
  973. Offset,
  974. &Where);
  975. //
  976. // From here on, they are WCHAR aligned
  977. //
  978. KerbPutWOWString(&pCacheEntry->DomainName,
  979. &TicketResponseWOW->DomainName,
  980. Offset,
  981. &Where);
  982. KerbPutWOWString(&pCacheEntry->TargetDomainName,
  983. &TicketResponseWOW->TargetDomainName,
  984. Offset,
  985. &Where);
  986. KerbPutWOWString(&pCacheEntry->AltTargetDomainName,
  987. &TicketResponseWOW->AltTargetDomainName,
  988. Offset,
  989. &Where);
  990. //
  991. // And from here they are BYTE aligned
  992. //
  993. TicketResponseWOW->SessionKey.Value = PtrToUlong(Where + Offset);
  994. RtlCopyMemory(Where,
  995. pCacheEntry->SessionKey.keyvalue.value,
  996. pCacheEntry->SessionKey.keyvalue.length);
  997. Where += pCacheEntry->SessionKey.keyvalue.length;
  998. TicketResponseWOW->SessionKey.Length = pCacheEntry->SessionKey.keyvalue.length;
  999. TicketResponseWOW->EncodedTicketSize = pEncodedTicket->BufferSize;
  1000. TicketResponseWOW->EncodedTicket = PtrToUlong(Where + Offset);
  1001. RtlCopyMemory(Where,
  1002. pEncodedTicket->Buffer,
  1003. pEncodedTicket->BufferSize);
  1004. Where += pEncodedTicket->BufferSize;
  1005. DsysAssert(Where - ((PUCHAR) TicketResponseWOW) == (LONG_PTR) ulTicketSize);
  1006. *pTicketResponse = (PKERB_EXTERNAL_TICKET) TicketResponseWOW;
  1007. *pClientTicketResponse = ClientTicketResponseWOW;
  1008. *pTicketSize = ulTicketSize;
  1009. return STATUS_SUCCESS;
  1010. Cleanup:
  1011. if (TicketResponseWOW != NULL)
  1012. {
  1013. KerbFree(TicketResponseWOW);
  1014. }
  1015. if (ClientTicketResponseWOW != NULL)
  1016. {
  1017. LsaFunctions->FreeClientBuffer(NULL, ClientTicketResponseWOW);
  1018. }
  1019. *pTicketResponse = NULL;
  1020. *pClientTicketResponse = NULL;
  1021. *pTicketSize = 0;
  1022. return Status;
  1023. }
  1024. #endif // _WIN64