[DLLS] Fix 64 bit issues
[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;
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 */