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.

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