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.

530 lines
14 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. cachelogon.cxx
  5. Abstract:
  6. cachelogon
  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 <logonmsv.h>
  16. #include <tchar.h>
  17. #include "cachelogon.hxx"
  18. EXTERN_C
  19. NTSTATUS NTAPI
  20. LsaICallPackage(
  21. IN PUNICODE_STRING AuthenticationPackage,
  22. IN PVOID ProtocolSubmitBuffer,
  23. IN ULONG SubmitBufferLength,
  24. OUT PVOID *ProtocolReturnBuffer,
  25. OUT PULONG ReturnBufferLength,
  26. OUT PNTSTATUS ProtocolStatus
  27. );
  28. BOOL
  29. DllMain(
  30. IN HANDLE hModule,
  31. IN DWORD dwReason,
  32. IN DWORD dwReserved
  33. )
  34. {
  35. BOOL bRet;
  36. switch (dwReason)
  37. {
  38. case DLL_THREAD_ATTACH:
  39. break;
  40. case DLL_THREAD_DETACH:
  41. break;
  42. case DLL_PROCESS_DETACH:
  43. break;
  44. case DLL_PROCESS_ATTACH:
  45. break;
  46. default:
  47. break;
  48. }
  49. bRet = DllMainDefaultHandler(hModule, dwReason, dwReserved);
  50. DebugPrintf(SSPI_LOG, "DllMain leaving %#x\n", bRet);
  51. return bRet;
  52. }
  53. int
  54. RunIt(
  55. IN ULONG cbParameters,
  56. IN VOID* pvParameters
  57. )
  58. {
  59. //
  60. // RunItDefaultHandler calls Start() and adds try except
  61. //
  62. DWORD dwErr;
  63. dwErr = RunItDefaultHandler(cbParameters, pvParameters);
  64. DebugPrintf(SSPI_LOG, "RunIt leaving %#x\n", dwErr);
  65. return dwErr;
  66. }
  67. NTSTATUS
  68. CacheLogonInformation(
  69. IN PUNICODE_STRING pUserName,
  70. IN PUNICODE_STRING pDomainName,
  71. IN OPTIONAL PUNICODE_STRING pPassword,
  72. IN OPTIONAL PUNICODE_STRING pDnsDomainName,
  73. IN OPTIONAL PUNICODE_STRING pUpn,
  74. IN ULONG ParameterControl,
  75. IN BOOLEAN bIsMitLogon,
  76. IN ULONG CacheRequestFlags,
  77. IN OPTIONAL PNETLOGON_VALIDATION_SAM_INFO3 pValidationInfo,
  78. IN OPTIONAL PVOID pSupplementalCreds,
  79. IN OPTIONAL ULONG cbSupplementalCredSize
  80. )
  81. {
  82. TNtStatus Status = STATUS_SUCCESS;
  83. ULONG cbCacheRequest = 0;
  84. HANDLE hLsa = NULL;
  85. ULONG PackageId = 0;
  86. MSV1_0_CACHE_LOGON_REQUEST* pCacheRequest = NULL;
  87. NETLOGON_VALIDATION_SAM_INFO4* pValidationInfoToUse = NULL;
  88. NETLOGON_INTERACTIVE_INFO* pMsvLogonInfo = NULL;
  89. PVOID pOutputBuffer = NULL;
  90. ULONG cbOutputBufferSize = NULL;
  91. PVOID pSupplementalMitCreds = NULL;
  92. ULONG cbSupplementalMitCredSize = 0;
  93. WCHAR szWorkStation[256] = {0};
  94. UNICODE_STRING Workstation = {0, sizeof(szWorkStation), szWorkStation};
  95. UNICODE_STRING MsvPackageName = CONSTANT_UNICODE_STRING(TEXT(MSV1_0_PACKAGE_NAME));
  96. NTSTATUS SubStatus = STATUS_UNSUCCESSFUL;
  97. WCHAR* pWhere = NULL;
  98. ULONG cchWorkstation = COUNTOF(szWorkStation);
  99. (VOID) GetComputerNameW(szWorkStation, &cchWorkstation);
  100. Workstation.Length = (USHORT) cchWorkstation * sizeof(WCHAR);
  101. SspiPrint(SSPI_LOG,
  102. TEXT("CacheLogonInformation workstation %wZ, User %wZ, Domain %wZ, Password %wZ, DnsDomain %wZ, Upn %wZ, ")
  103. TEXT("ParameterControl %#x, bIsMitLogon %#x, CacheRequestFlags %#x, pValidationInfo %p, ")
  104. TEXT("pSupplementalCreds %p, cbSupplementalCredSize %#x\n"),
  105. &Workstation, pUserName, pDomainName, pPassword, pDnsDomainName, pUpn,
  106. ParameterControl, bIsMitLogon, CacheRequestFlags, pValidationInfo,
  107. pSupplementalCreds, cbSupplementalCredSize);
  108. cbCacheRequest = ROUND_UP_COUNT(sizeof(NETLOGON_INTERACTIVE_INFO), sizeof(ULONG_PTR))
  109. + ROUND_UP_COUNT(pDomainName->Length + sizeof(WCHAR), sizeof(ULONG_PTR))
  110. + ROUND_UP_COUNT(Workstation.Length + sizeof(WCHAR), sizeof(ULONG_PTR))
  111. + ROUND_UP_COUNT(pUserName->Length + sizeof(WCHAR), sizeof(ULONG_PTR)) + 10 * sizeof(ULONG_PTR);
  112. if (bIsMitLogon)
  113. {
  114. cbSupplementalMitCredSize = (2 * ROUND_UP_COUNT(sizeof(UNICODE_STRING), sizeof(ULONG_PTR)))
  115. + ROUND_UP_COUNT(pUserName->Length + sizeof(WCHAR), sizeof(ULONG_PTR))
  116. + ROUND_UP_COUNT(pDomainName->Length + sizeof(WCHAR), sizeof(ULONG_PTR));
  117. cbCacheRequest = cbSupplementalMitCredSize;
  118. }
  119. else
  120. {
  121. cbCacheRequest += ROUND_UP_COUNT(cbSupplementalCredSize, sizeof(ULONG_PTR));
  122. }
  123. cbCacheRequest += ROUND_UP_COUNT(sizeof(NETLOGON_VALIDATION_SAM_INFO4), sizeof(ULONG_PTR));
  124. if (pDnsDomainName)
  125. {
  126. cbCacheRequest += ROUND_UP_COUNT(pDnsDomainName->Length + sizeof(WCHAR), sizeof(ULONG_PTR));
  127. }
  128. pCacheRequest = (MSV1_0_CACHE_LOGON_REQUEST*) new CHAR[cbCacheRequest];
  129. Status DBGCHK = pCacheRequest ? STATUS_SUCCESS : STATUS_NO_MEMORY;
  130. if (NT_SUCCESS(Status))
  131. {
  132. RtlZeroMemory(pCacheRequest, cbCacheRequest);
  133. pCacheRequest->MessageType = MsV1_0CacheLogon;
  134. pMsvLogonInfo = (NETLOGON_INTERACTIVE_INFO*) ROUND_UP_POINTER(((PCHAR)pCacheRequest) + ROUND_UP_COUNT(sizeof(*pCacheRequest), sizeof(ULONG_PTR)), sizeof(ULONG_PTR));
  135. pCacheRequest->LogonInformation = pMsvLogonInfo;
  136. pWhere = (WCHAR*) (((PCHAR) pMsvLogonInfo) + ROUND_UP_COUNT(sizeof(*pMsvLogonInfo), sizeof(ULONG_PTR)));
  137. pMsvLogonInfo->Identity.ParameterControl = ParameterControl;
  138. PackUnicodeStringAsUnicodeStringZ(pDomainName, &pWhere, &pMsvLogonInfo->Identity.LogonDomainName);
  139. PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, &pMsvLogonInfo->Identity.UserName);
  140. PackUnicodeStringAsUnicodeStringZ(&Workstation, &pWhere, &pMsvLogonInfo->Identity.Workstation);
  141. if (pPassword)
  142. {
  143. Status DBGCHK = RtlCalculateNtOwfPassword(
  144. pPassword,
  145. &pMsvLogonInfo->NtOwfPassword
  146. );
  147. }
  148. }
  149. //
  150. // If this was a logon to an MIT realm that we know about,
  151. // then add the MIT username (upn?) & realm to the supplemental data
  152. //
  153. if (NT_SUCCESS(Status))
  154. {
  155. if (bIsMitLogon)
  156. {
  157. SspiPrint(SSPI_LOG, TEXT("Using MIT caching\n"));
  158. pCacheRequest->RequestFlags = MSV1_0_CACHE_LOGON_REQUEST_MIT_LOGON | CacheRequestFlags;
  159. pSupplementalMitCreds = ROUND_UP_POINTER(pWhere, sizeof(ULONG_PTR));
  160. pWhere += /* 2 * */ ROUND_UP_COUNT(sizeof(UNICODE_STRING), sizeof(ULONG_PTR));
  161. PackUnicodeStringAsUnicodeStringZ(pUserName, &pWhere, (UNICODE_STRING*) pSupplementalMitCreds);
  162. PackUnicodeStringAsUnicodeStringZ(pDomainName, &pWhere, ((UNICODE_STRING*) pSupplementalMitCreds) + 1);
  163. pCacheRequest->SupplementalCacheData = pSupplementalMitCreds;
  164. pCacheRequest->SupplementalCacheDataLength = cbSupplementalMitCredSize;
  165. }
  166. else
  167. {
  168. pCacheRequest->RequestFlags = CacheRequestFlags;
  169. pCacheRequest->SupplementalCacheData = ROUND_UP_POINTER(pWhere, sizeof(ULONG_PTR));
  170. pCacheRequest->SupplementalCacheDataLength = cbSupplementalCredSize;
  171. pWhere = (WCHAR*) ROUND_UP_POINTER(((CHAR*) pWhere) + sizeof(ULONG_PTR) + cbSupplementalCredSize, sizeof(ULONG_PTR));
  172. if (pSupplementalCreds)
  173. {
  174. RtlCopyMemory(pCacheRequest->SupplementalCacheData, pSupplementalCreds, cbSupplementalCredSize);
  175. }
  176. }
  177. }
  178. if (NT_SUCCESS(Status))
  179. {
  180. pValidationInfoToUse = (NETLOGON_VALIDATION_SAM_INFO4*) ROUND_UP_POINTER(pWhere, sizeof(ULONG_PTR));
  181. pCacheRequest->ValidationInformation = pValidationInfoToUse;
  182. pCacheRequest->RequestFlags |= MSV1_0_CACHE_LOGON_REQUEST_INFO4;
  183. pWhere = (WCHAR*) ROUND_UP_POINTER(pValidationInfoToUse, sizeof(ULONG_PTR));
  184. if (pValidationInfo)
  185. {
  186. RtlCopyMemory(pValidationInfoToUse,
  187. pValidationInfo,
  188. sizeof(*pValidationInfo));
  189. }
  190. if (pDnsDomainName)
  191. {
  192. PackUnicodeStringAsUnicodeStringZ(pDnsDomainName, &pWhere, &pValidationInfoToUse->DnsLogonDomainName);
  193. }
  194. }
  195. if (NT_SUCCESS(Status))
  196. {
  197. SspiPrintHex(SSPI_LOG, TEXT("CacheRequest"), cbCacheRequest, pCacheRequest);
  198. Status DBGCHK = GetLsaHandleAndPackageId(MSV1_0_PACKAGE_NAME, &hLsa, &PackageId);
  199. }
  200. if (NT_SUCCESS(Status))
  201. {
  202. Status DBGCHK = LsaICallPackage(
  203. &MsvPackageName,
  204. pCacheRequest,
  205. sizeof(MSV1_0_CACHE_LOGON_REQUEST), // cbCacheRequest,
  206. &pOutputBuffer,
  207. &cbOutputBufferSize,
  208. &SubStatus
  209. );
  210. }
  211. if (NT_SUCCESS(Status))
  212. {
  213. Status DBGCHK = SubStatus;
  214. }
  215. if (pCacheRequest)
  216. {
  217. delete [] pCacheRequest;
  218. }
  219. if (pOutputBuffer)
  220. {
  221. LsaFreeReturnBuffer(pOutputBuffer);
  222. }
  223. if (hLsa)
  224. {
  225. LsaDeregisterLogonProcess(hLsa);
  226. }
  227. return Status;
  228. }
  229. #if 0
  230. Return Values for Start():
  231. ERROR_NO_MORE_USER_HANDLES unload repeatedly
  232. ERROR_SERVER_HAS_OPEN_HANDLES no unload at all
  233. others unload once
  234. #endif 0
  235. int
  236. Start(
  237. IN ULONG cbParameters,
  238. IN VOID* pvParameters
  239. )
  240. {
  241. DWORD dwErr = ERROR_SUCCESS;
  242. CHAR* pNlpCacheEncryptionKey = NULL;
  243. LIST_ENTRY** ppNlpActiveCtes = NULL;
  244. SspiPrintHex(SSPI_LOG, TEXT("Start Parameters"), cbParameters, pvParameters);
  245. if (cbParameters >= 3)
  246. {
  247. TNtStatus Status;
  248. UNICODE_STRING UserName = {0};
  249. UNICODE_STRING DomainName = {0};
  250. ULONG ParameterControl = RPC_C_AUTHN_GSS_KERBEROS;
  251. ULONG CacheRequestFlags = MSV1_0_CACHE_LOGON_DELETE_ENTRY;
  252. Status DBGCHK = CreateUnicodeStringFromAsciiz((CHAR*)pvParameters, &UserName);
  253. if (NT_SUCCESS(Status))
  254. {
  255. Status DBGCHK = CreateUnicodeStringFromAsciiz(((CHAR*) pvParameters) + strlen((CHAR*) pvParameters) + 1, &DomainName);
  256. }
  257. if (NT_SUCCESS(Status))
  258. {
  259. Status DBGCHK = CacheLogonInformation(
  260. &UserName,
  261. &DomainName,
  262. NULL, // no password
  263. NULL, // no dns domain
  264. NULL, // no upn
  265. ParameterControl,
  266. FALSE, // not MIT
  267. CacheRequestFlags, // flags
  268. NULL, // no validation info
  269. NULL, // no supplemental creds
  270. 0 // sizeof supplemental cred is 0
  271. );
  272. }
  273. RtlFreeUnicodeString(&UserName);
  274. RtlFreeUnicodeString(&DomainName);
  275. if (NT_SUCCESS(Status))
  276. {
  277. SspiPrint(SSPI_LOG, TEXT("Operation succeeded\n"));
  278. }
  279. else
  280. {
  281. SspiPrint(SSPI_LOG, TEXT("Operation failed\n"));
  282. }
  283. }
  284. else
  285. {
  286. dwErr = ERROR_INVALID_PARAMETER;
  287. SspiPrint(SSPI_LOG, TEXT("Start received invalid parameter\n"));
  288. }
  289. return dwErr;
  290. }
  291. #if 0
  292. VOID
  293. Usage(
  294. IN PCTSTR pszApp
  295. )
  296. {
  297. SspiPrint(SSPI_ERROR,
  298. TEXT("\n\nUsage: %s -u<user> -d<domain> [-c<ParameterControl>] [-f<CacheRequestFlags>]\n\n"),
  299. pszApp);
  300. exit(-1);
  301. }
  302. VOID __cdecl
  303. _tmain(
  304. IN INT argc,
  305. IN PTSTR argv[]
  306. )
  307. {
  308. TNtStatus Status = STATUS_SUCCESS;
  309. UNICODE_STRING ClientName = {0};
  310. UNICODE_STRING ClientRealm = {0};
  311. ULONG ParameterControl = RPC_C_AUTHN_GSS_KERBEROS;
  312. ULONG CacheRequestFlags = MSV1_0_CACHE_LOGON_DELETE_ENTRY;
  313. AUTO_LOG_OPEN(TEXT("cachelogon.exe"));
  314. for (INT i = 1; NT_SUCCESS(Status) && (i < argc); i++)
  315. {
  316. if ((*argv[i] == TEXT('-')) || (*argv[i] == TEXT('/')))
  317. {
  318. switch (argv[i][1])
  319. {
  320. case TEXT('u'):
  321. RtlInitUnicodeString(&ClientName, argv[i] + 2);
  322. break;
  323. case TEXT('d'):
  324. RtlInitUnicodeString(&ClientRealm, argv[i] + 2);
  325. break;
  326. case TEXT('c'):
  327. ParameterControl = wcstol(argv[i] + 2, NULL, 0);
  328. break;
  329. case TEXT('f'):
  330. CacheRequestFlags = wcstol(argv[i] + 2, NULL, 0);
  331. break;
  332. case TEXT('h'):
  333. case TEXT('?'):
  334. default:
  335. Usage(argv[0]);
  336. break;
  337. }
  338. }
  339. else
  340. {
  341. Usage(argv[0]);
  342. }
  343. }
  344. Status DBGCHK = CacheLogonInformation(
  345. &ClientName,
  346. &ClientRealm,
  347. NULL, // no password
  348. NULL, // no dns domain
  349. NULL, // no upn
  350. ParameterControl,
  351. FALSE, // not MIT
  352. CacheRequestFlags, // flags
  353. NULL, // no validation info
  354. NULL, // no supplemental creds
  355. 0 // sizeof supplemental cred is 0
  356. );
  357. if (NT_SUCCESS(Status))
  358. {
  359. SspiPrint(SSPI_LOG, TEXT("Operation succeeded\n"));
  360. }
  361. else
  362. {
  363. SspiPrint(SSPI_ERROR, TEXT("Operation failed\n"));
  364. }
  365. AUTO_LOG_CLOSE();
  366. }
  367. #endif
  368. Init(
  369. IN ULONG argc,
  370. IN PCSTR argv[],
  371. OUT ULONG* pcbParameters,
  372. OUT VOID** ppvParameters
  373. )
  374. {
  375. DWORD dwErr = ERROR_SUCCESS;
  376. CHAR Parameters[REMOTE_PACKET_SIZE] = {0};
  377. ULONG cbBuffer = sizeof(Parameters);
  378. ULONG cbParameter = 0;
  379. CHAR* pNlpCacheEncryptionKey = NULL;
  380. LIST_ENTRY** ppNlpActiveCtes = NULL;
  381. *pcbParameters = 0;
  382. *ppvParameters = NULL;
  383. if (argc == 2)
  384. {
  385. DebugPrintf(SSPI_LOG, "argv[0] %s, argv[1] %s\n", argv[0], argv[1]);
  386. pNlpCacheEncryptionKey = (CHAR*) (ULONG_PTR) strtol(argv[0], NULL, 0);
  387. ppNlpActiveCtes = (LIST_ENTRY**) (ULONG_PTR) strtol(argv[1], NULL, 0);
  388. SspiPrint(SSPI_LOG, TEXT("msv1_0!NlpCacheEncryptionKey %p, addr of msv1_0!NlpActiveCtes %p\n"), pNlpCacheEncryptionKey, ppNlpActiveCtes);
  389. memcpy(Parameters, argv[0], strlen(argv[0]) + 1);
  390. cbParameter = strlen(argv[0]) + 1;
  391. memcpy(Parameters + cbParameter, argv[1], strlen(argv[1]) + 1);
  392. cbParameter += strlen(argv[1]) + 1;
  393. cbParameter++; // add a NULL
  394. }
  395. else // return "Usage" in ppvParameters, must be a NULL terminated string
  396. {
  397. strcpy(Parameters, "<user name> <domain name>");
  398. cbParameter = strlen(Parameters) + 1;
  399. dwErr = ERROR_INVALID_PARAMETER;
  400. }
  401. *ppvParameters = new CHAR[cbParameter];
  402. if (*ppvParameters)
  403. {
  404. *pcbParameters = cbParameter;
  405. memcpy(*ppvParameters, Parameters, *pcbParameters);
  406. }
  407. else
  408. {
  409. dwErr = ERROR_OUTOFMEMORY;
  410. goto Cleanup;
  411. }
  412. Cleanup:
  413. return dwErr;
  414. }