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.

495 lines
16 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. GetSubAuthLogonInfo(
  18. IN ULONG SubAuthId,
  19. IN BOOLEAN bUseNewSubAuthStyle,
  20. IN UNICODE_STRING* pUserName,
  21. IN UNICODE_STRING* pDomainName,
  22. IN UNICODE_STRING* pPassword,
  23. IN UNICODE_STRING* pWorkstation,
  24. OUT ULONG* pcbLogonInfo,
  25. OUT VOID** ppLognInfo
  26. )
  27. {
  28. TNtStatus Status;
  29. PMSV1_0_LM20_LOGON pMsvNetAuthInfo = NULL;
  30. ULONG cbMsvNetAuthInfo;
  31. NT_OWF_PASSWORD PasswordHash;
  32. OEM_STRING LmPassword;
  33. UCHAR LmPasswordBuf[ LM20_PWLEN + 1 ];
  34. LM_OWF_PASSWORD LmPasswordHash;
  35. NT_CHALLENGE NtChallenge;
  36. DebugPrintf(SSPI_LOG, "GetSubAuthLogonInfo UserName %wZ, DomainName %wZ, Password %wZ, Workstation %wZ\n",
  37. pUserName, pDomainName, pPassword, pWorkstation);
  38. *ppLognInfo = NULL;
  39. *pcbLogonInfo = 0;
  40. cbMsvNetAuthInfo = ROUND_UP_COUNT(sizeof(MSV1_0_SUBAUTH_LOGON), sizeof(ULONG_PTR))
  41. + pUserName->Length
  42. + pDomainName->Length
  43. + pWorkstation->Length
  44. + NT_RESPONSE_LENGTH
  45. + LM_RESPONSE_LENGTH;
  46. pMsvNetAuthInfo = (PMSV1_0_LM20_LOGON) new CHAR[cbMsvNetAuthInfo];
  47. Status DBGCHK = pMsvNetAuthInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  48. if (NT_SUCCESS(Status))
  49. {
  50. //
  51. // Start packing in the string
  52. //
  53. RtlZeroMemory(pMsvNetAuthInfo, cbMsvNetAuthInfo);
  54. pMsvNetAuthInfo->MessageType = bUseNewSubAuthStyle ? MsV1_0SubAuthLogon : MsV1_0NetworkLogon; // if set MsV1_0Lm20Logon, ignore ParameterControl
  55. //
  56. // Copy the user name into the authentication buffer
  57. //
  58. pMsvNetAuthInfo->UserName.Length = pUserName->Length;
  59. pMsvNetAuthInfo->UserName.MaximumLength = pMsvNetAuthInfo->UserName.Length;
  60. pMsvNetAuthInfo->UserName.Buffer = (PWSTR)( ((CHAR*)pMsvNetAuthInfo) + sizeof(MSV1_0_SUBAUTH_LOGON) ); // could be aligned here
  61. RtlCopyMemory(
  62. pMsvNetAuthInfo->UserName.Buffer,
  63. pUserName->Buffer,
  64. pUserName->Length
  65. );
  66. //
  67. // Copy the domain name into the authentication buffer
  68. //
  69. pMsvNetAuthInfo->LogonDomainName.Length = pDomainName->Length;
  70. pMsvNetAuthInfo->LogonDomainName.MaximumLength = pDomainName->Length ;
  71. pMsvNetAuthInfo->LogonDomainName.Buffer = (PWSTR) ((PBYTE)(pMsvNetAuthInfo->UserName.Buffer)
  72. + pMsvNetAuthInfo->UserName.MaximumLength);
  73. RtlCopyMemory(
  74. pMsvNetAuthInfo->LogonDomainName.Buffer,
  75. pDomainName->Buffer,
  76. pDomainName->Length
  77. );
  78. //
  79. // Copy the workstation name into the buffer
  80. //
  81. pMsvNetAuthInfo->Workstation.Length = pWorkstation->Length;
  82. pMsvNetAuthInfo->Workstation.MaximumLength = pMsvNetAuthInfo->Workstation.Length;
  83. pMsvNetAuthInfo->Workstation.Buffer = (PWSTR) ((PBYTE) (pMsvNetAuthInfo->LogonDomainName.Buffer)
  84. + pMsvNetAuthInfo->LogonDomainName.MaximumLength);
  85. RtlCopyMemory(
  86. pMsvNetAuthInfo->Workstation.Buffer,
  87. pWorkstation->Buffer,
  88. pWorkstation->Length
  89. );
  90. //
  91. // Now, generate the bits for the challenge
  92. //
  93. RtlGenRandom(&NtChallenge, sizeof(NtChallenge));
  94. RtlCopyMemory(pMsvNetAuthInfo->ChallengeToClient,
  95. &NtChallenge,
  96. MSV1_0_CHALLENGE_LENGTH);
  97. //
  98. // Set up space for response
  99. //
  100. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer =
  101. (((PCHAR) pMsvNetAuthInfo->Workstation.Buffer)
  102. + pMsvNetAuthInfo->Workstation.MaximumLength);
  103. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Length = NT_RESPONSE_LENGTH;
  104. pMsvNetAuthInfo->CaseSensitiveChallengeResponse.MaximumLength = NT_RESPONSE_LENGTH;
  105. RtlCalculateNtOwfPassword(
  106. pPassword,
  107. &PasswordHash
  108. );
  109. RtlCalculateNtResponse(
  110. &NtChallenge,
  111. &PasswordHash,
  112. (PNT_RESPONSE) pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer
  113. );
  114. //
  115. // Now do the painful LM compatible hash, so anyone who is maintaining
  116. // their account from a WfW machine will still have a password.
  117. //
  118. LmPassword.Buffer = (PCHAR) LmPasswordBuf;
  119. LmPassword.Length = LmPassword.MaximumLength = LM20_PWLEN + 1;
  120. Status DBGCHK = RtlUpcaseUnicodeStringToOemString(
  121. &LmPassword,
  122. pPassword,
  123. FALSE
  124. );
  125. }
  126. if (NT_SUCCESS(Status))
  127. {
  128. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Buffer =
  129. ((PCHAR) (pMsvNetAuthInfo->CaseSensitiveChallengeResponse.Buffer)
  130. + pMsvNetAuthInfo->CaseSensitiveChallengeResponse.MaximumLength);
  131. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Length = LM_RESPONSE_LENGTH;
  132. pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.MaximumLength = LM_RESPONSE_LENGTH;
  133. RtlCalculateLmOwfPassword(
  134. LmPassword.Buffer,
  135. &LmPasswordHash
  136. );
  137. RtlZeroMemory(LmPassword.Buffer, LmPassword.Length);
  138. RtlCalculateLmResponse(
  139. &NtChallenge,
  140. &LmPasswordHash,
  141. (PLM_RESPONSE) pMsvNetAuthInfo->CaseInsensitiveChallengeResponse.Buffer
  142. );
  143. if (bUseNewSubAuthStyle)
  144. {
  145. ((MSV1_0_SUBAUTH_LOGON*) pMsvNetAuthInfo)->SubAuthPackageId = SubAuthId;
  146. }
  147. else
  148. {
  149. pMsvNetAuthInfo->ParameterControl |= SubAuthId << MSV1_0_SUBAUTHENTICATION_DLL_SHIFT;
  150. }
  151. *ppLognInfo = pMsvNetAuthInfo;
  152. pMsvNetAuthInfo = NULL;
  153. *pcbLogonInfo = cbMsvNetAuthInfo;
  154. }
  155. if (pMsvNetAuthInfo)
  156. {
  157. delete [] pMsvNetAuthInfo;
  158. }
  159. return Status;
  160. }
  161. NTSTATUS
  162. MsvSubAuthLsaLogon(
  163. IN HANDLE hLsa,
  164. IN ULONG PackageId,
  165. IN SECURITY_LOGON_TYPE LogonType,
  166. IN ULONG SubAuthId,
  167. IN BOOLEAN bUseNewSubAuthStyle,
  168. IN UNICODE_STRING* pUserName,
  169. IN UNICODE_STRING* pDomainName,
  170. IN UNICODE_STRING* pPassword,
  171. IN UNICODE_STRING* pWorkstation,
  172. OUT HANDLE* phToken
  173. )
  174. {
  175. TNtStatus Status;
  176. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  177. VOID* pLogonInfo = NULL;
  178. ULONG cbLogonInfoSize = 0;
  179. LSA_STRING Name = {0};
  180. TOKEN_SOURCE SourceContext = {0};
  181. VOID* pProfile = NULL;
  182. ULONG cbProfileSize = 0;
  183. LUID LogonId = {0};
  184. QUOTA_LIMITS Quotas = {0};
  185. DebugPrintf(SSPI_LOG, "MsvSubAuthLsaLogon PackageId %#x, LogonType %#x, SubAuthId %#x, "
  186. "UserName %wZ, DomainName %wZ, Password %wZ, Workstation %wZ\n",
  187. PackageId, LogonType, SubAuthId, pUserName,
  188. pDomainName, pPassword, pWorkstation);
  189. strncpy(
  190. SourceContext.SourceName,
  191. "ssptest",
  192. sizeof(SourceContext.SourceName)
  193. );
  194. NtAllocateLocallyUniqueId(&SourceContext.SourceIdentifier);
  195. //
  196. // Now call LsaLogonUser
  197. //
  198. RtlInitString(
  199. &Name,
  200. "ssptest"
  201. );
  202. Status DBGCHK = GetSubAuthLogonInfo(
  203. SubAuthId,
  204. bUseNewSubAuthStyle,
  205. pUserName,
  206. pDomainName,
  207. pPassword,
  208. pWorkstation,
  209. &cbLogonInfoSize,
  210. &pLogonInfo
  211. );
  212. if (NT_SUCCESS(Status))
  213. {
  214. SspiPrintHex(SSPI_LOG, TEXT("SubAuthInfo"), cbLogonInfoSize, pLogonInfo);
  215. Status DBGCHK = LsaLogonUser(
  216. hLsa,
  217. &Name,
  218. LogonType,
  219. PackageId,
  220. pLogonInfo,
  221. cbLogonInfoSize,
  222. NULL, // no token groups
  223. &SourceContext,
  224. (VOID**) &pProfile,
  225. &cbProfileSize,
  226. &LogonId,
  227. phToken,
  228. &Quotas,
  229. &SubStatus
  230. );
  231. }
  232. if (NT_SUCCESS(Status))
  233. {
  234. Status DBGCHK = SubStatus;
  235. }
  236. if (NT_SUCCESS(Status))
  237. {
  238. DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", LogonId.HighPart, LogonId.LowPart);
  239. DebugPrintf(SSPI_LOG, "Token handle %p\n", *phToken);
  240. DebugPrintf(SSPI_LOG, "Quotas PagedPoolLimit %p, NonPagedPoolLimit %p, "
  241. "MinimumWorkingSetSize %p, MaximumWorkingSetSize %p, PagedPoolLimit %p\n",
  242. Quotas.PagedPoolLimit, Quotas.NonPagedPoolLimit,
  243. Quotas.MinimumWorkingSetSize, Quotas.MaximumWorkingSetSize,
  244. Quotas.PagedPoolLimit);
  245. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "TimeLimit", &Quotas.TimeLimit);
  246. if (MsV1_0InteractiveProfile == *((ULONG*) pProfile))
  247. {
  248. MSV1_0_INTERACTIVE_PROFILE* pMsvInteractiveProfile = (MSV1_0_INTERACTIVE_PROFILE*) pProfile;
  249. DebugPrintf(SSPI_LOG, "interactive logon profile: "
  250. "LogCount %#x, BaddPasswordCount %#x, LogonScript %wZ, "
  251. "HomeDirectory %wZ, FullName %wZ, ProfilePath %wZ, "
  252. "HomeDriectoryDrive %wZ, LogonServer %wZ, UserFlags %#x\n",
  253. pMsvInteractiveProfile->LogonCount,
  254. pMsvInteractiveProfile->BadPasswordCount,
  255. &pMsvInteractiveProfile->LogonScript,
  256. &pMsvInteractiveProfile->HomeDirectory,
  257. &pMsvInteractiveProfile->FullName,
  258. &pMsvInteractiveProfile->ProfilePath,
  259. &pMsvInteractiveProfile->HomeDirectoryDrive,
  260. &pMsvInteractiveProfile->LogonServer,
  261. pMsvInteractiveProfile->UserFlags);
  262. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "LogonTime ", &pMsvInteractiveProfile->LogonTime);
  263. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "KickOffTime ", &pMsvInteractiveProfile->KickOffTime );
  264. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "PasswordLastSet ", &pMsvInteractiveProfile->PasswordLastSet );
  265. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "PasswordCanChange ", &pMsvInteractiveProfile->PasswordCanChange );
  266. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "PasswordMustChange ", &pMsvInteractiveProfile->PasswordMustChange );
  267. }
  268. else if (MsV1_0Lm20LogonProfile == *((ULONG*) pProfile))
  269. {
  270. MSV1_0_LM20_LOGON_PROFILE* pMsvLm20LogonProfile = (MSV1_0_LM20_LOGON_PROFILE*) pProfile;
  271. DebugPrintf(SSPI_LOG, "Lm20 logon profile: "
  272. "UserFlags %#x, LogonDomainName %wZ, LogonServer %wZ, UserParameters %#x\n",
  273. pMsvLm20LogonProfile->UserFlags,
  274. &pMsvLm20LogonProfile->LogonDomainName,
  275. &pMsvLm20LogonProfile->LogonServer,
  276. pMsvLm20LogonProfile->UserParameters);
  277. DebugPrintHex(SSPI_LOG, "UserSessionKey:", MSV1_0_USER_SESSION_KEY_LENGTH, pMsvLm20LogonProfile->UserSessionKey);
  278. DebugPrintHex(SSPI_LOG, "LanmanSessionKey:", MSV1_0_LANMAN_SESSION_KEY_LENGTH, pMsvLm20LogonProfile->LanmanSessionKey);
  279. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "KickOffTime", &pMsvLm20LogonProfile->KickOffTime);
  280. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "LogoffTime", &pMsvLm20LogonProfile->LogoffTime);
  281. }
  282. else
  283. {
  284. DebugPrintf(SSPI_ERROR, "Unsupported profile type %#x\n", *((ULONG*) pProfile));
  285. }
  286. }
  287. if (pProfile)
  288. {
  289. LsaFreeReturnBuffer(pProfile);
  290. }
  291. return Status;
  292. }
  293. NTSTATUS
  294. MsvSubAuthLogon(
  295. IN HANDLE hLsa,
  296. IN ULONG PackageId,
  297. IN ULONG SubAuthId,
  298. IN UNICODE_STRING* pUserName,
  299. IN UNICODE_STRING* pDomainName,
  300. IN UNICODE_STRING* pPassword,
  301. IN UNICODE_STRING* pWorkstation
  302. )
  303. {
  304. TNtStatus Status;
  305. WCHAR LogonInfo[MAX_PATH] = {0};
  306. PMSV1_0_PASSTHROUGH_REQUEST pPassthroughRequest = NULL;
  307. ULONG cbRequest = 0;
  308. ULONG cbResponse = 0;
  309. PMSV1_0_PASSTHROUGH_RESPONSE pPassthroughResponse = NULL;
  310. MSV1_0_SUBAUTH_REQUEST* pSubAuthRequest = NULL;
  311. UNICODE_STRING MsvPackageName = {0};
  312. UCHAR* pWhere = NULL;
  313. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  314. SspiPrint(SSPI_LOG, TEXT("MsvSubAuthLsaLogon PackageId %#x, SubAuthId %#x(%d), ")
  315. TEXT("UserName %wZ, DomainName %wZ, Password %wZ, Workstation %wZ\n"),
  316. PackageId, SubAuthId, SubAuthId, pUserName, pDomainName, pPassword, pWorkstation);
  317. _snwprintf(LogonInfo, COUNTOF(LogonInfo) - 1, L"%wZ%wZ%wZ%wZ",
  318. pUserName, pDomainName, pPassword, pWorkstation);
  319. RtlInitUnicodeString(&MsvPackageName, L"NTLM");
  320. cbRequest = sizeof(MSV1_0_PASSTHROUGH_REQUEST)
  321. + ROUND_UP_COUNT(pDomainName->Length + sizeof(WCHAR), ALIGN_LPTSTR)
  322. + ROUND_UP_COUNT(MsvPackageName.Length + sizeof(WCHAR), ALIGN_LPTSTR)
  323. + ROUND_UP_COUNT(sizeof(MSV1_0_SUBAUTH_REQUEST), ALIGN_LPTSTR)
  324. + ROUND_UP_COUNT(wcslen(LogonInfo) * sizeof(WCHAR) + sizeof(WCHAR), ALIGN_LPTSTR);
  325. pPassthroughRequest = (PMSV1_0_PASSTHROUGH_REQUEST) new CHAR[cbRequest];
  326. Status DBGCHK = pPassthroughRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  327. if (NT_SUCCESS(Status))
  328. {
  329. RtlZeroMemory(pPassthroughRequest, cbRequest);
  330. pWhere = (PUCHAR) (pPassthroughRequest + 1);
  331. pPassthroughRequest->MessageType = MsV1_0GenericPassthrough;
  332. pPassthroughRequest->DomainName = *pDomainName;
  333. pPassthroughRequest->DomainName.Buffer = (PWSTR) pWhere;
  334. RtlCopyMemory(
  335. pWhere,
  336. pDomainName->Buffer,
  337. pDomainName->Length
  338. );
  339. pWhere += ROUND_UP_COUNT(pDomainName->Length + sizeof(WCHAR), ALIGN_LPTSTR);
  340. pPassthroughRequest->PackageName = MsvPackageName;
  341. pPassthroughRequest->PackageName.Buffer = (PWSTR) pWhere;
  342. RtlCopyMemory(
  343. pWhere,
  344. MsvPackageName.Buffer,
  345. MsvPackageName.Length
  346. );
  347. pWhere += ROUND_UP_COUNT(MsvPackageName.Length + sizeof(WCHAR), ALIGN_LPTSTR);
  348. pPassthroughRequest->LogonData = pWhere;
  349. pPassthroughRequest->DataLength = ROUND_UP_COUNT(sizeof(MSV1_0_SUBAUTH_REQUEST), ALIGN_LPTSTR)
  350. + ROUND_UP_COUNT(wcslen(LogonInfo) * sizeof(WCHAR), ALIGN_LPTSTR);
  351. pSubAuthRequest = (MSV1_0_SUBAUTH_REQUEST*) pPassthroughRequest->LogonData;
  352. pSubAuthRequest->MessageType = MsV1_0SubAuth;
  353. pWhere = (UCHAR*) (pSubAuthRequest + 1);
  354. pSubAuthRequest->SubAuthPackageId = SubAuthId;
  355. pSubAuthRequest->SubAuthInfoLength = wcslen(LogonInfo) * sizeof(WCHAR);
  356. pSubAuthRequest->SubAuthSubmitBuffer = pWhere;
  357. RtlCopyMemory(
  358. pSubAuthRequest->SubAuthSubmitBuffer,
  359. LogonInfo,
  360. pSubAuthRequest->SubAuthInfoLength
  361. );
  362. pSubAuthRequest->SubAuthSubmitBuffer = (UCHAR*) (pWhere - (UCHAR*) pSubAuthRequest);
  363. SspiPrintHex(SSPI_LOG, TEXT("PassthroughRequest"), cbRequest, pPassthroughRequest);
  364. Status DBGCHK = LsaCallAuthenticationPackage(
  365. hLsa,
  366. PackageId,
  367. pPassthroughRequest,
  368. cbRequest,
  369. (PVOID *) &pPassthroughResponse,
  370. &cbResponse,
  371. &SubStatus
  372. );
  373. }
  374. if (NT_SUCCESS(Status))
  375. {
  376. Status DBGCHK = SubStatus;
  377. }
  378. if (NT_SUCCESS(Status))
  379. {
  380. Status DBGCHK = SubStatus;
  381. }
  382. if (NT_SUCCESS(Status))
  383. {
  384. SspiPrintHex(SSPI_LOG, TEXT("ValidationData"), pPassthroughResponse->DataLength, pPassthroughResponse->ValidationData);
  385. }
  386. if (pPassthroughRequest)
  387. {
  388. delete [] pPassthroughRequest;
  389. }
  390. if (pPassthroughResponse)
  391. {
  392. LsaFreeReturnBuffer(pPassthroughResponse);
  393. }
  394. return Status;
  395. }