[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(IN PLUID LogonId)
68 {
69 PLSAP_LOGON_SESSION Session;
70
71 TRACE("LsapSetLogonSessionData(%p)\n", LogonId);
72
73 Session = LsapGetLogonSession(LogonId);
74 if (Session == NULL)
75 return STATUS_NO_SUCH_LOGON_SESSION;
76
77
78 return STATUS_SUCCESS;
79 }
80
81
82 NTSTATUS
83 NTAPI
84 LsapCreateLogonSession(IN PLUID LogonId)
85 {
86 PLSAP_LOGON_SESSION Session;
87 NTSTATUS Status;
88
89 TRACE("LsapCreateLogonSession(%p)\n", LogonId);
90
91 /* Fail, if a session already exists */
92 if (LsapGetLogonSession(LogonId) != NULL)
93 return STATUS_LOGON_SESSION_COLLISION;
94
95 /* Allocate a new session entry */
96 Session = RtlAllocateHeap(RtlGetProcessHeap(),
97 HEAP_ZERO_MEMORY,
98 sizeof(LSAP_LOGON_SESSION));
99 if (Session == NULL)
100 return STATUS_INSUFFICIENT_RESOURCES;
101
102 /* Initialize the session entry */
103 RtlCopyLuid(&Session->LogonId, LogonId);
104
105 TRACE("LsapCreateLogonSession(<0x%lx,0x%lx>)\n",
106 LogonId->HighPart, LogonId->LowPart);
107
108 /* Tell ntoskrnl to create a new logon session */
109 Status = LsapRmCreateLogonSession(LogonId);
110 if (!NT_SUCCESS(Status))
111 {
112 RtlFreeHeap(RtlGetProcessHeap(), 0, Session);
113 return Status;
114 }
115
116 /* Insert the new session into the session list */
117 InsertHeadList(&SessionListHead, &Session->Entry);
118 SessionCount++;
119
120 return STATUS_SUCCESS;
121 }
122
123
124 NTSTATUS
125 NTAPI
126 LsapDeleteLogonSession(IN PLUID LogonId)
127 {
128 PLSAP_LOGON_SESSION Session;
129 NTSTATUS Status;
130
131 TRACE("LsapDeleteLogonSession(%p)\n", LogonId);
132
133 /* Fail, if the session does not exist */
134 Session = LsapGetLogonSession(LogonId);
135 if (Session == NULL)
136 return STATUS_NO_SUCH_LOGON_SESSION;
137
138 TRACE("LsapDeleteLogonSession(<0x%lx,0x%lx>)\n",
139 LogonId->HighPart, LogonId->LowPart);
140
141 /* Tell ntoskrnl to delete the logon session */
142 Status = LsapRmDeleteLogonSession(LogonId);
143 if (!NT_SUCCESS(Status))
144 return Status;
145
146 /* Remove the session entry from the list */
147 RemoveEntryList(&Session->Entry);
148 SessionCount--;
149
150 /* Free the session data */
151 if (Session->Sid != NULL)
152 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Sid);
153
154 if (Session->UserName.Buffer != NULL)
155 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->UserName.Buffer);
156
157 if (Session->LogonDomain.Buffer != NULL)
158 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonDomain.Buffer);
159
160 if (Session->AuthenticationPackage.Buffer != NULL)
161 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->AuthenticationPackage.Buffer);
162
163 if (Session->LogonServer.Buffer != NULL)
164 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->LogonServer.Buffer);
165
166 if (Session->DnsDomainName.Buffer != NULL)
167 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->DnsDomainName.Buffer);
168
169 if (Session->Upn.Buffer != NULL)
170 RtlFreeHeap(RtlGetProcessHeap(), 0, Session->Upn.Buffer);
171
172 /* Free the session entry */
173 RtlFreeHeap(RtlGetProcessHeap(), 0, Session);
174
175 return STATUS_SUCCESS;
176 }
177
178
179 NTSTATUS
180 LsapEnumLogonSessions(IN OUT PLSA_API_MSG RequestMsg)
181 {
182 OBJECT_ATTRIBUTES ObjectAttributes;
183 HANDLE ProcessHandle = NULL;
184 PLIST_ENTRY SessionEntry;
185 PLSAP_LOGON_SESSION CurrentSession;
186 PLUID SessionList;
187 ULONG i, Length, MemSize;
188 PVOID ClientBaseAddress = NULL;
189 NTSTATUS Status;
190
191 TRACE("LsapEnumLogonSessions(%p)\n", RequestMsg);
192
193 Length = SessionCount * sizeof(LUID);
194 SessionList = RtlAllocateHeap(RtlGetProcessHeap(),
195 HEAP_ZERO_MEMORY,
196 Length);
197 if (SessionList == NULL)
198 return STATUS_INSUFFICIENT_RESOURCES;
199
200 i = 0;
201 SessionEntry = SessionListHead.Flink;
202 while (SessionEntry != &SessionListHead)
203 {
204 CurrentSession = CONTAINING_RECORD(SessionEntry,
205 LSAP_LOGON_SESSION,
206 Entry);
207
208 RtlCopyLuid(&SessionList[i],
209 &CurrentSession->LogonId);
210
211 SessionEntry = SessionEntry->Flink;
212 i++;
213 }
214
215 InitializeObjectAttributes(&ObjectAttributes,
216 NULL,
217 0,
218 NULL,
219 NULL);
220
221 Status = NtOpenProcess(&ProcessHandle,
222 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
223 &ObjectAttributes,
224 &RequestMsg->h.ClientId);
225 if (!NT_SUCCESS(Status))
226 {
227 TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
228 goto done;
229 }
230
231 TRACE("Length: %lu\n", Length);
232
233 MemSize = Length;
234 Status = NtAllocateVirtualMemory(ProcessHandle,
235 &ClientBaseAddress,
236 0,
237 &MemSize,
238 MEM_COMMIT,
239 PAGE_READWRITE);
240 if (!NT_SUCCESS(Status))
241 {
242 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
243 goto done;
244 }
245
246 TRACE("MemSize: %lu\n", MemSize);
247 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
248
249 Status = NtWriteVirtualMemory(ProcessHandle,
250 ClientBaseAddress,
251 SessionList,
252 Length,
253 NULL);
254 if (!NT_SUCCESS(Status))
255 {
256 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
257 goto done;
258 }
259
260 RequestMsg->EnumLogonSessions.Reply.LogonSessionCount = SessionCount;
261 RequestMsg->EnumLogonSessions.Reply.LogonSessionBuffer = ClientBaseAddress;
262
263 done:
264 if (ProcessHandle != NULL)
265 NtClose(ProcessHandle);
266
267 if (SessionList != NULL)
268 RtlFreeHeap(RtlGetProcessHeap(), 0, SessionList);
269
270 return Status;
271 }
272
273
274 NTSTATUS
275 LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg)
276 {
277 OBJECT_ATTRIBUTES ObjectAttributes;
278 HANDLE ProcessHandle = NULL;
279 PLSAP_LOGON_SESSION Session;
280 PSECURITY_LOGON_SESSION_DATA LocalSessionData;
281 PVOID ClientBaseAddress = NULL;
282 ULONG Length, MemSize;
283 LPWSTR Ptr;
284 NTSTATUS Status;
285
286 TRACE("LsapGetLogonSessionData(%p)\n", RequestMsg);
287
288 TRACE("LogonId: %lx\n", RequestMsg->GetLogonSessionData.Request.LogonId.LowPart);
289 Session = LsapGetLogonSession(&RequestMsg->GetLogonSessionData.Request.LogonId);
290 if (Session == NULL)
291 return STATUS_NO_SUCH_LOGON_SESSION;
292
293 Length = sizeof(SECURITY_LOGON_SESSION_DATA);
294 /*
295 Session->UserName.MaximumLength +
296 Session->LogonDomain.MaximumLength +
297 Session->AuthenticationPackage.MaximumLength +
298 Session->LogonServer.MaximumLength +
299 Session->DnsDomainName.MaximumLength +
300 Session->Upn.MaximumLength;
301
302 if (Session->Sid != NULL)
303 RtlLengthSid(Session->Sid);
304 */
305
306 TRACE("Length: %lu\n", Length);
307
308 LocalSessionData = RtlAllocateHeap(RtlGetProcessHeap(),
309 HEAP_ZERO_MEMORY,
310 Length);
311 if (LocalSessionData == NULL)
312 return STATUS_INSUFFICIENT_RESOURCES;
313
314 Ptr = (LPWSTR)((ULONG_PTR)LocalSessionData + sizeof(SECURITY_LOGON_SESSION_DATA));
315 TRACE("LocalSessionData: %p Ptr: %p\n", LocalSessionData, Ptr);
316
317 LocalSessionData->Size = sizeof(SECURITY_LOGON_SESSION_DATA);
318
319 RtlCopyLuid(&LocalSessionData->LogonId,
320 &RequestMsg->GetLogonSessionData.Request.LogonId);
321
322 InitializeObjectAttributes(&ObjectAttributes,
323 NULL,
324 0,
325 NULL,
326 NULL);
327
328 Status = NtOpenProcess(&ProcessHandle,
329 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
330 &ObjectAttributes,
331 &RequestMsg->h.ClientId);
332 if (!NT_SUCCESS(Status))
333 {
334 TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
335 goto done;
336 }
337
338 MemSize = Length;
339 Status = NtAllocateVirtualMemory(ProcessHandle,
340 &ClientBaseAddress,
341 0,
342 &MemSize,
343 MEM_COMMIT,
344 PAGE_READWRITE);
345 if (!NT_SUCCESS(Status))
346 {
347 TRACE("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
348 goto done;
349 }
350
351 TRACE("MemSize: %lu\n", MemSize);
352 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
353
354 Status = NtWriteVirtualMemory(ProcessHandle,
355 ClientBaseAddress,
356 LocalSessionData,
357 Length,
358 NULL);
359 if (!NT_SUCCESS(Status))
360 {
361 TRACE("NtWriteVirtualMemory() failed (Status %lx)\n", Status);
362 goto done;
363 }
364
365 RequestMsg->GetLogonSessionData.Reply.SessionDataBuffer = ClientBaseAddress;
366
367 done:
368 if (ProcessHandle != NULL)
369 NtClose(ProcessHandle);
370
371 if (LocalSessionData != NULL)
372 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalSessionData);
373
374 return Status;
375 }
376
377 /* EOF */