2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/lsasrv/session.c
5 * PURPOSE: Logon session management routines
6 * COPYRIGHT: Copyright 2013 Eric Kohl
11 typedef struct _LSAP_LOGON_SESSION
17 LARGE_INTEGER LogonTime
;
19 UNICODE_STRING UserName
;
20 UNICODE_STRING LogonDomain
;
21 UNICODE_STRING AuthenticationPackage
;
22 UNICODE_STRING LogonServer
;
23 UNICODE_STRING DnsDomainName
;
25 } LSAP_LOGON_SESSION
, *PLSAP_LOGON_SESSION
;
28 /* GLOBALS *****************************************************************/
30 LIST_ENTRY SessionListHead
;
33 /* FUNCTIONS ***************************************************************/
36 LsapInitLogonSessions(VOID
)
38 InitializeListHead(&SessionListHead
);
45 LsapGetLogonSession(IN PLUID LogonId
)
47 PLIST_ENTRY SessionEntry
;
48 PLSAP_LOGON_SESSION CurrentSession
;
50 SessionEntry
= SessionListHead
.Flink
;
51 while (SessionEntry
!= &SessionListHead
)
53 CurrentSession
= CONTAINING_RECORD(SessionEntry
,
56 if (RtlEqualLuid(&CurrentSession
->LogonId
, LogonId
))
57 return CurrentSession
;
59 SessionEntry
= SessionEntry
->Flink
;
67 LsapSetLogonSessionData(
70 _In_ PUNICODE_STRING UserName
,
71 _In_ PUNICODE_STRING LogonDomain
,
74 PLSAP_LOGON_SESSION Session
;
77 TRACE("LsapSetLogonSessionData(%p)\n", LogonId
);
79 Session
= LsapGetLogonSession(LogonId
);
81 return STATUS_NO_SUCH_LOGON_SESSION
;
83 TRACE("LogonType %lu\n", LogonType
);
84 Session
->LogonType
= LogonType
;
86 TRACE("UserName %wZ\n", UserName
);
87 Session
->UserName
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, UserName
->MaximumLength
);
88 if (Session
->UserName
.Buffer
== NULL
)
89 return STATUS_INSUFFICIENT_RESOURCES
;
91 Session
->UserName
.Length
= UserName
->Length
;
92 Session
->UserName
.MaximumLength
= UserName
->MaximumLength
;
93 RtlCopyMemory(Session
->UserName
.Buffer
, UserName
->Buffer
, UserName
->MaximumLength
);
95 TRACE("LogonDomain %wZ\n", LogonDomain
);
96 Session
->LogonDomain
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, LogonDomain
->MaximumLength
);
97 if (Session
->LogonDomain
.Buffer
== NULL
)
98 return STATUS_INSUFFICIENT_RESOURCES
;
100 Session
->LogonDomain
.Length
= LogonDomain
->Length
;
101 Session
->LogonDomain
.MaximumLength
= LogonDomain
->MaximumLength
;
102 RtlCopyMemory(Session
->LogonDomain
.Buffer
, LogonDomain
->Buffer
, LogonDomain
->MaximumLength
);
104 Length
= RtlLengthSid(Sid
);
105 Session
->Sid
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, Length
);
106 if (Session
->UserName
.Buffer
== NULL
)
107 return STATUS_INSUFFICIENT_RESOURCES
;
109 RtlCopyMemory(Session
->Sid
, Sid
, Length
);
111 return STATUS_SUCCESS
;
117 LsapCreateLogonSession(IN PLUID LogonId
)
119 PLSAP_LOGON_SESSION Session
;
122 TRACE("LsapCreateLogonSession(%p)\n", LogonId
);
124 /* Fail, if a session already exists */
125 if (LsapGetLogonSession(LogonId
) != NULL
)
126 return STATUS_LOGON_SESSION_COLLISION
;
128 /* Allocate a new session entry */
129 Session
= RtlAllocateHeap(RtlGetProcessHeap(),
131 sizeof(LSAP_LOGON_SESSION
));
133 return STATUS_INSUFFICIENT_RESOURCES
;
135 /* Initialize the session entry */
136 RtlCopyLuid(&Session
->LogonId
, LogonId
);
138 TRACE("LsapCreateLogonSession(<0x%lx,0x%lx>)\n",
139 LogonId
->HighPart
, LogonId
->LowPart
);
141 /* Tell ntoskrnl to create a new logon session */
142 Status
= LsapRmCreateLogonSession(LogonId
);
143 if (!NT_SUCCESS(Status
))
145 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
);
149 /* Insert the new session into the session list */
150 InsertHeadList(&SessionListHead
, &Session
->Entry
);
153 return STATUS_SUCCESS
;
159 LsapDeleteLogonSession(IN PLUID LogonId
)
161 PLSAP_LOGON_SESSION Session
;
164 TRACE("LsapDeleteLogonSession(%p)\n", LogonId
);
166 /* Fail, if the session does not exist */
167 Session
= LsapGetLogonSession(LogonId
);
169 return STATUS_NO_SUCH_LOGON_SESSION
;
171 TRACE("LsapDeleteLogonSession(<0x%lx,0x%lx>)\n",
172 LogonId
->HighPart
, LogonId
->LowPart
);
174 /* Tell ntoskrnl to delete the logon session */
175 Status
= LsapRmDeleteLogonSession(LogonId
);
176 if (!NT_SUCCESS(Status
))
179 /* Remove the session entry from the list */
180 RemoveEntryList(&Session
->Entry
);
183 /* Free the session data */
184 if (Session
->Sid
!= NULL
)
185 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
->Sid
);
187 if (Session
->UserName
.Buffer
!= NULL
)
188 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
->UserName
.Buffer
);
190 if (Session
->LogonDomain
.Buffer
!= NULL
)
191 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
->LogonDomain
.Buffer
);
193 if (Session
->AuthenticationPackage
.Buffer
!= NULL
)
194 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
->AuthenticationPackage
.Buffer
);
196 if (Session
->LogonServer
.Buffer
!= NULL
)
197 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
->LogonServer
.Buffer
);
199 if (Session
->DnsDomainName
.Buffer
!= NULL
)
200 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
->DnsDomainName
.Buffer
);
202 if (Session
->Upn
.Buffer
!= NULL
)
203 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
->Upn
.Buffer
);
205 /* Free the session entry */
206 RtlFreeHeap(RtlGetProcessHeap(), 0, Session
);
208 return STATUS_SUCCESS
;
216 _In_ ULONG AuthenticationPackage
,
217 _In_ PLSA_STRING PrimaryKeyValue
,
218 _In_ PLSA_STRING Credential
)
221 return STATUS_SUCCESS
;
229 _In_ ULONG AuthenticationPackage
,
230 _Inout_ PULONG QueryContext
,
231 _In_ BOOLEAN RetrieveAllCredentials
,
232 _Inout_ PLSA_STRING PrimaryKeyValue
,
233 _Out_ PULONG PrimaryKeyLength
,
234 _Out_ PLSA_STRING Credentials
)
237 return STATUS_SUCCESS
;
243 LsapDeleteCredential(
245 _In_ ULONG AuthenticationPackage
,
246 _In_ PLSA_STRING PrimaryKeyValue
)
249 return STATUS_SUCCESS
;
254 LsapEnumLogonSessions(IN OUT PLSA_API_MSG RequestMsg
)
256 OBJECT_ATTRIBUTES ObjectAttributes
;
257 HANDLE ProcessHandle
= NULL
;
258 PLIST_ENTRY SessionEntry
;
259 PLSAP_LOGON_SESSION CurrentSession
;
263 PVOID ClientBaseAddress
= NULL
;
266 TRACE("LsapEnumLogonSessions(%p)\n", RequestMsg
);
268 Length
= SessionCount
* sizeof(LUID
);
269 SessionList
= RtlAllocateHeap(RtlGetProcessHeap(),
272 if (SessionList
== NULL
)
273 return STATUS_INSUFFICIENT_RESOURCES
;
276 SessionEntry
= SessionListHead
.Flink
;
277 while (SessionEntry
!= &SessionListHead
)
279 CurrentSession
= CONTAINING_RECORD(SessionEntry
,
283 RtlCopyLuid(&SessionList
[i
],
284 &CurrentSession
->LogonId
);
286 SessionEntry
= SessionEntry
->Flink
;
290 InitializeObjectAttributes(&ObjectAttributes
,
296 Status
= NtOpenProcess(&ProcessHandle
,
297 PROCESS_VM_READ
| PROCESS_VM_WRITE
| PROCESS_VM_OPERATION
,
299 &RequestMsg
->h
.ClientId
);
300 if (!NT_SUCCESS(Status
))
302 TRACE("NtOpenProcess() failed (Status %lx)\n", Status
);
306 TRACE("Length: %lu\n", Length
);
309 Status
= NtAllocateVirtualMemory(ProcessHandle
,
315 if (!NT_SUCCESS(Status
))
317 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
321 TRACE("MemSize: %lu\n", MemSize
);
322 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress
);
324 Status
= NtWriteVirtualMemory(ProcessHandle
,
329 if (!NT_SUCCESS(Status
))
331 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status
);
335 RequestMsg
->EnumLogonSessions
.Reply
.LogonSessionCount
= SessionCount
;
336 RequestMsg
->EnumLogonSessions
.Reply
.LogonSessionBuffer
= ClientBaseAddress
;
339 if (ProcessHandle
!= NULL
)
340 NtClose(ProcessHandle
);
342 if (SessionList
!= NULL
)
343 RtlFreeHeap(RtlGetProcessHeap(), 0, SessionList
);
350 LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg
)
352 OBJECT_ATTRIBUTES ObjectAttributes
;
353 HANDLE ProcessHandle
= NULL
;
354 PLSAP_LOGON_SESSION Session
;
355 PSECURITY_LOGON_SESSION_DATA LocalSessionData
;
356 PVOID ClientBaseAddress
= NULL
;
357 ULONG TotalLength
, SidLength
= 0;
362 TRACE("LsapGetLogonSessionData(%p)\n", RequestMsg
);
364 TRACE("LogonId: %lx\n", RequestMsg
->GetLogonSessionData
.Request
.LogonId
.LowPart
);
365 Session
= LsapGetLogonSession(&RequestMsg
->GetLogonSessionData
.Request
.LogonId
);
367 return STATUS_NO_SUCH_LOGON_SESSION
;
369 /* Calculate the required buffer size */
370 TotalLength
= sizeof(SECURITY_LOGON_SESSION_DATA
) +
371 Session
->UserName
.MaximumLength
+
372 Session
->LogonDomain
.MaximumLength
+
373 Session
->AuthenticationPackage
.MaximumLength
+
374 Session
->LogonServer
.MaximumLength
+
375 Session
->DnsDomainName
.MaximumLength
+
376 Session
->Upn
.MaximumLength
;
377 if (Session
->Sid
!= NULL
)
379 SidLength
= RtlLengthSid(Session
->Sid
);
380 TotalLength
+= SidLength
;
382 TRACE("TotalLength: %lu\n", TotalLength
);
384 /* Allocate the buffer */
385 LocalSessionData
= RtlAllocateHeap(RtlGetProcessHeap(),
388 if (LocalSessionData
== NULL
)
389 return STATUS_INSUFFICIENT_RESOURCES
;
391 Ptr
= (PUCHAR
)((ULONG_PTR
)LocalSessionData
+ sizeof(SECURITY_LOGON_SESSION_DATA
));
392 TRACE("LocalSessionData: %p Ptr: %p\n", LocalSessionData
, Ptr
);
394 LocalSessionData
->Size
= sizeof(SECURITY_LOGON_SESSION_DATA
);
396 /* Copy the LogonId */
397 RtlCopyLuid(&LocalSessionData
->LogonId
,
398 &RequestMsg
->GetLogonSessionData
.Request
.LogonId
);
400 /* Copy the UserName string*/
401 LocalSessionData
->UserName
.Length
= Session
->UserName
.Length
;
402 LocalSessionData
->UserName
.MaximumLength
= Session
->UserName
.MaximumLength
;
404 if (Session
->UserName
.MaximumLength
!= 0)
406 RtlCopyMemory(Ptr
, Session
->UserName
.Buffer
, Session
->UserName
.MaximumLength
);
407 LocalSessionData
->UserName
.Buffer
= (PWSTR
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalSessionData
);
409 Ptr
= (PUCHAR
)((ULONG_PTR
)Ptr
+ Session
->UserName
.MaximumLength
);
412 /* Copy the LogonDomain string */
413 LocalSessionData
->LogonDomain
.Length
= Session
->LogonDomain
.Length
;
414 LocalSessionData
->LogonDomain
.MaximumLength
= Session
->LogonDomain
.MaximumLength
;
415 if (Session
->LogonDomain
.MaximumLength
!= 0)
417 RtlCopyMemory(Ptr
, Session
->LogonDomain
.Buffer
, Session
->LogonDomain
.MaximumLength
);
418 LocalSessionData
->LogonDomain
.Buffer
= (PWSTR
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalSessionData
);
420 Ptr
= (PUCHAR
)((ULONG_PTR
)Ptr
+ Session
->LogonDomain
.MaximumLength
);
423 /* Copy the AuthenticationPackage string */
424 LocalSessionData
->AuthenticationPackage
.Length
= Session
->AuthenticationPackage
.Length
;
425 LocalSessionData
->AuthenticationPackage
.MaximumLength
= Session
->AuthenticationPackage
.MaximumLength
;
426 if (Session
->AuthenticationPackage
.MaximumLength
!= 0)
428 RtlCopyMemory(Ptr
, Session
->AuthenticationPackage
.Buffer
, Session
->AuthenticationPackage
.MaximumLength
);
429 LocalSessionData
->AuthenticationPackage
.Buffer
= (PWSTR
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalSessionData
);
431 Ptr
= (PUCHAR
)((ULONG_PTR
)Ptr
+ Session
->AuthenticationPackage
.MaximumLength
);
434 LocalSessionData
->LogonType
= Session
->LogonType
;
435 LocalSessionData
->Session
= 0;
438 if (Session
->Sid
!= NULL
)
440 RtlCopyMemory(Ptr
, Session
->Sid
, SidLength
);
441 LocalSessionData
->Sid
= (PSID
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalSessionData
);
443 Ptr
= (PUCHAR
)((ULONG_PTR
)Ptr
+ SidLength
);
447 LocalSessionData
->LogonTime
.QuadPart
= Session
->LogonTime
.QuadPart
;
449 /* Copy the LogonServer string */
450 LocalSessionData
->LogonServer
.Length
= Session
->LogonServer
.Length
;
451 LocalSessionData
->LogonServer
.MaximumLength
= Session
->LogonServer
.MaximumLength
;
452 if (Session
->LogonServer
.MaximumLength
!= 0)
454 RtlCopyMemory(Ptr
, Session
->LogonServer
.Buffer
, Session
->LogonServer
.MaximumLength
);
455 LocalSessionData
->LogonServer
.Buffer
= (PWSTR
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalSessionData
);
457 Ptr
= (PUCHAR
)((ULONG_PTR
)Ptr
+ Session
->LogonServer
.MaximumLength
);
460 /* Copy the DnsDomainName string */
461 LocalSessionData
->DnsDomainName
.Length
= Session
->DnsDomainName
.Length
;
462 LocalSessionData
->DnsDomainName
.MaximumLength
= Session
->DnsDomainName
.MaximumLength
;
463 if (Session
->DnsDomainName
.MaximumLength
!= 0)
465 RtlCopyMemory(Ptr
, Session
->DnsDomainName
.Buffer
, Session
->DnsDomainName
.MaximumLength
);
466 LocalSessionData
->DnsDomainName
.Buffer
= (PWSTR
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalSessionData
);
468 Ptr
= (PUCHAR
)((ULONG_PTR
)Ptr
+ Session
->DnsDomainName
.MaximumLength
);
471 /* Copy the Upn string */
472 LocalSessionData
->Upn
.Length
= Session
->Upn
.Length
;
473 LocalSessionData
->Upn
.MaximumLength
= Session
->Upn
.MaximumLength
;
474 if (Session
->Upn
.MaximumLength
!= 0)
476 RtlCopyMemory(Ptr
, Session
->Upn
.Buffer
, Session
->Upn
.MaximumLength
);
477 LocalSessionData
->Upn
.Buffer
= (PWSTR
)((ULONG_PTR
)Ptr
- (ULONG_PTR
)LocalSessionData
);
479 Ptr
= (PUCHAR
)((ULONG_PTR
)Ptr
+ Session
->Upn
.MaximumLength
);
483 InitializeObjectAttributes(&ObjectAttributes
,
489 Status
= NtOpenProcess(&ProcessHandle
,
490 PROCESS_VM_READ
| PROCESS_VM_WRITE
| PROCESS_VM_OPERATION
,
492 &RequestMsg
->h
.ClientId
);
493 if (!NT_SUCCESS(Status
))
495 TRACE("NtOpenProcess() failed (Status %lx)\n", Status
);
499 MemSize
= TotalLength
;
500 Status
= NtAllocateVirtualMemory(ProcessHandle
,
506 if (!NT_SUCCESS(Status
))
508 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status
);
512 TRACE("MemSize: %lu\n", MemSize
);
513 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress
);
515 Status
= NtWriteVirtualMemory(ProcessHandle
,
520 if (!NT_SUCCESS(Status
))
522 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status
);
526 RequestMsg
->GetLogonSessionData
.Reply
.SessionDataBuffer
= ClientBaseAddress
;
529 if (ProcessHandle
!= NULL
)
530 NtClose(ProcessHandle
);
532 if (LocalSessionData
!= NULL
)
533 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSessionData
);