Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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