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.

2122 lines
66 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 2000
  6. //
  7. // File: krnlapi.cxx
  8. //
  9. // Contents: Kernel-mode APIs to the WDigest security packageSSP
  10. // Main kernel mode entry points into this dll:
  11. // WDigestInitKernelPackage,
  12. // WDigestDeleteKernelContext,
  13. // WDigestInitKernelContext,
  14. // WDigestMapKernelHandle,
  15. // WDigestMakeSignature,
  16. // WDigestVerifySignature,
  17. // WDigestSealMessage,
  18. // WDigestUnsealMessage,
  19. // WDigestGetContextToken,
  20. // WDigestQueryContextAttributes,
  21. // WDigestCompleteToken,
  22. // WDigestExportSecurityContext,
  23. // WDigestImportSecurityContext,
  24. // WDigestSetPagingMode
  25. //
  26. // Helper functions:
  27. //
  28. //
  29. //
  30. // History: KDamour 18Mar00 Based on NTLM's kernel mode functions
  31. // We could merge the digest processing parameters into unified code for longhorn
  32. //
  33. //------------------------------------------------------------------------
  34. #include "..\global.h"
  35. #include "krnldgst.h"
  36. #include <stdio.h> // For sprintf
  37. #if defined (_MSC_VER)
  38. #if _MSC_VER >= 1200
  39. #pragma warning(push)
  40. #endif
  41. #pragma warning(disable:4201) // Disable warning/error for nameless struct/union
  42. #endif
  43. extern "C"
  44. {
  45. #include <ntosp.h>
  46. // #include <ntlsa.h>
  47. // #include <ntsam.h>
  48. }
  49. #if defined (_MSC_VER) && ( _MSC_VER >= 800 )
  50. #if _MSC_VER >= 1200
  51. #pragma warning(pop)
  52. #else
  53. #pragma warning(default:4201) // Disable warning/error for nameless struct/union
  54. #endif
  55. #endif
  56. SECPKG_KERNEL_FUNCTION_TABLE WDigestFunctionTable = {
  57. WDigestInitKernelPackage,
  58. WDigestDeleteKernelContext,
  59. WDigestInitKernelContext,
  60. WDigestMapKernelHandle,
  61. WDigestMakeSignature,
  62. WDigestVerifySignature,
  63. WDigestSealMessage,
  64. WDigestUnsealMessage,
  65. WDigestGetContextToken,
  66. WDigestQueryContextAttributes,
  67. WDigestCompleteToken,
  68. WDigestExportSecurityContext,
  69. WDigestImportSecurityContext,
  70. WDigestSetPagingMode
  71. };
  72. #ifdef ALLOC_PRAGMA
  73. #pragma alloc_text(PAGE, WDigestInitKernelPackage)
  74. #pragma alloc_text(PAGE, WDigestDeleteKernelContext)
  75. #pragma alloc_text(PAGE, WDigestInitKernelContext)
  76. #pragma alloc_text(PAGE, WDigestMapKernelHandle)
  77. #pragma alloc_text(PAGEMSG, WDigestMakeSignature)
  78. #pragma alloc_text(PAGEMSG, WDigestVerifySignature)
  79. #pragma alloc_text(PAGEMSG, WDigestSealMessage)
  80. #pragma alloc_text(PAGEMSG, WDigestUnsealMessage)
  81. #pragma alloc_text(PAGEMSG, WDigestGetContextToken)
  82. #pragma alloc_text(PAGEMSG, WDigestQueryContextAttributes)
  83. #pragma alloc_text(PAGEMSG, WDigestDerefContext )
  84. #pragma alloc_text(PAGE, WDigestCompleteToken)
  85. #pragma alloc_text(PAGE, WDigestExportSecurityContext)
  86. #pragma alloc_text(PAGE, WDigestImportSecurityContext)
  87. #pragma alloc_text(PAGEMSG, WDigestFreeKernelContext )
  88. #endif
  89. PSECPKG_KERNEL_FUNCTIONS g_LsaKernelFunctions = NULL;
  90. POOL_TYPE WDigestPoolType = PagedPool;
  91. PVOID WDigestPagedList = NULL;
  92. PVOID WDigestNonPagedList = NULL;
  93. PVOID WDigestActiveList = NULL;
  94. ULONG WDigestPackageId = 0;
  95. //+-------------------------------------------------------------------------
  96. //
  97. // Function: WDigestInitKernelPackage
  98. //
  99. // Synopsis: Initialize an instance of the WDigest package in
  100. // a client's (kernel) address space
  101. //
  102. // Arguments: None
  103. //
  104. // Returns: STATUS_SUCCESS
  105. //
  106. // Notes:
  107. //
  108. //--------------------------------------------------------------------------
  109. NTSTATUS NTAPI
  110. WDigestInitKernelPackage(
  111. IN PSECPKG_KERNEL_FUNCTIONS KernelFunctions
  112. )
  113. {
  114. NTSTATUS Status = STATUS_SUCCESS;
  115. PAGED_CODE();
  116. DebugLog(( DEB_TRACE, "Entering WDigestInitKernelPackage\n" ));
  117. g_LsaKernelFunctions = KernelFunctions;
  118. //
  119. // Set up Context list support:
  120. //
  121. WDigestPoolType = PagedPool ;
  122. WDigestPagedList = g_LsaKernelFunctions->CreateContextList( KSecPaged );
  123. if ( !WDigestPagedList )
  124. {
  125. return STATUS_NO_MEMORY ;
  126. }
  127. WDigestActiveList = WDigestPagedList;
  128. DebugLog(( DEB_TRACE, "Leaving WDigestInitKernelPackage 0x%lx\n", Status ));
  129. return(Status);
  130. }
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Function: WDigestDeleteKernelContext
  134. //
  135. // Synopsis: Deletes a kernel mode context by unlinking it and then
  136. // dereferencing it.
  137. //
  138. // Effects:
  139. //
  140. // Arguments: KernelContextHandle - Kernel context handle of the context to delete
  141. // LsaContextHandle - The Lsa mode handle
  142. //
  143. // Requires:
  144. //
  145. // Returns: STATUS_SUCCESS on success, STATUS_INVALID_HANDLE if the
  146. // context can't be located
  147. //
  148. // Notes:
  149. //
  150. //
  151. //--------------------------------------------------------------------------
  152. NTSTATUS NTAPI
  153. WDigestDeleteKernelContext(
  154. IN ULONG_PTR pKernelContextHandle,
  155. OUT PULONG_PTR pLsaContextHandle
  156. )
  157. {
  158. PDIGEST_KERNELCONTEXT pContext = NULL;
  159. NTSTATUS Status = STATUS_SUCCESS;
  160. PAGED_CODE();
  161. DebugLog(( DEB_TRACE, "WDigestDeleteKernelContext: Entering\n" ));
  162. Status = WDigestReferenceContext( pKernelContextHandle, TRUE );
  163. if ( NT_SUCCESS( Status ) )
  164. {
  165. pContext = (PDIGEST_KERNELCONTEXT) pKernelContextHandle ;
  166. }
  167. else
  168. {
  169. *pLsaContextHandle = pKernelContextHandle;
  170. DebugLog(( DEB_ERROR,
  171. "WDigestDeleteKernelContext: Bad kernel context 0x%lx\n", pKernelContextHandle));
  172. goto CleanUp;
  173. }
  174. *pLsaContextHandle = pContext->LsaContext;
  175. CleanUp:
  176. if (pContext != NULL)
  177. {
  178. WDigestDerefContext( pContext );
  179. }
  180. DebugLog(( DEB_TRACE, "WDigestDeleteKernelContext: Leaving 0x%lx\n", Status ));
  181. return(Status);
  182. }
  183. //+---------------------------------------------------------------------------
  184. //
  185. // Function: WDigestDerefContext
  186. //
  187. // Synopsis: Dereference a kernel context
  188. //
  189. // Arguments: [Context] --
  190. //
  191. // History: 7-07-98 RichardW Created
  192. //
  193. // Notes:
  194. //
  195. //----------------------------------------------------------------------------
  196. VOID
  197. WDigestDerefContext(
  198. PDIGEST_KERNELCONTEXT pContext
  199. )
  200. {
  201. BOOLEAN Delete ;
  202. MAYBE_PAGED_CODE();
  203. KSecDereferenceListEntry(
  204. &pContext->List,
  205. &Delete );
  206. if ( Delete )
  207. {
  208. WDigestFreeKernelContext( pContext );
  209. }
  210. }
  211. //+-------------------------------------------------------------------------
  212. //
  213. // Function: WDigestFreeKernelContext
  214. //
  215. // Synopsis: frees alloced pointers in this context and
  216. // then frees the context
  217. //
  218. // Arguments: KernelContext - the unlinked kernel context
  219. //
  220. // Returns: STATUS_SUCCESS on success
  221. //
  222. // Notes:
  223. //
  224. //--------------------------------------------------------------------------
  225. NTSTATUS
  226. WDigestFreeKernelContext (
  227. PDIGEST_KERNELCONTEXT pKernelContext
  228. )
  229. {
  230. NTSTATUS Status = STATUS_SUCCESS;
  231. int i = 0;
  232. MAYBE_PAGED_CODE();
  233. DebugLog(( DEB_TRACE, "WDigestFreeKernelContext: Entering\n" ));
  234. if (!pKernelContext)
  235. {
  236. Status = STATUS_INVALID_PARAMETER;
  237. goto CleanUp;
  238. }
  239. if (pKernelContext->ClientTokenHandle)
  240. {
  241. NTSTATUS IgnoreStatus;
  242. IgnoreStatus = NtClose(pKernelContext->ClientTokenHandle);
  243. // ASSERT (NT_SUCCESS (IgnoreStatus));
  244. if (!NT_SUCCESS(IgnoreStatus))
  245. {
  246. DebugLog((DEB_ERROR, "WDigestFreeKernelContext: Could not Close the TokenHandle!!!!\n"));
  247. }
  248. pKernelContext->ClientTokenHandle = NULL;
  249. }
  250. StringFree(&(pKernelContext->strSessionKey));
  251. UnicodeStringFree(&(pKernelContext->ustrAccountName));
  252. //
  253. // Values utilized in the Initial Digest Auth ChallResponse
  254. // Can be utilized for defaults in future MakeSignature/VerifySignature
  255. //
  256. for (i=0; i < MD5_AUTH_LAST; i++)
  257. {
  258. StringFree(&(pKernelContext->strParam[i]));
  259. }
  260. DebugLog(( DEB_TRACE, "WDigestFreeKernelContext: Deleting Context 0x%lx\n", pKernelContext));
  261. DigestFreeMemory(pKernelContext);
  262. CleanUp:
  263. DebugLog(( DEB_TRACE, "WDigestFreeKernelContext: Leaving 0x%lx\n", Status ));
  264. return Status;
  265. }
  266. //+-------------------------------------------------------------------------
  267. //
  268. // Function: WDigestInitKernelContext
  269. //
  270. // Synopsis: Creates a kernel-mode context from a packed LSA mode context
  271. //
  272. // Arguments: LsaContextHandle - Lsa mode context handle for the context
  273. // PackedContext - A marshalled buffer containing the LSA
  274. // mode context.
  275. //
  276. // Requires:
  277. //
  278. // Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
  279. //
  280. // Notes:
  281. //
  282. //--------------------------------------------------------------------------
  283. NTSTATUS NTAPI
  284. WDigestInitKernelContext(
  285. IN ULONG_PTR LsaContextHandle,
  286. IN PSecBuffer PackedContext,
  287. OUT PULONG_PTR NewContextHandle
  288. )
  289. {
  290. NTSTATUS Status = STATUS_SUCCESS;
  291. PDIGEST_KERNELCONTEXT pContext = NULL;
  292. PDIGEST_PACKED_USERCONTEXT pPackedUserContext = NULL;
  293. PAGED_CODE();
  294. DebugLog(( DEB_TRACE, "WDigestInitKernelContext: Entering\n" ));
  295. *NewContextHandle = NULL;
  296. if (PackedContext->cbBuffer < sizeof(DIGEST_PACKED_USERCONTEXT))
  297. {
  298. Status = STATUS_INVALID_PARAMETER;
  299. DebugLog(( DEB_ERROR,
  300. "WDigestInitKernelContext: Bad size of Packed context 0x%lx\n", PackedContext->cbBuffer));
  301. goto CleanUp;
  302. }
  303. pPackedUserContext = (PDIGEST_PACKED_USERCONTEXT) DigestAllocateMemory(PackedContext->cbBuffer);
  304. if (!pPackedUserContext)
  305. {
  306. Status = STATUS_INSUFFICIENT_RESOURCES;
  307. DebugLog((DEB_ERROR, "WDigestInitKernelContext: DigestAllocateMemory for Packed Copy returns NULL\n" ));
  308. goto CleanUp;
  309. }
  310. // Copy the Packed User Context from LSA to local memory so it wil be long word aligned
  311. memcpy(pPackedUserContext, PackedContext->pvBuffer, PackedContext->cbBuffer);
  312. // Now we will unpack this transfered LSA context into UserMode space Context List
  313. pContext = (PDIGEST_KERNELCONTEXT) DigestAllocateMemory( sizeof(DIGEST_KERNELCONTEXT) );
  314. if (!pContext)
  315. {
  316. Status = STATUS_INSUFFICIENT_RESOURCES;
  317. DebugLog((DEB_ERROR, "WDigestInitKernelContext: DigestAllocateMemory returns NULL\n" ));
  318. goto CleanUp;
  319. }
  320. KsecInitializeListEntry( &pContext->List, WDIGEST_CONTEXT_SIGNATURE );
  321. pContext->LsaContext = LsaContextHandle;
  322. Status = DigestKernelUnpackContext(pPackedUserContext, pContext);
  323. if (!NT_SUCCESS(Status))
  324. {
  325. DebugLog((DEB_ERROR, "WDigestInitKernelContext: DigestUnpackContext error 0x%x\n", Status));
  326. goto CleanUp;
  327. }
  328. KernelContextPrint(pContext);
  329. KSecInsertListEntry(
  330. WDigestActiveList,
  331. &pContext->List );
  332. WDigestDerefContext( pContext );
  333. *NewContextHandle = (ULONG_PTR) pContext;
  334. CleanUp:
  335. if (!NT_SUCCESS(Status))
  336. {
  337. if (pContext != NULL)
  338. {
  339. WDigestFreeKernelContext( pContext );
  340. }
  341. }
  342. if (pPackedUserContext)
  343. {
  344. DigestFreeMemory(pPackedUserContext);
  345. pPackedUserContext = NULL;
  346. }
  347. if (PackedContext->pvBuffer != NULL)
  348. {
  349. g_LsaKernelFunctions->FreeHeap(PackedContext->pvBuffer);
  350. PackedContext->pvBuffer = NULL;
  351. PackedContext->cbBuffer = 0;
  352. }
  353. DebugLog(( DEB_TRACE, "WDigestInitKernelContext: Leaving status 0x%lx\n", Status ));
  354. return(Status);
  355. }
  356. // Unpack the context from LSA mode into the User mode Context
  357. NTSTATUS DigestKernelUnpackContext(
  358. IN PDIGEST_PACKED_USERCONTEXT pPackedUserContext,
  359. OUT PDIGEST_KERNELCONTEXT pContext)
  360. {
  361. NTSTATUS Status = STATUS_SUCCESS;
  362. PUCHAR pucLoc = NULL;
  363. USHORT uNumWChars = 0;
  364. int iAuth = 0;
  365. DebugLog((DEB_TRACE_FUNC, "DigestKernelUnpackContext: Entering\n"));
  366. ASSERT(pContext);
  367. //
  368. // If TokenHandle is NULL, we are being called as
  369. // as an effect of InitializeSecurityContext, else we are
  370. // being called because of AcceptSecurityContext
  371. //
  372. if (pPackedUserContext->ClientTokenHandle != NULL)
  373. {
  374. Status = STATUS_NOT_SUPPORTED;
  375. // put support here for ASC calls
  376. DebugLog((DEB_ERROR, "DigestKernelUnpackContext: ASC contexts not supported\n" ));
  377. goto CleanUp;
  378. }
  379. else
  380. {
  381. DebugLog((DEB_TRACE, "DigestUnpackContext: Called from ISC\n" ));
  382. }
  383. //
  384. // Copy over all of the other fields - some data might be binary so
  385. // use RtlCopyMemory(Dest, Src, len)
  386. //
  387. pContext->ExpirationTime = pPackedUserContext->ExpirationTime;
  388. pContext->typeAlgorithm = (ALGORITHM_TYPE)pPackedUserContext->typeAlgorithm;
  389. pContext->typeCharset = (CHARSET_TYPE)pPackedUserContext->typeCharset;
  390. pContext->typeCipher = (CIPHER_TYPE)pPackedUserContext->typeCipher;
  391. pContext->typeDigest = (DIGEST_TYPE)pPackedUserContext->typeDigest;
  392. pContext->typeQOP = (QOP_TYPE)pPackedUserContext->typeQOP;
  393. pContext->ulSendMaxBuf = pPackedUserContext->ulSendMaxBuf;
  394. pContext->ulRecvMaxBuf = pPackedUserContext->ulRecvMaxBuf;
  395. pContext->ulNC = 1; // Force to one to account for ISC/ASC first message verify
  396. pContext->lReferences = 1;
  397. pContext->ContextReq = pPackedUserContext->ContextReq;
  398. pContext->CredentialUseFlags = pPackedUserContext->CredentialUseFlags;
  399. pContext->ulFlags = pPackedUserContext->ulFlags;
  400. // Now check on the strings attached
  401. pucLoc = &(pPackedUserContext->ucData);
  402. for (iAuth = 0; iAuth < MD5_AUTH_LAST; iAuth++)
  403. {
  404. if (pPackedUserContext->uDigestLen[iAuth])
  405. {
  406. Status = StringAllocate(&(pContext->strParam[iAuth]), (USHORT)pPackedUserContext->uDigestLen[iAuth]);
  407. if (!NT_SUCCESS(Status))
  408. {
  409. Status = STATUS_INSUFFICIENT_RESOURCES;
  410. DebugLog((DEB_ERROR, "DigestKernelUnpackContext: DigestAllocateMemory for Params returns NULL\n" ));
  411. goto CleanUp;
  412. }
  413. memcpy(pContext->strParam[iAuth].Buffer, pucLoc, (USHORT)pPackedUserContext->uDigestLen[iAuth]);
  414. pContext->strParam[iAuth].Length = (USHORT)pPackedUserContext->uDigestLen[iAuth];
  415. pucLoc += (USHORT)pPackedUserContext->uDigestLen[iAuth];
  416. DebugLog((DEB_TRACE, "DigestKernelUnpackContext: Param[%d] is length %d - %.50s\n",
  417. iAuth, pPackedUserContext->uDigestLen[iAuth], pContext->strParam[iAuth].Buffer ));
  418. }
  419. }
  420. // Now do the SessionKey
  421. if (pPackedUserContext->uSessionKeyLen)
  422. {
  423. ASSERT(pPackedUserContext->uSessionKeyLen == MD5_HASH_HEX_SIZE);
  424. if (pPackedUserContext->uSessionKeyLen != MD5_HASH_HEX_SIZE)
  425. {
  426. Status = STATUS_NO_USER_SESSION_KEY;
  427. DebugLog((DEB_ERROR, "DigestUnpackContext: Session key length incorrect\n" ));
  428. goto CleanUp;
  429. }
  430. Status = StringAllocate(&(pContext->strSessionKey), (USHORT)pPackedUserContext->uSessionKeyLen);
  431. if (!NT_SUCCESS(Status))
  432. {
  433. Status = STATUS_INSUFFICIENT_RESOURCES;
  434. DebugLog((DEB_ERROR, "DigestUnpackContext: DigestAllocateMemory for SessionKey returns NULL\n" ));
  435. goto CleanUp;
  436. }
  437. memcpy(pContext->strSessionKey.Buffer, pucLoc, pPackedUserContext->uSessionKeyLen);
  438. pContext->strSessionKey.Length = (USHORT)pPackedUserContext->uSessionKeyLen;
  439. pucLoc += (USHORT)pPackedUserContext->uSessionKeyLen;
  440. // Now determine the binary version of the SessionKey from HEX() version
  441. HexToBin(pContext->strSessionKey.Buffer, MD5_HASH_HEX_SIZE, pContext->bSessionKey);
  442. }
  443. // Now do the AccountName
  444. if (pPackedUserContext->uAccountNameLen)
  445. {
  446. uNumWChars = (USHORT)pPackedUserContext->uAccountNameLen / sizeof(WCHAR);
  447. Status = UnicodeStringAllocate(&(pContext->ustrAccountName), uNumWChars);
  448. if (!NT_SUCCESS(Status))
  449. {
  450. Status = STATUS_INSUFFICIENT_RESOURCES;
  451. DebugLog((DEB_ERROR, "DigestKernelUnpackContext: DigestAllocateMemory for AccountName returns NULL\n" ));
  452. goto CleanUp;
  453. }
  454. memcpy(pContext->ustrAccountName.Buffer, pucLoc, pPackedUserContext->uAccountNameLen);
  455. pContext->ustrAccountName.Length = (USHORT)pPackedUserContext->uAccountNameLen;
  456. pucLoc += (USHORT)pPackedUserContext->uAccountNameLen;
  457. }
  458. CleanUp:
  459. DebugLog((DEB_TRACE_FUNC, "DigestKernelUnpackContext: Leaving Status 0x%x\n", Status));
  460. return(Status);
  461. }
  462. //+-------------------------------------------------------------------------
  463. //
  464. // Function: DigestAllocateMemory
  465. //
  466. // Synopsis: Allocate memory in kernel mode
  467. //
  468. // Effects: Allocated chunk is zeroed out
  469. //
  470. // Arguments:
  471. //
  472. // Requires:
  473. //
  474. // Returns:
  475. //
  476. // Notes: Replacements for functions in SSP but for kernel mode
  477. //
  478. //--------------------------------------------------------------------------
  479. PVOID
  480. DigestAllocateMemory(
  481. IN ULONG BufferSize
  482. )
  483. {
  484. PVOID Buffer = NULL;
  485. // DebugLog((DEB_TRACE, "Entering DigestAllocateMemory\n"));
  486. Buffer = WDigestKAllocate(BufferSize);
  487. if (Buffer)
  488. {
  489. ZeroMemory(Buffer, BufferSize);
  490. }
  491. DebugLog((DEB_TRACE_MEM, "Memory: Local alloc %lu bytes at 0x%x\n", BufferSize, Buffer ));
  492. // DebugLog((DEB_TRACE, "Leaving DigestAllocateMemory\n"));
  493. return Buffer;
  494. }
  495. //+-------------------------------------------------------------------------
  496. //
  497. // Function: DigestFreeMemory
  498. //
  499. // Synopsis: Free memory in kernel mode
  500. //
  501. // Effects:
  502. //
  503. // Arguments:
  504. //
  505. // Requires:
  506. //
  507. // Returns:
  508. //
  509. // Notes:
  510. //
  511. //
  512. //--------------------------------------------------------------------------
  513. VOID
  514. DigestFreeMemory(
  515. IN PVOID Buffer
  516. )
  517. {
  518. // DebugLog((DEB_TRACE, "Entering DigestFreeMemory\n"));
  519. if (ARGUMENT_PRESENT(Buffer))
  520. {
  521. DebugLog((DEB_TRACE_MEM, "DigestFreeMemory: Local free at 0x%x\n", Buffer ));
  522. WDigestKFree(Buffer);
  523. }
  524. // DebugLog((DEB_TRACE, "Leaving DigestFreeMemory\n"));
  525. }
  526. //+-------------------------------------------------------------------------
  527. //
  528. // Function: WDigestMapKernelHandle
  529. //
  530. // Synopsis: Maps a kernel handle into an LSA handle
  531. //
  532. // Arguments: KernelContextHandle - Kernel context handle of the context to map
  533. // LsaContextHandle - Receives LSA context handle of the context
  534. // to map
  535. //
  536. // Returns: STATUS_SUCCESS on success
  537. //
  538. // Notes:
  539. //
  540. //--------------------------------------------------------------------------
  541. NTSTATUS NTAPI
  542. WDigestMapKernelHandle(
  543. IN ULONG_PTR KernelContextHandle,
  544. OUT PULONG_PTR LsaContextHandle
  545. )
  546. {
  547. NTSTATUS Status = STATUS_SUCCESS;
  548. PDIGEST_KERNELCONTEXT pContext = NULL;
  549. PAGED_CODE();
  550. DebugLog((DEB_TRACE,"WDigestMapKernelHandle: Entering\n"));
  551. Status = WDigestReferenceContext( KernelContextHandle, FALSE );
  552. if ( NT_SUCCESS( Status ) )
  553. {
  554. pContext = (PDIGEST_KERNELCONTEXT) KernelContextHandle ;
  555. *LsaContextHandle = pContext->LsaContext ;
  556. WDigestDerefContext( pContext );
  557. }
  558. else
  559. {
  560. DebugLog(( DEB_WARN, "WDigestMapKernelHandle: Invalid context handle - %x\n",
  561. KernelContextHandle ));
  562. *LsaContextHandle = KernelContextHandle ;
  563. }
  564. DebugLog((DEB_TRACE,"WDigestMapKernelHandle: Leaving 0x%lx\n", Status));
  565. return (Status);
  566. }
  567. //+-------------------------------------------------------------------------
  568. //
  569. // Function: WDigestMakeSignature
  570. //
  571. // Synopsis: Computes the Digest Auth response and and creates challengeResponse
  572. //
  573. // Effects:
  574. //
  575. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  576. // message.
  577. // QualityOfProtection - Unused flags.
  578. // MessageBuffers - Contains an array of buffers to sign and
  579. // to store the signature.
  580. // MessageSequenceNumber - Sequence number for this message,
  581. // only used in datagram cases.
  582. //
  583. // Returns: STATUS_INVALID_HANDLE - the context could not be found or
  584. // was not configured for message integrity.
  585. // STATUS_INVALID_PARAMETER - the signature buffer could not
  586. // be found.
  587. // STATUS_BUFFER_TOO_SMALL - the signature buffer is too small
  588. // to hold the signature
  589. //
  590. // STATUS_SUCCESS - completed normally
  591. //
  592. // Notes:
  593. //
  594. //
  595. //--------------------------------------------------------------------------
  596. NTSTATUS NTAPI
  597. WDigestMakeSignature(
  598. IN ULONG_PTR KernelContextHandle,
  599. IN ULONG fQOP,
  600. IN PSecBufferDesc pMessage,
  601. IN ULONG MessageSeqNo
  602. )
  603. {
  604. NTSTATUS Status = STATUS_SUCCESS;
  605. PDIGEST_KERNELCONTEXT pContext = NULL;
  606. MAYBE_PAGED_CODE();
  607. DebugLog(( DEB_TRACE, "WDigestMakeSignature: Entering\n" ));
  608. UNREFERENCED_PARAMETER(fQOP);
  609. Status = WDigestReferenceContext( KernelContextHandle, FALSE );
  610. if ( NT_SUCCESS( Status ) )
  611. {
  612. pContext = (PDIGEST_KERNELCONTEXT) KernelContextHandle ;
  613. }
  614. else
  615. {
  616. DebugLog(( DEB_ERROR,
  617. "WDigestMakeSignature: Bad kernel context 0x%lx\n", KernelContextHandle));
  618. goto CleanUp_NoDeref;
  619. }
  620. // Since we are in UserMode we MUST have a sessionkey to use - if not then can not process
  621. if (!pContext->strSessionKey.Length)
  622. {
  623. Status = STATUS_NO_USER_SESSION_KEY;
  624. DebugLog((DEB_ERROR, "WDigestMakeSignature: No Session Key contained in UserContext\n"));
  625. goto CleanUp;
  626. }
  627. Status = DigestKernelHTTPHelper(
  628. pContext,
  629. eSign,
  630. pMessage,
  631. MessageSeqNo
  632. );
  633. if( !NT_SUCCESS( Status ) )
  634. {
  635. DebugLog(( DEB_ERROR, "WDigestMakeSignature: SspSignSealHelper returns %lx\n", Status ));
  636. goto CleanUp;
  637. }
  638. CleanUp:
  639. WDigestDerefContext( pContext );
  640. CleanUp_NoDeref:
  641. DebugLog(( DEB_TRACE, "WDigestMakeSignature: Leaving 0x%lx\n", Status ));
  642. return(Status);
  643. }
  644. //+-------------------------------------------------------------------------
  645. //
  646. // Function: WDigestVerifySignature
  647. //
  648. // Synopsis: Verifies a a challengeResponse on a server (not implemented in kernel mode)
  649. //
  650. // Effects:
  651. //
  652. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  653. // message.
  654. // MessageBuffers - Contains an array of signed buffers and
  655. // a signature buffer.
  656. // MessageSequenceNumber - Sequence number for this message,
  657. // only used in datagram cases.
  658. // QualityOfProtection - Unused flags.
  659. //
  660. // Returns: STATUS_INVALID_HANDLE - the context could not be found or
  661. // was not configured for message integrity.
  662. // STATUS_INVALID_PARAMETER - the signature buffer could not
  663. // be found or was too small.
  664. //
  665. // Notes:
  666. //
  667. //
  668. //--------------------------------------------------------------------------
  669. NTSTATUS NTAPI
  670. WDigestVerifySignature(
  671. IN ULONG_PTR KernelContextHandle,
  672. IN PSecBufferDesc pMessage,
  673. IN ULONG MessageSeqNo,
  674. OUT PULONG pfQOP
  675. )
  676. {
  677. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  678. MAYBE_PAGED_CODE();
  679. DebugLog(( DEB_TRACE, "WDigestVerifySignature Entering\n" ));
  680. UNREFERENCED_PARAMETER(KernelContextHandle);
  681. UNREFERENCED_PARAMETER(pMessage);
  682. UNREFERENCED_PARAMETER(MessageSeqNo);
  683. UNREFERENCED_PARAMETER(pfQOP);
  684. DebugLog(( DEB_TRACE, "WDigestVerifySignature: Leaving 0x%lx\n", Status ));
  685. return(Status);
  686. }
  687. //+--------------------------------------------------------------------
  688. //
  689. // Function: DigestKernelHTTPHelper
  690. //
  691. // Synopsis: Process a SecBuffer with a given Kernel Security Context
  692. // Used with HTTP for auth after initial ASC/ISC exchange
  693. //
  694. // Arguments: pContext - KernelMode Context for the security state
  695. // Op - operation to perform on the Sec buffers
  696. // pMessage - sec buffers to processs and return output
  697. //
  698. // Returns: NTSTATUS
  699. //
  700. // Notes:
  701. //
  702. //---------------------------------------------------------------------
  703. NTSTATUS NTAPI
  704. DigestKernelHTTPHelper(
  705. IN PDIGEST_KERNELCONTEXT pContext,
  706. IN eSignSealOp Op,
  707. IN OUT PSecBufferDesc pSecBuff,
  708. IN ULONG MessageSeqNo
  709. )
  710. {
  711. NTSTATUS Status = STATUS_SUCCESS;
  712. ULONG ulSeqNo = 0;
  713. PSecBuffer pChalRspInputToken = NULL;
  714. PSecBuffer pMethodInputToken = NULL;
  715. PSecBuffer pURIInputToken = NULL;
  716. PSecBuffer pHEntityInputToken = NULL;
  717. PSecBuffer pFirstOutputToken = NULL;
  718. DIGEST_PARAMETER Digest;
  719. USHORT usLen = 0;
  720. int iAuth = 0;
  721. char *cptr = NULL;
  722. char szNCOverride[2*NCNUM]; // Overrides the provided NC if non-zero using only NCNUM digits
  723. STRING strURI = {0};
  724. DebugLog((DEB_TRACE, "DigestKernelHTTPHelper: Entering \n"));
  725. Status = DigestInit(&Digest);
  726. if (!NT_SUCCESS(Status))
  727. {
  728. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: Digest init error status 0x%x\n", Status));
  729. goto CleanUp;
  730. }
  731. if (pSecBuff->cBuffers < 1)
  732. {
  733. Status = SEC_E_INVALID_TOKEN;
  734. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: Not enough input buffers 0x%x\n", Status));
  735. goto CleanUp;
  736. }
  737. pChalRspInputToken = &(pSecBuff->pBuffers[0]);
  738. if (!ContextIsTokenOK(pChalRspInputToken, NTDIGEST_SP_MAX_TOKEN_SIZE))
  739. {
  740. Status = SEC_E_INVALID_TOKEN;
  741. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: ContextIsTokenOK (ChalRspInputToken) failed 0x%x\n", Status));
  742. goto CleanUp;
  743. }
  744. // Set any digest processing parameters based on Context
  745. if (pContext->ulFlags & FLAG_CONTEXT_NOBS_DECODE)
  746. {
  747. Digest.usFlags |= FLAG_NOBS_DECODE;
  748. }
  749. // We have input in the SECBUFFER 0th location - parse it
  750. Status = DigestParser2(pChalRspInputToken, MD5_AUTH_NAMES, MD5_AUTH_LAST, &Digest);
  751. if (!NT_SUCCESS(Status))
  752. {
  753. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: DigestParser error 0x%x\n", Status));
  754. goto CleanUp;
  755. }
  756. // Now determine all of the other buffers
  757. DebugLog((DEB_TRACE, "DigestKernelHTTPHelper: pContext->ContextReq 0x%lx \n", pContext->ContextReq));
  758. DebugLog((DEB_TRACE, "DigestKernelHTTPHelper: HTTP SecBuffer Format\n"));
  759. // Retrieve the information from the SecBuffers & check proper formattting
  760. if (pSecBuff->cBuffers < 4)
  761. {
  762. Status = SEC_E_INVALID_TOKEN;
  763. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: Not enough input buffers 0x%x\n", Status));
  764. goto CleanUp;
  765. }
  766. pMethodInputToken = &(pSecBuff->pBuffers[1]);
  767. if (!ContextIsTokenOK(pMethodInputToken, NTDIGEST_SP_MAX_TOKEN_SIZE))
  768. { // Check to make sure that string is present
  769. Status = SEC_E_INVALID_TOKEN;
  770. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: ContextIsTokenOK (MethodInputToken) failed 0x%x\n", Status));
  771. goto CleanUp;
  772. }
  773. pURIInputToken = &(pSecBuff->pBuffers[2]);
  774. if (!ContextIsTokenOK(pURIInputToken, NTDIGEST_SP_MAX_TOKEN_SIZE))
  775. {
  776. Status = SEC_E_INVALID_TOKEN;
  777. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: ContextIsTokenOK (URIInputToken) failed 0x%x\n", Status));
  778. goto CleanUp;
  779. }
  780. pHEntityInputToken = &(pSecBuff->pBuffers[3]);
  781. if (!ContextIsTokenOK(pHEntityInputToken, NTDIGEST_SP_MAX_TOKEN_SIZE))
  782. {
  783. Status = SEC_E_INVALID_TOKEN;
  784. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: ContextIsTokenOK (HEntityInputToken) failed 0x%x\n", Status));
  785. goto CleanUp;
  786. }
  787. // Take care of the output buffer
  788. if (Op == eSign)
  789. {
  790. if (pSecBuff->cBuffers < 5)
  791. {
  792. Status = SEC_E_INVALID_TOKEN;
  793. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: No Output Buffers %d\n", Status));
  794. goto CleanUp;
  795. }
  796. pFirstOutputToken = &(pSecBuff->pBuffers[4]);
  797. if (!ContextIsTokenOK(pFirstOutputToken, 0))
  798. {
  799. Status = SEC_E_INVALID_TOKEN;
  800. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper, ContextIsTokenOK (FirstOutputToken) failed 0x%x\n", Status));
  801. goto CleanUp;
  802. }
  803. // Reset output buffer
  804. if (pFirstOutputToken && (pFirstOutputToken->pvBuffer) && (pFirstOutputToken->cbBuffer >= 1))
  805. {
  806. cptr = (char *)pFirstOutputToken->pvBuffer;
  807. *cptr = '\0';
  808. }
  809. }
  810. else
  811. {
  812. pFirstOutputToken = NULL; // There is no output buffer
  813. }
  814. // Verify that there is a valid Method provided
  815. if (!pMethodInputToken->pvBuffer || !pMethodInputToken->cbBuffer ||
  816. (PBUFFERTYPE(pMethodInputToken) != SECBUFFER_PKG_PARAMS))
  817. {
  818. Status = SEC_E_INVALID_TOKEN;
  819. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: Method SecBuffer must have valid method string status 0x%x\n", Status));
  820. goto CleanUp;
  821. }
  822. usLen = strlencounted((char *)pMethodInputToken->pvBuffer, (USHORT)pMethodInputToken->cbBuffer);
  823. if (!usLen)
  824. {
  825. Status = SEC_E_INVALID_TOKEN;
  826. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: Method SecBuffer must have valid method string status 0x%x\n", Status));
  827. goto CleanUp;
  828. }
  829. Digest.refstrParam[MD5_AUTH_METHOD].Length = usLen;
  830. Digest.refstrParam[MD5_AUTH_METHOD].MaximumLength = (unsigned short)(pMethodInputToken->cbBuffer);
  831. Digest.refstrParam[MD5_AUTH_METHOD].Buffer = (char *)pMethodInputToken->pvBuffer; // refernce memory - no alloc!!!!
  832. // Check to see if we have H(Entity) data to utilize
  833. if (pHEntityInputToken->cbBuffer)
  834. {
  835. // Verify that there is a valid Method provided
  836. if (!pHEntityInputToken->pvBuffer || (PBUFFERTYPE(pMethodInputToken) != SECBUFFER_PKG_PARAMS))
  837. {
  838. Status = SEC_E_INVALID_TOKEN;
  839. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: HEntity SecBuffer must have valid string status 0x%x\n", Status));
  840. goto CleanUp;
  841. }
  842. usLen = strlencounted((char *)pHEntityInputToken->pvBuffer, (USHORT)pHEntityInputToken->cbBuffer);
  843. if ((usLen != 0) && (usLen != (MD5_HASH_BYTESIZE * 2)))
  844. {
  845. Status = SEC_E_INVALID_TOKEN;
  846. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: HEntity SecBuffer must have valid MD5 Hash data 0x%x\n", Status));
  847. goto CleanUp;
  848. }
  849. if (usLen)
  850. {
  851. Digest.refstrParam[MD5_AUTH_HENTITY].Length = usLen;
  852. Digest.refstrParam[MD5_AUTH_HENTITY].MaximumLength = (unsigned short)(pHEntityInputToken->cbBuffer);
  853. Digest.refstrParam[MD5_AUTH_HENTITY].Buffer = (char *)pHEntityInputToken->pvBuffer; // refernce memory - no alloc!!!!
  854. }
  855. }
  856. // Import the URI if it is a sign otherwise verify URI match if verify
  857. if (Op == eSign)
  858. {
  859. // Pull in the URI provided in SecBuffer
  860. if (!pURIInputToken || !pURIInputToken->cbBuffer || !pURIInputToken->pvBuffer)
  861. {
  862. Status = SEC_E_INVALID_TOKEN;
  863. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: URI SecBuffer must have valid string 0x%x\n", Status));
  864. goto CleanUp;
  865. }
  866. if (PBUFFERTYPE(pURIInputToken) == SECBUFFER_PKG_PARAMS)
  867. {
  868. usLen = strlencounted((char *)pURIInputToken->pvBuffer, (USHORT)pURIInputToken->cbBuffer);
  869. if (usLen > 0)
  870. {
  871. Status = StringCharDuplicate(&strURI, (char *)pURIInputToken->pvBuffer, usLen);
  872. if (!NT_SUCCESS(Status))
  873. {
  874. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: StringCharDuplicate error 0x%x\n", Status));
  875. goto CleanUp;
  876. }
  877. }
  878. }
  879. else
  880. {
  881. Status = SEC_E_INVALID_TOKEN;
  882. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: URI buffer type invalid error %d\n", Status));
  883. goto CleanUp;
  884. }
  885. StringReference(&(Digest.refstrParam[MD5_AUTH_URI]), &strURI); // refernce memory - no alloc!!!!
  886. }
  887. // If we have a NonceCount in the MessageSequenceNumber then use that
  888. if (MessageSeqNo)
  889. {
  890. ulSeqNo = MessageSeqNo;
  891. }
  892. else
  893. {
  894. ulSeqNo = pContext->ulNC + 1; // Else use the next sequence number
  895. }
  896. sprintf(szNCOverride, "%0.8x", ulSeqNo); // Buffer is twice as big as we need (for safety) so just clip out first 8 characters
  897. szNCOverride[NCNUM] = '\0'; // clip to 8 digits
  898. DebugLog((DEB_TRACE, "DigestKernelHTTPHelper: Message Sequence NC is %s\n", szNCOverride));
  899. Digest.refstrParam[MD5_AUTH_NC].Length = (USHORT)NCNUM;
  900. Digest.refstrParam[MD5_AUTH_NC].MaximumLength = (unsigned short)(NCNUM+1);
  901. Digest.refstrParam[MD5_AUTH_NC].Buffer = (char *)szNCOverride; // refernce memory - no alloc!!!!
  902. // Now link in the stored context values into the digest if this is a SignMessage
  903. // If there are values there from the input auth line then override them with context's value
  904. if (Op == eSign)
  905. {
  906. for (iAuth = 0; iAuth < MD5_AUTH_LAST; iAuth++)
  907. {
  908. if ((iAuth != MD5_AUTH_URI) &&
  909. (iAuth != MD5_AUTH_HENTITY) &&
  910. (iAuth != MD5_AUTH_METHOD) &&
  911. pContext->strParam[iAuth].Length)
  912. { // Link in only if passed into the user context from the LSA context
  913. Digest.refstrParam[iAuth].Length = pContext->strParam[iAuth].Length;
  914. Digest.refstrParam[iAuth].MaximumLength = pContext->strParam[iAuth].MaximumLength;
  915. Digest.refstrParam[iAuth].Buffer = pContext->strParam[iAuth].Buffer; // reference memory - no alloc!!!!
  916. }
  917. }
  918. }
  919. DebugLog((DEB_TRACE, "DigestKernelHTTPHelper: Digest inputs processing completed\n"));
  920. Status = DigestKernelProcessParameters(pContext, &Digest, pFirstOutputToken);
  921. if (!NT_SUCCESS(Status))
  922. {
  923. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: DigestUserProcessParameters error 0x%x\n", Status));
  924. goto CleanUp;
  925. }
  926. pContext->ulNC = ulSeqNo; // Everything verified so increment to next nonce count
  927. // Keep a copy of the new URI in ChallengeResponse
  928. StringFree(&(pContext->strParam[MD5_AUTH_URI]));
  929. Status = StringDuplicate(&(pContext->strParam[MD5_AUTH_URI]), &(Digest.refstrParam[MD5_AUTH_URI]));
  930. if (!NT_SUCCESS(Status))
  931. {
  932. DebugLog((DEB_ERROR, "DigestKernelHTTPHelper: Failed to copy over new URI\n"));
  933. goto CleanUp;
  934. }
  935. CleanUp:
  936. DigestFree(&Digest);
  937. StringFree(&strURI);
  938. DebugLog((DEB_TRACE, "DigestKernelHTTPHelper: Leaving Status 0x%x\n", Status));
  939. return(Status);
  940. }
  941. //+--------------------------------------------------------------------
  942. //
  943. // Function: DigestKernelProcessParameters
  944. //
  945. // Synopsis: Process the Digest information with the context info
  946. // and generate any output token info
  947. //
  948. // Arguments: pContext - KernelMode Context for the security state
  949. // pDigest - Digest parameters to process into output buffer
  950. // pFirstOutputToken - sec buffers to processs and return output
  951. //
  952. // Returns: NTSTATUS
  953. //
  954. // Notes:
  955. //
  956. //---------------------------------------------------------------------
  957. //
  958. NTSTATUS NTAPI
  959. DigestKernelProcessParameters(
  960. IN PDIGEST_KERNELCONTEXT pContext,
  961. IN PDIGEST_PARAMETER pDigest,
  962. OUT PSecBuffer pFirstOutputToken)
  963. {
  964. NTSTATUS Status = STATUS_SUCCESS;
  965. ULONG ulNonceCount = 0;
  966. DebugLog((DEB_TRACE_FUNC, "DigestKernelProcessParameters: Entering\n"));
  967. // Some common input verification tests
  968. // We must have a noncecount specified since we specified a qop in the Challenge
  969. // If we decide to support no noncecount modes then we need to make sure that qop is not specified
  970. if (pDigest->refstrParam[MD5_AUTH_NC].Length)
  971. {
  972. Status = RtlCharToInteger(pDigest->refstrParam[MD5_AUTH_NC].Buffer, HEXBASE, &ulNonceCount);
  973. if (!NT_SUCCESS(Status))
  974. {
  975. Status = STATUS_INVALID_PARAMETER;
  976. DebugLog((DEB_ERROR, "DigestKernelProcessParameters: Nonce Count badly formatted\n"));
  977. goto CleanUp;
  978. }
  979. }
  980. // Check nonceCount is incremented to preclude replay
  981. if (!(ulNonceCount > pContext->ulNC))
  982. {
  983. // We failed to verify next noncecount
  984. Status = SEC_E_OUT_OF_SEQUENCE;
  985. DebugLog((DEB_ERROR, "DigestKernelProcessParameters: NonceCount failed to increment!\n"));
  986. goto CleanUp;
  987. }
  988. // Since we are in UserMode we MUST have a sessionkey to use - if non then can not process
  989. if (!pContext->strSessionKey.Length)
  990. {
  991. Status = SEC_E_NO_AUTHENTICATING_AUTHORITY; // indicate that we needed a call to ASC or ISC first
  992. DebugLog((DEB_ERROR, "DigestKernelProcessParameters: No Session Key contained in UserContext\n"));
  993. goto CleanUp;
  994. }
  995. // Copy the SessionKey from the Context into the Digest Structure to verify against
  996. // This will have Digest Auth routines use the SessionKey rather than recompute H(A1)
  997. StringFree(&(pDigest->strSessionKey));
  998. Status = StringDuplicate(&(pDigest->strSessionKey), &(pContext->strSessionKey));
  999. if (!NT_SUCCESS(Status))
  1000. {
  1001. DebugLog((DEB_ERROR, "DigestKernelProcessParameters: Failed to copy over SessionKey\n"));
  1002. goto CleanUp;
  1003. }
  1004. // Set the type of Digest Parameters we are to process
  1005. pDigest->typeDigest = pContext->typeDigest;
  1006. pDigest->typeQOP = pContext->typeQOP;
  1007. pDigest->typeAlgorithm = pContext->typeAlgorithm;
  1008. pDigest->typeCharset = pContext->typeCharset;
  1009. if (pContext->ulFlags & FLAG_CONTEXT_QUOTE_QOP)
  1010. {
  1011. pDigest->usFlags |= FLAG_QUOTE_QOP;
  1012. }
  1013. (void)DigestPrint(pDigest);
  1014. // No check locally that Digest is authentic
  1015. Status = DigestCalculation(pDigest, NULL);
  1016. if (!NT_SUCCESS(Status))
  1017. {
  1018. DebugLog((DEB_ERROR, "DigestKernelProcessParameters: Oh no we FAILED Authentication!!!!\n"));
  1019. goto CleanUp;
  1020. }
  1021. // Send to output buffer only if there is an output buffer
  1022. // This allows this routine to be used in UserMode
  1023. if (pFirstOutputToken)
  1024. {
  1025. Status = DigestCreateChalResp(pDigest, NULL, pFirstOutputToken);
  1026. if (!NT_SUCCESS(Status))
  1027. {
  1028. DebugLog((DEB_ERROR, "DigestKernelProcessParameters: Failed to create Output String\n"));
  1029. goto CleanUp;
  1030. }
  1031. }
  1032. CleanUp:
  1033. DebugLog((DEB_TRACE_FUNC, "DigestKernelProcessParameters: Leaving Status 0x%x\n", Status));
  1034. return(Status);
  1035. }
  1036. //+-------------------------------------------------------------------------
  1037. //
  1038. // Function: WDigestSealMessage
  1039. //
  1040. // Synopsis: Not implemented
  1041. //
  1042. // Effects:
  1043. //
  1044. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  1045. // message.
  1046. // MessageBuffers - Contains an array of signed buffers and
  1047. // a signature buffer.
  1048. // MessageSequenceNumber - Sequence number for this message,
  1049. // only used in datagram cases.
  1050. // QualityOfProtection - Unused flags.
  1051. //
  1052. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1053. // was not configured for message integrity.
  1054. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1055. // be found or was too small.
  1056. //
  1057. // Returns:
  1058. //
  1059. // Notes:
  1060. //
  1061. //
  1062. //--------------------------------------------------------------------------
  1063. NTSTATUS NTAPI
  1064. WDigestSealMessage(
  1065. IN ULONG_PTR KernelContextHandle,
  1066. IN ULONG fQOP,
  1067. IN PSecBufferDesc pMessage,
  1068. IN ULONG MessageSeqNo
  1069. )
  1070. {
  1071. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  1072. MAYBE_PAGED_CODE();
  1073. DebugLog(( DEB_TRACE, "WDigestSealMessage: Entering\n" ));
  1074. UNREFERENCED_PARAMETER(KernelContextHandle);
  1075. UNREFERENCED_PARAMETER(fQOP);
  1076. UNREFERENCED_PARAMETER(pMessage);
  1077. UNREFERENCED_PARAMETER(MessageSeqNo);
  1078. DebugLog(( DEB_TRACE, "WDigestSealMessage: Leaving 0x%lx\n", Status ));
  1079. return(Status);
  1080. }
  1081. //+-------------------------------------------------------------------------
  1082. //
  1083. // Function: WDigestUnsealMessage
  1084. //
  1085. // Synopsis: Verifies a signed message buffer by calculating a checksum over all
  1086. // the non-read only data buffers and encrypting the checksum
  1087. // along with a nonce.
  1088. //
  1089. // Effects:
  1090. //
  1091. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  1092. // message.
  1093. // MessageBuffers - Contains an array of signed buffers and
  1094. // a signature buffer.
  1095. // MessageSequenceNumber - Sequence number for this message,
  1096. // only used in datagram cases.
  1097. // QualityOfProtection - Unused flags.
  1098. //
  1099. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1100. // was not configured for message integrity.
  1101. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1102. // be found or was too small.
  1103. //
  1104. // Returns:
  1105. //
  1106. // Notes:
  1107. //
  1108. //
  1109. //--------------------------------------------------------------------------
  1110. NTSTATUS NTAPI
  1111. WDigestUnsealMessage(
  1112. IN ULONG_PTR KernelContextHandle,
  1113. IN PSecBufferDesc pMessage,
  1114. IN ULONG MessageSeqNo,
  1115. OUT PULONG pfQOP
  1116. )
  1117. {
  1118. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  1119. MAYBE_PAGED_CODE();
  1120. DebugLog(( DEB_TRACE, "WDigestUnsealMessage: Entering\n" ));
  1121. UNREFERENCED_PARAMETER(KernelContextHandle);
  1122. UNREFERENCED_PARAMETER(pMessage);
  1123. UNREFERENCED_PARAMETER(MessageSeqNo);
  1124. UNREFERENCED_PARAMETER(pfQOP);
  1125. DebugLog(( DEB_TRACE, "WDigestUnsealMessage: Leaving 0x%lx\n", Status ));
  1126. return (Status);
  1127. }
  1128. //+-------------------------------------------------------------------------
  1129. //
  1130. // Function: WDigestGetContextToken
  1131. //
  1132. // Synopsis: returns a pointer to the token for a server-side context
  1133. //
  1134. // Effects:
  1135. //
  1136. // Arguments:
  1137. //
  1138. // Requires:
  1139. //
  1140. // Returns:
  1141. //
  1142. // Notes:
  1143. //
  1144. //
  1145. //--------------------------------------------------------------------------
  1146. NTSTATUS NTAPI
  1147. WDigestGetContextToken(
  1148. IN ULONG_PTR KernelContextHandle,
  1149. OUT PHANDLE ImpersonationToken,
  1150. OUT OPTIONAL PACCESS_TOKEN *RawToken
  1151. )
  1152. {
  1153. NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
  1154. MAYBE_PAGED_CODE();
  1155. DebugLog(( DEB_TRACE, "WDigestGetContextToken: Entering\n" ));
  1156. UNREFERENCED_PARAMETER(KernelContextHandle);
  1157. UNREFERENCED_PARAMETER(ImpersonationToken);
  1158. UNREFERENCED_PARAMETER(RawToken);
  1159. DebugLog(( DEB_TRACE, "WDigestGetContextToken: Leaving 0x%lx\n", Status ));
  1160. return (Status);
  1161. }
  1162. //+-------------------------------------------------------------------------
  1163. //
  1164. // Function: WDigestQueryContextAttributes
  1165. //
  1166. // Synopsis: Querys attributes of the specified context
  1167. // This API allows a customer of the security
  1168. // services to determine certain attributes of
  1169. // the context. These are: sizes, names, and lifespan.
  1170. //
  1171. // Effects:
  1172. //
  1173. // Arguments:
  1174. //
  1175. // ContextHandle - Handle to the context to query.
  1176. //
  1177. // Attribute - Attribute to query.
  1178. //
  1179. // #define SECPKG_ATTR_SIZES 0
  1180. // #define SECPKG_ATTR_NAMES 1
  1181. // #define SECPKG_ATTR_LIFESPAN 2
  1182. //
  1183. // Buffer - Buffer to copy the data into. The buffer must
  1184. // be large enough to fit the queried attribute.
  1185. //
  1186. //
  1187. // Requires:
  1188. //
  1189. // Returns:
  1190. //
  1191. // STATUS_SUCCESS - Call completed successfully
  1192. //
  1193. // STATUS_INVALID_HANDLE -- Credential/Context Handle is invalid
  1194. // STATUS_UNSUPPORTED_FUNCTION -- Function code is not supported
  1195. //
  1196. // Notes:
  1197. //
  1198. //--------------------------------------------------------------------------
  1199. NTSTATUS NTAPI
  1200. WDigestQueryContextAttributes(
  1201. IN ULONG_PTR KernelContextHandle,
  1202. IN ULONG Attribute,
  1203. IN OUT PVOID Buffer
  1204. )
  1205. {
  1206. NTSTATUS Status = STATUS_SUCCESS;
  1207. PDIGEST_KERNELCONTEXT pContext = NULL;
  1208. MAYBE_PAGED_CODE();
  1209. DebugLog((DEB_TRACE_FUNC, "WDigestQueryContextAttributes: Entering ContextHandle 0x%lx\n", KernelContextHandle ));
  1210. PSecPkgContext_Sizes ContextSizes = NULL;
  1211. PSecPkgContext_DceInfo ContextDceInfo = NULL;
  1212. PSecPkgContext_Names ContextNames = NULL;
  1213. PSecPkgContext_PackageInfo PackageInfo = NULL;
  1214. PSecPkgContext_NegotiationInfo NegInfo = NULL;
  1215. PSecPkgContext_PasswordExpiry PasswordExpires = NULL;
  1216. PSecPkgContext_KeyInfo KeyInfo = NULL;
  1217. PSecPkgContext_AccessToken AccessToken = NULL;
  1218. PSecPkgContext_StreamSizes StreamSizes = NULL;
  1219. ULONG PackageInfoSize = 0;
  1220. BOOL bServer = FALSE;
  1221. LPWSTR pszEncryptAlgorithmName = NULL;
  1222. LPWSTR pszSignatureAlgorithmName = NULL;
  1223. DWORD dwBytes = 0;
  1224. ULONG ulMaxMessage = 0;
  1225. DIGESTMODE_TYPE typeDigestMode = DIGESTMODE_UNDEFINED; // Are we in SASL or HTTP mode
  1226. Status = WDigestReferenceContext( KernelContextHandle, FALSE );
  1227. if ( NT_SUCCESS( Status ) )
  1228. {
  1229. pContext = (PDIGEST_KERNELCONTEXT) KernelContextHandle ;
  1230. }
  1231. else
  1232. {
  1233. DebugLog(( DEB_ERROR,
  1234. "WDigestQueryContextAttributes: Bad kernel context 0x%lx\n", KernelContextHandle));
  1235. goto CleanUp;
  1236. }
  1237. // Check to see if Integrity is negotiated for SC
  1238. bServer = pContext->CredentialUseFlags & DIGEST_CRED_INBOUND;
  1239. if ((pContext->typeDigest == SASL_CLIENT) ||
  1240. (pContext->typeDigest == SASL_SERVER))
  1241. {
  1242. typeDigestMode = DIGESTMODE_SASL;
  1243. }
  1244. else
  1245. {
  1246. typeDigestMode = DIGESTMODE_HTTP;
  1247. }
  1248. //
  1249. // Handle each of the various queried attributes
  1250. //
  1251. DebugLog((DEB_TRACE, "WDigestQueryContextAttributes : Attribute 0x%lx\n", Attribute ));
  1252. switch ( Attribute) {
  1253. case SECPKG_ATTR_SIZES:
  1254. ContextSizes = (PSecPkgContext_Sizes) Buffer;
  1255. ZeroMemory(ContextSizes, sizeof(SecPkgContext_Sizes));
  1256. ContextSizes->cbMaxToken = NTDIGEST_SP_MAX_TOKEN_SIZE;
  1257. if (typeDigestMode == DIGESTMODE_HTTP)
  1258. { // HTTP has signature the same as token in Authentication Header info
  1259. ContextSizes->cbMaxSignature = NTDIGEST_SP_MAX_TOKEN_SIZE;
  1260. }
  1261. else
  1262. { // SASL has specialized signature block
  1263. ContextSizes->cbMaxSignature = MAC_BLOCK_SIZE + MAX_PADDING;
  1264. }
  1265. if ((pContext->typeCipher == CIPHER_3DES) ||
  1266. (pContext->typeCipher == CIPHER_DES))
  1267. {
  1268. ContextSizes->cbBlockSize = DES_BLOCKSIZE;
  1269. ContextSizes->cbSecurityTrailer = MAC_BLOCK_SIZE + MAX_PADDING;
  1270. }
  1271. else if ((pContext->typeCipher == CIPHER_RC4) ||
  1272. (pContext->typeCipher == CIPHER_RC4_40) ||
  1273. (pContext->typeCipher == CIPHER_RC4_56))
  1274. {
  1275. ContextSizes->cbBlockSize = RC4_BLOCKSIZE;
  1276. ContextSizes->cbSecurityTrailer = MAC_BLOCK_SIZE + MAX_PADDING;
  1277. }
  1278. else
  1279. {
  1280. ContextSizes->cbBlockSize = 0;
  1281. if (typeDigestMode == DIGESTMODE_HTTP)
  1282. { // HTTP has signature the same as token in Authentication Header info
  1283. ContextSizes->cbSecurityTrailer = 0;
  1284. }
  1285. else
  1286. { // SASL has specialized signature block
  1287. ContextSizes->cbSecurityTrailer = MAC_BLOCK_SIZE + MAX_PADDING; // handle Auth-int case
  1288. }
  1289. }
  1290. break;
  1291. case SECPKG_ATTR_DCE_INFO:
  1292. ContextDceInfo = (PSecPkgContext_DceInfo) Buffer;
  1293. ZeroMemory(ContextDceInfo, sizeof(SecPkgContext_DceInfo));
  1294. ContextDceInfo->AuthzSvc = 0;
  1295. break;
  1296. case SECPKG_ATTR_NAMES:
  1297. ContextNames = (PSecPkgContext_Names) Buffer;
  1298. ZeroMemory(ContextNames, sizeof(SecPkgContext_Names));
  1299. if (pContext->ustrAccountName.Length && pContext->ustrAccountName.Buffer)
  1300. {
  1301. dwBytes = pContext->ustrAccountName.Length + sizeof(WCHAR);
  1302. ContextNames->sUserName = (LPWSTR)g_LsaKernelFunctions->AllocateHeap(dwBytes);
  1303. if (ContextNames->sUserName)
  1304. {
  1305. ZeroMemory(ContextNames->sUserName, dwBytes);
  1306. memcpy(ContextNames->sUserName, pContext->ustrAccountName.Buffer, pContext->ustrAccountName.Length);
  1307. }
  1308. else
  1309. {
  1310. Status = STATUS_INSUFFICIENT_RESOURCES;
  1311. }
  1312. }
  1313. else
  1314. {
  1315. Status = STATUS_INSUFFICIENT_RESOURCES;
  1316. }
  1317. break;
  1318. case SECPKG_ATTR_PACKAGE_INFO:
  1319. case SECPKG_ATTR_NEGOTIATION_INFO:
  1320. //
  1321. // Return the information about this package. This is useful for
  1322. // callers who used SPNEGO and don't know what package they got.
  1323. //
  1324. // if ((Attribute == SECPKG_ATTR_NEGOTIATION_INFO) && (g_fParameter_Negotiate == FALSE))
  1325. if (Attribute == SECPKG_ATTR_NEGOTIATION_INFO)
  1326. {
  1327. Status = STATUS_NOT_SUPPORTED;
  1328. goto CleanUp;
  1329. }
  1330. PackageInfo = (PSecPkgContext_PackageInfo) Buffer;
  1331. ZeroMemory(PackageInfo, sizeof(SecPkgContext_PackageInfo));
  1332. PackageInfoSize = sizeof(SecPkgInfoW) + sizeof(WDIGEST_SP_NAME) + sizeof(NTDIGEST_SP_COMMENT);
  1333. PackageInfo->PackageInfo = (PSecPkgInfoW)g_LsaKernelFunctions->AllocateHeap(PackageInfoSize);
  1334. if (PackageInfo->PackageInfo == NULL)
  1335. {
  1336. Status = STATUS_INSUFFICIENT_RESOURCES;
  1337. goto CleanUp;
  1338. }
  1339. PackageInfo->PackageInfo->Name = (LPWSTR) (PackageInfo->PackageInfo + 1);
  1340. PackageInfo->PackageInfo->Comment = (LPWSTR) ((((PBYTE) PackageInfo->PackageInfo->Name)) + sizeof(WDIGEST_SP_NAME));
  1341. wcscpy(
  1342. PackageInfo->PackageInfo->Name,
  1343. WDIGEST_SP_NAME
  1344. );
  1345. wcscpy(
  1346. PackageInfo->PackageInfo->Comment,
  1347. NTDIGEST_SP_COMMENT
  1348. );
  1349. PackageInfo->PackageInfo->wVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
  1350. PackageInfo->PackageInfo->wRPCID = RPC_C_AUTHN_DIGEST;
  1351. PackageInfo->PackageInfo->fCapabilities = NTDIGEST_SP_CAPS;
  1352. PackageInfo->PackageInfo->cbMaxToken = NTDIGEST_SP_MAX_TOKEN_SIZE;
  1353. if ( Attribute == SECPKG_ATTR_NEGOTIATION_INFO )
  1354. {
  1355. NegInfo = (PSecPkgContext_NegotiationInfo) PackageInfo ;
  1356. NegInfo->NegotiationState = SECPKG_NEGOTIATION_COMPLETE ;
  1357. }
  1358. break;
  1359. case SECPKG_ATTR_PASSWORD_EXPIRY:
  1360. PasswordExpires = (PSecPkgContext_PasswordExpiry) Buffer;
  1361. if (pContext->ExpirationTime.QuadPart != 0)
  1362. {
  1363. PasswordExpires->tsPasswordExpires = pContext->ExpirationTime;
  1364. }
  1365. else
  1366. Status = STATUS_NOT_SUPPORTED;
  1367. break;
  1368. case SECPKG_ATTR_KEY_INFO:
  1369. KeyInfo = (PSecPkgContext_KeyInfo) Buffer;
  1370. ZeroMemory(KeyInfo, sizeof(SecPkgContext_KeyInfo));
  1371. if (typeDigestMode == DIGESTMODE_HTTP)
  1372. {
  1373. // HTTP mode
  1374. KeyInfo->SignatureAlgorithm = CALG_MD5;
  1375. pszSignatureAlgorithmName = WSTR_CIPHER_MD5;
  1376. KeyInfo->sSignatureAlgorithmName = (LPWSTR)
  1377. g_LsaKernelFunctions->AllocateHeap(sizeof(WCHAR) * ((ULONG)wcslen(pszSignatureAlgorithmName) + 1));
  1378. if (KeyInfo->sSignatureAlgorithmName != NULL)
  1379. {
  1380. wcscpy(
  1381. KeyInfo->sSignatureAlgorithmName,
  1382. pszSignatureAlgorithmName
  1383. );
  1384. }
  1385. else
  1386. {
  1387. Status = STATUS_INSUFFICIENT_RESOURCES;
  1388. }
  1389. }
  1390. else
  1391. {
  1392. // SASL mode
  1393. KeyInfo->KeySize = 128; // All modes use a 128 bit key - may have less entropy though (i.e. rc4-XX)
  1394. KeyInfo->SignatureAlgorithm = CALG_HMAC;
  1395. pszSignatureAlgorithmName = WSTR_CIPHER_HMAC_MD5;
  1396. switch (pContext->typeCipher)
  1397. {
  1398. case CIPHER_RC4:
  1399. case CIPHER_RC4_40:
  1400. case CIPHER_RC4_56:
  1401. KeyInfo->KeySize = 16 * 8; // All modes use a 128 bit key - may have less entropy though (i.e. rc4-XX)
  1402. KeyInfo->SignatureAlgorithm = CALG_RC4;
  1403. pszEncryptAlgorithmName = WSTR_CIPHER_RC4;
  1404. break;
  1405. case CIPHER_DES:
  1406. KeyInfo->KeySize = 7 * 8;
  1407. KeyInfo->SignatureAlgorithm = CALG_DES;
  1408. pszEncryptAlgorithmName = WSTR_CIPHER_DES;
  1409. break;
  1410. case CIPHER_3DES:
  1411. KeyInfo->KeySize = 14 * 8;
  1412. KeyInfo->SignatureAlgorithm = CALG_3DES_112;
  1413. pszEncryptAlgorithmName = WSTR_CIPHER_3DES;
  1414. break;
  1415. }
  1416. if (pszEncryptAlgorithmName)
  1417. {
  1418. KeyInfo->sEncryptAlgorithmName = (LPWSTR)
  1419. g_LsaKernelFunctions->AllocateHeap(sizeof(WCHAR) * ((ULONG)wcslen(pszEncryptAlgorithmName) + 1));
  1420. if (KeyInfo->sEncryptAlgorithmName != NULL)
  1421. {
  1422. wcscpy(
  1423. KeyInfo->sEncryptAlgorithmName,
  1424. pszEncryptAlgorithmName
  1425. );
  1426. }
  1427. else
  1428. {
  1429. Status = STATUS_INSUFFICIENT_RESOURCES;
  1430. }
  1431. }
  1432. if (pszSignatureAlgorithmName)
  1433. {
  1434. KeyInfo->sSignatureAlgorithmName = (LPWSTR)
  1435. g_LsaKernelFunctions->AllocateHeap(sizeof(WCHAR) * ((ULONG)wcslen(pszSignatureAlgorithmName) + 1));
  1436. if (KeyInfo->sSignatureAlgorithmName != NULL)
  1437. {
  1438. wcscpy(
  1439. KeyInfo->sSignatureAlgorithmName,
  1440. pszSignatureAlgorithmName
  1441. );
  1442. }
  1443. else
  1444. {
  1445. Status = STATUS_INSUFFICIENT_RESOURCES;
  1446. }
  1447. }
  1448. }
  1449. // Make sure that EncryptAlgorithmName and SignatureAlgorithmName is a valid NULL terminated string #601928
  1450. if (NT_SUCCESS(Status) && !KeyInfo->sEncryptAlgorithmName)
  1451. {
  1452. KeyInfo->sEncryptAlgorithmName = (LPWSTR)
  1453. g_LsaKernelFunctions->AllocateHeap(sizeof(WCHAR));
  1454. if (KeyInfo->sEncryptAlgorithmName)
  1455. {
  1456. KeyInfo->sEncryptAlgorithmName[0] = L'\0';
  1457. }
  1458. else
  1459. {
  1460. Status = STATUS_INSUFFICIENT_RESOURCES;
  1461. }
  1462. }
  1463. if (NT_SUCCESS(Status) && !KeyInfo->sSignatureAlgorithmName)
  1464. {
  1465. KeyInfo->sSignatureAlgorithmName = (LPWSTR)
  1466. g_LsaKernelFunctions->AllocateHeap(sizeof(WCHAR));
  1467. if (KeyInfo->sSignatureAlgorithmName)
  1468. {
  1469. KeyInfo->sSignatureAlgorithmName[0] = L'\0';
  1470. }
  1471. else
  1472. {
  1473. Status = STATUS_INSUFFICIENT_RESOURCES;
  1474. }
  1475. }
  1476. break;
  1477. case SECPKG_ATTR_STREAM_SIZES:
  1478. StreamSizes = (PSecPkgContext_StreamSizes) Buffer;
  1479. ZeroMemory(StreamSizes, sizeof(SecPkgContext_StreamSizes));
  1480. if (typeDigestMode == DIGESTMODE_HTTP)
  1481. {
  1482. }
  1483. else
  1484. { // SASL
  1485. ulMaxMessage = pContext->ulRecvMaxBuf;
  1486. if (pContext->ulSendMaxBuf < ulMaxMessage)
  1487. {
  1488. ulMaxMessage = pContext->ulSendMaxBuf;
  1489. }
  1490. StreamSizes->cbMaximumMessage = ulMaxMessage - (MAC_BLOCK_SIZE + MAX_PADDING);
  1491. }
  1492. if ((pContext->typeCipher == CIPHER_3DES) ||
  1493. (pContext->typeCipher == CIPHER_DES))
  1494. {
  1495. StreamSizes->cbBlockSize = DES_BLOCKSIZE;
  1496. StreamSizes->cbTrailer = MAC_BLOCK_SIZE + MAX_PADDING;
  1497. }
  1498. else if ((pContext->typeCipher == CIPHER_RC4) ||
  1499. (pContext->typeCipher == CIPHER_RC4_40) ||
  1500. (pContext->typeCipher == CIPHER_RC4_56))
  1501. {
  1502. StreamSizes->cbBlockSize = RC4_BLOCKSIZE;
  1503. StreamSizes->cbTrailer = MAC_BLOCK_SIZE + MAX_PADDING;
  1504. }
  1505. break;
  1506. case SECPKG_ATTR_ACCESS_TOKEN:
  1507. AccessToken = (PSecPkgContext_AccessToken) Buffer;
  1508. //
  1509. // ClientTokenHandle can be NULL, for instance:
  1510. // 1. client side context.
  1511. // 2. incomplete server context.
  1512. // Token is not duped - caller must not CloseHandle
  1513. AccessToken->AccessToken = (void*)pContext->ClientTokenHandle;
  1514. break;
  1515. default:
  1516. Status = STATUS_NOT_SUPPORTED;
  1517. break;
  1518. }
  1519. CleanUp:
  1520. if (!NT_SUCCESS(Status))
  1521. {
  1522. switch (Attribute) {
  1523. case SECPKG_ATTR_NAMES:
  1524. if (ContextNames != NULL && ContextNames->sUserName )
  1525. {
  1526. g_LsaKernelFunctions->FreeHeap(ContextNames->sUserName);
  1527. ContextNames->sUserName = NULL;
  1528. }
  1529. break;
  1530. case SECPKG_ATTR_DCE_INFO:
  1531. if (ContextDceInfo != NULL && ContextDceInfo->pPac)
  1532. {
  1533. g_LsaKernelFunctions->FreeHeap(ContextDceInfo->pPac);
  1534. ContextDceInfo->pPac = NULL;
  1535. }
  1536. break;
  1537. case SECPKG_ATTR_KEY_INFO:
  1538. if (KeyInfo != NULL && KeyInfo->sEncryptAlgorithmName)
  1539. {
  1540. g_LsaKernelFunctions->FreeHeap(KeyInfo->sEncryptAlgorithmName);
  1541. KeyInfo->sEncryptAlgorithmName = NULL;
  1542. }
  1543. if (KeyInfo != NULL && KeyInfo->sSignatureAlgorithmName)
  1544. {
  1545. g_LsaKernelFunctions->FreeHeap(KeyInfo->sSignatureAlgorithmName);
  1546. KeyInfo->sSignatureAlgorithmName = NULL;
  1547. }
  1548. break;
  1549. }
  1550. }
  1551. if( pContext ) {
  1552. WDigestDerefContext( pContext );
  1553. }
  1554. DebugLog((DEB_TRACE_FUNC, "WDigestQueryContextAttributes: Leaving\n"));
  1555. return(Status);
  1556. }
  1557. //+-------------------------------------------------------------------------
  1558. //
  1559. // Function: WDigestCompleteToken
  1560. //
  1561. // Synopsis: Completes a context - used to perform user mode verification of
  1562. // challenge response for non-persistent connections re-established via ASC
  1563. // call.
  1564. //
  1565. // Effects:
  1566. //
  1567. // Arguments:
  1568. //
  1569. // Requires:
  1570. //
  1571. // Returns:
  1572. //
  1573. // Notes: Not implemented - server function not needed right now
  1574. //
  1575. //
  1576. //--------------------------------------------------------------------------
  1577. NTSTATUS NTAPI
  1578. WDigestCompleteToken(
  1579. IN ULONG_PTR ContextHandle,
  1580. IN PSecBufferDesc InputBuffer
  1581. )
  1582. {
  1583. UNREFERENCED_PARAMETER (ContextHandle);
  1584. UNREFERENCED_PARAMETER (InputBuffer);
  1585. PAGED_CODE();
  1586. DebugLog(( DEB_TRACE, "Entering WDigestCompleteToken: Entering\n" ));
  1587. DebugLog(( DEB_TRACE, "Leaving WDigestCompleteToken: Leaving \n" ));
  1588. return(STATUS_NOT_SUPPORTED);
  1589. }
  1590. //+-------------------------------------------------------------------------
  1591. //
  1592. // Function: WDigestExportSecurityContext
  1593. //
  1594. // Synopsis:
  1595. //
  1596. // Effects:
  1597. //
  1598. // Arguments:
  1599. //
  1600. // Requires:
  1601. //
  1602. // Returns:
  1603. //
  1604. // Notes:
  1605. //
  1606. //
  1607. //--------------------------------------------------------------------------
  1608. NTSTATUS
  1609. WDigestExportSecurityContext(
  1610. IN ULONG_PTR ContextHandle,
  1611. IN ULONG Flags,
  1612. OUT PSecBuffer PackedContext,
  1613. IN OUT PHANDLE TokenHandle
  1614. )
  1615. {
  1616. PAGED_CODE();
  1617. UNREFERENCED_PARAMETER (ContextHandle);
  1618. UNREFERENCED_PARAMETER (Flags);
  1619. UNREFERENCED_PARAMETER (PackedContext);
  1620. UNREFERENCED_PARAMETER (TokenHandle);
  1621. DebugLog(( DEB_TRACE, "WDigestExportSecurityContext: Entering\n" ));
  1622. DebugLog(( DEB_TRACE, "WDigestExportSecurityContext: Leaving\n" ));
  1623. return(STATUS_NOT_SUPPORTED);
  1624. }
  1625. //+-------------------------------------------------------------------------
  1626. //
  1627. // Function: WDigestImportSecurityContext
  1628. //
  1629. // Synopsis:
  1630. //
  1631. // Effects:
  1632. //
  1633. // Arguments:
  1634. //
  1635. // Requires:
  1636. //
  1637. // Returns:
  1638. //
  1639. // Notes:
  1640. //
  1641. //
  1642. //--------------------------------------------------------------------------
  1643. NTSTATUS
  1644. WDigestImportSecurityContext(
  1645. IN PSecBuffer PackedContext,
  1646. IN OPTIONAL HANDLE TokenHandle,
  1647. OUT PULONG_PTR ContextHandle
  1648. )
  1649. {
  1650. PAGED_CODE();
  1651. UNREFERENCED_PARAMETER (PackedContext);
  1652. UNREFERENCED_PARAMETER (TokenHandle);
  1653. UNREFERENCED_PARAMETER (ContextHandle);
  1654. DebugLog((DEB_TRACE,"WDigestImportSecurityContext: Entering\n"));
  1655. DebugLog((DEB_TRACE,"WDigestImportSecurityContext: Leaving\n"));
  1656. return(STATUS_NOT_SUPPORTED);
  1657. }
  1658. //+---------------------------------------------------------------------------
  1659. //
  1660. // Function: WDigestSetPagingMode
  1661. //
  1662. // Synopsis: Switch the paging mode for cluster support
  1663. //
  1664. // Arguments: [Pagable] --
  1665. //
  1666. // History: 7-07-98 RichardW Created
  1667. //
  1668. // Notes:
  1669. //
  1670. //----------------------------------------------------------------------------
  1671. NTSTATUS
  1672. WDigestSetPagingMode(
  1673. BOOLEAN Pagable
  1674. )
  1675. {
  1676. if ( Pagable )
  1677. {
  1678. WDigestPoolType = PagedPool ;
  1679. WDigestActiveList = WDigestPagedList ;
  1680. }
  1681. else
  1682. {
  1683. if ( WDigestNonPagedList == NULL )
  1684. {
  1685. WDigestNonPagedList = g_LsaKernelFunctions->CreateContextList( KSecNonPaged );
  1686. if ( WDigestNonPagedList == NULL )
  1687. {
  1688. return STATUS_NO_MEMORY ;
  1689. }
  1690. }
  1691. WDigestActiveList = WDigestNonPagedList ;
  1692. WDigestPoolType = NonPagedPool ;
  1693. }
  1694. return STATUS_SUCCESS ;
  1695. }
  1696. // Printout the fields present in usercontext pContext
  1697. NTSTATUS
  1698. KernelContextPrint(PDIGEST_KERNELCONTEXT pContext)
  1699. {
  1700. NTSTATUS Status = STATUS_SUCCESS;
  1701. int i = 0;
  1702. if (!pContext)
  1703. {
  1704. return (STATUS_INVALID_PARAMETER);
  1705. }
  1706. DebugLog((DEB_TRACE_FUNC, "KernelContextPrint: Entering for Context Handle at 0x%x\n", pContext));
  1707. DebugLog((DEB_TRACE, "KernelContextPrint: NC %ld\n", pContext->ulNC));
  1708. DebugLog((DEB_TRACE, "KernelContextPrint: LSA Context 0x%x\n", pContext->LsaContext));
  1709. if (pContext->typeDigest == DIGEST_CLIENT)
  1710. {
  1711. DebugLog((DEB_TRACE, "KernelContextPrint: DIGEST_CLIENT\n"));
  1712. }
  1713. if (pContext->typeDigest == DIGEST_SERVER)
  1714. {
  1715. DebugLog((DEB_TRACE, "KernelContextPrint: DIGEST_SERVER\n"));
  1716. }
  1717. if (pContext->typeDigest == SASL_SERVER)
  1718. {
  1719. DebugLog((DEB_TRACE, "KernelContextPrint: SASL_SERVER\n"));
  1720. }
  1721. if (pContext->typeDigest == SASL_CLIENT)
  1722. {
  1723. DebugLog((DEB_TRACE, "KernelContextPrint: SASL_CLIENT\n"));
  1724. }
  1725. if (pContext->typeQOP == AUTH)
  1726. {
  1727. DebugLog((DEB_TRACE, "KernelContextPrint: QOP: AUTH\n"));
  1728. }
  1729. if (pContext->typeQOP == AUTH_INT)
  1730. {
  1731. DebugLog((DEB_TRACE, "KernelContextPrint: QOP: AUTH_INT\n"));
  1732. }
  1733. if (pContext->typeQOP == AUTH_CONF)
  1734. {
  1735. DebugLog((DEB_TRACE, "KernelContextPrint: QOP: AUTH_CONF\n"));
  1736. }
  1737. if (pContext->typeAlgorithm == MD5)
  1738. {
  1739. DebugLog((DEB_TRACE, "KernelContextPrint: Algorithm: MD5\n"));
  1740. }
  1741. if (pContext->typeAlgorithm == MD5_SESS)
  1742. {
  1743. DebugLog((DEB_TRACE, "KernelContextPrint: Algorithm: MD5_SESS\n"));
  1744. }
  1745. if (pContext->typeCharset == ISO_8859_1)
  1746. {
  1747. DebugLog((DEB_TRACE, "KernelContextPrint: Charset: ISO 8859-1\n"));
  1748. }
  1749. if (pContext->typeCharset == UTF_8)
  1750. {
  1751. DebugLog((DEB_TRACE, "KernelContextPrint: Charset: UTF-8\n"));
  1752. }
  1753. if (pContext->typeCipher == CIPHER_RC4)
  1754. {
  1755. DebugLog((DEB_TRACE, "KernelContextPrint: Cipher: CIPHER_RC4\n"));
  1756. }
  1757. else if (pContext->typeCipher == CIPHER_RC4_40)
  1758. {
  1759. DebugLog((DEB_TRACE, "KernelContextPrint: Cipher: CIPHER_RC4_40\n"));
  1760. }
  1761. else if (pContext->typeCipher == CIPHER_RC4_56)
  1762. {
  1763. DebugLog((DEB_TRACE, "KernelContextPrint: Cipher: CIPHER_RC4_56\n"));
  1764. }
  1765. else if (pContext->typeCipher == CIPHER_DES)
  1766. {
  1767. DebugLog((DEB_TRACE, "KernelContextPrint: Cipher: CIPHER_DES\n"));
  1768. }
  1769. else if (pContext->typeCipher == CIPHER_3DES)
  1770. {
  1771. DebugLog((DEB_TRACE, "KernelContextPrint: Cipher: CIPHER_3DES\n"));
  1772. }
  1773. DebugLog((DEB_TRACE, "KernelContextPrint: ContextReq 0x%lx CredentialUseFlags 0x%x\n",
  1774. pContext->ContextReq,
  1775. pContext->CredentialUseFlags));
  1776. for (i=0; i < MD5_AUTH_LAST;i++)
  1777. {
  1778. if (pContext->strParam[i].Buffer &&
  1779. pContext->strParam[i].Length)
  1780. {
  1781. DebugLog((DEB_TRACE, "KernelContextPrint: Digest[%d] = \"%Z\"\n", i, &pContext->strParam[i]));
  1782. }
  1783. }
  1784. if (pContext->strSessionKey.Length)
  1785. {
  1786. DebugLog((DEB_TRACE, "KernelContextPrint: SessionKey %Z\n", &pContext->strSessionKey));
  1787. }
  1788. if (pContext->ustrAccountName.Length)
  1789. {
  1790. DebugLog((DEB_TRACE, "KernelContextPrint: AccountName %wZ\n", &pContext->ustrAccountName));
  1791. }
  1792. DebugLog((DEB_TRACE_FUNC, "KernelContextPrint: Leaving\n"));
  1793. return(Status);
  1794. }