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