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