[LSASRV]
[reactos.git] / reactos / dll / win32 / lsasrv / session.c
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 {
72 PLSAP_LOGON_SESSION Session;
73
74 TRACE("LsapSetLogonSessionData(%p)\n", LogonId);
75
76 Session = LsapGetLogonSession(LogonId);
77 if (Session == NULL)
78 return STATUS_NO_SUCH_LOGON_SESSION;
79
80 TRACE("LogonType %lu\n", LogonType);
81 Session->LogonType = LogonType;
82
83 TRACE("UserName %wZ\n", UserName);
84 Session->UserName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, UserName->MaximumLength);
85 if (Session->UserName.Buffer == NULL)
86 return STATUS_INSUFFICIENT_RESOURCES;
87
88 Session->UserName.Length = UserName->Length;
89 Session->UserName.MaximumLength = UserName->MaximumLength;
90 RtlCopyMemory(Session->UserName.Buffer, UserName->Buffer, UserName->MaximumLength);
91
92 return STATUS_SUCCESS;
93 }
94
95
96 NTSTATUS
97 NTAPI
98 LsapCreateLogonSession(IN PLUID LogonId)
99 {
100 PLSAP_LOGON_SESSION Session;
101 NTSTATUS Status;
102
103 TRACE("LsapCreateLogonSession(%p)\n", LogonId);
104
105 /* Fail, if a session already exists */
106 if (LsapGetLogonSession(LogonId) != NULL)
107 return STATUS_LOGON_SESSION_COLLISION;
108
109 /* Allocate a new session entry */
110 Session = RtlAllocateHeap(RtlGetProcessHeap(),
111 HEAP_ZERO_MEMORY,
112 sizeof(LSAP_LOGON_SESSION));
113 if (Session == NULL)
114 return STATUS_INSUFFICIENT_RESOURCES;
115
116 /* Initialize the session entry */
117 RtlCopyLuid(&Session->LogonId, LogonId);
118
119 TRACE("LsapCreateLogonSession(<0x%lx,0x%lx>)\n",
120 LogonId->HighPart, LogonId->LowPart);
121
122 /* Tell ntoskrnl to create a new logon session */
123 Status = LsapRmCreateLogonSession(LogonId);
124 if (!NT_SUCCESS(Status))
125 {
126 RtlFreeHeap(RtlGetProcessHeap(), 0, Session);
127 return Status;
128 }
129
130 /* Insert the new session into the session list */
131 InsertHeadList(&SessionListHead, &Session->Entry);
132 SessionCount++;
133
134 return STATUS_SUCCESS;
135 }
136
137
138 NTSTATUS
139 NTAPI
140 LsapDeleteLogonSession(IN PLUID LogonId)
141 {
142 PLSAP_LOGON_SESSION Session;
143 NTSTATUS Status;
144
145 TRACE("LsapDeleteLogonSession(%p)\n", LogonId);
146
147 /* Fail, if the session does not exist */
148 Session = LsapGetLogonSession(LogonId);
149 if (Session == NULL)
150 return STATUS_NO_SUCH_LOGON_SESSION;
151
152 TRACE("LsapDeleteLogonSession(<0x%lx,0x%lx>)\n",
153 LogonId->HighPart, LogonId->LowPart);
154
155 /* Tell ntoskrnl to delete the logon session */
156 Status = LsapRmDeleteLogonSession(LogonId);
157 if (!NT_SUCCESS(Status))
158 return Status;
159
160 /* Remove the session entry from the list */
161 RemoveEntryList(&Session->Entry);
162 SessionCount--;
163
164 /* Free the session data */
165 if (Session->Sid != NULL)
166 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Sid);
167
168 if (Session->UserName.Buffer != NULL)
169 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->UserName.Buffer);
170
171 if (Session->LogonDomain.Buffer != NULL)
172 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonDomain.Buffer);
173
174 if (Session->AuthenticationPackage.Buffer != NULL)
175 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->AuthenticationPackage.Buffer);
176
177 if (Session->LogonServer.Buffer != NULL)
178 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonServer.Buffer);
179
180 if (Session->DnsDomainName.Buffer != NULL)
181 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->DnsDomainName.Buffer);
182
183 if (Session->Upn.Buffer != NULL)
184 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Upn.Buffer);
185
186 /* Free the session entry */
187 RtlFreeHeap(RtlGetProcessHeap(), 0, Session);
188
189 return STATUS_SUCCESS;
190 }
191
192
193 NTSTATUS
194 NTAPI
195 LsapAddCredential(
196 _In_ PLUID LogonId,
197 _In_ ULONG AuthenticationPackage,
198 _In_ PLSA_STRING PrimaryKeyValue,
199 _In_ PLSA_STRING Credential)
200 {
201
202 return STATUS_SUCCESS;
203 }
204
205
206 NTSTATUS
207 NTAPI
208 LsapGetCredentials(
209 _In_ PLUID LogonId,
210 _In_ ULONG AuthenticationPackage,
211 _Inout_ PULONG QueryContext,
212 _In_ BOOLEAN RetrieveAllCredentials,
213 _Inout_ PLSA_STRING PrimaryKeyValue,
214 _Out_ PULONG PrimaryKeyLength,
215 _Out_ PLSA_STRING Credentials)
216 {
217
218 return STATUS_SUCCESS;
219 }
220
221
222 NTSTATUS
223 NTAPI
224 LsapDeleteCredential(
225 _In_ PLUID LogonId,
226 _In_ ULONG AuthenticationPackage,
227 _In_ PLSA_STRING PrimaryKeyValue)
228 {
229
230 return STATUS_SUCCESS;
231 }
232
233
234 NTSTATUS
235 LsapEnumLogonSessions(IN OUT PLSA_API_MSG RequestMsg)
236 {
237 OBJECT_ATTRIBUTES ObjectAttributes;
238 HANDLE ProcessHandle = NULL;
239 PLIST_ENTRY SessionEntry;
240 PLSAP_LOGON_SESSION CurrentSession;
241 PLUID SessionList;
242 ULONG i, Length, MemSize;
243 PVOID ClientBaseAddress = NULL;
244 NTSTATUS Status;
245
246 TRACE("LsapEnumLogonSessions(%p)\n", RequestMsg);
247
248 Length = SessionCount * sizeof(LUID);
249 SessionList = RtlAllocateHeap(RtlGetProcessHeap(),
250 HEAP_ZERO_MEMORY,
251 Length);
252 if (SessionList == NULL)
253 return STATUS_INSUFFICIENT_RESOURCES;
254
255 i = 0;
256 SessionEntry = SessionListHead.Flink;
257 while (SessionEntry != &SessionListHead)
258 {
259 CurrentSession = CONTAINING_RECORD(SessionEntry,
260 LSAP_LOGON_SESSION,
261 Entry);
262
263 RtlCopyLuid(&SessionList[i],
264 &CurrentSession->LogonId);
265
266 SessionEntry = SessionEntry->Flink;
267 i++;
268 }
269
270 InitializeObjectAttributes(&ObjectAttributes,
271 NULL,
272 0,
273 NULL,
274 NULL);
275
276 Status = NtOpenProcess(&ProcessHandle,
277 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
278 &ObjectAttributes,
279 &RequestMsg->h.ClientId);
280 if (!NT_SUCCESS(Status))
281 {
282 TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
283 goto done;
284 }
285
286 TRACE("Length: %lu\n", Length);
287
288 MemSize = Length;
289 Status = NtAllocateVirtualMemory(ProcessHandle,
290 &ClientBaseAddress,
291 0,
292 &MemSize,
293 MEM_COMMIT,
294 PAGE_READWRITE);
295 if (!NT_SUCCESS(Status))
296 {
297 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
298 goto done;
299 }
300
301 TRACE("MemSize: %lu\n", MemSize);
302 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
303
304 Status = NtWriteVirtualMemory(ProcessHandle,
305 ClientBaseAddress,
306 SessionList,
307 Length,
308 NULL);
309 if (!NT_SUCCESS(Status))
310 {
311 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
312 goto done;
313 }
314
315 RequestMsg->EnumLogonSessions.Reply.LogonSessionCount = SessionCount;
316 RequestMsg->EnumLogonSessions.Reply.LogonSessionBuffer = ClientBaseAddress;
317
318 done:
319 if (ProcessHandle != NULL)
320 NtClose(ProcessHandle);
321
322 if (SessionList != NULL)
323 RtlFreeHeap(RtlGetProcessHeap(), 0, SessionList);
324
325 return Status;
326 }
327
328
329 NTSTATUS
330 LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg)
331 {
332 OBJECT_ATTRIBUTES ObjectAttributes;
333 HANDLE ProcessHandle = NULL;
334 PLSAP_LOGON_SESSION Session;
335 PSECURITY_LOGON_SESSION_DATA LocalSessionData;
336 PVOID ClientBaseAddress = NULL;
337 ULONG TotalLength, MemSize, SidLength = 0;
338 PUCHAR Ptr;
339 NTSTATUS Status;
340
341 TRACE("LsapGetLogonSessionData(%p)\n", RequestMsg);
342
343 TRACE("LogonId: %lx\n", RequestMsg->GetLogonSessionData.Request.LogonId.LowPart);
344 Session = LsapGetLogonSession(&RequestMsg->GetLogonSessionData.Request.LogonId);
345 if (Session == NULL)
346 return STATUS_NO_SUCH_LOGON_SESSION;
347
348 /* Calculate the required buffer size */
349 TotalLength = sizeof(SECURITY_LOGON_SESSION_DATA) +
350 Session->UserName.MaximumLength +
351 Session->LogonDomain.MaximumLength +
352 Session->AuthenticationPackage.MaximumLength +
353 Session->LogonServer.MaximumLength +
354 Session->DnsDomainName.MaximumLength +
355 Session->Upn.MaximumLength;
356 if (Session->Sid != NULL)
357 {
358 SidLength = RtlLengthSid(Session->Sid);
359 TotalLength += SidLength;
360 }
361 TRACE("TotalLength: %lu\n", TotalLength);
362
363 /* Allocate the buffer */
364 LocalSessionData = RtlAllocateHeap(RtlGetProcessHeap(),
365 HEAP_ZERO_MEMORY,
366 TotalLength);
367 if (LocalSessionData == NULL)
368 return STATUS_INSUFFICIENT_RESOURCES;
369
370 Ptr = (PUCHAR)((ULONG_PTR)LocalSessionData + sizeof(SECURITY_LOGON_SESSION_DATA));
371 TRACE("LocalSessionData: %p Ptr: %p\n", LocalSessionData, Ptr);
372
373 LocalSessionData->Size = sizeof(SECURITY_LOGON_SESSION_DATA);
374
375 /* Copy the LogonId */
376 RtlCopyLuid(&LocalSessionData->LogonId,
377 &RequestMsg->GetLogonSessionData.Request.LogonId);
378
379 /* Copy the UserName string*/
380 LocalSessionData->UserName.Length = Session->UserName.Length;
381 LocalSessionData->UserName.MaximumLength = Session->UserName.MaximumLength;
382
383 if (Session->UserName.MaximumLength != 0)
384 {
385 RtlCopyMemory(Ptr, Session->UserName.Buffer, Session->UserName.MaximumLength);
386 LocalSessionData->UserName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
387
388 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->UserName.MaximumLength);
389 }
390
391 /* Copy the LogonDomain string */
392 LocalSessionData->LogonDomain.Length = Session->LogonDomain.Length;
393 LocalSessionData->LogonDomain.MaximumLength = Session->LogonDomain.MaximumLength;
394 if (Session->LogonDomain.MaximumLength != 0)
395 {
396 RtlCopyMemory(Ptr, Session->LogonDomain.Buffer, Session->LogonDomain.MaximumLength);
397 LocalSessionData->LogonDomain.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
398
399 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonDomain.MaximumLength);
400 }
401
402 /* Copy the AuthenticationPackage string */
403 LocalSessionData->AuthenticationPackage.Length = Session->AuthenticationPackage.Length;
404 LocalSessionData->AuthenticationPackage.MaximumLength = Session->AuthenticationPackage.MaximumLength;
405 if (Session->AuthenticationPackage.MaximumLength != 0)
406 {
407 RtlCopyMemory(Ptr, Session->AuthenticationPackage.Buffer, Session->AuthenticationPackage.MaximumLength);
408 LocalSessionData->AuthenticationPackage.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
409
410 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->AuthenticationPackage.MaximumLength);
411 }
412
413 LocalSessionData->LogonType = Session->LogonType;
414 LocalSessionData->Session = 0;
415
416 /* Sid */
417 if (Session->Sid != NULL)
418 {
419 RtlCopyMemory(Ptr, Session->Sid, SidLength);
420 LocalSessionData->Sid = (PSID)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
421
422 Ptr = (PUCHAR)((ULONG_PTR)Ptr + SidLength);
423 }
424
425 /* LogonTime */
426 LocalSessionData->LogonTime.QuadPart = Session->LogonTime.QuadPart;
427
428 /* Copy the LogonServer string */
429 LocalSessionData->LogonServer.Length = Session->LogonServer.Length;
430 LocalSessionData->LogonServer.MaximumLength = Session->LogonServer.MaximumLength;
431 if (Session->LogonServer.MaximumLength != 0)
432 {
433 RtlCopyMemory(Ptr, Session->LogonServer.Buffer, Session->LogonServer.MaximumLength);
434 LocalSessionData->LogonServer.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
435
436 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonServer.MaximumLength);
437 }
438
439 /* Copy the DnsDomainName string */
440 LocalSessionData->DnsDomainName.Length = Session->DnsDomainName.Length;
441 LocalSessionData->DnsDomainName.MaximumLength = Session->DnsDomainName.MaximumLength;
442 if (Session->DnsDomainName.MaximumLength != 0)
443 {
444 RtlCopyMemory(Ptr, Session->DnsDomainName.Buffer, Session->DnsDomainName.MaximumLength);
445 LocalSessionData->DnsDomainName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
446
447 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->DnsDomainName.MaximumLength);
448 }
449
450 /* Copy the Upn string */
451 LocalSessionData->Upn.Length = Session->Upn.Length;
452 LocalSessionData->Upn.MaximumLength = Session->Upn.MaximumLength;
453 if (Session->Upn.MaximumLength != 0)
454 {
455 RtlCopyMemory(Ptr, Session->Upn.Buffer, Session->Upn.MaximumLength);
456 LocalSessionData->Upn.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
457
458 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->Upn.MaximumLength);
459 }
460
461
462 InitializeObjectAttributes(&ObjectAttributes,
463 NULL,
464 0,
465 NULL,
466 NULL);
467
468 Status = NtOpenProcess(&ProcessHandle,
469 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
470 &ObjectAttributes,
471 &RequestMsg->h.ClientId);
472 if (!NT_SUCCESS(Status))
473 {
474 TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
475 goto done;
476 }
477
478 MemSize = TotalLength;
479 Status = NtAllocateVirtualMemory(ProcessHandle,
480 &ClientBaseAddress,
481 0,
482 &MemSize,
483 MEM_COMMIT,
484 PAGE_READWRITE);
485 if (!NT_SUCCESS(Status))
486 {
487 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
488 goto done;
489 }
490
491 TRACE("MemSize: %lu\n", MemSize);
492 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
493
494 Status = NtWriteVirtualMemory(ProcessHandle,
495 ClientBaseAddress,
496 LocalSessionData,
497 TotalLength,
498 NULL);
499 if (!NT_SUCCESS(Status))
500 {
501 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
502 goto done;
503 }
504
505 RequestMsg->GetLogonSessionData.Reply.SessionDataBuffer = ClientBaseAddress;
506
507 done:
508 if (ProcessHandle != NULL)
509 NtClose(ProcessHandle);
510
511 if (LocalSessionData != NULL)
512 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSessionData);
513
514 return Status;
515 }
516
517 /* EOF */