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.

592 lines
19 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. token.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Ramon J San Andres (ramonsa) 8-Nov-1993
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. DECLARE_API( logonsession )
  16. /*++
  17. Routine Description
  18. This extension will dump all logon sessions in the system, or the specified session.
  19. Arguments
  20. !logonsession LUID InfoLevel
  21. where luid is the session to dump (or 0 for all sessions) and levels are 1-4.
  22. Return Value
  23. S_OK or E_INVALIDARG
  24. --*/
  25. {
  26. //
  27. // Arguments
  28. //
  29. ULONG64 LogonId = 0;
  30. ULONG Level = 0;
  31. BOOLEAN bAll = FALSE;
  32. //
  33. // ntoskrnl globals
  34. //
  35. ULONG64 NtBuildNumber = 0;
  36. ULONG64 SepLogonSessions = 0;
  37. ULONG64 SepTokenLeakTracking = 0;
  38. //
  39. // for manipulating the LogonSessions tables
  40. //
  41. ULONG64 SessionList = 0;
  42. ULONG64 CurrentSession = 0;
  43. ULONG64 NextSession = 0;
  44. //
  45. // for manipulating a particular session
  46. //
  47. ULONG64 TokenListHead = 0;
  48. ULONG64 NextTokenLink = 0;
  49. ULONG64 CurrentTokenLink = 0;
  50. ULONG64 Token = 0;
  51. ULONG References = 0;
  52. ULONG TokenCount = 0;
  53. ULONG SessionCount = 0;
  54. LUID SessionLuid = {0};
  55. NTSTATUS Status = STATUS_SUCCESS;
  56. BOOLEAN Found = FALSE;
  57. BOOLEAN bChecked = FALSE;
  58. LONG PointerSize = 0;
  59. #define DUMP_TOKENS 0x1
  60. #define DUMP_SOME_TOKEN_INFO 0x2
  61. #define DUMP_LOTS_OF_TOKEN_INFO 0x3
  62. #define DUMP_TONS_OF_TOKEN_INFO 0x4
  63. #define VALID_SESSION_ADDRESS(x) (SepLogonSessions <= (x) && (x) <= (SepLogonSessions + 0xf * sizeof(ULONG_PTR)))
  64. if (strlen(args) < 1)
  65. {
  66. dprintf("usage: !logonsession LogonId [InfoLevel 1-4]\n");
  67. dprintf("\tuse LogonId = 0 to list all sessions\n");
  68. dprintf("\n\texample: \"!logonsession 3e7 1\" displays system session and all system tokens.\n");
  69. return E_INVALIDARG;
  70. }
  71. if (!GetExpressionEx(
  72. args,
  73. &LogonId,
  74. &args))
  75. {
  76. return E_INVALIDARG;
  77. }
  78. if (args && *args)
  79. {
  80. Level = (ULONG) GetExpression(args);
  81. }
  82. if (LogonId == 0)
  83. {
  84. bAll = TRUE;
  85. dprintf("\nDumping all logon sessions.\n\n");
  86. }
  87. else
  88. {
  89. dprintf("\nSearching for logon session with ID = 0x%x\n\n", LogonId);
  90. }
  91. //
  92. // read in relevant variables
  93. //
  94. SepLogonSessions = GetPointerValue("nt!SepLogonSessions");
  95. NtBuildNumber = GetPointerValue("nt!NtBuildNumber");
  96. //
  97. // This is bad but I don't know the right way to figure this out.
  98. //
  99. if ((SepLogonSessions & 0xffffffff00000000) == 0xffffffff00000000)
  100. {
  101. PointerSize = 4;
  102. }
  103. else
  104. {
  105. PointerSize = 8;
  106. }
  107. //
  108. // See if this is a checked build.
  109. //
  110. if (((ULONG)NtBuildNumber & 0xF0000000) == 0xC0000000)
  111. {
  112. bChecked = TRUE;
  113. //
  114. // It is a checked build, so see the value of SepTokenLeakTracking (valid symbol only on chk)
  115. //
  116. SepTokenLeakTracking = GetPointerValue("nt!SepTokenLeakTracking");
  117. if (SepTokenLeakTracking)
  118. {
  119. dprintf("TokenLeakTracking is ON. Use !tokenleak to view settings.\n\n");
  120. }
  121. }
  122. SessionList = SepLogonSessions;
  123. if (!bAll)
  124. {
  125. //
  126. // we want a particular index into the table
  127. //
  128. SessionList += PointerSize * (LogonId & 0xf);
  129. }
  130. //
  131. // SessionList currently points at the beginning of a list indexed in SepLogonSessions.
  132. // Dump it out, printing either all of the entries or only one with a matching LUID.
  133. //
  134. do
  135. {
  136. if (CheckControlC())
  137. {
  138. return S_OK;
  139. }
  140. CurrentSession = GetPointerFromAddress(SessionList);
  141. while (0 != CurrentSession)
  142. {
  143. if (CheckControlC())
  144. {
  145. return S_OK;
  146. }
  147. //
  148. // Get the LUID for the CurrentSession
  149. //
  150. GetFieldValue(CurrentSession, "SEP_LOGON_SESSION_REFERENCES", "LogonId", SessionLuid);
  151. //
  152. // if caller wants all sessions, or this one, print it.
  153. //
  154. if (bAll || SessionLuid.LowPart == LogonId)
  155. {
  156. Found = TRUE;
  157. GetFieldValue(CurrentSession, "SEP_LOGON_SESSION_REFERENCES", "ReferenceCount", References);
  158. if (bAll)
  159. {
  160. dprintf("** Session %3d = 0x%x\n", SessionCount, CurrentSession);
  161. }
  162. else
  163. {
  164. dprintf("** Session = 0x%x\n", CurrentSession);
  165. }
  166. dprintf(" LogonId = {0x%x 0x%x}\n", SessionLuid.LowPart, SessionLuid.HighPart);
  167. dprintf(" References = %d\n", References);
  168. SessionCount++;
  169. //
  170. // If Level dictates then print out lots more stuff.
  171. //
  172. if (Level != 0)
  173. {
  174. if (bChecked == FALSE)
  175. {
  176. dprintf("\nNo InfoLevels are valid on free builds.\n");
  177. }
  178. else
  179. {
  180. TokenCount = 0;
  181. //
  182. // retrieve the token list from the session
  183. //
  184. if (0 == GetFieldValue(
  185. CurrentSession,
  186. "SEP_LOGON_SESSION_REFERENCES",
  187. "TokenList",
  188. TokenListHead
  189. ))
  190. {
  191. CurrentTokenLink = TokenListHead;
  192. do
  193. {
  194. if (CheckControlC())
  195. {
  196. return S_OK;
  197. }
  198. GetFieldValue(
  199. CurrentTokenLink,
  200. "SEP_LOGON_SESSION_TOKEN",
  201. "Token",
  202. Token
  203. );
  204. GetFieldValue(
  205. CurrentTokenLink,
  206. "SEP_LOGON_SESSION_TOKEN",
  207. "ListEntry",
  208. NextTokenLink
  209. );
  210. if (NextTokenLink != TokenListHead)
  211. {
  212. if (TokenCount == 0)
  213. {
  214. ULONG DefaultOwnerIndex = 0;
  215. ULONG64 UserAndGroups = 0;
  216. UNICODE_STRING SidString = {0};
  217. ULONG64 SidAttr = 0;
  218. ULONG64 pSid = 0;
  219. ULONG ActualRead = 0;
  220. UCHAR Buffer[256];
  221. GetFieldValue(Token, "nt!_TOKEN", "DefaultOwnerIndex", DefaultOwnerIndex);
  222. GetFieldValue(Token, "nt!_TOKEN", "UserAndGroups", UserAndGroups);
  223. SidAttr = UserAndGroups + (DefaultOwnerIndex * sizeof(SID_AND_ATTRIBUTES));
  224. GetFieldValue(SidAttr, "_SID_AND_ATTRIBUTES", "Sid", pSid);
  225. dprintf(" Usersid = 0x%x ", pSid);
  226. ReadMemory(pSid, Buffer, sizeof(Buffer), &ActualRead);
  227. Status = RtlConvertSidToUnicodeString(&SidString, (PSID)Buffer, TRUE);
  228. if (NT_SUCCESS(Status))
  229. {
  230. dprintf("(%S)\n", SidString.Buffer);
  231. RtlFreeUnicodeString(&SidString);
  232. }
  233. else
  234. {
  235. dprintf("!! RtlConvertSidToUnicodeString failed 0x%x\n", Status);
  236. }
  237. dprintf(" Tokens:\n");
  238. }
  239. TokenCount++;
  240. CurrentTokenLink = NextTokenLink;
  241. dprintf(" 0x%x ", Token);
  242. if (Level > DUMP_TOKENS)
  243. {
  244. UCHAR ImageFileName[16];
  245. ULONG BodyOffset = 0;
  246. ULONG64 ProcessCid = 0;
  247. ULONG64 ObjectHeader = 0;
  248. ULONG64 HandleCount = 0;
  249. ULONG64 PointerCount = 0;
  250. GetFieldValue(Token, "nt!_TOKEN", "ImageFileName", ImageFileName);
  251. GetFieldValue(Token, "nt!_TOKEN", "ProcessCid", ProcessCid);
  252. dprintf(": %13s (%3x) ", ImageFileName, ProcessCid);
  253. GetFieldOffset("nt!_OBJECT_HEADER", "Body", &BodyOffset);
  254. ObjectHeader = Token - BodyOffset;
  255. GetFieldValue(ObjectHeader, "nt!_OBJECT_HEADER", "PointerCount", PointerCount);
  256. GetFieldValue(ObjectHeader, "nt!_OBJECT_HEADER", "HandleCount", HandleCount);
  257. dprintf(": HandleCount = 0x%I64x PointerCount = 0x%I64x ", HandleCount, PointerCount);
  258. }
  259. if (Level > DUMP_SOME_TOKEN_INFO)
  260. {
  261. ULONG CreateMethod = 0;
  262. GetFieldValue(Token, "nt!_TOKEN", "CreateMethod", CreateMethod);
  263. switch (CreateMethod)
  264. {
  265. case 0xD:
  266. dprintf(": SepDuplicateToken ");
  267. break;
  268. case 0xC:
  269. dprintf(": SepCreateToken ");
  270. break;
  271. case 0xF:
  272. dprintf(": SepFilterToken ");
  273. break;
  274. default:
  275. dprintf(": Unknown Method ");
  276. break;
  277. }
  278. if (Level > DUMP_LOTS_OF_TOKEN_INFO)
  279. {
  280. ULONG TokenType = 0;
  281. ULONG ImpersonationLevel = 0;
  282. ULONG SessionId = 0;
  283. ULONG Count = 0;
  284. GetFieldValue(Token, "nt!_TOKEN", "TokenType", TokenType);
  285. GetFieldValue(Token, "nt!_TOKEN", "ImpersonationLevel", ImpersonationLevel);
  286. GetFieldValue(Token, "nt!_TOKEN", "SessionId", SessionId);
  287. GetFieldValue(Token, "nt!_TOKEN", "Count", Count);
  288. dprintf(": Type %d ", TokenType);
  289. dprintf(": Level %d ", ImpersonationLevel);
  290. dprintf(": SessionId %d ", SessionId);
  291. if (SepTokenLeakTracking)
  292. {
  293. dprintf(": MethodCount = %3x ", Count);
  294. }
  295. }
  296. }
  297. }
  298. dprintf("\n");
  299. } while (NextTokenLink != TokenListHead);
  300. dprintf(" %d Tokens listed.\n\n", TokenCount);
  301. }
  302. }
  303. }
  304. }
  305. GetFieldValue(CurrentSession, "SEP_LOGON_SESSION_REFERENCES", "Next", NextSession);
  306. CurrentSession = NextSession;
  307. }
  308. if (bAll)
  309. {
  310. SessionList += sizeof(ULONG_PTR);
  311. }
  312. }
  313. while (bAll && VALID_SESSION_ADDRESS(SessionList));
  314. if (bAll)
  315. {
  316. dprintf("%d sessions in the system.\n", SessionCount);
  317. }
  318. if (!bAll && !Found)
  319. {
  320. dprintf("Session not found.\n");
  321. }
  322. return S_OK;
  323. }
  324. DECLARE_API( tokenleak )
  325. /*++
  326. Routine Description
  327. !tokenleak displays or sets the Se globals that facilitate tracking and finding token leaks.
  328. Arguments
  329. usage: !tokenleak [1 | 0 ProcessCid BreakCount MethodWatch]
  330. where 1 activates and 0 disables token leak tracking
  331. where ProcessCid is Cid of process to monitor (in hex)
  332. where BreakCount specifies which numbered call to Method to break on (in hex)
  333. where MethodWatch specifies which token method to watch (C D or F)
  334. --*/
  335. {
  336. //
  337. // Nt Globals.
  338. //
  339. ULONG64 SepTokenLeakTracking = 0;
  340. ULONG64 SepTokenLeakMethodWatch = 0;
  341. ULONG64 SepTokenLeakMethodCount = 0;
  342. ULONG64 SepTokenLeakBreakCount = 0;
  343. ULONG64 SepTokenLeakProcessCid = 0;
  344. ULONG64 SepTokenLeakTrackingAddr = 0;
  345. ULONG64 SepTokenLeakMethodWatchAddr = 0;
  346. ULONG64 SepTokenLeakMethodCountAddr = 0;
  347. ULONG64 SepTokenLeakBreakCountAddr = 0;
  348. ULONG64 SepTokenLeakProcessCidAddr = 0;
  349. ULONG64 NtBuildNumber = 0;
  350. BOOLEAN bModify = TRUE;
  351. ULONG64 InputOn = 0;
  352. ULONG64 InputCid = 0;
  353. ULONG64 InputMethodWatch = 0;
  354. ULONG64 InputBreakCount = 0;
  355. if (strlen(args) < 1)
  356. {
  357. dprintf("usage: !tokenleak [1 | 0 ProcessCid BreakCount MethodWatch]\n");
  358. dprintf("\t where 1 activates and 0 disables token leak tracking\n");
  359. dprintf("\t where ProcessCid is Cid of process to monitor (in hex)\n");
  360. dprintf("\t where BreakCount specifies which numbered call to Method to break on (in hex)\n");
  361. dprintf("\t where MethodWatch specifies which token method to watch (C D or F)\n\n");
  362. bModify = FALSE;
  363. }
  364. NtBuildNumber = GetPointerValue("nt!NtBuildNumber");
  365. if (((ULONG)NtBuildNumber & 0xf0000000) == 0xF0000000)
  366. {
  367. dprintf("This extension only works on checked builds.\n");
  368. return S_OK;
  369. }
  370. if (bModify)
  371. {
  372. SepTokenLeakTrackingAddr = GetExpression("SepTokenLeakTracking");
  373. SepTokenLeakMethodWatchAddr = GetExpression("SepTokenLeakMethodWatch");
  374. SepTokenLeakMethodCountAddr = GetExpression("SepTokenLeakMethodCount");
  375. SepTokenLeakBreakCountAddr = GetExpression("SepTokenLeakBreakCount");
  376. SepTokenLeakProcessCidAddr = GetExpression("SepTokenLeakProcessCid");
  377. if (!GetExpressionEx(
  378. args,
  379. &InputOn,
  380. &args))
  381. {
  382. return E_INVALIDARG;
  383. }
  384. WritePointer(SepTokenLeakTrackingAddr, InputOn);
  385. if (InputOn != 0)
  386. {
  387. dprintf("\nToken leak tracking is ON.\n\n");
  388. while (args && (*args == ' '))
  389. {
  390. args++;
  391. }
  392. if (!GetExpressionEx(
  393. args,
  394. &InputCid,
  395. &args))
  396. {
  397. return E_INVALIDARG;
  398. }
  399. while (args && (*args == ' '))
  400. {
  401. args++;
  402. }
  403. if (!GetExpressionEx(
  404. args,
  405. &InputBreakCount,
  406. &args))
  407. {
  408. return E_INVALIDARG;
  409. }
  410. while (args && (*args == ' '))
  411. {
  412. args++;
  413. }
  414. if (!GetExpressionEx(
  415. args,
  416. &InputMethodWatch,
  417. &args))
  418. {
  419. return E_INVALIDARG;
  420. }
  421. WritePointer(SepTokenLeakProcessCidAddr, InputCid);
  422. WritePointer(SepTokenLeakBreakCountAddr, InputBreakCount);
  423. WritePointer(SepTokenLeakMethodCountAddr, 0);
  424. WritePointer(SepTokenLeakMethodWatchAddr, InputMethodWatch);
  425. }
  426. }
  427. //
  428. // Print out the current settings.
  429. //
  430. SepTokenLeakTracking = GetPointerValue("SepTokenLeakTracking");
  431. SepTokenLeakMethodWatch = GetPointerValue("SepTokenLeakMethodWatch");
  432. SepTokenLeakMethodCount = GetPointerValue("SepTokenLeakMethodCount");
  433. SepTokenLeakBreakCount = GetPointerValue("SepTokenLeakBreakCount");
  434. SepTokenLeakProcessCid = GetPointerValue("SepTokenLeakProcessCid");
  435. if (SepTokenLeakTracking)
  436. {
  437. dprintf(" Currently watched method = ");
  438. switch (SepTokenLeakMethodWatch)
  439. {
  440. case 0xD:
  441. dprintf("SepDuplicateToken\n");
  442. break;
  443. case 0xC:
  444. dprintf("SepCreateToken\n");
  445. break;
  446. case 0xF:
  447. dprintf("SepFilterToken\n");
  448. break;
  449. default:
  450. dprintf("???\n");
  451. }
  452. dprintf(" Currently watched process = 0x%x\n", SepTokenLeakProcessCid);
  453. dprintf(" Method call count = 0x%x\n", SepTokenLeakMethodCount);
  454. dprintf(" Will break at count = 0x%x\n", SepTokenLeakBreakCount);
  455. }
  456. else
  457. {
  458. dprintf("\nToken leak tracking is OFF\n");
  459. }
  460. return S_OK;
  461. }