xref: /reactos/dll/win32/lsasrv/session.c (revision 07608028)
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