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.

1812 lines
47 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 2000
  6. //
  7. // File: ntdigestutil.cxx
  8. //
  9. // Contents: Utility functions for NtDigest package:
  10. // UnicodeStringDuplicate
  11. // SidDuplicate
  12. // DigestAllocateMemory
  13. // DigestFreeMemory
  14. //
  15. //
  16. // History: KDamour 15Mar00 Stolen from NTLM ntlmutil.cxx
  17. //
  18. //------------------------------------------------------------------------
  19. #include "global.h"
  20. #include <stdio.h>
  21. #include <malloc.h>
  22. #include <des.h>
  23. //+-------------------------------------------------------------------------
  24. //
  25. // Function: UnicodeStringDuplicate
  26. //
  27. // Synopsis: Duplicates a UNICODE_STRING. If the source string buffer is
  28. // NULL the destionation will be too. Assumes Destination has
  29. // no string info (called ClearUnicodeString)
  30. //
  31. // Arguments: DestinationString - Receives a copy of the source string
  32. // SourceString - String to copy
  33. //
  34. // Returns: SEC_E_OK - the copy succeeded
  35. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  36. // memory failed.
  37. //
  38. // Requires:
  39. //
  40. // Effects: allocates memory with DigestAllocateMemory
  41. //
  42. // Notes: will add a NULL character to resulting UNICODE_STRING
  43. //
  44. //--------------------------------------------------------------------------
  45. NTSTATUS
  46. UnicodeStringDuplicate(
  47. OUT PUNICODE_STRING DestinationString,
  48. IN OPTIONAL PUNICODE_STRING SourceString
  49. )
  50. {
  51. // DebugLog((DEB_TRACE, "NTDigest:Entering DuplicateUnicodeString\n"));
  52. NTSTATUS Status = STATUS_SUCCESS;
  53. ASSERT(!DestinationString->Buffer); // catch any memory leaks
  54. DestinationString->Buffer = NULL;
  55. DestinationString->Length = 0;
  56. DestinationString->MaximumLength = 0;
  57. if ((ARGUMENT_PRESENT(SourceString)) &&
  58. (SourceString->Buffer != NULL))
  59. {
  60. DestinationString->Buffer = (LPWSTR) DigestAllocateMemory(SourceString->Length + sizeof(WCHAR));
  61. if (DestinationString->Buffer != NULL)
  62. {
  63. DestinationString->Length = SourceString->Length;
  64. DestinationString->MaximumLength = SourceString->Length + sizeof(WCHAR);
  65. RtlCopyMemory(
  66. DestinationString->Buffer,
  67. SourceString->Buffer,
  68. SourceString->Length
  69. );
  70. DestinationString->Buffer[SourceString->Length/sizeof(WCHAR)] = L'\0';
  71. }
  72. else
  73. {
  74. Status = SEC_E_INSUFFICIENT_MEMORY;
  75. DebugLog((DEB_ERROR, "NTDigest: UnicodeStringDuplicate, Allocate returns NULL\n"));
  76. goto CleanUp;
  77. }
  78. }
  79. CleanUp:
  80. // DebugLog((DEB_TRACE, "NTDigest: Leaving UnicodeStringDuplicate\n"));
  81. return(Status);
  82. }
  83. //+-------------------------------------------------------------------------
  84. //
  85. // Function: UnicodeStringCopy
  86. //
  87. // Synopsis: Copies a UNICODE_STRING. If the source string buffer is
  88. // NULL the destionation will be too. If there is enough room
  89. // in the destination, no new memory will be allocated
  90. //
  91. // Arguments: DestinationString - Receives a copy of the source string
  92. // SourceString - String to copy
  93. //
  94. // Returns: SEC_E_OK - the copy succeeded
  95. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  96. // memory failed.
  97. //
  98. // Requires:
  99. //
  100. // Effects: no allocation of memory
  101. //
  102. // Notes:
  103. //
  104. //
  105. //--------------------------------------------------------------------------
  106. NTSTATUS
  107. UnicodeStringCopy(
  108. OUT PUNICODE_STRING DestinationString,
  109. IN OPTIONAL PUNICODE_STRING SourceString
  110. )
  111. {
  112. // DebugLog((DEB_TRACE, "NTDigest: Entering StringCopy\n"));
  113. NTSTATUS Status = STATUS_SUCCESS;
  114. // DestinationString->Buffer = NULL;
  115. // DestinationString->Length = 0;
  116. // DestinationString->MaximumLength = 0;
  117. if ((ARGUMENT_PRESENT(SourceString)) &&
  118. (SourceString->Buffer != NULL) &&
  119. (SourceString->Length))
  120. {
  121. if ((DestinationString->Buffer != NULL) &&
  122. (DestinationString->MaximumLength >= (SourceString->Length + sizeof(WCHAR))))
  123. {
  124. DestinationString->Length = SourceString->Length;
  125. RtlCopyMemory(
  126. DestinationString->Buffer,
  127. SourceString->Buffer,
  128. SourceString->Length
  129. );
  130. DestinationString->Buffer[SourceString->Length/sizeof(WCHAR)] = L'\0';
  131. }
  132. else
  133. {
  134. Status = STATUS_BUFFER_TOO_SMALL;
  135. DestinationString->Length = 0;
  136. DebugLog((DEB_ERROR, "UnicodeStringCopy: DestinationString not enough space\n"));
  137. goto CleanUp;
  138. }
  139. }
  140. else
  141. { // Indicate that there is no content in this string
  142. DestinationString->Length = 0;
  143. }
  144. CleanUp:
  145. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringDuplicate\n"));
  146. return(Status);
  147. }
  148. //+-------------------------------------------------------------------------
  149. //
  150. // Function: UnicodeDuplicatePassword
  151. //
  152. // Synopsis: Duplicates a UNICODE_STRING. If the source string buffer is
  153. // NULL the destionation will be too. The MaximumLength contains
  154. // room for encryption padding data.
  155. //
  156. // Effects: allocates memory with LsaFunctions.AllocatePrivateHeap
  157. //
  158. // Arguments: DestinationString - Receives a copy of the source string
  159. // SourceString - String to copy
  160. //
  161. // Requires:
  162. //
  163. // Returns: SEC_E_OK - the copy succeeded
  164. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  165. // memory failed.
  166. //
  167. // Notes:
  168. //
  169. //
  170. //--------------------------------------------------------------------------
  171. NTSTATUS
  172. UnicodeStringDuplicatePassword(
  173. OUT PUNICODE_STRING DestinationString,
  174. IN OPTIONAL PUNICODE_STRING SourceString
  175. )
  176. {
  177. // DebugLog((DEB_TRACE, "Entering UnicodeDuplicatePassword\n"));
  178. NTSTATUS Status = STATUS_SUCCESS;
  179. ASSERT(DestinationString);
  180. ASSERT(!DestinationString->Buffer); // catch any memory leaks
  181. DestinationString->Buffer = NULL;
  182. DestinationString->Length =
  183. DestinationString->MaximumLength =
  184. 0;
  185. if ((ARGUMENT_PRESENT(SourceString)) &&
  186. (SourceString->Buffer != NULL))
  187. {
  188. USHORT PaddingLength;
  189. PaddingLength = DESX_BLOCKLEN - (SourceString->Length % DESX_BLOCKLEN);
  190. if( PaddingLength == DESX_BLOCKLEN )
  191. {
  192. PaddingLength = 0;
  193. }
  194. DestinationString->Buffer = (LPWSTR) DigestAllocateMemory(
  195. SourceString->Length +
  196. PaddingLength
  197. );
  198. if (DestinationString->Buffer != NULL)
  199. {
  200. DestinationString->Length = SourceString->Length;
  201. DestinationString->MaximumLength = SourceString->Length + PaddingLength;
  202. if( DestinationString->MaximumLength == SourceString->MaximumLength )
  203. {
  204. //
  205. // duplicating an already padded buffer -- pickup the original
  206. // pad.
  207. //
  208. RtlCopyMemory(
  209. DestinationString->Buffer,
  210. SourceString->Buffer,
  211. SourceString->MaximumLength
  212. );
  213. } else {
  214. //
  215. // duplicating an unpadded buffer -- pickup only the string
  216. // and fill the rest with the boot time pad.
  217. //
  218. RtlCopyMemory(
  219. DestinationString->Buffer,
  220. SourceString->Buffer,
  221. SourceString->Length
  222. );
  223. }
  224. }
  225. else
  226. {
  227. Status = STATUS_NO_MEMORY;
  228. DebugLog((DEB_ERROR, "UnicodeDuplicatePassword, DigestAllocateMemory returns NULL\n"));
  229. goto CleanUp;
  230. }
  231. }
  232. CleanUp:
  233. // DebugLog((DEB_TRACE, "Entering UnicodeDuplicatePassword\n"));
  234. return(Status);
  235. }
  236. //+-------------------------------------------------------------------------
  237. //
  238. // Function: UnicodeStringAllocate
  239. //
  240. // Synopsis: Allocates cb wide chars to STRING Buffer
  241. //
  242. // Arguments: pString - pointer to String to allocate memory to
  243. //
  244. // Returns: STATUS_SUCCESS - Normal completion
  245. //
  246. // Requires:
  247. //
  248. // Effects: allocates memory and sets STRING sizes
  249. //
  250. // Notes: Must call StringFree() to release memory
  251. //
  252. //--------------------------------------------------------------------------
  253. NTSTATUS
  254. UnicodeStringAllocate(
  255. IN PUNICODE_STRING pString,
  256. IN USHORT cNumWChars
  257. )
  258. {
  259. // DebugLog((DEB_TRACE, "Entering UnicodeStringAllocate\n"));
  260. NTSTATUS Status = STATUS_SUCCESS;
  261. USHORT cb = 0;
  262. ASSERT(pString);
  263. ASSERT(!pString->Buffer);
  264. cb = cNumWChars + 1; // Add in extra room for the terminating NULL
  265. cb = cb * sizeof(WCHAR); // now convert to wide characters
  266. if (ARGUMENT_PRESENT(pString))
  267. {
  268. pString->Length = 0;
  269. pString->Buffer = (PWSTR)DigestAllocateMemory((ULONG)(cb));
  270. if (pString->Buffer)
  271. {
  272. pString->MaximumLength = cb; // this value is in terms of bytes not WCHAR count
  273. }
  274. else
  275. {
  276. pString->MaximumLength = 0;
  277. Status = SEC_E_INSUFFICIENT_MEMORY;
  278. goto CleanUp;
  279. }
  280. }
  281. else
  282. {
  283. Status = STATUS_INVALID_PARAMETER;
  284. goto CleanUp;
  285. }
  286. CleanUp:
  287. // DebugLog((DEB_TRACE, "Leaving UnicodeStringAllocate\n"));
  288. return(Status);
  289. }
  290. //+-------------------------------------------------------------------------
  291. //
  292. // Function: UnicodeStringClear
  293. //
  294. // Synopsis: Clears a UnicodeString and releases the memory
  295. //
  296. // Arguments: pString - pointer to UnicodeString to clear
  297. //
  298. // Returns: SEC_E_OK - released memory succeeded
  299. //
  300. // Requires:
  301. //
  302. // Effects: de-allocates memory with LsaFunctions.AllocateLsaHeap
  303. //
  304. // Notes:
  305. //
  306. //--------------------------------------------------------------------------
  307. NTSTATUS
  308. UnicodeStringFree(
  309. OUT PUNICODE_STRING pString
  310. )
  311. {
  312. // DebugLog((DEB_TRACE, "NTDigest:Entering UnicodeStringClear\n"));
  313. NTSTATUS Status = STATUS_SUCCESS;
  314. if (ARGUMENT_PRESENT(pString) &&
  315. (pString->Buffer != NULL))
  316. {
  317. DigestFreeMemory(pString->Buffer);
  318. pString->Length = 0;
  319. pString->MaximumLength = 0;
  320. pString->Buffer = NULL;
  321. }
  322. // DebugLog((DEB_TRACE, "NTDigest: Leaving UnicodeStringClear\n"));
  323. return(Status);
  324. }
  325. //+-------------------------------------------------------------------------
  326. //
  327. // Function: StringVerify
  328. //
  329. // Synopsis: If STRING length non-zero, Buffer exist
  330. //
  331. // Arguments: pString - pointer to String to check
  332. //
  333. // Returns: STATUS_SUCCESS - released memory succeeded
  334. // STATUS_INVALID_PARAMETER - String bad format
  335. //
  336. // Requires:
  337. //
  338. // Effects:
  339. //
  340. // Notes: If Strings are created properly, this should never fail
  341. //
  342. //--------------------------------------------------------------------------
  343. NTSTATUS
  344. StringVerify(
  345. OUT PSTRING pString
  346. )
  347. {
  348. NTSTATUS Status = STATUS_SUCCESS;
  349. if (!pString)
  350. {
  351. return STATUS_INVALID_PARAMETER;
  352. }
  353. // If there is a length, buffer must exist
  354. // MaxSize can not be smaller than string length
  355. if (pString->Length &&
  356. (!pString->Buffer ||
  357. (pString->MaximumLength < pString->Length)))
  358. {
  359. return STATUS_INVALID_PARAMETER;
  360. }
  361. return STATUS_SUCCESS;
  362. }
  363. //+-------------------------------------------------------------------------
  364. //
  365. // Function: StringDuplicate
  366. //
  367. // Synopsis: Duplicates a STRING. If the source string buffer is
  368. // NULL the destionation will be too.
  369. //
  370. // Arguments: DestinationString - Receives a copy of the source string
  371. // SourceString - String to copy
  372. //
  373. // Returns: SEC_E_OK - the copy succeeded
  374. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  375. // memory failed.
  376. //
  377. // Requires:
  378. //
  379. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  380. //
  381. // Notes:
  382. //
  383. //
  384. //--------------------------------------------------------------------------
  385. NTSTATUS
  386. StringDuplicate(
  387. OUT PSTRING DestinationString,
  388. IN OPTIONAL PSTRING SourceString
  389. )
  390. {
  391. // DebugLog((DEB_TRACE, "NTDigest: Entering StringDuplicate\n"));
  392. NTSTATUS Status = STATUS_SUCCESS;
  393. ASSERT(DestinationString);
  394. ASSERT(!DestinationString->Buffer); // catch any memory leaks
  395. DestinationString->Buffer = NULL;
  396. DestinationString->Length = 0;
  397. DestinationString->MaximumLength = 0;
  398. if ((ARGUMENT_PRESENT(SourceString)) &&
  399. (SourceString->Buffer != NULL))
  400. {
  401. DestinationString->Buffer = (LPSTR) DigestAllocateMemory(
  402. SourceString->Length + sizeof(CHAR));
  403. if (DestinationString->Buffer != NULL)
  404. {
  405. DestinationString->Length = SourceString->Length;
  406. DestinationString->MaximumLength = SourceString->Length + sizeof(CHAR);
  407. RtlCopyMemory(
  408. DestinationString->Buffer,
  409. SourceString->Buffer,
  410. SourceString->Length
  411. );
  412. DestinationString->Buffer[SourceString->Length/sizeof(CHAR)] = '\0';
  413. }
  414. else
  415. {
  416. Status = SEC_E_INSUFFICIENT_MEMORY;
  417. DebugLog((DEB_ERROR, "NTDigest: StringDuplicate, DigestAllocateMemory returns NULL\n"));
  418. goto CleanUp;
  419. }
  420. }
  421. CleanUp:
  422. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringDuplicate\n"));
  423. return(Status);
  424. }
  425. //+-------------------------------------------------------------------------
  426. //
  427. // Function: StringCopy
  428. //
  429. // Synopsis: Copies a STRING. If the source string buffer is
  430. // NULL the destionation will be too. If there is enough room
  431. // in the destination, no new memory will be allocated
  432. //
  433. // Arguments: DestinationString - Receives a copy of the source string
  434. // SourceString - String to copy
  435. //
  436. // Returns: SEC_E_OK - the copy succeeded
  437. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  438. // memory failed.
  439. //
  440. // Requires:
  441. //
  442. // Effects: no allocation of memory
  443. //
  444. // Notes:
  445. //
  446. //
  447. //--------------------------------------------------------------------------
  448. NTSTATUS
  449. StringCopy(
  450. OUT PSTRING DestinationString,
  451. IN OPTIONAL PSTRING SourceString
  452. )
  453. {
  454. // DebugLog((DEB_TRACE, "NTDigest: Entering StringCopy\n"));
  455. NTSTATUS Status = STATUS_SUCCESS;
  456. // DestinationString->Buffer = NULL;
  457. // DestinationString->Length = 0;
  458. // DestinationString->MaximumLength = 0;
  459. if ((ARGUMENT_PRESENT(SourceString)) &&
  460. (SourceString->Buffer != NULL) &&
  461. (SourceString->Length))
  462. {
  463. if ((DestinationString->Buffer != NULL) &&
  464. (DestinationString->MaximumLength >= (SourceString->Length + sizeof(CHAR))))
  465. {
  466. DestinationString->Length = SourceString->Length;
  467. RtlCopyMemory(
  468. DestinationString->Buffer,
  469. SourceString->Buffer,
  470. SourceString->Length
  471. );
  472. DestinationString->Buffer[SourceString->Length/sizeof(CHAR)] = '\0';
  473. }
  474. else
  475. {
  476. Status = STATUS_BUFFER_TOO_SMALL;
  477. DestinationString->Length = 0;
  478. DebugLog((DEB_ERROR, "StringCopy: DestinationString not enough space\n"));
  479. goto CleanUp;
  480. }
  481. }
  482. else
  483. { // Indicate that there is no content in this string
  484. DestinationString->Length = 0;
  485. }
  486. CleanUp:
  487. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringDuplicate\n"));
  488. return(Status);
  489. }
  490. //+-------------------------------------------------------------------------
  491. //
  492. // Function: StringReference
  493. //
  494. // Synopsis: Reference the source string to the destination. No memory allocated
  495. //
  496. // Arguments: DestinationString - Receives a reference of the source string
  497. // SourceString - String to reference
  498. //
  499. // Returns: SEC_E_OK - the copy succeeded
  500. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  501. // memory failed.
  502. //
  503. // Requires:
  504. //
  505. // Effects: no allocation of memory
  506. //
  507. // Notes:
  508. //
  509. //
  510. //--------------------------------------------------------------------------
  511. NTSTATUS
  512. StringReference(
  513. OUT PSTRING pDestinationString,
  514. IN PSTRING pSourceString
  515. )
  516. {
  517. if (!pDestinationString || !pSourceString)
  518. {
  519. return STATUS_INVALID_PARAMETER;
  520. }
  521. // This will only create a reference - no string buffer memory actually copied
  522. memcpy(pDestinationString, pSourceString, sizeof(STRING));
  523. return STATUS_SUCCESS;
  524. }
  525. //+-------------------------------------------------------------------------
  526. //
  527. // Function: StringCharDuplicate
  528. //
  529. // Synopsis: Duplicates a NULL terminated char. If the source string buffer is
  530. // NULL the destionation will be too.
  531. //
  532. // Arguments: Destination - Receives a copy of the source NULL Term char *
  533. // czSource - String to copy
  534. // uCnt - number of characters to copy over (0 if copy until NULL)
  535. //
  536. // Returns: SEC_E_OK - the copy succeeded
  537. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  538. // memory failed.
  539. //
  540. // Requires:
  541. //
  542. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  543. //
  544. // Notes:
  545. //
  546. //
  547. //--------------------------------------------------------------------------
  548. NTSTATUS
  549. StringCharDuplicate(
  550. OUT PSTRING DestinationString,
  551. IN OPTIONAL char *czSource,
  552. IN OPTIONAL USHORT uCnt
  553. )
  554. {
  555. // DebugLog((DEB_TRACE, "NTDigest: Entering StringCharDuplicate\n"));
  556. NTSTATUS Status = STATUS_SUCCESS;
  557. USHORT cbSourceCz = 0;
  558. //ASSERT(DestinationString);
  559. //ASSERT(!DestinationString->Buffer); // catch any memory leaks
  560. DestinationString->Buffer = NULL;
  561. DestinationString->Length = 0;
  562. DestinationString->MaximumLength = 0;
  563. // If uCnt specified then use that as max length, otherwise locate NULL terminator
  564. if (uCnt)
  565. {
  566. cbSourceCz = uCnt;
  567. }
  568. else
  569. {
  570. cbSourceCz = strlen(czSource);
  571. }
  572. if ((ARGUMENT_PRESENT(czSource)) &&
  573. (cbSourceCz != 0))
  574. {
  575. DestinationString->Buffer = (LPSTR) DigestAllocateMemory(cbSourceCz + sizeof(CHAR));
  576. if (DestinationString->Buffer != NULL)
  577. {
  578. DestinationString->Length = cbSourceCz;
  579. DestinationString->MaximumLength = cbSourceCz + sizeof(CHAR);
  580. RtlCopyMemory(
  581. DestinationString->Buffer,
  582. czSource,
  583. cbSourceCz
  584. );
  585. // Since AllocateMemory zeroes out buffer, already NULL terminated
  586. }
  587. else
  588. {
  589. Status = SEC_E_INSUFFICIENT_MEMORY;
  590. DebugLog((DEB_ERROR, "NTDigest: StringCharDuplicate, DigestAllocateMemory returns NULL\n"));
  591. goto CleanUp;
  592. }
  593. }
  594. CleanUp:
  595. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringCharDuplicate\n"));
  596. return(Status);
  597. }
  598. //+-------------------------------------------------------------------------
  599. //
  600. // Function: StringCharDuplicate
  601. //
  602. // Synopsis: Duplicates a NULL terminated char. If the source string buffer is
  603. // NULL the destionation will be too.
  604. //
  605. // Arguments: Destination - Receives a copy of the source NULL Term char *
  606. // czSource - String to copy
  607. //
  608. // Returns: SEC_E_OK - the copy succeeded
  609. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  610. // memory failed.
  611. //
  612. // Requires:
  613. //
  614. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  615. //
  616. // Notes:
  617. //
  618. //
  619. //--------------------------------------------------------------------------
  620. NTSTATUS
  621. UnicodeStringWCharDuplicate(
  622. OUT PUNICODE_STRING DestinationString,
  623. IN OPTIONAL WCHAR *szSource
  624. )
  625. {
  626. // DebugLog((DEB_TRACE, "NTDigest: Entering StringCharDuplicate\n"));
  627. NTSTATUS Status = STATUS_SUCCESS;
  628. USHORT cbSourceSz = 0;
  629. ASSERT(DestinationString);
  630. ASSERT(!DestinationString->Buffer); // catch any memory leaks
  631. DestinationString->Buffer = NULL;
  632. DestinationString->Length = 0;
  633. DestinationString->MaximumLength = 0;
  634. if ((ARGUMENT_PRESENT(szSource)) &&
  635. ((cbSourceSz = (USHORT)wcslen(szSource)) != 0))
  636. {
  637. DestinationString->Buffer = (PWSTR) DigestAllocateMemory((cbSourceSz * sizeof(WCHAR)) + sizeof(WCHAR));
  638. if (DestinationString->Buffer != NULL)
  639. {
  640. DestinationString->Length = (cbSourceSz * sizeof(WCHAR));
  641. DestinationString->MaximumLength = ((cbSourceSz * sizeof(WCHAR)) + sizeof(WCHAR)); // Account for NULL WCHAR at end
  642. RtlCopyMemory(
  643. DestinationString->Buffer,
  644. szSource,
  645. (cbSourceSz * sizeof(WCHAR))
  646. );
  647. DestinationString->Buffer[cbSourceSz] = '\0';
  648. }
  649. else
  650. {
  651. Status = SEC_E_INSUFFICIENT_MEMORY;
  652. DebugLog((DEB_ERROR, "NTDigest: StringCharDuplicate, DigestAllocateMemory returns NULL\n"));
  653. goto CleanUp;
  654. }
  655. }
  656. CleanUp:
  657. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringCharDuplicate\n"));
  658. return(Status);
  659. }
  660. //+-------------------------------------------------------------------------
  661. //
  662. // Function: UnicodeStringReference
  663. //
  664. // Synopsis: Reference the source unicode_string to the destination. No memory allocated
  665. //
  666. // Arguments: DestinationString - Receives a reference of the source string
  667. // SourceString - String to reference
  668. //
  669. // Returns: SEC_E_OK - the copy succeeded
  670. // SEC_E_INSUFFICIENT_MEMORY - the call to allocate
  671. // memory failed.
  672. //
  673. // Requires:
  674. //
  675. // Effects: no allocation of memory
  676. //
  677. // Notes:
  678. //
  679. //
  680. //--------------------------------------------------------------------------
  681. NTSTATUS
  682. UnicodeStringReference(
  683. OUT PUNICODE_STRING pDestinationString,
  684. IN PUNICODE_STRING pSourceString
  685. )
  686. {
  687. if (!pDestinationString || !pSourceString)
  688. {
  689. return STATUS_INVALID_PARAMETER;
  690. }
  691. // This will only create a reference - no string buffer memory actually copied
  692. memcpy(pDestinationString, pSourceString, sizeof(UNICODE_STRING));
  693. return STATUS_SUCCESS;
  694. }
  695. //+-------------------------------------------------------------------------
  696. //
  697. // Function: DecodeUnicodeString
  698. //
  699. // Synopsis: Convert an encoded string into Unicode
  700. //
  701. // Arguments: pstrSource - pointer to String with encoded input
  702. //
  703. // pustrDestination - pointer to a destination Unicode string
  704. //
  705. // Returns: STATUS_SUCCESS - Normal completion
  706. //
  707. // Requires:
  708. //
  709. // Effects: allocates memory and sets UNICODE_STRING sizes
  710. //
  711. // Notes: Must call UnicodeStringFree() to release memory
  712. //
  713. //--------------------------------------------------------------------------
  714. NTSTATUS
  715. DecodeUnicodeString(
  716. IN PSTRING pstrSource,
  717. IN UINT CodePage,
  718. OUT PUNICODE_STRING pustrDestination
  719. )
  720. {
  721. NTSTATUS Status = STATUS_SUCCESS;
  722. int cNumWChars = 0; // number of wide characters
  723. int cb = 0; // number of bytes to allocate
  724. int iRC = 0; // return code
  725. DWORD dwError = 0;
  726. // Handle case if there is no characters to convert
  727. if (!pstrSource->Length)
  728. {
  729. pustrDestination->Length = 0;
  730. pustrDestination->MaximumLength = 0;
  731. pustrDestination->Buffer = NULL;
  732. goto CleanUp;
  733. }
  734. // Determine number of characters needed in unicode string
  735. cNumWChars = MultiByteToWideChar(CodePage,
  736. 0,
  737. pstrSource->Buffer,
  738. pstrSource->Length,
  739. NULL,
  740. 0);
  741. if (cNumWChars <= 0)
  742. {
  743. Status = E_FAIL;
  744. dwError = GetLastError();
  745. DebugLog((DEB_ERROR, "DecodeUnicodeString: failed to determine wchar count error 0x%x\n", dwError));
  746. goto CleanUp;
  747. }
  748. Status = UnicodeStringAllocate(pustrDestination, (USHORT)cNumWChars);
  749. if (!NT_SUCCESS(Status))
  750. {
  751. DebugLog((DEB_ERROR, "DecodeUnicodeString: Failed Unicode allocation\n"));
  752. goto CleanUp;
  753. }
  754. // We now have the space allocated so convert encoded unicode
  755. iRC = MultiByteToWideChar(CodePage,
  756. 0,
  757. pstrSource->Buffer,
  758. pstrSource->Length,
  759. pustrDestination->Buffer,
  760. cNumWChars);
  761. if (iRC == 0)
  762. {
  763. UnicodeStringFree(pustrDestination); // Free up allocation on error
  764. Status = E_FAIL;
  765. dwError = GetLastError();
  766. DebugLog((DEB_ERROR, "DecodeUnicodeString: failed to decode source string error 0x%x\n", dwError));
  767. goto CleanUp;
  768. }
  769. // decoding successful set size of unicode string
  770. pustrDestination->Length = (USHORT)(iRC * sizeof(WCHAR));
  771. //DebugLog((DEB_TRACE, "DecodeUnicodeString: string (%Z) is unicode (%wZ)\n", pstrSource, pustrDestination));
  772. //DebugLog((DEB_TRACE, "DecodeUnicodeString: unicode length %d maxlength %d\n",
  773. //pustrDestination->Length, pustrDestination->MaximumLength));
  774. CleanUp:
  775. return Status;
  776. }
  777. //+-------------------------------------------------------------------------
  778. //
  779. // Function: EncodeUnicodeString
  780. //
  781. // Synopsis: Encode a Unicode string into a charset string
  782. //
  783. // Arguments: pustrSource - pointer to Unicode_String with input
  784. //
  785. // pstrDestination - pointer to a destination encoded string
  786. //
  787. // pfUsedDefaultChar - pointer to BOOL if default character had to be used since
  788. // the Source contains characters outside the character set specified
  789. //
  790. // Returns: STATUS_SUCCESS - Normal completion
  791. //
  792. // Requires:
  793. //
  794. // Effects: allocates memory and sets STRING sizes
  795. //
  796. // Notes: Must call StringFree() to release memory
  797. //
  798. //--------------------------------------------------------------------------
  799. NTSTATUS
  800. EncodeUnicodeString(
  801. IN PUNICODE_STRING pustrSource,
  802. IN UINT CodePage,
  803. OUT PSTRING pstrDestination,
  804. IN OUT PBOOL pfUsedDefaultChar
  805. )
  806. {
  807. NTSTATUS Status = STATUS_SUCCESS;
  808. int cNumChars = 0; // number of wide characters
  809. int iRC = 0; // return code
  810. DWORD dwError = 0;
  811. PBOOL pfUsedDef = NULL;
  812. DWORD dwFlags = 0;
  813. // Handle case if there is no characters to convert
  814. if (!pustrSource->Length)
  815. {
  816. pstrDestination->Length = 0;
  817. pstrDestination->MaximumLength = 0;
  818. pstrDestination->Buffer = NULL;
  819. goto CleanUp;
  820. }
  821. // If UTF-8 then do not allow default char mapping (ref MSDN)
  822. if (CodePage != CP_UTF8)
  823. {
  824. pfUsedDef = pfUsedDefaultChar;
  825. dwFlags = WC_NO_BEST_FIT_CHARS;
  826. }
  827. // Determine number of characters needed in unicode string
  828. cNumChars = WideCharToMultiByte(CodePage,
  829. dwFlags,
  830. pustrSource->Buffer,
  831. (pustrSource->Length / sizeof(WCHAR)),
  832. NULL,
  833. 0,
  834. NULL,
  835. NULL);
  836. if (cNumChars <= 0)
  837. {
  838. Status = E_FAIL;
  839. dwError = GetLastError();
  840. DebugLog((DEB_ERROR, "EncodeUnicodeString: failed to determine char count error 0x%x\n", dwError));
  841. goto CleanUp;
  842. }
  843. Status = StringAllocate(pstrDestination, (USHORT)cNumChars);
  844. if (!NT_SUCCESS(Status))
  845. {
  846. DebugLog((DEB_ERROR, "EncodeUnicodeString: Failed String allocation\n"));
  847. goto CleanUp;
  848. }
  849. // We now have the space allocated so convert to encoded unicode
  850. iRC = WideCharToMultiByte(CodePage,
  851. dwFlags,
  852. pustrSource->Buffer,
  853. (pustrSource->Length / sizeof(WCHAR)),
  854. pstrDestination->Buffer,
  855. cNumChars,
  856. NULL,
  857. pfUsedDef);
  858. if (iRC == 0)
  859. {
  860. Status = E_FAIL;
  861. dwError = GetLastError();
  862. DebugLog((DEB_ERROR, "EncodeUnicodeString: failed to decode source string error 0x%x\n", dwError));
  863. StringFree(pstrDestination); // Free up allocation on error
  864. goto CleanUp;
  865. }
  866. // decoding successful set size of unicode string
  867. pstrDestination->Length = (USHORT)iRC;
  868. CleanUp:
  869. return Status;
  870. }
  871. //+-------------------------------------------------------------------------
  872. //
  873. // Function: StringFree
  874. //
  875. // Synopsis: Clears a String and releases the memory
  876. //
  877. // Arguments: pString - pointer to String to clear
  878. //
  879. // Returns: SEC_E_OK - released memory succeeded
  880. //
  881. // Requires:
  882. //
  883. // Effects: de-allocates memory with LsaFunctions.AllocateLsaHeap
  884. //
  885. // Notes:
  886. //
  887. //--------------------------------------------------------------------------
  888. NTSTATUS
  889. StringFree(
  890. IN PSTRING pString
  891. )
  892. {
  893. // DebugLog((DEB_TRACE, "NTDigest:Entering StringFree\n"));
  894. NTSTATUS Status = STATUS_SUCCESS;
  895. if (ARGUMENT_PRESENT(pString) &&
  896. (pString->Buffer != NULL))
  897. {
  898. DigestFreeMemory(pString->Buffer);
  899. pString->Length = 0;
  900. pString->MaximumLength = 0;
  901. pString->Buffer = NULL;
  902. }
  903. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringFree\n"));
  904. return(Status);
  905. }
  906. //+-------------------------------------------------------------------------
  907. //
  908. // Function: StringAllocate
  909. //
  910. // Synopsis: Allocates cb chars to STRING Buffer
  911. //
  912. // Arguments: pString - pointer to String to allocate memory to
  913. //
  914. // Returns: STATUS_SUCCESS - Normal completion
  915. //
  916. // Requires:
  917. //
  918. // Effects: allocates memory and sets STRING sizes
  919. //
  920. // Notes: Must call StringFree() to release memory
  921. //
  922. //--------------------------------------------------------------------------
  923. NTSTATUS
  924. StringAllocate(
  925. IN PSTRING pString,
  926. IN USHORT cb
  927. )
  928. {
  929. // DebugLog((DEB_TRACE, "NTDigest:Entering StringAllocate\n"));
  930. NTSTATUS Status = STATUS_SUCCESS;
  931. ASSERT(pString);
  932. ASSERT(!pString->Buffer); // catch any memory leaks
  933. cb = cb + 1; // Add in extra room for the terminating NULL
  934. if (ARGUMENT_PRESENT(pString))
  935. {
  936. pString->Length = 0;
  937. pString->Buffer = (char *)DigestAllocateMemory((ULONG)(cb * sizeof(CHAR)));
  938. if (pString->Buffer)
  939. {
  940. pString->MaximumLength = cb;
  941. }
  942. else
  943. {
  944. pString->MaximumLength = 0;
  945. Status = SEC_E_INSUFFICIENT_MEMORY;
  946. goto CleanUp;
  947. }
  948. }
  949. else
  950. {
  951. Status = STATUS_INVALID_PARAMETER;
  952. goto CleanUp;
  953. }
  954. CleanUp:
  955. // DebugLog((DEB_TRACE, "NTDigest: Leaving StringAllocate\n"));
  956. return(Status);
  957. }
  958. //+-------------------------------------------------------------------------
  959. //
  960. // Function: SidDuplicate
  961. //
  962. // Synopsis: Duplicates a SID
  963. //
  964. // Arguments: DestinationSid - Receives a copy of the SourceSid
  965. // SourceSid - SID to copy
  966. //
  967. // Returns: STATUS_SUCCESS - the copy succeeded
  968. // STATUS_INSUFFICIENT_RESOURCES - the call to allocate memory
  969. // failed
  970. //
  971. // Requires:
  972. //
  973. // Effects: allocates memory with LsaFunctions.AllocateLsaHeap
  974. //
  975. // Notes:
  976. //
  977. //
  978. //--------------------------------------------------------------------------
  979. NTSTATUS
  980. SidDuplicate(
  981. OUT PSID * DestinationSid,
  982. IN PSID SourceSid
  983. )
  984. {
  985. // DebugLog((DEB_TRACE, "NTDigest: Entering SidDuplicate\n"));
  986. NTSTATUS Status = STATUS_SUCCESS;
  987. ULONG SidSize;
  988. // ASSERT(RtlValidSid(SourceSid));
  989. SidSize = RtlLengthSid(SourceSid);
  990. *DestinationSid = (PSID) DigestAllocateMemory( SidSize );
  991. if (ARGUMENT_PRESENT(*DestinationSid))
  992. {
  993. RtlCopyMemory(
  994. *DestinationSid,
  995. SourceSid,
  996. SidSize
  997. );
  998. }
  999. else
  1000. {
  1001. Status = STATUS_INSUFFICIENT_RESOURCES;
  1002. DebugLog((DEB_ERROR, "NTDigest: SidDuplicate, DigestAllocateMemory returns NULL\n"));
  1003. goto CleanUp;
  1004. }
  1005. CleanUp:
  1006. // DebugLog((DEB_TRACE, "NTDigest: Leaving SidDuplicate\n"));
  1007. return(Status);
  1008. }
  1009. //+-------------------------------------------------------------------------
  1010. //
  1011. // Function: DigestAllocateMemory
  1012. //
  1013. // Synopsis: Allocate memory in either lsa mode or user mode
  1014. //
  1015. // Effects: Allocated chunk is zeroed out
  1016. //
  1017. // Arguments:
  1018. //
  1019. // Requires:
  1020. //
  1021. // Returns:
  1022. //
  1023. // Notes:
  1024. //
  1025. //
  1026. //--------------------------------------------------------------------------
  1027. PVOID
  1028. DigestAllocateMemory(
  1029. IN ULONG BufferSize
  1030. )
  1031. {
  1032. PVOID Buffer = NULL;
  1033. // DebugLog((DEB_TRACE, "Entering DigestAllocateMemory\n"));
  1034. if (g_NtDigestState == NtDigestLsaMode)
  1035. {
  1036. Buffer = g_LsaFunctions->AllocateLsaHeap(BufferSize);
  1037. if (Buffer != NULL)
  1038. {
  1039. RtlZeroMemory(Buffer, BufferSize);
  1040. }
  1041. DebugLog((DEB_TRACE_MEM, "Memory: LSA alloc %lu bytes at 0x%x\n", BufferSize, Buffer ));
  1042. }
  1043. else
  1044. {
  1045. ASSERT(g_NtDigestState == NtDigestUserMode);
  1046. Buffer = LocalAlloc(LPTR, BufferSize);
  1047. DebugLog((DEB_TRACE_MEM, "Memory: Local alloc %lu bytes at 0x%x\n", BufferSize, Buffer ));
  1048. }
  1049. // DebugLog((DEB_TRACE, "Leaving DigestAllocateMemory\n"));
  1050. return Buffer;
  1051. }
  1052. //+-------------------------------------------------------------------------
  1053. //
  1054. // Function: DigestFreeMemory
  1055. //
  1056. // Synopsis: Free memory in either lsa mode or user mode
  1057. //
  1058. // Effects:
  1059. //
  1060. // Arguments:
  1061. //
  1062. // Requires:
  1063. //
  1064. // Returns:
  1065. //
  1066. // Notes:
  1067. //
  1068. //
  1069. //--------------------------------------------------------------------------
  1070. VOID
  1071. DigestFreeMemory(
  1072. IN PVOID Buffer
  1073. )
  1074. {
  1075. // DebugLog((DEB_TRACE, "Entering DigestFreeMemory\n"));
  1076. if (ARGUMENT_PRESENT(Buffer))
  1077. {
  1078. if (g_NtDigestState == NtDigestLsaMode)
  1079. {
  1080. DebugLog((DEB_TRACE_MEM, "DigestFreeMemory: LSA free at 0x%x\n", Buffer ));
  1081. g_LsaFunctions->FreeLsaHeap(Buffer);
  1082. }
  1083. else
  1084. {
  1085. ASSERT(g_NtDigestState == NtDigestUserMode);
  1086. DebugLog((DEB_TRACE_MEM, "DigestFreeMemory: Local free at 0x%x\n", Buffer ));
  1087. LocalFree(Buffer);
  1088. }
  1089. }
  1090. // DebugLog((DEB_TRACE, "Leaving DigestFreeMemory\n"));
  1091. }
  1092. // Helper functions
  1093. /*++
  1094. Routine Description:
  1095. Convert binary data to ASCII hex representation
  1096. Arguments:
  1097. pSrc - binary data to convert
  1098. cSrc - length of binary data
  1099. pDst - buffer receiving ASCII representation of pSrc
  1100. Return Value:
  1101. Nothing
  1102. --*/
  1103. VOID
  1104. BinToHex(
  1105. LPBYTE pSrc,
  1106. UINT cSrc,
  1107. LPSTR pDst
  1108. )
  1109. {
  1110. #define TOHEX(a) ((a)>=10 ? 'a'+(a)-10 : '0'+(a))
  1111. for ( UINT x = 0, y = 0 ; x < cSrc ; ++x )
  1112. {
  1113. UINT v;
  1114. v = pSrc[x]>>4;
  1115. pDst[y++] = TOHEX( v );
  1116. v = pSrc[x]&0x0f;
  1117. pDst[y++] = TOHEX( v );
  1118. }
  1119. pDst[y] = '\0';
  1120. }
  1121. /*++
  1122. Routine Description:
  1123. Convert binary data to ASCII hex representation
  1124. Arguments:
  1125. pSrc - ASCII data to convert to binary
  1126. cSrc - length of ASCII data
  1127. pDst - buffer receiving binary representation of pSrc
  1128. Return Value:
  1129. Nothing
  1130. --*/
  1131. VOID
  1132. HexToBin(
  1133. LPSTR pSrc,
  1134. UINT cSrc,
  1135. LPBYTE pDst
  1136. )
  1137. {
  1138. #define TOBIN(a) ((a)>='a' ? (a)-'a'+10 : (a)-'0')
  1139. for ( UINT x = 0, y = 0 ; x < cSrc ; x = x + 2 )
  1140. {
  1141. BYTE v;
  1142. v = TOBIN(pSrc[x])<<4;
  1143. pDst[y++] = v + TOBIN(pSrc[x+1]);
  1144. }
  1145. }
  1146. //+-------------------------------------------------------------------------
  1147. //
  1148. // Function: CopyClientString
  1149. //
  1150. // Synopsis: copies a client string to local memory, including
  1151. // allocating space for it locally.
  1152. //
  1153. // Arguments:
  1154. // SourceString - Could be Ansi or Wchar in client process
  1155. // SourceLength - bytes
  1156. // DoUnicode - whether the string is Wchar
  1157. //
  1158. // Returns:
  1159. // DestinationString - Unicode String in Lsa Process
  1160. //
  1161. // Notes:
  1162. //
  1163. //--------------------------------------------------------------------------
  1164. NTSTATUS
  1165. CopyClientString(
  1166. IN PWSTR SourceString,
  1167. IN ULONG SourceLength,
  1168. IN BOOLEAN DoUnicode,
  1169. OUT PUNICODE_STRING DestinationString
  1170. )
  1171. {
  1172. // DebugLog((DEB_TRACE,"NTDigest: Entering CopyClientString\n"));
  1173. NTSTATUS Status = STATUS_SUCCESS;
  1174. STRING TemporaryString;
  1175. ULONG SourceSize = 0;
  1176. ULONG CharacterSize = sizeof(CHAR);
  1177. ASSERT(DestinationString);
  1178. ASSERT(!DestinationString->Buffer);
  1179. //
  1180. // First initialize the string to zero, in case the source is a null
  1181. // string
  1182. //
  1183. DestinationString->Length = DestinationString->MaximumLength = 0;
  1184. DestinationString->Buffer = NULL;
  1185. TemporaryString.Buffer = NULL;
  1186. if (SourceString != NULL)
  1187. {
  1188. //
  1189. // If the length is zero, allocate one byte for a "\0" terminator
  1190. //
  1191. if (SourceLength == 0)
  1192. {
  1193. DestinationString->Buffer = (LPWSTR) DigestAllocateMemory(sizeof(WCHAR));
  1194. if (DestinationString->Buffer == NULL)
  1195. {
  1196. DebugLog((DEB_ERROR,"CopyClientString, Error from DigestAllocate is 0x%lx\n", Status));
  1197. Status = SEC_E_INSUFFICIENT_MEMORY;
  1198. goto Cleanup;
  1199. }
  1200. DestinationString->MaximumLength = sizeof(WCHAR);
  1201. *DestinationString->Buffer = L'\0';
  1202. }
  1203. else
  1204. {
  1205. //
  1206. // Allocate a temporary buffer to hold the client string. We may
  1207. // then create a buffer for the unicode version. The length
  1208. // is the length in characters, so possible expand to hold unicode
  1209. // characters and a null terminator.
  1210. //
  1211. if (DoUnicode)
  1212. {
  1213. CharacterSize = sizeof(WCHAR);
  1214. }
  1215. SourceSize = (SourceLength + 1) * CharacterSize;
  1216. //
  1217. // insure no overflow aggainst UNICODE_STRING
  1218. //
  1219. if ( (SourceSize > 0xFFFF) ||
  1220. ((SourceSize - CharacterSize) > 0xFFFF)
  1221. )
  1222. {
  1223. Status = STATUS_INVALID_PARAMETER;
  1224. DebugLog((DEB_ERROR,"CopyClientString: SourceSize is too large\n"));
  1225. goto Cleanup;
  1226. }
  1227. TemporaryString.Buffer = (LPSTR) DigestAllocateMemory(SourceSize);
  1228. if (TemporaryString.Buffer == NULL)
  1229. {
  1230. Status = SEC_E_INSUFFICIENT_MEMORY;
  1231. DebugLog((DEB_ERROR,"CopyClientString: Error from DigestAllocate is 0x%lx\n", Status));
  1232. goto Cleanup;
  1233. }
  1234. TemporaryString.Length = (USHORT) (SourceSize - CharacterSize);
  1235. TemporaryString.MaximumLength = (USHORT) SourceSize;
  1236. //
  1237. // Finally copy the string from the client
  1238. //
  1239. Status = g_LsaFunctions->CopyFromClientBuffer(
  1240. NULL,
  1241. SourceSize - CharacterSize,
  1242. TemporaryString.Buffer,
  1243. SourceString
  1244. );
  1245. if (!NT_SUCCESS(Status))
  1246. {
  1247. DebugLog((DEB_ERROR,"CopyClientString: Error from LsaFunctions->CopyFromClientBuffer is 0x%lx\n", Status));
  1248. goto Cleanup;
  1249. }
  1250. //
  1251. // If we are doing unicode, finish up now
  1252. //
  1253. if (DoUnicode)
  1254. {
  1255. DestinationString->Buffer = (LPWSTR) TemporaryString.Buffer;
  1256. DestinationString->Length = (USHORT) (SourceSize - CharacterSize);
  1257. DestinationString->MaximumLength = (USHORT) SourceSize;
  1258. }
  1259. else
  1260. {
  1261. NTSTATUS Status1;
  1262. Status1 = RtlAnsiStringToUnicodeString(
  1263. DestinationString,
  1264. &TemporaryString,
  1265. TRUE
  1266. ); // allocate destination
  1267. if (!NT_SUCCESS(Status1))
  1268. {
  1269. Status = SEC_E_INSUFFICIENT_MEMORY;
  1270. DebugLog((DEB_ERROR,"CopyClientString: Error from RtlAnsiStringToUnicodeString is 0x%lx\n", Status));
  1271. goto Cleanup;
  1272. }
  1273. }
  1274. }
  1275. }
  1276. Cleanup:
  1277. if (TemporaryString.Buffer != NULL)
  1278. {
  1279. //
  1280. // Free this if we failed and were doing unicode or if we weren't
  1281. // doing unicode
  1282. //
  1283. if ((DoUnicode && !NT_SUCCESS(Status)) || !DoUnicode)
  1284. {
  1285. DigestFreeMemory(TemporaryString.Buffer);
  1286. }
  1287. }
  1288. // DebugLog((DEB_TRACE,"NTDigest: Leaving CopyClientString\n"));
  1289. return(Status);
  1290. }
  1291. /*++
  1292. Routine Description:
  1293. This routine parses a Token Descriptor and pulls out the useful
  1294. information.
  1295. Arguments:
  1296. TokenDescriptor - Descriptor of the buffer containing the token.
  1297. BufferIndex - Selects which buffer to extract
  1298. Token - Handle to the SecBuffer to write selected buffer to.
  1299. ReadonlyOK - TRUE if the token buffer may be readonly.
  1300. Return Value:
  1301. TRUE - If token buffer was properly found.
  1302. --*/
  1303. BOOLEAN
  1304. SspGetTokenBufferByIndex(
  1305. IN PSecBufferDesc TokenDescriptor OPTIONAL,
  1306. IN ULONG BufferIndex,
  1307. OUT PSecBuffer * Token,
  1308. IN BOOLEAN ReadonlyOK
  1309. )
  1310. {
  1311. NTSTATUS StatusTmp = STATUS_SUCCESS;
  1312. ULONG i, Index = 0;
  1313. PSecBuffer Buffer = NULL;
  1314. //
  1315. // If there is no TokenDescriptor passed in,
  1316. // just pass out NULL to our caller.
  1317. //
  1318. ASSERT(*Token != NULL);
  1319. if ( !ARGUMENT_PRESENT( TokenDescriptor) ) {
  1320. return TRUE;
  1321. }
  1322. if (TokenDescriptor->ulVersion != SECBUFFER_VERSION)
  1323. {
  1324. DebugLog((DEB_ERROR,"SspGetTokenBufferByIndex: Wrong Version number\n"));
  1325. return FALSE;
  1326. }
  1327. //
  1328. // Verify that it is a valid location
  1329. //
  1330. if (BufferIndex >= TokenDescriptor->cBuffers)
  1331. {
  1332. DebugLog((DEB_ERROR,"SspGetTokenBufferByIndex: Index out of range for SecBufferDesc\n"));
  1333. return FALSE;
  1334. }
  1335. // DebugLog((DEB_TRACE,"SspGetTokenBufferByIndex: NumberTokens %d\n",TokenDescriptor->cBuffers));
  1336. Buffer = &TokenDescriptor->pBuffers[BufferIndex];
  1337. //
  1338. // If the buffer is readonly and readonly isn't OK,
  1339. // reject the buffer.
  1340. //
  1341. if (!ReadonlyOK && (Buffer->BufferType & SECBUFFER_READONLY))
  1342. {
  1343. DebugLog((DEB_TRACE,"SspGetTokenBufferByIndex: request write on READONLY Token buffer\n"));
  1344. return FALSE;
  1345. }
  1346. //
  1347. // Return the requested information
  1348. //
  1349. if (Buffer->cbBuffer && Buffer->pvBuffer)
  1350. {
  1351. StatusTmp = g_LsaFunctions->MapBuffer(Buffer, Buffer);
  1352. if (!NT_SUCCESS(StatusTmp))
  1353. {
  1354. DebugLog((DEB_ERROR,"SspGetTokenBufferByIndex: Unable to MapBuffer 0x%x\n", StatusTmp));
  1355. return FALSE;
  1356. }
  1357. }
  1358. *Token = Buffer;
  1359. return TRUE;
  1360. }
  1361. // determine strlen for a counted string buffer which may or may not be terminated
  1362. size_t strlencounted(const char *string,
  1363. size_t maxcnt)
  1364. {
  1365. size_t cnt = 0;
  1366. if (maxcnt <= 0)
  1367. {
  1368. return 0;
  1369. }
  1370. while (maxcnt--)
  1371. {
  1372. if (!*string)
  1373. {
  1374. break;
  1375. }
  1376. cnt++;
  1377. string++;
  1378. }
  1379. return cnt;
  1380. }
  1381. // determine strlen for a counted string buffer which may or may not be terminated
  1382. // maxcnt is the max number of BYTES (so number of unicode chars is 1/2 the maxcnt)
  1383. size_t ustrlencounted(const short *string,
  1384. size_t maxcnt)
  1385. {
  1386. size_t cnt = 0;
  1387. if (maxcnt <= 0)
  1388. {
  1389. return 0;
  1390. }
  1391. maxcnt = maxcnt / 2; // determine number of unicode characters to search
  1392. while (maxcnt--)
  1393. {
  1394. if (!*string)
  1395. {
  1396. break;
  1397. }
  1398. cnt++;
  1399. string++;
  1400. }
  1401. return cnt;
  1402. }
  1403. // Performs a Backslash encoding of the source string into the destination string per RFC 2831
  1404. // Section 7.2 and RFC 2616 sect 2.2
  1405. NTSTATUS BackslashEncodeString(IN PSTRING pstrSrc, OUT PSTRING pstrDst)
  1406. {
  1407. NTSTATUS Status = S_OK;
  1408. USHORT uCharsMax = 0;
  1409. PCHAR pcSrc = NULL;
  1410. PCHAR pcDst = NULL;
  1411. USHORT uCharsUsed = 0;
  1412. USHORT uCharSrcCnt = 0;
  1413. StringFree(pstrDst);
  1414. if (!pstrSrc || !pstrDst || !pstrSrc->Length)
  1415. {
  1416. return S_OK;
  1417. }
  1418. uCharsMax = pstrSrc->Length * 2; // Max size if each character needs to be encoded
  1419. Status = StringAllocate(pstrDst, uCharsMax);
  1420. if (!NT_SUCCESS(Status))
  1421. {
  1422. DebugLog((DEB_ERROR,"BackshlashEncodeString: String allocation failed 0x%x\n", Status));
  1423. goto CleanUp;
  1424. }
  1425. // now map over each character - encode as necessary
  1426. pcSrc = pstrSrc->Buffer;
  1427. pcDst = pstrDst->Buffer;
  1428. while (uCharSrcCnt < pstrSrc->Length)
  1429. {
  1430. switch (*pcSrc)
  1431. {
  1432. case CHAR_DQUOTE:
  1433. case CHAR_BACKSLASH:
  1434. *pcDst++ = CHAR_BACKSLASH;
  1435. *pcDst++ = *pcSrc++;
  1436. uCharsUsed+= 2;
  1437. break;
  1438. default:
  1439. *pcDst++ = *pcSrc++;
  1440. uCharsUsed++;
  1441. break;
  1442. }
  1443. uCharSrcCnt++;
  1444. }
  1445. pstrDst->Length = uCharsUsed;
  1446. CleanUp:
  1447. return Status;
  1448. }
  1449. // Print out the date and time from a given TimeStamp (converted to localtime)
  1450. NTSTATUS PrintTimeString(TimeStamp ConvertTime, BOOL fLocalTime)
  1451. {
  1452. NTSTATUS Status = STATUS_SUCCESS;
  1453. LARGE_INTEGER LocalTime;
  1454. LARGE_INTEGER SystemTime;
  1455. SystemTime = (LARGE_INTEGER)ConvertTime;
  1456. LocalTime.HighPart = 0;
  1457. LocalTime.LowPart = 0;
  1458. if (ConvertTime.HighPart == 0x7FFFFFFF)
  1459. {
  1460. DebugLog((DEB_TRACE, "PrintTimeString: Never ends\n"));
  1461. }
  1462. if (fLocalTime)
  1463. {
  1464. Status = RtlSystemTimeToLocalTime( &SystemTime, &LocalTime );
  1465. if (!NT_SUCCESS( Status )) {
  1466. DebugLog((DEB_ERROR, "PrintTimeString: Can't convert time from GMT to Local time\n"));
  1467. LocalTime = ConvertTime;
  1468. }
  1469. }
  1470. else
  1471. {
  1472. LocalTime = ConvertTime;
  1473. }
  1474. TIME_FIELDS TimeFields;
  1475. RtlTimeToTimeFields( &LocalTime, &TimeFields );
  1476. DebugLog((DEB_TRACE, "PrintTimeString: %ld/%ld/%ld %ld:%2.2ld:%2.2ld\n",
  1477. TimeFields.Month,
  1478. TimeFields.Day,
  1479. TimeFields.Year,
  1480. TimeFields.Hour,
  1481. TimeFields.Minute,
  1482. TimeFields.Second));
  1483. return Status;
  1484. }
  1485. // Printout the Hex representation of a buffer
  1486. NTSTATUS MyPrintBytes(void *pbuff, USHORT uNumBytes, PSTRING pstrOutput)
  1487. {
  1488. NTSTATUS Status = STATUS_SUCCESS;
  1489. USHORT uNumTotal = 0;
  1490. PCHAR pctr = NULL;
  1491. PCHAR pOut = NULL;
  1492. USHORT i = 0;
  1493. // Each byte will be encoded as XX <sp>
  1494. uNumTotal = (uNumBytes * 3) + 1;
  1495. StringFree(pstrOutput);
  1496. Status = StringAllocate(pstrOutput, uNumTotal);
  1497. if (!NT_SUCCESS (Status))
  1498. {
  1499. Status = SEC_E_INSUFFICIENT_MEMORY;
  1500. DebugLog((DEB_ERROR, "ContextInit: StringAllocate error 0x%x\n", Status));
  1501. goto CleanUp;
  1502. }
  1503. pOut = (PCHAR)pstrOutput->Buffer;
  1504. for (i = 0, pctr = (PCHAR)pbuff; i < uNumBytes; i++)
  1505. {
  1506. sprintf(pOut, "%02x ", (*pctr & 0xff));
  1507. pOut += 3;
  1508. pctr++;
  1509. }
  1510. pstrOutput->Length = uNumBytes * 3;
  1511. CleanUp:
  1512. return Status;
  1513. }