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.

710 lines
20 KiB

  1. /* Copyright (c) 1993, Microsoft Corporation, all rights reserved
  2. **
  3. ** clsa.c
  4. ** Client-side LSA Authentication Utilities
  5. **
  6. ** 11/12/93 MikeSa Pulled from NT 3.1 RAS authentication.
  7. */
  8. #define UNICODE
  9. #include <nt.h>
  10. #include <ntrtl.h>
  11. #include <nturtl.h>
  12. #include <ntlsa.h>
  13. #include <ntmsv1_0.h>
  14. #include <crypt.h>
  15. #include <windows.h>
  16. #include <lmcons.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <rasman.h>
  20. #include <raserror.h>
  21. #include <rtutils.h>
  22. //
  23. //Revisit the tracing for common components
  24. //in BC timeframe.
  25. //This really sucks...
  26. BOOL GetDESChallengeResponse(
  27. IN DWORD dwTraceId,
  28. IN PCHAR pszPassword,
  29. IN PBYTE pchChallenge,
  30. OUT PBYTE pchChallengeResponse
  31. );
  32. BOOL GetMD5ChallengeResponse(
  33. IN DWORD dwTraceId,
  34. IN PCHAR pszPassword,
  35. IN PBYTE pchChallenge,
  36. OUT PBYTE pchChallengeResponse
  37. );
  38. BOOL Uppercase(IN DWORD dwTraceId, PBYTE pString);
  39. #define GCR_MACHINE_CREDENTIAL 0x400
  40. DWORD
  41. RegisterLSA (DWORD dwTraceId,
  42. OUT HANDLE * phLsa,
  43. OUT DWORD * pdwAuthPkgId)
  44. {
  45. NTSTATUS ntstatus;
  46. STRING LsaName;
  47. LSA_OPERATIONAL_MODE LSASecurityMode ;
  48. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "RegisterLSA" );
  49. //
  50. // To be able to do authentications, we have to
  51. // register with the Lsa as a logon process.
  52. //
  53. RtlInitString(&LsaName, "CCHAP");
  54. *phLsa = NULL;
  55. ntstatus = LsaRegisterLogonProcess(&LsaName,
  56. phLsa,
  57. &LSASecurityMode);
  58. if (ntstatus != STATUS_SUCCESS)
  59. {
  60. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "LsaregisterLogonProcess Failed" );
  61. return (1);
  62. }
  63. //
  64. // We use the MSV1_0 authentication package for LM2.x
  65. // logons. We get to MSV1_0 via the Lsa. So we call
  66. // Lsa to get MSV1_0's package id, which we'll use in
  67. // later calls to Lsa.
  68. //
  69. RtlInitString(&LsaName, MSV1_0_PACKAGE_NAME);
  70. ntstatus = LsaLookupAuthenticationPackage(*phLsa,
  71. &LsaName,
  72. pdwAuthPkgId);
  73. if (ntstatus != STATUS_SUCCESS)
  74. {
  75. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "LsaLookupAuthenticationPackage Failed" );
  76. return (1);
  77. }
  78. return NO_ERROR;
  79. }
  80. DWORD
  81. GetMachineCredentials
  82. (
  83. IN DWORD dwTraceId,
  84. IN PBYTE pszMachineName,
  85. IN PLUID pLuid,
  86. IN PBYTE pbChallenge,
  87. OUT PBYTE CaseInsensitiveChallengeResponse,
  88. OUT PBYTE CaseSensitiveChallengeResponse,
  89. OUT PBYTE pLmSessionKey,
  90. OUT PBYTE pUserSessionKey
  91. )
  92. {
  93. DWORD dwRetCode = NO_ERROR;
  94. DWORD dwChallengeResponseRequestLength;
  95. DWORD dwChallengeResponseLength;
  96. MSV1_0_GETCHALLENRESP_REQUEST ChallengeResponseRequest;
  97. PMSV1_0_GETCHALLENRESP_RESPONSE pChallengeResponse;
  98. NTSTATUS status;
  99. NTSTATUS substatus;
  100. HANDLE hLsa = NULL;
  101. DWORD dwAuthPkgId = 0;
  102. dwRetCode = RegisterLSA ( dwTraceId,
  103. &hLsa,
  104. &dwAuthPkgId
  105. );
  106. if ( NO_ERROR != dwRetCode )
  107. goto LDone;
  108. ZeroMemory( &ChallengeResponseRequest, sizeof(ChallengeResponseRequest) );
  109. dwChallengeResponseRequestLength =
  110. sizeof(MSV1_0_GETCHALLENRESP_REQUEST);
  111. ChallengeResponseRequest.MessageType =
  112. MsV1_0Lm20GetChallengeResponse;
  113. ChallengeResponseRequest.ParameterControl =
  114. RETURN_PRIMARY_LOGON_DOMAINNAME |
  115. RETURN_PRIMARY_USERNAME |
  116. USE_PRIMARY_PASSWORD|
  117. GCR_MACHINE_CREDENTIAL;
  118. ChallengeResponseRequest.LogonId = *pLuid;
  119. ChallengeResponseRequest.Password.Length = 0;
  120. ChallengeResponseRequest.Password.MaximumLength = 0;
  121. ChallengeResponseRequest.Password.Buffer = NULL;
  122. RtlMoveMemory( ChallengeResponseRequest.ChallengeToClient,
  123. pbChallenge,
  124. (DWORD) MSV1_0_CHALLENGE_LENGTH);
  125. status = LsaCallAuthenticationPackage(hLsa,
  126. dwAuthPkgId,
  127. &ChallengeResponseRequest,
  128. dwChallengeResponseRequestLength,
  129. (PVOID *) &pChallengeResponse,
  130. &dwChallengeResponseLength,
  131. &substatus);
  132. if ( (status != STATUS_SUCCESS)
  133. || (substatus != STATUS_SUCCESS))
  134. {
  135. TracePrintfExA ( dwTraceId,
  136. 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC,
  137. "LsaCallAuthenticationPackage failed status:0x%x substatus:0x%x", status, substatus );
  138. dwRetCode = 1 ;
  139. }
  140. else
  141. {
  142. if(NULL !=
  143. pChallengeResponse->CaseInsensitiveChallengeResponse.Buffer)
  144. {
  145. RtlMoveMemory(CaseInsensitiveChallengeResponse,
  146. pChallengeResponse->CaseInsensitiveChallengeResponse.Buffer,
  147. SESSION_PWLEN);
  148. }
  149. else
  150. {
  151. ZeroMemory(CaseInsensitiveChallengeResponse,
  152. SESSION_PWLEN);
  153. }
  154. if(NULL !=
  155. pChallengeResponse->CaseSensitiveChallengeResponse.Buffer)
  156. {
  157. RtlMoveMemory(CaseSensitiveChallengeResponse,
  158. pChallengeResponse->CaseSensitiveChallengeResponse.Buffer,
  159. SESSION_PWLEN);
  160. }
  161. else
  162. {
  163. ZeroMemory(CaseSensitiveChallengeResponse,
  164. SESSION_PWLEN);
  165. }
  166. RtlMoveMemory(pLmSessionKey,
  167. pChallengeResponse->LanmanSessionKey,
  168. MAX_SESSIONKEY_SIZE);
  169. RtlMoveMemory(pUserSessionKey,
  170. pChallengeResponse->UserSessionKey,
  171. MAX_USERSESSIONKEY_SIZE);
  172. LsaFreeReturnBuffer(pChallengeResponse);
  173. }
  174. LDone:
  175. if ( hLsa )
  176. {
  177. LsaDeregisterLogonProcess (hLsa);
  178. }
  179. return dwRetCode;
  180. }
  181. DWORD
  182. GetChallengeResponse(
  183. IN DWORD dwTraceId,
  184. IN PBYTE pszUsername,
  185. IN PBYTE pszPassword,
  186. IN PLUID pLuid,
  187. IN PBYTE pbChallenge,
  188. IN BOOL fMachineAuth,
  189. OUT PBYTE CaseInsensitiveChallengeResponse,
  190. OUT PBYTE CaseSensitiveChallengeResponse,
  191. OUT PBYTE pfUseNtResponse,
  192. OUT PBYTE pLmSessionKey,
  193. OUT PBYTE pUserSessionKey
  194. )
  195. {
  196. DWORD dwRetCode = ERROR_SUCCESS;
  197. *pfUseNtResponse = TRUE;
  198. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetChallengeResponse" );
  199. //
  200. // Check if we're supposed to get credentials from the system
  201. //
  202. if ( fMachineAuth )
  203. {
  204. if ( ( dwRetCode = GetMachineCredentials (
  205. dwTraceId,
  206. pszUsername,
  207. pLuid,
  208. pbChallenge,
  209. CaseInsensitiveChallengeResponse,
  210. CaseSensitiveChallengeResponse,
  211. pLmSessionKey,
  212. pUserSessionKey
  213. ) ) )
  214. {
  215. TracePrintfExA (dwTraceId,
  216. 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC,
  217. "GetMachineCredentials Failed ErrorCode: 0x%x",
  218. dwRetCode );
  219. return (ERROR_AUTH_INTERNAL);
  220. }
  221. }
  222. else if (lstrlenA(pszUsername))
  223. {
  224. if (lstrlenA(pszPassword) <= LM20_PWLEN)
  225. {
  226. if (!GetDESChallengeResponse(dwTraceId, pszPassword, pbChallenge,
  227. CaseInsensitiveChallengeResponse))
  228. {
  229. //We dont want to send back the error that
  230. //this function must have failed with
  231. //but just log it in our logs...
  232. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetDESChallangeResponse Failed" );
  233. return (ERROR_AUTH_INTERNAL);
  234. }
  235. }
  236. //
  237. // And we'll always get the case sensitive response.
  238. //
  239. if (!GetMD5ChallengeResponse(dwTraceId, pszPassword, pbChallenge,
  240. CaseSensitiveChallengeResponse))
  241. {
  242. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetMD5ChallangeResponse Failed" );
  243. return (ERROR_AUTH_INTERNAL);
  244. }
  245. }
  246. else
  247. {
  248. WCHAR Username[UNLEN + DNLEN + 1];
  249. //
  250. // need to make sure that Rasman is started
  251. //
  252. dwRetCode = RasInitialize();
  253. if ( NO_ERROR != dwRetCode )
  254. {
  255. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "RasInitialize Failed ErrorCode: 0x%x", dwRetCode );
  256. return dwRetCode;
  257. }
  258. dwRetCode = RasReferenceRasman(TRUE);
  259. if ( NO_ERROR != dwRetCode )
  260. {
  261. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "RasReferenceRasman Failed ErrorCode: 0x%x", dwRetCode );
  262. return dwRetCode;
  263. }
  264. //
  265. // We can get credentials from the system
  266. //
  267. if ( ( dwRetCode = RasGetUserCredentials(
  268. pbChallenge,
  269. pLuid,
  270. Username,
  271. CaseSensitiveChallengeResponse,
  272. CaseInsensitiveChallengeResponse,
  273. pLmSessionKey,
  274. pUserSessionKey
  275. ) ) )
  276. {
  277. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "RasGetUserCredentials Failed ErrorCode: 0x%x", dwRetCode );
  278. RasReferenceRasman(FALSE);
  279. return (ERROR_AUTH_INTERNAL);
  280. }
  281. WideCharToMultiByte(
  282. CP_ACP,
  283. 0,
  284. Username,
  285. -1,
  286. pszUsername,
  287. UNLEN + 1,
  288. NULL,
  289. NULL);
  290. //
  291. // What if the conversion fails?
  292. //
  293. pszUsername[UNLEN] = 0;
  294. RasReferenceRasman(FALSE);
  295. }
  296. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetChallengeResponse Success");
  297. return (0L);
  298. }
  299. BOOL GetDESChallengeResponse(
  300. IN DWORD dwTraceId,
  301. IN PCHAR pszPassword,
  302. IN PBYTE pchChallenge,
  303. OUT PBYTE pchChallengeResponse
  304. )
  305. {
  306. CHAR LocalPassword[LM20_PWLEN + 1];
  307. DWORD dwRetCode = ERROR_SUCCESS;
  308. LM_OWF_PASSWORD LmOwfPassword;
  309. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetDESChallengeResponse" );
  310. if (lstrlenA(pszPassword) > LM20_PWLEN)
  311. {
  312. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "too big" );
  313. return (FALSE);
  314. }
  315. lstrcpyA(LocalPassword, pszPassword);
  316. if (!Uppercase(dwTraceId, LocalPassword))
  317. {
  318. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "UpperCase Fail" );
  319. ZeroMemory( LocalPassword, LM20_PWLEN );
  320. return (FALSE);
  321. }
  322. //
  323. // Encrypt standard text with the password as a key
  324. //
  325. if (( dwRetCode = RtlCalculateLmOwfPassword((PLM_PASSWORD) LocalPassword, &LmOwfPassword) ))
  326. {
  327. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetDesChallengeResponse Fail 1. ErrorCode: 0x%x", dwRetCode );
  328. ZeroMemory( LocalPassword, LM20_PWLEN );
  329. return (FALSE);
  330. }
  331. //
  332. // Use the challenge sent by the gateway to encrypt the
  333. // password digest from above.
  334. //
  335. if ( ( dwRetCode = RtlCalculateLmResponse((PLM_CHALLENGE) pchChallenge,
  336. &LmOwfPassword, (PLM_RESPONSE) pchChallengeResponse) ) )
  337. {
  338. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetDesChallengeResponse Fail 2. ErrorCode: 0x%x", dwRetCode );
  339. ZeroMemory( LocalPassword, LM20_PWLEN );
  340. return (FALSE);
  341. }
  342. #ifdef CHAPSAMPLES
  343. TRACE( "LM challenge..." );
  344. DUMPB( pchChallenge, sizeof(LM_CHALLENGE) );
  345. TRACE( "LM password..." );
  346. DUMPB( LocalPassword, LM20_PWLEN );
  347. TRACE( "LM OWF password..." );
  348. DUMPB( &LmOwfPassword, sizeof(LM_OWF_PASSWORD) );
  349. TRACE( "LM Response..." );
  350. DUMPB( pchChallengeResponse, sizeof(LM_RESPONSE) );
  351. #endif
  352. ZeroMemory( LocalPassword, LM20_PWLEN );
  353. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetDESChallengeResponse Success" );
  354. return (TRUE);
  355. }
  356. BOOL GetMD5ChallengeResponse(
  357. IN DWORD dwTraceId,
  358. IN PCHAR pszPassword,
  359. IN PBYTE pchChallenge,
  360. OUT PBYTE pchChallengeResponse
  361. )
  362. {
  363. NT_PASSWORD NtPassword;
  364. NT_OWF_PASSWORD NtOwfPassword;
  365. DWORD dwRetCode = ERROR_SUCCESS;
  366. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetMD5ChallengeResponse Success" );
  367. RtlCreateUnicodeStringFromAsciiz(&NtPassword, pszPassword);
  368. //
  369. // Encrypt standard text with the password as a key
  370. //
  371. if (( dwRetCode = RtlCalculateNtOwfPassword(&NtPassword, &NtOwfPassword) ) )
  372. {
  373. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetMD5ChallengeResponse Fail 1. ErrorCode:0x%x", dwRetCode );
  374. return (FALSE);
  375. }
  376. //
  377. // Use the challenge sent by the gateway to encrypt the
  378. // password digest from above.
  379. //
  380. if (( dwRetCode = RtlCalculateNtResponse((PNT_CHALLENGE) pchChallenge,
  381. &NtOwfPassword, (PNT_RESPONSE) pchChallengeResponse) ) )
  382. {
  383. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetMD5ChallengeResponse Fail 2. ErrorCode:0x%x", dwRetCode );
  384. return (FALSE);
  385. }
  386. #ifdef CHAPSAMPLES
  387. TRACE( "NT Challenge..." );
  388. DUMPB( pchChallenge, sizeof(NT_CHALLENGE) );
  389. TRACE( "NT password..." );
  390. DUMPB( NtPassword.Buffer, NtPassword.MaximumLength );
  391. TRACE( "NT OWF password..." );
  392. DUMPB( &NtOwfPassword, sizeof(NT_OWF_PASSWORD) );
  393. TRACE( "NT Response..." );
  394. DUMPB( pchChallengeResponse, sizeof(NT_RESPONSE) );
  395. #endif
  396. RtlFreeUnicodeString(&NtPassword);
  397. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "GetMD5ChallengeResponse Success" );
  398. return (TRUE);
  399. }
  400. DWORD GetEncryptedOwfPasswordsForChangePassword(
  401. IN PCHAR pClearTextOldPassword,
  402. IN PCHAR pClearTextNewPassword,
  403. IN PLM_SESSION_KEY pLmSessionKey,
  404. OUT PENCRYPTED_LM_OWF_PASSWORD pEncryptedLmOwfOldPassword,
  405. OUT PENCRYPTED_LM_OWF_PASSWORD pEncryptedLmOwfNewPassword,
  406. OUT PENCRYPTED_NT_OWF_PASSWORD pEncryptedNtOwfOldPassword,
  407. OUT PENCRYPTED_NT_OWF_PASSWORD pEncryptedNtOwfNewPassword
  408. )
  409. {
  410. NT_PASSWORD NtPassword;
  411. NT_OWF_PASSWORD NtOwfPassword;
  412. DWORD rc;
  413. if ((lstrlenA(pClearTextOldPassword) <= LM20_PWLEN) &&
  414. (lstrlenA(pClearTextOldPassword) <= LM20_PWLEN))
  415. {
  416. CHAR LmPassword[LM20_PWLEN + 1];
  417. LM_OWF_PASSWORD LmOwfPassword;
  418. //
  419. // Make an uppercased-version of old password
  420. //
  421. lstrcpyA(LmPassword, pClearTextOldPassword);
  422. if (!Uppercase(0, LmPassword))
  423. {
  424. memset(LmPassword, 0, lstrlenA(LmPassword));
  425. return (1L);
  426. }
  427. //
  428. // We need to calculate the OWF's for the old and new passwords
  429. //
  430. rc = RtlCalculateLmOwfPassword((PLM_PASSWORD) LmPassword,
  431. &LmOwfPassword);
  432. if (!NT_SUCCESS(rc))
  433. {
  434. memset(LmPassword, 0, lstrlenA(LmPassword));
  435. return (rc);
  436. }
  437. rc = RtlEncryptLmOwfPwdWithLmSesKey(&LmOwfPassword, pLmSessionKey,
  438. pEncryptedLmOwfOldPassword);
  439. if (!NT_SUCCESS(rc))
  440. {
  441. memset(LmPassword, 0, lstrlenA(LmPassword));
  442. return (rc);
  443. }
  444. //
  445. // Make an uppercased-version of new password
  446. //
  447. lstrcpyA(LmPassword, pClearTextNewPassword);
  448. if (!Uppercase(0, LmPassword))
  449. {
  450. memset(LmPassword, 0, lstrlenA(LmPassword));
  451. return (1L);
  452. }
  453. rc = RtlCalculateLmOwfPassword((PLM_PASSWORD) LmPassword,
  454. &LmOwfPassword);
  455. if (!NT_SUCCESS(rc))
  456. {
  457. memset(LmPassword, 0, lstrlenA(LmPassword));
  458. return (rc);
  459. }
  460. rc = RtlEncryptLmOwfPwdWithLmSesKey(&LmOwfPassword, pLmSessionKey,
  461. pEncryptedLmOwfNewPassword);
  462. if (!NT_SUCCESS(rc))
  463. {
  464. memset(LmPassword, 0, lstrlenA(LmPassword));
  465. return (rc);
  466. }
  467. }
  468. RtlCreateUnicodeStringFromAsciiz(&NtPassword, pClearTextOldPassword);
  469. rc = RtlCalculateNtOwfPassword(&NtPassword, &NtOwfPassword);
  470. if (!NT_SUCCESS(rc))
  471. {
  472. memset(NtPassword.Buffer, 0, NtPassword.Length);
  473. return (rc);
  474. }
  475. rc = RtlEncryptNtOwfPwdWithNtSesKey(&NtOwfPassword, pLmSessionKey,
  476. pEncryptedNtOwfOldPassword);
  477. if (!NT_SUCCESS(rc))
  478. {
  479. memset(NtPassword.Buffer, 0, NtPassword.Length);
  480. return (rc);
  481. }
  482. RtlCreateUnicodeStringFromAsciiz(&NtPassword, pClearTextNewPassword);
  483. rc = RtlCalculateNtOwfPassword(&NtPassword, &NtOwfPassword);
  484. if (!NT_SUCCESS(rc))
  485. {
  486. memset(NtPassword.Buffer, 0, NtPassword.Length);
  487. return (rc);
  488. }
  489. rc = RtlEncryptNtOwfPwdWithNtSesKey(&NtOwfPassword, pLmSessionKey,
  490. pEncryptedNtOwfNewPassword);
  491. if (!NT_SUCCESS(rc))
  492. {
  493. memset(NtPassword.Buffer, 0, NtPassword.Length);
  494. return (rc);
  495. }
  496. return (0L);
  497. }
  498. BOOL Uppercase(DWORD dwTraceId, PBYTE pString)
  499. {
  500. OEM_STRING OemString;
  501. ANSI_STRING AnsiString;
  502. UNICODE_STRING UnicodeString;
  503. NTSTATUS rc;
  504. RtlInitAnsiString(&AnsiString, pString);
  505. rc = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  506. if (!NT_SUCCESS(rc))
  507. {
  508. if ( dwTraceId )
  509. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "UpperCase Fail 1. ErrorCode:%x", rc );
  510. return (FALSE);
  511. }
  512. rc = RtlUpcaseUnicodeStringToOemString(&OemString, &UnicodeString, TRUE);
  513. if (!NT_SUCCESS(rc))
  514. {
  515. if ( dwTraceId )
  516. TracePrintfExA (dwTraceId, 0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC, "UpperCase Fail 2. ErrorCode:%x", rc );
  517. RtlFreeUnicodeString(&UnicodeString);
  518. return (FALSE);
  519. }
  520. OemString.Buffer[OemString.Length] = '\0';
  521. lstrcpyA(pString, OemString.Buffer);
  522. RtlFreeOemString(&OemString);
  523. RtlFreeUnicodeString(&UnicodeString);
  524. return (TRUE);
  525. }
  526. VOID
  527. CGetSessionKeys(
  528. IN CHAR* pszPw,
  529. OUT LM_SESSION_KEY* pLmKey,
  530. OUT USER_SESSION_KEY* pUserKey )
  531. /* Loads caller's 'pLmKey' buffer with the LAN Manager session key and
  532. ** caller's 'pUserKey' buffer with the user session key associated with
  533. ** password 'pszPw'. If a session key cannot be calculated, that key is
  534. ** returned as all zeros.
  535. */
  536. {
  537. /* The Lanman session key is the first 8 bytes of the Lanman
  538. ** one-way-function password.
  539. */
  540. {
  541. CHAR szPw[ LM20_PWLEN + 1 ];
  542. LM_OWF_PASSWORD lmowf;
  543. memset( pLmKey, '\0', sizeof(*pLmKey) );
  544. if (strlen( pszPw ) <= LM20_PWLEN )
  545. {
  546. memset( szPw, '\0', LM20_PWLEN + 1 );
  547. strcpy( szPw, pszPw );
  548. if (Uppercase( 0, szPw ))
  549. {
  550. if (RtlCalculateLmOwfPassword(
  551. (PLM_PASSWORD )szPw, &lmowf ) == 0)
  552. {
  553. memcpy( pLmKey, &lmowf, sizeof(*pLmKey) );
  554. }
  555. }
  556. memset( szPw, '\0', sizeof(szPw) );
  557. }
  558. }
  559. /* The user session key is the NT one-way-function of the NT
  560. ** one-way-function password.
  561. */
  562. {
  563. WCHAR szPw[ PWLEN + 1 ];
  564. NT_PASSWORD ntpw;
  565. NT_OWF_PASSWORD ntowf;
  566. ANSI_STRING ansi;
  567. memset( pUserKey, '\0', sizeof(pUserKey) );
  568. /* NT_PASSWORD is really a UNICODE_STRING, so we need to convert our
  569. ** ANSI password.
  570. */
  571. ntpw.Length = 0;
  572. ntpw.MaximumLength = sizeof(szPw);
  573. ntpw.Buffer = szPw;
  574. RtlInitAnsiString( &ansi, pszPw );
  575. RtlAnsiStringToUnicodeString( &ntpw, &ansi, FALSE );
  576. RtlCalculateNtOwfPassword( &ntpw, &ntowf );
  577. /* The first argument to RtlCalculateUserSessionKeyNt is the NT
  578. ** response, but it is not used internally.
  579. */
  580. RtlCalculateUserSessionKeyNt( NULL, &ntowf, pUserKey );
  581. memset( szPw, '\0', sizeof(szPw) );
  582. }
  583. }