xref: /reactos/dll/win32/lsasrv/session.c (revision cc439606)
1 /*
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
7  */
8 
9 #include "lsasrv.h"
10 
11 typedef struct _LSAP_LOGON_SESSION
12 {
13     LIST_ENTRY Entry;
14     LUID LogonId;
15     ULONG LogonType;
16     ULONG Session;
17     LARGE_INTEGER LogonTime;
18     PSID Sid;
19     UNICODE_STRING UserName;
20     UNICODE_STRING LogonDomain;
21     UNICODE_STRING AuthenticationPackage;
22     UNICODE_STRING LogonServer;
23     UNICODE_STRING DnsDomainName;
24     UNICODE_STRING Upn;
25 } LSAP_LOGON_SESSION, *PLSAP_LOGON_SESSION;
26 
27 
28 /* GLOBALS *****************************************************************/
29 
30 LIST_ENTRY SessionListHead;
31 ULONG SessionCount;
32 
33 /* FUNCTIONS ***************************************************************/
34 
35 VOID
36 LsapInitLogonSessions(VOID)
37 {
38     InitializeListHead(&SessionListHead);
39     SessionCount = 0;
40 }
41 
42 
43 static
44 PLSAP_LOGON_SESSION
45 LsapGetLogonSession(IN PLUID LogonId)
46 {
47     PLIST_ENTRY SessionEntry;
48     PLSAP_LOGON_SESSION CurrentSession;
49 
50     SessionEntry = SessionListHead.Flink;
51     while (SessionEntry != &SessionListHead)
52     {
53         CurrentSession = CONTAINING_RECORD(SessionEntry,
54                                            LSAP_LOGON_SESSION,
55                                            Entry);
56         if (RtlEqualLuid(&CurrentSession->LogonId, LogonId))
57             return CurrentSession;
58 
59         SessionEntry = SessionEntry->Flink;
60     }
61 
62     return NULL;
63 }
64 
65 
66 NTSTATUS
67 LsapSetLogonSessionData(
68     _In_ PLUID LogonId,
69     _In_ ULONG LogonType,
70     _In_ PUNICODE_STRING UserName,
71     _In_ PUNICODE_STRING LogonDomain,
72     _In_ PSID Sid)
73 {
74     PLSAP_LOGON_SESSION Session;
75     ULONG Length;
76 
77     TRACE("LsapSetLogonSessionData(%p)\n", LogonId);
78 
79     Session = LsapGetLogonSession(LogonId);
80     if (Session == NULL)
81         return STATUS_NO_SUCH_LOGON_SESSION;
82 
83     TRACE("LogonType %lu\n", LogonType);
84     Session->LogonType = LogonType;
85 
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;
90 
91     Session->UserName.Length = UserName->Length;
92     Session->UserName.MaximumLength = UserName->MaximumLength;
93     RtlCopyMemory(Session->UserName.Buffer, UserName->Buffer, UserName->MaximumLength);
94 
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;
99 
100     Session->LogonDomain.Length = LogonDomain->Length;
101     Session->LogonDomain.MaximumLength = LogonDomain->MaximumLength;
102     RtlCopyMemory(Session->LogonDomain.Buffer, LogonDomain->Buffer, LogonDomain->MaximumLength);
103 
104     Length = RtlLengthSid(Sid);
105     Session->Sid = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
106     if (Session->UserName.Buffer == NULL)
107         return STATUS_INSUFFICIENT_RESOURCES;
108 
109     RtlCopyMemory(Session->Sid, Sid, Length);
110 
111     return STATUS_SUCCESS;
112 }
113 
114 
115 NTSTATUS
116 NTAPI
117 LsapCreateLogonSession(IN PLUID LogonId)
118 {
119     PLSAP_LOGON_SESSION Session;
120     NTSTATUS Status;
121 
122     TRACE("LsapCreateLogonSession(%p)\n", LogonId);
123 
124     /* Fail, if a session already exists */
125     if (LsapGetLogonSession(LogonId) != NULL)
126         return STATUS_LOGON_SESSION_COLLISION;
127 
128     /* Allocate a new session entry */
129     Session = RtlAllocateHeap(RtlGetProcessHeap(),
130                               HEAP_ZERO_MEMORY,
131                               sizeof(LSAP_LOGON_SESSION));
132     if (Session == NULL)
133         return STATUS_INSUFFICIENT_RESOURCES;
134 
135     /* Initialize the session entry */
136     RtlCopyLuid(&Session->LogonId, LogonId);
137 
138     TRACE("LsapCreateLogonSession(<0x%lx,0x%lx>)\n",
139           LogonId->HighPart, LogonId->LowPart);
140 
141     /* Tell ntoskrnl to create a new logon session */
142     Status = LsapRmCreateLogonSession(LogonId);
143     if (!NT_SUCCESS(Status))
144     {
145         RtlFreeHeap(RtlGetProcessHeap(), 0, Session);
146         return Status;
147     }
148 
149     /* Insert the new session into the session list */
150     InsertHeadList(&SessionListHead, &Session->Entry);
151     SessionCount++;
152 
153     return STATUS_SUCCESS;
154 }
155 
156 
157 NTSTATUS
158 NTAPI
159 LsapDeleteLogonSession(IN PLUID LogonId)
160 {
161     PLSAP_LOGON_SESSION Session;
162     NTSTATUS Status;
163 
164     TRACE("LsapDeleteLogonSession(%p)\n", LogonId);
165 
166     /* Fail, if the session does not exist */
167     Session = LsapGetLogonSession(LogonId);
168     if (Session == NULL)
169         return STATUS_NO_SUCH_LOGON_SESSION;
170 
171     TRACE("LsapDeleteLogonSession(<0x%lx,0x%lx>)\n",
172           LogonId->HighPart, LogonId->LowPart);
173 
174     /* Tell ntoskrnl to delete the logon session */
175     Status = LsapRmDeleteLogonSession(LogonId);
176     if (!NT_SUCCESS(Status))
177         return Status;
178 
179     /* Remove the session entry from the list */
180     RemoveEntryList(&Session->Entry);
181     SessionCount--;
182 
183     /* Free the session data */
184     if (Session->Sid != NULL)
185         RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Sid);
186 
187     if (Session->UserName.Buffer != NULL)
188         RtlFreeHeap(RtlGetProcessHeap(), 0, Session->UserName.Buffer);
189 
190     if (Session->LogonDomain.Buffer != NULL)
191         RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonDomain.Buffer);
192 
193     if (Session->AuthenticationPackage.Buffer != NULL)
194         RtlFreeHeap(RtlGetProcessHeap(), 0, Session->AuthenticationPackage.Buffer);
195 
196     if (Session->LogonServer.Buffer != NULL)
197         RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonServer.Buffer);
198 
199     if (Session->DnsDomainName.Buffer != NULL)
200         RtlFreeHeap(RtlGetProcessHeap(), 0, Session->DnsDomainName.Buffer);
201 
202     if (Session->Upn.Buffer != NULL)
203         RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Upn.Buffer);
204 
205     /* Free the session entry */
206     RtlFreeHeap(RtlGetProcessHeap(), 0, Session);
207 
208     return STATUS_SUCCESS;
209 }
210 
211 
212 NTSTATUS
213 NTAPI
214 LsapAddCredential(
215     _In_ PLUID LogonId,
216     _In_ ULONG AuthenticationPackage,
217     _In_ PLSA_STRING PrimaryKeyValue,
218     _In_ PLSA_STRING Credential)
219 {
220 
221     return STATUS_SUCCESS;
222 }
223 
224 
225 NTSTATUS
226 NTAPI
227 LsapGetCredentials(
228     _In_ PLUID LogonId,
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)
235 {
236 
237     return STATUS_SUCCESS;
238 }
239 
240 
241 NTSTATUS
242 NTAPI
243 LsapDeleteCredential(
244     _In_ PLUID LogonId,
245     _In_ ULONG AuthenticationPackage,
246     _In_ PLSA_STRING PrimaryKeyValue)
247 {
248 
249     return STATUS_SUCCESS;
250 }
251 
252 
253 NTSTATUS
254 LsapEnumLogonSessions(IN OUT PLSA_API_MSG RequestMsg)
255 {
256     OBJECT_ATTRIBUTES ObjectAttributes;
257     HANDLE ProcessHandle = NULL;
258     PLIST_ENTRY SessionEntry;
259     PLSAP_LOGON_SESSION CurrentSession;
260     PLUID SessionList;
261     ULONG i, Length;
262     SIZE_T MemSize;
263     PVOID ClientBaseAddress = NULL;
264     NTSTATUS Status;
265 
266     TRACE("LsapEnumLogonSessions(%p)\n", RequestMsg);
267 
268     Length = SessionCount * sizeof(LUID);
269     SessionList = RtlAllocateHeap(RtlGetProcessHeap(),
270                                   HEAP_ZERO_MEMORY,
271                                   Length);
272     if (SessionList == NULL)
273         return STATUS_INSUFFICIENT_RESOURCES;
274 
275     i = 0;
276     SessionEntry = SessionListHead.Flink;
277     while (SessionEntry != &SessionListHead)
278     {
279         CurrentSession = CONTAINING_RECORD(SessionEntry,
280                                            LSAP_LOGON_SESSION,
281                                            Entry);
282 
283         RtlCopyLuid(&SessionList[i],
284                     &CurrentSession->LogonId);
285 
286         SessionEntry = SessionEntry->Flink;
287         i++;
288     }
289 
290     InitializeObjectAttributes(&ObjectAttributes,
291                                NULL,
292                                0,
293                                NULL,
294                                NULL);
295 
296     Status = NtOpenProcess(&ProcessHandle,
297                            PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
298                            &ObjectAttributes,
299                            &RequestMsg->h.ClientId);
300     if (!NT_SUCCESS(Status))
301     {
302         TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
303         goto done;
304     }
305 
306     TRACE("Length: %lu\n", Length);
307 
308     MemSize = Length;
309     Status = NtAllocateVirtualMemory(ProcessHandle,
310                                      &ClientBaseAddress,
311                                      0,
312                                      &MemSize,
313                                      MEM_COMMIT,
314                                      PAGE_READWRITE);
315     if (!NT_SUCCESS(Status))
316     {
317         TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
318         goto done;
319     }
320 
321     TRACE("MemSize: %lu\n", MemSize);
322     TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
323 
324     Status = NtWriteVirtualMemory(ProcessHandle,
325                                   ClientBaseAddress,
326                                   SessionList,
327                                   Length,
328                                   NULL);
329     if (!NT_SUCCESS(Status))
330     {
331         TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
332         goto done;
333     }
334 
335     RequestMsg->EnumLogonSessions.Reply.LogonSessionCount = SessionCount;
336     RequestMsg->EnumLogonSessions.Reply.LogonSessionBuffer = ClientBaseAddress;
337 
338 done:
339     if (ProcessHandle != NULL)
340         NtClose(ProcessHandle);
341 
342     if (SessionList != NULL)
343         RtlFreeHeap(RtlGetProcessHeap(), 0, SessionList);
344 
345     return Status;
346 }
347 
348 
349 NTSTATUS
350 LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg)
351 {
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;
358     SIZE_T MemSize;
359     PUCHAR Ptr;
360     NTSTATUS Status;
361 
362     TRACE("LsapGetLogonSessionData(%p)\n", RequestMsg);
363 
364     TRACE("LogonId: %lx\n", RequestMsg->GetLogonSessionData.Request.LogonId.LowPart);
365     Session = LsapGetLogonSession(&RequestMsg->GetLogonSessionData.Request.LogonId);
366     if (Session == NULL)
367         return STATUS_NO_SUCH_LOGON_SESSION;
368 
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)
378     {
379         SidLength = RtlLengthSid(Session->Sid);
380         TotalLength += SidLength;
381     }
382     TRACE("TotalLength: %lu\n", TotalLength);
383 
384     /* Allocate the buffer */
385     LocalSessionData = RtlAllocateHeap(RtlGetProcessHeap(),
386                                        HEAP_ZERO_MEMORY,
387                                        TotalLength);
388     if (LocalSessionData == NULL)
389         return STATUS_INSUFFICIENT_RESOURCES;
390 
391     Ptr = (PUCHAR)((ULONG_PTR)LocalSessionData + sizeof(SECURITY_LOGON_SESSION_DATA));
392     TRACE("LocalSessionData: %p  Ptr: %p\n", LocalSessionData, Ptr);
393 
394     LocalSessionData->Size = sizeof(SECURITY_LOGON_SESSION_DATA);
395 
396     /* Copy the LogonId */
397     RtlCopyLuid(&LocalSessionData->LogonId,
398                 &RequestMsg->GetLogonSessionData.Request.LogonId);
399 
400     /* Copy the UserName string*/
401     LocalSessionData->UserName.Length = Session->UserName.Length;
402     LocalSessionData->UserName.MaximumLength = Session->UserName.MaximumLength;
403 
404     if (Session->UserName.MaximumLength != 0)
405     {
406         RtlCopyMemory(Ptr, Session->UserName.Buffer, Session->UserName.MaximumLength);
407         LocalSessionData->UserName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
408 
409         Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->UserName.MaximumLength);
410     }
411 
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)
416     {
417         RtlCopyMemory(Ptr, Session->LogonDomain.Buffer, Session->LogonDomain.MaximumLength);
418         LocalSessionData->LogonDomain.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
419 
420         Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonDomain.MaximumLength);
421     }
422 
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)
427     {
428         RtlCopyMemory(Ptr, Session->AuthenticationPackage.Buffer, Session->AuthenticationPackage.MaximumLength);
429         LocalSessionData->AuthenticationPackage.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
430 
431         Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->AuthenticationPackage.MaximumLength);
432     }
433 
434     LocalSessionData->LogonType = Session->LogonType;
435     LocalSessionData->Session = 0;
436 
437     /* Sid */
438     if (Session->Sid != NULL)
439     {
440         RtlCopyMemory(Ptr, Session->Sid, SidLength);
441         LocalSessionData->Sid = (PSID)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
442 
443         Ptr = (PUCHAR)((ULONG_PTR)Ptr + SidLength);
444     }
445 
446     /* LogonTime */
447     LocalSessionData->LogonTime.QuadPart = Session->LogonTime.QuadPart;
448 
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)
453     {
454         RtlCopyMemory(Ptr, Session->LogonServer.Buffer, Session->LogonServer.MaximumLength);
455         LocalSessionData->LogonServer.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
456 
457         Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonServer.MaximumLength);
458     }
459 
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)
464     {
465         RtlCopyMemory(Ptr, Session->DnsDomainName.Buffer, Session->DnsDomainName.MaximumLength);
466         LocalSessionData->DnsDomainName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
467 
468         Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->DnsDomainName.MaximumLength);
469     }
470 
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)
475     {
476         RtlCopyMemory(Ptr, Session->Upn.Buffer, Session->Upn.MaximumLength);
477         LocalSessionData->Upn.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
478 
479         Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->Upn.MaximumLength);
480     }
481 
482 
483     InitializeObjectAttributes(&ObjectAttributes,
484                                NULL,
485                                0,
486                                NULL,
487                                NULL);
488 
489     Status = NtOpenProcess(&ProcessHandle,
490                            PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
491                            &ObjectAttributes,
492                            &RequestMsg->h.ClientId);
493     if (!NT_SUCCESS(Status))
494     {
495         TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
496         goto done;
497     }
498 
499     MemSize = TotalLength;
500     Status = NtAllocateVirtualMemory(ProcessHandle,
501                                      &ClientBaseAddress,
502                                      0,
503                                      &MemSize,
504                                      MEM_COMMIT,
505                                      PAGE_READWRITE);
506     if (!NT_SUCCESS(Status))
507     {
508         TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
509         goto done;
510     }
511 
512     TRACE("MemSize: %lu\n", MemSize);
513     TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
514 
515     Status = NtWriteVirtualMemory(ProcessHandle,
516                                   ClientBaseAddress,
517                                   LocalSessionData,
518                                   TotalLength,
519                                   NULL);
520     if (!NT_SUCCESS(Status))
521     {
522         TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
523         goto done;
524     }
525 
526     RequestMsg->GetLogonSessionData.Reply.SessionDataBuffer = ClientBaseAddress;
527 
528 done:
529     if (ProcessHandle != NULL)
530         NtClose(ProcessHandle);
531 
532     if (LocalSessionData != NULL)
533         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSessionData);
534 
535     return Status;
536 }
537 
538 /* EOF */
539