xref: /reactos/dll/win32/lsasrv/authport.c (revision 9c544a55)
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
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
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
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
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
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
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