OSDN Git Service

* cyglsa.c: Include ntddk.h again, but only if __MINGW32__ is defined.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / lsaauth / cyglsa.c
1 /* cyglsa.c: LSA authentication module for Cygwin
2
3    Copyright 2006, 2008 Red Hat, Inc.
4
5    Written by Corinna Vinschen <corinna@vinschen.de>
6
7 This file is part of Cygwin.
8
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for details. */
11
12 #define WINVER 0x0600
13 #define _CRT_SECURE_NO_DEPRECATE
14 #include <ntstatus.h>
15 #define WIN32_NO_STATUS
16 #include <wchar.h>
17 #include <windows.h>
18 #include <wininet.h>
19 #include <lm.h>
20 #include <iptypes.h>
21 #include <ntsecapi.h>
22 #ifdef __MINGW32__
23 #include <ntddk.h>
24 #endif
25 #include "../cygwin/cyglsa.h"
26 #include "../cygwin/include/cygwin/version.h"
27
28 static PLSA_SECPKG_FUNCS funcs;
29 static BOOL must_create_logon_sid;
30
31 BOOL APIENTRY
32 DllMain (HINSTANCE inst, DWORD reason, LPVOID res)
33 {
34   switch (reason)
35     {
36       case DLL_PROCESS_ATTACH:
37       case DLL_THREAD_ATTACH:
38       case DLL_THREAD_DETACH:
39       case DLL_PROCESS_DETACH:
40         break;
41     }
42   return TRUE;
43 }
44
45 #ifndef RtlInitEmptyUnicodeString
46 __inline VOID NTAPI
47 RtlInitEmptyUnicodeString(PUNICODE_STRING dest, PCWSTR buf, USHORT len)
48 {
49   dest->Length = 0;
50   dest->MaximumLength = len;
51   dest->Buffer = (PWSTR) buf;
52 }
53 #endif
54
55 static PUNICODE_STRING
56 uni_alloc (PWCHAR src, USHORT len)
57 {
58   PUNICODE_STRING tgt;
59
60   if (!(tgt = funcs->AllocateLsaHeap (sizeof (UNICODE_STRING))))
61     return NULL;
62   tgt->Length = len * sizeof (WCHAR);
63   tgt->MaximumLength = tgt->Length + sizeof (WCHAR);
64   if (!(tgt->Buffer = funcs->AllocateLsaHeap (tgt->MaximumLength)))
65     {
66       funcs->FreeLsaHeap (tgt);
67       return NULL;
68     }
69   wcscpy (tgt->Buffer, src);
70   return tgt;
71 }
72
73 /* No, I don't want to include stdio.h so I take what ntdll offers. */
74 extern int _vsnprintf (char *, size_t, const char *, va_list);
75
76 static HANDLE fh = INVALID_HANDLE_VALUE;
77
78 static int
79 printf (const char *format, ...)
80 {
81   char buf[256];
82   DWORD wr;
83   int ret;
84   va_list ap;
85
86   if (fh == INVALID_HANDLE_VALUE)
87     return 0;
88
89   va_start (ap, format);
90   ret = _vsnprintf (buf, 256, format, ap);
91   va_end (ap);
92   if (ret <= 0)
93     return ret;
94   if (ret > 256)
95     ret = 255;
96   buf[255] = '\0';
97   WriteFile (fh, buf, ret, &wr, NULL);
98   return wr;
99 }
100
101 static void
102 print_sid (const char *prefix, int idx, PISID sid)
103 {
104   DWORD i;
105
106   printf ("%s", prefix);
107   if (idx >= 0)
108     printf ("[%d] ", idx);
109   printf ("(0x%08x) ", (INT_PTR) sid);
110   if (!sid)
111     printf ("NULL\n");
112   else if (IsBadReadPtr (sid, 8))
113     printf ("INVALID POINTER\n");
114   else if (!IsValidSid ((PSID) sid))
115     printf ("INVALID SID\n");
116   else if (IsBadReadPtr (sid, 8 + sizeof (DWORD) * sid->SubAuthorityCount))
117     printf ("INVALID POINTER SPACE\n");
118   else
119     {
120       printf ("S-%d-%d", sid->Revision, sid->IdentifierAuthority.Value[5]);
121       for (i = 0; i < sid->SubAuthorityCount; ++i)
122         printf ("-%lu", sid->SubAuthority[i]);
123       printf ("\n");
124     }
125 }
126
127 static void
128 print_groups (PTOKEN_GROUPS grps)
129 {
130   DWORD i;
131
132   printf ("Groups: (0x%08x) ", (INT_PTR) grps);
133   if (!grps)
134     printf ("NULL\n");
135   else if (IsBadReadPtr (grps, sizeof (DWORD)))
136     printf ("INVALID POINTER\n");
137   else if (IsBadReadPtr (grps, sizeof (DWORD) + sizeof (SID_AND_ATTRIBUTES)
138                                                 * grps->GroupCount))
139     printf ("INVALID POINTER SPACE\n");
140   else
141     {
142       printf ("Count: %lu\n", grps->GroupCount);
143       for (i = 0; i < grps->GroupCount; ++i)
144         {
145           printf ("(attr: 0x%lx)", grps->Groups[i].Attributes);
146           print_sid (" ", i, (PISID) grps->Groups[i].Sid);
147         }
148     }
149 }
150
151 static void
152 print_privs (PTOKEN_PRIVILEGES privs)
153 {
154   DWORD i;
155
156   printf ("Privileges: (0x%08x) ", (INT_PTR) privs);
157   if (!privs)
158     printf ("NULL\n");
159   else if (IsBadReadPtr (privs, sizeof (DWORD)))
160     printf ("INVALID POINTER\n");
161   else if (IsBadReadPtr (privs, sizeof (DWORD) + sizeof (LUID_AND_ATTRIBUTES)
162                                                  * privs->PrivilegeCount))
163     printf ("INVALID POINTER SPACE\n");
164   else
165     {
166       printf ("Count: %lu\n", privs->PrivilegeCount);
167       for (i = 0; i < privs->PrivilegeCount; ++i)
168         printf ("Luid: {%ld, %lu} Attributes: 0x%lx\n",
169                 privs->Privileges[i].Luid.HighPart,
170                 privs->Privileges[i].Luid.LowPart,
171                 privs->Privileges[i].Attributes);
172     }
173 }
174
175 static void
176 print_dacl (PACL dacl)
177 {
178   DWORD i;
179
180   printf ("DefaultDacl: (0x%08x) ", (INT_PTR) dacl);
181   if (!dacl)
182     printf ("NULL\n");
183   else if (IsBadReadPtr (dacl, sizeof (ACL)))
184     printf ("INVALID POINTER\n");
185   else if (IsBadReadPtr (dacl, dacl->AclSize))
186     printf ("INVALID POINTER SPACE\n");
187   else
188     {
189       printf ("Rev: %d, Count: %d\n", dacl->AclRevision, dacl->AceCount);
190       for (i = 0; i < dacl->AceCount; ++i)
191         {
192           PVOID vace;
193           PACCESS_ALLOWED_ACE ace;
194
195           if (!GetAce (dacl, i, &vace))
196             printf ("[%lu] GetAce error %lu\n", i, GetLastError ());
197           else
198             {
199               ace = (PACCESS_ALLOWED_ACE) vace;
200               printf ("Type: %x, Flags: %x, Access: %lx,",
201                       ace->Header.AceType, ace->Header.AceFlags, (DWORD) ace->Mask);
202               print_sid (" ", i, (PISID) &ace->SidStart);
203             }
204         }
205     }
206 }
207
208 static void
209 print_tokinf (PLSA_TOKEN_INFORMATION_V2 ptok, size_t size,
210                PVOID got_start, PVOID gotinf_start, PVOID gotinf_end)
211 {
212   if (fh == INVALID_HANDLE_VALUE)
213     return;
214
215   printf ("INCOMING: start: 0x%08x infstart: 0x%08x infend: 0x%08x\n",
216           (INT_PTR) got_start, (INT_PTR) gotinf_start,
217           (INT_PTR) gotinf_end);
218
219   printf ("LSA_TOKEN_INFORMATION_V2: 0x%08x - 0x%08x\n",
220           (INT_PTR) ptok, (INT_PTR) ptok + size);
221
222   /* User SID */
223   printf ("User: (attr: 0x%lx)", ptok->User.User.Attributes);
224   print_sid (" ", -1, (PISID) ptok->User.User.Sid);
225
226   /* Groups */
227   print_groups (ptok->Groups);
228
229   /* Primary Group SID */
230   print_sid ("Primary Group: ", -1, (PISID)ptok->PrimaryGroup.PrimaryGroup);
231
232   /* Privileges */
233   print_privs (ptok->Privileges);
234
235   /* Owner */
236   print_sid ("Owner: ", -1, (PISID) ptok->Owner.Owner);
237
238   /* Default DACL */
239   print_dacl (ptok->DefaultDacl.DefaultDacl);
240
241   // CloseHandle (fh);
242 }
243
244 NTSTATUS NTAPI
245 LsaApInitializePackage (ULONG authp_id, PLSA_SECPKG_FUNCS dpt,
246                         PLSA_STRING dummy1, PLSA_STRING dummy2,
247                         PLSA_STRING *authp_name)
248 {
249   PLSA_STRING name = NULL;
250   DWORD vers, major, minor;
251
252   /* Set global pointer to lsa helper function table. */
253   funcs = dpt;
254
255   /* Allocate and set the name of the authentication package.  This is the
256      name which has to be used in LsaLookupAuthenticationPackage. */
257   if (!(name = funcs->AllocateLsaHeap (sizeof *name)))
258     return STATUS_NO_MEMORY;
259   if (!(name->Buffer = funcs->AllocateLsaHeap (sizeof (CYG_LSA_PKGNAME))))
260     {
261       funcs->FreeLsaHeap (name);
262       return STATUS_NO_MEMORY;
263     }
264   name->Length = sizeof (CYG_LSA_PKGNAME) - 1;
265   name->MaximumLength = sizeof (CYG_LSA_PKGNAME);
266   strcpy (name->Buffer, CYG_LSA_PKGNAME);
267   (*authp_name) = name;
268
269   vers = GetVersion ();
270   major = LOBYTE (LOWORD (vers));
271   minor = HIBYTE (LOWORD (vers));
272   /* Check if we're running on Windows 2000 or lower.  If so, we must create
273      the logon sid in the group list by ourselves. */
274   if (major < 5 || (major == 5 && minor == 0))
275     must_create_logon_sid = TRUE;
276
277 #ifdef DEBUGGING
278   fh = CreateFile ("C:\\cyglsa.dbgout", GENERIC_WRITE,
279                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
280                    NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
281   printf ("Initialized\n");
282 #endif /* DEBUGGING */
283
284   return STATUS_SUCCESS;
285 }
286
287 NTSTATUS NTAPI
288 LsaApLogonUserEx (PLSA_CLIENT_REQUEST request, SECURITY_LOGON_TYPE logon_type,
289                   PVOID auth, PVOID client_auth_base, ULONG auth_len,
290                   PVOID *pbuf, PULONG pbuf_len, PLUID logon_id,
291                   PNTSTATUS sub_stat, PLSA_TOKEN_INFORMATION_TYPE tok_type,
292                   PVOID *tok, PUNICODE_STRING *account,
293                   PUNICODE_STRING *authority, PUNICODE_STRING *machine)
294 {
295   DWORD checksum, i;
296   PDWORD csp, csp_end;
297   NTSTATUS stat;
298   SECPKG_CLIENT_INFO clinf;
299   PLSA_TOKEN_INFORMATION_V2 tokinf;
300
301   cyglsa_t *authinf = (cyglsa_t *) auth;
302
303   /* Check if the caller has the SeTcbPrivilege, otherwise refuse service. */
304   stat = funcs->GetClientInfo (&clinf);
305   if (stat != STATUS_SUCCESS)
306     {
307       printf ("GetClientInfo failed: 0x%08lx\n", stat);
308       return stat;
309     }
310   if (!clinf.HasTcbPrivilege)
311     {
312       printf ("Client has no TCB privilege.  Access denied.\n");
313       return STATUS_ACCESS_DENIED;
314     }
315
316   /* Make a couple of validity checks. */
317   if (auth_len < sizeof *authinf
318       || authinf->magic != CYG_LSA_MAGIC
319       || !authinf->username[0]
320       || !authinf->domain[0])
321     {
322       printf ("Invalid authentication parameter.\n");
323       return STATUS_INVALID_PARAMETER;
324     }
325   checksum = CYGWIN_VERSION_MAGIC (CYGWIN_VERSION_DLL_MAJOR,
326                                    CYGWIN_VERSION_DLL_MINOR);
327   csp = (PDWORD) &authinf->username;
328   csp_end = (PDWORD) ((PBYTE) authinf + auth_len);
329   while (csp < csp_end)
330     checksum += *csp++;
331   if (authinf->checksum != checksum)
332     {
333       printf ("Invalid checksum.\n");
334       return STATUS_INVALID_PARAMETER_3;
335     }
336
337   /* Set account to username and authority to domain resp. machine name.
338      The name of the logon account name as returned by LookupAccountSid
339      is created from here as "authority\account". */
340   authinf->username[UNLEN] = '\0';
341   authinf->domain[MAX_DOMAIN_NAME_LEN] = '\0';
342   if (account && !(*account = uni_alloc (authinf->username,
343                                          wcslen (authinf->username))))
344     {
345       printf ("No memory trying to create account.\n");
346       return STATUS_NO_MEMORY;
347     }
348   if (authority && !(*authority = uni_alloc (authinf->domain,
349                                              wcslen (authinf->domain))))
350     {
351       printf ("No memory trying to create authority.\n");
352       return STATUS_NO_MEMORY;
353     }
354   if (machine)
355     {
356       WCHAR mach[MAX_COMPUTERNAME_LENGTH + 1];
357       DWORD msize = MAX_COMPUTERNAME_LENGTH + 1;
358       if (!GetComputerNameW (mach, &msize))
359         wcscpy (mach, L"UNKNOWN");
360       if (!(*machine = uni_alloc (mach, wcslen (mach))))
361         {
362           printf ("No memory trying to create machine.\n");
363           return STATUS_NO_MEMORY;
364         }
365     }
366   /* Create a fake buffer in pbuf which is free'd again in the client.
367      Windows 2000 tends to crash when setting this pointer to NULL. */
368   if (pbuf)
369     {
370 #ifdef JUST_ANOTHER_NONWORKING_SOLUTION
371       cygprf_t prf;
372       WCHAR sam_username[MAX_DOMAIN_NAME_LEN + UNLEN + 2];
373       SECURITY_STRING sam_user, prefix;
374       PUCHAR user_auth;
375       ULONG user_auth_size;
376       WCHAR flatname[UNLEN + 1];
377       UNICODE_STRING flatnm;
378       TOKEN_SOURCE ts;
379       HANDLE token;
380 #endif /* JUST_ANOTHER_NONWORKING_SOLUTION */
381
382       stat = funcs->AllocateClientBuffer (request, 64UL, pbuf);
383       if (!LSA_SUCCESS (stat))
384         {
385           printf ("AllocateClientBuffer failed: 0x%08lx\n", stat);
386           return stat;
387         }
388 #ifdef JUST_ANOTHER_NONWORKING_SOLUTION
389       prf.magic_pre = MAGIC_PRE;
390       prf.token = NULL;
391       prf.magic_post = MAGIC_POST;
392
393 #if 0
394       /* That's how it was supposed to work according to MSDN... */
395       wcscpy (sam_username, authinf->domain);
396       wcscat (sam_username, L"\\");
397       wcscat (sam_username, authinf->username);
398 #else
399       /* That's the only solution which worked, and then it only worked
400          for machine local accounts.  No domain authentication possible.
401          STATUS_NO_SUCH_USER galore! */
402       wcscpy (sam_username, authinf->username);
403 #endif
404       RtlInitUnicodeString (&sam_user, sam_username);
405       RtlInitUnicodeString (&prefix, L"");
406       RtlInitEmptyUnicodeString (&flatnm, flatname,
407                                  (UNLEN + 1) * sizeof (WCHAR));
408
409       stat = funcs->GetAuthDataForUser (&sam_user, SecNameSamCompatible,
410                                         NULL, &user_auth,
411                                         &user_auth_size, &flatnm);
412       if (!NT_SUCCESS (stat))
413         {
414           char sam_u[MAX_DOMAIN_NAME_LEN + UNLEN + 2];
415           wcstombs (sam_u, sam_user.Buffer, sizeof (sam_u));
416           printf ("GetAuthDataForUser (%u,%u,%s) failed: 0x%08lx\n",
417                   sam_user.Length, sam_user.MaximumLength, sam_u, stat);
418           return stat;
419         }
420
421       memcpy (ts.SourceName, "Cygwin.1", 8);
422       ts.SourceIdentifier.HighPart = 0;
423       ts.SourceIdentifier.LowPart = 0x0104;
424       RtlInitEmptyUnicodeString (&flatnm, flatname,
425                                  (UNLEN + 1) * sizeof (WCHAR));
426       stat = funcs->ConvertAuthDataToToken (user_auth, user_auth_size,
427                                             SecurityDelegation, &ts,
428                                             Interactive, *authority,
429                                             &token, logon_id, &flatnm,
430                                             sub_stat);
431       if (!NT_SUCCESS (stat))
432         {
433           printf ("ConvertAuthDataToToken failed: 0x%08lx\n", stat);
434           return stat;
435         }
436
437       stat = funcs->DuplicateHandle (token, &prf.token);
438       if (!NT_SUCCESS (stat))
439         {
440           printf ("DuplicateHandle failed: 0x%08lx\n", stat);
441           return stat;
442         }
443       
444       stat = funcs->CopyToClientBuffer (request, sizeof prf, *pbuf, &prf);
445       if (!NT_SUCCESS (stat))
446         {
447           printf ("CopyToClientBuffer failed: 0x%08lx\n", stat);
448           return stat;
449         }
450       funcs->FreeLsaHeap (user_auth);
451 #endif /* JUST_ANOTHER_NONWORKING_SOLUTION */
452     }
453   if (pbuf_len)
454     *pbuf_len = 64UL;
455
456   /* A PLSA_TOKEN_INFORMATION_V2 is allocated in one piece, so... */
457 #if defined (__x86_64__) || defined (_M_AMD64)
458     {
459       /* ...on 64 bit systems we have to convert the incoming 32 bit offsets
460          into 64 bit pointers.  That requires to re-evaluate the size of the
461          outgoing tokinf structure and a somewhat awkward procedure to copy
462          the information over. */
463       LONG_PTR base;
464       PBYTE tptr;
465       DWORD size, newsize;
466       PSID src_sid;
467       PCYG_TOKEN_GROUPS src_grps;
468       PTOKEN_GROUPS grps;
469       PTOKEN_PRIVILEGES src_privs;
470       PACL src_acl;
471
472       base = (LONG_PTR) &authinf->inf;
473
474       newsize = authinf->inf_size;
475       newsize += sizeof (TOKEN_USER) - sizeof (CYG_TOKEN_USER); /* User SID */
476       newsize += sizeof (PTOKEN_GROUPS) - sizeof (OFFSET); /* Groups */
477       src_grps = (PCYG_TOKEN_GROUPS) (base + authinf->inf.Groups);
478       newsize += src_grps->GroupCount             /* Group SIDs */
479                  * (sizeof (SID_AND_ATTRIBUTES)
480                     - sizeof (CYG_SID_AND_ATTRIBUTES));
481       newsize += sizeof (PSID) - sizeof (OFFSET); /* Primary Group SID */
482       newsize += sizeof (PTOKEN_PRIVILEGES) - sizeof (OFFSET); /* Privileges */
483       newsize += 0; /* Owner SID */
484       newsize += sizeof (PACL) - sizeof (OFFSET); /* Default DACL */
485
486       if (!(tokinf = funcs->AllocateLsaHeap (newsize)))
487         return STATUS_NO_MEMORY;
488       tptr = (PBYTE)(tokinf + 1);
489
490       tokinf->ExpirationTime = authinf->inf.ExpirationTime;
491       /* User SID */
492       src_sid = (PSID) (base + authinf->inf.User.User.Sid);
493       size = GetLengthSid (src_sid);
494       CopySid (size, (PSID) tptr, src_sid);
495       tokinf->User.User.Sid = (PSID) tptr;
496       tptr += size;
497       tokinf->User.User.Attributes = authinf->inf.User.User.Attributes;
498       /* Groups */
499       grps = (PTOKEN_GROUPS) tptr;
500       tokinf->Groups = grps;
501       grps->GroupCount = src_grps->GroupCount;
502       tptr += sizeof grps->GroupCount
503               + grps->GroupCount * sizeof (SID_AND_ATTRIBUTES);
504       /* Group SIDs */
505       for (i = 0; i < src_grps->GroupCount; ++i)
506         {
507           src_sid = (PSID) (base + src_grps->Groups[i].Sid);
508           size = GetLengthSid (src_sid);
509           CopySid (size, (PSID) tptr, src_sid);
510           tokinf->Groups->Groups[i].Sid = (PSID) tptr;
511           tptr += size;
512           tokinf->Groups->Groups[i].Attributes = src_grps->Groups[i].Attributes;
513         }
514       /* Primary Group SID */
515       src_sid = (PSID) (base + authinf->inf.PrimaryGroup.PrimaryGroup);
516       size = GetLengthSid (src_sid);
517       CopySid (size, (PSID) tptr, src_sid);
518       tokinf->PrimaryGroup.PrimaryGroup = (PSID) tptr;
519       tptr += size;
520       /* Privileges */
521       src_privs = (PTOKEN_PRIVILEGES) (base + authinf->inf.Privileges);
522       size = sizeof src_privs->PrivilegeCount
523              + src_privs->PrivilegeCount * sizeof (LUID_AND_ATTRIBUTES);
524       memcpy (tptr, src_privs, size);
525       tokinf->Privileges = (PTOKEN_PRIVILEGES) tptr;
526       tptr += size;
527       /* Owner */
528       tokinf->Owner.Owner = NULL;
529       /* Default DACL */
530       src_acl = (PACL) (base + authinf->inf.DefaultDacl.DefaultDacl);
531       size = src_acl->AclSize;
532       memcpy (tptr, src_acl, size);
533       tokinf->DefaultDacl.DefaultDacl = (PACL) tptr;
534     }
535 #else
536     {
537       /* ...on 32 bit systems we just allocate tokinf with the same size as
538          we get, copy the whole structure and convert offsets into pointers. */
539
540       /* Allocate LUID for usage in the logon SID on Windows 2000.  This is
541          not done in the 64 bit code above for hopefully obvious reasons... */
542       LUID logon_sid_id;
543
544       if (must_create_logon_sid && !AllocateLocallyUniqueId (&logon_sid_id))
545         return STATUS_INSUFFICIENT_RESOURCES;
546
547       if (!(tokinf = funcs->AllocateLsaHeap (authinf->inf_size)))
548         return STATUS_NO_MEMORY;
549       memcpy (tokinf, &authinf->inf, authinf->inf_size);
550
551       /* User SID */
552       tokinf->User.User.Sid = (PSID)
553               ((PBYTE) tokinf + (LONG_PTR) tokinf->User.User.Sid);
554       /* Groups */
555       tokinf->Groups = (PTOKEN_GROUPS)
556               ((PBYTE) tokinf + (LONG_PTR) tokinf->Groups);
557       /* Group SIDs */
558       for (i = 0; i < tokinf->Groups->GroupCount; ++i)
559         {
560           tokinf->Groups->Groups[i].Sid = (PSID)
561                 ((PBYTE) tokinf + (LONG_PTR) tokinf->Groups->Groups[i].Sid);
562           if (must_create_logon_sid
563               && tokinf->Groups->Groups[i].Attributes & SE_GROUP_LOGON_ID
564               && *GetSidSubAuthorityCount (tokinf->Groups->Groups[i].Sid) == 3
565               && *GetSidSubAuthority (tokinf->Groups->Groups[i].Sid, 0)
566                  == SECURITY_LOGON_IDS_RID)
567             {
568               *GetSidSubAuthority (tokinf->Groups->Groups[i].Sid, 1)
569               = logon_sid_id.HighPart;
570               *GetSidSubAuthority (tokinf->Groups->Groups[i].Sid, 2)
571               = logon_sid_id.LowPart;
572             }
573         }
574
575       /* Primary Group SID */
576       tokinf->PrimaryGroup.PrimaryGroup = (PSID)
577               ((PBYTE) tokinf + (LONG_PTR) tokinf->PrimaryGroup.PrimaryGroup);
578       /* Privileges */
579       tokinf->Privileges = (PTOKEN_PRIVILEGES)
580               ((PBYTE) tokinf + (LONG_PTR) tokinf->Privileges);
581       /* Owner SID */
582       tokinf->Owner.Owner = NULL;
583       /* Default DACL */
584       tokinf->DefaultDacl.DefaultDacl = (PACL)
585               ((PBYTE) tokinf + (LONG_PTR) tokinf->DefaultDacl.DefaultDacl);
586
587     }
588 #endif
589
590   *tok = (PVOID) tokinf;
591   *tok_type = LsaTokenInformationV2;
592
593   print_tokinf (tokinf, authinf->inf_size, authinf, &authinf->inf,
594                 (PVOID)((LONG_PTR) &authinf->inf + authinf->inf_size));
595
596   /* Create logon session. */
597   if (!AllocateLocallyUniqueId (logon_id))
598     {
599       funcs->FreeLsaHeap (*tok);
600       *tok = NULL;
601       printf ("AllocateLocallyUniqueId failed: Win32 error %lu\n",
602               GetLastError ());
603       return STATUS_INSUFFICIENT_RESOURCES;
604     }
605   stat = funcs->CreateLogonSession (logon_id);
606   if (stat != STATUS_SUCCESS)
607     {
608       funcs->FreeLsaHeap (*tok);
609       *tok = NULL;
610       printf ("CreateLogonSession failed: 0x%08lx\n", stat);
611       return stat;
612     }
613
614   printf ("BINGO!!!\n", stat);
615   return STATUS_SUCCESS;
616 }
617
618 VOID NTAPI
619 LsaApLogonTerminated(PLUID LogonId)
620 {
621 }
622
623 NTSTATUS NTAPI
624 LsaApCallPackage (PLSA_CLIENT_REQUEST request, PVOID authinf,
625                   PVOID client_auth_base, ULONG auth_len, PVOID *ret_buf,
626                   PULONG ret_buf_len, PNTSTATUS ret_stat) 
627 {
628   return STATUS_NOT_IMPLEMENTED;
629 }