[LSASRV][MSV1_0]
[reactos.git] / reactos / dll / win32 / lsasrv / authpackage.c
1 /*
2 * PROJECT: Local Security Authority Server DLL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/lsasrv/authpackage.c
5 * PURPOSE: Authenticaton package management routines
6 * COPYRIGHT: Copyright 2013 Eric Kohl
7 */
8
9 #include "lsasrv.h"
10
11 typedef enum _LSA_TOKEN_INFORMATION_TYPE
12 {
13 LsaTokenInformationNull,
14 LsaTokenInformationV1
15 } LSA_TOKEN_INFORMATION_TYPE, *PLSA_TOKEN_INFORMATION_TYPE;
16
17 typedef struct _LSA_TOKEN_INFORMATION_V1
18 {
19 LARGE_INTEGER ExpirationTime;
20 TOKEN_USER User;
21 PTOKEN_GROUPS Groups;
22 TOKEN_PRIMARY_GROUP PrimaryGroup;
23 PTOKEN_PRIVILEGES Privileges;
24 TOKEN_OWNER Owner;
25 TOKEN_DEFAULT_DACL DefaultDacl;
26 } LSA_TOKEN_INFORMATION_V1, *PLSA_TOKEN_INFORMATION_V1;
27
28 typedef PVOID PLSA_CLIENT_REQUEST;
29
30 typedef NTSTATUS (NTAPI *PLSA_CREATE_LOGON_SESSION)(PLUID);
31 typedef NTSTATUS (NTAPI *PLSA_DELETE_LOGON_SESSION)(PLUID);
32
33 typedef PVOID (NTAPI *PLSA_ALLOCATE_LSA_HEAP)(ULONG);
34 typedef VOID (NTAPI *PLSA_FREE_LSA_HEAP)(PVOID);
35 typedef NTSTATUS (NTAPI *PLSA_ALLOCATE_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, ULONG, PVOID*);
36 typedef NTSTATUS (NTAPI *PLSA_FREE_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, PVOID);
37 typedef NTSTATUS (NTAPI *PLSA_COPY_TO_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, ULONG,
38 PVOID, PVOID);
39 typedef NTSTATUS (NTAPI *PLSA_COPY_FROM_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST,
40 ULONG, PVOID, PVOID);
41
42 typedef struct LSA_DISPATCH_TABLE
43 {
44 PLSA_CREATE_LOGON_SESSION CreateLogonSession;
45 PLSA_DELETE_LOGON_SESSION DeleteLogonSession;
46 PVOID /*PLSA_ADD_CREDENTIAL */ AddCredential;
47 PVOID /*PLSA_GET_CREDENTIALS */ GetCredentials;
48 PVOID /*PLSA_DELETE_CREDENTIAL */ DeleteCredential;
49 PLSA_ALLOCATE_LSA_HEAP AllocateLsaHeap;
50 PLSA_FREE_LSA_HEAP FreeLsaHeap;
51 PLSA_ALLOCATE_CLIENT_BUFFER AllocateClientBuffer;
52 PLSA_FREE_CLIENT_BUFFER FreeClientBuffer;
53 PLSA_COPY_TO_CLIENT_BUFFER CopyToClientBuffer;
54 PLSA_COPY_FROM_CLIENT_BUFFER CopyFromClientBuffer;
55 } LSA_DISPATCH_TABLE, *PLSA_DISPATCH_TABLE;
56
57
58 typedef NTSTATUS (NTAPI *PLSA_AP_INITIALIZE_PACKAGE)(ULONG, PLSA_DISPATCH_TABLE,
59 PLSA_STRING, PLSA_STRING, PLSA_STRING *);
60 typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_INTERNAL)(PLSA_CLIENT_REQUEST, PVOID, PVOID,
61 ULONG, PVOID *, PULONG, PNTSTATUS);
62 typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_PASSTHROUGH)(PLSA_CLIENT_REQUEST,
63 PVOID, PVOID, ULONG, PVOID *, PULONG, PNTSTATUS);
64 typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_UNTRUSTED)(PLSA_CLIENT_REQUEST,
65 PVOID, PVOID, ULONG, PVOID *, PULONG, PNTSTATUS);
66 typedef VOID (NTAPI *PLSA_AP_LOGON_TERMINATED)(PLUID);
67 typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_EX2)(PLSA_CLIENT_REQUEST,
68 SECURITY_LOGON_TYPE, PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS,
69 PLSA_TOKEN_INFORMATION_TYPE, PVOID *, PUNICODE_STRING *, PUNICODE_STRING *,
70 PUNICODE_STRING *, PVOID /*PSECPKG_PRIMARY_CRED*/, PVOID /*PSECPKG_SUPPLEMENTAL_CRED_ARRAY **/);
71 typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_EX)(PLSA_CLIENT_REQUEST,
72 SECURITY_LOGON_TYPE, PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS,
73 PLSA_TOKEN_INFORMATION_TYPE, PVOID *, PUNICODE_STRING *, PUNICODE_STRING *,
74 PUNICODE_STRING *);
75
76 typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_INTERNAL)(PLSA_CLIENT_REQUEST, SECURITY_LOGON_TYPE,
77 PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS, PLSA_TOKEN_INFORMATION_TYPE,
78 PVOID *, PUNICODE_STRING *, PUNICODE_STRING *);
79
80 typedef struct _AUTH_PACKAGE
81 {
82 LIST_ENTRY Entry;
83 PSTRING Name;
84 ULONG Id;
85 PVOID ModuleHandle;
86
87 PLSA_AP_INITIALIZE_PACKAGE LsaApInitializePackage;
88 PLSA_AP_CALL_PACKAGE_INTERNAL LsaApCallPackage;
89 PLSA_AP_CALL_PACKAGE_PASSTHROUGH LsaApCallPackagePassthrough;
90 PLSA_AP_CALL_PACKAGE_UNTRUSTED LsaApCallPackageUntrusted;
91 PLSA_AP_LOGON_TERMINATED LsaApLogonTerminated;
92 PLSA_AP_LOGON_USER_EX2 LsaApLogonUserEx2;
93 PLSA_AP_LOGON_USER_EX LsaApLogonUserEx;
94 PLSA_AP_LOGON_USER_INTERNAL LsaApLogonUser;
95 } AUTH_PACKAGE, *PAUTH_PACKAGE;
96
97
98 /* GLOBALS *****************************************************************/
99
100 static LIST_ENTRY PackageListHead;
101 static ULONG PackageId;
102 static LSA_DISPATCH_TABLE DispatchTable;
103
104
105 /* FUNCTIONS ***************************************************************/
106
107 static
108 NTSTATUS
109 NTAPI
110 LsapAddAuthPackage(IN PWSTR ValueName,
111 IN ULONG ValueType,
112 IN PVOID ValueData,
113 IN ULONG ValueLength,
114 IN PVOID Context,
115 IN PVOID EntryContext)
116 {
117 PAUTH_PACKAGE Package = NULL;
118 UNICODE_STRING PackageName;
119 STRING ProcName;
120 PULONG Id;
121 NTSTATUS Status = STATUS_SUCCESS;
122
123 TRACE("LsapAddAuthPackage()\n");
124
125 PackageName.Length = (USHORT)ValueLength - sizeof(WCHAR);
126 PackageName.MaximumLength = (USHORT)ValueLength;
127 PackageName.Buffer = ValueData;
128
129 Id = (PULONG)Context;
130
131 Package = RtlAllocateHeap(RtlGetProcessHeap(),
132 HEAP_ZERO_MEMORY,
133 sizeof(AUTH_PACKAGE));
134 if (Package == NULL)
135 return STATUS_INSUFFICIENT_RESOURCES;
136
137 Status = LdrLoadDll(NULL,
138 NULL,
139 &PackageName,
140 &Package->ModuleHandle);
141 if (!NT_SUCCESS(Status))
142 {
143 TRACE("LdrLoadDll failed (Status 0x%08lx)\n", Status);
144 goto done;
145 }
146
147 RtlInitAnsiString(&ProcName, "LsaApInitializePackage");
148 Status = LdrGetProcedureAddress(Package->ModuleHandle,
149 &ProcName,
150 0,
151 (PVOID *)&Package->LsaApInitializePackage);
152 if (!NT_SUCCESS(Status))
153 {
154 TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
155 goto done;
156 }
157
158 RtlInitAnsiString(&ProcName, "LsaApCallPackage");
159 Status = LdrGetProcedureAddress(Package->ModuleHandle,
160 &ProcName,
161 0,
162 (PVOID *)&Package->LsaApCallPackage);
163 if (!NT_SUCCESS(Status))
164 {
165 TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
166 goto done;
167 }
168
169 RtlInitAnsiString(&ProcName, "LsaApCallPackagePassthrough");
170 Status = LdrGetProcedureAddress(Package->ModuleHandle,
171 &ProcName,
172 0,
173 (PVOID *)&Package->LsaApCallPackagePassthrough);
174 if (!NT_SUCCESS(Status))
175 {
176 TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
177 goto done;
178 }
179
180 RtlInitAnsiString(&ProcName, "LsaApCallPackageUntrusted");
181 Status = LdrGetProcedureAddress(Package->ModuleHandle,
182 &ProcName,
183 0,
184 (PVOID *)&Package->LsaApCallPackageUntrusted);
185 if (!NT_SUCCESS(Status))
186 {
187 TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
188 goto done;
189 }
190
191 RtlInitAnsiString(&ProcName, "LsaApLogonTerminated");
192 Status = LdrGetProcedureAddress(Package->ModuleHandle,
193 &ProcName,
194 0,
195 (PVOID *)&Package->LsaApLogonTerminated);
196 if (!NT_SUCCESS(Status))
197 {
198 TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
199 goto done;
200 }
201
202 RtlInitAnsiString(&ProcName, "LsaApLogonUserEx2");
203 Status = LdrGetProcedureAddress(Package->ModuleHandle,
204 &ProcName,
205 0,
206 (PVOID *)&Package->LsaApLogonUserEx2);
207 if (!NT_SUCCESS(Status))
208 {
209 RtlInitAnsiString(&ProcName, "LsaApLogonUserEx");
210 Status = LdrGetProcedureAddress(Package->ModuleHandle,
211 &ProcName,
212 0,
213 (PVOID *)&Package->LsaApLogonUserEx);
214 if (!NT_SUCCESS(Status))
215 {
216 RtlInitAnsiString(&ProcName, "LsaApLogonUser");
217 Status = LdrGetProcedureAddress(Package->ModuleHandle,
218 &ProcName,
219 0,
220 (PVOID *)&Package->LsaApLogonUser);
221 if (!NT_SUCCESS(Status))
222 {
223 TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
224 goto done;
225 }
226 }
227 }
228
229 /* Initialize the current package */
230 Status = Package->LsaApInitializePackage(*Id,
231 &DispatchTable,
232 NULL,
233 NULL,
234 &Package->Name);
235 if (!NT_SUCCESS(Status))
236 {
237 TRACE("Package->LsaApInitializePackage() failed (Status 0x%08lx)\n", Status);
238 goto done;
239 }
240
241 TRACE("Package Name: %s\n", Package->Name->Buffer);
242
243 Package->Id = *Id;
244 (*Id)++;
245
246 InsertTailList(&PackageListHead, &Package->Entry);
247
248 done:
249 if (!NT_SUCCESS(Status))
250 {
251 if (Package != NULL)
252 {
253 if (Package->ModuleHandle != NULL)
254 LdrUnloadDll(Package->ModuleHandle);
255
256 if (Package->Name != NULL)
257 {
258 if (Package->Name->Buffer != NULL)
259 RtlFreeHeap(RtlGetProcessHeap(), 0, Package->Name->Buffer);
260
261 RtlFreeHeap(RtlGetProcessHeap(), 0, Package->Name);
262 }
263
264 RtlFreeHeap(RtlGetProcessHeap(), 0, Package);
265 }
266 }
267
268 return Status;
269 }
270
271
272 static
273 PAUTH_PACKAGE
274 LsapGetAuthenticationPackage(IN ULONG PackageId)
275 {
276 PLIST_ENTRY ListEntry;
277 PAUTH_PACKAGE Package;
278
279 ListEntry = PackageListHead.Flink;
280 while (ListEntry != &PackageListHead)
281 {
282 Package = CONTAINING_RECORD(ListEntry, AUTH_PACKAGE, Entry);
283
284 if (Package->Id == PackageId)
285 {
286 return Package;
287 }
288
289 ListEntry = ListEntry->Flink;
290 }
291
292 return NULL;
293 }
294
295
296 static
297 PVOID
298 NTAPI
299 LsapAllocateHeap(IN ULONG Length)
300 {
301 return RtlAllocateHeap(RtlGetProcessHeap(),
302 HEAP_ZERO_MEMORY,
303 Length);
304 }
305
306
307 static
308 VOID
309 NTAPI
310 LsapFreeHeap(IN PVOID Base)
311 {
312 RtlFreeHeap(RtlGetProcessHeap(),
313 0,
314 Base);
315 }
316
317
318 static
319 NTSTATUS
320 NTAPI
321 LsapAllocateClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
322 IN ULONG LengthRequired,
323 OUT PVOID *ClientBaseAddress)
324 {
325 PLSAP_LOGON_CONTEXT LogonContext;
326 ULONG Length;
327
328 *ClientBaseAddress = NULL;
329
330 LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
331
332 Length = LengthRequired;
333 return NtAllocateVirtualMemory(LogonContext->ClientProcessHandle,
334 ClientBaseAddress,
335 0,
336 &Length,
337 MEM_COMMIT,
338 PAGE_READWRITE);
339 }
340
341
342 static
343 NTSTATUS
344 NTAPI
345 LsapFreeClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
346 IN PVOID ClientBaseAddress)
347 {
348 PLSAP_LOGON_CONTEXT LogonContext;
349 ULONG Length;
350
351 if (ClientBaseAddress == NULL)
352 return STATUS_SUCCESS;
353
354 LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
355
356 Length = 0;
357 return NtFreeVirtualMemory(LogonContext->ClientProcessHandle,
358 &ClientBaseAddress,
359 &Length,
360 MEM_RELEASE);
361 }
362
363
364 static
365 NTSTATUS
366 NTAPI
367 LsapCopyToClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
368 IN ULONG Length,
369 IN PVOID ClientBaseAddress,
370 IN PVOID BufferToCopy)
371 {
372 PLSAP_LOGON_CONTEXT LogonContext;
373
374 LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
375
376 return NtWriteVirtualMemory(LogonContext->ClientProcessHandle,
377 ClientBaseAddress,
378 BufferToCopy,
379 Length,
380 NULL);
381 }
382
383
384 static
385 NTSTATUS
386 NTAPI
387 LsapCopyFromClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
388 IN ULONG Length,
389 IN PVOID BufferToCopy,
390 IN PVOID ClientBaseAddress)
391 {
392 PLSAP_LOGON_CONTEXT LogonContext;
393
394 LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
395
396 return NtReadVirtualMemory(LogonContext->ClientProcessHandle,
397 ClientBaseAddress,
398 BufferToCopy,
399 Length,
400 NULL);
401 }
402
403
404 NTSTATUS
405 LsapInitAuthPackages(VOID)
406 {
407 RTL_QUERY_REGISTRY_TABLE AuthPackageTable[] = {
408 {LsapAddAuthPackage, 0, L"Authentication Packages", NULL, REG_NONE, NULL, 0},
409 {NULL, 0, NULL, NULL, REG_NONE, NULL, 0}};
410
411 NTSTATUS Status;
412
413 InitializeListHead(&PackageListHead);
414 PackageId = 0;
415
416 /* Initialize the dispatch table */
417 DispatchTable.CreateLogonSession = &LsapCreateLogonSession;
418 DispatchTable.DeleteLogonSession = &LsapDeleteLogonSession;
419 DispatchTable.AddCredential = NULL;
420 DispatchTable.GetCredentials = NULL;
421 DispatchTable.DeleteCredential = NULL;
422 DispatchTable.AllocateLsaHeap = &LsapAllocateHeap;
423 DispatchTable.FreeLsaHeap = &LsapFreeHeap;
424 DispatchTable.AllocateClientBuffer = &LsapAllocateClientBuffer;
425 DispatchTable.FreeClientBuffer = &LsapFreeClientBuffer;
426 DispatchTable.CopyToClientBuffer = &LsapCopyToClientBuffer;
427 DispatchTable.CopyFromClientBuffer = &LsapCopyFromClientBuffer;
428
429 /* Add registered authentication packages */
430 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
431 L"Lsa",
432 AuthPackageTable,
433 &PackageId,
434 NULL);
435
436 return Status;
437 }
438
439
440 NTSTATUS
441 LsapLookupAuthenticationPackage(PLSA_API_MSG RequestMsg,
442 PLSAP_LOGON_CONTEXT LogonContext)
443 {
444 PLIST_ENTRY ListEntry;
445 PAUTH_PACKAGE Package;
446 ULONG PackageNameLength;
447 PCHAR PackageName;
448
449 TRACE("(%p %p)\n", RequestMsg, LogonContext);
450
451 PackageNameLength = RequestMsg->LookupAuthenticationPackage.Request.PackageNameLength;
452 PackageName = RequestMsg->LookupAuthenticationPackage.Request.PackageName;
453
454 TRACE("PackageName: %s\n", PackageName);
455
456 ListEntry = PackageListHead.Flink;
457 while (ListEntry != &PackageListHead)
458 {
459 Package = CONTAINING_RECORD(ListEntry, AUTH_PACKAGE, Entry);
460
461 if ((PackageNameLength == Package->Name->Length) &&
462 (_strnicmp(PackageName, Package->Name->Buffer, Package->Name->Length) == 0))
463 {
464 RequestMsg->LookupAuthenticationPackage.Reply.Package = Package->Id;
465 return STATUS_SUCCESS;
466 }
467
468 ListEntry = ListEntry->Flink;
469 }
470
471 return STATUS_NO_SUCH_PACKAGE;
472 }
473
474
475 NTSTATUS
476 LsapCallAuthenticationPackage(PLSA_API_MSG RequestMsg,
477 PLSAP_LOGON_CONTEXT LogonContext)
478 {
479 PAUTH_PACKAGE Package;
480 PVOID LocalBuffer = NULL;
481 ULONG PackageId;
482 NTSTATUS Status;
483
484 TRACE("(%p %p)\n", RequestMsg, LogonContext);
485
486 PackageId = RequestMsg->CallAuthenticationPackage.Request.AuthenticationPackage;
487
488 /* Get the right authentication package */
489 Package = LsapGetAuthenticationPackage(PackageId);
490 if (Package == NULL)
491 {
492 TRACE("LsapGetAuthenticationPackage() failed to find a package\n");
493 return STATUS_NO_SUCH_PACKAGE;
494 }
495
496 if (RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength > 0)
497 {
498 LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
499 HEAP_ZERO_MEMORY,
500 RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength);
501 if (LocalBuffer == NULL)
502 {
503 return STATUS_INSUFFICIENT_RESOURCES;
504 }
505
506 Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
507 RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
508 LocalBuffer,
509 RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
510 NULL);
511 if (!NT_SUCCESS(Status))
512 {
513 TRACE("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
514 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
515 return Status;
516 }
517 }
518
519 Status = Package->LsaApCallPackage((PLSA_CLIENT_REQUEST)LogonContext,
520 LocalBuffer,
521 RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
522 RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
523 &RequestMsg->CallAuthenticationPackage.Reply.ProtocolReturnBuffer,
524 &RequestMsg->CallAuthenticationPackage.Reply.ReturnBufferLength,
525 &RequestMsg->CallAuthenticationPackage.Reply.ProtocolStatus);
526 if (!NT_SUCCESS(Status))
527 {
528 TRACE("Package->LsaApCallPackage() failed (Status 0x%08lx)\n", Status);
529 }
530
531 if (LocalBuffer != NULL)
532 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
533
534 return Status;
535 }
536
537
538 static
539 NTSTATUS
540 LsapCopyLocalGroups(
541 IN PLSAP_LOGON_CONTEXT LogonContext,
542 IN PTOKEN_GROUPS ClientGroups,
543 IN ULONG ClientGroupsCount,
544 OUT PTOKEN_GROUPS *TokenGroups)
545 {
546 ULONG LocalGroupsLength = 0;
547 PTOKEN_GROUPS LocalGroups = NULL;
548 ULONG SidHeaderLength = 0;
549 PSID SidHeader = NULL;
550 PSID SrcSid, DstSid;
551 ULONG SidLength;
552 ULONG AllocatedSids = 0;
553 ULONG i;
554 NTSTATUS Status;
555
556 LocalGroupsLength = sizeof(TOKEN_GROUPS) +
557 (ClientGroupsCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
558 LocalGroups = RtlAllocateHeap(RtlGetProcessHeap(),
559 HEAP_ZERO_MEMORY,
560 LocalGroupsLength);
561 if (LocalGroups == NULL)
562 {
563 TRACE("RtlAllocateHeap() failed\n");
564 return STATUS_INSUFFICIENT_RESOURCES;
565 }
566
567 Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
568 ClientGroups,
569 LocalGroups,
570 LocalGroupsLength,
571 NULL);
572 if (!NT_SUCCESS(Status))
573 goto done;
574
575
576 SidHeaderLength = RtlLengthRequiredSid(0);
577 SidHeader = RtlAllocateHeap(RtlGetProcessHeap(),
578 HEAP_ZERO_MEMORY,
579 SidHeaderLength);
580 if (SidHeader == NULL)
581 {
582 Status = STATUS_INSUFFICIENT_RESOURCES;
583 goto done;
584 }
585
586 for (i = 0; i < ClientGroupsCount; i++)
587 {
588 SrcSid = LocalGroups->Groups[i].Sid;
589
590 Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
591 SrcSid,
592 SidHeader,
593 SidHeaderLength,
594 NULL);
595 if (!NT_SUCCESS(Status))
596 goto done;
597
598 SidLength = RtlLengthSid(SidHeader);
599 TRACE("Sid %lu: Length %lu\n", i, SidLength);
600
601 DstSid = RtlAllocateHeap(RtlGetProcessHeap(),
602 HEAP_ZERO_MEMORY,
603 SidLength);
604 if (DstSid == NULL)
605 {
606 Status = STATUS_INSUFFICIENT_RESOURCES;
607 goto done;
608 }
609
610 Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
611 SrcSid,
612 DstSid,
613 SidLength,
614 NULL);
615 if (!NT_SUCCESS(Status))
616 {
617 RtlFreeHeap(RtlGetProcessHeap(), 0, DstSid);
618 goto done;
619 }
620
621 LocalGroups->Groups[i].Sid = DstSid;
622 AllocatedSids++;
623 }
624
625 *TokenGroups = LocalGroups;
626
627 done:
628 if (SidHeader != NULL)
629 RtlFreeHeap(RtlGetProcessHeap(), 0, SidHeader);
630
631 if (!NT_SUCCESS(Status))
632 {
633 if (LocalGroups != NULL)
634 {
635 for (i = 0; i < AllocatedSids; i++)
636 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
637
638 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
639 }
640 }
641
642 return Status;
643 }
644
645
646 static
647 NTSTATUS
648 LsapAddLocalGroups(
649 IN PVOID TokenInformation,
650 IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
651 IN PTOKEN_GROUPS LocalGroups)
652 {
653 PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
654 PTOKEN_GROUPS Groups;
655 ULONG Length;
656 ULONG i;
657 ULONG j;
658
659 if (LocalGroups == NULL || LocalGroups->GroupCount == 0)
660 return STATUS_SUCCESS;
661
662 if (TokenInformationType == LsaTokenInformationV1)
663 {
664 TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
665
666 if (TokenInfo1->Groups != NULL)
667 {
668 Length = sizeof(TOKEN_GROUPS) +
669 (LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
670
671 Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
672 if (Groups == NULL)
673 {
674 ERR("Group buffer allocation failed!\n");
675 return STATUS_INSUFFICIENT_RESOURCES;
676 }
677
678 Groups->GroupCount = LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount;
679
680 for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
681 {
682 Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
683 Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
684 }
685
686 for (j = 0; j < LocalGroups->GroupCount; i++, j++)
687 {
688 Groups->Groups[i].Sid = LocalGroups->Groups[j].Sid;
689 Groups->Groups[i].Attributes = LocalGroups->Groups[j].Attributes;
690 LocalGroups->Groups[j].Sid = NULL;
691 }
692
693 RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
694
695 TokenInfo1->Groups = Groups;
696 }
697 else
698 {
699 Length = sizeof(TOKEN_GROUPS) +
700 (LocalGroups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
701
702 Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
703 if (Groups == NULL)
704 {
705 ERR("Group buffer allocation failed!\n");
706 return STATUS_INSUFFICIENT_RESOURCES;
707 }
708
709 Groups->GroupCount = LocalGroups->GroupCount;
710
711 for (i = 0; i < LocalGroups->GroupCount; i++)
712 {
713 Groups->Groups[i].Sid = LocalGroups->Groups[i].Sid;
714 Groups->Groups[i].Attributes = LocalGroups->Groups[i].Attributes;
715 }
716
717 TokenInfo1->Groups = Groups;
718 }
719 }
720 else
721 {
722 FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
723 return STATUS_NOT_IMPLEMENTED;
724 }
725
726 return STATUS_SUCCESS;
727 }
728
729
730 static
731 NTSTATUS
732 LsapSetTokenOwner(
733 IN PVOID TokenInformation,
734 IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
735 {
736 PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
737 PSID OwnerSid = NULL;
738 ULONG i, Length;
739
740 if (TokenInformationType == LsaTokenInformationV1)
741 {
742 TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
743
744 if (TokenInfo1->Owner.Owner != NULL)
745 return STATUS_SUCCESS;
746
747 OwnerSid = TokenInfo1->User.User.Sid;
748 for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
749 {
750 if (EqualSid(TokenInfo1->Groups->Groups[i].Sid, LsapAdministratorsSid))
751 {
752 OwnerSid = LsapAdministratorsSid;
753 break;
754 }
755 }
756
757 Length = RtlLengthSid(OwnerSid);
758 TokenInfo1->Owner.Owner = DispatchTable.AllocateLsaHeap(Length);
759 if (TokenInfo1->Owner.Owner == NULL)
760 return STATUS_INSUFFICIENT_RESOURCES;
761
762 RtlCopyMemory(TokenInfo1->Owner.Owner,
763 OwnerSid,
764 Length);
765 }
766
767 return STATUS_SUCCESS;
768 }
769
770
771 static
772 NTSTATUS
773 LsapAddTokenDefaultDacl(
774 IN PVOID TokenInformation,
775 IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
776 {
777 PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
778 PACL Dacl = NULL;
779 ULONG Length;
780
781 if (TokenInformationType == LsaTokenInformationV1)
782 {
783 TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
784
785 if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
786 return STATUS_SUCCESS;
787
788 Length = sizeof(ACL) +
789 (2 * sizeof(ACCESS_ALLOWED_ACE)) +
790 RtlLengthSid(TokenInfo1->Owner.Owner) +
791 RtlLengthSid(LsapLocalSystemSid);
792
793 Dacl = DispatchTable.AllocateLsaHeap(Length);
794 if (Dacl == NULL)
795 return STATUS_INSUFFICIENT_RESOURCES;
796
797 RtlCreateAcl(Dacl, Length, ACL_REVISION);
798
799 RtlAddAccessAllowedAce(Dacl,
800 ACL_REVISION,
801 GENERIC_ALL,
802 TokenInfo1->Owner.Owner);
803
804 /* SID: S-1-5-18 */
805 RtlAddAccessAllowedAce(Dacl,
806 ACL_REVISION,
807 GENERIC_ALL,
808 LsapLocalSystemSid);
809
810 TokenInfo1->DefaultDacl.DefaultDacl = Dacl;
811 }
812
813 return STATUS_SUCCESS;
814 }
815
816
817 NTSTATUS
818 LsapLogonUser(PLSA_API_MSG RequestMsg,
819 PLSAP_LOGON_CONTEXT LogonContext)
820 {
821 PAUTH_PACKAGE Package;
822 OBJECT_ATTRIBUTES ObjectAttributes;
823 SECURITY_QUALITY_OF_SERVICE Qos;
824 LSA_TOKEN_INFORMATION_TYPE TokenInformationType;
825 PVOID TokenInformation = NULL;
826 PLSA_TOKEN_INFORMATION_V1 TokenInfo1 = NULL;
827 PUNICODE_STRING AccountName = NULL;
828 PUNICODE_STRING AuthenticatingAuthority = NULL;
829 PUNICODE_STRING MachineName = NULL;
830 PVOID LocalAuthInfo = NULL;
831 PTOKEN_GROUPS LocalGroups = NULL;
832 HANDLE TokenHandle = NULL;
833 ULONG i;
834 ULONG PackageId;
835 NTSTATUS Status;
836
837 TRACE("(%p %p)\n", RequestMsg, LogonContext);
838
839 PackageId = RequestMsg->LogonUser.Request.AuthenticationPackage;
840
841 /* Get the right authentication package */
842 Package = LsapGetAuthenticationPackage(PackageId);
843 if (Package == NULL)
844 {
845 ERR("LsapGetAuthenticationPackage() failed to find a package\n");
846 return STATUS_NO_SUCH_PACKAGE;
847 }
848
849 if (RequestMsg->LogonUser.Request.AuthenticationInformationLength > 0)
850 {
851 /* Allocate the local authentication info buffer */
852 LocalAuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
853 HEAP_ZERO_MEMORY,
854 RequestMsg->LogonUser.Request.AuthenticationInformationLength);
855 if (LocalAuthInfo == NULL)
856 {
857 ERR("RtlAllocateHeap() failed\n");
858 return STATUS_INSUFFICIENT_RESOURCES;
859 }
860
861 /* Read the authentication info from the callers adress space */
862 Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
863 RequestMsg->LogonUser.Request.AuthenticationInformation,
864 LocalAuthInfo,
865 RequestMsg->LogonUser.Request.AuthenticationInformationLength,
866 NULL);
867 if (!NT_SUCCESS(Status))
868 {
869 ERR("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
870 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
871 return Status;
872 }
873 }
874
875 if (RequestMsg->LogonUser.Request.LocalGroupsCount > 0)
876 {
877 Status = LsapCopyLocalGroups(LogonContext,
878 RequestMsg->LogonUser.Request.LocalGroups,
879 RequestMsg->LogonUser.Request.LocalGroupsCount,
880 &LocalGroups);
881 if (!NT_SUCCESS(Status))
882 {
883 ERR("LsapCopyLocalGroups failed (Status 0x%08lx)\n", Status);
884 goto done;
885 }
886
887 TRACE("GroupCount: %lu\n", LocalGroups->GroupCount);
888 }
889
890 if (Package->LsaApLogonUserEx2 != NULL)
891 {
892 Status = Package->LsaApLogonUserEx2((PLSA_CLIENT_REQUEST)LogonContext,
893 RequestMsg->LogonUser.Request.LogonType,
894 LocalAuthInfo,
895 RequestMsg->LogonUser.Request.AuthenticationInformation,
896 RequestMsg->LogonUser.Request.AuthenticationInformationLength,
897 &RequestMsg->LogonUser.Reply.ProfileBuffer,
898 &RequestMsg->LogonUser.Reply.ProfileBufferLength,
899 &RequestMsg->LogonUser.Reply.LogonId,
900 &RequestMsg->LogonUser.Reply.SubStatus,
901 &TokenInformationType,
902 &TokenInformation,
903 &AccountName,
904 &AuthenticatingAuthority,
905 &MachineName,
906 NULL, /* FIXME: PSECPKG_PRIMARY_CRED PrimaryCredentials */
907 NULL); /* FIXME: PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials */
908 }
909 else if (Package->LsaApLogonUserEx != NULL)
910 {
911 Status = Package->LsaApLogonUserEx((PLSA_CLIENT_REQUEST)LogonContext,
912 RequestMsg->LogonUser.Request.LogonType,
913 LocalAuthInfo,
914 RequestMsg->LogonUser.Request.AuthenticationInformation,
915 RequestMsg->LogonUser.Request.AuthenticationInformationLength,
916 &RequestMsg->LogonUser.Reply.ProfileBuffer,
917 &RequestMsg->LogonUser.Reply.ProfileBufferLength,
918 &RequestMsg->LogonUser.Reply.LogonId,
919 &RequestMsg->LogonUser.Reply.SubStatus,
920 &TokenInformationType,
921 &TokenInformation,
922 &AccountName,
923 &AuthenticatingAuthority,
924 &MachineName);
925 }
926 else
927 {
928 Status = Package->LsaApLogonUser((PLSA_CLIENT_REQUEST)LogonContext,
929 RequestMsg->LogonUser.Request.LogonType,
930 LocalAuthInfo,
931 RequestMsg->LogonUser.Request.AuthenticationInformation,
932 RequestMsg->LogonUser.Request.AuthenticationInformationLength,
933 &RequestMsg->LogonUser.Reply.ProfileBuffer,
934 &RequestMsg->LogonUser.Reply.ProfileBufferLength,
935 &RequestMsg->LogonUser.Reply.LogonId,
936 &RequestMsg->LogonUser.Reply.SubStatus,
937 &TokenInformationType,
938 &TokenInformation,
939 &AccountName,
940 &AuthenticatingAuthority);
941 }
942
943 if (!NT_SUCCESS(Status))
944 {
945 ERR("LsaApLogonUser/Ex/2 failed (Status 0x%08lx)\n", Status);
946 goto done;
947 }
948
949 if (LocalGroups->GroupCount > 0)
950 {
951 /* Add local groups to the token information */
952 Status = LsapAddLocalGroups(TokenInformation,
953 TokenInformationType,
954 LocalGroups);
955 if (!NT_SUCCESS(Status))
956 {
957 ERR("LsapAddLocalGroupsToTokenInfo() failed (Status 0x%08lx)\n", Status);
958 goto done;
959 }
960 }
961
962 Status = LsapSetTokenOwner(TokenInformation,
963 TokenInformationType);
964 if (!NT_SUCCESS(Status))
965 {
966 ERR("LsapSetTokenOwner() failed (Status 0x%08lx)\n", Status);
967 goto done;
968 }
969
970 Status = LsapAddTokenDefaultDacl(TokenInformation,
971 TokenInformationType);
972 if (!NT_SUCCESS(Status))
973 {
974 ERR("LsapAddTokenDefaultDacl() failed (Status 0x%08lx)\n", Status);
975 goto done;
976 }
977
978 if (TokenInformationType == LsaTokenInformationV1)
979 {
980 TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
981
982 Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
983 Qos.ImpersonationLevel = SecurityImpersonation;
984 Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
985 Qos.EffectiveOnly = FALSE;
986
987 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
988 ObjectAttributes.RootDirectory = NULL;
989 ObjectAttributes.ObjectName = NULL;
990 ObjectAttributes.Attributes = 0;
991 ObjectAttributes.SecurityDescriptor = NULL;
992 ObjectAttributes.SecurityQualityOfService = &Qos;
993
994 /* Create the logon token */
995 Status = NtCreateToken(&TokenHandle,
996 TOKEN_ALL_ACCESS,
997 &ObjectAttributes,
998 TokenPrimary,
999 &RequestMsg->LogonUser.Reply.LogonId,
1000 &TokenInfo1->ExpirationTime,
1001 &TokenInfo1->User,
1002 TokenInfo1->Groups,
1003 TokenInfo1->Privileges,
1004 &TokenInfo1->Owner,
1005 &TokenInfo1->PrimaryGroup,
1006 &TokenInfo1->DefaultDacl,
1007 &RequestMsg->LogonUser.Request.SourceContext);
1008 if (!NT_SUCCESS(Status))
1009 {
1010 ERR("NtCreateToken failed (Status 0x%08lx)\n", Status);
1011 goto done;
1012 }
1013 }
1014 else
1015 {
1016 FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
1017 Status = STATUS_NOT_IMPLEMENTED;
1018 goto done;
1019 }
1020
1021 /* Duplicate the token handle into the client process */
1022 Status = NtDuplicateObject(NtCurrentProcess(),
1023 TokenHandle,
1024 LogonContext->ClientProcessHandle,
1025 &RequestMsg->LogonUser.Reply.Token,
1026 0,
1027 0,
1028 DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_CLOSE_SOURCE);
1029 if (!NT_SUCCESS(Status))
1030 {
1031 ERR("NtDuplicateObject failed (Status 0x%08lx)\n", Status);
1032 goto done;
1033 }
1034
1035 TokenHandle = NULL;
1036
1037 Status = LsapSetLogonSessionData(&RequestMsg->LogonUser.Reply.LogonId);
1038 if (!NT_SUCCESS(Status))
1039 {
1040 ERR("LsapSetLogonSessionData failed (Status 0x%08lx)\n", Status);
1041 goto done;
1042 }
1043
1044 done:
1045 if (!NT_SUCCESS(Status))
1046 {
1047 if (TokenHandle != NULL)
1048 NtClose(TokenHandle);
1049 }
1050
1051 /* Free the local groups */
1052 if (LocalGroups != NULL)
1053 {
1054 for (i = 0; i < LocalGroups->GroupCount; i++)
1055 {
1056 if (LocalGroups->Groups[i].Sid != NULL)
1057 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
1058 }
1059
1060 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
1061 }
1062
1063 /* Free the local authentication info buffer */
1064 if (LocalAuthInfo != NULL)
1065 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
1066
1067 /* Free the token information */
1068 if (TokenInformation != NULL)
1069 {
1070 if (TokenInformationType == LsaTokenInformationV1)
1071 {
1072 TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1073
1074 if (TokenInfo1 != NULL)
1075 {
1076 if (TokenInfo1->User.User.Sid != NULL)
1077 LsapFreeHeap(TokenInfo1->User.User.Sid);
1078
1079 if (TokenInfo1->Groups != NULL)
1080 {
1081 for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1082 {
1083 if (TokenInfo1->Groups->Groups[i].Sid != NULL)
1084 LsapFreeHeap(TokenInfo1->Groups->Groups[i].Sid);
1085 }
1086
1087 LsapFreeHeap(TokenInfo1->Groups);
1088 }
1089
1090 if (TokenInfo1->PrimaryGroup.PrimaryGroup != NULL)
1091 LsapFreeHeap(TokenInfo1->PrimaryGroup.PrimaryGroup);
1092
1093 if (TokenInfo1->Privileges != NULL)
1094 LsapFreeHeap(TokenInfo1->Privileges);
1095
1096 if (TokenInfo1->Owner.Owner != NULL)
1097 LsapFreeHeap(TokenInfo1->Owner.Owner);
1098
1099 if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
1100 LsapFreeHeap(TokenInfo1->DefaultDacl.DefaultDacl);
1101
1102 LsapFreeHeap(TokenInfo1);
1103 }
1104 }
1105 else
1106 {
1107 FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
1108 }
1109 }
1110
1111 /* Free the account name */
1112 if (AccountName != NULL)
1113 {
1114 if (AccountName->Buffer != NULL)
1115 LsapFreeHeap(AccountName->Buffer);
1116
1117 LsapFreeHeap(AccountName);
1118 }
1119
1120 /* Free the authentication authority */
1121 if (AuthenticatingAuthority != NULL)
1122 {
1123 if (AuthenticatingAuthority != NULL)
1124 LsapFreeHeap(AuthenticatingAuthority->Buffer);
1125
1126 LsapFreeHeap(AuthenticatingAuthority);
1127 }
1128
1129 /* Free the machine name */
1130 if (MachineName != NULL)
1131 {
1132 if (MachineName->Buffer != NULL)
1133 LsapFreeHeap(MachineName->Buffer);
1134
1135 LsapFreeHeap(MachineName);
1136 }
1137
1138 TRACE("LsapLogonUser done (Status 0x%08lx)\n", Status);
1139
1140 return Status;
1141 }
1142
1143 /* EOF */