Source code of Windows XP (NT5)
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.

503 lines
14 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 2000
  6. //
  7. // File: logsess.cxx
  8. //
  9. // Contents: LogonSession functions:
  10. //
  11. //
  12. // History: KDamour 15Mar00 Stolen from NTLM
  13. //
  14. //------------------------------------------------------------------------
  15. #include "global.h"
  16. //
  17. // Crit Sect to protect various globals in this module.
  18. //
  19. RTL_CRITICAL_SECTION l_LogSessCritSect;
  20. LIST_ENTRY l_LogSessList;
  21. // Simple variable to make sure that the package was initialize
  22. BOOL g_bLogSessInitialized = FALSE;
  23. //+--------------------------------------------------------------------
  24. //
  25. // Function: LogSessHandlerInit
  26. //
  27. // Synopsis: Initializes the LogonSession manager package
  28. //
  29. // Arguments: none
  30. //
  31. // Returns: NTSTATUS
  32. //
  33. // Notes: Called by SpInitialize
  34. //
  35. //---------------------------------------------------------------------
  36. NTSTATUS
  37. LogSessHandlerInit(VOID)
  38. {
  39. NTSTATUS Status = STATUS_SUCCESS;
  40. //
  41. // Initialize the LogonSession list to be empty.
  42. //
  43. Status = RtlInitializeCriticalSection(&l_LogSessCritSect);
  44. if (!NT_SUCCESS(Status))
  45. {
  46. DebugLog((DEB_ERROR, "LogSessHandlerInit: Failed to initialize critsec 0x%x\n", Status));
  47. goto CleanUp;
  48. }
  49. InitializeListHead( &l_LogSessList );
  50. // Simple variable test to make sure all initialized;
  51. g_bLogSessInitialized = TRUE;
  52. CleanUp:
  53. return Status;
  54. }
  55. NTSTATUS
  56. LogSessHandlerInsert(
  57. IN PDIGEST_LOGONSESSION pDigestLogSess
  58. )
  59. {
  60. RtlEnterCriticalSection( &l_LogSessCritSect );
  61. InsertHeadList( &l_LogSessList, &pDigestLogSess->Next );
  62. RtlLeaveCriticalSection( &l_LogSessCritSect );
  63. return STATUS_SUCCESS;
  64. }
  65. // Initialize the LogSess Structure
  66. NTSTATUS
  67. LogonSessionInit(
  68. IN PDIGEST_LOGONSESSION pLogonSession)
  69. {
  70. NTSTATUS Status = STATUS_SUCCESS;
  71. if (!pLogonSession)
  72. {
  73. return STATUS_INVALID_PARAMETER;
  74. }
  75. ZeroMemory(pLogonSession, sizeof(DIGEST_LOGONSESSION));
  76. pLogonSession->LogonSessionHandle = (ULONG_PTR)pLogonSession;
  77. pLogonSession->lReferences = 1;
  78. return(Status);
  79. }
  80. // Free up memory utilized by LogonSession Structure
  81. NTSTATUS
  82. LogonSessionFree(
  83. IN PDIGEST_LOGONSESSION pDigestLogSess)
  84. {
  85. NTSTATUS Status = STATUS_SUCCESS;
  86. // Free up all Unicode & String structures
  87. UnicodeStringFree(&(pDigestLogSess->ustrAccountName));
  88. UnicodeStringFree(&(pDigestLogSess->ustrDownlevelName));
  89. UnicodeStringFree(&(pDigestLogSess->ustrDomainName));
  90. UnicodeStringFree(&(pDigestLogSess->ustrPassword));
  91. UnicodeStringFree(&(pDigestLogSess->ustrDnsDomainName));
  92. UnicodeStringFree(&(pDigestLogSess->ustrUpn));
  93. UnicodeStringFree(&(pDigestLogSess->ustrLogonServer));
  94. DigestFreeMemory(pDigestLogSess);
  95. return(Status);
  96. }
  97. /*++
  98. Routine Description:
  99. This routine checks to see if the LogonID is from a currently
  100. active client, and references the LogSess if it is valid.
  101. The caller may optionally request that the client's LogSess be
  102. removed from the list of valid LogonSession - preventing future
  103. requests from finding this LogSess.
  104. For a client's LogSess to be valid, the LogSess value
  105. must be on our list of active LogonSession.
  106. Arguments:
  107. LogonSessionHandle - Points to the LogonSession Handle of the LogSess
  108. to be referenced.
  109. ForceRemove - This boolean value indicates whether the caller
  110. wants the logon process's LogSess to be removed from the list
  111. of LogonSession. TRUE indicates the LogSess is to be removed.
  112. FALSE indicates the LogSess is not to be removed.
  113. Return Value:
  114. STATUS_INVALID_HANDLE - the LogSess was not found.
  115. STATUS_SUCCESS - returns a pointer to the referenced LogonSession.
  116. --*/
  117. NTSTATUS
  118. LogSessHandlerLogonIdToPtr(
  119. IN PLUID pLogonId,
  120. IN BOOLEAN ForceRemove,
  121. OUT PDIGEST_LOGONSESSION * ppUserLogonSession
  122. )
  123. {
  124. PLIST_ENTRY ListEntry = NULL;
  125. PDIGEST_LOGONSESSION pLogonSession = NULL;
  126. NTSTATUS Status = STATUS_SUCCESS;
  127. LONG lReferences = 0;
  128. *ppUserLogonSession = NULL ;
  129. //
  130. // Acquire exclusive access to the LogonSession list
  131. //
  132. RtlEnterCriticalSection( &l_LogSessCritSect );
  133. //
  134. // Now walk the list of LogonSession looking for a match.
  135. //
  136. for ( ListEntry = l_LogSessList.Flink;
  137. ListEntry != &l_LogSessList;
  138. ListEntry = ListEntry->Flink )
  139. {
  140. pLogonSession = CONTAINING_RECORD( ListEntry, DIGEST_LOGONSESSION, Next );
  141. if (RtlEqualLuid(&(pLogonSession->LogonId), pLogonId))
  142. {
  143. // Found the LogonSession
  144. DebugLog((DEB_TRACE, "LogSessHandlerLogonIdToPtr: Found LogSess for LogonID (%x:%lx)\n",
  145. pLogonId->HighPart, pLogonId->LowPart ));
  146. if (!ForceRemove)
  147. {
  148. lReferences = InterlockedIncrement(&pLogonSession->lReferences);
  149. DebugLog((DEB_TRACE, "CredHandlerHandleToPtr: Incremented ReferenceCount %ld\n", lReferences));
  150. }
  151. else
  152. {
  153. // ForceRemove of True will unlink this LogonSession from the list of active LogonSessions
  154. // The structure pointet will be returned for the calling function to free up if required
  155. // Would call LogSessHandlerRelease to dereference the counter (and maybe free up)
  156. DebugLog((DEB_TRACE, "LogSessHandlerLogonIdToPtr: Unlinking 0x%lx Refcount = %d\n",
  157. pLogonSession, pLogonSession->lReferences));
  158. RemoveEntryList( &pLogonSession->Next );
  159. }
  160. // Return a pointer to the LogSess found
  161. *ppUserLogonSession = pLogonSession ;
  162. goto CleanUp;
  163. }
  164. }
  165. //
  166. // No match found
  167. //
  168. DebugLog((DEB_WARN, "LogSessHandlerLogonIdToPtr: Tried to reference unknown LogonID (%x:%lx)\n",
  169. pLogonId->HighPart, pLogonId->LowPart ));
  170. Status = STATUS_INVALID_HANDLE;
  171. CleanUp:
  172. RtlLeaveCriticalSection( &l_LogSessCritSect );
  173. return(Status);
  174. }
  175. // Locate a LogonSession based on a Principal Name (UserName) ok
  176. NTSTATUS
  177. LogSessHandlerAccNameToPtr(
  178. IN PUNICODE_STRING pustrAccountName,
  179. OUT PDIGEST_LOGONSESSION *ppUserLogonSession
  180. )
  181. {
  182. PLIST_ENTRY ListEntry = NULL;
  183. PDIGEST_LOGONSESSION pLogonSession = NULL;
  184. NTSTATUS Status = STATUS_SUCCESS;
  185. LONG lReferences = 0;
  186. *ppUserLogonSession = NULL ;
  187. if ((!pustrAccountName) || (!pustrAccountName->Length))
  188. {
  189. DebugLog((DEB_ERROR, "LogSessHandlerAccNameToPtr: No AccountName provided\n"));
  190. Status = STATUS_INVALID_PARAMETER_1;
  191. return(Status);
  192. }
  193. //
  194. // Acquire exclusive access to the LogonSession list
  195. //
  196. RtlEnterCriticalSection( &l_LogSessCritSect );
  197. //
  198. // Now walk the list of LogonSession looking for a match.
  199. //
  200. for ( ListEntry = l_LogSessList.Flink;
  201. ListEntry != &l_LogSessList;
  202. ListEntry = ListEntry->Flink )
  203. {
  204. pLogonSession = CONTAINING_RECORD( ListEntry, DIGEST_LOGONSESSION, Next );
  205. if ((pLogonSession->ustrAccountName).Length)
  206. {
  207. DebugLog((DEB_TRACE, "LogSessHandlerAccNameToPtr: Checking %wZ against AccountName %wZ\n",
  208. &(pLogonSession->ustrAccountName), pustrAccountName ));
  209. if (RtlEqualUnicodeString(&(pLogonSession->ustrAccountName), pustrAccountName, TRUE))
  210. {
  211. lReferences = InterlockedIncrement(&pLogonSession->lReferences);
  212. DebugLog((DEB_TRACE, "LogSessHandlerAccNameToPtr: Incremented ReferenceCount %ld\n", lReferences));
  213. // Found the LogonSession
  214. *ppUserLogonSession = pLogonSession ;
  215. goto CleanUp;
  216. }
  217. }
  218. }
  219. //
  220. // No match found
  221. //
  222. DebugLog((DEB_WARN, "LogSessHandlerAccNameToPtr: Tried to reference unknown AccountName %wZ\n",
  223. pustrAccountName ));
  224. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  225. CleanUp:
  226. RtlLeaveCriticalSection( &l_LogSessCritSect );
  227. return(Status);
  228. }
  229. //+--------------------------------------------------------------------
  230. //
  231. // Function: LogSessHandlerRelease
  232. //
  233. // Synopsis: Releases the LogonSession by decrementing reference counter
  234. //
  235. // Arguments: pLogonSession - pointer to logonsession to de-reference
  236. //
  237. // Returns: NTSTATUS
  238. //
  239. // Notes: Called by ACH & AcceptCredentials. Since multiple threads can have a context
  240. // checked out, simply decrease the reference counter on release. LsaApLogonTerminated
  241. // is called by LSA to remove the LogonSession from the Active LIst.
  242. // There can be atmost only 1 reference for a handle (owned by LSA and release by call
  243. // to this function). The other references will be pointer references so these can
  244. // be decremented without it being attached to active logonsession list.
  245. //
  246. //---------------------------------------------------------------------
  247. NTSTATUS
  248. LogSessHandlerRelease(
  249. PDIGEST_LOGONSESSION pLogonSession)
  250. {
  251. NTSTATUS Status = STATUS_SUCCESS;
  252. LONG lReferences = 0;
  253. DebugLog((DEB_TRACE_FUNC, "LogSessHandlerRelease: Entering for LogonSession 0x%0x LogonID (%x:%lx) \n",
  254. pLogonSession, pLogonSession->LogonId.HighPart, pLogonSession->LogonId.LowPart));
  255. lReferences = InterlockedDecrement(&pLogonSession->lReferences);
  256. DebugLog((DEB_TRACE, "LogSessHandlerRelease: Decremented to ReferenceCount %ld\n", lReferences));
  257. ASSERT( lReferences >= 0 );
  258. //
  259. // If the count has dropped to zero, then free all alloced stuff
  260. //
  261. if (lReferences == 0)
  262. {
  263. DebugLog((DEB_TRACE, "LogSessHandlerRelease: Deleting LogonSession\n"));
  264. Status = LogonSessionFree(pLogonSession);
  265. }
  266. DebugLog((DEB_TRACE_FUNC, "LogSessHandlerRelease: Leaving Status 0x%x\n", Status));
  267. return(Status);
  268. }
  269. // Helper functions for processing fields within the logonsessions
  270. //+--------------------------------------------------------------------
  271. //
  272. // Function: LogSessHandlerPasswdSet
  273. //
  274. // Synopsis: Set the unicode string password in the LogonSession
  275. //
  276. // Arguments: pLogonID - pointer to LogonSession LogonID to use
  277. // pustrPasswd - pointer to new password
  278. //
  279. // Returns: NTSTATUS
  280. //
  281. // Notes:
  282. //
  283. //---------------------------------------------------------------------
  284. NTSTATUS
  285. LogSessHandlerPasswdSet(
  286. IN PLUID pLogonId,
  287. IN PUNICODE_STRING pustrPasswd)
  288. {
  289. PLIST_ENTRY ListEntry = NULL;
  290. PDIGEST_LOGONSESSION pLogonSession = NULL;
  291. NTSTATUS Status = STATUS_SUCCESS;
  292. DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdSet: Entering LogonID (%x:%lx)\n",
  293. pLogonId->HighPart, pLogonId->LowPart));
  294. //
  295. // Acquire exclusive access to the LogonSession list
  296. //
  297. RtlEnterCriticalSection( &l_LogSessCritSect );
  298. //
  299. // Now walk the list of LogonSession looking for a match.
  300. //
  301. for ( ListEntry = l_LogSessList.Flink;
  302. ListEntry != &l_LogSessList;
  303. ListEntry = ListEntry->Flink )
  304. {
  305. pLogonSession = CONTAINING_RECORD( ListEntry, DIGEST_LOGONSESSION, Next );
  306. if (RtlEqualLuid(&(pLogonSession->LogonId), pLogonId))
  307. {
  308. // Found the LogonSession
  309. DebugLog((DEB_TRACE, "LogSessHandlerLogonIdToPtr: Found LogSess with LogonID (%x:%lx)\n",
  310. pLogonId->HighPart, pLogonId->LowPart ));
  311. if (pLogonSession->ustrPassword.Buffer)
  312. {
  313. UnicodeStringFree(&(pLogonSession->ustrPassword));
  314. }
  315. Status = UnicodeStringDuplicatePassword(&(pLogonSession->ustrPassword), pustrPasswd);
  316. if (!NT_SUCCESS(Status))
  317. {
  318. DebugLog((DEB_ERROR, "LogSessHandlerPasswdGet: Error in setting LogonSession password, status 0x%0x\n", Status ));
  319. goto CleanUp;
  320. }
  321. DebugLog((DEB_TRACE, "LogSessHandlerPasswdSet: updated password\n"));
  322. goto CleanUp;
  323. }
  324. }
  325. //
  326. // No match found
  327. //
  328. DebugLog((DEB_WARN, "LogSessHandlerPasswdSet: Unable to locate LogonID (%x:%lx) \n",
  329. pLogonId->HighPart, pLogonId->LowPart ));
  330. Status = STATUS_INVALID_HANDLE;
  331. CleanUp:
  332. RtlLeaveCriticalSection( &l_LogSessCritSect );
  333. DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdSet: Exiting LogonID (%x:%lx)\n",
  334. pLogonId->HighPart, pLogonId->LowPart));
  335. return(Status);
  336. }
  337. //+--------------------------------------------------------------------
  338. //
  339. // Function: LogSessHandlerPasswdGet
  340. //
  341. // Synopsis: Get the unicode string password in the logonsession
  342. //
  343. // Arguments: pLogonSession - pointer to LogonSession to use
  344. // pustrPasswd - pointer to destination copy of password
  345. //
  346. // Returns: NTSTATUS
  347. //
  348. // Notes:
  349. //
  350. //---------------------------------------------------------------------
  351. NTSTATUS
  352. LogSessHandlerPasswdGet(
  353. IN PDIGEST_LOGONSESSION pLogonSession,
  354. OUT PUNICODE_STRING pustrPasswd)
  355. {
  356. NTSTATUS Status = STATUS_SUCCESS;
  357. DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdGet: Entering\n" ));
  358. if (pustrPasswd->Buffer)
  359. {
  360. UnicodeStringFree(pustrPasswd);
  361. }
  362. // Protect reading from the LogonSession
  363. RtlEnterCriticalSection( &l_LogSessCritSect );
  364. Status = UnicodeStringDuplicatePassword(pustrPasswd, &(pLogonSession->ustrPassword));
  365. RtlLeaveCriticalSection( &l_LogSessCritSect );
  366. if (!NT_SUCCESS(Status))
  367. {
  368. DebugLog((DEB_ERROR, "LogSessHandlerPasswdGet: Error in getting LogonSession password, status 0x%0x\n", Status ));
  369. }
  370. DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdGet: Exiting, status 0x%0x\n", Status ));
  371. return(Status);
  372. }