39360caa38dbc018be0f82c663d42f480154db64
[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 * @implemented
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 ULONG MessageType;
1030 NTSTATUS Status;
1031
1032 TRACE("LsaApCallPackageUntrusted()\n");
1033
1034 if (SubmitBufferLength < sizeof(MSV1_0_PROTOCOL_MESSAGE_TYPE))
1035 return STATUS_INVALID_PARAMETER;
1036
1037 MessageType = (ULONG)*((PMSV1_0_PROTOCOL_MESSAGE_TYPE)ProtocolSubmitBuffer);
1038
1039 *ProtocolReturnBuffer = NULL;
1040 *ReturnBufferLength = 0;
1041
1042 if (MessageType == MsV1_0ChangePassword)
1043 Status = MsvpChangePassword(ClientRequest,
1044 ProtocolSubmitBuffer,
1045 ClientBufferBase,
1046 SubmitBufferLength,
1047 ProtocolReturnBuffer,
1048 ReturnBufferLength,
1049 ProtocolStatus);
1050 else
1051 Status = STATUS_ACCESS_DENIED;
1052
1053 return Status;
1054 }
1055
1056
1057 /*
1058 * @implemented
1059 */
1060 NTSTATUS
1061 NTAPI
1062 LsaApInitializePackage(IN ULONG AuthenticationPackageId,
1063 IN PLSA_DISPATCH_TABLE LsaDispatchTable,
1064 IN PLSA_STRING Database OPTIONAL,
1065 IN PLSA_STRING Confidentiality OPTIONAL,
1066 OUT PLSA_STRING *AuthenticationPackageName)
1067 {
1068 PANSI_STRING NameString;
1069 PCHAR NameBuffer;
1070
1071 TRACE("LsaApInitializePackage(%lu %p %p %p %p)\n",
1072 AuthenticationPackageId, LsaDispatchTable, Database,
1073 Confidentiality, AuthenticationPackageName);
1074
1075 /* Get the dispatch table entries */
1076 DispatchTable.CreateLogonSession = LsaDispatchTable->CreateLogonSession;
1077 DispatchTable.DeleteLogonSession = LsaDispatchTable->DeleteLogonSession;
1078 DispatchTable.AddCredential = LsaDispatchTable->AddCredential;
1079 DispatchTable.GetCredentials = LsaDispatchTable->GetCredentials;
1080 DispatchTable.DeleteCredential = LsaDispatchTable->DeleteCredential;
1081 DispatchTable.AllocateLsaHeap = LsaDispatchTable->AllocateLsaHeap;
1082 DispatchTable.FreeLsaHeap = LsaDispatchTable->FreeLsaHeap;
1083 DispatchTable.AllocateClientBuffer = LsaDispatchTable->AllocateClientBuffer;
1084 DispatchTable.FreeClientBuffer = LsaDispatchTable->FreeClientBuffer;
1085 DispatchTable.CopyToClientBuffer = LsaDispatchTable->CopyToClientBuffer;
1086 DispatchTable.CopyFromClientBuffer = LsaDispatchTable->CopyFromClientBuffer;
1087
1088 /* Return the package name */
1089 NameString = DispatchTable.AllocateLsaHeap(sizeof(LSA_STRING));
1090 if (NameString == NULL)
1091 return STATUS_INSUFFICIENT_RESOURCES;
1092
1093 NameBuffer = DispatchTable.AllocateLsaHeap(sizeof(MSV1_0_PACKAGE_NAME));
1094 if (NameBuffer == NULL)
1095 {
1096 DispatchTable.FreeLsaHeap(NameString);
1097 return STATUS_INSUFFICIENT_RESOURCES;
1098 }
1099
1100 strcpy(NameBuffer, MSV1_0_PACKAGE_NAME);
1101
1102 RtlInitAnsiString(NameString, NameBuffer);
1103
1104 *AuthenticationPackageName = (PLSA_STRING)NameString;
1105
1106 return STATUS_SUCCESS;
1107 }
1108
1109
1110 /*
1111 * @unimplemented
1112 */
1113 VOID
1114 NTAPI
1115 LsaApLogonTerminated(IN PLUID LogonId)
1116 {
1117 TRACE("LsaApLogonTerminated()\n");
1118 }
1119
1120
1121 /*
1122 * @implemented
1123 */
1124 NTSTATUS
1125 NTAPI
1126 LsaApLogonUserEx2(IN PLSA_CLIENT_REQUEST ClientRequest,
1127 IN SECURITY_LOGON_TYPE LogonType,
1128 IN PVOID ProtocolSubmitBuffer,
1129 IN PVOID ClientBufferBase,
1130 IN ULONG SubmitBufferSize,
1131 OUT PVOID *ProfileBuffer,
1132 OUT PULONG ProfileBufferSize,
1133 OUT PLUID LogonId,
1134 OUT PNTSTATUS SubStatus,
1135 OUT PLSA_TOKEN_INFORMATION_TYPE TokenInformationType,
1136 OUT PVOID *TokenInformation,
1137 OUT PUNICODE_STRING *AccountName,
1138 OUT PUNICODE_STRING *AuthenticatingAuthority,
1139 OUT PUNICODE_STRING *MachineName,
1140 OUT PSECPKG_PRIMARY_CRED PrimaryCredentials, /* Not supported yet */
1141 OUT PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials) /* Not supported yet */
1142 {
1143 PMSV1_0_INTERACTIVE_LOGON LogonInfo;
1144 WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
1145 SAMPR_HANDLE ServerHandle = NULL;
1146 SAMPR_HANDLE DomainHandle = NULL;
1147 SAMPR_HANDLE UserHandle = NULL;
1148 PRPC_SID AccountDomainSid = NULL;
1149 RPC_UNICODE_STRING Names[1];
1150 SAMPR_ULONG_ARRAY RelativeIds = {0, NULL};
1151 SAMPR_ULONG_ARRAY Use = {0, NULL};
1152 PSAMPR_USER_INFO_BUFFER UserInfo = NULL;
1153 BOOLEAN SessionCreated = FALSE;
1154 LARGE_INTEGER LogonTime;
1155 LARGE_INTEGER AccountExpires;
1156 LARGE_INTEGER PasswordMustChange;
1157 LARGE_INTEGER PasswordLastSet;
1158 DWORD ComputerNameSize;
1159 BOOL SpecialAccount = FALSE;
1160 NTSTATUS Status;
1161
1162 TRACE("LsaApLogonUser()\n");
1163
1164 TRACE("LogonType: %lu\n", LogonType);
1165 TRACE("ProtocolSubmitBuffer: %p\n", ProtocolSubmitBuffer);
1166 TRACE("SubmitBufferSize: %lu\n", SubmitBufferSize);
1167
1168 *ProfileBuffer = NULL;
1169 *ProfileBufferSize = 0;
1170 *SubStatus = STATUS_SUCCESS;
1171 *AccountName = NULL;
1172 *AuthenticatingAuthority = NULL;
1173
1174 if (LogonType == Interactive ||
1175 LogonType == Batch ||
1176 LogonType == Service)
1177 {
1178 ULONG_PTR PtrOffset;
1179
1180 LogonInfo = (PMSV1_0_INTERACTIVE_LOGON)ProtocolSubmitBuffer;
1181
1182 /* Fix-up pointers in the authentication info */
1183 PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase;
1184
1185 LogonInfo->LogonDomainName.Buffer = FIXUP_POINTER(LogonInfo->LogonDomainName.Buffer, PtrOffset);
1186 LogonInfo->UserName.Buffer = FIXUP_POINTER(LogonInfo->UserName.Buffer, PtrOffset);
1187 LogonInfo->Password.Buffer = FIXUP_POINTER(LogonInfo->Password.Buffer, PtrOffset);
1188
1189 TRACE("Domain: %S\n", LogonInfo->LogonDomainName.Buffer);
1190 TRACE("User: %S\n", LogonInfo->UserName.Buffer);
1191 TRACE("Password: %S\n", LogonInfo->Password.Buffer);
1192 }
1193 else
1194 {
1195 FIXME("LogonType %lu is not supported yet!\n", LogonType);
1196 return STATUS_NOT_IMPLEMENTED;
1197 }
1198
1199 /* Get the logon time */
1200 NtQuerySystemTime(&LogonTime);
1201
1202 /* Get the computer name */
1203 ComputerNameSize = MAX_COMPUTERNAME_LENGTH + 1;
1204 GetComputerNameW(ComputerName, &ComputerNameSize);
1205
1206 /* Check for special accounts */
1207 if (_wcsicmp(LogonInfo->LogonDomainName.Buffer, L"NT AUTHORITY") == 0)
1208 {
1209 SpecialAccount = TRUE;
1210
1211 /* Get the authority domain SID */
1212 Status = GetNtAuthorityDomainSid(&AccountDomainSid);
1213 if (!NT_SUCCESS(Status))
1214 {
1215 ERR("GetNtAuthorityDomainSid() failed (Status 0x%08lx)\n", Status);
1216 return Status;
1217 }
1218
1219 if (_wcsicmp(LogonInfo->UserName.Buffer, L"LocalService") == 0)
1220 {
1221 TRACE("SpecialAccount: LocalService\n");
1222
1223 if (LogonType != Service)
1224 return STATUS_LOGON_FAILURE;
1225
1226 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1227 HEAP_ZERO_MEMORY,
1228 sizeof(SAMPR_USER_ALL_INFORMATION));
1229 if (UserInfo == NULL)
1230 {
1231 Status = STATUS_INSUFFICIENT_RESOURCES;
1232 goto done;
1233 }
1234
1235 UserInfo->All.UserId = SECURITY_LOCAL_SERVICE_RID;
1236 UserInfo->All.PrimaryGroupId = SECURITY_LOCAL_SERVICE_RID;
1237 }
1238 else if (_wcsicmp(LogonInfo->UserName.Buffer, L"NetworkService") == 0)
1239 {
1240 TRACE("SpecialAccount: NetworkService\n");
1241
1242 if (LogonType != Service)
1243 return STATUS_LOGON_FAILURE;
1244
1245 UserInfo = RtlAllocateHeap(RtlGetProcessHeap(),
1246 HEAP_ZERO_MEMORY,
1247 sizeof(SAMPR_USER_ALL_INFORMATION));
1248 if (UserInfo == NULL)
1249 {
1250 Status = STATUS_INSUFFICIENT_RESOURCES;
1251 goto done;
1252 }
1253
1254 UserInfo->All.UserId = SECURITY_NETWORK_SERVICE_RID;
1255 UserInfo->All.PrimaryGroupId = SECURITY_NETWORK_SERVICE_RID;
1256 }
1257 else
1258 {
1259 Status = STATUS_NO_SUCH_USER;
1260 goto done;
1261 }
1262 }
1263 else
1264 {
1265 TRACE("NormalAccount\n");
1266
1267 /* Get the account domain SID */
1268 Status = GetAccountDomainSid(&AccountDomainSid);
1269 if (!NT_SUCCESS(Status))
1270 {
1271 ERR("GetAccountDomainSid() failed (Status 0x%08lx)\n", Status);
1272 return Status;
1273 }
1274
1275 /* Connect to the SAM server */
1276 Status = SamIConnect(NULL,
1277 &ServerHandle,
1278 SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
1279 TRUE);
1280 if (!NT_SUCCESS(Status))
1281 {
1282 TRACE("SamIConnect() failed (Status 0x%08lx)\n", Status);
1283 goto done;
1284 }
1285
1286 /* Open the account domain */
1287 Status = SamrOpenDomain(ServerHandle,
1288 DOMAIN_LOOKUP,
1289 AccountDomainSid,
1290 &DomainHandle);
1291 if (!NT_SUCCESS(Status))
1292 {
1293 ERR("SamrOpenDomain failed (Status %08lx)\n", Status);
1294 goto done;
1295 }
1296
1297 Names[0].Length = LogonInfo->UserName.Length;
1298 Names[0].MaximumLength = LogonInfo->UserName.MaximumLength;
1299 Names[0].Buffer = LogonInfo->UserName.Buffer;
1300
1301 /* Try to get the RID for the user name */
1302 Status = SamrLookupNamesInDomain(DomainHandle,
1303 1,
1304 Names,
1305 &RelativeIds,
1306 &Use);
1307 if (!NT_SUCCESS(Status))
1308 {
1309 ERR("SamrLookupNamesInDomain failed (Status %08lx)\n", Status);
1310 Status = STATUS_NO_SUCH_USER;
1311 goto done;
1312 }
1313
1314 /* Fail, if it is not a user account */
1315 if (Use.Element[0] != SidTypeUser)
1316 {
1317 ERR("Account is not a user account!\n");
1318 Status = STATUS_NO_SUCH_USER;
1319 goto done;
1320 }
1321
1322 /* Open the user object */
1323 Status = SamrOpenUser(DomainHandle,
1324 USER_READ_GENERAL | USER_READ_LOGON |
1325 USER_READ_ACCOUNT | USER_READ_PREFERENCES, /* FIXME */
1326 RelativeIds.Element[0],
1327 &UserHandle);
1328 if (!NT_SUCCESS(Status))
1329 {
1330 ERR("SamrOpenUser failed (Status %08lx)\n", Status);
1331 goto done;
1332 }
1333
1334 Status = SamrQueryInformationUser(UserHandle,
1335 UserAllInformation,
1336 &UserInfo);
1337 if (!NT_SUCCESS(Status))
1338 {
1339 ERR("SamrQueryInformationUser failed (Status %08lx)\n", Status);
1340 goto done;
1341 }
1342
1343 TRACE("UserName: %S\n", UserInfo->All.UserName.Buffer);
1344
1345 /* Check the password */
1346 if ((UserInfo->All.UserAccountControl & USER_PASSWORD_NOT_REQUIRED) == 0)
1347 {
1348 Status = MsvpCheckPassword(&(LogonInfo->Password),
1349 UserInfo);
1350 if (!NT_SUCCESS(Status))
1351 {
1352 ERR("MsvpCheckPassword failed (Status %08lx)\n", Status);
1353 goto done;
1354 }
1355 }
1356
1357 /* Check account restrictions for non-administrator accounts */
1358 if (RelativeIds.Element[0] != DOMAIN_USER_RID_ADMIN)
1359 {
1360 /* Check if the account has been disabled */
1361 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_DISABLED)
1362 {
1363 ERR("Account disabled!\n");
1364 *SubStatus = STATUS_ACCOUNT_DISABLED;
1365 Status = STATUS_ACCOUNT_RESTRICTION;
1366 goto done;
1367 }
1368
1369 /* Check if the account has been locked */
1370 if (UserInfo->All.UserAccountControl & USER_ACCOUNT_AUTO_LOCKED)
1371 {
1372 ERR("Account locked!\n");
1373 *SubStatus = STATUS_ACCOUNT_LOCKED_OUT;
1374 Status = STATUS_ACCOUNT_RESTRICTION;
1375 goto done;
1376 }
1377
1378 /* Check if the account expired */
1379 AccountExpires.LowPart = UserInfo->All.AccountExpires.LowPart;
1380 AccountExpires.HighPart = UserInfo->All.AccountExpires.HighPart;
1381 if (LogonTime.QuadPart >= AccountExpires.QuadPart)
1382 {
1383 ERR("Account expired!\n");
1384 *SubStatus = STATUS_ACCOUNT_EXPIRED;
1385 Status = STATUS_ACCOUNT_RESTRICTION;
1386 goto done;
1387 }
1388
1389 /* Check if the password expired */
1390 PasswordMustChange.LowPart = UserInfo->All.PasswordMustChange.LowPart;
1391 PasswordMustChange.HighPart = UserInfo->All.PasswordMustChange.HighPart;
1392 PasswordLastSet.LowPart = UserInfo->All.PasswordLastSet.LowPart;
1393 PasswordLastSet.HighPart = UserInfo->All.PasswordLastSet.HighPart;
1394
1395 if (LogonTime.QuadPart >= PasswordMustChange.QuadPart)
1396 {
1397 ERR("Password expired!\n");
1398 if (PasswordLastSet.QuadPart == 0)
1399 *SubStatus = STATUS_PASSWORD_MUST_CHANGE;
1400 else
1401 *SubStatus = STATUS_PASSWORD_EXPIRED;
1402
1403 Status = STATUS_ACCOUNT_RESTRICTION;
1404 goto done;
1405 }
1406
1407 /* Check logon hours */
1408 if (!MsvpCheckLogonHours(&UserInfo->All.LogonHours, &LogonTime))
1409 {
1410 ERR("Invalid logon hours!\n");
1411 *SubStatus = STATUS_INVALID_LOGON_HOURS;
1412 Status = STATUS_ACCOUNT_RESTRICTION;
1413 goto done;
1414 }
1415
1416 /* Check workstations */
1417 if (!MsvpCheckWorkstations(&UserInfo->All.WorkStations, ComputerName))
1418 {
1419 ERR("Invalid workstation!\n");
1420 *SubStatus = STATUS_INVALID_WORKSTATION;
1421 Status = STATUS_ACCOUNT_RESTRICTION;
1422 goto done;
1423 }
1424 }
1425 }
1426
1427 /* Return logon information */
1428
1429 /* Create and return a new logon id */
1430 Status = NtAllocateLocallyUniqueId(LogonId);
1431 if (!NT_SUCCESS(Status))
1432 {
1433 TRACE("NtAllocateLocallyUniqueId failed (Status %08lx)\n", Status);
1434 goto done;
1435 }
1436
1437 /* Create the logon session */
1438 Status = DispatchTable.CreateLogonSession(LogonId);
1439 if (!NT_SUCCESS(Status))
1440 {
1441 TRACE("CreateLogonSession failed (Status %08lx)\n", Status);
1442 goto done;
1443 }
1444
1445 SessionCreated = TRUE;
1446
1447 /* Build and fill the interactive profile buffer */
1448 Status = BuildInteractiveProfileBuffer(ClientRequest,
1449 UserInfo,
1450 ComputerName,
1451 (PMSV1_0_INTERACTIVE_PROFILE*)ProfileBuffer,
1452 ProfileBufferSize);
1453 if (!NT_SUCCESS(Status))
1454 {
1455 TRACE("BuildInteractiveProfileBuffer failed (Status %08lx)\n", Status);
1456 goto done;
1457 }
1458
1459 /* Return the token information type */
1460 *TokenInformationType = LsaTokenInformationV1;
1461
1462 /* Build and fill the token information buffer */
1463 Status = BuildTokenInformationBuffer((PLSA_TOKEN_INFORMATION_V1*)TokenInformation,
1464 AccountDomainSid,
1465 UserInfo,
1466 SpecialAccount);
1467 if (!NT_SUCCESS(Status))
1468 {
1469 TRACE("BuildTokenInformationBuffer failed (Status %08lx)\n", Status);
1470 goto done;
1471 }
1472
1473 done:
1474 /* Update the logon time/count or the bad password time/count */
1475 if ((UserHandle != NULL) &&
1476 (Status == STATUS_SUCCESS || Status == STATUS_WRONG_PASSWORD))
1477 {
1478 SAMPR_USER_INFO_BUFFER InternalInfo;
1479
1480 RtlZeroMemory(&InternalInfo, sizeof(InternalInfo));
1481
1482 if (Status == STATUS_SUCCESS)
1483 InternalInfo.Internal2.Flags = USER_LOGON_SUCCESS;
1484 else
1485 InternalInfo.Internal2.Flags = USER_LOGON_BAD_PASSWORD;
1486
1487 SamrSetInformationUser(UserHandle,
1488 UserInternal2Information,
1489 &InternalInfo);
1490 }
1491
1492 /* Return the account name */
1493 *AccountName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1494 if (*AccountName != NULL)
1495 {
1496 (*AccountName)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->UserName.Length +
1497 sizeof(UNICODE_NULL));
1498 if ((*AccountName)->Buffer != NULL)
1499 {
1500 (*AccountName)->MaximumLength = LogonInfo->UserName.Length +
1501 sizeof(UNICODE_NULL);
1502 RtlCopyUnicodeString(*AccountName, &LogonInfo->UserName);
1503 }
1504 }
1505
1506 /* Return the authenticating authority */
1507 *AuthenticatingAuthority = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1508 if (*AuthenticatingAuthority != NULL)
1509 {
1510 (*AuthenticatingAuthority)->Buffer = DispatchTable.AllocateLsaHeap(LogonInfo->LogonDomainName.Length +
1511 sizeof(UNICODE_NULL));
1512 if ((*AuthenticatingAuthority)->Buffer != NULL)
1513 {
1514 (*AuthenticatingAuthority)->MaximumLength = LogonInfo->LogonDomainName.Length +
1515 sizeof(UNICODE_NULL);
1516 RtlCopyUnicodeString(*AuthenticatingAuthority, &LogonInfo->LogonDomainName);
1517 }
1518 }
1519
1520 /* Return the machine name */
1521 *MachineName = DispatchTable.AllocateLsaHeap(sizeof(UNICODE_STRING));
1522 if (*MachineName != NULL)
1523 {
1524 (*MachineName)->Buffer = DispatchTable.AllocateLsaHeap((ComputerNameSize + 1) * sizeof(WCHAR));
1525 if ((*MachineName)->Buffer != NULL)
1526 {
1527 (*MachineName)->MaximumLength = (ComputerNameSize + 1) * sizeof(WCHAR);
1528 (*MachineName)->Length = ComputerNameSize * sizeof(WCHAR);
1529 RtlCopyMemory((*MachineName)->Buffer, ComputerName, (*MachineName)->MaximumLength);
1530 }
1531 }
1532
1533 if (!NT_SUCCESS(Status))
1534 {
1535 if (SessionCreated != FALSE)
1536 DispatchTable.DeleteLogonSession(LogonId);
1537
1538 if (*ProfileBuffer != NULL)
1539 {
1540 DispatchTable.FreeClientBuffer(ClientRequest,
1541 *ProfileBuffer);
1542 *ProfileBuffer = NULL;
1543 }
1544 }
1545
1546 if (UserHandle != NULL)
1547 SamrCloseHandle(&UserHandle);
1548
1549 SamIFree_SAMPR_USER_INFO_BUFFER(UserInfo,
1550 UserAllInformation);
1551 SamIFree_SAMPR_ULONG_ARRAY(&RelativeIds);
1552 SamIFree_SAMPR_ULONG_ARRAY(&Use);
1553
1554 if (DomainHandle != NULL)
1555 SamrCloseHandle(&DomainHandle);
1556
1557 if (ServerHandle != NULL)
1558 SamrCloseHandle(&ServerHandle);
1559
1560 if (AccountDomainSid != NULL)
1561 RtlFreeHeap(RtlGetProcessHeap(), 0, AccountDomainSid);
1562
1563 if (Status == STATUS_NO_SUCH_USER ||
1564 Status == STATUS_WRONG_PASSWORD)
1565 {
1566 *SubStatus = Status;
1567 Status = STATUS_LOGON_FAILURE;
1568 }
1569
1570 TRACE("LsaApLogonUser done (Status 0x%08lx SubStatus 0x%08lx)\n", Status, *SubStatus);
1571
1572 return Status;
1573 }
1574
1575
1576 /*
1577 * @unimplemented
1578 */
1579 NTSTATUS
1580 NTAPI
1581 SpLsaModeInitialize(
1582 _In_ ULONG LsaVersion,
1583 _Out_ PULONG PackageVersion,
1584 _Out_ PSECPKG_FUNCTION_TABLE *ppTables,
1585 _Out_ PULONG pcTables)
1586 {
1587 SECPKG_FUNCTION_TABLE Tables[1];
1588
1589 TRACE("SpLsaModeInitialize(0x%lx %p %p %p)\n",
1590 LsaVersion, PackageVersion, ppTables, pcTables);
1591
1592 if (LsaVersion != SECPKG_INTERFACE_VERSION)
1593 return STATUS_INVALID_PARAMETER;
1594
1595 *PackageVersion = SECPKG_INTERFACE_VERSION;
1596
1597 RtlZeroMemory(&Tables, sizeof(Tables));
1598
1599 Tables[0].InitializePackage = LsaApInitializePackage;
1600 // Tables[0].LogonUser = NULL;
1601 Tables[0].CallPackage = (PLSA_AP_CALL_PACKAGE)LsaApCallPackage;
1602 Tables[0].LogonTerminated = LsaApLogonTerminated;
1603 Tables[0].CallPackageUntrusted = LsaApCallPackageUntrusted;
1604 Tables[0].CallPackagePassthrough = (PLSA_AP_CALL_PACKAGE_PASSTHROUGH)LsaApCallPackagePassthrough;
1605 // Tables[0].LogonUserEx = NULL;
1606 Tables[0].LogonUserEx2 = LsaApLogonUserEx2;
1607 // Tables[0].Initialize = SpInitialize;
1608 // Tables[0].Shutdown = NULL;
1609 // Tables[0].GetInfo = NULL;
1610 // Tables[0].AcceptCredentials = NULL;
1611 // Tables[0].SpAcquireCredentialsHandle = NULL;
1612 // Tables[0].SpQueryCredentialsAttributes = NULL;
1613 // Tables[0].FreeCredentialsHandle = NULL;
1614 // Tables[0].SaveCredentials = NULL;
1615 // Tables[0].GetCredentials = NULL;
1616 // Tables[0].DeleteCredentials = NULL;
1617 // Tables[0].InitLsaModeContext = NULL;
1618 // Tables[0].AcceptLsaModeContext = NULL;
1619 // Tables[0].DeleteContext = NULL;
1620 // Tables[0].ApplyControlToken = NULL;
1621 // Tables[0].GetUserInfo = NULL;
1622 // Tables[0].GetExtendedInformation = NULL;
1623 // Tables[0].SpQueryContextAttributes = NULL;
1624 // Tables[0].SpAddCredentials = NULL;
1625 // Tables[0].SetExtendedInformation = NULL;
1626
1627 *ppTables = Tables;
1628 *pcTables = 1;
1629
1630 return STATUS_SUCCESS;
1631 }
1632
1633
1634 /*
1635 * @unimplemented
1636 */
1637 NTSTATUS
1638 WINAPI
1639 SpUserModeInitialize(
1640 _In_ ULONG LsaVersion,
1641 _Out_ PULONG PackageVersion,
1642 _Out_ PSECPKG_USER_FUNCTION_TABLE *ppTables,
1643 _Out_ PULONG pcTables)
1644 {
1645 SECPKG_USER_FUNCTION_TABLE Tables[1];
1646
1647 TRACE("SpUserModeInitialize(0x%lx %p %p %p)\n",
1648 LsaVersion, PackageVersion, ppTables, pcTables);
1649
1650 if (LsaVersion != SECPKG_INTERFACE_VERSION)
1651 return STATUS_INVALID_PARAMETER;
1652
1653 *PackageVersion = SECPKG_INTERFACE_VERSION;
1654
1655 RtlZeroMemory(&Tables, sizeof(Tables));
1656
1657 // Tables[0].InstanceInit = SpInstanceInit;
1658 // Tables[0].InitUserModeContext = NULL;
1659 // Tables[0].MakeSignature = NULL;
1660 // Tables[0].VerifySignature = NULL;
1661 // Tables[0].SealMessage = NULL;
1662 // Tables[0].UnsealMessage = NULL;
1663 // Tables[0].GetContextToken = NULL;
1664 // Tables[0].SpQueryContextAttributes = NULL;
1665 // Tables[0].CompleteAuthToken = NULL;
1666 // Tables[0].DeleteUserModeContext = NULL;
1667 // Tables[0].FormatCredentials = NULL;
1668 // Tables[0].MarshallSupplementalCreds = NULL;
1669 // Tables[0].ExportContext = NULL;
1670 // Tables[0].ImportContext = NULL;
1671
1672 *ppTables = Tables;
1673 *pcTables = 1;
1674
1675 return STATUS_SUCCESS;
1676 }
1677
1678 /* EOF */