[MSV1_0] Add SpLsaModeInitialize and SpUserModeInitialize.
[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 PWSTR ComputerName,
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 ((wcslen(ComputerName) + 3) * 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 = (wcslen(ComputerName) + 2) * sizeof(WCHAR);
208 LocalBuffer->LogonServer.MaximumLength = LocalBuffer->LogonServer.Length + sizeof(WCHAR);
209 LocalBuffer->LogonServer.Buffer = (LPWSTR)((ULONG_PTR)ClientBaseAddress + (ULONG_PTR)Ptr - (ULONG_PTR)LocalBuffer);
210 wcscpy(Ptr, L"\\");
211 wcscat(Ptr, ComputerName);
212
213 LocalBuffer->UserFlags = 0;
214
215 Status = DispatchTable.CopyToClientBuffer(ClientRequest,
216 BufferLength,
217 ClientBaseAddress,
218 LocalBuffer);
219 if (!NT_SUCCESS(Status))
220 {
221 TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status);
222 goto done;
223 }
224
225 *ProfileBuffer = (PMSV1_0_INTERACTIVE_PROFILE)ClientBaseAddress;
226 *ProfileBufferLength = BufferLength;
227
228 done:
229 if (LocalBuffer != NULL)
230 DispatchTable.FreeLsaHeap(LocalBuffer);
231
232 if (!NT_SUCCESS(Status))
233 {
234 if (ClientBaseAddress != NULL)
235 DispatchTable.FreeClientBuffer(ClientRequest,
236 ClientBaseAddress);
237 }
238
239 return Status;
240 }
241
242
243 static
244 PSID
245 AppendRidToSid(PSID SrcSid,
246 ULONG Rid)
247 {
248 PSID DstSid = NULL;
249 UCHAR RidCount;
250
251 RidCount = *RtlSubAuthorityCountSid(SrcSid);
252 if (RidCount >= 8)
253 return NULL;
254
255 DstSid = DispatchTable.AllocateLsaHeap(RtlLengthRequiredSid(RidCount + 1));
256 if (DstSid == NULL)
257 return NULL;
258
259 RtlCopyMemory(DstSid,
260 SrcSid,
261 RtlLengthRequiredSid(RidCount));
262
263 *RtlSubAuthorityCountSid(DstSid) = RidCount + 1;
264 *RtlSubAuthoritySid(DstSid, RidCount) = Rid;
265
266 return DstSid;
267 }
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 WARN("Failed to allocate the local buffer!\n");
419 Status = STATUS_INSUFFICIENT_RESOURCES;
420 goto done;
421 }
422
423 Buffer->ExpirationTime.LowPart = UserInfo->All.AccountExpires.LowPart;
424 Buffer->ExpirationTime.HighPart = UserInfo->All.AccountExpires.HighPart;
425
426 Status = BuildTokenUser(&Buffer->User,
427 (PSID)AccountDomainSid,
428 UserInfo->All.UserId);
429 if (!NT_SUCCESS(Status))
430 {
431 WARN("BuildTokenUser() failed (Status 0x%08lx)\n", Status);
432 goto done;
433 }
434
435 Status = BuildTokenPrimaryGroup(&Buffer->PrimaryGroup,
436 (PSID)AccountDomainSid,
437 UserInfo->All.PrimaryGroupId);
438 if (!NT_SUCCESS(Status))
439 {
440 WARN("BuildTokenPrimaryGroup() failed (Status 0x%08lx)\n", Status);
441 goto done;
442 }
443
444 Status = BuildTokenGroups(&Buffer->Groups,
445 (PSID)AccountDomainSid,
446 UserInfo->All.UserId,
447 SpecialAccount);
448 if (!NT_SUCCESS(Status))
449 {
450 WARN("BuildTokenGroups() failed (Status 0x%08lx)\n", Status);
451 goto done;
452 }
453
454 *TokenInformation = Buffer;
455
456 done:
457 if (!NT_SUCCESS(Status))
458 {
459 if (Buffer != NULL)
460 {
461 if (Buffer->User.User.Sid != NULL)
462 DispatchTable.FreeLsaHeap(Buffer->User.User.Sid);
463
464 if (Buffer->Groups != NULL)
465 {
466 for (i = 0; i < Buffer->Groups->GroupCount; i++)
467 {
468 if (Buffer->Groups->Groups[i].Sid != NULL)
469 DispatchTable.FreeLsaHeap(Buffer->Groups->Groups[i].Sid);
470 }
471
472 DispatchTable.FreeLsaHeap(Buffer->Groups);
473 }
474
475 if (Buffer->PrimaryGroup.PrimaryGroup != NULL)
476 DispatchTable.FreeLsaHeap(Buffer->PrimaryGroup.PrimaryGroup);
477
478 if (Buffer->DefaultDacl.DefaultDacl != NULL)
479 DispatchTable.FreeLsaHeap(Buffer->DefaultDacl.DefaultDacl);
480
481 DispatchTable.FreeLsaHeap(Buffer);
482 }
483 }
484
485 return Status;
486 }
487
488
489 static
490 NTSTATUS
491 MsvpChangePassword(IN PLSA_CLIENT_REQUEST ClientRequest,
492 IN PVOID ProtocolSubmitBuffer,
493 IN PVOID ClientBufferBase,
494 IN ULONG SubmitBufferLength,
495 OUT PVOID *ProtocolReturnBuffer,
496 OUT PULONG ReturnBufferLength,
497 OUT PNTSTATUS ProtocolStatus)
498 {
499 PMSV1_0_CHANGEPASSWORD_REQUEST RequestBuffer;
500 ULONG_PTR PtrOffset;
501
502 SAMPR_HANDLE ServerHandle = NULL;
503 SAMPR_HANDLE DomainHandle = NULL;
504 SAMPR_HANDLE UserHandle = NULL;
505 PRPC_SID DomainSid = NULL;
506 RPC_UNICODE_STRING Names[1];
507 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
508 SAMPR_ULONG_ARRAY Use = {0, NULL};
509 NTSTATUS Status;
510
511 ENCRYPTED_NT_OWF_PASSWORD OldNtPassword;
512 ENCRYPTED_NT_OWF_PASSWORD NewNtPassword;
513 ENCRYPTED_LM_OWF_PASSWORD OldLmPassword;
514 ENCRYPTED_LM_OWF_PASSWORD NewLmPassword;
515 OEM_STRING LmPwdString;
516 CHAR LmPwdBuffer[15];
517 BOOLEAN OldLmPasswordPresent = FALSE;
518 BOOLEAN NewLmPasswordPresent = FALSE;
519
520 ENCRYPTED_LM_OWF_PASSWORD OldLmEncryptedWithNewLm;
521 ENCRYPTED_LM_OWF_PASSWORD NewLmEncryptedWithOldLm;
522 ENCRYPTED_LM_OWF_PASSWORD OldNtEncryptedWithNewNt;
523 ENCRYPTED_LM_OWF_PASSWORD NewNtEncryptedWithOldNt;
524 PENCRYPTED_LM_OWF_PASSWORD pOldLmEncryptedWithNewLm = NULL;
525 PENCRYPTED_LM_OWF_PASSWORD pNewLmEncryptedWithOldLm = NULL;
526
527 TRACE("()\n");
528
529 RequestBuffer = (PMSV1_0_CHANGEPASSWORD_REQUEST)ProtocolSubmitBuffer;
530
531 /* Fix-up pointers in the request buffer info */
532 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
533
534 RequestBuffer->DomainName.Buffer = FIXUP_POINTER(RequestBuffer->DomainName.Buffer, PtrOffset);
535 RequestBuffer->AccountName.Buffer = FIXUP_POINTER(RequestBuffer->AccountName.Buffer, PtrOffset);
536 RequestBuffer->OldPassword.Buffer = FIXUP_POINTER(RequestBuffer->OldPassword.Buffer, PtrOffset);
537 RequestBuffer->NewPassword.Buffer = FIXUP_POINTER(RequestBuffer->NewPassword.Buffer, PtrOffset);
538
539 TRACE("Domain: %S\n", RequestBuffer->DomainName.Buffer);
540 TRACE("Account: %S\n", RequestBuffer->AccountName.Buffer);
541 TRACE("Old Password: %S\n", RequestBuffer->OldPassword.Buffer);
542 TRACE("New Password: %S\n", RequestBuffer->NewPassword.Buffer);
543
544 /* Connect to the SAM server */
545 Status = SamIConnect(NULL,
546 &ServerHandle,
547 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
548 TRUE);
549 if (!NT_SUCCESS(Status))
550 {
551 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
552 goto done;
553 }
554
555 /* Get the domain SID */
556 Status = SamrLookupDomainInSamServer(ServerHandle,
557 (PRPC_UNICODE_STRING)&RequestBuffer->DomainName,
558 &DomainSid);
559 if (!NT_SUCCESS(Status))
560 {
561 TRACE("SamrLookupDomainInSamServer failed (Status %08lx)\n", Status);
562 goto done;
563 }
564
565 /* Open the domain */
566 Status = SamrOpenDomain(ServerHandle,
567 DOMAIN_LOOKUP,
568 DomainSid,
569 &DomainHandle);
570 if (!NT_SUCCESS(Status))
571 {
572 TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
573 goto done;
574 }
575
576 Names[0].Length = RequestBuffer->AccountName.Length;
577 Names[0].MaximumLength = RequestBuffer->AccountName.MaximumLength;
578 Names[0].Buffer = RequestBuffer->AccountName.Buffer;
579
580 /* Try to get the RID for the user name */
581 Status = SamrLookupNamesInDomain(DomainHandle,
582 1,
583 Names,
584 &RelativeIds,
585 &Use);
586 if (!NT_SUCCESS(Status))
587 {
588 TRACE("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
589 Status = STATUS_NO_SUCH_USER;
590 goto done;
591 }
592
593 /* Fail, if it is not a user account */
594 if (Use.Element[0] != SidTypeUser)
595 {
596 TRACE("Account is not a user account!\n");
597 Status = STATUS_NO_SUCH_USER;
598 goto done;
599 }
600
601 /* Open the user object */
602 Status = SamrOpenUser(DomainHandle,
603 USER_CHANGE_PASSWORD,
604 RelativeIds.Element[0],
605 &UserHandle);
606 if (!NT_SUCCESS(Status))
607 {
608 TRACE("SamrOpenUser failed (Status %08lx)\n", Status);
609 goto done;
610 }
611
612
613 /* Calculate the NT hash for the old password */
614 Status = SystemFunction007(&RequestBuffer->OldPassword,
615 (LPBYTE)&OldNtPassword);
616 if (!NT_SUCCESS(Status))
617 {
618 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
619 goto done;
620 }
621
622 /* Calculate the NT hash for the new password */
623 Status = SystemFunction007(&RequestBuffer->NewPassword,
624 (LPBYTE)&NewNtPassword);
625 if (!NT_SUCCESS(Status))
626 {
627 TRACE("SystemFunction007 failed (Status 0x%08lx)\n", Status);
628 goto done;
629 }
630
631 /* Calculate the LM password and hash for the old password */
632 LmPwdString.Length = 15;
633 LmPwdString.MaximumLength = 15;
634 LmPwdString.Buffer = LmPwdBuffer;
635 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
636
637 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
638 &RequestBuffer->OldPassword,
639 FALSE);
640 if (NT_SUCCESS(Status))
641 {
642 /* Calculate the LM hash value of the password */
643 Status = SystemFunction006(LmPwdString.Buffer,
644 (LPSTR)&OldLmPassword);
645 if (NT_SUCCESS(Status))
646 {
647 OldLmPasswordPresent = TRUE;
648 }
649 }
650
651 /* Calculate the LM password and hash for the new password */
652 LmPwdString.Length = 15;
653 LmPwdString.MaximumLength = 15;
654 LmPwdString.Buffer = LmPwdBuffer;
655 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
656
657 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
658 &RequestBuffer->NewPassword,
659 FALSE);
660 if (NT_SUCCESS(Status))
661 {
662 /* Calculate the LM hash value of the password */
663 Status = SystemFunction006(LmPwdString.Buffer,
664 (LPSTR)&NewLmPassword);
665 if (NT_SUCCESS(Status))
666 {
667 NewLmPasswordPresent = TRUE;
668 }
669 }
670
671 /* Encrypt the old and new LM passwords, if they exist */
672 if (OldLmPasswordPresent && NewLmPasswordPresent)
673 {
674 /* Encrypt the old LM password */
675 Status = SystemFunction012((const BYTE *)&OldLmPassword,
676 (const BYTE *)&NewLmPassword,
677 (LPBYTE)&OldLmEncryptedWithNewLm);
678 if (!NT_SUCCESS(Status))
679 {
680 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
681 goto done;
682 }
683
684 /* Encrypt the new LM password */
685 Status = SystemFunction012((const BYTE *)&NewLmPassword,
686 (const BYTE *)&OldLmPassword,
687 (LPBYTE)&NewLmEncryptedWithOldLm);
688 if (!NT_SUCCESS(Status))
689 {
690 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
691 goto done;
692 }
693
694 pOldLmEncryptedWithNewLm = &OldLmEncryptedWithNewLm;
695 pNewLmEncryptedWithOldLm = &NewLmEncryptedWithOldLm;
696 }
697
698 /* Encrypt the old NT password */
699 Status = SystemFunction012((const BYTE *)&OldNtPassword,
700 (const BYTE *)&NewNtPassword,
701 (LPBYTE)&OldNtEncryptedWithNewNt);
702 if (!NT_SUCCESS(Status))
703 {
704 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
705 goto done;
706 }
707
708 /* Encrypt the new NT password */
709 Status = SystemFunction012((const BYTE *)&NewNtPassword,
710 (const BYTE *)&OldNtPassword,
711 (LPBYTE)&NewNtEncryptedWithOldNt);
712 if (!NT_SUCCESS(Status))
713 {
714 TRACE("SystemFunction012 failed (Status 0x%08lx)\n", Status);
715 goto done;
716 }
717
718 /* Change the password */
719 Status = SamrChangePasswordUser(UserHandle,
720 OldLmPasswordPresent && NewLmPasswordPresent,
721 pOldLmEncryptedWithNewLm,
722 pNewLmEncryptedWithOldLm,
723 TRUE,
724 &OldNtEncryptedWithNewNt,
725 &NewNtEncryptedWithOldNt,
726 FALSE,
727 NULL,
728 FALSE,
729 NULL);
730 if (!NT_SUCCESS(Status))
731 {
732 TRACE("SamrChangePasswordUser failed (Status %08lx)\n", Status);
733 goto done;
734 }
735
736 done:
737 if (UserHandle != NULL)
738 SamrCloseHandle(&UserHandle);
739
740 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
741 SamIFree_SAMPR_ULONG_ARRAY(&Use);
742
743 if (DomainHandle != NULL)
744 SamrCloseHandle(&DomainHandle);
745
746 if (DomainSid != NULL)
747 SamIFreeVoid(DomainSid);
748
749 if (ServerHandle != NULL)
750 SamrCloseHandle(&ServerHandle);
751
752 return Status;
753 }
754
755
756 static
757 NTSTATUS
758 MsvpCheckPassword(PUNICODE_STRING UserPassword,
759 PSAMPR_USER_INFO_BUFFER UserInfo)
760 {
761 ENCRYPTED_NT_OWF_PASSWORD UserNtPassword;
762 ENCRYPTED_LM_OWF_PASSWORD UserLmPassword;
763 BOOLEAN UserLmPasswordPresent = FALSE;
764 BOOLEAN UserNtPasswordPresent = FALSE;
765 OEM_STRING LmPwdString;
766 CHAR LmPwdBuffer[15];
767 NTSTATUS Status;
768
769 TRACE("(%p %p)\n", UserPassword, UserInfo);
770
771 /* Calculate the LM password and hash for the users password */
772 LmPwdString.Length = 15;
773 LmPwdString.MaximumLength = 15;
774 LmPwdString.Buffer = LmPwdBuffer;
775 ZeroMemory(LmPwdString.Buffer, LmPwdString.MaximumLength);
776
777 Status = RtlUpcaseUnicodeStringToOemString(&LmPwdString,
778 UserPassword,
779 FALSE);
780 if (NT_SUCCESS(Status))
781 {
782 /* Calculate the LM hash value of the users password */
783 Status = SystemFunction006(LmPwdString.Buffer,
784 (LPSTR)&UserLmPassword);
785 if (NT_SUCCESS(Status))
786 {
787 UserLmPasswordPresent = TRUE;
788 }
789 }
790
791 /* Calculate the NT hash of the users password */
792 Status = SystemFunction007(UserPassword,
793 (LPBYTE)&UserNtPassword);
794 if (NT_SUCCESS(Status))
795 {
796 UserNtPasswordPresent = TRUE;
797 }
798
799 Status = STATUS_WRONG_PASSWORD;
800
801 /* Succeed, if no password has been set */
802 if (UserInfo->All.NtPasswordPresent == FALSE &&
803 UserInfo->All.LmPasswordPresent == FALSE)
804 {
805 TRACE("No password check!\n");
806 Status = STATUS_SUCCESS;
807 goto done;
808 }
809
810 /* Succeed, if NT password matches */
811 if (UserNtPasswordPresent && UserInfo->All.NtPasswordPresent)
812 {
813 TRACE("Check NT password hashes:\n");
814 if (RtlEqualMemory(&UserNtPassword,
815 UserInfo->All.NtOwfPassword.Buffer,
816 sizeof(ENCRYPTED_NT_OWF_PASSWORD)))
817 {
818 TRACE(" success!\n");
819 Status = STATUS_SUCCESS;
820 goto done;
821 }
822
823 TRACE(" failed!\n");
824 }
825
826 /* Succeed, if LM password matches */
827 if (UserLmPasswordPresent && UserInfo->All.LmPasswordPresent)
828 {
829 TRACE("Check LM password hashes:\n");
830 if (RtlEqualMemory(&UserLmPassword,
831 UserInfo->All.LmOwfPassword.Buffer,
832 sizeof(ENCRYPTED_LM_OWF_PASSWORD)))
833 {
834 TRACE(" success!\n");
835 Status = STATUS_SUCCESS;
836 goto done;
837 }
838 TRACE(" failed!\n");
839 }
840
841 done:
842 return Status;
843 }
844
845
846 static
847 BOOL
848 MsvpCheckLogonHours(
849 _In_ PSAMPR_LOGON_HOURS LogonHours,
850 _In_ PLARGE_INTEGER LogonTime)
851 {
852 #if 0
853 LARGE_INTEGER LocalLogonTime;
854 TIME_FIELDS TimeFields;
855 USHORT MinutesPerUnit, Offset;
856 BOOL bFound;
857
858 FIXME("MsvpCheckLogonHours(%p %p)\n", LogonHours, LogonTime);
859
860 if (LogonHours->UnitsPerWeek == 0 || LogonHours->LogonHours == NULL)
861 {
862 FIXME("No logon hours!\n");
863 return TRUE;
864 }
865
866 RtlSystemTimeToLocalTime(LogonTime, &LocalLogonTime);
867 RtlTimeToTimeFields(&LocalLogonTime, &TimeFields);
868
869 FIXME("UnitsPerWeek: %u\n", LogonHours->UnitsPerWeek);
870 MinutesPerUnit = 10080 / LogonHours->UnitsPerWeek;
871
872 Offset = ((TimeFields.Weekday * 24 + TimeFields.Hour) * 60 + TimeFields.Minute) / MinutesPerUnit;
873 FIXME("Offset: %us\n", Offset);
874
875 bFound = (BOOL)(LogonHours->LogonHours[Offset / 8] & (1 << (Offset % 8)));
876 FIXME("Logon permitted: %s\n", bFound ? "Yes" : "No");
877
878 return bFound;
879 #endif
880 return TRUE;
881 }
882
883
884 static
885 BOOL
886 MsvpCheckWorkstations(
887 _In_ PRPC_UNICODE_STRING WorkStations,
888 _In_ PWSTR ComputerName)
889 {
890 PWSTR pStart, pEnd;
891 BOOL bFound = FALSE;
892
893 TRACE("MsvpCheckWorkstations(%p %S)\n", WorkStations, ComputerName);
894
895 if (WorkStations->Length == 0 || WorkStations->Buffer == NULL)
896 {
897 TRACE("No workstations!\n");
898 return TRUE;
899 }
900
901 TRACE("Workstations: %wZ\n", WorkStations);
902
903 pStart = WorkStations->Buffer;
904 for (;;)
905 {
906 pEnd = wcschr(pStart, L',');
907 if (pEnd != NULL)
908 *pEnd = UNICODE_NULL;
909
910 TRACE("Comparing '%S' and '%S'\n", ComputerName, pStart);
911 if (_wcsicmp(ComputerName, pStart) == 0)
912 {
913 bFound = TRUE;
914 if (pEnd != NULL)
915 *pEnd = L',';
916 break;
917 }
918
919 if (pEnd == NULL)
920 break;
921
922 *pEnd = L',';
923 pStart = pEnd + 1;
924 }
925
926 TRACE("Found allowed workstation: %s\n", (bFound) ? "Yes" : "No");
927
928 return bFound;
929 }
930
931
932 /*
933 * @unimplemented
934 */
935 NTSTATUS
936 NTAPI
937 LsaApCallPackage(IN PLSA_CLIENT_REQUEST ClientRequest,
938 IN PVOID ProtocolSubmitBuffer,
939 IN PVOID ClientBufferBase,
940 IN ULONG SubmitBufferLength,
941 OUT PVOID *ProtocolReturnBuffer,
942 OUT PULONG ReturnBufferLength,
943 OUT PNTSTATUS ProtocolStatus)
944 {
945 ULONG MessageType;
946 NTSTATUS Status;
947
948 TRACE("LsaApCallPackage()\n");
949
950 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
951 return STATUS_INVALID_PARAMETER;
952
953 MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
954
955 *ProtocolReturnBuffer = NULL;
956 *ReturnBufferLength = 0;
957
958 switch (MessageType)
959 {
960 case MsV1_0Lm20ChallengeRequest:
961 case MsV1_0Lm20GetChallengeResponse:
962 Status = STATUS_NOT_IMPLEMENTED;
963 break;
964
965 case MsV1_0EnumerateUsers:
966 case MsV1_0GetUserInfo:
967 case MsV1_0ReLogonUsers:
968 Status = STATUS_INVALID_PARAMETER;
969 break;
970
971 case MsV1_0ChangePassword:
972 Status = MsvpChangePassword(ClientRequest,
973 ProtocolSubmitBuffer,
974 ClientBufferBase,
975 SubmitBufferLength,
976 ProtocolReturnBuffer,
977 ReturnBufferLength,
978 ProtocolStatus);
979 break;
980
981 case MsV1_0ChangeCachedPassword:
982 case MsV1_0GenericPassthrough:
983 case MsV1_0CacheLogon:
984 case MsV1_0SubAuth:
985 case MsV1_0DeriveCredential:
986 case MsV1_0CacheLookup:
987 Status = STATUS_NOT_IMPLEMENTED;
988 break;
989
990 default:
991 return STATUS_INVALID_PARAMETER;
992 }
993
994 return Status;
995 }
996
997
998 /*
999 * @unimplemented
1000 */
1001 NTSTATUS
1002 NTAPI
1003 LsaApCallPackagePassthrough(IN PLSA_CLIENT_REQUEST ClientRequest,
1004 IN PVOID ProtocolSubmitBuffer,
1005 IN PVOID ClientBufferBase,
1006 IN ULONG SubmitBufferLength,
1007 OUT PVOID *ProtocolReturnBuffer,
1008 OUT PULONG ReturnBufferLength,
1009 OUT PNTSTATUS ProtocolStatus)
1010 {
1011 TRACE("LsaApCallPackagePassthrough()\n");
1012 return STATUS_NOT_IMPLEMENTED;
1013 }
1014
1015
1016 /*
1017 * @unimplemented
1018 */
1019 NTSTATUS
1020 NTAPI
1021 LsaApCallPackageUntrusted(IN PLSA_CLIENT_REQUEST ClientRequest,
1022 IN PVOID ProtocolSubmitBuffer,
1023 IN PVOID ClientBufferBase,
1024 IN ULONG SubmitBufferLength,
1025 OUT PVOID *ProtocolReturnBuffer,
1026 OUT PULONG ReturnBufferLength,
1027 OUT PNTSTATUS ProtocolStatus)
1028 {
1029 TRACE("LsaApCallPackageUntrusted()\n");
1030 return STATUS_NOT_IMPLEMENTED;
1031 }
1032
1033
1034 /*
1035 * @implemented
1036 */
1037 NTSTATUS
1038 NTAPI
1039 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
1040 IN PLSA_DISPATCH_TABLE LsaDispatchTable,
1041 IN PLSA_STRING Database OPTIONAL,
1042 IN PLSA_STRING Confidentiality OPTIONAL,
1043 OUT PLSA_STRING *AuthenticationPackageName)
1044 {
1045 PANSI_STRING NameString;
1046 PCHAR NameBuffer;
1047
1048 TRACE("LsaApInitializePackage(%lu %p %p %p %p)\n",
1049 AuthenticationPackageId, LsaDispatchTable, Database,
1050 Confidentiality, AuthenticationPackageName);
1051
1052 /* Get the dispatch table entries */
1053 DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
1054 DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
1055 DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
1056 DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
1057 DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
1058 DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
1059 DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
1060 DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
1061 DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
1062 DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
1063 DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
1064
1065 /* Return the package name */
1066 NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
1067 if (NameString == NULL)
1068 return STATUS_INSUFFICIENT_RESOURCES;
1069
1070 NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
1071 if (NameBuffer == NULL)
1072 {
1073 DispatchTable.FreeLsaHeap(NameString);
1074 return STATUS_INSUFFICIENT_RESOURCES;
1075 }
1076
1077 strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
1078
1079 RtlInitAnsiString(NameString, NameBuffer);
1080
1081 *AuthenticationPackageName = (PLSA_STRING)NameString;
1082
1083 return STATUS_SUCCESS;
1084 }
1085
1086
1087 /*
1088 * @unimplemented
1089 */
1090 VOID
1091 NTAPI
1092 LsaApLogonTerminated(IN PLUID LogonId)
1093 {
1094 TRACE("LsaApLogonTerminated()\n");
1095 }
1096
1097
1098 /*
1099 * @implemented
1100 */
1101 NTSTATUS
1102 NTAPI
1103 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1104 IN SECURITY_LOGON_TYPE LogonType,
1105 IN PVOID ProtocolSubmitBuffer,
1106 IN PVOID ClientBufferBase,
1107 IN ULONG SubmitBufferSize,
1108 OUT PVOID *ProfileBuffer,
1109 OUT PULONG ProfileBufferSize,
1110 OUT PLUID LogonId,
1111 OUT PNTSTATUS SubStatus,
1112 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1113 OUT PVOID *TokenInformation,
1114 OUT PUNICODE_STRING *AccountName,
1115 OUT PUNICODE_STRING *AuthenticatingAuthority,
1116 OUT PUNICODE_STRING *MachineName,
1117 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials, /* Not supported yet */
1118 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials) /* Not supported yet */
1119 {
1120 PMSV1_0_INTERACTIVE_LOGON LogonInfo;
1121 WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1122 SAMPR_HANDLE ServerHandle = NULL;
1123 SAMPR_HANDLE DomainHandle = NULL;
1124 SAMPR_HANDLE UserHandle = NULL;
1125 PRPC_SID AccountDomainSid = NULL;
1126 RPC_UNICODE_STRING Names[1];
1127 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
1128 SAMPR_ULONG_ARRAY Use = {0, NULL};
1129 PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
1130 BOOLEAN SessionCreated = FALSE;
1131 LARGE_INTEGER LogonTime;
1132 LARGE_INTEGER AccountExpires;
1133 LARGE_INTEGER PasswordMustChange;
1134 LARGE_INTEGER PasswordLastSet;
1135 DWORD ComputerNameSize;
1136 BOOL SpecialAccount = FALSE;
1137 NTSTATUS Status;
1138
1139 TRACE("LsaApLogonUser()\n");
1140
1141 TRACE("LogonType: %lu\n", LogonType);
1142 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1143 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1144
1145 *ProfileBuffer = NULL;
1146 *ProfileBufferSize = 0;
1147 *SubStatus = STATUS_SUCCESS;
1148 *AccountName = NULL;
1149 *AuthenticatingAuthority = NULL;
1150
1151 if (LogonType == Interactive ||
1152 LogonType == Batch ||
1153 LogonType == Service)
1154 {
1155 ULONG_PTR PtrOffset;
1156
1157 LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)ProtocolSubmitBuffer;
1158
1159 /* Fix-up pointers in the authentication info */
1160 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
1161
1162 LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
1163 LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
1164 LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
1165
1166 TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
1167 TRACE("User: %S\n", LogonInfo->UserName.Buffer);
1168 TRACE("Password: %S\n", LogonInfo->Password.Buffer);
1169 }
1170 else
1171 {
1172 FIXME("LogonType %lu is not supported yet!\n", LogonType);
1173 return STATUS_NOT_IMPLEMENTED;
1174 }
1175
1176 /* Get the logon time */
1177 NtQuerySystemTime(&LogonTime);
1178
1179 /* Get the computer name */
1180 ComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
1181 GetComputerNameW(ComputerName, &ComputerNameSize);
1182
1183 /* Check for special accounts */
1184 if (_wcsicmp(LogonInfo->LogonDomainName.Buffer, L"NT AUTHORITY") == 0)
1185 {
1186 SpecialAccount = TRUE;
1187
1188 /* Get the authority domain SID */
1189 Status = GetNtAuthorityDomainSid(&AccountDomainSid);
1190 if (!NT_SUCCESS(Status))
1191 {
1192 ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
1193 return Status;
1194 }
1195
1196 if (_wcsicmp(LogonInfo->UserName.Buffer, L"LocalService") == 0)
1197 {
1198 TRACE("SpecialAccount: LocalService\n");
1199
1200 if (LogonType != Service)
1201 return STATUS_LOGON_FAILURE;
1202
1203 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1204 HEAP_ZERO_MEMORY,
1205 sizeof(SAMPR_USER_ALL_INFORMATION));
1206 if (UserInfo == NULL)
1207 {
1208 Status = STATUS_INSUFFICIENT_RESOURCES;
1209 goto done;
1210 }
1211
1212 UserInfo->All.UserId = SECURITY_LOCAL_SERVICE_RID;
1213 UserInfo->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
1214 }
1215 else if (_wcsicmp(LogonInfo->UserName.Buffer, L"NetworkService") == 0)
1216 {
1217 TRACE("SpecialAccount: NetworkService\n");
1218
1219 if (LogonType != Service)
1220 return STATUS_LOGON_FAILURE;
1221
1222 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1223 HEAP_ZERO_MEMORY,
1224 sizeof(SAMPR_USER_ALL_INFORMATION));
1225 if (UserInfo == NULL)
1226 {
1227 Status = STATUS_INSUFFICIENT_RESOURCES;
1228 goto done;
1229 }
1230
1231 UserInfo->All.UserId = SECURITY_NETWORK_SERVICE_RID;
1232 UserInfo->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
1233 }
1234 else
1235 {
1236 Status = STATUS_NO_SUCH_USER;
1237 goto done;
1238 }
1239 }
1240 else
1241 {
1242 TRACE("NormalAccount\n");
1243
1244 /* Get the account domain SID */
1245 Status = GetAccountDomainSid(&AccountDomainSid);
1246 if (!NT_SUCCESS(Status))
1247 {
1248 ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status);
1249 return Status;
1250 }
1251
1252 /* Connect to the SAM server */
1253 Status = SamIConnect(NULL,
1254 &ServerHandle,
1255 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1256 TRUE);
1257 if (!NT_SUCCESS(Status))
1258 {
1259 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
1260 goto done;
1261 }
1262
1263 /* Open the account domain */
1264 Status = SamrOpenDomain(ServerHandle,
1265 DOMAIN_LOOKUP,
1266 AccountDomainSid,
1267 &DomainHandle);
1268 if (!NT_SUCCESS(Status))
1269 {
1270 ERR("SamrOpenDomain failed (Status %08lx)\n", Status);
1271 goto done;
1272 }
1273
1274 Names[0].Length = LogonInfo->UserName.Length;
1275 Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
1276 Names[0].Buffer = LogonInfo->UserName.Buffer;
1277
1278 /* Try to get the RID for the user name */
1279 Status = SamrLookupNamesInDomain(DomainHandle,
1280 1,
1281 Names,
1282 &RelativeIds,
1283 &Use);
1284 if (!NT_SUCCESS(Status))
1285 {
1286 ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
1287 Status = STATUS_NO_SUCH_USER;
1288 goto done;
1289 }
1290
1291 /* Fail, if it is not a user account */
1292 if (Use.Element[0] != SidTypeUser)
1293 {
1294 ERR("Account is not a user account!\n");
1295 Status = STATUS_NO_SUCH_USER;
1296 goto done;
1297 }
1298
1299 /* Open the user object */
1300 Status = SamrOpenUser(DomainHandle,
1301 USER_READ_GENERAL | USER_READ_LOGON |
1302 USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
1303 RelativeIds.Element[0],
1304 &UserHandle);
1305 if (!NT_SUCCESS(Status))
1306 {
1307 ERR("SamrOpenUser failed (Status %08lx)\n", Status);
1308 goto done;
1309 }
1310
1311 Status = SamrQueryInformationUser(UserHandle,
1312 UserAllInformation,
1313 &UserInfo);
1314 if (!NT_SUCCESS(Status))
1315 {
1316 ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status);
1317 goto done;
1318 }
1319
1320 TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
1321
1322 /* Check the password */
1323 if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
1324 {
1325 Status = MsvpCheckPassword(&(LogonInfo->Password),
1326 UserInfo);
1327 if (!NT_SUCCESS(Status))
1328 {
1329 ERR("MsvpCheckPassword failed (Status %08lx)\n", Status);
1330 goto done;
1331 }
1332 }
1333
1334 /* Check account restrictions for non-administrator accounts */
1335 if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
1336 {
1337 /* Check if the account has been disabled */
1338 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
1339 {
1340 ERR("Account disabled!\n");
1341 *SubStatus = STATUS_ACCOUNT_DISABLED;
1342 Status = STATUS_ACCOUNT_RESTRICTION;
1343 goto done;
1344 }
1345
1346 /* Check if the account has been locked */
1347 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
1348 {
1349 ERR("Account locked!\n");
1350 *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
1351 Status = STATUS_ACCOUNT_RESTRICTION;
1352 goto done;
1353 }
1354
1355 /* Check if the account expired */
1356 AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
1357 AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;
1358 if (LogonTime.QuadPart >= AccountExpires.QuadPart)
1359 {
1360 ERR("Account expired!\n");
1361 *SubStatus = STATUS_ACCOUNT_EXPIRED;
1362 Status = STATUS_ACCOUNT_RESTRICTION;
1363 goto done;
1364 }
1365
1366 /* Check if the password expired */
1367 PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
1368 PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
1369 PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
1370 PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
1371
1372 if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
1373 {
1374 ERR("Password expired!\n");
1375 if (PasswordLastSet.QuadPart == 0)
1376 *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
1377 else
1378 *SubStatus = STATUS_PASSWORD_EXPIRED;
1379
1380 Status = STATUS_ACCOUNT_RESTRICTION;
1381 goto done;
1382 }
1383
1384 /* Check logon hours */
1385 if (!MsvpCheckLogonHours(&UserInfo->All.LogonHours, &LogonTime))
1386 {
1387 ERR("Invalid logon hours!\n");
1388 *SubStatus = STATUS_INVALID_LOGON_HOURS;
1389 Status = STATUS_ACCOUNT_RESTRICTION;
1390 goto done;
1391 }
1392
1393 /* Check workstations */
1394 if (!MsvpCheckWorkstations(&UserInfo->All.WorkStations, ComputerName))
1395 {
1396 ERR("Invalid workstation!\n");
1397 *SubStatus = STATUS_INVALID_WORKSTATION;
1398 Status = STATUS_ACCOUNT_RESTRICTION;
1399 goto done;
1400 }
1401 }
1402 }
1403
1404 /* Return logon information */
1405
1406 /* Create and return a new logon id */
1407 Status = NtAllocateLocallyUniqueId(LogonId);
1408 if (!NT_SUCCESS(Status))
1409 {
1410 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1411 goto done;
1412 }
1413
1414 /* Create the logon session */
1415 Status = DispatchTable.CreateLogonSession(LogonId);
1416 if (!NT_SUCCESS(Status))
1417 {
1418 TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1419 goto done;
1420 }
1421
1422 SessionCreated = TRUE;
1423
1424 /* Build and fill the interactive profile buffer */
1425 Status = BuildInteractiveProfileBuffer(ClientRequest,
1426 UserInfo,
1427 ComputerName,
1428 (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1429 ProfileBufferSize);
1430 if (!NT_SUCCESS(Status))
1431 {
1432 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1433 goto done;
1434 }
1435
1436 /* Return the token information type */
1437 *TokenInformationType = LsaTokenInformationV1;
1438
1439 /* Build and fill the token information buffer */
1440 Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1441 AccountDomainSid,
1442 UserInfo,
1443 SpecialAccount);
1444 if (!NT_SUCCESS(Status))
1445 {
1446 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1447 goto done;
1448 }
1449
1450 done:
1451 /* Update the logon time/count or the bad password time/count */
1452 if ((UserHandle != NULL) &&
1453 (Status == STATUS_SUCCESS || Status == STATUS_WRONG_PASSWORD))
1454 {
1455 SAMPR_USER_INFO_BUFFER InternalInfo;
1456
1457 RtlZeroMemory(&InternalInfo, sizeof(InternalInfo));
1458
1459 if (Status == STATUS_SUCCESS)
1460 InternalInfo.Internal2.Flags = USER_LOGON_SUCCESS;
1461 else
1462 InternalInfo.Internal2.Flags = USER_LOGON_BAD_PASSWORD;
1463
1464 SamrSetInformationUser(UserHandle,
1465 UserInternal2Information,
1466 &InternalInfo);
1467 }
1468
1469 /* Return the account name */
1470 *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1471 if (*AccountName != NULL)
1472 {
1473 (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1474 sizeof(UNICODE_NULL));
1475 if ((*AccountName)->Buffer != NULL)
1476 {
1477 (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1478 sizeof(UNICODE_NULL);
1479 RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1480 }
1481 }
1482
1483 /* Return the authenticating authority */
1484 *AuthenticatingAuthority = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1485 if (*AuthenticatingAuthority != NULL)
1486 {
1487 (*AuthenticatingAuthority)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->LogonDomainName.Length +
1488 sizeof(UNICODE_NULL));
1489 if ((*AuthenticatingAuthority)->Buffer != NULL)
1490 {
1491 (*AuthenticatingAuthority)->MaximumLength = LogonInfo->LogonDomainName.Length +
1492 sizeof(UNICODE_NULL);
1493 RtlCopyUnicodeString(*AuthenticatingAuthority, &LogonInfo->LogonDomainName);
1494 }
1495 }
1496
1497 /* Return the machine name */
1498 *MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1499 if (*MachineName != NULL)
1500 {
1501 (*MachineName)->Buffer = DispatchTable.AllocateLsaHeap((ComputerNameSize + 1) * sizeof(WCHAR));
1502 if ((*MachineName)->Buffer != NULL)
1503 {
1504 (*MachineName)->MaximumLength = (ComputerNameSize + 1) * sizeof(WCHAR);
1505 (*MachineName)->Length = ComputerNameSize * sizeof(WCHAR);
1506 RtlCopyMemory((*MachineName)->Buffer, ComputerName, (*MachineName)->MaximumLength);
1507 }
1508 }
1509
1510 if (!NT_SUCCESS(Status))
1511 {
1512 if (SessionCreated != FALSE)
1513 DispatchTable.DeleteLogonSession(LogonId);
1514
1515 if (*ProfileBuffer != NULL)
1516 {
1517 DispatchTable.FreeClientBuffer(ClientRequest,
1518 *ProfileBuffer);
1519 *ProfileBuffer = NULL;
1520 }
1521 }
1522
1523 if (UserHandle != NULL)
1524 SamrCloseHandle(&UserHandle);
1525
1526 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1527 UserAllInformation);
1528 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1529 SamIFree_SAMPR_ULONG_ARRAY(&Use);
1530
1531 if (DomainHandle != NULL)
1532 SamrCloseHandle(&DomainHandle);
1533
1534 if (ServerHandle != NULL)
1535 SamrCloseHandle(&ServerHandle);
1536
1537 if (AccountDomainSid != NULL)
1538 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1539
1540 if (Status == STATUS_NO_SUCH_USER ||
1541 Status == STATUS_WRONG_PASSWORD)
1542 {
1543 *SubStatus = Status;
1544 Status = STATUS_LOGON_FAILURE;
1545 }
1546
1547 TRACE("LsaApLogonUser done (Status 0x%08lx SubStatus 0x%08lx)\n", Status, *SubStatus);
1548
1549 return Status;
1550 }
1551
1552
1553 /*
1554 * @unimplemented
1555 */
1556 NTSTATUS
1557 NTAPI
1558 SpLsaModeInitialize(
1559 _In_ ULONG LsaVersion,
1560 _Out_ PULONG PackageVersion,
1561 _Out_ PSECPKG_FUNCTION_TABLE *ppTables,
1562 _Out_ PULONG pcTables)
1563 {
1564 SECPKG_FUNCTION_TABLE Tables[1];
1565
1566 TRACE("SpLsaModeInitialize(0x%lx %p %p %p)\n",
1567 LsaVersion, PackageVersion, ppTables, pcTables);
1568
1569 if (LsaVersion != SECPKG_INTERFACE_VERSION)
1570 return STATUS_INVALID_PARAMETER;
1571
1572 *PackageVersion = SECPKG_INTERFACE_VERSION;
1573
1574 RtlZeroMemory(&Tables, sizeof(Tables));
1575
1576 Tables[0].InitializePackage = LsaApInitializePackage;
1577 // Tables[0].LogonUser = NULL;
1578 Tables[0].CallPackage = (PLSA_AP_CALL_PACKAGE)LsaApCallPackage;
1579 Tables[0].LogonTerminated = LsaApLogonTerminated;
1580 Tables[0].CallPackageUntrusted = LsaApCallPackageUntrusted;
1581 Tables[0].CallPackagePassthrough = (PLSA_AP_CALL_PACKAGE_PASSTHROUGH)LsaApCallPackagePassthrough;
1582 // Tables[0].LogonUserEx = NULL;
1583 Tables[0].LogonUserEx2 = LsaApLogonUserEx2;
1584 // Tables[0].Initialize = SpInitialize;
1585 // Tables[0].Shutdown = NULL;
1586 // Tables[0].GetInfo = NULL;
1587 // Tables[0].AcceptCredentials = NULL;
1588 // Tables[0].SpAcquireCredentialsHandle = NULL;
1589 // Tables[0].SpQueryCredentialsAttributes = NULL;
1590 // Tables[0].FreeCredentialsHandle = NULL;
1591 // Tables[0].SaveCredentials = NULL;
1592 // Tables[0].GetCredentials = NULL;
1593 // Tables[0].DeleteCredentials = NULL;
1594 // Tables[0].InitLsaModeContext = NULL;
1595 // Tables[0].AcceptLsaModeContext = NULL;
1596 // Tables[0].DeleteContext = NULL;
1597 // Tables[0].ApplyControlToken = NULL;
1598 // Tables[0].GetUserInfo = NULL;
1599 // Tables[0].GetExtendedInformation = NULL;
1600 // Tables[0].SpQueryContextAttributes = NULL;
1601 // Tables[0].SpAddCredentials = NULL;
1602 // Tables[0].SetExtendedInformation = NULL;
1603
1604 *ppTables = Tables;
1605 *pcTables = 1;
1606
1607 return STATUS_SUCCESS;
1608 }
1609
1610
1611 /*
1612 * @unimplemented
1613 */
1614 NTSTATUS
1615 WINAPI
1616 SpUserModeInitialize(
1617 _In_ ULONG LsaVersion,
1618 _Out_ PULONG PackageVersion,
1619 _Out_ PSECPKG_USER_FUNCTION_TABLE *ppTables,
1620 _Out_ PULONG pcTables)
1621 {
1622 SECPKG_USER_FUNCTION_TABLE Tables[1];
1623
1624 TRACE("SpUserModeInitialize(0x%lx %p %p %p)\n",
1625 LsaVersion, PackageVersion, ppTables, pcTables);
1626
1627 if (LsaVersion != SECPKG_INTERFACE_VERSION)
1628 return STATUS_INVALID_PARAMETER;
1629
1630 *PackageVersion = SECPKG_INTERFACE_VERSION;
1631
1632 RtlZeroMemory(&Tables, sizeof(Tables));
1633
1634 // Tables[0].InstanceInit = SpInstanceInit;
1635 // Tables[0].InitUserModeContext = NULL;
1636 // Tables[0].MakeSignature = NULL;
1637 // Tables[0].VerifySignature = NULL;
1638 // Tables[0].SealMessage = NULL;
1639 // Tables[0].UnsealMessage = NULL;
1640 // Tables[0].GetContextToken = NULL;
1641 // Tables[0].SpQueryContextAttributes = NULL;
1642 // Tables[0].CompleteAuthToken = NULL;
1643 // Tables[0].DeleteUserModeContext = NULL;
1644 // Tables[0].FormatCredentials = NULL;
1645 // Tables[0].MarshallSupplementalCreds = NULL;
1646 // Tables[0].ExportContext = NULL;
1647 // Tables[0].ImportContext = NULL;
1648
1649 *ppTables = Tables;
1650 *pcTables = 1;
1651
1652 return STATUS_SUCCESS;
1653 }
1654
1655 /* EOF */