xref: /reactos/dll/win32/msv1_0/msv1_0.c (revision dbad45a2)
1 /*
2  * PROJECT:     Authentication Package DLL
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        dll/win32/msv1_0/msv1_0.c
5  * PURPOSE:     Main file
6  * COPYRIGHT:   Copyright 2013 Eric Kohl
7  */
8 
9 /* INCLUDES ****************************************************************/
10 
11 #include "precomp.h"
12 
13 WINE_DEFAULT_DEBUG_CHANNEL(msv1_0);
14 
15 typedef struct _LOGON_LIST_ENTRY
16 {
17     LIST_ENTRY ListEntry;
18     LUID LogonId;
19     ULONG EnumHandle;
20 } LOGON_LIST_ENTRY, *PLOGON_LIST_ENTRY;
21 
22 /* GLOBALS *****************************************************************/
23 
24 BOOL PackageInitialized = FALSE;
25 LIST_ENTRY LogonListHead;
26 ULONG EnumCounter;
27 
28 /* FUNCTIONS ***************************************************************/
29 
30 static
31 NTSTATUS
BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,IN PSAMPR_USER_INFO_BUFFER UserInfo,IN PWSTR ComputerName,OUT PMSV1_0_INTERACTIVE_PROFILE * ProfileBuffer,OUT PULONG ProfileBufferLength)32 BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
33                               IN PSAMPR_USER_INFO_BUFFER UserInfo,
34                               IN PWSTR ComputerName,
35                               OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
36                               OUT PULONG ProfileBufferLength)
37 {
38     PMSV1_0_INTERACTIVE_PROFILE LocalBuffer = NULL;
39     PVOID ClientBaseAddress = NULL;
40     LPWSTR Ptr;
41     ULONG BufferLength;
42     USHORT ComputerNameLength;
43     NTSTATUS Status = STATUS_SUCCESS;
44 
45     *ProfileBuffer = NULL;
46     *ProfileBufferLength = 0;
47 
48     if (UIntPtrToUShort(wcslen(ComputerName), &ComputerNameLength) != S_OK)
49     {
50         return STATUS_INVALID_PARAMETER;
51     }
52 
53     BufferLength = sizeof(MSV1_0_INTERACTIVE_PROFILE) +
54                    UserInfo->All.FullName.Length + sizeof(WCHAR) +
55                    UserInfo->All.HomeDirectory.Length + sizeof(WCHAR) +
56                    UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR) +
57                    UserInfo->All.ScriptPath.Length + sizeof(WCHAR) +
58                    UserInfo->All.ProfilePath.Length + sizeof(WCHAR) +
59                    ((ComputerNameLength + 3) * sizeof(WCHAR));
60 
61     LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
62     if (LocalBuffer == NULL)
63     {
64         TRACE("Failed to allocate the local buffer!\n");
65         Status = STATUS_INSUFFICIENT_RESOURCES;
66         goto done;
67     }
68 
69     Status = DispatchTable.AllocateClientBuffer(ClientRequest,
70                                                 BufferLength,
71                                                 &ClientBaseAddress);
72     if (!NT_SUCCESS(Status))
73     {
74         TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
75         goto done;
76     }
77 
78     TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
79 
80     Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
81 
82     LocalBuffer->MessageType = MsV1_0InteractiveProfile;
83     LocalBuffer->LogonCount = UserInfo->All.LogonCount;
84     LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
85 
86     LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
87     LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
88 
89     LocalBuffer->LogoffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
90     LocalBuffer->LogoffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
91 
92     LocalBuffer->KickOffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
93     LocalBuffer->KickOffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
94 
95     LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
96     LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
97 
98     LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
99     LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
100 
101     LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
102     LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
103 
104     LocalBuffer->LogonScript.Length = UserInfo->All.ScriptPath.Length;
105     LocalBuffer->LogonScript.MaximumLength = UserInfo->All.ScriptPath.Length + sizeof(WCHAR);
106     LocalBuffer->LogonScript.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
107     memcpy(Ptr,
108            UserInfo->All.ScriptPath.Buffer,
109            UserInfo->All.ScriptPath.Length);
110 
111     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
112 
113     LocalBuffer->HomeDirectory.Length = UserInfo->All.HomeDirectory.Length;
114     LocalBuffer->HomeDirectory.MaximumLength = UserInfo->All.HomeDirectory.Length + sizeof(WCHAR);
115     LocalBuffer->HomeDirectory.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
116     memcpy(Ptr,
117            UserInfo->All.HomeDirectory.Buffer,
118            UserInfo->All.HomeDirectory.Length);
119 
120     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
121 
122     LocalBuffer->FullName.Length = UserInfo->All.FullName.Length;
123     LocalBuffer->FullName.MaximumLength = UserInfo->All.FullName.Length + sizeof(WCHAR);
124     LocalBuffer->FullName.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
125     memcpy(Ptr,
126            UserInfo->All.FullName.Buffer,
127            UserInfo->All.FullName.Length);
128     TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
129 
130     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
131 
132     LocalBuffer->ProfilePath.Length = UserInfo->All.ProfilePath.Length;
133     LocalBuffer->ProfilePath.MaximumLength = UserInfo->All.ProfilePath.Length + sizeof(WCHAR);
134     LocalBuffer->ProfilePath.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
135     memcpy(Ptr,
136            UserInfo->All.ProfilePath.Buffer,
137            UserInfo->All.ProfilePath.Length);
138 
139     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
140 
141     LocalBuffer->HomeDirectoryDrive.Length = UserInfo->All.HomeDirectoryDrive.Length;
142     LocalBuffer->HomeDirectoryDrive.MaximumLength = UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR);
143     LocalBuffer->HomeDirectoryDrive.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
144     memcpy(Ptr,
145            UserInfo->All.HomeDirectoryDrive.Buffer,
146            UserInfo->All.HomeDirectoryDrive.Length);
147 
148     Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
149 
150     LocalBuffer->LogonServer.Length = (ComputerNameLength + 2) * sizeof(WCHAR);
151     LocalBuffer->LogonServer.MaximumLength = LocalBuffer->LogonServer.Length + sizeof(WCHAR);
152     LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
153     wcscpy(Ptr, L"\\");
154     wcscat(Ptr, ComputerName);
155 
156     LocalBuffer->UserFlags = 0;
157 
158     Status = DispatchTable.CopyToClientBuffer(ClientRequest,
159                                               BufferLength,
160                                               ClientBaseAddress,
161                                               LocalBuffer);
162     if (!NT_SUCCESS(Status))
163     {
164         TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
165         goto done;
166     }
167 
168     *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
169     *ProfileBufferLength = BufferLength;
170 
171 done:
172     if (LocalBuffer != NULL)
173         DispatchTable.FreeLsaHeap(LocalBuffer);
174 
175     if (!NT_SUCCESS(Status))
176     {
177         if (ClientBaseAddress != NULL)
178             DispatchTable.FreeClientBuffer(ClientRequest,
179                                            ClientBaseAddress);
180     }
181 
182     return Status;
183 }
184 
185 
186 static
187 NTSTATUS
BuildLm20LogonProfileBuffer(_In_ PLSA_CLIENT_REQUEST ClientRequest,_In_ PSAMPR_USER_INFO_BUFFER UserInfo,_In_ PLSA_SAM_PWD_DATA LogonPwdData,_Out_ PMSV1_0_LM20_LOGON_PROFILE * ProfileBuffer,_Out_ PULONG ProfileBufferLength)188 BuildLm20LogonProfileBuffer(
189     _In_ PLSA_CLIENT_REQUEST ClientRequest,
190     _In_ PSAMPR_USER_INFO_BUFFER UserInfo,
191     _In_ PLSA_SAM_PWD_DATA LogonPwdData,
192     _Out_ PMSV1_0_LM20_LOGON_PROFILE *ProfileBuffer,
193     _Out_ PULONG ProfileBufferLength)
194 {
195     PMSV1_0_LM20_LOGON_PROFILE LocalBuffer;
196     NTLM_CLIENT_BUFFER Buffer;
197     PBYTE PtrOffset;
198     ULONG BufferLength;
199     NTSTATUS Status = STATUS_SUCCESS;
200     UNICODE_STRING ComputerNameUCS;
201 
202     *ProfileBuffer = NULL;
203     *ProfileBufferLength = 0;
204 
205     if (!NtlmUStrAlloc(&ComputerNameUCS, LogonPwdData->ComputerName->Length + sizeof(WCHAR) * 3, 0))
206     {
207         Status = STATUS_INSUFFICIENT_RESOURCES;
208         goto done;
209     }
210     Status = RtlAppendUnicodeToString(&ComputerNameUCS, L"\\\\");
211     if (!NT_SUCCESS(Status))
212     {
213         ERR("RtlAppendUnicodeToString failed 0x%lx\n", Status);
214         goto done;
215     }
216     Status = RtlAppendUnicodeStringToString(&ComputerNameUCS, LogonPwdData->ComputerName);
217     if (!NT_SUCCESS(Status))
218     {
219         ERR("RtlAppendUnicodeStringToString failed 0x%lx\n", Status);
220         goto done;
221     }
222 
223     BufferLength = sizeof(MSV1_0_LM20_LOGON_PROFILE) + ComputerNameUCS.Length + sizeof(WCHAR);
224 
225     Status = NtlmAllocateClientBuffer(ClientRequest, BufferLength, &Buffer);
226     if (!NT_SUCCESS(Status))
227     {
228         TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
229         goto done;
230     }
231 
232     TRACE("ClientBaseAddress: %p\n", Buffer.ClientBaseAddress);
233 
234     LocalBuffer = (PMSV1_0_LM20_LOGON_PROFILE)Buffer.LocalBuffer;
235     PtrOffset = (PBYTE)(LocalBuffer + 1);
236 
237     LocalBuffer->MessageType = MsV1_0Lm20LogonProfile;
238     LocalBuffer->KickOffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
239     LocalBuffer->KickOffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
240     LocalBuffer->LogoffTime.LowPart = UserInfo->All.AccountExpires.LowPart;
241     LocalBuffer->LogoffTime.HighPart = UserInfo->All.AccountExpires.HighPart;
242 
243     memcpy(LocalBuffer->UserSessionKey,
244            &LogonPwdData->UserSessionKey,
245            MSV1_0_USER_SESSION_KEY_LENGTH);
246 
247     //FIXME: Set Domainname if we domain joined
248     //       what to do if not? WORKGROUP
249     RtlInitUnicodeString(&LocalBuffer->LogonDomainName, NULL);
250 
251     memcpy(LocalBuffer->LanmanSessionKey,
252            &LogonPwdData->LanmanSessionKey,
253            MSV1_0_LANMAN_SESSION_KEY_LENGTH);
254 
255     if (!NtlmUStrWriteToStruct(LocalBuffer,
256                                BufferLength,
257                                &LocalBuffer->LogonServer,
258                                &ComputerNameUCS,
259                                &PtrOffset,
260                                TRUE))
261     {
262         ERR("NtlmStructWriteUCS failed.\n");
263         Status = ERROR_INTERNAL_ERROR;
264         goto done;
265     }
266     /* not supported */
267     RtlInitUnicodeString(&LocalBuffer->UserParameters, NULL);
268     /* Build user flags */
269     LocalBuffer->UserFlags = 0x0;
270     if (LogonPwdData->LogonType == NetLogonLmKey)
271         LocalBuffer->UserFlags |= LOGON_USED_LM_PASSWORD;
272 
273     /* copy data to client buffer */
274     Status = NtlmCopyToClientBuffer(ClientRequest, BufferLength, &Buffer);
275     if (!NT_SUCCESS(Status))
276     {
277         TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
278         goto done;
279     }
280 
281     *ProfileBuffer = (PMSV1_0_LM20_LOGON_PROFILE)Buffer.ClientBaseAddress;
282     *ProfileBufferLength = BufferLength;
283 done:
284     /* On success Buffer.ClientBaseAddress will not be free */
285     NtlmFreeClientBuffer(ClientRequest, !NT_SUCCESS(Status), &Buffer);
286     NtlmUStrFree(&ComputerNameUCS);
287     return Status;
288 }
289 
290 static
291 PSID
AppendRidToSid(PSID SrcSid,ULONG Rid)292 AppendRidToSid(PSID SrcSid,
293                ULONG Rid)
294 {
295     PSID DstSid = NULL;
296     UCHAR RidCount;
297 
298     RidCount = *RtlSubAuthorityCountSid(SrcSid);
299     if (RidCount >= 8)
300         return NULL;
301 
302     DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
303     if (DstSid == NULL)
304         return NULL;
305 
306     RtlCopyMemory(DstSid,
307                   SrcSid,
308                   RtlLengthRequiredSid(RidCount));
309 
310     *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
311     *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
312 
313     return DstSid;
314 }
315 
316 
317 static
318 NTSTATUS
BuildTokenUser(OUT PTOKEN_USER User,IN PSID AccountDomainSid,IN ULONG RelativeId)319 BuildTokenUser(OUT PTOKEN_USER User,
320                IN PSID AccountDomainSid,
321                IN ULONG RelativeId)
322 {
323     User->User.Sid = AppendRidToSid(AccountDomainSid,
324                                     RelativeId);
325     if (User->User.Sid == NULL)
326     {
327         ERR("Could not create the user SID\n");
328         return STATUS_INSUFFICIENT_RESOURCES;
329     }
330 
331     User->User.Attributes = 0;
332 
333     return STATUS_SUCCESS;
334 }
335 
336 
337 static
338 NTSTATUS
BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,IN PSID AccountDomainSid,IN ULONG RelativeId)339 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
340                        IN PSID AccountDomainSid,
341                        IN ULONG RelativeId)
342 {
343     PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
344                                                 RelativeId);
345     if (PrimaryGroup->PrimaryGroup == NULL)
346     {
347         ERR("Could not create the primary group SID\n");
348         return STATUS_INSUFFICIENT_RESOURCES;
349     }
350 
351     return STATUS_SUCCESS;
352 }
353 
354 
355 static
356 NTSTATUS
BuildTokenGroups(OUT PTOKEN_GROUPS * Groups,IN PSID AccountDomainSid,IN ULONG RelativeId,IN BOOL SpecialAccount)357 BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
358                  IN PSID AccountDomainSid,
359                  IN ULONG RelativeId,
360                  IN BOOL SpecialAccount)
361 {
362     SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
363     PTOKEN_GROUPS TokenGroups;
364     DWORD GroupCount = 0;
365     DWORD MaxGroups = 2;
366     PSID Sid;
367     NTSTATUS Status = STATUS_SUCCESS;
368 
369     if (SpecialAccount)
370         MaxGroups++;
371 
372     TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
373                                                 MaxGroups * sizeof(SID_AND_ATTRIBUTES));
374     if (TokenGroups == NULL)
375     {
376         return STATUS_INSUFFICIENT_RESOURCES;
377     }
378 
379     if (SpecialAccount)
380     {
381         /* Self */
382         Sid = AppendRidToSid(AccountDomainSid, RelativeId);
383         if (Sid == NULL)
384         {
385 
386         }
387 
388         TokenGroups->Groups[GroupCount].Sid = Sid;
389         TokenGroups->Groups[GroupCount].Attributes =
390             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
391         GroupCount++;
392 
393         /* Member of 'Users' alias */
394         RtlAllocateAndInitializeSid(&SystemAuthority,
395                                     2,
396                                     SECURITY_BUILTIN_DOMAIN_RID,
397                                     DOMAIN_ALIAS_RID_USERS,
398                                     SECURITY_NULL_RID,
399                                     SECURITY_NULL_RID,
400                                     SECURITY_NULL_RID,
401                                     SECURITY_NULL_RID,
402                                     SECURITY_NULL_RID,
403                                     SECURITY_NULL_RID,
404                                     &Sid);
405         TokenGroups->Groups[GroupCount].Sid = Sid;
406         TokenGroups->Groups[GroupCount].Attributes =
407             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
408         GroupCount++;
409     }
410     else
411     {
412         /* Member of the domains users group */
413         Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
414         if (Sid == NULL)
415         {
416 
417         }
418 
419         TokenGroups->Groups[GroupCount].Sid = Sid;
420         TokenGroups->Groups[GroupCount].Attributes =
421             SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
422         GroupCount++;
423     }
424 
425     /* Member of 'Authenticated users' */
426     RtlAllocateAndInitializeSid(&SystemAuthority,
427                                 1,
428                                 SECURITY_AUTHENTICATED_USER_RID,
429                                 SECURITY_NULL_RID,
430                                 SECURITY_NULL_RID,
431                                 SECURITY_NULL_RID,
432                                 SECURITY_NULL_RID,
433                                 SECURITY_NULL_RID,
434                                 SECURITY_NULL_RID,
435                                 SECURITY_NULL_RID,
436                                 &Sid);
437     TokenGroups->Groups[GroupCount].Sid = Sid;
438     TokenGroups->Groups[GroupCount].Attributes =
439         SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
440     GroupCount++;
441 
442     TokenGroups->GroupCount = GroupCount;
443     ASSERT(TokenGroups->GroupCount <= MaxGroups);
444 
445     *Groups = TokenGroups;
446 
447     return Status;
448 }
449 
450 
451 static
452 NTSTATUS
BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 * TokenInformation,PRPC_SID AccountDomainSid,PSAMPR_USER_INFO_BUFFER UserInfo,BOOL SpecialAccount)453 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
454                             PRPC_SID AccountDomainSid,
455                             PSAMPR_USER_INFO_BUFFER UserInfo,
456                             BOOL SpecialAccount)
457 {
458     PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
459     ULONG i;
460     NTSTATUS Status = STATUS_SUCCESS;
461 
462     Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
463     if (Buffer == NULL)
464     {
465         WARN("Failed to allocate the local buffer!\n");
466         Status = STATUS_INSUFFICIENT_RESOURCES;
467         goto done;
468     }
469 
470     Buffer->ExpirationTime.LowPart = UserInfo->All.AccountExpires.LowPart;
471     Buffer->ExpirationTime.HighPart = UserInfo->All.AccountExpires.HighPart;
472 
473     Status = BuildTokenUser(&Buffer->User,
474                             (PSID)AccountDomainSid,
475                             UserInfo->All.UserId);
476     if (!NT_SUCCESS(Status))
477     {
478         WARN("BuildTokenUser() failed (Status 0x%08lx)\n", Status);
479         goto done;
480     }
481 
482     Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
483                                     (PSID)AccountDomainSid,
484                                     UserInfo->All.PrimaryGroupId);
485     if (!NT_SUCCESS(Status))
486     {
487         WARN("BuildTokenPrimaryGroup() failed (Status 0x%08lx)\n", Status);
488         goto done;
489     }
490 
491     Status = BuildTokenGroups(&Buffer->Groups,
492                               (PSID)AccountDomainSid,
493                               UserInfo->All.UserId,
494                               SpecialAccount);
495     if (!NT_SUCCESS(Status))
496     {
497         WARN("BuildTokenGroups() failed (Status 0x%08lx)\n", Status);
498         goto done;
499     }
500 
501     *TokenInformation = Buffer;
502 
503 done:
504     if (!NT_SUCCESS(Status))
505     {
506         if (Buffer != NULL)
507         {
508             if (Buffer->User.User.Sid != NULL)
509                 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
510 
511             if (Buffer->Groups != NULL)
512             {
513                 for (i = 0; i < Buffer->Groups->GroupCount; i++)
514                 {
515                     if (Buffer->Groups->Groups[i].Sid != NULL)
516                         DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
517                 }
518 
519                 DispatchTable.FreeLsaHeap(Buffer->Groups);
520             }
521 
522             if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
523                 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
524 
525             if (Buffer->DefaultDacl.DefaultDacl != NULL)
526                 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
527 
528             DispatchTable.FreeLsaHeap(Buffer);
529         }
530     }
531 
532     return Status;
533 }
534 
535 
536 static
537 NTSTATUS
MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,IN PVOID ProtocolSubmitBuffer,IN PVOID ClientBufferBase,IN ULONG SubmitBufferLength,OUT PVOID * ProtocolReturnBuffer,OUT PULONG ReturnBufferLength,OUT PNTSTATUS ProtocolStatus)538 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
539                    IN PVOID ProtocolSubmitBuffer,
540                    IN PVOID ClientBufferBase,
541                    IN ULONG SubmitBufferLength,
542                    OUT PVOID *ProtocolReturnBuffer,
543                    OUT PULONG ReturnBufferLength,
544                    OUT PNTSTATUS ProtocolStatus)
545 {
546     NTSTATUS Status;
547     PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
548     ULONG_PTR PtrOffset;
549 
550     SAMPR_HANDLE ServerHandle = NULL;
551     SAMPR_HANDLE DomainHandle = NULL;
552     SAMPR_HANDLE UserHandle = NULL;
553     PRPC_SID DomainSid = NULL;
554     RPC_UNICODE_STRING Names[1];
555     SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
556     SAMPR_ULONG_ARRAY Use = {0, NULL};
557 
558     ENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
559     ENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
560     ENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
561     ENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
562     OEM_STRING LmPwdString;
563     CHAR LmPwdBuffer[15];
564     BOOLEAN OldLmPasswordPresent = FALSE;
565     BOOLEAN NewLmPasswordPresent = FALSE;
566 
567     ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
568     ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
569     ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt;
570     ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt;
571     PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
572     PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
573 
574     TRACE("MsvpChangePassword()\n");
575 
576     /* Parameters validation */
577 
578     if (SubmitBufferLength < sizeof(MSV1_0_CHANGEPASSWORD_REQUEST))
579     {
580         ERR("Invalid SubmitBufferLength %lu\n", SubmitBufferLength);
581         return STATUS_INVALID_PARAMETER;
582     }
583 
584     RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
585 
586     /* Fix-up pointers in the request buffer info */
587     PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
588 
589     Status = RtlValidateUnicodeString(0, &RequestBuffer->DomainName);
590     if (!NT_SUCCESS(Status))
591         return STATUS_INVALID_PARAMETER;
592     // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
593     RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
594     RequestBuffer->DomainName.MaximumLength = RequestBuffer->DomainName.Length;
595 
596     Status = RtlValidateUnicodeString(0, &RequestBuffer->AccountName);
597     if (!NT_SUCCESS(Status))
598         return STATUS_INVALID_PARAMETER;
599     // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
600     RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
601     RequestBuffer->AccountName.MaximumLength = RequestBuffer->AccountName.Length;
602 
603     Status = RtlValidateUnicodeString(0, &RequestBuffer->OldPassword);
604     if (!NT_SUCCESS(Status))
605         return STATUS_INVALID_PARAMETER;
606     // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
607     RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
608     RequestBuffer->OldPassword.MaximumLength = RequestBuffer->OldPassword.Length;
609 
610     Status = RtlValidateUnicodeString(0, &RequestBuffer->NewPassword);
611     if (!NT_SUCCESS(Status))
612         return STATUS_INVALID_PARAMETER;
613     // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
614     RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
615     RequestBuffer->NewPassword.MaximumLength = RequestBuffer->NewPassword.Length;
616 
617     TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
618     TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
619     TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
620     TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
621 
622     /* Connect to the SAM server */
623     Status = SamIConnect(NULL,
624                          &ServerHandle,
625                          SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
626                          TRUE);
627     if (!NT_SUCCESS(Status))
628     {
629         TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
630         goto done;
631     }
632 
633     /* Get the domain SID */
634     Status = SamrLookupDomainInSamServer(ServerHandle,
635                                          (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
636                                          &DomainSid);
637     if (!NT_SUCCESS(Status))
638     {
639         TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
640         goto done;
641     }
642 
643     /* Open the domain */
644     Status = SamrOpenDomain(ServerHandle,
645                             DOMAIN_LOOKUP,
646                             DomainSid,
647                             &DomainHandle);
648     if (!NT_SUCCESS(Status))
649     {
650         TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
651         goto done;
652     }
653 
654     Names[0].Length = RequestBuffer->AccountName.Length;
655     Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
656     Names[0].Buffer = RequestBuffer->AccountName.Buffer;
657 
658     /* Try to get the RID for the user name */
659     Status = SamrLookupNamesInDomain(DomainHandle,
660                                      1,
661                                      Names,
662                                      &RelativeIds,
663                                      &Use);
664     if (!NT_SUCCESS(Status))
665     {
666         TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
667         Status = STATUS_NO_SUCH_USER;
668         goto done;
669     }
670 
671     /* Fail, if it is not a user account */
672     if (Use.Element[0] != SidTypeUser)
673     {
674         TRACE("Account is not a user account!\n");
675         Status = STATUS_NO_SUCH_USER;
676         goto done;
677     }
678 
679     /* Open the user object */
680     Status = SamrOpenUser(DomainHandle,
681                           USER_CHANGE_PASSWORD,
682                           RelativeIds.Element[0],
683                           &UserHandle);
684     if (!NT_SUCCESS(Status))
685     {
686         TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
687         goto done;
688     }
689 
690 
691     /* Calculate the NT hash for the old password */
692     Status = SystemFunction007(&RequestBuffer->OldPassword,
693                                (LPBYTE)&OldNtPassword);
694     if (!NT_SUCCESS(Status))
695     {
696         TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
697         goto done;
698     }
699 
700     /* Calculate the NT hash for the new password */
701     Status = SystemFunction007(&RequestBuffer->NewPassword,
702                                (LPBYTE)&NewNtPassword);
703     if (!NT_SUCCESS(Status))
704     {
705         TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
706         goto done;
707     }
708 
709     /* Calculate the LM password and hash for the old password */
710     LmPwdString.Length = 15;
711     LmPwdString.MaximumLength = 15;
712     LmPwdString.Buffer = LmPwdBuffer;
713     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
714 
715     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
716                                                &RequestBuffer->OldPassword,
717                                                FALSE);
718     if (NT_SUCCESS(Status))
719     {
720         /* Calculate the LM hash value of the password */
721         Status = SystemFunction006(LmPwdString.Buffer,
722                                    (LPSTR)&OldLmPassword);
723         if (NT_SUCCESS(Status))
724         {
725             OldLmPasswordPresent = TRUE;
726         }
727     }
728 
729     /* Calculate the LM password and hash for the new password */
730     LmPwdString.Length = 15;
731     LmPwdString.MaximumLength = 15;
732     LmPwdString.Buffer = LmPwdBuffer;
733     ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
734 
735     Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
736                                                &RequestBuffer->NewPassword,
737                                                FALSE);
738     if (NT_SUCCESS(Status))
739     {
740         /* Calculate the LM hash value of the password */
741         Status = SystemFunction006(LmPwdString.Buffer,
742                                    (LPSTR)&NewLmPassword);
743         if (NT_SUCCESS(Status))
744         {
745             NewLmPasswordPresent = TRUE;
746         }
747     }
748 
749     /* Encrypt the old and new LM passwords, if they exist */
750     if (OldLmPasswordPresent && NewLmPasswordPresent)
751     {
752         /* Encrypt the old LM password */
753         Status = SystemFunction012((const BYTE *)&OldLmPassword,
754                                    (const BYTE *)&NewLmPassword,
755                                    (LPBYTE)&OldLmEncryptedWithNewLm);
756         if (!NT_SUCCESS(Status))
757         {
758             TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
759             goto done;
760         }
761 
762         /* Encrypt the new LM password */
763         Status = SystemFunction012((const BYTE *)&NewLmPassword,
764                                    (const BYTE *)&OldLmPassword,
765                                    (LPBYTE)&NewLmEncryptedWithOldLm);
766         if (!NT_SUCCESS(Status))
767         {
768             TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
769             goto done;
770         }
771 
772         pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
773         pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
774     }
775 
776     /* Encrypt the old NT password */
777     Status = SystemFunction012((const BYTE *)&OldNtPassword,
778                                (const BYTE *)&NewNtPassword,
779                                (LPBYTE)&OldNtEncryptedWithNewNt);
780     if (!NT_SUCCESS(Status))
781     {
782         TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
783         goto done;
784     }
785 
786     /* Encrypt the new NT password */
787     Status = SystemFunction012((const BYTE *)&NewNtPassword,
788                                (const BYTE *)&OldNtPassword,
789                                (LPBYTE)&NewNtEncryptedWithOldNt);
790     if (!NT_SUCCESS(Status))
791     {
792         TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
793         goto done;
794     }
795 
796     /* Change the password */
797     Status = SamrChangePasswordUser(UserHandle,
798                                     OldLmPasswordPresent && NewLmPasswordPresent,
799                                     pOldLmEncryptedWithNewLm,
800                                     pNewLmEncryptedWithOldLm,
801                                     TRUE,
802                                     &OldNtEncryptedWithNewNt,
803                                     &NewNtEncryptedWithOldNt,
804                                     FALSE,
805                                     NULL,
806                                     FALSE,
807                                     NULL);
808     if (!NT_SUCCESS(Status))
809     {
810         TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
811         goto done;
812     }
813 
814 done:
815     if (UserHandle != NULL)
816         SamrCloseHandle(&UserHandle);
817 
818     SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
819     SamIFree_SAMPR_ULONG_ARRAY(&Use);
820 
821     if (DomainHandle != NULL)
822         SamrCloseHandle(&DomainHandle);
823 
824     if (DomainSid != NULL)
825         SamIFreeVoid(DomainSid);
826 
827     if (ServerHandle != NULL)
828         SamrCloseHandle(&ServerHandle);
829 
830     return Status;
831 }
832 
833 
834 static
835 NTSTATUS
MsvpEnumerateUsers(_In_ PLSA_CLIENT_REQUEST ClientRequest,_In_ PVOID ProtocolSubmitBuffer,_In_ PVOID ClientBufferBase,_In_ ULONG SubmitBufferLength,_Out_ PVOID * ProtocolReturnBuffer,_Out_ PULONG ReturnBufferLength,_Out_ PNTSTATUS ProtocolStatus)836 MsvpEnumerateUsers(
837     _In_ PLSA_CLIENT_REQUEST ClientRequest,
838     _In_ PVOID ProtocolSubmitBuffer,
839     _In_ PVOID ClientBufferBase,
840     _In_ ULONG SubmitBufferLength,
841     _Out_ PVOID *ProtocolReturnBuffer,
842     _Out_ PULONG ReturnBufferLength,
843     _Out_ PNTSTATUS ProtocolStatus)
844 {
845     PMSV1_0_ENUMUSERS_RESPONSE LocalBuffer = NULL;
846     PVOID ClientBaseAddress = NULL;
847     ULONG BufferLength;
848     PLIST_ENTRY CurrentEntry;
849     PLOGON_LIST_ENTRY LogonEntry;
850     ULONG LogonCount = 0;
851     PLUID LuidPtr;
852     PULONG EnumPtr;
853     NTSTATUS Status = STATUS_SUCCESS;
854 
855     TRACE("MsvpEnumerateUsers()\n");
856 
857     /* Count the currently logged-on users */
858     CurrentEntry = LogonListHead.Flink;
859     while (CurrentEntry != &LogonListHead)
860     {
861         LogonEntry = CONTAINING_RECORD(CurrentEntry,
862                                        LOGON_LIST_ENTRY,
863                                        ListEntry);
864 
865         TRACE("Logon %lu: 0x%08lx\n", LogonCount, LogonEntry->LogonId.LowPart);
866         LogonCount++;
867 
868         CurrentEntry = CurrentEntry->Flink;
869     }
870 
871     TRACE("LogonCount %lu\n", LogonCount);
872 
873     BufferLength = sizeof(MSV1_0_ENUMUSERS_RESPONSE) +
874                    (LogonCount * sizeof(LUID)) +
875                    (LogonCount * sizeof(ULONG));
876 
877     LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
878     if (LocalBuffer == NULL)
879     {
880         ERR("Failed to allocate the local buffer!\n");
881         Status = STATUS_INSUFFICIENT_RESOURCES;
882         goto done;
883     }
884 
885     Status = DispatchTable.AllocateClientBuffer(ClientRequest,
886                                                 BufferLength,
887                                                 &ClientBaseAddress);
888     if (!NT_SUCCESS(Status))
889     {
890         ERR("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
891         goto done;
892     }
893 
894     TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
895 
896     /* Fill the local buffer */
897     LocalBuffer->MessageType = MsV1_0EnumerateUsers;
898     LocalBuffer->NumberOfLoggedOnUsers = LogonCount;
899 
900     LuidPtr = (PLUID)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_ENUMUSERS_RESPONSE));
901     EnumPtr = (PULONG)((ULONG_PTR)LuidPtr + LogonCount * sizeof(LUID));
902 
903     LocalBuffer->LogonIds = (PLUID)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)LuidPtr - (ULONG_PTR)LocalBuffer);
904     LocalBuffer->EnumHandles = (PULONG)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)EnumPtr - (ULONG_PTR)LocalBuffer);
905 
906     /* Copy the LogonIds and EnumHandles into the local buffer */
907     CurrentEntry = LogonListHead.Flink;
908     while (CurrentEntry != &LogonListHead)
909     {
910         LogonEntry = CONTAINING_RECORD(CurrentEntry,
911                                        LOGON_LIST_ENTRY,
912                                        ListEntry);
913 
914         TRACE("Logon: 0x%08lx  %lu\n", LogonEntry->LogonId.LowPart, LogonEntry->EnumHandle);
915         RtlCopyMemory(LuidPtr, &LogonEntry->LogonId, sizeof(LUID));
916         LuidPtr++;
917 
918         *EnumPtr = LogonEntry->EnumHandle;
919         EnumPtr++;
920 
921         CurrentEntry = CurrentEntry->Flink;
922     }
923 
924     Status = DispatchTable.CopyToClientBuffer(ClientRequest,
925                                               BufferLength,
926                                               ClientBaseAddress,
927                                               LocalBuffer);
928     if (!NT_SUCCESS(Status))
929     {
930         ERR("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
931         goto done;
932     }
933 
934     *ProtocolReturnBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
935     *ReturnBufferLength = BufferLength;
936     *ProtocolStatus = STATUS_SUCCESS;
937 
938 done:
939     if (LocalBuffer != NULL)
940         DispatchTable.FreeLsaHeap(LocalBuffer);
941 
942     if (!NT_SUCCESS(Status))
943     {
944         if (ClientBaseAddress != NULL)
945             DispatchTable.FreeClientBuffer(ClientRequest,
946                                            ClientBaseAddress);
947     }
948 
949     return STATUS_SUCCESS;
950 }
951 
952 
953 /*
954  * @unimplemented
955  */
956 NTSTATUS
957 NTAPI
LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,IN PVOID ProtocolSubmitBuffer,IN PVOID ClientBufferBase,IN ULONG SubmitBufferLength,OUT PVOID * ProtocolReturnBuffer,OUT PULONG ReturnBufferLength,OUT PNTSTATUS ProtocolStatus)958 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
959                  IN PVOID ProtocolSubmitBuffer,
960                  IN PVOID ClientBufferBase,
961                  IN ULONG SubmitBufferLength,
962                  OUT PVOID *ProtocolReturnBuffer,
963                  OUT PULONG ReturnBufferLength,
964                  OUT PNTSTATUS ProtocolStatus)
965 {
966     NTSTATUS Status;
967     MSV1_0_PROTOCOL_MESSAGE_TYPE MessageType;
968 
969     TRACE("LsaApCallPackage()\n");
970 
971     if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
972         return STATUS_INVALID_PARAMETER;
973 
974     MessageType = *((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
975 
976     *ProtocolReturnBuffer = NULL;
977     *ReturnBufferLength = 0;
978 
979     switch (MessageType)
980     {
981         case MsV1_0Lm20ChallengeRequest:
982         case MsV1_0Lm20GetChallengeResponse:
983             Status = STATUS_NOT_IMPLEMENTED;
984             break;
985 
986         case MsV1_0EnumerateUsers:
987              Status = MsvpEnumerateUsers(ClientRequest,
988                                          ProtocolSubmitBuffer,
989                                          ClientBufferBase,
990                                          SubmitBufferLength,
991                                          ProtocolReturnBuffer,
992                                          ReturnBufferLength,
993                                          ProtocolStatus);
994              break;
995 
996         case MsV1_0GetUserInfo:
997         case MsV1_0ReLogonUsers:
998             Status = STATUS_INVALID_PARAMETER;
999             break;
1000 
1001         case MsV1_0ChangePassword:
1002             Status = MsvpChangePassword(ClientRequest,
1003                                         ProtocolSubmitBuffer,
1004                                         ClientBufferBase,
1005                                         SubmitBufferLength,
1006                                         ProtocolReturnBuffer,
1007                                         ReturnBufferLength,
1008                                         ProtocolStatus);
1009             break;
1010 
1011         case MsV1_0ChangeCachedPassword:
1012         case MsV1_0GenericPassthrough:
1013         case MsV1_0CacheLogon:
1014         case MsV1_0SubAuth:
1015         case MsV1_0DeriveCredential:
1016         case MsV1_0CacheLookup:
1017             Status = STATUS_NOT_IMPLEMENTED;
1018             break;
1019 
1020         default:
1021             return STATUS_INVALID_PARAMETER;
1022     }
1023 
1024     return Status;
1025 }
1026 
1027 
1028 /*
1029  * @unimplemented
1030  */
1031 NTSTATUS
1032 NTAPI
LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,IN PVOID ProtocolSubmitBuffer,IN PVOID ClientBufferBase,IN ULONG SubmitBufferLength,OUT PVOID * ProtocolReturnBuffer,OUT PULONG ReturnBufferLength,OUT PNTSTATUS ProtocolStatus)1033 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,
1034                             IN PVOID ProtocolSubmitBuffer,
1035                             IN PVOID ClientBufferBase,
1036                             IN ULONG SubmitBufferLength,
1037                             OUT PVOID *ProtocolReturnBuffer,
1038                             OUT PULONG ReturnBufferLength,
1039                             OUT PNTSTATUS ProtocolStatus)
1040 {
1041     TRACE("LsaApCallPackagePassthrough()\n");
1042     return STATUS_NOT_IMPLEMENTED;
1043 }
1044 
1045 
1046 /*
1047  * @implemented
1048  */
1049 NTSTATUS
1050 NTAPI
LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,IN PVOID ProtocolSubmitBuffer,IN PVOID ClientBufferBase,IN ULONG SubmitBufferLength,OUT PVOID * ProtocolReturnBuffer,OUT PULONG ReturnBufferLength,OUT PNTSTATUS ProtocolStatus)1051 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
1052                           IN PVOID ProtocolSubmitBuffer,
1053                           IN PVOID ClientBufferBase,
1054                           IN ULONG SubmitBufferLength,
1055                           OUT PVOID *ProtocolReturnBuffer,
1056                           OUT PULONG ReturnBufferLength,
1057                           OUT PNTSTATUS ProtocolStatus)
1058 {
1059     ULONG MessageType;
1060     NTSTATUS Status;
1061 
1062     TRACE("LsaApCallPackageUntrusted()\n");
1063 
1064     if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
1065         return STATUS_INVALID_PARAMETER;
1066 
1067     MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
1068 
1069     *ProtocolReturnBuffer = NULL;
1070     *ReturnBufferLength = 0;
1071 
1072     if (MessageType == MsV1_0ChangePassword)
1073         Status = MsvpChangePassword(ClientRequest,
1074                                     ProtocolSubmitBuffer,
1075                                     ClientBufferBase,
1076                                     SubmitBufferLength,
1077                                     ProtocolReturnBuffer,
1078                                     ReturnBufferLength,
1079                                     ProtocolStatus);
1080     else
1081         Status = STATUS_ACCESS_DENIED;
1082 
1083     return Status;
1084 }
1085 
1086 
1087 /*
1088  * @implemented
1089  */
1090 NTSTATUS
1091 NTAPI
LsaApInitializePackage(IN ULONG AuthenticationPackageId,IN PLSA_DISPATCH_TABLE LsaDispatchTable,IN PLSA_STRING Database OPTIONAL,IN PLSA_STRING Confidentiality OPTIONAL,OUT PLSA_STRING * AuthenticationPackageName)1092 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
1093                        IN PLSA_DISPATCH_TABLE LsaDispatchTable,
1094                        IN PLSA_STRING Database OPTIONAL,
1095                        IN PLSA_STRING Confidentiality OPTIONAL,
1096                        OUT PLSA_STRING *AuthenticationPackageName)
1097 {
1098     PANSI_STRING NameString;
1099     PCHAR NameBuffer;
1100 
1101     TRACE("LsaApInitializePackage(%lu %p %p %p %p)\n",
1102           AuthenticationPackageId, LsaDispatchTable, Database,
1103           Confidentiality, AuthenticationPackageName);
1104 
1105     if (!PackageInitialized)
1106     {
1107         InitializeListHead(&LogonListHead);
1108         EnumCounter = 0;
1109         PackageInitialized = TRUE;
1110     }
1111 
1112     /* Get the dispatch table entries */
1113     DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
1114     DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
1115     DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
1116     DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
1117     DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
1118     DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
1119     DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
1120     DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
1121     DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
1122     DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
1123     DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
1124 
1125     /* Return the package name */
1126     NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
1127     if (NameString == NULL)
1128         return STATUS_INSUFFICIENT_RESOURCES;
1129 
1130     NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
1131     if (NameBuffer == NULL)
1132     {
1133         DispatchTable.FreeLsaHeap(NameString);
1134         return STATUS_INSUFFICIENT_RESOURCES;
1135     }
1136 
1137     strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
1138 
1139     RtlInitAnsiString(NameString, NameBuffer);
1140 
1141     *AuthenticationPackageName = (PLSA_STRING)NameString;
1142 
1143     return STATUS_SUCCESS;
1144 }
1145 
1146 
1147 /*
1148  * @unimplemented
1149  */
1150 VOID
1151 NTAPI
LsaApLogonTerminated(IN PLUID LogonId)1152 LsaApLogonTerminated(IN PLUID LogonId)
1153 {
1154     TRACE("LsaApLogonTerminated()\n");
1155 }
1156 
1157 
1158 /*
1159  * Handle Network logon
1160  */
1161 static
1162 NTSTATUS
LsaApLogonUserEx2_Network(_In_ PLSA_CLIENT_REQUEST ClientRequest,_In_ PVOID ProtocolSubmitBuffer,_In_ PVOID ClientBufferBase,_In_ ULONG SubmitBufferSize,_In_ PUNICODE_STRING ComputerName,_Out_ PUNICODE_STRING * LogonUserRef,_Out_ PUNICODE_STRING * LogonDomainRef,_Inout_ PLSA_SAM_PWD_DATA LogonPwdData,_Out_ SAMPR_HANDLE * UserHandlePtr,_Out_ PSAMPR_USER_INFO_BUFFER * UserInfoPtr,_Out_ PRPC_SID * AccountDomainSidPtr,_Out_ PBOOL SpecialAccount,_Out_ PMSV1_0_LM20_LOGON_PROFILE * LogonProfile,_Out_ PULONG LogonProfileSize,_Out_ PNTSTATUS SubStatus)1163 LsaApLogonUserEx2_Network(
1164     _In_ PLSA_CLIENT_REQUEST ClientRequest,
1165     _In_ PVOID ProtocolSubmitBuffer,
1166     _In_ PVOID ClientBufferBase,
1167     _In_ ULONG SubmitBufferSize,
1168     _In_ PUNICODE_STRING ComputerName,
1169     _Out_ PUNICODE_STRING* LogonUserRef,
1170     _Out_ PUNICODE_STRING* LogonDomainRef,
1171     _Inout_ PLSA_SAM_PWD_DATA LogonPwdData,
1172     _Out_ SAMPR_HANDLE* UserHandlePtr,
1173     _Out_ PSAMPR_USER_INFO_BUFFER* UserInfoPtr,
1174     _Out_ PRPC_SID* AccountDomainSidPtr,
1175     _Out_ PBOOL SpecialAccount,
1176     _Out_ PMSV1_0_LM20_LOGON_PROFILE *LogonProfile,
1177     _Out_ PULONG LogonProfileSize,
1178     _Out_ PNTSTATUS SubStatus)
1179 {
1180     NTSTATUS Status;
1181     PMSV1_0_LM20_LOGON LogonInfo;
1182     ULONG_PTR PtrOffset;
1183 
1184     *LogonProfile = NULL;
1185     *LogonProfileSize = 0;
1186     *UserInfoPtr = NULL;
1187     *AccountDomainSidPtr = NULL;
1188     *SpecialAccount = FALSE;
1189     LogonInfo = ProtocolSubmitBuffer;
1190 
1191     if (SubmitBufferSize < sizeof(MSV1_0_LM20_LOGON))
1192     {
1193         ERR("Invalid SubmitBufferSize %lu\n", SubmitBufferSize);
1194         return STATUS_INVALID_PARAMETER;
1195     }
1196 
1197     /* Fix-up pointers in the authentication info */
1198     PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
1199 
1200     if ((!NtlmFixupAndValidateUStr(&LogonInfo->LogonDomainName, PtrOffset)) ||
1201         (!NtlmFixupAndValidateUStr(&LogonInfo->UserName, PtrOffset)) ||
1202         (!NtlmFixupAndValidateUStr(&LogonInfo->Workstation, PtrOffset)) ||
1203         (!NtlmFixupAStr(&LogonInfo->CaseSensitiveChallengeResponse, PtrOffset)) ||
1204         (!NtlmFixupAStr(&LogonInfo->CaseInsensitiveChallengeResponse, PtrOffset)))
1205     {
1206         return STATUS_INVALID_PARAMETER;
1207     }
1208 
1209     LogonPwdData->IsNetwork = TRUE;
1210     LogonPwdData->LogonInfo = LogonInfo;
1211     LogonPwdData->ComputerName = ComputerName;
1212     Status = SamValidateUser(Network,
1213                              &LogonInfo->UserName,
1214                              &LogonInfo->LogonDomainName,
1215                              LogonPwdData,
1216                              ComputerName,
1217                              SpecialAccount,
1218                              AccountDomainSidPtr,
1219                              UserHandlePtr,
1220                              UserInfoPtr,
1221                              SubStatus);
1222     if (!NT_SUCCESS(Status))
1223     {
1224         ERR("SamValidateUser failed with 0x%lx\n", Status);
1225         return Status;
1226     }
1227 
1228     if (LogonInfo->ParameterControl & MSV1_0_RETURN_PROFILE_PATH)
1229     {
1230         Status = BuildLm20LogonProfileBuffer(ClientRequest,
1231                                              *UserInfoPtr,
1232                                              LogonPwdData,
1233                                              LogonProfile,
1234                                              LogonProfileSize);
1235         if (!NT_SUCCESS(Status))
1236         {
1237             ERR("BuildLm20LogonProfileBuffer failed with 0x%lx\n", Status);
1238             return Status;
1239         }
1240     }
1241 
1242     *LogonUserRef = &LogonInfo->UserName;
1243     *LogonDomainRef = &LogonInfo->LogonDomainName;
1244 
1245     return Status;
1246 }
1247 
1248 /*
1249  * @implemented
1250  */
1251 NTSTATUS
1252 NTAPI
LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,IN SECURITY_LOGON_TYPE LogonType,IN PVOID ProtocolSubmitBuffer,IN PVOID ClientBufferBase,IN ULONG SubmitBufferSize,OUT PVOID * ProfileBuffer,OUT PULONG ProfileBufferSize,OUT PLUID LogonId,OUT PNTSTATUS SubStatus,OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,OUT PVOID * TokenInformation,OUT PUNICODE_STRING * AccountName,OUT PUNICODE_STRING * AuthenticatingAuthority,OUT PUNICODE_STRING * MachineName,OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY * SupplementalCredentials)1253 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1254                   IN SECURITY_LOGON_TYPE LogonType,
1255                   IN PVOID ProtocolSubmitBuffer,
1256                   IN PVOID ClientBufferBase,
1257                   IN ULONG SubmitBufferSize,
1258                   OUT PVOID *ProfileBuffer,
1259                   OUT PULONG ProfileBufferSize,
1260                   OUT PLUID LogonId,
1261                   OUT PNTSTATUS SubStatus,
1262                   OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1263                   OUT PVOID *TokenInformation,
1264                   OUT PUNICODE_STRING *AccountName,
1265                   OUT PUNICODE_STRING *AuthenticatingAuthority,
1266                   OUT PUNICODE_STRING *MachineName,
1267                   OUT PSECPKG_PRIMARY_CRED PrimaryCredentials, /* Not supported yet */
1268                   OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials) /* Not supported yet */
1269 {
1270     NTSTATUS Status;
1271     UNICODE_STRING ComputerName;
1272     WCHAR ComputerNameData[MAX_COMPUTERNAME_LENGTH + 1];
1273     PUNICODE_STRING LogonUserName = NULL;
1274     LSA_SAM_PWD_DATA LogonPwdData = { FALSE, NULL };
1275     PUNICODE_STRING LogonDomain = NULL;
1276     SAMPR_HANDLE UserHandle = NULL;
1277     PRPC_SID AccountDomainSid = NULL;
1278     PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
1279     BOOLEAN SessionCreated = FALSE;
1280     DWORD ComputerNameSize;
1281     BOOL SpecialAccount = FALSE;
1282     UCHAR LogonPassHash;
1283     PUNICODE_STRING ErasePassword = NULL;
1284     PLOGON_LIST_ENTRY LogonEntry = NULL;
1285 
1286     TRACE("LsaApLogonUserEx2()\n");
1287 
1288     TRACE("LogonType: %lu\n", LogonType);
1289     TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1290     TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1291 
1292     *ProfileBuffer = NULL;
1293     *ProfileBufferSize = 0;
1294     *SubStatus = STATUS_SUCCESS;
1295     *AccountName = NULL;
1296     *AuthenticatingAuthority = NULL;
1297 
1298     /* Get the computer name */
1299     ComputerNameSize = ARRAYSIZE(ComputerNameData);
1300     if (!GetComputerNameW(ComputerNameData, &ComputerNameSize))
1301     {
1302         ERR("Failed to get Computername.\n");
1303         return STATUS_INTERNAL_ERROR;
1304     }
1305     RtlInitUnicodeString(&ComputerName, ComputerNameData);
1306 
1307     /* Parameters validation */
1308     if (LogonType == Interactive ||
1309         LogonType == Batch ||
1310         LogonType == Service)
1311     {
1312         PMSV1_0_INTERACTIVE_LOGON LogonInfo;
1313         ULONG_PTR PtrOffset;
1314 
1315         if (SubmitBufferSize < sizeof(MSV1_0_INTERACTIVE_LOGON))
1316         {
1317             ERR("Invalid SubmitBufferSize %lu\n", SubmitBufferSize);
1318             return STATUS_INVALID_PARAMETER;
1319         }
1320 
1321         LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)ProtocolSubmitBuffer;
1322 
1323         if (LogonInfo->MessageType != MsV1_0InteractiveLogon &&
1324             LogonInfo->MessageType != MsV1_0WorkstationUnlockLogon)
1325         {
1326             ERR("Invalid MessageType %lu\n", LogonInfo->MessageType);
1327             return STATUS_BAD_VALIDATION_CLASS;
1328         }
1329 
1330 #if 0   // FIXME: These checks happen to be done on Windows. We however keep them general on ReactOS for now...
1331         if (LogonInfo->UserName.Length > 512) // CRED_MAX_STRING_LENGTH * sizeof(WCHAR) or (CREDUI_MAX_USERNAME_LENGTH (== CRED_MAX_USERNAME_LENGTH) - 1) * sizeof(WCHAR)
1332         {
1333             ERR("UserName too long (%lu, maximum 512)\n", LogonInfo->UserName.Length);
1334             return STATUS_NAME_TOO_LONG;
1335         }
1336         if (LogonInfo->Password.Length > 512) // CREDUI_MAX_PASSWORD_LENGTH * sizeof(WCHAR)
1337         {
1338             ERR("Password too long (%lu, maximum 512)\n", LogonInfo->Password.Length);
1339             return STATUS_NAME_TOO_LONG;
1340         }
1341 #endif
1342 
1343         /* Fix-up pointers in the authentication info */
1344         PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
1345 
1346         /* LogonDomainName is optional and can be an empty string */
1347         if (LogonInfo->LogonDomainName.Length)
1348         {
1349             // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1350             LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
1351             LogonInfo->LogonDomainName.MaximumLength = LogonInfo->LogonDomainName.Length;
1352         }
1353         else
1354         {
1355             LogonInfo->LogonDomainName.Buffer = NULL;
1356             LogonInfo->LogonDomainName.MaximumLength = 0;
1357         }
1358         Status = RtlValidateUnicodeString(0, &LogonInfo->LogonDomainName);
1359         if (!NT_SUCCESS(Status))
1360             return STATUS_INVALID_PARAMETER;
1361 
1362         /* UserName is mandatory and cannot be an empty string */
1363         // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1364         LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
1365         LogonInfo->UserName.MaximumLength = LogonInfo->UserName.Length;
1366 
1367         Status = RtlValidateUnicodeString(0, &LogonInfo->UserName);
1368         if (!NT_SUCCESS(Status))
1369             return STATUS_INVALID_PARAMETER;
1370 
1371         /* MS docs says max length is 0xFF bytes. But thats not the full story:
1372          *
1373          * A Quote from https://groups.google.com/forum/#!topic/microsoft.public.win32.programmer.kernel/eFGcCo_ZObk:
1374          * "... At least on my WinXP SP2. Domain and UserName are passed
1375          * in clear text, but the Password is NOT. ..."
1376          *
1377          * If the higher byte of length != 0 we have to use RtlRunDecodeUnicodeString.
1378          */
1379         LogonPassHash = (LogonInfo->Password.Length >> 8) & 0xFF;
1380         LogonInfo->Password.Length = LogonInfo->Password.Length & 0xFF;
1381 
1382         /* Password is optional and can be an empty string */
1383         if (LogonInfo->Password.Length)
1384         {
1385             // TODO: Check for Buffer limits wrt. ClientBufferBase and alignment.
1386             LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
1387             LogonInfo->Password.MaximumLength = LogonInfo->Password.Length;
1388         }
1389         else
1390         {
1391             LogonInfo->Password.Buffer = NULL;
1392             LogonInfo->Password.MaximumLength = 0;
1393         }
1394 
1395         /* Decode password */
1396         if (LogonPassHash > 0)
1397         {
1398             RtlRunDecodeUnicodeString(LogonPassHash, &LogonInfo->Password);
1399         }
1400 
1401         /* ErasePassword will be "erased" before we return */
1402         ErasePassword = &LogonInfo->Password;
1403 
1404         Status = RtlValidateUnicodeString(0, &LogonInfo->Password);
1405         if (!NT_SUCCESS(Status))
1406             return STATUS_INVALID_PARAMETER;
1407 
1408         LogonUserName = &LogonInfo->UserName;
1409         LogonDomain = &LogonInfo->LogonDomainName;
1410         LogonPwdData.IsNetwork = FALSE;
1411         LogonPwdData.PlainPwd = &LogonInfo->Password;
1412         LogonPwdData.ComputerName = &ComputerName;
1413 
1414         TRACE("Domain: %wZ\n", &LogonInfo->LogonDomainName);
1415         TRACE("User: %wZ\n", &LogonInfo->UserName);
1416         TRACE("Password: %wZ\n", &LogonInfo->Password);
1417 
1418         // TODO: If LogonType == Service, do some extra work using LogonInfo->Password.
1419     }
1420     else if (LogonType == Network)
1421     {
1422         Status = LsaApLogonUserEx2_Network(ClientRequest,
1423                                            ProtocolSubmitBuffer,
1424                                            ClientBufferBase,
1425                                            SubmitBufferSize,
1426                                            &ComputerName,
1427                                            &LogonUserName,
1428                                            &LogonDomain,
1429                                            &LogonPwdData,
1430                                            &UserHandle,
1431                                            &UserInfo,
1432                                            &AccountDomainSid,
1433                                            &SpecialAccount,
1434                                            (PMSV1_0_LM20_LOGON_PROFILE*)ProfileBuffer,
1435                                            ProfileBufferSize,
1436                                            SubStatus);
1437         if (!NT_SUCCESS(Status))
1438             goto done;
1439     }
1440     else
1441     {
1442         FIXME("LogonType %lu is not supported yet!\n", LogonType);
1443         return STATUS_NOT_IMPLEMENTED;
1444     }
1445     // TODO: Add other LogonType validity checks.
1446 
1447     Status = SamValidateUser(LogonType,
1448                              LogonUserName,
1449                              LogonDomain,
1450                              &LogonPwdData,
1451                              &ComputerName,
1452                              &SpecialAccount,
1453                              &AccountDomainSid,
1454                              &UserHandle,
1455                              &UserInfo,
1456                              SubStatus);
1457     if (!NT_SUCCESS(Status))
1458         goto done;
1459 
1460     /* Return logon information */
1461 
1462     /* Create and return a new logon id */
1463     Status = NtAllocateLocallyUniqueId(LogonId);
1464     if (!NT_SUCCESS(Status))
1465     {
1466         TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1467         goto done;
1468     }
1469 
1470     /* Create the logon session */
1471     Status = DispatchTable.CreateLogonSession(LogonId);
1472     if (!NT_SUCCESS(Status))
1473     {
1474         TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1475         goto done;
1476     }
1477 
1478     SessionCreated = TRUE;
1479 
1480     LogonEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LOGON_LIST_ENTRY));
1481     if (LogonEntry)
1482     {
1483         RtlCopyMemory(&LogonEntry->LogonId, LogonId, sizeof(LUID));
1484         LogonEntry->EnumHandle = EnumCounter;
1485         EnumCounter++;
1486 
1487         InsertTailList(&LogonListHead, &LogonEntry->ListEntry);
1488     }
1489 
1490     if (LogonType == Interactive || LogonType == Batch || LogonType == Service)
1491     {
1492         /* Build and fill the interactive profile buffer */
1493         Status = BuildInteractiveProfileBuffer(ClientRequest,
1494                                                UserInfo,
1495                                                ComputerName.Buffer,
1496                                                (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1497                                                ProfileBufferSize);
1498         if (!NT_SUCCESS(Status))
1499         {
1500             TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1501             goto done;
1502         }
1503     }
1504     else if (LogonType == Network)
1505     {
1506         //FIXME: no need to do anything, its already done ...
1507     }
1508 
1509     /* Return the token information type */
1510     *TokenInformationType = LsaTokenInformationV1;
1511 
1512     /* Build and fill the token information buffer */
1513     Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1514                                          AccountDomainSid,
1515                                          UserInfo,
1516                                          SpecialAccount);
1517     if (!NT_SUCCESS(Status))
1518     {
1519         TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1520         goto done;
1521     }
1522 
1523 done:
1524     /* Erase password */
1525     if (ErasePassword)
1526     {
1527         RtlEraseUnicodeString(ErasePassword);
1528     }
1529 
1530     /* Update the logon time/count or the bad password time/count */
1531     if ((UserHandle != NULL) &&
1532         (Status == STATUS_SUCCESS || Status == STATUS_WRONG_PASSWORD))
1533     {
1534         SAMPR_USER_INFO_BUFFER InternalInfo;
1535 
1536         RtlZeroMemory(&InternalInfo, sizeof(InternalInfo));
1537 
1538         if (Status == STATUS_SUCCESS)
1539             InternalInfo.Internal2.Flags = USER_LOGON_SUCCESS;
1540         else
1541             InternalInfo.Internal2.Flags = USER_LOGON_BAD_PASSWORD;
1542 
1543         SamrSetInformationUser(UserHandle,
1544                                UserInternal2Information,
1545                                &InternalInfo);
1546     }
1547 
1548     if (NT_SUCCESS(Status))
1549     {
1550         /* Return the account name */
1551         *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1552         if ((LogonUserName != NULL) &&
1553             (*AccountName != NULL))
1554         {
1555             (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonUserName->Length +
1556                                                                    sizeof(UNICODE_NULL));
1557             if ((*AccountName)->Buffer != NULL)
1558             {
1559                 (*AccountName)->MaximumLength = LogonUserName->Length +
1560                                                 sizeof(UNICODE_NULL);
1561                 RtlCopyUnicodeString(*AccountName, LogonUserName);
1562             }
1563         }
1564 
1565         /* Return the authenticating authority */
1566         *AuthenticatingAuthority = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1567         if ((LogonDomain != NULL) &&
1568             (*AuthenticatingAuthority != NULL))
1569         {
1570             (*AuthenticatingAuthority)->Buffer = DispatchTable.AllocateLsaHeap(LogonDomain->Length +
1571                                                                                sizeof(UNICODE_NULL));
1572             if ((*AuthenticatingAuthority)->Buffer != NULL)
1573             {
1574                 (*AuthenticatingAuthority)->MaximumLength = LogonDomain->Length +
1575                                                             sizeof(UNICODE_NULL);
1576                 RtlCopyUnicodeString(*AuthenticatingAuthority, LogonDomain);
1577             }
1578         }
1579 
1580         /* Return the machine name */
1581         *MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1582         if (*MachineName != NULL)
1583         {
1584             (*MachineName)->Buffer = DispatchTable.AllocateLsaHeap(ComputerName.MaximumLength);
1585             if ((*MachineName)->Buffer != NULL)
1586             {
1587                 (*MachineName)->MaximumLength = ComputerName.MaximumLength;
1588                 (*MachineName)->Length = ComputerName.Length;
1589                 RtlCopyMemory((*MachineName)->Buffer,
1590                               ComputerName.Buffer,
1591                               ComputerName.MaximumLength);
1592             }
1593         }
1594     }
1595 
1596     if (!NT_SUCCESS(Status))
1597     {
1598         if (SessionCreated != FALSE)
1599             DispatchTable.DeleteLogonSession(LogonId);
1600 
1601         if (*ProfileBuffer != NULL)
1602         {
1603             DispatchTable.FreeClientBuffer(ClientRequest,
1604                                            *ProfileBuffer);
1605             *ProfileBuffer = NULL;
1606         }
1607     }
1608 
1609     if (UserHandle != NULL)
1610         SamrCloseHandle(&UserHandle);
1611 
1612     SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1613                                     UserAllInformation);
1614 
1615     if (AccountDomainSid != NULL)
1616         RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1617 
1618     if (Status == STATUS_NO_SUCH_USER ||
1619         Status == STATUS_WRONG_PASSWORD)
1620     {
1621         *SubStatus = Status;
1622         Status = STATUS_LOGON_FAILURE;
1623     }
1624 
1625     TRACE("LsaApLogonUserEx2 done (Status 0x%08lx, SubStatus 0x%08lx)\n", Status, *SubStatus);
1626 
1627     return Status;
1628 }
1629 
1630 
1631 /*
1632  * @unimplemented
1633  */
1634 NTSTATUS
1635 NTAPI
SpLsaModeInitialize(_In_ ULONG LsaVersion,_Out_ PULONG PackageVersion,_Out_ PSECPKG_FUNCTION_TABLE * ppTables,_Out_ PULONG pcTables)1636 SpLsaModeInitialize(
1637     _In_ ULONG LsaVersion,
1638     _Out_ PULONG PackageVersion,
1639     _Out_ PSECPKG_FUNCTION_TABLE *ppTables,
1640     _Out_ PULONG pcTables)
1641 {
1642     TRACE("SpLsaModeInitialize(0x%lx %p %p %p)\n",
1643           LsaVersion, PackageVersion, ppTables, pcTables);
1644 
1645     if (LsaVersion != SECPKG_INTERFACE_VERSION)
1646         return STATUS_INVALID_PARAMETER;
1647 
1648     *PackageVersion = SECPKG_INTERFACE_VERSION;
1649 
1650     *ppTables = NtlmLsaFn;
1651     *pcTables = 1;
1652 
1653     return STATUS_SUCCESS;
1654 }
1655 
1656 /*
1657  * @unimplemented
1658  */
1659 NTSTATUS
1660 WINAPI
SpUserModeInitialize(_In_ ULONG LsaVersion,_Out_ PULONG PackageVersion,_Out_ PSECPKG_USER_FUNCTION_TABLE * ppTables,_Out_ PULONG pcTables)1661 SpUserModeInitialize(
1662     _In_ ULONG LsaVersion,
1663     _Out_ PULONG PackageVersion,
1664     _Out_ PSECPKG_USER_FUNCTION_TABLE *ppTables,
1665     _Out_ PULONG pcTables)
1666 {
1667     TRACE("SpUserModeInitialize(0x%lx %p %p %p)\n",
1668           LsaVersion, PackageVersion, ppTables, pcTables);
1669 
1670     if (LsaVersion != SECPKG_INTERFACE_VERSION)
1671         return STATUS_INVALID_PARAMETER;
1672 
1673     *PackageVersion = SECPKG_INTERFACE_VERSION;
1674 
1675     *ppTables = NtlmUsrFn;
1676     *pcTables = 1;
1677 
1678     return STATUS_SUCCESS;
1679 }
1680 
1681 /* EOF */
1682