1 /*
2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/lsasrv/authport.c
5 * PURPOSE: LsaAuthenticationPort server routines
6 * COPYRIGHT: Copyright 2009 Eric Kohl
7 */
8
9 #include "lsasrv.h"
10
11 #include <ndk/lpcfuncs.h>
12
13 static LIST_ENTRY LsapLogonContextList;
14
15 static HANDLE PortThreadHandle = NULL;
16 static HANDLE AuthPortHandle = NULL;
17
18
19 /* FUNCTIONS ***************************************************************/
20
21 static NTSTATUS
LsapDeregisterLogonProcess(PLSA_API_MSG RequestMsg,PLSAP_LOGON_CONTEXT LogonContext)22 LsapDeregisterLogonProcess(PLSA_API_MSG RequestMsg,
23 PLSAP_LOGON_CONTEXT LogonContext)
24 {
25 TRACE("LsapDeregisterLogonProcess(%p %p)\n", RequestMsg, LogonContext);
26
27 RemoveHeadList(&LogonContext->Entry);
28
29 NtClose(LogonContext->ClientProcessHandle);
30 NtClose(LogonContext->ConnectionHandle);
31
32 RtlFreeHeap(RtlGetProcessHeap(), 0, LogonContext);
33
34 return STATUS_SUCCESS;
35 }
36
37
38 static
39 BOOL
LsapIsTrustedClient(_In_ HANDLE ProcessHandle)40 LsapIsTrustedClient(
41 _In_ HANDLE ProcessHandle)
42 {
43 LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};
44 HANDLE TokenHandle = NULL;
45 PTOKEN_PRIVILEGES Privileges = NULL;
46 ULONG Size, i;
47 BOOL Trusted = FALSE;
48 NTSTATUS Status;
49
50 Status = NtOpenProcessToken(ProcessHandle,
51 TOKEN_QUERY,
52 &TokenHandle);
53 if (!NT_SUCCESS(Status))
54 goto done;
55
56 Status = NtQueryInformationToken(TokenHandle,
57 TokenPrivileges,
58 NULL,
59 0,
60 &Size);
61 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
62 goto done;
63
64 Privileges = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
65 if (Privileges == NULL)
66 goto done;
67
68 Status = NtQueryInformationToken(TokenHandle,
69 TokenPrivileges,
70 Privileges,
71 Size,
72 &Size);
73 if (!NT_SUCCESS(Status))
74 goto done;
75
76 for (i = 0; i < Privileges->PrivilegeCount; i++)
77 {
78 if (RtlEqualLuid(&Privileges->Privileges[i].Luid, &TcbPrivilege))
79 {
80 Trusted = TRUE;
81 break;
82 }
83 }
84
85 done:
86 if (Privileges != NULL)
87 RtlFreeHeap(RtlGetProcessHeap(), 0, Privileges);
88
89 if (TokenHandle != NULL)
90 NtClose(TokenHandle);
91
92 return Trusted;
93 }
94
95
96 static NTSTATUS
LsapCheckLogonProcess(PLSA_API_MSG RequestMsg,PLSAP_LOGON_CONTEXT * LogonContext)97 LsapCheckLogonProcess(PLSA_API_MSG RequestMsg,
98 PLSAP_LOGON_CONTEXT *LogonContext)
99 {
100 OBJECT_ATTRIBUTES ObjectAttributes;
101 HANDLE ProcessHandle = NULL;
102 PLSAP_LOGON_CONTEXT Context = NULL;
103 NTSTATUS Status;
104
105 TRACE("LsapCheckLogonProcess(%p)\n", RequestMsg);
106
107 TRACE("Client ID: %p %p\n", RequestMsg->h.ClientId.UniqueProcess, RequestMsg->h.ClientId.UniqueThread);
108
109 InitializeObjectAttributes(&ObjectAttributes,
110 NULL,
111 0,
112 NULL,
113 NULL);
114
115 Status = NtOpenProcess(&ProcessHandle,
116 PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
117 &ObjectAttributes,
118 &RequestMsg->h.ClientId);
119 if (!NT_SUCCESS(Status))
120 {
121 TRACE("NtOpenProcess() failed (Status %lx)\n", Status);
122 return Status;
123 }
124
125 /* Allocate the logon context */
126 Context = RtlAllocateHeap(RtlGetProcessHeap(),
127 HEAP_ZERO_MEMORY,
128 sizeof(LSAP_LOGON_CONTEXT));
129 if (Context == NULL)
130 {
131 NtClose(ProcessHandle);
132 return STATUS_INSUFFICIENT_RESOURCES;
133 }
134
135 TRACE("New LogonContext: %p\n", Context);
136
137 Context->ClientProcessHandle = ProcessHandle;
138
139 switch (RequestMsg->ConnectInfo.TrustedCaller)
140 {
141 case NO:
142 Context->TrustedCaller = FALSE;
143 break;
144
145 case YES:
146 Context->TrustedCaller = TRUE;
147 break;
148
149 case CHECK:
150 default:
151 Context->TrustedCaller = LsapIsTrustedClient(ProcessHandle);
152 break;
153 }
154
155 TRACE("TrustedCaller: %u\n", Context->TrustedCaller);
156
157 *LogonContext = Context;
158
159 return STATUS_SUCCESS;
160 }
161
162
163 static NTSTATUS
LsapHandlePortConnection(PLSA_API_MSG RequestMsg)164 LsapHandlePortConnection(PLSA_API_MSG RequestMsg)
165 {
166 PLSAP_LOGON_CONTEXT LogonContext = NULL;
167 HANDLE ConnectionHandle = NULL;
168 BOOLEAN Accept;
169 REMOTE_PORT_VIEW RemotePortView;
170 NTSTATUS Status = STATUS_SUCCESS;
171
172 TRACE("LsapHandlePortConnection(%p)\n", RequestMsg);
173
174 TRACE("Logon Process Name: %s\n", RequestMsg->ConnectInfo.LogonProcessNameBuffer);
175
176 if (RequestMsg->ConnectInfo.CreateContext != FALSE)
177 {
178 Status = LsapCheckLogonProcess(RequestMsg,
179 &LogonContext);
180
181 RequestMsg->ConnectInfo.OperationalMode = 0x43218765;
182
183 RequestMsg->ConnectInfo.Status = Status;
184 }
185
186 if (NT_SUCCESS(Status))
187 {
188 Accept = TRUE;
189 }
190 else
191 {
192 Accept = FALSE;
193 }
194
195 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
196 Status = NtAcceptConnectPort(&ConnectionHandle,
197 (PVOID*)LogonContext,
198 &RequestMsg->h,
199 Accept,
200 NULL,
201 &RemotePortView);
202 if (!NT_SUCCESS(Status))
203 {
204 ERR("NtAcceptConnectPort failed (Status 0x%lx)\n", Status);
205 return Status;
206 }
207
208 if (Accept != FALSE)
209 {
210 if (LogonContext != NULL)
211 {
212 LogonContext->ConnectionHandle = ConnectionHandle;
213
214 InsertHeadList(&LsapLogonContextList,
215 &LogonContext->Entry);
216 }
217
218 Status = NtCompleteConnectPort(ConnectionHandle);
219 if (!NT_SUCCESS(Status))
220 {
221 ERR("NtCompleteConnectPort failed (Status 0x%lx)\n", Status);
222 return Status;
223 }
224 }
225
226 return Status;
227 }
228
229
230 NTSTATUS WINAPI
AuthPortThreadRoutine(PVOID Param)231 AuthPortThreadRoutine(PVOID Param)
232 {
233 PLSAP_LOGON_CONTEXT LogonContext;
234 PLSA_API_MSG ReplyMsg = NULL;
235 LSA_API_MSG RequestMsg;
236 NTSTATUS Status;
237
238 TRACE("AuthPortThreadRoutine() called\n");
239
240 Status = STATUS_SUCCESS;
241
242 for (;;)
243 {
244 TRACE("Reply: %p\n", ReplyMsg);
245 Status = NtReplyWaitReceivePort(AuthPortHandle,
246 (PVOID*)&LogonContext,
247 (PPORT_MESSAGE)ReplyMsg,
248 (PPORT_MESSAGE)&RequestMsg);
249 if (!NT_SUCCESS(Status))
250 {
251 TRACE("NtReplyWaitReceivePort() failed (Status %lx)\n", Status);
252 break;
253 }
254
255 TRACE("Received message\n");
256
257 switch (RequestMsg.h.u2.s2.Type)
258 {
259 case LPC_CONNECTION_REQUEST:
260 TRACE("Port connection request\n");
261 Status = LsapHandlePortConnection(&RequestMsg);
262 ReplyMsg = NULL;
263 break;
264
265 case LPC_PORT_CLOSED:
266 TRACE("Port closed\n");
267 ReplyMsg = NULL;
268 break;
269
270 case LPC_CLIENT_DIED:
271 TRACE("Client died\n");
272 ReplyMsg = NULL;
273 break;
274
275 default:
276 TRACE("Received request (ApiNumber: %lu)\n", RequestMsg.ApiNumber);
277
278 switch (RequestMsg.ApiNumber)
279 {
280 case LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE:
281 RequestMsg.Status = LsapCallAuthenticationPackage(&RequestMsg,
282 LogonContext);
283 ReplyMsg = &RequestMsg;
284 break;
285
286 case LSASS_REQUEST_DEREGISTER_LOGON_PROCESS:
287
288 ReplyMsg = &RequestMsg;
289 RequestMsg.Status = STATUS_SUCCESS;
290 NtReplyPort(AuthPortHandle,
291 &ReplyMsg->h);
292
293 LsapDeregisterLogonProcess(&RequestMsg,
294 LogonContext);
295
296 ReplyMsg = NULL;
297 break;
298
299 case LSASS_REQUEST_LOGON_USER:
300 RequestMsg.Status = LsapLogonUser(&RequestMsg,
301 LogonContext);
302 ReplyMsg = &RequestMsg;
303 break;
304
305 case LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE:
306 RequestMsg.Status = LsapLookupAuthenticationPackage(&RequestMsg,
307 LogonContext);
308 ReplyMsg = &RequestMsg;
309 break;
310
311 case LSASS_REQUEST_ENUM_LOGON_SESSIONS:
312 RequestMsg.Status = LsapEnumLogonSessions(&RequestMsg);
313 ReplyMsg = &RequestMsg;
314 break;
315
316 case LSASS_REQUEST_GET_LOGON_SESSION_DATA:
317 RequestMsg.Status = LsapGetLogonSessionData(&RequestMsg);
318 ReplyMsg = &RequestMsg;
319 break;
320
321 case LSASS_REQUEST_POLICY_CHANGE_NOTIFY:
322 RequestMsg.Status = LsapRegisterNotification(&RequestMsg);
323 ReplyMsg = &RequestMsg;
324 break;
325
326 default:
327 RequestMsg.Status = STATUS_INVALID_SYSTEM_SERVICE;
328 ReplyMsg = &RequestMsg;
329 break;
330 }
331
332 break;
333 }
334 }
335
336 return STATUS_SUCCESS;
337 }
338
339
340 NTSTATUS
StartAuthenticationPort(VOID)341 StartAuthenticationPort(VOID)
342 {
343 OBJECT_ATTRIBUTES ObjectAttributes;
344 UNICODE_STRING PortName;
345 DWORD ThreadId;
346 UNICODE_STRING EventName;
347 HANDLE EventHandle;
348 NTSTATUS Status;
349
350 TRACE("StartAuthenticationPort()\n");
351
352 /* Initialize the logon context list */
353 InitializeListHead(&LsapLogonContextList);
354
355 RtlInitUnicodeString(&PortName,
356 L"\\LsaAuthenticationPort");
357
358 InitializeObjectAttributes(&ObjectAttributes,
359 &PortName,
360 0,
361 NULL,
362 NULL);
363
364 Status = NtCreatePort(&AuthPortHandle,
365 &ObjectAttributes,
366 sizeof(LSA_CONNECTION_INFO),
367 sizeof(LSA_API_MSG),
368 sizeof(LSA_API_MSG) * 32);
369 if (!NT_SUCCESS(Status))
370 {
371 WARN("NtCreatePort() failed (Status %lx)\n", Status);
372 return Status;
373 }
374
375 RtlInitUnicodeString(&EventName,
376 L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED");
377 InitializeObjectAttributes(&ObjectAttributes,
378 &EventName,
379 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
380 NULL,
381 NULL);
382 Status = NtOpenEvent(&EventHandle,
383 EVENT_MODIFY_STATE,
384 &ObjectAttributes);
385 if (!NT_SUCCESS(Status))
386 {
387 TRACE("NtOpenEvent failed (Status 0x%08lx)\n", Status);
388
389 Status = NtCreateEvent(&EventHandle,
390 EVENT_MODIFY_STATE,
391 &ObjectAttributes,
392 NotificationEvent,
393 FALSE);
394 if (!NT_SUCCESS(Status))
395 {
396 WARN("NtCreateEvent failed (Status 0x%08lx)\n", Status);
397 return Status;
398 }
399 }
400
401 Status = NtSetEvent(EventHandle, NULL);
402 NtClose(EventHandle);
403 if (!NT_SUCCESS(Status))
404 {
405 WARN("NtSetEvent failed (Status 0x%08lx)\n", Status);
406 return Status;
407 }
408
409 PortThreadHandle = CreateThread(NULL,
410 0x1000,
411 (LPTHREAD_START_ROUTINE)AuthPortThreadRoutine,
412 NULL,
413 0,
414 &ThreadId);
415
416
417 return STATUS_SUCCESS;
418 }
419
420 /* EOF */
421