a290e3428fa88b05e3c71097a895fde7bc2a30d8
[reactos.git] / 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 _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, MemSize;
262 PVOID ClientBaseAddress = NULL;
263 NTSTATUS Status;
264
265 TRACE("LsapEnumLogonSessions(%p)\n", RequestMsg);
266
267 Length = SessionCount * sizeof(LUID);
268 SessionList = RtlAllocateHeap(RtlGetProcessHeap(),
269 HEAP_ZERO_MEMORY,
270 Length);
271 if (SessionList == NULL)
272 return STATUS_INSUFFICIENT_RESOURCES;
273
274 i = 0;
275 SessionEntry = SessionListHead.Flink;
276 while (SessionEntry != &SessionListHead)
277 {
278 CurrentSession = CONTAINING_RECORD(SessionEntry,
279 LSAP_LOGON_SESSION,
280 Entry);
281
282 RtlCopyLuid(&SessionList[i],
283 &CurrentSession->LogonId);
284
285 SessionEntry = SessionEntry->Flink;
286 i++;
287 }
288
289 InitializeObjectAttributes(&ObjectAttributes,
290 NULL,
291 0,
292 NULL,
293 NULL);
294
295 Status = NtOpenProcess(&ProcessHandle,
296 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
297 &ObjectAttributes,
298 &RequestMsg->h.ClientId);
299 if (!NT_SUCCESS(Status))
300 {
301 TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
302 goto done;
303 }
304
305 TRACE("Length: %lu\n", Length);
306
307 MemSize = Length;
308 Status = NtAllocateVirtualMemory(ProcessHandle,
309 &ClientBaseAddress,
310 0,
311 &MemSize,
312 MEM_COMMIT,
313 PAGE_READWRITE);
314 if (!NT_SUCCESS(Status))
315 {
316 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
317 goto done;
318 }
319
320 TRACE("MemSize: %lu\n", MemSize);
321 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
322
323 Status = NtWriteVirtualMemory(ProcessHandle,
324 ClientBaseAddress,
325 SessionList,
326 Length,
327 NULL);
328 if (!NT_SUCCESS(Status))
329 {
330 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
331 goto done;
332 }
333
334 RequestMsg->EnumLogonSessions.Reply.LogonSessionCount = SessionCount;
335 RequestMsg->EnumLogonSessions.Reply.LogonSessionBuffer = ClientBaseAddress;
336
337 done:
338 if (ProcessHandle != NULL)
339 NtClose(ProcessHandle);
340
341 if (SessionList != NULL)
342 RtlFreeHeap(RtlGetProcessHeap(), 0, SessionList);
343
344 return Status;
345 }
346
347
348 NTSTATUS
349 LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg)
350 {
351 OBJECT_ATTRIBUTES ObjectAttributes;
352 HANDLE ProcessHandle = NULL;
353 PLSAP_LOGON_SESSION Session;
354 PSECURITY_LOGON_SESSION_DATA LocalSessionData;
355 PVOID ClientBaseAddress = NULL;
356 ULONG TotalLength, MemSize, SidLength = 0;
357 PUCHAR Ptr;
358 NTSTATUS Status;
359
360 TRACE("LsapGetLogonSessionData(%p)\n", RequestMsg);
361
362 TRACE("LogonId: %lx\n", RequestMsg->GetLogonSessionData.Request.LogonId.LowPart);
363 Session = LsapGetLogonSession(&RequestMsg->GetLogonSessionData.Request.LogonId);
364 if (Session == NULL)
365 return STATUS_NO_SUCH_LOGON_SESSION;
366
367 /* Calculate the required buffer size */
368 TotalLength = sizeof(SECURITY_LOGON_SESSION_DATA) +
369 Session->UserName.MaximumLength +
370 Session->LogonDomain.MaximumLength +
371 Session->AuthenticationPackage.MaximumLength +
372 Session->LogonServer.MaximumLength +
373 Session->DnsDomainName.MaximumLength +
374 Session->Upn.MaximumLength;
375 if (Session->Sid != NULL)
376 {
377 SidLength = RtlLengthSid(Session->Sid);
378 TotalLength += SidLength;
379 }
380 TRACE("TotalLength: %lu\n", TotalLength);
381
382 /* Allocate the buffer */
383 LocalSessionData = RtlAllocateHeap(RtlGetProcessHeap(),
384 HEAP_ZERO_MEMORY,
385 TotalLength);
386 if (LocalSessionData == NULL)
387 return STATUS_INSUFFICIENT_RESOURCES;
388
389 Ptr = (PUCHAR)((ULONG_PTR)LocalSessionData + sizeof(SECURITY_LOGON_SESSION_DATA));
390 TRACE("LocalSessionData: %p Ptr: %p\n", LocalSessionData, Ptr);
391
392 LocalSessionData->Size = sizeof(SECURITY_LOGON_SESSION_DATA);
393
394 /* Copy the LogonId */
395 RtlCopyLuid(&LocalSessionData->LogonId,
396 &RequestMsg->GetLogonSessionData.Request.LogonId);
397
398 /* Copy the UserName string*/
399 LocalSessionData->UserName.Length = Session->UserName.Length;
400 LocalSessionData->UserName.MaximumLength = Session->UserName.MaximumLength;
401
402 if (Session->UserName.MaximumLength != 0)
403 {
404 RtlCopyMemory(Ptr, Session->UserName.Buffer, Session->UserName.MaximumLength);
405 LocalSessionData->UserName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
406
407 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->UserName.MaximumLength);
408 }
409
410 /* Copy the LogonDomain string */
411 LocalSessionData->LogonDomain.Length = Session->LogonDomain.Length;
412 LocalSessionData->LogonDomain.MaximumLength = Session->LogonDomain.MaximumLength;
413 if (Session->LogonDomain.MaximumLength != 0)
414 {
415 RtlCopyMemory(Ptr, Session->LogonDomain.Buffer, Session->LogonDomain.MaximumLength);
416 LocalSessionData->LogonDomain.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
417
418 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonDomain.MaximumLength);
419 }
420
421 /* Copy the AuthenticationPackage string */
422 LocalSessionData->AuthenticationPackage.Length = Session->AuthenticationPackage.Length;
423 LocalSessionData->AuthenticationPackage.MaximumLength = Session->AuthenticationPackage.MaximumLength;
424 if (Session->AuthenticationPackage.MaximumLength != 0)
425 {
426 RtlCopyMemory(Ptr, Session->AuthenticationPackage.Buffer, Session->AuthenticationPackage.MaximumLength);
427 LocalSessionData->AuthenticationPackage.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
428
429 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->AuthenticationPackage.MaximumLength);
430 }
431
432 LocalSessionData->LogonType = Session->LogonType;
433 LocalSessionData->Session = 0;
434
435 /* Sid */
436 if (Session->Sid != NULL)
437 {
438 RtlCopyMemory(Ptr, Session->Sid, SidLength);
439 LocalSessionData->Sid = (PSID)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
440
441 Ptr = (PUCHAR)((ULONG_PTR)Ptr + SidLength);
442 }
443
444 /* LogonTime */
445 LocalSessionData->LogonTime.QuadPart = Session->LogonTime.QuadPart;
446
447 /* Copy the LogonServer string */
448 LocalSessionData->LogonServer.Length = Session->LogonServer.Length;
449 LocalSessionData->LogonServer.MaximumLength = Session->LogonServer.MaximumLength;
450 if (Session->LogonServer.MaximumLength != 0)
451 {
452 RtlCopyMemory(Ptr, Session->LogonServer.Buffer, Session->LogonServer.MaximumLength);
453 LocalSessionData->LogonServer.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
454
455 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->LogonServer.MaximumLength);
456 }
457
458 /* Copy the DnsDomainName string */
459 LocalSessionData->DnsDomainName.Length = Session->DnsDomainName.Length;
460 LocalSessionData->DnsDomainName.MaximumLength = Session->DnsDomainName.MaximumLength;
461 if (Session->DnsDomainName.MaximumLength != 0)
462 {
463 RtlCopyMemory(Ptr, Session->DnsDomainName.Buffer, Session->DnsDomainName.MaximumLength);
464 LocalSessionData->DnsDomainName.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
465
466 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->DnsDomainName.MaximumLength);
467 }
468
469 /* Copy the Upn string */
470 LocalSessionData->Upn.Length = Session->Upn.Length;
471 LocalSessionData->Upn.MaximumLength = Session->Upn.MaximumLength;
472 if (Session->Upn.MaximumLength != 0)
473 {
474 RtlCopyMemory(Ptr, Session->Upn.Buffer, Session->Upn.MaximumLength);
475 LocalSessionData->Upn.Buffer = (PWSTR)((ULONG_PTR)Ptr - (ULONG_PTR)LocalSessionData);
476
477 Ptr = (PUCHAR)((ULONG_PTR)Ptr + Session->Upn.MaximumLength);
478 }
479
480
481 InitializeObjectAttributes(&ObjectAttributes,
482 NULL,
483 0,
484 NULL,
485 NULL);
486
487 Status = NtOpenProcess(&ProcessHandle,
488 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
489 &ObjectAttributes,
490 &RequestMsg->h.ClientId);
491 if (!NT_SUCCESS(Status))
492 {
493 TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
494 goto done;
495 }
496
497 MemSize = TotalLength;
498 Status = NtAllocateVirtualMemory(ProcessHandle,
499 &ClientBaseAddress,
500 0,
501 &MemSize,
502 MEM_COMMIT,
503 PAGE_READWRITE);
504 if (!NT_SUCCESS(Status))
505 {
506 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
507 goto done;
508 }
509
510 TRACE("MemSize: %lu\n", MemSize);
511 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
512
513 Status = NtWriteVirtualMemory(ProcessHandle,
514 ClientBaseAddress,
515 LocalSessionData,
516 TotalLength,
517 NULL);
518 if (!NT_SUCCESS(Status))
519 {
520 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
521 goto done;
522 }
523
524 RequestMsg->GetLogonSessionData.Reply.SessionDataBuffer = ClientBaseAddress;
525
526 done:
527 if (ProcessHandle != NULL)
528 NtClose(ProcessHandle);
529
530 if (LocalSessionData != NULL)
531 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSessionData);
532
533 return Status;
534 }
535
536 /* EOF */