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.

1289 lines
38 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. logon.cxx
  5. Abstract:
  6. logon
  7. Author:
  8. Larry Zhu (LZhu) December 1, 2001 Created
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "logon.hxx"
  16. NTSTATUS
  17. LogonUserWrapper(
  18. IN PCWSTR pszUserName,
  19. IN PCWSTR pszDomainName,
  20. IN PCWSTR pszPassword,
  21. IN DWORD LogonType,
  22. IN DWORD dwLogonProvider,
  23. OUT HANDLE* phToken
  24. )
  25. {
  26. THResult hResult = S_OK;
  27. PSID pLoginSid = NULL;
  28. VOID* pProfile = NULL;
  29. ULONG cbProfile = 0;
  30. QUOTA_LIMITS Quotas = {0};
  31. DebugPrintf(SSPI_LOG, "LogonUserWrapper UserName %ws, DomainName %ws, Password %ws, LogonType %#x, Provider %#x\n",
  32. pszUserName, pszDomainName, pszPassword, LogonType, dwLogonProvider);
  33. hResult DBGCHK = LogonUserExW(
  34. (PWSTR) pszUserName,
  35. (PWSTR) pszDomainName,
  36. (PWSTR) pszPassword,
  37. LogonType,
  38. dwLogonProvider,
  39. phToken,
  40. &pLoginSid,
  41. &pProfile,
  42. &cbProfile,
  43. &Quotas
  44. ) ? S_OK : GetLastErrorAsHResult();
  45. if (SUCCEEDED(hResult))
  46. {
  47. DebugPrintSidFriendlyName(SSPI_LOG, "LogonSid:", pLoginSid);
  48. DebugPrintProfileAndQuotas(SSPI_LOG, pProfile, &Quotas);
  49. DebugPrintf(SSPI_LOG, "LogonUserWrapper TokenHandle %p\n", *phToken);
  50. }
  51. if (pLoginSid)
  52. {
  53. LsaFreeReturnBuffer(pLoginSid);
  54. }
  55. if (pProfile)
  56. {
  57. LsaFreeReturnBuffer(pProfile);
  58. }
  59. return SUCCEEDED(hResult) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  60. }
  61. VOID
  62. DebugPrintProfileAndQuotas(
  63. IN ULONG Level,
  64. IN OPTIONAL VOID* pProfile,
  65. IN OPTIONAL QUOTA_LIMITS* pQuotas
  66. )
  67. {
  68. if (pQuotas)
  69. {
  70. DebugPrintf(Level, "Quotas PagedPoolLimit %p, NonPagedPoolLimit %p, "
  71. "MinimumWorkingSetSize %p, MaximumWorkingSetSize %p, PagedPoolLimit %p\n",
  72. pQuotas->PagedPoolLimit, pQuotas->NonPagedPoolLimit,
  73. pQuotas->MinimumWorkingSetSize, pQuotas->MaximumWorkingSetSize,
  74. pQuotas->PagedPoolLimit);
  75. DebugPrintSysTimeAsLocalTime(Level, "TimeLimit", &pQuotas->TimeLimit);
  76. }
  77. if (pProfile)
  78. {
  79. if (MsV1_0InteractiveProfile == *((ULONG*) pProfile))
  80. {
  81. MSV1_0_INTERACTIVE_PROFILE* pMsvInteractiveProfile = (MSV1_0_INTERACTIVE_PROFILE*) pProfile;
  82. DebugPrintf(Level, "MsV1_0InteractiveProfile: "
  83. "LogonCount %#x, BadPasswordCount %#x, LogonScript %wZ, "
  84. "HomeDirectory %wZ, FullName %wZ, ProfilePath %wZ, "
  85. "HomeDriectoryDrive %wZ, LogonServer %wZ, UserFlags %#x\n",
  86. pMsvInteractiveProfile->LogonCount,
  87. pMsvInteractiveProfile->BadPasswordCount,
  88. &pMsvInteractiveProfile->LogonScript,
  89. &pMsvInteractiveProfile->HomeDirectory,
  90. &pMsvInteractiveProfile->FullName,
  91. &pMsvInteractiveProfile->ProfilePath,
  92. &pMsvInteractiveProfile->HomeDirectoryDrive,
  93. &pMsvInteractiveProfile->LogonServer,
  94. pMsvInteractiveProfile->UserFlags);
  95. DebugPrintSysTimeAsLocalTime(Level, "LogonTime", &pMsvInteractiveProfile->LogonTime);
  96. DebugPrintSysTimeAsLocalTime(Level, "LogoffTime", &pMsvInteractiveProfile->LogoffTime);
  97. DebugPrintSysTimeAsLocalTime(Level, "KickOffTime", &pMsvInteractiveProfile->KickOffTime );
  98. DebugPrintSysTimeAsLocalTime(Level, "PasswordLastSet", &pMsvInteractiveProfile->PasswordLastSet );
  99. DebugPrintSysTimeAsLocalTime(Level, "PasswordCanChange", &pMsvInteractiveProfile->PasswordCanChange );
  100. DebugPrintSysTimeAsLocalTime(Level, "PasswordMustChange", &pMsvInteractiveProfile->PasswordMustChange );
  101. }
  102. else if (MsV1_0Lm20LogonProfile == *((ULONG*) pProfile))
  103. {
  104. MSV1_0_LM20_LOGON_PROFILE* pMsvLm20LogonProfile = (MSV1_0_LM20_LOGON_PROFILE*) pProfile;
  105. DebugPrintf(Level, "MsV1_0Lm20LogonProfile: "
  106. "UserFlags %#x, LogonDomainName %wZ, LogonServer %wZ, UserParameters %#x\n",
  107. pMsvLm20LogonProfile->UserFlags,
  108. &pMsvLm20LogonProfile->LogonDomainName,
  109. &pMsvLm20LogonProfile->LogonServer,
  110. pMsvLm20LogonProfile->UserParameters);
  111. DebugPrintHex(Level, "UserSessionKey:", MSV1_0_USER_SESSION_KEY_LENGTH, pMsvLm20LogonProfile->UserSessionKey);
  112. DebugPrintHex(Level, "LanmanSessionKey:", MSV1_0_LANMAN_SESSION_KEY_LENGTH, pMsvLm20LogonProfile->LanmanSessionKey);
  113. DebugPrintSysTimeAsLocalTime(Level, "KickOffTime", &pMsvLm20LogonProfile->KickOffTime);
  114. DebugPrintSysTimeAsLocalTime(Level, "LogoffTime", &pMsvLm20LogonProfile->LogoffTime);
  115. }
  116. else if (KerbInteractiveProfile == *((ULONG*) pProfile))
  117. {
  118. KERB_TICKET_PROFILE* pKerbTicketProfile = (KERB_TICKET_PROFILE*) pProfile;
  119. KERB_INTERACTIVE_PROFILE* pKrbInteractiveProfile = &pKerbTicketProfile->Profile;
  120. DebugPrintf(Level, "KerbInteractiveProfile: "
  121. "LogCount %#x, BaddPasswordCount %#x, LogonScript %wZ, "
  122. "HomeDirectory %wZ, FullName %wZ, ProfilePath %wZ, "
  123. "HomeDriectoryDrive %wZ, LogonServer %wZ, UserFlags %#x\n",
  124. pKrbInteractiveProfile->LogonCount,
  125. pKrbInteractiveProfile->BadPasswordCount,
  126. &pKrbInteractiveProfile->LogonScript,
  127. &pKrbInteractiveProfile->HomeDirectory,
  128. &pKrbInteractiveProfile->FullName,
  129. &pKrbInteractiveProfile->ProfilePath,
  130. &pKrbInteractiveProfile->HomeDirectoryDrive,
  131. &pKrbInteractiveProfile->LogonServer,
  132. pKrbInteractiveProfile->UserFlags);
  133. DebugPrintSysTimeAsLocalTime(Level, "LogonTime", &pKrbInteractiveProfile->LogonTime);
  134. DebugPrintSysTimeAsLocalTime(Level, "LogoffTime", &pKrbInteractiveProfile->LogoffTime);
  135. DebugPrintSysTimeAsLocalTime(Level, "KickOffTime", &pKrbInteractiveProfile->KickOffTime);
  136. DebugPrintSysTimeAsLocalTime(Level, "PasswordLastSet", &pKrbInteractiveProfile->PasswordLastSet);
  137. DebugPrintSysTimeAsLocalTime(Level, "PasswordCanChange", &pKrbInteractiveProfile->PasswordCanChange);
  138. DebugPrintSysTimeAsLocalTime(Level, "PasswordMustChange", &pKrbInteractiveProfile->PasswordMustChange);
  139. DebugPrintHex(Level, "SessionKey:", sizeof(pKerbTicketProfile->SessionKey), &pKerbTicketProfile->SessionKey);
  140. }
  141. else
  142. {
  143. DebugPrintf(SSPI_ERROR, "Unsupported profile type %#x\n", *((ULONG*) pProfile));
  144. }
  145. }
  146. }
  147. NTSTATUS
  148. GetLm20LogonInfoNtlmv1(
  149. IN UNICODE_STRING* pUserName,
  150. IN UNICODE_STRING* pDomainName,
  151. IN UNICODE_STRING* pPassword,
  152. IN UNICODE_STRING* pWorkstation,
  153. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  154. OUT ULONG* pcbLogonInfo,
  155. OUT PMSV1_0_LM20_LOGON *ppLognInfo
  156. )
  157. {
  158. TNtStatus Status;
  159. PMSV1_0_LM20_LOGON pMsvNetAuthInfo = NULL;
  160. ULONG cbMsvNetAuthInfo;
  161. NT_OWF_PASSWORD PasswordHash;
  162. OEM_STRING LmPassword;
  163. UCHAR LmPasswordBuf[ LM20_PWLEN + 1 ];
  164. LM_OWF_PASSWORD LmPasswordHash;
  165. DebugPrintf(SSPI_LOG, "GetLm20LogonInfoNtlmv1 UserName %wZ, DomainName %wZ, Password %wZ, Workstation %wZ\n",
  166. pUserName, pDomainName, pPassword, pWorkstation);
  167. *ppLognInfo = NULL;
  168. *pcbLogonInfo = 0;
  169. cbMsvNetAuthInfo = ROUND_UP_COUNT(sizeof(MSV1_0_LM20_LOGON), sizeof(ULONG_PTR))
  170. + pUserName->Length
  171. + pDomainName->Length
  172. + pWorkstation->Length
  173. + NT_RESPONSE_LENGTH
  174. + LM_RESPONSE_LENGTH;
  175. pMsvNetAuthInfo = (PMSV1_0_LM20_LOGON) new CHAR[cbMsvNetAuthInfo];
  176. Status DBGCHK = pMsvNetAuthInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  177. if (NT_SUCCESS(Status))
  178. {
  179. //
  180. // Start packing in the string
  181. //
  182. RtlZeroMemory(pMsvNetAuthInfo, cbMsvNetAuthInfo);
  183. pMsvNetAuthInfo->MessageType = MsV1_0NetworkLogon; // if set MsV1_0Lm20Logon, ignore ParameterControl
  184. //
  185. // Copy the user name into the authentication buffer
  186. //
  187. pMsvNetAuthInfo->UserName.Length = pUserName->Length;
  188. pMsvNetAuthInfo->UserName.MaximumLength = pMsvNetAuthInfo->UserName.Length;
  189. pMsvNetAuthInfo->UserName.Buffer = (PWSTR)(pMsvNetAuthInfo + 1); // could be aligned here
  190. RtlCopyMemory(
  191. pMsvNetAuthInfo->UserName.Buffer,
  192. pUserName->Buffer,
  193. pUserName->Length
  194. );
  195. //
  196. // Copy the domain name into the authentication buffer
  197. //
  198. pMsvNetAuthInfo->LogonDomainName.Length = pDomainName->Length;
  199. pMsvNetAuthInfo->LogonDomainName.MaximumLength = pDomainName->Length ;
  200. pMsvNetAuthInfo->LogonDomainName.Buffer = (PWSTR) ((PBYTE)(pMsvNetAuthInfo->UserName.Buffer)
  201. + pMsvNetAuthInfo->UserName.MaximumLength);
  202. RtlCopyMemory(
  203. pMsvNetAuthInfo->LogonDomainName.Buffer,
  204. pDomainName->Buffer,
  205. pDomainName->Length
  206. );
  207. //
  208. // Copy the workstation name into the buffer
  209. //
  210. pMsvNetAuthInfo->Workstation.Length = pWorkstation->Length;
  211. pMsvNetAuthInfo->Workstation.MaximumLength = pMsvNetAuthInfo->Workstation.Length;
  212. pMsvNetAuthInfo->Workstation.Buffer = (PWSTR) ((PBYTE) (pMsvNetAuthInfo->LogonDomainName.Buffer)
  213. + pMsvNetAuthInfo->LogonDomainName.MaximumLength);
  214. RtlCopyMemory(
  215. pMsvNetAuthInfo->Workstation.Buffer,
  216. pWorkstation->Buffer,
  217. pWorkstation->Length
  218. );
  219. RtlCopyMemory(pMsvNetAuthInfo->ChallengeToClient,
  220. ChallengeToClient,
  221. MSV1_0_CHALLENGE_LENGTH);
  222. //
  223. // Set up space for response
  224. //
  225. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer =
  226. (((PCHAR) pMsvNetAuthInfo->Workstation.Buffer)
  227. + pMsvNetAuthInfo->Workstation.MaximumLength);
  228. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Length = NT_RESPONSE_LENGTH;
  229. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.MaximumLength = NT_RESPONSE_LENGTH;
  230. RtlCalculateNtOwfPassword(
  231. pPassword,
  232. &PasswordHash
  233. );
  234. RtlCalculateNtResponse(
  235. (PNT_CHALLENGE) ChallengeToClient,
  236. &PasswordHash,
  237. (PNT_RESPONSE) pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer
  238. );
  239. //
  240. // Now do the painful LM compatible hash, so anyone who is maintaining
  241. // their account from a WfW machine will still have a password.
  242. //
  243. LmPassword.Buffer = (PCHAR) LmPasswordBuf;
  244. LmPassword.Length = LmPassword.MaximumLength = LM20_PWLEN + 1;
  245. Status DBGCHK = RtlUpcaseUnicodeStringToOemString(
  246. &LmPassword,
  247. pPassword,
  248. FALSE
  249. );
  250. }
  251. if (NT_SUCCESS(Status))
  252. {
  253. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Buffer =
  254. ((PCHAR) (pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer)
  255. + pMsvNetAuthInfo->CaseSensitiveChallengeResponse.MaximumLength);
  256. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Length = LM_RESPONSE_LENGTH;
  257. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.MaximumLength = LM_RESPONSE_LENGTH;
  258. RtlCalculateLmOwfPassword(
  259. LmPassword.Buffer,
  260. &LmPasswordHash
  261. );
  262. RtlZeroMemory(LmPassword.Buffer, LmPassword.Length);
  263. RtlCalculateLmResponse(
  264. (PLM_CHALLENGE) ChallengeToClient,
  265. &LmPasswordHash,
  266. (PLM_RESPONSE) pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Buffer
  267. );
  268. *ppLognInfo = pMsvNetAuthInfo;
  269. pMsvNetAuthInfo = NULL;
  270. *pcbLogonInfo = cbMsvNetAuthInfo;
  271. }
  272. if (pMsvNetAuthInfo)
  273. {
  274. delete [] pMsvNetAuthInfo;
  275. }
  276. return Status;
  277. }
  278. VOID
  279. CalculateNtlmv2Owf(
  280. IN NT_OWF_PASSWORD* pNtOwfPassword,
  281. IN UNICODE_STRING* pUserName,
  282. IN UNICODE_STRING* pLogonDomainName,
  283. OUT UCHAR Ntlmv2Owf[MSV1_0_NTLM3_OWF_LENGTH]
  284. )
  285. {
  286. HMACMD5_CTX HMACMD5Context;
  287. //
  288. // reserve a scratch buffer
  289. //
  290. WCHAR szUserName[(UNLEN + 4)] = {0};
  291. UNICODE_STRING UserName = {0, sizeof(szUserName), szUserName};
  292. //
  293. // first make a copy then upcase it
  294. //
  295. UserName.Length = min(UserName.MaximumLength, pUserName->Length);
  296. ASSERT(UserName.Length == pUserName->Length);
  297. RtlCopyMemory(UserName.Buffer, pUserName->Buffer, UserName.Length);
  298. RtlUpcaseUnicodeString(&UserName, &UserName, FALSE);
  299. //
  300. // Calculate Ntlmv2 OWF -- HMAC(MD4(P), (UserName, LogonDomainName))
  301. //
  302. HMACMD5Init(
  303. &HMACMD5Context,
  304. (UCHAR *) pNtOwfPassword,
  305. sizeof(*pNtOwfPassword)
  306. );
  307. HMACMD5Update(
  308. &HMACMD5Context,
  309. (UCHAR *) UserName.Buffer,
  310. UserName.Length
  311. );
  312. HMACMD5Update(
  313. &HMACMD5Context,
  314. (UCHAR *) pLogonDomainName->Buffer,
  315. pLogonDomainName->Length
  316. );
  317. HMACMD5Final(
  318. &HMACMD5Context,
  319. Ntlmv2Owf
  320. );
  321. }
  322. VOID
  323. GetLmv2Response(
  324. IN NT_OWF_PASSWORD* pNtOwfPassword,
  325. IN UNICODE_STRING* pUserName,
  326. IN UNICODE_STRING* pLogonDomainName,
  327. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  328. IN UCHAR ChallengeFromClient[MSV1_0_CHALLENGE_LENGTH],
  329. OUT UCHAR Response[MSV1_0_NTLM3_RESPONSE_LENGTH],
  330. OUT OPTIONAL USER_SESSION_KEY* pUserSessionKey,
  331. OUT OPTIONAL LM_SESSION_KEY* pLanmanSessionKey // [MSV1_0_LANMAN_SESSION_KEY_LENGTH]
  332. )
  333. {
  334. HMACMD5_CTX HMACMD5Context;
  335. UCHAR Ntlmv2Owf[MSV1_0_NTLM3_OWF_LENGTH];
  336. C_ASSERT(MD5DIGESTLEN == MSV1_0_NTLM3_RESPONSE_LENGTH);
  337. //
  338. // get Ntlmv2 OWF
  339. //
  340. CalculateNtlmv2Owf(
  341. pNtOwfPassword,
  342. pUserName,
  343. pLogonDomainName,
  344. Ntlmv2Owf
  345. );
  346. //
  347. // Calculate Ntlmv2 Response
  348. // HMAC(Ntlmv2Owf, (ChallengeToClient, ChallengeFromClient))
  349. //
  350. HMACMD5Init(
  351. &HMACMD5Context,
  352. Ntlmv2Owf,
  353. MSV1_0_NTLM3_OWF_LENGTH
  354. );
  355. HMACMD5Update(
  356. &HMACMD5Context,
  357. ChallengeToClient,
  358. MSV1_0_CHALLENGE_LENGTH
  359. );
  360. HMACMD5Update(
  361. &HMACMD5Context,
  362. ChallengeFromClient,
  363. MSV1_0_CHALLENGE_LENGTH
  364. );
  365. HMACMD5Final(
  366. &HMACMD5Context,
  367. Response
  368. );
  369. if (pUserSessionKey && pLanmanSessionKey)
  370. {
  371. // now compute the session keys
  372. // HMAC(Kr, R)
  373. HMACMD5Init(
  374. &HMACMD5Context,
  375. Ntlmv2Owf,
  376. MSV1_0_NTLM3_OWF_LENGTH
  377. );
  378. HMACMD5Update(
  379. &HMACMD5Context,
  380. Response,
  381. MSV1_0_NTLM3_RESPONSE_LENGTH
  382. );
  383. ASSERT(MD5DIGESTLEN == MSV1_0_USER_SESSION_KEY_LENGTH);
  384. HMACMD5Final(
  385. &HMACMD5Context,
  386. (PUCHAR)pUserSessionKey
  387. );
  388. ASSERT(MSV1_0_LANMAN_SESSION_KEY_LENGTH <= MSV1_0_USER_SESSION_KEY_LENGTH);
  389. RtlCopyMemory(
  390. pLanmanSessionKey,
  391. pUserSessionKey,
  392. MSV1_0_LANMAN_SESSION_KEY_LENGTH
  393. );
  394. }
  395. }
  396. VOID
  397. Lm20GetNtlmv2Response(
  398. IN NT_OWF_PASSWORD* pNtOwfPassword,
  399. IN UNICODE_STRING* pUserName,
  400. IN UNICODE_STRING* pLogonDomainName,
  401. IN STRING* pTargetInfo,
  402. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  403. OUT MSV1_0_NTLM3_RESPONSE* pNtlmv2Response,
  404. OUT MSV1_0_LM3_RESPONSE* pLmv2Response,
  405. OUT USER_SESSION_KEY* pNtUserSessionKey,
  406. OUT LM_SESSION_KEY* pLmSessionKey
  407. )
  408. {
  409. //
  410. // fill in version numbers, timestamp, and client's challenge
  411. //
  412. pNtlmv2Response->RespType = 1;
  413. pNtlmv2Response->HiRespType = 1;
  414. pNtlmv2Response->Flags = 0;
  415. pNtlmv2Response->MsgWord = 0;
  416. GetSystemTimeAsFileTime((FILETIME*)(&pNtlmv2Response->TimeStamp));
  417. RtlGenRandom(pNtlmv2Response->ChallengeFromClient, MSV1_0_CHALLENGE_LENGTH);
  418. RtlCopyMemory(pNtlmv2Response->Buffer, pTargetInfo->Buffer, pTargetInfo->Length);
  419. //
  420. // Calculate Ntlmv2 response, filling in response field
  421. //
  422. GetNtlmv2Response(
  423. pNtOwfPassword,
  424. pUserName,
  425. pLogonDomainName,
  426. pTargetInfo->Length,
  427. ChallengeToClient,
  428. pNtlmv2Response,
  429. pNtUserSessionKey,
  430. pLmSessionKey
  431. );
  432. //
  433. // Use same challenge to compute the LMV2 response
  434. //
  435. RtlCopyMemory(pLmv2Response->ChallengeFromClient, pNtlmv2Response->ChallengeFromClient, MSV1_0_CHALLENGE_LENGTH);
  436. //
  437. // Calculate LMV2 response
  438. //
  439. GetLmv2Response(
  440. pNtOwfPassword,
  441. pUserName,
  442. pLogonDomainName,
  443. ChallengeToClient,
  444. pLmv2Response->ChallengeFromClient,
  445. pLmv2Response->Response,
  446. NULL,
  447. NULL
  448. );
  449. }
  450. VOID
  451. GetNtlmv2Response(
  452. IN NT_OWF_PASSWORD* pNtOwfPassword,
  453. IN UNICODE_STRING* pUserName,
  454. IN UNICODE_STRING* pLogonDomainName,
  455. IN ULONG TargetInfoLength,
  456. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  457. IN OUT MSV1_0_NTLM3_RESPONSE* pNtlmv2Response,
  458. OUT USER_SESSION_KEY* pNtUserSessionKey,
  459. OUT LM_SESSION_KEY* pLmSessionKey
  460. )
  461. {
  462. HMACMD5_CTX HMACMD5Context;
  463. UCHAR Ntlmv2Owf[MSV1_0_NTLM3_OWF_LENGTH];
  464. C_ASSERT(MD5DIGESTLEN == MSV1_0_NTLM3_RESPONSE_LENGTH);
  465. C_ASSERT(MD5DIGESTLEN == sizeof(USER_SESSION_KEY));
  466. C_ASSERT(sizeof(LM_SESSION_KEY) <= sizeof(USER_SESSION_KEY));
  467. //
  468. // get Ntlmv2 OWF
  469. //
  470. CalculateNtlmv2Owf(
  471. pNtOwfPassword,
  472. pUserName,
  473. pLogonDomainName,
  474. Ntlmv2Owf
  475. );
  476. HMACMD5Init(
  477. &HMACMD5Context,
  478. Ntlmv2Owf,
  479. MSV1_0_NTLM3_OWF_LENGTH
  480. );
  481. HMACMD5Update(
  482. &HMACMD5Context,
  483. ChallengeToClient,
  484. MSV1_0_CHALLENGE_LENGTH
  485. );
  486. HMACMD5Update(
  487. &HMACMD5Context,
  488. &pNtlmv2Response->RespType,
  489. (MSV1_0_NTLM3_INPUT_LENGTH + TargetInfoLength)
  490. );
  491. HMACMD5Final(
  492. &HMACMD5Context,
  493. pNtlmv2Response->Response
  494. );
  495. //
  496. // now compute the session keys
  497. // HMAC(Kr, R)
  498. //
  499. HMACMD5Init(
  500. &HMACMD5Context,
  501. Ntlmv2Owf,
  502. MSV1_0_NTLM3_OWF_LENGTH
  503. );
  504. HMACMD5Update(
  505. &HMACMD5Context,
  506. pNtlmv2Response->Response,
  507. MSV1_0_NTLM3_RESPONSE_LENGTH
  508. );
  509. HMACMD5Final(
  510. &HMACMD5Context,
  511. (UCHAR*) pNtUserSessionKey
  512. );
  513. RtlCopyMemory(pLmSessionKey, pNtUserSessionKey, sizeof(LM_SESSION_KEY));
  514. }
  515. NTSTATUS
  516. GetLm20LogonInfoNtlmv2(
  517. IN UNICODE_STRING* pUserName,
  518. IN UNICODE_STRING* pDomainName,
  519. IN UNICODE_STRING* pPassword,
  520. IN UNICODE_STRING* pWorkstation,
  521. IN OPTIONAL UNICODE_STRING* pTargetName,
  522. IN OPTIONAL STRING* pTargetInfo,
  523. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  524. OUT ULONG* pcbLogonInfo,
  525. OUT PMSV1_0_LM20_LOGON *ppLognInfo
  526. )
  527. {
  528. TNtStatus Status = STATUS_SUCCESS;
  529. STRING TargetInfo = {0};
  530. PMSV1_0_LM20_LOGON pMsvNetAuthInfo = NULL;
  531. ULONG cbMsvNetAuthInfo = 0;
  532. NT_OWF_PASSWORD NtOwfPassword;
  533. USER_SESSION_KEY NtUserSessionKey;
  534. LM_SESSION_KEY LmSessionKey;
  535. MSV1_0_LM3_RESPONSE Lmv2Response;
  536. MSV1_0_NTLM3_RESPONSE* pNtlmv2Reponse = NULL;
  537. ULONG cbNtlmv2Response = 0;
  538. DebugPrintf(SSPI_LOG, "GetLm20LogonInfoNtlmv2 UserName %wZ, DomainName %wZ, Password %wZ, Workstation %wZ\n",
  539. pUserName, pDomainName, pPassword, pWorkstation);
  540. *ppLognInfo = NULL;
  541. *pcbLogonInfo = 0;
  542. RtlCalculateNtOwfPassword(
  543. pPassword,
  544. &NtOwfPassword
  545. );
  546. if (pTargetInfo)
  547. {
  548. TargetInfo = *pTargetInfo;
  549. }
  550. else if (pTargetName)
  551. {
  552. Status DBGCHK = CreateTargetInfo(pTargetName, &TargetInfo);
  553. }
  554. if (NT_SUCCESS(Status))
  555. {
  556. cbNtlmv2Response = ROUND_UP_COUNT(sizeof(MSV1_0_NTLM3_RESPONSE), sizeof(ULONG_PTR)) + TargetInfo.Length;
  557. pNtlmv2Reponse = (MSV1_0_NTLM3_RESPONSE*) new CHAR[cbNtlmv2Response];
  558. Status DBGCHK = pNtlmv2Reponse ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  559. }
  560. if (NT_SUCCESS(Status))
  561. {
  562. Lm20GetNtlmv2Response(
  563. &NtOwfPassword,
  564. pUserName,
  565. pDomainName,
  566. &TargetInfo,
  567. ChallengeToClient,
  568. pNtlmv2Reponse,
  569. &Lmv2Response,
  570. &NtUserSessionKey,
  571. &LmSessionKey
  572. );
  573. cbMsvNetAuthInfo = ROUND_UP_COUNT(sizeof(MSV1_0_LM20_LOGON), sizeof(ULONG_PTR))
  574. + pUserName->Length
  575. + pDomainName->Length
  576. + pWorkstation->Length
  577. + cbNtlmv2Response
  578. + sizeof(Lmv2Response);
  579. pMsvNetAuthInfo = (PMSV1_0_LM20_LOGON) new CHAR[cbMsvNetAuthInfo];
  580. Status DBGCHK = pMsvNetAuthInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  581. }
  582. if (NT_SUCCESS(Status))
  583. {
  584. //
  585. // Start packing in the string
  586. //
  587. RtlZeroMemory(pMsvNetAuthInfo, cbMsvNetAuthInfo);
  588. pMsvNetAuthInfo->MessageType = MsV1_0NetworkLogon;
  589. //
  590. // Copy the user name into the authentication buffer
  591. //
  592. pMsvNetAuthInfo->UserName.Length = pUserName->Length;
  593. pMsvNetAuthInfo->UserName.MaximumLength = pMsvNetAuthInfo->UserName.Length;
  594. pMsvNetAuthInfo->UserName.Buffer = (PWSTR) (pMsvNetAuthInfo + 1); // could be aligned here
  595. RtlCopyMemory(
  596. pMsvNetAuthInfo->UserName.Buffer,
  597. pUserName->Buffer,
  598. pUserName->Length
  599. );
  600. //
  601. // Copy the domain name into the authentication buffer
  602. //
  603. pMsvNetAuthInfo->LogonDomainName.Length = pDomainName->Length;
  604. pMsvNetAuthInfo->LogonDomainName.MaximumLength = pDomainName->Length ;
  605. pMsvNetAuthInfo->LogonDomainName.Buffer = (PWSTR) ((PBYTE)(pMsvNetAuthInfo->UserName.Buffer)
  606. + pMsvNetAuthInfo->UserName.MaximumLength);
  607. RtlCopyMemory(
  608. pMsvNetAuthInfo->LogonDomainName.Buffer,
  609. pDomainName->Buffer,
  610. pDomainName->Length
  611. );
  612. //
  613. // Copy the workstation name into the buffer
  614. //
  615. pMsvNetAuthInfo->Workstation.Length = pWorkstation->Length;
  616. pMsvNetAuthInfo->Workstation.MaximumLength = pMsvNetAuthInfo->Workstation.Length;
  617. pMsvNetAuthInfo->Workstation.Buffer = (PWSTR) ((PBYTE) (pMsvNetAuthInfo->LogonDomainName.Buffer)
  618. + pMsvNetAuthInfo->LogonDomainName.MaximumLength );
  619. RtlCopyMemory(
  620. pMsvNetAuthInfo->Workstation.Buffer,
  621. pWorkstation->Buffer,
  622. pWorkstation->Length
  623. );
  624. RtlCopyMemory(pMsvNetAuthInfo->ChallengeToClient,
  625. ChallengeToClient,
  626. MSV1_0_CHALLENGE_LENGTH);
  627. //
  628. // Set up space for response
  629. //
  630. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer =
  631. ((PCHAR) (pMsvNetAuthInfo->Workstation.Buffer)
  632. + pMsvNetAuthInfo->Workstation.MaximumLength);
  633. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Length = (USHORT) cbNtlmv2Response;
  634. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.MaximumLength = (USHORT) cbNtlmv2Response;
  635. RtlCopyMemory(
  636. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer,
  637. pNtlmv2Reponse,
  638. cbNtlmv2Response
  639. );
  640. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Buffer =
  641. ((PCHAR) (pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer)
  642. + pMsvNetAuthInfo->CaseSensitiveChallengeResponse.MaximumLength );
  643. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Length = sizeof(Lmv2Response);
  644. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.MaximumLength = sizeof(Lmv2Response);
  645. RtlCopyMemory(
  646. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Buffer,
  647. &Lmv2Response,
  648. sizeof(Lmv2Response)
  649. );
  650. *ppLognInfo = pMsvNetAuthInfo;
  651. pMsvNetAuthInfo = NULL;
  652. *pcbLogonInfo = cbMsvNetAuthInfo;
  653. }
  654. if (pMsvNetAuthInfo)
  655. {
  656. delete [] pMsvNetAuthInfo;
  657. }
  658. if (pNtlmv2Reponse)
  659. {
  660. delete [] pNtlmv2Reponse;
  661. }
  662. return Status;
  663. }
  664. NTSTATUS
  665. GetMsvInteractiveLogonInfo(
  666. IN UNICODE_STRING* pUserName,
  667. IN UNICODE_STRING* pLogonDomainName,
  668. IN UNICODE_STRING* pPassword,
  669. OUT ULONG* pcbLogonInfo,
  670. OUT MSV1_0_INTERACTIVE_LOGON** ppLogonInfo
  671. )
  672. {
  673. TNtStatus Status;
  674. ULONG cbLogonInfo = 0;
  675. UCHAR* pWhere = NULL;
  676. MSV1_0_INTERACTIVE_LOGON* pLogonInfo = NULL;
  677. DebugPrintf(SSPI_LOG, "GetMsvInteractiveLogonInfo UserName %wZ, LogonDomainName %wZ, Password %wZ\n",
  678. pUserName, pLogonDomainName, pPassword);
  679. cbLogonInfo = ROUND_UP_COUNT(sizeof(MSV1_0_INTERACTIVE_LOGON), sizeof(ULONG_PTR))
  680. + pUserName->Length
  681. + pLogonDomainName->Length
  682. + pPassword->Length;
  683. pLogonInfo = (MSV1_0_INTERACTIVE_LOGON*) new CHAR[cbLogonInfo];
  684. Status DBGCHK = pLogonInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  685. if (NT_SUCCESS(Status))
  686. {
  687. pLogonInfo->MessageType = MsV1_0InteractiveLogon;
  688. pWhere = (PUCHAR) (pLogonInfo + 1);
  689. pLogonInfo->UserName.Buffer = (PWSTR) pWhere;
  690. pLogonInfo->UserName.MaximumLength = pUserName->Length;
  691. pLogonInfo->UserName.Length = pUserName->Length;
  692. RtlCopyMemory(pLogonInfo->UserName.Buffer,
  693. pUserName->Buffer,
  694. pUserName->Length);
  695. pWhere += pLogonInfo->UserName.Length;
  696. pLogonInfo->LogonDomainName.Buffer = (PWSTR) pWhere;
  697. pLogonInfo->LogonDomainName.MaximumLength = pLogonDomainName->Length;
  698. pLogonInfo->LogonDomainName.Length = pLogonDomainName->Length;
  699. RtlCopyMemory(pLogonInfo->LogonDomainName.Buffer,
  700. pLogonDomainName->Buffer,
  701. pLogonDomainName->Length);
  702. pWhere += pLogonInfo->LogonDomainName.Length;
  703. pLogonInfo->Password.Buffer = (PWSTR) pWhere;
  704. pLogonInfo->Password.MaximumLength = pPassword->Length;
  705. pLogonInfo->Password.Length = pPassword->Length;
  706. RtlCopyMemory(pLogonInfo->Password.Buffer,
  707. pPassword->Buffer,
  708. pPassword->Length);
  709. pWhere += pLogonInfo->Password.Length;
  710. *ppLogonInfo = pLogonInfo;
  711. pLogonInfo = NULL;
  712. *pcbLogonInfo = cbLogonInfo;
  713. }
  714. if (pLogonInfo)
  715. {
  716. delete [] pLogonInfo;
  717. }
  718. return Status;
  719. }
  720. NTSTATUS
  721. GetKrbS4U2SelfLogonInfo(
  722. IN UNICODE_STRING* pClientUpn,
  723. IN OPTIONAL UNICODE_STRING* pClientRealm,
  724. IN ULONG Flags,
  725. OUT ULONG* pcbLogonInfo,
  726. OUT KERB_S4U_LOGON** ppLogonInfo
  727. )
  728. {
  729. TNtStatus Status;
  730. ULONG cbLogonInfo = 0;
  731. WCHAR* pWhere = NULL;
  732. KERB_S4U_LOGON* pLogonInfo = NULL;
  733. DebugPrintf(SSPI_LOG, "GetKrbS4U2SelfLogonInfo ClientUpn %wZ, ClientRealm %wZ, Flags %#x\n",
  734. pClientUpn, pClientRealm, Flags);
  735. cbLogonInfo = ROUND_UP_COUNT(sizeof(KERB_S4U_LOGON), sizeof(ULONG_PTR))
  736. + pClientUpn->Length + sizeof(WCHAR)
  737. + (pClientRealm ? pClientRealm->Length : 0) + sizeof(WCHAR);
  738. pLogonInfo = (KERB_S4U_LOGON*) new CHAR[cbLogonInfo];
  739. Status DBGCHK = pLogonInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  740. if (NT_SUCCESS(Status))
  741. {
  742. RtlZeroMemory(pLogonInfo, cbLogonInfo);
  743. pLogonInfo->MessageType = KerbS4ULogon;
  744. pWhere = (PWCHAR) (pLogonInfo + 1);
  745. PackUnicodeStringAsUnicodeStringZ(pClientUpn, &pWhere, &pLogonInfo->ClientUpn);
  746. if (pClientRealm)
  747. {
  748. PackUnicodeStringAsUnicodeStringZ(pClientRealm, &pWhere, &pLogonInfo->ClientRealm);
  749. }
  750. pLogonInfo->Flags = Flags;
  751. *ppLogonInfo = pLogonInfo;
  752. pLogonInfo = NULL;
  753. *pcbLogonInfo = cbLogonInfo;
  754. }
  755. if (pLogonInfo)
  756. {
  757. delete [] pLogonInfo;
  758. }
  759. return Status;
  760. }
  761. NTSTATUS
  762. GetKrbInteractiveLogonInfo(
  763. IN UNICODE_STRING* pUserName,
  764. IN UNICODE_STRING* pLogonDomainName,
  765. IN UNICODE_STRING* pPassword,
  766. OUT ULONG* pcbLogonInfo,
  767. OUT KERB_INTERACTIVE_LOGON** ppLogonInfo
  768. )
  769. {
  770. TNtStatus Status;
  771. ULONG cbLogonInfo = 0;
  772. UCHAR* pWhere = NULL;
  773. KERB_INTERACTIVE_LOGON* pLogonInfo = NULL;
  774. DebugPrintf(SSPI_LOG, "GetKrbInteractiveLogonInfo UserName %wZ, LogonDomainName %wZ, Password %wZ\n",
  775. pUserName, pLogonDomainName, pPassword);
  776. cbLogonInfo = ROUND_UP_COUNT(sizeof(KERB_INTERACTIVE_LOGON), sizeof(ULONG_PTR))
  777. + pUserName->Length
  778. + pLogonDomainName->Length
  779. + pPassword->Length;
  780. pLogonInfo = (KERB_INTERACTIVE_LOGON*) new CHAR[cbLogonInfo];
  781. Status DBGCHK = pLogonInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  782. if (NT_SUCCESS(Status))
  783. {
  784. pLogonInfo->MessageType = KerbInteractiveLogon;
  785. pWhere = (PUCHAR) (pLogonInfo + 1);
  786. pLogonInfo->UserName.Buffer = (PWSTR) pWhere;
  787. pLogonInfo->UserName.MaximumLength = pUserName->Length;
  788. pLogonInfo->UserName.Length = pUserName->Length;
  789. RtlCopyMemory(pLogonInfo->UserName.Buffer,
  790. pUserName->Buffer,
  791. pUserName->Length);
  792. pWhere += pLogonInfo->UserName.Length;
  793. pLogonInfo->LogonDomainName.Buffer = (PWSTR) pWhere;
  794. pLogonInfo->LogonDomainName.MaximumLength = pLogonDomainName->Length;
  795. pLogonInfo->LogonDomainName.Length = pLogonDomainName->Length;
  796. RtlCopyMemory(pLogonInfo->LogonDomainName.Buffer,
  797. pLogonDomainName->Buffer,
  798. pLogonDomainName->Length);
  799. pWhere += pLogonInfo->LogonDomainName.Length;
  800. pLogonInfo->Password.Buffer = (PWSTR) pWhere;
  801. pLogonInfo->Password.MaximumLength = pPassword->Length;
  802. pLogonInfo->Password.Length = pPassword->Length;
  803. RtlCopyMemory(pLogonInfo->Password.Buffer,
  804. pPassword->Buffer,
  805. pPassword->Length);
  806. pWhere += pLogonInfo->Password.Length;
  807. *ppLogonInfo = pLogonInfo;
  808. pLogonInfo = NULL;
  809. *pcbLogonInfo = cbLogonInfo;
  810. }
  811. if (pLogonInfo)
  812. {
  813. delete [] pLogonInfo;
  814. }
  815. return Status;
  816. }
  817. NTSTATUS
  818. KrbLsaLogonUser(
  819. IN HANDLE hLsa,
  820. IN ULONG PackageId,
  821. IN SECURITY_LOGON_TYPE LogonType,
  822. IN UNICODE_STRING* pUserName,
  823. IN UNICODE_STRING* pDomainName,
  824. IN UNICODE_STRING* pPassword,
  825. IN ULONG Flags,
  826. OUT HANDLE* phToken
  827. )
  828. {
  829. TNtStatus Status;
  830. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  831. PVOID pLogonInfo = NULL;
  832. ULONG cbLogonInfo = 0;
  833. LSA_STRING Name = {0};
  834. TOKEN_SOURCE SourceContext = {0};
  835. KERB_TICKET_PROFILE* pKerbTicketProfile = NULL;
  836. ULONG cbProfileSize = 0;
  837. LUID LogonId = {0};
  838. QUOTA_LIMITS Quotas = {0};
  839. DebugPrintf(SSPI_LOG, "KrbLsaLogonUser PackageId %#x, LogonType %#x, "
  840. "UserName %wZ, DomainName %wZ, Password %wZ\n",
  841. PackageId, LogonType, pUserName,
  842. pDomainName, pPassword);
  843. switch (LogonType)
  844. {
  845. case Network:
  846. Status DBGCHK = GetKrbS4U2SelfLogonInfo(
  847. pUserName,
  848. pDomainName,
  849. Flags,
  850. &cbLogonInfo,
  851. (KERB_S4U_LOGON**) &pLogonInfo
  852. );
  853. break;
  854. case Interactive:
  855. case CachedInteractive:
  856. case RemoteInteractive:
  857. case Unlock:
  858. default:
  859. Status DBGCHK = GetKrbInteractiveLogonInfo(
  860. pUserName,
  861. pDomainName,
  862. pPassword,
  863. &cbLogonInfo,
  864. (KERB_INTERACTIVE_LOGON**) &pLogonInfo
  865. );
  866. break;
  867. }
  868. if (NT_SUCCESS(Status))
  869. {
  870. SspiPrintHex(SSPI_LOG, TEXT("KrbLsaLogonUser LogonInfo"), cbLogonInfo, pLogonInfo);
  871. strncpy(
  872. SourceContext.SourceName,
  873. "ssptest",
  874. sizeof(SourceContext.SourceName)
  875. );
  876. NtAllocateLocallyUniqueId(&SourceContext.SourceIdentifier);
  877. //
  878. // Now call LsaLogonUser
  879. //
  880. RtlInitString(
  881. &Name,
  882. "ssptest"
  883. );
  884. Status DBGCHK = LsaLogonUser(
  885. hLsa,
  886. &Name,
  887. LogonType,
  888. PackageId,
  889. pLogonInfo,
  890. cbLogonInfo,
  891. NULL, // no token groups
  892. &SourceContext,
  893. (VOID**) &pKerbTicketProfile,
  894. &cbProfileSize,
  895. &LogonId,
  896. phToken,
  897. &Quotas,
  898. &SubStatus
  899. );
  900. }
  901. if (NT_SUCCESS(Status))
  902. {
  903. Status DBGCHK = SubStatus;
  904. }
  905. if (NT_SUCCESS(Status))
  906. {
  907. DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", LogonId.HighPart, LogonId.LowPart);
  908. DebugPrintf(SSPI_LOG, "TokenHandle %p\n", *phToken);
  909. DebugPrintProfileAndQuotas(SSPI_LOG, pKerbTicketProfile, &Quotas);
  910. }
  911. if (pKerbTicketProfile)
  912. {
  913. LsaFreeReturnBuffer(pKerbTicketProfile);
  914. }
  915. return Status;
  916. }
  917. NTSTATUS
  918. MsvLsaLogonUser(
  919. IN HANDLE hLsa,
  920. IN ULONG PackageId,
  921. IN SECURITY_LOGON_TYPE LogonType,
  922. IN UNICODE_STRING* pUserName,
  923. IN UNICODE_STRING* pDomainName,
  924. IN UNICODE_STRING* pPassword,
  925. IN UNICODE_STRING* pWorkstation,
  926. IN ELogonTypeSubType SubType,
  927. OUT HANDLE* phToken
  928. )
  929. {
  930. TNtStatus Status;
  931. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  932. PVOID pLogonInfo = NULL;
  933. ULONG cbLogonInfo = 0;
  934. LSA_STRING Name = {0};
  935. TOKEN_SOURCE SourceContext = {0};
  936. VOID* pProfile = NULL;
  937. ULONG cbProfileSize = 0;
  938. LUID LogonId = {0};
  939. QUOTA_LIMITS Quotas = {0};
  940. UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH] = {0};
  941. DebugPrintf(SSPI_LOG, "MsvLsaLogonUser PackageId %#x, LogonType %#x, SubType %#x, "
  942. "UserName %wZ, DomainName %wZ, Password %wZ, Workstation %wZ\n",
  943. PackageId, LogonType, SubType, pUserName,
  944. pDomainName, pPassword, pWorkstation);
  945. RtlGenRandom(ChallengeToClient, sizeof(ChallengeToClient));
  946. switch (LogonType)
  947. {
  948. case Network:
  949. switch (SubType)
  950. {
  951. case kNetworkLogonNtlmv1:
  952. Status DBGCHK = GetLm20LogonInfoNtlmv1(
  953. pUserName,
  954. pDomainName,
  955. pPassword,
  956. pWorkstation,
  957. ChallengeToClient,
  958. &cbLogonInfo,
  959. (MSV1_0_LM20_LOGON **) &pLogonInfo
  960. );
  961. break;
  962. case kNetworkLogonNtlmv2:
  963. Status DBGCHK = GetLm20LogonInfoNtlmv2(
  964. pUserName,
  965. pDomainName,
  966. pPassword,
  967. pWorkstation,
  968. NULL, // no target name
  969. NULL, // no target info
  970. ChallengeToClient,
  971. &cbLogonInfo,
  972. (MSV1_0_LM20_LOGON **) &pLogonInfo
  973. );
  974. break;
  975. case kSubAuthLogon:
  976. default:
  977. Status DBGCHK = STATUS_NOT_SUPPORTED;
  978. break;
  979. }
  980. break;
  981. case Interactive:
  982. case CachedInteractive:
  983. case RemoteInteractive:
  984. case Unlock:
  985. default:
  986. Status DBGCHK = GetMsvInteractiveLogonInfo(
  987. pUserName,
  988. pDomainName,
  989. pPassword,
  990. &cbLogonInfo,
  991. (MSV1_0_INTERACTIVE_LOGON **) &pLogonInfo
  992. );
  993. break;
  994. }
  995. if (NT_SUCCESS(Status))
  996. {
  997. strncpy(
  998. SourceContext.SourceName,
  999. "ssptest",
  1000. sizeof(SourceContext.SourceName)
  1001. );
  1002. NtAllocateLocallyUniqueId(&SourceContext.SourceIdentifier);
  1003. //
  1004. // Now call LsaLogonUser
  1005. //
  1006. RtlInitString(
  1007. &Name,
  1008. "ssptest"
  1009. );
  1010. Status DBGCHK = LsaLogonUser(
  1011. hLsa,
  1012. &Name,
  1013. LogonType,
  1014. PackageId,
  1015. pLogonInfo,
  1016. cbLogonInfo,
  1017. NULL, // no token groups
  1018. &SourceContext,
  1019. (VOID**) &pProfile,
  1020. &cbProfileSize,
  1021. &LogonId,
  1022. phToken,
  1023. &Quotas,
  1024. &SubStatus
  1025. );
  1026. }
  1027. if (NT_SUCCESS(Status))
  1028. {
  1029. Status DBGCHK = SubStatus;
  1030. }
  1031. if (NT_SUCCESS(Status))
  1032. {
  1033. DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", LogonId.HighPart, LogonId.LowPart);
  1034. DebugPrintf(SSPI_LOG, "TokenHandle %p\n", *phToken);
  1035. DebugPrintProfileAndQuotas(SSPI_LOG, pProfile, &Quotas);
  1036. }
  1037. if (pProfile)
  1038. {
  1039. LsaFreeReturnBuffer(pProfile);
  1040. }
  1041. return Status;
  1042. }