OSDN Git Service

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