xref: /reactos/dll/win32/lsasrv/authpackage.c (revision 682f85ad)
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     if (LogonContext->Untrusted)
589         Status = Package->LsaApCallPackageUntrusted((PLSA_CLIENT_REQUEST)LogonContext,
590                                                     LocalBuffer,
591                                                     RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
592                                                     RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
593                                                     &RequestMsg->CallAuthenticationPackage.Reply.ProtocolReturnBuffer,
594                                                     &RequestMsg->CallAuthenticationPackage.Reply.ReturnBufferLength,
595                                                     &RequestMsg->CallAuthenticationPackage.Reply.ProtocolStatus);
596     else
597         Status = Package->LsaApCallPackage((PLSA_CLIENT_REQUEST)LogonContext,
598                                            LocalBuffer,
599                                            RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
600                                            RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
601                                            &RequestMsg->CallAuthenticationPackage.Reply.ProtocolReturnBuffer,
602                                            &RequestMsg->CallAuthenticationPackage.Reply.ReturnBufferLength,
603                                            &RequestMsg->CallAuthenticationPackage.Reply.ProtocolStatus);
604     if (!NT_SUCCESS(Status))
605     {
606         TRACE("Package->LsaApCallPackage() failed (Status 0x%08lx)\n", Status);
607     }
608 
609     if (LocalBuffer != NULL)
610         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
611 
612     return Status;
613 }
614 
615 
616 static
617 NTSTATUS
618 LsapCopyLocalGroups(
619     IN PLSAP_LOGON_CONTEXT LogonContext,
620     IN PTOKEN_GROUPS ClientGroups,
621     IN ULONG ClientGroupsCount,
622     OUT PTOKEN_GROUPS *TokenGroups)
623 {
624     ULONG LocalGroupsLength = 0;
625     PTOKEN_GROUPS LocalGroups = NULL;
626     ULONG SidHeaderLength = 0;
627     PSID SidHeader = NULL;
628     PSID SrcSid, DstSid;
629     ULONG SidLength;
630     ULONG AllocatedSids = 0;
631     ULONG i;
632     NTSTATUS Status;
633 
634     LocalGroupsLength = sizeof(TOKEN_GROUPS) +
635                         (ClientGroupsCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
636     LocalGroups = RtlAllocateHeap(RtlGetProcessHeap(),
637                                   HEAP_ZERO_MEMORY,
638                                   LocalGroupsLength);
639     if (LocalGroups == NULL)
640     {
641         TRACE("RtlAllocateHeap() failed\n");
642         return STATUS_INSUFFICIENT_RESOURCES;
643     }
644 
645     Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
646                                  ClientGroups,
647                                  LocalGroups,
648                                  LocalGroupsLength,
649                                  NULL);
650     if (!NT_SUCCESS(Status))
651         goto done;
652 
653 
654     SidHeaderLength  = RtlLengthRequiredSid(0);
655     SidHeader = RtlAllocateHeap(RtlGetProcessHeap(),
656                                 HEAP_ZERO_MEMORY,
657                                 SidHeaderLength);
658     if (SidHeader == NULL)
659     {
660         Status = STATUS_INSUFFICIENT_RESOURCES;
661         goto done;
662     }
663 
664     for (i = 0; i < ClientGroupsCount; i++)
665     {
666         SrcSid = LocalGroups->Groups[i].Sid;
667 
668         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
669                                      SrcSid,
670                                      SidHeader,
671                                      SidHeaderLength,
672                                      NULL);
673         if (!NT_SUCCESS(Status))
674             goto done;
675 
676         SidLength = RtlLengthSid(SidHeader);
677         TRACE("Sid %lu: Length %lu\n", i, SidLength);
678 
679         DstSid = RtlAllocateHeap(RtlGetProcessHeap(),
680                                  HEAP_ZERO_MEMORY,
681                                  SidLength);
682         if (DstSid == NULL)
683         {
684             Status = STATUS_INSUFFICIENT_RESOURCES;
685             goto done;
686         }
687 
688         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
689                                      SrcSid,
690                                      DstSid,
691                                      SidLength,
692                                      NULL);
693         if (!NT_SUCCESS(Status))
694         {
695             RtlFreeHeap(RtlGetProcessHeap(), 0, DstSid);
696             goto done;
697         }
698 
699         LocalGroups->Groups[i].Sid = DstSid;
700         AllocatedSids++;
701     }
702 
703     *TokenGroups = LocalGroups;
704 
705 done:
706     if (SidHeader != NULL)
707         RtlFreeHeap(RtlGetProcessHeap(), 0, SidHeader);
708 
709     if (!NT_SUCCESS(Status))
710     {
711         if (LocalGroups != NULL)
712         {
713             for (i = 0; i < AllocatedSids; i++)
714                 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
715 
716             RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
717         }
718     }
719 
720     return Status;
721 }
722 
723 
724 static
725 NTSTATUS
726 LsapAddLocalGroups(
727     IN PVOID TokenInformation,
728     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
729     IN PTOKEN_GROUPS LocalGroups)
730 {
731     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
732     PTOKEN_GROUPS Groups;
733     ULONG Length;
734     ULONG i;
735     ULONG j;
736 
737     if (LocalGroups == NULL || LocalGroups->GroupCount == 0)
738         return STATUS_SUCCESS;
739 
740     if (TokenInformationType == LsaTokenInformationV1)
741     {
742         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
743 
744         if (TokenInfo1->Groups != NULL)
745         {
746             Length = sizeof(TOKEN_GROUPS) +
747                      (LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
748 
749             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
750             if (Groups == NULL)
751             {
752                 ERR("Group buffer allocation failed!\n");
753                 return STATUS_INSUFFICIENT_RESOURCES;
754             }
755 
756             Groups->GroupCount = LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount;
757 
758             for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
759             {
760                 Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
761                 Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
762             }
763 
764             for (j = 0; j < LocalGroups->GroupCount; i++, j++)
765             {
766                 Groups->Groups[i].Sid = LocalGroups->Groups[j].Sid;
767                 Groups->Groups[i].Attributes = LocalGroups->Groups[j].Attributes;
768                 LocalGroups->Groups[j].Sid = NULL;
769             }
770 
771             RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
772 
773             TokenInfo1->Groups = Groups;
774         }
775         else
776         {
777             Length = sizeof(TOKEN_GROUPS) +
778                      (LocalGroups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
779 
780             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
781             if (Groups == NULL)
782             {
783                 ERR("Group buffer allocation failed!\n");
784                 return STATUS_INSUFFICIENT_RESOURCES;
785             }
786 
787             Groups->GroupCount = LocalGroups->GroupCount;
788 
789             for (i = 0; i < LocalGroups->GroupCount; i++)
790             {
791                 Groups->Groups[i].Sid = LocalGroups->Groups[i].Sid;
792                 Groups->Groups[i].Attributes = LocalGroups->Groups[i].Attributes;
793             }
794 
795             TokenInfo1->Groups = Groups;
796         }
797     }
798     else
799     {
800         FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
801         return STATUS_NOT_IMPLEMENTED;
802     }
803 
804     return STATUS_SUCCESS;
805 }
806 
807 static
808 NTSTATUS
809 LsapAddDefaultGroups(
810     IN PVOID TokenInformation,
811     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
812     IN SECURITY_LOGON_TYPE LogonType)
813 {
814     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
815     PTOKEN_GROUPS Groups;
816     ULONG i, Length;
817     PSID SrcSid;
818 
819     if (TokenInformationType == LsaTokenInformationV1)
820     {
821         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
822 
823         if (TokenInfo1->Groups != NULL)
824         {
825             Length = sizeof(TOKEN_GROUPS) +
826                      (TokenInfo1->Groups->GroupCount + 2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
827 
828             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
829             if (Groups == NULL)
830             {
831                 ERR("Group buffer allocation failed!\n");
832                 return STATUS_INSUFFICIENT_RESOURCES;
833             }
834 
835             Groups->GroupCount = TokenInfo1->Groups->GroupCount;
836 
837             for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
838             {
839                 Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
840                 Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
841             }
842 
843             RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
844 
845             TokenInfo1->Groups = Groups;
846 
847         }
848         else
849         {
850             Length = sizeof(TOKEN_GROUPS) +
851                      (2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
852 
853             Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
854             if (Groups == NULL)
855             {
856                 ERR("Group buffer allocation failed!\n");
857                 return STATUS_INSUFFICIENT_RESOURCES;
858             }
859 
860             TokenInfo1->Groups = Groups;
861         }
862 
863         /* Append the World SID (aka Everyone) */
864         Length = RtlLengthSid(LsapWorldSid);
865         Groups->Groups[Groups->GroupCount].Sid = RtlAllocateHeap(RtlGetProcessHeap(),
866                                                                  HEAP_ZERO_MEMORY,
867                                                                  Length);
868         if (Groups->Groups[Groups->GroupCount].Sid == NULL)
869             return STATUS_INSUFFICIENT_RESOURCES;
870 
871         RtlCopyMemory(Groups->Groups[Groups->GroupCount].Sid,
872                       LsapWorldSid,
873                       Length);
874 
875         Groups->Groups[Groups->GroupCount].Attributes =
876             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
877 
878         Groups->GroupCount++;
879 
880         /* Append the logon type SID */
881         switch (LogonType)
882         {
883             case Interactive:
884                 SrcSid = LsapInteractiveSid;
885                 break;
886 
887             case Network:
888                 SrcSid = LsapNetworkSid;
889                 break;
890 
891             case Batch:
892                 SrcSid = LsapBatchSid;
893                 break;
894 
895             case Service:
896                 SrcSid = LsapServiceSid;
897                 break;
898 
899             default:
900                 FIXME("LogonType %d is not supported!\n", LogonType);
901                 return STATUS_NOT_IMPLEMENTED;
902         }
903 
904         Length = RtlLengthSid(SrcSid);
905         Groups->Groups[Groups->GroupCount].Sid = RtlAllocateHeap(RtlGetProcessHeap(),
906                                                                  HEAP_ZERO_MEMORY,
907                                                                  Length);
908         if (Groups->Groups[Groups->GroupCount].Sid == NULL)
909             return STATUS_INSUFFICIENT_RESOURCES;
910 
911         RtlCopyMemory(Groups->Groups[Groups->GroupCount].Sid,
912                       SrcSid,
913                       Length);
914 
915         Groups->Groups[Groups->GroupCount].Attributes =
916             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
917 
918         Groups->GroupCount++;
919     }
920     else
921     {
922         FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
923         return STATUS_NOT_IMPLEMENTED;
924     }
925 
926     return STATUS_SUCCESS;
927 }
928 
929 
930 static
931 NTSTATUS
932 LsapAppendSidToGroups(
933     IN PTOKEN_GROUPS *TokenGroups,
934     IN PSID DomainSid,
935     IN ULONG RelativeId)
936 {
937     PTOKEN_GROUPS Groups;
938     PSID Sid;
939     ULONG Length;
940     ULONG i;
941 
942     Sid = LsapAppendRidToSid(DomainSid, RelativeId);
943     if (Sid == NULL)
944     {
945         ERR("Group SID creation failed!\n");
946         return STATUS_INSUFFICIENT_RESOURCES;
947     }
948 
949     if (*TokenGroups == NULL)
950     {
951         Length = sizeof(TOKEN_GROUPS) +
952                  (1 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
953 
954         Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
955         if (Groups == NULL)
956         {
957             ERR("Group buffer allocation failed!\n");
958             return STATUS_INSUFFICIENT_RESOURCES;
959         }
960 
961         Groups->GroupCount = 1;
962 
963         Groups->Groups[0].Sid = Sid;
964         Groups->Groups[0].Attributes =
965             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
966 
967         *TokenGroups = Groups;
968     }
969     else
970     {
971         for (i = 0; i < (*TokenGroups)->GroupCount; i++)
972         {
973             if (RtlEqualSid((*TokenGroups)->Groups[i].Sid, Sid))
974             {
975                 RtlFreeHeap(RtlGetProcessHeap(), 0, Sid);
976                 return STATUS_SUCCESS;
977             }
978         }
979 
980         Length = sizeof(TOKEN_GROUPS) +
981                  ((*TokenGroups)->GroupCount + 1 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
982 
983         Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
984         if (Groups == NULL)
985         {
986             ERR("Group buffer allocation failed!\n");
987             return STATUS_INSUFFICIENT_RESOURCES;
988         }
989 
990         Groups->GroupCount = (*TokenGroups)->GroupCount;
991 
992         for (i = 0; i < (*TokenGroups)->GroupCount; i++)
993         {
994             Groups->Groups[i].Sid = (*TokenGroups)->Groups[i].Sid;
995             Groups->Groups[i].Attributes = (*TokenGroups)->Groups[i].Attributes;
996         }
997 
998         Groups->Groups[Groups->GroupCount].Sid = Sid;
999         Groups->Groups[Groups->GroupCount].Attributes =
1000             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
1001 
1002         Groups->GroupCount++;
1003 
1004         RtlFreeHeap(RtlGetProcessHeap(), 0, *TokenGroups);
1005 
1006         *TokenGroups = Groups;
1007     }
1008 
1009     return STATUS_SUCCESS;
1010 }
1011 
1012 
1013 static
1014 NTSTATUS
1015 LsapAddSamGroups(
1016     IN PVOID TokenInformation,
1017     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1018 {
1019     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1020     SAMPR_HANDLE ServerHandle = NULL;
1021     SAMPR_HANDLE BuiltinDomainHandle = NULL;
1022     SAMPR_HANDLE AccountDomainHandle = NULL;
1023     SAMPR_PSID_ARRAY SidArray;
1024     SAMPR_ULONG_ARRAY BuiltinMembership;
1025     SAMPR_ULONG_ARRAY AccountMembership;
1026     ULONG i;
1027     NTSTATUS Status = STATUS_SUCCESS;
1028 
1029     if (TokenInformationType != LsaTokenInformationV1)
1030         return STATUS_SUCCESS;
1031 
1032     TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1033 
1034     SidArray.Count = TokenInfo1->Groups->GroupCount + 1;
1035     SidArray.Sids = RtlAllocateHeap(RtlGetProcessHeap(),
1036                                     HEAP_ZERO_MEMORY,
1037                                     (TokenInfo1->Groups->GroupCount + 1) * sizeof(PRPC_SID));
1038     if (SidArray.Sids == NULL)
1039         return STATUS_INSUFFICIENT_RESOURCES;
1040 
1041     SidArray.Sids[0].SidPointer = TokenInfo1->User.User.Sid;
1042     for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1043         SidArray.Sids[i + 1].SidPointer = TokenInfo1->Groups->Groups[i].Sid;
1044 
1045     BuiltinMembership.Element = NULL;
1046     AccountMembership.Element = NULL;
1047 
1048     Status = SamIConnect(NULL,
1049                          &ServerHandle,
1050                          SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1051                          FALSE);
1052     if (!NT_SUCCESS(Status))
1053     {
1054         TRACE("SamIConnect failed (Status %08lx)\n", Status);
1055         goto done;
1056     }
1057 
1058     Status = SamrOpenDomain(ServerHandle,
1059                             DOMAIN_GET_ALIAS_MEMBERSHIP,
1060                             BuiltinDomainSid,
1061                             &BuiltinDomainHandle);
1062     if (!NT_SUCCESS(Status))
1063     {
1064         TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
1065         goto done;
1066     }
1067 
1068     Status = SamrOpenDomain(ServerHandle,
1069                             DOMAIN_GET_ALIAS_MEMBERSHIP,
1070                             AccountDomainSid,
1071                             &AccountDomainHandle);
1072     if (!NT_SUCCESS(Status))
1073     {
1074         TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
1075         goto done;
1076     }
1077 
1078     Status = SamrGetAliasMembership(BuiltinDomainHandle,
1079                                     &SidArray,
1080                                     &BuiltinMembership);
1081     if (!NT_SUCCESS(Status))
1082     {
1083         TRACE("SamrGetAliasMembership failed (Status %08lx)\n", Status);
1084         goto done;
1085     }
1086 
1087     Status = SamrGetAliasMembership(AccountDomainHandle,
1088                                     &SidArray,
1089                                     &AccountMembership);
1090     if (!NT_SUCCESS(Status))
1091     {
1092         TRACE("SamrGetAliasMembership failed (Status %08lx)\n", Status);
1093         goto done;
1094     }
1095 
1096     TRACE("Builtin Memberships: %lu\n", BuiltinMembership.Count);
1097     for (i = 0; i < BuiltinMembership.Count; i++)
1098     {
1099         TRACE("RID %lu: %lu (0x%lx)\n", i, BuiltinMembership.Element[i], BuiltinMembership.Element[i]);
1100         Status = LsapAppendSidToGroups(&TokenInfo1->Groups,
1101                                        BuiltinDomainSid,
1102                                        BuiltinMembership.Element[i]);
1103         if (!NT_SUCCESS(Status))
1104         {
1105             TRACE("LsapAppendSidToGroups failed (Status %08lx)\n", Status);
1106             goto done;
1107         }
1108     }
1109 
1110     TRACE("Account Memberships: %lu\n", AccountMembership.Count);
1111     for (i = 0; i < AccountMembership.Count; i++)
1112     {
1113         TRACE("RID %lu: %lu (0x%lx)\n", i, AccountMembership.Element[i], AccountMembership.Element[i]);
1114         Status = LsapAppendSidToGroups(&TokenInfo1->Groups,
1115                                        AccountDomainSid,
1116                                        AccountMembership.Element[i]);
1117         if (!NT_SUCCESS(Status))
1118         {
1119             TRACE("LsapAppendSidToGroups failed (Status %08lx)\n", Status);
1120             goto done;
1121         }
1122     }
1123 
1124 done:
1125     RtlFreeHeap(RtlGetProcessHeap(), 0, SidArray.Sids);
1126 
1127     if (AccountMembership.Element != NULL)
1128         SamIFree_SAMPR_ULONG_ARRAY(&AccountMembership);
1129 
1130     if (BuiltinMembership.Element != NULL)
1131         SamIFree_SAMPR_ULONG_ARRAY(&BuiltinMembership);
1132 
1133     if (AccountDomainHandle != NULL)
1134         SamrCloseHandle(&AccountDomainHandle);
1135 
1136     if (BuiltinDomainHandle != NULL)
1137         SamrCloseHandle(&BuiltinDomainHandle);
1138 
1139     if (ServerHandle != NULL)
1140         SamrCloseHandle(&ServerHandle);
1141 
1142 //    return Status;
1143 
1144     return STATUS_SUCCESS;
1145 }
1146 
1147 
1148 static
1149 NTSTATUS
1150 LsapSetTokenOwner(
1151     IN PVOID TokenInformation,
1152     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1153 {
1154     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1155     PSID_AND_ATTRIBUTES OwnerSid = NULL;
1156     ULONG i, Length;
1157 
1158     if (TokenInformationType == LsaTokenInformationV1)
1159     {
1160         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1161 
1162         if (TokenInfo1->Owner.Owner != NULL)
1163             return STATUS_SUCCESS;
1164 
1165         OwnerSid = &TokenInfo1->User.User;
1166         for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1167         {
1168             if (EqualSid(TokenInfo1->Groups->Groups[i].Sid, LsapAdministratorsSid))
1169             {
1170                 OwnerSid = &TokenInfo1->Groups->Groups[i];
1171                 break;
1172             }
1173         }
1174 
1175         Length = RtlLengthSid(OwnerSid->Sid);
1176         TokenInfo1->Owner.Owner = DispatchTable.AllocateLsaHeap(Length);
1177         if (TokenInfo1->Owner.Owner == NULL)
1178             return STATUS_INSUFFICIENT_RESOURCES;
1179 
1180         RtlCopyMemory(TokenInfo1->Owner.Owner,
1181                       OwnerSid->Sid,
1182                       Length);
1183         OwnerSid->Attributes |= SE_GROUP_OWNER;
1184     }
1185 
1186     return STATUS_SUCCESS;
1187 }
1188 
1189 
1190 static
1191 NTSTATUS
1192 LsapAddTokenDefaultDacl(
1193     IN PVOID TokenInformation,
1194     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1195 {
1196     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1197     PACL Dacl = NULL;
1198     ULONG Length;
1199 
1200     if (TokenInformationType == LsaTokenInformationV1)
1201     {
1202         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1203 
1204         if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
1205             return STATUS_SUCCESS;
1206 
1207         Length = sizeof(ACL) +
1208                  (2 * sizeof(ACCESS_ALLOWED_ACE)) +
1209                  RtlLengthSid(TokenInfo1->Owner.Owner) +
1210                  RtlLengthSid(LsapLocalSystemSid);
1211 
1212         Dacl = DispatchTable.AllocateLsaHeap(Length);
1213         if (Dacl == NULL)
1214             return STATUS_INSUFFICIENT_RESOURCES;
1215 
1216         RtlCreateAcl(Dacl, Length, ACL_REVISION);
1217 
1218         RtlAddAccessAllowedAce(Dacl,
1219                                ACL_REVISION,
1220                                GENERIC_ALL,
1221                                TokenInfo1->Owner.Owner);
1222 
1223         /* SID: S-1-5-18 */
1224         RtlAddAccessAllowedAce(Dacl,
1225                                ACL_REVISION,
1226                                GENERIC_ALL,
1227                                LsapLocalSystemSid);
1228 
1229         TokenInfo1->DefaultDacl.DefaultDacl = Dacl;
1230     }
1231 
1232     return STATUS_SUCCESS;
1233 }
1234 
1235 
1236 static
1237 NTSTATUS
1238 LsapAddPrivilegeToTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges,
1239                                   PLSAPR_LUID_AND_ATTRIBUTES Privilege)
1240 {
1241     PTOKEN_PRIVILEGES LocalPrivileges;
1242     ULONG Length, TokenPrivilegeCount, i;
1243     NTSTATUS Status = STATUS_SUCCESS;
1244 
1245     if (*TokenPrivileges == NULL)
1246     {
1247         Length = sizeof(TOKEN_PRIVILEGES) +
1248                  (1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES);
1249         LocalPrivileges = RtlAllocateHeap(RtlGetProcessHeap(),
1250                                           0,
1251                                           Length);
1252         if (LocalPrivileges == NULL)
1253             return STATUS_INSUFFICIENT_RESOURCES;
1254 
1255         LocalPrivileges->PrivilegeCount = 1;
1256         LocalPrivileges->Privileges[0].Luid = Privilege->Luid;
1257         LocalPrivileges->Privileges[0].Attributes = Privilege->Attributes;
1258     }
1259     else
1260     {
1261         TokenPrivilegeCount = (*TokenPrivileges)->PrivilegeCount;
1262 
1263         for (i = 0; i < TokenPrivilegeCount; i++)
1264         {
1265             if (RtlEqualLuid(&(*TokenPrivileges)->Privileges[i].Luid, &Privilege->Luid))
1266                 return STATUS_SUCCESS;
1267         }
1268 
1269         Length = sizeof(TOKEN_PRIVILEGES) +
1270                  (TokenPrivilegeCount + 1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES);
1271         LocalPrivileges = RtlAllocateHeap(RtlGetProcessHeap(),
1272                                           0,
1273                                           Length);
1274         if (LocalPrivileges == NULL)
1275             return STATUS_INSUFFICIENT_RESOURCES;
1276 
1277         LocalPrivileges->PrivilegeCount = TokenPrivilegeCount + 1;
1278         for (i = 0; i < TokenPrivilegeCount; i++)
1279         {
1280             LocalPrivileges->Privileges[i].Luid = (*TokenPrivileges)->Privileges[i].Luid;
1281             LocalPrivileges->Privileges[i].Attributes = (*TokenPrivileges)->Privileges[i].Attributes;
1282         }
1283 
1284         LocalPrivileges->Privileges[TokenPrivilegeCount].Luid = Privilege->Luid;
1285         LocalPrivileges->Privileges[TokenPrivilegeCount].Attributes = Privilege->Attributes;
1286 
1287         RtlFreeHeap(RtlGetProcessHeap(), 0, *TokenPrivileges);
1288     }
1289 
1290     *TokenPrivileges = LocalPrivileges;
1291 
1292     return Status;
1293 }
1294 
1295 static
1296 NTSTATUS
1297 LsapSetPrivileges(
1298     IN PVOID TokenInformation,
1299     IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
1300 {
1301     PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
1302     LSAPR_HANDLE PolicyHandle = NULL;
1303     LSAPR_HANDLE AccountHandle = NULL;
1304     PLSAPR_PRIVILEGE_SET Privileges = NULL;
1305     ULONG i, j;
1306     NTSTATUS Status;
1307 
1308     if (TokenInformationType == LsaTokenInformationV1)
1309     {
1310         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1311 
1312         Status = LsarOpenPolicy(NULL,
1313                                 NULL,
1314                                 0,
1315                                 &PolicyHandle);
1316         if (!NT_SUCCESS(Status))
1317             return Status;
1318 
1319         for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1320         {
1321             Status = LsarOpenAccount(PolicyHandle,
1322                                      TokenInfo1->Groups->Groups[i].Sid,
1323                                      ACCOUNT_VIEW,
1324                                      &AccountHandle);
1325             if (!NT_SUCCESS(Status))
1326                 continue;
1327 
1328             Status = LsarEnumeratePrivilegesAccount(AccountHandle,
1329                                                     &Privileges);
1330             if (NT_SUCCESS(Status))
1331             {
1332                 for (j = 0; j < Privileges->PrivilegeCount; j++)
1333                 {
1334                     Status = LsapAddPrivilegeToTokenPrivileges(&TokenInfo1->Privileges,
1335                                                                &(Privileges->Privilege[j]));
1336                     if (!NT_SUCCESS(Status))
1337                     {
1338                         /* We failed, clean everything and return */
1339                         LsaIFree_LSAPR_PRIVILEGE_SET(Privileges);
1340                         LsarClose(&AccountHandle);
1341                         LsarClose(&PolicyHandle);
1342 
1343                         return Status;
1344                     }
1345                 }
1346 
1347                 LsaIFree_LSAPR_PRIVILEGE_SET(Privileges);
1348                 Privileges = NULL;
1349             }
1350 
1351             LsarClose(&AccountHandle);
1352         }
1353 
1354         LsarClose(&PolicyHandle);
1355 
1356         if (TokenInfo1->Privileges != NULL)
1357         {
1358             for (i = 0; i < TokenInfo1->Privileges->PrivilegeCount; i++)
1359             {
1360                 if (RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeChangeNotifyPrivilege) ||
1361                     RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeCreateGlobalPrivilege) ||
1362                     RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeImpersonatePrivilege))
1363                 {
1364                     TokenInfo1->Privileges->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
1365                 }
1366             }
1367         }
1368     }
1369 
1370     return STATUS_SUCCESS;
1371 }
1372 
1373 
1374 NTSTATUS
1375 LsapLogonUser(PLSA_API_MSG RequestMsg,
1376               PLSAP_LOGON_CONTEXT LogonContext)
1377 {
1378     PAUTH_PACKAGE Package;
1379     OBJECT_ATTRIBUTES ObjectAttributes;
1380     SECURITY_QUALITY_OF_SERVICE Qos;
1381     LSA_TOKEN_INFORMATION_TYPE TokenInformationType;
1382     PVOID TokenInformation = NULL;
1383     PLSA_TOKEN_INFORMATION_NULL TokenInfo0 = NULL;
1384     PLSA_TOKEN_INFORMATION_V1 TokenInfo1 = NULL;
1385     PUNICODE_STRING AccountName = NULL;
1386     PUNICODE_STRING AuthenticatingAuthority = NULL;
1387     PUNICODE_STRING MachineName = NULL;
1388     PVOID LocalAuthInfo = NULL;
1389     PTOKEN_GROUPS LocalGroups = NULL;
1390     HANDLE TokenHandle = NULL;
1391     ULONG i;
1392     ULONG PackageId;
1393     SECURITY_LOGON_TYPE LogonType;
1394     NTSTATUS Status;
1395 
1396     PUNICODE_STRING UserName = NULL;
1397     PUNICODE_STRING LogonDomainName = NULL;
1398 //    UNICODE_STRING LogonServer;
1399 
1400 
1401     TRACE("LsapLogonUser(%p %p)\n", RequestMsg, LogonContext);
1402 
1403     PackageId = RequestMsg->LogonUser.Request.AuthenticationPackage;
1404     LogonType = RequestMsg->LogonUser.Request.LogonType;
1405 
1406     /* Get the right authentication package */
1407     Package = LsapGetAuthenticationPackage(PackageId);
1408     if (Package == NULL)
1409     {
1410         ERR("LsapGetAuthenticationPackage() failed to find a package\n");
1411         return STATUS_NO_SUCH_PACKAGE;
1412     }
1413 
1414     if (RequestMsg->LogonUser.Request.AuthenticationInformationLength > 0)
1415     {
1416         /* Allocate the local authentication info buffer */
1417         LocalAuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1418                                         HEAP_ZERO_MEMORY,
1419                                         RequestMsg->LogonUser.Request.AuthenticationInformationLength);
1420         if (LocalAuthInfo == NULL)
1421         {
1422             ERR("RtlAllocateHeap() failed\n");
1423             return STATUS_INSUFFICIENT_RESOURCES;
1424         }
1425 
1426         /* Read the authentication info from the callers address space */
1427         Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
1428                                      RequestMsg->LogonUser.Request.AuthenticationInformation,
1429                                      LocalAuthInfo,
1430                                      RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1431                                      NULL);
1432         if (!NT_SUCCESS(Status))
1433         {
1434             ERR("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
1435             RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
1436             return Status;
1437         }
1438     }
1439 
1440     if (RequestMsg->LogonUser.Request.LocalGroupsCount > 0)
1441     {
1442         Status = LsapCopyLocalGroups(LogonContext,
1443                                      RequestMsg->LogonUser.Request.LocalGroups,
1444                                      RequestMsg->LogonUser.Request.LocalGroupsCount,
1445                                      &LocalGroups);
1446         if (!NT_SUCCESS(Status))
1447         {
1448             ERR("LsapCopyLocalGroups failed (Status 0x%08lx)\n", Status);
1449             goto done;
1450         }
1451 
1452         TRACE("GroupCount: %lu\n", LocalGroups->GroupCount);
1453     }
1454 
1455     if (Package->LsaApLogonUserEx2 != NULL)
1456     {
1457         Status = Package->LsaApLogonUserEx2((PLSA_CLIENT_REQUEST)LogonContext,
1458                                             RequestMsg->LogonUser.Request.LogonType,
1459                                             LocalAuthInfo,
1460                                             RequestMsg->LogonUser.Request.AuthenticationInformation,
1461                                             RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1462                                             &RequestMsg->LogonUser.Reply.ProfileBuffer,
1463                                             &RequestMsg->LogonUser.Reply.ProfileBufferLength,
1464                                             &RequestMsg->LogonUser.Reply.LogonId,
1465                                             &RequestMsg->LogonUser.Reply.SubStatus,
1466                                             &TokenInformationType,
1467                                             &TokenInformation,
1468                                             &AccountName,
1469                                             &AuthenticatingAuthority,
1470                                             &MachineName,
1471                                             NULL,  /* FIXME: PSECPKG_PRIMARY_CRED PrimaryCredentials */
1472                                             NULL); /* FIXME: PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials */
1473     }
1474     else if (Package->LsaApLogonUserEx != NULL)
1475     {
1476         Status = Package->LsaApLogonUserEx((PLSA_CLIENT_REQUEST)LogonContext,
1477                                            RequestMsg->LogonUser.Request.LogonType,
1478                                            LocalAuthInfo,
1479                                            RequestMsg->LogonUser.Request.AuthenticationInformation,
1480                                            RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1481                                            &RequestMsg->LogonUser.Reply.ProfileBuffer,
1482                                            &RequestMsg->LogonUser.Reply.ProfileBufferLength,
1483                                            &RequestMsg->LogonUser.Reply.LogonId,
1484                                            &RequestMsg->LogonUser.Reply.SubStatus,
1485                                            &TokenInformationType,
1486                                            &TokenInformation,
1487                                            &AccountName,
1488                                            &AuthenticatingAuthority,
1489                                            &MachineName);
1490     }
1491     else
1492     {
1493         Status = Package->LsaApLogonUser((PLSA_CLIENT_REQUEST)LogonContext,
1494                                          RequestMsg->LogonUser.Request.LogonType,
1495                                          LocalAuthInfo,
1496                                          RequestMsg->LogonUser.Request.AuthenticationInformation,
1497                                          RequestMsg->LogonUser.Request.AuthenticationInformationLength,
1498                                          &RequestMsg->LogonUser.Reply.ProfileBuffer,
1499                                          &RequestMsg->LogonUser.Reply.ProfileBufferLength,
1500                                          &RequestMsg->LogonUser.Reply.LogonId,
1501                                          &RequestMsg->LogonUser.Reply.SubStatus,
1502                                          &TokenInformationType,
1503                                          &TokenInformation,
1504                                          &AccountName,
1505                                          &AuthenticatingAuthority);
1506     }
1507 
1508     if (!NT_SUCCESS(Status))
1509     {
1510         ERR("LsaApLogonUser/Ex/2 failed (Status 0x%08lx)\n", Status);
1511         goto done;
1512     }
1513 
1514     if (LocalGroups->GroupCount > 0)
1515     {
1516         /* Add local groups to the token information */
1517         Status = LsapAddLocalGroups(TokenInformation,
1518                                     TokenInformationType,
1519                                     LocalGroups);
1520         if (!NT_SUCCESS(Status))
1521         {
1522             ERR("LsapAddLocalGroupsToTokenInfo() failed (Status 0x%08lx)\n", Status);
1523             goto done;
1524         }
1525     }
1526 
1527     Status = LsapAddDefaultGroups(TokenInformation,
1528                                   TokenInformationType,
1529                                   LogonType);
1530     if (!NT_SUCCESS(Status))
1531     {
1532         ERR("LsapAddDefaultGroups() failed (Status 0x%08lx)\n", Status);
1533         goto done;
1534     }
1535 
1536     Status = LsapAddSamGroups(TokenInformation,
1537                               TokenInformationType);
1538     if (!NT_SUCCESS(Status))
1539     {
1540         ERR("LsapAddSamGroups() failed (Status 0x%08lx)\n", Status);
1541         goto done;
1542     }
1543 
1544     Status = LsapSetTokenOwner(TokenInformation,
1545                                TokenInformationType);
1546     if (!NT_SUCCESS(Status))
1547     {
1548         ERR("LsapSetTokenOwner() failed (Status 0x%08lx)\n", Status);
1549         goto done;
1550     }
1551 
1552     Status = LsapAddTokenDefaultDacl(TokenInformation,
1553                                      TokenInformationType);
1554     if (!NT_SUCCESS(Status))
1555     {
1556         ERR("LsapAddTokenDefaultDacl() failed (Status 0x%08lx)\n", Status);
1557         goto done;
1558     }
1559 
1560     Status = LsapSetPrivileges(TokenInformation,
1561                                TokenInformationType);
1562     if (!NT_SUCCESS(Status))
1563     {
1564         ERR("LsapSetPrivileges() failed (Status 0x%08lx)\n", Status);
1565         goto done;
1566     }
1567 
1568     if (TokenInformationType == LsaTokenInformationNull)
1569     {
1570         TOKEN_USER TokenUser;
1571         TOKEN_PRIMARY_GROUP TokenPrimaryGroup;
1572         TOKEN_GROUPS NoGroups = {0};
1573         TOKEN_PRIVILEGES NoPrivileges = {0};
1574 
1575         TokenInfo0 = (PLSA_TOKEN_INFORMATION_NULL)TokenInformation;
1576 
1577         TokenUser.User.Sid = LsapWorldSid;
1578         TokenUser.User.Attributes = 0;
1579         TokenPrimaryGroup.PrimaryGroup = LsapWorldSid;
1580 
1581         Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
1582         Qos.ImpersonationLevel = SecurityImpersonation;
1583         Qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
1584         Qos.EffectiveOnly = TRUE;
1585 
1586         ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
1587         ObjectAttributes.RootDirectory = NULL;
1588         ObjectAttributes.ObjectName = NULL;
1589         ObjectAttributes.Attributes = 0;
1590         ObjectAttributes.SecurityDescriptor = NULL;
1591         ObjectAttributes.SecurityQualityOfService = &Qos;
1592 
1593         /* Create the logon token */
1594         Status = NtCreateToken(&TokenHandle,
1595                                TOKEN_ALL_ACCESS,
1596                                &ObjectAttributes,
1597                                TokenImpersonation,
1598                                &RequestMsg->LogonUser.Reply.LogonId,
1599                                &TokenInfo0->ExpirationTime,
1600                                &TokenUser,
1601                                &NoGroups,
1602                                &NoPrivileges,
1603                                NULL,
1604                                &TokenPrimaryGroup,
1605                                NULL,
1606                                &RequestMsg->LogonUser.Request.SourceContext);
1607     }
1608     else if (TokenInformationType == LsaTokenInformationV1)
1609     {
1610         TOKEN_PRIVILEGES NoPrivileges = {0};
1611 
1612         TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1613 
1614         Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
1615         Qos.ImpersonationLevel = SecurityImpersonation;
1616         Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
1617         Qos.EffectiveOnly = FALSE;
1618 
1619         ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
1620         ObjectAttributes.RootDirectory = NULL;
1621         ObjectAttributes.ObjectName = NULL;
1622         ObjectAttributes.Attributes = 0;
1623         ObjectAttributes.SecurityDescriptor = NULL;
1624         ObjectAttributes.SecurityQualityOfService = &Qos;
1625 
1626         /* Create the logon token */
1627         Status = NtCreateToken(&TokenHandle,
1628                                TOKEN_ALL_ACCESS,
1629                                &ObjectAttributes,
1630                                (RequestMsg->LogonUser.Request.LogonType == Network) ? TokenImpersonation : TokenPrimary,
1631                                &RequestMsg->LogonUser.Reply.LogonId,
1632                                &TokenInfo1->ExpirationTime,
1633                                &TokenInfo1->User,
1634                                TokenInfo1->Groups,
1635                                TokenInfo1->Privileges ? TokenInfo1->Privileges : &NoPrivileges,
1636                                &TokenInfo1->Owner,
1637                                &TokenInfo1->PrimaryGroup,
1638                                &TokenInfo1->DefaultDacl,
1639                                &RequestMsg->LogonUser.Request.SourceContext);
1640         if (!NT_SUCCESS(Status))
1641         {
1642             ERR("NtCreateToken failed (Status 0x%08lx)\n", Status);
1643             goto done;
1644         }
1645     }
1646     else
1647     {
1648         FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
1649         Status = STATUS_NOT_IMPLEMENTED;
1650         goto done;
1651     }
1652 
1653     if (LogonType == Interactive ||
1654         LogonType == Batch ||
1655         LogonType == Service)
1656     {
1657         UserName = &((PMSV1_0_INTERACTIVE_LOGON)LocalAuthInfo)->UserName;
1658         LogonDomainName = &((PMSV1_0_INTERACTIVE_LOGON)LocalAuthInfo)->LogonDomainName;
1659     }
1660     else
1661     {
1662         FIXME("LogonType %lu is not supported yet!\n", LogonType);
1663     }
1664 
1665     Status = LsapSetLogonSessionData(&RequestMsg->LogonUser.Reply.LogonId,
1666                                      LogonType,
1667                                      UserName,
1668                                      LogonDomainName,
1669                                      TokenInfo1->User.User.Sid);
1670     if (!NT_SUCCESS(Status))
1671     {
1672         ERR("LsapSetLogonSessionData failed (Status 0x%08lx)\n", Status);
1673         goto done;
1674     }
1675 
1676     /*
1677      * Duplicate the token handle into the client process.
1678      * This must be the last step because we cannot
1679      * close the duplicated token handle in case something fails.
1680      */
1681     Status = NtDuplicateObject(NtCurrentProcess(),
1682                                TokenHandle,
1683                                LogonContext->ClientProcessHandle,
1684                                &RequestMsg->LogonUser.Reply.Token,
1685                                0,
1686                                0,
1687                                DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_CLOSE_SOURCE);
1688     if (!NT_SUCCESS(Status))
1689     {
1690         ERR("NtDuplicateObject failed (Status 0x%08lx)\n", Status);
1691         goto done;
1692     }
1693 
1694 done:
1695     if (!NT_SUCCESS(Status))
1696     {
1697         /* Notify the authentification package of the failure */
1698         Package->LsaApLogonTerminated(&RequestMsg->LogonUser.Reply.LogonId);
1699 
1700         /* Delete the logon session */
1701         LsapDeleteLogonSession(&RequestMsg->LogonUser.Reply.LogonId);
1702 
1703         /* Release the profile buffer */
1704         LsapFreeClientBuffer((PLSA_CLIENT_REQUEST)LogonContext,
1705                              RequestMsg->LogonUser.Reply.ProfileBuffer);
1706         RequestMsg->LogonUser.Reply.ProfileBuffer = NULL;
1707     }
1708 
1709     if (TokenHandle != NULL)
1710         NtClose(TokenHandle);
1711 
1712     /* Free the local groups */
1713     if (LocalGroups != NULL)
1714     {
1715         for (i = 0; i < LocalGroups->GroupCount; i++)
1716         {
1717             if (LocalGroups->Groups[i].Sid != NULL)
1718                 RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
1719         }
1720 
1721         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
1722     }
1723 
1724     /* Free the local authentication info buffer */
1725     if (LocalAuthInfo != NULL)
1726         RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
1727 
1728     /* Free the token information */
1729     if (TokenInformation != NULL)
1730     {
1731         if (TokenInformationType == LsaTokenInformationNull)
1732         {
1733             TokenInfo0 = (PLSA_TOKEN_INFORMATION_NULL)TokenInformation;
1734 
1735             if (TokenInfo0 != NULL)
1736             {
1737                 if (TokenInfo0->Groups != NULL)
1738                 {
1739                     for (i = 0; i < TokenInfo0->Groups->GroupCount; i++)
1740                     {
1741                         if (TokenInfo0->Groups->Groups[i].Sid != NULL)
1742                             LsapFreeHeap(TokenInfo0->Groups->Groups[i].Sid);
1743                     }
1744 
1745                     LsapFreeHeap(TokenInfo0->Groups);
1746                 }
1747 
1748                 LsapFreeHeap(TokenInfo0);
1749             }
1750         }
1751         else if (TokenInformationType == LsaTokenInformationV1)
1752         {
1753             TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
1754 
1755             if (TokenInfo1 != NULL)
1756             {
1757                 if (TokenInfo1->User.User.Sid != NULL)
1758                     LsapFreeHeap(TokenInfo1->User.User.Sid);
1759 
1760                 if (TokenInfo1->Groups != NULL)
1761                 {
1762                     for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
1763                     {
1764                         if (TokenInfo1->Groups->Groups[i].Sid != NULL)
1765                             LsapFreeHeap(TokenInfo1->Groups->Groups[i].Sid);
1766                     }
1767 
1768                     LsapFreeHeap(TokenInfo1->Groups);
1769                 }
1770 
1771                 if (TokenInfo1->PrimaryGroup.PrimaryGroup != NULL)
1772                     LsapFreeHeap(TokenInfo1->PrimaryGroup.PrimaryGroup);
1773 
1774                 if (TokenInfo1->Privileges != NULL)
1775                     LsapFreeHeap(TokenInfo1->Privileges);
1776 
1777                 if (TokenInfo1->Owner.Owner != NULL)
1778                     LsapFreeHeap(TokenInfo1->Owner.Owner);
1779 
1780                 if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
1781                     LsapFreeHeap(TokenInfo1->DefaultDacl.DefaultDacl);
1782 
1783                 LsapFreeHeap(TokenInfo1);
1784             }
1785         }
1786         else
1787         {
1788             FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
1789         }
1790     }
1791 
1792     /* Free the account name */
1793     if (AccountName != NULL)
1794     {
1795         if (AccountName->Buffer != NULL)
1796             LsapFreeHeap(AccountName->Buffer);
1797 
1798         LsapFreeHeap(AccountName);
1799     }
1800 
1801     /* Free the authentication authority */
1802     if (AuthenticatingAuthority != NULL)
1803     {
1804         if (AuthenticatingAuthority->Buffer != NULL)
1805             LsapFreeHeap(AuthenticatingAuthority->Buffer);
1806 
1807         LsapFreeHeap(AuthenticatingAuthority);
1808     }
1809 
1810     /* Free the machine name */
1811     if (MachineName != NULL)
1812     {
1813         if (MachineName->Buffer != NULL)
1814             LsapFreeHeap(MachineName->Buffer);
1815 
1816         LsapFreeHeap(MachineName);
1817     }
1818 
1819     TRACE("LsapLogonUser done (Status 0x%08lx)\n", Status);
1820 
1821     return Status;
1822 }
1823 
1824 /* EOF */
1825