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

2269 lines
71 KiB

  1. /*++
  2. Copyright (c) 1993-2000 Microsoft Corporation
  3. Module Name:
  4. ctxtsrv.cxx
  5. Abstract:
  6. API and support routines for handling security contexts.
  7. Author:
  8. Cliff Van Dyke (CliffV) 13-Jul-1993
  9. Revision History:
  10. ChandanS 03-Aug-1996 Stolen from net\svcdlls\ntlmssp\common\context.c
  11. JClark 28-Jun-2000 Added WMI Trace Logging Support
  12. --*/
  13. //
  14. // Common include files.
  15. //
  16. #include <global.h>
  17. #include <align.h> // ALIGN_WCHAR, etc
  18. #include "Trace.h"
  19. NTSTATUS
  20. SsprHandleNegotiateMessage(
  21. IN ULONG_PTR CredentialHandle,
  22. IN OUT PULONG_PTR ContextHandle,
  23. IN ULONG ContextReqFlags,
  24. IN ULONG InputTokenSize,
  25. IN PVOID InputToken,
  26. IN OUT PULONG OutputTokenSize,
  27. OUT PVOID *OutputToken,
  28. OUT PULONG ContextAttributes,
  29. OUT PTimeStamp ExpirationTime
  30. )
  31. /*++
  32. Routine Description:
  33. Handle the Negotiate message part of AcceptSecurityContext.
  34. Arguments:
  35. All arguments same as for AcceptSecurityContext
  36. Return Value:
  37. STATUS_SUCCESS - Message handled
  38. SEC_I_CONTINUE_NEEDED -- Caller should call again later
  39. SEC_E_INVALID_TOKEN -- Token improperly formatted
  40. SEC_E_INVALID_HANDLE -- Credential/Context Handle is invalid
  41. SEC_E_BUFFER_TOO_SMALL -- Buffer for output token isn't big enough
  42. SEC_E_INSUFFICIENT_MEMORY -- Not enough memory
  43. --*/
  44. {
  45. NTSTATUS Status = STATUS_SUCCESS;
  46. PSSP_CONTEXT Context = NULL;
  47. PSSP_CREDENTIAL Credential = NULL;
  48. STRING TargetName;
  49. ULONG TargetFlags = 0;
  50. PNEGOTIATE_MESSAGE NegotiateMessage = NULL;
  51. PCHALLENGE_MESSAGE ChallengeMessage = NULL;
  52. ULONG ChallengeMessageSize = 0;
  53. PCHAR Where = NULL;
  54. ULONG NegotiateFlagsKeyStrength;
  55. UNICODE_STRING NtLmLocalUnicodeTargetName;
  56. UNICODE_STRING TargetInfo;
  57. STRING NtLmLocalOemTargetName;
  58. STRING OemWorkstationName;
  59. STRING OemDomainName;
  60. SspPrint(( SSP_API_MORE, "Entering SsprNegotiateMessage\n" ));
  61. //
  62. // Initialization
  63. //
  64. *ContextAttributes = 0;
  65. RtlInitString( &TargetName, NULL );
  66. RtlInitUnicodeString( &NtLmLocalUnicodeTargetName, NULL );
  67. RtlInitString( &NtLmLocalOemTargetName, NULL );
  68. RtlInitUnicodeString( &TargetInfo, NULL );
  69. //
  70. // Get a pointer to the credential
  71. //
  72. Status = SspCredentialReferenceCredential(
  73. CredentialHandle,
  74. FALSE,
  75. &Credential );
  76. if ( !NT_SUCCESS( Status ) ) {
  77. SspPrint(( SSP_CRITICAL,
  78. "SsprHandleNegotiateMessage: invalid credential handle.\n" ));
  79. goto Cleanup;
  80. }
  81. if ( (Credential->CredentialUseFlags & SECPKG_CRED_INBOUND) == 0 ) {
  82. Status = SEC_E_INVALID_CREDENTIAL_USE;
  83. SspPrint(( SSP_CRITICAL,
  84. "SsprHandleNegotiateMessage: invalid credential use.\n" ));
  85. goto Cleanup;
  86. }
  87. //
  88. // Allocate a new context
  89. //
  90. Context = SspContextAllocateContext( );
  91. if ( Context == NULL ) {
  92. Status = STATUS_NO_MEMORY;
  93. SspPrint(( SSP_CRITICAL,
  94. "SsprHandleNegotiateMessage: SspContextAllocateContext() returned NULL.\n" ));
  95. goto Cleanup;
  96. }
  97. //
  98. // Build a handle to the newly created context.
  99. //
  100. *ContextHandle = (ULONG_PTR) Context;
  101. if ( (ContextReqFlags & ASC_REQ_IDENTIFY) != 0 ) {
  102. *ContextAttributes |= ASC_RET_IDENTIFY;
  103. Context->ContextFlags |= ASC_RET_IDENTIFY;
  104. }
  105. if ( (ContextReqFlags & ASC_REQ_DATAGRAM) != 0 ) {
  106. *ContextAttributes |= ASC_RET_DATAGRAM;
  107. Context->ContextFlags |= ASC_RET_DATAGRAM;
  108. }
  109. if ( (ContextReqFlags & ASC_REQ_CONNECTION) != 0 ) {
  110. *ContextAttributes |= ASC_RET_CONNECTION;
  111. Context->ContextFlags |= ASC_RET_CONNECTION;
  112. }
  113. if ( (ContextReqFlags & ASC_REQ_INTEGRITY) != 0 ) {
  114. *ContextAttributes |= ASC_RET_INTEGRITY;
  115. Context->ContextFlags |= ASC_RET_INTEGRITY;
  116. }
  117. if ( (ContextReqFlags & ASC_REQ_REPLAY_DETECT) != 0){
  118. *ContextAttributes |= ASC_RET_REPLAY_DETECT;
  119. Context->ContextFlags |= ASC_RET_REPLAY_DETECT;
  120. }
  121. if ( (ContextReqFlags & ASC_REQ_SEQUENCE_DETECT ) != 0) {
  122. *ContextAttributes |= ASC_RET_SEQUENCE_DETECT;
  123. Context->ContextFlags |= ASC_RET_SEQUENCE_DETECT;
  124. }
  125. // Nothing to return, we might need this on the next server side call.
  126. if ( (ContextReqFlags & ASC_REQ_ALLOW_NULL_SESSION ) != 0) {
  127. Context->ContextFlags |= ASC_REQ_ALLOW_NULL_SESSION;
  128. }
  129. if ( (ContextReqFlags & ASC_REQ_ALLOW_NON_USER_LOGONS ) != 0) {
  130. *ContextAttributes |= ASC_RET_ALLOW_NON_USER_LOGONS;
  131. Context->ContextFlags |= ASC_RET_ALLOW_NON_USER_LOGONS;
  132. }
  133. if ( ContextReqFlags & ASC_REQ_CONFIDENTIALITY ) {
  134. if (NtLmGlobalEncryptionEnabled) {
  135. *ContextAttributes |= ASC_RET_CONFIDENTIALITY;
  136. Context->ContextFlags |= ASC_RET_CONFIDENTIALITY;
  137. } else {
  138. Status = STATUS_NOT_SUPPORTED;
  139. SspPrint(( SSP_CRITICAL,
  140. "SsprHandleNegotiateMessage: invalid ContextReqFlags 0x%lx\n", ContextReqFlags ));
  141. goto Cleanup;
  142. }
  143. }
  144. //
  145. // Supported key strength(s)
  146. //
  147. NegotiateFlagsKeyStrength = NTLMSSP_NEGOTIATE_56;
  148. if( NtLmSecPkg.MachineState & SECPKG_STATE_STRONG_ENCRYPTION_PERMITTED )
  149. {
  150. NegotiateFlagsKeyStrength |= NTLMSSP_NEGOTIATE_128;
  151. }
  152. //
  153. // Get the NegotiateMessage. If we are re-establishing a datagram
  154. // context then there may not be one.
  155. //
  156. if ( InputTokenSize >= sizeof(OLD_NEGOTIATE_MESSAGE) ) {
  157. Status = SspContextGetMessage( InputToken,
  158. InputTokenSize,
  159. NtLmNegotiate,
  160. (PVOID *)&NegotiateMessage );
  161. if ( !NT_SUCCESS(Status) ) {
  162. SspPrint(( SSP_CRITICAL,
  163. "SsprHandleNegotiateMessage: "
  164. "NegotiateMessage GetMessage returns 0x%lx\n",
  165. Status ));
  166. goto Cleanup;
  167. }
  168. //
  169. // Compute the TargetName to return in the ChallengeMessage.
  170. //
  171. if ( NegotiateMessage->NegotiateFlags & NTLMSSP_REQUEST_TARGET ||
  172. NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2 ) {
  173. RtlAcquireResourceShared(&NtLmGlobalCritSect, TRUE);
  174. if ( NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE) {
  175. Status = NtLmDuplicateUnicodeString( &NtLmLocalUnicodeTargetName, &NtLmGlobalUnicodeTargetName );
  176. TargetName = *((PSTRING)&NtLmLocalUnicodeTargetName);
  177. } else {
  178. Status = NtLmDuplicateString( &NtLmLocalOemTargetName, &NtLmGlobalOemTargetName );
  179. TargetName = NtLmLocalOemTargetName;
  180. }
  181. //
  182. // if client is NTLM2-aware, send it target info AV pairs
  183. //
  184. if(NT_SUCCESS(Status))
  185. {
  186. Status = NtLmDuplicateUnicodeString( &TargetInfo, &NtLmGlobalNtLm3TargetInfo );
  187. }
  188. TargetFlags = NtLmGlobalTargetFlags;
  189. RtlReleaseResource (&NtLmGlobalCritSect);
  190. TargetFlags |= NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO;
  191. if(!NT_SUCCESS(Status)) {
  192. SspPrint(( SSP_CRITICAL,
  193. "SsprHandleNegotiateMessage: "
  194. "failed to duplicate UnicodeTargetName or OemTargetName error 0x%lx\n",
  195. Status ));
  196. goto Cleanup;
  197. }
  198. } else {
  199. TargetFlags = 0;
  200. }
  201. //
  202. // Allocate a Challenge message
  203. //
  204. ChallengeMessageSize = sizeof(*ChallengeMessage) +
  205. TargetName.Length +
  206. TargetInfo.Length ;
  207. if ((ContextReqFlags & ASC_REQ_ALLOCATE_MEMORY) == 0)
  208. {
  209. if ( ChallengeMessageSize > *OutputTokenSize ) {
  210. SspPrint(( SSP_CRITICAL,
  211. "SsprHandleNegotiateMessage: invalid ChallengeMessageSize\n"));
  212. Status = SEC_E_BUFFER_TOO_SMALL;
  213. goto Cleanup;
  214. }
  215. }
  216. ChallengeMessage = (PCHALLENGE_MESSAGE)
  217. NtLmAllocateLsaHeap( ChallengeMessageSize );
  218. if ( ChallengeMessage == NULL ) {
  219. SspPrint(( SSP_CRITICAL,
  220. "SsprHandleNegotiateMessage: Error allocating ChallengeMessage.\n" ));
  221. Status = STATUS_NO_MEMORY;
  222. goto Cleanup;
  223. }
  224. ChallengeMessage->NegotiateFlags = 0;
  225. //
  226. // Check that both sides can use the same authentication model. For
  227. // compatibility with beta 1 and 2 (builds 612 and 683), no requested
  228. // authentication type is assumed to be NTLM. If NetWare is explicitly
  229. // asked for, it is assumed that NTLM would have been also, so if it
  230. // wasn't, return an error.
  231. //
  232. if ( (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NETWARE) &&
  233. ((NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM) == 0) &&
  234. ((NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) == 0)
  235. ) {
  236. Status = STATUS_NOT_SUPPORTED;
  237. SspPrint(( SSP_CRITICAL,
  238. "SsprHandleNegotiateMessage: "
  239. "NegotiateMessage asked for Netware only.\n" ));
  240. goto Cleanup;
  241. } else {
  242. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
  243. }
  244. //
  245. // if client can do NTLM2, nuke LM_KEY
  246. //
  247. if (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) {
  248. NegotiateMessage->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
  249. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM2;
  250. } else if (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY) {
  251. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY;
  252. }
  253. //
  254. // If the client wants to always sign messages, so be it.
  255. //
  256. if (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN ) {
  257. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
  258. }
  259. //
  260. // If the caller wants identify level, so be it.
  261. //
  262. if (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_IDENTIFY ) {
  263. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_IDENTIFY;
  264. *ContextAttributes |= ASC_RET_IDENTIFY;
  265. Context->ContextFlags |= ASC_RET_IDENTIFY;
  266. }
  267. //
  268. // Determine if the caller wants OEM or UNICODE
  269. //
  270. // Prefer UNICODE if caller allows both.
  271. //
  272. if ( NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE ) {
  273. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
  274. } else if ( NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM ){
  275. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM;
  276. } else {
  277. Status = SEC_E_INVALID_TOKEN;
  278. SspPrint(( SSP_CRITICAL,
  279. "SsprHandleNegotiateMessage: "
  280. "NegotiateMessage bad NegotiateFlags 0x%lx\n",
  281. NegotiateMessage->NegotiateFlags ));
  282. goto Cleanup;
  283. }
  284. //
  285. // Client wants Sign capability, OK.
  286. //
  287. if (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN) {
  288. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
  289. *ContextAttributes |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT);
  290. Context->ContextFlags |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT);
  291. }
  292. //
  293. // Client wants Seal, OK.
  294. //
  295. if (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL)
  296. {
  297. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
  298. *ContextAttributes |= ASC_RET_CONFIDENTIALITY;
  299. Context->ContextFlags |= ASC_RET_CONFIDENTIALITY;
  300. }
  301. if(NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
  302. {
  303. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
  304. }
  305. if( (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_56) &&
  306. (NegotiateFlagsKeyStrength & NTLMSSP_NEGOTIATE_56) )
  307. {
  308. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
  309. }
  310. if( (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_128) &&
  311. (NegotiateFlagsKeyStrength & NTLMSSP_NEGOTIATE_128) )
  312. {
  313. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
  314. }
  315. //
  316. // If the client supplied the Domain Name and User Name,
  317. // and did not request datagram, see if the client is running
  318. // on this local machine.
  319. //
  320. if ( ( (NegotiateMessage->NegotiateFlags &
  321. NTLMSSP_NEGOTIATE_DATAGRAM) == 0) &&
  322. ( (NegotiateMessage->NegotiateFlags &
  323. (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED|
  324. NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)) ==
  325. (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED|
  326. NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) ) ) {
  327. //
  328. // The client must pass the new negotiate message if they pass
  329. // these flags
  330. //
  331. if (InputTokenSize < sizeof(NEGOTIATE_MESSAGE)) {
  332. Status = SEC_E_INVALID_TOKEN;
  333. SspPrint(( SSP_CRITICAL,
  334. "SsprHandleNegotiateMessage: invalid InputTokenSize.\n" ));
  335. goto Cleanup;
  336. }
  337. //
  338. // Convert the names to absolute references so we
  339. // can compare them
  340. //
  341. if ( !SspConvertRelativeToAbsolute(
  342. NegotiateMessage,
  343. InputTokenSize,
  344. &NegotiateMessage->OemDomainName,
  345. &OemDomainName,
  346. FALSE, // No special alignment
  347. FALSE ) ) { // NULL not OK
  348. Status = SEC_E_INVALID_TOKEN;
  349. SspPrint(( SSP_CRITICAL,
  350. "SsprHandleNegotiateMessage: Error from SspConvertRelativeToAbsolute.\n" ));
  351. goto Cleanup;
  352. }
  353. if ( !SspConvertRelativeToAbsolute(
  354. NegotiateMessage,
  355. InputTokenSize,
  356. &NegotiateMessage->OemWorkstationName,
  357. &OemWorkstationName,
  358. FALSE, // No special alignment
  359. FALSE ) ) { // NULL not OK
  360. Status = SEC_E_INVALID_TOKEN;
  361. SspPrint(( SSP_CRITICAL,
  362. "SsprHandleNegotiateMessage: Error from SspConvertRelativeToAbsolute.\n" ));
  363. goto Cleanup;
  364. }
  365. //
  366. // If both strings match,
  367. // this is a local call.
  368. // The strings have already been uppercased.
  369. //
  370. RtlAcquireResourceShared(&NtLmGlobalCritSect, TRUE);
  371. if ( RtlEqualString( &OemWorkstationName,
  372. &NtLmGlobalOemComputerNameString,
  373. FALSE ) &&
  374. RtlEqualString( &OemDomainName,
  375. &NtLmGlobalOemPrimaryDomainNameString,
  376. FALSE )
  377. )
  378. {
  379. #if DBG
  380. IF_DEBUG( NO_LOCAL ) {
  381. // nothing.
  382. } else {
  383. #endif
  384. ChallengeMessage->NegotiateFlags |=
  385. NTLMSSP_NEGOTIATE_LOCAL_CALL;
  386. SspPrint(( SSP_MISC,
  387. "SsprHandleNegotiateMessage: Local Call.\n" ));
  388. ChallengeMessage->ServerContextHandle = (ULONG64)*ContextHandle;
  389. #if DBG
  390. }
  391. #endif
  392. }
  393. RtlReleaseResource (&NtLmGlobalCritSect);
  394. }
  395. //
  396. // Check if datagram is being negotiated
  397. //
  398. if ( (NegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) ==
  399. NTLMSSP_NEGOTIATE_DATAGRAM) {
  400. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_DATAGRAM;
  401. }
  402. } else {
  403. //
  404. // No negotiate message. We need to check if the caller is asking
  405. // for datagram.
  406. //
  407. if ((ContextReqFlags & ASC_REQ_DATAGRAM) == 0 ) {
  408. SspPrint(( SSP_CRITICAL,
  409. "SsprHandleNegotiateMessage: "
  410. "NegotiateMessage size wrong %ld\n",
  411. InputTokenSize ));
  412. Status = SEC_E_INVALID_TOKEN;
  413. goto Cleanup;
  414. }
  415. //
  416. // Allocate a Challenge message
  417. //
  418. //
  419. // always send target info -- new for NTLM3!
  420. //
  421. TargetFlags = NTLMSSP_NEGOTIATE_TARGET_INFO;
  422. ChallengeMessageSize = sizeof(*ChallengeMessage) + TargetInfo.Length;
  423. if ((ContextReqFlags & ASC_REQ_ALLOCATE_MEMORY) == 0)
  424. {
  425. if ( ChallengeMessageSize > *OutputTokenSize ) {
  426. Status = SEC_E_BUFFER_TOO_SMALL;
  427. SspPrint(( SSP_CRITICAL,
  428. "SsprHandleNegotiateMessage: invalid ChallengeMessageSize.\n" ));
  429. goto Cleanup;
  430. }
  431. }
  432. ChallengeMessage = (PCHALLENGE_MESSAGE)
  433. NtLmAllocateLsaHeap(ChallengeMessageSize );
  434. if ( ChallengeMessage == NULL ) {
  435. Status = STATUS_NO_MEMORY;
  436. SspPrint(( SSP_CRITICAL,
  437. "SsprHandleNegotiateMessage: Error allocating ChallengeMessage.\n" ));
  438. goto Cleanup;
  439. }
  440. //
  441. // Record in the context that we are doing datagram. We will tell
  442. // the client everything we can negotiate and let it decide what
  443. // to negotiate.
  444. //
  445. ChallengeMessage->NegotiateFlags = NTLMSSP_NEGOTIATE_DATAGRAM |
  446. NTLMSSP_NEGOTIATE_UNICODE |
  447. NTLMSSP_NEGOTIATE_OEM |
  448. NTLMSSP_NEGOTIATE_SIGN |
  449. NTLMSSP_NEGOTIATE_LM_KEY |
  450. NTLMSSP_NEGOTIATE_NTLM |
  451. NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
  452. NTLMSSP_NEGOTIATE_IDENTIFY |
  453. NTLMSSP_NEGOTIATE_NTLM2 |
  454. NTLMSSP_NEGOTIATE_KEY_EXCH |
  455. NegotiateFlagsKeyStrength
  456. ;
  457. if (NtLmGlobalEncryptionEnabled) {
  458. ChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
  459. }
  460. }
  461. //
  462. // Build the Challenge Message
  463. //
  464. strcpy( (char *) ChallengeMessage->Signature, NTLMSSP_SIGNATURE );
  465. ChallengeMessage->MessageType = NtLmChallenge;
  466. Status = SspGenerateRandomBits( (UCHAR*)ChallengeMessage->Challenge,
  467. MSV1_0_CHALLENGE_LENGTH );
  468. if( !NT_SUCCESS( Status ) ) {
  469. SspPrint(( SSP_CRITICAL,
  470. "SsprHandleNegotiateMessage: SspGenerateRandomBits failed\n"));
  471. goto Cleanup;
  472. }
  473. Where = (PCHAR)(ChallengeMessage+1);
  474. SspContextCopyString( ChallengeMessage,
  475. &ChallengeMessage->TargetName,
  476. &TargetName,
  477. &Where );
  478. SspContextCopyString( ChallengeMessage,
  479. &ChallengeMessage->TargetInfo,
  480. (PSTRING)&TargetInfo,
  481. &Where );
  482. ChallengeMessage->NegotiateFlags |= TargetFlags;
  483. //
  484. // Save the Challenge and Negotiate Flags in the Context so it
  485. // is available when the authenticate message comes in.
  486. //
  487. RtlCopyMemory( Context->Challenge,
  488. ChallengeMessage->Challenge,
  489. sizeof( Context->Challenge ) );
  490. Context->NegotiateFlags = ChallengeMessage->NegotiateFlags;
  491. if (!SsprCheckMinimumSecurity(
  492. Context->NegotiateFlags,
  493. NtLmGlobalMinimumServerSecurity)) {
  494. Status = SEC_E_UNSUPPORTED_FUNCTION;
  495. SspPrint(( SSP_CRITICAL,
  496. "SsprHandleNegotiateMessage: "
  497. "NegotiateMessage didn't support minimum security requirements. (caller=0x%lx wanted=0x%lx\n",
  498. Context->NegotiateFlags, NtLmGlobalMinimumServerSecurity ));
  499. goto Cleanup;
  500. }
  501. if ((ContextReqFlags & ASC_REQ_ALLOCATE_MEMORY) == 0)
  502. {
  503. RtlCopyMemory( *OutputToken,
  504. ChallengeMessage,
  505. ChallengeMessageSize );
  506. }
  507. else
  508. {
  509. *OutputToken = ChallengeMessage;
  510. ChallengeMessage = NULL;
  511. *ContextAttributes |= ASC_RET_ALLOCATED_MEMORY;
  512. }
  513. *OutputTokenSize = ChallengeMessageSize;
  514. //
  515. // Return output parameters to the caller.
  516. //
  517. *ExpirationTime = SspContextGetTimeStamp( Context, TRUE );
  518. Context->State = ChallengeSentState;
  519. Status = SEC_I_CONTINUE_NEEDED;
  520. //
  521. // Free and locally used resources.
  522. //
  523. Cleanup:
  524. if ( Context != NULL ) {
  525. //
  526. // If we failed, deallocate the context we allocated above.
  527. // Delinking is a side effect of referencing, so do that.
  528. //
  529. if ( !NT_SUCCESS(Status) ) {
  530. PSSP_CONTEXT LocalContext;
  531. SspContextReferenceContext( *ContextHandle,
  532. TRUE,
  533. &LocalContext
  534. );
  535. ASSERT( LocalContext != NULL );
  536. if ( LocalContext != NULL ) {
  537. SspContextDereferenceContext( LocalContext );
  538. }
  539. }
  540. // Always dereference it.
  541. SspContextDereferenceContext( Context );
  542. }
  543. if ( NegotiateMessage != NULL ) {
  544. (VOID) NtLmFreePrivateHeap( NegotiateMessage );
  545. }
  546. if ( ChallengeMessage != NULL ) {
  547. (VOID) NtLmFreeLsaHeap( ChallengeMessage );
  548. }
  549. if ( Credential != NULL ) {
  550. SspCredentialDereferenceCredential( Credential );
  551. }
  552. if ( NtLmLocalUnicodeTargetName.Buffer != NULL ) {
  553. (VOID) NtLmFreePrivateHeap( NtLmLocalUnicodeTargetName.Buffer );
  554. }
  555. if ( NtLmLocalOemTargetName.Buffer != NULL ) {
  556. (VOID) NtLmFreePrivateHeap( NtLmLocalOemTargetName.Buffer );
  557. }
  558. if (TargetInfo.Buffer != NULL ) {
  559. (VOID) NtLmFreePrivateHeap( TargetInfo.Buffer );
  560. }
  561. SspPrint(( SSP_API_MORE, "Leaving SsprHandleNegotiateMessage: 0x%lx\n", Status ));
  562. return Status;
  563. }
  564. NTSTATUS
  565. SsprHandleAuthenticateMessage(
  566. IN LSA_SEC_HANDLE CredentialHandle,
  567. IN OUT PLSA_SEC_HANDLE ContextHandle,
  568. IN ULONG ContextReqFlags,
  569. IN ULONG InputTokenSize,
  570. IN PVOID InputToken,
  571. IN ULONG SecondInputTokenSize,
  572. IN PVOID SecondInputToken,
  573. IN OUT PULONG OutputTokenSize,
  574. OUT PVOID *OutputToken,
  575. OUT PULONG ContextAttributes,
  576. OUT PTimeStamp ExpirationTime,
  577. OUT PUCHAR SessionKey,
  578. OUT PULONG NegotiateFlags,
  579. OUT PHANDLE TokenHandle,
  580. OUT PNTSTATUS ApiSubStatus,
  581. OUT PTimeStamp PasswordExpiry,
  582. OUT PULONG UserFlags
  583. )
  584. /*++
  585. Routine Description:
  586. Handle the authenticate message part of AcceptSecurityContext.
  587. Arguments:
  588. SessionKey - The session key for the context, used for signing and sealing
  589. NegotiateFlags - The flags negotiated for the context, used for sign & seal
  590. ApiSubStatus - Returns the substatus for why the logon failed.
  591. PasswordExpiry - Contains the time that the authenticated user's password
  592. expires, or 0x7fffffff ffffffff for local callers.
  593. UserFlags - UserFlags returned in LogonProfile.
  594. All other arguments same as for AcceptSecurityContext
  595. Return Value:
  596. STATUS_SUCCESS - Message handled
  597. SEC_E_INVALID_TOKEN -- Token improperly formatted
  598. SEC_E_INVALID_HANDLE -- Credential/Context Handle is invalid
  599. SEC_E_BUFFER_TOO_SMALL -- Buffer for output token isn't big enough
  600. SEC_E_LOGON_DENIED -- User is no allowed to logon to this server
  601. SEC_E_INSUFFICIENT_MEMORY -- Not enough memory
  602. --*/
  603. {
  604. SECURITY_STATUS SecStatus = STATUS_SUCCESS;
  605. NTSTATUS Status = STATUS_SUCCESS;
  606. PSSP_CONTEXT Context = NULL;
  607. PNEGOTIATE_MESSAGE NegotiateMessage = NULL;
  608. PAUTHENTICATE_MESSAGE AuthenticateMessage = NULL;
  609. PNTLM_AUTHENTICATE_MESSAGE NtLmAuthenticateMessage = NULL;
  610. PNTLM_ACCEPT_RESPONSE NtLmAcceptResponse = NULL;
  611. ULONG MsvLogonMessageSize = 0;
  612. PMSV1_0_LM20_LOGON MsvLogonMessage = NULL;
  613. ULONG MsvSubAuthLogonMessageSize = 0;
  614. PMSV1_0_SUBAUTH_LOGON MsvSubAuthLogonMessage = NULL;
  615. ULONG LogonProfileMessageSize;
  616. PMSV1_0_LM20_LOGON_PROFILE LogonProfileMessage = NULL;
  617. BOOLEAN DoUnicode = FALSE;
  618. STRING DomainName2;
  619. STRING UserName2;
  620. STRING Workstation2;
  621. STRING SessionKeyString;
  622. UNICODE_STRING DomainName;
  623. UNICODE_STRING UserName;
  624. UNICODE_STRING Workstation;
  625. LARGE_INTEGER KickOffTime;
  626. LUID LogonId = {0};
  627. HANDLE LocalTokenHandle = NULL;
  628. BOOLEAN LocalTokenHandleOpenned = FALSE;
  629. TOKEN_SOURCE SourceContext;
  630. QUOTA_LIMITS Quotas;
  631. NTSTATUS SubStatus;
  632. STRING OriginName;
  633. PCHAR Where;
  634. UCHAR LocalSessionKey[LM_RESPONSE_LENGTH];
  635. PSSP_CREDENTIAL Credential = NULL;
  636. BOOLEAN fCallFromSrv = FALSE;
  637. PUNICODE_STRING AccountName = NULL;
  638. PUNICODE_STRING AuthenticatingAuthority = NULL;
  639. PUNICODE_STRING WorkstationName = NULL;
  640. STRING NtChallengeResponse;
  641. STRING LmChallengeResponse;
  642. BOOL fSubAuth = FALSE;
  643. ULONG SubAuthPackageId = 0;
  644. PSID AllocatedAuditSid = NULL ;
  645. PSID AuditSid = NULL;
  646. BOOLEAN fAvoidGuestAudit = FALSE;
  647. SECPKG_PRIMARY_CRED PrimaryCredentials;
  648. //Tracing State
  649. NTLM_TRACE_INFO TraceInfo = {0};
  650. PLSA_SEC_HANDLE TraceOldContextHandle = ContextHandle;
  651. ASSERT(LM_RESPONSE_LENGTH >= MSV1_0_USER_SESSION_KEY_LENGTH);
  652. SspPrint(( SSP_API_MORE, "Entering SsprHandleAuthenticateMessage\n"));
  653. //
  654. // Initialization
  655. //
  656. *ContextAttributes = 0;
  657. RtlInitUnicodeString(
  658. &DomainName,
  659. NULL
  660. );
  661. RtlInitUnicodeString(
  662. &UserName,
  663. NULL
  664. );
  665. RtlInitUnicodeString(
  666. &Workstation,
  667. NULL
  668. );
  669. *ApiSubStatus = STATUS_SUCCESS;
  670. PasswordExpiry->LowPart = 0xffffffff;
  671. PasswordExpiry->HighPart = 0x7fffffff;
  672. *UserFlags = 0;
  673. RtlZeroMemory(&PrimaryCredentials, sizeof(SECPKG_PRIMARY_CRED));
  674. if (*ContextHandle == NULL)
  675. {
  676. // This is possibly an old style srv call (for 4.0 and before)
  677. // so, alloc the context and replace the creds if new ones exists
  678. fCallFromSrv = TRUE;
  679. SspPrint((SSP_API_MORE, "SsprHandleAuthenticateMessage: *ContextHandle is NULL (old style SRV)\n"));
  680. SECPKG_CALL_INFO CallInfo = {0};
  681. //
  682. // Client must have TCB, otherwise an un-trusted LSA-client could use a
  683. // stolen challenge/response pair to network logon any user
  684. //
  685. if ( !LsaFunctions->GetCallInfo( &CallInfo ) ||
  686. ((CallInfo.Attributes & SECPKG_CALL_IS_TCB) == 0)
  687. )
  688. {
  689. Status = STATUS_PRIVILEGE_NOT_HELD;
  690. SspPrint((SSP_CRITICAL,
  691. "SsprHandleAuthenticateMessage: Client does not hold Tcb\n"));
  692. goto Cleanup;
  693. }
  694. SecStatus = SspCredentialReferenceCredential(
  695. CredentialHandle,
  696. FALSE,
  697. &Credential );
  698. if ( !NT_SUCCESS( SecStatus ) )
  699. {
  700. SspPrint(( SSP_CRITICAL,
  701. "SsprHandleAuthenticateMessage: SspCredentialReferenceCredential returns %x.\n", SecStatus ));
  702. goto Cleanup;
  703. }
  704. // check the validity of the NtlmAuthenticateMessage
  705. if (SecondInputTokenSize < sizeof(NTLM_AUTHENTICATE_MESSAGE))
  706. {
  707. SspPrint(( SSP_CRITICAL,
  708. "SsprHandleAuthenticateMessage: NtlmAuthenticateMessage size if bogus.\n" ));
  709. SecStatus = SEC_E_INVALID_TOKEN;
  710. goto Cleanup;
  711. }
  712. // This is a superflous check since we alloc only if the caller
  713. // has asked us too. This is to make sure that the srv always allocs
  714. if (ContextReqFlags & ISC_REQ_ALLOCATE_MEMORY)
  715. {
  716. SspPrint(( SSP_CRITICAL,
  717. "SsprHandleAuthenticateMessage: ContextReqFlags has ISC_REQ_ALLOCATE_MEMORY.\n" ));
  718. SecStatus = STATUS_NOT_SUPPORTED;
  719. goto Cleanup;
  720. }
  721. if (*OutputTokenSize < sizeof(NTLM_ACCEPT_RESPONSE))
  722. {
  723. SspPrint(( SSP_CRITICAL,
  724. "SsprHandleAuthenticateMessage: NtlmAcceptResponse size if bogus.\n" ));
  725. SecStatus = SEC_E_INVALID_TOKEN;
  726. goto Cleanup;
  727. }
  728. //
  729. // Allocate a new context
  730. //
  731. Context = SspContextAllocateContext();
  732. if (Context == NULL)
  733. {
  734. SspPrint(( SSP_CRITICAL,
  735. "SsprHandleAuthenticateMessage: SspContextAllocateContext returns NULL.\n" ));
  736. SecStatus = STATUS_NO_MEMORY;
  737. goto Cleanup;
  738. }
  739. // We've just added a context, we don't nornally add and then
  740. // reference it.
  741. SspContextDereferenceContext( Context );
  742. *ContextHandle = (LSA_SEC_HANDLE) Context;
  743. // Assign the Credential
  744. Context->Credential = Credential;
  745. Credential = NULL;
  746. NtLmAuthenticateMessage = (PNTLM_AUTHENTICATE_MESSAGE) SecondInputToken;
  747. if (NtLmAuthenticateMessage == NULL)
  748. {
  749. SspPrint(( SSP_CRITICAL,
  750. "SsprHandleAuthenticateMessage: Error while assigning NtLmAuthenticateMessage\n" ));
  751. SecStatus = STATUS_NO_MEMORY;
  752. goto Cleanup;
  753. }
  754. // copy challenge from NTLM_AUTHENTICATE_MESSAGE
  755. RtlCopyMemory(Context->Challenge,
  756. NtLmAuthenticateMessage->ChallengeToClient,
  757. MSV1_0_CHALLENGE_LENGTH);
  758. if (NtLmAuthenticateMessage->ParameterControl & MSV1_0_SUBAUTHENTICATION_FLAGS)
  759. {
  760. fSubAuth = TRUE;
  761. SubAuthPackageId = (NtLmAuthenticateMessage->ParameterControl >>
  762. MSV1_0_SUBAUTHENTICATION_DLL_SHIFT)
  763. ;
  764. }
  765. Context->State = ChallengeSentState;
  766. Context->NegotiateFlags = NTLMSSP_NEGOTIATE_UNICODE ;
  767. //
  768. // The server may request this option with a <= 4.0 client, in
  769. // which case HandleNegotiateMessage, which normally sets
  770. // this flag, won't have been called.
  771. //
  772. if ( (ContextReqFlags & ASC_REQ_ALLOW_NON_USER_LOGONS ) != 0) {
  773. *ContextAttributes |= ASC_RET_ALLOW_NON_USER_LOGONS;
  774. Context->ContextFlags |= ASC_RET_ALLOW_NON_USER_LOGONS;
  775. }
  776. }
  777. //
  778. // Find the currently existing context.
  779. //
  780. SecStatus = SspContextReferenceContext( *ContextHandle, FALSE, &Context );
  781. if ( !NT_SUCCESS(SecStatus) )
  782. {
  783. SspPrint(( SSP_CRITICAL,
  784. "SsprHandleAuthenticateMessage: Error from SspContextReferenceContext.\n" ));
  785. goto Cleanup;
  786. }
  787. if ( ( Context->State != ChallengeSentState) &&
  788. ( Context->State != AuthenticatedState) ) {
  789. SspPrint(( SSP_CRITICAL,
  790. "SsprHandleAuthenticateMessage: "
  791. "Context not in ChallengeSentState\n" ));
  792. SecStatus = SEC_E_OUT_OF_SEQUENCE;
  793. goto Cleanup;
  794. }
  795. //
  796. // Ignore the Credential Handle.
  797. //
  798. // Since this is the second call,
  799. // the credential is implied by the Context.
  800. // We could double check that the Credential Handle is either NULL or
  801. // correct. However, our implementation doesn't maintain a close
  802. // association between the two (actually no association) so checking
  803. // would require a lot of overhead.
  804. //
  805. UNREFERENCED_PARAMETER( CredentialHandle );
  806. //
  807. // Get the AuthenticateMessage.
  808. //
  809. if ( InputTokenSize < sizeof(OLD_AUTHENTICATE_MESSAGE) ) {
  810. SspPrint(( SSP_CRITICAL,
  811. "SsprHandleAuthenticateMessage: "
  812. "AuthenticateMessage size wrong %ld\n",
  813. InputTokenSize ));
  814. SecStatus = SEC_E_INVALID_TOKEN;
  815. goto Cleanup;
  816. }
  817. SecStatus = SspContextGetMessage( InputToken,
  818. InputTokenSize,
  819. NtLmAuthenticate,
  820. (PVOID *)&AuthenticateMessage );
  821. if ( !NT_SUCCESS(SecStatus) ) {
  822. SspPrint(( SSP_CRITICAL,
  823. "SsprHandleAuthenticateMessage: "
  824. "AuthenticateMessage GetMessage returns 0x%lx\n",
  825. SecStatus ));
  826. goto Cleanup;
  827. }
  828. if (fCallFromSrv)
  829. {
  830. // Copy the Context Negotiate Flags from what's sent in
  831. Context->NegotiateFlags |= AuthenticateMessage->NegotiateFlags;
  832. }
  833. //
  834. // If the call comes and we have already authenticated, then it is
  835. // probably RPC trying to reauthenticate, which happens when someone
  836. // calls two interfaces on the same connection. In this case we don't
  837. // have to do anything - we just return success and let them get on
  838. // with it. We do want to check that the input token is all zeros,
  839. // though.
  840. //
  841. if ( Context->State == AuthenticatedState ) {
  842. AUTHENTICATE_MESSAGE NullMessage;
  843. *OutputTokenSize = 0;
  844. //
  845. // Check that all the fields are null. There are 5 strings
  846. // in the Authenticate message that have to be set to zero.
  847. //
  848. RtlZeroMemory(&NullMessage.LmChallengeResponse,5*sizeof(STRING32));
  849. if (memcmp(&AuthenticateMessage->LmChallengeResponse,
  850. &NullMessage.LmChallengeResponse,
  851. sizeof(STRING32) * 5) ) {
  852. SecStatus = SEC_E_INVALID_TOKEN;
  853. SspPrint(( SSP_CRITICAL,
  854. "SsprHandleAuthenticateMessage: "
  855. "AuthenticateMessage->LmChallengeResponse is not zeroed\n"));
  856. }
  857. else
  858. {
  859. *ContextAttributes = SSP_RET_REAUTHENTICATION;
  860. SecStatus = STATUS_SUCCESS;
  861. }
  862. goto Cleanup;
  863. }
  864. //
  865. // If we are re-establishing a datagram context, get the negotiate flags
  866. // out of this message.
  867. //
  868. if ((Context->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) != 0) {
  869. if ((InputTokenSize < sizeof(AUTHENTICATE_MESSAGE)) ||
  870. ((AuthenticateMessage->NegotiateFlags &
  871. NTLMSSP_NEGOTIATE_DATAGRAM) == 0) ) {
  872. SecStatus = SEC_E_INVALID_TOKEN;
  873. goto Cleanup;
  874. }
  875. Context->NegotiateFlags = AuthenticateMessage->NegotiateFlags;
  876. //
  877. // always do key exchange with datagram if we need a key (for SIGN or SEAL)
  878. //
  879. if (Context->NegotiateFlags & (NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL))
  880. {
  881. Context->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
  882. }
  883. //
  884. // if got NTLM2, don't use LM_KEY
  885. //
  886. if ( (Context->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) != 0 )
  887. {
  888. if( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY ) {
  889. SspPrint(( SSP_NEGOTIATE_FLAGS,
  890. "SsprHandleAuthenticateMessage: "
  891. "AuthenticateMessage (datagram) NTLM2 caused LM_KEY to be disabled.\n" ));
  892. }
  893. Context->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
  894. }
  895. }
  896. //
  897. // Check that client asked for minimum security required.
  898. // not done for legacy down-level case, as, NegotiateFlags are
  899. // constructed from incomplete information.
  900. //
  901. if( !fCallFromSrv )
  902. {
  903. if (!SsprCheckMinimumSecurity(
  904. AuthenticateMessage->NegotiateFlags,
  905. NtLmGlobalMinimumServerSecurity)) {
  906. SecStatus = SEC_E_UNSUPPORTED_FUNCTION;
  907. SspPrint(( SSP_CRITICAL,
  908. "SsprHandleAuthenticateMessage: "
  909. "client didn't support minimum security requirements.\n" ));
  910. goto Cleanup;
  911. }
  912. }
  913. //
  914. // Convert relative pointers to absolute.
  915. //
  916. DoUnicode = ( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE ) != 0;
  917. if (!SspConvertRelativeToAbsolute(AuthenticateMessage,
  918. InputTokenSize,
  919. &AuthenticateMessage->LmChallengeResponse,
  920. (PSTRING) &LmChallengeResponse,
  921. FALSE, // No special alignment
  922. TRUE ) ) { // NULL OK
  923. SecStatus = SEC_E_INVALID_TOKEN;
  924. goto Cleanup;
  925. }
  926. if (!SspConvertRelativeToAbsolute(AuthenticateMessage,
  927. InputTokenSize,
  928. &AuthenticateMessage->NtChallengeResponse,
  929. (PSTRING) &NtChallengeResponse,
  930. FALSE, // No special alignment
  931. TRUE ) ) { // NULL OK
  932. SecStatus = SEC_E_INVALID_TOKEN;
  933. goto Cleanup;
  934. }
  935. if (!SspConvertRelativeToAbsolute(AuthenticateMessage,
  936. InputTokenSize,
  937. &AuthenticateMessage->DomainName,
  938. &DomainName2,
  939. DoUnicode, // Unicode alignment
  940. TRUE ) ) { // NULL OK
  941. SecStatus = SEC_E_INVALID_TOKEN;
  942. goto Cleanup;
  943. }
  944. if ( !SspConvertRelativeToAbsolute( AuthenticateMessage,
  945. InputTokenSize,
  946. &AuthenticateMessage->UserName,
  947. &UserName2,
  948. DoUnicode, // Unicode alignment
  949. #ifdef notdef
  950. //
  951. // Allow null sessions. The server should guard against them if
  952. // it doesn't want them.
  953. //
  954. FALSE )) { // User name cannot be NULL
  955. #endif // notdef
  956. TRUE ) ) { // NULL OK
  957. SecStatus = SEC_E_INVALID_TOKEN;
  958. goto Cleanup;
  959. }
  960. if ( !SspConvertRelativeToAbsolute( AuthenticateMessage,
  961. InputTokenSize,
  962. &AuthenticateMessage->Workstation,
  963. &Workstation2,
  964. DoUnicode, // Unicode alignment
  965. TRUE ) ) { // NULL OK
  966. SecStatus = SEC_E_INVALID_TOKEN;
  967. goto Cleanup;
  968. }
  969. //
  970. // If this is datagram, get the session key
  971. //
  972. /// if ((Context->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) != 0) {
  973. if ((Context->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH) != 0) {
  974. if ( !SspConvertRelativeToAbsolute( AuthenticateMessage,
  975. InputTokenSize,
  976. &AuthenticateMessage->SessionKey,
  977. &SessionKeyString,
  978. FALSE, // No special alignment
  979. TRUE) ) { // NULL OK
  980. SecStatus = SEC_E_INVALID_TOKEN;
  981. goto Cleanup;
  982. }
  983. //
  984. // It should be NULL if this is a local call
  985. //
  986. if (((Context->NegotiateFlags & NTLMSSP_NEGOTIATE_LOCAL_CALL) == 0) &&
  987. (SessionKeyString.Buffer == NULL)) {
  988. SecStatus = SEC_E_INVALID_TOKEN;
  989. goto Cleanup;
  990. }
  991. if(Context->NegotiateFlags & NTLMSSP_NEGOTIATE_LOCAL_CALL)
  992. {
  993. static const UCHAR FixedSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH] = {
  994. 'S', 'y', 's', 't', 'e', 'm', 'L', 'i',
  995. 'b', 'r', 'a', 'r', 'y', 'D', 'T', 'C'
  996. };
  997. RtlCopyMemory(Context->SessionKey, FixedSessionKey, MSV1_0_USER_SESSION_KEY_LENGTH);
  998. }
  999. }
  1000. //
  1001. // Convert the domainname/user name/workstation to the right character set.
  1002. //
  1003. if ( DoUnicode ) {
  1004. DomainName = *((PUNICODE_STRING) &DomainName2);
  1005. UserName = *((PUNICODE_STRING) &UserName2);
  1006. Workstation = *((PUNICODE_STRING) &Workstation2);
  1007. } else {
  1008. SspPrint(( SSP_API_MORE, "SsprHandleAuthenticateMessage: Not doing Unicode\n"));
  1009. Status = RtlOemStringToUnicodeString(
  1010. &DomainName,
  1011. &DomainName2,
  1012. TRUE);
  1013. if ( !NT_SUCCESS(Status) ) {
  1014. SecStatus = SspNtStatusToSecStatus( Status,
  1015. SEC_E_INSUFFICIENT_MEMORY );
  1016. goto Cleanup;
  1017. }
  1018. Status = RtlOemStringToUnicodeString(
  1019. &UserName,
  1020. &UserName2,
  1021. TRUE);
  1022. if ( !NT_SUCCESS(Status) ) {
  1023. SecStatus = SspNtStatusToSecStatus( Status,
  1024. SEC_E_INSUFFICIENT_MEMORY );
  1025. goto Cleanup;
  1026. }
  1027. Status = RtlOemStringToUnicodeString(
  1028. &Workstation,
  1029. &Workstation2,
  1030. TRUE);
  1031. if ( !NT_SUCCESS(Status) ) {
  1032. SecStatus = SspNtStatusToSecStatus( Status,
  1033. SEC_E_INSUFFICIENT_MEMORY );
  1034. goto Cleanup;
  1035. }
  1036. }
  1037. //
  1038. // Trace the username, domain name and workstation
  1039. //
  1040. if (NtlmGlobalEventTraceFlag){
  1041. //Header goo
  1042. SET_TRACE_HEADER(TraceInfo,
  1043. NtlmAcceptGuid,
  1044. EVENT_TRACE_TYPE_INFO,
  1045. WNODE_FLAG_TRACED_GUID|WNODE_FLAG_USE_MOF_PTR,
  1046. 10);
  1047. int TraceHint = TRACE_ACCEPT_INFO;
  1048. SET_TRACE_DATA(TraceInfo,
  1049. TRACE_INITACC_STAGEHINT,
  1050. TraceHint);
  1051. SET_TRACE_DATAPTR(TraceInfo,
  1052. TRACE_INITACC_INCONTEXT,
  1053. TraceOldContextHandle);
  1054. SET_TRACE_DATAPTR(TraceInfo,
  1055. TRACE_INITACC_OUTCONTEXT,
  1056. ContextHandle);
  1057. // lets see the negotiate flags here
  1058. SET_TRACE_DATA(TraceInfo,
  1059. TRACE_INITACC_STATUS,
  1060. Context->NegotiateFlags);
  1061. SET_TRACE_USTRING(TraceInfo,
  1062. TRACE_INITACC_CLIENTNAME,
  1063. UserName);
  1064. SET_TRACE_USTRING(TraceInfo,
  1065. TRACE_INITACC_CLIENTDOMAIN,
  1066. DomainName);
  1067. SET_TRACE_USTRING(TraceInfo,
  1068. TRACE_INITACC_WORKSTATION,
  1069. Workstation);
  1070. TraceEvent(
  1071. NtlmGlobalTraceLoggerHandle,
  1072. (PEVENT_TRACE_HEADER)&TraceInfo
  1073. );
  1074. }
  1075. //
  1076. // If the client is on the same machine as we are, just
  1077. // use the token the client has already placed in our context structure,
  1078. //
  1079. if ( (Context->NegotiateFlags & NTLMSSP_NEGOTIATE_LOCAL_CALL ) &&
  1080. Context->TokenHandle != NULL &&
  1081. DomainName.Length == 0 &&
  1082. UserName.Length == 0 &&
  1083. Workstation.Length == 0 &&
  1084. AuthenticateMessage->NtChallengeResponse.Length == 0 &&
  1085. AuthenticateMessage->LmChallengeResponse.Length == 0 )
  1086. {
  1087. static const UCHAR FixedSessionKey[MSV1_0_USER_SESSION_KEY_LENGTH] = {
  1088. 'S', 'y', 's', 't', 'e', 'm', 'L', 'i',
  1089. 'b', 'r', 'a', 'r', 'y', 'D', 'T', 'C'
  1090. };
  1091. LocalTokenHandle = Context->TokenHandle;
  1092. Context->TokenHandle = NULL;
  1093. KickOffTime.HighPart = 0x7FFFFFFF;
  1094. KickOffTime.LowPart = 0xFFFFFFFF;
  1095. RtlCopyMemory(Context->SessionKey, FixedSessionKey, MSV1_0_USER_SESSION_KEY_LENGTH);
  1096. SspPrint(( SSP_MISC, "SsprHandleAuthenticateMessage: Local Call\n"));
  1097. if( (ContextReqFlags & ASC_REQ_DELEGATE) )
  1098. {
  1099. //
  1100. // can support another hop if loopback.
  1101. //
  1102. *ContextAttributes |= ASC_RET_DELEGATE;
  1103. Context->ContextFlags |= ASC_RET_DELEGATE;
  1104. }
  1105. //
  1106. // If the client is on a different machine than we are,
  1107. // use LsaLogonUser to create a token for the client.
  1108. //
  1109. } else {
  1110. //
  1111. // Store user name and domain name
  1112. //
  1113. SecStatus = NtLmDuplicateUnicodeString(
  1114. &Context->UserName,
  1115. &UserName);
  1116. if (!NT_SUCCESS(SecStatus)) {
  1117. goto Cleanup;
  1118. }
  1119. SecStatus = NtLmDuplicateUnicodeString(
  1120. &Context->DomainName,
  1121. &DomainName);
  1122. if (!NT_SUCCESS(SecStatus)) {
  1123. goto Cleanup;
  1124. }
  1125. //
  1126. // Allocate an MSV1_0 network logon message
  1127. //
  1128. if (!fSubAuth)
  1129. {
  1130. //
  1131. // The string buffers may be used as structure pointers later on.
  1132. // Align them to pointer boundaries to avoid alignment problems.
  1133. //
  1134. MsvLogonMessageSize =
  1135. ROUND_UP_COUNT(sizeof(*MsvLogonMessage) +
  1136. DomainName.Length +
  1137. UserName.Length +
  1138. Workstation.Length, ALIGN_LPVOID) +
  1139. ROUND_UP_COUNT(AuthenticateMessage->NtChallengeResponse.Length, ALIGN_LPVOID) +
  1140. AuthenticateMessage->LmChallengeResponse.Length;
  1141. MsvLogonMessage = (PMSV1_0_LM20_LOGON)
  1142. NtLmAllocatePrivateHeap(MsvLogonMessageSize );
  1143. if ( MsvLogonMessage == NULL ) {
  1144. SecStatus = STATUS_NO_MEMORY;
  1145. SspPrint(( SSP_CRITICAL,
  1146. "SsprHandleAuthenticateMessage: Error allocating MsvLogonMessage"));
  1147. goto Cleanup;
  1148. }
  1149. //
  1150. // Build the MSV1_0 network logon message to pass to the LSA.
  1151. //
  1152. MsvLogonMessage->MessageType = MsV1_0NetworkLogon;
  1153. Where = (PCHAR)(MsvLogonMessage+1);
  1154. SspContextCopyStringAbsolute( MsvLogonMessage,
  1155. (PSTRING)&MsvLogonMessage->LogonDomainName,
  1156. (PSTRING)&DomainName,
  1157. &Where );
  1158. SspContextCopyStringAbsolute( MsvLogonMessage,
  1159. (PSTRING)&MsvLogonMessage->UserName,
  1160. (PSTRING)&UserName,
  1161. &Where );
  1162. SspContextCopyStringAbsolute( MsvLogonMessage,
  1163. (PSTRING)&MsvLogonMessage->Workstation,
  1164. (PSTRING)&Workstation,
  1165. &Where );
  1166. RtlCopyMemory( MsvLogonMessage->ChallengeToClient,
  1167. Context->Challenge,
  1168. sizeof( MsvLogonMessage->ChallengeToClient ) );
  1169. Where = (PCHAR) ROUND_UP_POINTER(Where, ALIGN_LPVOID);
  1170. SspContextCopyStringAbsolute( MsvLogonMessage,
  1171. &MsvLogonMessage->CaseSensitiveChallengeResponse,
  1172. &NtChallengeResponse,
  1173. &Where );
  1174. Where = (PCHAR) ROUND_UP_POINTER(Where, ALIGN_LPVOID);
  1175. SspContextCopyStringAbsolute(MsvLogonMessage,
  1176. &MsvLogonMessage->CaseInsensitiveChallengeResponse,
  1177. &LmChallengeResponse,
  1178. &Where );
  1179. MsvLogonMessage->ParameterControl = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
  1180. // This is required by the pre 4.0 server
  1181. if (fCallFromSrv)
  1182. {
  1183. MsvLogonMessage->ParameterControl = MSV1_0_CLEARTEXT_PASSWORD_ALLOWED | NtLmAuthenticateMessage->ParameterControl;
  1184. if ( (Context->ContextFlags & ASC_RET_ALLOW_NON_USER_LOGONS ) != 0)
  1185. {
  1186. MsvLogonMessage->ParameterControl |= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
  1187. }
  1188. } else {
  1189. MsvLogonMessage->ParameterControl |= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
  1190. }
  1191. //
  1192. // Get the profile path for EFS
  1193. //
  1194. MsvLogonMessage->ParameterControl |= MSV1_0_RETURN_PROFILE_PATH;
  1195. //
  1196. // By passing in the RETURN_PASSWORD_EXPIRY flag, the password
  1197. // expiration time is returned in the logoff time
  1198. //
  1199. MsvLogonMessage->ParameterControl |= MSV1_0_RETURN_PASSWORD_EXPIRY;
  1200. //
  1201. // for Personal easy file/print sharing, hint to LsaLogonUser
  1202. // that Forced Guest may occur.
  1203. //
  1204. MsvLogonMessage->ParameterControl |= MSV1_0_ALLOW_FORCE_GUEST;
  1205. }
  1206. else
  1207. {
  1208. MsvSubAuthLogonMessageSize =
  1209. ROUND_UP_COUNT(sizeof(*MsvSubAuthLogonMessage) +
  1210. DomainName.Length +
  1211. UserName.Length +
  1212. Workstation.Length, ALIGN_LPVOID) +
  1213. ROUND_UP_COUNT(AuthenticateMessage->NtChallengeResponse.Length, ALIGN_LPVOID) +
  1214. AuthenticateMessage->LmChallengeResponse.Length;
  1215. MsvSubAuthLogonMessage = (PMSV1_0_SUBAUTH_LOGON)
  1216. NtLmAllocatePrivateHeap(MsvSubAuthLogonMessageSize );
  1217. if ( MsvSubAuthLogonMessage == NULL ) {
  1218. SecStatus = STATUS_NO_MEMORY;
  1219. SspPrint(( SSP_CRITICAL,
  1220. "SsprHandleAuthenticateMessage: Error allocating MsvSubAuthLogonMessage"));
  1221. goto Cleanup;
  1222. }
  1223. //
  1224. // Build the MSV1_0 subauth logon message to pass to the LSA.
  1225. //
  1226. MsvSubAuthLogonMessage->MessageType = MsV1_0SubAuthLogon;
  1227. Where = (PCHAR)(MsvSubAuthLogonMessage+1);
  1228. SspContextCopyStringAbsolute( MsvSubAuthLogonMessage,
  1229. (PSTRING)&MsvSubAuthLogonMessage->LogonDomainName,
  1230. (PSTRING)&DomainName,
  1231. &Where );
  1232. SspContextCopyStringAbsolute( MsvSubAuthLogonMessage,
  1233. (PSTRING)&MsvSubAuthLogonMessage->UserName,
  1234. (PSTRING)&UserName,
  1235. &Where );
  1236. SspContextCopyStringAbsolute( MsvSubAuthLogonMessage,
  1237. (PSTRING)&MsvSubAuthLogonMessage->Workstation,
  1238. (PSTRING)&Workstation,
  1239. &Where );
  1240. RtlCopyMemory( MsvSubAuthLogonMessage->ChallengeToClient,
  1241. Context->Challenge,
  1242. sizeof( MsvSubAuthLogonMessage->ChallengeToClient ) );
  1243. Where = (PCHAR) ROUND_UP_POINTER(Where, ALIGN_LPVOID);
  1244. SspContextCopyStringAbsolute( MsvSubAuthLogonMessage,
  1245. &MsvSubAuthLogonMessage->AuthenticationInfo1,
  1246. &LmChallengeResponse,
  1247. &Where );
  1248. Where = (PCHAR) ROUND_UP_POINTER(Where, ALIGN_LPVOID);
  1249. SspContextCopyStringAbsolute(MsvSubAuthLogonMessage,
  1250. &MsvSubAuthLogonMessage->AuthenticationInfo2,
  1251. &NtChallengeResponse,
  1252. &Where );
  1253. MsvSubAuthLogonMessage->ParameterControl = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
  1254. MsvSubAuthLogonMessage->SubAuthPackageId = SubAuthPackageId;
  1255. // This is required by the pre 4.0 server
  1256. if (fCallFromSrv)
  1257. {
  1258. MsvSubAuthLogonMessage->ParameterControl = MSV1_0_CLEARTEXT_PASSWORD_ALLOWED | NtLmAuthenticateMessage->ParameterControl;
  1259. }
  1260. if ( (Context->ContextFlags & ASC_RET_ALLOW_NON_USER_LOGONS ) != 0) {
  1261. MsvSubAuthLogonMessage->ParameterControl |= MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
  1262. }
  1263. //
  1264. // By passing in the RETURN_PASSWORD_EXPIRY flag, the password
  1265. // expiration time is returned in the logoff time
  1266. //
  1267. MsvSubAuthLogonMessage->ParameterControl |= MSV1_0_RETURN_PASSWORD_EXPIRY;
  1268. //
  1269. // for Personal easy file/print sharing, hint to LsaLogonUser
  1270. // that Forced Guest may occur.
  1271. //
  1272. MsvSubAuthLogonMessage->ParameterControl |= MSV1_0_ALLOW_FORCE_GUEST;
  1273. }
  1274. //
  1275. // if NTLM2 is negotiated, then mix my challenge with the client's...
  1276. // But, special case for null sessions. since we already negotiated
  1277. // NTLM2, but the LmChallengeResponse field is actually used
  1278. // here. REVIEW -- maybe don't negotiate NTLM2 if NULL session
  1279. //
  1280. if((Context->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) &&
  1281. (AuthenticateMessage->LmChallengeResponse.Length >= MSV1_0_CHALLENGE_LENGTH))
  1282. {
  1283. MsvLogonMessage->ParameterControl |= MSV1_0_USE_CLIENT_CHALLENGE;
  1284. }
  1285. //
  1286. // Log this user on.
  1287. //
  1288. // No origin (could use F(workstaion))
  1289. RtlInitString( &OriginName, NULL );
  1290. strncpy( SourceContext.SourceName,
  1291. "NtLmSsp ",
  1292. sizeof(SourceContext.SourceName) );
  1293. RtlZeroMemory( &SourceContext.SourceIdentifier,
  1294. sizeof(SourceContext.SourceIdentifier) );
  1295. {
  1296. PVOID TokenInformation;
  1297. LSA_TOKEN_INFORMATION_TYPE TokenInformationType;
  1298. LSA_TOKEN_INFORMATION_TYPE OriginalTokenType;
  1299. PSECPKG_SUPPLEMENTAL_CRED_ARRAY Credentials = NULL;
  1300. PPRIVILEGE_SET PrivilegesAssigned = NULL;
  1301. if (!fSubAuth)
  1302. {
  1303. Status = LsaApLogonUserEx2(
  1304. (PLSA_CLIENT_REQUEST) (-1),
  1305. Network,
  1306. MsvLogonMessage,
  1307. MsvLogonMessage,
  1308. MsvLogonMessageSize,
  1309. (PVOID *) &LogonProfileMessage,
  1310. &LogonProfileMessageSize,
  1311. &LogonId,
  1312. &SubStatus,
  1313. &TokenInformationType,
  1314. &TokenInformation,
  1315. &AccountName,
  1316. &AuthenticatingAuthority,
  1317. &WorkstationName,
  1318. &PrimaryCredentials,
  1319. &Credentials
  1320. );
  1321. }
  1322. else
  1323. {
  1324. Status = LsaApLogonUserEx2(
  1325. (PLSA_CLIENT_REQUEST) (-1),
  1326. Network,
  1327. MsvSubAuthLogonMessage,
  1328. MsvSubAuthLogonMessage,
  1329. MsvSubAuthLogonMessageSize,
  1330. (PVOID *) &LogonProfileMessage,
  1331. &LogonProfileMessageSize,
  1332. &LogonId,
  1333. &SubStatus,
  1334. &TokenInformationType,
  1335. &TokenInformation,
  1336. &AccountName,
  1337. &AuthenticatingAuthority,
  1338. &WorkstationName,
  1339. &PrimaryCredentials,
  1340. &Credentials
  1341. );
  1342. }
  1343. if ( !NT_SUCCESS(Status) ) {
  1344. SspPrint(( SSP_CRITICAL,
  1345. "SsprHandleAuthenticateMessage: "
  1346. "LsaApLogonUserEx2 returns 0x%lx for context 0x%x\n",
  1347. Status, Context ));
  1348. SecStatus = SspNtStatusToSecStatus( Status, SEC_E_LOGON_DENIED );
  1349. if (Status == STATUS_PASSWORD_MUST_CHANGE) {
  1350. *ApiSubStatus = Status;
  1351. }
  1352. else if (Status == STATUS_ACCOUNT_RESTRICTION) {
  1353. *ApiSubStatus = SubStatus;
  1354. } else {
  1355. *ApiSubStatus = Status;
  1356. }
  1357. goto Cleanup;
  1358. }
  1359. if ( !NT_SUCCESS(SubStatus) ) {
  1360. SspPrint(( SSP_CRITICAL,
  1361. "SsprHandleAuthenticateMessage: "
  1362. "LsaApLogonUserEx2 returns SubStatus of 0x%lx\n",
  1363. SubStatus ));
  1364. SecStatus = SspNtStatusToSecStatus( SubStatus, SEC_E_LOGON_DENIED );
  1365. goto Cleanup;
  1366. }
  1367. //
  1368. // Check if this was a null session. The TokenInformationType will
  1369. // be LsaTokenInformationNull if it is. If so, we may need to fail
  1370. // the logon.
  1371. //
  1372. if (TokenInformationType == LsaTokenInformationNull)
  1373. {
  1374. //
  1375. // RESTRICT_NULL_SESSIONS deemed too risky because legacy behavior of package
  1376. // allows null sessions from SYSTEM.
  1377. //
  1378. #ifdef RESTRICT_NULL_SESSIONS
  1379. if ((Context->ContextFlags & ASC_REQ_ALLOW_NULL_SESSION) == 0) {
  1380. SspPrint(( SSP_CRITICAL,
  1381. "SsprHandleAuthenticateMessage: "
  1382. "Null session logon attempted but not allowed\n" ));
  1383. SecStatus = SEC_E_LOGON_DENIED;
  1384. goto Cleanup;
  1385. }
  1386. #endif
  1387. *ContextAttributes |= ASC_RET_NULL_SESSION;
  1388. Context->ContextFlags |= ASC_RET_NULL_SESSION;
  1389. Context->NegotiateFlags |= NTLMSSP_NEGOTIATE_NULL_SESSION;
  1390. AuditSid = NtLmGlobalAnonymousSid;
  1391. }
  1392. else
  1393. {
  1394. PLSA_TOKEN_INFORMATION_V2 TokenInfoV2 ;
  1395. TokenInfoV2 = (PLSA_TOKEN_INFORMATION_V2) TokenInformation ;
  1396. SafeAllocaAllocate( AllocatedAuditSid, RtlLengthSid( TokenInfoV2->User.User.Sid ) );
  1397. if ( AllocatedAuditSid )
  1398. {
  1399. RtlCopyMemory( AllocatedAuditSid,
  1400. TokenInfoV2->User.User.Sid,
  1401. RtlLengthSid( TokenInfoV2->User.User.Sid ) );
  1402. }
  1403. AuditSid = AllocatedAuditSid;
  1404. }
  1405. Status = LsaFunctions->CreateTokenEx(
  1406. &LogonId,
  1407. &SourceContext,
  1408. Network,
  1409. (((Context->NegotiateFlags & NTLMSSP_NEGOTIATE_IDENTIFY) != 0) ?
  1410. SecurityIdentification : SecurityImpersonation),
  1411. TokenInformationType,
  1412. TokenInformation,
  1413. NULL,
  1414. WorkstationName,
  1415. ((LogonProfileMessage->UserFlags & LOGON_PROFILE_PATH_RETURNED) != 0) ? &LogonProfileMessage->UserParameters : NULL,
  1416. &PrimaryCredentials,
  1417. SecSessionPrimaryCred,
  1418. &LocalTokenHandle,
  1419. &SubStatus);
  1420. } // end of block for LsaLogonUser
  1421. if ( !NT_SUCCESS(Status) ) {
  1422. SspPrint(( SSP_CRITICAL,
  1423. "SsprHandleAuthenticateMessage: "
  1424. "CreateToken returns 0x%lx\n",
  1425. Status ));
  1426. SecStatus = Status;
  1427. goto Cleanup;
  1428. }
  1429. if ( !NT_SUCCESS(SubStatus) ) {
  1430. SspPrint(( SSP_CRITICAL,
  1431. "SsprHandleAuthenticateMessage: "
  1432. "CreateToken returns SubStatus of 0x%lx\n",
  1433. SubStatus ));
  1434. SecStatus = SubStatus;
  1435. goto Cleanup;
  1436. }
  1437. LocalTokenHandleOpenned = TRUE;
  1438. //
  1439. // Don't allow cleartext password on the logon.
  1440. // Except if called from Downlevel
  1441. if (!fCallFromSrv)
  1442. {
  1443. if ( LogonProfileMessage->UserFlags & LOGON_NOENCRYPTION ) {
  1444. SspPrint(( SSP_CRITICAL,
  1445. "SsprHandleAuthenticateMessage: "
  1446. "LsaLogonUser used cleartext password\n" ));
  1447. SecStatus = SEC_E_LOGON_DENIED;
  1448. goto Cleanup;
  1449. }
  1450. }
  1451. //
  1452. // If we did a guest logon, set the substatus to be STATUS_NO_SUCH_USER
  1453. //
  1454. if ( LogonProfileMessage->UserFlags & LOGON_GUEST ) {
  1455. fAvoidGuestAudit = TRUE;
  1456. *ApiSubStatus = STATUS_NO_SUCH_USER;
  1457. #if 0
  1458. //
  1459. // If caller required Sign/Seal, fail them here
  1460. //
  1461. if (
  1462. (!NtLmGlobalForceGuest) &&
  1463. (Context->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL)
  1464. )
  1465. {
  1466. SspPrint(( SSP_CRITICAL,
  1467. "SsprHandleAuthenticateMessage: "
  1468. "LsaLogonUser logged user as a guest but seal is requested\n" ));
  1469. SecStatus = SEC_E_LOGON_DENIED;
  1470. goto Cleanup;
  1471. }
  1472. #endif
  1473. }
  1474. //
  1475. // Save important information about the caller.
  1476. //
  1477. KickOffTime = LogonProfileMessage->KickOffTime;
  1478. //
  1479. // By passing in the RETURN_PASSWORD_EXPIRY flag, the password
  1480. // expiration time is returned in the logoff time
  1481. //
  1482. *PasswordExpiry = LogonProfileMessage->LogoffTime;
  1483. *UserFlags = LogonProfileMessage->UserFlags;
  1484. //
  1485. // set the session key to what the client sent us (if anything)
  1486. //
  1487. if (Context->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH &&
  1488. AuthenticateMessage->SessionKey.Length == MSV1_0_USER_SESSION_KEY_LENGTH)
  1489. {
  1490. RtlCopyMemory(
  1491. Context->SessionKey,
  1492. SessionKeyString.Buffer,
  1493. MSV1_0_USER_SESSION_KEY_LENGTH
  1494. );
  1495. }
  1496. //
  1497. // Generate the session key, or decrypt the generated random one sent to
  1498. // us by the client, from various bits of info
  1499. //
  1500. SecStatus = SsprMakeSessionKey(
  1501. Context,
  1502. &LmChallengeResponse,
  1503. LogonProfileMessage->UserSessionKey,
  1504. LogonProfileMessage->LanmanSessionKey,
  1505. NULL
  1506. );
  1507. if ( !NT_SUCCESS(SecStatus) ) {
  1508. SspPrint(( SSP_CRITICAL,
  1509. "SsprHandleAuthenticateMessage: "
  1510. "SsprMakeSessionKey failed.\n" ));
  1511. goto Cleanup;
  1512. }
  1513. }
  1514. //
  1515. // Copy the logon domain name returned by the LSA if it is different.
  1516. // from the one the caller passed in. This may happen with temp duplicate
  1517. // accounts and local account
  1518. //
  1519. if ((LogonProfileMessage != NULL) &&
  1520. (LogonProfileMessage->LogonDomainName.Length != 0) &&
  1521. !RtlEqualUnicodeString(
  1522. &Context->DomainName,
  1523. &LogonProfileMessage->LogonDomainName,
  1524. TRUE // case insensitive
  1525. )) {
  1526. //
  1527. // erase the old domain name
  1528. //
  1529. if (Context->DomainName.Buffer != NULL) {
  1530. NtLmFreePrivateHeap(Context->DomainName.Buffer);
  1531. Context->DomainName.Buffer = NULL;
  1532. }
  1533. SecStatus = NtLmDuplicateUnicodeString(
  1534. &Context->DomainName,
  1535. &LogonProfileMessage->LogonDomainName
  1536. );
  1537. if (!NT_SUCCESS(SecStatus)) {
  1538. goto Cleanup;
  1539. }
  1540. }
  1541. //
  1542. // Allow the context to live until kickoff time.
  1543. //
  1544. SspContextSetTimeStamp( Context, KickOffTime );
  1545. //
  1546. // Return output parameters to the caller.
  1547. //
  1548. *ExpirationTime = SspContextGetTimeStamp( Context, TRUE );
  1549. //
  1550. // Return output token
  1551. //
  1552. if (fCallFromSrv)
  1553. {
  1554. NtLmAcceptResponse = (PNTLM_ACCEPT_RESPONSE) *OutputToken;
  1555. if (NtLmAcceptResponse == NULL)
  1556. {
  1557. SecStatus = SEC_E_INSUFFICIENT_MEMORY;
  1558. goto Cleanup;
  1559. }
  1560. LUID UNALIGNED * TempLogonId = (LUID UNALIGNED *) &NtLmAcceptResponse->LogonId;
  1561. *TempLogonId = LogonId;
  1562. NtLmAcceptResponse->UserFlags = LogonProfileMessage->UserFlags;
  1563. RtlCopyMemory(
  1564. NtLmAcceptResponse->UserSessionKey,
  1565. LogonProfileMessage->UserSessionKey,
  1566. MSV1_0_USER_SESSION_KEY_LENGTH
  1567. );
  1568. RtlCopyMemory(
  1569. NtLmAcceptResponse->LanmanSessionKey,
  1570. LogonProfileMessage->LanmanSessionKey,
  1571. MSV1_0_LANMAN_SESSION_KEY_LENGTH
  1572. );
  1573. LARGE_INTEGER UNALIGNED *TempKickoffTime = (LARGE_INTEGER UNALIGNED *) &NtLmAcceptResponse->KickoffTime;
  1574. *TempKickoffTime = LogonProfileMessage->KickOffTime;
  1575. }
  1576. else
  1577. {
  1578. *OutputTokenSize = 0;
  1579. }
  1580. //
  1581. // We don't support sign/seal options if fallback to Guest
  1582. // this is because the client and server won't have a matched session-key
  1583. // AND even if they did match (ie: blank password), the session-key
  1584. // would likely be well-known.
  1585. //
  1586. if ( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN ) {
  1587. *ContextAttributes |= ASC_RET_REPLAY_DETECT |
  1588. ASC_RET_SEQUENCE_DETECT |
  1589. ASC_RET_INTEGRITY;
  1590. }
  1591. if( !fAvoidGuestAudit )
  1592. {
  1593. if ( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL ) {
  1594. *ContextAttributes |= ASC_RET_CONFIDENTIALITY;
  1595. }
  1596. }
  1597. if( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_IDENTIFY ) {
  1598. *ContextAttributes |= ASC_RET_IDENTIFY;
  1599. }
  1600. if( Context->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM ) {
  1601. *ContextAttributes |= ASC_RET_DATAGRAM;
  1602. }
  1603. if ( ContextReqFlags & ASC_REQ_REPLAY_DETECT ) {
  1604. *ContextAttributes |= ASC_RET_REPLAY_DETECT;
  1605. }
  1606. if ( ContextReqFlags & ASC_REQ_SEQUENCE_DETECT ) {
  1607. *ContextAttributes |= ASC_RET_SEQUENCE_DETECT;
  1608. }
  1609. if ( ContextReqFlags & ASC_REQ_ALLOW_NON_USER_LOGONS ) {
  1610. *ContextAttributes |= ASC_RET_ALLOW_NON_USER_LOGONS;
  1611. }
  1612. SecStatus = STATUS_SUCCESS;
  1613. //
  1614. // Free and locally used resources.
  1615. //
  1616. Cleanup:
  1617. //
  1618. // Audit this logon
  1619. //
  1620. if (NT_SUCCESS(SecStatus)) {
  1621. //
  1622. // If we don't have an account name, this was a local connection
  1623. // and we didn't build a new token, so don't bother auditing.
  1624. // also, don't bother auditing logons that fellback to guest.
  1625. //
  1626. if ( (AccountName != NULL) &&
  1627. ((AccountName->Length != 0) || (*ContextAttributes & ASC_RET_NULL_SESSION)) &&
  1628. !fAvoidGuestAudit ) {
  1629. LsaFunctions->AuditLogon(
  1630. STATUS_SUCCESS,
  1631. STATUS_SUCCESS,
  1632. AccountName,
  1633. AuthenticatingAuthority,
  1634. WorkstationName,
  1635. AuditSid,
  1636. Network,
  1637. &SourceContext,
  1638. &LogonId
  1639. );
  1640. }
  1641. } else {
  1642. LsaFunctions->AuditLogon(
  1643. !NT_SUCCESS(Status) ? Status : SecStatus,
  1644. SubStatus,
  1645. &UserName,
  1646. &DomainName,
  1647. &Workstation,
  1648. NULL,
  1649. Network,
  1650. &SourceContext,
  1651. &LogonId
  1652. );
  1653. }
  1654. if ( Context != NULL ) {
  1655. Context->Server = TRUE;
  1656. Context->LastStatus = SecStatus;
  1657. Context->DownLevel = fCallFromSrv;
  1658. //
  1659. // Don't allow this context to be used again.
  1660. //
  1661. if ( NT_SUCCESS(SecStatus) ) {
  1662. Context->State = AuthenticatedState;
  1663. if ( LocalTokenHandle ) {
  1664. *TokenHandle = LocalTokenHandle;
  1665. }
  1666. LocalTokenHandle = NULL;
  1667. RtlCopyMemory(
  1668. SessionKey,
  1669. Context->SessionKey,
  1670. MSV1_0_USER_SESSION_KEY_LENGTH );
  1671. *NegotiateFlags = Context->NegotiateFlags;
  1672. //
  1673. // if caller wants only INTEGRITY, then wants application
  1674. // supplied sequence numbers...
  1675. //
  1676. if ((Context->ContextFlags &
  1677. (ASC_REQ_INTEGRITY | ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT)) ==
  1678. ASC_REQ_INTEGRITY)
  1679. {
  1680. *NegotiateFlags |= NTLMSSP_APP_SEQ;
  1681. }
  1682. } else {
  1683. Context->State = IdleState;
  1684. }
  1685. // If we just created this context, then we need to dereference it
  1686. // once more with feeling
  1687. if (fCallFromSrv && !NT_SUCCESS(SecStatus))
  1688. {
  1689. PSSP_CONTEXT LocalContext;
  1690. SspContextReferenceContext (*ContextHandle, TRUE, &LocalContext);
  1691. ASSERT (LocalContext != NULL);
  1692. if (LocalContext != NULL)
  1693. {
  1694. SspContextDereferenceContext( LocalContext );
  1695. }
  1696. }
  1697. SspContextDereferenceContext( Context );
  1698. }
  1699. if ( NegotiateMessage != NULL ) {
  1700. (VOID) NtLmFreePrivateHeap( NegotiateMessage );
  1701. }
  1702. if ( AuthenticateMessage != NULL ) {
  1703. (VOID) NtLmFreePrivateHeap( AuthenticateMessage );
  1704. }
  1705. if ( MsvLogonMessage != NULL ) {
  1706. (VOID) NtLmFreePrivateHeap( MsvLogonMessage );
  1707. }
  1708. if ( MsvSubAuthLogonMessage != NULL ) {
  1709. (VOID) NtLmFreePrivateHeap( MsvSubAuthLogonMessage );
  1710. }
  1711. if ( LogonProfileMessage != NULL ) {
  1712. (VOID) LsaFunctions->FreeLsaHeap( LogonProfileMessage );
  1713. }
  1714. if ( LocalTokenHandle != NULL && LocalTokenHandleOpenned ) {
  1715. (VOID) NtClose( LocalTokenHandle );
  1716. }
  1717. if ( !DoUnicode ) {
  1718. if ( DomainName.Buffer != NULL) {
  1719. RtlFreeUnicodeString( &DomainName );
  1720. }
  1721. if ( UserName.Buffer != NULL) {
  1722. RtlFreeUnicodeString( &UserName );
  1723. }
  1724. if ( Workstation.Buffer != NULL) {
  1725. RtlFreeUnicodeString( &Workstation );
  1726. }
  1727. }
  1728. if (AccountName != NULL) {
  1729. if (AccountName->Buffer != NULL) {
  1730. LsaFunctions->FreeLsaHeap(AccountName->Buffer);
  1731. }
  1732. LsaFunctions->FreeLsaHeap(AccountName);
  1733. }
  1734. if (AuthenticatingAuthority != NULL) {
  1735. if (AuthenticatingAuthority->Buffer != NULL) {
  1736. LsaFunctions->FreeLsaHeap(AuthenticatingAuthority->Buffer);
  1737. }
  1738. LsaFunctions->FreeLsaHeap(AuthenticatingAuthority);
  1739. }
  1740. if (WorkstationName != NULL) {
  1741. if (WorkstationName->Buffer != NULL) {
  1742. LsaFunctions->FreeLsaHeap(WorkstationName->Buffer);
  1743. }
  1744. LsaFunctions->FreeLsaHeap(WorkstationName);
  1745. }
  1746. if ( AllocatedAuditSid )
  1747. {
  1748. SafeAllocaFree( AllocatedAuditSid );
  1749. }
  1750. //
  1751. // need to free the PrimaryCredentials fields filled in by LsaApLogonUserEx2
  1752. //
  1753. if( PrimaryCredentials.DownlevelName.Buffer )
  1754. {
  1755. LsaFunctions->FreeLsaHeap(PrimaryCredentials.DownlevelName.Buffer);
  1756. }
  1757. if( PrimaryCredentials.DomainName.Buffer )
  1758. {
  1759. LsaFunctions->FreeLsaHeap(PrimaryCredentials.DomainName.Buffer);
  1760. }
  1761. if( PrimaryCredentials.UserSid )
  1762. {
  1763. LsaFunctions->FreeLsaHeap(PrimaryCredentials.UserSid);
  1764. }
  1765. if( PrimaryCredentials.LogonServer.Buffer )
  1766. {
  1767. LsaFunctions->FreeLsaHeap(PrimaryCredentials.LogonServer.Buffer);
  1768. }
  1769. //
  1770. // Set a flag telling RPC not to destroy the connection yet
  1771. //
  1772. if (!NT_SUCCESS(SecStatus)) {
  1773. *ContextAttributes |= ASC_RET_THIRD_LEG_FAILED;
  1774. }
  1775. SspPrint(( SSP_API_MORE, "Leaving SsprHandleAutheticateMessage: 0x%lx\n", SecStatus ));
  1776. return SecStatus;
  1777. }