4ed6b45912991000a2ad27d210d0b399d8a8ec47
[reactos.git] / reactos / sdk / lib / lsalib / lsa.c
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 <psdk/ntsecapi.h>
19 #include <lsass/lsass.h>
20
21 #define NDEBUG
22 #include <debug.h>
23
24 /* GLOBALS *******************************************************************/
25
26 // FIXME: Do we really need this?!
27 #if !defined(__NTOSKRNL__) && !defined(_NTOSKRNL_) && !defined(_NTSYSTEM_)
28 extern HANDLE Secur32Heap;
29 #endif
30
31 /* FUNCTIONS *****************************************************************/
32
33 /* This API is not defined and exported by NTOSKRNL */
34 #if !defined(__NTOSKRNL__) && !defined(_NTOSKRNL_) && !defined(_NTSYSTEM_)
35 /*
36 * @implemented
37 */
38 NTSTATUS
39 NTAPI
40 LsaConnectUntrusted(OUT PHANDLE LsaHandle)
41 {
42 NTSTATUS Status;
43 UNICODE_STRING PortName; // = RTL_CONSTANT_STRING(L"\\LsaAuthenticationPort");
44 SECURITY_QUALITY_OF_SERVICE SecurityQos;
45 LSA_CONNECTION_INFO ConnectInfo;
46 ULONG ConnectInfoLength = sizeof(ConnectInfo);
47
48 DPRINT("LsaConnectUntrusted(%p)\n", LsaHandle);
49
50 // TODO: Wait on L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED" event
51 // for the LSA server to be ready, and because we are untrusted,
52 // we may need to impersonate ourselves before!
53
54 RtlInitUnicodeString(&PortName, L"\\LsaAuthenticationPort");
55
56 SecurityQos.Length = sizeof(SecurityQos);
57 SecurityQos.ImpersonationLevel = SecurityIdentification;
58 SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
59 SecurityQos.EffectiveOnly = TRUE;
60
61 RtlZeroMemory(&ConnectInfo,
62 ConnectInfoLength);
63
64 ConnectInfo.CreateContext = TRUE;
65
66 Status = ZwConnectPort(LsaHandle,
67 &PortName,
68 &SecurityQos,
69 NULL,
70 NULL,
71 NULL,
72 &ConnectInfo,
73 &ConnectInfoLength);
74 if (!NT_SUCCESS(Status))
75 {
76 DPRINT1("ZwConnectPort failed (Status 0x%08lx)\n", Status);
77 return Status;
78 }
79
80 if (!NT_SUCCESS(ConnectInfo.Status))
81 {
82 DPRINT1("ConnectInfo.Status: 0x%08lx\n", ConnectInfo.Status);
83 }
84
85 return ConnectInfo.Status;
86 }
87 #endif
88
89 /*
90 * @implemented
91 */
92 NTSTATUS
93 NTAPI
94 LsaCallAuthenticationPackage(IN HANDLE LsaHandle,
95 IN ULONG AuthenticationPackage,
96 IN PVOID ProtocolSubmitBuffer,
97 IN ULONG SubmitBufferLength,
98 OUT PVOID *ProtocolReturnBuffer,
99 OUT PULONG ReturnBufferLength,
100 OUT PNTSTATUS ProtocolStatus)
101 {
102 NTSTATUS Status;
103 LSA_API_MSG ApiMessage;
104
105 DPRINT1("LsaCallAuthenticationPackage()\n");
106
107 ApiMessage.ApiNumber = LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE;
108 ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.CallAuthenticationPackage);
109 ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
110 ApiMessage.h.u2.ZeroInit = 0;
111
112 ApiMessage.CallAuthenticationPackage.Request.AuthenticationPackage = AuthenticationPackage;
113 ApiMessage.CallAuthenticationPackage.Request.ProtocolSubmitBuffer = ProtocolSubmitBuffer;
114 ApiMessage.CallAuthenticationPackage.Request.SubmitBufferLength = SubmitBufferLength;
115
116 Status = ZwRequestWaitReplyPort(LsaHandle,
117 (PPORT_MESSAGE)&ApiMessage,
118 (PPORT_MESSAGE)&ApiMessage);
119 if (!NT_SUCCESS(Status))
120 {
121 DPRINT1("ZwRequestWaitReplyPort() failed (Status 0x%08lx)\n", Status);
122 return Status;
123 }
124
125 if (!NT_SUCCESS(ApiMessage.Status))
126 {
127 DPRINT1("ZwRequestWaitReplyPort() failed (ApiMessage.Status 0x%08lx)\n", ApiMessage.Status);
128 return ApiMessage.Status;
129 }
130
131 *ProtocolReturnBuffer = ApiMessage.CallAuthenticationPackage.Reply.ProtocolReturnBuffer;
132 *ReturnBufferLength = ApiMessage.CallAuthenticationPackage.Reply.ReturnBufferLength;
133 *ProtocolStatus = ApiMessage.CallAuthenticationPackage.Reply.ProtocolStatus;
134
135 return Status;
136 }
137
138
139 /*
140 * @implemented
141 */
142 NTSTATUS
143 NTAPI
144 LsaFreeReturnBuffer(IN PVOID Buffer)
145 {
146 SIZE_T Size = 0;
147 return ZwFreeVirtualMemory(NtCurrentProcess(),
148 &Buffer,
149 &Size,
150 MEM_RELEASE);
151 }
152
153
154 /*
155 * @implemented
156 */
157 NTSTATUS
158 NTAPI
159 LsaLookupAuthenticationPackage(IN HANDLE LsaHandle,
160 IN PLSA_STRING PackageName,
161 OUT PULONG AuthenticationPackage)
162 {
163 NTSTATUS Status;
164 LSA_API_MSG ApiMessage;
165
166 /* Check the package name length */
167 if (PackageName->Length > LSASS_MAX_PACKAGE_NAME_LENGTH)
168 {
169 return STATUS_NAME_TOO_LONG;
170 }
171
172 ApiMessage.ApiNumber = LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE;
173 ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.LookupAuthenticationPackage);
174 ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
175 ApiMessage.h.u2.ZeroInit = 0;
176
177 ApiMessage.LookupAuthenticationPackage.Request.PackageNameLength = PackageName->Length;
178 strncpy(ApiMessage.LookupAuthenticationPackage.Request.PackageName,
179 PackageName->Buffer,
180 ApiMessage.LookupAuthenticationPackage.Request.PackageNameLength);
181 ApiMessage.LookupAuthenticationPackage.Request.PackageName[ApiMessage.LookupAuthenticationPackage.Request.PackageNameLength] = ANSI_NULL;
182
183 Status = ZwRequestWaitReplyPort(LsaHandle,
184 (PPORT_MESSAGE)&ApiMessage,
185 (PPORT_MESSAGE)&ApiMessage);
186 if (!NT_SUCCESS(Status))
187 {
188 return Status;
189 }
190
191 if (!NT_SUCCESS(ApiMessage.Status))
192 {
193 return ApiMessage.Status;
194 }
195
196 *AuthenticationPackage = ApiMessage.LookupAuthenticationPackage.Reply.Package;
197
198 return Status;
199 }
200
201
202 /*
203 * @implemented
204 */
205 NTSTATUS
206 NTAPI
207 LsaLogonUser(IN HANDLE LsaHandle,
208 IN PLSA_STRING OriginName,
209 IN SECURITY_LOGON_TYPE LogonType,
210 IN ULONG AuthenticationPackage,
211 IN PVOID AuthenticationInformation,
212 IN ULONG AuthenticationInformationLength,
213 IN PTOKEN_GROUPS LocalGroups OPTIONAL,
214 IN PTOKEN_SOURCE SourceContext,
215 OUT PVOID *ProfileBuffer,
216 OUT PULONG ProfileBufferLength,
217 OUT PLUID LogonId,
218 OUT PHANDLE Token,
219 OUT PQUOTA_LIMITS Quotas,
220 OUT PNTSTATUS SubStatus)
221 {
222 NTSTATUS Status;
223 LSA_API_MSG ApiMessage;
224
225 ApiMessage.ApiNumber = LSASS_REQUEST_LOGON_USER;
226 ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.LogonUser);
227 ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
228 ApiMessage.h.u2.ZeroInit = 0;
229
230 ApiMessage.LogonUser.Request.OriginName = *OriginName;
231 ApiMessage.LogonUser.Request.LogonType = LogonType;
232 ApiMessage.LogonUser.Request.AuthenticationPackage = AuthenticationPackage;
233 ApiMessage.LogonUser.Request.AuthenticationInformation = AuthenticationInformation;
234 ApiMessage.LogonUser.Request.AuthenticationInformationLength = AuthenticationInformationLength;
235 ApiMessage.LogonUser.Request.LocalGroups = LocalGroups;
236 if (LocalGroups != NULL)
237 ApiMessage.LogonUser.Request.LocalGroupsCount = LocalGroups->GroupCount;
238 else
239 ApiMessage.LogonUser.Request.LocalGroupsCount = 0;
240 ApiMessage.LogonUser.Request.SourceContext = *SourceContext;
241
242 Status = ZwRequestWaitReplyPort(LsaHandle,
243 (PPORT_MESSAGE)&ApiMessage,
244 (PPORT_MESSAGE)&ApiMessage);
245 if (!NT_SUCCESS(Status))
246 {
247 return Status;
248 }
249
250 *SubStatus = ApiMessage.LogonUser.Reply.SubStatus;
251
252 if (!NT_SUCCESS(ApiMessage.Status))
253 {
254 return ApiMessage.Status;
255 }
256
257 *ProfileBuffer = ApiMessage.LogonUser.Reply.ProfileBuffer;
258 *ProfileBufferLength = ApiMessage.LogonUser.Reply.ProfileBufferLength;
259 *LogonId = ApiMessage.LogonUser.Reply.LogonId;
260 *Token = ApiMessage.LogonUser.Reply.Token;
261 *Quotas = ApiMessage.LogonUser.Reply.Quotas;
262
263 return Status;
264 }
265
266
267 /*
268 * @implemented
269 */
270 NTSTATUS
271 NTAPI
272 LsaRegisterLogonProcess(IN PLSA_STRING LogonProcessName,
273 OUT PHANDLE LsaHandle,
274 OUT PLSA_OPERATIONAL_MODE OperationalMode)
275 {
276 NTSTATUS Status;
277 HANDLE EventHandle;
278 UNICODE_STRING PortName; // = RTL_CONSTANT_STRING(L"\\LsaAuthenticationPort");
279 OBJECT_ATTRIBUTES ObjectAttributes;
280 SECURITY_QUALITY_OF_SERVICE SecurityQos;
281 LSA_CONNECTION_INFO ConnectInfo;
282 ULONG ConnectInfoLength = sizeof(ConnectInfo);
283
284 DPRINT("LsaRegisterLogonProcess()\n");
285
286 /* Check the logon process name length */
287 if (LogonProcessName->Length > LSASS_MAX_LOGON_PROCESS_NAME_LENGTH)
288 return STATUS_NAME_TOO_LONG;
289
290 /*
291 * First check whether the LSA server is ready:
292 * open the LSA event and wait on it.
293 */
294 // Note that we just reuse the 'PortName' variable here.
295 RtlInitUnicodeString(&PortName, L"\\SECURITY\\LSA_AUTHENTICATION_INITIALIZED");
296 InitializeObjectAttributes(&ObjectAttributes,
297 &PortName,
298 OBJ_CASE_INSENSITIVE,
299 NULL,
300 NULL);
301 Status = NtOpenEvent(&EventHandle, SYNCHRONIZE, &ObjectAttributes);
302 if (!NT_SUCCESS(Status))
303 {
304 DPRINT1("NtOpenEvent failed (Status 0x%08lx)\n", Status);
305 return Status;
306 }
307
308 Status = NtWaitForSingleObject(EventHandle, TRUE, NULL);
309 NtClose(EventHandle);
310 if (!NT_SUCCESS(Status))
311 {
312 DPRINT1("NtWaitForSingleObject failed (Status 0x%08lx)\n", Status);
313 return Status;
314 }
315
316 /* Now attempt the connection */
317 RtlInitUnicodeString(&PortName, L"\\LsaAuthenticationPort");
318
319 SecurityQos.Length = sizeof(SecurityQos);
320 SecurityQos.ImpersonationLevel = SecurityIdentification;
321 SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
322 SecurityQos.EffectiveOnly = TRUE;
323
324 strncpy(ConnectInfo.LogonProcessNameBuffer,
325 LogonProcessName->Buffer,
326 LogonProcessName->Length);
327 ConnectInfo.Length = LogonProcessName->Length;
328 ConnectInfo.LogonProcessNameBuffer[ConnectInfo.Length] = ANSI_NULL;
329 ConnectInfo.CreateContext = TRUE;
330
331 Status = ZwConnectPort(LsaHandle,
332 &PortName,
333 &SecurityQos,
334 NULL,
335 NULL,
336 NULL,
337 &ConnectInfo,
338 &ConnectInfoLength);
339 if (!NT_SUCCESS(Status))
340 {
341 DPRINT1("ZwConnectPort failed (Status 0x%08lx)\n", Status);
342 return Status;
343 }
344
345 DPRINT("ConnectInfo.OperationalMode: 0x%08lx\n", ConnectInfo.OperationalMode);
346 *OperationalMode = ConnectInfo.OperationalMode;
347
348 if (!NT_SUCCESS(ConnectInfo.Status))
349 {
350 DPRINT1("ConnectInfo.Status: 0x%08lx\n", ConnectInfo.Status);
351 }
352
353 return ConnectInfo.Status;
354 }
355
356
357 /*
358 * @implemented
359 */
360 NTSTATUS
361 NTAPI
362 LsaDeregisterLogonProcess(IN HANDLE LsaHandle)
363 {
364 NTSTATUS Status;
365 LSA_API_MSG ApiMessage;
366
367 DPRINT("LsaDeregisterLogonProcess()\n");
368
369 ApiMessage.ApiNumber = LSASS_REQUEST_DEREGISTER_LOGON_PROCESS;
370 ApiMessage.h.u1.s1.DataLength = LSA_PORT_DATA_SIZE(ApiMessage.DeregisterLogonProcess);
371 ApiMessage.h.u1.s1.TotalLength = LSA_PORT_MESSAGE_SIZE;
372 ApiMessage.h.u2.ZeroInit = 0;
373
374 Status = ZwRequestWaitReplyPort(LsaHandle,
375 (PPORT_MESSAGE)&ApiMessage,
376 (PPORT_MESSAGE)&ApiMessage);
377 if (!NT_SUCCESS(Status))
378 {
379 DPRINT1("ZwRequestWaitReplyPort() failed (Status 0x%08lx)\n", Status);
380 return Status;
381 }
382
383 if (!NT_SUCCESS(ApiMessage.Status))
384 {
385 DPRINT1("ZwRequestWaitReplyPort() failed (ApiMessage.Status 0x%08lx)\n", ApiMessage.Status);
386 return ApiMessage.Status;
387 }
388
389 NtClose(LsaHandle);
390
391 DPRINT("LsaDeregisterLogonProcess() done (Status 0x%08lx)\n", Status);
392
393 return Status;
394 }