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.

1163 lines
36 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. msvsharelevel.cxx
  5. Abstract:
  6. msvsharelevel
  7. Author:
  8. Larry Zhu (LZhu) January 1, 2002 Created
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "msvsharelevel.hxx"
  16. NTSTATUS
  17. GetNtlmChallengeMessage(
  18. IN OPTIONAL UNICODE_STRING* pPassword,
  19. IN OPTIONAL UNICODE_STRING* pUserName,
  20. IN OPTIONAL UNICODE_STRING* pDomainName,
  21. OUT ULONG* pcbNtlmChallengeMessage,
  22. OUT NTLM_CHALLENGE_MESSAGE** ppNtlmChallengeMessage
  23. )
  24. {
  25. TNtStatus Status;
  26. UCHAR* pWhere = NULL;
  27. ULONG cbNtlmChallengeMessage = 0;
  28. NTLM_CHALLENGE_MESSAGE* pNtlmChallengeMessage = NULL;
  29. *ppNtlmChallengeMessage = NULL;
  30. *pcbNtlmChallengeMessage = 0;
  31. cbNtlmChallengeMessage = (pPassword ? pPassword->Length : 0)
  32. + (pUserName ? pUserName->Length : 0)
  33. + (pDomainName ? pDomainName->Length : 0)
  34. + ROUND_UP_COUNT(sizeof(NTLM_CHALLENGE_MESSAGE), sizeof(ULONG_PTR));
  35. pNtlmChallengeMessage = (NTLM_CHALLENGE_MESSAGE*) new CHAR[cbNtlmChallengeMessage];
  36. Status DBGCHK = pNtlmChallengeMessage ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  37. if (NT_SUCCESS(Status))
  38. {
  39. RtlZeroMemory(pNtlmChallengeMessage, cbNtlmChallengeMessage);
  40. pWhere = (UCHAR*) (pNtlmChallengeMessage + 1);
  41. SspCopyStringAsString32(
  42. pNtlmChallengeMessage,
  43. (STRING*) pPassword,
  44. &pWhere,
  45. &pNtlmChallengeMessage->Password
  46. );
  47. SspCopyStringAsString32(
  48. pNtlmChallengeMessage,
  49. (STRING*) pUserName,
  50. &pWhere,
  51. &pNtlmChallengeMessage->UserName
  52. );
  53. SspCopyStringAsString32(
  54. pNtlmChallengeMessage,
  55. (STRING*) pDomainName,
  56. &pWhere,
  57. &pNtlmChallengeMessage->DomainName
  58. );
  59. *ppNtlmChallengeMessage = pNtlmChallengeMessage;
  60. pNtlmChallengeMessage = NULL;
  61. *pcbNtlmChallengeMessage = cbNtlmChallengeMessage;
  62. }
  63. if (pNtlmChallengeMessage)
  64. {
  65. delete [] pNtlmChallengeMessage;
  66. }
  67. return Status;
  68. }
  69. NTSTATUS
  70. GetNegociateMessage(
  71. IN OPTIONAL OEM_STRING* pOemDomainName,
  72. IN OPTIONAL OEM_STRING* pOemWorkstationName,
  73. IN ULONG NegotiateFlags,
  74. OUT ULONG* pcbNegotiateMessage,
  75. OUT NEGOTIATE_MESSAGE** ppNegotiateMessage
  76. )
  77. {
  78. TNtStatus Status = STATUS_SUCCESS;
  79. NEGOTIATE_MESSAGE* pNegotiateMessage = NULL;
  80. ULONG cbNegotiateMessage = 0;
  81. PUCHAR pWhere = NULL;
  82. *ppNegotiateMessage = NULL;
  83. *pcbNegotiateMessage = 0;
  84. cbNegotiateMessage = sizeof(NEGOTIATE_MESSAGE);
  85. if (pOemDomainName && pOemDomainName->Length && (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED & NegotiateFlags))
  86. {
  87. cbNegotiateMessage += pOemDomainName->MaximumLength;
  88. }
  89. if (pOemWorkstationName && pOemWorkstationName->Length && (NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED & NegotiateFlags))
  90. {
  91. cbNegotiateMessage += pOemWorkstationName->MaximumLength;
  92. }
  93. pNegotiateMessage = (NEGOTIATE_MESSAGE*) new char[cbNegotiateMessage];
  94. Status DBGCHK = pNegotiateMessage ? S_OK : E_OUTOFMEMORY;
  95. if (NT_SUCCESS(Status))
  96. {
  97. RtlZeroMemory(pNegotiateMessage, cbNegotiateMessage);
  98. cbNegotiateMessage = sizeof(NEGOTIATE_MESSAGE);
  99. strcpy(reinterpret_cast<char*>(pNegotiateMessage->Signature), NTLMSSP_SIGNATURE);
  100. pNegotiateMessage->MessageType = NtLmNegotiate;
  101. pWhere = (UCHAR*)(pNegotiateMessage + 1);
  102. if (pOemDomainName && pOemDomainName->Length && (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED & NegotiateFlags))
  103. {
  104. SspCopyStringAsString32(
  105. pNegotiateMessage,
  106. (STRING*)pOemDomainName,
  107. &pWhere,
  108. &pNegotiateMessage->OemDomainName
  109. );
  110. }
  111. if (pOemWorkstationName && pOemWorkstationName->Length && (NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED & NegotiateFlags))
  112. {
  113. SspCopyStringAsString32(
  114. pNegotiateMessage,
  115. (STRING*) pOemWorkstationName,
  116. &pWhere,
  117. &pNegotiateMessage->OemWorkstationName);
  118. }
  119. pNegotiateMessage->NegotiateFlags = NegotiateFlags;
  120. *ppNegotiateMessage = pNegotiateMessage;
  121. pNegotiateMessage = NULL;
  122. *pcbNegotiateMessage = cbNegotiateMessage;
  123. }
  124. if (pNegotiateMessage)
  125. {
  126. delete [] pNegotiateMessage;
  127. }
  128. return Status;
  129. }
  130. NTSTATUS
  131. GetChallengeMessage(
  132. IN ULONG ContextReqFlags,
  133. IN OPTIONAL ULONG cbNegotiateMessage,
  134. IN ULONG TargetFlags,
  135. IN UNICODE_STRING* pTargetInfo,
  136. IN UNICODE_STRING* pTargetName,
  137. IN PNEGOTIATE_MESSAGE pNegotiateMessage,
  138. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  139. OUT PULONG pcbChallengeMessage,
  140. OUT CHALLENGE_MESSAGE** ppChallengeMessage,
  141. OUT PULONG pContextAttributes
  142. )
  143. {
  144. TNtStatus Status = STATUS_SUCCESS;
  145. ULONG ContextAttributes = 0;
  146. STRING StringTargetName = {0};
  147. ULONG ChallengeMessageTargetFlags = 0;
  148. CHALLENGE_MESSAGE* pChallengeMessage = NULL;
  149. ULONG cbChallengeMessage = 0;
  150. PUCHAR pWhere = NULL;
  151. STRING OemWorkstationName = {0};
  152. STRING OemDomainName = {0};
  153. ULONG NegotiateFlagsKeyStrength = NTLMSSP_NEGOTIATE_56;
  154. *ppChallengeMessage = NULL;
  155. *pContextAttributes = 0;
  156. if ((ContextReqFlags & ASC_REQ_IDENTIFY) != 0)
  157. {
  158. ContextAttributes |= ASC_RET_IDENTIFY;
  159. }
  160. if ( (ContextReqFlags & ASC_REQ_DATAGRAM) != 0 )
  161. {
  162. ContextAttributes |= ASC_RET_DATAGRAM;
  163. }
  164. if ((ContextReqFlags & ASC_REQ_CONNECTION) != 0 )
  165. {
  166. ContextAttributes |= ASC_RET_CONNECTION;
  167. }
  168. if ((ContextReqFlags & ASC_REQ_INTEGRITY) != 0 )
  169. {
  170. ContextAttributes |= ASC_RET_INTEGRITY;
  171. }
  172. if ((ContextReqFlags & ASC_REQ_REPLAY_DETECT) != 0)
  173. {
  174. ContextAttributes |= ASC_RET_REPLAY_DETECT;
  175. }
  176. if ( (ContextReqFlags & ASC_REQ_SEQUENCE_DETECT ) != 0)
  177. {
  178. ContextAttributes |= ASC_RET_SEQUENCE_DETECT;
  179. }
  180. if ((ContextReqFlags & ASC_REQ_ALLOW_NON_USER_LOGONS ) != 0)
  181. {
  182. ContextAttributes |= ASC_RET_ALLOW_NON_USER_LOGONS;
  183. }
  184. if ( ContextReqFlags & ASC_REQ_CONFIDENTIALITY )
  185. {
  186. ContextAttributes|= ASC_RET_CONFIDENTIALITY;
  187. }
  188. NegotiateFlagsKeyStrength |= NTLMSSP_NEGOTIATE_128;
  189. //
  190. // Get the pNegotiateMessage. If we are re-establishing a datagram
  191. // context then there may not be one.
  192. //
  193. if ( cbNegotiateMessage >= sizeof(OLD_NEGOTIATE_MESSAGE) )
  194. {
  195. //
  196. // Compute the TargetName to return in the ChallengeMessage.
  197. //
  198. if ( pNegotiateMessage->NegotiateFlags & NTLMSSP_REQUEST_TARGET ||
  199. pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2)
  200. {
  201. Status DBGCHK = RtlDuplicateUnicodeString(
  202. RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING | RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
  203. pTargetName, (UNICODE_STRING*) &StringTargetName
  204. );
  205. if (NT_SUCCESS(Status) && ( 0 == (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE)) )
  206. {
  207. Status DBGCHK = RtlUnicodeStringToOemString((POEM_STRING) &StringTargetName, (PCUNICODE_STRING)&StringTargetName, FALSE);
  208. }
  209. //
  210. // if client is NTLM2-aware, send it target info AV pairs
  211. //
  212. if (NT_SUCCESS(Status))
  213. {
  214. ChallengeMessageTargetFlags = TargetFlags | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO;
  215. }
  216. }
  217. else
  218. {
  219. ChallengeMessageTargetFlags = 0;
  220. }
  221. //
  222. // Allocate a Challenge message
  223. //
  224. if (NT_SUCCESS(Status))
  225. {
  226. cbChallengeMessage = sizeof(*pChallengeMessage)
  227. + pTargetName->Length + pTargetInfo->Length;
  228. pChallengeMessage = (CHALLENGE_MESSAGE*)
  229. new CHAR [cbChallengeMessage];
  230. Status DBGCHK = pChallengeMessage ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  231. }
  232. if (NT_SUCCESS(Status))
  233. {
  234. RtlZeroMemory(pChallengeMessage, cbChallengeMessage);
  235. pChallengeMessage->NegotiateFlags = 0;
  236. //
  237. // Check that both sides can use the same authentication model. For
  238. // compatibility with beta 1 and 2 (builds 612 and 683), no requested
  239. // authentication type is assumed to be NTLM. If NetWare is explicitly
  240. // asked for, it is assumed that NTLM would have been also, so if it
  241. // wasn't, return an error.
  242. //
  243. if ( (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NETWARE) &&
  244. ((pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM) == 0) &&
  245. ((pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2) == 0)
  246. )
  247. {
  248. Status DBGCHK = STATUS_NOT_SUPPORTED;
  249. }
  250. else
  251. {
  252. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM;
  253. }
  254. }
  255. //
  256. // if client can do NTLM2, nuke LM_KEY
  257. //
  258. if (NT_SUCCESS(Status))
  259. {
  260. if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLM2)
  261. {
  262. pNegotiateMessage->NegotiateFlags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
  263. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM2;
  264. }
  265. else if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_LM_KEY)
  266. {
  267. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY;
  268. }
  269. //
  270. // If the client wants to always sign messages, so be it.
  271. //
  272. if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN )
  273. {
  274. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
  275. }
  276. //
  277. // If the caller wants identify level, so be it.
  278. //
  279. if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_IDENTIFY )
  280. {
  281. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_IDENTIFY;
  282. ContextAttributes |= ASC_RET_IDENTIFY;
  283. }
  284. //
  285. // Determine if the caller wants OEM or UNICODE
  286. //
  287. // Prefer UNICODE if caller allows both.
  288. //
  289. if ( pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_UNICODE )
  290. {
  291. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE;
  292. }
  293. else if ( pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_OEM )
  294. {
  295. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM;
  296. }
  297. else
  298. {
  299. Status DBGCHK = SEC_E_INVALID_TOKEN;
  300. }
  301. }
  302. if (NT_SUCCESS(Status))
  303. {
  304. //
  305. // Client wants Sign capability, OK.
  306. //
  307. if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SIGN)
  308. {
  309. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
  310. ContextAttributes |= (ASC_RET_SEQUENCE_DETECT | ASC_RET_REPLAY_DETECT);
  311. }
  312. //
  313. // Client wants Seal, OK.
  314. //
  315. if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_SEAL)
  316. {
  317. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
  318. ContextAttributes |= ASC_RET_CONFIDENTIALITY;
  319. }
  320. if (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_KEY_EXCH)
  321. {
  322. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_KEY_EXCH;
  323. }
  324. if ( (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_56) &&
  325. (NegotiateFlagsKeyStrength & NTLMSSP_NEGOTIATE_56) )
  326. {
  327. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_56;
  328. }
  329. if ( (pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_128) &&
  330. (NegotiateFlagsKeyStrength & NTLMSSP_NEGOTIATE_128) )
  331. {
  332. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_128;
  333. }
  334. //
  335. // If the client supplied the Domain Name and User Name,
  336. // and did not request datagram, see if the client is running
  337. // on this local machine.
  338. //
  339. if ( ( (pNegotiateMessage->NegotiateFlags &
  340. NTLMSSP_NEGOTIATE_DATAGRAM) == 0) &&
  341. ( (pNegotiateMessage->NegotiateFlags &
  342. (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED|
  343. NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED)) ==
  344. (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED|
  345. NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) ) )
  346. {
  347. //
  348. // The client must pass the new negotiate message if they pass
  349. // these flags
  350. //
  351. if (cbNegotiateMessage < sizeof(NEGOTIATE_MESSAGE))
  352. {
  353. Status DBGCHK = SEC_E_INVALID_TOKEN;
  354. }
  355. //
  356. // Convert the names to absolute references so we
  357. // can compare them
  358. //
  359. if (NT_SUCCESS(Status))
  360. {
  361. Status DBGCHK = SspConvertRelativeToAbsolute(
  362. pNegotiateMessage,
  363. cbNegotiateMessage,
  364. &pNegotiateMessage->OemDomainName,
  365. FALSE, // No special alignment
  366. FALSE,
  367. &OemDomainName
  368. );
  369. }
  370. }
  371. if (NT_SUCCESS(Status))
  372. {
  373. Status DBGCHK = SspConvertRelativeToAbsolute(
  374. pNegotiateMessage,
  375. cbNegotiateMessage,
  376. &pNegotiateMessage->OemWorkstationName,
  377. FALSE, // No special alignment
  378. FALSE,
  379. &OemWorkstationName
  380. );
  381. }
  382. }
  383. //
  384. // Check if datagram is being negotiated
  385. //
  386. if ( NT_SUCCESS(Status) &&
  387. ((pNegotiateMessage->NegotiateFlags & NTLMSSP_NEGOTIATE_DATAGRAM) ==
  388. NTLMSSP_NEGOTIATE_DATAGRAM) )
  389. {
  390. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_DATAGRAM;
  391. }
  392. }
  393. else
  394. {
  395. //
  396. // No negotiate message. We need to check if the caller is asking
  397. // for datagram.
  398. //
  399. SspiPrint(SSPI_WARN, TEXT("GetChallengeMessage get OLD_NEGOTIATE_MESSAGE\n"))
  400. ;
  401. if ((ContextReqFlags & ASC_REQ_DATAGRAM) == 0)
  402. {
  403. Status DBGCHK = SEC_E_INVALID_TOKEN;
  404. }
  405. //
  406. // always send target info -- new for NTLM3!
  407. //
  408. if (NT_SUCCESS(Status))
  409. {
  410. ChallengeMessageTargetFlags = NTLMSSP_NEGOTIATE_TARGET_INFO;
  411. cbChallengeMessage = sizeof(*pChallengeMessage) + pTargetInfo->Length;
  412. pChallengeMessage = (CHALLENGE_MESSAGE*) new CHAR[cbChallengeMessage];
  413. Status DBGCHK = pChallengeMessage ? S_OK : STATUS_NO_MEMORY;
  414. }
  415. //
  416. // Record in the context that we are doing datagram. We will tell
  417. // the client everything we can negotiate and let it decide what
  418. // to negotiate.
  419. //
  420. if (NT_SUCCESS(Status))
  421. {
  422. RtlZeroMemory(pChallengeMessage, cbChallengeMessage);
  423. pChallengeMessage->NegotiateFlags = NTLMSSP_NEGOTIATE_DATAGRAM |
  424. NTLMSSP_NEGOTIATE_UNICODE |
  425. NTLMSSP_NEGOTIATE_OEM |
  426. NTLMSSP_NEGOTIATE_SIGN |
  427. NTLMSSP_NEGOTIATE_LM_KEY |
  428. NTLMSSP_NEGOTIATE_NTLM |
  429. NTLMSSP_NEGOTIATE_ALWAYS_SIGN |
  430. NTLMSSP_NEGOTIATE_IDENTIFY |
  431. NTLMSSP_NEGOTIATE_NTLM2 |
  432. NTLMSSP_NEGOTIATE_KEY_EXCH |
  433. NegotiateFlagsKeyStrength;
  434. pChallengeMessage->NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL;
  435. }
  436. }
  437. //
  438. // Build the Challenge Message
  439. //
  440. if (NT_SUCCESS(Status))
  441. {
  442. strcpy((PSTR) pChallengeMessage->Signature, NTLMSSP_SIGNATURE );
  443. pChallengeMessage->MessageType = NtLmChallenge;
  444. RtlCopyMemory(
  445. pChallengeMessage->Challenge,
  446. ChallengeToClient,
  447. MSV1_0_CHALLENGE_LENGTH
  448. );
  449. pWhere = (PUCHAR) (pChallengeMessage + 1);
  450. SspCopyStringAsString32(pChallengeMessage,
  451. (PSTRING) pTargetName,
  452. &pWhere,
  453. &pChallengeMessage->TargetName);
  454. SspCopyStringAsString32(pChallengeMessage,
  455. (PSTRING)pTargetInfo,
  456. &pWhere,
  457. &pChallengeMessage->TargetInfo);
  458. pChallengeMessage->NegotiateFlags |= ChallengeMessageTargetFlags;
  459. SspiPrint(SSPI_LOG, TEXT("GetChallengeMessage pNegotiateMessage->NegotiateFlags %#x, pChallengeMessage->NegotiateFlags %#x\n"),
  460. pNegotiateMessage->NegotiateFlags, pChallengeMessage->NegotiateFlags);
  461. SspiPrintHex(SSPI_LOG, TEXT("pNegotiateMessage"), cbNegotiateMessage, pNegotiateMessage);
  462. SspiPrintHex(SSPI_LOG, TEXT("pChallengeMessage"), cbChallengeMessage, pChallengeMessage);
  463. *ppChallengeMessage = pChallengeMessage;
  464. pChallengeMessage = NULL;
  465. *pContextAttributes = ContextReqFlags;
  466. *pcbChallengeMessage = cbChallengeMessage;
  467. }
  468. if (pChallengeMessage)
  469. {
  470. delete [] pChallengeMessage;
  471. }
  472. RtlFreeUnicodeString((PUNICODE_STRING) &StringTargetName);
  473. return Status;
  474. }
  475. NTSTATUS
  476. GetAuthenticateMessage(
  477. IN PCredHandle phCredentialHandle,
  478. IN ULONG fContextReq,
  479. IN PTSTR pszTargetName,
  480. IN ULONG TargetDataRep,
  481. IN ULONG cbNtlmChallengeMessage,
  482. IN OPTIONAL NTLM_CHALLENGE_MESSAGE* pNtlmChallengeMessage,
  483. IN ULONG cbChallengeMessage,
  484. IN CHALLENGE_MESSAGE* pChallengeMessage,
  485. OUT PCtxtHandle phClientContextHandle,
  486. OUT ULONG* pfContextAttr,
  487. OUT ULONG* pcbAuthMessage,
  488. OUT AUTHENTICATE_MESSAGE** ppAuthMessage,
  489. OUT NTLM_INITIALIZE_RESPONSE* pInitResponse
  490. )
  491. {
  492. TNtStatus Status = S_OK;
  493. ULONG fContextAttr = 0;
  494. CtxtHandle hClientCtxtHandle;
  495. SecBufferDesc InBuffDesc = {0};
  496. SecBuffer InBuffs[2] = {0};
  497. SecBufferDesc OutBuffDesc = {0};
  498. SecBuffer OutBuffs[2] = {0};
  499. TimeStamp Expiry = {0};
  500. SecInvalidateHandle(&hClientCtxtHandle);
  501. SecInvalidateHandle(phClientContextHandle);
  502. InBuffDesc.pBuffers = InBuffs;
  503. InBuffDesc.cBuffers = 1;
  504. InBuffDesc.ulVersion = 0;
  505. InBuffs[0].pvBuffer = pChallengeMessage;
  506. InBuffs[0].cbBuffer = cbChallengeMessage;
  507. InBuffs[0].BufferType = SECBUFFER_TOKEN;
  508. if ((fContextReq & ISC_REQ_USE_SUPPLIED_CREDS)
  509. && (pNtlmChallengeMessage && cbNtlmChallengeMessage))
  510. {
  511. InBuffDesc.cBuffers = 2;
  512. InBuffs[1].pvBuffer = pNtlmChallengeMessage;
  513. InBuffs[1].cbBuffer = cbNtlmChallengeMessage;
  514. InBuffs[1].BufferType = SECBUFFER_TOKEN;
  515. if (0 == (fContextReq & ISC_REQ_USE_SUPPLIED_CREDS))
  516. {
  517. fContextReq |= ISC_REQ_USE_SUPPLIED_CREDS;
  518. SspiPrint(SSPI_WARN, TEXT("Creds supplied but ISC_REQ_USE_SUPPLIED_CREDS was not set, added\n"));
  519. }
  520. }
  521. OutBuffDesc.pBuffers = OutBuffs;
  522. OutBuffDesc.cBuffers = 2;
  523. OutBuffDesc.ulVersion = 0;
  524. if (0 == (fContextReq & ISC_REQ_ALLOCATE_MEMORY))
  525. {
  526. fContextReq |= ISC_REQ_ALLOCATE_MEMORY;
  527. SspiPrint(SSPI_LOG, TEXT("ISC_REQ_ALLOCATE_MEMORY was not set, added\n"));
  528. }
  529. OutBuffs[0].pvBuffer = NULL;
  530. OutBuffs[0].cbBuffer = 0;
  531. OutBuffs[0].BufferType = SECBUFFER_TOKEN;
  532. OutBuffs[1].pvBuffer = NULL;
  533. OutBuffs[1].cbBuffer = 0;
  534. OutBuffs[1].BufferType = SECBUFFER_TOKEN;
  535. SspiPrint(SSPI_LOG, TEXT("GetAuthenticateMessage calling InitializeSecurityContext pszTargetName (%s), fContextReq %#x, TargetDataRep %#x, hCred %#x:%#x\n"),
  536. pszTargetName, fContextReq, TargetDataRep, phCredentialHandle->dwUpper, phCredentialHandle->dwLower);
  537. Status DBGCHK = InitializeSecurityContext(
  538. phCredentialHandle,
  539. NULL,
  540. pszTargetName,
  541. fContextReq,
  542. 0,
  543. TargetDataRep,
  544. &InBuffDesc,
  545. 0,
  546. &hClientCtxtHandle,
  547. &OutBuffDesc,
  548. &fContextAttr,
  549. &Expiry
  550. );
  551. if (NT_SUCCESS(Status))
  552. {
  553. *phClientContextHandle = hClientCtxtHandle;
  554. SecInvalidateHandle(&hClientCtxtHandle);
  555. *pfContextAttr = fContextAttr;
  556. *ppAuthMessage = (AUTHENTICATE_MESSAGE *) OutBuffs[0].pvBuffer;
  557. OutBuffs[0].pvBuffer = NULL;
  558. *pcbAuthMessage = OutBuffs[0].cbBuffer;
  559. ASSERT(sizeof(*pInitResponse) == OutBuffs[1].cbBuffer);
  560. RtlCopyMemory(pInitResponse, OutBuffs[1].pvBuffer, sizeof(*pInitResponse));
  561. SspiPrint(SSPI_LOG, TEXT("ClientCtxtHandle is %#x:%#x, fContextAttr %#x\n"),
  562. phClientContextHandle->dwUpper, phClientContextHandle->dwLower, *pfContextAttr);
  563. SspiPrintHex(SSPI_LOG, TEXT("AuthMessage"), *pcbAuthMessage, *ppAuthMessage);
  564. SspiPrintHex(SSPI_LOG, TEXT("UserSessionKey"), MSV1_0_USER_SESSION_KEY_LENGTH, pInitResponse->UserSessionKey);
  565. SspiPrintHex(SSPI_LOG, TEXT("LanmanSessionKey"), MSV1_0_LANMAN_SESSION_KEY_LENGTH, pInitResponse->LanmanSessionKey);
  566. SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("Expiry"), &Expiry);
  567. }
  568. if (OutBuffs[0].pvBuffer)
  569. {
  570. FreeContextBuffer(OutBuffs[0].pvBuffer);
  571. }
  572. if (OutBuffs[1].pvBuffer)
  573. {
  574. FreeContextBuffer(OutBuffs[1].pvBuffer);
  575. }
  576. return Status;
  577. }
  578. NTSTATUS
  579. MsvChallenge(
  580. IN OPTIONAL PTSTR pszCredPrincipal,
  581. IN OPTIONAL LUID* pCredLogonID,
  582. IN OPTIONAL VOID* pAuthData,
  583. IN OEM_STRING* pOemDomainName,
  584. IN OEM_STRING* pOemWorkstationName,
  585. IN ULONG NegotiateFlags,
  586. IN ULONG TargetFlags,
  587. IN BOOLEAN bForceGuest,
  588. IN ULONG fContextAttr,
  589. IN ULONG TargetDataRep,
  590. IN UNICODE_STRING* pPassword,
  591. IN UNICODE_STRING* pUserName,
  592. IN UNICODE_STRING* pDomainName,
  593. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  594. IN OPTIONAL UNICODE_STRING* pDnsDomainName,
  595. IN OPTIONAL UNICODE_STRING* pDnsComputerName,
  596. IN OPTIONAL UNICODE_STRING* pDnsTreeName,
  597. IN OPTIONAL UNICODE_STRING* pComputerName,
  598. IN OPTIONAL UNICODE_STRING* pComputerDomainName,
  599. OUT ULONG* pcbAuthMessage,
  600. OUT AUTHENTICATE_MESSAGE** ppAuthMessage,
  601. OUT PCtxtHandle phCliCtxt,
  602. OUT ULONG* pfContextAttr
  603. )
  604. {
  605. TNtStatus Status;
  606. UNICODE_STRING TargetInfo = {0};
  607. WCHAR ScratchBuffer[2 * DNS_MAX_NAME_LENGTH + 2] = {0};
  608. UNICODE_STRING TargetName = {0, sizeof(ScratchBuffer), ScratchBuffer};
  609. NTLM_CHALLENGE_MESSAGE* pNtlmChallengeMessage = NULL;
  610. ULONG cbNtlmChallengeMessage = 0;
  611. NEGOTIATE_MESSAGE* pNegotiateMessage = NULL;
  612. ULONG cbNegotiateMessage = 0;
  613. CHALLENGE_MESSAGE* pChallengeMesssage = NULL;
  614. ULONG cbChallengeMessage = 0;
  615. AUTHENTICATE_MESSAGE* pAuthMessage = NULL;
  616. ULONG cbAuthMessage = 0;
  617. NTLM_INITIALIZE_RESPONSE InitResponse = {0};
  618. CtxtHandle hCliCtxt;
  619. CredHandle hCliCred;
  620. SecInvalidateHandle(&hCliCred);
  621. SecInvalidateHandle(&hCliCtxt);
  622. *pfContextAttr = 0;
  623. SecInvalidateHandle(phCliCtxt);
  624. *ppAuthMessage = NULL;
  625. *pcbAuthMessage = 0;
  626. SspiPrint(SSPI_LOG, TEXT("MsvChallenge CredPrincipal %s, NegotiateFlags %#x, TargetFlags %#x, bForceGuest %#x")
  627. TEXT("fContextAttr %#x, TargetDataRep %#x, pAuthData %p, pCredLogonID %p\n"),
  628. pszCredPrincipal, NegotiateFlags, TargetFlags, bForceGuest, fContextAttr, TargetDataRep, pAuthData, pCredLogonID);
  629. DebugPrintf(SSPI_LOG, "OemDomainName (%s), OemWorkstation (%s)\n", pOemDomainName, pOemWorkstationName);
  630. SspiPrintHex(SSPI_LOG, TEXT("ChallengeToClient"), MSV1_0_CHALLENGE_LENGTH, ChallengeToClient);
  631. SspiPrint(SSPI_LOG, TEXT("pPassword %wZ, pUserName %wZ, pDomainName %wZ, pDnsDomainName %wZ, pDnsComputerName %wZ, pDnsTreeName %wZ, pComputerName %wZ, pComputerDomainName %wZ\n"),
  632. pPassword, pUserName, pDomainName, pDnsDomainName, pDnsComputerName, pDnsTreeName, pComputerName, pComputerDomainName);
  633. if (pComputerDomainName && pComputerDomainName->Length)
  634. {
  635. //
  636. // Target name is of form "domain name\0computer name"
  637. //
  638. RtlCopyMemory(ScratchBuffer, pComputerDomainName->Buffer, pComputerDomainName->Length);
  639. if (pComputerName && pComputerName->Length)
  640. {
  641. RtlCopyMemory(ScratchBuffer + (pComputerDomainName->Length / sizeof(WCHAR)) + 1, pComputerName->Buffer, pComputerName->Length);
  642. TargetName.Length = pComputerDomainName->Length + pComputerName->Length + 1;
  643. }
  644. else
  645. {
  646. TargetName.Length = pComputerDomainName->Length;
  647. }
  648. }
  649. else if (pComputerName && pComputerName->Length)
  650. {
  651. RtlCopyMemory(ScratchBuffer, pComputerName->Buffer, pComputerName->Length);
  652. TargetName.Length = pComputerName->Length;
  653. }
  654. SspiPrintHex(SSPI_LOG, TEXT("MsvChallenge TargetName"), TargetName.Length, TargetName.Buffer);
  655. Status DBGCHK = GetNegociateMessage(
  656. pOemDomainName,
  657. pOemWorkstationName,
  658. NegotiateFlags,
  659. &cbNegotiateMessage,
  660. &pNegotiateMessage
  661. );
  662. if (NT_SUCCESS(Status))
  663. {
  664. Status DBGCHK = GetTargetInfo(
  665. TargetFlags,
  666. bForceGuest,
  667. pDnsDomainName,
  668. pDnsComputerName,
  669. pDnsTreeName,
  670. &TargetName,
  671. pComputerName,
  672. &TargetInfo
  673. );
  674. }
  675. if (NT_SUCCESS(Status))
  676. {
  677. Status DBGCHK = GetChallengeMessage(
  678. fContextAttr,
  679. cbNegotiateMessage,
  680. TargetFlags,
  681. &TargetInfo,
  682. &TargetName,
  683. pNegotiateMessage,
  684. ChallengeToClient,
  685. &cbChallengeMessage,
  686. &pChallengeMesssage,
  687. &fContextAttr
  688. );
  689. }
  690. if (NT_SUCCESS(Status)
  691. && ((pPassword && pPassword->Length)
  692. || (pDomainName && pDomainName->Length)
  693. || (pUserName && pUserName->Length)))
  694. {
  695. if (0 == (fContextAttr & ISC_REQ_USE_SUPPLIED_CREDS))
  696. {
  697. SspiPrint(SSPI_WARN, TEXT("MsvChallenge explicit cred supplied, but ISC_REQ_USE_SUPPLIED_CREDS was not set, added\n"));
  698. fContextAttr |= ISC_REQ_USE_SUPPLIED_CREDS;
  699. }
  700. Status DBGCHK = GetNtlmChallengeMessage(
  701. pPassword,
  702. pUserName,
  703. pDomainName,
  704. &cbNtlmChallengeMessage,
  705. &pNtlmChallengeMessage
  706. );
  707. }
  708. if (NT_SUCCESS(Status))
  709. {
  710. Status DBGCHK = GetCredHandle(
  711. pszCredPrincipal,
  712. pCredLogonID,
  713. TEXT("NTLM"),
  714. pAuthData,
  715. SECPKG_CRED_OUTBOUND,
  716. &hCliCred
  717. );
  718. }
  719. #if defined(UNICODE) || defined(_UNICODE)
  720. if (NT_SUCCESS(Status))
  721. {
  722. SspiPrint(SSPI_LOG, TEXT("MsvChallenge hCliCred %#x:%#x\n"), hCliCred.dwUpper, hCliCred.dwLower);
  723. Status DBGCHK = GetAuthenticateMessage(
  724. &hCliCred,
  725. fContextAttr,
  726. TargetName.Buffer,
  727. TargetDataRep,
  728. cbNtlmChallengeMessage,
  729. pNtlmChallengeMessage,
  730. cbChallengeMessage,
  731. pChallengeMesssage,
  732. &hCliCtxt,
  733. &fContextAttr,
  734. &cbAuthMessage,
  735. &pAuthMessage,
  736. &InitResponse
  737. );
  738. }
  739. #else
  740. ANSI_STRING AnsiTargetName = {0};
  741. //
  742. // RtlUnicodeStringToAnsiString appends the NULL
  743. //
  744. if (NT_SUCCESS(Status))
  745. {
  746. Status DBGCHK = RtlUnicodeStringToAnsiString(&AnsiTargetName, &TargetName, TRUE);
  747. }
  748. if (NT_SUCCESS(Status))
  749. {
  750. SspiPrint(SSPI_LOG, TEXT("MsvChallenge hCliCred %#x:%#x\n"), hCliCred.dwUpper, hCliCred.dwLower);
  751. Status DBGCHK = GetAuthenticateMessage(
  752. &hCliCred,
  753. fContextAttr,
  754. AnsiTargetName.Buffer,
  755. TargetDataRep,
  756. cbNtlmChallengeMessage,
  757. pNtlmChallengeMessage,
  758. cbChallengeMessage,
  759. pChallengeMesssage,
  760. &hCliCtxt,
  761. &fContextAttr,
  762. &cbAuthMessage,
  763. &pAuthMessage,
  764. &InitResponse
  765. );
  766. }
  767. RtlFreeAnsiString(&AnsiTargetName);
  768. #endif
  769. if (NT_SUCCESS(Status))
  770. {
  771. *phCliCtxt = hCliCtxt;
  772. SecInvalidateHandle(&hCliCtxt);
  773. *ppAuthMessage = pAuthMessage;
  774. pAuthMessage = NULL;
  775. *pcbAuthMessage = cbAuthMessage;
  776. *pfContextAttr = fContextAttr;
  777. }
  778. if (SecIsValidHandle(&hCliCtxt))
  779. {
  780. DeleteSecurityContext(&hCliCtxt);
  781. }
  782. if (SecIsValidHandle(&hCliCred))
  783. {
  784. DeleteSecurityContext(&hCliCred);
  785. }
  786. if (pAuthMessage)
  787. {
  788. FreeContextBuffer(pAuthMessage);
  789. }
  790. if (pNegotiateMessage)
  791. {
  792. delete[] pNegotiateMessage;
  793. }
  794. if (pChallengeMesssage)
  795. {
  796. delete [] pChallengeMesssage;
  797. }
  798. if (pNtlmChallengeMessage)
  799. {
  800. delete [] pNtlmChallengeMessage;
  801. }
  802. return Status;
  803. }
  804. NTSTATUS
  805. GetAuthenticateResponse(
  806. IN PCredHandle pServerCredHandle,
  807. IN ULONG fContextAttr,
  808. IN ULONG TargetDataRep,
  809. IN ULONG cbAuthMessage,
  810. IN AUTHENTICATE_MESSAGE* pAuthMessage,
  811. IN NTLM_AUTHENTICATE_MESSAGE* pNtlmAuthMessage,
  812. OUT PCtxtHandle phServerCtxtHandle,
  813. OUT ULONG* pfContextAttr,
  814. OUT NTLM_ACCEPT_RESPONSE* pAcceptResponse
  815. )
  816. {
  817. TNtStatus Status = STATUS_SUCCESS;
  818. CtxtHandle hServerCtxtHandle;
  819. SecBufferDesc InBuffDesc = {0};
  820. SecBuffer InBuffs[2] = {0};
  821. SecBufferDesc OutBuffDesc = {0};
  822. SecBuffer OutBuff = {0};
  823. TimeStamp Expiry = {0};
  824. SecInvalidateHandle(&hServerCtxtHandle);
  825. SecInvalidateHandle(phServerCtxtHandle);
  826. InBuffDesc.pBuffers = InBuffs;
  827. InBuffDesc.cBuffers = 2;
  828. InBuffDesc.ulVersion = 0;
  829. InBuffs[0].pvBuffer = pAuthMessage;
  830. InBuffs[0].cbBuffer = cbAuthMessage;
  831. InBuffs[0].BufferType = SECBUFFER_TOKEN;
  832. InBuffs[1].pvBuffer = pNtlmAuthMessage;
  833. InBuffs[1].cbBuffer = sizeof(*pNtlmAuthMessage);
  834. InBuffs[1].BufferType = SECBUFFER_TOKEN;
  835. OutBuffDesc.pBuffers = &OutBuff;
  836. OutBuffDesc.cBuffers = 1;
  837. OutBuffDesc.ulVersion = 0;
  838. OutBuff.pvBuffer = pAcceptResponse;
  839. OutBuff.cbBuffer = sizeof(*pAcceptResponse);
  840. OutBuff.BufferType = SECBUFFER_TOKEN;
  841. if (fContextAttr & ASC_REQ_ALLOCATE_MEMORY)
  842. {
  843. SspiPrint(SSPI_WARN, TEXT("Authenticate ASC_REQ_ALLOCATE_MEMORY was set, removed\n"));
  844. fContextAttr &= ~(ASC_REQ_ALLOCATE_MEMORY);
  845. }
  846. SspiPrint(SSPI_LOG, TEXT("GetAuthenticateResponse calling AcceptSecurityContext fContextAttr %#x, TargetDataRep %#x, hCred %#x:%#x\n"),
  847. fContextAttr, TargetDataRep, pServerCredHandle->dwUpper, pServerCredHandle->dwLower);
  848. Status DBGCHK = AcceptSecurityContext(
  849. pServerCredHandle,
  850. NULL,
  851. &InBuffDesc,
  852. fContextAttr,
  853. TargetDataRep,
  854. &hServerCtxtHandle,
  855. &OutBuffDesc,
  856. &fContextAttr,
  857. &Expiry
  858. );
  859. if (NT_SUCCESS(Status))
  860. {
  861. *phServerCtxtHandle = hServerCtxtHandle;
  862. SecInvalidateHandle(&hServerCtxtHandle);
  863. *pfContextAttr = fContextAttr;
  864. ASSERT(sizeof(*pAcceptResponse) == OutBuff.cbBuffer);
  865. RtlCopyMemory(pAcceptResponse, OutBuff.pvBuffer, sizeof(*pAcceptResponse));
  866. SspiPrint(SSPI_LOG, TEXT("ServerCtxtHandle is %#x:%#x, fContextAttr %#x\n"),
  867. phServerCtxtHandle->dwUpper, phServerCtxtHandle->dwLower, *pfContextAttr);
  868. SspiPrint(SSPI_LOG, TEXT("Authenticate LogonId %#x:%#x, UserFlags %#x\n"),
  869. pAcceptResponse->LogonId.HighPart, pAcceptResponse->LogonId.LowPart, pAcceptResponse->UserFlags);
  870. SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("KickoffTime"), &pAcceptResponse->KickoffTime);
  871. SspiPrintHex(SSPI_LOG, TEXT("UserSessionKey"), MSV1_0_USER_SESSION_KEY_LENGTH, pAcceptResponse->UserSessionKey);
  872. SspiPrintHex(SSPI_LOG, TEXT("LanmanSessionKey"), MSV1_0_LANMAN_SESSION_KEY_LENGTH, pAcceptResponse->LanmanSessionKey);
  873. SspiPrintSysTimeAsLocalTime(SSPI_LOG, TEXT("Expiry"), &Expiry);
  874. }
  875. if (SecIsValidHandle(&hServerCtxtHandle))
  876. {
  877. DeleteSecurityContext(&hServerCtxtHandle);
  878. }
  879. return Status;
  880. }
  881. NTSTATUS
  882. MsvAuthenticate(
  883. IN OPTIONAL PTSTR pszCredPrincipal,
  884. IN OPTIONAL LUID* pCredLogonID,
  885. IN OPTIONAL VOID* pAuthData,
  886. IN ULONG fContextAttr,
  887. IN ULONG TargetDataRep,
  888. IN ULONG cbAuthMessage,
  889. IN AUTHENTICATE_MESSAGE* pAuthMessage,
  890. IN NTLM_AUTHENTICATE_MESSAGE* pNtlmAuthMessage,
  891. OUT PCtxtHandle phServerCtxt,
  892. OUT ULONG* pfContextAttr
  893. )
  894. {
  895. TNtStatus Status;
  896. CredHandle hServerCred;
  897. CtxtHandle hServerCtxt;
  898. NTLM_ACCEPT_RESPONSE AcceptResponse = {0};
  899. SecInvalidateHandle(&hServerCred);
  900. SecInvalidateHandle(&hServerCtxt);
  901. SspiPrint(SSPI_LOG, TEXT("MsvAuthenticate pszCredPrincipal %s, fContextAttr %#x, TargetDataRep %#x, pCredLogonID %p, pAuthData %p\n"),
  902. pszCredPrincipal, fContextAttr, TargetDataRep, pCredLogonID, pAuthData);
  903. SspiPrintHex(SSPI_LOG, TEXT("pAuthMessage"), cbAuthMessage, pAuthMessage);
  904. SspiPrintHex(SSPI_LOG, TEXT("pNtlmAuthMessage->ChallengeToClient"), MSV1_0_CHALLENGE_LENGTH, pNtlmAuthMessage->ChallengeToClient);
  905. SspiPrint(SSPI_LOG, TEXT("pNtlmAuthMessage->ParameterControl %#x\n"), pNtlmAuthMessage->ParameterControl);
  906. Status DBGCHK = GetCredHandle(
  907. pszCredPrincipal,
  908. pCredLogonID,
  909. TEXT("NTLM"),
  910. pAuthData,
  911. SECPKG_CRED_INBOUND,
  912. &hServerCred
  913. );
  914. if (NT_SUCCESS(Status))
  915. {
  916. Status DBGCHK = GetAuthenticateResponse(
  917. &hServerCred,
  918. fContextAttr,
  919. TargetDataRep,
  920. cbAuthMessage,
  921. pAuthMessage,
  922. pNtlmAuthMessage,
  923. &hServerCtxt,
  924. &fContextAttr,
  925. &AcceptResponse
  926. );
  927. }
  928. if (NT_SUCCESS(Status))
  929. {
  930. *pfContextAttr = fContextAttr;
  931. *phServerCtxt = hServerCtxt;
  932. SecInvalidateHandle(&hServerCtxt);
  933. }
  934. if (SecIsValidHandle(&hServerCtxt))
  935. {
  936. DeleteSecurityContext(&hServerCtxt);
  937. }
  938. if (SecIsValidHandle(&hServerCred))
  939. {
  940. FreeCredentialsHandle(&hServerCred);
  941. }
  942. return Status;
  943. }