[MSV1_0]
[reactos.git] / reactos / dll / win32 / msv1_0 / msv1_0.c
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 "msv1_0.h"
12
13 WINE_DEFAULT_DEBUG_CHANNEL(msv1_0);
14
15
16 /* GLOBALS *****************************************************************/
17
18 LSA_DISPATCH_TABLE DispatchTable;
19
20
21 /* FUNCTIONS ***************************************************************/
22
23 static
24 NTSTATUS
25 GetDomainSid(PRPC_SID *Sid)
26 {
27 LSAPR_HANDLE PolicyHandle = NULL;
28 PLSAPR_POLICY_INFORMATION PolicyInfo = NULL;
29 ULONG Length = 0;
30 NTSTATUS Status;
31
32 Status = LsaIOpenPolicyTrusted(&PolicyHandle);
33 if (!NT_SUCCESS(Status))
34 {
35 TRACE("LsaIOpenPolicyTrusted() failed (Status 0x%08lx)\n", Status);
36 return Status;
37 }
38
39 Status = LsarQueryInformationPolicy(PolicyHandle,
40 PolicyAccountDomainInformation,
41 &PolicyInfo);
42 if (!NT_SUCCESS(Status))
43 {
44 TRACE("LsarQueryInformationPolicy() failed (Status 0x%08lx)\n", Status);
45 goto done;
46 }
47
48 Length = RtlLengthSid(PolicyInfo->PolicyAccountDomainInfo.Sid);
49
50 *Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
51 if (*Sid == NULL)
52 {
53 ERR("Failed to allocate SID\n");
54 Status = STATUS_INSUFFICIENT_RESOURCES;
55 goto done;
56 }
57
58 memcpy(*Sid, PolicyInfo->PolicyAccountDomainInfo.Sid, Length);
59
60 done:
61 if (PolicyInfo != NULL)
62 LsaIFree_LSAPR_POLICY_INFORMATION(PolicyAccountDomainInformation,
63 PolicyInfo);
64
65 if (PolicyHandle != NULL)
66 LsarClose(&PolicyHandle);
67
68 return Status;
69 }
70
71
72 static
73 NTSTATUS
74 BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
75 IN PSAMPR_USER_INFO_BUFFER UserInfo,
76 IN PUNICODE_STRING LogonServer,
77 OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
78 OUT PULONG ProfileBufferLength)
79 {
80 PMSV1_0_INTERACTIVE_PROFILE LocalBuffer = NULL;
81 PVOID ClientBaseAddress = NULL;
82 LPWSTR Ptr;
83 ULONG BufferLength;
84 NTSTATUS Status = STATUS_SUCCESS;
85
86 *ProfileBuffer = NULL;
87 *ProfileBufferLength = 0;
88
89 BufferLength = sizeof(MSV1_0_INTERACTIVE_PROFILE) +
90 UserInfo->All.FullName.Length + sizeof(WCHAR) +
91 UserInfo->All.HomeDirectory.Length + sizeof(WCHAR) +
92 UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR) +
93 UserInfo->All.ScriptPath.Length + sizeof(WCHAR) +
94 UserInfo->All.ProfilePath.Length + sizeof(WCHAR) +
95 LogonServer->Length + sizeof(WCHAR);
96
97 LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
98 if (LocalBuffer == NULL)
99 {
100 TRACE("Failed to allocate the local buffer!\n");
101 Status = STATUS_INSUFFICIENT_RESOURCES;
102 goto done;
103 }
104
105 Status = DispatchTable.AllocateClientBuffer(ClientRequest,
106 BufferLength,
107 &ClientBaseAddress);
108 if (!NT_SUCCESS(Status))
109 {
110 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
111 goto done;
112 }
113
114 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
115
116 Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
117
118 LocalBuffer->MessageType = MsV1_0InteractiveProfile;
119 LocalBuffer->LogonCount = UserInfo->All.LogonCount;
120 LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
121
122 LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
123 LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
124
125 // LocalBuffer->LogoffTime.LowPart =
126 // LocalBuffer->LogoffTime.HighPart =
127
128 // LocalBuffer->KickOffTime.LowPart =
129 // LocalBuffer->KickOffTime.HighPart =
130
131 LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
132 LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
133
134 LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
135 LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
136
137 LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
138 LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
139
140 LocalBuffer->LogonScript.Length = UserInfo->All.ScriptPath.Length;
141 LocalBuffer->LogonScript.MaximumLength = UserInfo->All.ScriptPath.Length + sizeof(WCHAR);
142 LocalBuffer->LogonScript.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
143 memcpy(Ptr,
144 UserInfo->All.ScriptPath.Buffer,
145 UserInfo->All.ScriptPath.Length);
146
147 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
148
149 LocalBuffer->HomeDirectory.Length = UserInfo->All.HomeDirectory.Length;
150 LocalBuffer->HomeDirectory.MaximumLength = UserInfo->All.HomeDirectory.Length + sizeof(WCHAR);
151 LocalBuffer->HomeDirectory.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
152 memcpy(Ptr,
153 UserInfo->All.HomeDirectory.Buffer,
154 UserInfo->All.HomeDirectory.Length);
155
156 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
157
158 LocalBuffer->FullName.Length = UserInfo->All.FullName.Length;
159 LocalBuffer->FullName.MaximumLength = UserInfo->All.FullName.Length + sizeof(WCHAR);
160 LocalBuffer->FullName.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
161 memcpy(Ptr,
162 UserInfo->All.FullName.Buffer,
163 UserInfo->All.FullName.Length);
164 TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
165
166 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
167
168 LocalBuffer->ProfilePath.Length = UserInfo->All.ProfilePath.Length;
169 LocalBuffer->ProfilePath.MaximumLength = UserInfo->All.ProfilePath.Length + sizeof(WCHAR);
170 LocalBuffer->ProfilePath.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
171 memcpy(Ptr,
172 UserInfo->All.ProfilePath.Buffer,
173 UserInfo->All.ProfilePath.Length);
174
175 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
176
177 LocalBuffer->HomeDirectoryDrive.Length = UserInfo->All.HomeDirectoryDrive.Length;
178 LocalBuffer->HomeDirectoryDrive.MaximumLength = UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR);
179 LocalBuffer->HomeDirectoryDrive.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
180 memcpy(Ptr,
181 UserInfo->All.HomeDirectoryDrive.Buffer,
182 UserInfo->All.HomeDirectoryDrive.Length);
183
184 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
185
186 LocalBuffer->LogonServer.Length = LogonServer->Length;
187 LocalBuffer->LogonServer.MaximumLength = LogonServer->Length + sizeof(WCHAR);
188 LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);;
189 memcpy(Ptr,
190 LogonServer->Buffer,
191 LogonServer->Length);
192
193 LocalBuffer->UserFlags = 0;
194
195 Status = DispatchTable.CopyToClientBuffer(ClientRequest,
196 BufferLength,
197 ClientBaseAddress,
198 LocalBuffer);
199 if (!NT_SUCCESS(Status))
200 {
201 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
202 goto done;
203 }
204
205 *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
206 *ProfileBufferLength = BufferLength;
207
208 done:
209 if (LocalBuffer != NULL)
210 DispatchTable.FreeLsaHeap(LocalBuffer);
211
212 if (!NT_SUCCESS(Status))
213 {
214 if (ClientBaseAddress != NULL)
215 DispatchTable.FreeClientBuffer(ClientRequest,
216 ClientBaseAddress);
217 }
218
219 return Status;
220 }
221
222
223 static
224 PSID
225 AppendRidToSid(PSID SrcSid,
226 ULONG Rid)
227 {
228 PSID DstSid = NULL;
229 UCHAR RidCount;
230
231 RidCount = *RtlSubAuthorityCountSid(SrcSid);
232 if (RidCount >= 8)
233 return NULL;
234
235 DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
236 if (DstSid == NULL)
237 return NULL;
238
239 RtlCopyMemory(DstSid,
240 SrcSid,
241 RtlLengthRequiredSid(RidCount));
242
243 *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
244 *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
245
246 return DstSid;
247 }
248
249 static
250 NTSTATUS
251 BuildTokenUser(OUT PTOKEN_USER User,
252 IN PSID AccountDomainSid,
253 IN ULONG RelativeId)
254 {
255 User->User.Sid = AppendRidToSid(AccountDomainSid,
256 RelativeId);
257 if (User->User.Sid == NULL)
258 {
259 ERR("Could not create the user SID\n");
260 return STATUS_INSUFFICIENT_RESOURCES;
261 }
262
263 User->User.Attributes = 0;
264
265 return STATUS_SUCCESS;
266 }
267
268
269 static
270 NTSTATUS
271 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
272 IN PSID AccountDomainSid,
273 IN ULONG RelativeId)
274 {
275 PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
276 RelativeId);
277 if (PrimaryGroup->PrimaryGroup == NULL)
278 {
279 ERR("Could not create the primary group SID\n");
280 return STATUS_INSUFFICIENT_RESOURCES;
281 }
282
283 return STATUS_SUCCESS;
284 }
285
286
287 static
288 NTSTATUS
289 BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
290 IN PSID AccountDomainSid)
291 {
292 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
293 PTOKEN_GROUPS TokenGroups;
294 #define MAX_GROUPS 4
295 DWORD GroupCount = 0;
296 PSID Sid;
297 NTSTATUS Status = STATUS_SUCCESS;
298
299 TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
300 MAX_GROUPS * sizeof(SID_AND_ATTRIBUTES));
301 if (TokenGroups == NULL)
302 {
303 return STATUS_INSUFFICIENT_RESOURCES;
304 }
305
306 Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
307 if (Sid == NULL)
308 {
309
310 }
311
312 /* Member of the domain */
313 TokenGroups->Groups[GroupCount].Sid = Sid;
314 TokenGroups->Groups[GroupCount].Attributes =
315 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
316 GroupCount++;
317
318
319 #if 1
320 /* Member of 'Administrators' */
321 RtlAllocateAndInitializeSid(&SystemAuthority,
322 2,
323 SECURITY_BUILTIN_DOMAIN_RID,
324 DOMAIN_ALIAS_RID_ADMINS,
325 SECURITY_NULL_RID,
326 SECURITY_NULL_RID,
327 SECURITY_NULL_RID,
328 SECURITY_NULL_RID,
329 SECURITY_NULL_RID,
330 SECURITY_NULL_RID,
331 &Sid);
332 TokenGroups->Groups[GroupCount].Sid = Sid;
333 TokenGroups->Groups[GroupCount].Attributes =
334 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
335 GroupCount++;
336 #else
337 TRACE("Not adding user to Administrators group\n");
338 #endif
339
340 /* Member of 'Users' */
341 RtlAllocateAndInitializeSid(&SystemAuthority,
342 2,
343 SECURITY_BUILTIN_DOMAIN_RID,
344 DOMAIN_ALIAS_RID_USERS,
345 SECURITY_NULL_RID,
346 SECURITY_NULL_RID,
347 SECURITY_NULL_RID,
348 SECURITY_NULL_RID,
349 SECURITY_NULL_RID,
350 SECURITY_NULL_RID,
351 &Sid);
352 TokenGroups->Groups[GroupCount].Sid = Sid;
353 TokenGroups->Groups[GroupCount].Attributes =
354 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
355 GroupCount++;
356
357
358 /* Member of 'Authenticated users' */
359 RtlAllocateAndInitializeSid(&SystemAuthority,
360 1,
361 SECURITY_AUTHENTICATED_USER_RID,
362 SECURITY_NULL_RID,
363 SECURITY_NULL_RID,
364 SECURITY_NULL_RID,
365 SECURITY_NULL_RID,
366 SECURITY_NULL_RID,
367 SECURITY_NULL_RID,
368 SECURITY_NULL_RID,
369 &Sid);
370 TokenGroups->Groups[GroupCount].Sid = Sid;
371 TokenGroups->Groups[GroupCount].Attributes =
372 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
373 GroupCount++;
374
375 TokenGroups->GroupCount = GroupCount;
376 ASSERT(TokenGroups->GroupCount <= MAX_GROUPS);
377
378 *Groups = TokenGroups;
379
380 return Status;
381 }
382
383
384 static
385 NTSTATUS
386 BuildTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges)
387 {
388 /* FIXME shouldn't use hard-coded list of privileges */
389 static struct
390 {
391 LPCWSTR PrivName;
392 DWORD Attributes;
393 }
394 DefaultPrivs[] =
395 {
396 { L"SeMachineAccountPrivilege", 0 },
397 { L"SeSecurityPrivilege", 0 },
398 { L"SeTakeOwnershipPrivilege", 0 },
399 { L"SeLoadDriverPrivilege", 0 },
400 { L"SeSystemProfilePrivilege", 0 },
401 { L"SeSystemtimePrivilege", 0 },
402 { L"SeProfileSingleProcessPrivilege", 0 },
403 { L"SeIncreaseBasePriorityPrivilege", 0 },
404 { L"SeCreatePagefilePrivilege", 0 },
405 { L"SeBackupPrivilege", 0 },
406 { L"SeRestorePrivilege", 0 },
407 { L"SeShutdownPrivilege", 0 },
408 { L"SeDebugPrivilege", 0 },
409 { L"SeSystemEnvironmentPrivilege", 0 },
410 { L"SeChangeNotifyPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
411 { L"SeRemoteShutdownPrivilege", 0 },
412 { L"SeUndockPrivilege", 0 },
413 { L"SeEnableDelegationPrivilege", 0 },
414 { L"SeImpersonatePrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT },
415 { L"SeCreateGlobalPrivilege", SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT }
416 };
417 PTOKEN_PRIVILEGES Privileges = NULL;
418 ULONG i;
419 RPC_UNICODE_STRING PrivilegeName;
420 LSAPR_HANDLE PolicyHandle = NULL;
421 NTSTATUS Status = STATUS_SUCCESS;
422
423 Status = LsaIOpenPolicyTrusted(&PolicyHandle);
424 if (!NT_SUCCESS(Status))
425 {
426 goto done;
427 }
428
429 /* Allocate and initialize token privileges */
430 Privileges = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_PRIVILEGES) +
431 sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]) *
432 sizeof(LUID_AND_ATTRIBUTES));
433 if (Privileges == NULL)
434 {
435 Status = STATUS_INSUFFICIENT_RESOURCES;
436 goto done;
437 }
438
439 Privileges->PrivilegeCount = 0;
440 for (i = 0; i < sizeof(DefaultPrivs) / sizeof(DefaultPrivs[0]); i++)
441 {
442 PrivilegeName.Length = wcslen(DefaultPrivs[i].PrivName) * sizeof(WCHAR);
443 PrivilegeName.MaximumLength = PrivilegeName.Length + sizeof(WCHAR);
444 PrivilegeName.Buffer = (LPWSTR)DefaultPrivs[i].PrivName;
445
446 Status = LsarLookupPrivilegeValue(PolicyHandle,
447 &PrivilegeName,
448 &Privileges->Privileges[Privileges->PrivilegeCount].Luid);
449 if (!NT_SUCCESS(Status))
450 {
451 WARN("Can't set privilege %S\n", DefaultPrivs[i].PrivName);
452 }
453 else
454 {
455 Privileges->Privileges[Privileges->PrivilegeCount].Attributes = DefaultPrivs[i].Attributes;
456 Privileges->PrivilegeCount++;
457 }
458 }
459
460 *TokenPrivileges = Privileges;
461
462 done:
463 if (PolicyHandle != NULL)
464 LsarClose(&PolicyHandle);
465
466 return Status;
467 }
468
469
470 static
471 NTSTATUS
472 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
473 PRPC_SID AccountDomainSid,
474 PSAMPR_USER_INFO_BUFFER UserInfo)
475 {
476 PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
477 ULONG i;
478 NTSTATUS Status = STATUS_SUCCESS;
479
480 Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
481 if (Buffer == NULL)
482 {
483 TRACE("Failed to allocate the local buffer!\n");
484 Status = STATUS_INSUFFICIENT_RESOURCES;
485 goto done;
486 }
487
488 /* FIXME: */
489 Buffer->ExpirationTime.QuadPart = -1;
490
491 Status = BuildTokenUser(&Buffer->User,
492 (PSID)AccountDomainSid,
493 UserInfo->All.UserId);
494 if (!NT_SUCCESS(Status))
495 goto done;
496
497 Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
498 (PSID)AccountDomainSid,
499 UserInfo->All.PrimaryGroupId);
500 if (!NT_SUCCESS(Status))
501 goto done;
502
503 Status = BuildTokenGroups(&Buffer->Groups,
504 (PSID)AccountDomainSid);
505 if (!NT_SUCCESS(Status))
506 goto done;
507
508 Status = BuildTokenPrivileges(&Buffer->Privileges);
509 if (!NT_SUCCESS(Status))
510 goto done;
511
512 *TokenInformation = Buffer;
513
514 done:
515 if (!NT_SUCCESS(Status))
516 {
517 if (Buffer != NULL)
518 {
519 if (Buffer->User.User.Sid != NULL)
520 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
521
522 if (Buffer->Groups != NULL)
523 {
524 for (i = 0; i < Buffer->Groups->GroupCount; i++)
525 {
526 if (Buffer->Groups->Groups[i].Sid != NULL)
527 DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
528 }
529
530 DispatchTable.FreeLsaHeap(Buffer->Groups);
531 }
532
533 if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
534 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
535
536 if (Buffer->Privileges != NULL)
537 DispatchTable.FreeLsaHeap(Buffer->Privileges);
538
539 if (Buffer->DefaultDacl.DefaultDacl != NULL)
540 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
541
542 DispatchTable.FreeLsaHeap(Buffer);
543 }
544 }
545
546 return Status;
547 }
548
549
550 static
551 NTSTATUS
552 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
553 IN PVOID ProtocolSubmitBuffer,
554 IN PVOID ClientBufferBase,
555 IN ULONG SubmitBufferLength,
556 OUT PVOID *ProtocolReturnBuffer,
557 OUT PULONG ReturnBufferLength,
558 OUT PNTSTATUS ProtocolStatus)
559 {
560 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
561 ULONG_PTR PtrOffset;
562
563 TRACE("()\n");
564
565 RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
566
567 /* Fix-up pointers in the request buffer info */
568 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
569
570 RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
571 RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
572 RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
573 RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
574
575 TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
576 TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
577 TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
578 TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
579
580
581 return STATUS_SUCCESS;
582 }
583
584
585 static
586 NTSTATUS
587 MsvpCheckPassword(PUNICODE_STRING UserPassword,
588 PSAMPR_USER_INFO_BUFFER UserInfo)
589 {
590 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
591 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
592 BOOLEAN UserLmPasswordPresent = FALSE;
593 BOOLEAN UserNtPasswordPresent = FALSE;
594 OEM_STRING LmPwdString;
595 CHAR LmPwdBuffer[15];
596 NTSTATUS Status;
597
598 TRACE("(%p %p)\n", UserPassword, UserInfo);
599
600 /* Calculate the LM password and hash for the users password */
601 LmPwdString.Length = 15;
602 LmPwdString.MaximumLength = 15;
603 LmPwdString.Buffer = LmPwdBuffer;
604 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
605
606 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
607 UserPassword,
608 FALSE);
609 if (NT_SUCCESS(Status))
610 {
611 /* Calculate the LM hash value of the users password */
612 Status = SystemFunction006(LmPwdString.Buffer,
613 (LPSTR)&UserLmPassword);
614 if (NT_SUCCESS(Status))
615 {
616 UserLmPasswordPresent = TRUE;
617 }
618 }
619
620 /* Calculate the NT hash of the users password */
621 Status = SystemFunction007(UserPassword,
622 (LPBYTE)&UserNtPassword);
623 if (NT_SUCCESS(Status))
624 {
625 UserNtPasswordPresent = TRUE;
626 }
627
628 Status = STATUS_WRONG_PASSWORD;
629
630 /* Succeed, if no password has been set */
631 if (UserInfo->All.NtPasswordPresent == FALSE &&
632 UserInfo->All.LmPasswordPresent == FALSE)
633 {
634 TRACE("No password check!\n");
635 Status = STATUS_SUCCESS;
636 goto done;
637 }
638
639 /* Succeed, if NT password matches */
640 if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
641 {
642 TRACE("Check NT password hashes:\n");
643 if (RtlEqualMemory(&UserNtPassword,
644 UserInfo->All.NtOwfPassword.Buffer,
645 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
646 {
647 TRACE(" success!\n");
648 Status = STATUS_SUCCESS;
649 goto done;
650 }
651
652 TRACE(" failed!\n");
653 }
654
655 /* Succeed, if LM password matches */
656 if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
657 {
658 TRACE("Check LM password hashes:\n");
659 if (RtlEqualMemory(&UserLmPassword,
660 UserInfo->All.LmOwfPassword.Buffer,
661 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
662 {
663 TRACE(" success!\n");
664 Status = STATUS_SUCCESS;
665 goto done;
666 }
667 TRACE(" failed!\n");
668 }
669
670 done:
671 return Status;
672 }
673
674
675 /*
676 * @unimplemented
677 */
678 NTSTATUS
679 NTAPI
680 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
681 IN PVOID ProtocolSubmitBuffer,
682 IN PVOID ClientBufferBase,
683 IN ULONG SubmitBufferLength,
684 OUT PVOID *ProtocolReturnBuffer,
685 OUT PULONG ReturnBufferLength,
686 OUT PNTSTATUS ProtocolStatus)
687 {
688 ULONG MessageType;
689 NTSTATUS Status;
690
691 TRACE("()\n");
692
693 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
694 return STATUS_INVALID_PARAMETER;
695
696 MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
697
698 *ProtocolReturnBuffer = NULL;
699 *ReturnBufferLength = 0;
700
701 switch (MessageType)
702 {
703 case MsV1_0Lm20ChallengeRequest:
704 case MsV1_0Lm20GetChallengeResponse:
705 case MsV1_0EnumerateUsers:
706 case MsV1_0GetUserInfo:
707 case MsV1_0ReLogonUsers:
708 Status = STATUS_NOT_IMPLEMENTED;
709 break;
710
711 case MsV1_0ChangePassword:
712 Status = MsvpChangePassword(ClientRequest,
713 ProtocolSubmitBuffer,
714 ClientBufferBase,
715 SubmitBufferLength,
716 ProtocolReturnBuffer,
717 ReturnBufferLength,
718 ProtocolStatus);
719 break;
720
721 case MsV1_0ChangeCachedPassword:
722 case MsV1_0GenericPassthrough:
723 case MsV1_0CacheLogon:
724 case MsV1_0SubAuth:
725 case MsV1_0DeriveCredential:
726 case MsV1_0CacheLookup:
727 Status = STATUS_NOT_IMPLEMENTED;
728 break;
729
730 default:
731 return STATUS_INVALID_PARAMETER;
732 }
733
734 return Status;
735 }
736
737
738 /*
739 * @unimplemented
740 */
741 NTSTATUS
742 NTAPI
743 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,
744 IN PVOID ProtocolSubmitBuffer,
745 IN PVOID ClientBufferBase,
746 IN ULONG SubmitBufferLength,
747 OUT PVOID *ProtocolReturnBuffer,
748 OUT PULONG ReturnBufferLength,
749 OUT PNTSTATUS ProtocolStatus)
750 {
751 TRACE("()\n");
752 return STATUS_NOT_IMPLEMENTED;
753 }
754
755
756 /*
757 * @unimplemented
758 */
759 NTSTATUS
760 NTAPI
761 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
762 IN PVOID ProtocolSubmitBuffer,
763 IN PVOID ClientBufferBase,
764 IN ULONG SubmitBufferLength,
765 OUT PVOID *ProtocolReturnBuffer,
766 OUT PULONG ReturnBufferLength,
767 OUT PNTSTATUS ProtocolStatus)
768 {
769 TRACE("()\n");
770 return STATUS_NOT_IMPLEMENTED;
771 }
772
773
774 /*
775 * @unimplemented
776 */
777 NTSTATUS
778 NTAPI
779 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
780 IN PLSA_DISPATCH_TABLE LsaDispatchTable,
781 IN PLSA_STRING Database OPTIONAL,
782 IN PLSA_STRING Confidentiality OPTIONAL,
783 OUT PLSA_STRING *AuthenticationPackageName)
784 {
785 PANSI_STRING NameString;
786 PCHAR NameBuffer;
787
788 TRACE("(%lu %p %p %p %p)\n",
789 AuthenticationPackageId, LsaDispatchTable, Database,
790 Confidentiality, AuthenticationPackageName);
791
792 /* Get the dispatch table entries */
793 DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
794 DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
795 DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
796 DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
797 DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
798 DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
799 DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
800 DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
801 DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
802 DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
803 DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
804
805 /* Return the package name */
806 NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
807 if (NameString == NULL)
808 return STATUS_INSUFFICIENT_RESOURCES;
809
810 NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
811 if (NameBuffer == NULL)
812 {
813 DispatchTable.FreeLsaHeap(NameString);
814 return STATUS_INSUFFICIENT_RESOURCES;
815 }
816
817 strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
818
819 RtlInitAnsiString(NameString, NameBuffer);
820
821 *AuthenticationPackageName = (PLSA_STRING)NameString;
822
823 return STATUS_SUCCESS;
824 }
825
826
827 /*
828 * @unimplemented
829 */
830 VOID
831 NTAPI
832 LsaApLogonTerminated(IN PLUID LogonId)
833 {
834 TRACE("()\n");
835 }
836
837
838 /*
839 * @unimplemented
840 */
841 NTSTATUS
842 NTAPI
843 LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
844 IN SECURITY_LOGON_TYPE LogonType,
845 IN PVOID AuthenticationInformation,
846 IN PVOID ClientAuthenticationBase,
847 IN ULONG AuthenticationInformationLength,
848 OUT PVOID *ProfileBuffer,
849 OUT PULONG ProfileBufferLength,
850 OUT PLUID LogonId,
851 OUT PNTSTATUS SubStatus,
852 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
853 OUT PVOID *TokenInformation,
854 OUT PLSA_UNICODE_STRING *AccountName,
855 OUT PLSA_UNICODE_STRING *AuthenticatingAuthority)
856 {
857 PMSV1_0_INTERACTIVE_LOGON LogonInfo;
858
859 SAMPR_HANDLE ServerHandle = NULL;
860 SAMPR_HANDLE DomainHandle = NULL;
861 SAMPR_HANDLE UserHandle = NULL;
862 PRPC_SID AccountDomainSid = NULL;
863 RPC_UNICODE_STRING Names[1];
864 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
865 SAMPR_ULONG_ARRAY Use = {0, NULL};
866 PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
867 UNICODE_STRING LogonServer;
868 BOOLEAN SessionCreated = FALSE;
869 NTSTATUS Status;
870
871 TRACE("()\n");
872
873 TRACE("LogonType: %lu\n", LogonType);
874 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
875 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
876
877 *ProfileBuffer = NULL;
878 *ProfileBufferLength = 0;
879 *SubStatus = STATUS_SUCCESS;
880
881 if (LogonType == Interactive ||
882 LogonType == Batch ||
883 LogonType == Service)
884 {
885 ULONG_PTR PtrOffset;
886
887 LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)AuthenticationInformation;
888
889 /* Fix-up pointers in the authentication info */
890 PtrOffset = (ULONG_PTR)AuthenticationInformation - (ULONG_PTR)ClientAuthenticationBase;
891
892 LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
893 LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
894 LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
895
896 TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
897 TRACE("User: %S\n", LogonInfo->UserName.Buffer);
898 TRACE("Password: %S\n", LogonInfo->Password.Buffer);
899
900 RtlInitUnicodeString(&LogonServer, L"Testserver");
901 }
902 else
903 {
904 FIXME("LogonType %lu is not supported yet!\n", LogonType);
905 return STATUS_NOT_IMPLEMENTED;
906 }
907
908 Status = GetDomainSid(&AccountDomainSid);
909 if (!NT_SUCCESS(Status))
910 {
911 TRACE("GetDomainSid() failed (Status 0x%08lx)\n", Status);
912 return Status;
913 }
914
915 /* Connect to the SAM server */
916 Status = SamIConnect(NULL,
917 &ServerHandle,
918 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
919 TRUE);
920 if (!NT_SUCCESS(Status))
921 {
922 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
923 goto done;
924 }
925
926 /* Open the account domain */
927 Status = SamrOpenDomain(ServerHandle,
928 DOMAIN_LOOKUP,
929 AccountDomainSid,
930 &DomainHandle);
931 if (!NT_SUCCESS(Status))
932 {
933 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
934 goto done;
935 }
936
937 Names[0].Length = LogonInfo->UserName.Length;
938 Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
939 Names[0].Buffer = LogonInfo->UserName.Buffer;
940
941 /* Try to get the RID for the user name */
942 Status = SamrLookupNamesInDomain(DomainHandle,
943 1,
944 Names,
945 &RelativeIds,
946 &Use);
947 if (!NT_SUCCESS(Status))
948 {
949 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
950 Status = STATUS_NO_SUCH_USER;
951 goto done;
952 }
953
954 /* Fail, if it is not a user account */
955 if (Use.Element[0] != SidTypeUser)
956 {
957 TRACE("Account is not a user account!\n");
958 Status = STATUS_NO_SUCH_USER;
959 goto done;
960 }
961
962 /* Open the user object */
963 Status = SamrOpenUser(DomainHandle,
964 USER_READ_GENERAL | USER_READ_LOGON |
965 USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
966 RelativeIds.Element[0],
967 &UserHandle);
968 if (!NT_SUCCESS(Status))
969 {
970 TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
971 goto done;
972 }
973
974 Status = SamrQueryInformationUser(UserHandle,
975 UserAllInformation,
976 &UserInfo);
977 if (!NT_SUCCESS(Status))
978 {
979 TRACE("SamrQueryInformationUser failed (Status %08lx)\n", Status);
980 goto done;
981 }
982
983
984 TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
985
986 /* FIXME: Check restrictions */
987
988 /* Check the password */
989 if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
990 {
991 Status = MsvpCheckPassword(&(LogonInfo->Password),
992 UserInfo);
993 if (!NT_SUCCESS(Status))
994 {
995 TRACE("MsvpCheckPassword failed (Status %08lx)\n", Status);
996 goto done;
997 }
998 }
999
1000 /* Return logon information */
1001
1002 /* Create and return a new logon id */
1003 Status = NtAllocateLocallyUniqueId(LogonId);
1004 if (!NT_SUCCESS(Status))
1005 {
1006 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1007 goto done;
1008 }
1009
1010 /* Create the logon session */
1011 Status = DispatchTable.CreateLogonSession(LogonId);
1012 if (!NT_SUCCESS(Status))
1013 {
1014 TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1015 goto done;
1016 }
1017
1018 SessionCreated = TRUE;
1019
1020 /* Build and fill the interactve profile buffer */
1021 Status = BuildInteractiveProfileBuffer(ClientRequest,
1022 UserInfo,
1023 &LogonServer,
1024 (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1025 ProfileBufferLength);
1026 if (!NT_SUCCESS(Status))
1027 {
1028 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1029 goto done;
1030 }
1031
1032 /* Return the token information type */
1033 *TokenInformationType = LsaTokenInformationV1;
1034
1035 /* Build and fill the token information buffer */
1036 Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1037 AccountDomainSid,
1038 UserInfo);
1039 if (!NT_SUCCESS(Status))
1040 {
1041 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1042 goto done;
1043 }
1044
1045 done:
1046 /* Return the account name */
1047 *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1048 if (*AccountName != NULL)
1049 {
1050 (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1051 sizeof(UNICODE_NULL));
1052 if ((*AccountName)->Buffer != NULL)
1053 {
1054 (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1055 sizeof(UNICODE_NULL);
1056 RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1057 }
1058 }
1059
1060 if (!NT_SUCCESS(Status))
1061 {
1062 if (SessionCreated == TRUE)
1063 DispatchTable.DeleteLogonSession(LogonId);
1064
1065 if (*ProfileBuffer != NULL)
1066 {
1067 DispatchTable.FreeClientBuffer(ClientRequest,
1068 *ProfileBuffer);
1069 *ProfileBuffer = NULL;
1070 }
1071 }
1072
1073 if (UserHandle != NULL)
1074 SamrCloseHandle(&UserHandle);
1075
1076 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1077 UserAllInformation);
1078 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1079 SamIFree_SAMPR_ULONG_ARRAY(&Use);
1080
1081 if (DomainHandle != NULL)
1082 SamrCloseHandle(&DomainHandle);
1083
1084 if (ServerHandle != NULL)
1085 SamrCloseHandle(&ServerHandle);
1086
1087 if (AccountDomainSid != NULL)
1088 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1089
1090 if (Status == STATUS_NO_SUCH_USER ||
1091 Status == STATUS_WRONG_PASSWORD)
1092 {
1093 *SubStatus = Status;
1094 Status = STATUS_LOGON_FAILURE;
1095 }
1096
1097 TRACE("LsaApLogonUser done (Status %08lx)\n", Status);
1098
1099 return Status;
1100 }
1101
1102
1103 /*
1104 * @unimplemented
1105 */
1106 #if 0
1107 NTSTATUS
1108 NTAPI
1109 LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest,
1110 IN SECURITY_LOGON_TYPE LogonType,
1111 IN PVOID AuthenticationInformation,
1112 IN PVOID ClientAuthenticationBase,
1113 IN ULONG AuthenticationInformationLength,
1114 OUT PVOID *ProfileBuffer,
1115 OUT PULONG ProfileBufferLength,
1116 OUT PLUID LogonId,
1117 OUT PNTSTATUS SubStatus,
1118 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1119 OUT PVOID *TokenInformation,
1120 OUT PUNICODE_STRING *AccountName,
1121 OUT PUNICODE_STRING *AuthenticatingAuthority,
1122 OUT PUNICODE_STRING *MachineName)
1123 {
1124 TRACE("()\n");
1125
1126 TRACE("LogonType: %lu\n", LogonType);
1127 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
1128 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
1129
1130 return STATUS_NOT_IMPLEMENTED;
1131 }
1132
1133
1134 /*
1135 * @unimplemented
1136 */
1137 NTSTATUS
1138 NTAPI
1139 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1140 IN SECURITY_LOGON_TYPE LogonType,
1141 IN PVOID ProtocolSubmitBuffer,
1142 IN PVOID ClientBufferBase,
1143 IN ULONG SubmitBufferSize,
1144 OUT PVOID *ProfileBuffer,
1145 OUT PULONG ProfileBufferSize,
1146 OUT PLUID LogonId,
1147 OUT PNTSTATUS SubStatus,
1148 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1149 OUT PVOID *TokenInformation,
1150 OUT PUNICODE_STRING *AccountName,
1151 OUT PUNICODE_STRING *AuthenticatingAuthority,
1152 OUT PUNICODE_STRING *MachineName,
1153 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
1154 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials)
1155 {
1156 TRACE("()\n");
1157
1158 TRACE("LogonType: %lu\n", LogonType);
1159 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1160 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1161
1162
1163 return STATUS_NOT_IMPLEMENTED;
1164 }
1165 #endif
1166
1167 /* EOF */