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