xref: /reactos/dll/win32/lsasrv/authpackage.c (revision 5e2fe089)
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:     Authentication package management routines
6  * COPYRIGHT:   Copyright 2013 Eric Kohl
7  */
8 
9 #include "lsasrv.h"
10 
11 #include <ndk/sefuncs.h>
12 #include <ndk/umfuncs.h>
13 
14 typedef enum _LSA_TOKEN_INFORMATION_TYPE
15 {
16     LsaTokenInformationNull,
17     LsaTokenInformationV1
18 } LSA_TOKEN_INFORMATION_TYPE, *PLSA_TOKEN_INFORMATION_TYPE;
19 
20 typedef struct _LSA_TOKEN_INFORMATION_V1
21 {
22     LARGE_INTEGER ExpirationTime;
23     TOKEN_USER User;
24     PTOKEN_GROUPS Groups;
25     TOKEN_PRIMARY_GROUP PrimaryGroup;
26     PTOKEN_PRIVILEGES Privileges;
27     TOKEN_OWNER Owner;
28     TOKEN_DEFAULT_DACL DefaultDacl;
29 } LSA_TOKEN_INFORMATION_V1, *PLSA_TOKEN_INFORMATION_V1;
30 
31 typedef PVOID PLSA_CLIENT_REQUEST;
32 
33 typedef NTSTATUS (NTAPI *PLSA_CREATE_LOGON_SESSION)(PLUID);
34 typedef NTSTATUS (NTAPI *PLSA_DELETE_LOGON_SESSION)(PLUID);
35 typedef NTSTATUS (NTAPI *PLSA_ADD_CREDENTIAL)(PLUID, ULONG, PLSA_STRING, PLSA_STRING);
36 typedef NTSTATUS (NTAPI *PLSA_GET_CREDENTIALS)(PLUID, ULONG, PULONG, BOOLEAN, PLSA_STRING, PULONG, PLSA_STRING);
37 typedef NTSTATUS (NTAPI *PLSA_DELETE_CREDENTIAL)(PLUID, ULONG, PLSA_STRING);
38 typedef PVOID (NTAPI *PLSA_ALLOCATE_LSA_HEAP)(ULONG);
39 typedef VOID (NTAPI *PLSA_FREE_LSA_HEAP)(PVOID);
40 typedef NTSTATUS (NTAPI *PLSA_ALLOCATE_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, ULONG, PVOID*);
41 typedef NTSTATUS (NTAPI *PLSA_FREE_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, PVOID);
42 typedef NTSTATUS (NTAPI *PLSA_COPY_TO_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, ULONG,
43  PVOID, PVOID);
44 typedef NTSTATUS (NTAPI *PLSA_COPY_FROM_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST,
45  ULONG, PVOID, PVOID);
46 
47 typedef struct LSA_DISPATCH_TABLE
48 {
49     PLSA_CREATE_LOGON_SESSION CreateLogonSession;
50     PLSA_DELETE_LOGON_SESSION DeleteLogonSession;
51     PLSA_ADD_CREDENTIAL AddCredential;
52     PLSA_GET_CREDENTIALS GetCredentials;
53     PLSA_DELETE_CREDENTIAL DeleteCredential;
54     PLSA_ALLOCATE_LSA_HEAP AllocateLsaHeap;
55     PLSA_FREE_LSA_HEAP FreeLsaHeap;
56     PLSA_ALLOCATE_CLIENT_BUFFER AllocateClientBuffer;
57     PLSA_FREE_CLIENT_BUFFER FreeClientBuffer;
58     PLSA_COPY_TO_CLIENT_BUFFER CopyToClientBuffer;
59     PLSA_COPY_FROM_CLIENT_BUFFER CopyFromClientBuffer;
60 } LSA_DISPATCH_TABLE, *PLSA_DISPATCH_TABLE;
61 
62 
63 typedef NTSTATUS (NTAPI *PLSA_AP_INITIALIZE_PACKAGE)(ULONG, PLSA_DISPATCH_TABLE,
64  PLSA_STRING, PLSA_STRING, PLSA_STRING *);
65 typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_INTERNAL)(PLSA_CLIENT_REQUEST, PVOID, PVOID,
66  ULONG, PVOID *, PULONG, PNTSTATUS);
67 typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_PASSTHROUGH)(PLSA_CLIENT_REQUEST,
68  PVOID, PVOID, ULONG, PVOID *, PULONG, PNTSTATUS);
69 typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_UNTRUSTED)(PLSA_CLIENT_REQUEST,
70  PVOID, PVOID, ULONG, PVOID *, PULONG, PNTSTATUS);
71 typedef VOID (NTAPI *PLSA_AP_LOGON_TERMINATED)(PLUID);
72 typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_EX2)(PLSA_CLIENT_REQUEST,
73  SECURITY_LOGON_TYPE, PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS,
74  PLSA_TOKEN_INFORMATION_TYPE, PVOID *, PUNICODE_STRING *, PUNICODE_STRING *,
75  PUNICODE_STRING *, PVOID /*PSECPKG_PRIMARY_CRED*/, PVOID /*PSECPKG_SUPPLEMENTAL_CRED_ARRAY **/);
76 typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_EX)(PLSA_CLIENT_REQUEST,
77  SECURITY_LOGON_TYPE, PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS,
78  PLSA_TOKEN_INFORMATION_TYPE, PVOID *, PUNICODE_STRING *, PUNICODE_STRING *,
79  PUNICODE_STRING *);
80 
81 typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_INTERNAL)(PLSA_CLIENT_REQUEST, SECURITY_LOGON_TYPE,
82  PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS, PLSA_TOKEN_INFORMATION_TYPE,
83  PVOID *, PUNICODE_STRING *, PUNICODE_STRING *);
84 
85 typedef struct _AUTH_PACKAGE
86 {
87     LIST_ENTRY Entry;
88     PSTRING Name;
89     ULONG Id;
90     PVOID ModuleHandle;
91 
92     PLSA_AP_INITIALIZE_PACKAGE LsaApInitializePackage;
93     PLSA_AP_CALL_PACKAGE_INTERNAL LsaApCallPackage;
94     PLSA_AP_CALL_PACKAGE_PASSTHROUGH LsaApCallPackagePassthrough;
95     PLSA_AP_CALL_PACKAGE_UNTRUSTED LsaApCallPackageUntrusted;
96     PLSA_AP_LOGON_TERMINATED LsaApLogonTerminated;
97     PLSA_AP_LOGON_USER_EX2 LsaApLogonUserEx2;
98     PLSA_AP_LOGON_USER_EX LsaApLogonUserEx;
99     PLSA_AP_LOGON_USER_INTERNAL LsaApLogonUser;
100 } AUTH_PACKAGE, *PAUTH_PACKAGE;
101 
102 VOID
103 NTAPI
104 LsaIFree_LSAPR_PRIVILEGE_SET(IN PLSAPR_PRIVILEGE_SET Ptr);
105 
106 typedef wchar_t *PSAMPR_SERVER_NAME;
107 typedef void *SAMPR_HANDLE;
108 
109 typedef struct _SAMPR_SID_INFORMATION
110 {
111     PRPC_SID SidPointer;
112 } SAMPR_SID_INFORMATION, *PSAMPR_SID_INFORMATION;
113 
114 typedef struct _SAMPR_PSID_ARRAY
115 {
116     unsigned long Count;
117     PSAMPR_SID_INFORMATION Sids;
118 } SAMPR_PSID_ARRAY, *PSAMPR_PSID_ARRAY;
119 
120 NTSTATUS
121 NTAPI
122 SamIConnect(
123     PSAMPR_SERVER_NAME ServerName,
124     SAMPR_HANDLE *ServerHandle,
125     ACCESS_MASK DesiredAccess,
126     BOOLEAN Trusted);
127 
128 VOID
129 NTAPI
130 SamIFree_SAMPR_ULONG_ARRAY(
131     PSAMPR_ULONG_ARRAY Ptr);
132 
133 NTSTATUS
134 __stdcall
135 SamrCloseHandle(
136     SAMPR_HANDLE *SamHandle);
137 
138 NTSTATUS
139 __stdcall
140 SamrOpenDomain(
141     SAMPR_HANDLE ServerHandle,
142     ACCESS_MASK DesiredAccess,
143     PRPC_SID DomainId,
144     SAMPR_HANDLE *DomainHandle);
145 
146 NTSTATUS
147 __stdcall
148 SamrGetAliasMembership(
149     SAMPR_HANDLE DomainHandle,
150     PSAMPR_PSID_ARRAY SidArray,
151     PSAMPR_ULONG_ARRAY Membership);
152 
153 
154 /* GLOBALS *****************************************************************/
155 
156 static LIST_ENTRY PackageListHead;
157 static ULONG PackageId;
158 static LSA_DISPATCH_TABLE DispatchTable;
159 
160 #define CONST_LUID(x1, x2) {x1, x2}
161 static const LUID SeChangeNotifyPrivilege = CONST_LUID(SE_CHANGE_NOTIFY_PRIVILEGE, 0);
162 static const LUID SeCreateGlobalPrivilege = CONST_LUID(SE_CREATE_GLOBAL_PRIVILEGE, 0);
163 static const LUID SeImpersonatePrivilege = CONST_LUID(SE_IMPERSONATE_PRIVILEGE, 0);
164 
165 
166 /* FUNCTIONS ***************************************************************/
167 
168 static
169 NTSTATUS
170 NTAPI
171 LsapAddAuthPackage(IN PWSTR ValueName,
172                    IN ULONG ValueType,
173                    IN PVOID ValueData,
174                    IN ULONG ValueLength,
175                    IN PVOID Context,
176                    IN PVOID EntryContext)
177 {
178     PAUTH_PACKAGE Package = NULL;
179     UNICODE_STRING PackageName;
180     STRING ProcName;
181     PULONG Id;
182     NTSTATUS Status = STATUS_SUCCESS;
183 
184     TRACE("LsapAddAuthPackage()\n");
185 
186     PackageName.Length = (USHORT)ValueLength - sizeof(WCHAR);
187     PackageName.MaximumLength = (USHORT)ValueLength;
188     PackageName.Buffer = ValueData;
189 
190     Id = (PULONG)Context;
191 
192     Package = RtlAllocateHeap(RtlGetProcessHeap(),
193                                   HEAP_ZERO_MEMORY,
194                                   sizeof(AUTH_PACKAGE));
195     if (Package == NULL)
196         return STATUS_INSUFFICIENT_RESOURCES;
197 
198     Status = LdrLoadDll(NULL,
199                         NULL,
200                         &PackageName,
201                         &Package->ModuleHandle);
202     if (!NT_SUCCESS(Status))
203     {
204         TRACE("LdrLoadDll failed (Status 0x%08lx)\n", Status);
205         goto done;
206     }
207 
208     RtlInitAnsiString(&ProcName, "LsaApInitializePackage");
209     Status = LdrGetProcedureAddress(Package->ModuleHandle,
210                                     &ProcName,
211                                     0,
212                                     (PVOID *)&Package->LsaApInitializePackage);
213     if (!NT_SUCCESS(Status))
214     {
215         TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
216         goto done;
217     }
218 
219     RtlInitAnsiString(&ProcName, "LsaApCallPackage");
220     Status = LdrGetProcedureAddress(Package->ModuleHandle,
221                                     &ProcName,
222                                     0,
223                                     (PVOID *)&Package->LsaApCallPackage);
224     if (!NT_SUCCESS(Status))
225     {
226         TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
227         goto done;
228     }
229 
230     RtlInitAnsiString(&ProcName, "LsaApCallPackagePassthrough");
231     Status = LdrGetProcedureAddress(Package->ModuleHandle,
232                                     &ProcName,
233                                     0,
234                                     (PVOID *)&Package->LsaApCallPackagePassthrough);
235     if (!NT_SUCCESS(Status))
236     {
237         TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
238         goto done;
239     }
240 
241     RtlInitAnsiString(&ProcName, "LsaApCallPackageUntrusted");
242     Status = LdrGetProcedureAddress(Package->ModuleHandle,
243                                     &ProcName,
244                                     0,
245                                     (PVOID *)&Package->LsaApCallPackageUntrusted);
246     if (!NT_SUCCESS(Status))
247     {
248         TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
249         goto done;
250     }
251 
252     RtlInitAnsiString(&ProcName, "LsaApLogonTerminated");
253     Status = LdrGetProcedureAddress(Package->ModuleHandle,
254                                     &ProcName,
255                                     0,
256                                     (PVOID *)&Package->LsaApLogonTerminated);
257     if (!NT_SUCCESS(Status))
258     {
259         TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
260         goto done;
261     }
262 
263     RtlInitAnsiString(&ProcName, "LsaApLogonUserEx2");
264     Status = LdrGetProcedureAddress(Package->ModuleHandle,
265                                     &ProcName,
266                                     0,
267                                     (PVOID *)&Package->LsaApLogonUserEx2);
268     if (!NT_SUCCESS(Status))
269     {
270         RtlInitAnsiString(&ProcName, "LsaApLogonUserEx");
271         Status = LdrGetProcedureAddress(Package->ModuleHandle,
272                                         &ProcName,
273                                         0,
274                                         (PVOID *)&Package->LsaApLogonUserEx);
275         if (!NT_SUCCESS(Status))
276         {
277             RtlInitAnsiString(&ProcName, "LsaApLogonUser");
278             Status = LdrGetProcedureAddress(Package->ModuleHandle,
279                                             &ProcName,
280                                             0,
281                                             (PVOID *)&Package->LsaApLogonUser);
282             if (!NT_SUCCESS(Status))
283             {
284                 TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
285                 goto done;
286             }
287         }
288     }
289 
290     /* Initialize the current package */
291     Status = Package->LsaApInitializePackage(*Id,
292                                              &DispatchTable,
293                                              NULL,
294                                              NULL,
295                                              &Package->Name);
296     if (!NT_SUCCESS(Status))
297     {
298         TRACE("Package->LsaApInitializePackage() failed (Status 0x%08lx)\n", Status);
299         goto done;
300     }
301 
302     TRACE("Package Name: %s\n", Package->Name->Buffer);
303 
304     Package->Id = *Id;
305     (*Id)++;
306 
307     InsertTailList(&PackageListHead, &Package->Entry);
308 
309 done:
310     if (!NT_SUCCESS(Status))
311     {
312         if (Package != NULL)
313         {
314             if (Package->ModuleHandle != NULL)
315                 LdrUnloadDll(Package->ModuleHandle);
316 
317             if (Package->Name != NULL)
318             {
319                 if (Package->Name->Buffer != NULL)
320                     RtlFreeHeap(RtlGetProcessHeap(), 0, Package->Name->Buffer);
321 
322                 RtlFreeHeap(RtlGetProcessHeap(), 0, Package->Name);
323             }
324 
325             RtlFreeHeap(RtlGetProcessHeap(), 0, Package);
326         }
327     }
328 
329     return Status;
330 }
331 
332 
333 static
334 PAUTH_PACKAGE
335 LsapGetAuthenticationPackage(IN ULONG PackageId)
336 {
337     PLIST_ENTRY ListEntry;
338     PAUTH_PACKAGE Package;
339 
340     ListEntry = PackageListHead.Flink;
341     while (ListEntry != &PackageListHead)
342     {
343         Package = CONTAINING_RECORD(ListEntry, AUTH_PACKAGE, Entry);
344 
345         if (Package->Id == PackageId)
346         {
347             return Package;
348         }
349 
350         ListEntry = ListEntry->Flink;
351     }
352 
353     return NULL;
354 }
355 
356 
357 PVOID
358 NTAPI
359 LsapAllocateHeap(IN ULONG Length)
360 {
361     return RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
362 }
363 
364 
365 PVOID
366 NTAPI
367 LsapAllocateHeapZero(IN ULONG Length)
368 {
369     return RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
370 }
371 
372 
373 VOID
374 NTAPI
375 LsapFreeHeap(IN PVOID Base)
376 {
377     RtlFreeHeap(RtlGetProcessHeap(), 0, Base);
378 }
379 
380 
381 static
382 NTSTATUS
383 NTAPI
384 LsapAllocateClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
385                          IN ULONG LengthRequired,
386                          OUT PVOID *ClientBaseAddress)
387 {
388     PLSAP_LOGON_CONTEXT LogonContext;
389     SIZE_T Length;
390 
391     *ClientBaseAddress = NULL;
392 
393     LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
394 
395     Length = LengthRequired;
396     return NtAllocateVirtualMemory(LogonContext->ClientProcessHandle,
397                                    ClientBaseAddress,
398                                    0,
399                                    &Length,
400                                    MEM_COMMIT,
401                                    PAGE_READWRITE);
402 }
403 
404 
405 static
406 NTSTATUS
407 NTAPI
408 LsapFreeClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
409                      IN PVOID ClientBaseAddress)
410 {
411     PLSAP_LOGON_CONTEXT LogonContext;
412     SIZE_T Length;
413 
414     if (ClientBaseAddress == NULL)
415         return STATUS_SUCCESS;
416 
417     LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
418 
419     Length = 0;
420     return NtFreeVirtualMemory(LogonContext->ClientProcessHandle,
421                                &ClientBaseAddress,
422                                &Length,
423                                MEM_RELEASE);
424 }
425 
426 
427 static
428 NTSTATUS
429 NTAPI
430 LsapCopyToClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
431                        IN ULONG Length,
432                        IN PVOID ClientBaseAddress,
433                        IN PVOID BufferToCopy)
434 {
435     PLSAP_LOGON_CONTEXT LogonContext;
436 
437     LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
438 
439     return NtWriteVirtualMemory(LogonContext->ClientProcessHandle,
440                                 ClientBaseAddress,
441                                 BufferToCopy,
442                                 Length,
443                                 NULL);
444 }
445 
446 
447 static
448 NTSTATUS
449 NTAPI
450 LsapCopyFromClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
451                          IN ULONG Length,
452                          IN PVOID BufferToCopy,
453                          IN PVOID ClientBaseAddress)
454 {
455     PLSAP_LOGON_CONTEXT LogonContext;
456 
457     LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
458 
459     return NtReadVirtualMemory(LogonContext->ClientProcessHandle,
460                                ClientBaseAddress,
461                                BufferToCopy,
462                                Length,
463                                NULL);
464 }
465 
466 
467 NTSTATUS
468 LsapInitAuthPackages(VOID)
469 {
470     RTL_QUERY_REGISTRY_TABLE AuthPackageTable[] = {
471     {LsapAddAuthPackage, 0, L"Authentication Packages", NULL, REG_NONE, NULL, 0},
472     {NULL, 0, NULL, NULL, REG_NONE, NULL, 0}};
473 
474     NTSTATUS Status;
475 
476     InitializeListHead(&PackageListHead);
477     PackageId = 0;
478 
479     /* Initialize the dispatch table */
480     DispatchTable.CreateLogonSession = &LsapCreateLogonSession;
481     DispatchTable.DeleteLogonSession = &LsapDeleteLogonSession;
482     DispatchTable.AddCredential = &LsapAddCredential;
483     DispatchTable.GetCredentials = &LsapGetCredentials;
484     DispatchTable.DeleteCredential = &LsapDeleteCredential;
485     DispatchTable.AllocateLsaHeap = &LsapAllocateHeapZero;
486     DispatchTable.FreeLsaHeap = &LsapFreeHeap;
487     DispatchTable.AllocateClientBuffer = &LsapAllocateClientBuffer;
488     DispatchTable.FreeClientBuffer = &LsapFreeClientBuffer;
489     DispatchTable.CopyToClientBuffer = &LsapCopyToClientBuffer;
490     DispatchTable.CopyFromClientBuffer = &LsapCopyFromClientBuffer;
491 
492     /* Add registered authentication packages */
493     Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
494                                     L"Lsa",
495                                     AuthPackageTable,
496                                     &PackageId,
497                                     NULL);
498 
499     return Status;
500 }
501 
502 
503 NTSTATUS
504 LsapLookupAuthenticationPackage(PLSA_API_MSG RequestMsg,
505                                 PLSAP_LOGON_CONTEXT LogonContext)
506 {
507     PLIST_ENTRY ListEntry;
508     PAUTH_PACKAGE Package;
509     ULONG PackageNameLength;
510     PCHAR PackageName;
511 
512     TRACE("(%p %p)\n", RequestMsg, LogonContext);
513 
514     PackageNameLength = RequestMsg->LookupAuthenticationPackage.Request.PackageNameLength;
515     PackageName = RequestMsg->LookupAuthenticationPackage.Request.PackageName;
516 
517     TRACE("PackageName: %s\n", PackageName);
518 
519     ListEntry = PackageListHead.Flink;
520     while (ListEntry != &PackageListHead)
521     {
522         Package = CONTAINING_RECORD(ListEntry, AUTH_PACKAGE, Entry);
523 
524         if ((PackageNameLength == Package->Name->Length) &&
525             (_strnicmp(PackageName, Package->Name->Buffer, Package->Name->Length) == 0))
526         {
527             RequestMsg->LookupAuthenticationPackage.Reply.Package = Package->Id;
528             return STATUS_SUCCESS;
529         }
530 
531         ListEntry = ListEntry->Flink;
532     }
533 
534     return STATUS_NO_SUCH_PACKAGE;
535 }
536 
537 
538 NTSTATUS
539 LsapCallAuthenticationPackage(PLSA_API_MSG RequestMsg,
540                               PLSAP_LOGON_CONTEXT LogonContext)
541 {
542     PAUTH_PACKAGE Package;
543     PVOID LocalBuffer = NULL;
544     ULONG PackageId;
545     NTSTATUS Status;
546 
547     TRACE("(%p %p)\n", RequestMsg, LogonContext);
548 
549     PackageId = RequestMsg->CallAuthenticationPackage.Request.AuthenticationPackage;
550 
551     /* Get the right authentication package */
552     Package = LsapGetAuthenticationPackage(PackageId);
553     if (Package == NULL)
554     {
555         TRACE("LsapGetAuthenticationPackage() failed to find a package\n");
556         return STATUS_NO_SUCH_PACKAGE;
557     }
558 
559     if (RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength > 0)
560     {
561         LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
562                                       HEAP_ZERO_MEMORY,
563                                       RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength);
564         if (LocalBuffer == NULL)
565         {
566             return STATUS_INSUFFICIENT_RESOURCES;
567         }
568 
569         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
570                                      RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
571                                      LocalBuffer,
572                                      RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
573                                      NULL);
574         if (!NT_SUCCESS(Status))
575         {
576             TRACE("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
577             RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
578             return Status;
579         }
580     }
581 
582     Status = Package->LsaApCallPackage((PLSA_CLIENT_REQUEST)LogonContext,
583                                        LocalBuffer,
584                                        RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
585                                        RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
586                                        &RequestMsg->CallAuthenticationPackage.Reply.ProtocolReturnBuffer,
587                                        &RequestMsg->CallAuthenticationPackage.Reply.ReturnBufferLength,
588                                        &RequestMsg->CallAuthenticationPackage.Reply.ProtocolStatus);
589     if (!NT_SUCCESS(Status))
590     {
591         TRACE("Package->LsaApCallPackage() failed (Status 0x%08lx)\n", Status);
592     }
593 
594     if (LocalBuffer != NULL)
595         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
596 
597     return Status;
598 }
599 
600 
601 static
602 NTSTATUS
603 LsapCopyLocalGroups(
604     IN PLSAP_LOGON_CONTEXT LogonContext,
605     IN PTOKEN_GROUPS ClientGroups,
606     IN ULONG ClientGroupsCount,
607     OUT PTOKEN_GROUPS *TokenGroups)
608 {
609     ULONG LocalGroupsLength = 0;
610     PTOKEN_GROUPS LocalGroups = NULL;
611     ULONG SidHeaderLength = 0;
612     PSID SidHeader = NULL;
613     PSID SrcSid, DstSid;
614     ULONG SidLength;
615     ULONG AllocatedSids = 0;
616     ULONG i;
617     NTSTATUS Status;
618 
619     LocalGroupsLength = sizeof(TOKEN_GROUPS) +
620                         (ClientGroupsCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
621     LocalGroups = RtlAllocateHeap(RtlGetProcessHeap(),
622                                   HEAP_ZERO_MEMORY,
623                                   LocalGroupsLength);
624     if (LocalGroups == NULL)
625     {
626         TRACE("RtlAllocateHeap() failed\n");
627         return STATUS_INSUFFICIENT_RESOURCES;
628     }
629 
630     Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
631                                  ClientGroups,
632                                  LocalGroups,
633                                  LocalGroupsLength,
634                                  NULL);
635     if (!NT_SUCCESS(Status))
636         goto done;
637 
638 
639     SidHeaderLength  = RtlLengthRequiredSid(0);
640     SidHeader = RtlAllocateHeap(RtlGetProcessHeap(),
641                                 HEAP_ZERO_MEMORY,
642                                 SidHeaderLength);
643     if (SidHeader == NULL)
644     {
645         Status = STATUS_INSUFFICIENT_RESOURCES;
646         goto done;
647     }
648 
649     for (i = 0; i < ClientGroupsCount; i++)
650     {
651         SrcSid = LocalGroups->Groups[i].Sid;
652 
653         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
654                                      SrcSid,
655                                      SidHeader,
656                                      SidHeaderLength,
657                                      NULL);
658         if (!NT_SUCCESS(Status))
659             goto done;
660 
661         SidLength = RtlLengthSid(SidHeader);
662         TRACE("Sid %lu: Length %lu\n", i, SidLength);
663 
664         DstSid = RtlAllocateHeap(RtlGetProcessHeap(),
665                                  HEAP_ZERO_MEMORY,
666                                  SidLength);
667         if (DstSid == NULL)
668         {
669             Status = STATUS_INSUFFICIENT_RESOURCES;
670             goto done;
671         }
672 
673         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
674                                      SrcSid,
675                                      DstSid,
676                                      SidLength,
677                                      NULL);
678         if (!NT_SUCCESS(Status))
679         {
680             RtlFreeHeap(RtlGetProcessHeap(), 0, DstSid);
681             goto done;
682         }
683 
684         LocalGroups->Groups[i].Sid = DstSid;
685         AllocatedSids++;
686     }
687 
688     *TokenGroups = LocalGroups;
689 
690 done:
691     if (SidHeader != NULL)
692         RtlFreeHeap(RtlGetProcessHeap(), 0, SidHeader);
693 
694     if (!NT_SUCCESS(Status))
695     {
696         if (LocalGroups != NULL)
697         {
698             for (i = 0; i < AllocatedSids; i++)
699                 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
700 
701             RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
702         }
703     }
704 
705     return Status;
706 }
707 
708 
709 static
710 NTSTATUS
711 LsapAddLocalGroups(
712     IN PVOID TokenInformation,
713     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
714     IN PTOKEN_GROUPS LocalGroups)
715 {
716     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
717     PTOKEN_GROUPS Groups;
718     ULONG Length;
719     ULONG i;
720     ULONG j;
721 
722     if (LocalGroups == NULL || LocalGroups->GroupCount == 0)
723         return STATUS_SUCCESS;
724 
725     if (TokenInformationType == LsaTokenInformationV1)
726     {
727         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
728 
729         if (TokenInfo1->Groups != NULL)
730         {
731             Length = sizeof(TOKEN_GROUPS) +
732                      (LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
733 
734             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
735             if (Groups == NULL)
736             {
737                 ERR("Group buffer allocation failed!\n");
738                 return STATUS_INSUFFICIENT_RESOURCES;
739             }
740 
741             Groups->GroupCount = LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount;
742 
743             for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
744             {
745                 Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
746                 Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
747             }
748 
749             for (j = 0; j < LocalGroups->GroupCount; i++, j++)
750             {
751                 Groups->Groups[i].Sid = LocalGroups->Groups[j].Sid;
752                 Groups->Groups[i].Attributes = LocalGroups->Groups[j].Attributes;
753                 LocalGroups->Groups[j].Sid = NULL;
754             }
755 
756             RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
757 
758             TokenInfo1->Groups = Groups;
759         }
760         else
761         {
762             Length = sizeof(TOKEN_GROUPS) +
763                      (LocalGroups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
764 
765             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
766             if (Groups == NULL)
767             {
768                 ERR("Group buffer allocation failed!\n");
769                 return STATUS_INSUFFICIENT_RESOURCES;
770             }
771 
772             Groups->GroupCount = LocalGroups->GroupCount;
773 
774             for (i = 0; i < LocalGroups->GroupCount; i++)
775             {
776                 Groups->Groups[i].Sid = LocalGroups->Groups[i].Sid;
777                 Groups->Groups[i].Attributes = LocalGroups->Groups[i].Attributes;
778             }
779 
780             TokenInfo1->Groups = Groups;
781         }
782     }
783     else
784     {
785         FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
786         return STATUS_NOT_IMPLEMENTED;
787     }
788 
789     return STATUS_SUCCESS;
790 }
791 
792 static
793 NTSTATUS
794 LsapAddDefaultGroups(
795     IN PVOID TokenInformation,
796     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
797     IN SECURITY_LOGON_TYPE LogonType)
798 {
799     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
800     PTOKEN_GROUPS Groups;
801     ULONG i, Length;
802     PSID SrcSid;
803 
804     if (TokenInformationType == LsaTokenInformationV1)
805     {
806         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
807 
808         if (TokenInfo1->Groups != NULL)
809         {
810             Length = sizeof(TOKEN_GROUPS) +
811                      (TokenInfo1->Groups->GroupCount + 2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
812 
813             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
814             if (Groups == NULL)
815             {
816                 ERR("Group buffer allocation failed!\n");
817                 return STATUS_INSUFFICIENT_RESOURCES;
818             }
819 
820             Groups->GroupCount = TokenInfo1->Groups->GroupCount;
821 
822             for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
823             {
824                 Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
825                 Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
826             }
827 
828             RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
829 
830             TokenInfo1->Groups = Groups;
831 
832         }
833         else
834         {
835             Length = sizeof(TOKEN_GROUPS) +
836                      (2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
837 
838             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
839             if (Groups == NULL)
840             {
841                 ERR("Group buffer allocation failed!\n");
842                 return STATUS_INSUFFICIENT_RESOURCES;
843             }
844 
845             TokenInfo1->Groups = Groups;
846         }
847 
848         /* Append the World SID (aka Everyone) */
849         Length = RtlLengthSid(LsapWorldSid);
850         Groups->Groups[Groups->GroupCount].Sid = RtlAllocateHeap(RtlGetProcessHeap(),
851                                                                  HEAP_ZERO_MEMORY,
852                                                                  Length);
853         if (Groups->Groups[Groups->GroupCount].Sid == NULL)
854             return STATUS_INSUFFICIENT_RESOURCES;
855 
856         RtlCopyMemory(Groups->Groups[Groups->GroupCount].Sid,
857                       LsapWorldSid,
858                       Length);
859 
860         Groups->Groups[Groups->GroupCount].Attributes =
861             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
862 
863         Groups->GroupCount++;
864 
865         /* Append the logon type SID */
866         switch (LogonType)
867         {
868             case Interactive:
869                 SrcSid = LsapInteractiveSid;
870                 break;
871 
872             case Network:
873                 SrcSid = LsapNetworkSid;
874                 break;
875 
876             case Batch:
877                 SrcSid = LsapBatchSid;
878                 break;
879 
880             case Service:
881                 SrcSid = LsapServiceSid;
882                 break;
883 
884             default:
885                 FIXME("LogonType %d is not supported!\n", LogonType);
886                 return STATUS_NOT_IMPLEMENTED;
887         }
888 
889         Length = RtlLengthSid(SrcSid);
890         Groups->Groups[Groups->GroupCount].Sid = RtlAllocateHeap(RtlGetProcessHeap(),
891                                                                  HEAP_ZERO_MEMORY,
892                                                                  Length);
893         if (Groups->Groups[Groups->GroupCount].Sid == NULL)
894             return STATUS_INSUFFICIENT_RESOURCES;
895 
896         RtlCopyMemory(Groups->Groups[Groups->GroupCount].Sid,
897                       SrcSid,
898                       Length);
899 
900         Groups->Groups[Groups->GroupCount].Attributes =
901             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
902 
903         Groups->GroupCount++;
904     }
905     else
906     {
907         FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
908         return STATUS_NOT_IMPLEMENTED;
909     }
910 
911     return STATUS_SUCCESS;
912 }
913 
914 
915 static
916 NTSTATUS
917 LsapAppendSidToGroups(
918     IN PTOKEN_GROUPS *TokenGroups,
919     IN PSID DomainSid,
920     IN ULONG RelativeId)
921 {
922     PTOKEN_GROUPS Groups;
923     PSID Sid;
924     ULONG Length;
925     ULONG i;
926 
927     Sid = LsapAppendRidToSid(DomainSid, RelativeId);
928     if (Sid == NULL)
929     {
930         ERR("Group SID creation failed!\n");
931         return STATUS_INSUFFICIENT_RESOURCES;
932     }
933 
934     if (*TokenGroups == NULL)
935     {
936         Length = sizeof(TOKEN_GROUPS) +
937                  (1 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
938 
939         Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
940         if (Groups == NULL)
941         {
942             ERR("Group buffer allocation failed!\n");
943             return STATUS_INSUFFICIENT_RESOURCES;
944         }
945 
946         Groups->GroupCount = 1;
947 
948         Groups->Groups[0].Sid = Sid;
949         Groups->Groups[0].Attributes =
950             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
951 
952         *TokenGroups = Groups;
953     }
954     else
955     {
956         for (i = 0; i < (*TokenGroups)->GroupCount; i++)
957         {
958             if (RtlEqualSid((*TokenGroups)->Groups[i].Sid, Sid))
959             {
960                 RtlFreeHeap(RtlGetProcessHeap(), 0, Sid);
961                 return STATUS_SUCCESS;
962             }
963         }
964 
965         Length = sizeof(TOKEN_GROUPS) +
966                  ((*TokenGroups)->GroupCount + 1 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
967 
968         Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
969         if (Groups == NULL)
970         {
971             ERR("Group buffer allocation failed!\n");
972             return STATUS_INSUFFICIENT_RESOURCES;
973         }
974 
975         Groups->GroupCount = (*TokenGroups)->GroupCount;
976 
977         for (i = 0; i < (*TokenGroups)->GroupCount; i++)
978         {
979             Groups->Groups[i].Sid = (*TokenGroups)->Groups[i].Sid;
980             Groups->Groups[i].Attributes = (*TokenGroups)->Groups[i].Attributes;
981         }
982 
983         Groups->Groups[Groups->GroupCount].Sid = Sid;
984         Groups->Groups[Groups->GroupCount].Attributes =
985             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
986 
987         Groups->GroupCount++;
988 
989         RtlFreeHeap(RtlGetProcessHeap(), 0, *TokenGroups);
990 
991         *TokenGroups = Groups;
992     }
993 
994     return STATUS_SUCCESS;
995 }
996 
997 
998 static
999 NTSTATUS
1000 LsapAddSamGroups(
1001     IN PVOID TokenInformation,
1002     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1003 {
1004     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1005     SAMPR_HANDLE ServerHandle = NULL;
1006     SAMPR_HANDLE BuiltinDomainHandle = NULL;
1007     SAMPR_HANDLE AccountDomainHandle = NULL;
1008     SAMPR_PSID_ARRAY SidArray;
1009     SAMPR_ULONG_ARRAY BuiltinMembership;
1010     SAMPR_ULONG_ARRAY AccountMembership;
1011     ULONG i;
1012     NTSTATUS Status = STATUS_SUCCESS;
1013 
1014     if (TokenInformationType != LsaTokenInformationV1)
1015         return STATUS_SUCCESS;
1016 
1017     TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1018 
1019     SidArray.Count = TokenInfo1->Groups->GroupCount + 1;
1020     SidArray.Sids = RtlAllocateHeap(RtlGetProcessHeap(),
1021                                     HEAP_ZERO_MEMORY,
1022                                     (TokenInfo1->Groups->GroupCount + 1) * sizeof(PRPC_SID));
1023     if (SidArray.Sids == NULL)
1024         return STATUS_INSUFFICIENT_RESOURCES;
1025 
1026     SidArray.Sids[0].SidPointer = TokenInfo1->User.User.Sid;
1027     for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1028         SidArray.Sids[i + 1].SidPointer = TokenInfo1->Groups->Groups[i].Sid;
1029 
1030     BuiltinMembership.Element = NULL;
1031     AccountMembership.Element = NULL;
1032 
1033     Status = SamIConnect(NULL,
1034                          &ServerHandle,
1035                          SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1036                          FALSE);
1037     if (!NT_SUCCESS(Status))
1038     {
1039         TRACE("SamIConnect failed (Status %08lx)\n", Status);
1040         goto done;
1041     }
1042 
1043     Status = SamrOpenDomain(ServerHandle,
1044                             DOMAIN_GET_ALIAS_MEMBERSHIP,
1045                             BuiltinDomainSid,
1046                             &BuiltinDomainHandle);
1047     if (!NT_SUCCESS(Status))
1048     {
1049         TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
1050         goto done;
1051     }
1052 
1053     Status = SamrOpenDomain(ServerHandle,
1054                             DOMAIN_GET_ALIAS_MEMBERSHIP,
1055                             AccountDomainSid,
1056                             &AccountDomainHandle);
1057     if (!NT_SUCCESS(Status))
1058     {
1059         TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
1060         goto done;
1061     }
1062 
1063     Status = SamrGetAliasMembership(BuiltinDomainHandle,
1064                                     &SidArray,
1065                                     &BuiltinMembership);
1066     if (!NT_SUCCESS(Status))
1067     {
1068         TRACE("SamrGetAliasMembership failed (Status %08lx)\n", Status);
1069         goto done;
1070     }
1071 
1072     Status = SamrGetAliasMembership(AccountDomainHandle,
1073                                     &SidArray,
1074                                     &AccountMembership);
1075     if (!NT_SUCCESS(Status))
1076     {
1077         TRACE("SamrGetAliasMembership failed (Status %08lx)\n", Status);
1078         goto done;
1079     }
1080 
1081     TRACE("Builtin Memberships: %lu\n", BuiltinMembership.Count);
1082     for (i = 0; i < BuiltinMembership.Count; i++)
1083     {
1084         TRACE("RID %lu: %lu (0x%lx)\n", i, BuiltinMembership.Element[i], BuiltinMembership.Element[i]);
1085         Status = LsapAppendSidToGroups(&TokenInfo1->Groups,
1086                                        BuiltinDomainSid,
1087                                        BuiltinMembership.Element[i]);
1088         if (!NT_SUCCESS(Status))
1089         {
1090             TRACE("LsapAppendSidToGroups failed (Status %08lx)\n", Status);
1091             goto done;
1092         }
1093     }
1094 
1095     TRACE("Account Memberships: %lu\n", AccountMembership.Count);
1096     for (i = 0; i < AccountMembership.Count; i++)
1097     {
1098         TRACE("RID %lu: %lu (0x%lx)\n", i, AccountMembership.Element[i], AccountMembership.Element[i]);
1099         Status = LsapAppendSidToGroups(&TokenInfo1->Groups,
1100                                        AccountDomainSid,
1101                                        AccountMembership.Element[i]);
1102         if (!NT_SUCCESS(Status))
1103         {
1104             TRACE("LsapAppendSidToGroups failed (Status %08lx)\n", Status);
1105             goto done;
1106         }
1107     }
1108 
1109 done:
1110     RtlFreeHeap(RtlGetProcessHeap(), 0, SidArray.Sids);
1111 
1112     if (AccountMembership.Element != NULL)
1113         SamIFree_SAMPR_ULONG_ARRAY(&AccountMembership);
1114 
1115     if (BuiltinMembership.Element != NULL)
1116         SamIFree_SAMPR_ULONG_ARRAY(&BuiltinMembership);
1117 
1118     if (AccountDomainHandle != NULL)
1119         SamrCloseHandle(&AccountDomainHandle);
1120 
1121     if (BuiltinDomainHandle != NULL)
1122         SamrCloseHandle(&BuiltinDomainHandle);
1123 
1124     if (ServerHandle != NULL)
1125         SamrCloseHandle(&ServerHandle);
1126 
1127 //    return Status;
1128 
1129     return STATUS_SUCCESS;
1130 }
1131 
1132 
1133 static
1134 NTSTATUS
1135 LsapSetTokenOwner(
1136     IN PVOID TokenInformation,
1137     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1138 {
1139     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1140     PSID_AND_ATTRIBUTES OwnerSid = NULL;
1141     ULONG i, Length;
1142 
1143     if (TokenInformationType == LsaTokenInformationV1)
1144     {
1145         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1146 
1147         if (TokenInfo1->Owner.Owner != NULL)
1148             return STATUS_SUCCESS;
1149 
1150         OwnerSid = &TokenInfo1->User.User;
1151         for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1152         {
1153             if (EqualSid(TokenInfo1->Groups->Groups[i].Sid, LsapAdministratorsSid))
1154             {
1155                 OwnerSid = &TokenInfo1->Groups->Groups[i];
1156                 break;
1157             }
1158         }
1159 
1160         Length = RtlLengthSid(OwnerSid->Sid);
1161         TokenInfo1->Owner.Owner = DispatchTable.AllocateLsaHeap(Length);
1162         if (TokenInfo1->Owner.Owner == NULL)
1163             return STATUS_INSUFFICIENT_RESOURCES;
1164 
1165         RtlCopyMemory(TokenInfo1->Owner.Owner,
1166                       OwnerSid->Sid,
1167                       Length);
1168         OwnerSid->Attributes |= SE_GROUP_OWNER;
1169     }
1170 
1171     return STATUS_SUCCESS;
1172 }
1173 
1174 
1175 static
1176 NTSTATUS
1177 LsapAddTokenDefaultDacl(
1178     IN PVOID TokenInformation,
1179     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1180 {
1181     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1182     PACL Dacl = NULL;
1183     ULONG Length;
1184 
1185     if (TokenInformationType == LsaTokenInformationV1)
1186     {
1187         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1188 
1189         if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
1190             return STATUS_SUCCESS;
1191 
1192         Length = sizeof(ACL) +
1193                  (2 * sizeof(ACCESS_ALLOWED_ACE)) +
1194                  RtlLengthSid(TokenInfo1->Owner.Owner) +
1195                  RtlLengthSid(LsapLocalSystemSid);
1196 
1197         Dacl = DispatchTable.AllocateLsaHeap(Length);
1198         if (Dacl == NULL)
1199             return STATUS_INSUFFICIENT_RESOURCES;
1200 
1201         RtlCreateAcl(Dacl, Length, ACL_REVISION);
1202 
1203         RtlAddAccessAllowedAce(Dacl,
1204                                ACL_REVISION,
1205                                GENERIC_ALL,
1206                                TokenInfo1->Owner.Owner);
1207 
1208         /* SID: S-1-5-18 */
1209         RtlAddAccessAllowedAce(Dacl,
1210                                ACL_REVISION,
1211                                GENERIC_ALL,
1212                                LsapLocalSystemSid);
1213 
1214         TokenInfo1->DefaultDacl.DefaultDacl = Dacl;
1215     }
1216 
1217     return STATUS_SUCCESS;
1218 }
1219 
1220 
1221 static
1222 NTSTATUS
1223 LsapAddPrivilegeToTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges,
1224                                   PLSAPR_LUID_AND_ATTRIBUTES Privilege)
1225 {
1226     PTOKEN_PRIVILEGES LocalPrivileges;
1227     ULONG Length, TokenPrivilegeCount, i;
1228     NTSTATUS Status = STATUS_SUCCESS;
1229 
1230     if (*TokenPrivileges == NULL)
1231     {
1232         Length = sizeof(TOKEN_PRIVILEGES) +
1233                  (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES);
1234         LocalPrivileges = RtlAllocateHeap(RtlGetProcessHeap(),
1235                                           0,
1236                                           Length);
1237         if (LocalPrivileges == NULL)
1238             return STATUS_INSUFFICIENT_RESOURCES;
1239 
1240         LocalPrivileges->PrivilegeCount = 1;
1241         LocalPrivileges->Privileges[0].Luid = Privilege->Luid;
1242         LocalPrivileges->Privileges[0].Attributes = Privilege->Attributes;
1243     }
1244     else
1245     {
1246         TokenPrivilegeCount = (*TokenPrivileges)->PrivilegeCount;
1247 
1248         for (i = 0; i < TokenPrivilegeCount; i++)
1249         {
1250             if (RtlEqualLuid(&(*TokenPrivileges)->Privileges[i].Luid, &Privilege->Luid))
1251                 return STATUS_SUCCESS;
1252         }
1253 
1254         Length = sizeof(TOKEN_PRIVILEGES) +
1255                  (TokenPrivilegeCount + 1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES);
1256         LocalPrivileges = RtlAllocateHeap(RtlGetProcessHeap(),
1257                                           0,
1258                                           Length);
1259         if (LocalPrivileges == NULL)
1260             return STATUS_INSUFFICIENT_RESOURCES;
1261 
1262         LocalPrivileges->PrivilegeCount = TokenPrivilegeCount + 1;
1263         for (i = 0; i < TokenPrivilegeCount; i++)
1264         {
1265             LocalPrivileges->Privileges[i].Luid = (*TokenPrivileges)->Privileges[i].Luid;
1266             LocalPrivileges->Privileges[i].Attributes = (*TokenPrivileges)->Privileges[i].Attributes;
1267         }
1268 
1269         LocalPrivileges->Privileges[TokenPrivilegeCount].Luid = Privilege->Luid;
1270         LocalPrivileges->Privileges[TokenPrivilegeCount].Attributes = Privilege->Attributes;
1271 
1272         RtlFreeHeap(RtlGetProcessHeap(), 0, *TokenPrivileges);
1273     }
1274 
1275     *TokenPrivileges = LocalPrivileges;
1276 
1277     return Status;
1278 }
1279 
1280 static
1281 NTSTATUS
1282 LsapSetPrivileges(
1283     IN PVOID TokenInformation,
1284     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1285 {
1286     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1287     LSAPR_HANDLE PolicyHandle = NULL;
1288     LSAPR_HANDLE AccountHandle = NULL;
1289     PLSAPR_PRIVILEGE_SET Privileges = NULL;
1290     ULONG i, j;
1291     NTSTATUS Status;
1292 
1293     if (TokenInformationType == LsaTokenInformationV1)
1294     {
1295         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1296 
1297         Status = LsarOpenPolicy(NULL,
1298                                 NULL,
1299                                 0,
1300                                 &PolicyHandle);
1301         if (!NT_SUCCESS(Status))
1302             return Status;
1303 
1304         for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1305         {
1306             Status = LsarOpenAccount(PolicyHandle,
1307                                      TokenInfo1->Groups->Groups[i].Sid,
1308                                      ACCOUNT_VIEW,
1309                                      &AccountHandle);
1310             if (!NT_SUCCESS(Status))
1311                 continue;
1312 
1313             Status = LsarEnumeratePrivilegesAccount(AccountHandle,
1314                                                     &Privileges);
1315             if (NT_SUCCESS(Status))
1316             {
1317                 for (j = 0; j < Privileges->PrivilegeCount; j++)
1318                 {
1319                     Status = LsapAddPrivilegeToTokenPrivileges(&TokenInfo1->Privileges,
1320                                                                &(Privileges->Privilege[j]));
1321                     if (!NT_SUCCESS(Status))
1322                     {
1323                         /* We failed, clean everything and return */
1324                         LsaIFree_LSAPR_PRIVILEGE_SET(Privileges);
1325                         LsarClose(&AccountHandle);
1326                         LsarClose(&PolicyHandle);
1327 
1328                         return Status;
1329                     }
1330                 }
1331 
1332                 LsaIFree_LSAPR_PRIVILEGE_SET(Privileges);
1333                 Privileges = NULL;
1334             }
1335 
1336             LsarClose(&AccountHandle);
1337         }
1338 
1339         LsarClose(&PolicyHandle);
1340 
1341         if (TokenInfo1->Privileges != NULL)
1342         {
1343             for (i = 0; i < TokenInfo1->Privileges->PrivilegeCount; i++)
1344             {
1345                 if (RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeChangeNotifyPrivilege) ||
1346                     RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeCreateGlobalPrivilege) ||
1347                     RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeImpersonatePrivilege))
1348                 {
1349                     TokenInfo1->Privileges->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
1350                 }
1351             }
1352         }
1353     }
1354 
1355     return STATUS_SUCCESS;
1356 }
1357 
1358 
1359 NTSTATUS
1360 LsapLogonUser(PLSA_API_MSG RequestMsg,
1361               PLSAP_LOGON_CONTEXT LogonContext)
1362 {
1363     PAUTH_PACKAGE Package;
1364     OBJECT_ATTRIBUTES ObjectAttributes;
1365     SECURITY_QUALITY_OF_SERVICE Qos;
1366     LSA_TOKEN_INFORMATION_TYPE TokenInformationType;
1367     PVOID TokenInformation = NULL;
1368     PLSA_TOKEN_INFORMATION_V1 TokenInfo1 = NULL;
1369     PUNICODE_STRING AccountName = NULL;
1370     PUNICODE_STRING AuthenticatingAuthority = NULL;
1371     PUNICODE_STRING MachineName = NULL;
1372     PVOID LocalAuthInfo = NULL;
1373     PTOKEN_GROUPS LocalGroups = NULL;
1374     HANDLE TokenHandle = NULL;
1375     ULONG i;
1376     ULONG PackageId;
1377     SECURITY_LOGON_TYPE LogonType;
1378     NTSTATUS Status;
1379 
1380     PUNICODE_STRING UserName = NULL;
1381     PUNICODE_STRING LogonDomainName = NULL;
1382 //    UNICODE_STRING LogonServer;
1383 
1384 
1385     TRACE("LsapLogonUser(%p %p)\n", RequestMsg, LogonContext);
1386 
1387     PackageId = RequestMsg->LogonUser.Request.AuthenticationPackage;
1388     LogonType = RequestMsg->LogonUser.Request.LogonType;
1389 
1390     /* Get the right authentication package */
1391     Package = LsapGetAuthenticationPackage(PackageId);
1392     if (Package == NULL)
1393     {
1394         ERR("LsapGetAuthenticationPackage() failed to find a package\n");
1395         return STATUS_NO_SUCH_PACKAGE;
1396     }
1397 
1398     if (RequestMsg->LogonUser.Request.AuthenticationInformationLength > 0)
1399     {
1400         /* Allocate the local authentication info buffer */
1401         LocalAuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1402                                         HEAP_ZERO_MEMORY,
1403                                         RequestMsg->LogonUser.Request.AuthenticationInformationLength);
1404         if (LocalAuthInfo == NULL)
1405         {
1406             ERR("RtlAllocateHeap() failed\n");
1407             return STATUS_INSUFFICIENT_RESOURCES;
1408         }
1409 
1410         /* Read the authentication info from the callers address space */
1411         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
1412                                      RequestMsg->LogonUser.Request.AuthenticationInformation,
1413                                      LocalAuthInfo,
1414                                      RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1415                                      NULL);
1416         if (!NT_SUCCESS(Status))
1417         {
1418             ERR("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
1419             RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
1420             return Status;
1421         }
1422     }
1423 
1424     if (RequestMsg->LogonUser.Request.LocalGroupsCount > 0)
1425     {
1426         Status = LsapCopyLocalGroups(LogonContext,
1427                                      RequestMsg->LogonUser.Request.LocalGroups,
1428                                      RequestMsg->LogonUser.Request.LocalGroupsCount,
1429                                      &LocalGroups);
1430         if (!NT_SUCCESS(Status))
1431         {
1432             ERR("LsapCopyLocalGroups failed (Status 0x%08lx)\n", Status);
1433             goto done;
1434         }
1435 
1436         TRACE("GroupCount: %lu\n", LocalGroups->GroupCount);
1437     }
1438 
1439     if (Package->LsaApLogonUserEx2 != NULL)
1440     {
1441         Status = Package->LsaApLogonUserEx2((PLSA_CLIENT_REQUEST)LogonContext,
1442                                             RequestMsg->LogonUser.Request.LogonType,
1443                                             LocalAuthInfo,
1444                                             RequestMsg->LogonUser.Request.AuthenticationInformation,
1445                                             RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1446                                             &RequestMsg->LogonUser.Reply.ProfileBuffer,
1447                                             &RequestMsg->LogonUser.Reply.ProfileBufferLength,
1448                                             &RequestMsg->LogonUser.Reply.LogonId,
1449                                             &RequestMsg->LogonUser.Reply.SubStatus,
1450                                             &TokenInformationType,
1451                                             &TokenInformation,
1452                                             &AccountName,
1453                                             &AuthenticatingAuthority,
1454                                             &MachineName,
1455                                             NULL,  /* FIXME: PSECPKG_PRIMARY_CRED PrimaryCredentials */
1456                                             NULL); /* FIXME: PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials */
1457     }
1458     else if (Package->LsaApLogonUserEx != NULL)
1459     {
1460         Status = Package->LsaApLogonUserEx((PLSA_CLIENT_REQUEST)LogonContext,
1461                                            RequestMsg->LogonUser.Request.LogonType,
1462                                            LocalAuthInfo,
1463                                            RequestMsg->LogonUser.Request.AuthenticationInformation,
1464                                            RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1465                                            &RequestMsg->LogonUser.Reply.ProfileBuffer,
1466                                            &RequestMsg->LogonUser.Reply.ProfileBufferLength,
1467                                            &RequestMsg->LogonUser.Reply.LogonId,
1468                                            &RequestMsg->LogonUser.Reply.SubStatus,
1469                                            &TokenInformationType,
1470                                            &TokenInformation,
1471                                            &AccountName,
1472                                            &AuthenticatingAuthority,
1473                                            &MachineName);
1474     }
1475     else
1476     {
1477         Status = Package->LsaApLogonUser((PLSA_CLIENT_REQUEST)LogonContext,
1478                                          RequestMsg->LogonUser.Request.LogonType,
1479                                          LocalAuthInfo,
1480                                          RequestMsg->LogonUser.Request.AuthenticationInformation,
1481                                          RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1482                                          &RequestMsg->LogonUser.Reply.ProfileBuffer,
1483                                          &RequestMsg->LogonUser.Reply.ProfileBufferLength,
1484                                          &RequestMsg->LogonUser.Reply.LogonId,
1485                                          &RequestMsg->LogonUser.Reply.SubStatus,
1486                                          &TokenInformationType,
1487                                          &TokenInformation,
1488                                          &AccountName,
1489                                          &AuthenticatingAuthority);
1490     }
1491 
1492     if (!NT_SUCCESS(Status))
1493     {
1494         ERR("LsaApLogonUser/Ex/2 failed (Status 0x%08lx)\n", Status);
1495         goto done;
1496     }
1497 
1498     if (LocalGroups->GroupCount > 0)
1499     {
1500         /* Add local groups to the token information */
1501         Status = LsapAddLocalGroups(TokenInformation,
1502                                     TokenInformationType,
1503                                     LocalGroups);
1504         if (!NT_SUCCESS(Status))
1505         {
1506             ERR("LsapAddLocalGroupsToTokenInfo() failed (Status 0x%08lx)\n", Status);
1507             goto done;
1508         }
1509     }
1510 
1511     Status = LsapAddDefaultGroups(TokenInformation,
1512                                   TokenInformationType,
1513                                   LogonType);
1514     if (!NT_SUCCESS(Status))
1515     {
1516         ERR("LsapAddDefaultGroups() failed (Status 0x%08lx)\n", Status);
1517         goto done;
1518     }
1519 
1520     Status = LsapAddSamGroups(TokenInformation,
1521                               TokenInformationType);
1522     if (!NT_SUCCESS(Status))
1523     {
1524         ERR("LsapAddSamGroups() failed (Status 0x%08lx)\n", Status);
1525         goto done;
1526     }
1527 
1528     Status = LsapSetTokenOwner(TokenInformation,
1529                                TokenInformationType);
1530     if (!NT_SUCCESS(Status))
1531     {
1532         ERR("LsapSetTokenOwner() failed (Status 0x%08lx)\n", Status);
1533         goto done;
1534     }
1535 
1536     Status = LsapAddTokenDefaultDacl(TokenInformation,
1537                                      TokenInformationType);
1538     if (!NT_SUCCESS(Status))
1539     {
1540         ERR("LsapAddTokenDefaultDacl() failed (Status 0x%08lx)\n", Status);
1541         goto done;
1542     }
1543 
1544     Status = LsapSetPrivileges(TokenInformation,
1545                                TokenInformationType);
1546     if (!NT_SUCCESS(Status))
1547     {
1548         ERR("LsapSetPrivileges() failed (Status 0x%08lx)\n", Status);
1549         goto done;
1550     }
1551 
1552     if (TokenInformationType == LsaTokenInformationV1)
1553     {
1554         TOKEN_PRIVILEGES NoPrivilege = {0};
1555         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1556 
1557         Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
1558         Qos.ImpersonationLevel = SecurityImpersonation;
1559         Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
1560         Qos.EffectiveOnly = FALSE;
1561 
1562         ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
1563         ObjectAttributes.RootDirectory = NULL;
1564         ObjectAttributes.ObjectName = NULL;
1565         ObjectAttributes.Attributes = 0;
1566         ObjectAttributes.SecurityDescriptor = NULL;
1567         ObjectAttributes.SecurityQualityOfService = &Qos;
1568 
1569         /* Create the logon token */
1570         Status = NtCreateToken(&TokenHandle,
1571                                TOKEN_ALL_ACCESS,
1572                                &ObjectAttributes,
1573                                (RequestMsg->LogonUser.Request.LogonType == Network) ? TokenImpersonation : TokenPrimary,
1574                                &RequestMsg->LogonUser.Reply.LogonId,
1575                                &TokenInfo1->ExpirationTime,
1576                                &TokenInfo1->User,
1577                                TokenInfo1->Groups,
1578                                TokenInfo1->Privileges ? TokenInfo1->Privileges
1579                                                       : &NoPrivilege,
1580                                &TokenInfo1->Owner,
1581                                &TokenInfo1->PrimaryGroup,
1582                                &TokenInfo1->DefaultDacl,
1583                                &RequestMsg->LogonUser.Request.SourceContext);
1584         if (!NT_SUCCESS(Status))
1585         {
1586             ERR("NtCreateToken failed (Status 0x%08lx)\n", Status);
1587             goto done;
1588         }
1589     }
1590     else
1591     {
1592         FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
1593         Status = STATUS_NOT_IMPLEMENTED;
1594         goto done;
1595     }
1596 
1597     /* Duplicate the token handle into the client process */
1598     Status = NtDuplicateObject(NtCurrentProcess(),
1599                                TokenHandle,
1600                                LogonContext->ClientProcessHandle,
1601                                &RequestMsg->LogonUser.Reply.Token,
1602                                0,
1603                                0,
1604                                DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_CLOSE_SOURCE);
1605     if (!NT_SUCCESS(Status))
1606     {
1607         ERR("NtDuplicateObject failed (Status 0x%08lx)\n", Status);
1608         goto done;
1609     }
1610 
1611 //    TokenHandle = NULL;
1612 
1613     if (LogonType == Interactive ||
1614         LogonType == Batch ||
1615         LogonType == Service)
1616     {
1617         UserName = &((PMSV1_0_INTERACTIVE_LOGON)LocalAuthInfo)->UserName;
1618         LogonDomainName = &((PMSV1_0_INTERACTIVE_LOGON)LocalAuthInfo)->LogonDomainName;
1619     }
1620     else
1621     {
1622         FIXME("LogonType %lu is not supported yet!\n", LogonType);
1623     }
1624 
1625     Status = LsapSetLogonSessionData(&RequestMsg->LogonUser.Reply.LogonId,
1626                                      LogonType,
1627                                      UserName,
1628                                      LogonDomainName,
1629                                      TokenInfo1->User.User.Sid);
1630     if (!NT_SUCCESS(Status))
1631     {
1632         ERR("LsapSetLogonSessionData failed (Status 0x%08lx)\n", Status);
1633         goto done;
1634     }
1635 
1636 done:
1637 //    if (!NT_SUCCESS(Status))
1638 //    {
1639         if (TokenHandle != NULL)
1640             NtClose(TokenHandle);
1641 //    }
1642 
1643     /* Free the local groups */
1644     if (LocalGroups != NULL)
1645     {
1646         for (i = 0; i < LocalGroups->GroupCount; i++)
1647         {
1648             if (LocalGroups->Groups[i].Sid != NULL)
1649                 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
1650         }
1651 
1652         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
1653     }
1654 
1655     /* Free the local authentication info buffer */
1656     if (LocalAuthInfo != NULL)
1657         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
1658 
1659     /* Free the token information */
1660     if (TokenInformation != NULL)
1661     {
1662         if (TokenInformationType == LsaTokenInformationV1)
1663         {
1664             TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1665 
1666             if (TokenInfo1 != NULL)
1667             {
1668                 if (TokenInfo1->User.User.Sid != NULL)
1669                     LsapFreeHeap(TokenInfo1->User.User.Sid);
1670 
1671                 if (TokenInfo1->Groups != NULL)
1672                 {
1673                     for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1674                     {
1675                         if (TokenInfo1->Groups->Groups[i].Sid != NULL)
1676                             LsapFreeHeap(TokenInfo1->Groups->Groups[i].Sid);
1677                     }
1678 
1679                     LsapFreeHeap(TokenInfo1->Groups);
1680                 }
1681 
1682                 if (TokenInfo1->PrimaryGroup.PrimaryGroup != NULL)
1683                     LsapFreeHeap(TokenInfo1->PrimaryGroup.PrimaryGroup);
1684 
1685                 if (TokenInfo1->Privileges != NULL)
1686                     LsapFreeHeap(TokenInfo1->Privileges);
1687 
1688                 if (TokenInfo1->Owner.Owner != NULL)
1689                     LsapFreeHeap(TokenInfo1->Owner.Owner);
1690 
1691                 if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
1692                     LsapFreeHeap(TokenInfo1->DefaultDacl.DefaultDacl);
1693 
1694                 LsapFreeHeap(TokenInfo1);
1695             }
1696         }
1697         else
1698         {
1699             FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
1700         }
1701     }
1702 
1703     /* Free the account name */
1704     if (AccountName != NULL)
1705     {
1706         if (AccountName->Buffer != NULL)
1707             LsapFreeHeap(AccountName->Buffer);
1708 
1709         LsapFreeHeap(AccountName);
1710     }
1711 
1712     /* Free the authentication authority */
1713     if (AuthenticatingAuthority != NULL)
1714     {
1715         if (AuthenticatingAuthority != NULL)
1716             LsapFreeHeap(AuthenticatingAuthority->Buffer);
1717 
1718         LsapFreeHeap(AuthenticatingAuthority);
1719     }
1720 
1721     /* Free the machine name */
1722     if (MachineName != NULL)
1723     {
1724         if (MachineName->Buffer != NULL)
1725             LsapFreeHeap(MachineName->Buffer);
1726 
1727         LsapFreeHeap(MachineName);
1728     }
1729 
1730     TRACE("LsapLogonUser done (Status 0x%08lx)\n", Status);
1731 
1732     return Status;
1733 }
1734 
1735 /* EOF */
1736