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

2466 lines
63 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1996
  6. //
  7. // File: userapi.cxx
  8. //
  9. // Contents: User-mode APIs to Kerberos package
  10. //
  11. //
  12. // History: 17-April-1996 Created MikeSw
  13. //
  14. //------------------------------------------------------------------------
  15. #include <kerbkrnl.h>
  16. extern "C"
  17. {
  18. #include <cryptdll.h>
  19. }
  20. #include "krnlapi.h"
  21. #define DONT_SUPPORT_OLD_TYPES_USER 1
  22. //
  23. // Make these extern "C" to allow them to be pageable.
  24. //
  25. extern "C"
  26. {
  27. KspInitPackageFn KerbInitKernelPackage;
  28. KspDeleteContextFn KerbDeleteKernelContext;
  29. KspInitContextFn KerbInitKernelContext;
  30. KspMapHandleFn KerbMapKernelHandle;
  31. KspMakeSignatureFn KerbMakeSignature;
  32. KspVerifySignatureFn KerbVerifySignature;
  33. KspSealMessageFn KerbSealMessage;
  34. KspUnsealMessageFn KerbUnsealMessage;
  35. KspGetTokenFn KerbGetContextToken;
  36. KspQueryAttributesFn KerbQueryContextAttributes;
  37. KspCompleteTokenFn KerbCompleteToken;
  38. SpExportSecurityContextFn KerbExportContext;
  39. SpImportSecurityContextFn KerbImportContext;
  40. KspSetPagingModeFn KerbSetPageMode ;
  41. NTSTATUS
  42. KerbMakeSignatureToken(
  43. IN PKERB_KERNEL_CONTEXT Context,
  44. IN ULONG QualityOfProtection,
  45. IN PSecBuffer SignatureBuffer,
  46. IN ULONG TotalBufferSize,
  47. IN BOOLEAN Encrypt,
  48. IN ULONG SuppliedNonce,
  49. OUT PKERB_GSS_SIGNATURE * OutputSignature,
  50. OUT PULONG ChecksumType,
  51. OUT PULONG EncryptionType,
  52. OUT PULONG SequenceNumber
  53. );
  54. NTSTATUS
  55. KerbVerifySignatureToken(
  56. IN PKERB_KERNEL_CONTEXT Context,
  57. IN PSecBuffer SignatureBuffer,
  58. IN ULONG TotalBufferSize,
  59. IN BOOLEAN Decrypt,
  60. IN ULONG SuppliedNonce,
  61. OUT PKERB_GSS_SIGNATURE * OutputSignature,
  62. OUT PULONG QualityOfProtection,
  63. OUT PULONG ChecksumType,
  64. OUT PCRYPTO_SYSTEM * CryptSystem,
  65. OUT PULONG SequenceNumber
  66. );
  67. NTSTATUS NTAPI
  68. KerbInitDefaults();
  69. }
  70. #ifdef ALLOC_PRAGMA
  71. #pragma alloc_text(PAGE, KerbInitKernelPackage)
  72. #pragma alloc_text(PAGE, KerbDeleteKernelContext)
  73. #pragma alloc_text(PAGE, KerbInitKernelContext)
  74. #pragma alloc_text(PAGE, KerbMapKernelHandle)
  75. #pragma alloc_text(PAGEMSG, KerbMakeSignature)
  76. #pragma alloc_text(PAGEMSG, KerbVerifySignature)
  77. #pragma alloc_text(PAGEMSG, KerbSealMessage)
  78. #pragma alloc_text(PAGEMSG, KerbUnsealMessage)
  79. #pragma alloc_text(PAGEMSG, KerbGetContextToken)
  80. #pragma alloc_text(PAGEMSG, KerbQueryContextAttributes)
  81. #pragma alloc_text(PAGEMSG, KerbMakeSignatureToken)
  82. #pragma alloc_text(PAGEMSG, KerbVerifySignatureToken)
  83. #pragma alloc_text(PAGE, KerbCompleteToken)
  84. #pragma alloc_text(PAGE, KerbExportContext)
  85. #pragma alloc_text(PAGE, KerbImportContext)
  86. #pragma alloc_text(PAGE, KerbInitDefaults)
  87. #endif
  88. SECPKG_KERNEL_FUNCTION_TABLE KerberosFunctionTable = {
  89. KerbInitKernelPackage,
  90. KerbDeleteKernelContext,
  91. KerbInitKernelContext,
  92. KerbMapKernelHandle,
  93. KerbMakeSignature,
  94. KerbVerifySignature,
  95. KerbSealMessage,
  96. KerbUnsealMessage,
  97. KerbGetContextToken,
  98. KerbQueryContextAttributes,
  99. KerbCompleteToken,
  100. KerbExportContext,
  101. KerbImportContext,
  102. KerbSetPageMode
  103. };
  104. POOL_TYPE KerbPoolType ;
  105. #define MAYBE_PAGED_CODE() \
  106. if ( KerbPoolType == PagedPool ) \
  107. { \
  108. PAGED_CODE(); \
  109. }
  110. PVOID KerbPagedList ;
  111. PVOID KerbNonPagedList ;
  112. PVOID KerbActiveList ;
  113. ERESOURCE KerbGlobalResource;
  114. BOOLEAN KerbCryptInitialized;
  115. ULONG KerbMaxTokenSize = KERBEROS_MAX_TOKEN;
  116. extern "C"
  117. {
  118. int LibAttach(HANDLE, PVOID);
  119. }
  120. #define KerbWriteLockGlobals() \
  121. { \
  122. DebugLog((DEB_TRACE_LOCKS,"Write locking Globals\n")); \
  123. KeEnterCriticalRegion(); \
  124. ExAcquireResourceExclusiveLite(&KerbGlobalResource,TRUE); \
  125. }
  126. #define KerbReadLockGlobals() \
  127. { \
  128. DebugLog((DEB_TRACE_LOCKS,"Read locking Globals\n")); \
  129. KeEnterCriticalRegion(); \
  130. ExAcquireSharedWaitForExclusive(&KerbGlobalResource, TRUE); \
  131. }
  132. #define KerbUnlockGlobals() \
  133. { \
  134. DebugLog((DEB_TRACE_LOCKS,"Unlocking Globals\n")); \
  135. ExReleaseResourceLite(&KerbGlobalResource); \
  136. KeLeaveCriticalRegion(); \
  137. }
  138. //
  139. // Common GSS object IDs, taken from MIT kerberos distribution.
  140. //
  141. gss_OID_desc oids[] = {
  142. {5, "\053\005\001\005\002"}, // original mech id
  143. {9, "\052\206\110\206\367\022\001\002\002"}, // standard mech id
  144. {10, "\052\206\110\206\367\022\001\002\002\001"}, // krb5_name type
  145. {10, "\052\206\110\206\367\022\001\002\002\002"}, // krb5_principal type
  146. {10, "\052\206\110\206\367\022\001\002\002\003"}, // user2user mech id
  147. };
  148. gss_OID_desc * gss_mech_krb5 = oids;
  149. gss_OID_desc * gss_mech_krb5_new = oids+1;
  150. gss_OID_desc * gss_mech_krb5_u2u = oids+4;
  151. #define KERB_MAX_CHECKSUM_LENGTH 24
  152. //+-------------------------------------------------------------------------
  153. //
  154. // Function: KerbInitDefaults
  155. //
  156. // Synopsis: Opens registry key, and gets custom defaults
  157. //
  158. // Effects: Changes MaxTokenSize
  159. //
  160. // Arguments: None
  161. //
  162. // Requires:
  163. //
  164. // Returns: STATUS_SUCCESS on success
  165. //
  166. // Notes:
  167. //
  168. //
  169. //--------------------------------------------------------------------------
  170. NTSTATUS NTAPI
  171. KerbInitDefaults()
  172. {
  173. UNICODE_STRING ParameterPath;
  174. UNICODE_STRING MaxTokenValue;
  175. OBJECT_ATTRIBUTES oa;
  176. ULONG BytesRead;
  177. NTSTATUS Status;
  178. HANDLE hParamKey = INVALID_HANDLE_VALUE;
  179. KEY_VALUE_PARTIAL_INFORMATION KeyPartialInformation;
  180. PAGED_CODE();
  181. RtlInitUnicodeString(&ParameterPath, KERB_PARAMETER_PATH);
  182. RtlInitUnicodeString(&MaxTokenValue, KERB_PARAMETER_MAX_TOKEN_SIZE);
  183. InitializeObjectAttributes(
  184. &oa,
  185. &ParameterPath,
  186. OBJ_CASE_INSENSITIVE,
  187. NULL,
  188. NULL
  189. );
  190. Status = ZwOpenKey(
  191. &hParamKey,
  192. KEY_READ,
  193. &oa
  194. );
  195. if (!NT_SUCCESS(Status))
  196. {
  197. DebugLog((DEB_WARN, "KerbInitDefault:OpenKey failed:0x%x\n",Status));
  198. goto Cleanup;
  199. }
  200. Status = ZwQueryValueKey(
  201. hParamKey,
  202. &MaxTokenValue,
  203. KeyValuePartialInformation,
  204. (PVOID)&KeyPartialInformation,
  205. sizeof(KeyPartialInformation),
  206. &BytesRead
  207. );
  208. if (!NT_SUCCESS(Status) || KeyPartialInformation.Type != REG_DWORD)
  209. {
  210. DebugLog((DEB_WARN, "KerbInitDefault:QueryValueKey failed:0x%x\n",Status));
  211. goto Cleanup;
  212. } else {
  213. PULONG Value = (PULONG) &KeyPartialInformation.Data;
  214. KerbMaxTokenSize = *((PULONG)Value);
  215. }
  216. Cleanup:
  217. if (INVALID_HANDLE_VALUE != hParamKey)
  218. {
  219. ZwClose(hParamKey);
  220. }
  221. return Status;
  222. }
  223. //+-------------------------------------------------------------------------
  224. //
  225. // Function: KerbInitKernelPackage
  226. //
  227. // Synopsis: Initialize an instance of the Kerberos package in the kernel
  228. //
  229. // Effects:
  230. //
  231. // Arguments: Version - Version of the security dll loading the package
  232. // FunctionTable - Contains helper routines for use by Kerberos
  233. // UserFunctions - Receives a copy of Kerberos's user mode
  234. // function table
  235. //
  236. // Requires:
  237. //
  238. // Returns: STATUS_SUCCESS
  239. //
  240. // Notes:
  241. //
  242. //
  243. //--------------------------------------------------------------------------
  244. NTSTATUS NTAPI
  245. KerbInitKernelPackage(
  246. PSECPKG_KERNEL_FUNCTIONS FunctionTable
  247. )
  248. {
  249. NTSTATUS Status = STATUS_SUCCESS;
  250. PAGED_CODE();
  251. KerbPoolType = PagedPool ;
  252. KerbPagedList = KSecCreateContextList( KSecPaged );
  253. if ( !KerbPagedList )
  254. {
  255. return STATUS_NO_MEMORY ;
  256. }
  257. KerbActiveList = KerbPagedList ;
  258. Status = ExInitializeResourceLite (&KerbGlobalResource);
  259. if (!NT_SUCCESS(Status))
  260. {
  261. return Status;
  262. }
  263. // Get registry values, ignore failures
  264. KerbInitDefaults();
  265. return STATUS_SUCCESS ;
  266. }
  267. //+-------------------------------------------------------------------------
  268. //
  269. // Function: KerbDeleteKernelContext
  270. //
  271. // Synopsis: Deletes a kernel mode context by unlinking it and then
  272. // dereferencing it.
  273. //
  274. // Effects:
  275. //
  276. // Arguments: ContextHandle - Kernel context handle of the context to delete
  277. // LsaContextHandle - Receives LSA context handle of the context
  278. // to delete
  279. //
  280. // Requires:
  281. //
  282. // Returns: STATUS_SUCCESS on success
  283. //
  284. // Notes:
  285. //
  286. //
  287. //--------------------------------------------------------------------------
  288. NTSTATUS NTAPI
  289. KerbDeleteKernelContext(
  290. IN LSA_SEC_HANDLE ContextHandle,
  291. OUT PLSA_SEC_HANDLE LsaContextHandle
  292. )
  293. {
  294. PKERB_KERNEL_CONTEXT Context = NULL;
  295. NTSTATUS SaveStatus = STATUS_SUCCESS;
  296. DebugLog((DEB_TRACE,"KerbDeleteUserModeContext called\n"));
  297. Context = KerbReferenceContext(
  298. ContextHandle,
  299. TRUE // unlink it
  300. );
  301. if (Context == NULL)
  302. {
  303. DebugLog((DEB_WARN,"Failed to reference context 0x%x by lsa handle\n",
  304. ContextHandle ));
  305. *LsaContextHandle = ContextHandle;
  306. return(STATUS_INVALID_HANDLE);
  307. }
  308. KerbReadLockContexts();
  309. *LsaContextHandle = Context->LsaContextHandle;
  310. if ((Context->ContextAttributes & KERB_CONTEXT_EXPORTED) != 0)
  311. {
  312. SaveStatus = SEC_I_NO_LSA_CONTEXT;
  313. }
  314. KerbUnlockContexts();
  315. KerbDereferenceContext(
  316. Context
  317. );
  318. return((SaveStatus == SEC_I_NO_LSA_CONTEXT) ?
  319. SEC_I_NO_LSA_CONTEXT :
  320. STATUS_SUCCESS);
  321. }
  322. //+-------------------------------------------------------------------------
  323. //
  324. // Function: KerbInitKernelContext
  325. //
  326. // Synopsis: Creates a kernel-mode context from a packed LSA mode context
  327. //
  328. // Effects:
  329. //
  330. // Arguments: ContextHandle - Lsa mode context handle for the context
  331. // PackedContext - A marshalled buffer containing the LSA
  332. // mode context.
  333. // NewContextHandle - Receives kernel mode context handle
  334. //
  335. // Requires:
  336. //
  337. // Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
  338. //
  339. // Notes:
  340. //
  341. //
  342. //--------------------------------------------------------------------------
  343. NTSTATUS NTAPI
  344. KerbInitKernelContext(
  345. IN LSA_SEC_HANDLE LsaContextHandle,
  346. IN PSecBuffer PackedContext,
  347. OUT PLSA_SEC_HANDLE NewContextHandle
  348. )
  349. {
  350. NTSTATUS Status;
  351. PKERB_KERNEL_CONTEXT Context = NULL;
  352. PAGED_CODE();
  353. DebugLog((DEB_TRACE,"KerbInitUserModeContex called\n"));
  354. Status = KerbCreateKernelModeContext(
  355. LsaContextHandle,
  356. PackedContext,
  357. &Context
  358. );
  359. if (!NT_SUCCESS(Status))
  360. {
  361. DebugLog((DEB_ERROR,"Failed to create kernel mode context: 0x%x\n",
  362. Status));
  363. goto Cleanup;
  364. }
  365. *NewContextHandle = KerbGetContextHandle(Context);
  366. Cleanup:
  367. if (Context != NULL)
  368. {
  369. KerbDereferenceContext(Context);
  370. }
  371. if (PackedContext->pvBuffer != NULL)
  372. {
  373. KspKernelFunctions.FreeHeap(PackedContext->pvBuffer);
  374. PackedContext->pvBuffer = NULL;
  375. }
  376. return(Status);
  377. }
  378. //+-------------------------------------------------------------------------
  379. //
  380. // Function: KerbMapKernelHandle
  381. //
  382. // Synopsis: Maps a kernel handle into an LSA handle
  383. //
  384. // Effects:
  385. //
  386. // Arguments: ContextHandle - Kernel context handle of the context to map
  387. // LsaContextHandle - Receives LSA context handle of the context
  388. // to map
  389. //
  390. // Requires:
  391. //
  392. // Returns: STATUS_SUCCESS on success
  393. //
  394. // Notes:
  395. //
  396. //
  397. //--------------------------------------------------------------------------
  398. NTSTATUS NTAPI
  399. KerbMapKernelHandle(
  400. IN LSA_SEC_HANDLE ContextHandle,
  401. OUT PLSA_SEC_HANDLE LsaContextHandle
  402. )
  403. {
  404. PKERB_KERNEL_CONTEXT Context = NULL;
  405. DebugLog((DEB_TRACE,"KerbMapKernelhandle called\n"));
  406. PAGED_CODE();
  407. Context = KerbReferenceContext(
  408. ContextHandle,
  409. FALSE // don't it
  410. );
  411. if (Context == NULL)
  412. {
  413. DebugLog((DEB_WARN,"Failed to reference context 0x%x by lsa handle\n",
  414. ContextHandle ));
  415. *LsaContextHandle = ContextHandle;
  416. }
  417. else
  418. {
  419. *LsaContextHandle = Context->LsaContextHandle;
  420. KerbDereferenceContext(
  421. Context
  422. );
  423. //
  424. // If the lsa context handle is zero, this is an imported context
  425. // so there is no lsa context
  426. //
  427. if (*LsaContextHandle == 0)
  428. {
  429. return(SEC_E_UNSUPPORTED_FUNCTION);
  430. }
  431. }
  432. return(STATUS_SUCCESS);
  433. }
  434. //+-------------------------------------------------------------------------
  435. //
  436. // Function: KerbRandomFill
  437. //
  438. // Synopsis: Generates random data in the buffer.
  439. //
  440. // Arguments: [pbBuffer] --
  441. // [cbBuffer] --
  442. //
  443. // History: 5-20-93 RichardW Created
  444. //
  445. // Notes:
  446. //
  447. //--------------------------------------------------------------------------
  448. VOID
  449. KerbRandomFill( PUCHAR pbBuffer,
  450. ULONG cbBuffer)
  451. {
  452. if (!CDGenerateRandomBits(pbBuffer, cbBuffer))
  453. {
  454. return;
  455. }
  456. return;
  457. }
  458. //+-------------------------------------------------------------------------
  459. //
  460. // Function: KerbMakeSignatureToken
  461. //
  462. // Synopsis: Makes the signature token for a signed or sealed message
  463. //
  464. // Effects:
  465. //
  466. // Arguments: Context - Context to use for signing
  467. // QualityOfProtection - flags indicating what kind of checksum
  468. // to use
  469. // SignatureBuffer - Buffer in which to place signature
  470. // TotalBufferSize - Total size of all buffers to be signed
  471. // Encrypt - if TRUE, then prepare a header for an encrypted buffer
  472. // SuppliedNonce - Nonce supplied by caller, used for datagram
  473. // ChecksumType - Receives the type of checksum to use
  474. // EncryptionType - Receives the type of encryption to use
  475. //
  476. // Requires: The context must be write locked
  477. //
  478. // Returns:
  479. //
  480. // Notes:
  481. //
  482. //
  483. //--------------------------------------------------------------------------
  484. NTSTATUS
  485. KerbMakeSignatureToken(
  486. IN PKERB_KERNEL_CONTEXT Context,
  487. IN ULONG QualityOfProtection,
  488. IN PSecBuffer SignatureBuffer,
  489. IN ULONG TotalBufferSize,
  490. IN BOOLEAN Encrypt,
  491. IN ULONG SuppliedNonce,
  492. OUT PKERB_GSS_SIGNATURE * OutputSignature,
  493. OUT PULONG ChecksumType,
  494. OUT PULONG EncryptionType,
  495. OUT PULONG SequenceNumber
  496. )
  497. {
  498. NTSTATUS Status = STATUS_SUCCESS;
  499. PKERB_GSS_SIGNATURE Signature;
  500. PKERB_GSS_SEAL_SIGNATURE SealSignature;
  501. ULONG MessageSize;
  502. ULONG SignatureSize = 0;
  503. PULONG Nonce;
  504. gss_OID MechUsed;
  505. BOOLEAN GssCompatible = TRUE;
  506. //
  507. // Make sure that cryptdll stuff is initialized.
  508. //
  509. MAYBE_PAGED_CODE();
  510. if (!KerbCryptInitialized)
  511. {
  512. KerbWriteLockGlobals();
  513. if ( !KerbCryptInitialized )
  514. {
  515. if (LibAttach(NULL, NULL))
  516. {
  517. KerbCryptInitialized = TRUE;
  518. }
  519. }
  520. KerbUnlockGlobals();
  521. }
  522. //
  523. // Compute the size of the header. For encryption headers, we need
  524. // to round up the size of the data & add 8 bytes for a confounder.
  525. //
  526. if (QualityOfProtection == GSS_KRB5_INTEG_C_QOP_DEFAULT)
  527. {
  528. GssCompatible = FALSE;
  529. }
  530. //
  531. // Since RPC doesn't carry around the size of the size of the
  532. // signature bufer, we use it in the header. This break rfc1964 compat.
  533. //
  534. if (!Encrypt || !GssCompatible)
  535. {
  536. TotalBufferSize = 0;
  537. }
  538. if ((Context->ContextAttributes & KERB_CONTEXT_USER_TO_USER) != 0)
  539. {
  540. MechUsed = gss_mech_krb5_u2u;
  541. }
  542. else
  543. {
  544. MechUsed = gss_mech_krb5_new;
  545. }
  546. if (Encrypt)
  547. {
  548. //
  549. // NOTE: according to rfc1964, buffers that are an even multiple of
  550. // 8 bytes have 8 bytes of zeros appended. Because we cannot modify
  551. // the input buffers, the caller will have to do this for us.
  552. //
  553. MessageSize = TotalBufferSize + sizeof(KERB_GSS_SEAL_SIGNATURE);
  554. }
  555. else
  556. {
  557. MessageSize = TotalBufferSize + sizeof(KERB_GSS_SIGNATURE);
  558. }
  559. SignatureSize = g_token_size(MechUsed, MessageSize) - TotalBufferSize;
  560. //
  561. // Make Dave happy (verify that the supplied signature buffer is large
  562. // enough for a signature):
  563. //
  564. if (SignatureBuffer->cbBuffer < SignatureSize)
  565. {
  566. Status = STATUS_BUFFER_TOO_SMALL;
  567. goto Cleanup;
  568. }
  569. //
  570. // create the header with the GSS oid
  571. //
  572. Signature = (PKERB_GSS_SIGNATURE) SignatureBuffer->pvBuffer;
  573. g_make_token_header(
  574. MechUsed,
  575. MessageSize,
  576. (PUCHAR *) &Signature,
  577. (Encrypt ? KG_TOK_WRAP_MSG : KG_TOK_MIC_MSG)
  578. );
  579. //
  580. // Fill in the header information according to RFC1964
  581. //
  582. Signature->SignatureAlgorithm[1] = KERB_GSS_SIG_SECOND;
  583. //
  584. // If the keytype is an MS keytype, we need to use an MS encryption
  585. // scheme.
  586. //
  587. if (!KERB_IS_DES_ENCRYPTION(Context->SessionKey.keytype))
  588. {
  589. #ifndef DONT_SUPPORT_OLD_TYPES_USER
  590. if (Context->SessionKey.keytype == KERB_ETYPE_RC4_HMAC_OLD)
  591. {
  592. *ChecksumType = KERB_CHECKSUM_HMAC_MD5;
  593. *EncryptionType = KERB_ETYPE_RC4_PLAIN_OLD;
  594. Signature->SignatureAlgorithm[0] = KERB_GSS_SIG_HMAC;
  595. if (Encrypt)
  596. {
  597. Signature->SealAlgorithm[1] = KERB_GSS_SIG_SECOND;
  598. Signature->SealAlgorithm[0] = KERB_GSS_SEAL_RC4_OLD;
  599. }
  600. }
  601. else if (Context->SessionKey.keytype == KERB_ETYPE_RC4_HMAC_OLD_EXP)
  602. {
  603. *ChecksumType = KERB_CHECKSUM_HMAC_MD5;
  604. *EncryptionType = KERB_ETYPE_RC4_PLAIN_OLD_EXP;
  605. Signature->SignatureAlgorithm[0] = KERB_GSS_SIG_HMAC;
  606. if (Encrypt)
  607. {
  608. Signature->SealAlgorithm[1] = KERB_GSS_SIG_SECOND;
  609. Signature->SealAlgorithm[0] = KERB_GSS_SEAL_RC4_OLD;
  610. }
  611. }
  612. else
  613. #endif
  614. if (Context->SessionKey.keytype == KERB_ETYPE_RC4_HMAC_NT)
  615. {
  616. *ChecksumType = KERB_CHECKSUM_HMAC_MD5;
  617. *EncryptionType = KERB_ETYPE_RC4_PLAIN;
  618. Signature->SignatureAlgorithm[0] = KERB_GSS_SIG_HMAC;
  619. if (Encrypt)
  620. {
  621. Signature->SealAlgorithm[1] = KERB_GSS_SIG_SECOND;
  622. Signature->SealAlgorithm[0] = KERB_GSS_SEAL_RC4;
  623. }
  624. }
  625. else
  626. {
  627. ASSERT (Context->SessionKey.keytype == KERB_ETYPE_RC4_HMAC_NT_EXP);
  628. *ChecksumType = KERB_CHECKSUM_HMAC_MD5;
  629. *EncryptionType = KERB_ETYPE_RC4_PLAIN_EXP;
  630. Signature->SignatureAlgorithm[0] = KERB_GSS_SIG_HMAC;
  631. if (Encrypt)
  632. {
  633. Signature->SealAlgorithm[1] = KERB_GSS_SIG_SECOND;
  634. Signature->SealAlgorithm[0] = KERB_GSS_SEAL_RC4;
  635. }
  636. }
  637. }
  638. else
  639. {
  640. if (Encrypt)
  641. {
  642. Signature->SealAlgorithm[1] = KERB_GSS_SIG_SECOND;
  643. Signature->SealAlgorithm[0] = KERB_GSS_SEAL_DES_CBC;
  644. }
  645. //
  646. // Use the exportable version if necessasry
  647. //
  648. *EncryptionType = KERB_ETYPE_DES_PLAIN;
  649. switch(QualityOfProtection)
  650. {
  651. case GSS_KRB5_INTEG_C_QOP_MD5:
  652. Signature->SignatureAlgorithm[0] = KERB_GSS_SIG_MD25;
  653. *ChecksumType = KERB_CHECKSUM_MD25;
  654. break;
  655. case GSS_KRB5_INTEG_C_QOP_DEFAULT:
  656. case GSS_KRB5_INTEG_C_QOP_DES_MD5:
  657. Signature->SignatureAlgorithm[0] = KERB_GSS_SIG_DES_MAC_MD5;
  658. *ChecksumType = KERB_CHECKSUM_DES_MAC_MD5;
  659. break;
  660. case GSS_KRB5_INTEG_C_QOP_DES_MAC:
  661. Signature->SignatureAlgorithm[0] = KERB_GSS_SIG_DES_MAC;
  662. *ChecksumType = KERB_CHECKSUM_DES_MAC;
  663. break;
  664. default:
  665. DebugLog((DEB_ERROR,"Invalid quality of protection sent to MakeSignature: %d.\n",
  666. QualityOfProtection ));
  667. Status = STATUS_INVALID_PARAMETER;
  668. goto Cleanup;
  669. }
  670. }
  671. //
  672. // Put in the filler - it is different for signing & sealing
  673. //
  674. if (Encrypt)
  675. {
  676. memset(Signature->SealFiller,0xff,2);
  677. }
  678. else
  679. {
  680. memset(Signature->SignFiller,0xff,4);
  681. }
  682. //
  683. // Inbound contexts get a high dword of 0xffffffff, outbound gets
  684. // 0x00000000.
  685. //
  686. if (Context->ContextAttributes & KERB_CONTEXT_INBOUND)
  687. {
  688. *(PULONG)(&Signature->SequenceNumber[4]) = 0xffffffff;
  689. Nonce = &Context->ReceiveNonce;
  690. }
  691. else
  692. {
  693. ASSERT((Context->ContextAttributes & KERB_CONTEXT_OUTBOUND) != 0);
  694. *(PULONG)(&Signature->SequenceNumber[4]) = 0x00000000;
  695. Nonce = &Context->Nonce;
  696. }
  697. //
  698. // If this is datagram, or integrity without replay & sequence detection,
  699. // use the nonce from the caller
  700. //
  701. if (((Context->ContextFlags & ISC_RET_DATAGRAM) != 0) ||
  702. ((Context->ContextFlags & (ISC_RET_INTEGRITY | ISC_RET_SEQUENCE_DETECT | ISC_RET_REPLAY_DETECT)) == ISC_RET_INTEGRITY))
  703. {
  704. Nonce = &SuppliedNonce;
  705. }
  706. Signature->SequenceNumber[0] = (UCHAR) ((*Nonce & 0xff000000) >> 24);
  707. Signature->SequenceNumber[1] = (UCHAR) ((*Nonce & 0x00ff0000) >> 16);
  708. Signature->SequenceNumber[2] = (UCHAR) ((*Nonce & 0x0000ff00) >> 8);
  709. Signature->SequenceNumber[3] = (UCHAR) (*Nonce & 0x000000ff);
  710. (*Nonce)++;
  711. *SequenceNumber = *(PULONG)Signature->SequenceNumber;
  712. //
  713. // If we are encrypting, add the confounder to the end of the signature
  714. //
  715. if (Encrypt)
  716. {
  717. SealSignature = (PKERB_GSS_SEAL_SIGNATURE) Signature;
  718. KerbRandomFill(
  719. SealSignature->Confounder,
  720. KERB_GSS_SIG_CONFOUNDER_SIZE
  721. );
  722. }
  723. //
  724. // Set the size of the signature
  725. //
  726. SignatureBuffer->cbBuffer = SignatureSize;
  727. *OutputSignature = Signature;
  728. Cleanup:
  729. return(Status);
  730. }
  731. //+-------------------------------------------------------------------------
  732. //
  733. // Function: KerbVerifySignatureToken
  734. //
  735. // Synopsis: Verifies the header on a signed or sealed message
  736. //
  737. // Effects:
  738. //
  739. // Arguments: Context - context to use for verification
  740. // SignatureBuffer - Buffer containing signature
  741. // TotalBufferSize - Size of all buffers signed/encrypted
  742. // Decrypt - TRUE if we are unsealing
  743. // SuppliedNonce - Nonce supplied by caller, used for datagram
  744. // QualityOfProtection - returns GSS quality of protection flags
  745. // ChecksumType - Type of checksum used in this signature
  746. // EncryptionType - Type of encryption used in this signature
  747. //
  748. // Requires:
  749. //
  750. // Returns:
  751. //
  752. // Notes:
  753. //
  754. //
  755. //--------------------------------------------------------------------------
  756. NTSTATUS
  757. KerbVerifySignatureToken(
  758. IN PKERB_KERNEL_CONTEXT Context,
  759. IN PSecBuffer SignatureBuffer,
  760. IN ULONG TotalBufferSize,
  761. IN BOOLEAN Decrypt,
  762. IN ULONG SuppliedNonce,
  763. OUT PKERB_GSS_SIGNATURE * OutputSignature,
  764. OUT PULONG QualityOfProtection,
  765. OUT PULONG ChecksumType,
  766. OUT PCRYPTO_SYSTEM * CryptSystem,
  767. OUT PULONG SequenceNumber
  768. )
  769. {
  770. NTSTATUS Status = STATUS_SUCCESS;
  771. ULONG SignatureSize = 0;
  772. UCHAR Nonce[8];
  773. PCRYPT_STATE_BUFFER CryptBuffer = NULL;
  774. ULONG OutputSize;
  775. ULONG EncryptionType;
  776. PCRYPTO_SYSTEM LocalCryptSystem = NULL ;
  777. PKERB_GSS_SIGNATURE Signature;
  778. PULONG ContextNonce;
  779. gss_OID MechUsed;
  780. //
  781. // Make sure that cryptdll stuff is initialized.
  782. //
  783. MAYBE_PAGED_CODE();
  784. if (!KerbCryptInitialized)
  785. {
  786. KerbWriteLockGlobals();
  787. if ( !KerbCryptInitialized )
  788. {
  789. if (LibAttach(NULL, NULL))
  790. {
  791. KerbCryptInitialized = TRUE;
  792. }
  793. }
  794. KerbUnlockGlobals();
  795. }
  796. //
  797. // Since RPC doesn't carry around the size of the size of the
  798. // signature bufer, we use it in the header. This break rfc1964 compat.
  799. //
  800. if (!Decrypt ||
  801. ((Context->ContextFlags & ISC_RET_USED_DCE_STYLE) != 0) ||
  802. ((Context->ContextFlags & ISC_RET_DATAGRAM) != 0))
  803. {
  804. TotalBufferSize = 0;
  805. }
  806. //
  807. // Verify the signature header
  808. //
  809. if ((Context->ContextAttributes & KERB_CONTEXT_USER_TO_USER) != 0)
  810. {
  811. MechUsed = gss_mech_krb5_u2u;
  812. }
  813. else
  814. {
  815. MechUsed = gss_mech_krb5_new;
  816. }
  817. Signature = (PKERB_GSS_SIGNATURE) SignatureBuffer->pvBuffer;
  818. if (!g_verify_token_header(
  819. MechUsed,
  820. (int *) &SignatureSize,
  821. (PUCHAR *) &Signature,
  822. (Decrypt ? KG_TOK_WRAP_MSG : KG_TOK_MIC_MSG),
  823. SignatureBuffer->cbBuffer + TotalBufferSize))
  824. {
  825. Status = SEC_E_MESSAGE_ALTERED;
  826. }
  827. //
  828. // If that didn't work, try with the old mech. Need this is for DCE clients
  829. // for whom we can't tell what mech they use.
  830. //
  831. if (!NT_SUCCESS(Status) && ((Context->ContextFlags & ISC_RET_USED_DCE_STYLE) != 0))
  832. {
  833. Signature = (PKERB_GSS_SIGNATURE) SignatureBuffer->pvBuffer;
  834. if (!g_verify_token_header(
  835. gss_mech_krb5,
  836. (int *) &SignatureSize,
  837. (PUCHAR *) &Signature,
  838. (Decrypt ? KG_TOK_WRAP_MSG : KG_TOK_MIC_MSG),
  839. SignatureBuffer->cbBuffer + TotalBufferSize))
  840. {
  841. Status = SEC_E_MESSAGE_ALTERED;
  842. }
  843. else
  844. {
  845. Status = STATUS_SUCCESS;
  846. }
  847. }
  848. //
  849. // MS RPC clients don't send the size properly, so set the total size
  850. // to zero and try again.
  851. //
  852. if (Decrypt && !NT_SUCCESS(Status))
  853. {
  854. TotalBufferSize = 0;
  855. Signature = (PKERB_GSS_SIGNATURE) SignatureBuffer->pvBuffer;
  856. if (!g_verify_token_header(
  857. MechUsed,
  858. (int *) &SignatureSize,
  859. (PUCHAR *) &Signature,
  860. (Decrypt ? KG_TOK_WRAP_MSG : KG_TOK_MIC_MSG),
  861. SignatureBuffer->cbBuffer + TotalBufferSize))
  862. {
  863. Status = SEC_E_MESSAGE_ALTERED;
  864. }
  865. else
  866. {
  867. Status = STATUS_SUCCESS;
  868. }
  869. //
  870. // If that didn't work, try with the old mech. Need this is for DCE clients
  871. // for whom we can't tell what mech they use.
  872. //
  873. if (!NT_SUCCESS(Status) && ((Context->ContextFlags & ISC_RET_USED_DCE_STYLE) != 0))
  874. {
  875. Signature = (PKERB_GSS_SIGNATURE) SignatureBuffer->pvBuffer;
  876. if (!g_verify_token_header(
  877. gss_mech_krb5,
  878. (int *) &SignatureSize,
  879. (PUCHAR *) &Signature,
  880. (Decrypt ? KG_TOK_WRAP_MSG : KG_TOK_MIC_MSG),
  881. SignatureBuffer->cbBuffer + TotalBufferSize))
  882. {
  883. Status = SEC_E_MESSAGE_ALTERED;
  884. }
  885. else
  886. {
  887. Status = STATUS_SUCCESS;
  888. }
  889. }
  890. }
  891. //
  892. // Protection from bad Signature Size
  893. //
  894. if (SignatureSize == 0)
  895. {
  896. Status = SEC_E_MESSAGE_ALTERED;
  897. goto Cleanup;
  898. }
  899. //
  900. // Subtract the total buffer size from Signature size to get the real
  901. // size of the signature.
  902. //
  903. SignatureSize -= TotalBufferSize;
  904. //
  905. // Make sure the signature is big enough. We can't enforce a strict
  906. // size because RPC will transmit the maximum number of bytes instead
  907. // of the actual number.
  908. //
  909. if ((Decrypt && (SignatureSize < sizeof(KERB_GSS_SEAL_SIGNATURE))) ||
  910. (!Decrypt && (SignatureSize < sizeof(KERB_GSS_SIGNATURE))))
  911. {
  912. Status = SEC_E_MESSAGE_ALTERED;
  913. goto Cleanup;
  914. }
  915. //
  916. // Verify the sequence number
  917. //
  918. if (Signature->SignatureAlgorithm[1] != KERB_GSS_SIG_SECOND)
  919. {
  920. Status = SEC_E_MESSAGE_ALTERED;
  921. goto Cleanup;
  922. }
  923. //
  924. // Figure out the algorithm
  925. //
  926. switch(Context->SessionKey.keytype) {
  927. case KERB_ETYPE_DES_CBC_MD5:
  928. case KERB_ETYPE_DES_CBC_CRC:
  929. EncryptionType = KERB_ETYPE_DES_PLAIN;
  930. break;
  931. case KERB_ETYPE_RC4_HMAC_OLD_EXP:
  932. EncryptionType = KERB_ETYPE_RC4_PLAIN_OLD_EXP;
  933. break;
  934. case KERB_ETYPE_RC4_HMAC_OLD:
  935. EncryptionType = KERB_ETYPE_RC4_PLAIN_OLD;
  936. break;
  937. case KERB_ETYPE_RC4_HMAC_NT_EXP:
  938. EncryptionType = KERB_ETYPE_RC4_PLAIN_EXP;
  939. break;
  940. case KERB_ETYPE_RC4_HMAC_NT:
  941. EncryptionType = KERB_ETYPE_RC4_PLAIN;
  942. break;
  943. default:
  944. DebugLog((DEB_ERROR,"Unknown key type: %d\n",
  945. Context->SessionKey.keytype ));
  946. Status = STATUS_INTERNAL_ERROR;
  947. goto Cleanup;
  948. }
  949. //
  950. // if the key is exportable, make sure to use the exportable plain
  951. // version.
  952. //
  953. switch(Signature->SignatureAlgorithm[0]) {
  954. case KERB_GSS_SIG_MD25:
  955. *QualityOfProtection = GSS_KRB5_INTEG_C_QOP_MD5;
  956. *ChecksumType = KERB_CHECKSUM_MD25;
  957. break;
  958. case KERB_GSS_SIG_DES_MAC_MD5:
  959. *QualityOfProtection = GSS_KRB5_INTEG_C_QOP_DES_MD5;
  960. *ChecksumType = KERB_CHECKSUM_DES_MAC_MD5;
  961. break;
  962. case KERB_GSS_SIG_DES_MAC:
  963. *QualityOfProtection = GSS_KRB5_INTEG_C_QOP_DES_MAC;
  964. *ChecksumType = KERB_CHECKSUM_DES_MAC;
  965. break;
  966. case KERB_GSS_SIG_HMAC:
  967. *QualityOfProtection = GSS_KRB5_INTEG_C_QOP_DEFAULT;
  968. *ChecksumType = KERB_CHECKSUM_HMAC_MD5;
  969. break;
  970. default:
  971. DebugLog((DEB_ERROR,"Invalid signature type to VerifySignature: %d\n",
  972. Signature->SignatureAlgorithm[0]));
  973. Status = SEC_E_MESSAGE_ALTERED;
  974. goto Cleanup;
  975. }
  976. if (Decrypt)
  977. {
  978. if (Signature->SealAlgorithm[1] != KERB_GSS_SIG_SECOND)
  979. {
  980. Status = SEC_E_MESSAGE_ALTERED;
  981. goto Cleanup;
  982. }
  983. //
  984. // Verify the seal algorithm
  985. //
  986. switch(EncryptionType) {
  987. case KERB_ETYPE_DES_PLAIN:
  988. if (Signature->SealAlgorithm[0] != KERB_GSS_SEAL_DES_CBC)
  989. {
  990. DebugLog((DEB_ERROR,"Trying to mix encryption types\n" ));
  991. Status = SEC_E_MESSAGE_ALTERED;
  992. goto Cleanup;
  993. }
  994. break;
  995. case KERB_ETYPE_RC4_PLAIN_OLD_EXP:
  996. case KERB_ETYPE_RC4_PLAIN_OLD:
  997. if (Signature->SealAlgorithm[0] != KERB_GSS_SEAL_RC4_OLD)
  998. {
  999. DebugLog((DEB_ERROR,"Trying to mix encryption types\n"));
  1000. Status = SEC_E_MESSAGE_ALTERED;
  1001. goto Cleanup;
  1002. }
  1003. break;
  1004. case KERB_ETYPE_RC4_PLAIN_EXP:
  1005. case KERB_ETYPE_RC4_PLAIN:
  1006. if (Signature->SealAlgorithm[0] != KERB_GSS_SEAL_RC4)
  1007. {
  1008. DebugLog((DEB_ERROR,"Trying to mix encryption types\n"));
  1009. Status = SEC_E_MESSAGE_ALTERED;
  1010. goto Cleanup;
  1011. }
  1012. break;
  1013. default:
  1014. DebugLog((DEB_ERROR,"Invalid seal type to VerifySignature: %d, %d\n", Signature->SealAlgorithm[0], EncryptionType));
  1015. Status = SEC_E_MESSAGE_ALTERED;
  1016. goto Cleanup;
  1017. }
  1018. }
  1019. //
  1020. // Check the filler
  1021. //
  1022. if ((Decrypt && (*(PUSHORT) Signature->SealFiller != 0xffff)) ||
  1023. (!Decrypt && (*(PULONG) Signature->SignFiller != 0xffffffff)))
  1024. {
  1025. Status = SEC_E_MESSAGE_ALTERED;
  1026. goto Cleanup;
  1027. }
  1028. //
  1029. // Verify the sequence number. To do this we need to decrypt it with
  1030. // the session key with the checksum as the IV.
  1031. //
  1032. Status = CDLocateCSystem(EncryptionType, &LocalCryptSystem);
  1033. if (!NT_SUCCESS(Status))
  1034. {
  1035. DebugLog((DEB_ERROR,"Failed to load %d crypt system: 0x%x\n", EncryptionType,Status));
  1036. goto Cleanup;
  1037. }
  1038. //
  1039. // Now we need to Decrypt the sequence number, using the checksum as the
  1040. // IV
  1041. //
  1042. Status = LocalCryptSystem->Initialize(
  1043. Context->SessionKey.keyvalue.value,
  1044. Context->SessionKey.keyvalue.length,
  1045. 0, // no flags
  1046. &CryptBuffer
  1047. );
  1048. if (!NT_SUCCESS(Status))
  1049. {
  1050. goto Cleanup;
  1051. }
  1052. //
  1053. // Set the initial vector
  1054. //
  1055. Status = LocalCryptSystem->Control(
  1056. CRYPT_CONTROL_SET_INIT_VECT,
  1057. CryptBuffer,
  1058. Signature->Checksum,
  1059. 8
  1060. );
  1061. if (!NT_SUCCESS(Status))
  1062. {
  1063. goto Cleanup;
  1064. }
  1065. //
  1066. // Now encrypt the sequence number
  1067. //
  1068. OutputSize = 8;
  1069. Status = LocalCryptSystem->Decrypt(
  1070. CryptBuffer,
  1071. Signature->SequenceNumber,
  1072. 8,
  1073. Signature->SequenceNumber,
  1074. &OutputSize
  1075. );
  1076. if (!NT_SUCCESS(Status))
  1077. {
  1078. goto Cleanup;
  1079. }
  1080. //
  1081. // For datagram or integrity only, we use just the supplied nonce.
  1082. //
  1083. if (((Context->ContextFlags & ISC_RET_DATAGRAM) != 0) ||
  1084. ((Context->ContextFlags & (ISC_RET_INTEGRITY | ISC_RET_SEQUENCE_DETECT | ISC_RET_REPLAY_DETECT)) == ISC_RET_INTEGRITY))
  1085. {
  1086. ContextNonce = &SuppliedNonce;
  1087. }
  1088. else
  1089. {
  1090. if ((Context->ContextAttributes & KERB_CONTEXT_OUTBOUND) != 0)
  1091. {
  1092. ContextNonce = &Context->ReceiveNonce;
  1093. }
  1094. else
  1095. {
  1096. ContextNonce = &Context->Nonce;
  1097. }
  1098. }
  1099. Nonce[0] = (UCHAR) ((*ContextNonce & 0xff000000) >> 24);
  1100. Nonce[1] = (UCHAR) ((*ContextNonce & 0x00ff0000) >> 16);
  1101. Nonce[2] = (UCHAR) ((*ContextNonce & 0x0000ff00) >> 8);
  1102. Nonce[3] = (UCHAR) (*ContextNonce & 0x000000ff);
  1103. *SequenceNumber = *(PULONG) Nonce;
  1104. if (!RtlEqualMemory(
  1105. Nonce,
  1106. Signature->SequenceNumber,
  1107. 4))
  1108. {
  1109. Status = SEC_E_OUT_OF_SEQUENCE;
  1110. goto Cleanup;
  1111. }
  1112. (*ContextNonce)++;
  1113. //
  1114. // Inbound contexts send a high dword of 0xffffffff, outbound gets
  1115. // 0x00000000.
  1116. //
  1117. if (Context->ContextAttributes & KERB_CONTEXT_OUTBOUND)
  1118. {
  1119. if (*(PULONG)(&Signature->SequenceNumber[4]) != 0xffffffff)
  1120. {
  1121. Status = SEC_E_MESSAGE_ALTERED;
  1122. goto Cleanup;
  1123. }
  1124. }
  1125. else
  1126. {
  1127. ASSERT((Context->ContextAttributes & KERB_CONTEXT_INBOUND) != 0);
  1128. if (*(PULONG)(&Signature->SequenceNumber[4]) != 0)
  1129. {
  1130. Status = SEC_E_MESSAGE_ALTERED;
  1131. goto Cleanup;
  1132. }
  1133. }
  1134. if (ARGUMENT_PRESENT(CryptSystem))
  1135. {
  1136. *CryptSystem = LocalCryptSystem;
  1137. }
  1138. *OutputSignature = Signature;
  1139. Cleanup:
  1140. if ( ( CryptBuffer != NULL) &&
  1141. ( LocalCryptSystem != NULL ) )
  1142. {
  1143. LocalCryptSystem->Discard(&CryptBuffer);
  1144. }
  1145. return(Status);
  1146. }
  1147. //+-------------------------------------------------------------------------
  1148. //
  1149. // Function: KerbMakeSignature
  1150. //
  1151. // Synopsis: Signs a message buffer by calculatinga checksum over all
  1152. // the non-read only data buffers and encrypting the checksum
  1153. // along with a nonce.
  1154. //
  1155. // Effects:
  1156. //
  1157. // Arguments: ContextHandle - Handle of the context to use to sign the
  1158. // message.
  1159. // QualityOfProtection - Unused flags.
  1160. // MessageBuffers - Contains an array of buffers to sign and
  1161. // to store the signature.
  1162. // MessageSequenceNumber - Sequence number for this message,
  1163. // only used in datagram cases.
  1164. //
  1165. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1166. // was not configured for message integrity.
  1167. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1168. // be found.
  1169. // STATUS_BUFFER_TOO_SMALL - the signature buffer is too small
  1170. // to hold the signature
  1171. //
  1172. // Returns:
  1173. //
  1174. // Notes: Cluster folks need to run this at dpc level (non paged)
  1175. //
  1176. //
  1177. //--------------------------------------------------------------------------
  1178. NTSTATUS NTAPI
  1179. KerbMakeSignature(
  1180. IN LSA_SEC_HANDLE ContextHandle,
  1181. IN ULONG QualityOfProtection,
  1182. IN PSecBufferDesc MessageBuffers,
  1183. IN ULONG MessageSequenceNumber
  1184. )
  1185. {
  1186. NTSTATUS Status = STATUS_SUCCESS;
  1187. PKERB_KERNEL_CONTEXT Context = NULL;
  1188. PCHECKSUM_FUNCTION Check;
  1189. PCRYPTO_SYSTEM CryptSystem = NULL ;
  1190. PSecBuffer SignatureBuffer = NULL;
  1191. ULONG Index;
  1192. PCHECKSUM_BUFFER CheckBuffer = NULL;
  1193. PCRYPT_STATE_BUFFER CryptBuffer = NULL;
  1194. PKERB_GSS_SIGNATURE Signature;
  1195. UCHAR LocalChecksum[KERB_MAX_CHECKSUM_LENGTH];
  1196. BOOLEAN ContextsLocked = FALSE;
  1197. ULONG ChecksumType = 0;
  1198. ULONG EncryptType;
  1199. ULONG TotalBufferSize = 0;
  1200. ULONG OutputSize;
  1201. ULONG SequenceNumber;
  1202. MAYBE_PAGED_CODE();
  1203. DebugLog((DEB_TRACE,"KerbMakeSignature Called\n"));
  1204. Context = KerbReferenceContext(
  1205. ContextHandle,
  1206. FALSE // don't unlink
  1207. );
  1208. if (Context == NULL)
  1209. {
  1210. DebugLog((DEB_ERROR, "Invalid handle supplied for MakeSignature(0x%x)\n",
  1211. ContextHandle));
  1212. Status = STATUS_INVALID_HANDLE;
  1213. goto Cleanup;
  1214. }
  1215. //
  1216. // Find the body and signature SecBuffers from pMessage
  1217. //
  1218. for (Index = 0; Index < MessageBuffers->cBuffers ; Index++ )
  1219. {
  1220. if (BUFFERTYPE(MessageBuffers->pBuffers[Index]) == SECBUFFER_TOKEN)
  1221. {
  1222. SignatureBuffer = &MessageBuffers->pBuffers[Index];
  1223. }
  1224. else if ((BUFFERTYPE(MessageBuffers->pBuffers[Index]) != SECBUFFER_TOKEN) &&
  1225. (!(MessageBuffers->pBuffers[Index].BufferType & SECBUFFER_READONLY)))
  1226. {
  1227. TotalBufferSize += MessageBuffers->pBuffers[Index].cbBuffer;
  1228. }
  1229. }
  1230. if (SignatureBuffer == NULL)
  1231. {
  1232. DebugLog((DEB_ERROR, "No signature buffer found\n"));
  1233. Status = STATUS_INVALID_PARAMETER;
  1234. goto Cleanup;
  1235. }
  1236. KerbWriteLockContexts();
  1237. ContextsLocked = TRUE;
  1238. //
  1239. // Verify that the context was created with the integrity bit
  1240. //
  1241. if ((Context->ContextFlags & KERB_SIGN_FLAGS) == 0)
  1242. {
  1243. if (SignatureBuffer->cbBuffer < sizeof(KERB_NULL_SIGNATURE))
  1244. {
  1245. Status = SEC_E_BUFFER_TOO_SMALL;
  1246. goto Cleanup;
  1247. }
  1248. SignatureBuffer->cbBuffer = sizeof(KERB_NULL_SIGNATURE);
  1249. *(PKERB_NULL_SIGNATURE) SignatureBuffer->pvBuffer = 0;
  1250. Status = STATUS_SUCCESS;
  1251. goto Cleanup;
  1252. }
  1253. Status = KerbMakeSignatureToken(
  1254. Context,
  1255. QualityOfProtection,
  1256. SignatureBuffer,
  1257. TotalBufferSize,
  1258. FALSE, // don't encrypt
  1259. MessageSequenceNumber,
  1260. &Signature,
  1261. &ChecksumType,
  1262. &EncryptType,
  1263. &SequenceNumber
  1264. );
  1265. if (!NT_SUCCESS(Status))
  1266. {
  1267. goto Cleanup;
  1268. }
  1269. //
  1270. // Locate the checksum for the context, loading it if necessary from the
  1271. // the crypto support DLL
  1272. //
  1273. Status = CDLocateCheckSum(ChecksumType, &Check);
  1274. if (!NT_SUCCESS(Status))
  1275. {
  1276. DebugLog((DEB_ERROR,"Failed to load %d checksum: 0x%x.\n ",ChecksumType,Status ));
  1277. goto Cleanup;
  1278. }
  1279. ASSERT(Check->CheckSumSize <= sizeof(LocalChecksum));
  1280. Status = CDLocateCSystem(EncryptType, &CryptSystem);
  1281. if (!NT_SUCCESS(Status))
  1282. {
  1283. DebugLog((DEB_ERROR,"Failed to load %d crypt system: 0x%x.\n",EncryptType,Status ));
  1284. goto Cleanup;
  1285. }
  1286. //
  1287. // Generate a check sum of the message, and store it into the signature
  1288. // buffer.
  1289. //
  1290. if (NULL != Check->InitializeEx2)
  1291. {
  1292. Status = Check->InitializeEx2(
  1293. Context->SessionKey.keyvalue.value,
  1294. (ULONG) Context->SessionKey.keyvalue.length,
  1295. NULL,
  1296. KERB_SAFE_SALT,
  1297. &CheckBuffer
  1298. );
  1299. }
  1300. else
  1301. {
  1302. Status = Check->InitializeEx(
  1303. Context->SessionKey.keyvalue.value,
  1304. (ULONG) Context->SessionKey.keyvalue.length,
  1305. KERB_SAFE_SALT,
  1306. &CheckBuffer
  1307. );
  1308. }
  1309. if (!NT_SUCCESS(Status))
  1310. {
  1311. goto Cleanup;
  1312. }
  1313. KerbUnlockContexts();
  1314. ContextsLocked = FALSE;
  1315. //
  1316. // Sum in 8 bytes of the signature
  1317. //
  1318. Check->Sum(
  1319. CheckBuffer,
  1320. 8,
  1321. ((PUCHAR) Signature) -2
  1322. );
  1323. for (Index = 0; Index < MessageBuffers->cBuffers; Index++ )
  1324. {
  1325. if ((BUFFERTYPE(MessageBuffers->pBuffers[Index]) != SECBUFFER_TOKEN) &&
  1326. (!(MessageBuffers->pBuffers[Index].BufferType & SECBUFFER_READONLY)) &&
  1327. (MessageBuffers->pBuffers[Index].cbBuffer != 0))
  1328. {
  1329. Check->Sum(
  1330. CheckBuffer,
  1331. MessageBuffers->pBuffers[Index].cbBuffer,
  1332. (PBYTE) MessageBuffers->pBuffers[Index].pvBuffer
  1333. );
  1334. }
  1335. }
  1336. (void) Check->Finalize(CheckBuffer, LocalChecksum);
  1337. Status = Check->Finish(&CheckBuffer);
  1338. if (!NT_SUCCESS(Status))
  1339. {
  1340. goto Cleanup;
  1341. }
  1342. //
  1343. // Copy in the first 8 bytes of the checksum
  1344. //
  1345. RtlCopyMemory(
  1346. Signature->Checksum,
  1347. LocalChecksum,
  1348. 8
  1349. );
  1350. //
  1351. // Now we need to encrypt the sequence number, using the checksum as the
  1352. // IV
  1353. //
  1354. Status = CryptSystem->Initialize(
  1355. Context->SessionKey.keyvalue.value,
  1356. Context->SessionKey.keyvalue.length,
  1357. 0, // no options
  1358. &CryptBuffer
  1359. );
  1360. if (!NT_SUCCESS(Status))
  1361. {
  1362. goto Cleanup;
  1363. }
  1364. //
  1365. // Set the initial vector
  1366. //
  1367. Status = CryptSystem->Control(
  1368. CRYPT_CONTROL_SET_INIT_VECT,
  1369. CryptBuffer,
  1370. LocalChecksum,
  1371. 8
  1372. );
  1373. if (!NT_SUCCESS(Status))
  1374. {
  1375. goto Cleanup;
  1376. }
  1377. //
  1378. // Now encrypt the sequence number
  1379. //
  1380. Status = CryptSystem->Encrypt(
  1381. CryptBuffer,
  1382. Signature->SequenceNumber,
  1383. 8,
  1384. Signature->SequenceNumber,
  1385. &OutputSize
  1386. );
  1387. if (!NT_SUCCESS(Status))
  1388. {
  1389. goto Cleanup;
  1390. }
  1391. Cleanup:
  1392. if ( ( CryptBuffer != NULL ) &&
  1393. ( CryptSystem != NULL ) )
  1394. {
  1395. CryptSystem->Discard(&CryptBuffer);
  1396. }
  1397. if (ContextsLocked)
  1398. {
  1399. KerbUnlockContexts();
  1400. }
  1401. if (Context != NULL)
  1402. {
  1403. KerbDereferenceContext(Context);
  1404. }
  1405. return(Status);
  1406. }
  1407. //+-------------------------------------------------------------------------
  1408. //
  1409. // Function: KerbVerifySignature
  1410. //
  1411. // Synopsis: Verifies a signed message buffer by calculating a checksum over all
  1412. // the non-read only data buffers and encrypting the checksum
  1413. // along with a nonce.
  1414. //
  1415. // Effects:
  1416. //
  1417. // Arguments: ContextHandle - Handle of the context to use to sign the
  1418. // message.
  1419. // MessageBuffers - Contains an array of signed buffers and
  1420. // a signature buffer.
  1421. // MessageSequenceNumber - Sequence number for this message,
  1422. // only used in datagram cases.
  1423. // QualityOfProtection - Unused flags.
  1424. //
  1425. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1426. // was not configured for message integrity.
  1427. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1428. // be found or was too small.
  1429. //
  1430. // Returns:
  1431. //
  1432. // Notes: Cluster folks need to run this at dpc level (non paged)
  1433. //
  1434. //
  1435. //--------------------------------------------------------------------------
  1436. NTSTATUS NTAPI
  1437. KerbVerifySignature(
  1438. IN LSA_SEC_HANDLE ContextHandle,
  1439. IN PSecBufferDesc MessageBuffers,
  1440. IN ULONG MessageSequenceNumber,
  1441. OUT PULONG QualityOfProtection
  1442. )
  1443. {
  1444. NTSTATUS Status = STATUS_SUCCESS;
  1445. PKERB_KERNEL_CONTEXT Context = NULL;
  1446. PCHECKSUM_FUNCTION Check;
  1447. PSecBuffer SignatureBuffer = NULL;
  1448. ULONG Index;
  1449. PCHECKSUM_BUFFER CheckBuffer = NULL;
  1450. PKERB_GSS_SIGNATURE Signature;
  1451. ULONG ChecksumType;
  1452. BOOLEAN ContextsLocked = FALSE;
  1453. UCHAR LocalChecksum[KERB_MAX_CHECKSUM_LENGTH];
  1454. ULONG Protection;
  1455. ULONG TotalBufferSize = 0;
  1456. ULONG SequenceNumber;
  1457. MAYBE_PAGED_CODE();
  1458. DebugLog((DEB_TRACE,"KerbVerifySignature Called\n"));
  1459. Context = KerbReferenceContext(
  1460. ContextHandle,
  1461. FALSE // don't unlink
  1462. );
  1463. if (Context == NULL)
  1464. {
  1465. DebugLog((DEB_ERROR, "Invalid handle supplied for VerifySignature(0x%x)\n",
  1466. ContextHandle));
  1467. Status = STATUS_INVALID_HANDLE;
  1468. goto Cleanup;
  1469. }
  1470. //
  1471. // Find the body and signature SecBuffers from pMessage
  1472. //
  1473. for (Index = 0; Index < MessageBuffers->cBuffers ; Index++ )
  1474. {
  1475. if (BUFFERTYPE(MessageBuffers->pBuffers[Index]) == SECBUFFER_TOKEN)
  1476. {
  1477. SignatureBuffer = &MessageBuffers->pBuffers[Index];
  1478. }
  1479. else if ((BUFFERTYPE(MessageBuffers->pBuffers[Index]) != SECBUFFER_TOKEN) &&
  1480. (!(MessageBuffers->pBuffers[Index].BufferType & SECBUFFER_READONLY)))
  1481. {
  1482. TotalBufferSize += MessageBuffers->pBuffers[Index].cbBuffer;
  1483. }
  1484. }
  1485. if (SignatureBuffer == NULL)
  1486. {
  1487. DebugLog((DEB_ERROR, "No signature buffer found\n"));
  1488. Status = STATUS_INVALID_PARAMETER;
  1489. goto Cleanup;
  1490. }
  1491. KerbWriteLockContexts();
  1492. ContextsLocked = TRUE;
  1493. //
  1494. // Also, verify that the context was created with the integrity bit
  1495. //
  1496. if ((Context->ContextFlags & KERB_SIGN_FLAGS) == 0)
  1497. {
  1498. PKERB_NULL_SIGNATURE NullSignature = (PKERB_NULL_SIGNATURE) SignatureBuffer->pvBuffer;
  1499. if (SignatureBuffer->cbBuffer >= sizeof(KERB_NULL_SIGNATURE) &&
  1500. (*NullSignature == 0))
  1501. {
  1502. Status = STATUS_SUCCESS;
  1503. }
  1504. else
  1505. {
  1506. Status = SEC_E_MESSAGE_ALTERED;
  1507. }
  1508. goto Cleanup;
  1509. }
  1510. //
  1511. // Verify the signature header
  1512. //
  1513. Status = KerbVerifySignatureToken(
  1514. Context,
  1515. SignatureBuffer,
  1516. TotalBufferSize,
  1517. FALSE, // don't decrypt
  1518. MessageSequenceNumber,
  1519. &Signature,
  1520. &Protection,
  1521. &ChecksumType,
  1522. NULL, // don't need crypt system
  1523. &SequenceNumber
  1524. );
  1525. if (!NT_SUCCESS(Status))
  1526. {
  1527. DebugLog((DEB_ERROR, "Failed to verify signature token: 0x%x\n", Status));
  1528. goto Cleanup;
  1529. }
  1530. //
  1531. // Now compute the checksum and verify it
  1532. //
  1533. Status = CDLocateCheckSum(ChecksumType, &Check);
  1534. if (!NT_SUCCESS(Status))
  1535. {
  1536. DebugLog((DEB_ERROR,"Failed to load MD5 checksum: 0x%x\n", Status));
  1537. goto Cleanup;
  1538. }
  1539. ASSERT(Check->CheckSumSize <= sizeof(LocalChecksum));
  1540. //
  1541. // Generate a check sum of the message, and store it into the signature
  1542. // buffer.
  1543. //
  1544. //
  1545. // if available use the Ex2 version for keyed checksums where checksum
  1546. // must be passed in on verification
  1547. //
  1548. if (NULL != Check->InitializeEx2)
  1549. {
  1550. Status = Check->InitializeEx2(
  1551. Context->SessionKey.keyvalue.value,
  1552. (ULONG) Context->SessionKey.keyvalue.length,
  1553. Signature->Checksum,
  1554. KERB_SAFE_SALT,
  1555. &CheckBuffer
  1556. );
  1557. }
  1558. else
  1559. {
  1560. Status = Check->InitializeEx(
  1561. Context->SessionKey.keyvalue.value,
  1562. (ULONG) Context->SessionKey.keyvalue.length,
  1563. KERB_SAFE_SALT,
  1564. &CheckBuffer
  1565. );
  1566. }
  1567. if (!NT_SUCCESS(Status))
  1568. {
  1569. goto Cleanup;
  1570. }
  1571. KerbUnlockContexts();
  1572. ContextsLocked = FALSE;
  1573. //
  1574. // Sum in 8 bytes of the signature
  1575. //
  1576. Check->Sum(
  1577. CheckBuffer,
  1578. 8,
  1579. ((PUCHAR) Signature) -2
  1580. );
  1581. for (Index = 0; Index < MessageBuffers->cBuffers; Index++ )
  1582. {
  1583. if ((BUFFERTYPE(MessageBuffers->pBuffers[Index]) != SECBUFFER_TOKEN) &&
  1584. (!(MessageBuffers->pBuffers[Index].BufferType & SECBUFFER_READONLY)) &&
  1585. (MessageBuffers->pBuffers[Index].cbBuffer != 0))
  1586. {
  1587. Check->Sum(
  1588. CheckBuffer,
  1589. MessageBuffers->pBuffers[Index].cbBuffer,
  1590. (PBYTE) MessageBuffers->pBuffers[Index].pvBuffer
  1591. );
  1592. }
  1593. }
  1594. (void) Check->Finalize(CheckBuffer, LocalChecksum);
  1595. Status = Check->Finish(&CheckBuffer);
  1596. if (!NT_SUCCESS(Status))
  1597. {
  1598. goto Cleanup;
  1599. }
  1600. if (!RtlEqualMemory(
  1601. LocalChecksum,
  1602. Signature->Checksum,
  1603. 8))
  1604. {
  1605. Status = SEC_E_MESSAGE_ALTERED;
  1606. goto Cleanup;
  1607. }
  1608. if (ARGUMENT_PRESENT(QualityOfProtection))
  1609. {
  1610. *QualityOfProtection = Protection;
  1611. }
  1612. Cleanup:
  1613. if (ContextsLocked)
  1614. {
  1615. KerbUnlockContexts();
  1616. }
  1617. if (Context != NULL)
  1618. {
  1619. KerbDereferenceContext(Context);
  1620. }
  1621. DebugLog((DEB_TRACE, "SpVerifySignature returned 0x%x\n", Status));
  1622. return(Status);
  1623. }
  1624. NTSTATUS NTAPI
  1625. KerbSealMessage(
  1626. IN LSA_SEC_HANDLE ContextHandle,
  1627. IN ULONG QualityOfProtection,
  1628. IN PSecBufferDesc MessageBuffers,
  1629. IN ULONG MessageSequenceNumber
  1630. )
  1631. {
  1632. MAYBE_PAGED_CODE();
  1633. return(STATUS_NOT_SUPPORTED);
  1634. }
  1635. NTSTATUS NTAPI
  1636. KerbUnsealMessage(
  1637. IN LSA_SEC_HANDLE ContextHandle,
  1638. IN PSecBufferDesc MessageBuffers,
  1639. IN ULONG MessageSequenceNumber,
  1640. OUT PULONG QualityOfProtection
  1641. )
  1642. {
  1643. MAYBE_PAGED_CODE();
  1644. return(STATUS_NOT_SUPPORTED);
  1645. }
  1646. //+-------------------------------------------------------------------------
  1647. //
  1648. // Function: KerbGetContextToken
  1649. //
  1650. // Synopsis: returns a pointer to the token for a server-side context
  1651. //
  1652. // Effects:
  1653. //
  1654. // Arguments:
  1655. //
  1656. // Requires:
  1657. //
  1658. // Returns:
  1659. //
  1660. // Notes:
  1661. //
  1662. //
  1663. //--------------------------------------------------------------------------
  1664. NTSTATUS NTAPI
  1665. KerbGetContextToken(
  1666. IN LSA_SEC_HANDLE ContextHandle,
  1667. OUT OPTIONAL PHANDLE ImpersonationToken,
  1668. OUT OPTIONAL PACCESS_TOKEN * RawToken
  1669. )
  1670. {
  1671. NTSTATUS Status = STATUS_SUCCESS;
  1672. PKERB_KERNEL_CONTEXT Context = NULL;
  1673. PAGED_CODE();
  1674. DebugLog((DEB_TRACE,"KerbGetContextToken Called\n"));
  1675. Context = KerbReferenceContext(
  1676. ContextHandle,
  1677. FALSE // don't unlink
  1678. );
  1679. if (Context == NULL)
  1680. {
  1681. DebugLog((DEB_ERROR, "Invalid handle supplied for GetContextToken(0x%x)\n",
  1682. ContextHandle));
  1683. return(STATUS_INVALID_HANDLE);
  1684. }
  1685. KerbReadLockContexts();
  1686. if (Context->TokenHandle == NULL)
  1687. {
  1688. Status = SEC_E_NO_IMPERSONATION;
  1689. KerbUnlockContexts();
  1690. goto Cleanup;
  1691. }
  1692. if (ARGUMENT_PRESENT(ImpersonationToken))
  1693. {
  1694. *ImpersonationToken = Context->TokenHandle;
  1695. }
  1696. if (ARGUMENT_PRESENT(RawToken))
  1697. {
  1698. if (Context->TokenHandle != NULL)
  1699. {
  1700. if (Context->AccessToken == NULL)
  1701. {
  1702. Status = ObReferenceObjectByHandle(
  1703. Context->TokenHandle,
  1704. TOKEN_IMPERSONATE,
  1705. NULL,
  1706. ExGetPreviousMode(),
  1707. (PVOID *) &Context->AccessToken,
  1708. NULL // no handle information
  1709. );
  1710. }
  1711. }
  1712. if (NT_SUCCESS(Status))
  1713. {
  1714. *RawToken = Context->AccessToken;
  1715. }
  1716. }
  1717. KerbUnlockContexts();
  1718. Cleanup:
  1719. if (Context != NULL)
  1720. {
  1721. //
  1722. // Note: once we dereference the context the handle we return
  1723. // may go away or be re-used. That is the price we have to pay
  1724. // to avoid duplicating it.
  1725. //
  1726. KerbDereferenceContext(Context);
  1727. }
  1728. return(Status);
  1729. }
  1730. //+-------------------------------------------------------------------------
  1731. //
  1732. // Function: KerbQueryContextAttributes
  1733. //
  1734. // Synopsis: Querys attributes of the specified context
  1735. //
  1736. // Effects:
  1737. //
  1738. // Arguments:
  1739. //
  1740. // Requires:
  1741. //
  1742. // Returns:
  1743. //
  1744. // Notes:
  1745. //
  1746. //
  1747. //--------------------------------------------------------------------------
  1748. NTSTATUS NTAPI
  1749. KerbQueryContextAttributes(
  1750. IN LSA_SEC_HANDLE ContextHandle,
  1751. IN ULONG ContextAttribute,
  1752. IN OUT PVOID Buffer
  1753. )
  1754. {
  1755. NTSTATUS Status = STATUS_SUCCESS;
  1756. PKERB_KERNEL_CONTEXT Context = NULL;
  1757. PSecPkgContext_Sizes SizeInfo;
  1758. PSecPkgContext_Names NameInfo;
  1759. PSecPkgContext_Lifespan LifespanInfo;
  1760. PSecPkgContext_Flags FlagsInfo;
  1761. PSecPkgContext_SessionKey SessionKeyInfo;
  1762. PSecPkgContext_UserFlags UserFlagsInfo ;
  1763. PSecPkgContext_PackageInfo PackageInfo = NULL;
  1764. PSecPkgContext_TargetInformation TargetInformation = NULL;
  1765. UNICODE_STRING FullName;
  1766. PAGED_CODE();
  1767. DebugLog((DEB_TRACE,"SpQueryContextAttributes Called\n"));
  1768. Context = KerbReferenceContext(
  1769. ContextHandle,
  1770. FALSE // don't unlink
  1771. );
  1772. //
  1773. // allow PACKAGE_INFO or NEGOTIATION_INFO to be queried against
  1774. // incomplete contexts.
  1775. //
  1776. if( (Context == NULL) &&
  1777. (ContextAttribute != SECPKG_ATTR_PACKAGE_INFO) &&
  1778. (ContextAttribute != SECPKG_ATTR_NEGOTIATION_INFO)
  1779. ) {
  1780. DebugLog((DEB_ERROR, "Invalid handle supplied for QueryContextAttributes(0x%x)\n",
  1781. ContextHandle));
  1782. return(STATUS_INVALID_HANDLE);
  1783. }
  1784. //
  1785. // Return the appropriate information
  1786. //
  1787. switch(ContextAttribute)
  1788. {
  1789. case SECPKG_ATTR_SIZES:
  1790. //
  1791. // The sizes returned are used by RPC to determine whether to call
  1792. // MakeSignature or SealMessage. The signature size should be zero
  1793. // if neither is to be called, and the block size and trailer size
  1794. // should be zero if SignMessage is not to be called.
  1795. //
  1796. SizeInfo = (PSecPkgContext_Sizes) Buffer;
  1797. SizeInfo->cbMaxToken = KerbMaxTokenSize;
  1798. // if ((Context->ContextFlags & (ISC_RET_CONFIDENTIALITY | ISC_RET_SEQUENCE_DETECT)) != 0)
  1799. // {
  1800. SizeInfo->cbMaxSignature = KERB_SIGNATURE_SIZE;
  1801. // }
  1802. // else
  1803. // {
  1804. // SizeInfo->cbMaxSignature = 0;
  1805. // }
  1806. if ((Context->ContextFlags & ISC_RET_CONFIDENTIALITY) != 0)
  1807. {
  1808. SizeInfo->cbBlockSize = 1;
  1809. SizeInfo->cbSecurityTrailer = KERB_SIGNATURE_SIZE;
  1810. }
  1811. else
  1812. {
  1813. SizeInfo->cbBlockSize = 0;
  1814. SizeInfo->cbSecurityTrailer = 0;
  1815. }
  1816. break;
  1817. case SECPKG_ATTR_NAMES:
  1818. NameInfo = (PSecPkgContext_Names) Buffer;
  1819. NameInfo->sUserName = (LPWSTR) KspKernelFunctions.AllocateHeap(Context->FullName.Length + sizeof(WCHAR));
  1820. if (NameInfo->sUserName != NULL)
  1821. {
  1822. RtlCopyMemory(
  1823. NameInfo->sUserName,
  1824. Context->FullName.Buffer,
  1825. Context->FullName.Length
  1826. );
  1827. NameInfo->sUserName[Context->FullName.Length/sizeof(WCHAR)] = L'\0';
  1828. }
  1829. else
  1830. {
  1831. Status = STATUS_INSUFFICIENT_RESOURCES;
  1832. }
  1833. break;
  1834. case SECPKG_ATTR_TARGET_INFORMATION:
  1835. TargetInformation = (PSecPkgContext_TargetInformation) Buffer;
  1836. if (TargetInformation == NULL)
  1837. {
  1838. Status = STATUS_INVALID_PARAMETER;
  1839. break;
  1840. }
  1841. TargetInformation->MarshalledTargetInfo = NULL;
  1842. if (Context->pbMarshalledTargetInfo == NULL)
  1843. {
  1844. Status = STATUS_NOT_FOUND;
  1845. break;
  1846. }
  1847. TargetInformation->MarshalledTargetInfo = (PUCHAR) KspKernelFunctions.AllocateHeap(
  1848. Context->cbMarshalledTargetInfo
  1849. );
  1850. if (TargetInformation->MarshalledTargetInfo != NULL)
  1851. {
  1852. RtlCopyMemory(
  1853. TargetInformation->MarshalledTargetInfo,
  1854. Context->pbMarshalledTargetInfo,
  1855. Context->cbMarshalledTargetInfo
  1856. );
  1857. TargetInformation->MarshalledTargetInfoLength = Context->cbMarshalledTargetInfo;
  1858. }
  1859. else
  1860. {
  1861. Status = STATUS_INSUFFICIENT_RESOURCES;
  1862. }
  1863. break;
  1864. case SECPKG_ATTR_LIFESPAN:
  1865. LifespanInfo = (PSecPkgContext_Lifespan) Buffer;
  1866. //
  1867. // BUG 454552: set start time properly.
  1868. //
  1869. LifespanInfo->tsStart.QuadPart = 0;
  1870. LifespanInfo->tsExpiry = Context->Lifetime;
  1871. break;
  1872. case SECPKG_ATTR_FLAGS:
  1873. FlagsInfo = (PSecPkgContext_Flags) Buffer;
  1874. FlagsInfo->Flags = Context->ContextFlags;
  1875. break;
  1876. case SECPKG_ATTR_SESSION_KEY:
  1877. SessionKeyInfo = (PSecPkgContext_SessionKey) Buffer;
  1878. SessionKeyInfo->SessionKeyLength = Context->SessionKey.keyvalue.length;
  1879. if (SessionKeyInfo->SessionKeyLength != 0)
  1880. {
  1881. SessionKeyInfo->SessionKey = (PUCHAR) KspKernelFunctions.AllocateHeap(SessionKeyInfo->SessionKeyLength);
  1882. if (SessionKeyInfo->SessionKey != NULL)
  1883. {
  1884. RtlCopyMemory(
  1885. SessionKeyInfo->SessionKey,
  1886. Context->SessionKey.keyvalue.value,
  1887. Context->SessionKey.keyvalue.length
  1888. );
  1889. }
  1890. else
  1891. {
  1892. Status = STATUS_INSUFFICIENT_RESOURCES;
  1893. }
  1894. }
  1895. else
  1896. {
  1897. SessionKeyInfo->SessionKey = (PUCHAR) KspKernelFunctions.AllocateHeap(1);
  1898. if (SessionKeyInfo->SessionKey != NULL)
  1899. {
  1900. *(PUCHAR) SessionKeyInfo->SessionKey = 0;
  1901. }
  1902. else
  1903. {
  1904. Status = STATUS_INSUFFICIENT_RESOURCES;
  1905. }
  1906. }
  1907. break;
  1908. case SECPKG_ATTR_USER_FLAGS:
  1909. UserFlagsInfo = (PSecPkgContext_UserFlags) Buffer ;
  1910. UserFlagsInfo->UserFlags = 0 ;
  1911. Status = STATUS_SUCCESS ;
  1912. break;
  1913. case SECPKG_ATTR_PACKAGE_INFO:
  1914. case SECPKG_ATTR_NEGOTIATION_INFO:
  1915. //
  1916. // Return the information about this package. This is useful for
  1917. // callers who used SPNEGO and don't know what package they got.
  1918. //
  1919. PackageInfo = (PSecPkgContext_PackageInfo) Buffer;
  1920. PackageInfo->PackageInfo = (PSecPkgInfo) KspKernelFunctions.AllocateHeap(
  1921. sizeof(SecPkgInfo) +
  1922. sizeof(KERBEROS_PACKAGE_NAME) +
  1923. sizeof(KERBEROS_PACKAGE_COMMENT)
  1924. );
  1925. if (PackageInfo->PackageInfo == NULL)
  1926. {
  1927. Status = STATUS_INSUFFICIENT_RESOURCES;
  1928. break;
  1929. }
  1930. PackageInfo->PackageInfo->Name = (LPTSTR) (PackageInfo->PackageInfo + 1);
  1931. PackageInfo->PackageInfo->Comment = (LPTSTR) (((PBYTE) PackageInfo->PackageInfo->Name) + sizeof(KERBEROS_PACKAGE_NAME));
  1932. wcscpy(
  1933. PackageInfo->PackageInfo->Name,
  1934. KERBEROS_PACKAGE_NAME
  1935. );
  1936. wcscpy(
  1937. PackageInfo->PackageInfo->Comment,
  1938. KERBEROS_PACKAGE_COMMENT
  1939. );
  1940. PackageInfo->PackageInfo->wVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
  1941. PackageInfo->PackageInfo->wRPCID = KERBEROS_RPCID;
  1942. PackageInfo->PackageInfo->fCapabilities = KERBEROS_CAPABILITIES;
  1943. PackageInfo->PackageInfo->cbMaxToken = KerbMaxTokenSize;
  1944. if ( ContextAttribute == SECPKG_ATTR_NEGOTIATION_INFO )
  1945. {
  1946. PSecPkgContext_NegotiationInfo NegInfo ;
  1947. NegInfo = (PSecPkgContext_NegotiationInfo) PackageInfo ;
  1948. if( Context != NULL ) {
  1949. NegInfo->NegotiationState = SECPKG_NEGOTIATION_COMPLETE ;
  1950. } else {
  1951. NegInfo->NegotiationState = 0;
  1952. }
  1953. }
  1954. break;
  1955. default:
  1956. Status = STATUS_NOT_SUPPORTED;
  1957. break;
  1958. }
  1959. if (Context != NULL)
  1960. {
  1961. KerbDereferenceContext(Context);
  1962. }
  1963. return(Status);
  1964. }
  1965. //+-------------------------------------------------------------------------
  1966. //
  1967. // Function: KerbCompleteToken
  1968. //
  1969. // Synopsis:
  1970. //
  1971. // Effects:
  1972. //
  1973. // Arguments:
  1974. //
  1975. // Requires:
  1976. //
  1977. // Returns:
  1978. //
  1979. // Notes:
  1980. //
  1981. //
  1982. //--------------------------------------------------------------------------
  1983. NTSTATUS NTAPI
  1984. KerbCompleteToken(
  1985. IN LSA_SEC_HANDLE ContextId,
  1986. IN PSecBufferDesc Token
  1987. )
  1988. {
  1989. PAGED_CODE();
  1990. return(SEC_E_UNSUPPORTED_FUNCTION);
  1991. }
  1992. //+-------------------------------------------------------------------------
  1993. //
  1994. // Function:
  1995. //
  1996. // Synopsis:
  1997. //
  1998. // Effects:
  1999. //
  2000. // Arguments:
  2001. //
  2002. // Requires:
  2003. //
  2004. // Returns:
  2005. //
  2006. // Notes:
  2007. //
  2008. //
  2009. //--------------------------------------------------------------------------
  2010. NTSTATUS
  2011. KerbExportContext(
  2012. IN LSA_SEC_HANDLE Context,
  2013. IN ULONG Flags,
  2014. OUT PSecBuffer PackedContext,
  2015. IN OUT PHANDLE TokenHandle
  2016. )
  2017. {
  2018. return(SEC_E_UNSUPPORTED_FUNCTION);
  2019. }
  2020. //+-------------------------------------------------------------------------
  2021. //
  2022. // Function:
  2023. //
  2024. // Synopsis:
  2025. //
  2026. // Effects:
  2027. //
  2028. // Arguments:
  2029. //
  2030. // Requires:
  2031. //
  2032. // Returns:
  2033. //
  2034. // Notes:
  2035. //
  2036. //
  2037. //--------------------------------------------------------------------------
  2038. NTSTATUS
  2039. KerbImportContext(
  2040. IN PSecBuffer PackedContext,
  2041. IN OPTIONAL HANDLE TokenHandle,
  2042. OUT PLSA_SEC_HANDLE ContextHandle
  2043. )
  2044. {
  2045. NTSTATUS Status;
  2046. PKERB_KERNEL_CONTEXT Context = NULL;
  2047. PAGED_CODE();
  2048. DebugLog((DEB_TRACE,"KerbInitUserModeContext called\n"));
  2049. Status = KerbCreateKernelModeContext(
  2050. 0, // LsaContextHandle not present
  2051. PackedContext,
  2052. &Context
  2053. );
  2054. if (!NT_SUCCESS(Status))
  2055. {
  2056. DebugLog((DEB_ERROR,"Failed to create kernel mode context: 0x%x\n",
  2057. Status));
  2058. goto Cleanup;
  2059. }
  2060. if (!KerbCryptInitialized)
  2061. {
  2062. KerbWriteLockGlobals();
  2063. if ( !KerbCryptInitialized )
  2064. {
  2065. if (LibAttach(NULL, NULL))
  2066. {
  2067. KerbCryptInitialized = TRUE;
  2068. }
  2069. }
  2070. KerbUnlockGlobals();
  2071. }
  2072. KerbWriteLockContexts();
  2073. Context->TokenHandle = TokenHandle;
  2074. *ContextHandle = KerbGetContextHandle(Context);
  2075. Context->ContextAttributes |= KERB_CONTEXT_IMPORTED;
  2076. KerbUnlockContexts();
  2077. Cleanup:
  2078. if (Context != NULL)
  2079. {
  2080. KerbDereferenceContext(Context);
  2081. }
  2082. return(Status);
  2083. }
  2084. NTSTATUS
  2085. KerbSetPageMode(
  2086. BOOLEAN Pagable
  2087. )
  2088. {
  2089. if ( Pagable )
  2090. {
  2091. KerbPoolType = PagedPool ;
  2092. KerbActiveList = KerbPagedList ;
  2093. }
  2094. else
  2095. {
  2096. if ( KerbNonPagedList == NULL )
  2097. {
  2098. KerbNonPagedList = KSecCreateContextList( KSecNonPaged );
  2099. if ( KerbNonPagedList == NULL )
  2100. {
  2101. return STATUS_NO_MEMORY ;
  2102. }
  2103. }
  2104. KerbActiveList = KerbNonPagedList ;
  2105. KerbPoolType = NonPagedPool ;
  2106. }
  2107. return STATUS_SUCCESS ;
  2108. }