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.

3003 lines
83 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1999
  6. //
  7. // File: krnlapi.cxx
  8. //
  9. // Contents: Kernel-mode APIs to the NTLM package
  10. //
  11. //
  12. // History: 07-Sep-1996 Created ChandanS
  13. //
  14. //------------------------------------------------------------------------
  15. #include <ntlmkrnl.h>
  16. extern "C"
  17. {
  18. #include <cryptdll.h>
  19. #include <zwapi.h>
  20. }
  21. #include "crc32.h" // How to use crc32
  22. extern "C"
  23. {
  24. #include <rc4.h> // How to use RC4 routine
  25. #include <md5.h>
  26. #include <hmac.h>
  27. }
  28. #define DEFENSIVE_HANDLES
  29. // Context Signatures
  30. #define NTLM_CONTEXT_SIGNATURE 'MLTN'
  31. #define NTLM_CONTEXT_DELETED_SIGNATURE 'XXXX'
  32. // Keep this is sync with NTLM_KERNEL_CONTEXT defined in
  33. // security\msv_sspi\userapi.cxx
  34. typedef struct _NTLM_KERNEL_CONTEXT{
  35. KSEC_LIST_ENTRY List;
  36. ULONG_PTR LsaContext;
  37. ULONG NegotiateFlags;
  38. HANDLE ClientTokenHandle;
  39. PACCESS_TOKEN AccessToken;
  40. PULONG pSendNonce; // ptr to nonce to use for send
  41. PULONG pRecvNonce; // ptr to nonce to use for receive
  42. struct RC4_KEYSTRUCT * pSealRc4Sched; // ptr to key sched used for Seal
  43. struct RC4_KEYSTRUCT * pUnsealRc4Sched; // ptr to key sched used to Unseal
  44. ULONG SendNonce;
  45. ULONG RecvNonce;
  46. LPWSTR ContextNames;
  47. PUCHAR pbMarshalledTargetInfo;
  48. ULONG cbMarshalledTargetInfo;
  49. UCHAR SessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  50. ULONG ContextSignature;
  51. ULONG References ;
  52. TimeStamp PasswordExpiry;
  53. ULONG UserFlags;
  54. UCHAR SignSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  55. UCHAR VerifySessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  56. UCHAR SealSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  57. UCHAR UnsealSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  58. ULONG64 Pad1; // pad keystructs to 64.
  59. struct RC4_KEYSTRUCT SealRc4Sched; // key struct used for Seal
  60. ULONG64 Pad2; // pad keystructs to 64.
  61. struct RC4_KEYSTRUCT UnsealRc4Sched; // key struct used to Unseal
  62. } NTLM_KERNEL_CONTEXT, * PNTLM_KERNEL_CONTEXT;
  63. typedef struct _NTLM_PACKED_CONTEXT {
  64. ULONG Tag ;
  65. ULONG NegotiateFlags ;
  66. ULONG ClientTokenHandle ;
  67. ULONG SendNonce ;
  68. ULONG RecvNonce ;
  69. UCHAR SessionKey[ MSV1_0_USER_SESSION_KEY_LENGTH ];
  70. ULONG ContextSignature ;
  71. TimeStamp PasswordExpiry ;
  72. ULONG UserFlags ;
  73. ULONG ContextNames ;
  74. ULONG ContextNameLength ;
  75. ULONG MarshalledTargetInfo; // offset
  76. ULONG MarshalledTargetInfoLength;
  77. UCHAR SignSessionKey[ MSV1_0_USER_SESSION_KEY_LENGTH ];
  78. UCHAR VerifySessionKey[ MSV1_0_USER_SESSION_KEY_LENGTH ];
  79. UCHAR SealSessionKey[ MSV1_0_USER_SESSION_KEY_LENGTH ];
  80. UCHAR UnsealSessionKey[ MSV1_0_USER_SESSION_KEY_LENGTH ];
  81. struct RC4_KEYSTRUCT SealRc4Sched;
  82. struct RC4_KEYSTRUCT UnsealRc4Sched;
  83. } NTLM_PACKED_CONTEXT, * PNTLM_PACKED_CONTEXT ;
  84. #define NTLM_PACKED_CONTEXT_MAP 0
  85. #define CSSEALMAGIC "session key to client-to-server sealing key magic constant"
  86. #define SCSEALMAGIC "session key to server-to-client sealing key magic constant"
  87. #define CSSIGNMAGIC "session key to client-to-server signing key magic constant"
  88. #define SCSIGNMAGIC "session key to server-to-client signing key magic constant"
  89. typedef enum _eSignSealOp {
  90. eSign, // MakeSignature is calling
  91. eVerify, // VerifySignature is calling
  92. eSeal, // SealMessage is calling
  93. eUnseal // UnsealMessage is calling
  94. } eSignSealOp;
  95. //
  96. // Make these extern "C" to allow them to be pageable.
  97. //
  98. extern "C"
  99. {
  100. KspInitPackageFn NtLmInitKernelPackage;
  101. KspDeleteContextFn NtLmDeleteKernelContext;
  102. KspInitContextFn NtLmInitKernelContext;
  103. KspMapHandleFn NtLmMapKernelHandle;
  104. KspMakeSignatureFn NtLmMakeSignature;
  105. KspVerifySignatureFn NtLmVerifySignature;
  106. KspSealMessageFn NtLmSealMessage;
  107. KspUnsealMessageFn NtLmUnsealMessage;
  108. KspGetTokenFn NtLmGetContextToken;
  109. KspQueryAttributesFn NtLmQueryContextAttributes;
  110. KspCompleteTokenFn NtLmCompleteToken;
  111. SpExportSecurityContextFn NtLmExportSecurityContext;
  112. SpImportSecurityContextFn NtLmImportSecurityContext;
  113. KspSetPagingModeFn NtlmSetPagingMode ;
  114. //
  115. // Local prototypes:
  116. //
  117. NTSTATUS
  118. NtLmCreateKernelModeContext(
  119. IN ULONG ContextHandle,
  120. IN PSecBuffer MarshalledContext,
  121. OUT PNTLM_KERNEL_CONTEXT * NewContext
  122. );
  123. NTSTATUS
  124. NtLmMakePackedContext(
  125. IN PNTLM_KERNEL_CONTEXT Context,
  126. OUT PBOOLEAN MappedContext,
  127. OUT PSecBuffer ContextData,
  128. IN ULONG Flags
  129. );
  130. NTSTATUS
  131. NtlmFreeKernelContext (
  132. PNTLM_KERNEL_CONTEXT KernelContext
  133. );
  134. #define NtlmReferenceContext( Context, Remove ) \
  135. KSecReferenceListEntry( (PKSEC_LIST_ENTRY) Context, \
  136. NTLM_CONTEXT_SIGNATURE, \
  137. Remove )
  138. VOID
  139. NtlmDerefContext(
  140. PNTLM_KERNEL_CONTEXT Context
  141. );
  142. void
  143. SspGenCheckSum(
  144. IN PSecBuffer pMessage,
  145. OUT PNTLMSSP_MESSAGE_SIGNATURE pSig
  146. );
  147. VOID
  148. SspEncryptBuffer(
  149. IN PNTLM_KERNEL_CONTEXT pContext,
  150. IN struct RC4_KEYSTRUCT * pRc4Key,
  151. IN ULONG BufferSize,
  152. IN OUT PVOID Buffer
  153. );
  154. VOID
  155. SspRc4Key(
  156. IN ULONG NegotiateFlags,
  157. OUT struct RC4_KEYSTRUCT *pRc4Key,
  158. IN PUCHAR pSessionKey
  159. );
  160. SECURITY_STATUS
  161. SspSignSealHelper(
  162. IN PNTLM_KERNEL_CONTEXT pContext,
  163. IN eSignSealOp Op,
  164. IN OUT PSecBufferDesc pMessage,
  165. IN ULONG MessageSeqNo,
  166. OUT PNTLMSSP_MESSAGE_SIGNATURE pSig,
  167. OUT PNTLMSSP_MESSAGE_SIGNATURE * ppSig
  168. );
  169. } // extern "C"
  170. #ifdef ALLOC_PRAGMA
  171. #pragma alloc_text(PAGE, NtLmInitKernelPackage)
  172. #pragma alloc_text(PAGE, NtLmDeleteKernelContext)
  173. #pragma alloc_text(PAGE, NtLmInitKernelContext)
  174. #pragma alloc_text(PAGE, NtLmMapKernelHandle)
  175. #pragma alloc_text(PAGEMSG, NtLmMakeSignature)
  176. #pragma alloc_text(PAGEMSG, NtLmVerifySignature)
  177. #pragma alloc_text(PAGEMSG, NtLmSealMessage)
  178. #pragma alloc_text(PAGEMSG, NtLmUnsealMessage)
  179. #pragma alloc_text(PAGEMSG, NtLmGetContextToken)
  180. #pragma alloc_text(PAGEMSG, NtLmQueryContextAttributes)
  181. #pragma alloc_text(PAGEMSG, NtlmDerefContext )
  182. #pragma alloc_text(PAGE, NtLmCompleteToken)
  183. #pragma alloc_text(PAGE, NtLmExportSecurityContext)
  184. #pragma alloc_text(PAGE, NtLmImportSecurityContext)
  185. #pragma alloc_text(PAGEMSG, NtlmFreeKernelContext )
  186. #pragma alloc_text(PAGE, NtLmCreateKernelModeContext )
  187. #pragma alloc_text(PAGE, NtLmMakePackedContext )
  188. #pragma alloc_text(PAGEMSG, SspGenCheckSum)
  189. #pragma alloc_text(PAGEMSG, SspEncryptBuffer)
  190. #pragma alloc_text(PAGE, SspRc4Key)
  191. #pragma alloc_text(PAGEMSG, SspSignSealHelper)
  192. #endif
  193. SECPKG_KERNEL_FUNCTION_TABLE NtLmFunctionTable = {
  194. NtLmInitKernelPackage,
  195. NtLmDeleteKernelContext,
  196. NtLmInitKernelContext,
  197. NtLmMapKernelHandle,
  198. NtLmMakeSignature,
  199. NtLmVerifySignature,
  200. NtLmSealMessage,
  201. NtLmUnsealMessage,
  202. NtLmGetContextToken,
  203. NtLmQueryContextAttributes,
  204. NtLmCompleteToken,
  205. NtLmExportSecurityContext,
  206. NtLmImportSecurityContext,
  207. NtlmSetPagingMode
  208. };
  209. PSECPKG_KERNEL_FUNCTIONS LsaKernelFunctions;
  210. POOL_TYPE NtlmPoolType ;
  211. PVOID NtlmPagedList ;
  212. PVOID NtlmNonPagedList ;
  213. PVOID NtlmActiveList ;
  214. #define MAYBE_PAGED_CODE() \
  215. if ( NtlmPoolType == PagedPool ) \
  216. { \
  217. PAGED_CODE(); \
  218. }
  219. //+-------------------------------------------------------------------------
  220. //
  221. // Function: FreeKernelContext
  222. //
  223. // Synopsis: frees alloced pointers in this context and
  224. // then frees the context
  225. //
  226. // Arguments: KernelContext - the unlinked kernel context
  227. //
  228. // Returns: STATUS_SUCCESS on success
  229. //
  230. // Notes:
  231. //
  232. //--------------------------------------------------------------------------
  233. NTSTATUS
  234. NtlmFreeKernelContext (
  235. PNTLM_KERNEL_CONTEXT KernelContext
  236. )
  237. {
  238. NTSTATUS Status = STATUS_SUCCESS;
  239. MAYBE_PAGED_CODE();
  240. DebugLog(( DEB_TRACE, "Entering FreeKernelContext\n" ));
  241. if (KernelContext->ContextNames != NULL)
  242. {
  243. NtLmFree (KernelContext->ContextNames);
  244. }
  245. if (KernelContext->ClientTokenHandle != NULL)
  246. {
  247. NTSTATUS IgnoreStatus;
  248. #ifdef DEFENSIVE_HANDLES
  249. OBJECT_HANDLE_FLAG_INFORMATION HandleInfo ;
  250. HandleInfo.Inherit = FALSE ;
  251. HandleInfo.ProtectFromClose = FALSE ;
  252. IgnoreStatus = ZwSetInformationObject(
  253. KernelContext->ClientTokenHandle,
  254. ObjectHandleFlagInformation,
  255. &HandleInfo,
  256. sizeof(HandleInfo) );
  257. ASSERT( NT_SUCCESS( IgnoreStatus ) );
  258. #endif
  259. IgnoreStatus = NtClose( KernelContext->ClientTokenHandle);
  260. ASSERT (NT_SUCCESS (IgnoreStatus));
  261. }
  262. if (KernelContext->AccessToken != NULL)
  263. {
  264. ObDereferenceObject (KernelContext->AccessToken);
  265. }
  266. DebugLog(( DEB_TRACE, "Deleting Context 0x%lx\n", KernelContext));
  267. NtLmFree (KernelContext);
  268. DebugLog(( DEB_TRACE, "Leaving FreeKernelContext: 0x%lx\n", Status ));
  269. return Status;
  270. }
  271. //+---------------------------------------------------------------------------
  272. //
  273. // Function: NtlmDerefContext
  274. //
  275. // Synopsis: Dereference a kernel context
  276. //
  277. // Arguments: [Context] --
  278. //
  279. // History: 7-07-98 RichardW Created
  280. //
  281. // Notes:
  282. //
  283. //----------------------------------------------------------------------------
  284. VOID
  285. NtlmDerefContext(
  286. PNTLM_KERNEL_CONTEXT Context
  287. )
  288. {
  289. BOOLEAN Delete ;
  290. MAYBE_PAGED_CODE();
  291. KSecDereferenceListEntry(
  292. &Context->List,
  293. &Delete );
  294. if ( Delete )
  295. {
  296. NtlmFreeKernelContext( Context );
  297. }
  298. }
  299. //+-------------------------------------------------------------------------
  300. //
  301. // Function: NtLmInitKernelPackage
  302. //
  303. // Synopsis: Initialize an instance of the NtLm package in
  304. // a client's (kernel) address space
  305. //
  306. // Arguments: None
  307. //
  308. // Returns: STATUS_SUCCESS or
  309. // returns from ExInitializeResource
  310. //
  311. // Notes: we do what was done in SpInstanceInit()
  312. // from security\msv_sspi\userapi.cxx
  313. //
  314. //--------------------------------------------------------------------------
  315. NTSTATUS NTAPI
  316. NtLmInitKernelPackage(
  317. IN PSECPKG_KERNEL_FUNCTIONS KernelFunctions
  318. )
  319. {
  320. NTSTATUS Status = STATUS_SUCCESS;
  321. PAGED_CODE();
  322. DebugLog(( DEB_TRACE, "Entering NtLmInitKernelPackage\n" ));
  323. LsaKernelFunctions = KernelFunctions;
  324. //
  325. // Set up Context list support:
  326. //
  327. NtlmPoolType = PagedPool ;
  328. NtlmPagedList = LsaKernelFunctions->CreateContextList( KSecPaged );
  329. if ( !NtlmPagedList )
  330. {
  331. return STATUS_NO_MEMORY ;
  332. }
  333. NtlmActiveList = NtlmPagedList ;
  334. DebugLog(( DEB_TRACE, "Leaving NtLmInitKernelPackage 0x%lx\n", Status ));
  335. return(Status);
  336. }
  337. //+-------------------------------------------------------------------------
  338. //
  339. // Function: NtLmDeleteKernelContext
  340. //
  341. // Synopsis: Deletes a kernel mode context by unlinking it and then
  342. // dereferencing it.
  343. //
  344. // Effects:
  345. //
  346. // Arguments: KernelContextHandle - Kernel context handle of the context to delete
  347. // LsaContextHandle - The Lsa mode handle
  348. //
  349. // Requires:
  350. //
  351. // Returns: STATUS_SUCCESS on success, STATUS_INVALID_HANDLE if the
  352. // context can't be located
  353. //
  354. // Notes:
  355. //
  356. //
  357. //--------------------------------------------------------------------------
  358. NTSTATUS NTAPI
  359. NtLmDeleteKernelContext(
  360. IN ULONG_PTR KernelContextHandle,
  361. OUT PULONG_PTR LsaContextHandle
  362. )
  363. {
  364. PNTLM_KERNEL_CONTEXT pContext = NULL;
  365. NTSTATUS Status = STATUS_SUCCESS, SaveStatus = STATUS_SUCCESS;
  366. PAGED_CODE();
  367. DebugLog(( DEB_TRACE, "Entering NtLmDeleteKernelContext\n" ));
  368. Status = NtlmReferenceContext( KernelContextHandle, TRUE );
  369. if ( NT_SUCCESS( Status ) )
  370. {
  371. pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  372. }
  373. else
  374. {
  375. *LsaContextHandle = KernelContextHandle;
  376. DebugLog(( DEB_ERROR,
  377. "Bad kernel context 0x%lx\n", KernelContextHandle));
  378. goto CleanUp;
  379. }
  380. *LsaContextHandle = pContext->LsaContext;
  381. if ((pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_EXPORTED_CONTEXT) != 0)
  382. {
  383. // Ignore all other errors and pass back
  384. SaveStatus = SEC_I_NO_LSA_CONTEXT;
  385. }
  386. CleanUp:
  387. if (pContext != NULL)
  388. {
  389. NtlmDerefContext( pContext );
  390. }
  391. if (SaveStatus == SEC_I_NO_LSA_CONTEXT)
  392. {
  393. Status = SaveStatus;
  394. }
  395. DebugLog(( DEB_TRACE, "Leaving NtLmDeleteKernelContext 0x%lx\n", Status ));
  396. return(Status);
  397. }
  398. //+-------------------------------------------------------------------------
  399. //
  400. // Function: NtLmInitKernelContext
  401. //
  402. // Synopsis: Creates a kernel-mode context from a packed LSA mode context
  403. //
  404. // Arguments: LsaContextHandle - Lsa mode context handle for the context
  405. // PackedContext - A marshalled buffer containing the LSA
  406. // mode context.
  407. //
  408. // Requires:
  409. //
  410. // Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
  411. //
  412. // Notes:
  413. //
  414. //--------------------------------------------------------------------------
  415. NTSTATUS NTAPI
  416. NtLmInitKernelContext(
  417. IN ULONG_PTR LsaContextHandle,
  418. IN PSecBuffer PackedContext,
  419. OUT PULONG_PTR NewContextHandle
  420. )
  421. {
  422. NTSTATUS Status = STATUS_SUCCESS;
  423. PNTLM_KERNEL_CONTEXT pContext = NULL;
  424. PNTLM_PACKED_CONTEXT pTmpContext = (PNTLM_PACKED_CONTEXT) PackedContext->pvBuffer;
  425. PAGED_CODE();
  426. DebugLog(( DEB_TRACE, "Entering NtLmInitKernelContext\n" ));
  427. *NewContextHandle = NULL;
  428. if (PackedContext->cbBuffer < sizeof(NTLM_PACKED_CONTEXT))
  429. {
  430. Status = STATUS_INVALID_PARAMETER;
  431. DebugLog(( DEB_ERROR,
  432. "Bad size of Packed context 0x%lx\n", PackedContext->cbBuffer));
  433. goto Cleanup;
  434. }
  435. pContext = (PNTLM_KERNEL_CONTEXT) NtLmAllocate(
  436. sizeof(NTLM_KERNEL_CONTEXT) +
  437. pTmpContext->MarshalledTargetInfoLength
  438. );
  439. if (!pContext)
  440. {
  441. Status = STATUS_INSUFFICIENT_RESOURCES;
  442. DebugLog(( DEB_ERROR, "Allocation error for pContext\n"));
  443. goto Cleanup;
  444. }
  445. RtlZeroMemory(
  446. pContext,
  447. sizeof(NTLM_KERNEL_CONTEXT)
  448. );
  449. KsecInitializeListEntry( &pContext->List, NTLM_CONTEXT_SIGNATURE );
  450. // Copy contents of PackedContext->pvBuffer to pContext
  451. pContext->ClientTokenHandle = (HANDLE) ULongToPtr(pTmpContext->ClientTokenHandle);
  452. #ifdef DEFENSIVE_HANDLES
  453. if ( pContext->ClientTokenHandle )
  454. {
  455. OBJECT_HANDLE_FLAG_INFORMATION HandleInfo ;
  456. POBJECT_TYPE_INFORMATION TypeInfo ;
  457. NTSTATUS IgnoreStatus = STATUS_SUCCESS ;
  458. UNICODE_STRING TokenTypeName ;
  459. TypeInfo = (POBJECT_TYPE_INFORMATION) ExAllocatePoolWithTag( PagedPool, sizeof( OBJECT_TYPE_INFORMATION ) + 16, NTLM_KRNL_POOL_TAG );
  460. if ( TypeInfo )
  461. {
  462. IgnoreStatus = ZwQueryObject(pContext->ClientTokenHandle,
  463. ObjectTypeInformation,
  464. TypeInfo,
  465. (sizeof( OBJECT_TYPE_INFORMATION ) + 16 ),
  466. NULL );
  467. if ( NT_SUCCESS( IgnoreStatus ) )
  468. {
  469. RtlInitUnicodeString( &TokenTypeName, L"Token" );
  470. if ( !RtlEqualUnicodeString( &TypeInfo->TypeName, &TokenTypeName, FALSE ))
  471. {
  472. IgnoreStatus = STATUS_INVALID_HANDLE ;
  473. }
  474. }
  475. else if ( IgnoreStatus != STATUS_INVALID_HANDLE )
  476. {
  477. IgnoreStatus = STATUS_SUCCESS ;
  478. }
  479. ExFreePool( TypeInfo );
  480. }
  481. if ( !NT_SUCCESS( IgnoreStatus ) )
  482. {
  483. ASSERT( NT_SUCCESS( IgnoreStatus ) );
  484. Status = IgnoreStatus ;
  485. DebugLog(( DEB_ERROR, "Bad token handle from LSA: %p\n", pContext->ClientTokenHandle ));
  486. goto Cleanup;
  487. }
  488. HandleInfo.Inherit = FALSE ;
  489. HandleInfo.ProtectFromClose = TRUE ;
  490. IgnoreStatus = ZwSetInformationObject(
  491. pContext->ClientTokenHandle,
  492. ObjectHandleFlagInformation,
  493. &HandleInfo,
  494. sizeof( HandleInfo ) );
  495. }
  496. #endif
  497. pContext->LsaContext = LsaContextHandle;
  498. pContext->NegotiateFlags = pTmpContext->NegotiateFlags;
  499. //
  500. // keep all 128 bits here, so signing can be strong even if encrypt can't be
  501. //
  502. RtlCopyMemory( pContext->SessionKey,
  503. pTmpContext->SessionKey,
  504. MSV1_0_USER_SESSION_KEY_LENGTH);
  505. //
  506. // if doing full duplex as part of NTLM2, generate different sign
  507. // and seal keys for each direction
  508. // all we do is MD5 the base session key with a different magic constant
  509. //
  510. if ( pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2 ) {
  511. MD5_CTX Md5Context;
  512. ULONG KeyLen;
  513. ASSERT(MD5DIGESTLEN == MSV1_0_USER_SESSION_KEY_LENGTH);
  514. if( pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_128 )
  515. KeyLen = 16;
  516. else if( pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_56 )
  517. KeyLen = 7;
  518. else
  519. KeyLen = 5;
  520. // DebugLog(( SSP_SESSION_KEYS, "NTLMv2 session key size: %lu\n", KeyLen));
  521. //
  522. // make client to server encryption key
  523. //
  524. MD5Init(&Md5Context);
  525. MD5Update(&Md5Context, pContext->SessionKey, KeyLen);
  526. MD5Update(&Md5Context, (unsigned char*)CSSEALMAGIC, sizeof(CSSEALMAGIC));
  527. MD5Final(&Md5Context);
  528. //
  529. // if TokenHandle == NULL, this is the client side
  530. // put key in the right place: for client it's seal, for server it's unseal
  531. //
  532. if (pContext->ClientTokenHandle == NULL)
  533. RtlCopyMemory(pContext->SealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  534. else
  535. RtlCopyMemory(pContext->UnsealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  536. //
  537. // make server to client encryption key
  538. //
  539. MD5Init(&Md5Context);
  540. MD5Update(&Md5Context, pContext->SessionKey, KeyLen);
  541. MD5Update(&Md5Context, (unsigned char*)SCSEALMAGIC, sizeof(SCSEALMAGIC));
  542. MD5Final(&Md5Context);
  543. ASSERT(MD5DIGESTLEN == MSV1_0_USER_SESSION_KEY_LENGTH);
  544. if (pContext->ClientTokenHandle == NULL)
  545. RtlCopyMemory(pContext->UnsealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  546. else
  547. RtlCopyMemory(pContext->SealSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  548. //
  549. // make client to server signing key -- always 128 bits!
  550. //
  551. MD5Init(&Md5Context);
  552. MD5Update(&Md5Context, pContext->SessionKey, MSV1_0_USER_SESSION_KEY_LENGTH);
  553. MD5Update(&Md5Context, (unsigned char*)CSSIGNMAGIC, sizeof(CSSIGNMAGIC));
  554. MD5Final(&Md5Context);
  555. if (pContext->ClientTokenHandle == NULL)
  556. RtlCopyMemory(pContext->SignSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  557. else
  558. RtlCopyMemory(pContext->VerifySessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  559. //
  560. // make server to client signing key
  561. //
  562. MD5Init(&Md5Context);
  563. MD5Update(&Md5Context, pContext->SessionKey, MSV1_0_USER_SESSION_KEY_LENGTH);
  564. MD5Update(&Md5Context, (unsigned char*)SCSIGNMAGIC, sizeof(SCSIGNMAGIC));
  565. MD5Final(&Md5Context);
  566. if (pContext->ClientTokenHandle == NULL)
  567. RtlCopyMemory(pContext->VerifySessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  568. else
  569. RtlCopyMemory(pContext->SignSessionKey, Md5Context.digest, MSV1_0_USER_SESSION_KEY_LENGTH);
  570. //
  571. // set pointers to different key schedule and nonce for each direction
  572. // key schedule will be filled in later...
  573. //
  574. pContext->pSealRc4Sched = &pContext->SealRc4Sched;
  575. pContext->pUnsealRc4Sched = &pContext->UnsealRc4Sched;
  576. pContext->pSendNonce = &pContext->SendNonce;
  577. pContext->pRecvNonce = &pContext->RecvNonce;
  578. } else {
  579. //
  580. // just copy session key to all four keys
  581. // leave them 128 bits -- they get cut to 40 bits later
  582. //
  583. RtlCopyMemory( pContext->SealSessionKey,
  584. pContext->SessionKey,
  585. MSV1_0_USER_SESSION_KEY_LENGTH);
  586. RtlCopyMemory( pContext->UnsealSessionKey,
  587. pContext->SessionKey,
  588. MSV1_0_USER_SESSION_KEY_LENGTH);
  589. RtlCopyMemory( pContext->SignSessionKey,
  590. pContext->SessionKey,
  591. MSV1_0_USER_SESSION_KEY_LENGTH);
  592. RtlCopyMemory( pContext->VerifySessionKey,
  593. pContext->SessionKey,
  594. MSV1_0_USER_SESSION_KEY_LENGTH);
  595. //
  596. // set pointers to share a key schedule and nonce for each direction
  597. // (OK because half duplex!)
  598. //
  599. pContext->pSealRc4Sched = &pContext->SealRc4Sched;
  600. pContext->pUnsealRc4Sched = &pContext->SealRc4Sched;
  601. pContext->pSendNonce = &pContext->SendNonce;
  602. pContext->pRecvNonce = &pContext->SendNonce;
  603. }
  604. if ( pTmpContext->ContextNameLength == 0 )
  605. {
  606. //There's no string after the NTLM_KERNEL_CONTEXT struct
  607. pContext->ContextNames = NULL;
  608. }
  609. else
  610. {
  611. pContext->ContextNames = (LPWSTR) NtLmAllocate( pTmpContext->ContextNameLength );
  612. if (!pContext->ContextNames)
  613. {
  614. Status = STATUS_INSUFFICIENT_RESOURCES;
  615. goto Cleanup;
  616. }
  617. RtlCopyMemory(pContext->ContextNames,
  618. (PUCHAR) pTmpContext + pTmpContext->ContextNames,
  619. pTmpContext->ContextNameLength );
  620. }
  621. if( pTmpContext->MarshalledTargetInfo )
  622. {
  623. pContext->pbMarshalledTargetInfo = (PUCHAR)(pContext+1);
  624. pContext->cbMarshalledTargetInfo = pTmpContext->MarshalledTargetInfoLength;
  625. RtlCopyMemory( pContext->pbMarshalledTargetInfo,
  626. (PUCHAR) pTmpContext + pTmpContext->MarshalledTargetInfo,
  627. pTmpContext->MarshalledTargetInfoLength );
  628. }
  629. pContext->SendNonce = pTmpContext->SendNonce;
  630. pContext->RecvNonce = pTmpContext->RecvNonce;
  631. SspRc4Key(pContext->NegotiateFlags, &pContext->SealRc4Sched, pContext->SealSessionKey);
  632. SspRc4Key(pContext->NegotiateFlags, &pContext->UnsealRc4Sched, pContext->UnsealSessionKey);
  633. pContext->PasswordExpiry = pTmpContext->PasswordExpiry;
  634. pContext->UserFlags = pTmpContext->UserFlags;
  635. KSecInsertListEntry(
  636. NtlmActiveList,
  637. &pContext->List );
  638. NtlmDerefContext( pContext );
  639. *NewContextHandle = (ULONG_PTR) pContext;
  640. Cleanup:
  641. if (!NT_SUCCESS(Status))
  642. {
  643. if (pContext != NULL)
  644. {
  645. NtlmFreeKernelContext( pContext );
  646. }
  647. }
  648. if (PackedContext->pvBuffer != NULL)
  649. {
  650. LsaKernelFunctions->FreeHeap(PackedContext->pvBuffer);
  651. PackedContext->pvBuffer = NULL;
  652. }
  653. DebugLog(( DEB_TRACE, "Leaving NtLmInitKernelContext 0x%lx\n", Status ));
  654. return(Status);
  655. }
  656. //+-------------------------------------------------------------------------
  657. //
  658. // Function: NtLmMapKernelHandle
  659. //
  660. // Synopsis: Maps a kernel handle into an LSA handle
  661. //
  662. // Arguments: KernelContextHandle - Kernel context handle of the context to map
  663. // LsaContextHandle - Receives LSA context handle of the context
  664. // to map
  665. //
  666. // Returns: STATUS_SUCCESS on success
  667. //
  668. // Notes:
  669. //
  670. //--------------------------------------------------------------------------
  671. NTSTATUS NTAPI
  672. NtLmMapKernelHandle(
  673. IN ULONG_PTR KernelContextHandle,
  674. OUT PULONG_PTR LsaContextHandle
  675. )
  676. {
  677. NTSTATUS Status = STATUS_SUCCESS;
  678. PNTLM_KERNEL_CONTEXT Context = NULL;
  679. PAGED_CODE();
  680. DebugLog((DEB_TRACE,"Entering NtLmMapKernelhandle\n"));
  681. Status = NtlmReferenceContext( KernelContextHandle, FALSE );
  682. if ( NT_SUCCESS( Status ) )
  683. {
  684. Context = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  685. *LsaContextHandle = Context->LsaContext ;
  686. NtlmDerefContext( Context );
  687. }
  688. else
  689. {
  690. DebugLog(( DEB_WARN, "Invalid context handle - %x\n",
  691. KernelContextHandle ));
  692. *LsaContextHandle = KernelContextHandle ;
  693. }
  694. DebugLog((DEB_TRACE,"Leaving NtLmMapKernelhandle 0x%lx\n", Status));
  695. return (Status);
  696. }
  697. //
  698. // Bogus add-shift check sum
  699. //
  700. void
  701. SspGenCheckSum(
  702. IN PSecBuffer pMessage,
  703. OUT PNTLMSSP_MESSAGE_SIGNATURE pSig
  704. )
  705. /*++
  706. RoutineDescription:
  707. Generate a crc-32 checksum for a buffer
  708. Arguments:
  709. Return Value:
  710. Notes: This was stolen from net\svcdlls\ntlmssp\client\sign.c ,
  711. routine SspGenCheckSum. It's possible that
  712. bugs got copied too
  713. --*/
  714. {
  715. MAYBE_PAGED_CODE();
  716. Crc32(pSig->CheckSum,pMessage->cbBuffer,pMessage->pvBuffer,&pSig->CheckSum);
  717. }
  718. VOID
  719. SspEncryptBuffer(
  720. IN PNTLM_KERNEL_CONTEXT pContext,
  721. IN struct RC4_KEYSTRUCT * pRc4Key,
  722. IN ULONG BufferSize,
  723. IN OUT PVOID Buffer
  724. )
  725. /*++
  726. RoutineDescription:
  727. Encrypts a buffer with the RC4 key in the context. If the context
  728. is for a datagram session, then the key is copied before being used
  729. to encrypt the buffer.
  730. Arguments:
  731. pContext - Context containing the key to encrypt the data
  732. BufferSize - Length of buffer in bytes
  733. Buffer - Buffer to encrypt.
  734. Notes: This was stolen from net\svcdlls\ntlmssp\client\sign.c ,
  735. routine SspEncryptBuffer. It's possible that
  736. bugs got copied too
  737. Return Value:
  738. --*/
  739. {
  740. MAYBE_PAGED_CODE();
  741. struct RC4_KEYSTRUCT TemporaryKey;
  742. struct RC4_KEYSTRUCT * EncryptionKey = pRc4Key;
  743. if (BufferSize == 0)
  744. {
  745. return;
  746. }
  747. //
  748. // For datagram (application supplied sequence numbers) before NTLM2
  749. // we used to copy the key before encrypting so we don't
  750. // have a changing key; but that reused the key stream. Now we only
  751. // do that when backwards compatibility is explicitly called for.
  752. //
  753. if (((pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) != 0) &&
  754. ((pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) == 0) ) {
  755. RtlCopyMemory(
  756. &TemporaryKey,
  757. EncryptionKey,
  758. sizeof(TemporaryKey)
  759. );
  760. EncryptionKey = &TemporaryKey;
  761. }
  762. rc4(
  763. EncryptionKey,
  764. BufferSize,
  765. (PUCHAR) Buffer
  766. );
  767. }
  768. VOID
  769. SspRc4Key(
  770. IN ULONG NegotiateFlags,
  771. OUT struct RC4_KEYSTRUCT *pRc4Key,
  772. IN PUCHAR pSessionKey
  773. )
  774. /*++
  775. RoutineDescription:
  776. Create an RC4 key schedule, making sure key length is OK for export
  777. Arguments:
  778. NegotiateFlags negotiate feature flags; NTLM2 bit is only one looked at
  779. pRc4Key pointer to RC4 key schedule structure; filled in by this routine
  780. pSessionKey pointer to session key -- must be full 16 bytes
  781. Return Value:
  782. --*/
  783. {
  784. PAGED_CODE();
  785. //
  786. // For NTLM2, effective length was already cut down
  787. //
  788. if ((NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) != 0) {
  789. rc4_key(pRc4Key, MSV1_0_USER_SESSION_KEY_LENGTH, pSessionKey);
  790. } else if( NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY ) {
  791. UCHAR Key[MSV1_0_LANMAN_SESSION_KEY_LENGTH];
  792. ULONG KeyLen;
  793. ASSERT(MSV1_0_LANMAN_SESSION_KEY_LENGTH == 8);
  794. // prior to Win2k, negotiated key strength had no bearing on
  795. // key size. So, to allow proper interop to NT4, we don't
  796. // worry about 128bit. 56bit and 40bit are the only supported options.
  797. // 56bit is enabled because this was introduced in Win2k, and
  798. // Win2k -> Win2k interops correctly.
  799. //
  800. #if 0
  801. if( NegotiateFlags & NTLMSSP_NEGOTIATE_128 ) {
  802. KeyLen = 8;
  803. } else
  804. #endif
  805. if( NegotiateFlags & NTLMSSP_NEGOTIATE_56 ) {
  806. KeyLen = 7;
  807. //
  808. // Put a well-known salt at the end of the key to
  809. // limit the changing part to 56 bits.
  810. //
  811. Key[7] = 0xa0;
  812. } else {
  813. KeyLen = 5;
  814. //
  815. // Put a well-known salt at the end of the key to
  816. // limit the changing part to 40 bits.
  817. //
  818. Key[5] = 0xe5;
  819. Key[6] = 0x38;
  820. Key[7] = 0xb0;
  821. }
  822. /// DebugLog(( SSP_SESSION_KEYS, "Non NTLMv2 session key size: %lu\n", KeyLen));
  823. RtlCopyMemory(Key,pSessionKey,KeyLen);
  824. rc4_key(pRc4Key, MSV1_0_LANMAN_SESSION_KEY_LENGTH, Key);
  825. } else {
  826. rc4_key(pRc4Key, MSV1_0_USER_SESSION_KEY_LENGTH, pSessionKey);
  827. }
  828. }
  829. SECURITY_STATUS
  830. SspSignSealHelper(
  831. IN PNTLM_KERNEL_CONTEXT pContext,
  832. IN eSignSealOp Op,
  833. IN OUT PSecBufferDesc pMessage,
  834. IN ULONG MessageSeqNo,
  835. OUT PNTLMSSP_MESSAGE_SIGNATURE pSig,
  836. OUT PNTLMSSP_MESSAGE_SIGNATURE * ppSig
  837. )
  838. /*++
  839. RoutineDescription:
  840. Handle signing a message
  841. Arguments:
  842. Return Value:
  843. --*/
  844. {
  845. HMACMD5_CTX HMACMD5Context;
  846. UCHAR TempSig[MD5DIGESTLEN];
  847. NTLMSSP_MESSAGE_SIGNATURE Sig;
  848. int Signature;
  849. ULONG i;
  850. PUCHAR pKey; // ptr to key to use for encryption
  851. PUCHAR pSignKey; // ptr to key to use for signing
  852. PULONG pNonce; // ptr to nonce to use
  853. struct RC4_KEYSTRUCT * pRc4Sched; // ptr to key schedule to use
  854. NTLMSSP_MESSAGE_SIGNATURE AlignedSig;
  855. MAYBE_PAGED_CODE();
  856. Signature = -1;
  857. for (i = 0; i < pMessage->cBuffers; i++)
  858. {
  859. if ((pMessage->pBuffers[i].BufferType & 0xFF) == SECBUFFER_TOKEN)
  860. {
  861. Signature = i;
  862. break;
  863. }
  864. }
  865. if (Signature == -1)
  866. {
  867. return(SEC_E_INVALID_TOKEN);
  868. }
  869. if (pMessage->pBuffers[Signature].cbBuffer < NTLMSSP_MESSAGE_SIGNATURE_SIZE)
  870. {
  871. return(SEC_E_INVALID_TOKEN);
  872. }
  873. *ppSig = (NTLMSSP_MESSAGE_SIGNATURE*)pMessage->pBuffers[Signature].pvBuffer;
  874. RtlCopyMemory( &AlignedSig, *ppSig, sizeof(AlignedSig) );
  875. //
  876. // If sequence detect wasn't requested, put on an empty
  877. // security token . Don't do the check if Seal/Unseal is called.
  878. //
  879. if (!(pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN) &&
  880. (Op == eSign || Op == eVerify))
  881. {
  882. RtlZeroMemory(pSig,NTLMSSP_MESSAGE_SIGNATURE_SIZE);
  883. pSig->Version = NTLM_SIGN_VERSION;
  884. return(SEC_E_OK);
  885. }
  886. // figure out which key, key schedule, and nonce to use
  887. // depends on the op. SspAddLocalContext set up so that code on client
  888. // and server just (un)seals with (un)seal key or key schedule, etc.
  889. // and also sets pointers to share sending/receiving key schedule/nonce
  890. // when in half duplex mode. Hence, this code gets to act as if it were
  891. // always in full duplex mode.
  892. switch (Op) {
  893. case eSeal:
  894. pSignKey = pContext->SignSessionKey; // if NTLM2
  895. pKey = pContext->SealSessionKey;
  896. pRc4Sched = pContext->pSealRc4Sched;
  897. pNonce = pContext->pSendNonce;
  898. break;
  899. case eUnseal:
  900. pSignKey = pContext->VerifySessionKey; // if NTLM2
  901. pKey = pContext->UnsealSessionKey;
  902. pRc4Sched = pContext->pUnsealRc4Sched;
  903. pNonce = pContext->pRecvNonce;
  904. break;
  905. case eSign:
  906. pSignKey = pContext->SignSessionKey; // if NTLM2
  907. pKey = pContext->SealSessionKey; // might be used to encrypt the signature
  908. pRc4Sched = pContext->pSealRc4Sched;
  909. pNonce = pContext->pSendNonce;
  910. break;
  911. case eVerify:
  912. pSignKey = pContext->VerifySessionKey; // if NTLM2
  913. pKey = pContext->UnsealSessionKey; // might be used to decrypt the signature
  914. pRc4Sched = pContext->pUnsealRc4Sched;
  915. pNonce = pContext->pRecvNonce;
  916. break;
  917. default:
  918. ASSERT(FALSE);
  919. return(STATUS_INVALID_LEVEL);
  920. }
  921. //
  922. // Either we can supply the sequence number, or
  923. // the application can supply the message sequence number.
  924. //
  925. Sig.Version = NTLM_SIGN_VERSION;
  926. // if we're doing the new NTLM2 version:
  927. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) {
  928. if ((pContext->NegotiateFlags & NTLMSSP_APP_SEQ) == 0)
  929. {
  930. Sig.Nonce = *pNonce; // use our sequence number
  931. (*pNonce) += 1;
  932. }
  933. else {
  934. if (Op == eSeal || Op == eSign || MessageSeqNo != 0)
  935. Sig.Nonce = MessageSeqNo;
  936. else
  937. Sig.Nonce = AlignedSig.Nonce;
  938. // if using RC4, must rekey for each packet
  939. // RC4 is used for seal, unseal; and for encrypting the HMAC hash if
  940. // key exchange was negotiated (we use just HMAC if no key exchange,
  941. // so that a good signing option exists with no RC4 encryption needed)
  942. if (Op == eSeal || Op == eUnseal || pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
  943. {
  944. MD5_CTX Md5ContextReKey;
  945. MD5Init(&Md5ContextReKey);
  946. MD5Update(&Md5ContextReKey, pKey, MSV1_0_USER_SESSION_KEY_LENGTH);
  947. MD5Update(&Md5ContextReKey, (unsigned char*)&Sig.Nonce, sizeof(Sig.Nonce));
  948. MD5Final(&Md5ContextReKey);
  949. ASSERT(MD5DIGESTLEN == MSV1_0_USER_SESSION_KEY_LENGTH);
  950. SspRc4Key(pContext->NegotiateFlags, pRc4Sched, Md5ContextReKey.digest);
  951. }
  952. }
  953. //
  954. // using HMAC hash, init it with the key
  955. //
  956. HMACMD5Init(&HMACMD5Context, pSignKey, MSV1_0_USER_SESSION_KEY_LENGTH);
  957. //
  958. // include the message sequence number
  959. //
  960. HMACMD5Update(&HMACMD5Context, (unsigned char*)&Sig.Nonce, sizeof(Sig.Nonce));
  961. for (i = 0; i < pMessage->cBuffers ; i++ )
  962. {
  963. if (((pMessage->pBuffers[i].BufferType & 0xFF) == SECBUFFER_DATA) &&
  964. (pMessage->pBuffers[i].cbBuffer != 0))
  965. {
  966. if ((pMessage->pBuffers[i].BufferType & (SECBUFFER_READONLY | SECBUFFER_READONLY_WITH_CHECKSUM))
  967. == (SECBUFFER_READONLY | SECBUFFER_READONLY_WITH_CHECKSUM))
  968. {
  969. //
  970. // FESTER: return INVALID_TOKEN because of data buffers
  971. //
  972. return SEC_E_INVALID_TOKEN;
  973. }
  974. // decrypt (before checksum...) if it's not READ_ONLY
  975. if ( (Op == eUnseal)
  976. && !(pMessage->pBuffers[i].BufferType & (SECBUFFER_READONLY | SECBUFFER_READONLY_WITH_CHECKSUM) )
  977. )
  978. {
  979. SspEncryptBuffer(
  980. pContext,
  981. pRc4Sched,
  982. pMessage->pBuffers[i].cbBuffer,
  983. pMessage->pBuffers[i].pvBuffer
  984. );
  985. }
  986. HMACMD5Update(
  987. &HMACMD5Context,
  988. (unsigned char*)pMessage->pBuffers[i].pvBuffer,
  989. pMessage->pBuffers[i].cbBuffer);
  990. //
  991. // Encrypt if its not READ_ONLY
  992. //
  993. if ( (Op == eSeal)
  994. && !(pMessage->pBuffers[i].BufferType & (SECBUFFER_READONLY | SECBUFFER_READONLY_WITH_CHECKSUM) )
  995. )
  996. {
  997. SspEncryptBuffer(
  998. pContext,
  999. pRc4Sched,
  1000. pMessage->pBuffers[i].cbBuffer,
  1001. pMessage->pBuffers[i].pvBuffer
  1002. );
  1003. }
  1004. }
  1005. }
  1006. HMACMD5Final(&HMACMD5Context, TempSig);
  1007. //
  1008. // use RandomPad and Checksum fields for 8 bytes of MD5 hash
  1009. //
  1010. RtlCopyMemory(&Sig.RandomPad, TempSig, 8);
  1011. //
  1012. // if we're using crypto for KEY_EXCH, may as well use it for signing too...
  1013. //
  1014. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
  1015. SspEncryptBuffer(
  1016. pContext,
  1017. pRc4Sched,
  1018. 8,
  1019. &Sig.RandomPad
  1020. );
  1021. }
  1022. //
  1023. // pre-NTLM2 methods
  1024. //
  1025. else {
  1026. //
  1027. // required by CRC-32 algorithm
  1028. //
  1029. Sig.CheckSum = 0xffffffff;
  1030. for (i = 0; i < pMessage->cBuffers ; i++ )
  1031. {
  1032. if (((pMessage->pBuffers[i].BufferType & 0xFF) == SECBUFFER_DATA)
  1033. && (pMessage->pBuffers[i].cbBuffer != 0))
  1034. {
  1035. if ((pMessage->pBuffers[i].BufferType & (SECBUFFER_READONLY | SECBUFFER_READONLY_WITH_CHECKSUM))
  1036. == (SECBUFFER_READONLY | SECBUFFER_READONLY_WITH_CHECKSUM))
  1037. {
  1038. //
  1039. // FESTER: return invalid token because of data buffers
  1040. //
  1041. return SEC_E_INVALID_TOKEN;
  1042. }
  1043. //
  1044. // retain the "read-only" semantics for NTLMv1
  1045. //
  1046. if (pMessage->pBuffers[i].BufferType & SECBUFFER_READONLY)
  1047. {
  1048. continue;
  1049. }
  1050. // decrypt (before checksum...)
  1051. if ( (Op == eUnseal)
  1052. && !(pMessage->pBuffers[i].BufferType & SECBUFFER_READONLY_WITH_CHECKSUM) )
  1053. {
  1054. SspEncryptBuffer(
  1055. pContext,
  1056. pRc4Sched,
  1057. pMessage->pBuffers[i].cbBuffer,
  1058. pMessage->pBuffers[i].pvBuffer
  1059. );
  1060. }
  1061. SspGenCheckSum(&pMessage->pBuffers[i], &Sig);
  1062. // Encrypt
  1063. if ( (Op == eSeal)
  1064. && !(pMessage->pBuffers[i].BufferType & SECBUFFER_READONLY_WITH_CHECKSUM) )
  1065. {
  1066. SspEncryptBuffer(
  1067. pContext,
  1068. pRc4Sched,
  1069. pMessage->pBuffers[i].cbBuffer,
  1070. pMessage->pBuffers[i].pvBuffer
  1071. );
  1072. }
  1073. }
  1074. }
  1075. //
  1076. // Required by CRC-32 algorithm
  1077. //
  1078. Sig.CheckSum ^= 0xffffffff;
  1079. // when we encrypt 0, we will get the cipher stream for the nonce!
  1080. Sig.Nonce = 0;
  1081. SspEncryptBuffer(
  1082. pContext,
  1083. pRc4Sched,
  1084. sizeof(NTLMSSP_MESSAGE_SIGNATURE) - sizeof(ULONG),
  1085. &Sig.RandomPad
  1086. );
  1087. if ((pContext->NegotiateFlags & NTLMSSP_APP_SEQ) == 0)
  1088. {
  1089. Sig.Nonce ^= *pNonce; // use our sequence number and encrypt it
  1090. (*pNonce) += 1;
  1091. }
  1092. else if (Op == eSeal || Op == eSign || MessageSeqNo != 0)
  1093. Sig.Nonce ^= MessageSeqNo; // use caller's sequence number and encrypt it
  1094. else
  1095. Sig.Nonce = AlignedSig.Nonce; // use sender's sequence number
  1096. //
  1097. // for SignMessage calling, does nothing (copies garbage)
  1098. // For VerifyMessage calling, allows it to compare sig block
  1099. // upon return to Verify without knowing whether its MD5 or CRC32
  1100. //
  1101. Sig.RandomPad = AlignedSig.RandomPad;
  1102. }
  1103. pMessage->pBuffers[Signature].cbBuffer = sizeof(NTLMSSP_MESSAGE_SIGNATURE);
  1104. RtlCopyMemory(
  1105. pSig,
  1106. &Sig,
  1107. NTLMSSP_MESSAGE_SIGNATURE_SIZE
  1108. );
  1109. return(SEC_E_OK);
  1110. }
  1111. //+-------------------------------------------------------------------------
  1112. //
  1113. // Function: NtLmMakeSignature
  1114. //
  1115. // Synopsis: Signs a message buffer by calculatinga checksum over all
  1116. // the non-read only data buffers and encrypting the checksum
  1117. // along with a nonce.
  1118. //
  1119. // Effects:
  1120. //
  1121. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  1122. // message.
  1123. // QualityOfProtection - Unused flags.
  1124. // MessageBuffers - Contains an array of buffers to sign and
  1125. // to store the signature.
  1126. // MessageSequenceNumber - Sequence number for this message,
  1127. // only used in datagram cases.
  1128. //
  1129. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1130. // was not configured for message integrity.
  1131. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1132. // be found.
  1133. // STATUS_BUFFER_TOO_SMALL - the signature buffer is too small
  1134. // to hold the signature
  1135. //
  1136. // Returns:
  1137. //
  1138. // Notes: This was stolen from net\svcdlls\ntlmssp\client\sign.c ,
  1139. // routine SspHandleSignMessage. It's possible that
  1140. // bugs got copied too
  1141. //
  1142. //
  1143. //--------------------------------------------------------------------------
  1144. NTSTATUS NTAPI
  1145. NtLmMakeSignature(
  1146. IN ULONG_PTR KernelContextHandle,
  1147. IN ULONG fQOP,
  1148. IN PSecBufferDesc pMessage,
  1149. IN ULONG MessageSeqNo
  1150. )
  1151. {
  1152. NTSTATUS Status = STATUS_SUCCESS;
  1153. PNTLM_KERNEL_CONTEXT pContext;
  1154. NTLMSSP_MESSAGE_SIGNATURE Sig;
  1155. NTLMSSP_MESSAGE_SIGNATURE *pSig;
  1156. MAYBE_PAGED_CODE();
  1157. DebugLog(( DEB_TRACE, "Entering NtLmMakeSignature\n" ));
  1158. UNREFERENCED_PARAMETER(fQOP);
  1159. Status = NtlmReferenceContext( KernelContextHandle, FALSE );
  1160. if ( NT_SUCCESS( Status ) )
  1161. {
  1162. pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  1163. }
  1164. else
  1165. {
  1166. DebugLog(( DEB_ERROR,
  1167. "Bad kernel context 0x%lx\n", KernelContextHandle));
  1168. goto CleanUp_NoDeref;
  1169. }
  1170. Status = SspSignSealHelper(
  1171. pContext,
  1172. eSign,
  1173. pMessage,
  1174. MessageSeqNo,
  1175. &Sig,
  1176. &pSig
  1177. );
  1178. if( !NT_SUCCESS( Status ) )
  1179. {
  1180. DebugLog(( DEB_ERROR, "NtLmMakeSignature, SspSignSealHelper returns %lx\n", Status ));
  1181. goto CleanUp;
  1182. }
  1183. RtlCopyMemory(
  1184. pSig,
  1185. &Sig,
  1186. NTLMSSP_MESSAGE_SIGNATURE_SIZE
  1187. );
  1188. CleanUp:
  1189. NtlmDerefContext( pContext );
  1190. CleanUp_NoDeref:
  1191. DebugLog(( DEB_TRACE, "Leaving NtLmMakeSignature 0x%lx\n", Status ));
  1192. return(Status);
  1193. }
  1194. //+-------------------------------------------------------------------------
  1195. //
  1196. // Function: NtLmVerifySignature
  1197. //
  1198. // Synopsis: Verifies a signed message buffer by calculating a checksum over all
  1199. // the non-read only data buffers and encrypting the checksum
  1200. // along with a nonce.
  1201. //
  1202. // Effects:
  1203. //
  1204. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  1205. // message.
  1206. // MessageBuffers - Contains an array of signed buffers and
  1207. // a signature buffer.
  1208. // MessageSequenceNumber - Sequence number for this message,
  1209. // only used in datagram cases.
  1210. // QualityOfProtection - Unused flags.
  1211. //
  1212. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1213. // was not configured for message integrity.
  1214. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1215. // be found or was too small.
  1216. //
  1217. // Returns:
  1218. //
  1219. // Notes: This was stolen from net\svcdlls\ntlmssp\client\sign.c ,
  1220. // routine SspHandleVerifyMessage. It's possible that
  1221. // bugs got copied too
  1222. //
  1223. //
  1224. //--------------------------------------------------------------------------
  1225. NTSTATUS NTAPI
  1226. NtLmVerifySignature(
  1227. IN ULONG_PTR KernelContextHandle,
  1228. IN PSecBufferDesc pMessage,
  1229. IN ULONG MessageSeqNo,
  1230. OUT PULONG pfQOP
  1231. )
  1232. {
  1233. NTSTATUS Status = STATUS_SUCCESS;
  1234. PNTLM_KERNEL_CONTEXT pContext;
  1235. NTLMSSP_MESSAGE_SIGNATURE Sig;
  1236. PNTLMSSP_MESSAGE_SIGNATURE pSig; // pointer to buffer with sig in it
  1237. NTLMSSP_MESSAGE_SIGNATURE AlignedSig; // Aligned sig buffer.
  1238. MAYBE_PAGED_CODE();
  1239. DebugLog(( DEB_TRACE, "Entering NtLmVerifySignature\n" ));
  1240. UNREFERENCED_PARAMETER(pfQOP);
  1241. Status = NtlmReferenceContext( KernelContextHandle, FALSE );
  1242. if ( NT_SUCCESS( Status ) )
  1243. {
  1244. pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  1245. }
  1246. else
  1247. {
  1248. DebugLog(( DEB_ERROR,
  1249. "Bad kernel context 0x%lx\n", KernelContextHandle));
  1250. goto CleanUp_NoDeref;
  1251. }
  1252. Status = SspSignSealHelper(
  1253. pContext,
  1254. eVerify,
  1255. pMessage,
  1256. MessageSeqNo,
  1257. &Sig,
  1258. &pSig
  1259. );
  1260. if( !NT_SUCCESS( Status ) )
  1261. {
  1262. DebugLog(( DEB_ERROR, "NtLmVerifySignature, SspSignSealHelper returns %lx\n", Status ));
  1263. goto CleanUp;
  1264. }
  1265. RtlCopyMemory( &AlignedSig, pSig, sizeof( AlignedSig ) );
  1266. if (AlignedSig.Version != NTLM_SIGN_VERSION) {
  1267. Status = SEC_E_INVALID_TOKEN;
  1268. goto CleanUp;
  1269. }
  1270. // validate the signature...
  1271. if (AlignedSig.CheckSum != Sig.CheckSum)
  1272. {
  1273. Status = SEC_E_MESSAGE_ALTERED;
  1274. goto CleanUp;
  1275. }
  1276. // with MD5 sig, this now matters!
  1277. if (AlignedSig.RandomPad != Sig.RandomPad)
  1278. {
  1279. Status = SEC_E_MESSAGE_ALTERED;
  1280. goto CleanUp;
  1281. }
  1282. if (AlignedSig.Nonce != Sig.Nonce)
  1283. {
  1284. Status = SEC_E_OUT_OF_SEQUENCE;
  1285. goto CleanUp;
  1286. }
  1287. CleanUp:
  1288. NtlmDerefContext( pContext );
  1289. CleanUp_NoDeref:
  1290. DebugLog(( DEB_TRACE, "Leaving NtLmVerifySignature 0x%lx\n", Status ));
  1291. return(Status);
  1292. }
  1293. //+-------------------------------------------------------------------------
  1294. //
  1295. // Function: NtLmSealMessage
  1296. //
  1297. // Synopsis: Verifies a signed message buffer by calculating a checksum over all
  1298. // the non-read only data buffers and encrypting the checksum
  1299. // along with a nonce.
  1300. //
  1301. // Effects:
  1302. //
  1303. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  1304. // message.
  1305. // MessageBuffers - Contains an array of signed buffers and
  1306. // a signature buffer.
  1307. // MessageSequenceNumber - Sequence number for this message,
  1308. // only used in datagram cases.
  1309. // QualityOfProtection - Unused flags.
  1310. //
  1311. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1312. // was not configured for message integrity.
  1313. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1314. // be found or was too small.
  1315. //
  1316. // Returns:
  1317. //
  1318. // Notes: This was stolen from net\svcdlls\ntlmssp\client\sign.c ,
  1319. // routine SspHandleSealMessage. It's possible that
  1320. // bugs got copied too
  1321. //
  1322. //
  1323. //--------------------------------------------------------------------------
  1324. NTSTATUS NTAPI
  1325. NtLmSealMessage(
  1326. IN ULONG_PTR KernelContextHandle,
  1327. IN ULONG fQOP,
  1328. IN PSecBufferDesc pMessage,
  1329. IN ULONG MessageSeqNo
  1330. )
  1331. {
  1332. NTSTATUS Status = STATUS_SUCCESS;
  1333. PNTLM_KERNEL_CONTEXT pContext;
  1334. NTLMSSP_MESSAGE_SIGNATURE Sig;
  1335. PNTLMSSP_MESSAGE_SIGNATURE pSig; // pointer to buffer where sig goes
  1336. MAYBE_PAGED_CODE();
  1337. DebugLog(( DEB_TRACE, "Entering NtLmSealMessage\n" ));
  1338. UNREFERENCED_PARAMETER(fQOP);
  1339. Status = NtlmReferenceContext( KernelContextHandle, FALSE );
  1340. if ( NT_SUCCESS( Status ) )
  1341. {
  1342. pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  1343. }
  1344. else
  1345. {
  1346. DebugLog(( DEB_ERROR,
  1347. "Bad kernel context 0x%lx\n", KernelContextHandle));
  1348. goto CleanUp_NoDeref;
  1349. }
  1350. Status = SspSignSealHelper(
  1351. pContext,
  1352. eSeal,
  1353. pMessage,
  1354. MessageSeqNo,
  1355. &Sig,
  1356. &pSig
  1357. );
  1358. if (!NT_SUCCESS(Status))
  1359. {
  1360. DebugLog(( DEB_ERROR, "SpSealMessage, SspSignSealHelper returns %lx\n", Status ));
  1361. goto CleanUp;
  1362. }
  1363. RtlCopyMemory(
  1364. pSig,
  1365. &Sig,
  1366. NTLMSSP_MESSAGE_SIGNATURE_SIZE
  1367. );
  1368. CleanUp:
  1369. NtlmDerefContext( pContext );
  1370. CleanUp_NoDeref:
  1371. DebugLog(( DEB_TRACE, "Leaving NtLmSealMessage 0x%lx\n", Status ));
  1372. return(Status);
  1373. }
  1374. //+-------------------------------------------------------------------------
  1375. //
  1376. // Function: NtLmUnsealMessage
  1377. //
  1378. // Synopsis: Verifies a signed message buffer by calculating a checksum over all
  1379. // the non-read only data buffers and encrypting the checksum
  1380. // along with a nonce.
  1381. //
  1382. // Effects:
  1383. //
  1384. // Arguments: KernelContextHandle - Handle of the context to use to sign the
  1385. // message.
  1386. // MessageBuffers - Contains an array of signed buffers and
  1387. // a signature buffer.
  1388. // MessageSequenceNumber - Sequence number for this message,
  1389. // only used in datagram cases.
  1390. // QualityOfProtection - Unused flags.
  1391. //
  1392. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  1393. // was not configured for message integrity.
  1394. // STATUS_INVALID_PARAMETER - the signature buffer could not
  1395. // be found or was too small.
  1396. //
  1397. // Returns:
  1398. //
  1399. // Notes: This was stolen from net\svcdlls\ntlmssp\client\sign.c ,
  1400. // routine SspHandleUnsealMessage. It's possible that
  1401. // bugs got copied too
  1402. //
  1403. //
  1404. //--------------------------------------------------------------------------
  1405. NTSTATUS NTAPI
  1406. NtLmUnsealMessage(
  1407. IN ULONG_PTR KernelContextHandle,
  1408. IN PSecBufferDesc pMessage,
  1409. IN ULONG MessageSeqNo,
  1410. OUT PULONG pfQOP
  1411. )
  1412. {
  1413. NTSTATUS Status = STATUS_SUCCESS;
  1414. PNTLM_KERNEL_CONTEXT pContext;
  1415. NTLMSSP_MESSAGE_SIGNATURE Sig;
  1416. PNTLMSSP_MESSAGE_SIGNATURE pSig; // pointer to buffer where sig goes
  1417. NTLMSSP_MESSAGE_SIGNATURE AlignedSig; // aligned buffer.
  1418. MAYBE_PAGED_CODE();
  1419. DebugLog(( DEB_TRACE, "Entering NtLmUnsealMessage\n" ));
  1420. UNREFERENCED_PARAMETER(pfQOP);
  1421. Status = NtlmReferenceContext( KernelContextHandle, FALSE );
  1422. if ( NT_SUCCESS( Status ) )
  1423. {
  1424. pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  1425. }
  1426. else
  1427. {
  1428. DebugLog(( DEB_ERROR,
  1429. "Bad kernel context 0x%lx\n", KernelContextHandle));
  1430. goto CleanUp_NoDeref;
  1431. }
  1432. Status = SspSignSealHelper(
  1433. pContext,
  1434. eUnseal,
  1435. pMessage,
  1436. MessageSeqNo,
  1437. &Sig,
  1438. &pSig
  1439. );
  1440. if (!NT_SUCCESS(Status))
  1441. {
  1442. DebugLog(( DEB_ERROR, "SpUnsealMessage, SspSignSealHelper returns %lx\n", Status ));
  1443. goto CleanUp;
  1444. }
  1445. RtlCopyMemory( &AlignedSig, pSig, sizeof(AlignedSig) );
  1446. if (AlignedSig.Version != NTLM_SIGN_VERSION) {
  1447. Status = SEC_E_INVALID_TOKEN;
  1448. goto CleanUp;
  1449. }
  1450. // validate the signature...
  1451. if (AlignedSig.CheckSum != Sig.CheckSum)
  1452. {
  1453. Status = SEC_E_MESSAGE_ALTERED;
  1454. goto CleanUp;
  1455. }
  1456. if (AlignedSig.RandomPad != Sig.RandomPad)
  1457. {
  1458. Status = SEC_E_MESSAGE_ALTERED;
  1459. goto CleanUp;
  1460. }
  1461. if (AlignedSig.Nonce != Sig.Nonce)
  1462. {
  1463. Status = SEC_E_OUT_OF_SEQUENCE;
  1464. goto CleanUp;
  1465. }
  1466. CleanUp:
  1467. NtlmDerefContext( pContext );
  1468. CleanUp_NoDeref:
  1469. DebugLog(( DEB_TRACE, "Leaving NtLmUnsealMessage 0x%lx\n", Status ));
  1470. return (Status);
  1471. }
  1472. //+-------------------------------------------------------------------------
  1473. //
  1474. // Function: NtLmGetContextToken
  1475. //
  1476. // Synopsis: returns a pointer to the token for a server-side context
  1477. //
  1478. // Effects:
  1479. //
  1480. // Arguments:
  1481. //
  1482. // Requires:
  1483. //
  1484. // Returns:
  1485. //
  1486. // Notes:
  1487. //
  1488. //
  1489. //--------------------------------------------------------------------------
  1490. NTSTATUS NTAPI
  1491. NtLmGetContextToken(
  1492. IN ULONG_PTR KernelContextHandle,
  1493. OUT PHANDLE ImpersonationToken,
  1494. OUT OPTIONAL PACCESS_TOKEN *RawToken
  1495. )
  1496. {
  1497. NTSTATUS Status = STATUS_SUCCESS;
  1498. PNTLM_KERNEL_CONTEXT pContext = NULL;
  1499. MAYBE_PAGED_CODE();
  1500. DebugLog(( DEB_TRACE, "Entering NtLmGetContextToken\n" ));
  1501. Status = NtlmReferenceContext( KernelContextHandle, FALSE );
  1502. if ( NT_SUCCESS( Status ) )
  1503. {
  1504. pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  1505. }
  1506. else
  1507. {
  1508. DebugLog(( DEB_ERROR,
  1509. "Bad kernel context 0x%lx\n", KernelContextHandle));
  1510. goto CleanUp_NoDeref;
  1511. }
  1512. if (pContext->ClientTokenHandle == NULL)
  1513. {
  1514. DebugLog(( DEB_ERROR, "Invalid TokenHandle for context 0x%lx\n", pContext ));
  1515. Status= SEC_E_NO_IMPERSONATION;
  1516. goto CleanUp;
  1517. }
  1518. if (ARGUMENT_PRESENT(ImpersonationToken))
  1519. {
  1520. *ImpersonationToken = pContext->ClientTokenHandle;
  1521. }
  1522. if (ARGUMENT_PRESENT(RawToken))
  1523. {
  1524. if (pContext->ClientTokenHandle != NULL)
  1525. {
  1526. if (pContext->AccessToken == NULL)
  1527. {
  1528. Status = ObReferenceObjectByHandle(
  1529. pContext->ClientTokenHandle,
  1530. TOKEN_IMPERSONATE | TOKEN_QUERY,
  1531. NULL,
  1532. ExGetPreviousMode(),
  1533. (PVOID *) &pContext->AccessToken,
  1534. NULL);
  1535. }
  1536. }
  1537. if (NT_SUCCESS(Status))
  1538. {
  1539. ASSERT(pContext->AccessToken != NULL);
  1540. *RawToken = pContext->AccessToken;
  1541. }
  1542. }
  1543. CleanUp:
  1544. NtlmDerefContext( pContext );
  1545. CleanUp_NoDeref:
  1546. DebugLog(( DEB_TRACE, "Leaving NtLmGetContextToken 0x%lx\n", Status ));
  1547. return (Status);
  1548. }
  1549. //+-------------------------------------------------------------------------
  1550. //
  1551. // Function: NtLmQueryContextAttributes
  1552. //
  1553. // Synopsis: Querys attributes of the specified context
  1554. // This API allows a customer of the security
  1555. // services to determine certain attributes of
  1556. // the context. These are: sizes, names, and lifespan.
  1557. //
  1558. // Effects:
  1559. //
  1560. // Arguments:
  1561. //
  1562. // ContextHandle - Handle to the context to query.
  1563. //
  1564. // Attribute - Attribute to query.
  1565. //
  1566. // #define SECPKG_ATTR_SIZES 0
  1567. // #define SECPKG_ATTR_NAMES 1
  1568. // #define SECPKG_ATTR_LIFESPAN 2
  1569. //
  1570. // Buffer - Buffer to copy the data into. The buffer must
  1571. // be large enough to fit the queried attribute.
  1572. //
  1573. //
  1574. // Requires:
  1575. //
  1576. // Returns:
  1577. //
  1578. // STATUS_SUCCESS - Call completed successfully
  1579. //
  1580. // STATUS_INVALID_HANDLE -- Credential/Context Handle is invalid
  1581. // STATUS_UNSUPPORTED_FUNCTION -- Function code is not supported
  1582. //
  1583. // Notes:
  1584. //
  1585. //--------------------------------------------------------------------------
  1586. NTSTATUS NTAPI
  1587. NtLmQueryContextAttributes(
  1588. IN ULONG_PTR KernelContextHandle,
  1589. IN ULONG Attribute,
  1590. IN OUT PVOID Buffer
  1591. )
  1592. {
  1593. NTSTATUS Status = STATUS_SUCCESS;
  1594. PSecPkgContext_NamesW ContextNames = NULL;
  1595. PSecPkgContext_DceInfo ContextDceInfo = NULL;
  1596. PSecPkgContext_SessionKey ContextSessionKeyInfo = NULL;
  1597. PSecPkgContext_Sizes ContextSizes = NULL;
  1598. PSecPkgContext_Flags ContextFlags = NULL;
  1599. PSecPkgContext_PasswordExpiry PasswordExpires;
  1600. PSecPkgContext_UserFlags UserFlags;
  1601. PSecPkgContext_PackageInfo PackageInfo = NULL;
  1602. PSecPkgContext_TargetInformation TargetInformation = NULL;
  1603. PNTLM_KERNEL_CONTEXT pContext = NULL;
  1604. unsigned int Length = 0;
  1605. MAYBE_PAGED_CODE();
  1606. DebugLog(( DEB_TRACE, "Entering NtLmQueryContextAttributes\n" ));
  1607. Status = NtlmReferenceContext( KernelContextHandle, FALSE );
  1608. if ( NT_SUCCESS( Status ) )
  1609. {
  1610. pContext = (PNTLM_KERNEL_CONTEXT) KernelContextHandle ;
  1611. } else {
  1612. //
  1613. // for PACKAGE_INFO or NEGOTIATION_INFO, don't require a completed
  1614. // context.
  1615. //
  1616. if( (Attribute != SECPKG_ATTR_PACKAGE_INFO) &&
  1617. (Attribute != SECPKG_ATTR_NEGOTIATION_INFO)
  1618. )
  1619. {
  1620. DebugLog(( DEB_ERROR,
  1621. "Bad kernel context 0x%lx\n", KernelContextHandle));
  1622. goto CleanUp_NoDeref;
  1623. }
  1624. Status = STATUS_SUCCESS;
  1625. }
  1626. //
  1627. // Handle each of the various queried attributes
  1628. //
  1629. switch ( Attribute ) {
  1630. case SECPKG_ATTR_SIZES:
  1631. ContextSizes = (PSecPkgContext_Sizes) Buffer;
  1632. ContextSizes->cbMaxToken = NTLMSP_MAX_TOKEN_SIZE;
  1633. if (pContext->NegotiateFlags & (NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
  1634. NTLMSSP_NEGOTIATE_SIGN |
  1635. NTLMSSP_NEGOTIATE_SEAL) ) {
  1636. ContextSizes->cbMaxSignature = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  1637. } else {
  1638. ContextSizes->cbMaxSignature = 0;
  1639. }
  1640. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL) {
  1641. ContextSizes->cbBlockSize = 1;
  1642. ContextSizes->cbSecurityTrailer = NTLMSSP_MESSAGE_SIGNATURE_SIZE;
  1643. }
  1644. else
  1645. {
  1646. ContextSizes->cbBlockSize = 0;
  1647. ContextSizes->cbSecurityTrailer = 0;
  1648. }
  1649. break;
  1650. //
  1651. // No one uses the function so don't go to the overhead of maintaining
  1652. // the username in the context structure.
  1653. //
  1654. case SECPKG_ATTR_DCE_INFO:
  1655. ContextDceInfo = (PSecPkgContext_DceInfo) Buffer;
  1656. if (ContextDceInfo == NULL)
  1657. {
  1658. DebugLog(( DEB_ERROR, "Null buffer SECPKG_ATTR_DCE_INFO.\n" ));
  1659. Status = STATUS_INVALID_PARAMETER;
  1660. goto Cleanup;
  1661. }
  1662. if (pContext->ContextNames)
  1663. {
  1664. Length = (unsigned int) wcslen(pContext->ContextNames);
  1665. }
  1666. ContextDceInfo->pPac = (LPWSTR) LsaKernelFunctions->AllocateHeap(
  1667. (Length + 1) * sizeof(WCHAR));
  1668. if (ContextDceInfo->pPac != NULL)
  1669. {
  1670. RtlCopyMemory(
  1671. ContextDceInfo->pPac,
  1672. pContext->ContextNames,
  1673. Length * sizeof(WCHAR));
  1674. LPWSTR Temp = (LPWSTR)ContextDceInfo->pPac;
  1675. Temp[Length] = L'\0';
  1676. }
  1677. else
  1678. {
  1679. DebugLog(( DEB_ERROR, "Bad Context->pPac in SECPKG_ATTR_DCE_INFO.\n" ));
  1680. Status = STATUS_INSUFFICIENT_RESOURCES;
  1681. goto Cleanup;
  1682. }
  1683. ContextDceInfo->AuthzSvc = 0;
  1684. break;
  1685. case SECPKG_ATTR_NAMES:
  1686. ContextNames = (PSecPkgContext_Names) Buffer;
  1687. if (ContextNames == NULL)
  1688. {
  1689. DebugLog(( DEB_ERROR, "Null buffer SECPKG_ATTR_NAMES.\n" ));
  1690. Status = STATUS_INVALID_PARAMETER;
  1691. goto Cleanup;
  1692. }
  1693. if (pContext->ContextNames)
  1694. {
  1695. Length = (unsigned int) wcslen(pContext->ContextNames);
  1696. DebugLog(( DEB_TRACE, "NtLmQueryContextAttributes: ContextNames length is 0x%lx\n", Length));
  1697. }
  1698. ContextNames->sUserName = (LPWSTR) LsaKernelFunctions->AllocateHeap(
  1699. (Length + 1) * sizeof(WCHAR));
  1700. if (ContextNames->sUserName != NULL)
  1701. {
  1702. RtlCopyMemory(
  1703. ContextNames->sUserName,
  1704. pContext->ContextNames,
  1705. Length * sizeof(WCHAR));
  1706. ContextNames->sUserName[Length] = L'\0';
  1707. }
  1708. else
  1709. {
  1710. DebugLog(( DEB_ERROR, "Bad Context->sUserName in SECPKG_ATTR_NAMES.\n" ));
  1711. Status = STATUS_INSUFFICIENT_RESOURCES;
  1712. goto Cleanup;
  1713. }
  1714. break;
  1715. case SECPKG_ATTR_TARGET_INFORMATION:
  1716. TargetInformation = (PSecPkgContext_TargetInformation) Buffer;
  1717. if (TargetInformation == NULL)
  1718. {
  1719. DebugLog(( DEB_ERROR, "Null buffer SECPKG_ATTR_TARGET_INFORMATION.\n" ));
  1720. Status = STATUS_INVALID_PARAMETER;
  1721. goto Cleanup;
  1722. }
  1723. TargetInformation->MarshalledTargetInfo = NULL;
  1724. if (pContext->pbMarshalledTargetInfo == NULL)
  1725. {
  1726. Status = STATUS_NOT_FOUND;
  1727. goto Cleanup;
  1728. }
  1729. Length = pContext->cbMarshalledTargetInfo;
  1730. DebugLog(( DEB_TRACE, "NtLmQueryContextAttributes: TargetInformation length is 0x%lx\n", Length));
  1731. TargetInformation->MarshalledTargetInfo = (PUCHAR) LsaKernelFunctions->AllocateHeap(
  1732. Length
  1733. );
  1734. if (TargetInformation->MarshalledTargetInfo != NULL)
  1735. {
  1736. RtlCopyMemory(
  1737. TargetInformation->MarshalledTargetInfo,
  1738. pContext->pbMarshalledTargetInfo,
  1739. Length
  1740. );
  1741. TargetInformation->MarshalledTargetInfoLength = Length;
  1742. }
  1743. else
  1744. {
  1745. Status = STATUS_INSUFFICIENT_RESOURCES;
  1746. goto Cleanup;
  1747. }
  1748. break;
  1749. case SECPKG_ATTR_SESSION_KEY:
  1750. ContextSessionKeyInfo = (PSecPkgContext_SessionKey) Buffer;
  1751. ContextSessionKeyInfo->SessionKeyLength = MSV1_0_USER_SESSION_KEY_LENGTH;
  1752. ContextSessionKeyInfo->SessionKey =
  1753. (PUCHAR) LsaKernelFunctions->AllocateHeap(
  1754. ContextSessionKeyInfo->SessionKeyLength);
  1755. if (ContextSessionKeyInfo->SessionKey != NULL)
  1756. {
  1757. RtlCopyMemory(
  1758. ContextSessionKeyInfo->SessionKey,
  1759. pContext->SessionKey,
  1760. MSV1_0_USER_SESSION_KEY_LENGTH);
  1761. }
  1762. else
  1763. {
  1764. Status = STATUS_INSUFFICIENT_RESOURCES;
  1765. }
  1766. break;
  1767. case SECPKG_ATTR_PASSWORD_EXPIRY:
  1768. PasswordExpires = (PSecPkgContext_PasswordExpiry) Buffer;
  1769. if(pContext->PasswordExpiry.QuadPart != 0) {
  1770. PasswordExpires->tsPasswordExpires = pContext->PasswordExpiry;
  1771. } else {
  1772. Status = SEC_E_UNSUPPORTED_FUNCTION;
  1773. }
  1774. break;
  1775. case SECPKG_ATTR_USER_FLAGS:
  1776. UserFlags = (PSecPkgContext_UserFlags) Buffer;
  1777. UserFlags->UserFlags = pContext->UserFlags;
  1778. break;
  1779. case SECPKG_ATTR_FLAGS:
  1780. {
  1781. BOOLEAN Client = (pContext->ClientTokenHandle == 0);
  1782. ULONG Flags = 0;
  1783. ContextFlags = (PSecPkgContext_Flags) Buffer;
  1784. ContextFlags->Flags = 0;
  1785. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL) {
  1786. if( Client )
  1787. {
  1788. Flags |= ISC_RET_CONFIDENTIALITY;
  1789. } else {
  1790. Flags |= ASC_RET_CONFIDENTIALITY;
  1791. }
  1792. }
  1793. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN) {
  1794. if( Client )
  1795. {
  1796. Flags |= ISC_RET_SEQUENCE_DETECT | ISC_RET_REPLAY_DETECT | ISC_RET_INTEGRITY;
  1797. } else {
  1798. Flags |= ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT | ASC_RET_INTEGRITY;
  1799. }
  1800. }
  1801. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_NULL_SESSION) {
  1802. if( Client )
  1803. {
  1804. Flags |= ISC_RET_NULL_SESSION;
  1805. } else {
  1806. Flags |= ASC_RET_NULL_SESSION;
  1807. }
  1808. }
  1809. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) {
  1810. if( Client )
  1811. {
  1812. Flags |= ISC_RET_DATAGRAM;
  1813. } else {
  1814. Flags |= ASC_RET_DATAGRAM;
  1815. }
  1816. }
  1817. if (pContext->NegotiateFlags & NTLMSSP_NEGOTIATE_IDENTIFY) {
  1818. if( Client )
  1819. {
  1820. Flags |= ISC_RET_IDENTIFY;
  1821. } else {
  1822. Flags |= ASC_RET_IDENTIFY;
  1823. }
  1824. }
  1825. ContextFlags->Flags |= Flags;
  1826. break;
  1827. }
  1828. case SECPKG_ATTR_PACKAGE_INFO:
  1829. case SECPKG_ATTR_NEGOTIATION_INFO:
  1830. //
  1831. // Return the information about this package. This is useful for
  1832. // callers who used SPNEGO and don't know what package they got.
  1833. //
  1834. PackageInfo = (PSecPkgContext_PackageInfo) Buffer;
  1835. PackageInfo->PackageInfo = (PSecPkgInfoW) LsaKernelFunctions->AllocateHeap(
  1836. sizeof(SecPkgInfoW) +
  1837. sizeof(NTLMSP_NAME) +
  1838. sizeof(NTLMSP_COMMENT)
  1839. );
  1840. if (PackageInfo->PackageInfo == NULL)
  1841. {
  1842. Status = STATUS_INSUFFICIENT_RESOURCES;
  1843. goto Cleanup;
  1844. }
  1845. PackageInfo->PackageInfo->Name = (LPWSTR) (PackageInfo->PackageInfo + 1);
  1846. PackageInfo->PackageInfo->Comment = (LPWSTR) ((((PCHAR) PackageInfo->PackageInfo->Name)) + sizeof(NTLMSP_NAME));
  1847. wcscpy(
  1848. PackageInfo->PackageInfo->Name,
  1849. NTLMSP_NAME
  1850. );
  1851. wcscpy(
  1852. PackageInfo->PackageInfo->Comment,
  1853. NTLMSP_COMMENT
  1854. );
  1855. PackageInfo->PackageInfo->wVersion = SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION;
  1856. PackageInfo->PackageInfo->wRPCID = NTLMSP_RPCID;
  1857. PackageInfo->PackageInfo->fCapabilities = NTLMSP_CAPS;
  1858. PackageInfo->PackageInfo->cbMaxToken = NTLMSP_MAX_TOKEN_SIZE;
  1859. if ( Attribute == SECPKG_ATTR_NEGOTIATION_INFO )
  1860. {
  1861. PSecPkgContext_NegotiationInfo NegInfo ;
  1862. NegInfo = (PSecPkgContext_NegotiationInfo) PackageInfo ;
  1863. if( pContext ) {
  1864. NegInfo->NegotiationState = SECPKG_NEGOTIATION_COMPLETE ;
  1865. } else {
  1866. NegInfo->NegotiationState = 0;
  1867. }
  1868. }
  1869. break;
  1870. case SECPKG_ATTR_LIFESPAN:
  1871. default:
  1872. Status = STATUS_NOT_SUPPORTED;
  1873. break;
  1874. }
  1875. Cleanup:
  1876. if (!NT_SUCCESS(Status)) {
  1877. switch ( Attribute) {
  1878. case SECPKG_ATTR_NAMES:
  1879. if (ContextNames && ContextNames->sUserName)
  1880. {
  1881. LsaKernelFunctions->FreeHeap(ContextNames->sUserName);
  1882. ContextNames->sUserName = NULL;
  1883. }
  1884. break;
  1885. case SECPKG_ATTR_DCE_INFO:
  1886. if (ContextDceInfo && ContextDceInfo->pPac)
  1887. {
  1888. LsaKernelFunctions->FreeHeap(ContextDceInfo->pPac);
  1889. ContextDceInfo->pPac = NULL;
  1890. }
  1891. break;
  1892. case SECPKG_ATTR_SESSION_KEY:
  1893. if(ContextSessionKeyInfo && ContextSessionKeyInfo->SessionKey)
  1894. {
  1895. LsaKernelFunctions->FreeHeap(ContextSessionKeyInfo->SessionKey);
  1896. ContextSessionKeyInfo->SessionKey = NULL;
  1897. }
  1898. break;
  1899. case SECPKG_ATTR_NEGOTIATION_INFO:
  1900. if(PackageInfo && PackageInfo->PackageInfo)
  1901. {
  1902. LsaKernelFunctions->FreeHeap(PackageInfo->PackageInfo);
  1903. PackageInfo->PackageInfo = NULL;
  1904. }
  1905. break;
  1906. }
  1907. }
  1908. if( pContext ) {
  1909. NtlmDerefContext( pContext );
  1910. }
  1911. CleanUp_NoDeref:
  1912. DebugLog(( DEB_TRACE, "Leaving NtLmQueryContextAttributes 0x%lx\n", Status ));
  1913. return Status;
  1914. }
  1915. //+-------------------------------------------------------------------------
  1916. //
  1917. // Function: NtLmCompleteToken
  1918. //
  1919. // Synopsis: Completes a context
  1920. //
  1921. // Effects:
  1922. //
  1923. // Arguments:
  1924. //
  1925. // Requires:
  1926. //
  1927. // Returns:
  1928. //
  1929. // Notes:
  1930. //
  1931. //
  1932. //--------------------------------------------------------------------------
  1933. NTSTATUS NTAPI
  1934. NtLmCompleteToken(
  1935. IN ULONG_PTR ContextHandle,
  1936. IN PSecBufferDesc InputBuffer
  1937. )
  1938. {
  1939. UNREFERENCED_PARAMETER (ContextHandle);
  1940. UNREFERENCED_PARAMETER (InputBuffer);
  1941. PAGED_CODE();
  1942. DebugLog(( DEB_TRACE, "Entering NtLmCompleteToken\n" ));
  1943. DebugLog(( DEB_TRACE, "Leaving NtLmCompleteToken\n" ));
  1944. return(STATUS_NOT_SUPPORTED);
  1945. }
  1946. //+-------------------------------------------------------------------------
  1947. //
  1948. // Function: NtLmMakePackedContext
  1949. //
  1950. // Synopsis: Maps a context to the caller's address space
  1951. //
  1952. // Effects:
  1953. //
  1954. // Arguments: Context - The context to map
  1955. // MappedContext - Set to TRUE on success
  1956. // ContextData - Receives a buffer in the caller's address space
  1957. // with the mapped context.
  1958. //
  1959. // Requires:
  1960. //
  1961. // Returns:
  1962. //
  1963. // Notes:
  1964. //
  1965. //
  1966. //--------------------------------------------------------------------------
  1967. NTSTATUS
  1968. NtLmMakePackedContext(
  1969. IN PNTLM_KERNEL_CONTEXT Context,
  1970. OUT PBOOLEAN MappedContext,
  1971. OUT PSecBuffer ContextData,
  1972. IN ULONG Flags
  1973. )
  1974. {
  1975. NTSTATUS Status = STATUS_SUCCESS;
  1976. PNTLM_PACKED_CONTEXT PackedContext = NULL;
  1977. ULONG ContextSize, ContextNameSize = 0;
  1978. PAGED_CODE();
  1979. if (Context->ContextNames)
  1980. {
  1981. ContextNameSize = (ULONG) wcslen(Context->ContextNames);
  1982. }
  1983. ContextSize = sizeof(NTLM_PACKED_CONTEXT) +
  1984. ContextNameSize * sizeof(WCHAR);
  1985. PackedContext = (PNTLM_PACKED_CONTEXT) NtLmAllocate(ContextSize);
  1986. if (PackedContext == NULL)
  1987. {
  1988. Status = STATUS_INSUFFICIENT_RESOURCES;
  1989. goto Cleanup;
  1990. }
  1991. RtlZeroMemory( PackedContext, ContextSize );
  1992. #if 0
  1993. // Copy all fields of the old context
  1994. RtlCopyMemory(
  1995. PackedContext,
  1996. Context,
  1997. sizeof(NTLM_KERNEL_CONTEXT)
  1998. );
  1999. if (ContextNameSize > 0)
  2000. {
  2001. PackedContext->ContextNames = (LPWSTR) sizeof(NTLM_PACKED_CONTEXT);
  2002. RtlCopyMemory(
  2003. PackedContext+1,
  2004. Context->ContextNames,
  2005. ContextNameSize * sizeof(WCHAR));
  2006. }
  2007. else
  2008. {
  2009. PackedContext->ContextNames=NULL;
  2010. }
  2011. // Replace some fields
  2012. //
  2013. // Token will be returned by the caller of this routine
  2014. //
  2015. PackedContext->ClientTokenHandle = NULL;
  2016. PackedContext->NegotiateFlags |= NTLMSSP_NEGOTIATE_EXPORTED_CONTEXT;
  2017. if ((Flags & SECPKG_CONTEXT_EXPORT_RESET_NEW) != 0)
  2018. {
  2019. PackedContext->SendNonce = (ULONG) -1;
  2020. PackedContext->RecvNonce = (ULONG) -1;
  2021. }
  2022. RtlZeroMemory(
  2023. &PackedContext->SessionKey,
  2024. MSV1_0_USER_SESSION_KEY_LENGTH
  2025. );
  2026. #endif
  2027. PackedContext->Tag = NTLM_PACKED_CONTEXT_MAP ;
  2028. PackedContext->NegotiateFlags = Context->NegotiateFlags ;
  2029. PackedContext->SendNonce = Context->SendNonce ;
  2030. PackedContext->RecvNonce = Context->RecvNonce ;
  2031. RtlCopyMemory(
  2032. PackedContext->SessionKey,
  2033. Context->SessionKey,
  2034. MSV1_0_USER_SESSION_KEY_LENGTH );
  2035. PackedContext->ContextSignature = Context->ContextSignature ;
  2036. PackedContext->PasswordExpiry = Context->PasswordExpiry ;
  2037. PackedContext->UserFlags = Context->UserFlags ;
  2038. if ( ContextNameSize )
  2039. {
  2040. PackedContext->ContextNames = sizeof( NTLM_PACKED_CONTEXT );
  2041. PackedContext->ContextNameLength = (ContextNameSize + 1) * sizeof( WCHAR ) ;
  2042. RtlCopyMemory(
  2043. (PackedContext + 1),
  2044. Context->ContextNames,
  2045. PackedContext->ContextNameLength );
  2046. }
  2047. else
  2048. {
  2049. PackedContext->ContextNames = 0 ;
  2050. }
  2051. RtlCopyMemory(
  2052. PackedContext->SignSessionKey,
  2053. Context->SignSessionKey,
  2054. MSV1_0_USER_SESSION_KEY_LENGTH );
  2055. RtlCopyMemory(
  2056. PackedContext->VerifySessionKey,
  2057. Context->VerifySessionKey,
  2058. MSV1_0_USER_SESSION_KEY_LENGTH );
  2059. RtlCopyMemory(
  2060. PackedContext->SealSessionKey,
  2061. Context->SealSessionKey,
  2062. MSV1_0_USER_SESSION_KEY_LENGTH );
  2063. RtlCopyMemory(
  2064. PackedContext->UnsealSessionKey,
  2065. Context->SealSessionKey,
  2066. MSV1_0_USER_SESSION_KEY_LENGTH );
  2067. RtlCopyMemory(
  2068. &PackedContext->SealRc4Sched,
  2069. &Context->SealRc4Sched,
  2070. sizeof( struct RC4_KEYSTRUCT ) );
  2071. RtlCopyMemory(
  2072. &PackedContext->UnsealRc4Sched,
  2073. &Context->UnsealRc4Sched,
  2074. sizeof( struct RC4_KEYSTRUCT ) );
  2075. // Replace some fields
  2076. //
  2077. // Token will be returned by the caller of this routine
  2078. //
  2079. PackedContext->ClientTokenHandle = 0 ;
  2080. // Save the fact that it's exported
  2081. PackedContext->NegotiateFlags |= NTLMSSP_NEGOTIATE_EXPORTED_CONTEXT;
  2082. if ((Flags & SECPKG_CONTEXT_EXPORT_RESET_NEW) != 0)
  2083. {
  2084. PackedContext->SendNonce = (ULONG) -1;
  2085. PackedContext->RecvNonce = (ULONG) -1;
  2086. }
  2087. ContextData->pvBuffer = PackedContext;
  2088. ContextData->cbBuffer = ContextSize;
  2089. *MappedContext = TRUE;
  2090. Cleanup:
  2091. if (!NT_SUCCESS(Status))
  2092. {
  2093. if (PackedContext != NULL)
  2094. {
  2095. NtLmFree(PackedContext);
  2096. }
  2097. }
  2098. return(Status);
  2099. }
  2100. //+-------------------------------------------------------------------------
  2101. //
  2102. // Function:
  2103. //
  2104. // Synopsis:
  2105. //
  2106. // Effects:
  2107. //
  2108. // Arguments:
  2109. //
  2110. // Requires:
  2111. //
  2112. // Returns:
  2113. //
  2114. // Notes:
  2115. //
  2116. //
  2117. //--------------------------------------------------------------------------
  2118. NTSTATUS
  2119. NtLmExportSecurityContext(
  2120. IN ULONG_PTR ContextHandle,
  2121. IN ULONG Flags,
  2122. OUT PSecBuffer PackedContext,
  2123. IN OUT PHANDLE TokenHandle
  2124. )
  2125. {
  2126. PNTLM_KERNEL_CONTEXT Context = NULL;
  2127. NTSTATUS Status = STATUS_SUCCESS;
  2128. BOOLEAN MappedContext = FALSE;
  2129. PAGED_CODE();
  2130. DebugLog(( DEB_TRACE, "Entering NtLmExportSecurityContext\n" ));
  2131. if (ARGUMENT_PRESENT(TokenHandle))
  2132. {
  2133. *TokenHandle = NULL;
  2134. }
  2135. PackedContext->pvBuffer = NULL;
  2136. PackedContext->cbBuffer = 0;
  2137. PackedContext->BufferType = 0;
  2138. Status = NtlmReferenceContext( ContextHandle, FALSE );
  2139. if ( NT_SUCCESS( Status ) )
  2140. {
  2141. Context = (PNTLM_KERNEL_CONTEXT) ContextHandle ;
  2142. }
  2143. else
  2144. {
  2145. goto Cleanup_NoDeref ;
  2146. }
  2147. Status = NtLmMakePackedContext(
  2148. Context,
  2149. &MappedContext,
  2150. PackedContext,
  2151. Flags
  2152. );
  2153. if (!NT_SUCCESS(Status))
  2154. {
  2155. goto Cleanup;
  2156. }
  2157. ASSERT(MappedContext);
  2158. //
  2159. // Now either duplicate the token or copy it.
  2160. //
  2161. if (ARGUMENT_PRESENT(TokenHandle))
  2162. {
  2163. if ((Flags & SECPKG_CONTEXT_EXPORT_DELETE_OLD) != 0)
  2164. {
  2165. *TokenHandle = Context->ClientTokenHandle;
  2166. Context->ClientTokenHandle = NULL;
  2167. }
  2168. else
  2169. {
  2170. Status = NtDuplicateObject(
  2171. NtCurrentProcess(),
  2172. Context->ClientTokenHandle,
  2173. NULL,
  2174. TokenHandle,
  2175. 0, // no new access
  2176. 0, // no handle attributes
  2177. DUPLICATE_SAME_ACCESS
  2178. );
  2179. }
  2180. if (!NT_SUCCESS(Status))
  2181. {
  2182. goto Cleanup;
  2183. }
  2184. }
  2185. Cleanup:
  2186. NtlmDerefContext( Context );
  2187. Cleanup_NoDeref:
  2188. return (Status);
  2189. }
  2190. //+-------------------------------------------------------------------------
  2191. //
  2192. // Function: NtLmCreateKernelModeContext
  2193. //
  2194. // Synopsis: Creates a kernel-mode context to support impersonation and
  2195. // message integrity and privacy
  2196. //
  2197. // Effects:
  2198. //
  2199. // Arguments:
  2200. //
  2201. // Requires:
  2202. //
  2203. // Returns:
  2204. //
  2205. // Notes:
  2206. //
  2207. //
  2208. //--------------------------------------------------------------------------
  2209. NTSTATUS
  2210. NtLmCreateKernelModeContext(
  2211. IN ULONG_PTR ContextHandle,
  2212. IN OPTIONAL HANDLE TokenHandle,
  2213. IN PSecBuffer MarshalledContext,
  2214. OUT PNTLM_KERNEL_CONTEXT * NewContext
  2215. )
  2216. {
  2217. NTSTATUS Status = STATUS_SUCCESS;
  2218. PNTLM_KERNEL_CONTEXT Context = NULL;
  2219. PNTLM_PACKED_CONTEXT PackedContext;
  2220. unsigned int Length = 0;
  2221. PAGED_CODE();
  2222. if (MarshalledContext->cbBuffer < sizeof(NTLM_PACKED_CONTEXT))
  2223. {
  2224. DebugLog((DEB_ERROR,"NtLmCreateKernelModeContext: Invalid buffer size for marshalled context: was 0x%x, needed 0x%x\n",
  2225. MarshalledContext->cbBuffer, sizeof(NTLM_PACKED_CONTEXT)));
  2226. return(STATUS_INVALID_PARAMETER);
  2227. }
  2228. PackedContext = (PNTLM_PACKED_CONTEXT) MarshalledContext->pvBuffer;
  2229. Context = (PNTLM_KERNEL_CONTEXT) NtLmAllocate( sizeof(NTLM_KERNEL_CONTEXT));
  2230. if (!Context)
  2231. {
  2232. Status = STATUS_INSUFFICIENT_RESOURCES;
  2233. DebugLog((DEB_ERROR,"NtLmCreateKernelModeContext: Allocation error for Context\n"));
  2234. goto Cleanup;
  2235. }
  2236. RtlZeroMemory(
  2237. Context,
  2238. sizeof(NTLM_KERNEL_CONTEXT));
  2239. // Copy contenets of PackedContext->pvBuffer to Context
  2240. //// *Context = *PackedContext;
  2241. Context->NegotiateFlags = PackedContext->NegotiateFlags;
  2242. //// Context->ClientTokenHandle = (HANDLE)PackedContext->ClientTokenHandle;
  2243. Context->ContextSignature = PackedContext->ContextSignature;
  2244. RtlCopyMemory( Context->SessionKey, PackedContext->SessionKey, sizeof(PackedContext->SessionKey) );
  2245. RtlCopyMemory( Context->SignSessionKey, PackedContext->SignSessionKey, sizeof(PackedContext->SignSessionKey) );
  2246. RtlCopyMemory( Context->VerifySessionKey, PackedContext->VerifySessionKey, sizeof(PackedContext->VerifySessionKey) );
  2247. RtlCopyMemory( Context->SealSessionKey, PackedContext->SealSessionKey, sizeof(PackedContext->SealSessionKey) );
  2248. RtlCopyMemory( Context->UnsealSessionKey, PackedContext->UnsealSessionKey, sizeof(PackedContext->UnsealSessionKey) );
  2249. RtlCopyMemory( &Context->SealRc4Sched, &PackedContext->SealRc4Sched, sizeof(PackedContext->SealRc4Sched) );
  2250. RtlCopyMemory( &Context->UnsealRc4Sched, &PackedContext->UnsealRc4Sched, sizeof(PackedContext->UnsealRc4Sched) );
  2251. KsecInitializeListEntry( &Context->List, NTLM_CONTEXT_SIGNATURE );
  2252. // These need to be changed
  2253. Context->ClientTokenHandle = TokenHandle;
  2254. if (Context->SendNonce == (ULONG) -1)
  2255. {
  2256. // The context was exported with the reset flag
  2257. Context->SendNonce = 0;
  2258. }
  2259. if (Context->RecvNonce == (ULONG) -1)
  2260. {
  2261. // The context was exported with the reset flag
  2262. Context->RecvNonce = 0;
  2263. }
  2264. if( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2 ) {
  2265. Context->pSealRc4Sched = &Context->SealRc4Sched;
  2266. Context->pUnsealRc4Sched = &Context->UnsealRc4Sched;
  2267. Context->pSendNonce = &Context->SendNonce;
  2268. Context->pRecvNonce = &Context->RecvNonce;
  2269. } else {
  2270. Context->pSealRc4Sched = &Context->SealRc4Sched;
  2271. Context->pUnsealRc4Sched = &Context->SealRc4Sched;
  2272. Context->pSendNonce = &Context->SendNonce;
  2273. Context->pRecvNonce = &Context->SendNonce;
  2274. }
  2275. Context->ContextNames = NULL;
  2276. Length = (MarshalledContext->cbBuffer - sizeof(NTLM_PACKED_CONTEXT));
  2277. if (Length > 0)
  2278. {
  2279. Context->ContextNames = (LPWSTR) NtLmAllocate(Length + sizeof(WCHAR));
  2280. if (!Context->ContextNames)
  2281. {
  2282. Status = STATUS_INSUFFICIENT_RESOURCES;
  2283. goto Cleanup;
  2284. }
  2285. RtlCopyMemory(Context->ContextNames, PackedContext + 1, Length);
  2286. // null terminate the string
  2287. *(Context->ContextNames + (Length/2)) = UNICODE_NULL;
  2288. }
  2289. Context->PasswordExpiry = PackedContext->PasswordExpiry;
  2290. Context->UserFlags = PackedContext->UserFlags;
  2291. KSecInsertListEntry(
  2292. NtlmActiveList,
  2293. &Context->List );
  2294. *NewContext = Context;
  2295. Cleanup:
  2296. if (!NT_SUCCESS(Status))
  2297. {
  2298. if (Context != NULL)
  2299. {
  2300. NtlmFreeKernelContext(Context);
  2301. }
  2302. }
  2303. DebugLog(( DEB_TRACE, "Leaving NtLmCreateKernelContext 0x%lx\n", Status ));
  2304. return(Status);
  2305. }
  2306. //+-------------------------------------------------------------------------
  2307. //
  2308. // Function:
  2309. //
  2310. // Synopsis:
  2311. //
  2312. // Effects:
  2313. //
  2314. // Arguments:
  2315. //
  2316. // Requires:
  2317. //
  2318. // Returns:
  2319. //
  2320. // Notes:
  2321. //
  2322. //
  2323. //--------------------------------------------------------------------------
  2324. NTSTATUS
  2325. NtLmImportSecurityContext(
  2326. IN PSecBuffer PackedContext,
  2327. IN OPTIONAL HANDLE TokenHandle,
  2328. OUT PULONG_PTR ContextHandle
  2329. )
  2330. {
  2331. NTSTATUS Status;
  2332. PNTLM_KERNEL_CONTEXT Context = NULL;
  2333. PAGED_CODE();
  2334. DebugLog((DEB_TRACE,"Entering NtLmImportSecurityContext\n"));
  2335. Status = NtLmCreateKernelModeContext(
  2336. 0, // LsaContextHandle not present
  2337. TokenHandle,
  2338. PackedContext,
  2339. &Context
  2340. );
  2341. if (!NT_SUCCESS(Status))
  2342. {
  2343. DebugLog((DEB_ERROR,"NtLmImportSecurityContext: Failed to create kernel mode context: 0x%x\n",
  2344. Status));
  2345. goto Cleanup;
  2346. }
  2347. *ContextHandle = (ULONG_PTR) Context;
  2348. Cleanup:
  2349. if (Context != NULL)
  2350. {
  2351. NtlmDerefContext( Context );
  2352. }
  2353. return(Status);
  2354. }
  2355. //+---------------------------------------------------------------------------
  2356. //
  2357. // Function: NtlmSetPagingMode
  2358. //
  2359. // Synopsis: Switch the paging mode for cluster support
  2360. //
  2361. // Arguments: [Pagable] --
  2362. //
  2363. // History: 7-07-98 RichardW Created
  2364. //
  2365. // Notes:
  2366. //
  2367. //----------------------------------------------------------------------------
  2368. NTSTATUS
  2369. NtlmSetPagingMode(
  2370. BOOLEAN Pagable
  2371. )
  2372. {
  2373. if ( Pagable )
  2374. {
  2375. NtlmPoolType = PagedPool ;
  2376. NtlmActiveList = NtlmPagedList ;
  2377. }
  2378. else
  2379. {
  2380. if ( NtlmNonPagedList == NULL )
  2381. {
  2382. NtlmNonPagedList = LsaKernelFunctions->CreateContextList( KSecNonPaged );
  2383. if ( NtlmNonPagedList == NULL )
  2384. {
  2385. return STATUS_NO_MEMORY ;
  2386. }
  2387. }
  2388. NtlmActiveList = NtlmNonPagedList ;
  2389. NtlmPoolType = NonPagedPool ;
  2390. }
  2391. return STATUS_SUCCESS ;
  2392. }