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 Context->TrustedCaller = RequestMsg->ConnectInfo.TrustedCaller;
139
140 if (Context->TrustedCaller)
141 Context->TrustedCaller = LsapIsTrustedClient(ProcessHandle);
142
143 *LogonContext = Context;
144
145 return STATUS_SUCCESS;
146 }
147
148
149 static NTSTATUS
LsapHandlePortConnection(PLSA_API_MSG RequestMsg)150 LsapHandlePortConnection(PLSA_API_MSG RequestMsg)
151 {
152 PLSAP_LOGON_CONTEXT LogonContext = NULL;
153 HANDLE ConnectionHandle = NULL;
154 BOOLEAN Accept;
155 REMOTE_PORT_VIEW RemotePortView;
156 NTSTATUS Status = STATUS_SUCCESS;
157
158 TRACE("LsapHandlePortConnection(%p)\n", RequestMsg);
159
160 TRACE("Logon Process Name: %s\n", RequestMsg->ConnectInfo.LogonProcessNameBuffer);
161
162 if (RequestMsg->ConnectInfo.CreateContext != FALSE)
163 {
164 Status = LsapCheckLogonProcess(RequestMsg,
165 &LogonContext);
166
167 RequestMsg->ConnectInfo.OperationalMode = 0x43218765;
168
169 RequestMsg->ConnectInfo.Status = Status;
170 }
171
172 if (NT_SUCCESS(Status))
173 {
174 Accept = TRUE;
175 }
176 else
177 {
178 Accept = FALSE;
179 }
180
181 RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
182 Status = NtAcceptConnectPort(&ConnectionHandle,
183 (PVOID*)LogonContext,
184 &RequestMsg->h,
185 Accept,
186 NULL,
187 &RemotePortView);
188 if (!NT_SUCCESS(Status))
189 {
190 ERR("NtAcceptConnectPort failed (Status 0x%lx)\n", Status);
191 return Status;
192 }
193
194 if (Accept != FALSE)
195 {
196 if (LogonContext != NULL)
197 {
198 LogonContext->ConnectionHandle = ConnectionHandle;
199
200 InsertHeadList(&LsapLogonContextList,
201 &LogonContext->Entry);
202 }
203
204 Status = NtCompleteConnectPort(ConnectionHandle);
205 if (!NT_SUCCESS(Status))
206 {
207 ERR("NtCompleteConnectPort failed (Status 0x%lx)\n", Status);
208 return Status;
209 }
210 }
211
212 return Status;
213 }
214
215
216 NTSTATUS WINAPI
AuthPortThreadRoutine(PVOID Param)217 AuthPortThreadRoutine(PVOID Param)
218 {
219 PLSAP_LOGON_CONTEXT LogonContext;
220 PLSA_API_MSG ReplyMsg = NULL;
221 LSA_API_MSG RequestMsg;
222 NTSTATUS Status;
223
224 TRACE("AuthPortThreadRoutine() called\n");
225
226 Status = STATUS_SUCCESS;
227
228 for (;;)
229 {
230 TRACE("Reply: %p\n", ReplyMsg);
231 Status = NtReplyWaitReceivePort(AuthPortHandle,
232 (PVOID*)&LogonContext,
233 (PPORT_MESSAGE)ReplyMsg,
234 (PPORT_MESSAGE)&RequestMsg);
235 if (!NT_SUCCESS(Status))
236 {
237 TRACE("NtReplyWaitReceivePort() failed (Status %lx)\n", Status);
238 break;
239 }
240
241 TRACE("Received message\n");
242
243 switch (RequestMsg.h.u2.s2.Type)
244 {
245 case LPC_CONNECTION_REQUEST:
246 TRACE("Port connection request\n");
247 Status = LsapHandlePortConnection(&RequestMsg);
248 ReplyMsg = NULL;
249 break;
250
251 case LPC_PORT_CLOSED:
252 TRACE("Port closed\n");
253 ReplyMsg = NULL;
254 break;
255
256 case LPC_CLIENT_DIED:
257 TRACE("Client died\n");
258 ReplyMsg = NULL;
259 break;
260
261 default:
262 TRACE("Received request (ApiNumber: %lu)\n", RequestMsg.ApiNumber);
263
264 switch (RequestMsg.ApiNumber)
265 {
266 case LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE:
267 RequestMsg.Status = LsapCallAuthenticationPackage(&RequestMsg,
268 LogonContext);
269 ReplyMsg = &RequestMsg;
270 break;
271
272 case LSASS_REQUEST_DEREGISTER_LOGON_PROCESS:
273
274 ReplyMsg = &RequestMsg;
275 RequestMsg.Status = STATUS_SUCCESS;
276 NtReplyPort(AuthPortHandle,
277 &ReplyMsg->h);
278
279 LsapDeregisterLogonProcess(&RequestMsg,
280 LogonContext);
281
282 ReplyMsg = NULL;
283 break;
284
285 case LSASS_REQUEST_LOGON_USER:
286 RequestMsg.Status = LsapLogonUser(&RequestMsg,
287 LogonContext);
288 ReplyMsg = &RequestMsg;
289 break;
290
291 case LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE:
292 RequestMsg.Status = LsapLookupAuthenticationPackage(&RequestMsg,
293 LogonContext);
294 ReplyMsg = &RequestMsg;
295 break;
296
297 case LSASS_REQUEST_ENUM_LOGON_SESSIONS:
298 RequestMsg.Status = LsapEnumLogonSessions(&RequestMsg);
299 ReplyMsg = &RequestMsg;
300 break;
301
302 case LSASS_REQUEST_GET_LOGON_SESSION_DATA:
303 RequestMsg.Status = LsapGetLogonSessionData(&RequestMsg);
304 ReplyMsg = &RequestMsg;
305 break;
306
307 case LSASS_REQUEST_POLICY_CHANGE_NOTIFY:
308 RequestMsg.Status = LsapRegisterNotification(&RequestMsg);
309 ReplyMsg = &RequestMsg;
310 break;
311
312 default:
313 RequestMsg.Status = STATUS_INVALID_SYSTEM_SERVICE;
314 ReplyMsg = &RequestMsg;
315 break;
316 }
317
318 break;
319 }
320 }
321
322 return STATUS_SUCCESS;
323 }
324
325
326 NTSTATUS
StartAuthenticationPort(VOID)327 StartAuthenticationPort(VOID)
328 {
329 OBJECT_ATTRIBUTES ObjectAttributes;
330 UNICODE_STRING PortName;
331 DWORD ThreadId;
332 UNICODE_STRING EventName;
333 HANDLE EventHandle;
334 NTSTATUS Status;
335
336 TRACE("StartAuthenticationPort()\n");
337
338 /* Initialize the logon context list */
339 InitializeListHead(&LsapLogonContextList);
340
341 RtlInitUnicodeString(&PortName,
342 L"\\LsaAuthenticationPort");
343
344 InitializeObjectAttributes(&ObjectAttributes,
345 &PortName,
346 0,
347 NULL,
348 NULL);
349
350 Status = NtCreatePort(&AuthPortHandle,
351 &ObjectAttributes,
352 sizeof(LSA_CONNECTION_INFO),
353 sizeof(LSA_API_MSG),
354 sizeof(LSA_API_MSG) * 32);
355 if (!NT_SUCCESS(Status))
356 {
357 WARN("NtCreatePort() failed (Status %lx)\n", Status);
358 return Status;
359 }
360
361 RtlInitUnicodeString(&EventName,
362 L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED");
363 InitializeObjectAttributes(&ObjectAttributes,
364 &EventName,
365 OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
366 NULL,
367 NULL);
368 Status = NtOpenEvent(&EventHandle,
369 EVENT_MODIFY_STATE,
370 &ObjectAttributes);
371 if (!NT_SUCCESS(Status))
372 {
373 TRACE("NtOpenEvent failed (Status 0x%08lx)\n", Status);
374
375 Status = NtCreateEvent(&EventHandle,
376 EVENT_MODIFY_STATE,
377 &ObjectAttributes,
378 NotificationEvent,
379 FALSE);
380 if (!NT_SUCCESS(Status))
381 {
382 WARN("NtCreateEvent failed (Status 0x%08lx)\n", Status);
383 return Status;
384 }
385 }
386
387 Status = NtSetEvent(EventHandle, NULL);
388 NtClose(EventHandle);
389 if (!NT_SUCCESS(Status))
390 {
391 WARN("NtSetEvent failed (Status 0x%08lx)\n", Status);
392 return Status;
393 }
394
395 PortThreadHandle = CreateThread(NULL,
396 0x1000,
397 (LPTHREAD_START_ROUTINE)AuthPortThreadRoutine,
398 NULL,
399 0,
400 &ThreadId);
401
402
403 return STATUS_SUCCESS;
404 }
405
406 /* EOF */
407