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