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