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.

493 lines
12 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <stdio.h>
  5. #include <windows.h>
  6. #include <wincrypt.h>
  7. #define SECURITY_WIN32
  8. #include <security.h>
  9. #include <sspi.h>
  10. #include <ntsecapi.h>
  11. #include <ntrtl.h>
  12. #include <schannel.h>
  13. #include <sslcache.h>
  14. #define LIST_CACHE_ENTRIES 1
  15. #define LIST_ENTRIES_INTERACTIVE 2
  16. #define PURGE_CACHE_ENTRIES 3
  17. DWORD dwOperation = LIST_CACHE_ENTRIES;
  18. BOOL fIncludeClient = FALSE;
  19. BOOL fIncludeServer = FALSE;
  20. BOOL fIncludeMappedEntries = FALSE;
  21. LPSTR pszServerName = NULL;
  22. void
  23. DisplayCacheInfo(
  24. HANDLE LsaHandle,
  25. DWORD PackageNumber,
  26. BOOL fClient,
  27. BOOL fServer);
  28. void
  29. PurgeCacheEntries(
  30. HANDLE LsaHandle,
  31. DWORD PackageNumber);
  32. void
  33. DisplayCacheInfoInteractive(
  34. HANDLE LsaHandle,
  35. DWORD PackageNumber);
  36. void Usage(void)
  37. {
  38. printf("USAGE: sslcache [ operation ] [ flags ]\n");
  39. printf("\n");
  40. printf(" OPERATIONS:\n");
  41. printf(" -l List cache entries (default)\n");
  42. printf(" -i List cache entries interactively\n");
  43. printf(" -p Purge cache entries\n");
  44. printf("\n");
  45. printf(" FLAGS:\n");
  46. printf(" -c Include client entries (default)\n");
  47. printf(" -s Include server entries\n");
  48. printf(" -S Include IIS mapped server entries (purge only)\n");
  49. }
  50. void _cdecl main(int argc, char *argv[])
  51. {
  52. DWORD Status;
  53. HANDLE LsaHandle;
  54. DWORD PackageNumber;
  55. LSA_STRING PackageName;
  56. BOOLEAN Trusted = TRUE;
  57. BOOLEAN WasEnabled;
  58. STRING Name;
  59. ULONG Dummy;
  60. INT i;
  61. INT iOption;
  62. PCHAR pszOption;
  63. //
  64. // Parse user-supplied parameters.
  65. //
  66. for(i = 1; i < argc; i++)
  67. {
  68. if(argv[i][0] == '/') argv[i][0] = '-';
  69. if(argv[i][0] != '-')
  70. {
  71. printf("**** Invalid argument \"%s\"\n", argv[i]);
  72. Usage();
  73. return;
  74. }
  75. iOption = argv[i][1];
  76. pszOption = &argv[i][2];
  77. switch(iOption)
  78. {
  79. case 'l':
  80. dwOperation = LIST_CACHE_ENTRIES;
  81. break;
  82. case 'i':
  83. dwOperation = LIST_ENTRIES_INTERACTIVE;
  84. break;
  85. case 'p':
  86. dwOperation = PURGE_CACHE_ENTRIES;
  87. break;
  88. case 'c':
  89. fIncludeClient = TRUE;
  90. break;
  91. case 's':
  92. if(*pszOption == '\0')
  93. {
  94. fIncludeServer = TRUE;
  95. }
  96. else
  97. {
  98. pszServerName = pszOption;
  99. fIncludeClient = TRUE;
  100. }
  101. break;
  102. case 'S':
  103. fIncludeMappedEntries = TRUE;
  104. fIncludeServer = TRUE;
  105. break;
  106. default:
  107. printf("**** Invalid option \"%s\"\n", argv[i]);
  108. Usage();
  109. return;
  110. }
  111. }
  112. //
  113. // If neither client nor server was specified by user set appropriate default.
  114. //
  115. if(!fIncludeClient && !fIncludeServer)
  116. {
  117. if(dwOperation == PURGE_CACHE_ENTRIES)
  118. {
  119. fIncludeClient = TRUE;
  120. }
  121. else
  122. {
  123. fIncludeClient = TRUE;
  124. fIncludeServer = TRUE;
  125. }
  126. }
  127. //
  128. // Get handle to schannel security package.
  129. //
  130. Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  131. if (!NT_SUCCESS(Status))
  132. {
  133. Trusted = FALSE;
  134. }
  135. RtlInitString(
  136. &Name,
  137. "sslcache");
  138. if(Trusted)
  139. {
  140. Status = LsaRegisterLogonProcess(
  141. &Name,
  142. &LsaHandle,
  143. &Dummy);
  144. if(FAILED(Status))
  145. {
  146. printf("**** Error 0x%x returned by LsaRegisterLogonProcess\n", Status);
  147. return;
  148. }
  149. }
  150. else
  151. {
  152. Status = LsaConnectUntrusted(&LsaHandle);
  153. if(FAILED(Status))
  154. {
  155. printf("**** Error 0x%x returned by LsaConnectUntrusted\n", Status);
  156. return;
  157. }
  158. }
  159. PackageName.Buffer = UNISP_NAME_A;
  160. PackageName.Length = (USHORT)strlen(PackageName.Buffer);
  161. PackageName.MaximumLength = PackageName.Length + 1;
  162. Status = LsaLookupAuthenticationPackage(
  163. LsaHandle,
  164. &PackageName,
  165. &PackageNumber);
  166. if(FAILED(Status))
  167. {
  168. printf("**** Error 0x%x returned by LsaLookupAuthenticationPackage\n", Status);
  169. CloseHandle(LsaHandle);
  170. return;
  171. }
  172. //
  173. // Perform specified operation.
  174. //
  175. if(dwOperation == LIST_CACHE_ENTRIES)
  176. {
  177. printf("\nDISPLAY CACHE ENTRIES\n");
  178. printf("\n");
  179. if(fIncludeClient)
  180. {
  181. printf("--CLIENT--\n");
  182. DisplayCacheInfo(LsaHandle, PackageNumber, TRUE, FALSE);
  183. }
  184. if(fIncludeServer)
  185. {
  186. printf("--SERVER--\n");
  187. DisplayCacheInfo(LsaHandle, PackageNumber, FALSE, TRUE);
  188. }
  189. if(fIncludeClient && fIncludeServer)
  190. {
  191. printf("--TOTAL--\n");
  192. DisplayCacheInfo(LsaHandle, PackageNumber, TRUE, TRUE);
  193. }
  194. }
  195. else if(dwOperation == LIST_ENTRIES_INTERACTIVE)
  196. {
  197. DisplayCacheInfoInteractive(LsaHandle, PackageNumber);
  198. }
  199. else
  200. {
  201. PurgeCacheEntries(LsaHandle, PackageNumber);
  202. }
  203. CloseHandle(LsaHandle);
  204. }
  205. void
  206. PurgeCacheEntries(
  207. HANDLE LsaHandle,
  208. DWORD PackageNumber)
  209. {
  210. PSSL_PURGE_SESSION_CACHE_REQUEST pRequest;
  211. DWORD cchServerName;
  212. DWORD cbServerName;
  213. DWORD SubStatus;
  214. DWORD Status;
  215. printf("\nPURGE CACHE ENTRIES\n");
  216. printf("Client:%s\n", fIncludeClient ? "yes" : "no");
  217. printf("Server:%s\n", fIncludeServer ? "yes" : "no");
  218. if(pszServerName == NULL)
  219. {
  220. cbServerName = 0;
  221. pRequest = (PSSL_PURGE_SESSION_CACHE_REQUEST)LocalAlloc(LPTR, sizeof(SSL_PURGE_SESSION_CACHE_REQUEST));
  222. if(pRequest == NULL)
  223. {
  224. printf("**** Out of memory\n");
  225. return;
  226. }
  227. }
  228. else
  229. {
  230. cchServerName = MultiByteToWideChar(CP_ACP, 0, pszServerName, -1, NULL, 0);
  231. cbServerName = (cchServerName + 1) * sizeof(WCHAR);
  232. pRequest = LocalAlloc(LPTR, sizeof(SSL_PURGE_SESSION_CACHE_REQUEST) + cbServerName);
  233. if(pRequest == NULL)
  234. {
  235. printf("**** Out of memory\n");
  236. return;
  237. }
  238. cchServerName = MultiByteToWideChar(CP_ACP, 0, pszServerName, -1, (LPWSTR)(pRequest + 1), cchServerName);
  239. if(cchServerName == 0)
  240. {
  241. printf("**** Error converting server name\n");
  242. return;
  243. }
  244. pRequest->ServerName.Buffer = (LPWSTR)(pRequest + 1);
  245. pRequest->ServerName.Length = (WORD)(cchServerName * sizeof(WCHAR));
  246. pRequest->ServerName.MaximumLength = (WORD)cbServerName;
  247. }
  248. pRequest->MessageType = SslPurgeSessionCacheMessage;
  249. if(fIncludeClient)
  250. {
  251. pRequest->Flags |= SSL_PURGE_CLIENT_ENTRIES;
  252. }
  253. if(fIncludeServer)
  254. {
  255. pRequest->Flags |= SSL_PURGE_SERVER_ENTRIES | SSL_PURGE_SERVER_ALL_ENTRIES;
  256. }
  257. if(fIncludeMappedEntries)
  258. {
  259. pRequest->Flags |= SSL_PURGE_SERVER_ENTRIES_DISCARD_LOCATORS;
  260. }
  261. Status = LsaCallAuthenticationPackage(
  262. LsaHandle,
  263. PackageNumber,
  264. pRequest,
  265. sizeof(SSL_PURGE_SESSION_CACHE_REQUEST) + cbServerName,
  266. NULL,
  267. NULL,
  268. &SubStatus);
  269. if(FAILED(Status))
  270. {
  271. printf("**** Error 0x%x returned by LsaCallAuthenticationPackage\n", Status);
  272. return;
  273. }
  274. if(FAILED(SubStatus))
  275. {
  276. if(SubStatus == 0xC0000061)
  277. {
  278. printf("**** The TCB privilege is required to perform this operation.\n");
  279. }
  280. else
  281. {
  282. printf("**** Error 0x%x occurred while purging cache entries.\n", SubStatus);
  283. }
  284. }
  285. }
  286. void
  287. DisplayCacheInfo(
  288. HANDLE LsaHandle,
  289. DWORD PackageNumber,
  290. BOOL fClient,
  291. BOOL fServer)
  292. {
  293. PSSL_SESSION_CACHE_INFO_REQUEST pRequest = NULL;
  294. PSSL_SESSION_CACHE_INFO_RESPONSE pResponse = NULL;
  295. DWORD cbResponse = 0;
  296. DWORD SubStatus;
  297. DWORD Status;
  298. pRequest = (PSSL_SESSION_CACHE_INFO_REQUEST)LocalAlloc(LPTR, sizeof(SSL_SESSION_CACHE_INFO_REQUEST));
  299. if(pRequest == NULL)
  300. {
  301. printf("**** Out of memory\n");
  302. goto cleanup;
  303. }
  304. pRequest->MessageType = SslSessionCacheInfoMessage;
  305. if(fClient)
  306. {
  307. pRequest->Flags |= SSL_RETRIEVE_CLIENT_ENTRIES;
  308. }
  309. if(fServer)
  310. {
  311. pRequest->Flags |= SSL_RETRIEVE_SERVER_ENTRIES;
  312. }
  313. Status = LsaCallAuthenticationPackage(
  314. LsaHandle,
  315. PackageNumber,
  316. pRequest,
  317. sizeof(SSL_SESSION_CACHE_INFO_REQUEST),
  318. &pResponse,
  319. &cbResponse,
  320. &SubStatus);
  321. if(FAILED(Status))
  322. {
  323. printf("**** Error 0x%x returned by LsaCallAuthenticationPackage\n", Status);
  324. goto cleanup;
  325. }
  326. if(FAILED(SubStatus))
  327. {
  328. printf("**** Error 0x%x occurred while reading cache entries.\n", SubStatus);
  329. }
  330. printf("CacheSize: %d \n", pResponse->CacheSize);
  331. printf("Entries: %d \n", pResponse->Entries);
  332. printf("ActiveEntries: %d \n", pResponse->ActiveEntries);
  333. printf("Zombies: %d \n", pResponse->Zombies);
  334. printf("ExpiredZombies: %d \n", pResponse->ExpiredZombies);
  335. printf("AbortedZombies: %d \n", pResponse->AbortedZombies);
  336. printf("DeletedZombies: %d \n", pResponse->DeletedZombies);
  337. printf("\n");
  338. cleanup:
  339. if(pRequest)
  340. {
  341. LocalFree(pRequest);
  342. }
  343. if (pResponse != NULL)
  344. {
  345. LsaFreeReturnBuffer(pResponse);
  346. }
  347. }
  348. void cls(HANDLE hConsole)
  349. {
  350. COORD coordScreen = { 0, 0 }; /* here's where we'll home the
  351. cursor */
  352. BOOL bSuccess;
  353. DWORD cCharsWritten;
  354. CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
  355. DWORD dwConSize; /* number of character cells in
  356. the current buffer */
  357. /* get the number of character cells in the current buffer */
  358. bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
  359. dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
  360. /* fill the entire screen with blanks */
  361. bSuccess = FillConsoleOutputCharacter( hConsole, (TCHAR) ' ',
  362. dwConSize, coordScreen, &cCharsWritten );
  363. /* get the current text attribute */
  364. bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
  365. /* now set the buffer's attributes accordingly */
  366. bSuccess = FillConsoleOutputAttribute( hConsole, csbi.wAttributes,
  367. dwConSize, coordScreen, &cCharsWritten );
  368. /* put the cursor at (0, 0) */
  369. bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );
  370. }
  371. void home(HANDLE hConsole)
  372. {
  373. COORD coordScreen = { 0, 0 }; /* here's where we'll home the
  374. cursor */
  375. BOOL bSuccess;
  376. /* put the cursor at (0, 0) */
  377. bSuccess = SetConsoleCursorPosition( hConsole, coordScreen );
  378. }
  379. void
  380. DisplayCacheInfoInteractive(
  381. HANDLE LsaHandle,
  382. DWORD PackageNumber)
  383. {
  384. HANDLE hConsoleOut;
  385. hConsoleOut = GetStdHandle( STD_OUTPUT_HANDLE );
  386. cls(hConsoleOut);
  387. while(TRUE)
  388. {
  389. home(hConsoleOut);
  390. if(fIncludeClient)
  391. {
  392. printf("--CLIENT--\n");
  393. DisplayCacheInfo(LsaHandle, PackageNumber, TRUE, FALSE);
  394. }
  395. if(fIncludeServer)
  396. {
  397. printf("--SERVER--\n");
  398. DisplayCacheInfo(LsaHandle, PackageNumber, FALSE, TRUE);
  399. }
  400. if(fIncludeClient && fIncludeServer)
  401. {
  402. printf("--TOTAL--\n");
  403. DisplayCacheInfo(LsaHandle, PackageNumber, TRUE, TRUE);
  404. }
  405. Sleep(2000);
  406. }
  407. }