xref: /reactos/sdk/lib/lsalib/lsa.c (revision dc0433f0)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS system libraries
4  * FILE:            lib/lsalib/lsa.c
5  * PURPOSE:         Client-side LSA functions
6  * UPDATE HISTORY:
7  *                  Created 05/08/00
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <ndk/exfuncs.h>
13 #include <ndk/lpctypes.h>
14 #include <ndk/lpcfuncs.h>
15 #include <ndk/mmfuncs.h>
16 #include <ndk/rtlfuncs.h>
17 #include <ndk/obfuncs.h>
18 #include <lsass/lsass.h>
19 
20 #define NDEBUG
21 #include <debug.h>
22 
23 /* FUNCTIONS *****************************************************************/
24 
25 /*
26  * @implemented
27  */
28 NTSTATUS
29 NTAPI
30 LsaCallAuthenticationPackage(IN HANDLE LsaHandle,
31                              IN ULONG AuthenticationPackage,
32                              IN PVOID ProtocolSubmitBuffer,
33                              IN ULONG SubmitBufferLength,
34                              OUT PVOID *ProtocolReturnBuffer,
35                              OUT PULONG ReturnBufferLength,
36                              OUT PNTSTATUS ProtocolStatus)
37 {
38     LSA_API_MSG ApiMessage;
39     NTSTATUS Status;
40 
41     DPRINT1("LsaCallAuthenticationPackage()\n");
42 
43     ApiMessage.ApiNumber = LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE;
44     ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.CallAuthenticationPackage);
45     ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
46     ApiMessage.h.u2.ZeroInit = 0;
47 
48     ApiMessage.CallAuthenticationPackage.Request.AuthenticationPackage = AuthenticationPackage;
49     ApiMessage.CallAuthenticationPackage.Request.ProtocolSubmitBuffer = ProtocolSubmitBuffer;
50     ApiMessage.CallAuthenticationPackage.Request.SubmitBufferLength = SubmitBufferLength;
51 
52     Status = ZwRequestWaitReplyPort(LsaHandle,
53                                     (PPORT_MESSAGE)&ApiMessage,
54                                     (PPORT_MESSAGE)&ApiMessage);
55     if (!NT_SUCCESS(Status))
56     {
57         DPRINT1("ZwRequestWaitReplyPort() failed (Status 0x%08lx)\n", Status);
58         return Status;
59     }
60 
61     if (!NT_SUCCESS(ApiMessage.Status))
62     {
63         DPRINT1("ZwRequestWaitReplyPort() failed (ApiMessage.Status 0x%08lx)\n", ApiMessage.Status);
64         return ApiMessage.Status;
65     }
66 
67     *ProtocolReturnBuffer = ApiMessage.CallAuthenticationPackage.Reply.ProtocolReturnBuffer;
68     *ReturnBufferLength = ApiMessage.CallAuthenticationPackage.Reply.ReturnBufferLength;
69     *ProtocolStatus = ApiMessage.CallAuthenticationPackage.Reply.ProtocolStatus;
70 
71     return Status;
72 }
73 
74 
75 /*
76  * @implemented
77  */
78 NTSTATUS
79 NTAPI
80 LsaDeregisterLogonProcess(IN HANDLE LsaHandle)
81 {
82     LSA_API_MSG ApiMessage;
83     NTSTATUS Status;
84 
85     DPRINT("LsaDeregisterLogonProcess()\n");
86 
87     ApiMessage.ApiNumber = LSASS_REQUEST_DEREGISTER_LOGON_PROCESS;
88     ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.DeregisterLogonProcess);
89     ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
90     ApiMessage.h.u2.ZeroInit = 0;
91 
92     Status = ZwRequestWaitReplyPort(LsaHandle,
93                                     (PPORT_MESSAGE)&ApiMessage,
94                                     (PPORT_MESSAGE)&ApiMessage);
95     if (!NT_SUCCESS(Status))
96     {
97         DPRINT1("ZwRequestWaitReplyPort() failed (Status 0x%08lx)\n", Status);
98         return Status;
99     }
100 
101     if (!NT_SUCCESS(ApiMessage.Status))
102     {
103         DPRINT1("ZwRequestWaitReplyPort() failed (ApiMessage.Status 0x%08lx)\n", ApiMessage.Status);
104         return ApiMessage.Status;
105     }
106 
107     ZwClose(LsaHandle);
108 
109     DPRINT("LsaDeregisterLogonProcess() done (Status 0x%08lx)\n", Status);
110 
111     return Status;
112 }
113 
114 
115 /*
116  * @implemented
117  */
118 NTSTATUS
119 NTAPI
120 LsaFreeReturnBuffer(IN PVOID Buffer)
121 {
122     SIZE_T Size = 0;
123 
124     return ZwFreeVirtualMemory(NtCurrentProcess(),
125                                &Buffer,
126                                &Size,
127                                MEM_RELEASE);
128 }
129 
130 
131 /*
132  * @implemented
133  */
134 NTSTATUS
135 NTAPI
136 LsaLookupAuthenticationPackage(IN HANDLE LsaHandle,
137                                IN PLSA_STRING PackageName,
138                                OUT PULONG AuthenticationPackage)
139 {
140     LSA_API_MSG ApiMessage;
141     NTSTATUS Status;
142 
143     /* Check the package name length */
144     if (PackageName->Length > LSASS_MAX_PACKAGE_NAME_LENGTH)
145     {
146         return STATUS_NAME_TOO_LONG;
147     }
148 
149     ApiMessage.ApiNumber = LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE;
150     ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.LookupAuthenticationPackage);
151     ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
152     ApiMessage.h.u2.ZeroInit = 0;
153 
154     ApiMessage.LookupAuthenticationPackage.Request.PackageNameLength = PackageName->Length;
155     strncpy(ApiMessage.LookupAuthenticationPackage.Request.PackageName,
156             PackageName->Buffer,
157             ApiMessage.LookupAuthenticationPackage.Request.PackageNameLength);
158     ApiMessage.LookupAuthenticationPackage.Request.PackageName[ApiMessage.LookupAuthenticationPackage.Request.PackageNameLength] = ANSI_NULL;
159 
160     Status = ZwRequestWaitReplyPort(LsaHandle,
161                                     (PPORT_MESSAGE)&ApiMessage,
162                                     (PPORT_MESSAGE)&ApiMessage);
163     if (!NT_SUCCESS(Status))
164     {
165         return Status;
166     }
167 
168     if (!NT_SUCCESS(ApiMessage.Status))
169     {
170         return ApiMessage.Status;
171     }
172 
173     *AuthenticationPackage = ApiMessage.LookupAuthenticationPackage.Reply.Package;
174 
175     return Status;
176 }
177 
178 
179 /*
180  * @implemented
181  */
182 NTSTATUS
183 NTAPI
184 LsaLogonUser(IN HANDLE LsaHandle,
185              IN PLSA_STRING OriginName,
186              IN SECURITY_LOGON_TYPE LogonType,
187              IN ULONG AuthenticationPackage,
188              IN PVOID AuthenticationInformation,
189              IN ULONG AuthenticationInformationLength,
190              IN PTOKEN_GROUPS LocalGroups OPTIONAL,
191              IN PTOKEN_SOURCE SourceContext,
192              OUT PVOID *ProfileBuffer,
193              OUT PULONG ProfileBufferLength,
194              OUT PLUID LogonId,
195              OUT PHANDLE Token,
196              OUT PQUOTA_LIMITS Quotas,
197              OUT PNTSTATUS SubStatus)
198 {
199     LSA_API_MSG ApiMessage;
200     NTSTATUS Status;
201 
202     ApiMessage.ApiNumber = LSASS_REQUEST_LOGON_USER;
203     ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.LogonUser);
204     ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
205     ApiMessage.h.u2.ZeroInit = 0;
206 
207     ApiMessage.LogonUser.Request.OriginName = *OriginName;
208     ApiMessage.LogonUser.Request.LogonType = LogonType;
209     ApiMessage.LogonUser.Request.AuthenticationPackage = AuthenticationPackage;
210     ApiMessage.LogonUser.Request.AuthenticationInformation = AuthenticationInformation;
211     ApiMessage.LogonUser.Request.AuthenticationInformationLength = AuthenticationInformationLength;
212     ApiMessage.LogonUser.Request.LocalGroups = LocalGroups;
213     if (LocalGroups != NULL)
214         ApiMessage.LogonUser.Request.LocalGroupsCount = LocalGroups->GroupCount;
215     else
216         ApiMessage.LogonUser.Request.LocalGroupsCount = 0;
217     ApiMessage.LogonUser.Request.SourceContext = *SourceContext;
218 
219     Status = ZwRequestWaitReplyPort(LsaHandle,
220                                     (PPORT_MESSAGE)&ApiMessage,
221                                     (PPORT_MESSAGE)&ApiMessage);
222     if (!NT_SUCCESS(Status))
223     {
224         return Status;
225     }
226 
227     *SubStatus = ApiMessage.LogonUser.Reply.SubStatus;
228 
229     if (!NT_SUCCESS(ApiMessage.Status))
230     {
231         return ApiMessage.Status;
232     }
233 
234     *ProfileBuffer = ApiMessage.LogonUser.Reply.ProfileBuffer;
235     *ProfileBufferLength = ApiMessage.LogonUser.Reply.ProfileBufferLength;
236     *LogonId = ApiMessage.LogonUser.Reply.LogonId;
237     *Token = ApiMessage.LogonUser.Reply.Token;
238     *Quotas = ApiMessage.LogonUser.Reply.Quotas;
239 
240     return Status;
241 }
242 
243 
244 /*
245  * @implemented
246  */
247 NTSTATUS
248 NTAPI
249 LsaRegisterLogonProcess(IN PLSA_STRING LogonProcessName,
250                         OUT PHANDLE LsaHandle,
251                         OUT PLSA_OPERATIONAL_MODE OperationalMode)
252 {
253     SECURITY_QUALITY_OF_SERVICE SecurityQos;
254     LSA_CONNECTION_INFO ConnectInfo;
255     ULONG ConnectInfoLength = sizeof(ConnectInfo);
256     UNICODE_STRING PortName;
257     OBJECT_ATTRIBUTES ObjectAttributes;
258     UNICODE_STRING EventName;
259     HANDLE EventHandle;
260     NTSTATUS Status;
261 
262     DPRINT("LsaRegisterLogonProcess()\n");
263 
264     /* Check the logon process name length */
265     if (LogonProcessName->Length > LSASS_MAX_LOGON_PROCESS_NAME_LENGTH)
266         return STATUS_NAME_TOO_LONG;
267 
268     /* Wait for the LSA authentication thread */
269     RtlInitUnicodeString(&EventName,
270                          L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED");
271     InitializeObjectAttributes(&ObjectAttributes,
272                                &EventName,
273                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
274                                NULL,
275                                NULL);
276     Status = ZwOpenEvent(&EventHandle,
277                          SYNCHRONIZE,
278                          &ObjectAttributes);
279     if (!NT_SUCCESS(Status))
280     {
281         DPRINT("ZwOpenEvent failed (Status 0x%08lx)\n", Status);
282 
283         Status = ZwCreateEvent(&EventHandle,
284                                SYNCHRONIZE,
285                                &ObjectAttributes,
286                                NotificationEvent,
287                                FALSE);
288         if (!NT_SUCCESS(Status))
289         {
290             DPRINT1("ZwCreateEvent failed (Status 0x%08lx)\n", Status);
291             return Status;
292         }
293     }
294 
295     Status = ZwWaitForSingleObject(EventHandle,
296                                    TRUE,
297                                    NULL);
298     ZwClose(EventHandle);
299     if (!NT_SUCCESS(Status))
300     {
301         DPRINT1("ZwWaitForSingleObject failed (Status 0x%08lx)\n", Status);
302         return Status;
303     }
304 
305     /* Establish the connection */
306     RtlInitUnicodeString(&PortName,
307                          L"\\LsaAuthenticationPort");
308 
309     SecurityQos.Length              = sizeof(SecurityQos);
310     SecurityQos.ImpersonationLevel  = SecurityIdentification;
311     SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
312     SecurityQos.EffectiveOnly       = TRUE;
313 
314     strncpy(ConnectInfo.LogonProcessNameBuffer,
315             LogonProcessName->Buffer,
316             LogonProcessName->Length);
317     ConnectInfo.Length = LogonProcessName->Length;
318     ConnectInfo.LogonProcessNameBuffer[ConnectInfo.Length] = ANSI_NULL;
319     ConnectInfo.CreateContext = TRUE;
320 
321     Status = ZwConnectPort(LsaHandle,
322                            &PortName,
323                            &SecurityQos,
324                            NULL,
325                            NULL,
326                            NULL,
327                            &ConnectInfo,
328                            &ConnectInfoLength);
329     if (!NT_SUCCESS(Status))
330     {
331         DPRINT1("ZwConnectPort failed (Status 0x%08lx)\n", Status);
332         return Status;
333     }
334 
335     DPRINT("ConnectInfo.OperationalMode: 0x%08lx\n", ConnectInfo.OperationalMode);
336     *OperationalMode = ConnectInfo.OperationalMode;
337 
338     if (!NT_SUCCESS(ConnectInfo.Status))
339     {
340         DPRINT1("ConnectInfo.Status: 0x%08lx\n", ConnectInfo.Status);
341     }
342 
343     return ConnectInfo.Status;
344 }
345