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.

505 lines
14 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. msvlogon.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 "msvlogon.hxx"
  16. VOID
  17. Usage(
  18. IN PCSTR pszApp
  19. )
  20. {
  21. DebugPrintf(SSPI_ERROR, "\n\nUsage: %s [-p<ParameterControl>] -s<server> -S<server domain> "
  22. "-c<client name> -C<client realm> -k<password> -h<LogonId.highpart> -l<LognId.LowPart> "
  23. "-H<challeng HighPart> -L<challenge LowPart> -w<Workstation> -a<application>\n\n",
  24. pszApp);
  25. exit(-1);
  26. }
  27. NTSTATUS
  28. GetMsvLogonInfo(
  29. IN HANDLE hLogonHandle,
  30. IN ULONG PackageId,
  31. IN LUID* pLogonId,
  32. IN ULONG ParameterControl,
  33. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  34. IN UNICODE_STRING* pUserName,
  35. IN UNICODE_STRING* pUserDomain,
  36. IN UNICODE_STRING* pPassword,
  37. IN UNICODE_STRING* pServerName,
  38. IN UNICODE_STRING* pServerDomain,
  39. IN UNICODE_STRING* pWorkstation,
  40. OUT ULONG* pcbLogonInfo,
  41. OUT MSV1_0_LM20_LOGON** ppLogonInfo
  42. )
  43. {
  44. TNtStatus Status;
  45. NTSTATUS AuthPackageStatus = STATUS_UNSUCCESSFUL;
  46. MSV1_0_GETCHALLENRESP_REQUEST* pRequest = NULL;
  47. MSV1_0_GETCHALLENRESP_RESPONSE* pResponse = NULL;
  48. ULONG cbResponse = 0;
  49. ULONG cbRequest = 0;
  50. WCHAR* pWhere = NULL;
  51. UNICODE_STRING NtlmServerName = {0};
  52. ULONG cbLogonInfo = 0;
  53. MSV1_0_LM20_LOGON* pLogonInfo = NULL;
  54. NtlmServerName.Length = (pServerDomain->Length ? pServerDomain->Length + sizeof(WCHAR) : 0)
  55. + pServerName->Length;
  56. NtlmServerName.MaximumLength = NtlmServerName.Length + sizeof(WCHAR);
  57. NtlmServerName.Buffer = (PWSTR) new CHAR[NtlmServerName.MaximumLength];
  58. Status DBGCHK = NtlmServerName.Buffer ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  59. if (NT_SUCCESS(Status))
  60. {
  61. RtlZeroMemory(NtlmServerName.Buffer, NtlmServerName.MaximumLength);
  62. if (pServerDomain->Length)
  63. {
  64. RtlCopyMemory(NtlmServerName.Buffer, pServerDomain->Buffer, pServerDomain->Length);
  65. RtlCopyMemory(NtlmServerName.Buffer + (pServerDomain->Length / sizeof(WCHAR)) + 1,
  66. pServerName->Buffer, pServerName->Length);
  67. }
  68. else
  69. {
  70. RtlCopyMemory(NtlmServerName.Buffer, pServerName->Buffer, pServerName->Length);
  71. }
  72. cbRequest = ROUND_UP_COUNT(sizeof(MSV1_0_GETCHALLENRESP_REQUEST), sizeof(ULONG_PTR))
  73. + pUserName->Length + sizeof(WCHAR)
  74. + pUserDomain->Length + sizeof(WCHAR)
  75. + NtlmServerName.Length + sizeof(WCHAR)
  76. + pPassword->Length + sizeof(WCHAR);
  77. pRequest = (MSV1_0_GETCHALLENRESP_REQUEST*) new CHAR[cbRequest];
  78. Status DBGCHK = pRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  79. }
  80. if (NT_SUCCESS(Status))
  81. {
  82. RtlZeroMemory(pRequest, cbRequest);
  83. pWhere = (WCHAR*) (pRequest + 1);
  84. pRequest->MessageType = MsV1_0Lm20GetChallengeResponse;
  85. pRequest->ParameterControl = ParameterControl;
  86. pRequest->LogonId = *pLogonId;
  87. RtlCopyMemory(pRequest->ChallengeToClient, ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
  88. PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, &pRequest->UserName);
  89. PackUnicodeStringAsUnicodeStringZ(pUserDomain, &pWhere, &pRequest->LogonDomainName);
  90. PackUnicodeStringAsUnicodeStringZ(&NtlmServerName, &pWhere, &pRequest->ServerName);
  91. PackUnicodeStringAsUnicodeStringZ(pPassword, &pWhere, &pRequest->Password);
  92. DebugPrintf(SSPI_LOG, "MsvLsaLogonUser PackageId %#x, "
  93. "UserName %wZ, DomainName %wZ, Password %wZ, "
  94. "ParameterControl %#x, LogonId %#x:%#x\n",
  95. PackageId, &pRequest->UserName, &pRequest->LogonDomainName, &pRequest->Password,
  96. pRequest->ParameterControl, pRequest->LogonId.HighPart,
  97. pRequest->LogonId.LowPart);
  98. DebugPrintHex(SSPI_LOG, "pRequest->ServerName:", pRequest->ServerName.MaximumLength, pRequest->ServerName.Buffer);
  99. DebugPrintHex(SSPI_LOG, "ChallengeToClient:", MSV1_0_CHALLENGE_LENGTH, pRequest->ChallengeToClient);
  100. Status DBGCHK = LsaCallAuthenticationPackage(
  101. hLogonHandle,
  102. PackageId,
  103. pRequest,
  104. cbRequest,
  105. (VOID**) &pResponse,
  106. &cbResponse,
  107. &AuthPackageStatus
  108. );
  109. }
  110. if (NT_SUCCESS(Status))
  111. {
  112. Status DBGCHK = AuthPackageStatus;
  113. }
  114. if (NT_SUCCESS(Status))
  115. {
  116. DebugPrintf(SSPI_LOG, "GetMsvLogonInfo response LogonDomain %wZ, UserName %wZ\n",
  117. pResponse->LogonDomainName, pResponse->UserName);
  118. DebugPrintHex(SSPI_LOG, "CaseSensitiveChallengeResponse:",
  119. pResponse->CaseSensitiveChallengeResponse.Length,
  120. pResponse->CaseSensitiveChallengeResponse.Buffer);
  121. DebugPrintHex(SSPI_LOG, "CaseInsensitiveChallengeResponse:",
  122. pResponse->CaseInsensitiveChallengeResponse.Length,
  123. pResponse->CaseInsensitiveChallengeResponse.Buffer);
  124. DebugPrintHex(SSPI_LOG, "UserSessionKey:", MSV1_0_USER_SESSION_KEY_LENGTH, pResponse->UserSessionKey);
  125. DebugPrintHex(SSPI_LOG, "LanmanSessionKey:", MSV1_0_USER_SESSION_KEY_LENGTH, pResponse->LanmanSessionKey);
  126. cbLogonInfo = ROUND_UP_COUNT(sizeof(MSV1_0_LM20_LOGON), sizeof(ULONG_PTR))
  127. + pUserDomain->Length + sizeof(WCHAR)
  128. + pWorkstation->Length + sizeof(WCHAR)
  129. + pUserName->Length + sizeof(WCHAR)
  130. + pResponse->CaseSensitiveChallengeResponse.Length + sizeof(WCHAR)
  131. + pResponse->CaseInsensitiveChallengeResponse.Length + sizeof(WCHAR);
  132. pLogonInfo = (MSV1_0_LM20_LOGON*) new CHAR[cbLogonInfo];
  133. Status DBGCHK = pLogonInfo ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  134. }
  135. if (NT_SUCCESS(Status))
  136. {
  137. RtlZeroMemory(pLogonInfo, cbLogonInfo);
  138. pLogonInfo->MessageType = MsV1_0NetworkLogon;
  139. pLogonInfo->ParameterControl = ParameterControl;
  140. RtlCopyMemory(pLogonInfo->ChallengeToClient, ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
  141. pWhere = (PWSTR) (pLogonInfo + 1);
  142. PackUnicodeStringAsUnicodeStringZ(pUserDomain, &pWhere, &pLogonInfo->LogonDomainName);
  143. PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, &pLogonInfo->UserName);
  144. PackUnicodeStringAsUnicodeStringZ(pWorkstation, &pWhere, &pLogonInfo->Workstation);
  145. PackString(
  146. &pResponse->CaseSensitiveChallengeResponse,
  147. (CHAR**) &pWhere,
  148. &pLogonInfo->CaseSensitiveChallengeResponse
  149. );
  150. PackString(
  151. &pResponse->CaseSensitiveChallengeResponse,
  152. (CHAR**) &pWhere,
  153. &pLogonInfo->CaseSensitiveChallengeResponse
  154. );
  155. DebugPrintf(SSPI_LOG, "pLogonInfo ParameterControl %#x, LogonDomain %wZ, UserName %wZ, Workstation %wZ\n",
  156. pLogonInfo->ParameterControl,
  157. &pLogonInfo->LogonDomainName,
  158. &pLogonInfo->UserName,
  159. &pLogonInfo->Workstation);
  160. DebugPrintHex(SSPI_LOG, "ChallengeToClient:", MSV1_0_CHALLENGE_LENGTH, pLogonInfo->ChallengeToClient);
  161. DebugPrintHex(SSPI_LOG, "CaseSensitiveChallengeResponse:",
  162. pLogonInfo->CaseSensitiveChallengeResponse.Length,
  163. pLogonInfo->CaseSensitiveChallengeResponse.Buffer);
  164. DebugPrintHex(SSPI_LOG, "CaseInsensitiveChallengeResponse:",
  165. pLogonInfo->CaseInsensitiveChallengeResponse.Length,
  166. pLogonInfo->CaseInsensitiveChallengeResponse.Buffer);
  167. *ppLogonInfo = pLogonInfo;
  168. pLogonInfo = NULL;
  169. *pcbLogonInfo = cbLogonInfo;
  170. }
  171. if (pRequest)
  172. {
  173. delete [] pRequest;
  174. }
  175. if (pLogonInfo)
  176. {
  177. delete [] pLogonInfo;
  178. }
  179. if (pResponse)
  180. {
  181. LsaFreeReturnBuffer(pResponse);
  182. }
  183. return Status;
  184. }
  185. NTSTATUS
  186. MsvLsaLogon(
  187. IN HANDLE hLogonHandle,
  188. IN ULONG PackageId,
  189. IN LUID* pLogonId,
  190. IN ULONG ParameterControl,
  191. IN UCHAR ChallengeToClient[MSV1_0_CHALLENGE_LENGTH],
  192. IN UNICODE_STRING* pUserName,
  193. IN UNICODE_STRING* pUserDomain,
  194. IN UNICODE_STRING* pPassword,
  195. IN UNICODE_STRING* pServerName,
  196. IN UNICODE_STRING* pServerDomain,
  197. IN UNICODE_STRING* pWorkstation,
  198. OUT HANDLE* pTokenHandle
  199. )
  200. {
  201. TNtStatus Status;
  202. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  203. MSV1_0_LM20_LOGON* pLogonInfo = NULL;
  204. ULONG cbLogonInfoSize = 0;
  205. LSA_STRING Name = {0};
  206. TOKEN_SOURCE SourceContext = {0};
  207. VOID* pProfile = NULL;
  208. ULONG cbProfileSize = 0;
  209. LUID LogonId = {0};
  210. QUOTA_LIMITS Quotas = {0};
  211. Status DBGCHK = GetMsvLogonInfo(
  212. hLogonHandle,
  213. PackageId,
  214. pLogonId,
  215. ParameterControl,
  216. ChallengeToClient,
  217. pUserName,
  218. pUserDomain,
  219. pPassword,
  220. pServerName,
  221. pServerDomain,
  222. pWorkstation,
  223. &cbLogonInfoSize,
  224. &pLogonInfo
  225. );
  226. if (NT_SUCCESS(Status))
  227. {
  228. strncpy(
  229. SourceContext.SourceName,
  230. "ssptest",
  231. sizeof(SourceContext.SourceName)
  232. );
  233. NtAllocateLocallyUniqueId(&SourceContext.SourceIdentifier);
  234. //
  235. // Now call LsaLogonUser
  236. //
  237. RtlInitString(
  238. &Name,
  239. "ssptest"
  240. );
  241. Status DBGCHK = LsaLogonUser(
  242. hLogonHandle,
  243. &Name,
  244. Network,
  245. PackageId,
  246. pLogonInfo,
  247. cbLogonInfoSize,
  248. NULL, // no token groups
  249. &SourceContext,
  250. (VOID**) &pProfile,
  251. &cbProfileSize,
  252. &LogonId,
  253. pTokenHandle,
  254. &Quotas,
  255. &SubStatus
  256. );
  257. }
  258. if (NT_SUCCESS(Status))
  259. {
  260. Status DBGCHK = SubStatus;
  261. }
  262. if (NT_SUCCESS(Status))
  263. {
  264. DebugPrintf(SSPI_LOG, "LogonId %#x:%#x\n", LogonId.HighPart, LogonId.LowPart);
  265. DebugPrintf(SSPI_LOG, "TokenHandle %p\n", *pTokenHandle);
  266. DebugPrintProfileAndQuotas(SSPI_LOG, pProfile, &Quotas);
  267. }
  268. if (pProfile)
  269. {
  270. LsaFreeReturnBuffer(pProfile);
  271. }
  272. if (pLogonInfo)
  273. {
  274. delete [] pLogonInfo;
  275. }
  276. return Status;
  277. }
  278. VOID __cdecl
  279. main(
  280. IN INT argc,
  281. IN PSTR argv[]
  282. )
  283. {
  284. TNtStatus Status = STATUS_SUCCESS;
  285. UNICODE_STRING UserName = {0};
  286. UNICODE_STRING UserDomain = {0};
  287. UNICODE_STRING Password = {0};
  288. UNICODE_STRING Application = {0};
  289. UNICODE_STRING ServerName = {0};
  290. UNICODE_STRING ServerDomain = {0};
  291. UNICODE_STRING Workstation = {0};
  292. ULONG ParameterControl = 0;
  293. LUID LogonId = {0};
  294. LUID ChallengeToClient = {0};
  295. C_ASSERT(MSV1_0_CHALLENGE_LENGTH == sizeof(LUID));
  296. HANDLE hToken = NULL;
  297. HANDLE hLogonHandle = NULL;
  298. ULONG PackageId = 0;
  299. RtlGenRandom(&ChallengeToClient, sizeof(ChallengeToClient));
  300. for (INT i = 1; NT_SUCCESS(Status) && (i < argc); i++)
  301. {
  302. if ((*argv[i] == '-') || (*argv[i] == '/'))
  303. {
  304. switch (argv[i][1])
  305. {
  306. case 'c':
  307. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &UserName);
  308. break;
  309. case 'C':
  310. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &UserDomain);
  311. break;
  312. case 'a':
  313. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &Application);
  314. break;
  315. case 'k':
  316. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &Password);
  317. break;
  318. case 'p':
  319. ParameterControl = strtol(argv[i] + 2, NULL, 0);
  320. break;
  321. case 'h':
  322. LogonId.HighPart = strtol(argv[i] + 2, NULL, 0);
  323. break;
  324. case 'l':
  325. LogonId.LowPart = strtol(argv[i] + 2, NULL, 0);
  326. break;
  327. case 'H':
  328. ChallengeToClient.HighPart = strtol(argv[i] + 2, NULL, 0);
  329. break;
  330. case 'L':
  331. ChallengeToClient.LowPart = strtol(argv[i] + 2, NULL, 0);
  332. break;
  333. case 's':
  334. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ServerName);
  335. break;
  336. case 'S':
  337. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &ServerDomain);
  338. break;
  339. case 'w':
  340. Status DBGCHK = CreateUnicodeStringFromAsciiz(argv[i] + 2, &Workstation);
  341. break;
  342. case '?':
  343. default:
  344. Usage(argv[0]);
  345. break;
  346. }
  347. }
  348. else
  349. {
  350. Usage(argv[0]);
  351. }
  352. }
  353. DebugLogOpen(NULL, SSPI_LOG | SSPI_WARN | SSPI_ERROR);
  354. if (NT_SUCCESS(Status))
  355. {
  356. Status DBGCHK = GetLsaHandleAndPackageId(
  357. NTLMSP_NAME_A,
  358. &hLogonHandle,
  359. &PackageId
  360. );
  361. }
  362. if (NT_SUCCESS(Status))
  363. {
  364. Status DBGCHK = MsvLsaLogon(
  365. hLogonHandle,
  366. PackageId,
  367. &LogonId,
  368. ParameterControl,
  369. (UCHAR*) &ChallengeToClient,
  370. &UserName,
  371. &UserDomain,
  372. &Password,
  373. &ServerName,
  374. &ServerDomain,
  375. &Workstation,
  376. &hToken
  377. );
  378. }
  379. if (NT_SUCCESS(Status))
  380. {
  381. Status DBGCHK = CheckUserToken(hToken);
  382. }
  383. if (NT_SUCCESS(Status) && Application.Length && Application.Buffer)
  384. {
  385. Status DBGCHK = StartInteractiveClientProcessAsUser(hToken, Application.Buffer);
  386. }
  387. if (NT_SUCCESS(Status))
  388. {
  389. DebugPrintf(SSPI_LOG, "Operation succeeded\n");
  390. }
  391. else
  392. {
  393. DebugPrintf(SSPI_ERROR, "Operation failed\n");
  394. }
  395. if (hLogonHandle)
  396. {
  397. LsaDeregisterLogonProcess(hLogonHandle);
  398. }
  399. if (hToken)
  400. {
  401. CloseHandle(hToken);
  402. }
  403. RtlFreeUnicodeString(&UserName);
  404. RtlFreeUnicodeString(&UserDomain);
  405. RtlFreeUnicodeString(&Password);
  406. RtlFreeUnicodeString(&ServerName);
  407. RtlFreeUnicodeString(&ServerDomain);
  408. RtlFreeUnicodeString(&Application);
  409. RtlFreeUnicodeString(&Workstation);
  410. }