8c9a1b617b8084d0388455c1468b7c61aea56f99
[reactos.git] / 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 GetAccountDomainSid(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 GetNtAuthorityDomainSid(PRPC_SID *Sid)
75 {
76 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
77 ULONG Length = 0;
78
79 Length = RtlLengthRequiredSid(0);
80 *Sid = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
81 if (*Sid == NULL)
82 {
83 ERR("Failed to allocate SID\n");
84 return STATUS_INSUFFICIENT_RESOURCES;
85 }
86
87 RtlInitializeSid(*Sid,&NtAuthority, 0);
88
89 return STATUS_SUCCESS;
90 }
91
92
93 static
94 NTSTATUS
95 BuildInteractiveProfileBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
96 IN PSAMPR_USER_INFO_BUFFER UserInfo,
97 IN PUNICODE_STRING LogonServer,
98 OUT PMSV1_0_INTERACTIVE_PROFILE *ProfileBuffer,
99 OUT PULONG ProfileBufferLength)
100 {
101 PMSV1_0_INTERACTIVE_PROFILE LocalBuffer = NULL;
102 PVOID ClientBaseAddress = NULL;
103 LPWSTR Ptr;
104 ULONG BufferLength;
105 NTSTATUS Status = STATUS_SUCCESS;
106
107 *ProfileBuffer = NULL;
108 *ProfileBufferLength = 0;
109
110 BufferLength = sizeof(MSV1_0_INTERACTIVE_PROFILE) +
111 UserInfo->All.FullName.Length + sizeof(WCHAR) +
112 UserInfo->All.HomeDirectory.Length + sizeof(WCHAR) +
113 UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR) +
114 UserInfo->All.ScriptPath.Length + sizeof(WCHAR) +
115 UserInfo->All.ProfilePath.Length + sizeof(WCHAR) +
116 LogonServer->Length + sizeof(WCHAR);
117
118 LocalBuffer = DispatchTable.AllocateLsaHeap(BufferLength);
119 if (LocalBuffer == NULL)
120 {
121 TRACE("Failed to allocate the local buffer!\n");
122 Status = STATUS_INSUFFICIENT_RESOURCES;
123 goto done;
124 }
125
126 Status = DispatchTable.AllocateClientBuffer(ClientRequest,
127 BufferLength,
128 &ClientBaseAddress);
129 if (!NT_SUCCESS(Status))
130 {
131 TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status);
132 goto done;
133 }
134
135 TRACE("ClientBaseAddress: %p\n", ClientBaseAddress);
136
137 Ptr = (LPWSTR)((ULONG_PTR)LocalBuffer + sizeof(MSV1_0_INTERACTIVE_PROFILE));
138
139 LocalBuffer->MessageType = MsV1_0InteractiveProfile;
140 LocalBuffer->LogonCount = UserInfo->All.LogonCount;
141 LocalBuffer->BadPasswordCount = UserInfo->All.BadPasswordCount;
142
143 LocalBuffer->LogonTime.LowPart = UserInfo->All.LastLogon.LowPart;
144 LocalBuffer->LogonTime.HighPart = UserInfo->All.LastLogon.HighPart;
145
146 // LocalBuffer->LogoffTime.LowPart =
147 // LocalBuffer->LogoffTime.HighPart =
148
149 // LocalBuffer->KickOffTime.LowPart =
150 // LocalBuffer->KickOffTime.HighPart =
151
152 LocalBuffer->PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
153 LocalBuffer->PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
154
155 LocalBuffer->PasswordCanChange.LowPart = UserInfo->All.PasswordCanChange.LowPart;
156 LocalBuffer->PasswordCanChange.HighPart = UserInfo->All.PasswordCanChange.HighPart;
157
158 LocalBuffer->PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
159 LocalBuffer->PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
160
161 LocalBuffer->LogonScript.Length = UserInfo->All.ScriptPath.Length;
162 LocalBuffer->LogonScript.MaximumLength = UserInfo->All.ScriptPath.Length + sizeof(WCHAR);
163 LocalBuffer->LogonScript.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
164 memcpy(Ptr,
165 UserInfo->All.ScriptPath.Buffer,
166 UserInfo->All.ScriptPath.Length);
167
168 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->LogonScript.MaximumLength);
169
170 LocalBuffer->HomeDirectory.Length = UserInfo->All.HomeDirectory.Length;
171 LocalBuffer->HomeDirectory.MaximumLength = UserInfo->All.HomeDirectory.Length + sizeof(WCHAR);
172 LocalBuffer->HomeDirectory.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
173 memcpy(Ptr,
174 UserInfo->All.HomeDirectory.Buffer,
175 UserInfo->All.HomeDirectory.Length);
176
177 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectory.MaximumLength);
178
179 LocalBuffer->FullName.Length = UserInfo->All.FullName.Length;
180 LocalBuffer->FullName.MaximumLength = UserInfo->All.FullName.Length + sizeof(WCHAR);
181 LocalBuffer->FullName.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
182 memcpy(Ptr,
183 UserInfo->All.FullName.Buffer,
184 UserInfo->All.FullName.Length);
185 TRACE("FullName.Buffer: %p\n", LocalBuffer->FullName.Buffer);
186
187 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->FullName.MaximumLength);
188
189 LocalBuffer->ProfilePath.Length = UserInfo->All.ProfilePath.Length;
190 LocalBuffer->ProfilePath.MaximumLength = UserInfo->All.ProfilePath.Length + sizeof(WCHAR);
191 LocalBuffer->ProfilePath.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
192 memcpy(Ptr,
193 UserInfo->All.ProfilePath.Buffer,
194 UserInfo->All.ProfilePath.Length);
195
196 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->ProfilePath.MaximumLength);
197
198 LocalBuffer->HomeDirectoryDrive.Length = UserInfo->All.HomeDirectoryDrive.Length;
199 LocalBuffer->HomeDirectoryDrive.MaximumLength = UserInfo->All.HomeDirectoryDrive.Length + sizeof(WCHAR);
200 LocalBuffer->HomeDirectoryDrive.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
201 memcpy(Ptr,
202 UserInfo->All.HomeDirectoryDrive.Buffer,
203 UserInfo->All.HomeDirectoryDrive.Length);
204
205 Ptr = (LPWSTR)((ULONG_PTR)Ptr + LocalBuffer->HomeDirectoryDrive.MaximumLength);
206
207 LocalBuffer->LogonServer.Length = LogonServer->Length;
208 LocalBuffer->LogonServer.MaximumLength = LogonServer->Length + sizeof(WCHAR);
209 LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
210 memcpy(Ptr,
211 LogonServer->Buffer,
212 LogonServer->Length);
213
214 LocalBuffer->UserFlags = 0;
215
216 Status = DispatchTable.CopyToClientBuffer(ClientRequest,
217 BufferLength,
218 ClientBaseAddress,
219 LocalBuffer);
220 if (!NT_SUCCESS(Status))
221 {
222 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
223 goto done;
224 }
225
226 *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
227 *ProfileBufferLength = BufferLength;
228
229 done:
230 if (LocalBuffer != NULL)
231 DispatchTable.FreeLsaHeap(LocalBuffer);
232
233 if (!NT_SUCCESS(Status))
234 {
235 if (ClientBaseAddress != NULL)
236 DispatchTable.FreeClientBuffer(ClientRequest,
237 ClientBaseAddress);
238 }
239
240 return Status;
241 }
242
243
244 static
245 PSID
246 AppendRidToSid(PSID SrcSid,
247 ULONG Rid)
248 {
249 PSID DstSid = NULL;
250 UCHAR RidCount;
251
252 RidCount = *RtlSubAuthorityCountSid(SrcSid);
253 if (RidCount >= 8)
254 return NULL;
255
256 DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
257 if (DstSid == NULL)
258 return NULL;
259
260 RtlCopyMemory(DstSid,
261 SrcSid,
262 RtlLengthRequiredSid(RidCount));
263
264 *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
265 *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
266
267 return DstSid;
268 }
269
270 static
271 NTSTATUS
272 BuildTokenUser(OUT PTOKEN_USER User,
273 IN PSID AccountDomainSid,
274 IN ULONG RelativeId)
275 {
276 User->User.Sid = AppendRidToSid(AccountDomainSid,
277 RelativeId);
278 if (User->User.Sid == NULL)
279 {
280 ERR("Could not create the user SID\n");
281 return STATUS_INSUFFICIENT_RESOURCES;
282 }
283
284 User->User.Attributes = 0;
285
286 return STATUS_SUCCESS;
287 }
288
289
290 static
291 NTSTATUS
292 BuildTokenPrimaryGroup(OUT PTOKEN_PRIMARY_GROUP PrimaryGroup,
293 IN PSID AccountDomainSid,
294 IN ULONG RelativeId)
295 {
296 PrimaryGroup->PrimaryGroup = AppendRidToSid(AccountDomainSid,
297 RelativeId);
298 if (PrimaryGroup->PrimaryGroup == NULL)
299 {
300 ERR("Could not create the primary group SID\n");
301 return STATUS_INSUFFICIENT_RESOURCES;
302 }
303
304 return STATUS_SUCCESS;
305 }
306
307
308 static
309 NTSTATUS
310 BuildTokenGroups(OUT PTOKEN_GROUPS *Groups,
311 IN PSID AccountDomainSid,
312 IN ULONG RelativeId,
313 IN BOOL SpecialAccount)
314 {
315 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
316 PTOKEN_GROUPS TokenGroups;
317 DWORD GroupCount = 0;
318 DWORD MaxGroups = 2;
319 PSID Sid;
320 NTSTATUS Status = STATUS_SUCCESS;
321
322 if (SpecialAccount)
323 MaxGroups++;
324
325 TokenGroups = DispatchTable.AllocateLsaHeap(sizeof(TOKEN_GROUPS) +
326 MaxGroups * sizeof(SID_AND_ATTRIBUTES));
327 if (TokenGroups == NULL)
328 {
329 return STATUS_INSUFFICIENT_RESOURCES;
330 }
331
332 if (SpecialAccount)
333 {
334 /* Self */
335 Sid = AppendRidToSid(AccountDomainSid, RelativeId);
336 if (Sid == NULL)
337 {
338
339 }
340
341 TokenGroups->Groups[GroupCount].Sid = Sid;
342 TokenGroups->Groups[GroupCount].Attributes =
343 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
344 GroupCount++;
345
346 /* Member of 'Users' alias */
347 RtlAllocateAndInitializeSid(&SystemAuthority,
348 2,
349 SECURITY_BUILTIN_DOMAIN_RID,
350 DOMAIN_ALIAS_RID_USERS,
351 SECURITY_NULL_RID,
352 SECURITY_NULL_RID,
353 SECURITY_NULL_RID,
354 SECURITY_NULL_RID,
355 SECURITY_NULL_RID,
356 SECURITY_NULL_RID,
357 &Sid);
358 TokenGroups->Groups[GroupCount].Sid = Sid;
359 TokenGroups->Groups[GroupCount].Attributes =
360 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
361 GroupCount++;
362 }
363 else
364 {
365 /* Member of the domains users group */
366 Sid = AppendRidToSid(AccountDomainSid, DOMAIN_GROUP_RID_USERS);
367 if (Sid == NULL)
368 {
369
370 }
371
372 TokenGroups->Groups[GroupCount].Sid = Sid;
373 TokenGroups->Groups[GroupCount].Attributes =
374 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
375 GroupCount++;
376 }
377
378 /* Member of 'Authenticated users' */
379 RtlAllocateAndInitializeSid(&SystemAuthority,
380 1,
381 SECURITY_AUTHENTICATED_USER_RID,
382 SECURITY_NULL_RID,
383 SECURITY_NULL_RID,
384 SECURITY_NULL_RID,
385 SECURITY_NULL_RID,
386 SECURITY_NULL_RID,
387 SECURITY_NULL_RID,
388 SECURITY_NULL_RID,
389 &Sid);
390 TokenGroups->Groups[GroupCount].Sid = Sid;
391 TokenGroups->Groups[GroupCount].Attributes =
392 SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
393 GroupCount++;
394
395 TokenGroups->GroupCount = GroupCount;
396 ASSERT(TokenGroups->GroupCount <= MaxGroups);
397
398 *Groups = TokenGroups;
399
400 return Status;
401 }
402
403
404 static
405 NTSTATUS
406 BuildTokenInformationBuffer(PLSA_TOKEN_INFORMATION_V1 *TokenInformation,
407 PRPC_SID AccountDomainSid,
408 PSAMPR_USER_INFO_BUFFER UserInfo,
409 BOOL SpecialAccount)
410 {
411 PLSA_TOKEN_INFORMATION_V1 Buffer = NULL;
412 ULONG i;
413 NTSTATUS Status = STATUS_SUCCESS;
414
415 Buffer = DispatchTable.AllocateLsaHeap(sizeof(LSA_TOKEN_INFORMATION_V1));
416 if (Buffer == NULL)
417 {
418 TRACE("Failed to allocate the local buffer!\n");
419 Status = STATUS_INSUFFICIENT_RESOURCES;
420 goto done;
421 }
422
423 /* FIXME: */
424 Buffer->ExpirationTime.QuadPart = -1;
425
426 Status = BuildTokenUser(&Buffer->User,
427 (PSID)AccountDomainSid,
428 UserInfo->All.UserId);
429 if (!NT_SUCCESS(Status))
430 goto done;
431
432 Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
433 (PSID)AccountDomainSid,
434 UserInfo->All.PrimaryGroupId);
435 if (!NT_SUCCESS(Status))
436 goto done;
437
438 Status = BuildTokenGroups(&Buffer->Groups,
439 (PSID)AccountDomainSid,
440 UserInfo->All.UserId,
441 SpecialAccount);
442 if (!NT_SUCCESS(Status))
443 goto done;
444
445 *TokenInformation = Buffer;
446
447 done:
448 if (!NT_SUCCESS(Status))
449 {
450 if (Buffer != NULL)
451 {
452 if (Buffer->User.User.Sid != NULL)
453 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
454
455 if (Buffer->Groups != NULL)
456 {
457 for (i = 0; i < Buffer->Groups->GroupCount; i++)
458 {
459 if (Buffer->Groups->Groups[i].Sid != NULL)
460 DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
461 }
462
463 DispatchTable.FreeLsaHeap(Buffer->Groups);
464 }
465
466 if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
467 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
468
469 if (Buffer->DefaultDacl.DefaultDacl != NULL)
470 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
471
472 DispatchTable.FreeLsaHeap(Buffer);
473 }
474 }
475
476 return Status;
477 }
478
479
480 static
481 NTSTATUS
482 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
483 IN PVOID ProtocolSubmitBuffer,
484 IN PVOID ClientBufferBase,
485 IN ULONG SubmitBufferLength,
486 OUT PVOID *ProtocolReturnBuffer,
487 OUT PULONG ReturnBufferLength,
488 OUT PNTSTATUS ProtocolStatus)
489 {
490 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
491 ULONG_PTR PtrOffset;
492
493 SAMPR_HANDLE ServerHandle = NULL;
494 SAMPR_HANDLE DomainHandle = NULL;
495 SAMPR_HANDLE UserHandle = NULL;
496 PRPC_SID DomainSid = NULL;
497 RPC_UNICODE_STRING Names[1];
498 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
499 SAMPR_ULONG_ARRAY Use = {0, NULL};
500 NTSTATUS Status;
501
502 ENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
503 ENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
504 ENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
505 ENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
506 OEM_STRING LmPwdString;
507 CHAR LmPwdBuffer[15];
508 BOOLEAN OldLmPasswordPresent = FALSE;
509 BOOLEAN NewLmPasswordPresent = FALSE;
510
511 ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
512 ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
513 ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt;
514 ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt;
515 PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
516 PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
517
518 TRACE("()\n");
519
520 RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
521
522 /* Fix-up pointers in the request buffer info */
523 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
524
525 RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
526 RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
527 RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
528 RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
529
530 TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
531 TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
532 TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
533 TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
534
535 /* Connect to the SAM server */
536 Status = SamIConnect(NULL,
537 &ServerHandle,
538 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
539 TRUE);
540 if (!NT_SUCCESS(Status))
541 {
542 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
543 goto done;
544 }
545
546 /* Get the domain SID */
547 Status = SamrLookupDomainInSamServer(ServerHandle,
548 (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
549 &DomainSid);
550 if (!NT_SUCCESS(Status))
551 {
552 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
553 goto done;
554 }
555
556 /* Open the domain */
557 Status = SamrOpenDomain(ServerHandle,
558 DOMAIN_LOOKUP,
559 DomainSid,
560 &DomainHandle);
561 if (!NT_SUCCESS(Status))
562 {
563 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
564 goto done;
565 }
566
567 Names[0].Length = RequestBuffer->AccountName.Length;
568 Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
569 Names[0].Buffer = RequestBuffer->AccountName.Buffer;
570
571 /* Try to get the RID for the user name */
572 Status = SamrLookupNamesInDomain(DomainHandle,
573 1,
574 Names,
575 &RelativeIds,
576 &Use);
577 if (!NT_SUCCESS(Status))
578 {
579 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
580 Status = STATUS_NO_SUCH_USER;
581 goto done;
582 }
583
584 /* Fail, if it is not a user account */
585 if (Use.Element[0] != SidTypeUser)
586 {
587 TRACE("Account is not a user account!\n");
588 Status = STATUS_NO_SUCH_USER;
589 goto done;
590 }
591
592 /* Open the user object */
593 Status = SamrOpenUser(DomainHandle,
594 USER_CHANGE_PASSWORD,
595 RelativeIds.Element[0],
596 &UserHandle);
597 if (!NT_SUCCESS(Status))
598 {
599 TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
600 goto done;
601 }
602
603
604 /* Calculate the NT hash for the old password */
605 Status = SystemFunction007(&RequestBuffer->OldPassword,
606 (LPBYTE)&OldNtPassword);
607 if (!NT_SUCCESS(Status))
608 {
609 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
610 goto done;
611 }
612
613 /* Calculate the NT hash for the new password */
614 Status = SystemFunction007(&RequestBuffer->NewPassword,
615 (LPBYTE)&NewNtPassword);
616 if (!NT_SUCCESS(Status))
617 {
618 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
619 goto done;
620 }
621
622 /* Calculate the LM password and hash for the old password */
623 LmPwdString.Length = 15;
624 LmPwdString.MaximumLength = 15;
625 LmPwdString.Buffer = LmPwdBuffer;
626 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
627
628 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
629 &RequestBuffer->OldPassword,
630 FALSE);
631 if (NT_SUCCESS(Status))
632 {
633 /* Calculate the LM hash value of the password */
634 Status = SystemFunction006(LmPwdString.Buffer,
635 (LPSTR)&OldLmPassword);
636 if (NT_SUCCESS(Status))
637 {
638 OldLmPasswordPresent = TRUE;
639 }
640 }
641
642 /* Calculate the LM password and hash for the new password */
643 LmPwdString.Length = 15;
644 LmPwdString.MaximumLength = 15;
645 LmPwdString.Buffer = LmPwdBuffer;
646 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
647
648 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
649 &RequestBuffer->NewPassword,
650 FALSE);
651 if (NT_SUCCESS(Status))
652 {
653 /* Calculate the LM hash value of the password */
654 Status = SystemFunction006(LmPwdString.Buffer,
655 (LPSTR)&NewLmPassword);
656 if (NT_SUCCESS(Status))
657 {
658 NewLmPasswordPresent = TRUE;
659 }
660 }
661
662 /* Encrypt the old and new LM passwords, if they exist */
663 if (OldLmPasswordPresent && NewLmPasswordPresent)
664 {
665 /* Encrypt the old LM password */
666 Status = SystemFunction012((const BYTE *)&OldLmPassword,
667 (const BYTE *)&NewLmPassword,
668 (LPBYTE)&OldLmEncryptedWithNewLm);
669 if (!NT_SUCCESS(Status))
670 {
671 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
672 goto done;
673 }
674
675 /* Encrypt the new LM password */
676 Status = SystemFunction012((const BYTE *)&NewLmPassword,
677 (const BYTE *)&OldLmPassword,
678 (LPBYTE)&NewLmEncryptedWithOldLm);
679 if (!NT_SUCCESS(Status))
680 {
681 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
682 goto done;
683 }
684
685 pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
686 pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
687 }
688
689 /* Encrypt the old NT password */
690 Status = SystemFunction012((const BYTE *)&OldNtPassword,
691 (const BYTE *)&NewNtPassword,
692 (LPBYTE)&OldNtEncryptedWithNewNt);
693 if (!NT_SUCCESS(Status))
694 {
695 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
696 goto done;
697 }
698
699 /* Encrypt the new NT password */
700 Status = SystemFunction012((const BYTE *)&NewNtPassword,
701 (const BYTE *)&OldNtPassword,
702 (LPBYTE)&NewNtEncryptedWithOldNt);
703 if (!NT_SUCCESS(Status))
704 {
705 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
706 goto done;
707 }
708
709 /* Change the password */
710 Status = SamrChangePasswordUser(UserHandle,
711 OldLmPasswordPresent && NewLmPasswordPresent,
712 pOldLmEncryptedWithNewLm,
713 pNewLmEncryptedWithOldLm,
714 TRUE,
715 &OldNtEncryptedWithNewNt,
716 &NewNtEncryptedWithOldNt,
717 FALSE,
718 NULL,
719 FALSE,
720 NULL);
721 if (!NT_SUCCESS(Status))
722 {
723 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
724 goto done;
725 }
726
727 done:
728 if (UserHandle != NULL)
729 SamrCloseHandle(&UserHandle);
730
731 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
732 SamIFree_SAMPR_ULONG_ARRAY(&Use);
733
734 if (DomainHandle != NULL)
735 SamrCloseHandle(&DomainHandle);
736
737 if (DomainSid != NULL)
738 SamIFreeVoid(DomainSid);
739
740 if (ServerHandle != NULL)
741 SamrCloseHandle(&ServerHandle);
742
743 return Status;
744 }
745
746
747 static
748 NTSTATUS
749 MsvpCheckPassword(PUNICODE_STRING UserPassword,
750 PSAMPR_USER_INFO_BUFFER UserInfo)
751 {
752 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
753 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
754 BOOLEAN UserLmPasswordPresent = FALSE;
755 BOOLEAN UserNtPasswordPresent = FALSE;
756 OEM_STRING LmPwdString;
757 CHAR LmPwdBuffer[15];
758 NTSTATUS Status;
759
760 TRACE("(%p %p)\n", UserPassword, UserInfo);
761
762 /* Calculate the LM password and hash for the users password */
763 LmPwdString.Length = 15;
764 LmPwdString.MaximumLength = 15;
765 LmPwdString.Buffer = LmPwdBuffer;
766 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
767
768 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
769 UserPassword,
770 FALSE);
771 if (NT_SUCCESS(Status))
772 {
773 /* Calculate the LM hash value of the users password */
774 Status = SystemFunction006(LmPwdString.Buffer,
775 (LPSTR)&UserLmPassword);
776 if (NT_SUCCESS(Status))
777 {
778 UserLmPasswordPresent = TRUE;
779 }
780 }
781
782 /* Calculate the NT hash of the users password */
783 Status = SystemFunction007(UserPassword,
784 (LPBYTE)&UserNtPassword);
785 if (NT_SUCCESS(Status))
786 {
787 UserNtPasswordPresent = TRUE;
788 }
789
790 Status = STATUS_WRONG_PASSWORD;
791
792 /* Succeed, if no password has been set */
793 if (UserInfo->All.NtPasswordPresent == FALSE &&
794 UserInfo->All.LmPasswordPresent == FALSE)
795 {
796 TRACE("No password check!\n");
797 Status = STATUS_SUCCESS;
798 goto done;
799 }
800
801 /* Succeed, if NT password matches */
802 if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
803 {
804 TRACE("Check NT password hashes:\n");
805 if (RtlEqualMemory(&UserNtPassword,
806 UserInfo->All.NtOwfPassword.Buffer,
807 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
808 {
809 TRACE(" success!\n");
810 Status = STATUS_SUCCESS;
811 goto done;
812 }
813
814 TRACE(" failed!\n");
815 }
816
817 /* Succeed, if LM password matches */
818 if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
819 {
820 TRACE("Check LM password hashes:\n");
821 if (RtlEqualMemory(&UserLmPassword,
822 UserInfo->All.LmOwfPassword.Buffer,
823 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
824 {
825 TRACE(" success!\n");
826 Status = STATUS_SUCCESS;
827 goto done;
828 }
829 TRACE(" failed!\n");
830 }
831
832 done:
833 return Status;
834 }
835
836
837 /*
838 * @unimplemented
839 */
840 NTSTATUS
841 NTAPI
842 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
843 IN PVOID ProtocolSubmitBuffer,
844 IN PVOID ClientBufferBase,
845 IN ULONG SubmitBufferLength,
846 OUT PVOID *ProtocolReturnBuffer,
847 OUT PULONG ReturnBufferLength,
848 OUT PNTSTATUS ProtocolStatus)
849 {
850 ULONG MessageType;
851 NTSTATUS Status;
852
853 TRACE("()\n");
854
855 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
856 return STATUS_INVALID_PARAMETER;
857
858 MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
859
860 *ProtocolReturnBuffer = NULL;
861 *ReturnBufferLength = 0;
862
863 switch (MessageType)
864 {
865 case MsV1_0Lm20ChallengeRequest:
866 case MsV1_0Lm20GetChallengeResponse:
867 case MsV1_0EnumerateUsers:
868 case MsV1_0GetUserInfo:
869 case MsV1_0ReLogonUsers:
870 Status = STATUS_NOT_IMPLEMENTED;
871 break;
872
873 case MsV1_0ChangePassword:
874 Status = MsvpChangePassword(ClientRequest,
875 ProtocolSubmitBuffer,
876 ClientBufferBase,
877 SubmitBufferLength,
878 ProtocolReturnBuffer,
879 ReturnBufferLength,
880 ProtocolStatus);
881 break;
882
883 case MsV1_0ChangeCachedPassword:
884 case MsV1_0GenericPassthrough:
885 case MsV1_0CacheLogon:
886 case MsV1_0SubAuth:
887 case MsV1_0DeriveCredential:
888 case MsV1_0CacheLookup:
889 Status = STATUS_NOT_IMPLEMENTED;
890 break;
891
892 default:
893 return STATUS_INVALID_PARAMETER;
894 }
895
896 return Status;
897 }
898
899
900 /*
901 * @unimplemented
902 */
903 NTSTATUS
904 NTAPI
905 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,
906 IN PVOID ProtocolSubmitBuffer,
907 IN PVOID ClientBufferBase,
908 IN ULONG SubmitBufferLength,
909 OUT PVOID *ProtocolReturnBuffer,
910 OUT PULONG ReturnBufferLength,
911 OUT PNTSTATUS ProtocolStatus)
912 {
913 TRACE("()\n");
914 return STATUS_NOT_IMPLEMENTED;
915 }
916
917
918 /*
919 * @unimplemented
920 */
921 NTSTATUS
922 NTAPI
923 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
924 IN PVOID ProtocolSubmitBuffer,
925 IN PVOID ClientBufferBase,
926 IN ULONG SubmitBufferLength,
927 OUT PVOID *ProtocolReturnBuffer,
928 OUT PULONG ReturnBufferLength,
929 OUT PNTSTATUS ProtocolStatus)
930 {
931 TRACE("()\n");
932 return STATUS_NOT_IMPLEMENTED;
933 }
934
935
936 /*
937 * @unimplemented
938 */
939 NTSTATUS
940 NTAPI
941 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
942 IN PLSA_DISPATCH_TABLE LsaDispatchTable,
943 IN PLSA_STRING Database OPTIONAL,
944 IN PLSA_STRING Confidentiality OPTIONAL,
945 OUT PLSA_STRING *AuthenticationPackageName)
946 {
947 PANSI_STRING NameString;
948 PCHAR NameBuffer;
949
950 TRACE("(%lu %p %p %p %p)\n",
951 AuthenticationPackageId, LsaDispatchTable, Database,
952 Confidentiality, AuthenticationPackageName);
953
954 /* Get the dispatch table entries */
955 DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
956 DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
957 DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
958 DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
959 DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
960 DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
961 DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
962 DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
963 DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
964 DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
965 DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
966
967 /* Return the package name */
968 NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
969 if (NameString == NULL)
970 return STATUS_INSUFFICIENT_RESOURCES;
971
972 NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
973 if (NameBuffer == NULL)
974 {
975 DispatchTable.FreeLsaHeap(NameString);
976 return STATUS_INSUFFICIENT_RESOURCES;
977 }
978
979 strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
980
981 RtlInitAnsiString(NameString, NameBuffer);
982
983 *AuthenticationPackageName = (PLSA_STRING)NameString;
984
985 return STATUS_SUCCESS;
986 }
987
988
989 /*
990 * @unimplemented
991 */
992 VOID
993 NTAPI
994 LsaApLogonTerminated(IN PLUID LogonId)
995 {
996 TRACE("()\n");
997 }
998
999
1000 /*
1001 * @unimplemented
1002 */
1003 NTSTATUS
1004 NTAPI
1005 LsaApLogonUser(IN PLSA_CLIENT_REQUEST ClientRequest,
1006 IN SECURITY_LOGON_TYPE LogonType,
1007 IN PVOID AuthenticationInformation,
1008 IN PVOID ClientAuthenticationBase,
1009 IN ULONG AuthenticationInformationLength,
1010 OUT PVOID *ProfileBuffer,
1011 OUT PULONG ProfileBufferLength,
1012 OUT PLUID LogonId,
1013 OUT PNTSTATUS SubStatus,
1014 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1015 OUT PVOID *TokenInformation,
1016 OUT PLSA_UNICODE_STRING *AccountName,
1017 OUT PLSA_UNICODE_STRING *AuthenticatingAuthority)
1018 {
1019 PMSV1_0_INTERACTIVE_LOGON LogonInfo;
1020
1021 SAMPR_HANDLE ServerHandle = NULL;
1022 SAMPR_HANDLE DomainHandle = NULL;
1023 SAMPR_HANDLE UserHandle = NULL;
1024 PRPC_SID AccountDomainSid = NULL;
1025 RPC_UNICODE_STRING Names[1];
1026 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
1027 SAMPR_ULONG_ARRAY Use = {0, NULL};
1028 PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
1029 UNICODE_STRING LogonServer;
1030 BOOLEAN SessionCreated = FALSE;
1031 LARGE_INTEGER LogonTime;
1032 // LARGE_INTEGER AccountExpires;
1033 LARGE_INTEGER PasswordMustChange;
1034 LARGE_INTEGER PasswordLastSet;
1035 BOOL SpecialAccount = FALSE;
1036 NTSTATUS Status;
1037
1038 TRACE("LsaApLogonUser()\n");
1039
1040 TRACE("LogonType: %lu\n", LogonType);
1041 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
1042 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
1043
1044 *ProfileBuffer = NULL;
1045 *ProfileBufferLength = 0;
1046 *SubStatus = STATUS_SUCCESS;
1047
1048 if (LogonType == Interactive ||
1049 LogonType == Batch ||
1050 LogonType == Service)
1051 {
1052 ULONG_PTR PtrOffset;
1053
1054 LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)AuthenticationInformation;
1055
1056 /* Fix-up pointers in the authentication info */
1057 PtrOffset = (ULONG_PTR)AuthenticationInformation - (ULONG_PTR)ClientAuthenticationBase;
1058
1059 LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
1060 LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
1061 LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
1062
1063 TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
1064 TRACE("User: %S\n", LogonInfo->UserName.Buffer);
1065 TRACE("Password: %S\n", LogonInfo->Password.Buffer);
1066
1067 RtlInitUnicodeString(&LogonServer, L"Testserver");
1068 }
1069 else
1070 {
1071 FIXME("LogonType %lu is not supported yet!\n", LogonType);
1072 return STATUS_NOT_IMPLEMENTED;
1073 }
1074
1075 /* Get the logon time */
1076 NtQuerySystemTime(&LogonTime);
1077
1078 /* Check for special accounts */
1079 if (_wcsicmp(LogonInfo->LogonDomainName.Buffer, L"NT AUTHORITY") == 0)
1080 {
1081 SpecialAccount = TRUE;
1082
1083 /* Get the authority domain SID */
1084 Status = GetNtAuthorityDomainSid(&AccountDomainSid);
1085 if (!NT_SUCCESS(Status))
1086 {
1087 ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
1088 return Status;
1089 }
1090
1091 if (_wcsicmp(LogonInfo->UserName.Buffer, L"LocalService") == 0)
1092 {
1093 TRACE("SpecialAccount: LocalService\n");
1094
1095 if (LogonType != Service)
1096 return STATUS_LOGON_FAILURE;
1097
1098 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1099 HEAP_ZERO_MEMORY,
1100 sizeof(SAMPR_USER_ALL_INFORMATION));
1101 if (UserInfo == NULL)
1102 {
1103 Status = STATUS_INSUFFICIENT_RESOURCES;
1104 goto done;
1105 }
1106
1107 UserInfo->All.UserId = SECURITY_LOCAL_SERVICE_RID;
1108 UserInfo->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
1109 }
1110 else if (_wcsicmp(LogonInfo->UserName.Buffer, L"NetworkService") == 0)
1111 {
1112 TRACE("SpecialAccount: NetworkService\n");
1113
1114 if (LogonType != Service)
1115 return STATUS_LOGON_FAILURE;
1116
1117 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1118 HEAP_ZERO_MEMORY,
1119 sizeof(SAMPR_USER_ALL_INFORMATION));
1120 if (UserInfo == NULL)
1121 {
1122 Status = STATUS_INSUFFICIENT_RESOURCES;
1123 goto done;
1124 }
1125
1126 UserInfo->All.UserId = SECURITY_NETWORK_SERVICE_RID;
1127 UserInfo->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
1128 }
1129 else
1130 {
1131 Status = STATUS_NO_SUCH_USER;
1132 goto done;
1133 }
1134 }
1135 else
1136 {
1137 TRACE("NormalAccount\n");
1138
1139 /* Get the account domain SID */
1140 Status = GetAccountDomainSid(&AccountDomainSid);
1141 if (!NT_SUCCESS(Status))
1142 {
1143 ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status);
1144 return Status;
1145 }
1146
1147 /* Connect to the SAM server */
1148 Status = SamIConnect(NULL,
1149 &ServerHandle,
1150 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1151 TRUE);
1152 if (!NT_SUCCESS(Status))
1153 {
1154 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
1155 goto done;
1156 }
1157
1158 /* Open the account domain */
1159 Status = SamrOpenDomain(ServerHandle,
1160 DOMAIN_LOOKUP,
1161 AccountDomainSid,
1162 &DomainHandle);
1163 if (!NT_SUCCESS(Status))
1164 {
1165 ERR("SamrOpenDomain failed (Status %08lx)\n", Status);
1166 goto done;
1167 }
1168
1169 Names[0].Length = LogonInfo->UserName.Length;
1170 Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
1171 Names[0].Buffer = LogonInfo->UserName.Buffer;
1172
1173 /* Try to get the RID for the user name */
1174 Status = SamrLookupNamesInDomain(DomainHandle,
1175 1,
1176 Names,
1177 &RelativeIds,
1178 &Use);
1179 if (!NT_SUCCESS(Status))
1180 {
1181 ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
1182 Status = STATUS_NO_SUCH_USER;
1183 goto done;
1184 }
1185
1186 /* Fail, if it is not a user account */
1187 if (Use.Element[0] != SidTypeUser)
1188 {
1189 ERR("Account is not a user account!\n");
1190 Status = STATUS_NO_SUCH_USER;
1191 goto done;
1192 }
1193
1194 /* Open the user object */
1195 Status = SamrOpenUser(DomainHandle,
1196 USER_READ_GENERAL | USER_READ_LOGON |
1197 USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
1198 RelativeIds.Element[0],
1199 &UserHandle);
1200 if (!NT_SUCCESS(Status))
1201 {
1202 ERR("SamrOpenUser failed (Status %08lx)\n", Status);
1203 goto done;
1204 }
1205
1206 Status = SamrQueryInformationUser(UserHandle,
1207 UserAllInformation,
1208 &UserInfo);
1209 if (!NT_SUCCESS(Status))
1210 {
1211 ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status);
1212 goto done;
1213 }
1214
1215 TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
1216
1217 /* Check the password */
1218 if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
1219 {
1220 Status = MsvpCheckPassword(&(LogonInfo->Password),
1221 UserInfo);
1222 if (!NT_SUCCESS(Status))
1223 {
1224 ERR("MsvpCheckPassword failed (Status %08lx)\n", Status);
1225 goto done;
1226 }
1227 }
1228
1229 /* Check account restrictions for non-administrator accounts */
1230 if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
1231 {
1232 /* Check if the account has been disabled */
1233 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
1234 {
1235 ERR("Account disabled!\n");
1236 *SubStatus = STATUS_ACCOUNT_DISABLED;
1237 Status = STATUS_ACCOUNT_RESTRICTION;
1238 goto done;
1239 }
1240
1241 /* Check if the account has been locked */
1242 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
1243 {
1244 ERR("Account locked!\n");
1245 *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
1246 Status = STATUS_ACCOUNT_RESTRICTION;
1247 goto done;
1248 }
1249
1250 #if 0
1251 /* Check if the account expired */
1252 AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
1253 AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;
1254
1255 if (AccountExpires.QuadPart != 0 &&
1256 LogonTime.QuadPart >= AccountExpires.QuadPart)
1257 {
1258 ERR("Account expired!\n");
1259 *SubStatus = STATUS_ACCOUNT_EXPIRED;
1260 Status = STATUS_ACCOUNT_RESTRICTION;
1261 goto done;
1262 }
1263 #endif
1264
1265 /* Check if the password expired */
1266 PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
1267 PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
1268 PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
1269 PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
1270
1271 if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
1272 {
1273 ERR("Password expired!\n");
1274 if (PasswordLastSet.QuadPart == 0)
1275 *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
1276 else
1277 *SubStatus = STATUS_PASSWORD_EXPIRED;
1278
1279 Status = STATUS_ACCOUNT_RESTRICTION;
1280 goto done;
1281 }
1282
1283 /* FIXME: more checks */
1284 // STATUS_INVALID_LOGON_HOURS;
1285 // STATUS_INVALID_WORKSTATION;
1286 }
1287 }
1288
1289 /* Return logon information */
1290
1291 /* Create and return a new logon id */
1292 Status = NtAllocateLocallyUniqueId(LogonId);
1293 if (!NT_SUCCESS(Status))
1294 {
1295 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1296 goto done;
1297 }
1298
1299 /* Create the logon session */
1300 Status = DispatchTable.CreateLogonSession(LogonId);
1301 if (!NT_SUCCESS(Status))
1302 {
1303 TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1304 goto done;
1305 }
1306
1307 SessionCreated = TRUE;
1308
1309 /* Build and fill the interactive profile buffer */
1310 Status = BuildInteractiveProfileBuffer(ClientRequest,
1311 UserInfo,
1312 &LogonServer,
1313 (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1314 ProfileBufferLength);
1315 if (!NT_SUCCESS(Status))
1316 {
1317 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1318 goto done;
1319 }
1320
1321 /* Return the token information type */
1322 *TokenInformationType = LsaTokenInformationV1;
1323
1324 /* Build and fill the token information buffer */
1325 Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1326 AccountDomainSid,
1327 UserInfo,
1328 SpecialAccount);
1329 if (!NT_SUCCESS(Status))
1330 {
1331 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1332 goto done;
1333 }
1334
1335 done:
1336 /* Return the account name */
1337 *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1338 if (*AccountName != NULL)
1339 {
1340 (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1341 sizeof(UNICODE_NULL));
1342 if ((*AccountName)->Buffer != NULL)
1343 {
1344 (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1345 sizeof(UNICODE_NULL);
1346 RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1347 }
1348 }
1349
1350 if (!NT_SUCCESS(Status))
1351 {
1352 if (SessionCreated != FALSE)
1353 DispatchTable.DeleteLogonSession(LogonId);
1354
1355 if (*ProfileBuffer != NULL)
1356 {
1357 DispatchTable.FreeClientBuffer(ClientRequest,
1358 *ProfileBuffer);
1359 *ProfileBuffer = NULL;
1360 }
1361 }
1362
1363 if (UserHandle != NULL)
1364 SamrCloseHandle(&UserHandle);
1365
1366 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1367 UserAllInformation);
1368 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1369 SamIFree_SAMPR_ULONG_ARRAY(&Use);
1370
1371 if (DomainHandle != NULL)
1372 SamrCloseHandle(&DomainHandle);
1373
1374 if (ServerHandle != NULL)
1375 SamrCloseHandle(&ServerHandle);
1376
1377 if (AccountDomainSid != NULL)
1378 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1379
1380 if (Status == STATUS_NO_SUCH_USER ||
1381 Status == STATUS_WRONG_PASSWORD)
1382 {
1383 *SubStatus = Status;
1384 Status = STATUS_LOGON_FAILURE;
1385 }
1386
1387 TRACE("LsaApLogonUser done (Status 0x%08lx SubStatus 0x%08lx)\n", Status, *SubStatus);
1388
1389 return Status;
1390 }
1391
1392
1393 /*
1394 * @unimplemented
1395 */
1396 #if 0
1397 NTSTATUS
1398 NTAPI
1399 LsaApLogonUserEx(IN PLSA_CLIENT_REQUEST ClientRequest,
1400 IN SECURITY_LOGON_TYPE LogonType,
1401 IN PVOID AuthenticationInformation,
1402 IN PVOID ClientAuthenticationBase,
1403 IN ULONG AuthenticationInformationLength,
1404 OUT PVOID *ProfileBuffer,
1405 OUT PULONG ProfileBufferLength,
1406 OUT PLUID LogonId,
1407 OUT PNTSTATUS SubStatus,
1408 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1409 OUT PVOID *TokenInformation,
1410 OUT PUNICODE_STRING *AccountName,
1411 OUT PUNICODE_STRING *AuthenticatingAuthority,
1412 OUT PUNICODE_STRING *MachineName)
1413 {
1414 TRACE("()\n");
1415
1416 TRACE("LogonType: %lu\n", LogonType);
1417 TRACE("AuthenticationInformation: %p\n", AuthenticationInformation);
1418 TRACE("AuthenticationInformationLength: %lu\n", AuthenticationInformationLength);
1419
1420 return STATUS_NOT_IMPLEMENTED;
1421 }
1422
1423
1424 /*
1425 * @unimplemented
1426 */
1427 NTSTATUS
1428 NTAPI
1429 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1430 IN SECURITY_LOGON_TYPE LogonType,
1431 IN PVOID ProtocolSubmitBuffer,
1432 IN PVOID ClientBufferBase,
1433 IN ULONG SubmitBufferSize,
1434 OUT PVOID *ProfileBuffer,
1435 OUT PULONG ProfileBufferSize,
1436 OUT PLUID LogonId,
1437 OUT PNTSTATUS SubStatus,
1438 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1439 OUT PVOID *TokenInformation,
1440 OUT PUNICODE_STRING *AccountName,
1441 OUT PUNICODE_STRING *AuthenticatingAuthority,
1442 OUT PUNICODE_STRING *MachineName,
1443 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials,
1444 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials)
1445 {
1446 TRACE("()\n");
1447
1448 TRACE("LogonType: %lu\n", LogonType);
1449 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1450 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1451
1452
1453 return STATUS_NOT_IMPLEMENTED;
1454 }
1455 #endif
1456
1457 /* EOF */